1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
{
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
)
79 else if ( i
->second
.getGrabBagType() == PARA_GRAB_BAG
)
81 else if ( i
->second
.getGrabBagType() == CELL_GRAB_BAG
)
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();
93 else if ( i
->second
.getGrabBagType() == ROW_GRAB_BAG
)
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
)
147 pCharGrabBagValues
[nCharGrabBagValue
].Name
= rPropNameSupplier
.GetName( aMapIter
->first
);
148 pCharGrabBagValues
[nCharGrabBagValue
].Value
= aMapIter
->second
.getValue();
152 else if ( aMapIter
->second
.getGrabBagType() == PARA_GRAB_BAG
)
154 pParaGrabBagValues
[nParaGrabBagValue
].Name
= rPropNameSupplier
.GetName( aMapIter
->first
);
155 pParaGrabBagValues
[nParaGrabBagValue
].Value
= aMapIter
->second
.getValue();
158 else if ( aMapIter
->second
.getGrabBagType() == CELL_GRAB_BAG
)
160 pCellGrabBagValues
[nCellGrabBagValue
].Name
= rPropNameSupplier
.GetName( aMapIter
->first
);
161 pCellGrabBagValues
[nCellGrabBagValue
].Value
= aMapIter
->second
.getValue();
164 else if ( aMapIter
->second
.getGrabBagType() == ROW_GRAB_BAG
)
166 pRowGrabBagValues
[nRowGrabBagValue
].Name
= rPropNameSupplier
.GetName( aMapIter
->first
);
167 pRowGrabBagValues
[nRowGrabBagValue
].Value
= aMapIter
->second
.getValue();
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
];
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
);
201 beans::PropertyValue aValue
;
202 aValue
.Name
= "ParaInteropGrabBag";
203 aValue
.Value
= uno::makeAny(aParaGrabBagValues
);
204 m_aValues
.push_back(aValue
);
208 beans::PropertyValue aValue
;
209 aValue
.Name
= "CellInteropGrabBag";
210 aValue
.Value
= uno::makeAny(aCellGrabBagValues
);
211 m_aValues
.push_back(aValue
);
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
)
230 TagLogger::getInstance().attribute("value", rAny
);
232 TagLogger::getInstance().attribute("unsignedValue", 0);
235 sal_uInt32 auInt
= 0;
237 TagLogger::getInstance().attribute("unsignedValue", auInt
);
240 if (rAny
>>= aFloat
) {
241 TagLogger::getInstance().attribute("floatValue", rAny
);
243 TagLogger::getInstance().attribute("unsignedValue", 0);
248 TagLogger::getInstance().attribute("stringValue", aStr
);
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
);
264 TagLogger::getInstance().endElement();
268 m_vMap
.insert(std::make_pair(eId
, PropValue(rAny
, i_GrabBagType
)));
270 m_vMap
[eId
] = PropValue(rAny
, i_GrabBagType
);
275 void PropertyMap::Erase( PropertyIds eId
)
277 //Safe call to erase, it throws no exceptions, even if eId is not in m_vMap
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
>();
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());
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
);
327 aMapIter
->second
.getValue() >>= aFloat
;
328 TagLogger::getInstance().attribute("floatValue", aFloat
);
331 aMapIter
->second
.getValue() >>= auInt
;
332 TagLogger::getInstance().attribute("stringValue", aStr
);
340 TagLogger::getInstance().endElement();
345 TagLogger::getInstance().endElement();
349 void PropertyMap::InsertProps(const PropertyMapPtr
& 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());
363 void PropertyMap::insertTableProperties( const PropertyMap
* )
365 #ifdef DEBUG_WRITERFILTER
366 TagLogger::getInstance().element("PropertyMap.insertTableProperties");
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
;
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();
404 SectionPropertyMap::SectionPropertyMap(bool bIsFirstSection
) :
405 m_bIsFirstSection( bIsFirstSection
)
406 ,m_nBorderParams( 0 )
407 ,m_bTitlePage( false )
409 ,m_nColumnDistance( 1249 )
410 ,m_bSeparatorLineIsOn( false )
411 ,m_bEvenlySpaced( false )
412 ,m_bIsLandscape( false )
413 ,m_bPageNoRestart( false )
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
425 ,m_bGutterRTL( false )
428 ,m_nGridLinePitch( 1 )
429 ,m_nDxtCharSpace( 0 )
430 ,m_bGridSnapToChars(true)
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 ) );
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
)
503 OUString
sRet( sDefaultStyle
);
504 sRet
+= OUString::number( nMaxIndex
+ 1);
510 uno::Reference
< beans::XPropertySet
> SectionPropertyMap::GetPageStyle(
511 const uno::Reference
< container::XNameContainer
>& xPageStyles
,
512 const uno::Reference
< lang::XMultiServiceFactory
>& xTextFactory
,
515 uno::Reference
< beans::XPropertySet
> xRet
;
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"),
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
;
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"),
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
);
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
,
589 page border applies to:
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
597 page border offset from:
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 );
613 case 1: /*first page*/
614 if ( !m_sFirstPageStyleName
.isEmpty() )
615 xFirst
= GetPageStyle( xPageStyles
, xTextFactory
, true );
617 case 2: /*left and right*/
618 if ( !m_sFollowPageStyleName
.isEmpty() )
619 xFirst
= GetPageStyle( xPageStyles
, xTextFactory
, false );
621 case 3: //whole document?
622 //todo: how to apply a border to the whole document - find all sections or access all page styles?
626 //has to be sorted like enum BorderPosition: l-r-t-b
627 static const PropertyIds aBorderIds
[4] =
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] =
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
] );
656 xFirst
->setPropertyValue( sBorderName
, uno::makeAny( *m_pBorderLines
[nBorder
] ));
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
;
666 SetBorderDistance( xFirst
, aMarginIds
[nBorder
], aBorderDistanceIds
[nBorder
],
667 m_nBorderDistances
[nBorder
], nOffsetFrom
, nLineWidth
);
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
]);
678 xFirst
->setPropertyValue(rPropNameSupplier
.GetName(PROP_SHADOW_FORMAT
), uno::makeAny(aFormat
));
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
;
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;
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
);
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
];
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();
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
);
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");
789 bool SectionPropertyMap::HasHeader(bool bFirstPage
) const
792 if( (bFirstPage
&& m_aFirstPageStyle
.is()) ||( !bFirstPage
&& m_aFollowPageStyle
.is()) )
795 m_aFirstPageStyle
->getPropertyValue(
796 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_HEADER_IS_ON
) ) >>= bRet
;
798 m_aFollowPageStyle
->getPropertyValue(
799 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_HEADER_IS_ON
) ) >>= bRet
;
805 bool SectionPropertyMap::HasFooter(bool bFirstPage
) const
808 if( (bFirstPage
&& m_aFirstPageStyle
.is()) ||( !bFirstPage
&& m_aFollowPageStyle
.is()) )
811 m_aFirstPageStyle
->getPropertyValue(
812 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_FOOTER_IS_ON
) ) >>= bRet
;
814 m_aFollowPageStyle
->getPropertyValue(
815 PropertyNameSupplier::GetPropertyNameSupplier().GetName(PROP_FOOTER_IS_ON
) ) >>= 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();
829 // Loop over the Header and Footer properties to copy them
830 static const PropertyIds aProperties
[] =
836 bool bHasPrevHeader
= false;
837 bool bHasHeader
= false;
839 OUString sHeaderIsOn
= rPropNameSupplier
.GetName( PROP_HEADER_IS_ON
);
841 xPrevStyle
->getPropertyValue( sHeaderIsOn
) >>= bHasPrevHeader
;
843 xStyle
->getPropertyValue( sHeaderIsOn
) >>= bHasHeader
;
844 bool bCopyHeader
= bHasPrevHeader
&& !bHasHeader
;
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
);
854 xPrevStyle
->getPropertyValue( sFooterIsOn
) >>= bHasPrevFooter
;
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
;
875 xTxt
.set(xStyle
->getPropertyValue( sName
), uno::UNO_QUERY_THROW
);
877 uno::Reference
< text::XTextCopy
> xPrevTxt
;
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( );
897 uno::Reference
< beans::XPropertySet
> xPrevStyle
= pLastContext
->GetPageStyle(
898 rDM_Impl
.GetPageStyles(),
899 rDM_Impl
.GetTextFactory(),
901 uno::Reference
< beans::XPropertySet
> xStyle
= GetPageStyle(
902 rDM_Impl
.GetPageStyles(),
903 rDM_Impl
.GetTextFactory(),
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
;
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
));
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
;
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
));
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
1003 m_nRightMargin
+= m_nDzaGutter
;
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
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();
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
);
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
);
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
));
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
);
1154 pProp
->second
>>= nHeight
;
1156 sal_Int32 nWidth
= 1;
1157 pProp
= getProperty(PROP_WIDTH
);
1159 pProp
->second
>>= nWidth
;
1161 text::WritingMode eWritingMode
= text::WritingMode_LR_TB
;
1162 pProp
= getProperty(PROP_WRITING_MODE
);
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
;
1172 if (nGridLinePitch
< 1 || nGridLinePitch
> 31680)
1174 SAL_WARN("writerfilter", "sep.dyaLinePitch outside legal range: " << nGridLinePitch
);
1178 Insert(PROP_GRID_LINES
, uno::makeAny( static_cast<sal_Int16
>(nTextAreaHeight
/nGridLinePitch
)));
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));
1192 boost::optional
<PropertyMap::Property
> pPropHeight
= pEntry
->pProperties
->getProperty(PROP_CHAR_HEIGHT_ASIAN
);
1196 if( pPropHeight
->second
>>= fHeight
)
1197 nCharWidth
= ConversionHelper::convertTwipToMM100( (long)( fHeight
* 20.0 + 0.5 ));
1204 sal_Int32 nCharSpace
= m_nDxtCharSpace
;
1205 //main lives in top 20 bits, and is signed.
1206 sal_Int32 nMain
= (nCharSpace
& 0xFFFFF000);
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 )
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");
1236 if (rDM_Impl
.IsNewDoc())
1237 _ApplyProperties( xFollowPageStyle
);
1239 //todo: creating a "First Page" style depends on HasTitlePage und _fFacingPage_
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;
1251 xFirstPageStyle
->setPropertyValue( sTrayIndex
, uno::makeAny( nPaperBin
) );
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"),
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
{
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
,
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
);
1371 xMultiSet
->setPropertyValues(comphelper::containerToSequence(vNames
), comphelper::containerToSequence(vValues
));
1373 catch( const uno::Exception
& )
1375 OSL_FAIL( "Exception in SectionPropertyMap::_ApplyProperties");
1379 for (size_t i
= 0; i
< vNames
.size(); ++i
)
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
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
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 ),
1437 mnOutlineLevel( -1 ),
1443 StyleSheetPropertyMap::~StyleSheetPropertyMap()
1448 ParagraphProperties::ParagraphProperties() :
1449 m_bFrameMode( false ),
1450 m_nDropCap(NS_ooxml::LN_Value_doc_ST_DropCap_none
),
1456 m_vAnchor(text::RelOrientation::FRAME
),
1466 m_bAnchorLock(false),
1472 ParagraphProperties::ParagraphProperties(const ParagraphProperties
& rCopy
) :
1473 m_bFrameMode ( rCopy
.m_bFrameMode
),
1474 m_nDropCap ( rCopy
.m_nDropCap
),
1475 m_nLines ( rCopy
.m_nLines
),
1478 m_nWrap ( rCopy
.m_nWrap
),
1479 m_hAnchor ( rCopy
.m_hAnchor
),
1480 m_vAnchor ( rCopy
.m_vAnchor
),
1482 m_bxValid ( rCopy
.m_bxValid
),
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
)
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
;
1536 m_vAnchor
= text::RelOrientation::FRAME
;
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
;
1581 OSL_FAIL( "invalid TablePropertyMapTarget");
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
;
1595 OSL_FAIL( "invalid TablePropertyMapTarget");
1599 void TablePropertyMap::insertTableProperties( const PropertyMap
* pMap
)
1601 #ifdef DEBUG_WRITERFILTER
1602 TagLogger::getInstance().startElement("TablePropertyMap.insertTableProperties");
1606 const TablePropertyMap
* pSource
= dynamic_cast< const TablePropertyMap
* >(pMap
);
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
1621 TagLogger::getInstance().endElement();
1626 }//namespace dmapper
1627 }//namespace writerfilter
1629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */