update emoji autocorrect entries from po-files
[LibreOffice.git] / writerfilter / source / dmapper / PropertyMap.cxx
blobdab485fbbdca76569776bb0dc2774c039088a8e8
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 <PropertyMap.hxx>
20 #include <ooxml/resourceids.hxx>
21 #include <DomainMapper_Impl.hxx>
22 #include <ConversionHelper.hxx>
23 #include <i18nutil/paper.hxx>
24 #include <osl/diagnose.h>
25 #include <rtl/ustring.hxx>
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/beans/XMultiPropertySet.hpp>
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/table/BorderLine2.hpp>
31 #include <com/sun/star/container/XEnumeration.hpp>
32 #include <com/sun/star/container/XEnumerationAccess.hpp>
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/style/BreakType.hpp>
35 #include <com/sun/star/style/PageStyleLayout.hpp>
36 #include <com/sun/star/style/XStyle.hpp>
37 #include <com/sun/star/table/ShadowFormat.hpp>
38 #include <com/sun/star/text/RelOrientation.hpp>
39 #include <com/sun/star/text/WritingMode.hpp>
40 #include <com/sun/star/text/XTextColumns.hpp>
41 #include <com/sun/star/text/XText.hpp>
42 #include <com/sun/star/text/TextGridMode.hpp>
43 #include <com/sun/star/text/XTextCopy.hpp>
44 #include <comphelper/sequence.hxx>
45 #include "PropertyMapHelper.hxx"
47 using namespace ::com::sun::star;
49 namespace writerfilter {
50 namespace dmapper{
54 PropertyMap::PropertyMap() :
55 m_cFootnoteSymbol( 0 ),
56 m_nFootnoteFontId( -1 )
61 PropertyMap::~PropertyMap()
66 uno::Sequence< beans::PropertyValue > PropertyMap::GetPropertyValues(bool bCharGrabBag)
68 if(m_aValues.empty() && !m_vMap.empty())
70 size_t nCharGrabBag = 0;
71 size_t nParaGrabBag = 0;
72 size_t nCellGrabBag = 0;
73 size_t nCellGrabBagSaved = 0; // How many entries do we save from the returned sequence.
74 size_t nRowGrabBag = 0;
75 for (MapIterator i = m_vMap.begin(); i != m_vMap.end(); ++i)
77 if ( i->second.getGrabBagType() == CHAR_GRAB_BAG )
78 nCharGrabBag++;
79 else if ( i->second.getGrabBagType() == PARA_GRAB_BAG )
80 nParaGrabBag++;
81 else if ( i->second.getGrabBagType() == CELL_GRAB_BAG )
83 nCellGrabBag++;
84 nCellGrabBagSaved++;
86 else if ( i->first == PROP_CELL_INTEROP_GRAB_BAG)
88 uno::Sequence<beans::PropertyValue> aSeq;
89 i->second.getValue() >>= aSeq;
90 nCellGrabBag += aSeq.getLength();
91 nCellGrabBagSaved++;
93 else if ( i->second.getGrabBagType() == ROW_GRAB_BAG )
94 nRowGrabBag++;
97 // If there are any grab bag properties, we need one slot for them.
98 uno::Sequence<beans::PropertyValue> aCharGrabBagValues(nCharGrabBag);
99 uno::Sequence<beans::PropertyValue> aParaGrabBagValues(nParaGrabBag);
100 uno::Sequence<beans::PropertyValue> aCellGrabBagValues(nCellGrabBag);
101 uno::Sequence<beans::PropertyValue> aRowGrabBagValues(nRowGrabBag);
102 beans::PropertyValue* pCharGrabBagValues = aCharGrabBagValues.getArray();
103 beans::PropertyValue* pParaGrabBagValues = aParaGrabBagValues.getArray();
104 beans::PropertyValue* pCellGrabBagValues = aCellGrabBagValues.getArray();
105 beans::PropertyValue* pRowGrabBagValues = aRowGrabBagValues.getArray();
106 //style names have to be the first elements within the property sequence
107 //otherwise they will overwrite 'hard' attributes
108 sal_Int32 nRowGrabBagValue = 0;
109 sal_Int32 nCellGrabBagValue = 0;
110 sal_Int32 nParaGrabBagValue = 0;
111 sal_Int32 nCharGrabBagValue = 0;
112 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
113 MapIterator aParaStyleIter = m_vMap.find(PROP_PARA_STYLE_NAME);
114 if( aParaStyleIter != m_vMap.end())
116 beans::PropertyValue aValue;
117 aValue.Name = rPropNameSupplier.GetName( aParaStyleIter->first );
118 aValue.Value = aParaStyleIter->second.getValue();
119 m_aValues.push_back(aValue);
122 MapIterator aCharStyleIter = m_vMap.find(PROP_CHAR_STYLE_NAME);
123 if( aCharStyleIter != m_vMap.end())
125 beans::PropertyValue aValue;
126 aValue.Name = rPropNameSupplier.GetName( aCharStyleIter->first );
127 aValue.Value = aCharStyleIter->second.getValue();
128 m_aValues.push_back(aValue);
130 MapIterator aNumRuleIter = m_vMap.find(PROP_NUMBERING_RULES);
131 if( aNumRuleIter != m_vMap.end())
133 beans::PropertyValue aValue;
134 aValue.Name = rPropNameSupplier.GetName( aNumRuleIter->first );
135 aValue.Value = aNumRuleIter->second.getValue();
136 m_aValues.push_back(aValue);
138 MapIterator aMapIter = m_vMap.begin();
139 for( ; aMapIter != m_vMap.end(); ++aMapIter )
141 if( aMapIter != aParaStyleIter && aMapIter != aCharStyleIter && aMapIter != aNumRuleIter )
143 if ( aMapIter->second.getGrabBagType() == CHAR_GRAB_BAG )
145 if (bCharGrabBag)
147 pCharGrabBagValues[nCharGrabBagValue].Name = rPropNameSupplier.GetName( aMapIter->first );
148 pCharGrabBagValues[nCharGrabBagValue].Value = aMapIter->second.getValue();
149 ++nCharGrabBagValue;
152 else if ( aMapIter->second.getGrabBagType() == PARA_GRAB_BAG )
154 pParaGrabBagValues[nParaGrabBagValue].Name = rPropNameSupplier.GetName( aMapIter->first );
155 pParaGrabBagValues[nParaGrabBagValue].Value = aMapIter->second.getValue();
156 ++nParaGrabBagValue;
158 else if ( aMapIter->second.getGrabBagType() == CELL_GRAB_BAG )
160 pCellGrabBagValues[nCellGrabBagValue].Name = rPropNameSupplier.GetName( aMapIter->first );
161 pCellGrabBagValues[nCellGrabBagValue].Value = aMapIter->second.getValue();
162 ++nCellGrabBagValue;
164 else if ( aMapIter->second.getGrabBagType() == ROW_GRAB_BAG )
166 pRowGrabBagValues[nRowGrabBagValue].Name = rPropNameSupplier.GetName( aMapIter->first );
167 pRowGrabBagValues[nRowGrabBagValue].Value = aMapIter->second.getValue();
168 ++nRowGrabBagValue;
170 else
172 if (aMapIter->first == PROP_CELL_INTEROP_GRAB_BAG)
174 uno::Sequence<beans::PropertyValue> aSeq;
175 aMapIter->second.getValue() >>= aSeq;
176 for (sal_Int32 i = 0; i < aSeq.getLength(); ++i)
178 pCellGrabBagValues[nCellGrabBagValue] = aSeq[i];
179 ++nCellGrabBagValue;
182 else
184 beans::PropertyValue aValue;
185 aValue.Name = rPropNameSupplier.GetName( aMapIter->first );
186 aValue.Value = aMapIter->second.getValue();
187 m_aValues.push_back(aValue);
192 if (nCharGrabBag && bCharGrabBag)
194 beans::PropertyValue aValue;
195 aValue.Name = "CharInteropGrabBag";
196 aValue.Value = uno::makeAny(aCharGrabBagValues);
197 m_aValues.push_back(aValue);
199 if (nParaGrabBag)
201 beans::PropertyValue aValue;
202 aValue.Name = "ParaInteropGrabBag";
203 aValue.Value = uno::makeAny(aParaGrabBagValues);
204 m_aValues.push_back(aValue);
206 if (nCellGrabBag)
208 beans::PropertyValue aValue;
209 aValue.Name = "CellInteropGrabBag";
210 aValue.Value = uno::makeAny(aCellGrabBagValues);
211 m_aValues.push_back(aValue);
213 if (nRowGrabBag)
215 beans::PropertyValue aValue;
216 aValue.Name = "RowInteropGrabBag";
217 aValue.Value = uno::makeAny(aRowGrabBagValues);
218 m_aValues.push_back(aValue);
221 return comphelper::containerToSequence(m_aValues);
224 #ifdef DEBUG_WRITERFILTER
225 static void lcl_AnyToTag(const uno::Any & rAny)
227 try {
228 sal_Int32 aInt = 0;
229 if (rAny >>= aInt) {
230 TagLogger::getInstance().attribute("value", rAny);
231 } else {
232 TagLogger::getInstance().attribute("unsignedValue", 0);
235 sal_uInt32 auInt = 0;
236 rAny >>= auInt;
237 TagLogger::getInstance().attribute("unsignedValue", auInt);
239 float aFloat = 0.0f;
240 if (rAny >>= aFloat) {
241 TagLogger::getInstance().attribute("floatValue", rAny);
242 } else {
243 TagLogger::getInstance().attribute("unsignedValue", 0);
246 OUString aStr;
247 rAny >>= aStr;
248 TagLogger::getInstance().attribute("stringValue", aStr);
250 catch (...) {
253 #endif
255 void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite, GrabBagType i_GrabBagType )
257 #ifdef DEBUG_WRITERFILTER
258 const OUString& rInsert = PropertyNameSupplier::
259 GetPropertyNameSupplier().GetName(eId);
261 TagLogger::getInstance().startElement("propertyMap.insert");
262 TagLogger::getInstance().attribute("name", rInsert);
263 lcl_AnyToTag(rAny);
264 TagLogger::getInstance().endElement();
265 #endif
267 if (!bOverwrite)
268 m_vMap.insert(std::make_pair(eId, PropValue(rAny, i_GrabBagType)));
269 else
270 m_vMap[eId] = PropValue(rAny, i_GrabBagType);
272 Invalidate();
275 void PropertyMap::Erase( PropertyIds eId )
277 //Safe call to erase, it throws no exceptions, even if eId is not in m_vMap
278 m_vMap.erase(eId);
280 Invalidate();
283 boost::optional<PropertyMap::Property> PropertyMap::getProperty( PropertyIds eId ) const
285 MapIterator aIter = m_vMap.find(eId);
286 if (aIter==m_vMap.end())
287 return boost::optional<Property>();
288 else
289 return std::make_pair( eId, aIter->second.getValue() ) ;
292 bool PropertyMap::isSet( PropertyIds eId) const
294 return m_vMap.find(eId)!=m_vMap.end();
297 #ifdef DEBUG_WRITERFILTER
298 void PropertyMap::dumpXml() const
300 TagLogger::getInstance().startElement("PropertyMap");
302 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
303 MapIterator aMapIter = m_vMap.begin();
304 while (aMapIter != m_vMap.end())
306 TagLogger::getInstance().startElement("property");
308 TagLogger::getInstance().attribute("name", rPropNameSupplier.GetName( aMapIter->first ));
310 switch (aMapIter->first)
312 case PROP_TABLE_COLUMN_SEPARATORS:
313 lcl_DumpTableColumnSeparators(aMapIter->second.getValue());
314 break;
315 default:
317 try {
318 sal_Int32 aInt = 0;
319 aMapIter->second.getValue() >>= aInt;
320 TagLogger::getInstance().attribute("value", aInt);
322 sal_uInt32 auInt = 0;
323 aMapIter->second.getValue() >>= auInt;
324 TagLogger::getInstance().attribute("unsignedValue", auInt);
326 float aFloat = 0.0;
327 aMapIter->second.getValue() >>= aFloat;
328 TagLogger::getInstance().attribute("floatValue", aFloat);
330 OUString aStr;
331 aMapIter->second.getValue() >>= auInt;
332 TagLogger::getInstance().attribute("stringValue", aStr);
334 catch (...) {
337 break;
340 TagLogger::getInstance().endElement();
342 ++aMapIter;
345 TagLogger::getInstance().endElement();
347 #endif
349 void PropertyMap::InsertProps(const PropertyMapPtr& rMap)
351 if (rMap)
353 MapIterator pEnd = rMap->m_vMap.end();
354 for ( MapIterator iter = rMap->m_vMap.begin(); iter!=pEnd; ++iter )
355 m_vMap[iter->first] = iter->second;
357 insertTableProperties(rMap.get());
359 Invalidate();
363 void PropertyMap::insertTableProperties( const PropertyMap* )
365 #ifdef DEBUG_WRITERFILTER
366 TagLogger::getInstance().element("PropertyMap.insertTableProperties");
367 #endif
370 void PropertyMap::printProperties()
372 #ifdef DEBUG_WRITERFILTER
373 TagLogger::getInstance().startElement("properties");
375 MapIterator aMapIter = m_vMap.begin();
376 MapIterator aEndIter = m_vMap.end();
377 PropertyNameSupplier& rPropSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
378 for( ; aMapIter != aEndIter; ++aMapIter )
380 SAL_INFO("writerfilter", rPropSupplier.GetName(aMapIter->first));
382 table::BorderLine2 aLine;
383 sal_Int32 nColor;
384 if ( aMapIter->second.getValue() >>= aLine )
386 TagLogger::getInstance().startElement("borderline");
387 TagLogger::getInstance().attribute("color", aLine.Color);
388 TagLogger::getInstance().attribute("inner", aLine.InnerLineWidth);
389 TagLogger::getInstance().attribute("outer", aLine.OuterLineWidth);
390 TagLogger::getInstance().endElement();
392 else if ( aMapIter->second.getValue() >>= nColor )
394 TagLogger::getInstance().startElement("color");
395 TagLogger::getInstance().attribute("number", nColor);
396 TagLogger::getInstance().endElement();
400 TagLogger::getInstance().endElement();
401 #endif
404 SectionPropertyMap::SectionPropertyMap(bool bIsFirstSection) :
405 m_bIsFirstSection( bIsFirstSection )
406 ,m_nBorderParams( 0 )
407 ,m_bTitlePage( false )
408 ,m_nColumnCount( 0 )
409 ,m_nColumnDistance( 1249 )
410 ,m_bSeparatorLineIsOn( false )
411 ,m_bEvenlySpaced( false )
412 ,m_bIsLandscape( false )
413 ,m_bPageNoRestart( false )
414 ,m_nPageNumber( -1 )
415 ,m_nBreakType( -1 )
416 ,m_nPaperBin( -1 )
417 ,m_nFirstPaperBin( -1 )
418 ,m_nLeftMargin( 3175 ) //page left margin, default 0x708 (1800) twip -> 3175 1/100 mm
419 ,m_nRightMargin( 3175 )//page right margin, default 0x708 (1800) twip -> 3175 1/100 mm
420 ,m_nTopMargin( 2540 )
421 ,m_nBottomMargin( 2540 )
422 ,m_nHeaderTop( 1270 ) //720 twip
423 ,m_nHeaderBottom( 1270 )//720 twip
424 ,m_nDzaGutter( 0 )
425 ,m_bGutterRTL( false )
426 ,m_bSFBiDi( false )
427 ,m_nGridType(0)
428 ,m_nGridLinePitch( 1 )
429 ,m_nDxtCharSpace( 0 )
430 ,m_bGridSnapToChars(true)
431 ,m_nLnnMod( 0 )
432 ,m_nLnc( 0 )
433 ,m_ndxaLnn( 0 )
434 ,m_nLnnMin( 0 )
436 static sal_Int32 nNumber = 0;
437 nSectionNumber = nNumber++;
438 memset(&m_pBorderLines, 0x00, sizeof(m_pBorderLines));
439 for( sal_Int32 nBorder = 0; nBorder < 4; ++nBorder )
441 m_nBorderDistances[ nBorder ] = -1;
442 m_bBorderShadows[nBorder] = false;
444 //todo: set defaults in ApplyPropertiesToPageStyles
445 //initialize defaults
446 PaperInfo aLetter(PAPER_LETTER);
447 //page height, 1/100mm
448 Insert( PROP_HEIGHT, uno::makeAny( (sal_Int32) aLetter.getHeight() ) );
449 //page width, 1/100mm
450 Insert( PROP_WIDTH, uno::makeAny( (sal_Int32) aLetter.getWidth() ) );
451 //page left margin, default 0x708 (1800) twip -> 3175 1/100 mm
452 Insert( PROP_LEFT_MARGIN, uno::makeAny( (sal_Int32) 3175 ) );
453 //page right margin, default 0x708 (1800) twip -> 3175 1/100 mm
454 Insert( PROP_RIGHT_MARGIN, uno::makeAny( (sal_Int32) 3175 ) );
455 //page top margin, default 0x5a0 (1440) twip -> 2540 1/100 mm
456 Insert( PROP_TOP_MARGIN, uno::makeAny( (sal_Int32)2540 ) );
457 //page bottom margin, default 0x5a0 (1440) twip -> 2540 1/100 mm
458 Insert( PROP_BOTTOM_MARGIN, uno::makeAny( (sal_Int32) 2540 ) );
459 //page style layout
460 Insert(PROP_PAGE_STYLE_LAYOUT, uno::makeAny(style::PageStyleLayout_ALL));
461 uno::Any aFalse( ::uno::makeAny( false ) );
462 Insert( PROP_GRID_DISPLAY, aFalse);
463 Insert( PROP_GRID_PRINT, aFalse);
464 Insert( PROP_GRID_MODE, uno::makeAny(text::TextGridMode::NONE));
467 if( m_bIsFirstSection )
469 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
470 m_sFirstPageStyleName = rPropNameSupplier.GetName( PROP_FIRST_PAGE );
471 m_sFollowPageStyleName = rPropNameSupplier.GetName( PROP_STANDARD );
476 SectionPropertyMap::~SectionPropertyMap()
478 for( sal_Int16 ePos = BORDER_LEFT; ePos <= BORDER_BOTTOM; ++ePos)
479 delete m_pBorderLines[ePos];
483 OUString lcl_FindUnusedPageStyleName(const uno::Sequence< OUString >& rPageStyleNames)
485 static const sal_Char cDefaultStyle[] = "Converted";
486 //find the hightest number x in each style with the name "cDefaultStyle+x" and
487 //return an incremented name
488 sal_Int32 nMaxIndex = 0;
489 const sal_Int32 nDefaultLength = sizeof(cDefaultStyle)/sizeof(sal_Char) - 1;
490 const OUString sDefaultStyle( cDefaultStyle, nDefaultLength, RTL_TEXTENCODING_ASCII_US );
492 const OUString* pStyleNames = rPageStyleNames.getConstArray();
493 for( sal_Int32 nStyle = 0; nStyle < rPageStyleNames.getLength(); ++nStyle)
495 if( pStyleNames[nStyle].getLength() > nDefaultLength &&
496 !rtl_ustr_compare_WithLength( sDefaultStyle.getStr(), nDefaultLength, pStyleNames[nStyle].getStr(), nDefaultLength))
498 sal_Int32 nIndex = pStyleNames[nStyle].copy( nDefaultLength ).toInt32();
499 if( nIndex > nMaxIndex)
500 nMaxIndex = nIndex;
503 OUString sRet( sDefaultStyle );
504 sRet += OUString::number( nMaxIndex + 1);
505 return sRet;
510 uno::Reference< beans::XPropertySet > SectionPropertyMap::GetPageStyle(
511 const uno::Reference< container::XNameContainer >& xPageStyles,
512 const uno::Reference < lang::XMultiServiceFactory >& xTextFactory,
513 bool bFirst )
515 uno::Reference< beans::XPropertySet > xRet;
518 if( bFirst )
520 if( m_sFirstPageStyleName.isEmpty() && xPageStyles.is() )
522 uno::Sequence< OUString > aPageStyleNames = xPageStyles->getElementNames();
523 m_sFirstPageStyleName = lcl_FindUnusedPageStyleName(aPageStyleNames);
524 m_aFirstPageStyle = uno::Reference< beans::XPropertySet > (
525 xTextFactory->createInstance("com.sun.star.style.PageStyle"),
526 uno::UNO_QUERY);
528 // Call insertByName() before GetPageStyle(), otherwise the
529 // first and the follow page style will have the same name, and
530 // insertByName() will fail.
531 if (xPageStyles.is())
532 xPageStyles->insertByName( m_sFirstPageStyleName, uno::makeAny(m_aFirstPageStyle) );
534 // Ensure that m_aFollowPageStyle has been created
535 GetPageStyle( xPageStyles, xTextFactory, false );
536 // Chain m_aFollowPageStyle to be after m_aFirstPageStyle
537 m_aFirstPageStyle->setPropertyValue("FollowStyle",
538 uno::makeAny(m_sFollowPageStyleName));
540 else if( !m_aFirstPageStyle.is() && xPageStyles.is() )
542 xPageStyles->getByName(m_sFirstPageStyleName) >>= m_aFirstPageStyle;
544 xRet = m_aFirstPageStyle;
546 else
548 if( m_sFollowPageStyleName.isEmpty() && xPageStyles.is() )
550 uno::Sequence< OUString > aPageStyleNames = xPageStyles->getElementNames();
551 m_sFollowPageStyleName = lcl_FindUnusedPageStyleName(aPageStyleNames);
552 m_aFollowPageStyle = uno::Reference< beans::XPropertySet > (
553 xTextFactory->createInstance("com.sun.star.style.PageStyle"),
554 uno::UNO_QUERY);
555 xPageStyles->insertByName( m_sFollowPageStyleName, uno::makeAny(m_aFollowPageStyle) );
557 else if(!m_aFollowPageStyle.is() && xPageStyles.is() )
559 xPageStyles->getByName(m_sFollowPageStyleName) >>= m_aFollowPageStyle;
561 xRet = m_aFollowPageStyle;
565 catch( const uno::Exception& rException )
567 SAL_WARN("writerfilter", "SectionPropertyMap::GetPageStyle() failed: " << rException.Message);
570 return xRet;
574 void SectionPropertyMap::SetBorder( BorderPosition ePos, sal_Int32 nLineDistance, const table::BorderLine2& rBorderLine, bool bShadow )
576 delete m_pBorderLines[ePos];
577 m_pBorderLines[ePos] = new table::BorderLine2( rBorderLine );
578 m_nBorderDistances[ePos] = nLineDistance;
579 m_bBorderShadows[ePos] = bShadow;
583 void SectionPropertyMap::ApplyBorderToPageStyles(
584 const uno::Reference< container::XNameContainer >& xPageStyles,
585 const uno::Reference < lang::XMultiServiceFactory >& xTextFactory,
586 sal_Int32 nValue )
589 page border applies to:
590 nIntValue & 0x07 ->
591 0 all pages in this section
592 1 first page in this section
593 2 all pages in this section but first
594 3 whole document (all sections)
595 nIntValue & 0x18 -> page border depth 0 - in front 1- in back
596 nIntValue & 0xe0 ->
597 page border offset from:
598 0 offset from text
599 1 offset from edge of page
601 uno::Reference< beans::XPropertySet > xFirst;
602 uno::Reference< beans::XPropertySet > xSecond;
603 sal_Int32 nOffsetFrom = (nValue & 0x00E0) >> 5;
604 //todo: negative spacing (from ww8par6.cxx)
605 switch( nValue & 0x07)
607 case 0: /*all styles*/
608 if ( !m_sFollowPageStyleName.isEmpty() )
609 xFirst = GetPageStyle( xPageStyles, xTextFactory, false );
610 if ( !m_sFirstPageStyleName.isEmpty() )
611 xSecond = GetPageStyle( xPageStyles, xTextFactory, true );
612 break;
613 case 1: /*first page*/
614 if ( !m_sFirstPageStyleName.isEmpty() )
615 xFirst = GetPageStyle( xPageStyles, xTextFactory, true );
616 break;
617 case 2: /*left and right*/
618 if ( !m_sFollowPageStyleName.isEmpty() )
619 xFirst = GetPageStyle( xPageStyles, xTextFactory, false );
620 break;
621 case 3: //whole document?
622 //todo: how to apply a border to the whole document - find all sections or access all page styles?
623 default:
624 return;
626 //has to be sorted like enum BorderPosition: l-r-t-b
627 static const PropertyIds aBorderIds[4] =
629 PROP_LEFT_BORDER,
630 PROP_RIGHT_BORDER,
631 PROP_TOP_BORDER,
632 PROP_BOTTOM_BORDER
634 static const PropertyIds aBorderDistanceIds[4] =
636 PROP_LEFT_BORDER_DISTANCE,
637 PROP_RIGHT_BORDER_DISTANCE,
638 PROP_TOP_BORDER_DISTANCE,
639 PROP_BOTTOM_BORDER_DISTANCE
641 static const PropertyIds aMarginIds[4] =
643 PROP_LEFT_MARGIN,
644 PROP_RIGHT_MARGIN,
645 PROP_TOP_MARGIN,
646 PROP_BOTTOM_MARGIN
649 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
650 for( sal_Int32 nBorder = 0; nBorder < 4; ++nBorder)
652 if( m_pBorderLines[nBorder] )
654 const OUString sBorderName = rPropNameSupplier.GetName( aBorderIds[nBorder] );
655 if (xFirst.is())
656 xFirst->setPropertyValue( sBorderName, uno::makeAny( *m_pBorderLines[nBorder] ));
657 if(xSecond.is())
658 xSecond->setPropertyValue( sBorderName, uno::makeAny( *m_pBorderLines[nBorder] ));
660 if( m_nBorderDistances[nBorder] >= 0 )
662 sal_uInt32 nLineWidth = 0;
663 if (m_pBorderLines[nBorder])
664 nLineWidth = m_pBorderLines[nBorder]->LineWidth;
665 if(xFirst.is())
666 SetBorderDistance( xFirst, aMarginIds[nBorder], aBorderDistanceIds[nBorder],
667 m_nBorderDistances[nBorder], nOffsetFrom, nLineWidth );
668 if(xSecond.is())
669 SetBorderDistance( xSecond, aMarginIds[nBorder], aBorderDistanceIds[nBorder],
670 m_nBorderDistances[nBorder], nOffsetFrom, nLineWidth );
674 if (m_bBorderShadows[BORDER_RIGHT])
676 table::ShadowFormat aFormat = getShadowFromBorder(*m_pBorderLines[BORDER_RIGHT]);
677 if (xFirst.is())
678 xFirst->setPropertyValue(rPropNameSupplier.GetName(PROP_SHADOW_FORMAT), uno::makeAny(aFormat));
679 if (xSecond.is())
680 xSecond->setPropertyValue(rPropNameSupplier.GetName(PROP_SHADOW_FORMAT), uno::makeAny(aFormat));
684 table::ShadowFormat PropertyMap::getShadowFromBorder(const table::BorderLine2& rBorder)
686 // In Word UI, shadow is a boolean property, in OOXML, it's a boolean
687 // property of each 4 border type, finally in Writer the border is a
688 // property of the page style, with shadow location, distance and
689 // color. See SwWW8ImplReader::SetShadow().
690 table::ShadowFormat aFormat;
691 aFormat.Color = COL_BLACK;
692 aFormat.Location = table::ShadowLocation_BOTTOM_RIGHT;
693 aFormat.ShadowWidth = rBorder.LineWidth;
694 return aFormat;
697 void SectionPropertyMap::SetBorderDistance( uno::Reference< beans::XPropertySet > const& xStyle,
698 PropertyIds eMarginId, PropertyIds eDistId, sal_Int32 nDistance, sal_Int32 nOffsetFrom, sal_uInt32 nLineWidth )
700 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
702 sal_Int32 nDist = nDistance;
703 if( nOffsetFrom == 1 ) // From page
705 const OUString sMarginName = rPropNameSupplier.GetName( eMarginId );
706 uno::Any aMargin = xStyle->getPropertyValue( sMarginName );
707 sal_Int32 nMargin = 0;
708 aMargin >>= nMargin;
710 // Change the margins with the border distance
711 xStyle->setPropertyValue( sMarginName, uno::makeAny( nDistance ) );
713 // Set the distance to ( Margin - distance - nLineWidth )
714 nDist = nMargin - nDistance - nLineWidth;
716 const OUString sBorderDistanceName = rPropNameSupplier.GetName( eDistId );
717 if (xStyle.is())
718 xStyle->setPropertyValue( sBorderDistanceName, uno::makeAny( nDist ));
723 uno::Reference< text::XTextColumns > SectionPropertyMap::ApplyColumnProperties(
724 uno::Reference< beans::XPropertySet > const& xColumnContainer, DomainMapper_Impl& rDM_Impl )
726 uno::Reference< text::XTextColumns > xColumns;
729 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
730 const OUString sTextColumns = rPropNameSupplier.GetName( PROP_TEXT_COLUMNS );
731 if (xColumnContainer.is())
732 xColumnContainer->getPropertyValue(sTextColumns) >>= xColumns;
733 uno::Reference< beans::XPropertySet > xColumnPropSet( xColumns, uno::UNO_QUERY_THROW );
734 if( !m_bEvenlySpaced &&
735 (sal_Int32(m_aColWidth.size()) == (m_nColumnCount + 1 )) &&
736 ((sal_Int32(m_aColDistance.size()) == m_nColumnCount) || (sal_Int32(m_aColDistance.size()) == m_nColumnCount + 1)) )
738 //the column width in word is an absolute value, in OOo it's relative
739 //the distances are both absolute
740 sal_Int32 nColSum = 0;
741 for( sal_Int32 nCol = 0; nCol <= m_nColumnCount; ++nCol)
743 nColSum += m_aColWidth[nCol];
744 if(nCol)
745 nColSum += m_aColDistance[nCol -1];
748 sal_Int32 nRefValue = xColumns->getReferenceValue();
749 double fRel = nColSum ? double( nRefValue ) / double( nColSum ) : 0.0;
750 uno::Sequence< text::TextColumn > aColumns( m_nColumnCount + 1 );
751 text::TextColumn* pColumn = aColumns.getArray();
753 nColSum = 0;
754 for( sal_Int32 nCol = 0; nCol <= m_nColumnCount; ++nCol)
756 pColumn[nCol].LeftMargin = nCol ? m_aColDistance[nCol - 1 ] / 2 : 0;
757 pColumn[nCol].RightMargin = nCol == m_nColumnCount ? 0 : m_aColDistance[nCol] / 2;
758 pColumn[nCol].Width = sal_Int32((double( m_aColWidth[nCol] + pColumn[nCol].RightMargin + pColumn[nCol].LeftMargin ) + 0.5 ) * fRel );
759 nColSum += pColumn[nCol].Width;
761 if( nColSum != nRefValue )
762 pColumn[m_nColumnCount].Width -= ( nColSum - nRefValue );
763 xColumns->setColumns( aColumns );
765 else
767 xColumns->setColumnCount( m_nColumnCount + 1 );
768 xColumnPropSet->setPropertyValue( rPropNameSupplier.GetName( PROP_AUTOMATIC_DISTANCE ), uno::makeAny( m_nColumnDistance ));
771 if(m_bSeparatorLineIsOn)
772 xColumnPropSet->setPropertyValue(
773 rPropNameSupplier.GetName( PROP_SEPARATOR_LINE_IS_ON ),
774 uno::makeAny( m_bSeparatorLineIsOn ));
775 xColumnContainer->setPropertyValue( sTextColumns, uno::makeAny( xColumns ) );
776 // Set the columns to be unbalanced if that compatibility option is set or this is the last section.
777 if (rDM_Impl.GetSettingsTable()->GetNoColumnBalance() || rDM_Impl.GetIsLastSectionGroup())
778 xColumnContainer->setPropertyValue("DontBalanceTextColumns", uno::makeAny(true));
780 catch( const uno::Exception& )
782 OSL_FAIL( "Exception in SectionPropertyMap::ApplyColumnProperties");
784 return xColumns;
789 bool SectionPropertyMap::HasHeader(bool bFirstPage) const
791 bool bRet = false;
792 if( (bFirstPage && m_aFirstPageStyle.is()) ||( !bFirstPage && m_aFollowPageStyle.is()) )
794 if( bFirstPage )
795 m_aFirstPageStyle->getPropertyValue(
796 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_HEADER_IS_ON) ) >>= bRet;
797 else
798 m_aFollowPageStyle->getPropertyValue(
799 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_HEADER_IS_ON) ) >>= bRet;
801 return bRet;
805 bool SectionPropertyMap::HasFooter(bool bFirstPage) const
807 bool bRet = false;
808 if( (bFirstPage && m_aFirstPageStyle.is()) ||( !bFirstPage && m_aFollowPageStyle.is()) )
810 if( bFirstPage )
811 m_aFirstPageStyle->getPropertyValue(
812 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_FOOTER_IS_ON) ) >>= bRet;
813 else
814 m_aFollowPageStyle->getPropertyValue(
815 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_FOOTER_IS_ON) ) >>= bRet;
817 return bRet;
821 #define MIN_HEAD_FOOT_HEIGHT 100 //minimum header/footer height
823 void SectionPropertyMap::CopyHeaderFooter( uno::Reference< beans::XPropertySet > xPrevStyle,
824 uno::Reference< beans::XPropertySet > xStyle )
826 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
828 try {
829 // Loop over the Header and Footer properties to copy them
830 static const PropertyIds aProperties[] =
832 PROP_HEADER_TEXT,
833 PROP_FOOTER_TEXT,
836 bool bHasPrevHeader = false;
837 bool bHasHeader = false;
839 OUString sHeaderIsOn = rPropNameSupplier.GetName( PROP_HEADER_IS_ON );
840 if (xPrevStyle.is())
841 xPrevStyle->getPropertyValue( sHeaderIsOn ) >>= bHasPrevHeader;
842 if (xStyle.is())
843 xStyle->getPropertyValue( sHeaderIsOn ) >>= bHasHeader;
844 bool bCopyHeader = bHasPrevHeader && !bHasHeader;
846 if ( bCopyHeader )
847 xStyle->setPropertyValue( sHeaderIsOn, uno::makeAny( sal_True ) );
849 bool bHasPrevFooter = false;
850 bool bHasFooter = false;
852 OUString sFooterIsOn = rPropNameSupplier.GetName( PROP_FOOTER_IS_ON );
853 if (xPrevStyle.is())
854 xPrevStyle->getPropertyValue( sFooterIsOn ) >>= bHasPrevFooter;
855 if (xStyle.is())
856 xStyle->getPropertyValue( sFooterIsOn ) >>= bHasFooter;
857 bool bCopyFooter = bHasPrevFooter && !bHasFooter;
859 if ( bCopyFooter && xStyle.is() )
860 xStyle->setPropertyValue( sFooterIsOn, uno::makeAny( sal_True ) );
862 // Copying the text properties
863 for ( int i = 0, nNbProps = 2; i < nNbProps; i++ )
865 bool bIsHeader = ( i < nNbProps / 2 );
866 PropertyIds aPropId = aProperties[i];
867 OUString sName = rPropNameSupplier.GetName( aPropId );
869 if ( ( bIsHeader && bCopyHeader ) || ( !bIsHeader && bCopyFooter ) )
871 SAL_INFO("writerfilter", "Copying " << sName);
872 // TODO has to be copied
873 uno::Reference< text::XTextCopy > xTxt;
874 if (xStyle.is())
875 xTxt.set(xStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW );
877 uno::Reference< text::XTextCopy > xPrevTxt;
878 if (xPrevStyle.is())
879 xPrevTxt.set(xPrevStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW );
881 xTxt->copyText( xPrevTxt );
885 catch ( const uno::Exception& e )
887 SAL_INFO("writerfilter", "An exception occurred in SectionPropertyMap::CopyHeaderFooter( ) - " << e.Message);
891 void SectionPropertyMap::CopyLastHeaderFooter( bool bFirstPage, DomainMapper_Impl& rDM_Impl )
893 SAL_INFO("writerfilter", "START>>> SectionPropertyMap::CopyLastHeaderFooter()");
894 SectionPropertyMap* pLastContext = rDM_Impl.GetLastSectionContext( );
895 if ( pLastContext )
897 uno::Reference< beans::XPropertySet > xPrevStyle = pLastContext->GetPageStyle(
898 rDM_Impl.GetPageStyles(),
899 rDM_Impl.GetTextFactory(),
900 bFirstPage );
901 uno::Reference< beans::XPropertySet > xStyle = GetPageStyle(
902 rDM_Impl.GetPageStyles(),
903 rDM_Impl.GetTextFactory(),
904 bFirstPage );
905 CopyHeaderFooter( xPrevStyle, xStyle );
907 SAL_INFO("writerfilter", "END>>> SectionPropertyMap::CopyLastHeaderFooter()");
910 void SectionPropertyMap::PrepareHeaderFooterProperties( bool bFirstPage )
912 sal_Int32 nTopMargin = m_nTopMargin;
913 sal_Int32 nHeaderTop = m_nHeaderTop;
914 if(HasHeader(bFirstPage))
916 nTopMargin = nHeaderTop;
917 if( m_nTopMargin > 0 && m_nTopMargin > nHeaderTop )
918 nHeaderTop = m_nTopMargin - nHeaderTop;
919 else
920 nHeaderTop = 0;
922 //minimum header height 1mm
923 if( nHeaderTop < MIN_HEAD_FOOT_HEIGHT )
924 nHeaderTop = MIN_HEAD_FOOT_HEIGHT;
928 if( m_nTopMargin >= 0 ) //fixed height header -> see WW8Par6.hxx
930 Insert(PROP_HEADER_IS_DYNAMIC_HEIGHT, uno::makeAny( true ));
931 Insert(PROP_HEADER_DYNAMIC_SPACING, uno::makeAny( true ));
932 Insert(PROP_HEADER_BODY_DISTANCE, uno::makeAny( nHeaderTop - MIN_HEAD_FOOT_HEIGHT ));// ULSpace.Top()
933 Insert(PROP_HEADER_HEIGHT, uno::makeAny( nHeaderTop ));
936 else
938 //todo: old filter fakes a frame into the header/footer to support overlapping
939 //current setting is completely wrong!
940 Insert(PROP_HEADER_HEIGHT, uno::makeAny( nHeaderTop ));
941 Insert(PROP_HEADER_BODY_DISTANCE, uno::makeAny( m_nTopMargin - nHeaderTop ));
942 Insert(PROP_HEADER_IS_DYNAMIC_HEIGHT, uno::makeAny( false ));
943 Insert(PROP_HEADER_DYNAMIC_SPACING, uno::makeAny( false ));
946 sal_Int32 nBottomMargin = m_nBottomMargin;
947 sal_Int32 nHeaderBottom = m_nHeaderBottom;
948 if( HasFooter( bFirstPage ) )
950 nBottomMargin = nHeaderBottom;
951 if( m_nBottomMargin > 0 && m_nBottomMargin > nHeaderBottom )
952 nHeaderBottom = m_nBottomMargin - nHeaderBottom;
953 else
954 nHeaderBottom = 0;
955 if( nHeaderBottom < MIN_HEAD_FOOT_HEIGHT )
956 nHeaderBottom = MIN_HEAD_FOOT_HEIGHT;
959 if( m_nBottomMargin >= 0 ) //fixed height footer -> see WW8Par6.hxx
961 Insert(PROP_FOOTER_IS_DYNAMIC_HEIGHT, uno::makeAny( true ));
962 Insert(PROP_FOOTER_DYNAMIC_SPACING, uno::makeAny( true ));
963 Insert(PROP_FOOTER_BODY_DISTANCE, uno::makeAny( nHeaderBottom - MIN_HEAD_FOOT_HEIGHT));
964 Insert(PROP_FOOTER_HEIGHT, uno::makeAny( nHeaderBottom ));
966 else
968 //todo: old filter fakes a frame into the header/footer to support overlapping
969 //current setting is completely wrong!
970 Insert(PROP_FOOTER_IS_DYNAMIC_HEIGHT, uno::makeAny( false ));
971 Insert(PROP_FOOTER_DYNAMIC_SPACING, uno::makeAny( false ));
972 Insert(PROP_FOOTER_HEIGHT, uno::makeAny( m_nBottomMargin - nHeaderBottom ));
973 Insert(PROP_FOOTER_BODY_DISTANCE, uno::makeAny( nHeaderBottom ));
976 //now set the top/bottom margin for the follow page style
977 Insert(PROP_TOP_MARGIN, uno::makeAny( nTopMargin ));
978 Insert(PROP_BOTTOM_MARGIN, uno::makeAny( nBottomMargin ));
981 uno::Reference<beans::XPropertySet> lcl_GetRangeProperties(bool bIsFirstSection,
982 DomainMapper_Impl& rDM_Impl,
983 uno::Reference<text::XTextRange> const& xStartingRange)
985 uno::Reference< beans::XPropertySet > xRangeProperties;
986 if (bIsFirstSection && rDM_Impl.GetBodyText().is())
988 uno::Reference<container::XEnumerationAccess> xEnumAccess(rDM_Impl.GetBodyText(), uno::UNO_QUERY_THROW);
989 uno::Reference<container::XEnumeration> xEnum = xEnumAccess->createEnumeration();
990 xRangeProperties = uno::Reference<beans::XPropertySet>(xEnum->nextElement(), uno::UNO_QUERY_THROW);
992 else if (xStartingRange.is())
993 xRangeProperties = uno::Reference<beans::XPropertySet>(xStartingRange, uno::UNO_QUERY_THROW);
994 return xRangeProperties;
997 void SectionPropertyMap::HandleMarginsHeaderFooter(DomainMapper_Impl& rDM_Impl)
999 if( m_nDzaGutter > 0 )
1001 //todo: iGutterPos from DocProperties are missing
1002 if( m_bGutterRTL )
1003 m_nRightMargin += m_nDzaGutter;
1004 else
1005 m_nLeftMargin += m_nDzaGutter;
1007 Insert(PROP_LEFT_MARGIN, uno::makeAny( m_nLeftMargin ));
1008 Insert(PROP_RIGHT_MARGIN, uno::makeAny( m_nRightMargin ));
1010 if (rDM_Impl.m_oBackgroundColor)
1011 Insert(PROP_BACK_COLOR, uno::makeAny(*rDM_Impl.m_oBackgroundColor));
1012 if (!rDM_Impl.m_bHasFtnSep)
1013 // Set footnote line width to zero, document has no footnote separator.
1014 Insert(PROP_FOOTNOTE_LINE_RELATIVE_WIDTH, uno::makeAny(sal_Int32(0)));
1016 /*** if headers/footers are available then the top/bottom margins of the
1017 header/footer are copied to the top/bottom margin of the page
1019 CopyLastHeaderFooter( false, rDM_Impl );
1020 PrepareHeaderFooterProperties( false );
1023 void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
1025 // Text area width is known at the end of a section: decide if tables should be converted or not.
1026 std::vector<FloatingTableInfo>& rPendingFloatingTables = rDM_Impl.m_aPendingFloatingTables;
1027 sal_Int32 nTextAreaWidth = GetPageWidth() - GetLeftMargin() - GetRightMargin();
1028 uno::Reference<text::XTextAppendAndConvert> xBodyText( rDM_Impl.GetBodyText(), uno::UNO_QUERY );
1029 for (size_t i = 0; i < rPendingFloatingTables.size(); ++i)
1031 FloatingTableInfo& rInfo = rPendingFloatingTables[i];
1033 // Count the layout width of the table.
1034 sal_Int32 nTableWidth = rInfo.m_nTableWidth;
1035 sal_Int32 nLeftMargin = 0;
1036 if (rInfo.getPropertyValue("LeftMargin") >>= nLeftMargin)
1037 nTableWidth += nLeftMargin;
1038 sal_Int32 nRightMargin = 0;
1039 if (rInfo.getPropertyValue("RightMargin") >>= nRightMargin)
1040 nTableWidth += nRightMargin;
1042 // If the table is wider than the text area, then don't create a fly
1043 // for the table: no wrapping will be performed anyway, but multi-page
1044 // tables will be broken.
1045 // If the position is relative to the edge of the page, then we always
1046 // create the fly.
1047 // If there are columns, always create the fly, otherwise the columns would
1048 // restrict geometry of the table.
1049 if ( ( rInfo.getPropertyValue("HoriOrientRelation") == text::RelOrientation::PAGE_FRAME ) ||
1050 nTableWidth < nTextAreaWidth || ColumnCount() + 1 >= 2 )
1051 xBodyText->convertToTextFrame(rInfo.m_xStart, rInfo.m_xEnd, rInfo.m_aFrameProperties);
1053 rPendingFloatingTables.clear();
1055 PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
1056 if( m_nLnnMod )
1058 bool bFirst = rDM_Impl.IsLineNumberingSet();
1059 rDM_Impl.SetLineNumbering( m_nLnnMod, m_nLnc, m_ndxaLnn );
1060 if( m_nLnnMin > 0 || (bFirst && m_nLnc == NS_ooxml::LN_Value_ST_LineNumberRestart_newSection))
1062 //set the starting value at the beginning of the section
1065 uno::Reference< beans::XPropertySet > xRangeProperties;
1066 if( m_xStartingRange.is() )
1068 xRangeProperties = uno::Reference< beans::XPropertySet >( m_xStartingRange, uno::UNO_QUERY_THROW );
1070 else
1072 //set the start value at the beginning of the document
1073 xRangeProperties = uno::Reference< beans::XPropertySet >( rDM_Impl.GetTextDocument()->getText()->getStart(), uno::UNO_QUERY_THROW );
1075 xRangeProperties->setPropertyValue( rPropNameSupplier.GetName( PROP_PARA_LINE_NUMBER_START_VALUE ), uno::makeAny( m_nLnnMin ));
1077 catch( const uno::Exception& )
1079 OSL_FAIL( "Exception in SectionPropertyMap::CloseSectionGroup");
1084 // depending on the break type no page styles should be created
1085 // If the section type is missing, but we have columns, then this should be
1086 // handled as a continuous section break.
1087 if(m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous) || (m_nBreakType == -1 && m_nColumnCount > 0))
1089 //todo: insert a section or access the already inserted section
1090 uno::Reference< beans::XPropertySet > xSection =
1091 rDM_Impl.appendTextSectionAfter( m_xStartingRange );
1092 if( m_nColumnCount > 0 && xSection.is())
1093 ApplyColumnProperties( xSection, rDM_Impl );
1094 uno::Reference<beans::XPropertySet> xRangeProperties(lcl_GetRangeProperties(m_bIsFirstSection, rDM_Impl, m_xStartingRange));
1095 if (xRangeProperties.is())
1097 OUString aName = m_bTitlePage ? m_sFirstPageStyleName : m_sFollowPageStyleName;
1098 if (!aName.isEmpty())
1102 xRangeProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_PAGE_DESC_NAME), uno::makeAny(aName));
1103 uno::Reference<beans::XPropertySet> xPageStyle (rDM_Impl.GetPageStyles()->getByName(aName), uno::UNO_QUERY_THROW);
1104 HandleMarginsHeaderFooter(rDM_Impl);
1105 if (rDM_Impl.IsNewDoc())
1106 _ApplyProperties(xPageStyle);
1108 catch( const uno::Exception& )
1110 SAL_WARN("writerfilter", "failed to set PageDescName!");
1115 // If the section is of type "New column" (0x01), then simply insert a column break.
1116 // But only if there actually are columns on the page, otherwise a column break
1117 // seems to be handled like a page break by MSO.
1118 else if(m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_nextColumn) && m_nColumnCount > 0 )
1120 uno::Reference< beans::XPropertySet > xRangeProperties;
1121 if( m_xStartingRange.is() )
1123 xRangeProperties = uno::Reference< beans::XPropertySet >( m_xStartingRange, uno::UNO_QUERY_THROW );
1125 else
1127 //set the start value at the beginning of the document
1128 xRangeProperties = uno::Reference< beans::XPropertySet >( rDM_Impl.GetTextDocument()->getText()->getStart(), uno::UNO_QUERY_THROW );
1130 xRangeProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_BREAK_TYPE), uno::makeAny(style::BreakType_COLUMN_BEFORE));
1132 else
1134 //get the properties and create appropriate page styles
1135 uno::Reference< beans::XPropertySet > xFollowPageStyle = GetPageStyle( rDM_Impl.GetPageStyles(), rDM_Impl.GetTextFactory(), false );
1137 HandleMarginsHeaderFooter(rDM_Impl);
1139 const OUString sTrayIndex = rPropNameSupplier.GetName( PROP_PRINTER_PAPER_TRAY_INDEX );
1140 if( m_nPaperBin >= 0 )
1141 xFollowPageStyle->setPropertyValue( sTrayIndex, uno::makeAny( m_nPaperBin ) );
1142 if ( rDM_Impl.GetSettingsTable()->GetMirrorMarginSettings() )
1144 Insert(PROP_PAGE_STYLE_LAYOUT, uno::makeAny(style::PageStyleLayout_MIRRORED));
1146 uno::Reference< text::XTextColumns > xColumns;
1147 if( m_nColumnCount > 0 )
1148 xColumns = ApplyColumnProperties( xFollowPageStyle, rDM_Impl );
1150 //prepare text grid properties
1151 sal_Int32 nHeight = 1;
1152 boost::optional<PropertyMap::Property> pProp = getProperty(PROP_HEIGHT);
1153 if(pProp)
1154 pProp->second >>= nHeight;
1156 sal_Int32 nWidth = 1;
1157 pProp = getProperty(PROP_WIDTH);
1158 if(pProp)
1159 pProp->second >>= nWidth;
1161 text::WritingMode eWritingMode = text::WritingMode_LR_TB;
1162 pProp = getProperty(PROP_WRITING_MODE);
1163 if(pProp)
1164 pProp->second >>= eWritingMode;
1166 sal_Int32 nTextAreaHeight = eWritingMode == text::WritingMode_LR_TB ?
1167 nHeight - m_nTopMargin - m_nBottomMargin :
1168 nWidth - m_nLeftMargin - m_nRightMargin;
1170 sal_Int32 nGridLinePitch = m_nGridLinePitch;
1171 //sep.dyaLinePitch
1172 if (nGridLinePitch < 1 || nGridLinePitch > 31680)
1174 SAL_WARN("writerfilter", "sep.dyaLinePitch outside legal range: " << nGridLinePitch);
1175 nGridLinePitch = 1;
1178 Insert(PROP_GRID_LINES, uno::makeAny( static_cast<sal_Int16>(nTextAreaHeight/nGridLinePitch)));
1180 // PROP_GRID_MODE
1181 Insert( PROP_GRID_MODE, uno::makeAny( static_cast<sal_Int16> (m_nGridType) ));
1182 if (m_nGridType == text::TextGridMode::LINES_AND_CHARS)
1184 Insert( PROP_GRID_SNAP_TO_CHARS, uno::makeAny(m_bGridSnapToChars));
1187 sal_Int32 nCharWidth = 423; //240 twip/ 12 pt
1188 //todo: is '0' the right index here?
1189 const StyleSheetEntryPtr pEntry = rDM_Impl.GetStyleSheetTable()->FindStyleSheetByISTD(OUString::number(0, 16));
1190 if( pEntry.get( ) )
1192 boost::optional<PropertyMap::Property> pPropHeight = pEntry->pProperties->getProperty(PROP_CHAR_HEIGHT_ASIAN);
1193 if(pProp)
1195 double fHeight = 0;
1196 if( pPropHeight->second >>= fHeight )
1197 nCharWidth = ConversionHelper::convertTwipToMM100( (long)( fHeight * 20.0 + 0.5 ));
1201 //dxtCharSpace
1202 if(m_nDxtCharSpace)
1204 sal_Int32 nCharSpace = m_nDxtCharSpace;
1205 //main lives in top 20 bits, and is signed.
1206 sal_Int32 nMain = (nCharSpace & 0xFFFFF000);
1207 nMain /= 0x1000;
1208 nCharWidth += ConversionHelper::convertTwipToMM100( nMain * 20 );
1210 sal_Int32 nFraction = (nCharSpace & 0x00000FFF);
1211 nFraction = (nFraction * 20)/0xFFF;
1212 nCharWidth += ConversionHelper::convertTwipToMM100( nFraction );
1214 Insert(PROP_GRID_BASE_HEIGHT, uno::makeAny( nCharWidth ));
1215 sal_Int32 nRubyHeight = nGridLinePitch - nCharWidth;
1216 if(nRubyHeight < 0 )
1217 nRubyHeight = 0;
1218 Insert(PROP_GRID_RUBY_HEIGHT, uno::makeAny( nRubyHeight ));
1220 // #i119558#, force to set document as standard page mode,
1221 // refer to ww8 import process function "SwWW8ImplReader::SetDocumentGrid"
1224 uno::Reference< beans::XPropertySet > xDocProperties;
1225 xDocProperties = uno::Reference< beans::XPropertySet >( rDM_Impl.GetTextDocument(), uno::UNO_QUERY_THROW );
1226 bool bSquaredPageMode = false;
1227 Insert(PROP_GRID_STANDARD_MODE, uno::makeAny( !bSquaredPageMode ));
1228 xDocProperties->setPropertyValue("DefaultPageMode", uno::makeAny( bSquaredPageMode ));
1230 catch (const uno::Exception& rEx)
1232 OSL_ENSURE( false, "Exception in SectionPropertyMap::CloseSectionGroup");
1233 (void)rEx;
1236 if (rDM_Impl.IsNewDoc())
1237 _ApplyProperties( xFollowPageStyle );
1239 //todo: creating a "First Page" style depends on HasTitlePage und _fFacingPage_
1240 if( m_bTitlePage )
1242 CopyLastHeaderFooter( true, rDM_Impl );
1243 PrepareHeaderFooterProperties( true );
1244 uno::Reference< beans::XPropertySet > xFirstPageStyle = GetPageStyle(
1245 rDM_Impl.GetPageStyles(), rDM_Impl.GetTextFactory(), true );
1246 if (rDM_Impl.IsNewDoc())
1247 _ApplyProperties( xFirstPageStyle );
1249 sal_Int32 nPaperBin = m_nFirstPaperBin >= 0 ? m_nFirstPaperBin : m_nPaperBin >= 0 ? m_nPaperBin : 0;
1250 if( nPaperBin )
1251 xFirstPageStyle->setPropertyValue( sTrayIndex, uno::makeAny( nPaperBin ) );
1252 if( xColumns.is() )
1253 xFirstPageStyle->setPropertyValue(
1254 rPropNameSupplier.GetName( PROP_TEXT_COLUMNS ), uno::makeAny( xColumns ));
1257 ApplyBorderToPageStyles( rDM_Impl.GetPageStyles( ), rDM_Impl.GetTextFactory( ), m_nBorderParams );
1262 //now apply this break at the first paragraph of this section
1263 uno::Reference<beans::XPropertySet> xRangeProperties(lcl_GetRangeProperties(m_bIsFirstSection, rDM_Impl, m_xStartingRange));
1265 // Handle page breaks with odd/even page numbering. We need to use an extra page style for setting the page style
1266 // to left/right, because if we set it to the normal style, we'd set it to "First Page"/"Default Style", which would
1267 // break them (all default pages would be only left or right).
1268 if (m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_evenPage) || m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_oddPage))
1270 OUString* pageStyle = m_bTitlePage ? &m_sFirstPageStyleName : &m_sFollowPageStyleName;
1271 OUString evenOddStyleName = lcl_FindUnusedPageStyleName(rDM_Impl.GetPageStyles()->getElementNames());
1272 uno::Reference< beans::XPropertySet > evenOddStyle(
1273 rDM_Impl.GetTextFactory()->createInstance("com.sun.star.style.PageStyle"),
1274 uno::UNO_QUERY);
1275 // Unfortunately using setParent() does not work for page styles, so make a deep copy of the page style.
1276 uno::Reference< beans::XPropertySet > pageProperties( m_bTitlePage ? m_aFirstPageStyle : m_aFollowPageStyle );
1277 uno::Reference< beans::XPropertySetInfo > pagePropertiesInfo( pageProperties->getPropertySetInfo());
1278 uno::Sequence< beans::Property > propertyList( pagePropertiesInfo->getProperties());
1279 for( int i = 0; i < propertyList.getLength(); ++i )
1281 if(( propertyList[i].Attributes & beans::PropertyAttribute::READONLY ) == 0 )
1282 evenOddStyle->setPropertyValue( propertyList[ i ].Name, pageProperties->getPropertyValue( propertyList[ i ].Name ));
1284 evenOddStyle->setPropertyValue("FollowStyle", uno::makeAny(*pageStyle));
1285 rDM_Impl.GetPageStyles()->insertByName( evenOddStyleName, uno::makeAny( evenOddStyle ) );
1286 evenOddStyle->setPropertyValue("HeaderIsOn", uno::makeAny(sal_False));
1287 evenOddStyle->setPropertyValue("FooterIsOn", uno::makeAny(sal_False));
1288 CopyHeaderFooter( pageProperties, evenOddStyle );
1289 *pageStyle = evenOddStyleName; // And use it instead of the original one (which is set as follow of this one).
1290 if (m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_evenPage))
1291 evenOddStyle->setPropertyValue(rPropNameSupplier.GetName(PROP_PAGE_STYLE_LAYOUT), uno::makeAny(style::PageStyleLayout_LEFT));
1292 else if (m_nBreakType == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_oddPage))
1293 evenOddStyle->setPropertyValue(rPropNameSupplier.GetName(PROP_PAGE_STYLE_LAYOUT), uno::makeAny(style::PageStyleLayout_RIGHT));
1296 if (xRangeProperties.is() && rDM_Impl.IsNewDoc())
1297 xRangeProperties->setPropertyValue(
1298 rPropNameSupplier.GetName( PROP_PAGE_DESC_NAME ),
1299 uno::makeAny( m_bTitlePage ? m_sFirstPageStyleName
1300 : m_sFollowPageStyleName ));
1302 if(m_bPageNoRestart || m_nPageNumber >= 0)
1304 sal_Int16 nPageNumber = m_nPageNumber >= 0 ? static_cast< sal_Int16 >(m_nPageNumber) : 1;
1305 xRangeProperties->setPropertyValue(rPropNameSupplier.GetName( PROP_PAGE_NUMBER_OFFSET ),
1306 uno::makeAny( nPageNumber ));
1310 catch (const uno::Exception&)
1312 OSL_FAIL( "Exception in SectionPropertyMap::CloseSectionGroup");
1315 rDM_Impl.SetIsLastSectionGroup(false);
1316 rDM_Impl.SetIsFirstParagraphInSection(true);
1319 class NamedPropertyValue {
1320 OUString m_aName;
1321 public:
1322 explicit NamedPropertyValue(const OUString& i_aStr)
1323 : m_aName(i_aStr) { }
1324 bool operator() (beans::PropertyValue& aVal)
1325 { return aVal.Name == m_aName; }
1327 void SectionPropertyMap::_ApplyProperties(
1328 uno::Reference< beans::XPropertySet > const& xStyle)
1330 uno::Reference<beans::XMultiPropertySet> const xMultiSet(xStyle,
1331 uno::UNO_QUERY);
1333 std::vector<OUString> vNames;
1334 std::vector<uno::Any> vValues;
1335 { //Convert GetPropertyValues() value into something useful
1336 uno::Sequence<beans::PropertyValue> vPropVals = GetPropertyValues();
1338 //Temporarily store the items that are in grab bags
1339 uno::Sequence<beans::PropertyValue> vCharVals;
1340 uno::Sequence<beans::PropertyValue> vParaVals;
1341 beans::PropertyValue* pCharGrabBag = std::find_if(vPropVals.begin(),vPropVals.end(),NamedPropertyValue("CharInteropGrabBag") );
1342 if (pCharGrabBag!=vPropVals.end())
1343 (pCharGrabBag->Value)>>=vCharVals;
1344 beans::PropertyValue* pParaGrabBag = std::find_if(vPropVals.begin(),vPropVals.end(),NamedPropertyValue("ParaInteropGrabBag") );
1345 if (pParaGrabBag!=vPropVals.end())
1346 (pParaGrabBag->Value)>>=vParaVals;
1348 for (beans::PropertyValue* pIter = vPropVals.begin(); pIter!=vPropVals.end(); ++pIter)
1350 if(pIter!=pCharGrabBag && pIter!=pParaGrabBag)
1352 vNames.push_back(pIter->Name);
1353 vValues.push_back(pIter->Value);
1356 for (beans::PropertyValue* iter = vCharVals.begin(); iter!=vCharVals.end(); ++iter)
1358 vNames.push_back(iter->Name);
1359 vValues.push_back(iter->Value);
1361 for (beans::PropertyValue* iter = vParaVals.begin(); iter!=vParaVals.end(); ++iter)
1363 vNames.push_back(iter->Name);
1364 vValues.push_back(iter->Value);
1367 if (xMultiSet.is())
1371 xMultiSet->setPropertyValues(comphelper::containerToSequence(vNames), comphelper::containerToSequence(vValues));
1373 catch( const uno::Exception& )
1375 OSL_FAIL( "Exception in SectionPropertyMap::_ApplyProperties");
1377 return;
1379 for (size_t i = 0; i < vNames.size(); ++i)
1383 if (xStyle.is())
1384 xStyle->setPropertyValue(vNames[i], vValues[i]);
1386 catch( const uno::Exception& )
1388 OSL_FAIL( "Exception in SectionPropertyMap::_ApplyProperties");
1393 sal_Int32 lcl_AlignPaperBin( sal_Int32 nSet )
1395 //default tray numbers are above 0xff
1396 if( nSet > 0xff )
1397 nSet = nSet >> 8;
1398 //there are some special numbers which can't be handled easily
1399 //1, 4, 15, manual tray, upper tray, auto select? see ww8atr.cxx
1400 //todo: find out appropriate conversion
1401 return nSet;
1405 void SectionPropertyMap::SetPaperBin( sal_Int32 nSet )
1407 m_nPaperBin = lcl_AlignPaperBin( nSet );
1411 void SectionPropertyMap::SetFirstPaperBin( sal_Int32 nSet )
1413 m_nFirstPaperBin = lcl_AlignPaperBin( nSet );
1417 sal_Int32 SectionPropertyMap::GetPageWidth()
1419 return getProperty(PROP_WIDTH)->second.get<sal_Int32>();
1422 StyleSheetPropertyMap::StyleSheetPropertyMap() :
1423 mnCT_Spacing_line( 0 ),
1424 mnCT_Spacing_lineRule( 0 ),
1425 mbCT_TrPrBase_tblHeader( false ),
1426 mnCT_TrPrBase_jc( 0 ),
1427 mnCT_TblWidth_w( 0 ),
1428 mnCT_TblWidth_type( 0 ),
1429 mbCT_Spacing_lineSet( false ),
1430 mbCT_Spacing_lineRuleSet( false ),
1431 mbCT_TrPrBase_tblHeaderSet( false ),
1432 mbCT_TrPrBase_jcSet( false ),
1433 mbCT_TblWidth_wSet( false ),
1434 mbCT_TblWidth_typeSet( false ),
1435 mnListId( -1 ),
1436 mnListLevel( -1 ),
1437 mnOutlineLevel( -1 ),
1438 mnNumId( -1 )
1443 StyleSheetPropertyMap::~StyleSheetPropertyMap()
1448 ParagraphProperties::ParagraphProperties() :
1449 m_bFrameMode( false ),
1450 m_nDropCap(NS_ooxml::LN_Value_doc_ST_DropCap_none),
1451 m_nLines(0),
1452 m_w(-1),
1453 m_h(-1),
1454 m_nWrap(-1),
1455 m_hAnchor(-1),
1456 m_vAnchor(text::RelOrientation::FRAME),
1457 m_x(-1),
1458 m_bxValid( false ),
1459 m_y(-1),
1460 m_byValid( false ),
1461 m_hSpace(-1),
1462 m_vSpace(-1),
1463 m_hRule(-1),
1464 m_xAlign(-1),
1465 m_yAlign(-1),
1466 m_bAnchorLock(false),
1467 m_nDropCapLength(0)
1472 ParagraphProperties::ParagraphProperties(const ParagraphProperties& rCopy) :
1473 m_bFrameMode ( rCopy.m_bFrameMode),
1474 m_nDropCap ( rCopy.m_nDropCap),
1475 m_nLines ( rCopy.m_nLines),
1476 m_w ( rCopy.m_w),
1477 m_h ( rCopy.m_h),
1478 m_nWrap ( rCopy.m_nWrap),
1479 m_hAnchor ( rCopy.m_hAnchor),
1480 m_vAnchor ( rCopy.m_vAnchor),
1481 m_x ( rCopy.m_x),
1482 m_bxValid ( rCopy.m_bxValid),
1483 m_y ( rCopy.m_y),
1484 m_byValid ( rCopy.m_byValid),
1485 m_hSpace ( rCopy.m_hSpace),
1486 m_vSpace ( rCopy.m_vSpace),
1487 m_hRule ( rCopy.m_hRule),
1488 m_xAlign ( rCopy.m_xAlign),
1489 m_yAlign ( rCopy.m_yAlign),
1490 m_bAnchorLock( rCopy.m_bAnchorLock),
1491 m_nDropCapLength( rCopy.m_nDropCapLength ),
1492 m_sParaStyleName( rCopy.m_sParaStyleName),
1493 m_xStartingRange( rCopy.m_xStartingRange ),
1494 m_xEndingRange( rCopy.m_xEndingRange)
1499 ParagraphProperties::~ParagraphProperties()
1504 bool ParagraphProperties::operator==(const ParagraphProperties& rCompare)
1506 return
1507 m_bFrameMode == rCompare.m_bFrameMode &&
1508 m_nDropCap == rCompare.m_nDropCap &&
1509 m_nLines == rCompare.m_nLines &&
1510 m_w == rCompare.m_w &&
1511 m_h == rCompare.m_h &&
1512 m_nWrap == rCompare.m_nWrap &&
1513 m_hAnchor == rCompare.m_hAnchor &&
1514 m_vAnchor == rCompare.m_vAnchor &&
1515 m_x == rCompare.m_x &&
1516 m_bxValid == rCompare.m_bxValid &&
1517 m_y == rCompare.m_y &&
1518 m_byValid == rCompare.m_byValid &&
1519 m_hSpace == rCompare.m_hSpace &&
1520 m_vSpace == rCompare.m_vSpace &&
1521 m_hRule == rCompare.m_hRule &&
1522 m_xAlign == rCompare.m_xAlign &&
1523 m_yAlign == rCompare.m_yAlign &&
1524 m_bAnchorLock== rCompare.m_bAnchorLock;
1527 void ParagraphProperties::ResetFrameProperties()
1529 m_bFrameMode = false;
1530 m_nDropCap = NS_ooxml::LN_Value_doc_ST_DropCap_none;
1531 m_nLines = 0;
1532 m_w = -1;
1533 m_h = -1;
1534 m_nWrap = -1;
1535 m_hAnchor = -1;
1536 m_vAnchor = text::RelOrientation::FRAME;
1537 m_x = -1;
1538 m_bxValid = false;
1539 m_y = -1;
1540 m_byValid = false;
1541 m_hSpace = -1;
1542 m_vSpace = -1;
1543 m_hRule = -1;
1544 m_xAlign = -1;
1545 m_yAlign = -1;
1546 m_bAnchorLock = false;
1547 m_nDropCapLength = 0;
1551 ParagraphPropertyMap::ParagraphPropertyMap()
1556 ParagraphPropertyMap::~ParagraphPropertyMap()
1561 TablePropertyMap::TablePropertyMap()
1566 TablePropertyMap::~TablePropertyMap()
1571 bool TablePropertyMap::getValue( TablePropertyMapTarget eWhich, sal_Int32& nFill )
1573 if( eWhich < TablePropertyMapTarget_MAX )
1575 if(m_aValidValues[eWhich].bValid)
1576 nFill = m_aValidValues[eWhich].nValue;
1577 return m_aValidValues[eWhich].bValid;
1579 else
1581 OSL_FAIL( "invalid TablePropertyMapTarget");
1582 return false;
1587 void TablePropertyMap::setValue( TablePropertyMapTarget eWhich, sal_Int32 nSet )
1589 if( eWhich < TablePropertyMapTarget_MAX )
1591 m_aValidValues[eWhich].bValid = true;
1592 m_aValidValues[eWhich].nValue = nSet;
1594 else
1595 OSL_FAIL( "invalid TablePropertyMapTarget");
1599 void TablePropertyMap::insertTableProperties( const PropertyMap* pMap )
1601 #ifdef DEBUG_WRITERFILTER
1602 TagLogger::getInstance().startElement("TablePropertyMap.insertTableProperties");
1603 pMap->dumpXml();
1604 #endif
1606 const TablePropertyMap* pSource = dynamic_cast< const TablePropertyMap* >(pMap);
1607 if( pSource )
1609 for( sal_Int32 eTarget = TablePropertyMapTarget_START;
1610 eTarget < TablePropertyMapTarget_MAX; ++eTarget )
1612 if( pSource->m_aValidValues[eTarget].bValid )
1614 m_aValidValues[eTarget].bValid = true;
1615 m_aValidValues[eTarget].nValue = pSource->m_aValidValues[eTarget].nValue;
1619 #ifdef DEBUG_WRITERFILTER
1620 dumpXml();
1621 TagLogger::getInstance().endElement();
1622 #endif
1626 }//namespace dmapper
1627 }//namespace writerfilter
1629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */