tdf#131321 writerfilter: ApplyNumberingStyleNameToParaStyles()
[LibreOffice.git] / writerfilter / source / dmapper / DomainMapper.cxx
blob12fa4f26090a0b9d7d35959de8f4840223a85bca
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 "BorderHandler.hxx"
20 #include "PageBordersHandler.hxx"
22 #include "util.hxx"
23 #include "SdtHelper.hxx"
24 #include "TagLogger.hxx"
25 #include "TDefTableHandler.hxx"
26 #include "DomainMapper_Impl.hxx"
27 #include "ConversionHelper.hxx"
28 #include "ModelEventListener.hxx"
29 #include "MeasureHandler.hxx"
30 #include <i18nlangtag/languagetag.hxx>
31 #include <i18nutil/paper.hxx>
32 #include <ooxml/resourceids.hxx>
33 #include <oox/token/tokens.hxx>
34 #include <oox/drawingml/drawingmltypes.hxx>
35 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
36 #include <com/sun/star/document/XOOXMLDocumentPropertiesImporter.hpp>
37 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
38 #include <com/sun/star/table/BorderLineStyle.hpp>
39 #include <com/sun/star/table/ShadowFormat.hpp>
40 #include <com/sun/star/text/HoriOrientation.hpp>
41 #include <com/sun/star/text/RelOrientation.hpp>
42 #include <com/sun/star/text/VertOrientation.hpp>
43 #include <com/sun/star/text/WrapTextMode.hpp>
44 #include <com/sun/star/text/SizeType.hpp>
45 #include <com/sun/star/text/XEndnotesSupplier.hpp>
46 #include <com/sun/star/text/XFootnotesSupplier.hpp>
47 #include <com/sun/star/text/XLineNumberingProperties.hpp>
48 #include <com/sun/star/awt/FontRelief.hpp>
49 #include <com/sun/star/awt/FontWeight.hpp>
50 #include <com/sun/star/awt/FontUnderline.hpp>
51 #include <com/sun/star/awt/FontStrikeout.hpp>
52 #include <com/sun/star/awt/FontSlant.hpp>
53 #include <com/sun/star/document/XEventBroadcaster.hpp>
54 #include <com/sun/star/style/ParagraphAdjust.hpp>
55 #include <com/sun/star/style/BreakType.hpp>
56 #include <com/sun/star/style/CaseMap.hpp>
57 #include <com/sun/star/style/LineSpacing.hpp>
58 #include <com/sun/star/style/LineSpacingMode.hpp>
59 #include <com/sun/star/text/FootnoteNumbering.hpp>
60 #include <com/sun/star/text/TextGridMode.hpp>
61 #include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
62 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
63 #include <com/sun/star/text/WritingMode.hpp>
64 #include <com/sun/star/text/WritingMode2.hpp>
65 #include <com/sun/star/text/XFootnote.hpp>
66 #include <com/sun/star/text/XTextColumns.hpp>
67 #include <com/sun/star/text/RubyPosition.hpp>
68 #include <com/sun/star/uno/XComponentContext.hpp>
69 #include <com/sun/star/text/FontEmphasis.hpp>
70 #include <com/sun/star/awt/CharSet.hpp>
71 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
72 #include <comphelper/types.hxx>
73 #include <comphelper/storagehelper.hxx>
74 #include <comphelper/sequence.hxx>
75 #include <editeng/escapementitem.hxx>
76 #include <filter/msfilter/util.hxx>
77 #include <sfx2/DocumentMetadataAccess.hxx>
78 #include <unotools/mediadescriptor.hxx>
80 #include "TextEffectsHandler.hxx"
81 #include "CellColorHandler.hxx"
82 #include "SectionColumnHandler.hxx"
83 #include "GraphicHelpers.hxx"
84 #include <dmapper/GraphicZOrderHelper.hxx>
85 #include <tools/diagnose_ex.h>
86 #include <sal/log.hxx>
88 using namespace ::com::sun::star;
89 using namespace oox;
91 namespace writerfilter::dmapper{
93 struct
95 sal_Int32 h;
96 bool orient;
97 sal_Int32 w;
98 } CT_PageSz;
101 DomainMapper::DomainMapper( const uno::Reference< uno::XComponentContext >& xContext,
102 uno::Reference<io::XInputStream> const& xInputStream,
103 uno::Reference<lang::XComponent> const& xModel,
104 bool bRepairStorage,
105 SourceDocumentType eDocumentType,
106 utl::MediaDescriptor const & rMediaDesc) :
107 LoggedProperties("DomainMapper"),
108 LoggedTable("DomainMapper"),
109 LoggedStream("DomainMapper"),
110 m_pImpl(new DomainMapper_Impl(*this, xContext, xModel, eDocumentType, rMediaDesc)),
111 mbIsSplitPara(false)
112 ,mbHasControls(false)
114 // #i24363# tab stops relative to indent
115 m_pImpl->SetDocumentSettingsProperty(
116 getPropertyName( PROP_TABS_RELATIVE_TO_INDENT ),
117 uno::makeAny( false ) );
118 m_pImpl->SetDocumentSettingsProperty(
119 getPropertyName( PROP_SURROUND_TEXT_WRAP_SMALL ),
120 uno::makeAny( true ) );
121 m_pImpl->SetDocumentSettingsProperty(
122 getPropertyName( PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING ),
123 uno::makeAny( true ) );
125 // Don't load the default style definitions to avoid weird mix
126 m_pImpl->SetDocumentSettingsProperty("StylesNoDefault", uno::makeAny(true));
128 // Initialize RDF metadata, to be able to add statements during the import.
131 uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY_THROW);
132 uno::Reference<embed::XStorage> xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
133 OUString aBaseURL = rMediaDesc.getUnpackedValueOrDefault("URL", OUString());
134 const uno::Reference<frame::XModel> xModel_(xModel,
135 uno::UNO_QUERY_THROW);
136 const uno::Reference<rdf::XURI> xBaseURI(sfx2::createBaseURI(xContext, xModel_, aBaseURL, OUString()));
137 const uno::Reference<task::XInteractionHandler> xHandler;
138 xDocumentMetadataAccess->loadMetadataFromStorage(xStorage, xBaseURI, xHandler);
140 catch (const uno::Exception&)
142 DBG_UNHANDLED_EXCEPTION("writerfilter", "failed to initialize RDF metadata");
145 if (eDocumentType == SourceDocumentType::OOXML) {
146 // tdf#108350
147 // In Word since version 2007, the default document font is Calibri 11 pt.
148 // If a DOCX document doesn't contain font information, we should assume
149 // the intended font to provide best layout match.
152 uno::Reference< beans::XPropertySet > xDefProps(GetTextFactory()->createInstance("com.sun.star.text.Defaults"),
153 uno::UNO_QUERY_THROW);
154 xDefProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME), css::uno::Any(OUString("Calibri")));
155 xDefProps->setPropertyValue(getPropertyName(PROP_CHAR_HEIGHT), css::uno::Any(double(11)));
157 catch (const uno::Exception&)
159 DBG_UNHANDLED_EXCEPTION("writerfilter", "failed to initialize default font");
163 //import document properties
166 uno::Reference< embed::XStorage > xDocumentStorage =
167 comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(OFOPXML_STORAGE_FORMAT_STRING, xInputStream, xContext, bRepairStorage );
169 uno::Reference< uno::XInterface > xTemp = xContext->getServiceManager()->createInstanceWithContext(
170 "com.sun.star.document.OOXMLDocumentPropertiesImporter",
171 xContext);
173 uno::Reference< document::XOOXMLDocumentPropertiesImporter > xImporter( xTemp, uno::UNO_QUERY_THROW );
174 uno::Reference< document::XDocumentPropertiesSupplier > xPropSupplier( xModel, uno::UNO_QUERY_THROW);
175 xImporter->importProperties( xDocumentStorage, xPropSupplier->getDocumentProperties() );
177 catch( const uno::Exception& ) {}
180 DomainMapper::~DomainMapper()
184 uno::Reference< text::XDocumentIndexesSupplier> xIndexesSupplier( m_pImpl->GetTextDocument(), uno::UNO_QUERY );
185 sal_Int32 nIndexes = 0;
186 if( xIndexesSupplier.is() )
188 uno::Reference< container::XIndexAccess > xIndexes = xIndexesSupplier->getDocumentIndexes();
189 nIndexes = xIndexes->getCount();
191 // If we have page references, those need updating as well, similar to the indexes.
192 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(m_pImpl->GetTextDocument(), uno::UNO_QUERY);
193 if(xTextFieldsSupplier.is())
195 uno::Reference<container::XEnumeration> xEnumeration = xTextFieldsSupplier->getTextFields()->createEnumeration();
196 while(xEnumeration->hasMoreElements())
198 ++nIndexes;
199 xEnumeration->nextElement();
203 mbHasControls |= m_pImpl->m_pSdtHelper->hasElements();
204 if ( nIndexes || mbHasControls )
206 //index update has to wait until first view is created
207 uno::Reference< document::XEventBroadcaster > xBroadcaster(xIndexesSupplier, uno::UNO_QUERY);
208 if (xBroadcaster.is())
209 xBroadcaster->addEventListener(uno::Reference< document::XEventListener >(new ModelEventListener(nIndexes, mbHasControls)));
213 // Apply the document settings after everything else
214 m_pImpl->GetSettingsTable()->ApplyProperties( m_pImpl->GetTextDocument( ) );
216 // now that importing is finished, re-enable default styles for any that were never defined/imported.
217 m_pImpl->SetDocumentSettingsProperty("StylesNoDefault", uno::makeAny(false));
219 // Grab-bag handling
220 comphelper::SequenceAsHashMap aProperties;
222 // Add the saved w:themeFontLang setting
223 aProperties["ThemeFontLangProps"] <<= m_pImpl->GetSettingsTable()->GetThemeFontLangProperties();
225 // Add the saved compat settings
226 aProperties["CompatSettings"] <<= m_pImpl->GetSettingsTable()->GetCompatSettings();
228 // Add the saved DocumentProtection settings
229 aProperties["DocumentProtection"] <<= m_pImpl->GetSettingsTable()->GetDocumentProtectionSettings();
231 // Add the saved w:hypenationZone setting
232 aProperties["HyphenationZone"] <<= m_pImpl->GetSettingsTable()->GetHypenationZone();
234 // Add the saved w:doNotHyphenateCaps setting
235 aProperties["NoHyphenateCaps"] <<= m_pImpl->GetSettingsTable()->GetNoHyphenateCaps();
237 uno::Reference<beans::XPropertySet> xDocProps(m_pImpl->GetTextDocument(), uno::UNO_QUERY);
238 if (xDocProps.is())
240 comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue("InteropGrabBag"));
241 aGrabBag.update(aProperties);
242 xDocProps->setPropertyValue("InteropGrabBag", uno::Any(aGrabBag.getAsConstPropertyValueList()));
245 catch( const uno::Exception& ) {}
247 #ifdef DBG_UTIL
248 TagLogger::getInstance().endDocument();
249 #endif
252 void DomainMapper::lcl_attribute(Id nName, Value & val)
254 if (m_pImpl->hasTableManager() && m_pImpl->getTableManager().attribute(nName, val))
255 return;
257 static const int nSingleLineSpacing = 240;
258 sal_Int32 nIntValue = val.getInt();
259 OUString sStringValue = val.getString();
261 SectionPropertyMap * pSectionContext = m_pImpl->GetSectionContext();
262 switch( nName )
264 case NS_ooxml::LN_CT_Lvl_start:
265 break;
266 case NS_ooxml::LN_CT_Lvl_numFmt:
267 break;
268 case NS_ooxml::LN_CT_Lvl_isLgl:
269 break;
270 case NS_ooxml::LN_CT_Lvl_legacy:
271 break;
272 case NS_ooxml::LN_CT_AbstractNum_nsid:
273 break;
274 case NS_ooxml::LN_CT_AbstractNum_tmpl:
275 break;
276 case NS_ooxml::LN_CT_Border_sz:
277 break;
278 case NS_ooxml::LN_CT_Border_val:
279 break;
280 case NS_ooxml::LN_CT_Border_space:
281 break;
282 case NS_ooxml::LN_CT_Border_shadow:
283 break;
284 case NS_ooxml::LN_CT_Border_frame:
285 break;
286 case NS_ooxml::LN_headerr:
287 break;
288 case NS_ooxml::LN_footerr:
289 break;
290 case NS_ooxml::LN_endnote:
291 break;
292 case NS_ooxml::LN_CT_Bookmark_name:
293 m_pImpl->SetBookmarkName( sStringValue );
294 break;
295 case NS_ooxml::LN_CT_MarkupRangeBookmark_id:
296 // add a bookmark range -- this remembers a bookmark starting here
297 // or, if the bookmark was already started or, if the bookmark was
298 // already started before, writes out the bookmark
299 m_pImpl->StartOrEndBookmark( sStringValue );
300 break;
301 case NS_ooxml::LN_CT_MarkupRange_displacedByCustomXml:
302 break;
303 case NS_ooxml::LN_NUMBERING:
304 break;
305 case NS_ooxml::LN_FONTTABLE:
306 break;
307 case NS_ooxml::LN_STYLESHEET:
308 break;
310 case NS_ooxml::LN_CT_Sym_char:
311 m_pImpl->SetSymbolChar(nIntValue);
312 break;
313 case NS_ooxml::LN_CT_Sym_font:
314 m_pImpl->SetSymbolFont(sStringValue);
315 break;
316 case NS_ooxml::LN_CT_Underline_val:
317 if (m_pImpl->GetTopContext())
318 handleUnderlineType(nIntValue, m_pImpl->GetTopContext());
319 break;
320 case NS_ooxml::LN_CT_Color_val:
321 if (m_pImpl->GetTopContext())
322 m_pImpl->GetTopContext()->Insert(PROP_CHAR_COLOR, uno::makeAny( nIntValue ) );
323 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "val", OUString::fromUtf8(msfilter::util::ConvertColor(nIntValue)));
324 break;
325 case NS_ooxml::LN_CT_Underline_color:
326 if (m_pImpl->GetTopContext())
328 m_pImpl->GetTopContext()->Insert(PROP_CHAR_UNDERLINE_HAS_COLOR, uno::makeAny( true ) );
329 m_pImpl->GetTopContext()->Insert(PROP_CHAR_UNDERLINE_COLOR, uno::makeAny( nIntValue ) );
331 break;
333 case NS_ooxml::LN_CT_TabStop_val:
334 if (sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_TabJc_clear)
336 m_pImpl->m_aCurrentTabStop.bDeleted = true;
338 else
340 m_pImpl->m_aCurrentTabStop.bDeleted = false;
341 m_pImpl->m_aCurrentTabStop.Alignment = getTabAlignFromValue(nIntValue);
343 break;
344 case NS_ooxml::LN_CT_TabStop_leader:
345 m_pImpl->m_aCurrentTabStop.FillChar = getFillCharFromValue(nIntValue);
346 break;
347 case NS_ooxml::LN_CT_TabStop_pos:
348 m_pImpl->m_aCurrentTabStop.Position = ConversionHelper::convertTwipToMM100(nIntValue);
349 break;
351 case NS_ooxml::LN_CT_Fonts_ascii:
352 if (m_pImpl->GetTopContext())
354 m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME, uno::makeAny( sStringValue ));
355 if (m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) && m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->isSet(PROP_NUMBERING_RULES))
357 // Font of the paragraph mark should be used for the numbering as well.
358 uno::Reference<beans::XPropertySet> xCharStyle(m_pImpl->GetCurrentNumberingCharStyle());
359 if (xCharStyle.is())
360 xCharStyle->setPropertyValue("CharFontName", uno::makeAny(sStringValue));
363 break;
364 case NS_ooxml::LN_CT_Fonts_asciiTheme:
365 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "asciiTheme", ThemeTable::getStringForTheme(nIntValue));
366 if (m_pImpl->GetTopContext())
368 uno::Any aPropValue = uno::makeAny( m_pImpl->GetThemeTable()->getFontNameForTheme( nIntValue ) );
369 m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME, aPropValue );
370 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_FONT_NAME_ASCII, aPropValue, true, CHAR_GRAB_BAG );
371 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_ASCII, uno::makeAny( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG);
373 break;
374 case NS_ooxml::LN_CT_Fonts_hAnsi:
375 break;//unsupported
376 case NS_ooxml::LN_CT_Fonts_hAnsiTheme:
377 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "hAnsiTheme", ThemeTable::getStringForTheme(nIntValue));
378 if (m_pImpl->GetTopContext())
379 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_H_ANSI, uno::makeAny( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG);
380 break;
381 case NS_ooxml::LN_CT_Fonts_eastAsia:
382 if (m_pImpl->GetTopContext())
383 m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_ASIAN, uno::makeAny( sStringValue ));
384 break;
385 case NS_ooxml::LN_CT_Fonts_eastAsiaTheme:
386 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "eastAsiaTheme", ThemeTable::getStringForTheme(nIntValue));
387 if (m_pImpl->GetTopContext())
389 uno::Any aPropValue = uno::makeAny( m_pImpl->GetThemeTable()->getFontNameForTheme( nIntValue ) );
390 m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_ASIAN, aPropValue );
391 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_FONT_NAME_EAST_ASIA, aPropValue, true, CHAR_GRAB_BAG );
392 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_EAST_ASIA, uno::makeAny( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG);
394 break;
395 case NS_ooxml::LN_CT_Fonts_cs:
396 if (m_pImpl->GetTopContext())
397 m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_COMPLEX, uno::makeAny( sStringValue ));
398 break;
399 case NS_ooxml::LN_CT_Fonts_cstheme:
400 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "cstheme", ThemeTable::getStringForTheme(nIntValue));
401 if (m_pImpl->GetTopContext())
403 uno::Any aPropValue = uno::makeAny( m_pImpl->GetThemeTable()->getFontNameForTheme( nIntValue ) );
404 m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_COMPLEX, aPropValue );
405 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_FONT_NAME_CS, aPropValue, true, CHAR_GRAB_BAG );
406 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_CS, uno::makeAny( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG);
408 break;
409 case NS_ooxml::LN_CT_Spacing_before:
410 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "before", OUString::number(nIntValue));
411 if (m_pImpl->GetTopContext())
412 // Don't overwrite NS_ooxml::LN_CT_Spacing_beforeAutospacing.
413 m_pImpl->GetTopContext()->Insert(PROP_PARA_TOP_MARGIN, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ), false);
414 break;
415 case NS_ooxml::LN_CT_Spacing_beforeLines:
416 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "beforeLines", OUString::number(nIntValue));
417 // We would need to make sure that this doesn't overwrite any
418 // NS_ooxml::LN_CT_Spacing_before in parent styles before style
419 // sheet support can be enabled.
420 if (m_pImpl->GetTopContext() && !IsStyleSheetImport())
421 m_pImpl->GetTopContext()->Insert(PROP_PARA_TOP_MARGIN, uno::makeAny(ConversionHelper::convertTwipToMM100(nIntValue * nSingleLineSpacing / 100)), false);
422 break;
423 case NS_ooxml::LN_CT_Spacing_after:
424 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "after", OUString::number(nIntValue));
425 if (m_pImpl->GetTopContext())
427 // Don't overwrite NS_ooxml::LN_CT_Spacing_afterAutospacing.
428 m_pImpl->GetTopContext()->Insert(PROP_PARA_BOTTOM_MARGIN, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ), false);
430 uno::Any aContextualSpacingFromStyle = m_pImpl->GetPropertyFromParaStyleSheet(PROP_PARA_CONTEXT_MARGIN);
431 if (aContextualSpacingFromStyle.hasValue())
432 // Setting "after" spacing means Writer doesn't inherit
433 // contextual spacing anymore from style, but Word does.
434 m_pImpl->GetTopContext()->Insert(PROP_PARA_CONTEXT_MARGIN, aContextualSpacingFromStyle);
436 break;
437 case NS_ooxml::LN_CT_Spacing_afterLines:
438 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "afterLines", OUString::number(nIntValue));
439 // We would need to make sure that this doesn't overwrite any
440 // NS_ooxml::LN_CT_Spacing_after in parent styles before style
441 // sheet support can be enabled.
442 if (m_pImpl->GetTopContext() && !IsStyleSheetImport())
443 m_pImpl->GetTopContext()->Insert(PROP_PARA_BOTTOM_MARGIN, uno::makeAny(ConversionHelper::convertTwipToMM100(nIntValue * nSingleLineSpacing / 100)), false);
444 break;
445 case NS_ooxml::LN_CT_Spacing_line: //91434
446 case NS_ooxml::LN_CT_Spacing_lineRule: //91435
448 style::LineSpacing aSpacing;
449 PropertyMapPtr pTopContext = m_pImpl->GetTopContext();
450 std::optional<PropertyMap::Property> aLineSpacingVal;
451 if (pTopContext && (aLineSpacingVal = pTopContext->getProperty(PROP_PARA_LINE_SPACING)) )
453 aLineSpacingVal->second >>= aSpacing;
455 else
457 //default to single line spacing
458 aSpacing.Mode = style::LineSpacingMode::FIX;
459 aSpacing.Height = sal_Int16(ConversionHelper::convertTwipToMM100( nSingleLineSpacing ));
461 if( nName == NS_ooxml::LN_CT_Spacing_line )
463 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "line", OUString::number(nIntValue));
464 //now set the value depending on the Mode
465 if( aSpacing.Mode == style::LineSpacingMode::PROP )
466 aSpacing.Height = sal_Int16(nIntValue * 100 / nSingleLineSpacing );
467 else
468 aSpacing.Height = sal_Int16(ConversionHelper::convertTwipToMM100( nIntValue ));
470 else //NS_ooxml::LN_CT_Spacing_lineRule:
472 // exactly, atLeast, auto
473 if( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_LineSpacingRule_auto)
475 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "lineRule", "auto");
476 if (aSpacing.Height >= 0)
478 aSpacing.Mode = style::LineSpacingMode::PROP;
479 //reinterpret the already set value
480 aSpacing.Height = sal_Int16( aSpacing.Height * 100 / ConversionHelper::convertTwipToMM100( nSingleLineSpacing ));
482 else
484 // Negative value still means a positive height,
485 // just the mode is "exact".
486 aSpacing.Mode = style::LineSpacingMode::FIX;
487 aSpacing.Height *= -1;
490 else if( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast)
492 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "lineRule", "atLeast");
493 aSpacing.Mode = style::LineSpacingMode::MINIMUM;
495 else // NS_ooxml::LN_Value_doc_ST_LineSpacingRule_exact
497 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "lineRule", "exact");
498 aSpacing.Mode = style::LineSpacingMode::FIX;
501 if (pTopContext)
502 pTopContext->Insert(PROP_PARA_LINE_SPACING, uno::makeAny( aSpacing ));
504 break;
505 case NS_ooxml::LN_CT_Ind_start:
506 case NS_ooxml::LN_CT_Ind_left:
507 if (m_pImpl->GetTopContext())
509 // Word inherits FirstLineIndent property of the numbering, even if ParaLeftMargin is set, Writer does not.
510 // So copy it explicitly, if necessary.
511 sal_Int32 nFirstLineIndent = m_pImpl->getCurrentNumberingProperty("FirstLineIndent");
512 sal_Int32 nIndentAt = m_pImpl->getCurrentNumberingProperty("IndentAt");
514 sal_Int32 nParaLeftMargin = ConversionHelper::convertTwipToMM100(nIntValue);
515 if (nParaLeftMargin != 0 && nIndentAt == nParaLeftMargin)
516 // Avoid direct left margin when it's the same as from the
517 // numbering.
518 break;
520 if (nFirstLineIndent != 0)
521 m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::makeAny(nFirstLineIndent), /*bOverwrite=*/false);
523 m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN,
524 uno::makeAny(nParaLeftMargin));
526 break;
527 case NS_ooxml::LN_CT_Ind_end:
528 case NS_ooxml::LN_CT_Ind_right:
529 if (m_pImpl->GetTopContext())
531 // Word inherits FirstLineIndent/ParaLeftMargin property of the numbering, even if ParaRightMargin is set, Writer does not.
532 // So copy it explicitly, if necessary.
533 sal_Int32 nFirstLineIndent = m_pImpl->getCurrentNumberingProperty("FirstLineIndent");
534 sal_Int32 nParaLeftMargin = m_pImpl->getCurrentNumberingProperty("IndentAt");
536 if (nFirstLineIndent != 0)
537 m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::makeAny(nFirstLineIndent), /*bOverwrite=*/false);
538 if (nParaLeftMargin != 0)
539 m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN, uno::makeAny(nParaLeftMargin), /*bOverwrite=*/false);
541 m_pImpl->GetTopContext()->Insert(
542 PROP_PARA_RIGHT_MARGIN, uno::makeAny( ConversionHelper::convertTwipToMM100(nIntValue ) ));
544 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "right", OUString::number(nIntValue));
545 break;
546 case NS_ooxml::LN_CT_Ind_hanging:
547 if (m_pImpl->GetTopContext())
549 sal_Int32 nValue = ConversionHelper::convertTwipToMM100( nIntValue );
550 m_pImpl->GetTopContext()->Insert(
551 PROP_PARA_FIRST_LINE_INDENT, uno::makeAny( - nValue ));
553 // See above, need to inherit left margin from list style when first is set.
554 sal_Int32 nParaLeftMargin = m_pImpl->getCurrentNumberingProperty("IndentAt");
555 if (nParaLeftMargin != 0)
556 m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN, uno::makeAny(nParaLeftMargin), /*bOverwrite=*/false);
558 break;
559 case NS_ooxml::LN_CT_Ind_firstLine:
560 if (m_pImpl->GetTopContext())
562 sal_Int32 nFirstLineIndent
563 = m_pImpl->getCurrentNumberingProperty("FirstLineIndent");
564 sal_Int32 nParaFirstLineIndent = ConversionHelper::convertTwipToMM100(nIntValue);
565 if (nParaFirstLineIndent != 0 && nFirstLineIndent == nParaFirstLineIndent)
566 // Avoid direct first margin when it's the same as from the
567 // numbering.
568 break;
569 m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT,
570 uno::makeAny(nParaFirstLineIndent));
572 break;
573 case NS_ooxml::LN_CT_Ind_rightChars:
574 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "rightChars", OUString::number(nIntValue));
575 break;
577 case NS_ooxml::LN_CT_EastAsianLayout_id:
578 break;
579 case NS_ooxml::LN_CT_EastAsianLayout_combine:
580 if (m_pImpl->GetTopContext())
581 m_pImpl->GetTopContext()->Insert(PROP_CHAR_COMBINE_IS_ON, uno::makeAny ( nIntValue != 0 ));
582 break;
583 case NS_ooxml::LN_CT_EastAsianLayout_combineBrackets:
584 if (m_pImpl->GetTopContext())
586 OUString sCombinePrefix = getBracketStringFromEnum(nIntValue);
587 OUString sCombineSuffix = getBracketStringFromEnum(nIntValue, false);
588 m_pImpl->GetTopContext()->Insert(PROP_CHAR_COMBINE_PREFIX, uno::makeAny ( sCombinePrefix ));
589 m_pImpl->GetTopContext()->Insert(PROP_CHAR_COMBINE_SUFFIX, uno::makeAny ( sCombineSuffix ));
591 break;
592 case NS_ooxml::LN_CT_EastAsianLayout_vert:
593 if (m_pImpl->GetTopContext())
595 sal_Int16 nRotationAngle = (nIntValue ? 900 : 0);
596 m_pImpl->GetTopContext()->Insert(PROP_CHAR_ROTATION, uno::makeAny ( nRotationAngle ));
598 break;
599 case NS_ooxml::LN_CT_EastAsianLayout_vertCompress:
600 if (m_pImpl->GetTopContext())
601 m_pImpl->GetTopContext()->Insert(PROP_CHAR_ROTATION_IS_FIT_TO_LINE, uno::makeAny ( nIntValue != 0 ));
602 break;
604 case NS_ooxml::LN_CT_PageSz_code:
605 break;
606 case NS_ooxml::LN_CT_PageSz_h:
608 sal_Int32 nHeight = ConversionHelper::convertTwipToMM100(nIntValue);
609 CT_PageSz.h = PaperInfo::sloppyFitPageDimension(nHeight);
611 break;
612 case NS_ooxml::LN_CT_PageSz_orient:
613 CT_PageSz.orient = (nIntValue != static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_PageOrientation_portrait));
614 break;
615 case NS_ooxml::LN_CT_PageSz_w:
617 sal_Int32 nWidth = ConversionHelper::convertTwipToMM100(nIntValue);
618 CT_PageSz.w = PaperInfo::sloppyFitPageDimension(nWidth);
620 break;
622 case NS_ooxml::LN_CT_PageMar_top:
623 m_pImpl->SetPageMarginTwip( PAGE_MAR_TOP, nIntValue );
624 break;
625 case NS_ooxml::LN_CT_PageMar_right:
626 m_pImpl->SetPageMarginTwip( PAGE_MAR_RIGHT, nIntValue );
627 break;
628 case NS_ooxml::LN_CT_PageMar_bottom:
629 m_pImpl->SetPageMarginTwip( PAGE_MAR_BOTTOM, nIntValue );
630 break;
631 case NS_ooxml::LN_CT_PageMar_left:
632 m_pImpl->SetPageMarginTwip( PAGE_MAR_LEFT, nIntValue );
633 break;
634 case NS_ooxml::LN_CT_PageMar_header:
635 m_pImpl->SetPageMarginTwip( PAGE_MAR_HEADER, nIntValue );
636 break;
637 case NS_ooxml::LN_CT_PageMar_footer:
638 m_pImpl->SetPageMarginTwip( PAGE_MAR_FOOTER, nIntValue );
639 break;
640 case NS_ooxml::LN_CT_PageMar_gutter:
641 m_pImpl->SetPageMarginTwip( PAGE_MAR_GUTTER, nIntValue );
642 break;
643 case NS_ooxml::LN_CT_Language_val: //90314
644 case NS_ooxml::LN_CT_Language_eastAsia: //90315
645 case NS_ooxml::LN_CT_Language_bidi: //90316
647 if (nName == NS_ooxml::LN_CT_Language_eastAsia)
648 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "eastAsia", sStringValue);
649 else if (nName == NS_ooxml::LN_CT_Language_val)
650 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "val", sStringValue);
651 else if (nName == NS_ooxml::LN_CT_Language_bidi)
652 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "bidi", sStringValue);
653 lang::Locale aLocale( LanguageTag::convertToLocale( sStringValue));
654 if (m_pImpl->GetTopContext())
655 m_pImpl->GetTopContext()->Insert(NS_ooxml::LN_CT_Language_val== nName ? PROP_CHAR_LOCALE :
656 NS_ooxml::LN_CT_Language_eastAsia == nName ? PROP_CHAR_LOCALE_ASIAN : PROP_CHAR_LOCALE_COMPLEX,
657 uno::makeAny( aLocale ) );
659 break;
660 // See SwWW8ImplReader::GetParagraphAutoSpace() on why these are 100 and 280
661 case NS_ooxml::LN_CT_Spacing_beforeAutospacing:
663 sal_Int32 default_spacing = -1;
664 if (nIntValue)
666 m_pImpl->SetParaAutoBefore(true);
668 default_spacing = 100;
669 if (!m_pImpl->GetSettingsTable()->GetDoNotUseHTMLParagraphAutoSpacing())
671 // 49 is just the old value that should be removed, once the
672 // root cause in SwTabFrm::MakeAll() is fixed.
673 if (m_pImpl->GetSettingsTable()->GetView() == NS_ooxml::LN_Value_doc_ST_View_web)
674 default_spacing = 49;
675 else
676 default_spacing = 280;
678 // required at export (here mainly for StyleSheets) to determine if the setting has changed from grab_bag
679 m_pImpl->GetTopContext()->Insert(PROP_PARA_TOP_MARGIN, uno::makeAny(ConversionHelper::convertTwipToMM100(default_spacing)));
681 m_pImpl->GetTopContext()->Insert( PROP_PARA_TOP_MARGIN_BEFORE_AUTO_SPACING, uno::makeAny( ConversionHelper::convertTwipToMM100(default_spacing) ),true, PARA_GRAB_BAG );
683 break;
684 case NS_ooxml::LN_CT_Spacing_afterAutospacing:
686 sal_Int32 default_spacing = -1;
687 if (nIntValue)
689 default_spacing = 100;
690 if (!m_pImpl->GetSettingsTable()->GetDoNotUseHTMLParagraphAutoSpacing())
692 if (m_pImpl->GetSettingsTable()->GetView() == NS_ooxml::LN_Value_doc_ST_View_web)
693 default_spacing = 49;
694 else
695 default_spacing = 280;
697 m_pImpl->GetTopContext()->Insert(PROP_PARA_BOTTOM_MARGIN, uno::makeAny(ConversionHelper::convertTwipToMM100(default_spacing)));
699 m_pImpl->GetTopContext()->Insert( PROP_PARA_BOTTOM_MARGIN_AFTER_AUTO_SPACING, uno::makeAny( ConversionHelper::convertTwipToMM100(default_spacing) ),true, PARA_GRAB_BAG );
701 break;
702 case NS_ooxml::LN_CT_SmartTagRun_uri:
703 m_pImpl->getSmartTagHandler().setURI(val.getString());
704 break;
705 case NS_ooxml::LN_CT_SmartTagRun_element:
706 m_pImpl->getSmartTagHandler().setElement(val.getString());
707 break;
708 case NS_ooxml::LN_CT_Br_type :
709 //TODO: attributes for break (0x12) are not supported
710 break;
711 case NS_ooxml::LN_CT_Fonts_hint :
712 /* assigns script type to ambiguous characters, values can be:
713 NS_ooxml::LN_Value_ST_Hint_default
714 NS_ooxml::LN_Value_ST_Hint_eastAsia
715 NS_ooxml::LN_Value_ST_Hint_cs
717 //TODO: unsupported?
718 break;
719 case NS_ooxml::LN_CT_TblBorders_right:
720 case NS_ooxml::LN_CT_TblBorders_top:
721 case NS_ooxml::LN_CT_TblBorders_left:
722 case NS_ooxml::LN_CT_TblBorders_bottom:
723 //todo: handle cell mar
724 break;
725 case NS_ooxml::LN_blip: // contains the binary graphic
726 case NS_ooxml::LN_shape:
728 //looks a bit like a hack - and it is. The graphic import is split into the inline_inline part and
729 //afterwards the adding of the binary data.
730 m_pImpl->GetGraphicImport( IMPORT_AS_DETECTED_INLINE )->attribute(nName, val);
731 m_pImpl->ImportGraphic( val.getProperties(), IMPORT_AS_DETECTED_INLINE );
733 break;
734 case NS_ooxml::LN_starmath:
735 m_pImpl->appendStarMath( val );
736 break;
737 case NS_ooxml::LN_CT_FramePr_dropCap:
738 case NS_ooxml::LN_CT_FramePr_lines:
739 case NS_ooxml::LN_CT_FramePr_hAnchor:
740 case NS_ooxml::LN_CT_FramePr_vAnchor:
741 case NS_ooxml::LN_CT_FramePr_x:
742 case NS_ooxml::LN_CT_FramePr_xAlign:
743 case NS_ooxml::LN_CT_FramePr_y:
744 case NS_ooxml::LN_CT_FramePr_yAlign:
745 case NS_ooxml::LN_CT_FramePr_hRule:
746 case NS_ooxml::LN_CT_FramePr_w:
747 case NS_ooxml::LN_CT_FramePr_h:
748 case NS_ooxml::LN_CT_FramePr_wrap:
749 case NS_ooxml::LN_CT_FramePr_hSpace:
750 case NS_ooxml::LN_CT_FramePr_vSpace:
752 ParagraphProperties* pParaProperties = nullptr;
753 // handle frame properties at styles
754 if( m_pImpl->GetTopContextType() == CONTEXT_STYLESHEET )
755 pParaProperties = dynamic_cast< ParagraphProperties*>( m_pImpl->GetTopContextOfType( CONTEXT_STYLESHEET ).get() );
756 else
757 pParaProperties = dynamic_cast< ParagraphProperties*>( m_pImpl->GetTopContextOfType( CONTEXT_PARAGRAPH ).get() );
759 if( pParaProperties )
761 switch( nName )
763 case NS_ooxml::LN_CT_FramePr_dropCap:
764 pParaProperties->SetDropCap( nIntValue );
765 break;
766 case NS_ooxml::LN_CT_FramePr_lines:
767 pParaProperties->SetLines( nIntValue );
768 break;
769 case NS_ooxml::LN_CT_FramePr_hAnchor:
770 switch(nIntValue)
772 case NS_ooxml::LN_Value_doc_ST_HAnchor_text: //relative to column
773 nIntValue = text::RelOrientation::FRAME; break;
774 case NS_ooxml::LN_Value_doc_ST_HAnchor_margin: nIntValue = text::RelOrientation::PAGE_PRINT_AREA; break;
775 case NS_ooxml::LN_Value_doc_ST_HAnchor_page: nIntValue = text::RelOrientation::PAGE_FRAME; break;
776 default:;
778 pParaProperties->SethAnchor( nIntValue );
779 break;
780 case NS_ooxml::LN_CT_FramePr_vAnchor:
781 switch(nIntValue)
783 case NS_ooxml::LN_Value_doc_ST_VAnchor_text: //relative to paragraph
784 nIntValue = text::RelOrientation::FRAME; break;
785 case NS_ooxml::LN_Value_doc_ST_VAnchor_margin:nIntValue = text::RelOrientation::PAGE_PRINT_AREA ; break;
786 case NS_ooxml::LN_Value_doc_ST_VAnchor_page: nIntValue = text::RelOrientation::PAGE_FRAME; break;
787 default:;
789 pParaProperties->SetvAnchor( nIntValue );
790 break;
791 case NS_ooxml::LN_CT_FramePr_x:
792 pParaProperties->Setx( ConversionHelper::convertTwipToMM100(nIntValue ));
793 pParaProperties->SetxAlign( text::HoriOrientation::NONE );
794 break;
795 case NS_ooxml::LN_CT_FramePr_xAlign:
796 switch( nIntValue )
798 case NS_ooxml::LN_Value_doc_ST_XAlign_center : nIntValue = text::HoriOrientation::CENTER; break;
799 case NS_ooxml::LN_Value_doc_ST_XAlign_right : nIntValue = text::HoriOrientation::RIGHT; break;
800 case NS_ooxml::LN_Value_doc_ST_XAlign_inside : nIntValue = text::HoriOrientation::INSIDE; break;
801 case NS_ooxml::LN_Value_doc_ST_XAlign_outside : nIntValue = text::HoriOrientation::OUTSIDE; break;
802 case NS_ooxml::LN_Value_doc_ST_XAlign_left : nIntValue = text::HoriOrientation::LEFT; break;
803 default: nIntValue = text::HoriOrientation::NONE;
805 pParaProperties->SetxAlign( nIntValue );
806 break;
807 case NS_ooxml::LN_CT_FramePr_y:
808 pParaProperties->Sety( ConversionHelper::convertTwipToMM100(nIntValue ));
809 pParaProperties->SetyAlign( text::VertOrientation::NONE );
810 break;
811 case NS_ooxml::LN_CT_FramePr_yAlign:
812 switch( nIntValue )
814 case NS_ooxml::LN_Value_doc_ST_YAlign_top :
815 case NS_ooxml::LN_Value_doc_ST_YAlign_inside :nIntValue = text::VertOrientation::TOP; break;
816 case NS_ooxml::LN_Value_doc_ST_YAlign_center :nIntValue = text::VertOrientation::CENTER;break;
817 case NS_ooxml::LN_Value_doc_ST_YAlign_bottom :
818 case NS_ooxml::LN_Value_doc_ST_YAlign_outside :nIntValue = text::VertOrientation::BOTTOM;break;
819 case NS_ooxml::LN_Value_doc_ST_YAlign_inline :
821 // HACK: This is for bnc#780851, where a table has one cell that has w:framePr,
822 // which causes that paragraph to be converted to a text frame, and the original
823 // paragraph object no longer exists, which makes table creation fail and furthermore
824 // it would be missing in the table layout anyway. So actually no letting that paragraph
825 // be a text frame "fixes" it. I'm not sure what "inline" is supposed to mean in practice
826 // anyway, so as long as this doesn't cause trouble elsewhere ...
827 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
828 if( pContext.get() )
830 ParagraphPropertyMap* pParaContext = dynamic_cast< ParagraphPropertyMap* >( pContext.get() );
831 if (pParaContext)
832 pParaContext->SetFrameMode(false);
834 nIntValue = text::VertOrientation::NONE;
835 break;
837 default:
838 nIntValue = text::VertOrientation::NONE;
839 break;
841 pParaProperties->SetyAlign( nIntValue );
842 break;
843 case NS_ooxml::LN_CT_FramePr_hRule:
844 switch( nIntValue )
846 case NS_ooxml::LN_Value_doc_ST_HeightRule_exact:
847 nIntValue = text::SizeType::FIX;
848 break;
849 case NS_ooxml::LN_Value_doc_ST_HeightRule_atLeast:
850 nIntValue = text::SizeType::MIN;
851 break;
852 case NS_ooxml::LN_Value_doc_ST_HeightRule_auto:
853 //no break;
854 default:;
855 nIntValue = text::SizeType::VARIABLE;
857 pParaProperties->SethRule( nIntValue );
858 break;
859 case NS_ooxml::LN_CT_FramePr_wrap:
861 //should be either LN_Value_doc_ST_Wrap_notBeside or LN_Value_doc_ST_Wrap_around or LN_Value_doc_ST_Wrap_auto
862 OSL_ENSURE( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_around ||
863 sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_notBeside ||
864 sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_through ||
865 sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_none ||
866 sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_auto,
867 "wrap not around, not_Beside, through, none or auto?");
868 if( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_around ||
869 sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_through ||
870 sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_auto )
871 pParaProperties->SetWrap ( text::WrapTextMode_DYNAMIC ) ;
872 else if (sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_none)
873 pParaProperties->SetWrap ( text::WrapTextMode_THROUGH ) ;
874 else
875 pParaProperties->SetWrap ( text::WrapTextMode_NONE ) ;
877 break;
878 case NS_ooxml::LN_CT_FramePr_w:
879 pParaProperties->Setw(ConversionHelper::convertTwipToMM100(nIntValue));
880 break;
881 case NS_ooxml::LN_CT_FramePr_h:
882 pParaProperties->Seth(ConversionHelper::convertTwipToMM100(nIntValue));
883 break;
884 case NS_ooxml::LN_CT_FramePr_hSpace:
885 pParaProperties->SethSpace( ConversionHelper::convertTwipToMM100(nIntValue ));
886 break;
887 case NS_ooxml::LN_CT_FramePr_vSpace:
888 pParaProperties->SetvSpace( ConversionHelper::convertTwipToMM100(nIntValue ));
889 break;
890 default:;
894 break;
895 case NS_ooxml::LN_CT_TrackChange_author:
896 m_pImpl->SetCurrentRedlineAuthor( sStringValue );
897 break;
898 case NS_ooxml::LN_CT_TrackChange_date:
899 m_pImpl->SetCurrentRedlineDate( sStringValue );
900 break;
901 case NS_ooxml::LN_CT_Markup_id:
902 m_pImpl->SetCurrentRedlineId( nIntValue );
903 break;
904 case NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart:
905 m_pImpl->AddAnnotationPosition( true, nIntValue );
906 break;
907 case NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd:
908 m_pImpl->AddAnnotationPosition( false, nIntValue );
909 break;
910 case NS_ooxml::LN_CT_Comment_initials:
911 m_pImpl->SetCurrentRedlineInitials(sStringValue);
912 break;
913 case NS_ooxml::LN_token:
914 m_pImpl->SetCurrentRedlineToken( nIntValue );
915 break;
916 case NS_ooxml::LN_CT_LineNumber_start:
917 case NS_ooxml::LN_CT_LineNumber_distance:
918 case NS_ooxml::LN_CT_LineNumber_countBy:
919 case NS_ooxml::LN_CT_LineNumber_restart:
921 //line numbering in Writer is a global document setting
922 //in Word is a section setting
923 //if line numbering is switched on anywhere in the document it's set at the global settings
924 LineNumberSettings aSettings = m_pImpl->GetLineNumberSettings();
925 switch( nName )
927 case NS_ooxml::LN_CT_LineNumber_countBy:
928 aSettings.nInterval = nIntValue;
929 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
930 if( pSectionContext )
931 pSectionContext->SetLnnMod( nIntValue );
932 break;
933 case NS_ooxml::LN_CT_LineNumber_start:
934 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
935 if( pSectionContext )
936 pSectionContext->SetLnnMin( nIntValue );
937 break;
938 case NS_ooxml::LN_CT_LineNumber_distance:
939 aSettings.nDistance = ConversionHelper::convertTwipToMM100( nIntValue );
940 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
941 if( pSectionContext )
942 pSectionContext->SetdxaLnn( nIntValue );
943 break;
944 case NS_ooxml::LN_CT_LineNumber_restart:
945 aSettings.bRestartAtEachPage = nIntValue == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_LineNumberRestart_newPage);
946 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
947 if( pSectionContext )
948 pSectionContext->SetLnc( nIntValue );
949 break;
950 default:;
952 m_pImpl->SetLineNumberSettings( aSettings );
954 break;
955 case NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows:
956 m_pImpl->StartCustomFootnote(m_pImpl->GetTopContext());
957 break;
958 case NS_ooxml::LN_CT_FtnEdnRef_id:
959 // footnote or endnote reference id - not needed
960 break;
961 case NS_ooxml::LN_CT_Color_themeColor:
962 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "themeColor", TDefTableHandler::getThemeColorTypeString(nIntValue));
963 break;
964 case NS_ooxml::LN_CT_Color_themeTint:
965 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "themeTint", OUString::number(nIntValue, 16));
966 break;
967 case NS_ooxml::LN_CT_Color_themeShade:
968 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "themeShade", OUString::number(nIntValue, 16));
969 break;
970 case NS_ooxml::LN_CT_DocGrid_linePitch:
972 //see SwWW8ImplReader::SetDocumentGrid
973 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
974 if(pSectionContext)
976 pSectionContext->SetGridLinePitch( ConversionHelper::convertTwipToMM100( nIntValue ) );
979 break;
980 case NS_ooxml::LN_CT_DocGrid_charSpace:
982 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
983 if(pSectionContext)
985 pSectionContext->SetDxtCharSpace( nIntValue );
988 break;
989 case NS_ooxml::LN_CT_DocGrid_type:
991 if (pSectionContext != nullptr)
993 switch( nIntValue )
995 case NS_ooxml::LN_Value_doc_ST_DocGrid_default:
996 pSectionContext->SetGridType(text::TextGridMode::NONE);
997 break;
998 case NS_ooxml::LN_Value_doc_ST_DocGrid_lines:
999 pSectionContext->SetGridType(text::TextGridMode::LINES);
1000 break;
1001 case NS_ooxml::LN_Value_doc_ST_DocGrid_linesAndChars:
1002 pSectionContext->SetGridType(text::TextGridMode::LINES_AND_CHARS);
1003 pSectionContext->SetGridSnapToChars( false );
1004 break;
1005 case NS_ooxml::LN_Value_doc_ST_DocGrid_snapToChars:
1006 pSectionContext->SetGridType(text::TextGridMode::LINES_AND_CHARS);
1007 pSectionContext->SetGridSnapToChars( true );
1008 break;
1009 default :
1010 OSL_FAIL("unknown SwTextGrid value");
1014 break;
1015 case NS_ooxml::LN_CT_SdtBlock_sdtContent:
1016 m_pImpl->SetSdt(true);
1017 break;
1018 case NS_ooxml::LN_CT_SdtBlock_sdtEndContent:
1019 m_pImpl->SetSdt(false);
1021 // It's not possible to insert the relevant property to the character context here:
1022 // the previous, already sent character context may be still active, so the property would be lost.
1023 if (m_pImpl->m_pSdtHelper->isOutsideAParagraph())
1024 m_pImpl->setParaSdtEndDeferred(true);
1025 else
1026 m_pImpl->setSdtEndDeferred(true);
1028 if (m_pImpl->m_pSdtHelper->isInsideDropDownControl())
1029 m_pImpl->m_pSdtHelper->createDropDownControl();
1030 else if (m_pImpl->m_pSdtHelper->validateDateFormat())
1031 m_pImpl->m_pSdtHelper->createDateContentControl();
1032 break;
1033 case NS_ooxml::LN_CT_SdtListItem_displayText:
1034 // TODO handle when this is != value
1035 break;
1036 case NS_ooxml::LN_CT_SdtListItem_value:
1037 m_pImpl->m_pSdtHelper->getDropDownItems().push_back(sStringValue);
1038 break;
1039 case NS_ooxml::LN_CT_SdtDate_fullDate:
1040 m_pImpl->m_pSdtHelper->getDate().append(sStringValue);
1041 break;
1042 case NS_ooxml::LN_CT_Background_color:
1043 if (m_pImpl->GetSettingsTable()->GetDisplayBackgroundShape())
1044 m_pImpl->m_oBackgroundColor = nIntValue;
1045 break;
1046 case NS_ooxml::LN_CT_PageNumber_start:
1047 if (pSectionContext != nullptr)
1048 pSectionContext->SetPageNumber(nIntValue);
1049 break;
1050 case NS_ooxml::LN_CT_PageNumber_fmt:
1051 if (pSectionContext)
1053 switch (nIntValue)
1055 case NS_ooxml::LN_Value_ST_NumberFormat_decimal:
1056 // 1, 2, ...
1057 pSectionContext->SetPageNumberType(style::NumberingType::ARABIC);
1058 break;
1059 case NS_ooxml::LN_Value_ST_NumberFormat_upperLetter:
1060 // A, B, ...
1061 pSectionContext->SetPageNumberType(style::NumberingType::CHARS_UPPER_LETTER_N);
1062 break;
1063 case NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter:
1064 // a, b, ...
1065 pSectionContext->SetPageNumberType(style::NumberingType::CHARS_LOWER_LETTER_N);
1066 break;
1067 case NS_ooxml::LN_Value_ST_NumberFormat_upperRoman:
1068 // I, II, ...
1069 pSectionContext->SetPageNumberType(style::NumberingType::ROMAN_UPPER);
1070 break;
1071 case NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman:
1072 // i, ii, ...
1073 pSectionContext->SetPageNumberType(style::NumberingType::ROMAN_LOWER);
1074 break;
1077 break;
1078 case NS_ooxml::LN_CT_FtnEdn_type:
1079 // This is the "separator" footnote, ignore its linebreaks/text.
1080 if (static_cast<sal_uInt32>(nIntValue) == NS_ooxml::LN_Value_doc_ST_FtnEdn_separator)
1081 m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::ON );
1082 else
1083 m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::OFF );
1084 break;
1085 case NS_ooxml::LN_CT_FtnEdn_id:
1087 SkipFootnoteSeparator eSkip = m_pImpl->GetSkipFootnoteState();
1088 if ( eSkip == SkipFootnoteSeparator::ON )
1089 m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::SKIPPING );
1090 else if ( eSkip == SkipFootnoteSeparator::SKIPPING )
1091 m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::OFF );
1093 break;
1094 case NS_ooxml::LN_CT_DataBinding_prefixMappings:
1095 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_prefixMappings", sStringValue);
1096 break;
1097 case NS_ooxml::LN_CT_DataBinding_xpath:
1098 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_xpath", sStringValue);
1099 break;
1100 case NS_ooxml::LN_CT_DataBinding_storeItemID:
1101 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_storeItemID", sStringValue);
1102 break;
1103 case NS_ooxml::LN_CT_PTab_leader:
1104 case NS_ooxml::LN_CT_PTab_relativeTo:
1105 case NS_ooxml::LN_CT_PTab_alignment:
1106 break;
1107 case NS_ooxml::LN_CT_Cnf_lastRowLastColumn:
1108 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRowLastColumn", OUString::number(nIntValue));
1109 break;
1110 case NS_ooxml::LN_CT_Cnf_lastRowFirstColumn:
1111 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRowFirstColumn", OUString::number(nIntValue));
1112 break;
1113 case NS_ooxml::LN_CT_Cnf_firstRowLastColumn:
1114 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstRowLastColumn", OUString::number(nIntValue));
1115 break;
1116 case NS_ooxml::LN_CT_Cnf_oddHBand:
1117 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "oddHBand", OUString::number(nIntValue));
1118 break;
1119 case NS_ooxml::LN_CT_Cnf_firstRowFirstColumn:
1120 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstRowFirstColumn", OUString::number(nIntValue));
1121 break;
1122 case NS_ooxml::LN_CT_Cnf_evenVBand:
1123 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "evenVBand", OUString::number(nIntValue));
1124 break;
1125 case NS_ooxml::LN_CT_Cnf_evenHBand:
1126 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "evenHBand", OUString::number(nIntValue));
1127 break;
1128 case NS_ooxml::LN_CT_Cnf_lastColumn:
1129 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastColumn", OUString::number(nIntValue));
1130 break;
1131 case NS_ooxml::LN_CT_Cnf_firstColumn:
1132 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstColumn", OUString::number(nIntValue));
1133 break;
1134 case NS_ooxml::LN_CT_Cnf_oddVBand:
1135 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "oddVBand", OUString::number(nIntValue));
1136 break;
1137 case NS_ooxml::LN_CT_Cnf_lastRow:
1138 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRow", OUString::number(nIntValue));
1139 break;
1140 case NS_ooxml::LN_CT_Cnf_firstRow:
1141 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstRow", OUString::number(nIntValue));
1142 break;
1143 case NS_ooxml::LN_CT_Cnf_val:
1144 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "val", sStringValue);
1145 break;
1146 case NS_ooxml::LN_CT_DocPartName_val:
1148 m_sGlossaryEntryName = sStringValue;
1149 break;
1151 case NS_ooxml::LN_CT_DocPartGallery_val:
1153 const OUString& sGlossaryEntryGallery = sStringValue;
1154 if(m_pImpl->GetTopContext().get())
1156 OUString sName = sGlossaryEntryGallery + ":" + m_sGlossaryEntryName;
1157 // Add glossary entry name as a first paragraph in section
1158 m_pImpl->appendTextPortion(sName, m_pImpl->GetTopContext());
1160 break;
1162 case NS_ooxml::LN_CT_PermStart_ed:
1164 m_pImpl->setPermissionRangeEd(sStringValue);
1165 break;
1167 case NS_ooxml::LN_CT_PermStart_edGrp:
1169 m_pImpl->setPermissionRangeEdGrp(sStringValue);
1170 break;
1172 case NS_ooxml::LN_CT_PermStart_id:
1174 m_pImpl->startOrEndPermissionRange(nIntValue);
1175 break;
1177 case NS_ooxml::LN_CT_PermEnd_id:
1179 m_pImpl->startOrEndPermissionRange(nIntValue);
1180 break;
1182 case NS_ooxml::LN_CT_NumFmt_val:
1186 uno::Reference<beans::XPropertySet> xFtnEdnSettings;
1187 if (m_pImpl->IsInFootnoteProperties())
1189 uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(
1190 m_pImpl->GetTextDocument(), uno::UNO_QUERY);
1191 if (xFootnotesSupplier.is())
1192 xFtnEdnSettings = xFootnotesSupplier->getFootnoteSettings();
1194 else
1196 uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(
1197 m_pImpl->GetTextDocument(), uno::UNO_QUERY);
1198 if (xEndnotesSupplier.is())
1199 xFtnEdnSettings = xEndnotesSupplier->getEndnoteSettings();
1201 if (xFtnEdnSettings.is())
1203 sal_Int16 nNumType = ConversionHelper::ConvertNumberingType(nIntValue);
1204 xFtnEdnSettings->setPropertyValue(getPropertyName(PROP_NUMBERING_TYPE),
1205 uno::makeAny(nNumType));
1208 catch (const uno::Exception&)
1212 break;
1213 default:
1214 SAL_WARN("writerfilter", "DomainMapper::lcl_attribute: unhandled token: " << nName);
1218 void DomainMapper::lcl_sprm(Sprm & rSprm)
1220 if (!m_pImpl->hasTableManager() || !m_pImpl->getTableManager().sprm(rSprm))
1221 sprmWithProps(rSprm, m_pImpl->GetTopContext());
1224 // In rtl-paragraphs the meaning of left/right are to be exchanged
1225 static bool ExchangeLeftRight(const PropertyMapPtr& rContext, DomainMapper_Impl& rImpl)
1227 bool bExchangeLeftRight = false;
1228 sal_Int32 aAdjust;
1229 uno::Any aPropPara = rImpl.GetAnyProperty(PROP_WRITING_MODE, rContext);
1230 if( (aPropPara >>= aAdjust) && aAdjust == text::WritingMode2::RL_TB )
1231 bExchangeLeftRight = true;
1232 return bExchangeLeftRight;
1235 void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
1237 // These SPRM's are not specific to any section, so it's expected that there is no context yet.
1238 switch (rSprm.getId())
1240 case NS_ooxml::LN_background_background:
1241 return;
1242 break;
1243 default:
1244 break;
1247 OSL_ENSURE(rContext.get(), "PropertyMap has to be valid!");
1248 if(!rContext.get())
1249 return ;
1251 sal_uInt32 nSprmId = rSprm.getId();
1252 //needed for page properties
1253 SectionPropertyMap * pSectionContext = m_pImpl->GetSectionContext();
1254 Value::Pointer_t pValue = rSprm.getValue();
1255 sal_Int32 nIntValue = pValue->getInt();
1256 const OUString sStringValue = pValue->getString();
1258 switch(nSprmId)
1260 case NS_ooxml::LN_CT_PPrBase_jc:
1262 bool bExchangeLeftRight = !IsRTFImport() && ExchangeLeftRight(rContext, *m_pImpl);
1263 handleParaJustification(nIntValue, rContext, bExchangeLeftRight);
1264 break;
1266 case NS_ooxml::LN_CT_PPrBase_keepLines:
1267 rContext->Insert(PROP_PARA_SPLIT, uno::makeAny(nIntValue == 0));
1268 break;
1269 case NS_ooxml::LN_CT_PPrBase_keepNext:
1270 rContext->Insert(PROP_PARA_KEEP_TOGETHER, uno::makeAny( nIntValue != 0 ) );
1271 break;
1272 case NS_ooxml::LN_CT_PPrBase_pageBreakBefore:
1273 rContext->Insert(PROP_BREAK_TYPE, uno::makeAny(nIntValue ? style::BreakType_PAGE_BEFORE : style::BreakType_NONE));
1274 break;
1275 case NS_ooxml::LN_CT_NumPr_ilvl:
1276 if (nIntValue < 0 || 10 <= nIntValue) // Writer can't do everything
1278 SAL_INFO("writerfilter",
1279 "unsupported numbering level " << nIntValue);
1280 break;
1282 if( IsStyleSheetImport() )
1284 //style sheets cannot have a numbering rule attached
1285 StyleSheetPropertyMap* pStyleSheetPropertyMap = dynamic_cast< StyleSheetPropertyMap* >( rContext.get() );
1286 if (pStyleSheetPropertyMap)
1287 pStyleSheetPropertyMap->SetListLevel( static_cast<sal_Int16>(nIntValue) );
1289 else
1290 rContext->Insert( PROP_NUMBERING_LEVEL, uno::makeAny( static_cast<sal_Int16>(nIntValue) ));
1291 break;
1292 case NS_ooxml::LN_CT_NumPr_numId:
1294 //convert the ListTable entry to a NumberingRules property and apply it
1295 ListsManager::Pointer pListTable = m_pImpl->GetListTable();
1296 ListDef::Pointer pList = pListTable->GetList( nIntValue );
1297 if( IsStyleSheetImport() )
1299 //style sheets cannot have a numbering rule attached
1300 StyleSheetPropertyMap* pStyleSheetPropertyMap = dynamic_cast< StyleSheetPropertyMap* >( rContext.get() );
1301 if (pStyleSheetPropertyMap)
1302 pStyleSheetPropertyMap->SetListId( nIntValue );
1304 if( pList.get( ) )
1306 if( !IsStyleSheetImport() )
1308 uno::Any aRules = uno::makeAny( pList->GetNumberingRules( ) );
1309 rContext->Insert( PROP_NUMBERING_RULES, aRules );
1310 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
1311 if (pContext)
1313 assert(dynamic_cast<ParagraphPropertyMap*>(pContext.get()));
1314 static_cast<ParagraphPropertyMap*>(pContext.get())->SetListId(pList->GetId());
1316 // erase numbering from pStyle if already set
1317 rContext->Erase(PROP_NUMBERING_STYLE_NAME);
1319 // Indentation can came from:
1320 // 1) Paragraph style's numbering's indentation: the current non-style numId has priority over it.
1321 // 2) Numbering's indentation: Writer handles that natively, so it should not be set on rContext.
1322 // 3) Paragraph style's indentation: ditto.
1323 // 4) Direct paragraph formatting: that will came later.
1324 // So no situation where keeping indentation at this point would make sense -> erase.
1325 rContext->Erase(PROP_PARA_FIRST_LINE_INDENT);
1326 rContext->Erase(PROP_PARA_LEFT_MARGIN);
1327 rContext->Erase(PROP_PARA_RIGHT_MARGIN);
1330 else
1332 if( !IsStyleSheetImport() )
1334 // eg. disabled numbering using non-existent numId "0"
1335 rContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::makeAny( OUString() ) );
1336 // disable inheritance of indentation of parent styles
1337 rContext->Insert( PROP_PARA_LEFT_MARGIN, uno::makeAny( sal_Int32(0) ), /*bOverwrite=*/false);
1338 rContext->Insert( PROP_PARA_FIRST_LINE_INDENT,
1339 uno::makeAny( sal_Int32(0) ), /*bOverwrite=*/false);
1343 break;
1344 case NS_ooxml::LN_CT_PPrBase_suppressLineNumbers:
1345 rContext->Insert(PROP_PARA_LINE_NUMBER_COUNT, uno::makeAny( nIntValue == 0 ) );
1346 break;
1347 case NS_ooxml::LN_inTbl:
1348 break;
1349 case NS_ooxml::LN_tblDepth:
1350 //not handled via sprm but via text( 0x07 )
1351 break;
1352 case NS_ooxml::LN_CT_FramePr_w:
1353 break;
1354 case NS_ooxml::LN_CT_FramePr_wrap:
1355 break;
1357 case NS_ooxml::LN_CT_PrBase_pBdr: //paragraph border
1358 resolveSprmProps(*this, rSprm);
1359 break;
1360 case NS_ooxml::LN_CT_PBdr_top:
1361 case NS_ooxml::LN_CT_PBdr_left:
1362 case NS_ooxml::LN_CT_PBdr_bottom:
1363 case NS_ooxml::LN_CT_PBdr_right:
1364 case NS_ooxml::LN_CT_PBdr_between:
1366 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1367 if( pProperties.get())
1369 auto pBorderHandler = std::make_shared<BorderHandler>( true );
1370 pProperties->resolve(*pBorderHandler);
1371 PropertyIds eBorderId = PropertyIds( 0 );
1372 PropertyIds eBorderDistId = PropertyIds( 0 );
1373 switch( nSprmId )
1375 case NS_ooxml::LN_CT_PBdr_top:
1376 eBorderId = PROP_TOP_BORDER;
1377 eBorderDistId = PROP_TOP_BORDER_DISTANCE;
1378 break;
1379 case NS_ooxml::LN_CT_PBdr_left:
1380 eBorderId = PROP_LEFT_BORDER;
1381 eBorderDistId = PROP_LEFT_BORDER_DISTANCE;
1382 break;
1383 case NS_ooxml::LN_CT_PBdr_bottom:
1384 eBorderId = PROP_BOTTOM_BORDER ;
1385 eBorderDistId = PROP_BOTTOM_BORDER_DISTANCE;
1386 break;
1387 case NS_ooxml::LN_CT_PBdr_right:
1388 eBorderId = PROP_RIGHT_BORDER;
1389 eBorderDistId = PROP_RIGHT_BORDER_DISTANCE ;
1390 break;
1391 case NS_ooxml::LN_CT_PBdr_between:
1392 //not supported
1393 break;
1394 default:;
1396 if( eBorderId )
1397 rContext->Insert( eBorderId, uno::makeAny( pBorderHandler->getBorderLine()) );
1398 if(eBorderDistId)
1399 rContext->Insert(eBorderDistId, uno::makeAny( pBorderHandler->getLineDistance()));
1400 if ( nSprmId == NS_ooxml::LN_CT_PBdr_right )
1402 table::ShadowFormat aFormat;
1403 // Word only allows shadows on visible borders
1404 if ( pBorderHandler->getShadow() && pBorderHandler->getBorderLine().LineStyle != table::BorderLineStyle::NONE )
1405 aFormat = writerfilter::dmapper::PropertyMap::getShadowFromBorder(pBorderHandler->getBorderLine());
1406 rContext->Insert(PROP_PARA_SHADOW_FORMAT, uno::makeAny(aFormat));
1410 break;
1411 case NS_ooxml::LN_CT_PBdr_bar:
1412 break;
1413 case NS_ooxml::LN_CT_PPrBase_suppressAutoHyphens:
1414 rContext->Insert(PROP_PARA_IS_HYPHENATION, uno::makeAny( nIntValue == 0 ));
1415 break;
1416 case NS_ooxml::LN_CT_FramePr_h:
1417 break;
1418 case NS_ooxml::LN_CT_PrBase_shd:
1420 //contains fore color, back color and shadow percentage, results in a brush
1421 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1422 if( pProperties.get())
1424 auto pCellColorHandler = std::make_shared<CellColorHandler>();
1425 pCellColorHandler->setOutputFormat( CellColorHandler::Paragraph );
1426 bool bEnableTempGrabBag = !pCellColorHandler->isInteropGrabBagEnabled();
1427 if( bEnableTempGrabBag )
1428 pCellColorHandler->enableInteropGrabBag( "TempShdPropsGrabBag" );
1430 pProperties->resolve(*pCellColorHandler);
1431 rContext->InsertProps(pCellColorHandler->getProperties().get());
1433 rContext->Insert(PROP_CHAR_THEME_FILL, pCellColorHandler->getInteropGrabBag().Value, true, PARA_GRAB_BAG);
1434 if(bEnableTempGrabBag)
1435 pCellColorHandler->disableInteropGrabBag();
1438 break;
1439 case NS_ooxml::LN_CT_FramePr_vSpace:
1440 break; // sprmPDyaFromText
1441 case NS_ooxml::LN_CT_FramePr_hSpace:
1442 break; // sprmPDxaFromText
1443 case NS_ooxml::LN_CT_FramePr_anchorLock:
1444 break;
1445 case NS_ooxml::LN_CT_PPrBase_widowControl:
1447 uno::Any aVal( uno::makeAny( sal_Int8(nIntValue ? 2 : 0 )));
1448 rContext->Insert( PROP_PARA_WIDOWS, aVal );
1449 rContext->Insert( PROP_PARA_ORPHANS, aVal );
1451 break; // sprmPFWidowControl
1452 case NS_ooxml::LN_CT_PPrBase_overflowPunct:
1453 rContext->Insert(PROP_PARA_IS_HANGING_PUNCTUATION, uno::makeAny( nIntValue == 0 ));
1454 break;
1455 case NS_ooxml::LN_CT_PPrBase_topLinePunct:
1456 break;
1457 case NS_ooxml::LN_CT_PPrBase_autoSpaceDE:
1458 break;
1459 case NS_ooxml::LN_CT_PPrBase_autoSpaceDN:
1460 break;
1461 case NS_ooxml::LN_CT_PPrBase_textAlignment:
1463 sal_Int16 nAlignment = 0;
1464 switch (nIntValue)
1466 case NS_ooxml::LN_Value_doc_ST_TextAlignment_top:
1467 nAlignment = 2;
1468 break;
1469 case NS_ooxml::LN_Value_doc_ST_TextAlignment_center:
1470 nAlignment = 3;
1471 break;
1472 case NS_ooxml::LN_Value_doc_ST_TextAlignment_baseline:
1473 nAlignment = 1;
1474 break;
1475 case NS_ooxml::LN_Value_doc_ST_TextAlignment_bottom:
1476 nAlignment = 4;
1477 break;
1478 case NS_ooxml::LN_Value_doc_ST_TextAlignment_auto:
1479 default:
1480 break;
1482 rContext->Insert( PROP_PARA_VERT_ALIGNMENT, uno::makeAny( nAlignment) );
1484 break;
1485 case NS_ooxml::LN_CT_PPrBase_textDirection:
1486 break;
1487 case NS_ooxml::LN_CT_PPrBase_outlineLvl:
1489 sal_Int16 nLvl = static_cast< sal_Int16 >( nIntValue );
1490 if( IsStyleSheetImport() )
1493 StyleSheetPropertyMap* pStyleSheetPropertyMap = dynamic_cast< StyleSheetPropertyMap* >( rContext.get() );
1494 if (pStyleSheetPropertyMap)
1495 pStyleSheetPropertyMap->SetOutlineLevel( nLvl );
1497 else
1499 nLvl = nLvl >= WW_OUTLINE_MIN && nLvl < WW_OUTLINE_MAX? nLvl+1 : 0; //0 means no outline level set on
1500 rContext->Insert(PROP_OUTLINE_LEVEL, uno::makeAny ( nLvl ));
1503 break;
1504 case NS_ooxml::LN_CT_PPrBase_bidi:
1506 // Four situations to handle:
1507 // 1.) bidi same as previous setting: no adjust change
1508 // 2.) no previous adjust: set appropriate default for this bidi
1509 // 3.) previous adjust and bidi different from previous: swap adjusts
1510 // 4.) previous adjust and no previous bidi: RTL swaps adjust
1512 const sal_Int16 nWritingMode = nIntValue ? text::WritingMode2::RL_TB : text::WritingMode2::LR_TB;
1513 sal_Int16 nParentBidi = -1;
1514 m_pImpl->GetPropertyFromParaStyleSheet(PROP_WRITING_MODE) >>= nParentBidi;
1515 // Paragraph justification reverses its meaning in an RTL context.
1516 // 1. Only make adjustments if the BiDi changes.
1517 if ( nParentBidi != nWritingMode && !IsRTFImport() )
1519 style::ParagraphAdjust eAdjust = style::ParagraphAdjust(-1);
1520 // 2. no adjust property exists yet
1521 if ( !(m_pImpl->GetAnyProperty(PROP_PARA_ADJUST, rContext) >>= eAdjust) )
1523 // RTL defaults to right adjust
1524 eAdjust = nIntValue ? style::ParagraphAdjust_RIGHT : style::ParagraphAdjust_LEFT;
1525 rContext->Insert(PROP_PARA_ADJUST, uno::makeAny( eAdjust ), /*bOverwrite=*/false);
1527 // 3,4. existing adjust: if RTL, then swap. If LTR, but previous was RTL, also swap.
1528 else if ( nIntValue || nParentBidi == sal_Int16(text::WritingMode2::RL_TB) )
1530 if ( eAdjust == style::ParagraphAdjust_RIGHT )
1531 rContext->Insert(PROP_PARA_ADJUST, uno::makeAny( style::ParagraphAdjust_LEFT ));
1532 else if ( eAdjust == style::ParagraphAdjust_LEFT )
1533 rContext->Insert(PROP_PARA_ADJUST, uno::makeAny( style::ParagraphAdjust_RIGHT ));
1536 rContext->Insert(PROP_WRITING_MODE, uno::makeAny( nWritingMode ));
1539 break;
1540 case NS_ooxml::LN_EG_SectPrContents_bidi:
1541 if (pSectionContext != nullptr)
1543 const sal_Int16 writingMode = (nIntValue != 0) ? sal_Int16(text::WritingMode2::RL_TB) : sal_Int16(text::WritingMode2::LR_TB);
1544 pSectionContext->Insert(PROP_WRITING_MODE, uno::makeAny(writingMode));
1546 break;
1547 case NS_ooxml::LN_EG_RPrBase_highlight:
1549 // OOXML import uses an ID
1550 if( IsOOXMLImport() )
1552 sal_Int32 nColor = 0;
1553 if( getColorFromId(nIntValue, nColor) )
1554 rContext->Insert(PROP_CHAR_HIGHLIGHT, uno::makeAny( nColor ));
1556 // RTF import uses the actual color value
1557 else if( IsRTFImport() )
1559 rContext->Insert(PROP_CHAR_HIGHLIGHT, uno::makeAny( nIntValue ));
1562 break;
1563 case NS_ooxml::LN_EG_RPrBase_em:
1564 rContext->Insert(PROP_CHAR_EMPHASIS, uno::makeAny ( getEmphasisValue (nIntValue)));
1565 break;
1566 case NS_ooxml::LN_EG_RPrBase_emboss:
1567 case NS_ooxml::LN_EG_RPrBase_b:
1568 case NS_ooxml::LN_EG_RPrBase_bCs:
1569 case NS_ooxml::LN_EG_RPrBase_i:
1570 case NS_ooxml::LN_EG_RPrBase_iCs:
1571 case NS_ooxml::LN_EG_RPrBase_strike:
1572 case NS_ooxml::LN_EG_RPrBase_dstrike:
1573 case NS_ooxml::LN_EG_RPrBase_outline:
1574 case NS_ooxml::LN_EG_RPrBase_shadow:
1575 case NS_ooxml::LN_EG_RPrBase_caps:
1576 case NS_ooxml::LN_EG_RPrBase_smallCaps:
1577 case NS_ooxml::LN_EG_RPrBase_vanish:
1578 case NS_ooxml::LN_EG_RPrBase_webHidden:
1580 PropertyIds ePropertyId = PROP_CHAR_WEIGHT; //initialized to prevent warning!
1581 switch( nSprmId )
1583 case NS_ooxml::LN_EG_RPrBase_b:
1584 case NS_ooxml::LN_EG_RPrBase_bCs:
1585 ePropertyId = nSprmId != NS_ooxml::LN_EG_RPrBase_bCs ? PROP_CHAR_WEIGHT : PROP_CHAR_WEIGHT_COMPLEX;
1586 break;
1587 case NS_ooxml::LN_EG_RPrBase_i:
1588 case NS_ooxml::LN_EG_RPrBase_iCs:
1589 ePropertyId = nSprmId == NS_ooxml::LN_EG_RPrBase_i ? PROP_CHAR_POSTURE : PROP_CHAR_POSTURE_COMPLEX;
1590 break;
1591 case NS_ooxml::LN_EG_RPrBase_strike:
1592 case NS_ooxml::LN_EG_RPrBase_dstrike:
1593 ePropertyId = PROP_CHAR_STRIKEOUT;
1594 break;
1595 case NS_ooxml::LN_EG_RPrBase_outline:
1596 ePropertyId = PROP_CHAR_CONTOURED;
1597 break;
1598 case NS_ooxml::LN_EG_RPrBase_shadow:
1599 ePropertyId = PROP_CHAR_SHADOWED;
1600 break;
1601 case NS_ooxml::LN_EG_RPrBase_caps:
1602 case NS_ooxml::LN_EG_RPrBase_smallCaps:
1603 ePropertyId = PROP_CHAR_CASE_MAP;
1604 break;
1605 case NS_ooxml::LN_EG_RPrBase_vanish:
1606 case NS_ooxml::LN_EG_RPrBase_webHidden:
1607 ePropertyId = PROP_CHAR_HIDDEN;
1608 break;
1609 case NS_ooxml::LN_EG_RPrBase_emboss:
1610 ePropertyId = PROP_CHAR_RELIEF;
1611 break;
1613 //expected: 0,1,128,129
1614 if(nIntValue != 128) //inherited from paragraph - ignore
1616 if( nIntValue == 129) //inverted style sheet value
1618 //get value from style sheet and invert it
1619 sal_Int16 nStyleValue = 0;
1620 uno::Any aStyleVal = m_pImpl->GetPropertyFromParaStyleSheet(ePropertyId);
1621 if( !aStyleVal.hasValue() )
1623 nIntValue = NS_ooxml::LN_EG_RPrBase_smallCaps == nSprmId ?
1624 4 : 1;
1626 else if(aStyleVal.getValueTypeClass() == uno::TypeClass_FLOAT )
1628 double fDoubleValue = 0;
1629 //only in case of awt::FontWeight
1630 aStyleVal >>= fDoubleValue;
1631 nIntValue = fDoubleValue > 100. ? 0 : 1;
1633 else if((aStyleVal >>= nStyleValue) ||
1634 (nStyleValue = static_cast<sal_Int16>(comphelper::getEnumAsINT32(aStyleVal))) >= 0 )
1636 nIntValue = NS_ooxml::LN_EG_RPrBase_smallCaps == nSprmId ?
1637 nStyleValue ? 0 : 4 :
1638 nStyleValue ? 0 : 1;
1640 else
1642 OSL_FAIL( "what type was it");
1646 switch( nSprmId )
1648 case NS_ooxml::LN_EG_RPrBase_b:
1649 case NS_ooxml::LN_EG_RPrBase_bCs:
1651 uno::Any aBold( uno::makeAny( nIntValue ? awt::FontWeight::BOLD : awt::FontWeight::NORMAL ) );
1653 rContext->Insert(ePropertyId, aBold );
1654 if( nSprmId != NS_ooxml::LN_EG_RPrBase_bCs )
1655 rContext->Insert(PROP_CHAR_WEIGHT_ASIAN, aBold );
1657 uno::Reference<beans::XPropertySet> xCharStyle(m_pImpl->GetCurrentNumberingCharStyle());
1658 if (xCharStyle.is())
1659 xCharStyle->setPropertyValue(getPropertyName(PROP_CHAR_WEIGHT), aBold);
1660 if (nSprmId == NS_ooxml::LN_EG_RPrBase_b)
1661 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "b", OUString::number(nIntValue));
1662 else if (nSprmId == NS_ooxml::LN_EG_RPrBase_bCs)
1663 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "bCs", OUString::number(nIntValue));
1665 break;
1666 case NS_ooxml::LN_EG_RPrBase_i:
1667 case NS_ooxml::LN_EG_RPrBase_iCs:
1669 uno::Any aPosture( uno::makeAny( nIntValue ? awt::FontSlant_ITALIC : awt::FontSlant_NONE ) );
1670 rContext->Insert( ePropertyId, aPosture );
1671 if (nSprmId != NS_ooxml::LN_EG_RPrBase_iCs)
1672 rContext->Insert(PROP_CHAR_POSTURE_ASIAN, aPosture );
1673 if (nSprmId == NS_ooxml::LN_EG_RPrBase_i)
1674 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "i", OUString::number(nIntValue));
1676 break;
1677 case NS_ooxml::LN_EG_RPrBase_strike:
1678 rContext->Insert(ePropertyId,
1679 uno::makeAny( nIntValue ? awt::FontStrikeout::SINGLE : awt::FontStrikeout::NONE ) );
1680 break;
1681 case NS_ooxml::LN_EG_RPrBase_dstrike:
1682 rContext->Insert(ePropertyId,
1683 uno::makeAny( nIntValue ? awt::FontStrikeout::DOUBLE : awt::FontStrikeout::NONE ) );
1684 break;
1685 case NS_ooxml::LN_EG_RPrBase_outline:
1686 case NS_ooxml::LN_EG_RPrBase_shadow:
1687 case NS_ooxml::LN_EG_RPrBase_vanish:
1688 case NS_ooxml::LN_EG_RPrBase_webHidden:
1689 rContext->Insert(ePropertyId, uno::makeAny( nIntValue != 0 ));
1690 break;
1691 case NS_ooxml::LN_EG_RPrBase_smallCaps:
1692 // If smallcaps would be just disabled and another casemap is already inserted, don't do anything.
1693 if (nIntValue || !rContext->isSet(ePropertyId) )
1694 rContext->Insert(ePropertyId, uno::makeAny( nIntValue ? style::CaseMap::SMALLCAPS : style::CaseMap::NONE));
1695 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "smallCaps", OUString::number(nIntValue));
1696 break;
1697 case NS_ooxml::LN_EG_RPrBase_caps:
1698 rContext->Insert(ePropertyId,
1699 uno::makeAny( nIntValue ? style::CaseMap::UPPERCASE : style::CaseMap::NONE));
1700 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "caps", OUString::number(nIntValue));
1701 break;
1702 case NS_ooxml::LN_EG_RPrBase_emboss:
1703 rContext->Insert(ePropertyId,
1704 uno::makeAny( nIntValue ? awt::FontRelief::EMBOSSED : awt::FontRelief::NONE ));
1705 break;
1710 break;
1711 case NS_ooxml::LN_EG_RPrBase_sz:
1712 case NS_ooxml::LN_EG_RPrBase_szCs:
1714 //multiples of half points (12pt == 24)
1715 double fVal = double(nIntValue) / 2.;
1716 uno::Any aVal = uno::makeAny( fVal );
1717 if( NS_ooxml::LN_EG_RPrBase_szCs == nSprmId )
1719 rContext->Insert( PROP_CHAR_HEIGHT_COMPLEX, aVal );
1721 else
1723 const RubyInfo &aInfo = m_pImpl->GetRubyInfo();
1724 if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rt && aInfo.nHps > 0 )
1726 fVal = double(aInfo.nHps) / 2.;
1727 aVal <<= fVal;
1729 else if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rubyBase && aInfo.nHpsBaseText > 0 )
1731 fVal = double(aInfo.nHpsBaseText) / 2.;
1732 aVal <<= fVal;
1734 //Asian get the same value as Western
1735 rContext->Insert( PROP_CHAR_HEIGHT, aVal );
1736 rContext->Insert( PROP_CHAR_HEIGHT_ASIAN, aVal );
1738 uno::Reference<beans::XPropertySet> xCharStyle(m_pImpl->GetCurrentNumberingCharStyle());
1739 if (xCharStyle.is())
1740 xCharStyle->setPropertyValue(getPropertyName(PROP_CHAR_HEIGHT), aVal);
1742 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, (nSprmId == NS_ooxml::LN_EG_RPrBase_sz ? OUString("sz") : OUString("szCs")), OUString::number(nIntValue));
1744 break;
1745 case NS_ooxml::LN_EG_RPrBase_position:
1746 // The spec says 0 is the same as the lack of the value, so don't parse that.
1747 if ( nIntValue )
1749 if ( !IsStyleSheetImport() )
1750 m_pImpl->deferCharacterProperty( nSprmId, uno::makeAny( nIntValue ));
1751 else
1753 // DON'T FIXME: Truly calculating this for Character Styles will be tricky,
1754 // because it depends on the final fontsize - regardless of
1755 // where it is set. So at the style level,
1756 // the escapement value would need to be grabbagged.
1757 // At appendText time the final fontsize needs to be determined, and then
1758 // the escapement can be calculated from the grabbag'd half-point value
1759 // and directly applied. Yuck.
1760 // It seems best to just treat charstyle escapement like
1761 // pre-commit e70df84352d3670508a4666c97df44f82c1ce934
1762 // which just assigned default values and ignored the actual/given escapement.
1763 sal_Int16 nEscapement = nIntValue > 0 ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB;
1764 sal_Int8 nProp = DFLT_ESC_PROP;
1765 rContext->Insert(PROP_CHAR_ESCAPEMENT, uno::makeAny( nEscapement ) );
1766 rContext->Insert(PROP_CHAR_ESCAPEMENT_HEIGHT, uno::makeAny( nProp ) );
1769 break;
1770 case NS_ooxml::LN_EG_RPrBase_spacing:
1772 //Kerning half point values
1773 //TODO: there are two kerning values -
1774 // in ww8par6.cxx NS_sprm::LN_CHpsKern is used as boolean AutoKerning
1775 sal_Int16 nResult = static_cast<sal_Int16>(ConversionHelper::convertTwipToMM100(nIntValue));
1776 if (m_pImpl->IsInComments())
1778 nResult = static_cast<sal_Int16>(nIntValue);
1780 rContext->Insert(PROP_CHAR_CHAR_KERNING, uno::makeAny(nResult));
1781 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "spacing", OUString::number(nIntValue));
1783 break;
1784 case NS_ooxml::LN_EG_RPrBase_kern: // auto kerning is bound to a minimum font size in Word - but not in Writer :-(
1785 rContext->Insert(PROP_CHAR_AUTO_KERNING, uno::makeAny( nIntValue != 0 ) );
1786 break;
1787 case NS_ooxml::LN_EG_RPrBase_w:
1788 // ST_TextScale must fall between 1% and 600% according to spec, otherwise resets to 100% according to experience
1789 if ((1 <= nIntValue) && (nIntValue <= 600))
1791 rContext->Insert(PROP_CHAR_SCALE_WIDTH,
1792 uno::makeAny( sal_Int16(nIntValue) ));
1794 else
1796 rContext->Insert(PROP_CHAR_SCALE_WIDTH,
1797 uno::makeAny( sal_Int16(100) ));
1799 break;
1800 case NS_ooxml::LN_EG_RPrBase_imprint:
1801 // FontRelief: NONE, EMBOSSED, ENGRAVED
1802 rContext->Insert(PROP_CHAR_RELIEF,
1803 uno::makeAny( nIntValue ? awt::FontRelief::ENGRAVED : awt::FontRelief::NONE ));
1804 break;
1805 case NS_ooxml::LN_EG_RPrBase_effect:
1806 // The file-format has many character animations. We have only
1807 // one, so we use it always. Suboptimal solution though.
1808 if (nIntValue != NS_ooxml::LN_Value_ST_TextEffect_none)
1809 rContext->Insert(PROP_CHAR_FLASH, uno::makeAny( true ));
1810 else
1811 rContext->Insert(PROP_CHAR_FLASH, uno::makeAny( false ));
1812 break;
1813 case NS_ooxml::LN_EG_RPrBase_rtl:
1814 break;
1815 case NS_ooxml::LN_EG_RPrBase_shd:
1817 //contains fore color, back color and shadow percentage, results in a brush
1818 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1819 if( pProperties.get())
1821 auto pCellColorHandler = std::make_shared<CellColorHandler>();
1822 pCellColorHandler->setOutputFormat( CellColorHandler::Character );
1823 pProperties->resolve(*pCellColorHandler);
1824 rContext->InsertProps(pCellColorHandler->getProperties().get());
1825 m_pImpl->GetTopContext()->Insert(PROP_CHAR_SHADING_MARKER, uno::makeAny(true), true, CHAR_GRAB_BAG );
1827 break;
1829 case NS_ooxml::LN_EG_SectPrContents_type:
1830 /* break type
1831 0 - No break
1832 1 - New Column
1833 2 - New page
1834 3 - Even page
1835 4 - odd page
1837 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
1838 if(pSectionContext)
1840 //continuous break only allowed if it is not the only section break
1841 SectionPropertyMap* pLastContext = m_pImpl->GetLastSectionContext();
1842 if ( nIntValue != static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous) || pLastContext || m_pImpl->GetParaSectpr() )
1843 pSectionContext->SetBreakType( nIntValue );
1845 break;
1846 case NS_ooxml::LN_EG_SectPrContents_titlePg:
1848 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
1849 if(pSectionContext)
1850 pSectionContext->SetTitlePage( nIntValue > 0 );//section has title page
1852 break;
1853 case 165:
1855 //page height, rounded to default values, default: 0x3dc0 twip
1856 sal_Int32 nHeight = ConversionHelper::convertTwipToMM100( nIntValue );
1857 rContext->Insert( PROP_HEIGHT, uno::makeAny( PaperInfo::sloppyFitPageDimension( nHeight ) ) );
1859 break;
1860 case NS_ooxml::LN_EG_SectPrContents_textDirection:
1862 /* 0 HoriLR 1 Vert TR 2 Vert TR 3 Vert TT 4 HoriLT
1863 only 0 and 1 can be imported correctly
1865 text::WritingMode nDirection = text::WritingMode_LR_TB;
1866 switch( nIntValue )
1868 case NS_ooxml::LN_Value_ST_TextDirection_lrTb:
1869 case NS_ooxml::LN_Value_ST_TextDirection_lrTbV:
1870 nDirection = text::WritingMode_LR_TB;
1871 break;
1872 case NS_ooxml::LN_Value_ST_TextDirection_tbRl:
1873 case NS_ooxml::LN_Value_ST_TextDirection_btLr:
1874 nDirection = text::WritingMode_TB_RL;
1875 break;
1876 default:;
1879 PropertyMap * pTargetContext = rContext.get();
1881 if (pSectionContext)
1883 pTargetContext = pSectionContext;
1886 pTargetContext->Insert(PROP_WRITING_MODE, uno::makeAny( sal_Int16(nDirection) ) );
1888 break; // sprmSTextFlow
1889 // the following are not part of the official documentation
1890 case NS_ooxml::LN_CT_Tabs_tab:
1891 resolveSprmProps(*this, rSprm);
1892 m_pImpl->IncorporateTabStop(m_pImpl->m_aCurrentTabStop);
1893 m_pImpl->m_aCurrentTabStop = DeletableTabStop();
1894 break;
1895 case NS_ooxml::LN_CT_PPrBase_tabs:
1897 // Initialize tab stop vector from style sheet
1898 // fdo#81033: for RTF, a tab stop is inherited from the style if it
1899 // is also applied to the paragraph directly, and cleared if it is
1900 // not applied to the paragraph directly => don't InitTabStopFromStyle
1901 if ( !IsRTFImport() )
1903 uno::Any aValue = m_pImpl->GetPropertyFromParaStyleSheet(PROP_PARA_TAB_STOPS);
1904 uno::Sequence< style::TabStop > aStyleTabStops;
1905 if(aValue >>= aStyleTabStops)
1907 m_pImpl->InitTabStopFromStyle( aStyleTabStops );
1910 resolveSprmProps(*this, rSprm);
1911 rContext->Insert(PROP_PARA_TAB_STOPS, uno::makeAny( m_pImpl->GetCurrentTabStopAndClear()));
1913 break;
1915 case NS_ooxml::LN_CT_DocDefaults_pPrDefault:
1916 case NS_ooxml::LN_CT_DocDefaults_rPrDefault:
1917 GetStyleSheetTable()->sprm( rSprm );
1918 break;
1919 case NS_ooxml::LN_EG_RPrBase_bdr:
1921 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1922 if( pProperties.get())
1924 auto pBorderHandler = std::make_shared<BorderHandler>( true );
1925 pProperties->resolve(*pBorderHandler);
1927 rContext->Insert( PROP_CHAR_TOP_BORDER, uno::makeAny( pBorderHandler->getBorderLine()));
1928 rContext->Insert( PROP_CHAR_BOTTOM_BORDER, uno::makeAny( pBorderHandler->getBorderLine()));
1929 rContext->Insert( PROP_CHAR_LEFT_BORDER, uno::makeAny( pBorderHandler->getBorderLine()));
1930 rContext->Insert( PROP_CHAR_RIGHT_BORDER, uno::makeAny( pBorderHandler->getBorderLine()));
1932 rContext->Insert( PROP_CHAR_TOP_BORDER_DISTANCE, uno::makeAny( pBorderHandler->getLineDistance()));
1933 rContext->Insert( PROP_CHAR_BOTTOM_BORDER_DISTANCE, uno::makeAny( pBorderHandler->getLineDistance()));
1934 rContext->Insert( PROP_CHAR_LEFT_BORDER_DISTANCE, uno::makeAny( pBorderHandler->getLineDistance()));
1935 rContext->Insert( PROP_CHAR_RIGHT_BORDER_DISTANCE, uno::makeAny( pBorderHandler->getLineDistance()));
1937 table::ShadowFormat aFormat;
1938 // Word only allows shadows on visible borders
1939 if ( pBorderHandler->getShadow() && pBorderHandler->getBorderLine().LineStyle != table::BorderLineStyle::NONE )
1940 aFormat = writerfilter::dmapper::PropertyMap::getShadowFromBorder(pBorderHandler->getBorderLine());
1941 rContext->Insert(PROP_CHAR_SHADOW_FORMAT, uno::makeAny(aFormat));
1944 break;
1945 case NS_ooxml::LN_CT_PPr_sectPr:
1946 case NS_ooxml::LN_EG_RPrBase_color:
1947 case NS_ooxml::LN_EG_RPrBase_rFonts:
1948 case NS_ooxml::LN_EG_RPrBase_eastAsianLayout:
1949 case NS_ooxml::LN_EG_RPrBase_u:
1950 case NS_ooxml::LN_EG_RPrBase_lang:
1951 case NS_ooxml::LN_CT_PPrBase_spacing:
1952 case NS_ooxml::LN_CT_PPrBase_ind:
1953 case NS_ooxml::LN_CT_RPrDefault_rPr:
1954 case NS_ooxml::LN_CT_PPrDefault_pPr:
1955 case NS_ooxml::LN_CT_Style_pPr:
1956 case NS_ooxml::LN_CT_Style_rPr:
1957 case NS_ooxml::LN_CT_PPr_rPr:
1958 case NS_ooxml::LN_CT_PPrBase_numPr:
1960 bool bTempGrabBag = !m_pImpl->isInteropGrabBagEnabled();
1961 if (nSprmId == NS_ooxml::LN_CT_PPr_sectPr)
1962 m_pImpl->SetParaSectpr(true);
1963 else if (nSprmId == NS_ooxml::LN_EG_RPrBase_color && bTempGrabBag)
1964 // if DomainMapper grab bag is not enabled, enable it temporarily
1965 m_pImpl->enableInteropGrabBag("TempColorPropsGrabBag");
1966 resolveSprmProps(*this, rSprm);
1967 if (nSprmId == NS_ooxml::LN_CT_PPrBase_spacing)
1968 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "spacing", m_pImpl->m_aSubInteropGrabBag);
1969 else if (nSprmId == NS_ooxml::LN_EG_RPrBase_rFonts)
1970 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "rFonts", m_pImpl->m_aSubInteropGrabBag);
1971 else if (nSprmId == NS_ooxml::LN_EG_RPrBase_lang)
1972 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lang", m_pImpl->m_aSubInteropGrabBag);
1973 else if (nSprmId == NS_ooxml::LN_EG_RPrBase_color)
1975 for (const auto& rItem : m_pImpl->m_aSubInteropGrabBag)
1977 if (rItem.Name == "val")
1978 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_ORIGINAL_COLOR, rItem.Value, true, CHAR_GRAB_BAG);
1979 else if (rItem.Name == "themeColor")
1980 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_COLOR, rItem.Value, true, CHAR_GRAB_BAG);
1981 else if (rItem.Name == "themeShade")
1982 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_COLOR_SHADE, rItem.Value, true, CHAR_GRAB_BAG);
1983 else if (rItem.Name == "themeTint")
1984 m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_COLOR_TINT, rItem.Value, true, CHAR_GRAB_BAG);
1986 if (bTempGrabBag)
1987 //disable and clear DomainMapper grab bag if it wasn't enabled before
1988 m_pImpl->disableInteropGrabBag();
1990 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "color", m_pImpl->m_aSubInteropGrabBag);
1992 else if (nSprmId == NS_ooxml::LN_CT_PPrBase_ind)
1993 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ind", m_pImpl->m_aSubInteropGrabBag);
1995 break;
1996 case NS_ooxml::LN_CT_PPrBase_wordWrap:
1997 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "wordWrap", "");
1998 break;
1999 case NS_ooxml::LN_EG_SectPrContents_footnotePr:
2000 case NS_ooxml::LN_EG_SectPrContents_endnotePr:
2001 m_pImpl->SetInFootnoteProperties( NS_ooxml::LN_EG_SectPrContents_footnotePr == nSprmId );
2002 resolveSprmProps(*this, rSprm);
2003 break;
2004 case NS_ooxml::LN_EG_SectPrContents_lnNumType:
2006 resolveSprmProps(*this, rSprm);
2007 LineNumberSettings aSettings = m_pImpl->GetLineNumberSettings();
2008 m_pImpl->SetLineNumberSettings( aSettings );
2009 //apply settings at XLineNumberingProperties
2012 uno::Reference< text::XLineNumberingProperties > xLineNumberingProperties( m_pImpl->GetTextDocument(), uno::UNO_QUERY_THROW );
2013 uno::Reference< beans::XPropertySet > xLineNumberingPropSet = xLineNumberingProperties->getLineNumberingProperties();
2014 if( aSettings.nInterval == 0 )
2015 xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_IS_ON ), uno::makeAny(false) );
2016 else
2018 xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_IS_ON ), uno::makeAny(true) );
2019 if( aSettings.nInterval )
2020 xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_INTERVAL ), uno::makeAny(static_cast<sal_Int16>(aSettings.nInterval)) );
2021 if( aSettings.nDistance != -1 )
2022 xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_DISTANCE ), uno::makeAny(aSettings.nDistance) );
2023 else
2025 // set Auto value (0.5 cm)
2026 xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_DISTANCE ), uno::makeAny(static_cast<sal_Int32>(500)) );
2027 if( pSectionContext )
2028 pSectionContext->SetdxaLnn( static_cast<sal_Int32>(283) );
2030 xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_RESTART_AT_EACH_PAGE ), uno::makeAny(aSettings.bRestartAtEachPage) );
2033 catch( const uno::Exception& )
2038 break;
2039 case NS_ooxml::LN_CT_PPrBase_framePr:
2040 // Avoid frames if we're inside a structured document tag, would just cause outer tables fail to create.
2041 if (!m_pImpl->GetSdt())
2043 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
2044 if( pContext.get() )
2046 // If there is a deferred page break applied to this framed paragraph,
2047 // create a dummy paragraph without extra properties,
2048 // so that the anchored frame will be on the correct page (similar to shapes).
2049 if (pContext->isSet(PROP_BREAK_TYPE))
2051 pContext->Erase(PROP_BREAK_TYPE);
2053 lcl_startParagraphGroup();
2054 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_PAGE_BEFORE));
2055 lcl_startCharacterGroup();
2056 sal_uInt8 const sBreak[] = { 0xd };
2057 lcl_text(sBreak, 1);
2058 lcl_endCharacterGroup();
2059 lcl_endParagraphGroup();
2062 ParagraphPropertyMap* pParaContext = dynamic_cast< ParagraphPropertyMap* >( pContext.get() );
2063 if (pParaContext)
2064 pParaContext->SetFrameMode();
2066 if (!IsInHeaderFooter())
2067 m_pImpl->m_bIsActualParagraphFramed = true;
2069 else
2071 //TODO: What about style sheet import of frame properties
2073 resolveSprmProps(*this, rSprm);
2075 break;
2076 case NS_ooxml::LN_EG_SectPrContents_pgSz:
2078 PaperInfo aLetter(PAPER_LETTER);
2079 CT_PageSz.w = aLetter.getWidth();
2080 CT_PageSz.h = aLetter.getHeight();
2082 CT_PageSz.orient = false;
2083 resolveSprmProps(*this, rSprm);
2084 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
2085 if(pSectionContext)
2087 pSectionContext->Insert( PROP_HEIGHT, uno::makeAny( CT_PageSz.h ) );
2088 pSectionContext->Insert( PROP_IS_LANDSCAPE, uno::makeAny( CT_PageSz.orient ));
2089 pSectionContext->Insert( PROP_WIDTH, uno::makeAny( CT_PageSz.w ) );
2091 break;
2093 case NS_ooxml::LN_EG_SectPrContents_pgMar:
2094 m_pImpl->InitPageMargins();
2095 resolveSprmProps(*this, rSprm);
2096 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
2097 if(pSectionContext)
2099 const PageMar& rPageMar = m_pImpl->GetPageMargins();
2100 pSectionContext->SetTopMargin( rPageMar.top );
2101 pSectionContext->SetRightMargin( rPageMar.right );
2102 pSectionContext->SetBottomMargin( rPageMar.bottom );
2103 pSectionContext->SetLeftMargin( rPageMar.left );
2104 pSectionContext->SetHeaderTop( rPageMar.header );
2105 pSectionContext->SetHeaderBottom( rPageMar.footer );
2107 break;
2109 case NS_ooxml::LN_EG_SectPrContents_cols:
2111 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2112 if( pProperties.get())
2115 tools::SvRef< SectionColumnHandler > pSectHdl( new SectionColumnHandler );
2116 pProperties->resolve(*pSectHdl);
2117 if(pSectionContext && !m_pImpl->isInIndexContext())
2119 if( pSectHdl->IsEqualWidth() )
2121 pSectionContext->SetEvenlySpaced( true );
2122 pSectionContext->SetColumnCount( static_cast<sal_Int16>(pSectHdl->GetNum() - 1) );
2123 pSectionContext->SetColumnDistance( pSectHdl->GetSpace() );
2124 pSectionContext->SetSeparatorLine( pSectHdl->IsSeparator() );
2126 else if( !pSectHdl->GetColumns().empty() )
2128 pSectionContext->SetEvenlySpaced( false );
2129 pSectionContext->SetColumnDistance( pSectHdl->GetSpace() );
2130 pSectionContext->SetColumnCount( static_cast<sal_Int16>(pSectHdl->GetColumns().size() -1));
2131 std::vector<Column_>::const_iterator tmpIter = pSectHdl->GetColumns().begin();
2132 for (; tmpIter != pSectHdl->GetColumns().end(); ++tmpIter)
2134 pSectionContext->AppendColumnWidth( tmpIter->nWidth );
2135 if ((tmpIter != pSectHdl->GetColumns().end() - 1) || (tmpIter->nSpace > 0))
2136 pSectionContext->AppendColumnSpacing( tmpIter->nSpace );
2138 pSectionContext->SetSeparatorLine( pSectHdl->IsSeparator() );
2140 else if( pSectHdl->GetNum() > 0 )
2142 pSectionContext->SetColumnCount( static_cast<sal_Int16>(pSectHdl->GetNum()) - 1 );
2143 pSectionContext->SetColumnDistance( pSectHdl->GetSpace() );
2144 pSectionContext->SetSeparatorLine( pSectHdl->IsSeparator() );
2148 else if ( pSectionContext )
2150 FieldContextPtr pContext = m_pImpl->GetTopFieldContext();
2151 uno::Reference< beans::XPropertySet > xTOC = pContext->GetTOC();
2152 if( xTOC.is() )
2154 uno::Reference<text::XTextColumns> xTextColumns;
2155 xTOC->getPropertyValue(getPropertyName( PROP_TEXT_COLUMNS )) >>= xTextColumns;
2156 if (xTextColumns.is())
2158 uno::Reference< beans::XPropertySet > xColumnPropSet( xTextColumns, uno::UNO_QUERY_THROW );
2159 xColumnPropSet->setPropertyValue( getPropertyName( PROP_AUTOMATIC_DISTANCE ), uno::makeAny( pSectHdl->GetSpace() ));
2160 xTOC->setPropertyValue( getPropertyName( PROP_TEXT_COLUMNS ), uno::makeAny( xTextColumns ) );
2166 break;
2167 case NS_ooxml::LN_EG_SectPrContents_docGrid:
2168 resolveSprmProps(*this, rSprm);
2169 break;
2170 case NS_ooxml::LN_EG_SectPrContents_pgBorders:
2172 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2173 if( pProperties.get( ) && pSectionContext )
2175 tools::SvRef< PageBordersHandler > pHandler( new PageBordersHandler );
2176 pProperties->resolve( *pHandler );
2178 // Set the borders to the context and apply them to the styles
2179 pHandler->SetBorders( pSectionContext );
2182 break;
2184 case NS_ooxml::LN_CT_PPrBase_snapToGrid:
2185 if (!IsStyleSheetImport()||!m_pImpl->isInteropGrabBagEnabled())
2187 rContext->Insert( PROP_SNAP_TO_GRID, uno::makeAny(bool(nIntValue)));
2189 else
2191 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "snapToGrid", OUString::number(nIntValue));
2193 break;
2194 case NS_ooxml::LN_CT_PPrBase_pStyle:
2196 StyleSheetTablePtr pStyleTable = m_pImpl->GetStyleSheetTable();
2197 const OUString sConvertedStyleName = pStyleTable->ConvertStyleName( sStringValue, true );
2198 m_pImpl->SetCurrentParaStyleName( sConvertedStyleName );
2199 if (m_pImpl->GetTopContext() && m_pImpl->GetTopContextType() != CONTEXT_SECTION)
2200 m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, uno::makeAny( sConvertedStyleName ));
2202 break;
2203 case NS_ooxml::LN_EG_RPrBase_rStyle:
2205 OUString sConvertedName( m_pImpl->GetStyleSheetTable()->ConvertStyleName( sStringValue, true ) );
2206 if (m_pImpl->CheckFootnoteStyle())
2207 m_pImpl->SetHasFootnoteStyle(m_pImpl->GetFootnoteContext()->GetFootnoteStyle() == sConvertedName);
2209 // First check if the style exists in the document.
2210 StyleSheetEntryPtr pEntry = m_pImpl->GetStyleSheetTable( )->FindStyleSheetByConvertedStyleName( sConvertedName );
2211 bool bExists = pEntry.get( ) && ( pEntry->nStyleTypeCode == STYLE_TYPE_CHAR );
2212 // Add the property if the style exists, but do not add it elements in TOC:
2213 // they will receive later another style references from TOC
2214 if ( bExists && m_pImpl->GetTopContext() && !m_pImpl->IsInTOC())
2215 m_pImpl->GetTopContext()->Insert( PROP_CHAR_STYLE_NAME, uno::makeAny( sConvertedName ) );
2217 break;
2218 case NS_ooxml::LN_CT_TblPrBase_tblCellMar: //cell margins
2220 resolveSprmProps(*this, rSprm);//contains LN_CT_TblCellMar_top, LN_CT_TblCellMar_left, LN_CT_TblCellMar_bottom, LN_CT_TblCellMar_right
2222 break;
2223 case NS_ooxml::LN_CT_TblCellMar_top:
2224 case NS_ooxml::LN_CT_TblCellMar_start:
2225 case NS_ooxml::LN_CT_TblCellMar_left:
2226 case NS_ooxml::LN_CT_TblCellMar_bottom:
2227 case NS_ooxml::LN_CT_TblCellMar_end:
2228 case NS_ooxml::LN_CT_TblCellMar_right:
2230 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2231 if( pProperties.get())
2233 MeasureHandlerPtr pMeasureHandler( new MeasureHandler );
2234 pProperties->resolve(*pMeasureHandler);
2235 sal_Int32 nMeasureValue = pMeasureHandler->getMeasureValue();
2236 PropertyIds eId = META_PROP_CELL_MAR_TOP;
2237 bool rtl = false; // TODO
2238 switch(nSprmId)
2240 case NS_ooxml::LN_CT_TblCellMar_top:
2241 break;
2242 case NS_ooxml::LN_CT_TblCellMar_start:
2243 eId = rtl ? META_PROP_CELL_MAR_RIGHT : META_PROP_CELL_MAR_LEFT;
2244 break;
2245 case NS_ooxml::LN_CT_TblCellMar_left:
2246 eId = META_PROP_CELL_MAR_LEFT;
2247 break;
2248 case NS_ooxml::LN_CT_TblCellMar_bottom:
2249 eId = META_PROP_CELL_MAR_BOTTOM;
2250 break;
2251 case NS_ooxml::LN_CT_TblCellMar_end:
2252 eId = rtl ? META_PROP_CELL_MAR_LEFT : META_PROP_CELL_MAR_RIGHT;
2253 break;
2254 case NS_ooxml::LN_CT_TblCellMar_right:
2255 eId = META_PROP_CELL_MAR_RIGHT;
2256 break;
2257 default:;
2259 rContext->Insert( eId, uno::makeAny(nMeasureValue), false);
2262 break;
2263 case NS_ooxml::LN_EG_RPrBase_noProof: // no grammar and spell checking, unsupported
2264 break;
2265 case NS_ooxml::LN_anchor_anchor: // at_character drawing
2266 case NS_ooxml::LN_inline_inline: // as_character drawing
2268 if ( m_pImpl->IsDiscardHeaderFooter() )
2269 break;
2271 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2272 if( pProperties.get())
2274 GraphicImportType eGraphicType =
2275 (NS_ooxml::LN_anchor_anchor ==
2276 sal::static_int_cast<Id>(nSprmId)) ?
2277 IMPORT_AS_DETECTED_ANCHOR :
2278 IMPORT_AS_DETECTED_INLINE;
2279 GraphicImportPtr pGraphicImport =
2280 m_pImpl->GetGraphicImport(eGraphicType);
2281 pProperties->resolve(*pGraphicImport);
2282 m_pImpl->ImportGraphic(pProperties, eGraphicType);
2283 if( !pGraphicImport->IsGraphic() )
2285 m_pImpl->ResetGraphicImport();
2286 // todo: It's a shape, now start shape import
2290 break;
2291 case NS_ooxml::LN_EG_RPrBase_vertAlign:
2293 sal_Int16 nEscapement = 0;
2294 sal_Int8 nProp = DFLT_ESC_PROP;
2295 if ( sStringValue == "superscript" )
2296 nEscapement = DFLT_ESC_AUTO_SUPER;
2297 else if ( sStringValue == "subscript" )
2298 nEscapement = DFLT_ESC_AUTO_SUB;
2299 else
2300 nProp = 100;
2302 rContext->Insert(PROP_CHAR_ESCAPEMENT, uno::makeAny( nEscapement ) );
2303 rContext->Insert(PROP_CHAR_ESCAPEMENT_HEIGHT, uno::makeAny( nProp ) );
2305 break;
2306 case NS_ooxml::LN_CT_FtnProps_pos:
2307 //footnotes in word can be at page end or beneath text - writer supports only the first
2308 //endnotes in word can be at section end or document end - writer supports only the latter
2309 // -> so this property can be ignored
2310 break;
2311 case NS_ooxml::LN_CT_FtnProps_numFmt:
2312 case NS_ooxml::LN_CT_EdnProps_numFmt:
2314 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2315 if (pProperties.get())
2317 pProperties->resolve(*this);
2320 break;
2321 case NS_ooxml::LN_EG_FtnEdnNumProps_numStart:
2322 case NS_ooxml::LN_EG_FtnEdnNumProps_numRestart:
2326 uno::Reference< beans::XPropertySet > xFtnEdnSettings;
2327 if( m_pImpl->IsInFootnoteProperties() )
2329 uno::Reference< text::XFootnotesSupplier> xFootnotesSupplier( m_pImpl->GetTextDocument(), uno::UNO_QUERY );
2330 if (xFootnotesSupplier.is())
2331 xFtnEdnSettings = xFootnotesSupplier->getFootnoteSettings();
2333 else
2335 uno::Reference< text::XEndnotesSupplier> xEndnotesSupplier( m_pImpl->GetTextDocument(), uno::UNO_QUERY );
2336 if (xEndnotesSupplier.is())
2337 xFtnEdnSettings = xEndnotesSupplier->getEndnoteSettings();
2339 if( NS_ooxml::LN_EG_FtnEdnNumProps_numStart == nSprmId && xFtnEdnSettings.is())
2341 xFtnEdnSettings->setPropertyValue(
2342 getPropertyName( PROP_START_AT),
2343 uno::makeAny( sal_Int16( nIntValue - 1 )));
2345 else if( NS_ooxml::LN_EG_FtnEdnNumProps_numRestart == nSprmId && xFtnEdnSettings.is())
2347 sal_Int16 nFootnoteCounting = 0;
2348 switch (nIntValue)
2350 case NS_ooxml::LN_Value_ST_RestartNumber_continuous: nFootnoteCounting = text::FootnoteNumbering::PER_DOCUMENT; break;
2351 case NS_ooxml::LN_Value_ST_RestartNumber_eachPage: nFootnoteCounting = text::FootnoteNumbering::PER_PAGE; break;
2352 case NS_ooxml::LN_Value_ST_RestartNumber_eachSect: nFootnoteCounting = text::FootnoteNumbering::PER_CHAPTER; break;
2353 default: break;
2355 xFtnEdnSettings->setPropertyValue(
2356 getPropertyName( PROP_FOOTNOTE_COUNTING ),
2357 uno::makeAny( nFootnoteCounting ));
2359 else if (xFtnEdnSettings.is())
2361 sal_Int16 nNumType = ConversionHelper::ConvertNumberingType( nIntValue );
2362 xFtnEdnSettings->setPropertyValue(
2363 getPropertyName( PROP_NUMBERING_TYPE),
2364 uno::makeAny( nNumType ));
2367 catch( const uno::Exception& )
2371 break;
2372 case NS_ooxml::LN_paratrackchange:
2373 m_pImpl->StartParaMarkerChange( );
2374 [[fallthrough]];
2375 case NS_ooxml::LN_CT_PPr_pPrChange:
2376 case NS_ooxml::LN_CT_ParaRPr_rPrChange:
2377 case NS_ooxml::LN_trackchange:
2378 case NS_ooxml::LN_EG_RPrContent_rPrChange:
2379 case NS_ooxml::LN_EG_RangeMarkupElements_customXmlDelRangeStart:
2380 case NS_ooxml::LN_EG_RangeMarkupElements_customXmlDelRangeEnd:
2381 case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveFromRangeStart:
2382 case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveFromRangeEnd:
2383 case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveToRangeStart:
2384 case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveToRangeEnd:
2386 HandleRedline( rSprm );
2388 break;
2389 case NS_ooxml::LN_endtrackchange:
2390 m_pImpl->RemoveTopRedline();
2391 break;
2392 case NS_ooxml::LN_CT_RPrChange_rPr:
2394 // Push all the current 'Character' properties to the stack, so that we don't store them
2395 // as 'tracked changes' by mistake
2396 m_pImpl->PushProperties(CONTEXT_CHARACTER);
2398 // Resolve all the properties that are under the 'rPrChange'->'rPr' XML node
2399 resolveSprmProps(*this, rSprm );
2401 // Get all the properties that were processed in the 'rPrChange'->'rPr' XML node
2402 uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues();
2404 // Pop back out the character properties that were on the run
2405 m_pImpl->PopProperties(CONTEXT_CHARACTER);
2407 // Store these properties in the current redline object (do it after the PopProperties() above, since
2408 // otherwise it'd be stored in the content dropped there).
2409 m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties );
2411 break;
2412 case NS_ooxml::LN_CT_PPrChange_pPr:
2414 // Push all the current 'Paragraph' properties to the stack, so that we don't store them
2415 // as 'tracked changes' by mistake
2416 m_pImpl->PushProperties(CONTEXT_PARAGRAPH);
2418 // Resolve all the properties that are under the 'pPrChange'->'pPr' XML node
2419 resolveSprmProps(*this, rSprm );
2421 // Get all the properties that were processed in the 'pPrChange'->'pPr' XML node
2422 uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues();
2424 // Pop back out the character properties that were on the run
2425 m_pImpl->PopProperties(CONTEXT_PARAGRAPH);
2427 // Store these properties in the current redline object (do it after the PopProperties() above, since
2428 // otherwise it'd be stored in the content dropped there).
2429 m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties );
2431 break;
2432 case NS_ooxml::LN_object:
2434 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2435 if( pProperties.get( ) )
2437 auto pOLEHandler = std::make_shared<OLEHandler>(*this);
2438 pProperties->resolve(*pOLEHandler);
2439 if ( pOLEHandler->isOLEObject( ) )
2441 OUString sStreamName = pOLEHandler->copyOLEOStream( m_pImpl->GetTextDocument() );
2442 if( !sStreamName.isEmpty() )
2444 m_pImpl->appendOLE( sStreamName, pOLEHandler );
2449 break;
2450 case NS_ooxml::LN_EG_HdrFtrReferences_headerReference: // header reference - not needed
2451 case NS_ooxml::LN_EG_HdrFtrReferences_footerReference: // footer reference - not needed
2452 break;
2453 case NS_ooxml::LN_EG_RPrBase_snapToGrid: // "Use document grid settings for inter-paragraph spacing"
2454 break;
2455 case NS_ooxml::LN_CT_PPrBase_contextualSpacing:
2456 rContext->Insert(PROP_PARA_CONTEXT_MARGIN, uno::makeAny( nIntValue != 0 ));
2457 break;
2458 case NS_ooxml::LN_CT_PPrBase_mirrorIndents: // mirrorIndents
2459 rContext->Insert(PROP_MIRROR_INDENTS, uno::makeAny( nIntValue != 0 ), true, PARA_GRAB_BAG);
2460 break;
2461 case NS_ooxml::LN_EG_SectPrContents_formProt: //section protection
2463 if( pSectionContext )
2464 pSectionContext->Insert( PROP_IS_PROTECTED, uno::makeAny( bool(nIntValue) ) );
2466 break;
2467 case NS_ooxml::LN_EG_SectPrContents_vAlign:
2469 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
2470 if( pSectionContext )
2472 drawing::TextVerticalAdjust nVA = drawing::TextVerticalAdjust_TOP;
2473 switch( nIntValue )
2475 case NS_ooxml::LN_Value_ST_VerticalJc_center: //92367
2476 nVA = drawing::TextVerticalAdjust_CENTER;
2477 break;
2478 case NS_ooxml::LN_Value_ST_VerticalJc_both: //92368 - justify
2479 nVA = drawing::TextVerticalAdjust_BLOCK;
2480 break;
2481 case NS_ooxml::LN_Value_ST_VerticalJc_bottom: //92369
2482 nVA = drawing::TextVerticalAdjust_BOTTOM;
2483 break;
2484 default:
2485 break;
2487 pSectionContext->Insert( PROP_TEXT_VERTICAL_ADJUST, uno::makeAny( nVA ), true, PARA_GRAB_BAG );
2490 break;
2491 case NS_ooxml::LN_EG_RPrBase_fitText:
2492 break;
2493 case NS_ooxml::LN_ffdata:
2495 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2496 if (pProperties.get() != nullptr)
2498 FFDataHandler::Pointer_t pFFDataHandler(new FFDataHandler());
2500 pProperties->resolve(*pFFDataHandler);
2501 m_pImpl->SetFieldFFData(pFFDataHandler);
2504 break;
2505 case NS_ooxml::LN_CT_SdtPr_dropDownList:
2506 case NS_ooxml::LN_CT_SdtPr_comboBox:
2508 m_pImpl->m_pSdtHelper->setInsideDropDownControl(true);
2509 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2510 if (pProperties.get() != nullptr)
2511 pProperties->resolve(*this);
2513 break;
2514 case NS_ooxml::LN_CT_SdtDropDownList_listItem:
2516 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2517 if (pProperties.get() != nullptr)
2518 pProperties->resolve(*this);
2520 break;
2521 case NS_ooxml::LN_CT_SdtPr_date:
2523 resolveSprmProps(*this, rSprm);
2524 m_pImpl->m_pSdtHelper->setDateFieldStartRange(GetCurrentTextRange()->getEnd());
2526 break;
2527 case NS_ooxml::LN_CT_SdtDate_dateFormat:
2529 m_pImpl->m_pSdtHelper->getDateFormat().append(sStringValue);
2531 break;
2532 case NS_ooxml::LN_CT_SdtDate_storeMappedDataAs:
2535 break;
2536 case NS_ooxml::LN_CT_SdtDate_calendar:
2539 break;
2540 case NS_ooxml::LN_CT_SdtDate_lid:
2542 m_pImpl->m_pSdtHelper->getLocale().append(sStringValue);
2544 break;
2545 case NS_ooxml::LN_CT_SdtPr_dataBinding:
2546 case NS_ooxml::LN_CT_SdtPr_equation:
2547 case NS_ooxml::LN_CT_SdtPr_checkbox:
2548 case NS_ooxml::LN_CT_SdtPr_docPartObj:
2549 case NS_ooxml::LN_CT_SdtPr_docPartList:
2550 case NS_ooxml::LN_CT_SdtPr_picture:
2551 case NS_ooxml::LN_CT_SdtPr_citation:
2552 case NS_ooxml::LN_CT_SdtPr_group:
2553 case NS_ooxml::LN_CT_SdtPr_text:
2554 case NS_ooxml::LN_CT_SdtPr_id:
2555 case NS_ooxml::LN_CT_SdtPr_alias:
2557 // this is an unsupported SDT property, create a grab bag for it
2558 OUString sName;
2559 switch (nSprmId)
2561 case NS_ooxml::LN_CT_SdtPr_dataBinding: sName = "ooxml:CT_SdtPr_dataBinding"; break;
2562 case NS_ooxml::LN_CT_SdtPr_equation: sName = "ooxml:CT_SdtPr_equation"; break;
2563 case NS_ooxml::LN_CT_SdtPr_checkbox: sName = "ooxml:CT_SdtPr_checkbox"; break;
2564 case NS_ooxml::LN_CT_SdtPr_docPartObj: sName = "ooxml:CT_SdtPr_docPartObj"; break;
2565 case NS_ooxml::LN_CT_SdtPr_docPartList: sName = "ooxml:CT_SdtPr_docPartList"; break;
2566 case NS_ooxml::LN_CT_SdtPr_picture: sName = "ooxml:CT_SdtPr_picture"; break;
2567 case NS_ooxml::LN_CT_SdtPr_citation: sName = "ooxml:CT_SdtPr_citation"; break;
2568 case NS_ooxml::LN_CT_SdtPr_group: sName = "ooxml:CT_SdtPr_group"; break;
2569 case NS_ooxml::LN_CT_SdtPr_text: sName = "ooxml:CT_SdtPr_text"; break;
2570 case NS_ooxml::LN_CT_SdtPr_id: sName = "ooxml:CT_SdtPr_id"; break;
2571 case NS_ooxml::LN_CT_SdtPr_alias: sName = "ooxml:CT_SdtPr_alias"; break;
2572 default: assert(false);
2574 enableInteropGrabBag(sName);
2576 // process subitems
2577 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2578 if (pProperties.get() != nullptr)
2579 pProperties->resolve(*this);
2581 if (nSprmId == NS_ooxml::LN_CT_SdtPr_alias)
2583 beans::PropertyValue aValue;
2584 aValue.Name = sName;
2585 aValue.Value <<= sStringValue;
2586 m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue);
2588 else
2589 m_pImpl->m_pSdtHelper->appendToInteropGrabBag(getInteropGrabBag());
2590 m_pImpl->m_pSdtHelper->setOutsideAParagraph(m_pImpl->IsOutsideAParagraph());
2591 m_pImpl->disableInteropGrabBag();
2593 break;
2594 case NS_ooxml::LN_CT_SdtCheckbox_checked:
2595 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checked", sStringValue);
2596 break;
2597 case NS_ooxml::LN_CT_SdtCheckbox_checkedState:
2598 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checkedState", sStringValue);
2599 break;
2600 case NS_ooxml::LN_CT_SdtCheckbox_uncheckedState:
2601 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_uncheckedState", sStringValue);
2602 break;
2603 case NS_ooxml::LN_CT_SdtDocPart_docPartGallery:
2604 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartGallery", sStringValue);
2605 break;
2606 case NS_ooxml::LN_CT_SdtDocPart_docPartCategory:
2607 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartCategory", sStringValue);
2608 break;
2609 case NS_ooxml::LN_CT_SdtDocPart_docPartUnique:
2610 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartUnique", sStringValue);
2611 break;
2612 case NS_ooxml::LN_EG_SectPrContents_pgNumType:
2614 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2615 if( pProperties.get())
2617 pProperties->resolve(*this);
2620 break;
2621 case NS_ooxml::LN_tblStart:
2623 if (m_pImpl->hasTableManager())
2625 bool bTableStartsAtCellStart = m_pImpl->m_nTableDepth > 0 && m_pImpl->m_nTableCellDepth > m_pImpl->m_nLastTableCellParagraphDepth + 1;
2626 m_pImpl->getTableManager().setTableStartsAtCellStart(bTableStartsAtCellStart);
2629 * Hack for Importing Section Properties
2630 * LO is not able to import section properties if first element in the
2631 * section is a table. So in case first element is a table add a dummy para
2632 * and remove it again when lcl_endSectionGroup is called
2634 if(m_pImpl->m_nTableDepth == 0 && m_pImpl->GetIsFirstParagraphInSection()
2635 && !m_pImpl->GetIsDummyParaAddedForTableInSection() && !m_pImpl->GetIsTextFrameInserted()
2636 && !IsInHeaderFooter())
2638 m_pImpl->AddDummyParaForTableInSection();
2641 // if first paragraph style in table has break-before-page, transfer that setting to the table itself.
2642 if( m_pImpl->m_nTableDepth == 0 )
2644 const uno::Any aBreakType = uno::makeAny(style::BreakType_PAGE_BEFORE);
2645 const PropertyMapPtr pParagraphProps = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
2646 if( pParagraphProps && pParagraphProps->isSet(PROP_PARA_STYLE_NAME) )
2648 StyleSheetEntryPtr pStyle;
2649 OUString sStyleName;
2650 pParagraphProps->getProperty(PROP_PARA_STYLE_NAME)->second >>= sStyleName;
2651 if( !sStyleName.isEmpty() && GetStyleSheetTable() )
2652 pStyle = GetStyleSheetTable()->FindStyleSheetByConvertedStyleName( sStyleName );
2654 if( pStyle && pStyle->pProperties
2655 && pStyle->pProperties->isSet(PROP_BREAK_TYPE)
2656 && pStyle->pProperties->getProperty(PROP_BREAK_TYPE)->second == aBreakType )
2658 pParagraphProps->Insert(PROP_BREAK_TYPE, aBreakType);
2663 m_pImpl->m_nTableDepth++;
2665 break;
2666 case NS_ooxml::LN_tblEnd:
2667 m_pImpl->m_nTableDepth--;
2668 break;
2669 case NS_ooxml::LN_tcStart:
2670 m_pImpl->m_nTableCellDepth++;
2671 break;
2672 case NS_ooxml::LN_tcEnd:
2673 m_pImpl->m_nTableCellDepth--;
2674 m_pImpl->m_nLastTableCellParagraphDepth = 0;
2675 break;
2676 case NS_ooxml::LN_glow_glow:
2677 case NS_ooxml::LN_shadow_shadow:
2678 case NS_ooxml::LN_reflection_reflection:
2679 case NS_ooxml::LN_textOutline_textOutline:
2680 case NS_ooxml::LN_textFill_textFill:
2681 case NS_ooxml::LN_scene3d_scene3d:
2682 case NS_ooxml::LN_props3d_props3d:
2683 case NS_ooxml::LN_ligatures_ligatures:
2684 case NS_ooxml::LN_numForm_numForm:
2685 case NS_ooxml::LN_numSpacing_numSpacing:
2686 case NS_ooxml::LN_stylisticSets_stylisticSets:
2687 case NS_ooxml::LN_cntxtAlts_cntxtAlts:
2689 tools::SvRef<TextEffectsHandler> pTextEffectsHandlerPtr( new TextEffectsHandler(nSprmId) );
2690 std::optional<PropertyIds> aPropertyId = pTextEffectsHandlerPtr->getGrabBagPropertyId();
2691 if(aPropertyId)
2693 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2694 if( pProperties.get())
2696 pProperties->resolve(*pTextEffectsHandlerPtr);
2698 beans::PropertyValue aGrabBag = pTextEffectsHandlerPtr->getInteropGrabBag();
2699 rContext->Insert(*aPropertyId, uno::makeAny(aGrabBag), true, CHAR_GRAB_BAG);
2701 sal_Int16 nTransparency = TextEffectsHandler::GetTextFillSolidFillAlpha(aGrabBag);
2702 if (nTransparency != 0)
2704 rContext->Insert(PROP_CHAR_TRANSPARENCE, uno::makeAny(nTransparency));
2709 break;
2710 case NS_ooxml::LN_CT_SdtPr_rPr:
2712 // Make sure properties from a previous SDT are not merged with the current ones.
2713 m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
2715 break;
2716 case NS_ooxml::LN_CT_TblPrBase_tblLook:
2718 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2719 if (pProperties.get())
2721 pProperties->resolve(*this);
2722 m_pImpl->getTableManager().finishTableLook();
2725 break;
2726 case NS_ooxml::LN_CT_TrPrBase_cnfStyle:
2728 m_pImpl->enableInteropGrabBag("cnfStyle");
2729 resolveSprmProps(*this, rSprm);
2731 TablePropertyMapPtr pPropMap(new TablePropertyMap());
2732 pPropMap->Insert(PROP_ROW_CNF_STYLE, uno::makeAny(comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag)), true, ROW_GRAB_BAG);
2733 m_pImpl->getTableManager().insertRowProps(pPropMap);
2735 m_pImpl->disableInteropGrabBag();
2737 break;
2738 case NS_ooxml::LN_CT_TcPrBase_cnfStyle:
2740 m_pImpl->enableInteropGrabBag("cnfStyle");
2741 resolveSprmProps(*this, rSprm);
2743 TablePropertyMapPtr pPropMap(new TablePropertyMap());
2744 pPropMap->Insert(PROP_CELL_CNF_STYLE, uno::makeAny(comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag)), true, CELL_GRAB_BAG);
2745 m_pImpl->getTableManager().cellProps(pPropMap);
2747 m_pImpl->disableInteropGrabBag();
2749 break;
2750 case NS_ooxml::LN_CT_PPrBase_cnfStyle:
2752 m_pImpl->enableInteropGrabBag("cnfStyle");
2753 resolveSprmProps(*this, rSprm);
2754 rContext->Insert(PROP_PARA_CNF_STYLE, uno::makeAny(comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag)), true, PARA_GRAB_BAG);
2755 m_pImpl->disableInteropGrabBag();
2757 break;
2758 case NS_ooxml::LN_EG_RunInnerContent_sym:
2760 resolveSprmProps(*this, rSprm);
2761 SymbolData aSymbolData = m_pImpl->GetSymbolData();
2762 uno::Any aVal = uno::makeAny( aSymbolData.sFont );
2763 auto xFootnote = rContext->GetFootnote();
2764 if (!xFootnote.is() && m_pImpl->IsInCustomFootnote())
2765 xFootnote = m_pImpl->GetFootnoteContext()->GetFootnote();
2766 if (xFootnote.is())
2768 // DOCX can have different labels for the footnote reference and the footnote area.
2769 // This skips the one from the footnote area and just uses the reference one.
2770 if (!m_pImpl->IsInFootOrEndnote())
2772 auto xAnchorRange = xFootnote->getAnchor();
2773 auto xAnchorCursor(xAnchorRange->getText()->createTextCursorByRange(xAnchorRange));
2775 // append a dummy character, so the following properties will be set as
2776 // as SwpHints::SwTextAttr instead of the SwAttrSet of the paragraph,
2777 // which would be removed by SwXText::Impl::finishOrAppendParagraph
2778 xAnchorCursor->collapseToEnd();
2779 uno::Reference<text::XTextRange> xHackRange(xAnchorCursor, uno::UNO_QUERY);
2780 xHackRange->setString("x");
2782 uno::Reference<beans::XPropertySet> xAnchorProps(xAnchorRange, uno::UNO_QUERY);
2783 xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME), aVal);
2784 xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME_ASIAN), aVal);
2785 xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME_COMPLEX), aVal);
2786 xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_CHAR_SET), uno::makeAny(awt::CharSet::SYMBOL));
2788 // remove the dummy char
2789 xHackRange->setString("");
2791 OUString sLabel = xFootnote->getLabel() + OUStringChar(aSymbolData.cSymbol);
2792 xFootnote->setLabel(sLabel);
2795 else //it's a _real_ symbol
2797 rContext->Insert(PROP_CHAR_FONT_NAME, aVal);
2798 rContext->Insert(PROP_CHAR_FONT_NAME_ASIAN, aVal);
2799 rContext->Insert(PROP_CHAR_FONT_NAME_COMPLEX, aVal);
2800 rContext->Insert(PROP_CHAR_FONT_CHAR_SET, uno::makeAny(awt::CharSet::SYMBOL));
2801 utext( reinterpret_cast < const sal_uInt8 * >( &(aSymbolData.cSymbol) ), 1 );
2804 break;
2805 case NS_ooxml::LN_EG_RunInnerContent_ruby:
2807 RubyInfo aInfo ;
2808 m_pImpl->SetRubyInfo(aInfo);
2810 break;
2811 case NS_ooxml::LN_CT_RubyPr:
2812 case NS_ooxml::LN_CT_Ruby_rt:
2813 case NS_ooxml::LN_CT_Ruby_rubyBase:
2815 m_pImpl->SetRubySprmId(nSprmId);
2816 if (nSprmId == NS_ooxml::LN_CT_RubyPr)
2818 resolveSprmProps(*this, rSprm);
2821 break;
2822 case NS_ooxml::LN_EG_RubyContent_r:
2824 const RubyInfo & aInfo = m_pImpl->GetRubyInfo();
2825 if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rubyBase)
2827 rContext->Insert(PROP_RUBY_TEXT, uno::makeAny(aInfo.sRubyText));
2828 rContext->Insert(PROP_RUBY_STYLE, uno::makeAny(aInfo.sRubyStyle));
2829 rContext->Insert(PROP_RUBY_ADJUST, uno::makeAny(static_cast<sal_Int16>(ConversionHelper::convertRubyAlign(aInfo.nRubyAlign))));
2830 if ( aInfo.nRubyAlign == NS_ooxml::LN_Value_ST_RubyAlign_rightVertical )
2831 rContext->Insert(PROP_RUBY_POSITION, uno::makeAny(css::text::RubyPosition::INTER_CHARACTER));
2833 m_pImpl->SetRubySprmId(0);
2836 break;
2837 case NS_ooxml::LN_CT_RubyPr_rubyAlign:
2838 case NS_ooxml::LN_CT_RubyPr_hps:
2839 case NS_ooxml::LN_CT_RubyPr_hpsBaseText:
2841 RubyInfo aInfo = m_pImpl->GetRubyInfo();
2842 switch(nSprmId)
2844 case NS_ooxml::LN_CT_RubyPr_rubyAlign:
2845 aInfo.nRubyAlign = nIntValue;
2846 break;
2847 case NS_ooxml::LN_CT_RubyPr_hps:
2848 aInfo.nHps= nIntValue;
2849 break;
2850 case NS_ooxml::LN_CT_RubyPr_hpsBaseText:
2851 aInfo.nHpsBaseText = nIntValue;
2852 break;
2854 m_pImpl->SetRubyInfo(aInfo);
2856 break;
2857 case NS_ooxml::LN_CT_SmartTagRun_smartTagPr:
2859 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2860 if (pProperties.get() && m_pImpl->GetTopContextType() == CONTEXT_PARAGRAPH)
2861 pProperties->resolve(m_pImpl->getSmartTagHandler());
2863 break;
2864 case NS_ooxml::LN_CT_DocPartPr_name:
2866 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2867 if (pProperties.get() != nullptr)
2868 pProperties->resolve(*this);
2870 break;
2871 case NS_ooxml::LN_CT_DocPartPr_category:
2873 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2874 if (pProperties.get() != nullptr)
2875 pProperties->resolve(*this);
2877 break;
2878 case NS_ooxml::LN_CT_DocPartCategory_gallery:
2880 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
2881 if (pProperties.get() != nullptr)
2882 pProperties->resolve(*this);
2884 break;
2885 default:
2887 #ifdef DBG_UTIL
2888 TagLogger::getInstance().startElement("unhandled");
2889 TagLogger::getInstance().attribute("id", nSprmId);
2890 TagLogger::getInstance().attribute("name", rSprm.getName());
2891 TagLogger::getInstance().endElement();
2892 #endif
2897 void DomainMapper::processDeferredCharacterProperties( const std::map< sal_Int32, uno::Any >& deferredCharacterProperties )
2899 assert( m_pImpl->GetTopContextType() == CONTEXT_CHARACTER );
2900 PropertyMapPtr rContext = m_pImpl->GetTopContext();
2901 for( const auto& rProp : deferredCharacterProperties )
2903 sal_Int32 Id = rProp.first;
2904 sal_Int32 nIntValue = 0;
2905 OUString sStringValue;
2906 rProp.second >>= nIntValue;
2907 rProp.second >>= sStringValue;
2908 switch( Id )
2910 case NS_ooxml::LN_EG_RPrBase_position:
2912 double nEscapement = 0;
2913 sal_Int8 nProp = 0;
2914 if ( nIntValue )
2916 nProp = 100;
2917 double fFontSize = 0;
2918 m_pImpl->GetAnyProperty(PROP_CHAR_HEIGHT, rContext) >>= fFontSize;
2919 if ( fFontSize )
2920 // nIntValue is in half-points, fontsize is in points, escapement is a percentage.
2921 nEscapement = round( nIntValue/2.0 / fFontSize * 100 );
2922 else
2923 nEscapement = nIntValue > 0 ? DFLT_ESC_SUPER : DFLT_ESC_SUB;
2925 if ( nEscapement > MAX_ESC_POS )
2926 nEscapement = MAX_ESC_POS;
2927 else if ( nEscapement < -MAX_ESC_POS )
2928 nEscapement = -MAX_ESC_POS;
2930 rContext->Insert(PROP_CHAR_ESCAPEMENT, uno::makeAny( sal_Int16(nEscapement) ) );
2931 rContext->Insert(PROP_CHAR_ESCAPEMENT_HEIGHT, uno::makeAny( nProp ) );
2933 break;
2934 default:
2935 SAL_WARN( "writerfilter", "Unhandled property in processDeferredCharacterProperty()" );
2936 break;
2941 void DomainMapper::lcl_entry(writerfilter::Reference<Properties>::Pointer_t ref)
2943 ref->resolve(*this);
2946 void DomainMapper::data(const sal_uInt8* /*buf*/, size_t /*len*/)
2950 void DomainMapper::lcl_startSectionGroup()
2952 if (!m_pImpl->isInIndexContext() && !m_pImpl->isInBibliographyContext())
2954 m_pImpl->PushProperties(CONTEXT_SECTION);
2956 m_pImpl->SetIsFirstParagraphInSection(true);
2957 m_pImpl->SetIsFirstParagraphInSectionAfterRedline(true);
2960 void DomainMapper::lcl_endSectionGroup()
2962 if (!m_pImpl->isInIndexContext() && !m_pImpl->isInBibliographyContext())
2964 m_pImpl->CheckUnregisteredFrameConversion();
2965 m_pImpl->ExecuteFrameConversion();
2966 // When pasting, it's fine to not have any paragraph inside the document at all.
2967 if (m_pImpl->GetIsFirstParagraphInSection() && m_pImpl->IsNewDoc())
2969 // This section has no paragraph at all (e.g. they are all actually in a frame).
2970 // If this section has a page break, there would be nothing to apply to the page
2971 // style, so force a dummy paragraph.
2972 lcl_startParagraphGroup();
2973 lcl_startCharacterGroup();
2974 sal_uInt8 const sBreak[] = { 0xd };
2975 lcl_text(sBreak, 1);
2976 lcl_endCharacterGroup();
2977 lcl_endParagraphGroup();
2979 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_SECTION);
2980 SectionPropertyMap* pSectionContext = dynamic_cast< SectionPropertyMap* >( pContext.get() );
2981 OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
2982 if(pSectionContext)
2984 pSectionContext->CloseSectionGroup( *m_pImpl );
2985 // Remove the dummy paragraph if added for
2986 // handling the section properties if section starts with a table
2987 if (m_pImpl->GetIsDummyParaAddedForTableInSection())
2988 m_pImpl->RemoveDummyParaForTableInSection();
2990 m_pImpl->SetIsTextFrameInserted( false );
2991 m_pImpl->PopProperties(CONTEXT_SECTION);
2995 void DomainMapper::lcl_startParagraphGroup()
2997 if (m_pImpl->hasTableManager())
2998 m_pImpl->getTableManager().startParagraphGroup();
3000 * Add new para properties only if paragraph is not split
3001 * or the top context is not of paragraph properties
3002 * Set mbIsSplitPara to false as it has been handled
3004 if (!mbIsSplitPara)
3005 m_pImpl->PushProperties(CONTEXT_PARAGRAPH);
3006 mbIsSplitPara = false;
3007 if (m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) != m_pImpl->GetTopContext())
3008 m_pImpl->PushProperties(CONTEXT_PARAGRAPH);
3010 if (m_pImpl->GetTopContext())
3012 if (!m_pImpl->IsInShape())
3014 const OUString& sDefaultParaStyle = m_pImpl->GetDefaultParaStyleName();
3015 m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, uno::makeAny( sDefaultParaStyle ) );
3016 m_pImpl->SetCurrentParaStyleName( sDefaultParaStyle );
3018 if (m_pImpl->isBreakDeferred(PAGE_BREAK))
3019 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_PAGE_BEFORE));
3020 else if (m_pImpl->isBreakDeferred(COLUMN_BREAK))
3021 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_COLUMN_BEFORE));
3023 if (m_pImpl->isParaSdtEndDeferred())
3024 m_pImpl->GetTopContext()->Insert(PROP_PARA_SDT_END_BEFORE, uno::makeAny(true), true, PARA_GRAB_BAG);
3026 m_pImpl->SetIsFirstRun(true);
3027 m_pImpl->SetIsOutsideAParagraph(false);
3028 m_pImpl->clearDeferredBreaks();
3029 m_pImpl->setParaSdtEndDeferred(false);
3032 void DomainMapper::lcl_endParagraphGroup()
3034 m_pImpl->PopProperties(CONTEXT_PARAGRAPH);
3035 if (m_pImpl->hasTableManager())
3036 m_pImpl->getTableManager().endParagraphGroup();
3037 //frame conversion has to be executed after table conversion
3038 m_pImpl->ExecuteFrameConversion();
3039 m_pImpl->SetIsOutsideAParagraph(true);
3042 void DomainMapper::markLastParagraphInSection( )
3044 m_pImpl->SetIsLastParagraphInSection( true );
3047 void DomainMapper::markLastSectionGroup( )
3049 m_pImpl->SetIsLastSectionGroup( true );
3052 void DomainMapper::lcl_startShape(uno::Reference<drawing::XShape> const& xShape)
3054 assert(xShape.is());
3056 if (m_pImpl->GetTopContext())
3058 // If there is a deferred page break, handle it now, so that the
3059 // started shape will be on the correct page.
3060 if (m_pImpl->isBreakDeferred(PAGE_BREAK))
3062 m_pImpl->clearDeferredBreak(PAGE_BREAK);
3063 lcl_startCharacterGroup();
3064 sal_uInt8 const sBreak[] = { 0xd };
3065 lcl_text(sBreak, 1);
3066 lcl_endCharacterGroup();
3067 lcl_endParagraphGroup();
3068 lcl_startParagraphGroup();
3069 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_PAGE_BEFORE));
3071 m_pImpl->PushShapeContext( xShape );
3072 lcl_startParagraphGroup();
3074 else
3076 // No context? Then this image should not appear directly inside the
3077 // document, just save it for later usage.
3078 m_pImpl->PushPendingShape(xShape);
3081 m_pImpl->SetIsFirstParagraphInShape(true);
3085 void DomainMapper::lcl_endShape( )
3087 if (m_pImpl->GetTopContext())
3089 // End the current table, if there are any. Otherwise the unavoidable
3090 // empty paragraph at the end of the shape text will cause problems: if
3091 // the shape text ends with a table, the extra paragraph will be
3092 // handled as an additional row of the ending table.
3093 if (m_pImpl->hasTableManager())
3094 m_pImpl->getTableManager().endTable();
3096 lcl_endParagraphGroup();
3097 m_pImpl->PopShapeContext( );
3098 // A shape is always inside a paragraph (anchored or inline).
3099 m_pImpl->SetIsOutsideAParagraph(false);
3103 void DomainMapper::PushStyleSheetProperties( const PropertyMapPtr& pStyleProperties, bool bAffectTableMngr )
3105 m_pImpl->PushStyleProperties( pStyleProperties );
3106 if ( bAffectTableMngr )
3107 m_pImpl->getTableManager( ).SetStyleProperties( pStyleProperties );
3110 void DomainMapper::PopStyleSheetProperties( bool bAffectTableMngr )
3112 m_pImpl->PopProperties( CONTEXT_STYLESHEET );
3113 if ( bAffectTableMngr )
3115 PropertyMapPtr emptyPtr;
3116 m_pImpl->getTableManager( ).SetStyleProperties( emptyPtr );
3120 void DomainMapper::PushListProperties( const ::tools::SvRef<PropertyMap>& pListProperties )
3122 m_pImpl->PushListProperties( pListProperties );
3125 void DomainMapper::PopListProperties()
3127 m_pImpl->PopProperties( CONTEXT_LIST );
3130 void DomainMapper::lcl_startCharacterGroup()
3132 m_pImpl->PushProperties(CONTEXT_CHARACTER);
3133 if (m_pImpl->isSdtEndDeferred())
3135 // Fields have an empty character group before the real one, so don't
3136 // call setSdtEndDeferred(false) here, that will happen only in lcl_utext().
3137 m_pImpl->GetTopContext()->Insert(PROP_SDT_END_BEFORE, uno::makeAny(true), true, CHAR_GRAB_BAG);
3141 void DomainMapper::lcl_endCharacterGroup()
3143 if (m_pImpl->CheckFootnoteStyle())
3145 m_pImpl->SetCheckFootnoteStyle(m_pImpl->IsInCustomFootnote());
3146 m_pImpl->SetHasFootnoteStyle(false);
3148 m_pImpl->PopProperties(CONTEXT_CHARACTER);
3151 void DomainMapper::lcl_text(const sal_uInt8 * data_, size_t len)
3153 //TODO: Determine the right text encoding (FIB?)
3154 OUString sText( reinterpret_cast<const char*>(data_), len, RTL_TEXTENCODING_MS_1252 );
3155 #ifdef DBG_UTIL
3156 TagLogger::getInstance().startElement("text");
3157 TagLogger::getInstance().chars(sText);
3158 TagLogger::getInstance().endElement();
3159 #endif
3163 if(len == 1)
3165 switch(*data_)
3167 case 0x02: return; //footnote character
3168 case 0x08: // Lock field if in field context
3169 if (m_pImpl->IsOpenField())
3170 m_pImpl->SetFieldLocked();
3171 return;
3172 case 0x0c: //page break
3173 m_pImpl->deferBreak(PAGE_BREAK);
3174 return;
3175 case 0x0e: //column break
3176 m_pImpl->deferBreak(COLUMN_BREAK);
3177 return;
3178 case 0x07:
3179 m_pImpl->getTableManager().text(data_, len);
3180 return;
3181 case 0x0d:
3183 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
3184 if (pContext && m_pImpl->isBreakDeferred(COLUMN_BREAK))
3186 pContext->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_COLUMN_BEFORE));
3187 m_pImpl->clearDeferredBreak(COLUMN_BREAK);
3189 finishParagraph();
3190 return;
3192 case cFieldStart:
3193 m_pImpl->PushFieldContext();
3194 return;
3195 case cFieldSep:
3196 // delimiter not necessarily available
3197 // appears only if field contains further content
3198 m_pImpl->CloseFieldCommand();
3199 return;
3200 case cFieldEnd:
3201 m_pImpl->PopFieldContext();
3202 return;
3203 default:
3204 break;
3208 // GetTopContext() is changed by inserted breaks, but we want to keep the current context
3209 PropertyMapPtr pContext = m_pImpl->GetTopContext();
3210 if (!m_pImpl->GetFootnoteContext())
3212 if (m_pImpl->isBreakDeferred(PAGE_BREAK))
3213 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_PAGE_BEFORE));
3214 else if (m_pImpl->isBreakDeferred(COLUMN_BREAK))
3215 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_COLUMN_BEFORE));
3216 m_pImpl->clearDeferredBreaks();
3219 if (pContext && pContext->GetFootnote().is() && m_pImpl->IsInCustomFootnote())
3221 pContext->GetFootnote()->setLabel(sText);
3222 m_pImpl->EndCustomFootnote();
3223 //otherwise ignore sText
3225 else if (m_pImpl->IsOpenFieldCommand() && !m_pImpl->IsForceGenericFields())
3227 m_pImpl->AppendFieldCommand(sText);
3229 else if( m_pImpl->IsOpenField() && m_pImpl->IsFieldResultAsString())
3230 /*depending on the success of the field insert operation this result will be
3231 set at the field or directly inserted into the text*/
3232 m_pImpl->AppendFieldResult(sText);
3233 else
3235 if (pContext == nullptr)
3236 pContext = new PropertyMap();
3238 m_pImpl->appendTextPortion( sText, pContext );
3241 catch( const uno::RuntimeException& )
3243 TOOLS_WARN_EXCEPTION("writerfilter", "");
3247 void DomainMapper::lcl_positionOffset(const OUString& rText, bool bVertical)
3249 if (bVertical)
3250 m_pImpl->m_aPositionOffsets.second = rText;
3251 else
3252 m_pImpl->m_aPositionOffsets.first = rText;
3255 awt::Point DomainMapper::getPositionOffset()
3257 awt::Point aRet;
3258 aRet.X = oox::drawingml::convertEmuToHmm(m_pImpl->m_aPositionOffsets.first.toInt32());
3259 aRet.Y = oox::drawingml::convertEmuToHmm(m_pImpl->m_aPositionOffsets.second.toInt32());
3260 return aRet;
3263 void DomainMapper::lcl_align(const OUString& rText, bool bVertical)
3265 if (bVertical)
3266 m_pImpl->m_aAligns.second = rText;
3267 else
3268 m_pImpl->m_aAligns.first = rText;
3271 void DomainMapper::lcl_positivePercentage(const OUString& rText)
3273 m_pImpl->m_aPositivePercentages.push(rText);
3276 void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
3278 // All these fixed values are defined as static const sal_Unicode codepoints in the fast parser,
3279 // like uFtnEdnRef = 0x2, uFtnEdnSep = 0x3, ... and have a len of 1, if they aren't valid unicode.
3281 OUString sText(reinterpret_cast<const sal_Unicode *>(data_), len);
3282 const RubyInfo & aInfo = m_pImpl->GetRubyInfo();
3283 if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rt)
3285 PropertyMapPtr pContext = m_pImpl->GetTopContext();
3286 PropertyValueVector_t aProps = comphelper::sequenceToContainer< PropertyValueVector_t >(pContext->GetPropertyValues());
3287 OUString sStyle = getOrCreateCharStyle(aProps, /*bAlwaysCreate=*/false);
3288 m_pImpl->SetRubyText(sText,sStyle);
3289 return;
3292 if (len == 1)
3294 // If the footnote contains a Footnote Reference Mark, it can't be a custom footnote
3295 // ******
3296 // This code block is wrong, as it should also be in m_pImpl->IsInFootOrEndnote().
3297 // The main problem is that
3299 // assert(len != 1 || sText[0] != 0x2)
3301 // is triggered by the unit test SwLayoutWriter::testForcepoint75, so all these pseudo
3302 // value handling is broken.
3303 // But this is just a symptom, as I guess it's possible to generate broken DOCX documents,
3304 // which might be problematic, triggering *funny* code paths left and right.
3305 // ******
3306 if (sText[0] == 0x2)
3308 m_pImpl->EndCustomFootnote();
3309 return;
3312 if (m_pImpl->IsInCustomFootnote())
3314 if (sText[0] != 0xd && sText[0] != 0x3)
3316 // DOCX can have different labels for the footnote reference and the footnote area.
3317 // This skips the one from the footnote area and just uses the reference one.
3318 if (!m_pImpl->IsInFootOrEndnote())
3320 if (PropertyMapPtr pFootnoteContext = m_pImpl->GetFootnoteContext())
3322 auto xFootnote = pFootnoteContext->GetFootnote();
3323 xFootnote->setLabel(xFootnote->getLabel() + sText);
3326 return;
3328 else
3329 m_pImpl->SetHasFootnoteStyle(true);
3333 if (m_pImpl->isSdtEndDeferred())
3335 // In case we have a field context, then save the property there, so
3336 // SDT's ending right before a field start are handled as well.
3337 PropertyMapPtr pContext = m_pImpl->GetTopContext();
3338 if (m_pImpl->IsOpenField())
3339 pContext = m_pImpl->GetTopFieldContext()->getProperties();
3340 pContext->Insert(PROP_SDT_END_BEFORE, uno::makeAny(true), true, CHAR_GRAB_BAG);
3341 m_pImpl->setSdtEndDeferred(false);
3344 bool bNewLine = len == 1 && (sText[0] == 0x0d || sText[0] == 0x07);
3345 if (m_pImpl->m_pSdtHelper->isInsideDropDownControl())
3347 if (bNewLine)
3348 // Dropdown control has single-line texts, so in case of newline, create the control.
3349 m_pImpl->m_pSdtHelper->createDropDownControl();
3350 else
3352 m_pImpl->m_pSdtHelper->getSdtTexts().append(sText);
3353 return;
3356 else if (!m_pImpl->m_pSdtHelper->isInteropGrabBagEmpty())
3358 // Ignore grabbag when we have a date field, it can conflict during export
3359 if(m_pImpl->m_pSdtHelper->validateDateFormat())
3361 m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
3363 else
3366 // there are unsupported SDT properties in the document
3367 // save them in the paragraph interop grab bag
3368 if (m_pImpl->IsDiscardHeaderFooter())
3370 // Unless we're supposed to ignore this header/footer.
3371 m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
3372 return;
3374 if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
3375 m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") ||
3376 m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") ||
3377 m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") ||
3378 (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") &&
3379 m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
3381 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
3383 if (m_pImpl->IsOpenField())
3384 // We have a field, insert the SDT properties to the field's grab-bag, so they won't be lost.
3385 pContext = m_pImpl->GetTopFieldContext()->getProperties();
3387 pContext->Insert(PROP_SDTPR, uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, CHAR_GRAB_BAG);
3389 else
3390 m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR,
3391 uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, PARA_GRAB_BAG);
3394 else if (len == 1 && sText[0] == 0x03)
3396 // This is the uFtnEdnSep, remember that the document has a separator.
3397 m_pImpl->m_bHasFtnSep = true;
3398 return;
3400 else if (len == 1 && sText[0] == '\t' )
3402 if ( m_pImpl->m_bCheckFirstFootnoteTab && m_pImpl->IsInFootOrEndnote() )
3404 // Allow MSO to emulate LO footnote text starting at left margin - only meaningful with hanging indent
3405 m_pImpl->m_bCheckFirstFootnoteTab = false;
3406 sal_Int32 nFirstLineIndent = 0;
3407 m_pImpl->GetAnyProperty(PROP_PARA_FIRST_LINE_INDENT, m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)) >>= nFirstLineIndent;
3408 if ( nFirstLineIndent < 0 )
3409 m_pImpl->m_bIgnoreNextTab = true;
3412 if ( m_pImpl->m_bIgnoreNextTab )
3414 m_pImpl->m_bIgnoreNextTab = false;
3415 return;
3418 else if (m_pImpl->m_pSdtHelper->validateDateFormat())
3420 if(IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter())
3422 m_pImpl->m_pSdtHelper->getDateFormat().truncate();
3423 m_pImpl->m_pSdtHelper->getLocale().truncate();
3424 return;
3427 if (!m_pImpl->hasTableManager())
3428 return;
3430 SkipFootnoteSeparator eSkip = m_pImpl->GetSkipFootnoteState();
3431 if ( eSkip == SkipFootnoteSeparator::ON || eSkip == SkipFootnoteSeparator::SKIPPING )
3433 m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::SKIPPING );
3434 return;
3439 m_pImpl->getTableManager().utext(data_, len);
3441 if (bNewLine)
3443 const bool bSingleParagraph = m_pImpl->GetIsFirstParagraphInSection() && m_pImpl->GetIsLastParagraphInSection();
3444 const bool bSingleParagraphAfterRedline = m_pImpl->GetIsFirstParagraphInSection(true) && m_pImpl->GetIsLastParagraphInSection();
3445 PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
3446 if (!m_pImpl->GetFootnoteContext())
3448 if (m_pImpl->isBreakDeferred(PAGE_BREAK))
3450 if (m_pImpl->GetSettingsTable()->GetSplitPgBreakAndParaMark())
3452 if ( m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun() )
3454 m_pImpl->m_bIsSplitPara = true;
3455 finishParagraph();
3456 lcl_startParagraphGroup();
3460 pContext->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_PAGE_BEFORE));
3461 m_pImpl->clearDeferredBreaks();
3464 else if (m_pImpl->isBreakDeferred(COLUMN_BREAK))
3466 if ( m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun() )
3468 mbIsSplitPara = true;
3469 finishParagraph();
3470 lcl_startParagraphGroup();
3473 pContext->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_COLUMN_BEFORE));
3474 m_pImpl->clearDeferredBreaks();
3478 // If the paragraph contains only the section properties and it has
3479 // no runs, we should not create a paragraph for it in Writer, unless that would remove the whole section.
3480 SectionPropertyMap* pSectionContext = m_pImpl->GetSectionContext();
3481 bool bRemove = (!m_pImpl->GetParaChanged() && m_pImpl->GetRemoveThisPara()) ||
3482 (!m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr()
3483 && !bSingleParagraphAfterRedline
3484 && !m_pImpl->GetIsDummyParaAddedForTableInSection()
3485 && !( pSectionContext && pSectionContext->GetBreakType() != -1 && pContext && pContext->isSet(PROP_BREAK_TYPE) )
3486 && !m_pImpl->GetIsPreviousParagraphFramed());
3488 const bool bNoNumbering = bRemove || (!m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr() && bSingleParagraph);
3489 PropertyMapPtr xContext = bNoNumbering ? m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) : PropertyMapPtr();
3490 if (xContext)
3492 // tdf#97417 delete numbering of the paragraph
3493 // it will be deleted anyway, and the numbering would be copied
3494 // to the next paragraph in sw SplitNode and then be applied to
3495 // every following paragraph
3496 xContext->Erase(PROP_NUMBERING_RULES);
3497 xContext->Erase(PROP_NUMBERING_LEVEL);
3499 m_pImpl->SetParaSectpr(false);
3500 finishParagraph(bRemove);
3501 if (bRemove)
3502 m_pImpl->RemoveLastParagraph();
3504 else
3506 // GetTopContext() is changed by inserted breaks, but we want to keep the current context
3507 PropertyMapPtr pContext = m_pImpl->GetTopContext();
3508 if (!m_pImpl->GetFootnoteContext())
3510 if (m_pImpl->isBreakDeferred(PAGE_BREAK))
3512 /* If PAGEBREAK appears in first paragraph of the section or
3513 * after first run of any paragraph then need to split paragraph
3514 * to handle it properly.
3516 if (m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun())
3518 m_pImpl->m_bIsSplitPara = true;
3519 finishParagraph();
3520 lcl_startParagraphGroup();
3522 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_PAGE_BEFORE));
3524 else if (m_pImpl->isBreakDeferred(COLUMN_BREAK))
3526 if (m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun())
3528 mbIsSplitPara = true;
3529 finishParagraph();
3530 lcl_startParagraphGroup();
3532 m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::makeAny(style::BreakType_COLUMN_BEFORE));
3534 m_pImpl->clearDeferredBreaks();
3537 if (pContext && pContext->GetFootnote().is())
3539 pContext->GetFootnote()->setLabel( sText );
3540 //otherwise ignore sText
3542 else if (m_pImpl->IsOpenFieldCommand() && !m_pImpl->IsForceGenericFields())
3544 m_pImpl->AppendFieldCommand(sText);
3546 else if( m_pImpl->IsOpenField() && m_pImpl->IsFieldResultAsString())
3547 /*depending on the success of the field insert operation this result will be
3548 set at the field or directly inserted into the text*/
3549 m_pImpl->AppendFieldResult(sText);
3550 else
3552 if (pContext == nullptr)
3553 pContext = new PropertyMap();
3555 m_pImpl->appendTextPortion( sText, pContext );
3559 m_pImpl->SetIsFirstRun(false);
3561 catch( const uno::RuntimeException& )
3566 void DomainMapper::lcl_props(writerfilter::Reference<Properties>::Pointer_t ref)
3568 ref->resolve(*this);
3571 void DomainMapper::lcl_table(Id name, writerfilter::Reference<Table>::Pointer_t ref)
3573 m_pImpl->SetAnyTableImport(true);
3574 switch(name)
3576 case NS_ooxml::LN_FONTTABLE:
3578 // create a font table object that listens to the attributes
3579 // each entry call inserts a new font entry
3580 ref->resolve( *m_pImpl->GetFontTable() );
3581 break;
3582 case NS_ooxml::LN_STYLESHEET:
3583 //same as above to import style sheets
3584 m_pImpl->SetStyleSheetImport( true );
3585 ref->resolve( *m_pImpl->GetStyleSheetTable() );
3586 m_pImpl->GetStyleSheetTable()->ApplyStyleSheets(m_pImpl->GetFontTable());
3587 m_pImpl->SetStyleSheetImport( false );
3588 break;
3589 case NS_ooxml::LN_NUMBERING:
3592 //the same for list tables
3593 ref->resolve( *m_pImpl->GetListTable() );
3594 m_pImpl->GetListTable( )->CreateNumberingRules( );
3596 break;
3597 case NS_ooxml::LN_THEMETABLE:
3598 m_pImpl->GetThemeTable()->setThemeFontLangProperties(
3599 m_pImpl->GetSettingsTable()->GetThemeFontLangProperties() );
3600 ref->resolve ( *m_pImpl->GetThemeTable() );
3601 break;
3602 case NS_ooxml::LN_settings_settings:
3603 ref->resolve ( *m_pImpl->GetSettingsTable() );
3604 m_pImpl->ApplySettingsTable();
3605 break;
3606 default:
3607 OSL_FAIL( "which table is to be filled here?");
3609 m_pImpl->SetAnyTableImport(false);
3612 void DomainMapper::lcl_substream(Id rName, ::writerfilter::Reference<Stream>::Pointer_t ref)
3614 m_pImpl->substream(rName, ref);
3617 void DomainMapper::lcl_startGlossaryEntry()
3619 uno::Reference< text::XTextRange > xTextRange = GetCurrentTextRange();
3620 m_pImpl->setGlossaryEntryStart(xTextRange);
3623 void DomainMapper::lcl_endGlossaryEntry()
3625 m_pImpl->appendGlossaryEntry();
3628 void DomainMapper::handleUnderlineType(const Id nId, const ::tools::SvRef<PropertyMap>& rContext)
3630 sal_Int16 nUnderline = awt::FontUnderline::NONE;
3632 switch (nId)
3634 case NS_ooxml::LN_Value_ST_Underline_none:
3635 nUnderline = awt::FontUnderline::NONE;
3636 break;
3637 case NS_ooxml::LN_Value_ST_Underline_words:
3638 rContext->Insert(PROP_CHAR_WORD_MODE, uno::makeAny(true));
3639 [[fallthrough]];
3640 case NS_ooxml::LN_Value_ST_Underline_single:
3641 nUnderline = awt::FontUnderline::SINGLE;
3642 break;
3643 case NS_ooxml::LN_Value_ST_Underline_double:
3644 nUnderline = awt::FontUnderline::DOUBLE;
3645 break;
3646 case NS_ooxml::LN_Value_ST_Underline_dotted:
3647 nUnderline = awt::FontUnderline::DOTTED;
3648 break;
3649 case NS_ooxml::LN_Value_ST_Underline_dash:
3650 nUnderline = awt::FontUnderline::DASH;
3651 break;
3652 case NS_ooxml::LN_Value_ST_Underline_dotDash:
3653 nUnderline = awt::FontUnderline::DASHDOT;
3654 break;
3655 case NS_ooxml::LN_Value_ST_Underline_dotDotDash:
3656 nUnderline = awt::FontUnderline::DASHDOTDOT;
3657 break;
3658 case NS_ooxml::LN_Value_ST_Underline_thick:
3659 nUnderline = awt::FontUnderline::BOLD;
3660 break;
3661 case NS_ooxml::LN_Value_ST_Underline_wave:
3662 nUnderline = awt::FontUnderline::WAVE;
3663 break;
3664 case NS_ooxml::LN_Value_ST_Underline_dottedHeavy:
3665 nUnderline = awt::FontUnderline::BOLDDOTTED;
3666 break;
3667 case NS_ooxml::LN_Value_ST_Underline_dashedHeavy:
3668 nUnderline = awt::FontUnderline::BOLDDASH;
3669 break;
3670 case NS_ooxml::LN_Value_ST_Underline_dashLong:
3671 nUnderline = awt::FontUnderline::LONGDASH;
3672 break;
3673 case NS_ooxml::LN_Value_ST_Underline_dashLongHeavy:
3674 nUnderline = awt::FontUnderline::BOLDLONGDASH;
3675 break;
3676 case NS_ooxml::LN_Value_ST_Underline_dashDotHeavy:
3677 nUnderline = awt::FontUnderline::BOLDDASHDOT;
3678 break;
3679 case NS_ooxml::LN_Value_ST_Underline_dashDotDotHeavy:
3680 nUnderline = awt::FontUnderline::BOLDDASHDOTDOT;
3681 break;
3682 case NS_ooxml::LN_Value_ST_Underline_wavyHeavy:
3683 nUnderline = awt::FontUnderline::BOLDWAVE;
3684 break;
3685 case NS_ooxml::LN_Value_ST_Underline_wavyDouble:
3686 nUnderline = awt::FontUnderline::DOUBLEWAVE;
3687 break;
3689 rContext->Insert(PROP_CHAR_UNDERLINE, uno::makeAny(nUnderline));
3692 void DomainMapper::handleParaJustification(const sal_Int32 nIntValue, const ::tools::SvRef<PropertyMap>& rContext, const bool bExchangeLeftRight)
3694 style::ParagraphAdjust nAdjust = style::ParagraphAdjust_LEFT;
3695 style::ParagraphAdjust nLastLineAdjust = style::ParagraphAdjust_LEFT;
3696 OUString aStringValue = "left";
3697 switch(nIntValue)
3699 case NS_ooxml::LN_Value_ST_Jc_center:
3700 nAdjust = style::ParagraphAdjust_CENTER;
3701 aStringValue = "center";
3702 break;
3703 case NS_ooxml::LN_Value_ST_Jc_right:
3704 case NS_ooxml::LN_Value_ST_Jc_end:
3705 nAdjust = bExchangeLeftRight ? style::ParagraphAdjust_LEFT : style::ParagraphAdjust_RIGHT;
3706 aStringValue = "right";
3707 break;
3708 case NS_ooxml::LN_Value_ST_Jc_distribute:
3709 nLastLineAdjust = style::ParagraphAdjust_BLOCK;
3710 [[fallthrough]];
3711 case NS_ooxml::LN_Value_ST_Jc_both:
3712 nAdjust = style::ParagraphAdjust_BLOCK;
3713 aStringValue = "both";
3714 break;
3715 case NS_ooxml::LN_Value_ST_Jc_left:
3716 case NS_ooxml::LN_Value_ST_Jc_start:
3717 default:
3718 nAdjust = bExchangeLeftRight ? style::ParagraphAdjust_RIGHT : style::ParagraphAdjust_LEFT;
3719 break;
3721 rContext->Insert( PROP_PARA_ADJUST, uno::makeAny( nAdjust ) );
3722 rContext->Insert( PROP_PARA_LAST_LINE_ADJUST, uno::makeAny( nLastLineAdjust ) );
3723 m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "jc", aStringValue);
3726 bool DomainMapper::getColorFromId(const Id nId, sal_Int32 &nColor)
3728 nColor = 0;
3729 if ((nId < NS_ooxml::LN_Value_ST_HighlightColor_black) || (nId > NS_ooxml::LN_Value_ST_HighlightColor_lightGray))
3730 return false;
3732 switch (nId)
3734 case NS_ooxml::LN_Value_ST_HighlightColor_black: nColor=0x000000; break;
3735 case NS_ooxml::LN_Value_ST_HighlightColor_blue: nColor=0x0000ff; break;
3736 case NS_ooxml::LN_Value_ST_HighlightColor_cyan: nColor=0x00ffff; break;
3737 case NS_ooxml::LN_Value_ST_HighlightColor_green: nColor=0x00ff00; break;
3738 case NS_ooxml::LN_Value_ST_HighlightColor_magenta: nColor=0xff00ff; break;
3739 case NS_ooxml::LN_Value_ST_HighlightColor_red: nColor=0xff0000; break;
3740 case NS_ooxml::LN_Value_ST_HighlightColor_yellow: nColor=0xffff00; break;
3741 case NS_ooxml::LN_Value_ST_HighlightColor_white: nColor=0xffffff; break;
3742 case NS_ooxml::LN_Value_ST_HighlightColor_darkBlue: nColor=0x000080; break;
3743 case NS_ooxml::LN_Value_ST_HighlightColor_darkCyan: nColor=0x008080; break;
3744 case NS_ooxml::LN_Value_ST_HighlightColor_darkGreen: nColor=0x008000; break;
3745 case NS_ooxml::LN_Value_ST_HighlightColor_darkMagenta: nColor=0x800080; break;
3746 case NS_ooxml::LN_Value_ST_HighlightColor_darkRed: nColor=0x800000; break;
3747 case NS_ooxml::LN_Value_ST_HighlightColor_darkYellow: nColor=0x808000; break;
3748 case NS_ooxml::LN_Value_ST_HighlightColor_darkGray: nColor=0x808080; break;
3749 case NS_ooxml::LN_Value_ST_HighlightColor_lightGray: nColor=0xC0C0C0; break;
3750 default:
3751 return false;
3753 return true;
3756 sal_Int16 DomainMapper::getEmphasisValue(const sal_Int32 nIntValue)
3758 switch (nIntValue)
3760 case NS_ooxml::LN_Value_ST_Em_dot:
3761 return text::FontEmphasis::DOT_ABOVE;
3762 case NS_ooxml::LN_Value_ST_Em_comma:
3763 return text::FontEmphasis::ACCENT_ABOVE;
3764 case NS_ooxml::LN_Value_ST_Em_circle:
3765 return text::FontEmphasis::CIRCLE_ABOVE;
3766 case NS_ooxml::LN_Value_ST_Em_underDot:
3767 return text::FontEmphasis::DOT_BELOW;
3768 default:
3769 return text::FontEmphasis::NONE;
3773 OUString DomainMapper::getBracketStringFromEnum(const sal_Int32 nIntValue, const bool bIsPrefix)
3775 switch(nIntValue)
3777 case NS_ooxml::LN_Value_ST_CombineBrackets_round:
3778 if (bIsPrefix)
3779 return "(";
3780 return ")";
3782 case NS_ooxml::LN_Value_ST_CombineBrackets_square:
3783 if (bIsPrefix)
3784 return "[";
3785 return "]";
3787 case NS_ooxml::LN_Value_ST_CombineBrackets_angle:
3788 if (bIsPrefix)
3789 return "<";
3790 return ">";
3792 case NS_ooxml::LN_Value_ST_CombineBrackets_curly:
3793 if (bIsPrefix)
3794 return "{";
3795 return "}";
3797 case NS_ooxml::LN_Value_ST_CombineBrackets_none:
3798 default:
3799 return OUString();
3803 style::TabAlign DomainMapper::getTabAlignFromValue(const sal_Int32 nIntValue)
3805 switch (nIntValue)
3807 case NS_ooxml::LN_Value_ST_TabJc_start:
3808 case NS_ooxml::LN_Value_ST_TabJc_left:
3809 case NS_ooxml::LN_Value_ST_TabJc_bar: // bar not supported
3810 case NS_ooxml::LN_Value_ST_TabJc_num: // num not supported
3811 return style::TabAlign_LEFT;
3812 case NS_ooxml::LN_Value_ST_TabJc_center:
3813 return style::TabAlign_CENTER;
3814 case NS_ooxml::LN_Value_ST_TabJc_end:
3815 case NS_ooxml::LN_Value_ST_TabJc_right:
3816 return style::TabAlign_RIGHT;
3817 case NS_ooxml::LN_Value_ST_TabJc_decimal:
3818 return style::TabAlign_DECIMAL;
3820 return style::TabAlign_LEFT;
3823 sal_Unicode DomainMapper::getFillCharFromValue(const sal_Int32 nIntValue)
3825 switch (nIntValue)
3827 case NS_ooxml::LN_Value_ST_TabTlc_dot:
3828 return u'.';
3829 case NS_ooxml::LN_Value_ST_TabTlc_hyphen:
3830 return u'-';
3831 case NS_ooxml::LN_Value_ST_TabTlc_underscore:
3832 case NS_ooxml::LN_Value_ST_TabTlc_heavy: // FIXME ???
3833 return u'_';
3834 case NS_ooxml::LN_Value_ST_TabTlc_middleDot: // middleDot
3835 return u'\x00b7';
3836 case NS_ooxml::LN_Value_ST_TabTlc_none:
3837 default:
3838 return u' '; // blank space
3842 bool DomainMapper::IsOOXMLImport() const
3844 return m_pImpl->IsOOXMLImport();
3847 bool DomainMapper::IsRTFImport() const
3849 return m_pImpl->IsRTFImport();
3852 uno::Reference < lang::XMultiServiceFactory > const & DomainMapper::GetTextFactory() const
3854 return m_pImpl->GetTextFactory();
3857 uno::Reference< text::XTextRange > DomainMapper::GetCurrentTextRange()
3859 if (m_pImpl->HasTopText())
3860 return m_pImpl->GetTopTextAppend()->getEnd();
3861 return m_pImpl->m_xInsertTextRange;
3864 OUString DomainMapper::getOrCreateCharStyle( PropertyValueVector_t& rCharProperties, bool bAlwaysCreate )
3866 StyleSheetTablePtr pStyleSheets = m_pImpl->GetStyleSheetTable();
3867 return pStyleSheets->getOrCreateCharStyle( rCharProperties, bAlwaysCreate );
3870 StyleSheetTablePtr const & DomainMapper::GetStyleSheetTable( )
3872 return m_pImpl->GetStyleSheetTable( );
3875 GraphicZOrderHelper* DomainMapper::graphicZOrderHelper()
3877 if (zOrderHelper == nullptr)
3878 zOrderHelper.reset( new GraphicZOrderHelper );
3879 return zOrderHelper.get();
3882 GraphicNamingHelper& DomainMapper::GetGraphicNamingHelper()
3884 if (m_pGraphicNamingHelper == nullptr)
3885 m_pGraphicNamingHelper.reset(new GraphicNamingHelper());
3886 return *m_pGraphicNamingHelper;
3889 uno::Reference<drawing::XShape> DomainMapper::PopPendingShape()
3891 return m_pImpl->PopPendingShape();
3894 bool DomainMapper::IsInHeaderFooter() const
3896 return m_pImpl->IsInHeaderFooter();
3899 bool DomainMapper::IsInShape() const { return m_pImpl->IsInShape(); }
3901 bool DomainMapper::IsInTable() const
3903 return m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInCell();
3906 OUString DomainMapper::GetListStyleName(sal_Int32 nListId) const
3908 return m_pImpl->GetListStyleName( nListId );
3911 bool DomainMapper::IsStyleSheetImport() const
3913 return m_pImpl->IsStyleSheetImport();
3916 void DomainMapper::enableInteropGrabBag(const OUString& aName)
3918 m_pImpl->m_aInteropGrabBagName = aName;
3921 beans::PropertyValue DomainMapper::getInteropGrabBag()
3923 beans::PropertyValue aRet;
3924 aRet.Name = m_pImpl->m_aInteropGrabBagName;
3925 aRet.Value <<= comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag);
3927 m_pImpl->m_aInteropGrabBag.clear();
3928 m_pImpl->m_aInteropGrabBagName.clear();
3929 return aRet;
3932 void DomainMapper::HandleRedline( Sprm& rSprm )
3934 sal_uInt32 nSprmId = rSprm.getId();
3936 m_pImpl->AddNewRedline( nSprmId );
3938 if (nSprmId == NS_ooxml::LN_CT_PPr_pPrChange)
3940 m_pImpl->SetCurrentRedlineToken(XML_ParagraphFormat);
3942 else if (nSprmId == NS_ooxml::LN_CT_TrPr_ins)
3944 m_pImpl->SetCurrentRedlineToken(XML_tableRowInsert);
3946 else if (nSprmId == NS_ooxml::LN_CT_TrPr_del)
3948 m_pImpl->SetCurrentRedlineToken(XML_tableRowDelete);
3950 else if (nSprmId == NS_ooxml::LN_CT_TcPrBase_cellIns)
3952 m_pImpl->SetCurrentRedlineToken(XML_tableCellInsert);
3954 else if (nSprmId == NS_ooxml::LN_CT_TcPrBase_cellDel)
3956 m_pImpl->SetCurrentRedlineToken(XML_tableCellDelete);
3959 resolveSprmProps(*this, rSprm );
3960 // now the properties author, date and id should be available
3961 sal_Int32 nToken = m_pImpl->GetCurrentRedlineToken();
3962 switch( nToken & 0xffff )
3964 case XML_mod:
3965 case XML_ins:
3966 case XML_del:
3967 case XML_moveTo:
3968 case XML_moveFrom:
3969 case XML_ParagraphFormat:
3970 case XML_tableRowInsert:
3971 case XML_tableRowDelete:
3972 case XML_tableCellInsert:
3973 case XML_tableCellDelete:
3974 break;
3975 default: OSL_FAIL( "redline token other than mod, ins, del, moveTo, moveFrom or table row" ); break;
3977 m_pImpl->EndParaMarkerChange( );
3978 m_pImpl->SetCurrentRedlineIsRead();
3981 void DomainMapper::finishParagraph(const bool bRemove)
3983 if (m_pImpl->m_pSdtHelper->validateDateFormat())
3984 m_pImpl->m_pSdtHelper->createDateContentControl();
3985 m_pImpl->finishParagraph(m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH), bRemove);
3988 } //namespace writerfilter
3990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */