tdf#131321 writerfilter: ApplyNumberingStyleNameToParaStyles()
[LibreOffice.git] / writerfilter / source / dmapper / StyleSheetTable.cxx
blobf0524e71ed32ef2843d4a32fbfa848f6e6f45e1a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include "StyleSheetTable.hxx"
20 #include "util.hxx"
21 #include "ConversionHelper.hxx"
22 #include "TblStylePrHandler.hxx"
23 #include "TagLogger.hxx"
24 #include "BorderHandler.hxx"
25 #include "LatentStyleHandler.hxx"
26 #include <ooxml/resourceids.hxx>
27 #include <vector>
28 #include <iterator>
29 #include <com/sun/star/beans/XMultiPropertySet.hpp>
30 #include <com/sun/star/beans/XPropertyState.hpp>
31 #include <com/sun/star/beans/PropertyValue.hpp>
32 #include <com/sun/star/container/XNameContainer.hpp>
33 #include <com/sun/star/container/XIndexReplace.hpp>
34 #include <com/sun/star/text/XTextDocument.hpp>
35 #include <com/sun/star/style/NumberingType.hpp>
36 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
37 #include <com/sun/star/style/XStyle.hpp>
38 #include <com/sun/star/style/ParagraphAdjust.hpp>
39 #include <com/sun/star/text/WritingMode.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <map>
42 #include <osl/diagnose.h>
43 #include <rtl/ustrbuf.hxx>
44 #include <sal/log.hxx>
45 #include <comphelper/string.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <tools/diagnose_ex.h>
48 #include <o3tl/sorted_vector.hxx>
50 using namespace ::com::sun::star;
52 namespace writerfilter::dmapper
55 typedef ::std::map< OUString, OUString> StringPairMap_t;
58 StyleSheetEntry::StyleSheetEntry() :
59 sStyleIdentifierD()
60 ,bIsDefaultStyle(false)
61 ,bInvalidHeight(false)
62 ,bHasUPE(false)
63 ,nStyleTypeCode(STYLE_TYPE_UNKNOWN)
64 ,sBaseStyleIdentifier()
65 ,sNextStyleIdentifier()
66 ,pProperties(new StyleSheetPropertyMap)
67 ,bAutoRedefine(false)
71 StyleSheetEntry::~StyleSheetEntry()
75 TableStyleSheetEntry::TableStyleSheetEntry( StyleSheetEntry const & rEntry ):
76 StyleSheetEntry( )
78 bIsDefaultStyle = rEntry.bIsDefaultStyle;
79 bInvalidHeight = rEntry.bInvalidHeight;
80 bHasUPE = rEntry.bHasUPE;
81 nStyleTypeCode = STYLE_TYPE_TABLE;
82 sBaseStyleIdentifier = rEntry.sBaseStyleIdentifier;
83 sNextStyleIdentifier = rEntry.sNextStyleIdentifier;
84 sStyleName = rEntry.sStyleName;
85 sStyleIdentifierD = rEntry.sStyleIdentifierD;
88 TableStyleSheetEntry::~TableStyleSheetEntry( )
92 void TableStyleSheetEntry::AddTblStylePr( TblStyleType nType, const PropertyMapPtr& pProps )
94 static const int nTypesProps = 4;
95 static const TblStyleType pTypesToFix[nTypesProps] =
97 TBL_STYLE_FIRSTROW,
98 TBL_STYLE_LASTROW,
99 TBL_STYLE_FIRSTCOL,
100 TBL_STYLE_LASTCOL
103 static const PropertyIds pPropsToCheck[nTypesProps] =
105 PROP_BOTTOM_BORDER,
106 PROP_TOP_BORDER,
107 PROP_RIGHT_BORDER,
108 PROP_LEFT_BORDER
111 for (int i=0; i < nTypesProps; ++i )
113 if ( nType == pTypesToFix[i] )
115 PropertyIds nChecked = pPropsToCheck[i];
116 std::optional<PropertyMap::Property> pChecked = pProps->getProperty(nChecked);
118 PropertyIds nInsideProp = ( i < 2 ) ? META_PROP_HORIZONTAL_BORDER : META_PROP_VERTICAL_BORDER;
119 std::optional<PropertyMap::Property> pInside = pProps->getProperty(nInsideProp);
121 if ( pChecked && pInside )
123 // In this case, remove the inside border
124 pProps->Erase( nInsideProp );
127 break;
131 // Append the tblStylePr
132 m_aStyles[nType] = pProps;
135 PropertyMapPtr TableStyleSheetEntry::GetProperties( sal_Int32 nMask )
137 PropertyMapPtr pProps( new PropertyMap );
139 // And finally get the mask ones
140 pProps->InsertProps(GetLocalPropertiesFromMask(nMask));
142 return pProps;
145 beans::PropertyValues StyleSheetEntry::GetInteropGrabBagSeq() const
147 return comphelper::containerToSequence(m_aInteropGrabBag);
150 beans::PropertyValue StyleSheetEntry::GetInteropGrabBag()
152 beans::PropertyValue aRet;
153 aRet.Name = sStyleIdentifierD;
155 beans::PropertyValues aSeq = GetInteropGrabBagSeq();
156 aRet.Value <<= aSeq;
157 return aRet;
160 void StyleSheetEntry::AppendInteropGrabBag(const beans::PropertyValue& rValue)
162 m_aInteropGrabBag.push_back(rValue);
165 PropertyMapPtr StyleSheetEntry::GetMergedInheritedProperties(const StyleSheetTablePtr& pStyleSheetTable)
167 PropertyMapPtr pRet;
168 if ( pStyleSheetTable && !sBaseStyleIdentifier.isEmpty() && sBaseStyleIdentifier != sStyleIdentifierD )
170 const StyleSheetEntryPtr pParentStyleSheet = pStyleSheetTable->FindStyleSheetByISTD(sBaseStyleIdentifier);
171 if ( pParentStyleSheet )
172 pRet = pParentStyleSheet->GetMergedInheritedProperties(pStyleSheetTable);
175 if ( !pRet )
176 pRet = new PropertyMap;
178 pRet->InsertProps(pProperties);
180 return pRet;
183 static void lcl_mergeProps( const PropertyMapPtr& pToFill, const PropertyMapPtr& pToAdd, TblStyleType nStyleId )
185 static const PropertyIds pPropsToCheck[] =
187 PROP_BOTTOM_BORDER,
188 PROP_TOP_BORDER,
189 PROP_RIGHT_BORDER,
190 PROP_LEFT_BORDER,
193 bool pRemoveInside[] =
195 ( nStyleId == TBL_STYLE_FIRSTROW ),
196 ( nStyleId == TBL_STYLE_LASTROW ),
197 ( nStyleId == TBL_STYLE_LASTCOL ),
198 ( nStyleId == TBL_STYLE_FIRSTCOL )
201 for ( unsigned i = 0 ; i != SAL_N_ELEMENTS(pPropsToCheck); i++ )
203 PropertyIds nId = pPropsToCheck[i];
204 std::optional<PropertyMap::Property> pProp = pToAdd->getProperty(nId);
206 if ( pProp )
208 if ( pRemoveInside[i] )
210 // Remove the insideH and insideV depending on the cell pos
211 PropertyIds nInsideProp = ( i < 2 ) ? META_PROP_HORIZONTAL_BORDER : META_PROP_VERTICAL_BORDER;
212 pToFill->Erase(nInsideProp);
217 pToFill->InsertProps(pToAdd);
220 PropertyMapPtr TableStyleSheetEntry::GetLocalPropertiesFromMask( sal_Int32 nMask )
222 // Order from right to left
223 struct TblStyleTypeAndMask {
224 sal_Int32 mask;
225 TblStyleType type;
228 static const TblStyleTypeAndMask aOrderedStyleTable[] =
230 { 0x010, TBL_STYLE_BAND2HORZ },
231 { 0x020, TBL_STYLE_BAND1HORZ },
232 { 0x040, TBL_STYLE_BAND2VERT },
233 { 0x080, TBL_STYLE_BAND1VERT },
234 { 0x100, TBL_STYLE_LASTCOL },
235 { 0x200, TBL_STYLE_FIRSTCOL },
236 { 0x400, TBL_STYLE_LASTROW },
237 { 0x800, TBL_STYLE_FIRSTROW },
238 { 0x001, TBL_STYLE_SWCELL },
239 { 0x002, TBL_STYLE_SECELL },
240 { 0x004, TBL_STYLE_NWCELL },
241 { 0x008, TBL_STYLE_NECELL }
244 // Get the properties applying according to the mask
245 PropertyMapPtr pProps( new PropertyMap( ) );
246 for (const TblStyleTypeAndMask & i : aOrderedStyleTable)
248 TblStylePrs::iterator pIt = m_aStyles.find( i.type );
249 if ( ( nMask & i.mask ) && ( pIt != m_aStyles.end( ) ) )
250 lcl_mergeProps( pProps, pIt->second, i.type );
252 return pProps;
255 namespace {
257 struct ListCharStylePropertyMap_t
259 OUString sCharStyleName;
260 PropertyValueVector_t aPropertyValues;
262 ListCharStylePropertyMap_t(const OUString& rCharStyleName, const PropertyValueVector_t& rPropertyValues):
263 sCharStyleName( rCharStyleName ),
264 aPropertyValues( rPropertyValues )
270 typedef std::vector< ListCharStylePropertyMap_t > ListCharStylePropertyVector_t;
273 struct StyleSheetTable_Impl
275 DomainMapper& m_rDMapper;
276 uno::Reference< text::XTextDocument> m_xTextDocument;
277 uno::Reference< beans::XPropertySet> m_xTextDefaults;
278 std::vector< StyleSheetEntryPtr > m_aStyleSheetEntries;
279 StyleSheetEntryPtr m_pCurrentEntry;
280 PropertyMapPtr m_pDefaultParaProps, m_pDefaultCharProps;
281 OUString m_sDefaultParaStyleName; //WW8 name
282 ListCharStylePropertyVector_t m_aListCharStylePropertyVector;
283 bool m_bHasImportedDefaultParaProps;
284 bool m_bIsNewDoc;
286 StyleSheetTable_Impl(DomainMapper& rDMapper, uno::Reference< text::XTextDocument> const& xTextDocument, bool bIsNewDoc);
288 OUString HasListCharStyle( const PropertyValueVector_t& rCharProperties );
290 /// Appends the given key-value pair to the list of latent style properties of the current entry.
291 void AppendLatentStyleProperty(const OUString& aName, Value const & rValue);
292 /// Sets all properties of xStyle back to default.
293 static void SetPropertiesToDefault(const uno::Reference<style::XStyle>& xStyle);
297 StyleSheetTable_Impl::StyleSheetTable_Impl(DomainMapper& rDMapper,
298 uno::Reference< text::XTextDocument> const& xTextDocument,
299 bool const bIsNewDoc)
301 m_rDMapper( rDMapper ),
302 m_xTextDocument( xTextDocument ),
303 m_pCurrentEntry(),
304 m_pDefaultParaProps(new PropertyMap),
305 m_pDefaultCharProps(new PropertyMap),
306 m_sDefaultParaStyleName("Normal"),
307 m_bHasImportedDefaultParaProps(false),
308 m_bIsNewDoc(bIsNewDoc)
310 //set font height default to 10pt
311 uno::Any aVal = uno::makeAny( 10.0 );
312 m_pDefaultCharProps->Insert( PROP_CHAR_HEIGHT, aVal );
313 m_pDefaultCharProps->Insert( PROP_CHAR_HEIGHT_ASIAN, aVal );
314 m_pDefaultCharProps->Insert( PROP_CHAR_HEIGHT_COMPLEX, aVal );
316 // See SwDoc::RemoveAllFormatLanguageDependencies(), internal filters
317 // disable kerning by default, do the same here.
318 m_pDefaultCharProps->Insert(PROP_CHAR_AUTO_KERNING, uno::Any(false));
322 OUString StyleSheetTable_Impl::HasListCharStyle( const PropertyValueVector_t& rPropValues )
324 for( const auto& rListVector : m_aListCharStylePropertyVector )
326 const auto& rPropertyValues = rListVector.aPropertyValues;
327 //if size is identical
328 if( rPropertyValues.size() == rPropValues.size() )
330 bool bBreak = false;
331 //then search for all contained properties
332 for( const auto& rPropVal1 : rPropValues)
334 //find the property
335 auto aListIter = std::find_if(rPropertyValues.begin(), rPropertyValues.end(),
336 [&rPropVal1](const css::beans::PropertyValue& rPropVal2) { return rPropVal2.Name == rPropVal1.Name; });
337 //set break flag if property hasn't been found
338 bBreak = (aListIter == rPropertyValues.end()) || (aListIter->Value != rPropVal1.Value);
339 if( bBreak )
340 break;
342 if( !bBreak )
343 return rListVector.sCharStyleName;
346 return OUString();
349 void StyleSheetTable_Impl::AppendLatentStyleProperty(const OUString& aName, Value const & rValue)
351 beans::PropertyValue aValue;
352 aValue.Name = aName;
353 aValue.Value <<= rValue.getString();
354 m_pCurrentEntry->aLatentStyles.push_back(aValue);
357 void StyleSheetTable_Impl::SetPropertiesToDefault(const uno::Reference<style::XStyle>& xStyle)
359 // See if the existing style has any non-default properties. If so, reset them back to default.
360 uno::Reference<beans::XPropertySet> xPropertySet(xStyle, uno::UNO_QUERY);
361 uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
362 uno::Sequence<beans::Property> aProperties = xPropertySetInfo->getProperties();
363 std::vector<OUString> aPropertyNames;
364 aPropertyNames.reserve(aProperties.getLength());
365 std::transform(aProperties.begin(), aProperties.end(), std::back_inserter(aPropertyNames),
366 [](const beans::Property& rProp) { return rProp.Name; });
368 uno::Reference<beans::XPropertyState> xPropertyState(xStyle, uno::UNO_QUERY);
369 uno::Sequence<beans::PropertyState> aStates = xPropertyState->getPropertyStates(comphelper::containerToSequence(aPropertyNames));
370 for (sal_Int32 i = 0; i < aStates.getLength(); ++i)
372 if (aStates[i] == beans::PropertyState_DIRECT_VALUE)
376 xPropertyState->setPropertyToDefault(aPropertyNames[i]);
378 catch(const uno::Exception&)
380 TOOLS_INFO_EXCEPTION("writerfilter", "setPropertyToDefault(" << aPropertyNames[i] << ") failed");
386 StyleSheetTable::StyleSheetTable(DomainMapper& rDMapper,
387 uno::Reference< text::XTextDocument> const& xTextDocument,
388 bool const bIsNewDoc)
389 : LoggedProperties("StyleSheetTable")
390 , LoggedTable("StyleSheetTable")
391 , m_pImpl( new StyleSheetTable_Impl(rDMapper, xTextDocument, bIsNewDoc) )
396 StyleSheetTable::~StyleSheetTable()
400 void StyleSheetTable::SetDefaultParaProps(PropertyIds eId, const css::uno::Any& rAny)
402 m_pImpl->m_pDefaultParaProps->Insert(eId, rAny, /*bOverwrite=*/false, NO_GRAB_BAG, /*bDocDefault=*/true);
405 PropertyMapPtr const & StyleSheetTable::GetDefaultParaProps() const
407 return m_pImpl->m_pDefaultParaProps;
410 PropertyMapPtr const & StyleSheetTable::GetDefaultCharProps() const
412 return m_pImpl->m_pDefaultCharProps;
415 void StyleSheetTable::lcl_attribute(Id Name, Value & val)
417 OSL_ENSURE( m_pImpl->m_pCurrentEntry, "current entry has to be set here");
418 if(!m_pImpl->m_pCurrentEntry)
419 return ;
420 int nIntValue = val.getInt();
421 OUString sValue = val.getString();
423 // The default type is paragraph, and it needs to be processed first,
424 // because the NS_ooxml::LN_CT_Style_type handling may set m_pImpl->m_pCurrentEntry
425 // to point to a different object.
426 if( m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_UNKNOWN )
428 if( Name != NS_ooxml::LN_CT_Style_type )
429 m_pImpl->m_pCurrentEntry->nStyleTypeCode = STYLE_TYPE_PARA;
431 switch(Name)
433 case NS_ooxml::LN_CT_Style_type:
435 SAL_WARN_IF( m_pImpl->m_pCurrentEntry->nStyleTypeCode != STYLE_TYPE_UNKNOWN,
436 "writerfilter", "Style type needs to be processed first" );
437 StyleType nType(STYLE_TYPE_UNKNOWN);
438 switch (nIntValue)
440 case NS_ooxml::LN_Value_ST_StyleType_paragraph:
441 nType = STYLE_TYPE_PARA;
442 break;
443 case NS_ooxml::LN_Value_ST_StyleType_character:
444 nType = STYLE_TYPE_CHAR;
445 break;
446 case NS_ooxml::LN_Value_ST_StyleType_table:
447 nType = STYLE_TYPE_TABLE;
448 break;
449 case NS_ooxml::LN_Value_ST_StyleType_numbering:
450 nType = STYLE_TYPE_LIST;
451 break;
452 default:
453 SAL_WARN("writerfilter", "unknown LN_CT_Style_type " << nType);
454 [[fallthrough]];
455 case 0: // explicit unknown set by tokenizer
456 break;
459 if ( nType == STYLE_TYPE_TABLE )
461 StyleSheetEntryPtr pEntry = m_pImpl->m_pCurrentEntry;
462 tools::SvRef<TableStyleSheetEntry> pTableEntry( new TableStyleSheetEntry( *pEntry ) );
463 m_pImpl->m_pCurrentEntry = pTableEntry.get();
465 else
466 m_pImpl->m_pCurrentEntry->nStyleTypeCode = nType;
468 break;
469 case NS_ooxml::LN_CT_Style_default:
470 m_pImpl->m_pCurrentEntry->bIsDefaultStyle = (nIntValue != 0);
472 if (m_pImpl->m_pCurrentEntry->nStyleTypeCode != STYLE_TYPE_UNKNOWN)
474 // "If this attribute is specified by multiple styles, then the last instance shall be used."
475 if ( m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_PARA && !m_pImpl->m_pCurrentEntry->sStyleIdentifierD.isEmpty() )
476 m_pImpl->m_sDefaultParaStyleName = m_pImpl->m_pCurrentEntry->sStyleIdentifierD;
478 beans::PropertyValue aValue;
479 aValue.Name = "default";
480 aValue.Value <<= m_pImpl->m_pCurrentEntry->bIsDefaultStyle;
481 m_pImpl->m_pCurrentEntry->AppendInteropGrabBag(aValue);
483 break;
484 case NS_ooxml::LN_CT_Style_customStyle:
485 if (m_pImpl->m_pCurrentEntry->nStyleTypeCode != STYLE_TYPE_UNKNOWN)
487 beans::PropertyValue aValue;
488 aValue.Name = "customStyle";
489 aValue.Value <<= (nIntValue != 0);
490 m_pImpl->m_pCurrentEntry->AppendInteropGrabBag(aValue);
492 break;
493 case NS_ooxml::LN_CT_Style_styleId:
494 m_pImpl->m_pCurrentEntry->sStyleIdentifierD = sValue;
495 if(m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
497 TableStyleSheetEntry* pTableEntry = static_cast<TableStyleSheetEntry *>(m_pImpl->m_pCurrentEntry.get());
498 beans::PropertyValue aValue;
499 aValue.Name = "styleId";
500 aValue.Value <<= sValue;
501 pTableEntry->AppendInteropGrabBag(aValue);
503 break;
504 case NS_ooxml::LN_CT_TblWidth_w:
505 break;
506 case NS_ooxml::LN_CT_TblWidth_type:
507 break;
508 case NS_ooxml::LN_CT_LatentStyles_defQFormat:
509 m_pImpl->AppendLatentStyleProperty("defQFormat", val);
510 break;
511 case NS_ooxml::LN_CT_LatentStyles_defUnhideWhenUsed:
512 m_pImpl->AppendLatentStyleProperty("defUnhideWhenUsed", val);
513 break;
514 case NS_ooxml::LN_CT_LatentStyles_defSemiHidden:
515 m_pImpl->AppendLatentStyleProperty("defSemiHidden", val);
516 break;
517 case NS_ooxml::LN_CT_LatentStyles_count:
518 m_pImpl->AppendLatentStyleProperty("count", val);
519 break;
520 case NS_ooxml::LN_CT_LatentStyles_defUIPriority:
521 m_pImpl->AppendLatentStyleProperty("defUIPriority", val);
522 break;
523 case NS_ooxml::LN_CT_LatentStyles_defLockedState:
524 m_pImpl->AppendLatentStyleProperty("defLockedState", val);
525 break;
526 default:
528 #ifdef DBG_UTIL
529 TagLogger::getInstance().element("unhandled");
530 #endif
532 break;
537 void StyleSheetTable::lcl_sprm(Sprm & rSprm)
539 sal_uInt32 nSprmId = rSprm.getId();
540 Value::Pointer_t pValue = rSprm.getValue();
541 sal_Int32 nIntValue = pValue.get() ? pValue->getInt() : 0;
542 OUString sStringValue = pValue.get() ? pValue->getString() : OUString();
544 switch(nSprmId)
546 case NS_ooxml::LN_CT_Style_name:
547 //this is only a UI name!
548 m_pImpl->m_pCurrentEntry->sStyleName = sStringValue;
549 if(m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
551 TableStyleSheetEntry* pTableEntry = static_cast<TableStyleSheetEntry *>(m_pImpl->m_pCurrentEntry.get());
552 beans::PropertyValue aValue;
553 aValue.Name = "name";
554 aValue.Value <<= sStringValue;
555 pTableEntry->AppendInteropGrabBag(aValue);
557 break;
558 case NS_ooxml::LN_CT_Style_basedOn:
559 m_pImpl->m_pCurrentEntry->sBaseStyleIdentifier = sStringValue;
560 if(m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
562 TableStyleSheetEntry* pTableEntry = static_cast<TableStyleSheetEntry *>(m_pImpl->m_pCurrentEntry.get());
563 beans::PropertyValue aValue;
564 aValue.Name = "basedOn";
565 aValue.Value <<= sStringValue;
566 pTableEntry->AppendInteropGrabBag(aValue);
568 break;
569 case NS_ooxml::LN_CT_Style_next:
570 m_pImpl->m_pCurrentEntry->sNextStyleIdentifier = sStringValue;
571 break;
572 case NS_ooxml::LN_CT_Style_aliases:
573 case NS_ooxml::LN_CT_Style_hidden:
574 case NS_ooxml::LN_CT_Style_personal:
575 case NS_ooxml::LN_CT_Style_personalCompose:
576 case NS_ooxml::LN_CT_Style_personalReply:
577 break;
578 case NS_ooxml::LN_CT_Style_autoRedefine:
579 m_pImpl->m_pCurrentEntry->bAutoRedefine = nIntValue;
580 break;
581 case NS_ooxml::LN_CT_Style_tcPr:
583 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
584 if( pProperties.get() && m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
586 auto pTblStylePrHandler = std::make_shared<TblStylePrHandler>(m_pImpl->m_rDMapper);
587 pProperties->resolve(*pTblStylePrHandler);
588 StyleSheetEntry* pEntry = m_pImpl->m_pCurrentEntry.get();
589 TableStyleSheetEntry& rTableEntry = dynamic_cast<TableStyleSheetEntry&>(*pEntry);
590 rTableEntry.AppendInteropGrabBag(pTblStylePrHandler->getInteropGrabBag("tcPr"));
592 // This is a <w:tcPr> directly under <w:style>, so it affects the whole table.
593 rTableEntry.pProperties->InsertProps(pTblStylePrHandler->getProperties());
596 break;
597 case NS_ooxml::LN_CT_Style_trPr:
598 break;
599 case NS_ooxml::LN_CT_Style_rsid:
600 case NS_ooxml::LN_CT_Style_qFormat:
601 case NS_ooxml::LN_CT_Style_semiHidden:
602 case NS_ooxml::LN_CT_Style_unhideWhenUsed:
603 case NS_ooxml::LN_CT_Style_uiPriority:
604 case NS_ooxml::LN_CT_Style_link:
605 case NS_ooxml::LN_CT_Style_locked:
606 if (m_pImpl->m_pCurrentEntry->nStyleTypeCode != STYLE_TYPE_UNKNOWN)
608 StyleSheetEntryPtr pEntry = m_pImpl->m_pCurrentEntry;
609 beans::PropertyValue aValue;
610 switch (nSprmId)
612 case NS_ooxml::LN_CT_Style_rsid:
614 // We want the rsid as a hex string, but always with the length of 8.
615 OUStringBuffer aBuf = OUString::number(nIntValue, 16);
616 OUStringBuffer aStr;
617 comphelper::string::padToLength(aStr, 8 - aBuf.getLength(), '0');
618 aStr.append(aBuf.getStr());
620 aValue.Name = "rsid";
621 aValue.Value <<= aStr.makeStringAndClear();
623 break;
624 case NS_ooxml::LN_CT_Style_qFormat:
625 aValue.Name = "qFormat";
626 break;
627 case NS_ooxml::LN_CT_Style_semiHidden:
628 aValue.Name = "semiHidden";
629 break;
630 case NS_ooxml::LN_CT_Style_unhideWhenUsed:
631 aValue.Name = "unhideWhenUsed";
632 break;
633 case NS_ooxml::LN_CT_Style_uiPriority:
635 aValue.Name = "uiPriority";
636 aValue.Value <<= OUString::number(nIntValue);
638 break;
639 case NS_ooxml::LN_CT_Style_link:
641 aValue.Name = "link";
642 aValue.Value <<= sStringValue;
644 break;
645 case NS_ooxml::LN_CT_Style_locked:
646 aValue.Name = "locked";
647 break;
649 pEntry->AppendInteropGrabBag(aValue);
651 break;
652 case NS_ooxml::LN_CT_Style_tblPr: //contains table properties
653 case NS_ooxml::LN_CT_Style_tblStylePr: //contains to table properties
654 case NS_ooxml::LN_CT_TblPrBase_tblInd: //table properties - at least width value and type
655 case NS_ooxml::LN_EG_RPrBase_rFonts: //table fonts
657 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
658 if( pProperties.get())
660 auto pTblStylePrHandler = std::make_shared<TblStylePrHandler>( m_pImpl->m_rDMapper );
661 pProperties->resolve( *pTblStylePrHandler );
663 // Add the properties to the table style
664 TblStyleType nType = pTblStylePrHandler->getType( );
665 PropertyMapPtr pProps = pTblStylePrHandler->getProperties( );
666 StyleSheetEntry * pEntry = m_pImpl->m_pCurrentEntry.get();
668 TableStyleSheetEntry * pTableEntry = dynamic_cast<TableStyleSheetEntry*>( pEntry );
669 if (nType == TBL_STYLE_UNKNOWN)
671 pEntry->pProperties->InsertProps(pProps);
673 else
675 if (pTableEntry != nullptr)
676 pTableEntry->AddTblStylePr( nType, pProps );
679 if (nSprmId == NS_ooxml::LN_CT_Style_tblPr)
681 if (pTableEntry != nullptr)
682 pTableEntry->AppendInteropGrabBag(pTblStylePrHandler->getInteropGrabBag("tblPr"));
684 else if (nSprmId == NS_ooxml::LN_CT_Style_tblStylePr)
686 pTblStylePrHandler->appendInteropGrabBag("type", pTblStylePrHandler->getTypeString());
687 if (pTableEntry != nullptr)
688 pTableEntry->AppendInteropGrabBag(pTblStylePrHandler->getInteropGrabBag("tblStylePr"));
691 break;
693 case NS_ooxml::LN_CT_PPrDefault_pPr:
694 case NS_ooxml::LN_CT_DocDefaults_pPrDefault:
695 m_pImpl->m_rDMapper.PushStyleSheetProperties( m_pImpl->m_pDefaultParaProps );
696 resolveSprmProps( m_pImpl->m_rDMapper, rSprm );
697 if ( nSprmId == NS_ooxml::LN_CT_DocDefaults_pPrDefault && m_pImpl->m_pDefaultParaProps.get() &&
698 !m_pImpl->m_pDefaultParaProps->isSet( PROP_PARA_TOP_MARGIN ) )
700 SetDefaultParaProps( PROP_PARA_TOP_MARGIN, uno::makeAny( sal_Int32(0) ) );
702 m_pImpl->m_rDMapper.PopStyleSheetProperties();
703 applyDefaults( true );
704 m_pImpl->m_bHasImportedDefaultParaProps = true;
705 break;
706 case NS_ooxml::LN_CT_RPrDefault_rPr:
707 case NS_ooxml::LN_CT_DocDefaults_rPrDefault:
708 m_pImpl->m_rDMapper.PushStyleSheetProperties( m_pImpl->m_pDefaultCharProps );
709 resolveSprmProps( m_pImpl->m_rDMapper, rSprm );
710 m_pImpl->m_rDMapper.PopStyleSheetProperties();
711 applyDefaults( false );
712 break;
713 case NS_ooxml::LN_CT_TblPrBase_jc: //table alignment - row properties!
714 m_pImpl->m_pCurrentEntry->pProperties->Insert( PROP_HORI_ORIENT,
715 uno::makeAny( ConversionHelper::convertTableJustification( nIntValue )));
716 break;
717 case NS_ooxml::LN_CT_TrPrBase_jc: //table alignment - row properties!
718 break;
719 case NS_ooxml::LN_CT_TblPrBase_tblBorders: //table borders, might be defined in table style
721 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
722 if( pProperties.get())
724 auto pBorderHandler = std::make_shared<BorderHandler>(m_pImpl->m_rDMapper.IsOOXMLImport());
725 pProperties->resolve(*pBorderHandler);
726 m_pImpl->m_pCurrentEntry->pProperties->InsertProps(
727 pBorderHandler->getProperties());
730 break;
731 case NS_ooxml::LN_CT_TblPrBase_tblStyleRowBandSize:
732 case NS_ooxml::LN_CT_TblPrBase_tblStyleColBandSize:
733 break;
734 case NS_ooxml::LN_CT_TblPrBase_tblCellMar:
735 //no cell margins in styles
736 break;
737 case NS_ooxml::LN_CT_LatentStyles_lsdException:
739 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
740 if (pProperties.get())
742 tools::SvRef<LatentStyleHandler> pLatentStyleHandler(new LatentStyleHandler());
743 pProperties->resolve(*pLatentStyleHandler);
744 beans::PropertyValue aValue;
745 aValue.Name = "lsdException";
746 aValue.Value <<= comphelper::containerToSequence(pLatentStyleHandler->getAttributes());
747 m_pImpl->m_pCurrentEntry->aLsdExceptions.push_back(aValue);
750 break;
751 case NS_ooxml::LN_CT_Style_pPr:
752 // no break
753 case NS_ooxml::LN_CT_Style_rPr:
754 // no break
755 default:
757 if (!m_pImpl->m_pCurrentEntry)
758 break;
760 tools::SvRef<TablePropertiesHandler> pTblHandler(new TablePropertiesHandler());
761 pTblHandler->SetProperties( m_pImpl->m_pCurrentEntry->pProperties );
762 if ( !pTblHandler->sprm( rSprm ) )
764 m_pImpl->m_rDMapper.PushStyleSheetProperties( m_pImpl->m_pCurrentEntry->pProperties );
766 PropertyMapPtr pProps(new PropertyMap());
767 if (m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
769 if (nSprmId == NS_ooxml::LN_CT_Style_pPr)
770 m_pImpl->m_rDMapper.enableInteropGrabBag("pPr");
771 else if (nSprmId == NS_ooxml::LN_CT_Style_rPr)
772 m_pImpl->m_rDMapper.enableInteropGrabBag("rPr");
774 m_pImpl->m_rDMapper.sprmWithProps( rSprm, pProps );
775 if (m_pImpl->m_pCurrentEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
777 if (nSprmId == NS_ooxml::LN_CT_Style_pPr || nSprmId == NS_ooxml::LN_CT_Style_rPr)
779 TableStyleSheetEntry* pTableEntry = static_cast<TableStyleSheetEntry *>(m_pImpl->m_pCurrentEntry.get());
780 pTableEntry->AppendInteropGrabBag(m_pImpl->m_rDMapper.getInteropGrabBag());
784 m_pImpl->m_pCurrentEntry->pProperties->InsertProps(pProps);
786 m_pImpl->m_rDMapper.PopStyleSheetProperties( );
789 break;
794 void StyleSheetTable::lcl_entry(writerfilter::Reference<Properties>::Pointer_t ref)
796 //create a new style entry
797 OSL_ENSURE( !m_pImpl->m_pCurrentEntry, "current entry has to be NULL here");
798 StyleSheetEntryPtr pNewEntry( new StyleSheetEntry );
799 m_pImpl->m_pCurrentEntry = pNewEntry;
800 m_pImpl->m_rDMapper.PushStyleSheetProperties( m_pImpl->m_pCurrentEntry->pProperties );
801 ref->resolve(*this);
802 //append it to the table
803 m_pImpl->m_rDMapper.PopStyleSheetProperties();
804 if( !m_pImpl->m_rDMapper.IsOOXMLImport() || !m_pImpl->m_pCurrentEntry->sStyleName.isEmpty())
806 m_pImpl->m_pCurrentEntry->sConvertedStyleName = ConvertStyleName( m_pImpl->m_pCurrentEntry->sStyleName );
807 m_pImpl->m_aStyleSheetEntries.push_back( m_pImpl->m_pCurrentEntry );
809 else
811 //TODO: this entry contains the default settings - they have to be added to the settings
814 if (!m_pImpl->m_pCurrentEntry->aLatentStyles.empty())
816 // We have latent styles for this entry, then process them.
817 std::vector<beans::PropertyValue>& rLatentStyles = m_pImpl->m_pCurrentEntry->aLatentStyles;
819 if (!m_pImpl->m_pCurrentEntry->aLsdExceptions.empty())
821 std::vector<beans::PropertyValue>& rLsdExceptions = m_pImpl->m_pCurrentEntry->aLsdExceptions;
822 beans::PropertyValue aValue;
823 aValue.Name = "lsdExceptions";
824 aValue.Value <<= comphelper::containerToSequence(rLsdExceptions);
825 rLatentStyles.push_back(aValue);
828 uno::Sequence<beans::PropertyValue> aLatentStyles( comphelper::containerToSequence(rLatentStyles) );
830 // We can put all latent style info directly to the document interop
831 // grab bag, as we can be sure that only a single style entry has
832 // latent style info.
833 uno::Reference<beans::XPropertySet> xPropertySet(m_pImpl->m_xTextDocument, uno::UNO_QUERY);
834 auto aGrabBag = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(xPropertySet->getPropertyValue("InteropGrabBag").get< uno::Sequence<beans::PropertyValue> >());
835 beans::PropertyValue aValue;
836 aValue.Name = "latentStyles";
837 aValue.Value <<= aLatentStyles;
838 aGrabBag.push_back(aValue);
839 xPropertySet->setPropertyValue("InteropGrabBag", uno::makeAny(comphelper::containerToSequence(aGrabBag)));
842 StyleSheetEntryPtr pEmptyEntry;
843 m_pImpl->m_pCurrentEntry = pEmptyEntry;
845 /*-------------------------------------------------------------------------
846 sorting helper
847 -----------------------------------------------------------------------*/
848 namespace {
850 class PropValVector
852 std::vector<beans::PropertyValue> m_aValues;
853 public:
854 PropValVector(){}
856 void Insert(const beans::PropertyValue& rVal);
857 uno::Sequence< uno::Any > getValues();
858 uno::Sequence< OUString > getNames();
859 const std::vector<beans::PropertyValue>& getProperties() const { return m_aValues; };
864 void PropValVector::Insert(const beans::PropertyValue& rVal)
866 auto aIt = std::find_if(m_aValues.begin(), m_aValues.end(),
867 [&rVal](beans::PropertyValue& rPropVal) { return rPropVal.Name > rVal.Name; });
868 if (aIt != m_aValues.end())
870 m_aValues.insert( aIt, rVal );
871 return;
873 m_aValues.push_back(rVal);
876 uno::Sequence< uno::Any > PropValVector::getValues()
878 std::vector<uno::Any> aRet;
879 std::transform(m_aValues.begin(), m_aValues.end(), std::back_inserter(aRet), [](const beans::PropertyValue& rValue) { return rValue.Value; });
880 return comphelper::containerToSequence(aRet);
883 uno::Sequence< OUString > PropValVector::getNames()
885 std::vector<OUString> aRet;
886 std::transform(m_aValues.begin(), m_aValues.end(), std::back_inserter(aRet), [](const beans::PropertyValue& rValue) { return rValue.Name; });
887 return comphelper::containerToSequence(aRet);
890 void StyleSheetTable::ApplyNumberingStyleNameToParaStyles()
894 uno::Reference< style::XStyleFamiliesSupplier > xStylesSupplier( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW );
895 uno::Reference< lang::XMultiServiceFactory > xDocFactory( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW );
896 uno::Reference< container::XNameAccess > xStyleFamilies = xStylesSupplier->getStyleFamilies();
897 uno::Reference<container::XNameContainer> xParaStyles;
898 xStyleFamilies->getByName(getPropertyName( PROP_PARAGRAPH_STYLES )) >>= xParaStyles;
900 if ( !xParaStyles.is() )
901 return;
903 for ( auto& pEntry : m_pImpl->m_aStyleSheetEntries )
905 StyleSheetPropertyMap* pStyleSheetProperties = nullptr;
906 if ( pEntry->nStyleTypeCode == STYLE_TYPE_PARA && (pStyleSheetProperties = dynamic_cast<StyleSheetPropertyMap*>(pEntry->pProperties.get())) )
908 // ListId 0 means turn off numbering - to cancel inheritance - so make sure that can be set.
909 // Ignore the special "chapter numbering" outline styles as they are handled internally.
910 if ( pStyleSheetProperties->GetListId() > -1 && pStyleSheetProperties->GetOutlineLevel() == -1 )
912 uno::Reference< style::XStyle > xStyle;
913 xParaStyles->getByName( ConvertStyleName(pEntry->sStyleName) ) >>= xStyle;
915 if ( !xStyle.is() )
916 break;
918 uno::Reference<beans::XPropertySet> xPropertySet( xStyle, uno::UNO_QUERY_THROW );
919 const OUString sNumberingStyleName = m_pImpl->m_rDMapper.GetListStyleName( pStyleSheetProperties->GetListId() );
920 if ( !sNumberingStyleName.isEmpty() || !pStyleSheetProperties->GetListId() )
921 xPropertySet->setPropertyValue( getPropertyName(PROP_NUMBERING_STYLE_NAME), uno::makeAny(sNumberingStyleName) );
926 catch( const uno::Exception& )
928 DBG_UNHANDLED_EXCEPTION("writerfilter", "Failed applying numbering style name to Paragraph styles");
932 void StyleSheetTable::ApplyStyleSheets( const FontTablePtr& rFontTable )
936 uno::Reference< style::XStyleFamiliesSupplier > xStylesSupplier( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW );
937 uno::Reference< lang::XMultiServiceFactory > xDocFactory( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW );
938 uno::Reference< container::XNameAccess > xStyleFamilies = xStylesSupplier->getStyleFamilies();
939 uno::Reference<container::XNameContainer> xCharStyles;
940 uno::Reference<container::XNameContainer> xParaStyles;
941 uno::Reference<container::XNameContainer> xNumberingStyles;
943 xStyleFamilies->getByName(getPropertyName( PROP_CHARACTER_STYLES )) >>= xCharStyles;
944 xStyleFamilies->getByName(getPropertyName( PROP_PARAGRAPH_STYLES )) >>= xParaStyles;
945 xStyleFamilies->getByName("NumberingStyles") >>= xNumberingStyles;
946 if(xCharStyles.is() && xParaStyles.is())
948 std::vector< ::std::pair<OUString, uno::Reference<style::XStyle>> > aMissingParent;
949 std::vector< ::std::pair<OUString, uno::Reference<style::XStyle>> > aMissingFollow;
950 std::vector<beans::PropertyValue> aTableStylesVec;
951 for( auto& pEntry : m_pImpl->m_aStyleSheetEntries )
953 if( pEntry->nStyleTypeCode == STYLE_TYPE_CHAR || pEntry->nStyleTypeCode == STYLE_TYPE_PARA || pEntry->nStyleTypeCode == STYLE_TYPE_LIST )
955 bool bParaStyle = pEntry->nStyleTypeCode == STYLE_TYPE_PARA;
956 bool bListStyle = pEntry->nStyleTypeCode == STYLE_TYPE_LIST;
957 bool bInsert = false;
958 uno::Reference< container::XNameContainer > xStyles = bParaStyle ? xParaStyles : (bListStyle ? xNumberingStyles : xCharStyles);
959 uno::Reference< style::XStyle > xStyle;
960 const OUString sConvertedStyleName = ConvertStyleName( pEntry->sStyleName );
962 if(xStyles->hasByName( sConvertedStyleName ))
964 // When pasting, don't update existing styles.
965 if (!m_pImpl->m_bIsNewDoc)
967 continue;
969 xStyles->getByName( sConvertedStyleName ) >>= xStyle;
972 StyleSheetTable_Impl::SetPropertiesToDefault(xStyle);
974 // resolve import conflicts with built-in styles (only if defaults have been defined)
975 if ( m_pImpl->m_bHasImportedDefaultParaProps
976 && pEntry->sBaseStyleIdentifier.isEmpty() //imported style has no inheritance
977 && !xStyle->getParentStyle().isEmpty() ) //built-in style has a default inheritance
979 xStyle->setParentStyle( "" );
983 else
985 bInsert = true;
986 xStyle.set(xDocFactory->createInstance(
987 bParaStyle ?
988 getPropertyName( PROP_SERVICE_PARA_STYLE ) :
989 (bListStyle ? OUString("com.sun.star.style.NumberingStyle") : getPropertyName( PROP_SERVICE_CHAR_STYLE ))),
990 uno::UNO_QUERY_THROW);
992 // Numbering styles have to be inserted early, as e.g. the NumberingRules property is only available after insertion.
993 if (bListStyle)
995 xStyles->insertByName( sConvertedStyleName, uno::makeAny( xStyle ) );
996 xStyle.set(xStyles->getByName(sConvertedStyleName), uno::UNO_QUERY_THROW);
998 StyleSheetPropertyMap* pPropertyMap = dynamic_cast<StyleSheetPropertyMap*>(pEntry->pProperties.get());
999 if (pPropertyMap && pPropertyMap->GetListId() == -1)
1001 // No properties? Word default is 'none', Writer one is 'arabic', handle this.
1002 uno::Reference<beans::XPropertySet> xPropertySet(xStyle, uno::UNO_QUERY_THROW);
1003 uno::Reference<container::XIndexReplace> xNumberingRules;
1004 xPropertySet->getPropertyValue("NumberingRules") >>= xNumberingRules;
1005 uno::Reference<container::XIndexAccess> xIndexAccess(xNumberingRules, uno::UNO_QUERY_THROW);
1006 for (sal_Int32 i = 0; i < xIndexAccess->getCount(); ++i)
1008 uno::Sequence< beans::PropertyValue > aLvlProps(1);
1009 aLvlProps[0].Name = "NumberingType";
1010 aLvlProps[0].Value <<= style::NumberingType::NUMBER_NONE;
1011 xNumberingRules->replaceByIndex(i, uno::makeAny(aLvlProps));
1012 xPropertySet->setPropertyValue("NumberingRules", uno::makeAny(xNumberingRules));
1017 if( !pEntry->sBaseStyleIdentifier.isEmpty() )
1021 //TODO: Handle cases where a paragraph <> character style relation is needed
1022 StyleSheetEntryPtr pParent = FindStyleSheetByISTD( pEntry->sBaseStyleIdentifier );
1023 // Writer core doesn't support numbering styles having a parent style, it seems
1024 if (pParent.get() != nullptr && !bListStyle)
1026 const OUString sParentStyleName = ConvertStyleName( pParent->sStyleName );
1027 if ( !sParentStyleName.isEmpty() && !xStyles->hasByName( sParentStyleName ) )
1028 aMissingParent.emplace_back( sParentStyleName, xStyle );
1029 else
1030 xStyle->setParentStyle( sParentStyleName );
1033 catch( const uno::RuntimeException& )
1035 OSL_FAIL( "Styles parent could not be set");
1038 else if( bParaStyle )
1040 // Paragraph styles that don't inherit from some parent need to apply the DocDefaults
1041 pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bOverwrite=*/false );
1043 //now it's time to set the default parameters - for paragraph styles
1044 //Fonts: Western first entry in font table
1045 //CJK: second entry
1046 //CTL: third entry, if it exists
1048 sal_uInt32 nFontCount = rFontTable->size();
1049 if( !m_pImpl->m_rDMapper.IsOOXMLImport() && nFontCount > 2 )
1051 uno::Any aTwoHundredFortyTwip = uno::makeAny(12.);
1053 // font size to 240 twip (12 pts) for all if not set
1054 pEntry->pProperties->Insert(PROP_CHAR_HEIGHT, aTwoHundredFortyTwip, false);
1056 // western font not already set -> apply first font
1057 const FontEntry::Pointer_t pWesternFontEntry(rFontTable->getFontEntry( 0 ));
1058 OUString sWesternFontName = pWesternFontEntry->sFontName;
1059 pEntry->pProperties->Insert(PROP_CHAR_FONT_NAME, uno::makeAny( sWesternFontName ), false);
1061 // CJK ... apply second font
1062 const FontEntry::Pointer_t pCJKFontEntry(rFontTable->getFontEntry( 2 ));
1063 pEntry->pProperties->Insert(PROP_CHAR_FONT_NAME_ASIAN, uno::makeAny( pCJKFontEntry->sFontName ), false);
1064 pEntry->pProperties->Insert(PROP_CHAR_HEIGHT_ASIAN, aTwoHundredFortyTwip, false);
1066 // CTL ... apply third font, if available
1067 if( nFontCount > 3 )
1069 const FontEntry::Pointer_t pCTLFontEntry(rFontTable->getFontEntry( 3 ));
1070 pEntry->pProperties->Insert(PROP_CHAR_FONT_NAME_COMPLEX, uno::makeAny( pCTLFontEntry->sFontName ), false);
1071 pEntry->pProperties->Insert(PROP_CHAR_HEIGHT_COMPLEX, aTwoHundredFortyTwip, false);
1076 auto aPropValues = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(pEntry->pProperties->GetPropertyValues());
1078 if( bParaStyle )
1080 // delay adding FollowStyle property: all styles need to be created first
1081 if ( !pEntry->sNextStyleIdentifier.isEmpty() )
1083 StyleSheetEntryPtr pFollowStyle = FindStyleSheetByISTD( pEntry->sNextStyleIdentifier );
1084 if ( pFollowStyle && !pFollowStyle->sStyleName.isEmpty() )
1085 aMissingFollow.emplace_back( ConvertStyleName( pFollowStyle->sStyleName ), xStyle );
1088 // Set the outline levels
1089 StyleSheetPropertyMap* pStyleSheetProperties = dynamic_cast<StyleSheetPropertyMap*>(pEntry ? pEntry->pProperties.get() : nullptr);
1091 if ( pStyleSheetProperties )
1093 beans::PropertyValue aLvlVal( getPropertyName( PROP_OUTLINE_LEVEL ), 0,
1094 uno::makeAny( sal_Int16( pStyleSheetProperties->GetOutlineLevel( ) + 1 ) ),
1095 beans::PropertyState_DIRECT_VALUE );
1096 aPropValues.push_back(aLvlVal);
1098 // tdf#95495 missing list level settings in custom styles in old DOCX: apply settings of the parent style
1099 if (pStyleSheetProperties->GetListLevel() == -1 && pStyleSheetProperties->GetOutlineLevel() == -1)
1101 const beans::PropertyValues aPropGrabBag = pEntry->GetInteropGrabBagSeq();
1102 for (const auto& rVal : aPropGrabBag)
1104 if (rVal.Name == "customStyle" && rVal.Value == true)
1106 OUString sBaseId = pEntry->sBaseStyleIdentifier;
1107 for (const auto& aSheetProps : m_pImpl->m_aStyleSheetEntries)
1109 if (aSheetProps->sStyleIdentifierD == sBaseId)
1111 StyleSheetPropertyMap& rStyleSheetProps
1112 = dynamic_cast<StyleSheetPropertyMap&>(*aSheetProps->pProperties);
1113 pStyleSheetProperties->SetListLevel(rStyleSheetProps.GetListLevel());
1114 pStyleSheetProperties->SetOutlineLevel(rStyleSheetProps.GetOutlineLevel());
1115 pStyleSheetProperties->SetNumId(rStyleSheetProps.GetNumId());
1116 break;
1124 uno::Reference< beans::XPropertyState >xState( xStyle, uno::UNO_QUERY_THROW );
1125 if( sConvertedStyleName == "Contents Heading" ||
1126 sConvertedStyleName == "User Index Heading" ||
1127 sConvertedStyleName == "Index Heading" )
1129 // remove Left/RightMargin values from TOX heading styles
1130 //left margin is set to NULL by default
1131 xState->setPropertyToDefault(getPropertyName( PROP_PARA_LEFT_MARGIN ));
1133 else if ( sConvertedStyleName == "Text body" )
1134 xState->setPropertyToDefault(getPropertyName( PROP_PARA_BOTTOM_MARGIN ));
1135 else if ( sConvertedStyleName == "Heading 1" ||
1136 sConvertedStyleName == "Heading 2" ||
1137 sConvertedStyleName == "Heading 3" ||
1138 sConvertedStyleName == "Heading 4" ||
1139 sConvertedStyleName == "Heading 5" ||
1140 sConvertedStyleName == "Heading 6" ||
1141 sConvertedStyleName == "Heading 7" ||
1142 sConvertedStyleName == "Heading 8" ||
1143 sConvertedStyleName == "Heading 9" )
1145 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_WEIGHT ));
1146 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_WEIGHT_ASIAN ));
1147 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_WEIGHT_COMPLEX ));
1148 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_POSTURE ));
1149 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_POSTURE_ASIAN ));
1150 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_POSTURE_COMPLEX ));
1151 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_PROP_HEIGHT ));
1152 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_PROP_HEIGHT_ASIAN ));
1153 xState->setPropertyToDefault(getPropertyName( PROP_CHAR_PROP_HEIGHT_COMPLEX));
1158 if ( !aPropValues.empty() )
1160 PropValVector aSortedPropVals;
1161 for (const beans::PropertyValue& rValue : aPropValues)
1163 // Don't add the style name properties
1164 bool bIsParaStyleName = rValue.Name == "ParaStyleName";
1165 bool bIsCharStyleName = rValue.Name == "CharStyleName";
1166 if ( !bIsParaStyleName && !bIsCharStyleName )
1168 aSortedPropVals.Insert(rValue);
1174 uno::Reference< beans::XMultiPropertySet > xMultiPropertySet( xStyle, uno::UNO_QUERY_THROW);
1177 xMultiPropertySet->setPropertyValues( aSortedPropVals.getNames(), aSortedPropVals.getValues() );
1179 catch ( const uno::Exception& )
1181 uno::Reference<beans::XPropertySet> xPropertySet(xStyle, uno::UNO_QUERY_THROW);
1182 for ( const beans::PropertyValue& rValue : aSortedPropVals.getProperties() )
1186 xPropertySet->setPropertyValue( rValue.Name, rValue.Value );
1188 catch ( const uno::Exception& )
1190 SAL_WARN( "writerfilter", "StyleSheetTable::ApplyStyleSheets could not set property " << rValue.Name );
1194 // Duplicate MSWord's single footnote reference into Footnote Characters and Footnote anchor
1195 if( pEntry->sStyleName.equalsIgnoreAsciiCase("footnote reference")
1196 || pEntry->sStyleName.equalsIgnoreAsciiCase("endnote reference") )
1198 uno::Reference< style::XStyle > xCopyStyle;
1199 if( pEntry->sStyleName.equalsIgnoreAsciiCase("footnote reference") )
1200 xStyles->getByName( "Footnote anchor" ) >>= xCopyStyle;
1201 else
1202 xStyles->getByName( "Endnote anchor" ) >>= xCopyStyle;
1204 xMultiPropertySet.set( xCopyStyle, uno::UNO_QUERY_THROW);
1205 xMultiPropertySet->setPropertyValues( aSortedPropVals.getNames(), aSortedPropVals.getValues() );
1208 catch( const lang::WrappedTargetException& rWrapped)
1210 #ifdef DBG_UTIL
1211 OUString aMessage("StyleSheetTable::ApplyStyleSheets: Some style properties could not be set");
1212 beans::UnknownPropertyException aUnknownPropertyException;
1214 if (rWrapped.TargetException >>= aUnknownPropertyException)
1215 aMessage += ": " + aUnknownPropertyException.Message;
1217 SAL_WARN("writerfilter", aMessage);
1218 #else
1219 (void) rWrapped;
1220 #endif
1222 catch( const uno::Exception& )
1224 OSL_FAIL( "Some style properties could not be set");
1227 // Numbering style got inserted earlier.
1228 if(bInsert && !bListStyle)
1230 const OUString sParentStyle = xStyle->getParentStyle();
1231 if( !sParentStyle.isEmpty() && !xStyles->hasByName( sParentStyle ) )
1232 aMissingParent.emplace_back( sParentStyle, xStyle );
1234 xStyles->insertByName( sConvertedStyleName, uno::makeAny( xStyle) );
1237 beans::PropertyValues aGrabBag = pEntry->GetInteropGrabBagSeq();
1238 uno::Reference<beans::XPropertySet> xPropertySet(xStyle, uno::UNO_QUERY);
1239 if (aGrabBag.hasElements())
1241 xPropertySet->setPropertyValue("StyleInteropGrabBag", uno::makeAny(aGrabBag));
1244 // Only paragraph styles support automatic updates.
1245 if (pEntry->bAutoRedefine && bParaStyle)
1246 xPropertySet->setPropertyValue("IsAutoUpdate", uno::makeAny(true));
1248 else if(pEntry->nStyleTypeCode == STYLE_TYPE_TABLE)
1250 // If this is a table style, save its contents as-is for roundtrip purposes.
1251 TableStyleSheetEntry* pTableEntry = static_cast<TableStyleSheetEntry *>(pEntry.get());
1252 aTableStylesVec.push_back(pTableEntry->GetInteropGrabBag());
1254 // if DocDefaults exist, MS Word includes these in the table style definition.
1255 pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultCharProps, /*bOverwrite=*/false );
1256 pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bOverwrite=*/false );
1260 // Update the styles that were created before their parents or next-styles
1261 for( auto const & iter : aMissingParent )
1263 iter.second->setParentStyle( iter.first );
1266 for( auto const & iter : aMissingFollow )
1270 uno::Reference<beans::XPropertySet> xPropertySet(iter.second, uno::UNO_QUERY);
1271 xPropertySet->setPropertyValue( "FollowStyle", uno::makeAny(iter.first) );
1273 catch( uno::Exception & ) {}
1276 if (!aTableStylesVec.empty())
1278 // If we had any table styles, add a new document-level InteropGrabBag entry for them.
1279 uno::Reference<beans::XPropertySet> xPropertySet(m_pImpl->m_xTextDocument, uno::UNO_QUERY);
1280 uno::Any aAny = xPropertySet->getPropertyValue("InteropGrabBag");
1281 auto aGrabBag = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aAny.get< uno::Sequence<beans::PropertyValue> >());
1282 beans::PropertyValue aValue;
1283 aValue.Name = "tableStyles";
1284 aValue.Value <<= comphelper::containerToSequence(aTableStylesVec);
1285 aGrabBag.push_back(aValue);
1286 xPropertySet->setPropertyValue("InteropGrabBag", uno::makeAny(comphelper::containerToSequence(aGrabBag)));
1290 catch( const uno::Exception& )
1292 DBG_UNHANDLED_EXCEPTION("writerfilter", "Styles could not be imported completely");
1297 StyleSheetEntryPtr StyleSheetTable::FindStyleSheetByISTD(const OUString& sIndex)
1299 StyleSheetEntryPtr pRet;
1300 for(const StyleSheetEntryPtr & rpEntry : m_pImpl->m_aStyleSheetEntries)
1302 if( rpEntry->sStyleIdentifierD == sIndex)
1304 pRet = rpEntry;
1305 break;
1308 return pRet;
1312 StyleSheetEntryPtr StyleSheetTable::FindStyleSheetByConvertedStyleName(const OUString& sIndex)
1314 StyleSheetEntryPtr pRet;
1315 for(const StyleSheetEntryPtr & rpEntry : m_pImpl->m_aStyleSheetEntries)
1317 if( rpEntry->sConvertedStyleName == sIndex)
1319 pRet = rpEntry;
1320 break;
1323 return pRet;
1327 StyleSheetEntryPtr StyleSheetTable::FindDefaultParaStyle()
1329 return FindStyleSheetByISTD( m_pImpl->m_sDefaultParaStyleName );
1332 const StyleSheetEntryPtr & StyleSheetTable::GetCurrentEntry() const
1334 return m_pImpl->m_pCurrentEntry;
1337 OUString StyleSheetTable::ConvertStyleName( const OUString& rWWName, bool bExtendedSearch)
1339 OUString sRet( rWWName );
1340 if( bExtendedSearch )
1342 //search for the rWWName in the IdentifierD of the existing styles and convert the sStyleName member
1343 //TODO: performance issue - put styles list into a map sorted by its sStyleIdentifierD members
1344 for( const auto& rStyleSheetEntryPtr : m_pImpl->m_aStyleSheetEntries )
1346 if( rWWName == rStyleSheetEntryPtr->sStyleIdentifierD )
1347 sRet = rStyleSheetEntryPtr->sStyleName;
1351 // create a map only once
1352 static const StringPairMap_t StyleNameMap{
1353 { "Normal", "Standard" },
1354 { "heading 1", "Heading 1" },
1355 { "heading 2", "Heading 2" },
1356 { "heading 3", "Heading 3" },
1357 { "heading 4", "Heading 4" },
1358 { "heading 5", "Heading 5" },
1359 { "heading 6", "Heading 6" },
1360 { "heading 7", "Heading 7" },
1361 { "heading 8", "Heading 8" },
1362 { "heading 9", "Heading 9" },
1363 { "Heading 1", "Heading 1" },
1364 { "Heading 2", "Heading 2" },
1365 { "Heading 3", "Heading 3" },
1366 { "Heading 4", "Heading 4" },
1367 { "Heading 5", "Heading 5" },
1368 { "Heading 6", "Heading 6" },
1369 { "Heading 7", "Heading 7" },
1370 { "Heading 8", "Heading 8" },
1371 { "Heading 9", "Heading 9" },
1372 { "Index 1", "Index 1" },
1373 { "Index 2", "Index 2" },
1374 { "Index 3", "Index 3" },
1375 // { "Index 4", "" },
1376 // { "Index 5", "" },
1377 // { "Index 6", "" },
1378 // { "Index 7", "" },
1379 // { "Index 8", "" },
1380 // { "Index 9", "" },
1381 { "TOC 1", "Contents 1" },
1382 { "TOC 2", "Contents 2" },
1383 { "TOC 3", "Contents 3" },
1384 { "TOC 4", "Contents 4" },
1385 { "TOC 5", "Contents 5" },
1386 { "TOC 6", "Contents 6" },
1387 { "TOC 7", "Contents 7" },
1388 { "TOC 8", "Contents 8" },
1389 { "TOC 9", "Contents 9" },
1390 { "TOCHeading", "Contents Heading" },
1391 { "toc 1", "Contents 1" },
1392 { "toc 2", "Contents 2" },
1393 { "toc 3", "Contents 3" },
1394 { "toc 4", "Contents 4" },
1395 { "toc 5", "Contents 5" },
1396 { "toc 6", "Contents 6" },
1397 { "toc 7", "Contents 7" },
1398 { "toc 8", "Contents 8" },
1399 { "toc 9", "Contents 9" },
1400 { "TOC1", "Contents 1" },
1401 { "TOC2", "Contents 2" },
1402 { "TOC3", "Contents 3" },
1403 { "TOC4", "Contents 4" },
1404 { "TOC5", "Contents 5" },
1405 { "TOC6", "Contents 6" },
1406 { "TOC7", "Contents 7" },
1407 { "TOC8", "Contents 8" },
1408 { "TOC9", "Contents 9" },
1409 // { "Normal Indent", "" },
1410 { "footnote text", "Footnote" },
1411 { "Footnote Text", "Footnote" },
1412 // { "Annotation Text", "" },
1413 { "Header", "Header" },
1414 { "header", "Header" },
1415 { "Footer", "Footer" },
1416 { "footer", "Footer" },
1417 { "Index Heading", "Index Heading" },
1418 // { "Caption", "" },
1419 // { "Table of Figures", "" },
1420 { "Envelope Address", "Addressee" },
1421 { "Envelope Return", "Sender" },
1422 { "footnote reference", "Footnote Characters" },
1423 { "Footnote Reference", "Footnote Characters" },
1424 // { "Annotation Reference", "" },
1425 { "Line Number", "Line numbering" },
1426 { "Page Number", "Page Number" },
1427 { "endnote reference", "Endnote Characters" },
1428 { "Endnote Reference", "Endnote Characters" },
1429 { "endnote text", "Endnote" },
1430 { "Endnote Text", "Endnote" },
1431 // { "Table of Authorities", "" },
1432 // { "Macro Text", "" },
1433 // { "TOA Heading", "" },
1434 { "List", "List" },
1435 // { "List 2", "" },
1436 // { "List 3", "" },
1437 // { "List 4", "" },
1438 // { "List 5", "" },
1439 // { "List Bullet", "" },
1440 // { "List Bullet 2", "" },
1441 // { "List Bullet 3", "" },
1442 // { "List Bullet 4", "" },
1443 // { "List Bullet 5", "" },
1444 // { "List Number", "" },
1445 // { "List Number 2", "" },
1446 // { "List Number 3", "" },
1447 // { "List Number 4", "" },
1448 // { "List Number 5", "" },
1449 { "Title", "Title" },
1450 // { "Closing", "" },
1451 { "Signature", "Signature" },
1452 // { "Default Paragraph Font", "" },
1453 { "DefaultParagraphFont", "Default Paragraph Font" },
1454 { "Body Text", "Text body" },
1455 { "BodyText", "Text body" },
1456 { "BodyTextIndentItalic", "Text body indent italic" },
1457 { "Body Text Indent", "Text body indent" },
1458 { "BodyTextIndent", "Text body indent" },
1459 { "BodyTextIndent2", "Text body indent2" },
1460 // { "List Continue", "" },
1461 // { "List Continue 2", "" },
1462 // { "List Continue 3", "" },
1463 // { "List Continue 4", "" },
1464 // { "List Continue 5", "" },
1465 // { "Message Header", "" },
1466 { "Subtitle", "Subtitle" },
1467 // { "Salutation", "" },
1468 // { "Date", "" },
1469 { "Body Text First Indent", "Body Text Indent" },
1470 // { "Body Text First Indent 2", "" },
1471 // { "Note Heading", "" },
1472 // { "Body Text 2", "" },
1473 // { "Body Text 3", "" },
1474 // { "Body Text Indent 2", "" },
1475 // { "Body Text Indent 3", "" },
1476 // { "Block Text", "" },
1477 { "Hyperlink", "Internet link" },
1478 { "FollowedHyperlink", "Visited Internet Link" },
1479 { "Emphasis", "Emphasis" },
1480 // { "Document Map", "" },
1481 // { "Plain Text", "" },
1482 { "NoList", "No List" },
1483 { "AbstractHeading", "Abstract Heading" },
1484 { "AbstractBody", "Abstract Body" },
1485 { "PageNumber", "page number" },
1486 { "TableNormal", "Normal Table" },
1487 { "DocumentMap", "Document Map" },
1490 // find style-name using map
1491 if (const auto aIt = StyleNameMap.find(sRet); aIt != StyleNameMap.end())
1493 sRet = aIt->second;
1495 else
1497 // Style names which should not be used without a " (user)" suffix
1498 static const o3tl::sorted_vector<OUString> ReservedStyleNames = [] {
1499 o3tl::sorted_vector<OUString> set;
1500 for (const auto& pair : StyleNameMap)
1501 set.insert(pair.second);
1502 return set;
1503 }();
1504 // SwStyleNameMapper doc says: If the UI style name equals a
1505 // programmatic name, then it must append " (user)" to the end.
1506 if (ReservedStyleNames.find(sRet) != ReservedStyleNames.end())
1507 sRet += " (user)";
1510 return sRet;
1513 void StyleSheetTable::applyDefaults(bool bParaProperties)
1515 try{
1517 if (!m_pImpl->m_bIsNewDoc)
1519 // tdf#72942: do not corrupts original styles in master document
1520 // during inserting of text from second document
1521 return;
1524 if(!m_pImpl->m_xTextDefaults.is())
1526 m_pImpl->m_xTextDefaults.set(
1527 m_pImpl->m_rDMapper.GetTextFactory()->createInstance("com.sun.star.text.Defaults"),
1528 uno::UNO_QUERY_THROW );
1531 // WARNING: these defaults only take effect IF there is a DocDefaults style section. Normally there is, but not always.
1532 if( bParaProperties && m_pImpl->m_pDefaultParaProps.get())
1534 // tdf#87533 LO will have different defaults here, depending on the locale. Import with documented defaults
1535 SetDefaultParaProps(PROP_WRITING_MODE, uno::makeAny(sal_Int16(text::WritingMode_LR_TB)));
1536 SetDefaultParaProps(PROP_PARA_ADJUST, uno::makeAny(sal_Int16(style::ParagraphAdjust_LEFT)));
1538 // Widow/Orphan -> set both to two if not already set
1539 uno::Any aTwo = uno::makeAny(sal_Int8(2));
1540 SetDefaultParaProps(PROP_PARA_WIDOWS, aTwo);
1541 SetDefaultParaProps(PROP_PARA_ORPHANS, aTwo);
1543 uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier(m_pImpl->m_xTextDocument, uno::UNO_QUERY);
1544 uno::Reference<container::XNameAccess> xStyleFamilies = xStylesSupplier->getStyleFamilies();
1545 uno::Reference<container::XNameAccess> xParagraphStyles;
1546 xStyleFamilies->getByName("ParagraphStyles") >>= xParagraphStyles;
1547 uno::Reference<beans::XPropertySet> xDefault;
1548 // This is the built-in default style that every style inherits from
1549 xParagraphStyles->getByName("Paragraph style") >>= xDefault;
1551 const uno::Sequence< beans::PropertyValue > aPropValues = m_pImpl->m_pDefaultParaProps->GetPropertyValues();
1552 for( const auto& rPropValue : aPropValues )
1556 xDefault->setPropertyValue(rPropValue.Name, rPropValue.Value);
1558 catch( const uno::Exception& )
1560 OSL_FAIL( "setPropertyValue exception");
1564 if( !bParaProperties && m_pImpl->m_pDefaultCharProps.get())
1566 // tdf#108350: Earlier in DomainMapper for DOCX, Calibri/11pt was set to match MSWord 2007+,
1567 // but that is valid only if DocDefaults_rPrDefault is omitted.
1568 // Now that DocDefaults_rPrDefault is known, the defaults should be reset to Times New Roman/10pt.
1569 if ( m_pImpl->m_rDMapper.IsOOXMLImport() )
1570 m_pImpl->m_xTextDefaults->setPropertyValue( getPropertyName(PROP_CHAR_FONT_NAME), css::uno::Any(OUString("Times New Roman")) );
1572 const uno::Sequence< beans::PropertyValue > aPropValues = m_pImpl->m_pDefaultCharProps->GetPropertyValues();
1573 for( const auto& rPropValue : aPropValues )
1577 m_pImpl->m_xTextDefaults->setPropertyValue( rPropValue.Name, rPropValue.Value );
1579 catch( const uno::Exception& )
1581 OSL_FAIL( "setPropertyValue exception");
1586 catch( const uno::Exception& )
1592 OUString StyleSheetTable::getOrCreateCharStyle( PropertyValueVector_t& rCharProperties, bool bAlwaysCreate )
1594 //find out if any of the styles already has the required properties then return its name
1595 OUString sListLabel = m_pImpl->HasListCharStyle(rCharProperties);
1596 // Don't try to reuse an existing character style if requested.
1597 if( !sListLabel.isEmpty() && !bAlwaysCreate)
1598 return sListLabel;
1599 const char cListLabel[] = "ListLabel ";
1600 uno::Reference< style::XStyleFamiliesSupplier > xStylesSupplier( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW );
1601 uno::Reference< container::XNameAccess > xStyleFamilies = xStylesSupplier->getStyleFamilies();
1602 uno::Reference<container::XNameContainer> xCharStyles;
1603 xStyleFamilies->getByName("CharacterStyles") >>= xCharStyles;
1604 //search for all character styles with the name sListLabel + <index>
1605 sal_Int32 nStyleFound = 0;
1606 const uno::Sequence< OUString > aStyleNames = xCharStyles->getElementNames();
1607 for( const auto& rStyleName : aStyleNames )
1609 OUString sSuffix;
1610 if( rStyleName.startsWith( cListLabel, &sSuffix ) )
1612 sal_Int32 nSuffix = sSuffix.toInt32();
1613 if( nSuffix > 0 && nSuffix > nStyleFound )
1614 nStyleFound = nSuffix;
1617 sListLabel = cListLabel + OUString::number( ++nStyleFound );
1618 //create a new one otherwise
1619 uno::Reference< lang::XMultiServiceFactory > xDocFactory( m_pImpl->m_xTextDocument, uno::UNO_QUERY_THROW );
1622 uno::Reference< style::XStyle > xStyle( xDocFactory->createInstance(
1623 getPropertyName( PROP_SERVICE_CHAR_STYLE )), uno::UNO_QUERY_THROW);
1624 uno::Reference< beans::XPropertySet > xStyleProps(xStyle, uno::UNO_QUERY_THROW );
1625 for( const auto& rCharProp : rCharProperties)
1629 xStyleProps->setPropertyValue( rCharProp.Name, rCharProp.Value );
1631 catch( const uno::Exception& )
1633 OSL_FAIL( "Exception in StyleSheetTable::getOrCreateCharStyle - Style::setPropertyValue");
1636 xCharStyles->insertByName( sListLabel, uno::makeAny( xStyle) );
1637 m_pImpl->m_aListCharStylePropertyVector.emplace_back( sListLabel, rCharProperties );
1639 catch( const uno::Exception& )
1641 OSL_FAIL( "Exception in StyleSheetTable::getOrCreateCharStyle");
1644 return sListLabel;
1647 }//namespace writerfilter
1649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */