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 .
20 #include "docxattributeoutput.hxx"
21 #include "docxexportfilter.hxx"
22 #include "docxfootnotes.hxx"
23 #include "writerwordglue.hxx"
25 #include "fmtcntnt.hxx"
26 #include "fchrfmt.hxx"
27 #include "tgrditem.hxx"
28 #include "fmtruby.hxx"
29 #include "breakit.hxx"
31 #include <comphelper/string.hxx>
32 #include <oox/token/tokens.hxx>
33 #include <oox/export/utils.hxx>
34 #include <oox/mathml/export.hxx>
36 #include <i18nlangtag/languagetag.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <editeng/tstpitem.hxx>
40 #include <editeng/spltitem.hxx>
41 #include <editeng/widwitem.hxx>
42 #include <editeng/shaditem.hxx>
43 #include <editeng/brushitem.hxx>
44 #include <editeng/postitem.hxx>
45 #include <editeng/wghtitem.hxx>
46 #include <editeng/kernitem.hxx>
47 #include <editeng/crossedoutitem.hxx>
48 #include <editeng/cmapitem.hxx>
49 #include <editeng/udlnitem.hxx>
50 #include <editeng/langitem.hxx>
51 #include <editeng/escapementitem.hxx>
52 #include <editeng/fhgtitem.hxx>
53 #include <editeng/colritem.hxx>
54 #include <editeng/hyphenzoneitem.hxx>
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/boxitem.hxx>
57 #include <editeng/contouritem.hxx>
58 #include <editeng/shdditem.hxx>
59 #include <editeng/emphasismarkitem.hxx>
60 #include <editeng/twolinesitem.hxx>
61 #include <editeng/charscaleitem.hxx>
62 #include <editeng/charrotateitem.hxx>
63 #include <editeng/charreliefitem.hxx>
64 #include <editeng/paravertalignitem.hxx>
65 #include <editeng/pgrditem.hxx>
66 #include <editeng/frmdiritem.hxx>
67 #include <editeng/blinkitem.hxx>
68 #include <editeng/charhiddenitem.hxx>
69 #include <editeng/opaqitem.hxx>
70 #include <editeng/editobj.hxx>
71 #include <svx/svdmodel.hxx>
72 #include <svx/svdobj.hxx>
73 #include <svx/xfillit0.hxx>
74 #include <svx/xflgrit.hxx>
75 #include <sfx2/sfxbasemodel.hxx>
77 #include <anchoredobject.hxx>
78 #include <docufld.hxx>
79 #include <flddropdown.hxx>
80 #include <fmtanchr.hxx>
81 #include <fmtclds.hxx>
82 #include <fmtinfmt.hxx>
83 #include <fmtrowsplt.hxx>
84 #include <fmtline.hxx>
86 #include <ftninfo.hxx>
87 #include <htmltbl.hxx>
88 #include <lineinfo.hxx>
92 #include <pagedesc.hxx>
94 #include <charatr.hxx>
95 #include <swmodule.hxx>
96 #include <swtable.hxx>
98 #include <txtinet.hxx>
100 #include <osl/file.hxx>
101 #include <rtl/tencinfo.h>
102 #include <vcl/embeddedfontshelper.hxx>
104 #include <com/sun/star/i18n/ScriptType.hpp>
105 #include <com/sun/star/chart2/XChartDocument.hpp>
107 #if OSL_DEBUG_LEVEL > 1
111 using ::editeng::SvxBorderLine
;
114 using namespace docx
;
115 using namespace sax_fastparser
;
116 using namespace nsSwDocInfoSubType
;
117 using namespace nsFieldFlags
;
118 using namespace sw::util
;
119 using namespace ::com::sun::star
;
121 class FFDataWriterHelper
123 ::sax_fastparser::FSHelperPtr m_pSerializer
;
124 void writeCommonStart( const OUString
& rName
)
126 m_pSerializer
->startElementNS( XML_w
, XML_ffData
, FSEND
);
127 m_pSerializer
->singleElementNS( XML_w
, XML_name
,
128 FSNS( XML_w
, XML_val
), OUStringToOString( rName
, RTL_TEXTENCODING_UTF8
).getStr(),
130 m_pSerializer
->singleElementNS( XML_w
, XML_enabled
, FSEND
);
131 m_pSerializer
->singleElementNS( XML_w
, XML_calcOnExit
,
132 FSNS( XML_w
, XML_val
),
137 m_pSerializer
->endElementNS( XML_w
, XML_ffData
);
140 FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr pSerializer
) : m_pSerializer( pSerializer
){}
141 void WriteFormCheckbox( const OUString
& rName
, const OUString
& rDefault
, bool bChecked
)
143 writeCommonStart( rName
);
144 // Checkbox specific bits
145 m_pSerializer
->startElementNS( XML_w
, XML_checkBox
, FSEND
);
146 // currently hardcoding autosize
147 // #TODO check if this defaulted
148 m_pSerializer
->startElementNS( XML_w
, XML_sizeAuto
, FSEND
);
149 m_pSerializer
->endElementNS( XML_w
, XML_sizeAuto
);
150 if ( !rDefault
.isEmpty() )
152 m_pSerializer
->singleElementNS( XML_w
, XML_default
,
153 FSNS( XML_w
, XML_val
),
154 OUStringToOString( rDefault
, RTL_TEXTENCODING_UTF8
).getStr(), FSEND
);
157 m_pSerializer
->singleElementNS( XML_w
, XML_checked
, FSEND
);
158 m_pSerializer
->endElementNS( XML_w
, XML_checkBox
);
161 void WriteFormText( const OUString
& rName
, const OUString
& rDefault
)
163 writeCommonStart( rName
);
164 if ( !rDefault
.isEmpty() )
166 m_pSerializer
->startElementNS( XML_w
, XML_textInput
, FSEND
);
167 m_pSerializer
->singleElementNS( XML_w
, XML_default
,
168 FSNS( XML_w
, XML_val
),
169 OUStringToOString( rDefault
, RTL_TEXTENCODING_UTF8
).getStr(), FSEND
);
170 m_pSerializer
->endElementNS( XML_w
, XML_textInput
);
176 class FieldMarkParamsHelper
178 const sw::mark::IFieldmark
& mrFieldmark
;
180 FieldMarkParamsHelper( const sw::mark::IFieldmark
& rFieldmark
) : mrFieldmark( rFieldmark
) {}
181 OUString
getName() { return mrFieldmark
.GetName(); }
182 template < typename T
>
183 bool extractParam( const OUString
& rKey
, T
& rResult
)
185 bool bResult
= false;
186 if ( mrFieldmark
.GetParameters() )
188 sw::mark::IFieldmark::parameter_map_t::const_iterator it
= mrFieldmark
.GetParameters()->find( rKey
);
189 if ( it
!= mrFieldmark
.GetParameters()->end() )
190 bResult
= ( it
->second
>>= rResult
);
195 void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL
, sal_uInt16
/*nScript*/ )
198 m_pSerializer
->singleElementNS( XML_w
, XML_rtl
, FSNS( XML_w
, XML_val
), "true", FSEND
);
201 void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo
)
203 if ( m_nColBreakStatus
== COLBRK_POSTPONE
)
204 m_nColBreakStatus
= COLBRK_WRITE
;
206 // Output table/table row/table cell starts if needed
207 if ( pTextNodeInfo
.get() )
209 sal_uInt32 nRow
= pTextNodeInfo
->getRow();
210 sal_uInt32 nCell
= pTextNodeInfo
->getCell();
213 if ( m_nTableDepth
> 0 && !m_bTableCellOpen
)
215 ww8::WW8TableNodeInfoInner::Pointer_t
pDeepInner( pTextNodeInfo
->getInnerForDepth( m_nTableDepth
) );
216 if ( pDeepInner
->getCell() == 0 )
217 StartTableRow( pDeepInner
);
219 StartTableCell( pDeepInner
);
222 if ( nRow
== 0 && nCell
== 0 )
224 // Do we have to start the table?
225 // [If we are at the rigth depth already, it means that we
226 // continue the table cell]
227 sal_uInt32 nCurrentDepth
= pTextNodeInfo
->getDepth();
229 if ( nCurrentDepth
> m_nTableDepth
)
231 // Start all the tables that begin here
232 for ( sal_uInt32 nDepth
= m_nTableDepth
+ 1; nDepth
<= pTextNodeInfo
->getDepth(); ++nDepth
)
234 ww8::WW8TableNodeInfoInner::Pointer_t
pInner( pTextNodeInfo
->getInnerForDepth( nDepth
) );
236 StartTable( pInner
);
237 StartTableRow( pInner
);
238 StartTableCell( pInner
);
241 m_nTableDepth
= nCurrentDepth
;
246 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
248 // postpone the output of the run (we get it before the paragraph
249 // properties, but must write it after them)
250 m_pSerializer
->mark();
252 // no section break in this paragraph yet; can be set in SectionBreak()
253 m_pSectionInfo
.reset();
255 m_bParagraphOpened
= true;
258 void lcl_TextFrameShadow(FSHelperPtr pSerializer
, const SwFrmFmt
& rFrmFmt
)
260 SvxShadowItem aShadowItem
= rFrmFmt
.GetShadow();
261 if (aShadowItem
.GetLocation() == SVX_SHADOW_NONE
)
264 OString
aShadowWidth( OString::valueOf( double( aShadowItem
.GetWidth() ) / 20) + "pt");
266 switch (aShadowItem
.GetLocation())
268 case SVX_SHADOW_TOPLEFT
: aOffset
= "-" + aShadowWidth
+ ",-" + aShadowWidth
; break;
269 case SVX_SHADOW_TOPRIGHT
: aOffset
= aShadowWidth
+ ",-" + aShadowWidth
; break;
270 case SVX_SHADOW_BOTTOMLEFT
: aOffset
= "-" + aShadowWidth
+ "," + aShadowWidth
; break;
271 case SVX_SHADOW_BOTTOMRIGHT
: aOffset
= aShadowWidth
+ "," + aShadowWidth
; break;
272 case SVX_SHADOW_NONE
:
276 if (aOffset
.isEmpty())
279 OString aShadowColor
= msfilter::util::ConvertColor(aShadowItem
.GetColor());
280 pSerializer
->singleElementNS(XML_v
, XML_shadow
,
282 XML_color
, "#" + aShadowColor
,
287 void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner
)
289 // write the paragraph properties + the run, already in the correct order
290 m_pSerializer
->mergeTopMarks();
292 // Write the anchored frame if any
293 // Make a copy and clear the original early, as this method is called
294 // recursively for in-frame paragraphs
295 std::vector
<sw::Frame
> aParentFrames
= m_aParentFrames
;
296 m_aParentFrames
.clear();
297 for (size_t i
= 0; i
< aParentFrames
.size(); ++i
)
299 sw::Frame
* pParentFrame
= &aParentFrames
[i
];
301 const SwFrmFmt
& rFrmFmt
= pParentFrame
->GetFrmFmt( );
302 const SwNodeIndex
* pNodeIndex
= rFrmFmt
.GetCntnt().GetCntntIdx();
304 sal_uLong nStt
= pNodeIndex
? pNodeIndex
->GetIndex()+1 : 0;
305 sal_uLong nEnd
= pNodeIndex
? pNodeIndex
->GetNode().EndOfSectionIndex() : 0;
307 m_rExport
.SaveData( nStt
, nEnd
);
309 m_rExport
.mpParentFrame
= pParentFrame
;
311 // When a frame has some low height, but automatically expanded due
312 // to lots of contents, this size contains the real size.
313 const Size aSize
= pParentFrame
->GetSize();
314 m_pFlyFrameSize
= &aSize
;
316 m_bTextFrameSyntax
= true;
317 m_pFlyAttrList
= m_pSerializer
->createAttrList( );
318 m_pTextboxAttrList
= m_pSerializer
->createAttrList();
319 m_aTextFrameStyle
= "position:absolute";
320 m_rExport
.OutputFormat( pParentFrame
->GetFrmFmt(), false, false, true );
321 m_pFlyAttrList
->add(XML_style
, m_aTextFrameStyle
.makeStringAndClear());
322 XFastAttributeListRef
xFlyAttrList( m_pFlyAttrList
);
323 m_pFlyAttrList
= NULL
;
324 XFastAttributeListRef
xTextboxAttrList(m_pTextboxAttrList
);
325 m_pTextboxAttrList
= NULL
;
326 m_bTextFrameSyntax
= false;
329 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
330 m_pSerializer
->startElementNS( XML_w
, XML_pict
, FSEND
);
331 m_pSerializer
->startElementNS( XML_v
, XML_rect
, xFlyAttrList
);
332 lcl_TextFrameShadow(m_pSerializer
, rFrmFmt
);
333 if (m_pFlyFillAttrList
)
335 XFastAttributeListRef
xFlyFillAttrList(m_pFlyFillAttrList
);
336 m_pFlyFillAttrList
= NULL
;
337 m_pSerializer
->singleElementNS(XML_v
, XML_fill
, xFlyFillAttrList
);
339 m_pSerializer
->startElementNS( XML_v
, XML_textbox
, xTextboxAttrList
);
340 m_pSerializer
->startElementNS( XML_w
, XML_txbxContent
, FSEND
);
341 m_rExport
.WriteText( );
342 m_pSerializer
->endElementNS( XML_w
, XML_txbxContent
);
343 m_pSerializer
->endElementNS( XML_v
, XML_textbox
);
345 if (m_pFlyWrapAttrList
)
347 XFastAttributeListRef
xFlyWrapAttrList(m_pFlyWrapAttrList
);
348 m_pFlyWrapAttrList
= NULL
;
349 m_pSerializer
->singleElementNS(XML_w10
, XML_wrap
, xFlyWrapAttrList
);
352 m_pSerializer
->endElementNS( XML_v
, XML_rect
);
353 m_pSerializer
->endElementNS( XML_w
, XML_pict
);
354 m_pSerializer
->endElementNS( XML_w
, XML_r
);
356 m_rExport
.RestoreData();
358 m_rExport
.mpParentFrame
= NULL
;
361 m_pSerializer
->endElementNS( XML_w
, XML_p
);
363 // Check for end of cell, rows, tables here
364 FinishTableRowCell( pTextNodeInfoInner
);
366 m_bParagraphOpened
= false;
370 void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner
, bool bForceEmptyParagraph
)
374 // Where are we in the table
375 sal_uInt32 nRow
= pInner
->getRow( );
377 const SwTable
*pTable
= pInner
->getTable( );
378 const SwTableLines
& rLines
= pTable
->GetTabLines( );
379 sal_uInt16 nLinesCount
= rLines
.size( );
381 // msoffice seems to have an internal limitation of 63 columns for tables
382 // and refuses to load .docx with more, even though the spec seems to allow that;
383 // so simply if there are more columns, don't close the last one msoffice will handle
384 // and merge the contents of the remaining ones into it (since we don't close the cell
385 // here, following ones will not be opened)
386 bool limitWorkaround
= ( pInner
->getCell() >= 62 && !pInner
->isEndOfLine());
388 if ( pInner
->isEndOfCell() && !limitWorkaround
)
390 if ( bForceEmptyParagraph
)
391 m_pSerializer
->singleElementNS( XML_w
, XML_p
, FSEND
);
396 // This is a line end
397 if ( pInner
->isEndOfLine() )
400 // This is the end of the table
401 if ( pInner
->isEndOfLine( ) && ( nRow
+ 1 ) == nLinesCount
)
406 void DocxAttributeOutput::EmptyParagraph()
408 m_pSerializer
->singleElementNS( XML_w
, XML_p
, FSEND
);
411 void DocxAttributeOutput::StartParagraphProperties( const SwTxtNode
& rNode
)
413 // output page/section breaks
414 // Writer can have them at the beginning of a paragraph, or at the end, but
415 // in docx, we have to output them in the paragraph properties of the last
416 // paragraph in a section. To get it right, we have to switch to the next
417 // paragraph, and detect the section breaks there.
418 SwNodeIndex
aNextIndex( rNode
, 1 );
419 if ( aNextIndex
.GetNode().IsTxtNode() )
421 const SwTxtNode
* pTxtNode
= static_cast< SwTxtNode
* >( &aNextIndex
.GetNode() );
422 // If next node has no string - it is an empty node, so no need to output the section break
423 if (!pTxtNode
->GetTxt().isEmpty())
424 m_rExport
.OutputSectionBreaks( pTxtNode
->GetpSwAttrSet(), *pTxtNode
);
426 else if ( aNextIndex
.GetNode().IsTableNode() )
428 const SwTableNode
* pTableNode
= static_cast< SwTableNode
* >( &aNextIndex
.GetNode() );
429 const SwFrmFmt
*pFmt
= pTableNode
->GetTable().GetFrmFmt();
430 m_rExport
.OutputSectionBreaks( &(pFmt
->GetAttrSet()), *pTableNode
);
433 m_pSerializer
->mark( );
435 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
437 // and output the section break now (if it appeared)
438 if ( m_pSectionInfo
)
440 m_rExport
.SectionProperties( *m_pSectionInfo
);
441 m_pSectionInfo
.reset();
444 InitCollectedParagraphProperties();
447 void DocxAttributeOutput::InitCollectedParagraphProperties()
449 m_pParagraphSpacingAttrList
= NULL
;
451 // Write the elements in the spec order
452 static const sal_Int32 aOrder
[] =
454 FSNS( XML_w
, XML_pStyle
),
455 FSNS( XML_w
, XML_keepNext
),
456 FSNS( XML_w
, XML_keepLines
),
457 FSNS( XML_w
, XML_pageBreakBefore
),
458 FSNS( XML_w
, XML_framePr
),
459 FSNS( XML_w
, XML_widowControl
),
460 FSNS( XML_w
, XML_numPr
),
461 FSNS( XML_w
, XML_suppressLineNumbers
),
462 FSNS( XML_w
, XML_pBdr
),
463 FSNS( XML_w
, XML_shd
),
464 FSNS( XML_w
, XML_tabs
),
465 FSNS( XML_w
, XML_suppressAutoHyphens
),
466 FSNS( XML_w
, XML_kinsoku
),
467 FSNS( XML_w
, XML_wordWrap
),
468 FSNS( XML_w
, XML_overflowPunct
),
469 FSNS( XML_w
, XML_topLinePunct
),
470 FSNS( XML_w
, XML_autoSpaceDE
),
471 FSNS( XML_w
, XML_autoSpaceDN
),
472 FSNS( XML_w
, XML_bidi
),
473 FSNS( XML_w
, XML_adjustRightInd
),
474 FSNS( XML_w
, XML_snapToGrid
),
475 FSNS( XML_w
, XML_spacing
),
476 FSNS( XML_w
, XML_ind
),
477 FSNS( XML_w
, XML_contextualSpacing
),
478 FSNS( XML_w
, XML_mirrorIndents
),
479 FSNS( XML_w
, XML_suppressOverlap
),
480 FSNS( XML_w
, XML_jc
),
481 FSNS( XML_w
, XML_textDirection
),
482 FSNS( XML_w
, XML_textAlignment
),
483 FSNS( XML_w
, XML_textboxTightWrap
),
484 FSNS( XML_w
, XML_outlineLvl
),
485 FSNS( XML_w
, XML_divId
),
486 FSNS( XML_w
, XML_cnfStyle
),
487 FSNS( XML_w
, XML_rPr
),
488 FSNS( XML_w
, XML_sectPr
),
489 FSNS( XML_w
, XML_pPrChange
)
492 // postpone the output so that we can later [in EndParagraphProperties()]
493 // prepend the properties before the run
494 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
495 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
496 for ( sal_Int32 i
= 0; i
< len
; i
++ )
497 aSeqOrder
[i
] = aOrder
[i
];
499 m_pSerializer
->mark( aSeqOrder
);
502 void DocxAttributeOutput::WriteCollectedParagraphProperties()
504 if ( m_pFlyAttrList
)
506 XFastAttributeListRef
xAttrList( m_pFlyAttrList
);
507 m_pFlyAttrList
= NULL
;
509 m_pSerializer
->singleElementNS( XML_w
, XML_framePr
, xAttrList
);
512 if ( m_pParagraphSpacingAttrList
)
514 XFastAttributeListRef
xAttrList( m_pParagraphSpacingAttrList
);
515 m_pParagraphSpacingAttrList
= NULL
;
517 m_pSerializer
->singleElementNS( XML_w
, XML_spacing
, xAttrList
);
520 // Merge the marks for the ordered elements
521 m_pSerializer
->mergeTopMarks( );
524 void DocxAttributeOutput::EndParagraphProperties()
526 WriteCollectedParagraphProperties();
528 // insert copy of <rPr>
529 m_pSerializer
->copyTopMarkPop();
531 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
533 if ( m_nColBreakStatus
== COLBRK_WRITE
)
535 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
536 m_pSerializer
->singleElementNS( XML_w
, XML_br
,
537 FSNS( XML_w
, XML_type
), "column", FSEND
);
538 m_pSerializer
->endElementNS( XML_w
, XML_r
);
540 m_nColBreakStatus
= COLBRK_NONE
;
543 // merge the properties _before_ the run (strictly speaking, just
544 // after the start of the paragraph)
545 m_pSerializer
->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND
);
548 void DocxAttributeOutput::StartRun( const SwRedlineData
* pRedlineData
, bool /*bSingleEmptyRun*/ )
550 // Don't start redline data here, possibly there is a hyperlink later, and
551 // that has to be started first.
552 m_pRedlineData
= pRedlineData
;
554 // postpone the output of the start of a run (there are elements that need
555 // to be written before the start of the run, but we learn which they are
556 // _inside_ of the run)
557 m_pSerializer
->mark(); // let's call it "postponed run start"
559 // postpone the output of the text (we get it before the run properties,
560 // but must write it after them)
561 m_pSerializer
->mark(); // let's call it "postponed text"
564 void DocxAttributeOutput::EndRun()
566 // Write field starts
567 for ( std::vector
<FieldInfos
>::iterator pIt
= m_Fields
.begin(); pIt
!= m_Fields
.end(); )
569 // Add the fields starts for all but hyperlinks and TOCs
570 if ( pIt
->bOpen
&& pIt
->pField
)
572 StartField_Impl( *pIt
);
574 // Remove the field from the stack if only the start has to be written
575 // Unknown fields sould be removed too
576 if ( !pIt
->bClose
|| ( pIt
->eType
== ww::eUNKNOWN
) )
580 pIt
= m_Fields
.erase( pIt
);
587 // write the run properties + the text, already in the correct order
588 m_pSerializer
->mergeTopMarks(); // merges with "postponed text", see above
590 // level down, to be able to prepend the actual run start attribute (just
591 // before "postponed run start")
592 m_pSerializer
->mark(); // let's call it "actual run start"
594 if ( m_closeHyperlinkInPreviousRun
)
596 if ( m_startedHyperlink
)
598 m_pSerializer
->endElementNS( XML_w
, XML_hyperlink
);
599 m_startedHyperlink
= false;
601 m_closeHyperlinkInPreviousRun
= false;
604 // Write the hyperlink and toc fields starts
605 for ( std::vector
<FieldInfos
>::iterator pIt
= m_Fields
.begin(); pIt
!= m_Fields
.end(); )
607 // Add the fields starts for hyperlinks, TOCs and index marks
608 if ( pIt
->bOpen
&& !pIt
->pField
)
610 StartField_Impl( *pIt
, sal_True
);
612 // Remove the field if no end needs to be written
613 if ( !pIt
->bClose
) {
616 pIt
= m_Fields
.erase( pIt
);
623 // Start the hyperlink after the fields separators or we would generate invalid file
624 if ( m_pHyperlinkAttrList
)
626 XFastAttributeListRef
xAttrList ( m_pHyperlinkAttrList
);
628 m_pSerializer
->startElementNS( XML_w
, XML_hyperlink
, xAttrList
);
629 m_pHyperlinkAttrList
= NULL
;
630 m_startedHyperlink
= true;
633 // if there is some redlining in the document, output it
637 WriteCommentRanges();
639 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
640 m_pSerializer
->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND
); // merges with "postponed run start", see above
642 // write the run start + the run content
643 m_pSerializer
->mergeTopMarks(); // merges the "actual run start"
645 // append the actual run end
646 m_pSerializer
->endElementNS( XML_w
, XML_r
);
648 WritePostponedMath();
649 WritePendingPlaceholder();
651 // if there is some redlining in the document, output it
654 if ( m_closeHyperlinkInThisRun
)
656 if ( m_startedHyperlink
)
658 m_pSerializer
->endElementNS( XML_w
, XML_hyperlink
);
659 m_startedHyperlink
= false;
661 m_closeHyperlinkInThisRun
= false;
664 while ( m_Fields
.begin() != m_Fields
.end() )
666 EndField_Impl( m_Fields
.front( ) );
667 if (m_Fields
.front().pField
)
668 delete m_Fields
.front().pField
;
669 m_Fields
.erase( m_Fields
.begin( ) );
673 void DocxAttributeOutput::WriteCommentRanges()
677 m_bPostitStart
= false;
678 OString idstr
= OString::valueOf( sal_Int32( m_postitFieldsMaxId
));
679 m_pSerializer
->singleElementNS( XML_w
, XML_commentRangeStart
, FSNS( XML_w
, XML_id
), idstr
.getStr(), FSEND
);
683 m_bPostitEnd
= false;
684 OString idstr
= OString::valueOf( sal_Int32( m_postitFieldsMaxId
));
685 m_pSerializer
->singleElementNS( XML_w
, XML_commentRangeEnd
, FSNS( XML_w
, XML_id
), idstr
.getStr(), FSEND
);
689 void DocxAttributeOutput::DoWriteBookmarks()
691 // Write the start bookmarks
692 for ( std::vector
< OString
>::const_iterator it
= m_rMarksStart
.begin(), end
= m_rMarksStart
.end();
695 const OString
& rName
= *it
;
697 // Output the bookmark
698 sal_uInt16 nId
= m_nNextMarkId
++;
699 m_rOpenedMarksIds
[rName
] = nId
;
700 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkStart
,
701 FSNS( XML_w
, XML_id
), OString::valueOf( sal_Int32( nId
) ).getStr( ),
702 FSNS( XML_w
, XML_name
), rName
.getStr(),
704 m_sLastOpenedMark
= rName
;
706 m_rMarksStart
.clear();
708 // export the end bookmarks
709 for ( std::vector
< OString
>::const_iterator it
= m_rMarksEnd
.begin(), end
= m_rMarksEnd
.end();
712 const OString
& rName
= *it
;
714 // Get the id of the bookmark
715 std::map
< OString
, sal_uInt16
>::iterator pPos
= m_rOpenedMarksIds
.find( rName
);
716 if ( pPos
!= m_rOpenedMarksIds
.end( ) )
718 sal_uInt16 nId
= ( *pPos
).second
;
719 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkEnd
,
720 FSNS( XML_w
, XML_id
), OString::valueOf( sal_Int32( nId
) ).getStr( ),
722 m_rOpenedMarksIds
.erase( rName
);
728 void DocxAttributeOutput::WriteFFData( const FieldInfos
& rInfos
)
730 const ::sw::mark::IFieldmark
& rFieldmark
= *rInfos
.pFieldmark
;
731 if ( rInfos
.eType
== ww::eFORMDROPDOWN
)
733 uno::Sequence
< OUString
> vListEntries
;
734 OUString sName
, sHelp
, sToolTip
, sSelected
;
736 FieldMarkParamsHelper
params( rFieldmark
);
737 params
.extractParam( ODF_FORMDROPDOWN_LISTENTRY
, vListEntries
);
738 sName
= params
.getName();
739 sal_Int32 nSelectedIndex
= 0;
741 if ( params
.extractParam( ODF_FORMDROPDOWN_RESULT
, nSelectedIndex
) )
743 if (nSelectedIndex
< vListEntries
.getLength() )
744 sSelected
= vListEntries
[ nSelectedIndex
];
747 GetExport().DoComboBox( sName
, sHelp
, sToolTip
, sSelected
, vListEntries
);
749 else if ( rInfos
.eType
== ww::eFORMCHECKBOX
)
752 bool bChecked
= false;
754 FieldMarkParamsHelper
params( rFieldmark
);
755 params
.extractParam( ODF_FORMCHECKBOX_NAME
, sName
);
757 const sw::mark::ICheckboxFieldmark
* pCheckboxFm
= dynamic_cast<const sw::mark::ICheckboxFieldmark
*>(&rFieldmark
);
758 if ( pCheckboxFm
&& pCheckboxFm
->IsChecked() )
761 FFDataWriterHelper
ffdataOut( m_pSerializer
);
762 ffdataOut
.WriteFormCheckbox( sName
, OUString(), bChecked
);
764 else if ( rInfos
.eType
== ww::eFORMTEXT
)
766 FieldMarkParamsHelper
params( rFieldmark
);
767 FFDataWriterHelper
ffdataOut( m_pSerializer
);
768 ffdataOut
.WriteFormText( params
.getName(), OUString() );
772 void DocxAttributeOutput::StartField_Impl( FieldInfos
& rInfos
, bool bWriteRun
)
774 if ( rInfos
.pField
&& rInfos
.eType
== ww::eUNKNOWN
)
776 // Expand unsupported fields
777 RunText( rInfos
.pField
->GetFieldName() );
779 else if ( rInfos
.eType
!= ww::eNONE
) // HYPERLINK fields are just commands
782 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
784 if ( rInfos
.eType
== ww::eFORMDROPDOWN
)
786 m_pSerializer
->startElementNS( XML_w
, XML_fldChar
,
787 FSNS( XML_w
, XML_fldCharType
), "begin",
789 if ( rInfos
.pFieldmark
&& !rInfos
.pField
)
790 WriteFFData( rInfos
);
793 const SwDropDownField
& rFld2
= *(SwDropDownField
*)rInfos
.pField
;
794 uno::Sequence
<OUString
> aItems
=
795 rFld2
.GetItemSequence();
796 GetExport().DoComboBox(rFld2
.GetName(),
799 rFld2
.GetSelectedItem(), aItems
);
801 m_pSerializer
->endElementNS( XML_w
, XML_fldChar
);
804 m_pSerializer
->endElementNS( XML_w
, XML_r
);
805 if ( !rInfos
.pField
)
806 CmdField_Impl( rInfos
);
811 // Write the field start
812 m_pSerializer
->startElementNS( XML_w
, XML_fldChar
,
813 FSNS( XML_w
, XML_fldCharType
), "begin",
816 if ( rInfos
.pFieldmark
)
817 WriteFFData( rInfos
);
819 m_pSerializer
->endElementNS( XML_w
, XML_fldChar
);
822 m_pSerializer
->endElementNS( XML_w
, XML_r
);
824 // The hyperlinks fields can't be expanded: the value is
825 // normally in the text run
826 if ( !rInfos
.pField
)
827 CmdField_Impl( rInfos
);
832 void DocxAttributeOutput::DoWriteCmd( String
& rCmd
)
834 OUString sCmd
= OUString(rCmd
).trim();
835 if (sCmd
.startsWith("SEQ"))
837 OUString sSeqName
= msfilter::util::findQuotedText(sCmd
, "SEQ ", '\\').trim();
838 m_aSeqMarksNames
[sSeqName
].push_back(m_sLastOpenedMark
);
840 // Write the Field command
841 m_pSerializer
->startElementNS( XML_w
, XML_instrText
, FSEND
);
842 m_pSerializer
->writeEscaped( OUString( rCmd
) );
843 m_pSerializer
->endElementNS( XML_w
, XML_instrText
);
847 void DocxAttributeOutput::CmdField_Impl( FieldInfos
& rInfos
)
849 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
850 xub_StrLen nNbToken
= comphelper::string::getTokenCount(rInfos
.sCmd
, '\t');
852 for ( xub_StrLen i
= 0; i
< nNbToken
; i
++ )
854 String sToken
= rInfos
.sCmd
.GetToken( i
, '\t' );
855 if ( rInfos
.eType
== ww::eCREATEDATE
856 || rInfos
.eType
== ww::eSAVEDATE
857 || rInfos
.eType
== ww::ePRINTDATE
858 || rInfos
.eType
== ww::eDATE
859 || rInfos
.eType
== ww::eTIME
)
861 sToken
.SearchAndReplaceAll( String( "NNNN" ), String( "dddd" ) );
862 sToken
.SearchAndReplaceAll( String( "NN" ), String( "ddd" ) );
864 // Write the Field command
865 DoWriteCmd( sToken
);
867 // Replace tabs by </instrText><tab/><instrText>
868 if ( i
< ( nNbToken
- 1 ) )
869 RunText( OUString( "\t" ) );
872 m_pSerializer
->endElementNS( XML_w
, XML_r
);
874 // Write the Field separator
875 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
876 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
877 FSNS( XML_w
, XML_fldCharType
), "separate",
879 m_pSerializer
->endElementNS( XML_w
, XML_r
);
882 void DocxAttributeOutput::EndField_Impl( FieldInfos
& rInfos
)
884 // The command has to be written before for the hyperlinks
887 CmdField_Impl( rInfos
);
890 // Write the bookmark start if any
891 OUString
aBkmName( m_sFieldBkm
);
892 if ( !aBkmName
.isEmpty() )
894 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkStart
,
895 FSNS( XML_w
, XML_id
), OString::valueOf( sal_Int32( m_nNextMarkId
) ).getStr( ),
896 FSNS( XML_w
, XML_name
), OUStringToOString( aBkmName
, RTL_TEXTENCODING_UTF8
).getStr( ),
900 if (rInfos
.pField
) // For hyperlinks and TOX
902 // Write the Field latest value
903 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
905 String
sExpand( rInfos
.pField
->ExpandField( true ) );
906 // newlines embedded in fields are 0x0B in MSO and 0x0A for us
907 sExpand
.SearchAndReplaceAll( 0x0A, 0x0B );
910 m_pSerializer
->endElementNS( XML_w
, XML_r
);
913 // Write the bookmark end if any
914 if ( !aBkmName
.isEmpty() )
916 m_pSerializer
->singleElementNS( XML_w
, XML_bookmarkEnd
,
917 FSNS( XML_w
, XML_id
), OString::valueOf( sal_Int32( m_nNextMarkId
) ).getStr( ),
923 // Write the Field end
926 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
927 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
928 FSNS( XML_w
, XML_fldCharType
), "end",
930 m_pSerializer
->endElementNS( XML_w
, XML_r
);
932 // Write the ref field if a bookmark had to be set and the field
936 sal_uInt16 nSubType
= rInfos
.pField
->GetSubType( );
937 bool bIsSetField
= rInfos
.pField
->GetTyp( )->Which( ) == RES_SETEXPFLD
;
938 bool bShowRef
= ( !bIsSetField
|| ( nSubType
& nsSwExtendedSubType::SUB_INVISIBLE
) ) ? false : true;
940 if ( ( m_sFieldBkm
.Len( ) > 0 ) && bShowRef
)
942 // Write the field beginning
943 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
944 m_pSerializer
->singleElementNS( XML_w
, XML_fldChar
,
945 FSNS( XML_w
, XML_fldCharType
), "begin",
947 m_pSerializer
->endElementNS( XML_w
, XML_r
);
949 rInfos
.sCmd
= FieldString( ww::eREF
);
950 rInfos
.sCmd
.AppendAscii( "\"" );
951 rInfos
.sCmd
+= m_sFieldBkm
;
952 rInfos
.sCmd
.AppendAscii( "\" " );
954 // Clean the field bookmark data to avoid infinite loop
955 m_sFieldBkm
= String( );
957 // Write the end of the field
958 EndField_Impl( rInfos
);
963 void DocxAttributeOutput::StartRunProperties()
965 // postpone the output so that we can later [in EndRunProperties()]
966 // prepend the properties before the text
967 m_pSerializer
->mark();
969 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
971 InitCollectedRunProperties();
973 OSL_ASSERT( m_postponedGraphic
== NULL
);
974 m_postponedGraphic
= new std::list
< PostponedGraphic
>;
977 void DocxAttributeOutput::InitCollectedRunProperties()
979 m_pFontsAttrList
= NULL
;
980 m_pEastAsianLayoutAttrList
= NULL
;
981 m_pCharLangAttrList
= NULL
;
983 // Write the elements in the spec order
984 static const sal_Int32 aOrder
[] =
986 FSNS( XML_w
, XML_rStyle
),
987 FSNS( XML_w
, XML_rFonts
),
988 FSNS( XML_w
, XML_b
),
989 FSNS( XML_w
, XML_bCs
),
990 FSNS( XML_w
, XML_i
),
991 FSNS( XML_w
, XML_iCs
),
992 FSNS( XML_w
, XML_caps
),
993 FSNS( XML_w
, XML_smallCaps
),
994 FSNS( XML_w
, XML_strike
),
995 FSNS( XML_w
, XML_dstrike
),
996 FSNS( XML_w
, XML_outline
),
997 FSNS( XML_w
, XML_shadow
),
998 FSNS( XML_w
, XML_emboss
),
999 FSNS( XML_w
, XML_imprint
),
1000 FSNS( XML_w
, XML_noProof
),
1001 FSNS( XML_w
, XML_snapToGrid
),
1002 FSNS( XML_w
, XML_vanish
),
1003 FSNS( XML_w
, XML_webHidden
),
1004 FSNS( XML_w
, XML_color
),
1005 FSNS( XML_w
, XML_spacing
),
1006 FSNS( XML_w
, XML_w
),
1007 FSNS( XML_w
, XML_kern
),
1008 FSNS( XML_w
, XML_position
),
1009 FSNS( XML_w
, XML_sz
),
1010 FSNS( XML_w
, XML_szCs
),
1011 FSNS( XML_w
, XML_highlight
),
1012 FSNS( XML_w
, XML_u
),
1013 FSNS( XML_w
, XML_effect
),
1014 FSNS( XML_w
, XML_bdr
),
1015 FSNS( XML_w
, XML_shd
),
1016 FSNS( XML_w
, XML_fitText
),
1017 FSNS( XML_w
, XML_vertAlign
),
1018 FSNS( XML_w
, XML_rtl
),
1019 FSNS( XML_w
, XML_cs
),
1020 FSNS( XML_w
, XML_em
),
1021 FSNS( XML_w
, XML_lang
),
1022 FSNS( XML_w
, XML_eastAsianLayout
),
1023 FSNS( XML_w
, XML_specVanish
),
1024 FSNS( XML_w
, XML_oMath
),
1025 FSNS( XML_w
, XML_rPrChange
)
1028 // postpone the output so that we can later [in EndParagraphProperties()]
1029 // prepend the properties before the run
1030 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
1031 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
1032 for ( sal_Int32 i
= 0; i
< len
; i
++ )
1033 aSeqOrder
[i
] = aOrder
[i
];
1035 m_pSerializer
->mark( aSeqOrder
);
1039 void DocxAttributeOutput::WriteCollectedRunProperties()
1041 // Write all differed properties
1042 if ( m_pFontsAttrList
)
1044 XFastAttributeListRef
xAttrList( m_pFontsAttrList
);
1045 m_pFontsAttrList
= NULL
;
1047 m_pSerializer
->singleElementNS( XML_w
, XML_rFonts
, xAttrList
);
1050 if ( m_pEastAsianLayoutAttrList
)
1052 XFastAttributeListRef
xAttrList( m_pEastAsianLayoutAttrList
);
1053 m_pEastAsianLayoutAttrList
= NULL
;
1055 m_pSerializer
->singleElementNS( XML_w
, XML_eastAsianLayout
, xAttrList
);
1058 if ( m_pCharLangAttrList
)
1060 XFastAttributeListRef
xAttrList( m_pCharLangAttrList
);
1061 m_pCharLangAttrList
= NULL
;
1063 m_pSerializer
->singleElementNS( XML_w
, XML_lang
, xAttrList
);
1066 // Merge the marks for the ordered elements
1067 m_pSerializer
->mergeTopMarks();
1070 void DocxAttributeOutput::EndRunProperties( const SwRedlineData
* /*pRedlineData*/ )
1072 WriteCollectedRunProperties();
1074 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
1076 // Clone <rPr>...</rPr> for later re-use, in pPr
1077 m_pSerializer
->copyTopMarkPush();
1079 // write footnotes/endnotes if we have any
1080 FootnoteEndnoteReference();
1082 WritePostponedGraphic();
1084 // merge the properties _before_ the run text (strictly speaking, just
1085 // after the start of the run)
1086 m_pSerializer
->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND
);
1089 void DocxAttributeOutput::WritePostponedGraphic()
1091 for( std::list
< PostponedGraphic
>::const_iterator it
= m_postponedGraphic
->begin();
1092 it
!= m_postponedGraphic
->end();
1094 FlyFrameGraphic( it
->grfNode
, it
->size
);
1095 delete m_postponedGraphic
;
1096 m_postponedGraphic
= NULL
;
1099 void DocxAttributeOutput::FootnoteEndnoteRefTag()
1101 if( m_footnoteEndnoteRefTag
== 0 )
1103 m_pSerializer
->singleElementNS( XML_w
, m_footnoteEndnoteRefTag
, FSEND
);
1104 m_footnoteEndnoteRefTag
= 0;
1107 /** Output sal_Unicode* as a run text (<t>the text</t>).
1109 When bMove is true, update rBegin to point _after_ the end of the text +
1110 1, meaning that it skips one character after the text. This is to make
1111 the switch in DocxAttributeOutput::RunText() nicer ;-)
1113 static void impl_WriteRunText( FSHelperPtr pSerializer
, sal_Int32 nTextToken
,
1114 const sal_Unicode
* &rBegin
, const sal_Unicode
* pEnd
, bool bMove
= true )
1116 const sal_Unicode
*pBegin
= rBegin
;
1118 // skip one character after the end
1122 if ( pBegin
>= pEnd
)
1123 return; // we want to write at least one character
1125 // we have to add 'preserve' when starting/ending with space
1126 if ( *pBegin
== sal_Unicode( ' ' ) || *( pEnd
- 1 ) == sal_Unicode( ' ' ) )
1128 pSerializer
->startElementNS( XML_w
, nTextToken
, FSNS( XML_xml
, XML_space
), "preserve", FSEND
);
1131 pSerializer
->startElementNS( XML_w
, nTextToken
, FSEND
);
1133 pSerializer
->writeEscaped( OUString( pBegin
, pEnd
- pBegin
) );
1135 pSerializer
->endElementNS( XML_w
, nTextToken
);
1138 void DocxAttributeOutput::RunText( const String
& rText
, rtl_TextEncoding
/*eCharSet*/ )
1140 if( m_closeHyperlinkInThisRun
)
1142 m_closeHyperlinkInPreviousRun
= true;
1143 m_closeHyperlinkInThisRun
= false;
1145 OUString
aText( rText
);
1147 // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
1148 const sal_Unicode
*pBegin
= aText
.getStr();
1149 const sal_Unicode
*pEnd
= pBegin
+ aText
.getLength();
1151 // the text run is usually XML_t, with the exception of the deleted text
1152 sal_Int32 nTextToken
= XML_t
;
1153 if ( m_pRedlineData
&& m_pRedlineData
->GetType() == nsRedlineType_t::REDLINE_DELETE
)
1154 nTextToken
= XML_delText
;
1156 for ( const sal_Unicode
*pIt
= pBegin
; pIt
< pEnd
; ++pIt
)
1161 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
1162 m_pSerializer
->singleElementNS( XML_w
, XML_tab
, FSEND
);
1164 case 0x0b: // line break
1165 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
1166 m_pSerializer
->singleElementNS( XML_w
, XML_br
, FSEND
);
1168 case 0x1E: //non-breaking hyphen
1169 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
1170 m_pSerializer
->singleElementNS( XML_w
, XML_noBreakHyphen
, FSEND
);
1172 case 0x1F: //soft (on demand) hyphen
1173 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
1174 m_pSerializer
->singleElementNS( XML_w
, XML_softHyphen
, FSEND
);
1177 if ( *pIt
< 0x0020 ) // filter out the control codes
1179 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pIt
);
1180 OSL_TRACE( "Ignored control code %x in a text run.", *pIt
);
1186 impl_WriteRunText( m_pSerializer
, nTextToken
, pBegin
, pEnd
, false );
1189 void DocxAttributeOutput::RawText( const String
& /*rText*/, bool /*bForceUnicode*/, rtl_TextEncoding
/*eCharSet*/ )
1191 OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )" );
1194 void DocxAttributeOutput::StartRuby( const SwTxtNode
& rNode
, xub_StrLen nPos
, const SwFmtRuby
& rRuby
)
1196 OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )" );
1197 m_pSerializer
->startElementNS( XML_w
, XML_ruby
, FSEND
);
1198 m_pSerializer
->startElementNS( XML_w
, XML_rubyPr
, FSEND
);
1203 lang::Locale
aLocale( SwBreakIt::Get()->GetLocale(
1204 rNode
.GetLang( nPos
) ) );
1205 OUString
sLang( aLocale
.Language
);
1206 if ( !aLocale
.Country
.isEmpty() )
1207 sLang
+= "-" + aLocale
.Country
;
1208 m_pSerializer
->singleElementNS( XML_w
, XML_lid
,
1209 FSNS( XML_w
, XML_val
),
1210 OUStringToOString( sLang
, RTL_TEXTENCODING_UTF8
).getStr( ), FSEND
);
1212 OString
sAlign ( "center" );
1213 switch ( rRuby
.GetAdjustment( ) )
1216 sAlign
= OString( "left" );
1219 // Defaults to center
1222 sAlign
= OString( "right" );
1225 sAlign
= OString( "distributeLetter" );
1228 sAlign
= OString( "distributeSpace" );
1233 m_pSerializer
->singleElementNS( XML_w
, XML_rubyAlign
,
1234 FSNS( XML_w
, XML_val
), sAlign
.getStr(), FSEND
);
1235 m_pSerializer
->endElementNS( XML_w
, XML_rubyPr
);
1237 m_pSerializer
->startElementNS( XML_w
, XML_rt
, FSEND
);
1239 StartRunProperties( );
1240 SwWW8AttrIter
aAttrIt( m_rExport
, rNode
);
1241 aAttrIt
.OutAttr( nPos
, true );
1242 sal_uInt16 nStyle
= m_rExport
.GetId( *rRuby
.GetTxtRuby()->GetCharFmt() );
1243 OString
aStyleId( "style" );
1244 aStyleId
+= OString::valueOf( sal_Int32( nStyle
) );
1245 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
,
1246 FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
1247 EndRunProperties( NULL
);
1248 RunText( rRuby
.GetText( ) );
1250 m_pSerializer
->endElementNS( XML_w
, XML_rt
);
1252 m_pSerializer
->startElementNS( XML_w
, XML_rubyBase
, FSEND
);
1256 void DocxAttributeOutput::EndRuby()
1258 OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()" );
1260 m_pSerializer
->endElementNS( XML_w
, XML_rubyBase
);
1261 m_pSerializer
->endElementNS( XML_w
, XML_ruby
);
1264 bool DocxAttributeOutput::AnalyzeURL( const String
& rUrl
, const String
& rTarget
, String
* pLinkURL
, String
* pMark
)
1266 bool bBookMarkOnly
= AttributeOutputBase::AnalyzeURL( rUrl
, rTarget
, pLinkURL
, pMark
);
1268 String sURL
= *pLinkURL
;
1269 String sMark
= *pMark
;
1271 bool bOutputField
= sMark
.Len();
1275 if ( bBookMarkOnly
)
1276 sURL
= FieldString( ww::eHYPERLINK
);
1279 String
sFld( FieldString( ww::eHYPERLINK
) );
1280 sFld
.AppendAscii( "\"" );
1281 sURL
.Insert( sFld
, 0 );
1286 ( ( sURL
.AppendAscii( " \\l \"" ) ) += sMark
) += '\"';
1288 if ( rTarget
.Len() )
1289 ( sURL
.AppendAscii( " \\n " ) ) += rTarget
;
1295 return bBookMarkOnly
;
1298 bool DocxAttributeOutput::StartURL( const String
& rUrl
, const String
& rTarget
)
1303 bool bBookmarkOnly
= AnalyzeURL( rUrl
, rTarget
, &sUrl
, &sMark
);
1305 if ( sMark
.Len() && !bBookmarkOnly
)
1307 m_rExport
.OutputField( NULL
, ww::eHYPERLINK
, sUrl
);
1311 // Output a hyperlink XML element
1312 m_pHyperlinkAttrList
= m_pSerializer
->createAttrList();
1314 if ( !bBookmarkOnly
)
1316 OUString
osUrl( sUrl
);
1318 OString sId
= OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer
->getOutputStream(),
1319 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
1320 osUrl
, true ), RTL_TEXTENCODING_UTF8
);
1322 m_pHyperlinkAttrList
->add( FSNS( XML_r
, XML_id
), sId
.getStr());
1326 // Is this a link to a sequence? Then try to replace that with a
1327 // normal bookmark, as Word won't understand our special
1328 // <seqname>!<index>|sequence syntax.
1329 OUString
aMark(sMark
);
1330 if (aMark
.endsWith("|sequence"))
1332 sal_Int32 nPos
= aMark
.indexOf('!');
1335 // Extract <seqname>, the field instruction text has the name quoted.
1336 OUString aSequenceName
= OUString('"') + aMark
.copy(0, nPos
) + OUString('"');
1338 sal_uInt32 nIndex
= aMark
.copy(nPos
+ 1, aMark
.getLength() - nPos
- sizeof("|sequence")).toInt32();
1339 std::map
<OUString
, std::vector
<OString
> >::iterator it
= m_aSeqMarksNames
.find(aSequenceName
);
1340 if (it
!= m_aSeqMarksNames
.end())
1342 std::vector
<OString
>& rNames
= it
->second
;
1343 if (rNames
.size() > nIndex
)
1344 // We know the bookmark name for this sequence and this index, do the replacement.
1345 sMark
= OStringToOUString(rNames
[nIndex
], RTL_TEXTENCODING_UTF8
);
1349 m_pHyperlinkAttrList
->add( FSNS( XML_w
, XML_anchor
),
1350 OUStringToOString( OUString( sMark
), RTL_TEXTENCODING_UTF8
).getStr( ) );
1353 OUString
sTarget( rTarget
);
1354 if ( !sTarget
.isEmpty() )
1356 OString soTarget
= OUStringToOString( sTarget
, RTL_TEXTENCODING_UTF8
);
1357 m_pHyperlinkAttrList
->add(FSNS( XML_w
, XML_tgtFrame
), soTarget
.getStr());
1364 bool DocxAttributeOutput::EndURL()
1366 m_closeHyperlinkInThisRun
= true;
1370 void DocxAttributeOutput::FieldVanish( const String
& rTxt
, ww::eField eType
)
1372 WriteField_Impl( NULL
, eType
, rTxt
, WRITEFIELD_ALL
);
1375 void DocxAttributeOutput::Redline( const SwRedlineData
* /*pRedline*/ )
1377 OSL_TRACE( "TODO DocxAttributeOutput::Redline( const SwRedlineData* pRedline )" );
1380 void DocxAttributeOutput::StartRedline()
1382 if ( !m_pRedlineData
)
1384 const SwRedlineData
* pRedlineData
= m_pRedlineData
;
1386 // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
1388 OString
aId( OString::valueOf( m_nRedlineId
++ ) );
1390 const String
&rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData
->GetAuthor() ) );
1391 OString
aAuthor( OUStringToOString( rAuthor
, RTL_TEXTENCODING_UTF8
) );
1393 OString
aDate( msfilter::util::DateTimeToOString( pRedlineData
->GetTimeStamp() ) );
1395 switch ( pRedlineData
->GetType() )
1397 case nsRedlineType_t::REDLINE_INSERT
:
1398 m_pSerializer
->startElementNS( XML_w
, XML_ins
,
1399 FSNS( XML_w
, XML_id
), aId
.getStr(),
1400 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
1401 FSNS( XML_w
, XML_date
), aDate
.getStr(),
1405 case nsRedlineType_t::REDLINE_DELETE
:
1406 m_pSerializer
->startElementNS( XML_w
, XML_del
,
1407 FSNS( XML_w
, XML_id
), aId
.getStr(),
1408 FSNS( XML_w
, XML_author
), aAuthor
.getStr(),
1409 FSNS( XML_w
, XML_date
), aDate
.getStr(),
1413 case nsRedlineType_t::REDLINE_FORMAT
:
1414 OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()" );
1420 void DocxAttributeOutput::EndRedline()
1422 if ( !m_pRedlineData
)
1425 switch ( m_pRedlineData
->GetType() )
1427 case nsRedlineType_t::REDLINE_INSERT
:
1428 m_pSerializer
->endElementNS( XML_w
, XML_ins
);
1431 case nsRedlineType_t::REDLINE_DELETE
:
1432 m_pSerializer
->endElementNS( XML_w
, XML_del
);
1435 case nsRedlineType_t::REDLINE_FORMAT
:
1436 OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()" );
1442 m_pRedlineData
= NULL
;
1445 void DocxAttributeOutput::FormatDrop( const SwTxtNode
& /*rNode*/, const SwFmtDrop
& /*rSwFmtDrop*/, sal_uInt16
/*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t
/*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t
)
1447 OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle )" );
1450 void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle
)
1452 OString
aStyleId( "style" );
1453 aStyleId
+= OString::valueOf( sal_Int32( nStyle
) );
1455 m_pSerializer
->singleElementNS( XML_w
, XML_pStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
1458 static void impl_borderLine( FSHelperPtr pSerializer
, sal_Int32 elementToken
, const SvxBorderLine
* pBorderLine
, sal_uInt16 nDist
)
1460 FastAttributeList
* pAttr
= pSerializer
->createAttrList();
1463 // Compute val attribute value
1466 // basicWideOutline, basicWideInline
1467 // OOXml also supports those types of borders, but we'll try to play with the first ones.
1468 // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
1469 // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
1470 const char* pVal
= "nil";
1471 if ( pBorderLine
&& !pBorderLine
->isEmpty( ) )
1473 switch (pBorderLine
->GetBorderLineStyle())
1475 case table::BorderLineStyle::SOLID
:
1476 pVal
= ( sal_Char
* )"single";
1478 case table::BorderLineStyle::DOTTED
:
1479 pVal
= ( sal_Char
* )"dotted";
1481 case table::BorderLineStyle::DASHED
:
1482 pVal
= ( sal_Char
* )"dashed";
1484 case table::BorderLineStyle::DOUBLE
:
1485 pVal
= ( sal_Char
* )"double";
1487 case table::BorderLineStyle::THINTHICK_SMALLGAP
:
1488 pVal
= ( sal_Char
* )"thinThickSmallGap";
1490 case table::BorderLineStyle::THINTHICK_MEDIUMGAP
:
1491 pVal
= ( sal_Char
* )"thinThickMediumGap";
1493 case table::BorderLineStyle::THINTHICK_LARGEGAP
:
1494 pVal
= ( sal_Char
* )"thinThickLargeGap";
1496 case table::BorderLineStyle::THICKTHIN_SMALLGAP
:
1497 pVal
= ( sal_Char
* )"thickThinSmallGap";
1499 case table::BorderLineStyle::THICKTHIN_MEDIUMGAP
:
1500 pVal
= ( sal_Char
* )"thickThinMediumGap";
1502 case table::BorderLineStyle::THICKTHIN_LARGEGAP
:
1503 pVal
= ( sal_Char
* )"thickThinLargeGap";
1505 case table::BorderLineStyle::EMBOSSED
:
1506 pVal
= ( sal_Char
* )"threeDEmboss";
1508 case table::BorderLineStyle::ENGRAVED
:
1509 pVal
= ( sal_Char
* )"threeDEngrave";
1511 case table::BorderLineStyle::OUTSET
:
1512 pVal
= ( sal_Char
* )"outset";
1514 case table::BorderLineStyle::INSET
:
1515 pVal
= ( sal_Char
* )"inset";
1517 case table::BorderLineStyle::FINE_DASHED
:
1518 pVal
= ( sal_Char
* )"dashSmallGap";
1520 case table::BorderLineStyle::NONE
:
1526 pAttr
->add( FSNS( XML_w
, XML_val
), OString( pVal
) );
1528 if ( pBorderLine
&& !pBorderLine
->isEmpty() )
1530 // Compute the sz attribute
1532 double const fConverted( ::editeng::ConvertBorderWidthToWord(
1533 pBorderLine
->GetBorderLineStyle(), pBorderLine
->GetWidth()));
1534 // The unit is the 8th of point
1535 sal_Int32 nWidth
= sal_Int32( fConverted
/ 2.5 );
1536 sal_uInt16 nMinWidth
= 2;
1537 sal_uInt16 nMaxWidth
= 96;
1539 if ( nWidth
> nMaxWidth
)
1541 else if ( nWidth
< nMinWidth
)
1544 pAttr
->add( FSNS( XML_w
, XML_sz
), OString::valueOf( sal_Int32( nWidth
) ) );
1546 // Get the distance (in pt)
1547 pAttr
->add( FSNS( XML_w
, XML_space
), OString::valueOf( sal_Int32( nDist
/ 20 ) ) );
1549 // Get the color code as an RRGGBB hex value
1550 OString
sColor( msfilter::util::ConvertColor( pBorderLine
->GetColor( ) ) );
1551 pAttr
->add( FSNS( XML_w
, XML_color
), sColor
);
1554 XFastAttributeListRef
xAttrs( pAttr
);
1555 pSerializer
->singleElementNS( XML_w
, elementToken
, xAttrs
);
1558 static void impl_pageBorders( FSHelperPtr pSerializer
, const SvxBoxItem
& rBox
, sal_Int32 tag
, bool bUseStartEnd
= false, bool bWriteTag
= true, const SvxBoxItem
* pDefaultBorders
= 0)
1560 static const sal_uInt16 aBorders
[] =
1562 BOX_LINE_TOP
, BOX_LINE_LEFT
, BOX_LINE_BOTTOM
, BOX_LINE_RIGHT
1565 const sal_Int32 aXmlElements
[] =
1568 bUseStartEnd
? XML_start
: XML_left
,
1570 bUseStartEnd
? XML_end
: XML_right
1572 bool tagWritten
= false;
1573 const sal_uInt16
* pBrd
= aBorders
;
1574 for( int i
= 0; i
< 4; ++i
, ++pBrd
)
1576 const SvxBorderLine
* pLn
= rBox
.GetLine( *pBrd
);
1578 if (!tagWritten
&& bWriteTag
) {
1579 pSerializer
->startElementNS( XML_w
, tag
, FSEND
);
1583 impl_borderLine( pSerializer
, aXmlElements
[i
], pLn
, 0 );
1585 // When exporting default borders, we need to export these 2 attr
1586 if ( pDefaultBorders
== 0 ) {
1588 impl_borderLine( pSerializer
, XML_insideH
, pLn
, 0 );
1590 impl_borderLine( pSerializer
, XML_insideV
, pLn
, 0 );
1593 if (tagWritten
&& bWriteTag
) {
1594 pSerializer
->endElementNS( XML_w
, tag
);
1598 static void impl_cellMargins( FSHelperPtr pSerializer
, const SvxBoxItem
& rBox
, sal_Int32 tag
, bool bUseStartEnd
= false, const SvxBoxItem
* pDefaultMargins
= 0)
1600 static const sal_uInt16 aBorders
[] =
1602 BOX_LINE_TOP
, BOX_LINE_LEFT
, BOX_LINE_BOTTOM
, BOX_LINE_RIGHT
1605 const sal_Int32 aXmlElements
[] =
1608 bUseStartEnd
? XML_start
: XML_left
,
1610 bUseStartEnd
? XML_end
: XML_right
1612 bool tagWritten
= false;
1613 const sal_uInt16
* pBrd
= aBorders
;
1614 for( int i
= 0; i
< 4; ++i
, ++pBrd
)
1616 sal_Int32 nDist
= sal_Int32( rBox
.GetDistance( *pBrd
) );
1618 if ( aBorders
[i
] == BOX_LINE_LEFT
) {
1619 // Office's cell margin is measured from the right of the border.
1620 // While LO's cell spacing is measured from the center of the border.
1621 // So we add half left-border width to tblIndent value
1622 const SvxBorderLine
* pLn
= rBox
.GetLine( *pBrd
);
1624 nDist
-= pLn
->GetWidth() * 0.5;
1627 if (pDefaultMargins
)
1629 // Skip output if cell margin == table default margin
1630 if (sal_Int32( pDefaultMargins
->GetDistance( *pBrd
) ) == nDist
)
1635 pSerializer
->startElementNS( XML_w
, tag
, FSEND
);
1638 pSerializer
->singleElementNS( XML_w
, aXmlElements
[i
],
1639 FSNS( XML_w
, XML_w
), OString::valueOf( nDist
).getStr( ),
1640 FSNS( XML_w
, XML_type
), "dxa",
1644 pSerializer
->endElementNS( XML_w
, tag
);
1648 void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1650 m_pSerializer
->startElementNS( XML_w
, XML_tcPr
, FSEND
);
1652 const SwTableBox
*pTblBox
= pTableTextNodeInfoInner
->getTableBox( );
1654 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
1656 // Cell prefered width
1657 SwTwips nWidth
= GetGridCols( pTableTextNodeInfoInner
)->at( pTableTextNodeInfoInner
->getCell() );
1658 if ( pTableTextNodeInfoInner
->getCell() )
1659 nWidth
= nWidth
- GetGridCols( pTableTextNodeInfoInner
)->at( pTableTextNodeInfoInner
->getCell() - 1 );
1660 m_pSerializer
->singleElementNS( XML_w
, XML_tcW
,
1661 FSNS( XML_w
, XML_w
), OString::valueOf( sal_Int32( nWidth
) ).getStr( ),
1662 FSNS( XML_w
, XML_type
), "dxa",
1666 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows( );
1667 SwWriteTableRow
*pRow
= aRows
[ pTableTextNodeInfoInner
->getRow( ) ];
1668 const SwWriteTableCell
*pCell
= &pRow
->GetCells( )[ pTableTextNodeInfoInner
->getCell( ) ];
1670 sal_uInt16 nColSpan
= pCell
->GetColSpan();
1672 m_pSerializer
->singleElementNS( XML_w
, XML_gridSpan
,
1673 FSNS( XML_w
, XML_val
), OString::valueOf( sal_Int32( nColSpan
) ).getStr(),
1677 long vSpan
= pTblBox
->getRowSpan( );
1680 m_pSerializer
->singleElementNS( XML_w
, XML_vMerge
,
1681 FSNS( XML_w
, XML_val
), "restart",
1684 else if ( vSpan
< 0 )
1686 m_pSerializer
->singleElementNS( XML_w
, XML_vMerge
,
1687 FSNS( XML_w
, XML_val
), "continue",
1691 const SvxBoxItem
& rBox
= pTblBox
->GetFrmFmt( )->GetBox( );
1692 const SvxBoxItem
& rDefaultBox
= (*tableFirstCells
.rbegin())->getTableBox( )->GetFrmFmt( )->GetBox( );
1695 impl_pageBorders( m_pSerializer
, rBox
, XML_tcBorders
, !bEcma
, true, &rDefaultBox
);
1698 TableBackgrounds( pTableTextNodeInfoInner
);
1702 impl_cellMargins( m_pSerializer
, rBox
, XML_tcMar
, !bEcma
, &rDefaultBox
);
1705 TableVerticalCell( pTableTextNodeInfoInner
);
1707 m_pSerializer
->endElementNS( XML_w
, XML_tcPr
);
1710 void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1712 sal_uInt32 nPageSize
= 0;
1713 bool bRelBoxSize
= false;
1715 // Create the SwWriteTable instance to use col spans (and maybe other infos)
1716 GetTablePageSize( pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
1718 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable( );
1719 const SwFrmFmt
*pFmt
= pTable
->GetFrmFmt( );
1720 SwTwips nTblSz
= pFmt
->GetFrmSize( ).GetWidth( );
1722 const SwHTMLTableLayout
*pLayout
= pTable
->GetHTMLTableLayout();
1723 if( pLayout
&& pLayout
->IsExportable() )
1724 m_pTableWrt
= new SwWriteTable( pLayout
);
1726 m_pTableWrt
= new SwWriteTable( pTable
->GetTabLines(), (sal_uInt16
)nPageSize
,
1727 (sal_uInt16
)nTblSz
, false);
1730 void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1732 m_pSerializer
->startElementNS( XML_w
, XML_tbl
, FSEND
);
1734 tableFirstCells
.push_back(pTableTextNodeInfoInner
);
1736 InitTableHelper( pTableTextNodeInfoInner
);
1737 TableDefinition( pTableTextNodeInfoInner
);
1740 void DocxAttributeOutput::EndTable()
1742 m_pSerializer
->endElementNS( XML_w
, XML_tbl
);
1744 if ( m_nTableDepth
> 0 )
1747 tableFirstCells
.pop_back();
1749 // We closed the table; if it is a nested table, the cell that contains it
1751 m_bTableCellOpen
= true;
1753 // Cleans the table helper
1754 delete m_pTableWrt
, m_pTableWrt
= NULL
;
1757 void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1759 m_pSerializer
->startElementNS( XML_w
, XML_tr
, FSEND
);
1761 // Output the row properties
1762 m_pSerializer
->startElementNS( XML_w
, XML_trPr
, FSEND
);
1764 // Header row: tblHeader
1765 const SwTable
*pTable
= pTableTextNodeInfoInner
->getTable( );
1766 if ( pTable
->GetRowsToRepeat( ) > pTableTextNodeInfoInner
->getRow( ) )
1767 m_pSerializer
->singleElementNS( XML_w
, XML_tblHeader
,
1768 FSNS( XML_w
, XML_val
), "true",
1771 TableHeight( pTableTextNodeInfoInner
);
1772 TableCanSplit( pTableTextNodeInfoInner
);
1774 m_pSerializer
->endElementNS( XML_w
, XML_trPr
);
1777 void DocxAttributeOutput::EndTableRow( )
1779 m_pSerializer
->endElementNS( XML_w
, XML_tr
);
1782 void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1785 InitTableHelper( pTableTextNodeInfoInner
);
1787 m_pSerializer
->startElementNS( XML_w
, XML_tc
, FSEND
);
1789 // Write the cell properties here
1790 TableCellProperties( pTableTextNodeInfoInner
);
1792 m_bTableCellOpen
= true;
1795 void DocxAttributeOutput::EndTableCell( )
1797 m_pSerializer
->endElementNS( XML_w
, XML_tc
);
1800 m_bTableCellOpen
= false;
1803 void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ )
1807 void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfo*/ )
1811 void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1813 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
1815 // Write the table properties
1816 m_pSerializer
->startElementNS( XML_w
, XML_tblPr
, FSEND
);
1818 static const sal_Int32 aOrder
[] =
1820 FSNS( XML_w
, XML_tblStyle
),
1821 FSNS( XML_w
, XML_tblpPr
),
1822 FSNS( XML_w
, XML_tblOverlap
),
1823 FSNS( XML_w
, XML_bidiVisual
),
1824 FSNS( XML_w
, XML_tblStyleRowBandSize
),
1825 FSNS( XML_w
, XML_tblStyleColBandSize
),
1826 FSNS( XML_w
, XML_tblW
),
1827 FSNS( XML_w
, XML_jc
),
1828 FSNS( XML_w
, XML_tblCellSpacing
),
1829 FSNS( XML_w
, XML_tblInd
),
1830 FSNS( XML_w
, XML_tblBorders
),
1831 FSNS( XML_w
, XML_shd
),
1832 FSNS( XML_w
, XML_tblLayout
),
1833 FSNS( XML_w
, XML_tblCellMar
),
1834 FSNS( XML_w
, XML_tblLook
),
1835 FSNS( XML_w
, XML_tblPrChange
)
1838 // postpone the output so that we can later []
1839 // prepend the properties before the run
1840 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
1841 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
1842 for ( sal_Int32 i
= 0; i
< len
; i
++ )
1843 aSeqOrder
[i
] = aOrder
[i
];
1845 m_pSerializer
->mark( aSeqOrder
);
1847 sal_uInt32 nPageSize
= 0;
1848 bool bRelBoxSize
= false;
1850 // Create the SwWriteTable instance to use col spans (and maybe other infos)
1851 GetTablePageSize( pTableTextNodeInfoInner
.get(), nPageSize
, bRelBoxSize
);
1853 // Output the table prefered width
1854 if ( nPageSize
!= 0 )
1855 m_pSerializer
->singleElementNS( XML_w
, XML_tblW
,
1856 FSNS( XML_w
, XML_w
), OString::valueOf( sal_Int32( nPageSize
) ).getStr( ),
1857 FSNS( XML_w
, XML_type
), "dxa",
1860 // Output the table alignement
1861 const SwTable
*pTable
= pTableTextNodeInfoInner
->getTable();
1862 SwFrmFmt
*pTblFmt
= pTable
->GetFrmFmt( );
1864 sal_Int32 nIndent
= 0;
1865 switch ( pTblFmt
->GetHoriOrient( ).GetHoriOrient( ) )
1867 case text::HoriOrientation::CENTER
:
1870 case text::HoriOrientation::RIGHT
:
1877 case text::HoriOrientation::NONE
:
1878 case text::HoriOrientation::LEFT_AND_WIDTH
:
1884 nIndent
= sal_Int32( pTblFmt
->GetLRSpace( ).GetLeft( ) );
1885 // Table indentation has different meaning in Word, depending if the table is nested or not.
1886 // If nested, tblInd is added to parent table's left spacing and defines left edge position
1887 // If not nested, text position of left-most cell must be at absolute X = tblInd
1888 // so, table_spacing + table_spacing_to_content = tblInd
1889 if (m_nTableDepth
== 0)
1891 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
1892 const SwFrmFmt
* pFrmFmt
= pTabBox
->GetFrmFmt();
1893 nIndent
+= sal_Int32( pFrmFmt
->GetBox( ).GetDistance( BOX_LINE_LEFT
) );
1898 m_pSerializer
->singleElementNS( XML_w
, XML_jc
,
1899 FSNS( XML_w
, XML_val
), pJcVal
,
1902 // Output the table borders
1903 TableDefaultBorders( pTableTextNodeInfoInner
);
1905 // Output the default cell margins
1906 TableDefaultCellMargins( pTableTextNodeInfoInner
);
1908 TableBidi( pTableTextNodeInfoInner
);
1910 // Table indent (need to get written even if == 0)
1911 m_pSerializer
->singleElementNS( XML_w
, XML_tblInd
,
1912 FSNS( XML_w
, XML_w
), OString::valueOf( nIndent
).getStr( ),
1913 FSNS( XML_w
, XML_type
), "dxa",
1916 // Merge the marks for the ordered elements
1917 m_pSerializer
->mergeTopMarks( );
1919 m_pSerializer
->endElementNS( XML_w
, XML_tblPr
);
1921 // Write the table grid infos
1922 m_pSerializer
->startElementNS( XML_w
, XML_tblGrid
, FSEND
);
1924 ww8::GridColsPtr pGridCols
= GetGridCols( pTableTextNodeInfoInner
);
1925 for ( ww8::GridCols::const_iterator it
= pGridCols
->begin(); it
!= pGridCols
->end(); ++it
)
1927 sal_Int32 nWidth
= sal_Int32( *it
) - nPrv
;
1928 m_pSerializer
->singleElementNS( XML_w
, XML_gridCol
,
1929 FSNS( XML_w
, XML_w
), OString::valueOf( nWidth
).getStr( ),
1931 nPrv
= sal_Int32( *it
);
1934 m_pSerializer
->endElementNS( XML_w
, XML_tblGrid
);
1937 void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1939 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
1940 const SwFrmFmt
* pFrmFmt
= pTabBox
->GetFrmFmt();
1942 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
1944 // the defaults of the table are taken from the top-left cell
1945 impl_pageBorders( m_pSerializer
, pFrmFmt
->GetBox( ), XML_tblBorders
, !bEcma
, true );
1948 void DocxAttributeOutput::TableDefaultCellMargins( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1950 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
1951 const SwFrmFmt
* pFrmFmt
= pTabBox
->GetFrmFmt();
1952 const SvxBoxItem
& rBox
= pFrmFmt
->GetBox( );
1953 const bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
1955 impl_cellMargins(m_pSerializer
, rBox
, XML_tblCellMar
, !bEcma
);
1958 void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1960 const SwTableBox
*pTblBox
= pTableTextNodeInfoInner
->getTableBox( );
1961 const SwFrmFmt
*pFmt
= pTblBox
->GetFrmFmt( );
1962 const SfxPoolItem
*pI
= NULL
;
1965 if ( SFX_ITEM_ON
== pFmt
->GetAttrSet().GetItemState( RES_BACKGROUND
, false, &pI
) )
1966 aColor
= dynamic_cast<const SvxBrushItem
*>(pI
)->GetColor();
1970 OString sColor
= msfilter::util::ConvertColor( aColor
);
1971 m_pSerializer
->singleElementNS( XML_w
, XML_shd
,
1972 FSNS( XML_w
, XML_fill
), sColor
.getStr( ),
1973 FSNS( XML_w
, XML_val
), "clear",
1977 void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
1979 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
1980 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
1981 const SwFrmFmt
* pLineFmt
= pTabLine
->GetFrmFmt();
1983 const SwFmtFrmSize
& rLSz
= pLineFmt
->GetFrmSize();
1984 if ( ATT_VAR_SIZE
!= rLSz
.GetHeightSizeType() && rLSz
.GetHeight() )
1986 sal_Int32 nHeight
= rLSz
.GetHeight();
1987 const char *pRule
= NULL
;
1989 switch ( rLSz
.GetHeightSizeType() )
1991 case ATT_FIX_SIZE
: pRule
= "exact"; break;
1992 case ATT_MIN_SIZE
: pRule
= "atLeast"; break;
1997 m_pSerializer
->singleElementNS( XML_w
, XML_trHeight
,
1998 FSNS( XML_w
, XML_val
), OString::valueOf( nHeight
).getStr( ),
1999 FSNS( XML_w
, XML_hRule
), pRule
,
2004 void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2006 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2007 const SwTableLine
* pTabLine
= pTabBox
->GetUpper();
2008 const SwFrmFmt
* pLineFmt
= pTabLine
->GetFrmFmt();
2010 const SwFmtRowSplit
& rSplittable
= pLineFmt
->GetRowSplit( );
2011 const char* pCantSplit
= ( !rSplittable
.GetValue( ) ) ? "true" : "false";
2013 m_pSerializer
->singleElementNS( XML_w
, XML_cantSplit
,
2014 FSNS( XML_w
, XML_val
), pCantSplit
,
2018 void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2020 const SwTable
* pTable
= pTableTextNodeInfoInner
->getTable();
2021 const SwFrmFmt
* pFrmFmt
= pTable
->GetFrmFmt();
2023 if ( m_rExport
.TrueFrameDirection( *pFrmFmt
) == FRMDIR_HORI_RIGHT_TOP
)
2025 m_pSerializer
->singleElementNS( XML_w
, XML_bidiVisual
,
2026 FSNS( XML_w
, XML_val
), "true",
2031 void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner
)
2033 const SwTableBox
* pTabBox
= pTableTextNodeInfoInner
->getTableBox();
2034 const SwFrmFmt
*pFrmFmt
= pTabBox
->GetFrmFmt( );
2036 if ( FRMDIR_VERT_TOP_RIGHT
== m_rExport
.TrueFrameDirection( *pFrmFmt
) )
2037 m_pSerializer
->singleElementNS( XML_w
, XML_textDirection
,
2038 FSNS( XML_w
, XML_val
), "tbRl",
2040 else if ( FRMDIR_HORI_LEFT_TOP
== m_rExport
.TrueFrameDirection( *pFrmFmt
) )
2042 // Undo the text direction mangling done by the btLr handler in writerfilter::dmapper::DomainMapperTableManager::sprm()
2043 SwPaM
aPam(*pTabBox
->GetSttNd(), 0);
2044 aPam
.GetPoint()->nNode
++;
2045 if (aPam
.GetPoint()->nNode
.GetNode().IsTxtNode())
2047 const SwTxtNode
& rTxtNode
= (const SwTxtNode
&)aPam
.GetPoint()->nNode
.GetNode();
2048 if( const SwAttrSet
* pAttrSet
= rTxtNode
.GetpSwAttrSet())
2050 const SvxCharRotateItem
& rCharRotate
= pAttrSet
->GetCharRotate();
2051 if (rCharRotate
.GetValue() == 900)
2053 m_pSerializer
->singleElementNS( XML_w
, XML_textDirection
, FSNS( XML_w
, XML_val
), "btLr", FSEND
);
2060 const SwWriteTableRows
& aRows
= m_pTableWrt
->GetRows( );
2061 SwWriteTableRow
*pRow
= aRows
[ pTableTextNodeInfoInner
->getRow( ) ];
2062 const SwWriteTableCell
*pCell
= &pRow
->GetCells( )[ pTableTextNodeInfoInner
->getCell( ) ];
2063 switch( pCell
->GetVertOri())
2065 case text::VertOrientation::TOP
:
2067 case text::VertOrientation::CENTER
:
2068 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
2069 FSNS( XML_w
, XML_val
), "center", FSEND
);
2071 case text::VertOrientation::BOTTOM
:
2072 m_pSerializer
->singleElementNS( XML_w
, XML_vAlign
,
2073 FSNS( XML_w
, XML_val
), "bottom", FSEND
);
2078 void DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t
/*pNodeInfo*/ )
2080 OSL_TRACE( "TODO: DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )" );
2083 void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner
)
2085 // This is called when the nested table ends in a cell, and there's no
2086 // paragraph benhind that; so we must check for the ends of cell, rows,
2088 // ['true' to write an empty paragraph, MS Word insists on that]
2089 FinishTableRowCell( pNodeInfoInner
, true );
2092 void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ )
2094 OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )" );
2097 void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t
/*pTableTextNodeInfoInner*/ )
2099 #if OSL_DEBUG_LEVEL > 1
2100 fprintf( stderr
, "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
2104 void DocxAttributeOutput::TableRowEnd( sal_uInt32
/*nDepth*/ )
2106 OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )" );
2109 void DocxAttributeOutput::StartStyles()
2111 m_pSerializer
->startElementNS( XML_w
, XML_styles
,
2112 FSNS( XML_xmlns
, XML_w
), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
2116 void DocxAttributeOutput::EndStyles( sal_uInt16
/*nNumberOfStyles*/ )
2118 m_pSerializer
->endElementNS( XML_w
, XML_styles
);
2121 void DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle
)
2123 // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
2124 #if OSL_DEBUG_LEVEL > 1
2125 OSL_TRACE( "TODO DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )- %d", nStyle
);
2127 (void) nStyle
; // to quiet the warning
2131 void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode
* pGrfNode
, const Size
& rSize
, const SwFlyFrmFmt
* pOLEFrmFmt
, SwOLENode
* pOLENode
)
2133 OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode ) - some stuff still missing" );
2134 // detect mis-use of the API
2135 assert(pGrfNode
|| (pOLEFrmFmt
&& pOLENode
));
2136 const SwFrmFmt
* pFrmFmt
= pGrfNode
? pGrfNode
->GetFlyFmt() : pOLEFrmFmt
;
2137 // create the relation ID
2139 sal_Int32 nImageType
;
2140 if ( pGrfNode
&& pGrfNode
->IsLinkedFile() )
2142 // linked image, just create the relation
2144 pGrfNode
->GetFileFilterNms( &aFileName
, 0 );
2146 // TODO Convert the file name to relative for better interoperability
2148 aRelId
= m_rExport
.AddRelation(
2149 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
2150 OUString( aFileName
) );
2152 nImageType
= XML_link
;
2156 // inline, we also have to write the image itself
2157 const Graphic
* pGraphic
= 0;
2159 pGraphic
= &const_cast< Graphic
& >( pGrfNode
->GetGrf() );
2161 pGraphic
= pOLENode
->GetGraphic();
2163 m_rDrawingML
.SetFS( m_pSerializer
); // to be sure that we write to the right stream
2164 OUString aImageId
= m_rDrawingML
.WriteImage( *pGraphic
);
2166 aRelId
= OUStringToOString( aImageId
, RTL_TEXTENCODING_UTF8
);
2168 nImageType
= XML_embed
;
2171 if ( aRelId
.isEmpty() )
2174 m_pSerializer
->startElementNS( XML_w
, XML_drawing
,
2176 bool isAnchor
= pFrmFmt
->GetAnchor().GetAnchorId() != FLY_AS_CHAR
;
2179 ::sax_fastparser::FastAttributeList
* attrList
= m_pSerializer
->createAttrList();
2180 attrList
->add( XML_behindDoc
, pFrmFmt
->GetOpaque().GetValue() ? "0" : "1" );
2181 attrList
->add( XML_distT
, "0" );
2182 attrList
->add( XML_distB
, "0" );
2183 attrList
->add( XML_distL
, "0" );
2184 attrList
->add( XML_distR
, "0" );
2185 attrList
->add( XML_simplePos
, "0" );
2186 attrList
->add( XML_locked
, "0" );
2187 attrList
->add( XML_layoutInCell
, "1" );
2188 attrList
->add( XML_allowOverlap
, "1" ); // TODO
2189 if( const SdrObject
* pObj
= pFrmFmt
->FindRealSdrObject())
2190 attrList
->add( XML_relativeHeight
, OString::valueOf( sal_Int32( pObj
->GetOrdNum())));
2191 m_pSerializer
->startElementNS( XML_wp
, XML_anchor
, XFastAttributeListRef( attrList
));
2192 m_pSerializer
->singleElementNS( XML_wp
, XML_simplePos
, XML_x
, "0", XML_y
, "0", FSEND
); // required, unused
2193 const char* relativeFromH
;
2194 const char* relativeFromV
;
2195 switch( pFrmFmt
->GetAnchor().GetAnchorId())
2198 relativeFromV
= relativeFromH
= "page";
2201 relativeFromH
= "column";
2202 relativeFromV
= "paragraph";
2206 // We apply the same conversion that we do in import
2207 // (see writerfilter/source/dmapper/GraphicHelper.cxx)
2208 switch (pFrmFmt
->GetVertOrient().GetRelationOrient() )
2210 case text::RelOrientation::PAGE_PRINT_AREA
:
2211 relativeFromV
= "margin";
2213 case text::RelOrientation::PAGE_FRAME
:
2214 relativeFromV
= "page";
2216 case text::RelOrientation::FRAME
:
2217 relativeFromV
= "paragraph";
2219 case text::RelOrientation::TEXT_LINE
:
2221 relativeFromV
= "line";
2223 switch (pFrmFmt
->GetHoriOrient().GetRelationOrient() )
2225 case text::RelOrientation::PAGE_PRINT_AREA
:
2226 relativeFromH
= "margin";
2228 case text::RelOrientation::PAGE_FRAME
:
2229 relativeFromH
= "page";
2231 case text::RelOrientation::CHAR
:
2232 relativeFromH
= "character";
2234 case text::RelOrientation::FRAME
:
2236 relativeFromH
= "column";
2241 if( const SwFlyFrmFmt
* flyfmt
= dynamic_cast<const SwFlyFrmFmt
*>(pFrmFmt
)) // TODO is always true?
2242 pos
= flyfmt
->GetAnchoredObj()->GetCurrRelPos();
2243 OString
x( OString::valueOf( TwipsToEMU( pos
.X())));
2244 OString
y( OString::valueOf( TwipsToEMU( pos
.Y())));
2245 m_pSerializer
->startElementNS( XML_wp
, XML_positionH
, XML_relativeFrom
, relativeFromH
, FSEND
);
2246 m_pSerializer
->startElementNS( XML_wp
, XML_posOffset
, FSEND
);
2247 m_pSerializer
->write( x
.getStr() );
2248 m_pSerializer
->endElementNS( XML_wp
, XML_posOffset
);
2249 m_pSerializer
->endElementNS( XML_wp
, XML_positionH
);
2250 m_pSerializer
->startElementNS( XML_wp
, XML_positionV
, XML_relativeFrom
, relativeFromV
, FSEND
);
2251 m_pSerializer
->startElementNS( XML_wp
, XML_posOffset
, FSEND
);
2252 m_pSerializer
->write( y
.getStr() );
2253 m_pSerializer
->endElementNS( XML_wp
, XML_posOffset
);
2254 m_pSerializer
->endElementNS( XML_wp
, XML_positionV
);
2258 m_pSerializer
->startElementNS( XML_wp
, XML_inline
,
2259 XML_distT
, "0", XML_distB
, "0", XML_distL
, "0", XML_distR
, "0",
2262 // now the common parts
2263 // extent of the image
2264 OString
aWidth( OString::valueOf( TwipsToEMU( rSize
.Width() ) ) );
2265 OString
aHeight( OString::valueOf( TwipsToEMU( rSize
.Height() ) ) );
2266 m_pSerializer
->singleElementNS( XML_wp
, XML_extent
,
2267 XML_cx
, aWidth
.getStr(),
2268 XML_cy
, aHeight
.getStr(),
2271 // effectExtent, extent including the effect (shadow only for now)
2272 SvxShadowItem aShadowItem
= pFrmFmt
->GetShadow();
2273 OString
aLeftExt("0"), aRightExt("0"), aTopExt("0"), aBottomExt("0");
2274 if ( aShadowItem
.GetLocation() != SVX_SHADOW_NONE
)
2276 OString
aShadowWidth( OString::valueOf( TwipsToEMU( aShadowItem
.GetWidth() ) ) );
2277 switch ( aShadowItem
.GetLocation() )
2279 case SVX_SHADOW_TOPLEFT
:
2280 aTopExt
= aLeftExt
= aShadowWidth
;
2282 case SVX_SHADOW_TOPRIGHT
:
2283 aTopExt
= aRightExt
= aShadowWidth
;
2285 case SVX_SHADOW_BOTTOMLEFT
:
2286 aBottomExt
= aLeftExt
= aShadowWidth
;
2288 case SVX_SHADOW_BOTTOMRIGHT
:
2289 aBottomExt
= aRightExt
= aShadowWidth
;
2291 case SVX_SHADOW_NONE
:
2292 case SVX_SHADOW_END
:
2297 m_pSerializer
->singleElementNS( XML_wp
, XML_effectExtent
,
2298 XML_l
, aLeftExt
, XML_t
, aTopExt
, XML_r
, aRightExt
, XML_b
, aBottomExt
,
2303 switch( pFrmFmt
->GetSurround().GetValue())
2306 m_pSerializer
->singleElementNS( XML_wp
, XML_wrapTopAndBottom
, FSEND
);
2308 case SURROUND_THROUGHT
:
2309 m_pSerializer
->singleElementNS( XML_wp
, XML_wrapNone
, FSEND
);
2311 case SURROUND_PARALLEL
:
2312 m_pSerializer
->singleElementNS( XML_wp
, XML_wrapSquare
,
2313 XML_wrapText
, "bothSides", FSEND
);
2315 case SURROUND_IDEAL
:
2317 m_pSerializer
->singleElementNS( XML_wp
, XML_wrapSquare
,
2318 XML_wrapText
, "largest", FSEND
);
2322 // picture description (used for pic:cNvPr later too)
2323 ::sax_fastparser::FastAttributeList
* docPrattrList
= m_pSerializer
->createAttrList();
2324 docPrattrList
->add( XML_id
, OString::valueOf( sal_Int32( m_anchorId
++ )).getStr());
2325 docPrattrList
->add( XML_name
, "Picture" );
2326 docPrattrList
->add( XML_descr
, OUStringToOString( pGrfNode
? pGrfNode
->GetDescription() : pOLEFrmFmt
->GetObjDescription(), RTL_TEXTENCODING_UTF8
).getStr());
2327 if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT
)
2328 docPrattrList
->add( XML_title
, OUStringToOString( pGrfNode
? pGrfNode
->GetTitle() : pOLEFrmFmt
->GetObjTitle(), RTL_TEXTENCODING_UTF8
).getStr());
2329 XFastAttributeListRef
docPrAttrListRef( docPrattrList
);
2330 m_pSerializer
->startElementNS( XML_wp
, XML_docPr
, docPrAttrListRef
);
2332 // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
2333 // FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
2334 // FSNS( XML_r, XML_id ), "rId4",
2336 m_pSerializer
->endElementNS( XML_wp
, XML_docPr
);
2338 m_pSerializer
->startElementNS( XML_wp
, XML_cNvGraphicFramePr
,
2340 // TODO change aspect?
2341 m_pSerializer
->singleElementNS( XML_a
, XML_graphicFrameLocks
,
2342 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
2343 XML_noChangeAspect
, "1",
2345 m_pSerializer
->endElementNS( XML_wp
, XML_cNvGraphicFramePr
);
2347 m_pSerializer
->startElementNS( XML_a
, XML_graphic
,
2348 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
2350 m_pSerializer
->startElementNS( XML_a
, XML_graphicData
,
2351 XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/picture",
2354 m_pSerializer
->startElementNS( XML_pic
, XML_pic
,
2355 FSNS( XML_xmlns
, XML_pic
), "http://schemas.openxmlformats.org/drawingml/2006/picture",
2358 m_pSerializer
->startElementNS( XML_pic
, XML_nvPicPr
,
2360 // It seems pic:cNvpr and wp:docPr are pretty much the same thing with the same attributes
2361 m_pSerializer
->startElementNS( XML_pic
, XML_cNvPr
, docPrAttrListRef
);
2364 // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
2365 // FSNS( XML_r, XML_id ), "rId4",
2367 m_pSerializer
->endElementNS( XML_pic
, XML_cNvPr
);
2369 m_pSerializer
->startElementNS( XML_pic
, XML_cNvPicPr
,
2371 // TODO change aspect?
2372 m_pSerializer
->singleElementNS( XML_a
, XML_picLocks
,
2373 XML_noChangeAspect
, "1", XML_noChangeArrowheads
, "1",
2375 m_pSerializer
->endElementNS( XML_pic
, XML_cNvPicPr
);
2376 m_pSerializer
->endElementNS( XML_pic
, XML_nvPicPr
);
2378 // the actual picture
2379 m_pSerializer
->startElementNS( XML_pic
, XML_blipFill
,
2381 m_pSerializer
->singleElementNS( XML_a
, XML_blip
,
2382 FSNS( XML_r
, nImageType
), aRelId
.getStr(),
2384 m_pSerializer
->singleElementNS( XML_a
, XML_srcRect
,
2386 m_pSerializer
->startElementNS( XML_a
, XML_stretch
,
2388 m_pSerializer
->singleElementNS( XML_a
, XML_fillRect
,
2390 m_pSerializer
->endElementNS( XML_a
, XML_stretch
);
2391 m_pSerializer
->endElementNS( XML_pic
, XML_blipFill
);
2393 // TODO setup the right values below
2394 m_pSerializer
->startElementNS( XML_pic
, XML_spPr
,
2397 m_pSerializer
->startElementNS( XML_a
, XML_xfrm
,
2399 m_pSerializer
->singleElementNS( XML_a
, XML_off
,
2400 XML_x
, "0", XML_y
, "0",
2402 m_pSerializer
->singleElementNS( XML_a
, XML_ext
,
2403 XML_cx
, aWidth
.getStr(),
2404 XML_cy
, aHeight
.getStr(),
2406 m_pSerializer
->endElementNS( XML_a
, XML_xfrm
);
2407 m_pSerializer
->startElementNS( XML_a
, XML_prstGeom
,
2410 m_pSerializer
->singleElementNS( XML_a
, XML_avLst
,
2412 m_pSerializer
->endElementNS( XML_a
, XML_prstGeom
);
2413 m_pSerializer
->singleElementNS( XML_a
, XML_noFill
,
2415 m_pSerializer
->startElementNS( XML_a
, XML_ln
,
2418 m_pSerializer
->singleElementNS( XML_a
, XML_noFill
,
2420 m_pSerializer
->singleElementNS( XML_a
, XML_miter
,
2423 m_pSerializer
->singleElementNS( XML_a
, XML_headEnd
,
2425 m_pSerializer
->singleElementNS( XML_a
, XML_tailEnd
,
2427 m_pSerializer
->endElementNS( XML_a
, XML_ln
);
2430 if ( aShadowItem
.GetLocation() != SVX_SHADOW_NONE
)
2432 // Distance is measured diagonally from corner
2433 double nShadowDist
= sqrt((aShadowItem
.GetWidth()*aShadowItem
.GetWidth())*2.0);
2434 OString
aShadowDist( OString::valueOf( TwipsToEMU( nShadowDist
) ) );
2435 OString aShadowColor
= msfilter::util::ConvertColor( aShadowItem
.GetColor() );
2436 sal_uInt32 nShadowDir
= 0;
2437 switch ( aShadowItem
.GetLocation() )
2439 case SVX_SHADOW_TOPLEFT
: nShadowDir
= 13500000; break;
2440 case SVX_SHADOW_TOPRIGHT
: nShadowDir
= 18900000; break;
2441 case SVX_SHADOW_BOTTOMLEFT
: nShadowDir
= 8100000; break;
2442 case SVX_SHADOW_BOTTOMRIGHT
: nShadowDir
= 2700000; break;
2443 case SVX_SHADOW_NONE
:
2444 case SVX_SHADOW_END
:
2447 OString
aShadowDir( OString::valueOf( long(nShadowDir
) ) );
2449 m_pSerializer
->startElementNS( XML_a
, XML_effectLst
, FSEND
);
2450 m_pSerializer
->startElementNS( XML_a
, XML_outerShdw
,
2451 XML_dist
, aShadowDist
.getStr(),
2452 XML_dir
, aShadowDir
.getStr(), FSEND
);
2453 m_pSerializer
->singleElementNS( XML_a
, XML_srgbClr
,
2454 XML_val
, aShadowColor
.getStr(), FSEND
);
2455 m_pSerializer
->endElementNS( XML_a
, XML_outerShdw
);
2456 m_pSerializer
->endElementNS( XML_a
, XML_effectLst
);
2459 m_pSerializer
->endElementNS( XML_pic
, XML_spPr
);
2461 m_pSerializer
->endElementNS( XML_pic
, XML_pic
);
2463 m_pSerializer
->endElementNS( XML_a
, XML_graphicData
);
2464 m_pSerializer
->endElementNS( XML_a
, XML_graphic
);
2465 m_pSerializer
->endElementNS( XML_wp
, isAnchor
? XML_anchor
: XML_inline
);
2467 m_pSerializer
->endElementNS( XML_w
, XML_drawing
);
2470 void DocxAttributeOutput::WriteOLE2Obj( const SdrObject
* pSdrObj
, SwOLENode
& rOLENode
, const Size
& rSize
, const SwFlyFrmFmt
* pFlyFrmFmt
)
2472 if( WriteOLEChart( pSdrObj
, rSize
))
2474 if( WriteOLEMath( pSdrObj
, rOLENode
, rSize
))
2476 // Then we fall back to just export the object as a graphic.
2477 FlyFrameGraphic( 0, rSize
, pFlyFrmFmt
, &rOLENode
);
2480 bool DocxAttributeOutput::WriteOLEChart( const SdrObject
* pSdrObj
, const Size
& rSize
)
2482 uno::Reference
< chart2::XChartDocument
> xChartDoc
;
2483 uno::Reference
< drawing::XShape
> xShape( ((SdrObject
*)pSdrObj
)->getUnoShape(), uno::UNO_QUERY
);
2486 uno::Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
2488 xChartDoc
.set( xPropSet
->getPropertyValue( "Model" ), uno::UNO_QUERY
);
2491 if( xChartDoc
.is() )
2493 OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
2494 m_pSerializer
->startElementNS( XML_w
, XML_drawing
,
2496 m_pSerializer
->startElementNS( XML_wp
, XML_inline
,
2497 XML_distT
, "0", XML_distB
, "0", XML_distL
, "0", XML_distR
, "0",
2500 OString
aWidth( OString::valueOf( TwipsToEMU( rSize
.Width() ) ) );
2501 OString
aHeight( OString::valueOf( TwipsToEMU( rSize
.Height() ) ) );
2502 m_pSerializer
->singleElementNS( XML_wp
, XML_extent
,
2503 XML_cx
, aWidth
.getStr(),
2504 XML_cy
, aHeight
.getStr(),
2506 // TODO - the right effectExtent, extent including the effect
2507 m_pSerializer
->singleElementNS( XML_wp
, XML_effectExtent
,
2508 XML_l
, "0", XML_t
, "0", XML_r
, "0", XML_b
, "0",
2511 // should get the unique id
2513 OUString
sName("Object 1");
2514 uno::Reference
< container::XNamed
> xNamed( xShape
, uno::UNO_QUERY
);
2516 sName
= xNamed
->getName();
2518 m_pSerializer
->singleElementNS( XML_wp
, XML_docPr
,
2519 XML_id
, I32S( nID
),
2520 XML_name
, USS( sName
),
2523 m_pSerializer
->singleElementNS( XML_wp
, XML_cNvGraphicFramePr
,
2526 m_pSerializer
->startElementNS( XML_a
, XML_graphic
,
2527 FSNS( XML_xmlns
, XML_a
), "http://schemas.openxmlformats.org/drawingml/2006/main",
2530 m_pSerializer
->startElementNS( XML_a
, XML_graphicData
,
2531 XML_uri
, "http://schemas.openxmlformats.org/drawingml/2006/chart",
2535 static sal_Int32 nChartCount
= 0;
2537 uno::Reference
< frame::XModel
> xModel( xChartDoc
, uno::UNO_QUERY
);
2538 aRelId
= m_rExport
.OutputChart( xModel
, nChartCount
);
2540 m_pSerializer
->singleElementNS( XML_c
, XML_chart
,
2541 FSNS( XML_xmlns
, XML_c
), "http://schemas.openxmlformats.org/drawingml/2006/chart",
2542 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
2543 FSNS( XML_r
, XML_id
), aRelId
.getStr(),
2546 m_pSerializer
->endElementNS( XML_a
, XML_graphicData
);
2547 m_pSerializer
->endElementNS( XML_a
, XML_graphic
);
2548 m_pSerializer
->endElementNS( XML_wp
, XML_inline
);
2549 m_pSerializer
->endElementNS( XML_w
, XML_drawing
);
2556 bool DocxAttributeOutput::WriteOLEMath( const SdrObject
*, const SwOLENode
& rOLENode
, const Size
& )
2558 uno::Reference
< embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
&>(rOLENode
).GetOLEObj().GetOleRef());
2559 sal_Int64 nAspect
= rOLENode
.GetAspect();
2560 svt::EmbeddedObjectRef
aObjRef( xObj
, nAspect
);
2561 SvGlobalName
aObjName(aObjRef
->getClassID());
2563 if( !SotExchange::IsMath(aObjName
) )
2565 assert( m_postponedMath
== NULL
); // make it a list if there can be more inside one run
2566 m_postponedMath
= &rOLENode
;
2570 void DocxAttributeOutput::WritePostponedMath()
2572 if( m_postponedMath
== NULL
)
2574 uno::Reference
< embed::XEmbeddedObject
> xObj(const_cast<SwOLENode
*>(m_postponedMath
)->GetOLEObj().GetOleRef());
2575 uno::Reference
< uno::XInterface
> xInterface( xObj
->getComponent(), uno::UNO_QUERY
);
2576 // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
2577 // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
2578 // to RTLD_GLOBAL, so most probably a gcc bug.
2579 oox::FormulaExportBase
* formulaexport
= dynamic_cast<oox::FormulaExportBase
*>(dynamic_cast<SfxBaseModel
*>(xInterface
.get()));
2580 assert( formulaexport
!= NULL
);
2581 formulaexport
->writeFormulaOoxml( m_pSerializer
, GetExport().GetFilter().getVersion());
2582 m_postponedMath
= NULL
;
2585 void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame
&rFrame
, const Point
& /*rNdTopLeft*/ )
2587 m_pSerializer
->mark();
2589 switch ( rFrame
.GetWriterType() )
2591 case sw::Frame::eGraphic
:
2593 const SwNode
*pNode
= rFrame
.GetContent();
2594 const SwGrfNode
*pGrfNode
= pNode
? pNode
->GetGrfNode() : 0;
2597 if( m_postponedGraphic
== NULL
)
2598 FlyFrameGraphic( pGrfNode
, rFrame
.GetLayoutSize() );
2599 else // we are writing out attributes, but w:drawing should not be inside w:rPr,
2600 { // so write it out later
2601 m_postponedGraphic
->push_back( PostponedGraphic( pGrfNode
, rFrame
.GetLayoutSize()));
2606 case sw::Frame::eDrawing
:
2608 const SdrObject
* pSdrObj
= rFrame
.GetFrmFmt().FindRealSdrObject();
2611 bool bSwapInPage
= false;
2612 if ( !pSdrObj
->GetPage() )
2614 if ( SdrModel
* pModel
= m_rExport
.pDoc
->GetDrawModel() )
2616 if ( SdrPage
*pPage
= pModel
->GetPage( 0 ) )
2619 const_cast< SdrObject
* >( pSdrObj
)->SetPage( pPage
);
2624 m_pSerializer
->startElementNS( XML_w
, XML_pict
,
2627 m_rExport
.VMLExporter().AddSdrObject( *pSdrObj
);
2629 m_pSerializer
->endElementNS( XML_w
, XML_pict
);
2632 const_cast< SdrObject
* >( pSdrObj
)->SetPage( 0 );
2636 case sw::Frame::eTxtBox
:
2638 // The frame output is postponed to the end of the anchor paragraph
2639 m_aParentFrames
.push_back(sw::Frame(rFrame
));
2642 case sw::Frame::eOle
:
2644 const SwFrmFmt
&rFrmFmt
= rFrame
.GetFrmFmt();
2645 const SdrObject
*pSdrObj
= rFrmFmt
.FindRealSdrObject();
2648 SwNodeIndex
aIdx(*rFrmFmt
.GetCntnt().GetCntntIdx(), 1);
2649 SwOLENode
& rOLENd
= *aIdx
.GetNode().GetOLENode();
2650 WriteOLE2Obj( pSdrObj
, rOLENd
, rFrame
.GetLayoutSize(), dynamic_cast<const SwFlyFrmFmt
*>( &rFrmFmt
));
2655 OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
2656 rFrame
.GetWriterType() == sw::Frame::eTxtBox
? "eTxtBox":
2657 ( rFrame
.GetWriterType() == sw::Frame::eOle
? "eOle":
2658 ( rFrame
.GetWriterType() == sw::Frame::eFormControl
? "eFormControl": "???" ) ) );
2662 m_pSerializer
->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE
);
2665 void DocxAttributeOutput::WriteOutliner(const OutlinerParaObject
& rParaObj
)
2667 const EditTextObject
& rEditObj
= rParaObj
.GetTextObject();
2668 MSWord_SdrAttrIter
aAttrIter( m_rExport
, rEditObj
, TXT_HFTXTBOX
);
2670 sal_Int32 nPara
= rEditObj
.GetParagraphCount();
2672 m_pSerializer
->startElementNS( XML_v
, XML_textbox
, FSEND
);
2673 m_pSerializer
->startElementNS( XML_w
, XML_txbxContent
, FSEND
);
2674 for (sal_Int32 n
= 0; n
< nPara
; ++n
)
2677 aAttrIter
.NextPara( n
);
2679 String
aStr( rEditObj
.GetText( n
));
2680 xub_StrLen nAktPos
= 0;
2681 xub_StrLen nEnd
= aStr
.Len();
2683 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
2685 // Write paragraph properties.
2686 m_pSerializer
->startElementNS(XML_w
, XML_pPr
, FSEND
);
2687 aAttrIter
.OutParaAttr(false);
2688 m_pSerializer
->endElementNS(XML_w
, XML_pPr
);
2691 xub_StrLen nNextAttr
= aAttrIter
.WhereNext();
2692 if( nNextAttr
> nEnd
)
2695 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
2697 // Write run properties.
2698 m_pSerializer
->startElementNS(XML_w
, XML_rPr
, FSEND
);
2699 aAttrIter
.OutAttr(nAktPos
);
2700 m_pSerializer
->endElementNS(XML_w
, XML_rPr
);
2702 bool bTxtAtr
= aAttrIter
.IsTxtAttr( nAktPos
);
2705 String
aOut( aStr
.Copy( nAktPos
, nNextAttr
- nAktPos
) );
2709 m_pSerializer
->endElementNS( XML_w
, XML_r
);
2711 nAktPos
= nNextAttr
;
2712 aAttrIter
.NextPos();
2714 while( nAktPos
< nEnd
);
2715 m_pSerializer
->endElementNS( XML_w
, XML_p
);
2717 m_pSerializer
->endElementNS( XML_w
, XML_txbxContent
);
2718 m_pSerializer
->endElementNS( XML_v
, XML_textbox
);
2721 oox::drawingml::DrawingML
& DocxAttributeOutput::GetDrawingML()
2723 return m_rDrawingML
;
2726 void DocxAttributeOutput::StartStyle( const String
& rName
, bool bPapFmt
,
2727 sal_uInt16 nBase
, sal_uInt16 nNext
, sal_uInt16
/*nWwId*/, sal_uInt16 nId
, bool bAutoUpdate
)
2729 OString
aStyle( "style" );
2731 m_pSerializer
->startElementNS( XML_w
, XML_style
,
2732 FSNS( XML_w
, XML_type
), bPapFmt
? "paragraph": "character", // FIXME is this correct?
2733 FSNS( XML_w
, XML_styleId
), OString( aStyle
+ OString::valueOf( sal_Int32( nId
) ) ).getStr(),
2736 m_pSerializer
->singleElementNS( XML_w
, XML_name
,
2737 FSNS( XML_w
, XML_val
), OUStringToOString( OUString( rName
), RTL_TEXTENCODING_UTF8
).getStr(),
2740 if ( nBase
!= 0x0FFF )
2742 m_pSerializer
->singleElementNS( XML_w
, XML_basedOn
,
2743 FSNS( XML_w
, XML_val
), OString( aStyle
+ OString::valueOf( sal_Int32( nBase
) ) ).getStr(),
2747 m_pSerializer
->singleElementNS( XML_w
, XML_next
,
2748 FSNS( XML_w
, XML_val
), OString( aStyle
+ OString::valueOf( sal_Int32( nNext
) ) ).getStr(),
2752 m_pSerializer
->singleElementNS( XML_w
, XML_autoRedefine
, FSEND
);
2755 void DocxAttributeOutput::EndStyle()
2757 m_pSerializer
->endElementNS( XML_w
, XML_style
);
2760 void DocxAttributeOutput::StartStyleProperties( bool bParProp
, sal_uInt16
/*nStyle*/ )
2764 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
2765 InitCollectedParagraphProperties();
2769 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
2770 InitCollectedRunProperties();
2774 void DocxAttributeOutput::EndStyleProperties( bool bParProp
)
2778 WriteCollectedParagraphProperties();
2779 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
2783 WriteCollectedRunProperties();
2784 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
2788 void DocxAttributeOutput::OutlineNumbering( sal_uInt8 nLvl
, const SwNumFmt
& /*rNFmt*/, const SwFmt
& /*rFmt*/ )
2790 if ( nLvl
>= WW8ListManager::nMaxLevel
)
2791 nLvl
= WW8ListManager::nMaxLevel
- 1;
2793 m_pSerializer
->singleElementNS( XML_w
, XML_outlineLvl
,
2794 FSNS( XML_w
, XML_val
), OString::valueOf( sal_Int32( nLvl
) ).getStr( ),
2798 void DocxAttributeOutput::PageBreakBefore( bool bBreak
)
2801 m_pSerializer
->singleElementNS( XML_w
, XML_pageBreakBefore
, FSEND
);
2803 m_pSerializer
->singleElementNS( XML_w
, XML_pageBreakBefore
,
2804 FSNS( XML_w
, XML_val
), "false",
2808 void DocxAttributeOutput::SectionBreak( sal_uInt8 nC
, const WW8_SepInfo
* pSectionInfo
)
2812 case msword::ColumnBreak
:
2813 // The column break should be output in the next paragraph...
2814 m_nColBreakStatus
= COLBRK_POSTPONE
;
2816 case msword::PageBreak
:
2819 if ( !m_bParagraphOpened
)
2821 // Create a dummy paragraph if needed
2822 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
2823 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
2825 m_rExport
.SectionProperties( *pSectionInfo
);
2827 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
2828 m_pSerializer
->endElementNS( XML_w
, XML_p
);
2832 // postpone the output of this; it has to be done inside the
2833 // paragraph properties, so remember it until then
2834 m_pSectionInfo
.reset( new WW8_SepInfo( *pSectionInfo
));
2839 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
2840 m_pSerializer
->singleElementNS( XML_w
, XML_br
,
2841 FSNS( XML_w
, XML_type
), "page", FSEND
);
2842 m_pSerializer
->endElementNS( XML_w
, XML_r
);
2846 OSL_TRACE( "Unknown section break to write: %d", nC
);
2851 void DocxAttributeOutput::StartSection()
2853 m_pSerializer
->startElementNS( XML_w
, XML_sectPr
, FSEND
);
2854 m_bOpenedSectPr
= true;
2856 // Write the elements in the spec order
2857 static const sal_Int32 aOrder
[] =
2859 FSNS( XML_w
, XML_headerReference
),
2860 FSNS( XML_w
, XML_footerReference
),
2861 FSNS( XML_w
, XML_footnotePr
),
2862 FSNS( XML_w
, XML_endnotePr
),
2863 FSNS( XML_w
, XML_type
),
2864 FSNS( XML_w
, XML_pgSz
),
2865 FSNS( XML_w
, XML_pgMar
),
2866 FSNS( XML_w
, XML_paperSrc
),
2867 FSNS( XML_w
, XML_pgBorders
),
2868 FSNS( XML_w
, XML_lnNumType
),
2869 FSNS( XML_w
, XML_pgNumType
),
2870 FSNS( XML_w
, XML_cols
),
2871 FSNS( XML_w
, XML_formProt
),
2872 FSNS( XML_w
, XML_vAlign
),
2873 FSNS( XML_w
, XML_noEndnote
),
2874 FSNS( XML_w
, XML_titlePg
),
2875 FSNS( XML_w
, XML_textDirection
),
2876 FSNS( XML_w
, XML_bidi
),
2877 FSNS( XML_w
, XML_rtlGutter
),
2878 FSNS( XML_w
, XML_docGrid
),
2879 FSNS( XML_w
, XML_printerSettings
),
2880 FSNS( XML_w
, XML_sectPrChange
)
2883 // postpone the output so that we can later [in EndParagraphProperties()]
2884 // prepend the properties before the run
2885 sal_Int32 len
= sizeof ( aOrder
) / sizeof( sal_Int32
);
2886 uno::Sequence
< sal_Int32
> aSeqOrder( len
);
2887 for ( sal_Int32 i
= 0; i
< len
; i
++ )
2888 aSeqOrder
[i
] = aOrder
[i
];
2890 m_pSerializer
->mark( aSeqOrder
);
2893 void DocxAttributeOutput::EndSection()
2895 // Write the section properties
2896 if ( m_pSectionSpacingAttrList
)
2898 XFastAttributeListRef
xAttrList( m_pSectionSpacingAttrList
);
2899 m_pSectionSpacingAttrList
= NULL
;
2901 m_pSerializer
->singleElementNS( XML_w
, XML_pgMar
, xAttrList
);
2904 // Order the elements
2905 m_pSerializer
->mergeTopMarks( );
2907 m_pSerializer
->endElementNS( XML_w
, XML_sectPr
);
2908 m_bOpenedSectPr
= false;
2911 void DocxAttributeOutput::SectionFormProtection( bool bProtected
)
2914 m_pSerializer
->singleElementNS( XML_w
, XML_formProt
, FSEND
);
2916 m_pSerializer
->singleElementNS( XML_w
, XML_formProt
,
2917 FSNS( XML_w
, XML_val
), "false", FSEND
);
2920 void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo
, const SwLineNumberInfo
& rLnNumInfo
)
2922 FastAttributeList
* pAttr
= m_pSerializer
->createAttrList();
2923 pAttr
->add( FSNS( XML_w
, XML_countBy
), OString::number(rLnNumInfo
.GetCountBy()).getStr());
2924 pAttr
->add( FSNS( XML_w
, XML_restart
), rLnNumInfo
.IsRestartEachPage() ? "newPage" : "continuous" );
2925 if( rLnNumInfo
.GetPosFromLeft())
2926 pAttr
->add( FSNS( XML_w
, XML_distance
), OString::number(rLnNumInfo
.GetPosFromLeft()).getStr());
2928 pAttr
->add( FSNS( XML_w
, XML_start
), OString::valueOf( long( nRestartNo
)).getStr());
2929 XFastAttributeListRef
xAttrs( pAttr
);
2930 m_pSerializer
->singleElementNS( XML_w
, XML_lnNumType
, xAttrs
);
2933 void DocxAttributeOutput::SectionTitlePage()
2935 m_pSerializer
->singleElementNS( XML_w
, XML_titlePg
, FSEND
);
2938 void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt
* pFmt
, const SwFrmFmt
* /*pFirstPageFmt*/ )
2940 // Output the margins
2942 const SvxBoxItem
& rBox
= pFmt
->GetBox( );
2944 const SvxBorderLine
* pBottom
= rBox
.GetBottom( );
2945 const SvxBorderLine
* pTop
= rBox
.GetTop( );
2946 const SvxBorderLine
* pLeft
= rBox
.GetLeft( );
2947 const SvxBorderLine
* pRight
= rBox
.GetRight( );
2949 if ( pBottom
|| pTop
|| pLeft
|| pRight
)
2951 // All distances are relative to the text margins
2952 m_pSerializer
->startElementNS( XML_w
, XML_pgBorders
,
2953 FSNS( XML_w
, XML_display
), "allPages",
2954 FSNS( XML_w
, XML_offsetFrom
), "text",
2957 m_pSerializer
->mark();
2959 m_pSerializer
->endElementNS( XML_w
, XML_pgBorders
);
2960 m_pSerializer
->mark();
2964 void DocxAttributeOutput::SectionBiDi( bool bBiDi
)
2967 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSEND
);
2970 static OString
impl_NumberingType( sal_uInt16 nNumberingType
)
2974 switch ( nNumberingType
)
2976 case SVX_NUM_CHARS_UPPER_LETTER
:
2977 case SVX_NUM_CHARS_UPPER_LETTER_N
: aType
= "upperLetter"; break;
2978 case SVX_NUM_CHARS_LOWER_LETTER
:
2979 case SVX_NUM_CHARS_LOWER_LETTER_N
: aType
= "lowerLetter"; break;
2980 case SVX_NUM_ROMAN_UPPER
: aType
= "upperRoman"; break;
2981 case SVX_NUM_ROMAN_LOWER
: aType
= "lowerRoman"; break;
2983 case SVX_NUM_ARABIC
: aType
= "decimal"; break;
2985 case SVX_NUM_BITMAP
:
2986 case SVX_NUM_CHAR_SPECIAL
: aType
= "bullet"; break;
2988 default: aType
= "none"; break;
2994 void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType
, sal_uInt16 nPageRestartNumber
)
2996 // FIXME Not called properly with page styles like "First Page"
2998 FastAttributeList
* pAttr
= m_pSerializer
->createAttrList();
3000 // 0 means no restart: then don't output that attribute if 0
3001 if ( nPageRestartNumber
> 0 )
3002 pAttr
->add( FSNS( XML_w
, XML_start
), OString::valueOf( sal_Int32( nPageRestartNumber
) ) );
3004 // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
3005 OString
aFmt( impl_NumberingType( nNumType
) );
3006 if ( !aFmt
.isEmpty() )
3007 pAttr
->add( FSNS( XML_w
, XML_fmt
), aFmt
.getStr() );
3009 XFastAttributeListRef
xAttrs( pAttr
);
3010 m_pSerializer
->singleElementNS( XML_w
, XML_pgNumType
, xAttrs
);
3012 // see 2.6.12 pgNumType (Page Numbering Settings)
3013 OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()" );
3016 void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode
)
3018 /* break code: 0 No break, 1 New column
3019 2 New page, 3 Even page, 4 Odd page
3021 const char* pType
= NULL
;
3022 switch ( nBreakCode
)
3024 case 1: pType
= "nextColumn"; break;
3025 case 2: pType
= "nextPage"; break;
3026 case 3: pType
= "evenPage"; break;
3027 case 4: pType
= "oddPage"; break;
3028 default: pType
= "continuous"; break;
3032 m_pSerializer
->singleElementNS( XML_w
, XML_type
,
3033 FSNS( XML_w
, XML_val
), pType
,
3037 void DocxAttributeOutput::StartFont( const String
& rFamilyName
) const
3039 m_pSerializer
->startElementNS( XML_w
, XML_font
,
3040 FSNS( XML_w
, XML_name
), OUStringToOString( OUString( rFamilyName
), RTL_TEXTENCODING_UTF8
).getStr(),
3044 void DocxAttributeOutput::EndFont() const
3046 m_pSerializer
->endElementNS( XML_w
, XML_font
);
3049 void DocxAttributeOutput::FontAlternateName( const String
& rName
) const
3051 m_pSerializer
->singleElementNS( XML_w
, XML_altName
,
3052 FSNS( XML_w
, XML_val
), OUStringToOString( OUString( rName
), RTL_TEXTENCODING_UTF8
).getStr(),
3056 void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet
, rtl_TextEncoding nEncoding
) const
3058 FastAttributeList
* pAttr
= m_pSerializer
->createAttrList();
3060 OString
aCharSet( OString::valueOf( sal_Int32( nCharSet
), 16 ) );
3061 if ( aCharSet
.getLength() == 1 )
3062 aCharSet
= OString( "0" ) + aCharSet
;
3063 pAttr
->add( FSNS( XML_w
, XML_val
), aCharSet
.getStr());
3065 if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT
)
3067 if( const char* charset
= rtl_getMimeCharsetFromTextEncoding( nEncoding
))
3068 pAttr
->add( FSNS( XML_w
, XML_characterSet
), charset
);
3071 m_pSerializer
->singleElementNS( XML_w
, XML_charset
, XFastAttributeListRef( pAttr
));
3074 void DocxAttributeOutput::FontFamilyType( FontFamily eFamily
) const
3076 const char *pFamily
= NULL
;
3079 case FAMILY_ROMAN
: pFamily
= "roman"; break;
3080 case FAMILY_SWISS
: pFamily
= "swiss"; break;
3081 case FAMILY_MODERN
: pFamily
= "modern"; break;
3082 case FAMILY_SCRIPT
: pFamily
= "script"; break;
3083 case FAMILY_DECORATIVE
: pFamily
= "decorative"; break;
3084 default: pFamily
= "auto"; break; // no font family
3088 m_pSerializer
->singleElementNS( XML_w
, XML_family
,
3089 FSNS( XML_w
, XML_val
), pFamily
,
3093 void DocxAttributeOutput::FontPitchType( FontPitch ePitch
) const
3095 const char *pPitch
= NULL
;
3098 case PITCH_VARIABLE
: pPitch
= "variable"; break;
3099 case PITCH_FIXED
: pPitch
= "fixed"; break;
3100 default: pPitch
= "default"; break; // no info about the pitch
3104 m_pSerializer
->singleElementNS( XML_w
, XML_pitch
,
3105 FSNS( XML_w
, XML_val
), pPitch
,
3109 void DocxAttributeOutput::EmbedFont( const OUString
& name
, FontFamily family
, FontPitch pitch
, rtl_TextEncoding encoding
)
3111 if( !m_rExport
.pDoc
->get( IDocumentSettingAccess::EMBED_FONTS
))
3112 return; // no font embedding with this document
3113 EmbedFontStyle( name
, XML_embedRegular
, family
, ITALIC_NONE
, WEIGHT_NORMAL
, pitch
, encoding
);
3114 EmbedFontStyle( name
, XML_embedBold
, family
, ITALIC_NONE
, WEIGHT_BOLD
, pitch
, encoding
);
3115 EmbedFontStyle( name
, XML_embedItalic
, family
, ITALIC_NORMAL
, WEIGHT_NORMAL
, pitch
, encoding
);
3116 EmbedFontStyle( name
, XML_embedBoldItalic
, family
, ITALIC_NORMAL
, WEIGHT_BOLD
, pitch
, encoding
);
3119 static inline char toHexChar( int value
)
3121 return value
>= 10 ? value
+ 'A' - 10 : value
+ '0';
3124 void DocxAttributeOutput::EmbedFontStyle( const OUString
& name
, int tag
, FontFamily family
, FontItalic italic
,
3125 FontWeight weight
, FontPitch pitch
, rtl_TextEncoding encoding
)
3127 // Embed font if at least viewing is allowed (in which case the opening app must check
3128 // the font license rights too and open either read-only or not use the font for editing).
3129 OUString fontUrl
= EmbeddedFontsHelper::fontFileUrl( name
, family
, italic
, weight
, pitch
, encoding
,
3130 EmbeddedFontsHelper::ViewingAllowed
);
3131 if( fontUrl
.isEmpty())
3133 // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
3134 if( !fontFilesMap
.count( fontUrl
))
3136 osl::File
file( fontUrl
);
3137 if( file
.open( osl_File_OpenFlag_Read
) != osl::File::E_None
)
3139 uno::Reference
< com::sun::star::io::XOutputStream
> xOutStream
= m_rExport
.GetFilter().openFragmentStream(
3140 OUString( "word/fonts/font" ) + OUString::number(m_nextFontId
) + ".odttf",
3141 "application/vnd.openxmlformats-officedocument.obfuscatedFont" );
3142 // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway,
3143 // so just alter the first and last part of the key.
3144 char fontKeyStr
[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}";
3145 sal_uInt8 fontKey
[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E,
3146 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 };
3147 fontKey
[ 0 ] = fontKey
[ 15 ] = m_nextFontId
% 256;
3148 fontKeyStr
[ 1 ] = fontKeyStr
[ 35 ] = toHexChar(( m_nextFontId
% 256 ) / 16 );
3149 fontKeyStr
[ 2 ] = fontKeyStr
[ 36 ] = toHexChar(( m_nextFontId
% 256 ) % 16 );
3150 char buffer
[ 4096 ];
3151 sal_uInt64 readSize
;
3152 file
.read( buffer
, 32, readSize
);
3155 SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl
<< ")" );
3156 xOutStream
->closeOutput();
3163 buffer
[ i
] ^= fontKey
[ i
];
3164 buffer
[ i
+ 16 ] ^= fontKey
[ i
];
3166 xOutStream
->writeBytes( uno::Sequence
< sal_Int8
>( reinterpret_cast< const sal_Int8
* >( buffer
), 32 ));
3170 if( file
.isEndOfFile( &eof
) != osl::File::E_None
)
3172 SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl
);
3173 xOutStream
->closeOutput();
3178 if( file
.read( buffer
, 4096, readSize
) != osl::File::E_None
)
3180 SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl
);
3181 xOutStream
->closeOutput();
3186 xOutStream
->writeBytes( uno::Sequence
< sal_Int8
>( reinterpret_cast< const sal_Int8
* >( buffer
), readSize
));
3188 xOutStream
->closeOutput();
3189 OString relId
= OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer
->getOutputStream(),
3190 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
3191 OUString( "fonts/font" ) + OUString::number( m_nextFontId
) + ".odttf" ), RTL_TEXTENCODING_UTF8
);
3192 EmbeddedFontRef ref
;
3194 ref
.fontKey
= fontKeyStr
;
3195 fontFilesMap
[ fontUrl
] = ref
;
3198 m_pSerializer
->singleElementNS( XML_w
, tag
,
3199 FSNS( XML_r
, XML_id
), fontFilesMap
[ fontUrl
].relId
,
3200 FSNS( XML_w
, XML_fontKey
), fontFilesMap
[ fontUrl
].fontKey
,
3204 void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId
, const SwNumRule
&rRule
)
3206 // nId is the same both for abstract numbering definition as well as the
3207 // numbering definition itself
3208 // TODO check that this is actually true & fix if not ;-)
3209 OString
aId( OString::valueOf( sal_Int32( nId
) ) );
3211 m_pSerializer
->startElementNS( XML_w
, XML_num
,
3212 FSNS( XML_w
, XML_numId
), aId
.getStr(),
3215 m_pSerializer
->singleElementNS( XML_w
, XML_abstractNumId
,
3216 FSNS( XML_w
, XML_val
), aId
.getStr(),
3219 #if OSL_DEBUG_LEVEL > 1
3220 // TODO ww8 version writes this, anything to do about it here?
3221 if ( rRule
.IsContinusNum() )
3222 OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()" );
3224 (void) rRule
; // to quiet the warning...
3227 m_pSerializer
->endElementNS( XML_w
, XML_num
);
3230 void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId
)
3232 m_pSerializer
->startElementNS( XML_w
, XML_abstractNum
,
3233 FSNS( XML_w
, XML_abstractNumId
), OString::valueOf( sal_Int32( nId
) ).getStr(),
3237 void DocxAttributeOutput::EndAbstractNumbering()
3239 m_pSerializer
->endElementNS( XML_w
, XML_abstractNum
);
3242 void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel
,
3244 sal_uInt16 nNumberingType
,
3246 const sal_uInt8
* /*pNumLvlPos*/,
3248 const wwFont
*pFont
,
3249 const SfxItemSet
*pOutSet
,
3250 sal_Int16 nIndentAt
,
3251 sal_Int16 nFirstLineIndex
,
3252 sal_Int16 nListTabPos
,
3253 const String
&rNumberingString
,
3254 const SvxBrushItem
* pBrush
)
3256 m_pSerializer
->startElementNS( XML_w
, XML_lvl
,
3257 FSNS( XML_w
, XML_ilvl
), OString::valueOf( sal_Int32( nLevel
) ).getStr(),
3260 // start with the nStart value
3261 m_pSerializer
->singleElementNS( XML_w
, XML_start
,
3262 FSNS( XML_w
, XML_val
), OString::valueOf( sal_Int32( nStart
) ).getStr(),
3266 OString
aFmt( impl_NumberingType( nNumberingType
) );
3268 if ( !aFmt
.isEmpty() )
3269 m_pSerializer
->singleElementNS( XML_w
, XML_numFmt
,
3270 FSNS( XML_w
, XML_val
), aFmt
.getStr(),
3274 const char *pSuffix
= NULL
;
3277 case 1: pSuffix
= "space"; break;
3278 case 2: pSuffix
= "nothing"; break;
3279 default: /*pSuffix = "tab";*/ break;
3282 m_pSerializer
->singleElementNS( XML_w
, XML_suff
,
3283 FSNS( XML_w
, XML_val
), pSuffix
,
3287 OUString
aText( rNumberingString
);
3288 OUStringBuffer
aBuffer( aText
.getLength() + WW8ListManager::nMaxLevel
);
3290 const sal_Unicode
*pPrev
= aText
.getStr();
3291 const sal_Unicode
*pIt
= aText
.getStr();
3292 while ( pIt
< aText
.getStr() + aText
.getLength() )
3294 // convert the level values to %NUMBER form
3295 // (we don't use pNumLvlPos at all)
3296 // FIXME so far we support the ww8 limit of levels only
3297 if ( *pIt
< sal_Unicode( WW8ListManager::nMaxLevel
) )
3299 aBuffer
.append( pPrev
, pIt
- pPrev
);
3300 aBuffer
.append( '%' );
3301 aBuffer
.append( OUString::valueOf( sal_Int32( *pIt
) + 1 ) );
3308 aBuffer
.append( pPrev
, pIt
- pPrev
);
3310 m_pSerializer
->singleElementNS( XML_w
, XML_lvlText
,
3311 FSNS( XML_w
, XML_val
), OUStringToOString( aBuffer
.makeStringAndClear(), RTL_TEXTENCODING_UTF8
).getStr(),
3315 if (nNumberingType
== SVX_NUM_BITMAP
&& pBrush
)
3317 int nIndex
= m_rExport
.GetGrfIndex(*pBrush
);
3320 m_pSerializer
->singleElementNS(XML_w
, XML_lvlPicBulletId
,
3321 FSNS(XML_w
, XML_val
), OString::number(nIndex
).getStr(),
3328 bool ecmaDialect
= ( m_rExport
.GetFilter().getVersion() == oox::core::ECMA_DIALECT
);
3331 case SVX_ADJUST_CENTER
: pJc
= "center"; break;
3332 case SVX_ADJUST_RIGHT
: pJc
= !ecmaDialect
? "end" : "right"; break;
3333 default: pJc
= !ecmaDialect
? "start" : "left"; break;
3335 m_pSerializer
->singleElementNS( XML_w
, XML_lvlJc
,
3336 FSNS( XML_w
, XML_val
), pJc
,
3340 m_pSerializer
->startElementNS( XML_w
, XML_pPr
, FSEND
);
3341 if( nListTabPos
!= 0 )
3343 m_pSerializer
->startElementNS( XML_w
, XML_tabs
, FSEND
);
3344 m_pSerializer
->singleElementNS( XML_w
, XML_tab
,
3345 FSNS( XML_w
, XML_val
), "num",
3346 FSNS( XML_w
, XML_pos
), OString::number( nListTabPos
).getStr(),
3348 m_pSerializer
->endElementNS( XML_w
, XML_tabs
);
3351 sal_Int32 nToken
= ecmaDialect
? XML_left
: XML_start
;
3352 m_pSerializer
->singleElementNS( XML_w
, XML_ind
,
3353 FSNS( XML_w
, nToken
), OString::valueOf( sal_Int32( nIndentAt
) ).getStr(),
3354 FSNS( XML_w
, XML_hanging
), OString::valueOf( sal_Int32( -nFirstLineIndex
) ).getStr(),
3356 m_pSerializer
->endElementNS( XML_w
, XML_pPr
);
3361 m_pSerializer
->startElementNS( XML_w
, XML_rPr
, FSEND
);
3365 GetExport().GetId( *pFont
); // ensure font info is written to fontTable.xml
3366 OString
aFamilyName( OUStringToOString( OUString( pFont
->GetFamilyName() ), RTL_TEXTENCODING_UTF8
) );
3367 m_pSerializer
->singleElementNS( XML_w
, XML_rFonts
,
3368 FSNS( XML_w
, XML_ascii
), aFamilyName
.getStr(),
3369 FSNS( XML_w
, XML_hAnsi
), aFamilyName
.getStr(),
3370 FSNS( XML_w
, XML_cs
), aFamilyName
.getStr(),
3371 FSNS( XML_w
, XML_hint
), "default",
3374 m_rExport
.OutputItemSet( *pOutSet
, false, true, i18n::ScriptType::LATIN
, m_rExport
.mbExportModeRTF
);
3376 m_pSerializer
->endElementNS( XML_w
, XML_rPr
);
3379 // TODO anything to do about nListTabPos?
3381 m_pSerializer
->endElementNS( XML_w
, XML_lvl
);
3384 void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem
& rCaseMap
)
3386 switch ( rCaseMap
.GetValue() )
3388 case SVX_CASEMAP_KAPITAELCHEN
:
3389 m_pSerializer
->singleElementNS( XML_w
, XML_smallCaps
, FSEND
);
3391 case SVX_CASEMAP_VERSALIEN
:
3392 m_pSerializer
->singleElementNS( XML_w
, XML_caps
, FSEND
);
3394 default: // Something that ooxml does not support
3395 m_pSerializer
->singleElementNS( XML_w
, XML_smallCaps
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3396 m_pSerializer
->singleElementNS( XML_w
, XML_caps
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3401 void DocxAttributeOutput::CharColor( const SvxColorItem
& rColor
)
3403 const Color
aColor( rColor
.GetValue() );
3404 OString aColorString
;
3406 aColorString
= msfilter::util::ConvertColor( aColor
);
3408 m_pSerializer
->singleElementNS( XML_w
, XML_color
,
3409 FSNS( XML_w
, XML_val
), aColorString
.getStr(), FSEND
);
3412 void DocxAttributeOutput::CharContour( const SvxContourItem
& rContour
)
3414 if ( rContour
.GetValue() )
3415 m_pSerializer
->singleElementNS( XML_w
, XML_outline
, FSEND
);
3417 m_pSerializer
->singleElementNS( XML_w
, XML_outline
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3420 void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem
& rCrossedOut
)
3422 switch ( rCrossedOut
.GetStrikeout() )
3424 case STRIKEOUT_DOUBLE
:
3425 m_pSerializer
->singleElementNS( XML_w
, XML_dstrike
, FSEND
);
3427 case STRIKEOUT_NONE
:
3428 m_pSerializer
->singleElementNS( XML_w
, XML_dstrike
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3429 m_pSerializer
->singleElementNS( XML_w
, XML_strike
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3432 m_pSerializer
->singleElementNS( XML_w
, XML_strike
, FSEND
);
3437 void DocxAttributeOutput::CharEscapement( const SvxEscapementItem
& rEscapement
)
3440 short nEsc
= rEscapement
.GetEsc(), nProp
= rEscapement
.GetProp();
3443 sIss
= OString( "baseline" );
3447 else if ( DFLT_ESC_PROP
== nProp
)
3449 if ( DFLT_ESC_SUB
== nEsc
|| DFLT_ESC_AUTO_SUB
== nEsc
)
3450 sIss
= OString( "subscript" );
3451 else if ( DFLT_ESC_SUPER
== nEsc
|| DFLT_ESC_AUTO_SUPER
== nEsc
)
3452 sIss
= OString( "superscript" );
3455 if ( !sIss
.isEmpty() )
3456 m_pSerializer
->singleElementNS( XML_w
, XML_vertAlign
,
3457 FSNS( XML_w
, XML_val
), sIss
.getStr(), FSEND
);
3459 if ( sIss
.isEmpty() || sIss
.match( OString( "baseline" ) ) )
3461 long nHeight
= ((SvxFontHeightItem
&)m_rExport
.GetItem(
3462 RES_CHRATR_FONTSIZE
)).GetHeight();
3463 OString sPos
= OString::valueOf( ( nHeight
* nEsc
+ 500 ) / 1000 );
3464 m_pSerializer
->singleElementNS( XML_w
, XML_position
,
3465 FSNS( XML_w
, XML_val
), sPos
.getStr( ), FSEND
);
3467 if( 100 != nProp
|| sIss
.match( OString( "baseline" ) ) )
3469 OString sSize
= OString::valueOf( ( nHeight
* nProp
+ 500 ) / 1000 );
3470 m_pSerializer
->singleElementNS( XML_w
, XML_sz
,
3471 FSNS( XML_w
, XML_val
), sSize
.getStr( ), FSEND
);
3476 void DocxAttributeOutput::CharFont( const SvxFontItem
& rFont
)
3478 if (!m_pFontsAttrList
)
3479 m_pFontsAttrList
= m_pSerializer
->createAttrList();
3480 GetExport().GetId( rFont
); // ensure font info is written to fontTable.xml
3481 OUString
sFontName(rFont
.GetFamilyName());
3482 OString sFontNameUtf8
= OUStringToOString(sFontName
, RTL_TEXTENCODING_UTF8
);
3483 m_pFontsAttrList
->add(FSNS(XML_w
, XML_ascii
), sFontNameUtf8
);
3484 m_pFontsAttrList
->add(FSNS(XML_w
, XML_hAnsi
), sFontNameUtf8
);
3487 void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem
& rFontSize
)
3489 OString fontSize
= OString::valueOf( sal_Int32( ( rFontSize
.GetHeight() + 5 ) / 10 ) );
3491 switch ( rFontSize
.Which() )
3493 case RES_CHRATR_FONTSIZE
:
3494 case RES_CHRATR_CJK_FONTSIZE
:
3495 m_pSerializer
->singleElementNS( XML_w
, XML_sz
, FSNS( XML_w
, XML_val
), fontSize
.getStr(), FSEND
);
3497 case RES_CHRATR_CTL_FONTSIZE
:
3498 m_pSerializer
->singleElementNS( XML_w
, XML_szCs
, FSNS( XML_w
, XML_val
), fontSize
.getStr(), FSEND
);
3503 void DocxAttributeOutput::CharKerning( const SvxKerningItem
& rKerning
)
3505 OString aKerning
= OString::valueOf( ( sal_Int32
) rKerning
.GetValue() );
3506 m_pSerializer
->singleElementNS( XML_w
, XML_spacing
, FSNS(XML_w
, XML_val
), aKerning
.getStr(), FSEND
);
3509 void DocxAttributeOutput::CharLanguage( const SvxLanguageItem
& rLanguage
)
3511 if (!m_pCharLangAttrList
)
3512 m_pCharLangAttrList
= m_pSerializer
->createAttrList();
3514 ::com::sun::star::lang::Locale xLocale
= LanguageTag( rLanguage
.GetLanguage( ) ).getLocale();
3515 OString sLanguage
= OUStringToOString(xLocale
.Language
, RTL_TEXTENCODING_UTF8
);
3516 OString sCountry
= OUStringToOString(xLocale
.Country
, RTL_TEXTENCODING_UTF8
);
3518 OString aLanguageCode
= sLanguage
+ "-" + sCountry
;
3520 switch ( rLanguage
.Which() )
3522 case RES_CHRATR_LANGUAGE
:
3523 m_pCharLangAttrList
->add(FSNS(XML_w
, XML_val
), aLanguageCode
);
3525 case RES_CHRATR_CJK_LANGUAGE
:
3526 m_pCharLangAttrList
->add(FSNS(XML_w
, XML_eastAsia
), aLanguageCode
);
3528 case RES_CHRATR_CTL_LANGUAGE
:
3529 m_pCharLangAttrList
->add(FSNS(XML_w
, XML_bidi
), aLanguageCode
);
3534 void DocxAttributeOutput::CharPosture( const SvxPostureItem
& rPosture
)
3536 if ( rPosture
.GetPosture() != ITALIC_NONE
)
3537 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSEND
);
3539 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3542 void DocxAttributeOutput::CharShadow( const SvxShadowedItem
& rShadow
)
3544 if ( rShadow
.GetValue() )
3545 m_pSerializer
->singleElementNS( XML_w
, XML_shadow
, FSEND
);
3547 m_pSerializer
->singleElementNS( XML_w
, XML_shadow
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3550 void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem
& rUnderline
)
3552 const char *pUnderline
;
3554 switch ( rUnderline
.GetLineStyle() )
3556 case UNDERLINE_SINGLE
: pUnderline
= "single"; break;
3557 case UNDERLINE_BOLD
: pUnderline
= "thick"; break;
3558 case UNDERLINE_DOUBLE
: pUnderline
= "double"; break;
3559 case UNDERLINE_DOTTED
: pUnderline
= "dotted"; break;
3560 case UNDERLINE_DASH
: pUnderline
= "dash"; break;
3561 case UNDERLINE_DASHDOT
: pUnderline
= "dotDash"; break;
3562 case UNDERLINE_DASHDOTDOT
: pUnderline
= "dotDotDash"; break;
3563 case UNDERLINE_WAVE
: pUnderline
= "wave"; break;
3564 case UNDERLINE_BOLDDOTTED
: pUnderline
= "dottedHeavy"; break;
3565 case UNDERLINE_BOLDDASH
: pUnderline
= "dashedHeavy"; break;
3566 case UNDERLINE_LONGDASH
: pUnderline
= "dashLongHeavy"; break;
3567 case UNDERLINE_BOLDLONGDASH
: pUnderline
= "dashLongHeavy"; break;
3568 case UNDERLINE_BOLDDASHDOT
: pUnderline
= "dashDotHeavy"; break;
3569 case UNDERLINE_BOLDDASHDOTDOT
: pUnderline
= "dashDotDotHeavy"; break;
3570 case UNDERLINE_BOLDWAVE
: pUnderline
= "wavyHeavy"; break;
3571 case UNDERLINE_DOUBLEWAVE
: pUnderline
= "wavyDouble"; break;
3572 case UNDERLINE_NONE
: // fall through
3573 default: pUnderline
= "none"; break;
3576 m_pSerializer
->singleElementNS( XML_w
, XML_u
, FSNS( XML_w
, XML_val
), pUnderline
, FSEND
);
3579 void DocxAttributeOutput::CharWeight( const SvxWeightItem
& rWeight
)
3581 if ( rWeight
.GetWeight() == WEIGHT_BOLD
)
3582 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSEND
);
3584 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3587 void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem
& )
3589 OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()" );
3592 void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem
& rBlink
)
3594 if ( rBlink
.GetValue() )
3595 m_pSerializer
->singleElementNS(XML_w
, XML_effect
, FSNS( XML_w
, XML_val
), "blinkBackground", FSEND
);
3597 m_pSerializer
->singleElementNS(XML_w
, XML_effect
, FSNS( XML_w
, XML_val
), "none", FSEND
);
3600 void DocxAttributeOutput::CharBackground( const SvxBrushItem
& rBrush
)
3602 m_pSerializer
->singleElementNS( XML_w
, XML_shd
,
3603 FSNS( XML_w
, XML_fill
), msfilter::util::ConvertColor( rBrush
.GetColor() ).getStr(),
3604 FSNS( XML_w
, XML_val
), "clear",
3608 void DocxAttributeOutput::CharFontCJK( const SvxFontItem
& rFont
)
3610 if (!m_pFontsAttrList
)
3611 m_pFontsAttrList
= m_pSerializer
->createAttrList();
3612 OUString
sFontName(rFont
.GetFamilyName());
3613 OString sFontNameUtf8
= OUStringToOString(sFontName
, RTL_TEXTENCODING_UTF8
);
3614 m_pFontsAttrList
->add(FSNS(XML_w
, XML_eastAsia
), sFontNameUtf8
);
3617 void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem
& rPosture
)
3619 if ( rPosture
.GetPosture() != ITALIC_NONE
)
3620 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSEND
);
3622 m_pSerializer
->singleElementNS( XML_w
, XML_i
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3625 void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem
& rWeight
)
3627 if ( rWeight
.GetWeight() == WEIGHT_BOLD
)
3628 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSEND
);
3630 m_pSerializer
->singleElementNS( XML_w
, XML_b
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3633 void DocxAttributeOutput::CharFontCTL( const SvxFontItem
& rFont
)
3635 if (!m_pFontsAttrList
)
3636 m_pFontsAttrList
= m_pSerializer
->createAttrList();
3637 OUString
sFontName(rFont
.GetFamilyName());
3638 OString sFontNameUtf8
= OUStringToOString(sFontName
, RTL_TEXTENCODING_UTF8
);
3639 m_pFontsAttrList
->add(FSNS(XML_w
, XML_cs
), sFontNameUtf8
);
3643 void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem
& rPosture
)
3645 if ( rPosture
.GetPosture() != ITALIC_NONE
)
3646 m_pSerializer
->singleElementNS( XML_w
, XML_iCs
, FSEND
);
3648 m_pSerializer
->singleElementNS( XML_w
, XML_iCs
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3651 void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem
& rWeight
)
3653 if ( rWeight
.GetWeight() == WEIGHT_BOLD
)
3654 m_pSerializer
->singleElementNS( XML_w
, XML_bCs
, FSEND
);
3656 m_pSerializer
->singleElementNS( XML_w
, XML_bCs
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3659 void DocxAttributeOutput::CharRotate( const SvxCharRotateItem
& rRotate
)
3661 // Not rorated or we the rotation already handled?
3662 if ( !rRotate
.GetValue() || m_bBtLr
)
3665 if (!m_pEastAsianLayoutAttrList
)
3666 m_pEastAsianLayoutAttrList
= m_pSerializer
->createAttrList();
3667 OString
sTrue((sal_Char
*)"true");
3668 m_pEastAsianLayoutAttrList
->add(FSNS(XML_w
, XML_vert
), sTrue
);
3670 if (rRotate
.IsFitToLine())
3671 m_pEastAsianLayoutAttrList
->add(FSNS(XML_w
, XML_vertCompress
), sTrue
);
3674 void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem
& rEmphasisMark
)
3676 const char *pEmphasis
;
3678 switch ( rEmphasisMark
.GetValue() )
3680 case EMPHASISMARK_NONE
: pEmphasis
= "none"; break;
3681 case EMPHASISMARK_SIDE_DOTS
: pEmphasis
= "dot"; break;
3682 case EMPHASISMARK_CIRCLE_ABOVE
: pEmphasis
= "circle"; break;
3683 case EMPHASISMARK_DOTS_BELOW
: pEmphasis
= "underDot"; break;
3684 default: pEmphasis
= "comma"; break;
3687 m_pSerializer
->singleElementNS( XML_w
, XML_em
, FSNS( XML_w
, XML_val
), pEmphasis
, FSEND
);
3690 void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem
& rTwoLines
)
3692 if ( !rTwoLines
.GetValue() )
3695 if (!m_pEastAsianLayoutAttrList
)
3696 m_pEastAsianLayoutAttrList
= m_pSerializer
->createAttrList();
3697 OString
sTrue((sal_Char
*)"true");
3698 m_pEastAsianLayoutAttrList
->add(FSNS(XML_w
, XML_combine
), sTrue
);
3700 sal_Unicode cStart
= rTwoLines
.GetStartBracket();
3701 sal_Unicode cEnd
= rTwoLines
.GetEndBracket();
3703 if (!cStart
&& !cEnd
)
3707 if ((cStart
== '{') || (cEnd
== '}'))
3708 sBracket
= (sal_Char
*)"curly";
3709 else if ((cStart
== '<') || (cEnd
== '>'))
3710 sBracket
= (sal_Char
*)"angle";
3711 else if ((cStart
== '[') || (cEnd
== ']'))
3712 sBracket
= (sal_Char
*)"square";
3714 sBracket
= (sal_Char
*)"round";
3715 m_pEastAsianLayoutAttrList
->add(FSNS(XML_w
, XML_combineBrackets
), sBracket
);
3718 void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem
& rScaleWidth
)
3720 m_pSerializer
->singleElementNS( XML_w
, XML_w
,
3721 FSNS( XML_w
, XML_val
), OString::valueOf( sal_Int32( rScaleWidth
.GetValue() ) ).getStr(), FSEND
);
3724 void DocxAttributeOutput::CharRelief( const SvxCharReliefItem
& rRelief
)
3726 switch ( rRelief
.GetValue() )
3728 case RELIEF_EMBOSSED
:
3729 m_pSerializer
->singleElementNS( XML_w
, XML_emboss
, FSEND
);
3731 case RELIEF_ENGRAVED
:
3732 m_pSerializer
->singleElementNS( XML_w
, XML_imprint
, FSEND
);
3735 m_pSerializer
->singleElementNS( XML_w
, XML_emboss
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3736 m_pSerializer
->singleElementNS( XML_w
, XML_imprint
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3741 void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem
& rHidden
)
3743 if ( rHidden
.GetValue() )
3744 m_pSerializer
->singleElementNS( XML_w
, XML_vanish
, FSEND
);
3746 m_pSerializer
->singleElementNS( XML_w
, XML_vanish
, FSNS( XML_w
, XML_val
), "false", FSEND
);
3749 void DocxAttributeOutput::TextINetFormat( const SwFmtINetFmt
& rLink
)
3751 const SwTxtINetFmt
* pINetFmt
= rLink
.GetTxtINetFmt();
3752 const SwCharFmt
* pCharFmt
= pINetFmt
->GetCharFmt();
3754 OString
aStyleId( "style" );
3755 aStyleId
+= OString::valueOf( sal_Int32( m_rExport
.GetId( *pCharFmt
) ) );
3757 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
3760 void DocxAttributeOutput::TextCharFormat( const SwFmtCharFmt
& rCharFmt
)
3762 OString
aStyleId( "style" );
3763 aStyleId
+= OString::valueOf( sal_Int32( m_rExport
.GetId( *rCharFmt
.GetCharFmt() ) ) );
3765 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
3768 void DocxAttributeOutput::RefField( const SwField
& rFld
, const String
& rRef
)
3770 sal_uInt16 nType
= rFld
.GetTyp( )->Which( );
3771 if ( nType
== RES_GETEXPFLD
)
3773 String sCmd
= FieldString( ww::eREF
);
3774 sCmd
.AppendAscii( "\"" );
3776 sCmd
.AppendAscii( "\" " );
3778 m_rExport
.OutputField( &rFld
, ww::eREF
, sCmd
);
3781 // There is nothing to do here for the set fields
3784 void DocxAttributeOutput::HiddenField( const SwField
& /*rFld*/ )
3786 OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()" );
3789 void DocxAttributeOutput::PostitField( const SwField
* pFld
)
3791 assert( dynamic_cast< const SwPostItField
* >( pFld
));
3792 m_postitFields
.push_back( static_cast< const SwPostItField
* >( pFld
));
3795 void DocxAttributeOutput::WritePostitFieldReference()
3797 while( m_postitFieldsMaxId
< m_postitFields
.size())
3799 OString idstr
= OString::valueOf( sal_Int32( m_postitFieldsMaxId
));
3800 m_pSerializer
->singleElementNS( XML_w
, XML_commentReference
, FSNS( XML_w
, XML_id
), idstr
.getStr(), FSEND
);
3801 ++m_postitFieldsMaxId
;
3805 void DocxAttributeOutput::WritePostitFieldStart()
3807 m_bPostitStart
= true;
3810 void DocxAttributeOutput::WritePostitFieldEnd()
3812 m_bPostitEnd
= true;
3815 void DocxAttributeOutput::WritePostitFields()
3817 for( unsigned int i
= 0;
3818 i
< m_postitFields
.size();
3821 OString idstr
= OString::valueOf( sal_Int32( i
));
3822 const SwPostItField
* f
= m_postitFields
[ i
];
3823 m_pSerializer
->startElementNS( XML_w
, XML_comment
, FSNS( XML_w
, XML_id
), idstr
.getStr(),
3824 FSNS( XML_w
, XML_author
), OUStringToOString( f
->GetPar1(), RTL_TEXTENCODING_UTF8
).getStr(),
3825 FSNS( XML_w
, XML_date
), msfilter::util::DateTimeToOString(f
->GetDateTime()).getStr(),
3826 FSNS( XML_w
, XML_initials
), OUStringToOString( f
->GetInitials(), RTL_TEXTENCODING_UTF8
).getStr(), FSEND
);
3827 // Check for the text object existing, it seems that it can be NULL when saving a newly created
3828 // comment without giving focus back to the main document. As GetTxt() is empty in that case as well,
3829 // that is probably a bug in the Writer core.
3830 if( f
->GetTextObject() != NULL
)
3831 GetExport().WriteOutliner( *f
->GetTextObject(), TXT_ATN
);
3832 m_pSerializer
->endElementNS( XML_w
, XML_comment
);
3836 bool DocxAttributeOutput::DropdownField( const SwField
* pFld
)
3838 bool bExpand
= false;
3840 ww::eField eType
= ww::eFORMDROPDOWN
;
3841 String sCmd
= FieldString( eType
);
3842 GetExport( ).OutputField( pFld
, eType
, sCmd
);
3847 bool DocxAttributeOutput::PlaceholderField( const SwField
* pFld
)
3849 assert( pendingPlaceholder
== NULL
);
3850 pendingPlaceholder
= pFld
;
3851 return false; // do not expand
3854 void DocxAttributeOutput::WritePendingPlaceholder()
3856 if( pendingPlaceholder
== NULL
)
3858 const SwField
* pFld
= pendingPlaceholder
;
3859 pendingPlaceholder
= NULL
;
3860 m_pSerializer
->startElementNS( XML_w
, XML_sdt
, FSEND
);
3861 m_pSerializer
->startElementNS( XML_w
, XML_sdtPr
, FSEND
);
3862 if( !pFld
->GetPar2().isEmpty())
3863 m_pSerializer
->singleElementNS( XML_w
, XML_alias
,
3864 FSNS( XML_w
, XML_val
), OUStringToOString( pFld
->GetPar2(), RTL_TEXTENCODING_UTF8
), FSEND
);
3865 m_pSerializer
->singleElementNS( XML_w
, XML_temporary
, FSEND
);
3866 m_pSerializer
->singleElementNS( XML_w
, XML_showingPlcHdr
, FSEND
);
3867 m_pSerializer
->singleElementNS( XML_w
, XML_text
, FSEND
);
3868 m_pSerializer
->endElementNS( XML_w
, XML_sdtPr
);
3869 m_pSerializer
->startElementNS( XML_w
, XML_sdtContent
, FSEND
);
3870 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
3871 RunText( pFld
->GetPar1());
3872 m_pSerializer
->endElementNS( XML_w
, XML_r
);
3873 m_pSerializer
->endElementNS( XML_w
, XML_sdtContent
);
3874 m_pSerializer
->endElementNS( XML_w
, XML_sdt
);
3877 void DocxAttributeOutput::SetField( const SwField
& rFld
, ww::eField eType
, const String
& rCmd
)
3879 // field bookmarks are handled in the EndRun method
3880 GetExport().OutputField(&rFld
, eType
, rCmd
);
3883 void DocxAttributeOutput::WriteExpand( const SwField
* pFld
)
3885 // Will be written in the next End Run
3887 m_rExport
.OutputField( pFld
, ww::eUNKNOWN
, sCmd
);
3890 void DocxAttributeOutput::WriteField_Impl( const SwField
* pFld
, ww::eField eType
, const String
& rFldCmd
, sal_uInt8 nMode
)
3892 struct FieldInfos infos
;
3894 infos
.pField
= pFld
->CopyField();
3895 infos
.sCmd
= rFldCmd
;
3896 infos
.eType
= eType
;
3897 infos
.bClose
= WRITEFIELD_CLOSE
& nMode
;
3898 infos
.bOpen
= WRITEFIELD_START
& nMode
;
3899 m_Fields
.push_back( infos
);
3903 sal_uInt16 nType
= pFld
->GetTyp( )->Which( );
3904 sal_uInt16 nSubType
= pFld
->GetSubType();
3906 // TODO Any other field types here ?
3907 if ( ( nType
== RES_SETEXPFLD
) && ( nSubType
& nsSwGetSetExpType::GSE_STRING
) )
3909 const SwSetExpField
*pSet
= ( const SwSetExpField
* )( pFld
);
3910 m_sFieldBkm
= pSet
->GetPar1( );
3912 else if ( nType
== RES_DROPDOWN
)
3914 const SwDropDownField
* pDropDown
= ( const SwDropDownField
* )( pFld
);
3915 m_sFieldBkm
= pDropDown
->GetName( );
3920 void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark
& rFieldmark
)
3922 if ( !m_Fields
.empty() )
3923 m_Fields
.begin()->pFieldmark
= &rFieldmark
;
3926 void DocxAttributeOutput::WriteBookmarks_Impl( std::vector
< OUString
>& rStarts
,
3927 std::vector
< OUString
>& rEnds
)
3929 for ( std::vector
< OUString
>::const_iterator it
= rStarts
.begin(), end
= rStarts
.end(); it
!= end
; ++it
)
3931 OString rName
= OUStringToOString( *it
, RTL_TEXTENCODING_UTF8
).getStr( );
3932 m_rMarksStart
.push_back( rName
);
3936 for ( std::vector
< OUString
>::const_iterator it
= rEnds
.begin(), end
= rEnds
.end(); it
!= end
; ++it
)
3938 OString rName
= OUStringToOString( *it
, RTL_TEXTENCODING_UTF8
).getStr( );
3939 m_rMarksEnd
.push_back( rName
);
3944 void DocxAttributeOutput::TextFootnote_Impl( const SwFmtFtn
& rFootnote
)
3946 const SwEndNoteInfo
& rInfo
= rFootnote
.IsEndNote()?
3947 m_rExport
.pDoc
->GetEndNoteInfo(): m_rExport
.pDoc
->GetFtnInfo();
3949 // footnote/endnote run properties
3950 const SwCharFmt
* pCharFmt
= rInfo
.GetAnchorCharFmt( *m_rExport
.pDoc
);
3952 OString
aStyleId( "style" );
3953 aStyleId
+= OString::valueOf( sal_Int32( m_rExport
.GetId( *pCharFmt
) ) );
3955 m_pSerializer
->singleElementNS( XML_w
, XML_rStyle
, FSNS( XML_w
, XML_val
), aStyleId
.getStr(), FSEND
);
3957 // remember the footnote/endnote to
3958 // 1) write the footnoteReference/endnoteReference in EndRunProperties()
3959 // 2) be able to dump them all to footnotes.xml/endnotes.xml
3960 if ( !rFootnote
.IsEndNote() )
3961 m_pFootnotesList
->add( rFootnote
);
3963 m_pEndnotesList
->add( rFootnote
);
3966 void DocxAttributeOutput::FootnoteEndnoteReference()
3969 const SwFmtFtn
*pFootnote
= m_pFootnotesList
->getCurrent( nId
);
3971 // both cannot be set at the same time - if they are, it's a bug
3973 pFootnote
= m_pEndnotesList
->getCurrent( nId
);
3978 sal_Int32 nToken
= pFootnote
->IsEndNote()? XML_endnoteReference
: XML_footnoteReference
;
3981 if ( pFootnote
->GetNumStr().Len() == 0 )
3984 m_pSerializer
->singleElementNS( XML_w
, nToken
,
3985 FSNS( XML_w
, XML_id
), OString::valueOf( nId
).getStr(),
3991 m_pSerializer
->singleElementNS( XML_w
, nToken
,
3992 FSNS( XML_w
, XML_customMarkFollows
), "1",
3993 FSNS( XML_w
, XML_id
), OString::valueOf( nId
).getStr(),
3996 RunText( pFootnote
->GetNumStr() );
4000 void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes
)
4002 const FootnotesVector
& rVector
= bFootnotes
? m_pFootnotesList
->getVector(): m_pEndnotesList
->getVector();
4004 sal_Int32 nBody
= bFootnotes
? XML_footnotes
: XML_endnotes
;
4005 sal_Int32 nItem
= bFootnotes
? XML_footnote
: XML_endnote
;
4007 m_pSerializer
->startElementNS( XML_w
, nBody
,
4008 FSNS( XML_xmlns
, XML_w
), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
4009 FSNS( XML_xmlns
, XML_r
), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
4012 sal_Int32 nIndex
= 0;
4015 m_pSerializer
->startElementNS( XML_w
, nItem
,
4016 FSNS( XML_w
, XML_id
), OString::valueOf( nIndex
++ ).getStr(),
4017 FSNS( XML_w
, XML_type
), "separator",
4019 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
4020 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
4021 m_pSerializer
->singleElementNS( XML_w
, XML_separator
, FSEND
);
4022 m_pSerializer
->endElementNS( XML_w
, XML_r
);
4023 m_pSerializer
->endElementNS( XML_w
, XML_p
);
4024 m_pSerializer
->endElementNS( XML_w
, nItem
);
4027 m_pSerializer
->startElementNS( XML_w
, nItem
,
4028 FSNS( XML_w
, XML_id
), OString::valueOf( nIndex
++ ).getStr(),
4029 FSNS( XML_w
, XML_type
), "continuationSeparator",
4031 m_pSerializer
->startElementNS( XML_w
, XML_p
, FSEND
);
4032 m_pSerializer
->startElementNS( XML_w
, XML_r
, FSEND
);
4033 m_pSerializer
->singleElementNS( XML_w
, XML_continuationSeparator
, FSEND
);
4034 m_pSerializer
->endElementNS( XML_w
, XML_r
);
4035 m_pSerializer
->endElementNS( XML_w
, XML_p
);
4036 m_pSerializer
->endElementNS( XML_w
, nItem
);
4038 // if new special ones are added, update also WriteFootnoteEndnotePr()
4040 // footnotes/endnotes themselves
4041 for ( FootnotesVector::const_iterator i
= rVector
.begin(); i
!= rVector
.end(); ++i
, ++nIndex
)
4043 m_pSerializer
->startElementNS( XML_w
, nItem
,
4044 FSNS( XML_w
, XML_id
), OString::valueOf( nIndex
).getStr(),
4047 const SwNodeIndex
* pIndex
= (*i
)->GetTxtFtn()->GetStartNode();
4048 // tag required at the start of each footnote/endnote
4049 m_footnoteEndnoteRefTag
= bFootnotes
? XML_footnoteRef
: XML_endnoteRef
;
4051 m_rExport
.WriteSpecialText( pIndex
->GetIndex() + 1,
4052 pIndex
->GetNode().EndOfSectionIndex(),
4053 bFootnotes
? TXT_FTN
: TXT_EDN
);
4055 m_pSerializer
->endElementNS( XML_w
, nItem
);
4058 m_pSerializer
->endElementNS( XML_w
, nBody
);
4062 void DocxAttributeOutput::WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr fs
, int tag
,
4063 const SwEndNoteInfo
& info
, int listtag
)
4065 fs
->startElementNS( XML_w
, tag
, FSEND
);
4066 const char* fmt
= NULL
;
4067 switch( info
.aFmt
.GetNumberingType())
4069 case SVX_NUM_CHARS_UPPER_LETTER_N
: // fall through, map to upper letters
4070 case SVX_NUM_CHARS_UPPER_LETTER
:
4071 fmt
= "upperLetter";
4073 case SVX_NUM_CHARS_LOWER_LETTER_N
: // fall through, map to lower letters
4074 case SVX_NUM_CHARS_LOWER_LETTER
:
4075 fmt
= "lowerLetter";
4077 case SVX_NUM_ROMAN_UPPER
:
4080 case SVX_NUM_ROMAN_LOWER
:
4083 case SVX_NUM_ARABIC
:
4086 case SVX_NUM_NUMBER_NONE
:
4089 case SVX_NUM_CHAR_SPECIAL
:
4092 case SVX_NUM_PAGEDESC
:
4093 case SVX_NUM_BITMAP
:
4098 fs
->singleElementNS( XML_w
, XML_numFmt
, FSNS( XML_w
, XML_val
), fmt
, FSEND
);
4099 if( info
.nFtnOffset
!= 0 )
4100 fs
->singleElementNS( XML_w
, XML_numStart
, FSNS( XML_w
, XML_val
),
4101 OString::valueOf( sal_Int32( info
.nFtnOffset
+ 1 )).getStr(), FSEND
);
4102 if( listtag
!= 0 ) // we are writing to settings.xml, write also special footnote/endnote list
4103 { // there are currently only two hardcoded ones ( see FootnotesEndnotes())
4104 fs
->singleElementNS( XML_w
, listtag
, FSNS( XML_w
, XML_id
), "0", FSEND
);
4105 fs
->singleElementNS( XML_w
, listtag
, FSNS( XML_w
, XML_id
), "1", FSEND
);
4107 fs
->endElementNS( XML_w
, tag
);
4110 void DocxAttributeOutput::SectFootnoteEndnotePr()
4113 WriteFootnoteEndnotePr( m_pSerializer
, XML_footnotePr
, m_rExport
.pDoc
->GetFtnInfo(), 0 );
4115 WriteFootnoteEndnotePr( m_pSerializer
, XML_endnotePr
, m_rExport
.pDoc
->GetEndNoteInfo(), 0 );
4118 void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace
, short nMulti
)
4120 if ( !m_pParagraphSpacingAttrList
)
4121 m_pParagraphSpacingAttrList
= m_pSerializer
->createAttrList();
4125 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_lineRule
), "exact" );
4126 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_line
), OString::valueOf( sal_Int32( -nSpace
) ) );
4130 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_lineRule
), "auto" );
4131 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_line
), OString::valueOf( sal_Int32( nSpace
) ) );
4133 else if ( nSpace
> 0 )
4135 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_lineRule
), "atLeast" );
4136 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_line
), OString::valueOf( sal_Int32( nSpace
) ) );
4139 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_lineRule
), "auto" );
4142 void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem
& rAdjust
)
4144 const char *pAdjustString
;
4146 bool bEcma
= GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
4148 const SfxItemSet
* pItems
= GetExport().GetCurItemSet();
4149 const SvxFrameDirectionItem
* rFrameDir
= static_cast< const SvxFrameDirectionItem
* >( pItems
->GetItem( RES_FRAMEDIR
) );
4151 short nDir
= FRMDIR_ENVIRONMENT
;
4152 if( rFrameDir
!= NULL
)
4153 nDir
= rFrameDir
->GetValue();
4154 if ( nDir
== FRMDIR_ENVIRONMENT
)
4155 nDir
= GetExport( ).GetDefaultFrameDirection( );
4156 bool bRtl
= ( nDir
== FRMDIR_HORI_RIGHT_TOP
);
4158 switch ( rAdjust
.GetAdjust() )
4160 case SVX_ADJUST_LEFT
:
4162 pAdjustString
= "left";
4164 pAdjustString
= "end";
4166 pAdjustString
= "start";
4168 case SVX_ADJUST_RIGHT
:
4170 pAdjustString
= "right";
4172 pAdjustString
= "start";
4174 pAdjustString
= "end";
4176 case SVX_ADJUST_BLOCKLINE
:
4177 case SVX_ADJUST_BLOCK
:
4178 pAdjustString
= "both";
4180 case SVX_ADJUST_CENTER
:
4181 pAdjustString
= "center";
4184 return; // not supported attribute
4186 m_pSerializer
->singleElementNS( XML_w
, XML_jc
, FSNS( XML_w
, XML_val
), pAdjustString
, FSEND
);
4189 void DocxAttributeOutput::ParaSplit( const SvxFmtSplitItem
& rSplit
)
4191 if (rSplit
.GetValue())
4192 m_pSerializer
->singleElementNS( XML_w
, XML_keepLines
, FSNS( XML_w
, XML_val
), "false", FSEND
);
4194 m_pSerializer
->singleElementNS( XML_w
, XML_keepLines
, FSEND
);
4197 void DocxAttributeOutput::ParaWidows( const SvxWidowsItem
& rWidows
)
4199 if (rWidows
.GetValue())
4200 m_pSerializer
->singleElementNS( XML_w
, XML_widowControl
, FSEND
);
4202 m_pSerializer
->singleElementNS( XML_w
, XML_widowControl
, FSNS( XML_w
, XML_val
), "false", FSEND
);
4205 static void impl_WriteTabElement( FSHelperPtr pSerializer
,
4206 const SvxTabStop
& rTab
, long /* nCurrentLeft */ )
4208 FastAttributeList
*pTabElementAttrList
= pSerializer
->createAttrList();
4210 switch (rTab
.GetAdjustment())
4212 case SVX_TAB_ADJUST_RIGHT
:
4213 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( (sal_Char
*)"right") );
4215 case SVX_TAB_ADJUST_DECIMAL
:
4216 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( (sal_Char
*)"decimal") );
4218 case SVX_TAB_ADJUST_CENTER
:
4219 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( (sal_Char
*)"center") );
4221 case SVX_TAB_ADJUST_DEFAULT
:
4222 case SVX_TAB_ADJUST_LEFT
:
4224 pTabElementAttrList
->add( FSNS( XML_w
, XML_val
), OString( (sal_Char
*)"left") );
4228 // Because GetTabPos already includes indent, we don't need to add nCurrentLeft (CurrentLeft is indentation information)
4229 //pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
4230 pTabElementAttrList
->add( FSNS( XML_w
, XML_pos
), OString::valueOf( rTab
.GetTabPos() ) );
4232 sal_Unicode cFillChar
= rTab
.GetFill();
4234 if (sal_Unicode('.') == cFillChar
)
4235 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( (sal_Char
*) "dot" ) );
4236 else if ( sal_Unicode('-') == cFillChar
)
4237 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( (sal_Char
*) "hyphen" ) );
4238 else if ( sal_Unicode(0xB7) == cFillChar
) // middle dot
4239 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( (sal_Char
*) "middleDot" ) );
4240 else if ( sal_Unicode('_') == cFillChar
)
4241 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( (sal_Char
*) "underscore" ) );
4243 pTabElementAttrList
->add( FSNS( XML_w
, XML_leader
), OString( (sal_Char
*) "none" ) );
4245 pSerializer
->singleElementNS( XML_w
, XML_tab
, pTabElementAttrList
);
4248 void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem
& rTabStop
)
4250 const SfxPoolItem
* pLR
= m_rExport
.HasItem( RES_LR_SPACE
);
4251 long nCurrentLeft
= pLR
? ((const SvxLRSpaceItem
*)pLR
)->GetTxtLeft() : 0;
4253 sal_uInt16 nCount
= rTabStop
.Count();
4255 // <w:tabs> must contain at least one <w:tab>, so don't write it empty
4258 if( nCount
== 1 && rTabStop
[ 0 ].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT
)
4260 GetExport().setDefaultTabStop( rTabStop
[ 0 ].GetTabPos());
4264 m_pSerializer
->startElementNS( XML_w
, XML_tabs
, FSEND
);
4266 for (sal_uInt16 i
= 0; i
< nCount
; i
++ )
4268 if( rTabStop
[i
].GetAdjustment() != SVX_TAB_ADJUST_DEFAULT
)
4269 impl_WriteTabElement( m_pSerializer
, rTabStop
[i
], nCurrentLeft
);
4271 GetExport().setDefaultTabStop( rTabStop
[i
].GetTabPos());
4274 m_pSerializer
->endElementNS( XML_w
, XML_tabs
);
4277 void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem
& rHyphenZone
)
4279 m_pSerializer
->singleElementNS( XML_w
, XML_suppressAutoHyphens
,
4280 FSNS( XML_w
, XML_val
), rHyphenZone
.IsHyphen( ) ? "false" : "true" ,
4284 void DocxAttributeOutput::ParaNumRule_Impl( const SwTxtNode
* /*pTxtNd*/, sal_Int32 nLvl
, sal_Int32 nNumId
)
4286 if ( USHRT_MAX
!= nNumId
&& 0 != nNumId
)
4288 m_pSerializer
->startElementNS( XML_w
, XML_numPr
, FSEND
);
4289 m_pSerializer
->singleElementNS( XML_w
, XML_ilvl
, FSNS( XML_w
, XML_val
), OString::valueOf( sal_Int32( nLvl
)).getStr(), FSEND
);
4290 m_pSerializer
->singleElementNS( XML_w
, XML_numId
, FSNS( XML_w
, XML_val
), OString::valueOf( sal_Int32( nNumId
)).getStr(), FSEND
);
4291 m_pSerializer
->endElementNS( XML_w
, XML_numPr
);
4295 void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem
& rScriptSpace
)
4297 sal_uInt16 nXmlElement
= 0;
4299 switch ( rScriptSpace
.Which( ) )
4301 case RES_PARATR_SCRIPTSPACE
:
4302 nXmlElement
= XML_autoSpaceDE
;
4304 case RES_PARATR_HANGINGPUNCTUATION
:
4305 nXmlElement
= XML_overflowPunct
;
4307 case RES_PARATR_FORBIDDEN_RULES
:
4308 nXmlElement
= XML_kinsoku
;
4314 m_pSerializer
->singleElementNS( XML_w
, nXmlElement
,
4315 FSNS( XML_w
, XML_val
), rScriptSpace
.GetValue( ) ? "true": "false",
4320 void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem
& rAlign
)
4322 const char *pAlignString
;
4324 switch ( rAlign
.GetValue() )
4326 case SvxParaVertAlignItem::BASELINE
:
4327 pAlignString
= "baseline";
4329 case SvxParaVertAlignItem::TOP
:
4330 pAlignString
= "top";
4332 case SvxParaVertAlignItem::CENTER
:
4333 pAlignString
= "center";
4335 case SvxParaVertAlignItem::BOTTOM
:
4336 pAlignString
= "bottom";
4338 case SvxParaVertAlignItem::AUTOMATIC
:
4339 pAlignString
= "auto";
4342 return; // not supported attribute
4344 m_pSerializer
->singleElementNS( XML_w
, XML_textAlignment
, FSNS( XML_w
, XML_val
), pAlignString
, FSEND
);
4347 void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem
& rGrid
)
4349 m_pSerializer
->singleElementNS( XML_w
, XML_snapToGrid
,
4350 FSNS( XML_w
, XML_val
), rGrid
.GetValue( ) ? "true": "false",
4354 void DocxAttributeOutput::FormatFrameSize( const SwFmtFrmSize
& rSize
)
4356 if (m_bTextFrameSyntax
&& m_pFlyFrameSize
)
4358 m_aTextFrameStyle
.append(";width:").append(double(m_pFlyFrameSize
->Width()) / 20);
4359 m_aTextFrameStyle
.append("pt;height:").append(double(m_pFlyFrameSize
->Height()) / 20).append("pt");
4361 else if ( m_rExport
.bOutFlyFrmAttrs
)
4363 if ( !m_pFlyAttrList
)
4364 m_pFlyAttrList
= m_pSerializer
->createAttrList( );
4366 if ( rSize
.GetWidth() && rSize
.GetWidthSizeType() == ATT_FIX_SIZE
)
4368 m_pFlyAttrList
->add( FSNS( XML_w
, XML_w
), OString::valueOf( rSize
.GetWidth( ) ) );
4371 if ( rSize
.GetHeight() )
4373 OString
sRule( "exact" );
4374 if ( rSize
.GetHeightSizeType() == ATT_MIN_SIZE
)
4375 sRule
= OString( "atLeast" );
4376 m_pFlyAttrList
->add( FSNS( XML_w
, XML_hRule
), sRule
);
4377 m_pFlyAttrList
->add( FSNS( XML_w
, XML_h
), OString::valueOf( rSize
.GetHeight( ) ) );
4380 else if ( m_rExport
.bOutPageDescs
)
4382 FastAttributeList
*attrList
= m_pSerializer
->createAttrList( );
4383 if ( m_rExport
.pAktPageDesc
->GetLandscape( ) )
4384 attrList
->add( FSNS( XML_w
, XML_orient
), "landscape" );
4386 attrList
->add( FSNS( XML_w
, XML_w
), OString::valueOf( rSize
.GetWidth( ) ) );
4387 attrList
->add( FSNS( XML_w
, XML_h
), OString::valueOf( rSize
.GetHeight( ) ) );
4389 XFastAttributeListRef
xAttrList( attrList
);
4392 m_pSerializer
->singleElementNS( XML_w
, XML_pgSz
, xAttrList
);
4396 void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem
& )
4398 OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()" );
4401 void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem
& rLRSpace
)
4403 bool bEcma
= m_rExport
.GetFilter().getVersion( ) == oox::core::ECMA_DIALECT
;
4405 if (m_bTextFrameSyntax
)
4408 else if ( m_rExport
.bOutFlyFrmAttrs
)
4410 if ( !m_pFlyAttrList
)
4411 m_pFlyAttrList
= m_pSerializer
->createAttrList();
4413 m_pFlyAttrList
->add( FSNS( XML_w
, XML_hSpace
),
4415 sal_Int32( ( rLRSpace
.GetLeft() + rLRSpace
.GetRight() ) / 2 ) ) );
4417 else if ( m_rExport
.bOutPageDescs
)
4419 if ( !m_pSectionSpacingAttrList
)
4420 m_pSectionSpacingAttrList
= m_pSerializer
->createAttrList();
4422 sal_uInt16 nLDist
, nRDist
;
4423 const SfxPoolItem
* pItem
= m_rExport
.HasItem( RES_BOX
);
4426 nRDist
= ((SvxBoxItem
*)pItem
)->CalcLineSpace( BOX_LINE_LEFT
);
4427 nLDist
= ((SvxBoxItem
*)pItem
)->CalcLineSpace( BOX_LINE_RIGHT
);
4430 nLDist
= nRDist
= 0;
4431 nLDist
= nLDist
+ (sal_uInt16
)rLRSpace
.GetLeft();
4432 nRDist
= nRDist
+ (sal_uInt16
)rLRSpace
.GetRight();
4434 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_left
), OString::valueOf( sal_Int32( nLDist
) ) );
4435 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_right
), OString::valueOf( sal_Int32( nRDist
) ) );
4439 FastAttributeList
*pLRSpaceAttrList
= m_pSerializer
->createAttrList();
4441 pLRSpaceAttrList
->add( FSNS( XML_w
, ( bEcma
? XML_left
: XML_start
) ), OString::valueOf( (sal_Int32
) rLRSpace
.GetTxtLeft() ) );
4442 pLRSpaceAttrList
->add( FSNS( XML_w
, ( bEcma
? XML_right
: XML_end
) ), OString::valueOf( (sal_Int32
) rLRSpace
.GetRight() ) );
4444 sal_Int32 nFirstLineAdjustment
= rLRSpace
.GetTxtFirstLineOfst();
4445 if (nFirstLineAdjustment
> 0)
4446 pLRSpaceAttrList
->add( FSNS( XML_w
, XML_firstLine
), OString::valueOf( nFirstLineAdjustment
) );
4448 pLRSpaceAttrList
->add( FSNS( XML_w
, XML_hanging
), OString::valueOf( - nFirstLineAdjustment
) );
4449 m_pSerializer
->singleElementNS( XML_w
, XML_ind
, pLRSpaceAttrList
);
4453 void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem
& rULSpace
)
4456 if (m_bTextFrameSyntax
)
4459 else if ( m_rExport
.bOutFlyFrmAttrs
)
4461 if ( !m_pFlyAttrList
)
4462 m_pFlyAttrList
= m_pSerializer
->createAttrList();
4464 m_pFlyAttrList
->add( FSNS( XML_w
, XML_vSpace
),
4466 sal_Int32( ( rULSpace
.GetLower() + rULSpace
.GetUpper() ) / 2 ) ) );
4468 else if (m_rExport
.bOutPageDescs
)
4470 OSL_ENSURE( m_rExport
.GetCurItemSet(), "Impossible" );
4471 if ( !m_rExport
.GetCurItemSet() )
4474 if ( !m_pSectionSpacingAttrList
)
4475 m_pSectionSpacingAttrList
= m_pSerializer
->createAttrList();
4477 HdFtDistanceGlue
aDistances( *m_rExport
.GetCurItemSet() );
4479 sal_Int32 nHeader
= 0;
4480 if ( aDistances
.HasHeader() )
4481 nHeader
= sal_Int32( aDistances
.dyaHdrTop
);
4482 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_header
), OString::valueOf( nHeader
) );
4485 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_top
),
4486 OString::valueOf( sal_Int32( aDistances
.dyaTop
) ) );
4488 sal_Int32 nFooter
= 0;
4489 if ( aDistances
.HasFooter() )
4490 nFooter
= sal_Int32( aDistances
.dyaHdrBottom
);
4491 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_footer
), OString::valueOf( nFooter
) );
4494 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_bottom
),
4495 OString::valueOf( sal_Int32( aDistances
.dyaBottom
) ) );
4497 // FIXME Page Gutter is not handled ATM, setting to 0 as it's mandatory for OOXML
4498 m_pSectionSpacingAttrList
->add( FSNS( XML_w
, XML_gutter
),
4499 OString::valueOf( sal_Int32( 0 ) ) );
4504 if ( !m_pParagraphSpacingAttrList
)
4505 m_pParagraphSpacingAttrList
= m_pSerializer
->createAttrList();
4506 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_before
),
4507 OString::valueOf( (sal_Int32
)rULSpace
.GetUpper() ) );
4508 m_pParagraphSpacingAttrList
->add( FSNS( XML_w
, XML_after
),
4509 OString::valueOf( (sal_Int32
)rULSpace
.GetLower() ) );
4510 if (rULSpace
.GetContext())
4511 m_pSerializer
->singleElementNS( XML_w
, XML_contextualSpacing
, FSEND
);
4513 m_pSerializer
->singleElementNS( XML_w
, XML_contextualSpacing
, FSNS( XML_w
, XML_val
), "false", FSEND
);
4517 void DocxAttributeOutput::FormatSurround( const SwFmtSurround
& rSurround
)
4519 if (m_bTextFrameSyntax
)
4521 OString sType
, sSide
;
4522 switch (rSurround
.GetSurround())
4525 sType
= "topAndBottom";
4527 case SURROUND_PARALLEL
:
4530 case SURROUND_IDEAL
:
4538 case SURROUND_RIGHT
:
4542 case SURROUND_THROUGHT
:
4543 /* empty type and side means throught */
4547 if (!sType
.isEmpty() || !sSide
.isEmpty())
4549 m_pFlyWrapAttrList
= m_pSerializer
->createAttrList();
4550 if (!sType
.isEmpty())
4551 m_pFlyWrapAttrList
->add(XML_type
, sType
);
4552 if (!sSide
.isEmpty())
4553 m_pFlyWrapAttrList
->add(XML_side
, sSide
);
4556 else if ( m_rExport
.bOutFlyFrmAttrs
)
4558 if ( !m_pFlyAttrList
)
4559 m_pFlyAttrList
= m_pSerializer
->createAttrList();
4561 OString
sWrap( "auto" );
4562 switch ( rSurround
.GetSurround( ) )
4565 sWrap
= OString( "none" );
4567 case SURROUND_THROUGHT
:
4568 sWrap
= OString( "through" );
4570 case SURROUND_IDEAL
:
4571 case SURROUND_PARALLEL
:
4573 case SURROUND_RIGHT
:
4575 sWrap
= OString( "around" );
4578 m_pFlyAttrList
->add( FSNS( XML_w
, XML_wrap
), sWrap
);
4582 void DocxAttributeOutput::FormatVertOrientation( const SwFmtVertOrient
& rFlyVert
)
4584 if (m_bTextFrameSyntax
)
4586 m_aTextFrameStyle
.append(";margin-top:").append(double(rFlyVert
.GetPos()) / 20).append("pt");
4588 else if ( m_rExport
.bOutFlyFrmAttrs
)
4590 if ( !m_pFlyAttrList
)
4591 m_pFlyAttrList
= m_pSerializer
->createAttrList();
4594 switch( rFlyVert
.GetVertOrient() )
4596 case text::VertOrientation::NONE
:
4598 case text::VertOrientation::CENTER
:
4599 case text::VertOrientation::LINE_CENTER
:
4600 sAlign
= OString( "center" );
4602 case text::VertOrientation::BOTTOM
:
4603 case text::VertOrientation::LINE_BOTTOM
:
4604 sAlign
= OString( "bottom" );
4606 case text::VertOrientation::TOP
:
4607 case text::VertOrientation::LINE_TOP
:
4609 sAlign
= OString( "top" );
4613 if ( !sAlign
.isEmpty() )
4614 m_pFlyAttrList
->add( FSNS( XML_w
, XML_yAlign
), sAlign
);
4616 m_pFlyAttrList
->add( FSNS( XML_w
, XML_y
),
4617 OString::valueOf( sal_Int32( rFlyVert
.GetPos() ) ) );
4619 OString
sVAnchor( "page" );
4620 switch ( rFlyVert
.GetRelationOrient( ) )
4622 case text::RelOrientation::CHAR
:
4623 case text::RelOrientation::PRINT_AREA
:
4624 case text::RelOrientation::TEXT_LINE
:
4625 sVAnchor
= OString( "column" );
4627 case text::RelOrientation::FRAME
:
4628 case text::RelOrientation::PAGE_LEFT
:
4629 case text::RelOrientation::PAGE_RIGHT
:
4630 case text::RelOrientation::FRAME_LEFT
:
4631 case text::RelOrientation::FRAME_RIGHT
:
4632 sVAnchor
= OString( "margin" );
4634 case text::RelOrientation::PAGE_FRAME
:
4635 case text::RelOrientation::PAGE_PRINT_AREA
:
4640 m_pFlyAttrList
->add( FSNS( XML_w
, XML_vAnchor
), sVAnchor
);
4644 void DocxAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient
& rFlyHori
)
4646 if (m_bTextFrameSyntax
)
4648 m_aTextFrameStyle
.append(";margin-left:").append(double(rFlyHori
.GetPos()) / 20).append("pt");
4650 else if ( m_rExport
.bOutFlyFrmAttrs
)
4652 if ( !m_pFlyAttrList
)
4653 m_pFlyAttrList
= m_pSerializer
->createAttrList();
4656 switch( rFlyHori
.GetHoriOrient() )
4658 case text::HoriOrientation::NONE
:
4660 case text::HoriOrientation::LEFT
:
4661 sAlign
= OString( rFlyHori
.IsPosToggle( ) ? "inside" : "left" );
4663 case text::HoriOrientation::RIGHT
:
4664 sAlign
= OString( rFlyHori
.IsPosToggle( ) ? "outside" : "right" );
4666 case text::HoriOrientation::CENTER
:
4667 case text::HoriOrientation::FULL
: // FULL only for tables
4669 sAlign
= OString( "center" );
4673 if ( !sAlign
.isEmpty() )
4674 m_pFlyAttrList
->add( FSNS( XML_w
, XML_xAlign
), sAlign
);
4676 m_pFlyAttrList
->add( FSNS( XML_w
, XML_x
),
4677 OString::valueOf( sal_Int32( rFlyHori
.GetPos() ) ) );
4679 OString
sHAnchor( "page" );
4680 switch ( rFlyHori
.GetRelationOrient( ) )
4682 case text::RelOrientation::CHAR
:
4683 case text::RelOrientation::PRINT_AREA
:
4684 sHAnchor
= OString( "text" );
4686 case text::RelOrientation::FRAME
:
4687 case text::RelOrientation::PAGE_LEFT
:
4688 case text::RelOrientation::PAGE_RIGHT
:
4689 case text::RelOrientation::FRAME_LEFT
:
4690 case text::RelOrientation::FRAME_RIGHT
:
4691 sHAnchor
= OString( "margin" );
4693 case text::RelOrientation::PAGE_FRAME
:
4694 case text::RelOrientation::PAGE_PRINT_AREA
:
4699 m_pFlyAttrList
->add( FSNS( XML_w
, XML_hAnchor
), sHAnchor
);
4703 void DocxAttributeOutput::FormatAnchor( const SwFmtAnchor
& )
4705 // Fly frames: anchors here aren't matching the anchors in docx
4708 void DocxAttributeOutput::FormatBackground( const SvxBrushItem
& rBrush
)
4710 OString sColor
= msfilter::util::ConvertColor( rBrush
.GetColor( ) );
4711 if (m_bTextFrameSyntax
)
4712 m_pFlyAttrList
->add(XML_fillcolor
, "#" + sColor
);
4713 else if ( !m_rExport
.bOutPageDescs
)
4715 m_pSerializer
->singleElementNS( XML_w
, XML_shd
,
4716 FSNS( XML_w
, XML_fill
), sColor
.getStr( ),
4717 FSNS( XML_w
, XML_val
), "clear",
4722 void DocxAttributeOutput::FormatFillStyle( const XFillStyleItem
& rFillStyle
)
4724 m_oFillStyle
.reset(rFillStyle
.GetValue());
4727 void DocxAttributeOutput::FormatFillGradient( const XFillGradientItem
& rFillGradient
)
4729 if (*m_oFillStyle
== XFILL_GRADIENT
)
4731 m_pFlyFillAttrList
= m_pSerializer
->createAttrList();
4732 m_pFlyFillAttrList
->add(XML_type
, "gradient");
4734 const XGradient
& rGradient
= rFillGradient
.GetGradientValue();
4735 OString sStartColor
= msfilter::util::ConvertColor(rGradient
.GetStartColor());
4736 m_pFlyFillAttrList
->add(XML_color2
, "#" + sStartColor
);
4737 OString sEndColor
= msfilter::util::ConvertColor(rGradient
.GetEndColor());
4738 m_pFlyAttrList
->add(XML_fillcolor
, "#" + sEndColor
);
4740 switch (rGradient
.GetGradientStyle())
4742 case XGRAD_LINEAR
: break;
4744 m_pFlyFillAttrList
->add(XML_focus
, "50%");
4746 case XGRAD_RADIAL
: break;
4747 case XGRAD_ELLIPTICAL
: break;
4748 case XGRAD_SQUARE
: break;
4749 case XGRAD_RECT
: break;
4752 m_oFillStyle
.reset();
4755 void DocxAttributeOutput::FormatBox( const SvxBoxItem
& rBox
)
4757 if (m_bTextFrameSyntax
)
4759 const SvxBorderLine
* pLeft
= rBox
.GetLine(BOX_LINE_LEFT
);
4760 const SvxBorderLine
* pRight
= rBox
.GetLine(BOX_LINE_RIGHT
);
4761 const SvxBorderLine
* pTop
= rBox
.GetLine(BOX_LINE_TOP
);
4762 const SvxBorderLine
* pBottom
= rBox
.GetLine(BOX_LINE_BOTTOM
);
4763 if (pLeft
&& pRight
&& pTop
&& pBottom
&&
4764 *pLeft
== *pRight
&& *pLeft
== *pTop
&& *pLeft
== *pBottom
)
4766 OString
sColor("#" + msfilter::util::ConvertColor(pTop
->GetColor()));
4767 m_pFlyAttrList
->add(XML_strokecolor
, sColor
);
4769 double const fConverted(editeng::ConvertBorderWidthToWord(pTop
->GetBorderLineStyle(), pTop
->GetWidth()));
4770 sal_Int32 nWidth
= sal_Int32(fConverted
/ 20);
4771 m_pFlyAttrList
->add(XML_strokeweight
, OString::valueOf(nWidth
) + "pt");
4774 // v:textbox's inset attribute: inner margin values for textbox text
4775 OStringBuffer aInset
;
4776 aInset
.append(OString::number(double(rBox
.GetDistance(BOX_LINE_LEFT
))/20) + "pt,");
4777 aInset
.append(OString::number(double(rBox
.GetDistance(BOX_LINE_TOP
))/20) + "pt,");
4778 aInset
.append(OString::number(double(rBox
.GetDistance(BOX_LINE_RIGHT
))/20) + "pt,");
4779 aInset
.append(OString::number(double(rBox
.GetDistance(BOX_LINE_BOTTOM
))/20) + "pt");
4780 m_pTextboxAttrList
->add(XML_inset
, aInset
.makeStringAndClear());
4784 if ( !m_bOpenedSectPr
)
4786 // Normally open the borders tag for paragraphs
4787 m_pSerializer
->startElementNS( XML_w
, XML_pBdr
, FSEND
);
4790 impl_pageBorders( m_pSerializer
, rBox
, XML_pBdr
, false, false );
4792 if ( m_bOpenedSectPr
)
4794 // Special handling for pgBorder
4795 m_pSerializer
->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND
);
4796 m_pSerializer
->mergeTopMarks( );
4800 // Normally close the borders tag for paragraphs
4801 m_pSerializer
->endElementNS( XML_w
, XML_pBdr
);
4805 void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols
, const SwFmtCol
& rCol
, bool bEven
, SwTwips nPageSize
)
4807 // Get the columns attributes
4808 FastAttributeList
*pColsAttrList
= m_pSerializer
->createAttrList();
4810 pColsAttrList
->add( FSNS( XML_w
, XML_num
),
4811 OString::valueOf( sal_Int32( nCols
) ). getStr( ) );
4813 const char* pEquals
= "false";
4816 sal_uInt16 nWidth
= rCol
.GetGutterWidth( true );
4817 pColsAttrList
->add( FSNS( XML_w
, XML_space
),
4818 OString::valueOf( sal_Int32( nWidth
) ).getStr( ) );
4823 pColsAttrList
->add( FSNS( XML_w
, XML_equalWidth
), pEquals
);
4825 bool bHasSep
= COLADJ_NONE
== rCol
.GetLineAdj( );
4826 pColsAttrList
->add( FSNS( XML_w
, XML_sep
), bHasSep
? "true" : "false" );
4828 // Write the element
4829 m_pSerializer
->startElementNS( XML_w
, XML_cols
, pColsAttrList
);
4831 // Write the columns width if non-equals
4832 const SwColumns
& rColumns
= rCol
.GetColumns( );
4835 for ( sal_uInt16 n
= 0; n
< nCols
; ++n
)
4837 FastAttributeList
*pColAttrList
= m_pSerializer
->createAttrList();
4838 sal_uInt16 nWidth
= rCol
.CalcPrtColWidth( n
, ( sal_uInt16
) nPageSize
);
4839 pColAttrList
->add( FSNS( XML_w
, XML_w
),
4840 OString::valueOf( sal_Int32( nWidth
) ).getStr( ) );
4842 if ( n
+ 1 != nCols
)
4844 sal_uInt16 nSpacing
= rColumns
[n
].GetRight( ) + rColumns
[n
+ 1].GetLeft( );
4845 pColAttrList
->add( FSNS( XML_w
, XML_space
),
4846 OString::valueOf( sal_Int32( nSpacing
) ).getStr( ) );
4849 m_pSerializer
->singleElementNS( XML_w
, XML_col
, pColAttrList
);
4853 m_pSerializer
->endElementNS( XML_w
, XML_cols
);
4856 void DocxAttributeOutput::FormatKeep( const SvxFmtKeepItem
& )
4858 m_pSerializer
->singleElementNS( XML_w
, XML_keepNext
, FSEND
);
4861 void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem
& rGrid
)
4863 FastAttributeList
*pGridAttrList
= m_pSerializer
->createAttrList();
4866 switch ( rGrid
.GetGridType( ) )
4870 sGridType
= OString( "default" );
4872 case GRID_LINES_ONLY
:
4873 sGridType
= OString( "lines" );
4875 case GRID_LINES_CHARS
:
4876 if ( rGrid
.IsSnapToChars( ) )
4877 sGridType
= OString( "snapToChars" );
4879 sGridType
= OString( "linesAndChars" );
4882 pGridAttrList
->add( FSNS( XML_w
, XML_type
), sGridType
.getStr( ) );
4884 sal_uInt16 nHeight
= rGrid
.GetBaseHeight() + rGrid
.GetRubyHeight();
4885 pGridAttrList
->add( FSNS( XML_w
, XML_linePitch
),
4886 OString::valueOf( sal_Int32( nHeight
) ).getStr( ) );
4888 pGridAttrList
->add( FSNS( XML_w
, XML_charSpace
),
4889 OString::valueOf( sal_Int32( GridCharacterPitch( rGrid
) ) ).getStr( ) );
4891 m_pSerializer
->singleElementNS( XML_w
, XML_docGrid
, pGridAttrList
);
4894 void DocxAttributeOutput::FormatLineNumbering( const SwFmtLineNumber
& rNumbering
)
4896 if ( !rNumbering
.IsCount( ) )
4897 m_pSerializer
->singleElementNS( XML_w
, XML_suppressLineNumbers
, FSEND
);
4900 void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem
& rDirection
)
4904 short nDir
= rDirection
.GetValue();
4906 if ( nDir
== FRMDIR_ENVIRONMENT
)
4907 nDir
= GetExport( ).GetDefaultFrameDirection( );
4912 case FRMDIR_HORI_LEFT_TOP
:
4913 sTextFlow
= OString( "lrTb" );
4915 case FRMDIR_HORI_RIGHT_TOP
:
4916 sTextFlow
= OString( "lrTb" );
4919 case FRMDIR_VERT_TOP_LEFT
: // many things but not this one
4920 case FRMDIR_VERT_TOP_RIGHT
:
4921 sTextFlow
= OString( "tbRl" );
4925 if ( m_rExport
.bOutPageDescs
)
4927 m_pSerializer
->singleElementNS( XML_w
, XML_textDirection
,
4928 FSNS( XML_w
, XML_val
), sTextFlow
.getStr( ),
4931 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSEND
);
4933 else if ( !m_rExport
.bOutFlyFrmAttrs
)
4936 m_pSerializer
->singleElementNS( XML_w
, XML_bidi
, FSEND
);
4940 DocxAttributeOutput::DocxAttributeOutput( DocxExport
&rExport
, FSHelperPtr pSerializer
, oox::drawingml::DrawingML
* pDrawingML
)
4941 : m_rExport( rExport
),
4942 m_pSerializer( pSerializer
),
4943 m_rDrawingML( *pDrawingML
),
4944 m_pFontsAttrList( NULL
),
4945 m_pEastAsianLayoutAttrList( NULL
),
4946 m_pCharLangAttrList( NULL
),
4947 m_pSectionSpacingAttrList( NULL
),
4948 m_pParagraphSpacingAttrList( NULL
),
4949 m_pHyperlinkAttrList( NULL
),
4950 m_pFlyAttrList( NULL
),
4951 m_pFlyFillAttrList( NULL
),
4952 m_pFlyWrapAttrList( NULL
),
4953 m_pTextboxAttrList( NULL
),
4955 m_pFootnotesList( new ::docx::FootnotesList() ),
4956 m_pEndnotesList( new ::docx::FootnotesList() ),
4957 m_footnoteEndnoteRefTag( 0 ),
4958 m_pSectionInfo( NULL
),
4959 m_pRedlineData( NULL
),
4961 m_bOpenedSectPr( false ),
4964 m_bPostitStart(false),
4965 m_bPostitEnd(false),
4966 m_pTableWrt( NULL
),
4967 m_bTableCellOpen( false ),
4969 m_bParagraphOpened( false ),
4970 m_nColBreakStatus( COLBRK_NONE
),
4971 m_bTextFrameSyntax( false ),
4972 m_closeHyperlinkInThisRun( false ),
4973 m_closeHyperlinkInPreviousRun( false ),
4974 m_startedHyperlink( false ),
4975 m_postponedGraphic( NULL
),
4976 m_postponedMath( NULL
),
4977 pendingPlaceholder( NULL
),
4978 m_postitFieldsMaxId( 0 ),
4985 DocxAttributeOutput::~DocxAttributeOutput()
4987 delete m_pFontsAttrList
, m_pFontsAttrList
= NULL
;
4988 delete m_pEastAsianLayoutAttrList
, m_pEastAsianLayoutAttrList
= NULL
;
4989 delete m_pCharLangAttrList
, m_pCharLangAttrList
= NULL
;
4990 delete m_pSectionSpacingAttrList
, m_pSectionSpacingAttrList
= NULL
;
4991 delete m_pParagraphSpacingAttrList
, m_pParagraphSpacingAttrList
= NULL
;
4992 delete m_pHyperlinkAttrList
, m_pHyperlinkAttrList
= NULL
;
4993 delete m_pFlyAttrList
, m_pFlyAttrList
= NULL
;
4994 delete m_pTextboxAttrList
, m_pTextboxAttrList
= NULL
;
4996 delete m_pFootnotesList
, m_pFootnotesList
= NULL
;
4997 delete m_pEndnotesList
, m_pEndnotesList
= NULL
;
4999 delete m_pTableWrt
, m_pTableWrt
= NULL
;
5002 DocxExport
& DocxAttributeOutput::GetExport()
5007 bool DocxAttributeOutput::HasFootnotes() const
5009 return !m_pFootnotesList
->isEmpty();
5012 bool DocxAttributeOutput::HasEndnotes() const
5014 return !m_pEndnotesList
->isEmpty();
5017 bool DocxAttributeOutput::HasPostitFields() const
5019 return !m_postitFields
.empty();
5022 void DocxAttributeOutput::BulletDefinition(int nId
, const Graphic
& rGraphic
, Size aSize
)
5024 m_pSerializer
->startElementNS(XML_w
, XML_numPicBullet
,
5025 FSNS(XML_w
, XML_numPicBulletId
), OString::number(nId
).getStr(),
5028 OStringBuffer aStyle
;
5029 // Size is in twips, we need it in points.
5030 aStyle
.append("width:").append(double(aSize
.Width()) / 20);
5031 aStyle
.append("pt;height:").append(double(aSize
.Height()) / 20).append("pt");
5032 m_pSerializer
->startElementNS( XML_w
, XML_pict
, FSEND
);
5033 m_pSerializer
->startElementNS( XML_v
, XML_shape
,
5034 XML_style
, aStyle
.getStr(),
5035 FSNS(XML_o
, XML_bullet
), "t",
5038 m_rDrawingML
.SetFS(m_pSerializer
);
5039 OUString aRelId
= m_rDrawingML
.WriteImage(rGraphic
);
5040 m_pSerializer
->singleElementNS( XML_v
, XML_imagedata
,
5041 FSNS(XML_r
, XML_id
), OUStringToOString(aRelId
, RTL_TEXTENCODING_UTF8
),
5042 FSNS(XML_o
, XML_title
), "",
5045 m_pSerializer
->endElementNS(XML_v
, XML_shape
);
5046 m_pSerializer
->endElementNS(XML_w
, XML_pict
);
5048 m_pSerializer
->endElementNS(XML_w
, XML_numPicBullet
);
5051 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */