Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "docxattributeoutput.hxx"
21 : #include "docxexportfilter.hxx"
22 : #include "docxfootnotes.hxx"
23 : #include "writerwordglue.hxx"
24 : #include "ww8par.hxx"
25 : #include "fmtcntnt.hxx"
26 : #include "fchrfmt.hxx"
27 : #include "tgrditem.hxx"
28 : #include "fmtruby.hxx"
29 : #include "breakit.hxx"
30 :
31 : #include <comphelper/string.hxx>
32 : #include <oox/token/tokens.hxx>
33 : #include <oox/export/utils.hxx>
34 : #include <oox/mathml/export.hxx>
35 :
36 : #include <i18nlangtag/languagetag.hxx>
37 :
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>
76 :
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>
85 : #include <frmatr.hxx>
86 : #include <ftninfo.hxx>
87 : #include <htmltbl.hxx>
88 : #include <lineinfo.hxx>
89 : #include <ndgrf.hxx>
90 : #include <ndole.hxx>
91 : #include <ndtxt.hxx>
92 : #include <pagedesc.hxx>
93 : #include <paratr.hxx>
94 : #include <charatr.hxx>
95 : #include <swmodule.hxx>
96 : #include <swtable.hxx>
97 : #include <txtftn.hxx>
98 : #include <txtinet.hxx>
99 :
100 : #include <osl/file.hxx>
101 : #include <rtl/tencinfo.h>
102 : #include <vcl/embeddedfontshelper.hxx>
103 :
104 : #include <com/sun/star/i18n/ScriptType.hpp>
105 : #include <com/sun/star/chart2/XChartDocument.hpp>
106 : #include <com/sun/star/drawing/ShadingPattern.hpp>
107 :
108 : #if OSL_DEBUG_LEVEL > 1
109 : #include <stdio.h>
110 : #endif
111 :
112 : using ::editeng::SvxBorderLine;
113 :
114 : using namespace oox;
115 : using namespace docx;
116 : using namespace sax_fastparser;
117 : using namespace nsSwDocInfoSubType;
118 : using namespace nsFieldFlags;
119 : using namespace sw::util;
120 : using namespace ::com::sun::star;
121 : using namespace ::com::sun::star::drawing;
122 :
123 0 : class FFDataWriterHelper
124 : {
125 : ::sax_fastparser::FSHelperPtr m_pSerializer;
126 0 : void writeCommonStart( const OUString& rName )
127 : {
128 0 : m_pSerializer->startElementNS( XML_w, XML_ffData, FSEND );
129 : m_pSerializer->singleElementNS( XML_w, XML_name,
130 : FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
131 0 : FSEND );
132 0 : m_pSerializer->singleElementNS( XML_w, XML_enabled, FSEND );
133 : m_pSerializer->singleElementNS( XML_w, XML_calcOnExit,
134 : FSNS( XML_w, XML_val ),
135 0 : "0", FSEND );
136 0 : }
137 0 : void writeFinish()
138 : {
139 0 : m_pSerializer->endElementNS( XML_w, XML_ffData );
140 0 : }
141 : public:
142 0 : FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr pSerializer ) : m_pSerializer( pSerializer ){}
143 0 : void WriteFormCheckbox( const OUString& rName, const OUString& rDefault, bool bChecked )
144 : {
145 0 : writeCommonStart( rName );
146 : // Checkbox specific bits
147 0 : m_pSerializer->startElementNS( XML_w, XML_checkBox, FSEND );
148 : // currently hardcoding autosize
149 : // #TODO check if this defaulted
150 0 : m_pSerializer->startElementNS( XML_w, XML_sizeAuto, FSEND );
151 0 : m_pSerializer->endElementNS( XML_w, XML_sizeAuto );
152 0 : if ( !rDefault.isEmpty() )
153 : {
154 : m_pSerializer->singleElementNS( XML_w, XML_default,
155 : FSNS( XML_w, XML_val ),
156 0 : OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
157 : }
158 0 : if ( bChecked )
159 0 : m_pSerializer->singleElementNS( XML_w, XML_checked, FSEND );
160 0 : m_pSerializer->endElementNS( XML_w, XML_checkBox );
161 0 : writeFinish();
162 0 : }
163 0 : void WriteFormText( const OUString& rName, const OUString& rDefault )
164 : {
165 0 : writeCommonStart( rName );
166 0 : if ( !rDefault.isEmpty() )
167 : {
168 0 : m_pSerializer->startElementNS( XML_w, XML_textInput, FSEND );
169 : m_pSerializer->singleElementNS( XML_w, XML_default,
170 : FSNS( XML_w, XML_val ),
171 0 : OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
172 0 : m_pSerializer->endElementNS( XML_w, XML_textInput );
173 : }
174 0 : writeFinish();
175 0 : }
176 : };
177 :
178 : class FieldMarkParamsHelper
179 : {
180 : const sw::mark::IFieldmark& mrFieldmark;
181 : public:
182 0 : FieldMarkParamsHelper( const sw::mark::IFieldmark& rFieldmark ) : mrFieldmark( rFieldmark ) {}
183 0 : OUString getName() { return mrFieldmark.GetName(); }
184 : template < typename T >
185 0 : bool extractParam( const OUString& rKey, T& rResult )
186 : {
187 0 : bool bResult = false;
188 0 : if ( mrFieldmark.GetParameters() )
189 : {
190 0 : sw::mark::IFieldmark::parameter_map_t::const_iterator it = mrFieldmark.GetParameters()->find( rKey );
191 0 : if ( it != mrFieldmark.GetParameters()->end() )
192 0 : bResult = ( it->second >>= rResult );
193 : }
194 0 : return bResult;
195 : }
196 : };
197 289 : void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
198 : {
199 289 : if (bIsRTL)
200 0 : m_pSerializer->singleElementNS( XML_w, XML_rtl, FSNS( XML_w, XML_val ), "true", FSEND );
201 289 : }
202 :
203 228 : void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
204 : {
205 228 : if ( m_nColBreakStatus == COLBRK_POSTPONE )
206 0 : m_nColBreakStatus = COLBRK_WRITE;
207 :
208 : // Output table/table row/table cell starts if needed
209 228 : if ( pTextNodeInfo.get() )
210 : {
211 47 : sal_uInt32 nRow = pTextNodeInfo->getRow();
212 47 : sal_uInt32 nCell = pTextNodeInfo->getCell();
213 :
214 : // New cell/row?
215 47 : if ( m_nTableDepth > 0 && !m_bTableCellOpen )
216 : {
217 38 : ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) );
218 38 : if ( pDeepInner->getCell() == 0 )
219 8 : StartTableRow( pDeepInner );
220 :
221 38 : StartTableCell( pDeepInner );
222 : }
223 :
224 47 : if ( nRow == 0 && nCell == 0 )
225 : {
226 : // Do we have to start the table?
227 : // [If we are at the rigth depth already, it means that we
228 : // continue the table cell]
229 9 : sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
230 :
231 9 : if ( nCurrentDepth > m_nTableDepth )
232 : {
233 : // Start all the tables that begin here
234 18 : for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
235 : {
236 9 : ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
237 :
238 9 : StartTable( pInner );
239 9 : StartTableRow( pInner );
240 9 : StartTableCell( pInner );
241 9 : }
242 :
243 9 : m_nTableDepth = nCurrentDepth;
244 : }
245 : }
246 : }
247 :
248 228 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
249 :
250 : // postpone the output of the run (we get it before the paragraph
251 : // properties, but must write it after them)
252 228 : m_pSerializer->mark();
253 :
254 : // no section break in this paragraph yet; can be set in SectionBreak()
255 228 : m_pSectionInfo.reset();
256 :
257 228 : m_bParagraphOpened = true;
258 228 : }
259 :
260 8 : void lcl_TextFrameShadow(FSHelperPtr pSerializer, const SwFrmFmt& rFrmFmt)
261 : {
262 8 : SvxShadowItem aShadowItem = rFrmFmt.GetShadow();
263 8 : if (aShadowItem.GetLocation() == SVX_SHADOW_NONE)
264 5 : return;
265 :
266 6 : OString aShadowWidth( OString::valueOf( double( aShadowItem.GetWidth() ) / 20) + "pt");
267 6 : OString aOffset;
268 3 : switch (aShadowItem.GetLocation())
269 : {
270 0 : case SVX_SHADOW_TOPLEFT: aOffset = "-" + aShadowWidth + ",-" + aShadowWidth; break;
271 0 : case SVX_SHADOW_TOPRIGHT: aOffset = aShadowWidth + ",-" + aShadowWidth; break;
272 0 : case SVX_SHADOW_BOTTOMLEFT: aOffset = "-" + aShadowWidth + "," + aShadowWidth; break;
273 3 : case SVX_SHADOW_BOTTOMRIGHT: aOffset = aShadowWidth + "," + aShadowWidth; break;
274 : case SVX_SHADOW_NONE:
275 : case SVX_SHADOW_END:
276 0 : break;
277 : }
278 3 : if (aOffset.isEmpty())
279 0 : return;
280 :
281 3 : OString aShadowColor = msfilter::util::ConvertColor(aShadowItem.GetColor());
282 : pSerializer->singleElementNS(XML_v, XML_shadow,
283 : XML_on, "t",
284 6 : XML_color, "#" + aShadowColor,
285 : XML_offset, aOffset,
286 9 : FSEND);
287 : }
288 :
289 228 : void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
290 : {
291 : // write the paragraph properties + the run, already in the correct order
292 228 : m_pSerializer->mergeTopMarks();
293 :
294 : // Write the anchored frame if any
295 228 : if ( m_pParentFrame )
296 : {
297 8 : sw::Frame *pParentFrame = m_pParentFrame;
298 8 : m_pParentFrame = NULL;
299 :
300 8 : const SwFrmFmt& rFrmFmt = pParentFrame->GetFrmFmt( );
301 8 : const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
302 :
303 8 : sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
304 8 : sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
305 :
306 8 : m_rExport.SaveData( nStt, nEnd );
307 :
308 8 : m_rExport.mpParentFrame = pParentFrame;
309 :
310 : // When a frame has some low height, but automatically expanded due
311 : // to lots of contents, this size contains the real size.
312 8 : const Size aSize = pParentFrame->GetSize();
313 8 : m_pFlyFrameSize = &aSize;
314 :
315 8 : m_bTextFrameSyntax = true;
316 8 : m_pFlyAttrList = m_pSerializer->createAttrList( );
317 8 : m_pTextboxAttrList = m_pSerializer->createAttrList();
318 8 : m_aTextFrameStyle = "position:absolute";
319 8 : m_rExport.OutputFormat( pParentFrame->GetFrmFmt(), false, false, true );
320 8 : m_pFlyAttrList->add(XML_style, m_aTextFrameStyle.makeStringAndClear());
321 8 : XFastAttributeListRef xFlyAttrList( m_pFlyAttrList );
322 8 : m_pFlyAttrList = NULL;
323 16 : XFastAttributeListRef xTextboxAttrList(m_pTextboxAttrList);
324 8 : m_pTextboxAttrList = NULL;
325 8 : m_bTextFrameSyntax = false;
326 8 : m_pFlyFrameSize = 0;
327 :
328 8 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
329 8 : m_pSerializer->startElementNS( XML_w, XML_pict, FSEND );
330 8 : m_pSerializer->startElementNS( XML_v, XML_rect, xFlyAttrList );
331 8 : lcl_TextFrameShadow(m_pSerializer, rFrmFmt);
332 8 : if (m_pFlyFillAttrList)
333 : {
334 2 : XFastAttributeListRef xFlyFillAttrList(m_pFlyFillAttrList);
335 2 : m_pFlyFillAttrList = NULL;
336 2 : m_pSerializer->singleElementNS(XML_v, XML_fill, xFlyFillAttrList);
337 : }
338 8 : m_pSerializer->startElementNS( XML_v, XML_textbox, xTextboxAttrList );
339 8 : m_pSerializer->startElementNS( XML_w, XML_txbxContent, FSEND );
340 8 : m_rExport.WriteText( );
341 8 : m_pSerializer->endElementNS( XML_w, XML_txbxContent );
342 8 : m_pSerializer->endElementNS( XML_v, XML_textbox );
343 :
344 8 : if (m_pFlyWrapAttrList)
345 : {
346 6 : XFastAttributeListRef xFlyWrapAttrList(m_pFlyWrapAttrList);
347 6 : m_pFlyWrapAttrList = NULL;
348 6 : m_pSerializer->singleElementNS(XML_w10, XML_wrap, xFlyWrapAttrList);
349 : }
350 :
351 8 : m_pSerializer->endElementNS( XML_v, XML_rect );
352 8 : m_pSerializer->endElementNS( XML_w, XML_pict );
353 8 : m_pSerializer->endElementNS( XML_w, XML_r );
354 :
355 8 : m_rExport.RestoreData();
356 :
357 8 : m_rExport.mpParentFrame = NULL;
358 :
359 16 : delete pParentFrame;
360 : }
361 :
362 228 : m_pSerializer->endElementNS( XML_w, XML_p );
363 :
364 : // Check for end of cell, rows, tables here
365 228 : FinishTableRowCell( pTextNodeInfoInner );
366 :
367 228 : m_bParagraphOpened = false;
368 :
369 228 : }
370 :
371 322 : void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
372 : {
373 322 : if ( pInner.get() )
374 : {
375 : // Where are we in the table
376 141 : sal_uInt32 nRow = pInner->getRow( );
377 :
378 141 : const SwTable *pTable = pInner->getTable( );
379 141 : const SwTableLines& rLines = pTable->GetTabLines( );
380 141 : sal_uInt16 nLinesCount = rLines.size( );
381 : // HACK
382 : // msoffice seems to have an internal limitation of 63 columns for tables
383 : // and refuses to load .docx with more, even though the spec seems to allow that;
384 : // so simply if there are more columns, don't close the last one msoffice will handle
385 : // and merge the contents of the remaining ones into it (since we don't close the cell
386 : // here, following ones will not be opened)
387 141 : bool limitWorkaround = ( pInner->getCell() >= 62 && !pInner->isEndOfLine());
388 :
389 141 : if ( pInner->isEndOfCell() && !limitWorkaround )
390 : {
391 47 : if ( bForceEmptyParagraph )
392 0 : m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
393 :
394 47 : EndTableCell();
395 : }
396 :
397 : // This is a line end
398 141 : if ( pInner->isEndOfLine() )
399 17 : EndTableRow();
400 :
401 : // This is the end of the table
402 141 : if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
403 9 : EndTable();
404 : }
405 322 : }
406 :
407 0 : void DocxAttributeOutput::EmptyParagraph()
408 : {
409 0 : m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
410 0 : }
411 :
412 227 : void DocxAttributeOutput::StartParagraphProperties( const SwTxtNode& rNode )
413 : {
414 : // output page/section breaks
415 : // Writer can have them at the beginning of a paragraph, or at the end, but
416 : // in docx, we have to output them in the paragraph properties of the last
417 : // paragraph in a section. To get it right, we have to switch to the next
418 : // paragraph, and detect the section breaks there.
419 227 : SwNodeIndex aNextIndex( rNode, 1 );
420 227 : if ( aNextIndex.GetNode().IsTxtNode() )
421 : {
422 105 : const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
423 105 : m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode );
424 : }
425 122 : else if ( aNextIndex.GetNode().IsTableNode() )
426 : {
427 6 : const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
428 6 : const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
429 6 : m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
430 : }
431 :
432 227 : m_pSerializer->mark( );
433 :
434 227 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
435 :
436 : // and output the section break now (if it appeared)
437 227 : if ( m_pSectionInfo )
438 : {
439 0 : m_rExport.SectionProperties( *m_pSectionInfo );
440 0 : m_pSectionInfo.reset();
441 : }
442 :
443 227 : InitCollectedParagraphProperties();
444 227 : }
445 :
446 547 : void DocxAttributeOutput::InitCollectedParagraphProperties()
447 : {
448 547 : m_pParagraphSpacingAttrList = NULL;
449 :
450 : // Write the elements in the spec order
451 : static const sal_Int32 aOrder[] =
452 : {
453 : FSNS( XML_w, XML_pStyle ),
454 : FSNS( XML_w, XML_keepNext ),
455 : FSNS( XML_w, XML_keepLines ),
456 : FSNS( XML_w, XML_pageBreakBefore ),
457 : FSNS( XML_w, XML_framePr ),
458 : FSNS( XML_w, XML_widowControl ),
459 : FSNS( XML_w, XML_numPr ),
460 : FSNS( XML_w, XML_suppressLineNumbers ),
461 : FSNS( XML_w, XML_pBdr ),
462 : FSNS( XML_w, XML_shd ),
463 : FSNS( XML_w, XML_tabs ),
464 : FSNS( XML_w, XML_suppressAutoHyphens ),
465 : FSNS( XML_w, XML_kinsoku ),
466 : FSNS( XML_w, XML_wordWrap ),
467 : FSNS( XML_w, XML_overflowPunct ),
468 : FSNS( XML_w, XML_topLinePunct ),
469 : FSNS( XML_w, XML_autoSpaceDE ),
470 : FSNS( XML_w, XML_autoSpaceDN ),
471 : FSNS( XML_w, XML_bidi ),
472 : FSNS( XML_w, XML_adjustRightInd ),
473 : FSNS( XML_w, XML_snapToGrid ),
474 : FSNS( XML_w, XML_spacing ),
475 : FSNS( XML_w, XML_ind ),
476 : FSNS( XML_w, XML_contextualSpacing ),
477 : FSNS( XML_w, XML_mirrorIndents ),
478 : FSNS( XML_w, XML_suppressOverlap ),
479 : FSNS( XML_w, XML_jc ),
480 : FSNS( XML_w, XML_textDirection ),
481 : FSNS( XML_w, XML_textAlignment ),
482 : FSNS( XML_w, XML_textboxTightWrap ),
483 : FSNS( XML_w, XML_outlineLvl ),
484 : FSNS( XML_w, XML_divId ),
485 : FSNS( XML_w, XML_cnfStyle ),
486 : FSNS( XML_w, XML_rPr ),
487 : FSNS( XML_w, XML_sectPr ),
488 : FSNS( XML_w, XML_pPrChange )
489 : };
490 :
491 : // postpone the output so that we can later [in EndParagraphProperties()]
492 : // prepend the properties before the run
493 547 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
494 547 : uno::Sequence< sal_Int32 > aSeqOrder( len );
495 20239 : for ( sal_Int32 i = 0; i < len; i++ )
496 19692 : aSeqOrder[i] = aOrder[i];
497 :
498 547 : m_pSerializer->mark( aSeqOrder );
499 547 : }
500 :
501 547 : void DocxAttributeOutput::WriteCollectedParagraphProperties()
502 : {
503 547 : if ( m_pFlyAttrList )
504 : {
505 0 : XFastAttributeListRef xAttrList( m_pFlyAttrList );
506 0 : m_pFlyAttrList = NULL;
507 :
508 0 : m_pSerializer->singleElementNS( XML_w, XML_framePr, xAttrList );
509 : }
510 :
511 547 : if ( m_pParagraphSpacingAttrList )
512 : {
513 247 : XFastAttributeListRef xAttrList( m_pParagraphSpacingAttrList );
514 247 : m_pParagraphSpacingAttrList = NULL;
515 :
516 247 : m_pSerializer->singleElementNS( XML_w, XML_spacing, xAttrList );
517 : }
518 :
519 : // Merge the marks for the ordered elements
520 547 : m_pSerializer->mergeTopMarks( );
521 547 : }
522 :
523 227 : void DocxAttributeOutput::EndParagraphProperties()
524 : {
525 227 : WriteCollectedParagraphProperties();
526 :
527 : // insert copy of <rPr>
528 227 : m_pSerializer->copyTopMarkPop();
529 :
530 227 : m_pSerializer->endElementNS( XML_w, XML_pPr );
531 :
532 227 : if ( m_nColBreakStatus == COLBRK_WRITE )
533 : {
534 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
535 : m_pSerializer->singleElementNS( XML_w, XML_br,
536 0 : FSNS( XML_w, XML_type ), "column", FSEND );
537 0 : m_pSerializer->endElementNS( XML_w, XML_r );
538 :
539 0 : m_nColBreakStatus = COLBRK_NONE;
540 : }
541 :
542 : // merge the properties _before_ the run (strictly speaking, just
543 : // after the start of the paragraph)
544 227 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
545 227 : }
546 :
547 290 : void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSingleEmptyRun*/ )
548 : {
549 : // Don't start redline data here, possibly there is a hyperlink later, and
550 : // that has to be started first.
551 290 : m_pRedlineData = pRedlineData;
552 :
553 : // postpone the output of the start of a run (there are elements that need
554 : // to be written before the start of the run, but we learn which they are
555 : // _inside_ of the run)
556 290 : m_pSerializer->mark(); // let's call it "postponed run start"
557 :
558 : // postpone the output of the text (we get it before the run properties,
559 : // but must write it after them)
560 290 : m_pSerializer->mark(); // let's call it "postponed text"
561 290 : }
562 :
563 290 : void DocxAttributeOutput::EndRun()
564 : {
565 : // Write field starts
566 582 : for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
567 : {
568 : // Add the fields starts for all but hyperlinks and TOCs
569 2 : if ( pIt->bOpen && pIt->pField )
570 : {
571 0 : StartField_Impl( *pIt );
572 :
573 : // Remove the field from the stack if only the start has to be written
574 : // Unknown fields sould be removed too
575 0 : if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) )
576 : {
577 0 : if (pIt->pField)
578 0 : delete pIt->pField;
579 0 : pIt = m_Fields.erase( pIt );
580 0 : continue;
581 : }
582 : }
583 2 : ++pIt;
584 : }
585 :
586 : // write the run properties + the text, already in the correct order
587 290 : m_pSerializer->mergeTopMarks(); // merges with "postponed text", see above
588 :
589 : // level down, to be able to prepend the actual run start attribute (just
590 : // before "postponed run start")
591 290 : m_pSerializer->mark(); // let's call it "actual run start"
592 :
593 290 : if ( m_closeHyperlinkInPreviousRun )
594 : {
595 2 : if ( m_startedHyperlink )
596 : {
597 1 : m_pSerializer->endElementNS( XML_w, XML_hyperlink );
598 1 : m_startedHyperlink = false;
599 : }
600 2 : m_closeHyperlinkInPreviousRun = false;
601 : }
602 :
603 : // Write the hyperlink and toc fields starts
604 582 : for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
605 : {
606 : // Add the fields starts for hyperlinks, TOCs and index marks
607 2 : if ( pIt->bOpen && !pIt->pField )
608 : {
609 2 : StartField_Impl( *pIt, sal_True );
610 :
611 : // Remove the field if no end needs to be written
612 2 : if ( !pIt->bClose ) {
613 0 : if (pIt->pField)
614 0 : delete pIt->pField;
615 0 : pIt = m_Fields.erase( pIt );
616 0 : continue;
617 : }
618 : }
619 2 : ++pIt;
620 : }
621 :
622 : // Start the hyperlink after the fields separators or we would generate invalid file
623 290 : if ( m_pHyperlinkAttrList )
624 : {
625 1 : XFastAttributeListRef xAttrList ( m_pHyperlinkAttrList );
626 :
627 1 : m_pSerializer->startElementNS( XML_w, XML_hyperlink, xAttrList );
628 1 : m_pHyperlinkAttrList = NULL;
629 1 : m_startedHyperlink = true;
630 : }
631 :
632 : // if there is some redlining in the document, output it
633 290 : StartRedline();
634 :
635 290 : DoWriteBookmarks( );
636 290 : WriteCommentRanges();
637 :
638 290 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
639 290 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); // merges with "postponed run start", see above
640 :
641 : // write the run start + the run content
642 290 : m_pSerializer->mergeTopMarks(); // merges the "actual run start"
643 :
644 : // append the actual run end
645 290 : m_pSerializer->endElementNS( XML_w, XML_r );
646 :
647 290 : WritePostponedMath();
648 290 : WritePendingPlaceholder();
649 :
650 290 : if ( m_closeHyperlinkInThisRun )
651 : {
652 1 : if ( m_startedHyperlink )
653 : {
654 0 : m_pSerializer->endElementNS( XML_w, XML_hyperlink );
655 0 : m_startedHyperlink = false;
656 : }
657 1 : m_closeHyperlinkInThisRun = false;
658 : }
659 :
660 582 : while ( m_Fields.begin() != m_Fields.end() )
661 : {
662 2 : EndField_Impl( m_Fields.front( ) );
663 2 : if (m_Fields.front().pField)
664 0 : delete m_Fields.front().pField;
665 2 : m_Fields.erase( m_Fields.begin( ) );
666 : }
667 :
668 : // if there is some redlining in the document, output it
669 290 : EndRedline();
670 290 : }
671 :
672 290 : void DocxAttributeOutput::WriteCommentRanges()
673 : {
674 290 : if (m_bPostitStart)
675 : {
676 1 : m_bPostitStart = false;
677 1 : OString idstr = OString::valueOf( sal_Int32( m_postitFieldsMaxId ));
678 1 : m_pSerializer->singleElementNS( XML_w, XML_commentRangeStart, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND );
679 : }
680 290 : if (m_bPostitEnd)
681 : {
682 1 : m_bPostitEnd = false;
683 1 : OString idstr = OString::valueOf( sal_Int32( m_postitFieldsMaxId ));
684 1 : m_pSerializer->singleElementNS( XML_w, XML_commentRangeEnd, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND );
685 : }
686 290 : }
687 :
688 290 : void DocxAttributeOutput::DoWriteBookmarks()
689 : {
690 : // Write the start bookmarks
691 306 : for ( std::vector< OString >::const_iterator it = m_rMarksStart.begin(), end = m_rMarksStart.end();
692 : it != end; ++it )
693 : {
694 16 : const OString& rName = *it;
695 :
696 : // Output the bookmark
697 16 : sal_uInt16 nId = m_nNextMarkId++;
698 16 : m_rOpenedMarksIds[rName] = nId;
699 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
700 : FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr( ),
701 : FSNS( XML_w, XML_name ), rName.getStr(),
702 16 : FSEND );
703 : }
704 290 : m_rMarksStart.clear();
705 :
706 : // export the end bookmarks
707 306 : for ( std::vector< OString >::const_iterator it = m_rMarksEnd.begin(), end = m_rMarksEnd.end();
708 : it != end; ++it )
709 : {
710 16 : const OString& rName = *it;
711 :
712 : // Get the id of the bookmark
713 16 : std::map< OString, sal_uInt16 >::iterator pPos = m_rOpenedMarksIds.find( rName );
714 16 : if ( pPos != m_rOpenedMarksIds.end( ) )
715 : {
716 12 : sal_uInt16 nId = ( *pPos ).second;
717 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
718 : FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr( ),
719 12 : FSEND );
720 12 : m_rOpenedMarksIds.erase( rName );
721 : }
722 : }
723 290 : m_rMarksEnd.clear();
724 290 : }
725 :
726 0 : void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos )
727 : {
728 0 : const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
729 0 : if ( rInfos.eType == ww::eFORMDROPDOWN )
730 : {
731 0 : uno::Sequence< OUString> vListEntries;
732 0 : OUString sName, sHelp, sToolTip, sSelected;
733 :
734 0 : FieldMarkParamsHelper params( rFieldmark );
735 0 : params.extractParam( ODF_FORMDROPDOWN_LISTENTRY, vListEntries );
736 0 : sName = params.getName();
737 0 : sal_Int32 nSelectedIndex = 0;
738 :
739 0 : if ( params.extractParam( ODF_FORMDROPDOWN_RESULT, nSelectedIndex ) )
740 : {
741 0 : if (nSelectedIndex < vListEntries.getLength() )
742 0 : sSelected = vListEntries[ nSelectedIndex ];
743 : }
744 :
745 0 : GetExport().DoComboBox( sName, sHelp, sToolTip, sSelected, vListEntries );
746 : }
747 0 : else if ( rInfos.eType == ww::eFORMCHECKBOX )
748 : {
749 0 : OUString sName;
750 0 : bool bChecked = false;
751 :
752 0 : FieldMarkParamsHelper params( rFieldmark );
753 0 : params.extractParam( ODF_FORMCHECKBOX_NAME, sName );
754 :
755 0 : const sw::mark::ICheckboxFieldmark* pCheckboxFm = dynamic_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
756 0 : if ( pCheckboxFm && pCheckboxFm->IsChecked() )
757 0 : bChecked = true;
758 :
759 0 : FFDataWriterHelper ffdataOut( m_pSerializer );
760 0 : ffdataOut.WriteFormCheckbox( sName, OUString(), bChecked );
761 : }
762 0 : else if ( rInfos.eType == ww::eFORMTEXT )
763 : {
764 0 : FieldMarkParamsHelper params( rFieldmark );
765 0 : FFDataWriterHelper ffdataOut( m_pSerializer );
766 0 : ffdataOut.WriteFormText( params.getName(), OUString() );
767 : }
768 0 : }
769 :
770 2 : void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, bool bWriteRun )
771 : {
772 2 : if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
773 : {
774 : // Expand unsupported fields
775 0 : RunText( rInfos.pField->GetFieldName() );
776 : }
777 2 : else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
778 : {
779 2 : if ( bWriteRun )
780 2 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
781 :
782 2 : if ( rInfos.eType == ww::eFORMDROPDOWN )
783 : {
784 : m_pSerializer->startElementNS( XML_w, XML_fldChar,
785 : FSNS( XML_w, XML_fldCharType ), "begin",
786 0 : FSEND );
787 0 : if ( rInfos.pFieldmark && !rInfos.pField )
788 0 : WriteFFData( rInfos );
789 0 : if ( rInfos.pField )
790 : {
791 0 : const SwDropDownField& rFld2 = *(SwDropDownField*)rInfos.pField;
792 : uno::Sequence<OUString> aItems =
793 0 : rFld2.GetItemSequence();
794 0 : GetExport().DoComboBox(rFld2.GetName(),
795 0 : rFld2.GetHelp(),
796 0 : rFld2.GetToolTip(),
797 0 : rFld2.GetSelectedItem(), aItems);
798 : }
799 0 : m_pSerializer->endElementNS( XML_w, XML_fldChar );
800 :
801 0 : if ( bWriteRun )
802 0 : m_pSerializer->endElementNS( XML_w, XML_r );
803 0 : if ( !rInfos.pField )
804 0 : CmdField_Impl( rInfos );
805 :
806 : }
807 : else
808 : {
809 : // Write the field start
810 : m_pSerializer->startElementNS( XML_w, XML_fldChar,
811 : FSNS( XML_w, XML_fldCharType ), "begin",
812 2 : FSEND );
813 :
814 2 : if ( rInfos.pFieldmark )
815 0 : WriteFFData( rInfos );
816 :
817 2 : m_pSerializer->endElementNS( XML_w, XML_fldChar );
818 :
819 2 : if ( bWriteRun )
820 2 : m_pSerializer->endElementNS( XML_w, XML_r );
821 :
822 : // The hyperlinks fields can't be expanded: the value is
823 : // normally in the text run
824 2 : if ( !rInfos.pField )
825 2 : CmdField_Impl( rInfos );
826 : }
827 : }
828 2 : }
829 :
830 2 : void DocxAttributeOutput::DoWriteCmd( String& rCmd )
831 : {
832 : // Write the Field command
833 2 : m_pSerializer->startElementNS( XML_w, XML_instrText, FSEND );
834 2 : m_pSerializer->writeEscaped( OUString( rCmd ) );
835 2 : m_pSerializer->endElementNS( XML_w, XML_instrText );
836 :
837 2 : }
838 :
839 2 : void DocxAttributeOutput::CmdField_Impl( FieldInfos& rInfos )
840 : {
841 2 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
842 2 : xub_StrLen nNbToken = comphelper::string::getTokenCount(rInfos.sCmd, '\t');
843 :
844 4 : for ( xub_StrLen i = 0; i < nNbToken; i++ )
845 : {
846 2 : String sToken = rInfos.sCmd.GetToken( i, '\t' );
847 2 : if ( rInfos.eType == ww::eCREATEDATE
848 2 : || rInfos.eType == ww::eSAVEDATE
849 2 : || rInfos.eType == ww::ePRINTDATE
850 2 : || rInfos.eType == ww::eDATE
851 2 : || rInfos.eType == ww::eTIME )
852 : {
853 0 : sToken.SearchAndReplaceAll( String( "NNNN" ), String( "dddd" ) );
854 0 : sToken.SearchAndReplaceAll( String( "NN" ), String( "ddd" ) );
855 : }
856 : // Write the Field command
857 2 : DoWriteCmd( sToken );
858 :
859 : // Replace tabs by </instrText><tab/><instrText>
860 2 : if ( i < ( nNbToken - 1 ) )
861 0 : RunText( OUString( "\t" ) );
862 2 : }
863 :
864 2 : m_pSerializer->endElementNS( XML_w, XML_r );
865 :
866 : // Write the Field separator
867 2 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
868 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
869 : FSNS( XML_w, XML_fldCharType ), "separate",
870 2 : FSEND );
871 2 : m_pSerializer->endElementNS( XML_w, XML_r );
872 2 : }
873 :
874 2 : void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
875 : {
876 : // The command has to be written before for the hyperlinks
877 2 : if ( rInfos.pField )
878 : {
879 0 : CmdField_Impl( rInfos );
880 : }
881 :
882 : // Write the bookmark start if any
883 2 : OUString aBkmName( m_sFieldBkm );
884 2 : if ( !aBkmName.isEmpty() )
885 : {
886 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
887 : FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
888 : FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
889 0 : FSEND );
890 : }
891 :
892 2 : if (rInfos.pField ) // For hyperlinks and TOX
893 : {
894 : // Write the Field latest value
895 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
896 :
897 0 : String sExpand( rInfos.pField->ExpandField( true ) );
898 : // newlines embedded in fields are 0x0B in MSO and 0x0A for us
899 0 : sExpand.SearchAndReplaceAll( 0x0A, 0x0B );
900 0 : RunText( sExpand );
901 :
902 0 : m_pSerializer->endElementNS( XML_w, XML_r );
903 : }
904 :
905 : // Write the bookmark end if any
906 2 : if ( !aBkmName.isEmpty() )
907 : {
908 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
909 : FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
910 0 : FSEND );
911 :
912 0 : m_nNextMarkId++;
913 : }
914 :
915 : // Write the Field end
916 2 : if ( rInfos.bClose )
917 : {
918 2 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
919 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
920 : FSNS( XML_w, XML_fldCharType ), "end",
921 2 : FSEND );
922 2 : m_pSerializer->endElementNS( XML_w, XML_r );
923 : }
924 : // Write the ref field if a bookmark had to be set and the field
925 : // should be visible
926 2 : if ( rInfos.pField )
927 : {
928 0 : sal_uInt16 nSubType = rInfos.pField->GetSubType( );
929 0 : bool bIsSetField = rInfos.pField->GetTyp( )->Which( ) == RES_SETEXPFLD;
930 0 : bool bShowRef = ( !bIsSetField || ( nSubType & nsSwExtendedSubType::SUB_INVISIBLE ) ) ? false : true;
931 :
932 0 : if ( ( m_sFieldBkm.Len( ) > 0 ) && bShowRef )
933 : {
934 : // Write the field beginning
935 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
936 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
937 : FSNS( XML_w, XML_fldCharType ), "begin",
938 0 : FSEND );
939 0 : m_pSerializer->endElementNS( XML_w, XML_r );
940 :
941 0 : rInfos.sCmd = FieldString( ww::eREF );
942 0 : rInfos.sCmd.AppendAscii( "\"" );
943 0 : rInfos.sCmd += m_sFieldBkm;
944 0 : rInfos.sCmd.AppendAscii( "\" " );
945 :
946 : // Clean the field bookmark data to avoid infinite loop
947 0 : m_sFieldBkm = String( );
948 :
949 : // Write the end of the field
950 0 : EndField_Impl( rInfos );
951 : }
952 2 : }
953 2 : }
954 :
955 290 : void DocxAttributeOutput::StartRunProperties()
956 : {
957 : // postpone the output so that we can later [in EndRunProperties()]
958 : // prepend the properties before the text
959 290 : m_pSerializer->mark();
960 :
961 290 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
962 :
963 290 : InitCollectedRunProperties();
964 :
965 : OSL_ASSERT( m_postponedGraphic == NULL );
966 290 : m_postponedGraphic = new std::list< PostponedGraphic >;
967 290 : }
968 :
969 662 : void DocxAttributeOutput::InitCollectedRunProperties()
970 : {
971 662 : m_pFontsAttrList = NULL;
972 662 : m_pEastAsianLayoutAttrList = NULL;
973 662 : m_pCharLangAttrList = NULL;
974 :
975 : // Write the elements in the spec order
976 : static const sal_Int32 aOrder[] =
977 : {
978 : FSNS( XML_w, XML_rStyle ),
979 : FSNS( XML_w, XML_rFonts ),
980 : FSNS( XML_w, XML_b ),
981 : FSNS( XML_w, XML_bCs ),
982 : FSNS( XML_w, XML_i ),
983 : FSNS( XML_w, XML_iCs ),
984 : FSNS( XML_w, XML_caps ),
985 : FSNS( XML_w, XML_smallCaps ),
986 : FSNS( XML_w, XML_strike ),
987 : FSNS( XML_w, XML_dstrike ),
988 : FSNS( XML_w, XML_outline ),
989 : FSNS( XML_w, XML_shadow ),
990 : FSNS( XML_w, XML_emboss ),
991 : FSNS( XML_w, XML_imprint ),
992 : FSNS( XML_w, XML_noProof ),
993 : FSNS( XML_w, XML_snapToGrid ),
994 : FSNS( XML_w, XML_vanish ),
995 : FSNS( XML_w, XML_webHidden ),
996 : FSNS( XML_w, XML_color ),
997 : FSNS( XML_w, XML_spacing ),
998 : FSNS( XML_w, XML_w ),
999 : FSNS( XML_w, XML_kern ),
1000 : FSNS( XML_w, XML_position ),
1001 : FSNS( XML_w, XML_sz ),
1002 : FSNS( XML_w, XML_szCs ),
1003 : FSNS( XML_w, XML_highlight ),
1004 : FSNS( XML_w, XML_u ),
1005 : FSNS( XML_w, XML_effect ),
1006 : FSNS( XML_w, XML_bdr ),
1007 : FSNS( XML_w, XML_shd ),
1008 : FSNS( XML_w, XML_fitText ),
1009 : FSNS( XML_w, XML_vertAlign ),
1010 : FSNS( XML_w, XML_rtl ),
1011 : FSNS( XML_w, XML_cs ),
1012 : FSNS( XML_w, XML_em ),
1013 : FSNS( XML_w, XML_lang ),
1014 : FSNS( XML_w, XML_eastAsianLayout ),
1015 : FSNS( XML_w, XML_specVanish ),
1016 : FSNS( XML_w, XML_oMath ),
1017 : FSNS( XML_w, XML_rPrChange )
1018 : };
1019 :
1020 : // postpone the output so that we can later [in EndParagraphProperties()]
1021 : // prepend the properties before the run
1022 662 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
1023 662 : uno::Sequence< sal_Int32 > aSeqOrder( len );
1024 27142 : for ( sal_Int32 i = 0; i < len; i++ )
1025 26480 : aSeqOrder[i] = aOrder[i];
1026 :
1027 662 : m_pSerializer->mark( aSeqOrder );
1028 :
1029 662 : }
1030 :
1031 662 : void DocxAttributeOutput::WriteCollectedRunProperties()
1032 : {
1033 : // Write all differed properties
1034 662 : if ( m_pFontsAttrList )
1035 : {
1036 262 : XFastAttributeListRef xAttrList( m_pFontsAttrList );
1037 262 : m_pFontsAttrList = NULL;
1038 :
1039 262 : m_pSerializer->singleElementNS( XML_w, XML_rFonts, xAttrList );
1040 : }
1041 :
1042 662 : if ( m_pEastAsianLayoutAttrList )
1043 : {
1044 0 : XFastAttributeListRef xAttrList( m_pEastAsianLayoutAttrList );
1045 0 : m_pEastAsianLayoutAttrList = NULL;
1046 :
1047 0 : m_pSerializer->singleElementNS( XML_w, XML_eastAsianLayout, xAttrList );
1048 : }
1049 :
1050 662 : if ( m_pCharLangAttrList )
1051 : {
1052 98 : XFastAttributeListRef xAttrList( m_pCharLangAttrList );
1053 98 : m_pCharLangAttrList = NULL;
1054 :
1055 98 : m_pSerializer->singleElementNS( XML_w, XML_lang, xAttrList );
1056 : }
1057 :
1058 : // Merge the marks for the ordered elements
1059 662 : m_pSerializer->mergeTopMarks();
1060 662 : }
1061 :
1062 290 : void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
1063 : {
1064 : // Call the 'Redline' function. This will add redline (change-tracking) information that regards to run properties.
1065 : // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
1066 290 : Redline( pRedlineData );
1067 :
1068 290 : WriteCollectedRunProperties();
1069 :
1070 290 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1071 :
1072 : // Clone <rPr>...</rPr> for later re-use, in pPr
1073 290 : m_pSerializer->copyTopMarkPush();
1074 :
1075 : // write footnotes/endnotes if we have any
1076 290 : FootnoteEndnoteReference();
1077 :
1078 290 : WritePostponedGraphic();
1079 :
1080 : // merge the properties _before_ the run text (strictly speaking, just
1081 : // after the start of the run)
1082 290 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
1083 290 : }
1084 :
1085 290 : void DocxAttributeOutput::WritePostponedGraphic()
1086 : {
1087 870 : for( std::list< PostponedGraphic >::const_iterator it = m_postponedGraphic->begin();
1088 580 : it != m_postponedGraphic->end();
1089 : ++it )
1090 0 : FlyFrameGraphic( it->grfNode, it->size );
1091 290 : delete m_postponedGraphic;
1092 290 : m_postponedGraphic = NULL;
1093 290 : }
1094 :
1095 0 : void DocxAttributeOutput::FootnoteEndnoteRefTag()
1096 : {
1097 0 : if( m_footnoteEndnoteRefTag == 0 )
1098 0 : return;
1099 0 : m_pSerializer->singleElementNS( XML_w, m_footnoteEndnoteRefTag, FSEND );
1100 0 : m_footnoteEndnoteRefTag = 0;
1101 : }
1102 :
1103 : /** Output sal_Unicode* as a run text (<t>the text</t>).
1104 :
1105 : When bMove is true, update rBegin to point _after_ the end of the text +
1106 : 1, meaning that it skips one character after the text. This is to make
1107 : the switch in DocxAttributeOutput::RunText() nicer ;-)
1108 : */
1109 120 : static void impl_WriteRunText( FSHelperPtr pSerializer, sal_Int32 nTextToken,
1110 : const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true )
1111 : {
1112 120 : const sal_Unicode *pBegin = rBegin;
1113 :
1114 : // skip one character after the end
1115 120 : if ( bMove )
1116 0 : rBegin = pEnd + 1;
1117 :
1118 120 : if ( pBegin >= pEnd )
1119 121 : return; // we want to write at least one character
1120 :
1121 : // we have to add 'preserve' when starting/ending with space
1122 119 : if ( *pBegin == sal_Unicode( ' ' ) || *( pEnd - 1 ) == sal_Unicode( ' ' ) )
1123 : {
1124 29 : pSerializer->startElementNS( XML_w, nTextToken, FSNS( XML_xml, XML_space ), "preserve", FSEND );
1125 : }
1126 : else
1127 90 : pSerializer->startElementNS( XML_w, nTextToken, FSEND );
1128 :
1129 119 : pSerializer->writeEscaped( OUString( pBegin, pEnd - pBegin ) );
1130 :
1131 119 : pSerializer->endElementNS( XML_w, nTextToken );
1132 : }
1133 :
1134 120 : void DocxAttributeOutput::RunText( const String& rText, rtl_TextEncoding /*eCharSet*/ )
1135 : {
1136 120 : if( m_closeHyperlinkInThisRun )
1137 : {
1138 2 : m_closeHyperlinkInPreviousRun = true;
1139 2 : m_closeHyperlinkInThisRun = false;
1140 : }
1141 120 : OUString aText( rText );
1142 :
1143 : // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
1144 120 : const sal_Unicode *pBegin = aText.getStr();
1145 120 : const sal_Unicode *pEnd = pBegin + aText.getLength();
1146 :
1147 : // the text run is usually XML_t, with the exception of the deleted text
1148 120 : sal_Int32 nTextToken = XML_t;
1149 120 : if ( m_pRedlineData && m_pRedlineData->GetType() == nsRedlineType_t::REDLINE_DELETE )
1150 1 : nTextToken = XML_delText;
1151 :
1152 1773 : for ( const sal_Unicode *pIt = pBegin; pIt < pEnd; ++pIt )
1153 : {
1154 1653 : switch ( *pIt )
1155 : {
1156 : case 0x09: // tab
1157 0 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
1158 0 : m_pSerializer->singleElementNS( XML_w, XML_tab, FSEND );
1159 0 : break;
1160 : case 0x0b: // line break
1161 0 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
1162 0 : m_pSerializer->singleElementNS( XML_w, XML_br, FSEND );
1163 0 : break;
1164 : case 0x1E: //non-breaking hyphen
1165 0 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
1166 0 : m_pSerializer->singleElementNS( XML_w, XML_noBreakHyphen, FSEND );
1167 0 : break;
1168 : case 0x1F: //soft (on demand) hyphen
1169 0 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
1170 0 : m_pSerializer->singleElementNS( XML_w, XML_softHyphen, FSEND );
1171 0 : break;
1172 : default:
1173 1653 : if ( *pIt < 0x0020 ) // filter out the control codes
1174 : {
1175 0 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
1176 : OSL_TRACE( "Ignored control code %x in a text run.", *pIt );
1177 : }
1178 1653 : break;
1179 : }
1180 : }
1181 :
1182 120 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
1183 120 : }
1184 :
1185 0 : void DocxAttributeOutput::RawText( const String& /*rText*/, bool /*bForceUnicode*/, rtl_TextEncoding /*eCharSet*/ )
1186 : {
1187 : OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )" );
1188 0 : }
1189 :
1190 0 : void DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby )
1191 : {
1192 : OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )" );
1193 0 : m_pSerializer->startElementNS( XML_w, XML_ruby, FSEND );
1194 0 : m_pSerializer->startElementNS( XML_w, XML_rubyPr, FSEND );
1195 : // hps
1196 : // hpsBaseText
1197 : // hpsRaise
1198 : // lid
1199 : lang::Locale aLocale( SwBreakIt::Get()->GetLocale(
1200 0 : rNode.GetLang( nPos ) ) );
1201 0 : OUString sLang( aLocale.Language );
1202 0 : if ( !aLocale.Country.isEmpty() )
1203 0 : sLang += "-" + aLocale.Country;
1204 : m_pSerializer->singleElementNS( XML_w, XML_lid,
1205 : FSNS( XML_w, XML_val ),
1206 0 : OUStringToOString( sLang, RTL_TEXTENCODING_UTF8 ).getStr( ), FSEND );
1207 :
1208 0 : OString sAlign ( "center" );
1209 0 : switch ( rRuby.GetAdjustment( ) )
1210 : {
1211 : case 0:
1212 0 : sAlign = OString( "left" );
1213 0 : break;
1214 : case 1:
1215 : // Defaults to center
1216 0 : break;
1217 : case 2:
1218 0 : sAlign = OString( "right" );
1219 0 : break;
1220 : case 3:
1221 0 : sAlign = OString( "distributeLetter" );
1222 0 : break;
1223 : case 4:
1224 0 : sAlign = OString( "distributeSpace" );
1225 0 : break;
1226 : default:
1227 0 : break;
1228 : }
1229 : m_pSerializer->singleElementNS( XML_w, XML_rubyAlign,
1230 0 : FSNS( XML_w, XML_val ), sAlign.getStr(), FSEND );
1231 0 : m_pSerializer->endElementNS( XML_w, XML_rubyPr );
1232 :
1233 0 : m_pSerializer->startElementNS( XML_w, XML_rt, FSEND );
1234 0 : StartRun( NULL );
1235 0 : StartRunProperties( );
1236 0 : SwWW8AttrIter aAttrIt( m_rExport, rNode );
1237 0 : aAttrIt.OutAttr( nPos, true );
1238 0 : sal_uInt16 nStyle = m_rExport.GetId( *rRuby.GetTxtRuby()->GetCharFmt() );
1239 0 : OString aStyleId( "style" );
1240 0 : aStyleId += OString::valueOf( sal_Int32( nStyle ) );
1241 : m_pSerializer->singleElementNS( XML_w, XML_rStyle,
1242 0 : FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
1243 0 : EndRunProperties( NULL );
1244 0 : RunText( rRuby.GetText( ) );
1245 0 : EndRun( );
1246 0 : m_pSerializer->endElementNS( XML_w, XML_rt );
1247 :
1248 0 : m_pSerializer->startElementNS( XML_w, XML_rubyBase, FSEND );
1249 0 : StartRun( NULL );
1250 0 : }
1251 :
1252 0 : void DocxAttributeOutput::EndRuby()
1253 : {
1254 : OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()" );
1255 0 : EndRun( );
1256 0 : m_pSerializer->endElementNS( XML_w, XML_rubyBase );
1257 0 : m_pSerializer->endElementNS( XML_w, XML_ruby );
1258 0 : }
1259 :
1260 3 : bool DocxAttributeOutput::AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark )
1261 : {
1262 3 : bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
1263 :
1264 3 : String sURL = *pLinkURL;
1265 6 : String sMark = *pMark;
1266 :
1267 3 : bool bOutputField = sMark.Len();
1268 :
1269 3 : if ( bOutputField )
1270 : {
1271 2 : if ( bBookMarkOnly )
1272 0 : sURL = FieldString( ww::eHYPERLINK );
1273 : else
1274 : {
1275 2 : String sFld( FieldString( ww::eHYPERLINK ) );
1276 2 : sFld.AppendAscii( "\"" );
1277 2 : sURL.Insert( sFld, 0 );
1278 2 : sURL += '\"';
1279 : }
1280 :
1281 2 : if ( sMark.Len() )
1282 2 : ( ( sURL.AppendAscii( " \\l \"" ) ) += sMark ) += '\"';
1283 :
1284 2 : if ( rTarget.Len() )
1285 0 : ( sURL.AppendAscii( " \\n " ) ) += rTarget;
1286 : }
1287 :
1288 3 : *pLinkURL = sURL;
1289 3 : *pMark = sMark;
1290 :
1291 6 : return bBookMarkOnly;
1292 : }
1293 :
1294 3 : bool DocxAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
1295 : {
1296 3 : String sMark;
1297 6 : String sUrl;
1298 :
1299 3 : bool bBookmarkOnly = AnalyzeURL( rUrl, rTarget, &sUrl, &sMark );
1300 :
1301 3 : if ( sMark.Len() && !bBookmarkOnly )
1302 : {
1303 2 : m_rExport.OutputField( NULL, ww::eHYPERLINK, sUrl );
1304 : }
1305 : else
1306 : {
1307 : // Output a hyperlink XML element
1308 1 : m_pHyperlinkAttrList = m_pSerializer->createAttrList();
1309 :
1310 1 : if ( !bBookmarkOnly )
1311 : {
1312 1 : OUString osUrl( sUrl );
1313 :
1314 1 : OString sId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
1315 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
1316 3 : osUrl, true ), RTL_TEXTENCODING_UTF8 );
1317 :
1318 2 : m_pHyperlinkAttrList->add( FSNS( XML_r, XML_id), sId.getStr());
1319 : }
1320 : else
1321 : m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ),
1322 0 : OUStringToOString( OUString( sMark ), RTL_TEXTENCODING_UTF8 ).getStr( ) );
1323 :
1324 1 : OUString sTarget( rTarget );
1325 1 : if ( !sTarget.isEmpty() )
1326 : {
1327 0 : OString soTarget = OUStringToOString( sTarget, RTL_TEXTENCODING_UTF8 );
1328 0 : m_pHyperlinkAttrList->add(FSNS( XML_w, XML_tgtFrame ), soTarget.getStr());
1329 1 : }
1330 : }
1331 :
1332 6 : return true;
1333 : }
1334 :
1335 3 : bool DocxAttributeOutput::EndURL()
1336 : {
1337 3 : m_closeHyperlinkInThisRun = true;
1338 3 : return true;
1339 : }
1340 :
1341 0 : void DocxAttributeOutput::FieldVanish( const String& rTxt, ww::eField eType )
1342 : {
1343 0 : WriteField_Impl( NULL, eType, rTxt, WRITEFIELD_ALL );
1344 0 : }
1345 :
1346 : // The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
1347 : // 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
1348 : // 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
1349 291 : void DocxAttributeOutput::Redline( const SwRedlineData* pRedline)
1350 : {
1351 291 : if ( !pRedline )
1352 576 : return;
1353 :
1354 6 : OString aId( OString::valueOf( sal_Int32(pRedline->GetSeqNo()) ) );
1355 6 : const String &rAuthor( SW_MOD()->GetRedlineAuthor( pRedline->GetAuthor() ) );
1356 12 : OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
1357 12 : OString aDate( msfilter::util::DateTimeToOString( pRedline->GetTimeStamp() ) );
1358 :
1359 12 : OUString sVal;
1360 12 : OString sOVal;
1361 :
1362 6 : switch( pRedline->GetType() )
1363 : {
1364 : case nsRedlineType_t::REDLINE_INSERT:
1365 1 : break;
1366 :
1367 : case nsRedlineType_t::REDLINE_DELETE:
1368 3 : break;
1369 :
1370 : case nsRedlineType_t::REDLINE_FORMAT:
1371 : m_pSerializer->startElementNS( XML_w, XML_rPrChange,
1372 : FSNS( XML_w, XML_id ), aId.getStr(),
1373 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
1374 : FSNS( XML_w, XML_date ), aDate.getStr(),
1375 2 : FSEND );
1376 :
1377 2 : if ( m_pCharLangAttrList )
1378 : {
1379 2 : if (m_pCharLangAttrList->hasAttribute(FSNS(XML_w, XML_val)))
1380 : {
1381 2 : m_pSerializer->mark();
1382 2 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1383 2 : sVal = m_pCharLangAttrList->getValue(FSNS(XML_w, XML_val));
1384 2 : sOVal = OUStringToOString(sVal, RTL_TEXTENCODING_UTF8);
1385 : m_pSerializer->startElementNS(XML_w, XML_lang,
1386 : FSNS(XML_w, XML_val), sOVal.getStr(),
1387 2 : FSEND);
1388 2 : m_pSerializer->endElementNS(XML_w, XML_lang);
1389 2 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1390 2 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
1391 : }
1392 : }
1393 :
1394 2 : m_pSerializer->endElementNS( XML_w, XML_rPrChange );
1395 2 : break;
1396 : default:
1397 : SAL_WARN("sw.ww8", "Unhandled redline type for export " << pRedline->GetType());
1398 0 : break;
1399 6 : }
1400 : }
1401 :
1402 : // The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
1403 : // 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
1404 : // 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
1405 290 : void DocxAttributeOutput::StartRedline()
1406 : {
1407 290 : if ( !m_pRedlineData )
1408 575 : return;
1409 5 : const SwRedlineData* pRedlineData = m_pRedlineData;
1410 :
1411 : // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
1412 :
1413 5 : OString aId( OString::valueOf( m_nRedlineId++ ) );
1414 :
1415 5 : const String &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
1416 10 : OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
1417 :
1418 10 : OString aDate( msfilter::util::DateTimeToOString( pRedlineData->GetTimeStamp() ) );
1419 :
1420 5 : switch ( pRedlineData->GetType() )
1421 : {
1422 : case nsRedlineType_t::REDLINE_INSERT:
1423 : m_pSerializer->startElementNS( XML_w, XML_ins,
1424 : FSNS( XML_w, XML_id ), aId.getStr(),
1425 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
1426 : FSNS( XML_w, XML_date ), aDate.getStr(),
1427 1 : FSEND );
1428 1 : break;
1429 :
1430 : case nsRedlineType_t::REDLINE_DELETE:
1431 : m_pSerializer->startElementNS( XML_w, XML_del,
1432 : FSNS( XML_w, XML_id ), aId.getStr(),
1433 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
1434 : FSNS( XML_w, XML_date ), aDate.getStr(),
1435 2 : FSEND );
1436 2 : break;
1437 :
1438 : case nsRedlineType_t::REDLINE_FORMAT:
1439 : OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()" );
1440 : default:
1441 2 : break;
1442 5 : }
1443 : }
1444 :
1445 290 : void DocxAttributeOutput::EndRedline()
1446 : {
1447 290 : if ( !m_pRedlineData )
1448 575 : return;
1449 :
1450 5 : switch ( m_pRedlineData->GetType() )
1451 : {
1452 : case nsRedlineType_t::REDLINE_INSERT:
1453 1 : m_pSerializer->endElementNS( XML_w, XML_ins );
1454 1 : break;
1455 :
1456 : case nsRedlineType_t::REDLINE_DELETE:
1457 2 : m_pSerializer->endElementNS( XML_w, XML_del );
1458 2 : break;
1459 :
1460 : case nsRedlineType_t::REDLINE_FORMAT:
1461 : OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()" );
1462 2 : break;
1463 : default:
1464 0 : break;
1465 : }
1466 :
1467 5 : m_pRedlineData = NULL;
1468 : }
1469 :
1470 0 : void DocxAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
1471 : {
1472 : OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle )" );
1473 0 : }
1474 :
1475 227 : void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
1476 : {
1477 227 : OString aStyleId( "style" );
1478 227 : aStyleId += OString::valueOf( sal_Int32( nStyle ) );
1479 :
1480 227 : m_pSerializer->singleElementNS( XML_w, XML_pStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
1481 227 : }
1482 :
1483 336 : static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist )
1484 : {
1485 336 : FastAttributeList* pAttr = pSerializer->createAttrList();
1486 :
1487 :
1488 : // Compute val attribute value
1489 : // Can be one of:
1490 : // single, double,
1491 : // basicWideOutline, basicWideInline
1492 : // OOXml also supports those types of borders, but we'll try to play with the first ones.
1493 : // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
1494 : // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
1495 336 : const char* pVal = "nil";
1496 336 : if ( pBorderLine && !pBorderLine->isEmpty( ) )
1497 : {
1498 324 : switch (pBorderLine->GetBorderLineStyle())
1499 : {
1500 : case table::BorderLineStyle::SOLID:
1501 324 : pVal = ( sal_Char* )"single";
1502 324 : break;
1503 : case table::BorderLineStyle::DOTTED:
1504 0 : pVal = ( sal_Char* )"dotted";
1505 0 : break;
1506 : case table::BorderLineStyle::DASHED:
1507 0 : pVal = ( sal_Char* )"dashed";
1508 0 : break;
1509 : case table::BorderLineStyle::DOUBLE:
1510 0 : pVal = ( sal_Char* )"double";
1511 0 : break;
1512 : case table::BorderLineStyle::THINTHICK_SMALLGAP:
1513 0 : pVal = ( sal_Char* )"thinThickSmallGap";
1514 0 : break;
1515 : case table::BorderLineStyle::THINTHICK_MEDIUMGAP:
1516 0 : pVal = ( sal_Char* )"thinThickMediumGap";
1517 0 : break;
1518 : case table::BorderLineStyle::THINTHICK_LARGEGAP:
1519 0 : pVal = ( sal_Char* )"thinThickLargeGap";
1520 0 : break;
1521 : case table::BorderLineStyle::THICKTHIN_SMALLGAP:
1522 0 : pVal = ( sal_Char* )"thickThinSmallGap";
1523 0 : break;
1524 : case table::BorderLineStyle::THICKTHIN_MEDIUMGAP:
1525 0 : pVal = ( sal_Char* )"thickThinMediumGap";
1526 0 : break;
1527 : case table::BorderLineStyle::THICKTHIN_LARGEGAP:
1528 0 : pVal = ( sal_Char* )"thickThinLargeGap";
1529 0 : break;
1530 : case table::BorderLineStyle::EMBOSSED:
1531 0 : pVal = ( sal_Char* )"threeDEmboss";
1532 0 : break;
1533 : case table::BorderLineStyle::ENGRAVED:
1534 0 : pVal = ( sal_Char* )"threeDEngrave";
1535 0 : break;
1536 : case table::BorderLineStyle::OUTSET:
1537 0 : pVal = ( sal_Char* )"outset";
1538 0 : break;
1539 : case table::BorderLineStyle::INSET:
1540 0 : pVal = ( sal_Char* )"inset";
1541 0 : break;
1542 : case table::BorderLineStyle::FINE_DASHED:
1543 0 : pVal = ( sal_Char* )"dashSmallGap";
1544 0 : break;
1545 : case table::BorderLineStyle::NONE:
1546 : default:
1547 0 : break;
1548 : }
1549 : }
1550 :
1551 336 : pAttr->add( FSNS( XML_w, XML_val ), OString( pVal ) );
1552 :
1553 336 : if ( pBorderLine && !pBorderLine->isEmpty() )
1554 : {
1555 : // Compute the sz attribute
1556 :
1557 : double const fConverted( ::editeng::ConvertBorderWidthToWord(
1558 324 : pBorderLine->GetBorderLineStyle(), pBorderLine->GetWidth()));
1559 : // The unit is the 8th of point
1560 324 : sal_Int32 nWidth = sal_Int32( fConverted / 2.5 );
1561 324 : sal_uInt16 nMinWidth = 2;
1562 324 : sal_uInt16 nMaxWidth = 96;
1563 :
1564 324 : if ( nWidth > nMaxWidth )
1565 0 : nWidth = nMaxWidth;
1566 324 : else if ( nWidth < nMinWidth )
1567 0 : nWidth = nMinWidth;
1568 :
1569 324 : pAttr->add( FSNS( XML_w, XML_sz ), OString::valueOf( sal_Int32( nWidth ) ) );
1570 :
1571 : // Get the distance (in pt)
1572 324 : pAttr->add( FSNS( XML_w, XML_space ), OString::valueOf( sal_Int32( nDist / 20 ) ) );
1573 :
1574 : // Get the color code as an RRGGBB hex value
1575 324 : OString sColor( msfilter::util::ConvertColor( pBorderLine->GetColor( ) ) );
1576 324 : pAttr->add( FSNS( XML_w, XML_color ), sColor );
1577 : }
1578 :
1579 336 : XFastAttributeListRef xAttrs( pAttr );
1580 336 : pSerializer->singleElementNS( XML_w, elementToken, xAttrs );
1581 336 : }
1582 :
1583 9 : static OutputBorderOptions lcl_getTableDefaultBorderOptions(bool bEcma)
1584 : {
1585 9 : OutputBorderOptions rOptions;
1586 :
1587 9 : rOptions.tag = XML_tblBorders;
1588 9 : rOptions.bUseStartEnd = !bEcma;
1589 9 : rOptions.bWriteTag = true;
1590 9 : rOptions.bWriteInsideHV = true;
1591 9 : rOptions.bWriteDistance = false;
1592 :
1593 9 : return rOptions;
1594 : }
1595 :
1596 47 : static OutputBorderOptions lcl_getTableCellBorderOptions(bool bEcma)
1597 : {
1598 47 : OutputBorderOptions rOptions;
1599 :
1600 47 : rOptions.tag = XML_tcBorders;
1601 47 : rOptions.bUseStartEnd = !bEcma;
1602 47 : rOptions.bWriteTag = true;
1603 47 : rOptions.bWriteInsideHV = true;
1604 47 : rOptions.bWriteDistance = false;
1605 :
1606 47 : return rOptions;
1607 : }
1608 :
1609 0 : static OutputBorderOptions lcl_getBoxBorderOptions()
1610 : {
1611 0 : OutputBorderOptions rOptions;
1612 :
1613 0 : rOptions.tag = XML_pBdr;
1614 0 : rOptions.bUseStartEnd = false;
1615 0 : rOptions.bWriteTag = false;
1616 0 : rOptions.bWriteInsideHV = false;
1617 0 : rOptions.bWriteDistance = true;
1618 :
1619 0 : return rOptions;
1620 : }
1621 :
1622 56 : static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const OutputBorderOptions& rOptions)
1623 : {
1624 : static const sal_uInt16 aBorders[] =
1625 : {
1626 : BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
1627 : };
1628 :
1629 : const sal_Int32 aXmlElements[] =
1630 : {
1631 : XML_top,
1632 : rOptions.bUseStartEnd ? XML_start : XML_left,
1633 : XML_bottom,
1634 : rOptions.bUseStartEnd ? XML_end : XML_right
1635 56 : };
1636 56 : bool tagWritten = false;
1637 56 : const sal_uInt16* pBrd = aBorders;
1638 280 : for( int i = 0; i < 4; ++i, ++pBrd )
1639 : {
1640 224 : const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
1641 :
1642 224 : if (!tagWritten && rOptions.bWriteTag) {
1643 56 : pSerializer->startElementNS( XML_w, rOptions.tag, FSEND );
1644 56 : tagWritten = true;
1645 : }
1646 :
1647 224 : sal_uInt16 nDist = 0;
1648 224 : if (rOptions.bWriteDistance)
1649 : {
1650 0 : nDist = rBox.GetDistance( *pBrd );
1651 : }
1652 224 : impl_borderLine( pSerializer, aXmlElements[i], pLn, nDist );
1653 :
1654 : // When exporting default borders, we need to export these 2 attr
1655 224 : if ( rOptions.bWriteInsideHV) {
1656 224 : if ( i == 2 )
1657 56 : impl_borderLine( pSerializer, XML_insideH, pLn, 0 );
1658 168 : else if ( i == 3 )
1659 56 : impl_borderLine( pSerializer, XML_insideV, pLn, 0 );
1660 : }
1661 : }
1662 56 : if (tagWritten && rOptions.bWriteTag) {
1663 56 : pSerializer->endElementNS( XML_w, rOptions.tag );
1664 : }
1665 56 : }
1666 :
1667 56 : static void impl_cellMargins( FSHelperPtr pSerializer, const SvxBoxItem& rBox, sal_Int32 tag, bool bUseStartEnd = false, const SvxBoxItem* pDefaultMargins = 0)
1668 : {
1669 : static const sal_uInt16 aBorders[] =
1670 : {
1671 : BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
1672 : };
1673 :
1674 : const sal_Int32 aXmlElements[] =
1675 : {
1676 : XML_top,
1677 : bUseStartEnd ? XML_start : XML_left,
1678 : XML_bottom,
1679 : bUseStartEnd ? XML_end : XML_right
1680 56 : };
1681 56 : bool tagWritten = false;
1682 56 : const sal_uInt16* pBrd = aBorders;
1683 280 : for( int i = 0; i < 4; ++i, ++pBrd )
1684 : {
1685 224 : sal_Int32 nDist = sal_Int32( rBox.GetDistance( *pBrd ) );
1686 :
1687 224 : if ( aBorders[i] == BOX_LINE_LEFT ) {
1688 : // Office's cell margin is measured from the right of the border.
1689 : // While LO's cell spacing is measured from the center of the border.
1690 : // So we add half left-border width to tblIndent value
1691 56 : const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
1692 56 : if (pLn)
1693 54 : nDist -= pLn->GetWidth() * 0.5;
1694 : }
1695 :
1696 224 : if (pDefaultMargins)
1697 : {
1698 : // Skip output if cell margin == table default margin
1699 188 : if (sal_Int32( pDefaultMargins->GetDistance( *pBrd ) ) == nDist)
1700 143 : continue;
1701 : }
1702 :
1703 81 : if (!tagWritten) {
1704 54 : pSerializer->startElementNS( XML_w, tag, FSEND );
1705 54 : tagWritten = true;
1706 : }
1707 81 : pSerializer->singleElementNS( XML_w, aXmlElements[i],
1708 : FSNS( XML_w, XML_w ), OString::valueOf( nDist ).getStr( ),
1709 : FSNS( XML_w, XML_type ), "dxa",
1710 162 : FSEND );
1711 : }
1712 56 : if (tagWritten) {
1713 54 : pSerializer->endElementNS( XML_w, tag );
1714 : }
1715 56 : }
1716 :
1717 47 : void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1718 : {
1719 47 : m_pSerializer->startElementNS( XML_w, XML_tcPr, FSEND );
1720 :
1721 47 : const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
1722 :
1723 47 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
1724 :
1725 : // Cell prefered width
1726 47 : SwTwips nWidth = GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() );
1727 47 : if ( pTableTextNodeInfoInner->getCell() )
1728 30 : nWidth = nWidth - GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() - 1 );
1729 : m_pSerializer->singleElementNS( XML_w, XML_tcW,
1730 : FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nWidth ) ).getStr( ),
1731 : FSNS( XML_w, XML_type ), "dxa",
1732 47 : FSEND );
1733 :
1734 : // Horizontal spans
1735 47 : const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
1736 47 : SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
1737 47 : const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
1738 :
1739 47 : sal_uInt16 nColSpan = pCell->GetColSpan();
1740 47 : if ( nColSpan > 1 )
1741 : m_pSerializer->singleElementNS( XML_w, XML_gridSpan,
1742 : FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nColSpan ) ).getStr(),
1743 0 : FSEND );
1744 :
1745 : // Vertical merges
1746 47 : long vSpan = pTblBox->getRowSpan( );
1747 47 : if ( vSpan > 1 )
1748 : {
1749 : m_pSerializer->singleElementNS( XML_w, XML_vMerge,
1750 : FSNS( XML_w, XML_val ), "restart",
1751 0 : FSEND );
1752 : }
1753 47 : else if ( vSpan < 0 )
1754 : {
1755 : m_pSerializer->singleElementNS( XML_w, XML_vMerge,
1756 : FSNS( XML_w, XML_val ), "continue",
1757 0 : FSEND );
1758 : }
1759 :
1760 47 : const SvxBoxItem& rBox = pTblBox->GetFrmFmt( )->GetBox( );
1761 47 : const SvxBoxItem& rDefaultBox = (*tableFirstCells.rbegin())->getTableBox( )->GetFrmFmt( )->GetBox( );
1762 : {
1763 : // The cell borders
1764 47 : impl_borders( m_pSerializer, rBox, lcl_getTableCellBorderOptions(bEcma) );
1765 : }
1766 :
1767 47 : TableBackgrounds( pTableTextNodeInfoInner );
1768 :
1769 : {
1770 : // Cell margins
1771 47 : impl_cellMargins( m_pSerializer, rBox, XML_tcMar, !bEcma, &rDefaultBox );
1772 : }
1773 :
1774 47 : TableVerticalCell( pTableTextNodeInfoInner );
1775 :
1776 47 : m_pSerializer->endElementNS( XML_w, XML_tcPr );
1777 47 : }
1778 :
1779 9 : void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1780 : {
1781 9 : sal_uInt32 nPageSize = 0;
1782 9 : bool bRelBoxSize = false;
1783 :
1784 : // Create the SwWriteTable instance to use col spans (and maybe other infos)
1785 9 : GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
1786 :
1787 9 : const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
1788 9 : const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
1789 9 : SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
1790 :
1791 9 : const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
1792 9 : if( pLayout && pLayout->IsExportable() )
1793 0 : m_pTableWrt = new SwWriteTable( pLayout );
1794 : else
1795 : m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
1796 9 : (sal_uInt16)nTblSz, false);
1797 9 : }
1798 :
1799 9 : void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1800 : {
1801 9 : m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND );
1802 :
1803 9 : tableFirstCells.push_back(pTableTextNodeInfoInner);
1804 :
1805 9 : InitTableHelper( pTableTextNodeInfoInner );
1806 9 : TableDefinition( pTableTextNodeInfoInner );
1807 9 : }
1808 :
1809 9 : void DocxAttributeOutput::EndTable()
1810 : {
1811 9 : m_pSerializer->endElementNS( XML_w, XML_tbl );
1812 :
1813 9 : if ( m_nTableDepth > 0 )
1814 9 : --m_nTableDepth;
1815 :
1816 9 : tableFirstCells.pop_back();
1817 :
1818 : // We closed the table; if it is a nested table, the cell that contains it
1819 : // still continues
1820 9 : m_bTableCellOpen = true;
1821 :
1822 : // Cleans the table helper
1823 9 : delete m_pTableWrt, m_pTableWrt = NULL;
1824 9 : }
1825 :
1826 17 : void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1827 : {
1828 17 : m_pSerializer->startElementNS( XML_w, XML_tr, FSEND );
1829 :
1830 : // Output the row properties
1831 17 : m_pSerializer->startElementNS( XML_w, XML_trPr, FSEND );
1832 :
1833 : // Header row: tblHeader
1834 17 : const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
1835 17 : if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
1836 : m_pSerializer->singleElementNS( XML_w, XML_tblHeader,
1837 : FSNS( XML_w, XML_val ), "true",
1838 0 : FSEND );
1839 :
1840 17 : TableHeight( pTableTextNodeInfoInner );
1841 17 : TableCanSplit( pTableTextNodeInfoInner );
1842 :
1843 17 : m_pSerializer->endElementNS( XML_w, XML_trPr );
1844 17 : }
1845 :
1846 17 : void DocxAttributeOutput::EndTableRow( )
1847 : {
1848 17 : m_pSerializer->endElementNS( XML_w, XML_tr );
1849 17 : }
1850 :
1851 47 : void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1852 : {
1853 47 : if ( !m_pTableWrt )
1854 0 : InitTableHelper( pTableTextNodeInfoInner );
1855 :
1856 47 : m_pSerializer->startElementNS( XML_w, XML_tc, FSEND );
1857 :
1858 : // Write the cell properties here
1859 47 : TableCellProperties( pTableTextNodeInfoInner );
1860 :
1861 47 : m_bTableCellOpen = true;
1862 47 : }
1863 :
1864 47 : void DocxAttributeOutput::EndTableCell( )
1865 : {
1866 47 : m_pSerializer->endElementNS( XML_w, XML_tc );
1867 :
1868 47 : m_bBtLr = false;
1869 47 : m_bTableCellOpen = false;
1870 47 : }
1871 :
1872 47 : void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
1873 : {
1874 47 : }
1875 :
1876 0 : void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
1877 : {
1878 0 : }
1879 :
1880 9 : void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1881 : {
1882 9 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
1883 :
1884 : // Write the table properties
1885 9 : m_pSerializer->startElementNS( XML_w, XML_tblPr, FSEND );
1886 :
1887 : static const sal_Int32 aOrder[] =
1888 : {
1889 : FSNS( XML_w, XML_tblStyle ),
1890 : FSNS( XML_w, XML_tblpPr ),
1891 : FSNS( XML_w, XML_tblOverlap ),
1892 : FSNS( XML_w, XML_bidiVisual ),
1893 : FSNS( XML_w, XML_tblStyleRowBandSize ),
1894 : FSNS( XML_w, XML_tblStyleColBandSize ),
1895 : FSNS( XML_w, XML_tblW ),
1896 : FSNS( XML_w, XML_jc ),
1897 : FSNS( XML_w, XML_tblCellSpacing ),
1898 : FSNS( XML_w, XML_tblInd ),
1899 : FSNS( XML_w, XML_tblBorders ),
1900 : FSNS( XML_w, XML_shd ),
1901 : FSNS( XML_w, XML_tblLayout ),
1902 : FSNS( XML_w, XML_tblCellMar ),
1903 : FSNS( XML_w, XML_tblLook ),
1904 : FSNS( XML_w, XML_tblPrChange )
1905 : };
1906 :
1907 : // postpone the output so that we can later []
1908 : // prepend the properties before the run
1909 9 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
1910 9 : uno::Sequence< sal_Int32 > aSeqOrder( len );
1911 153 : for ( sal_Int32 i = 0; i < len; i++ )
1912 144 : aSeqOrder[i] = aOrder[i];
1913 :
1914 9 : m_pSerializer->mark( aSeqOrder );
1915 :
1916 9 : sal_uInt32 nPageSize = 0;
1917 9 : bool bRelBoxSize = false;
1918 :
1919 : // Create the SwWriteTable instance to use col spans (and maybe other infos)
1920 9 : GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
1921 :
1922 : // Output the table prefered width
1923 9 : if ( nPageSize != 0 )
1924 : m_pSerializer->singleElementNS( XML_w, XML_tblW,
1925 : FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nPageSize ) ).getStr( ),
1926 : FSNS( XML_w, XML_type ), "dxa",
1927 0 : FSEND );
1928 :
1929 : // Output the table alignement
1930 9 : const SwTable *pTable = pTableTextNodeInfoInner->getTable();
1931 9 : SwFrmFmt *pTblFmt = pTable->GetFrmFmt( );
1932 : const char* pJcVal;
1933 9 : sal_Int32 nIndent = 0;
1934 9 : switch ( pTblFmt->GetHoriOrient( ).GetHoriOrient( ) )
1935 : {
1936 : case text::HoriOrientation::CENTER:
1937 0 : pJcVal = "center";
1938 0 : break;
1939 : case text::HoriOrientation::RIGHT:
1940 0 : if ( bEcma )
1941 0 : pJcVal = "right";
1942 : else
1943 0 : pJcVal = "end";
1944 0 : break;
1945 : default:
1946 : case text::HoriOrientation::NONE:
1947 : case text::HoriOrientation::LEFT_AND_WIDTH:
1948 : {
1949 9 : if ( bEcma )
1950 0 : pJcVal = "left";
1951 : else
1952 9 : pJcVal = "start";
1953 9 : nIndent = sal_Int32( pTblFmt->GetLRSpace( ).GetLeft( ) );
1954 : // Table indentation has different meaning in Word, depending if the table is nested or not.
1955 : // If nested, tblInd is added to parent table's left spacing and defines left edge position
1956 : // If not nested, text position of left-most cell must be at absolute X = tblInd
1957 : // so, table_spacing + table_spacing_to_content = tblInd
1958 9 : if (m_nTableDepth == 0)
1959 : {
1960 9 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1961 9 : const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
1962 9 : nIndent += sal_Int32( pFrmFmt->GetBox( ).GetDistance( BOX_LINE_LEFT ) );
1963 : }
1964 9 : break;
1965 : }
1966 : }
1967 : m_pSerializer->singleElementNS( XML_w, XML_jc,
1968 : FSNS( XML_w, XML_val ), pJcVal,
1969 9 : FSEND );
1970 :
1971 : // Output the table borders
1972 9 : TableDefaultBorders( pTableTextNodeInfoInner );
1973 :
1974 : // Output the default cell margins
1975 9 : TableDefaultCellMargins( pTableTextNodeInfoInner );
1976 :
1977 9 : TableBidi( pTableTextNodeInfoInner );
1978 :
1979 : // Table indent (need to get written even if == 0)
1980 : m_pSerializer->singleElementNS( XML_w, XML_tblInd,
1981 : FSNS( XML_w, XML_w ), OString::valueOf( nIndent ).getStr( ),
1982 : FSNS( XML_w, XML_type ), "dxa",
1983 9 : FSEND );
1984 :
1985 : // Merge the marks for the ordered elements
1986 9 : m_pSerializer->mergeTopMarks( );
1987 :
1988 9 : m_pSerializer->endElementNS( XML_w, XML_tblPr );
1989 :
1990 : // Write the table grid infos
1991 9 : m_pSerializer->startElementNS( XML_w, XML_tblGrid, FSEND );
1992 9 : sal_Int32 nPrv = 0;
1993 9 : ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
1994 31 : for ( ww8::GridCols::const_iterator it = pGridCols->begin(); it != pGridCols->end(); ++it )
1995 : {
1996 22 : sal_Int32 nWidth = sal_Int32( *it ) - nPrv;
1997 : m_pSerializer->singleElementNS( XML_w, XML_gridCol,
1998 : FSNS( XML_w, XML_w ), OString::valueOf( nWidth ).getStr( ),
1999 22 : FSEND );
2000 22 : nPrv = sal_Int32( *it );
2001 : }
2002 :
2003 9 : m_pSerializer->endElementNS( XML_w, XML_tblGrid );
2004 9 : }
2005 :
2006 9 : void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2007 : {
2008 9 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2009 9 : const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
2010 :
2011 9 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
2012 :
2013 : // the defaults of the table are taken from the top-left cell
2014 9 : impl_borders( m_pSerializer, pFrmFmt->GetBox( ), lcl_getTableDefaultBorderOptions(bEcma) );
2015 9 : }
2016 :
2017 9 : void DocxAttributeOutput::TableDefaultCellMargins( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2018 : {
2019 9 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2020 9 : const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
2021 9 : const SvxBoxItem& rBox = pFrmFmt->GetBox( );
2022 9 : const bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
2023 :
2024 9 : impl_cellMargins(m_pSerializer, rBox, XML_tblCellMar, !bEcma);
2025 9 : }
2026 :
2027 47 : void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2028 : {
2029 47 : const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
2030 47 : const SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
2031 47 : const SfxPoolItem *pI = NULL;
2032 :
2033 47 : Color aColor;
2034 47 : if ( SFX_ITEM_ON == pFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
2035 3 : aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
2036 : else
2037 44 : aColor = COL_AUTO;
2038 :
2039 47 : OString sColor = msfilter::util::ConvertColor( aColor );
2040 : m_pSerializer->singleElementNS( XML_w, XML_shd,
2041 : FSNS( XML_w, XML_fill ), sColor.getStr( ),
2042 : FSNS( XML_w, XML_val ), "clear",
2043 47 : FSEND );
2044 47 : }
2045 :
2046 17 : void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2047 : {
2048 17 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2049 17 : const SwTableLine * pTabLine = pTabBox->GetUpper();
2050 17 : const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
2051 :
2052 17 : const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
2053 17 : if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
2054 : {
2055 3 : sal_Int32 nHeight = rLSz.GetHeight();
2056 3 : const char *pRule = NULL;
2057 :
2058 3 : switch ( rLSz.GetHeightSizeType() )
2059 : {
2060 3 : case ATT_FIX_SIZE: pRule = "exact"; break;
2061 0 : case ATT_MIN_SIZE: pRule = "atLeast"; break;
2062 0 : default: break;
2063 : }
2064 :
2065 3 : if ( pRule )
2066 : m_pSerializer->singleElementNS( XML_w, XML_trHeight,
2067 : FSNS( XML_w, XML_val ), OString::valueOf( nHeight ).getStr( ),
2068 : FSNS( XML_w, XML_hRule ), pRule,
2069 3 : FSEND );
2070 : }
2071 17 : }
2072 :
2073 17 : void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2074 : {
2075 17 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2076 17 : const SwTableLine * pTabLine = pTabBox->GetUpper();
2077 17 : const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
2078 :
2079 17 : const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
2080 17 : const char* pCantSplit = ( !rSplittable.GetValue( ) ) ? "true" : "false";
2081 :
2082 : m_pSerializer->singleElementNS( XML_w, XML_cantSplit,
2083 : FSNS( XML_w, XML_val ), pCantSplit,
2084 17 : FSEND );
2085 17 : }
2086 :
2087 9 : void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2088 : {
2089 9 : const SwTable * pTable = pTableTextNodeInfoInner->getTable();
2090 9 : const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
2091 :
2092 9 : if ( m_rExport.TrueFrameDirection( *pFrmFmt ) == FRMDIR_HORI_RIGHT_TOP )
2093 : {
2094 : m_pSerializer->singleElementNS( XML_w, XML_bidiVisual,
2095 : FSNS( XML_w, XML_val ), "true",
2096 0 : FSEND );
2097 : }
2098 9 : }
2099 :
2100 47 : void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2101 : {
2102 47 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
2103 47 : const SwFrmFmt *pFrmFmt = pTabBox->GetFrmFmt( );
2104 :
2105 47 : if ( FRMDIR_VERT_TOP_RIGHT == m_rExport.TrueFrameDirection( *pFrmFmt ) )
2106 : m_pSerializer->singleElementNS( XML_w, XML_textDirection,
2107 : FSNS( XML_w, XML_val ), "tbRl",
2108 0 : FSEND );
2109 47 : else if ( FRMDIR_HORI_LEFT_TOP == m_rExport.TrueFrameDirection( *pFrmFmt ) )
2110 : {
2111 : // Undo the text direction mangling done by the btLr handler in writerfilter::dmapper::DomainMapperTableManager::sprm()
2112 47 : SwPaM aPam(*pTabBox->GetSttNd(), 0);
2113 47 : aPam.GetPoint()->nNode++;
2114 47 : if (aPam.GetPoint()->nNode.GetNode().IsTxtNode())
2115 : {
2116 47 : const SwTxtNode& rTxtNode = (const SwTxtNode&)aPam.GetPoint()->nNode.GetNode();
2117 47 : if( const SwAttrSet* pAttrSet = rTxtNode.GetpSwAttrSet())
2118 : {
2119 47 : const SvxCharRotateItem& rCharRotate = pAttrSet->GetCharRotate();
2120 47 : if (rCharRotate.GetValue() == 900)
2121 : {
2122 3 : m_pSerializer->singleElementNS( XML_w, XML_textDirection, FSNS( XML_w, XML_val ), "btLr", FSEND );
2123 3 : m_bBtLr = true;
2124 : }
2125 : }
2126 47 : }
2127 : }
2128 :
2129 47 : const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
2130 47 : SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
2131 47 : const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
2132 47 : switch( pCell->GetVertOri())
2133 : {
2134 : case text::VertOrientation::TOP:
2135 47 : break;
2136 : case text::VertOrientation::CENTER:
2137 : m_pSerializer->singleElementNS( XML_w, XML_vAlign,
2138 0 : FSNS( XML_w, XML_val ), "center", FSEND );
2139 0 : break;
2140 : case text::VertOrientation::BOTTOM:
2141 : m_pSerializer->singleElementNS( XML_w, XML_vAlign,
2142 0 : FSNS( XML_w, XML_val ), "bottom", FSEND );
2143 0 : break;
2144 : }
2145 47 : }
2146 :
2147 0 : void DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
2148 : {
2149 : OSL_TRACE( "TODO: DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )" );
2150 0 : }
2151 :
2152 94 : void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
2153 : {
2154 : // This is called when the nested table ends in a cell, and there's no
2155 : // paragraph benhind that; so we must check for the ends of cell, rows,
2156 : // tables
2157 : // ['true' to write an empty paragraph, MS Word insists on that]
2158 94 : FinishTableRowCell( pNodeInfoInner, true );
2159 94 : }
2160 :
2161 0 : void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
2162 : {
2163 : OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )" );
2164 0 : }
2165 :
2166 0 : void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
2167 : {
2168 : #if OSL_DEBUG_LEVEL > 1
2169 : fprintf( stderr, "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
2170 : #endif
2171 0 : }
2172 :
2173 0 : void DocxAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
2174 : {
2175 : OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )" );
2176 0 : }
2177 :
2178 48 : void DocxAttributeOutput::StartStyles()
2179 : {
2180 : m_pSerializer->startElementNS( XML_w, XML_styles,
2181 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
2182 48 : FSEND );
2183 48 : }
2184 :
2185 48 : void DocxAttributeOutput::EndStyles( sal_uInt16 /*nNumberOfStyles*/ )
2186 : {
2187 48 : m_pSerializer->endElementNS( XML_w, XML_styles );
2188 48 : }
2189 :
2190 671 : void DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )
2191 : {
2192 : // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
2193 : #if OSL_DEBUG_LEVEL > 1
2194 : OSL_TRACE( "TODO DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )- %d", nStyle );
2195 : #else
2196 : (void) nStyle; // to quiet the warning
2197 : #endif
2198 671 : }
2199 :
2200 1 : void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode )
2201 : {
2202 : OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode ) - some stuff still missing" );
2203 : // detect mis-use of the API
2204 : assert(pGrfNode || (pOLEFrmFmt && pOLENode));
2205 1 : const SwFrmFmt* pFrmFmt = pGrfNode ? pGrfNode->GetFlyFmt() : pOLEFrmFmt;
2206 : // create the relation ID
2207 1 : OString aRelId;
2208 : sal_Int32 nImageType;
2209 1 : if ( pGrfNode && pGrfNode->IsLinkedFile() )
2210 : {
2211 : // linked image, just create the relation
2212 0 : String aFileName;
2213 0 : pGrfNode->GetFileFilterNms( &aFileName, 0 );
2214 :
2215 : // TODO Convert the file name to relative for better interoperability
2216 :
2217 0 : aRelId = m_rExport.AddRelation(
2218 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
2219 0 : OUString( aFileName ) );
2220 :
2221 0 : nImageType = XML_link;
2222 : }
2223 : else
2224 : {
2225 : // inline, we also have to write the image itself
2226 1 : const Graphic* pGraphic = 0;
2227 1 : if (pGrfNode)
2228 0 : pGraphic = &const_cast< Graphic& >( pGrfNode->GetGrf() );
2229 : else
2230 1 : pGraphic = pOLENode->GetGraphic();
2231 :
2232 1 : m_rDrawingML.SetFS( m_pSerializer ); // to be sure that we write to the right stream
2233 1 : OUString aImageId = m_rDrawingML.WriteImage( *pGraphic );
2234 :
2235 1 : aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
2236 :
2237 1 : nImageType = XML_embed;
2238 : }
2239 :
2240 1 : if ( aRelId.isEmpty() )
2241 1 : return;
2242 :
2243 : m_pSerializer->startElementNS( XML_w, XML_drawing,
2244 1 : FSEND );
2245 1 : bool isAnchor = pFrmFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
2246 1 : if( isAnchor )
2247 : {
2248 1 : ::sax_fastparser::FastAttributeList* attrList = m_pSerializer->createAttrList();
2249 1 : attrList->add( XML_behindDoc, pFrmFmt->GetOpaque().GetValue() ? "0" : "1" );
2250 1 : attrList->add( XML_distT, "0" );
2251 1 : attrList->add( XML_distB, "0" );
2252 1 : attrList->add( XML_distL, "0" );
2253 1 : attrList->add( XML_distR, "0" );
2254 1 : attrList->add( XML_simplePos, "0" );
2255 1 : attrList->add( XML_locked, "0" );
2256 1 : attrList->add( XML_layoutInCell, "1" );
2257 1 : attrList->add( XML_allowOverlap, "1" ); // TODO
2258 1 : if( const SdrObject* pObj = pFrmFmt->FindRealSdrObject())
2259 1 : attrList->add( XML_relativeHeight, OString::valueOf( sal_Int32( pObj->GetOrdNum())));
2260 1 : m_pSerializer->startElementNS( XML_wp, XML_anchor, XFastAttributeListRef( attrList ));
2261 1 : m_pSerializer->singleElementNS( XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND ); // required, unused
2262 : const char* relativeFromH;
2263 : const char* relativeFromV;
2264 1 : const char* alignH = NULL;
2265 1 : const char* alignV = NULL;
2266 1 : switch (pFrmFmt->GetVertOrient().GetRelationOrient() )
2267 : {
2268 : case text::RelOrientation::PAGE_PRINT_AREA:
2269 0 : relativeFromV = "margin";
2270 0 : break;
2271 : case text::RelOrientation::PAGE_FRAME:
2272 0 : relativeFromV = "page";
2273 0 : break;
2274 : case text::RelOrientation::FRAME:
2275 1 : relativeFromV = "paragraph";
2276 1 : break;
2277 : case text::RelOrientation::TEXT_LINE:
2278 : default:
2279 0 : relativeFromV = "line";
2280 0 : break;
2281 : }
2282 1 : switch (pFrmFmt->GetVertOrient().GetVertOrient() )
2283 : {
2284 : case text::VertOrientation::TOP:
2285 : case text::VertOrientation::CHAR_TOP:
2286 : case text::VertOrientation::LINE_TOP:
2287 1 : if( pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE)
2288 0 : alignV = "bottom";
2289 : else
2290 1 : alignV = "top";
2291 1 : break;
2292 : case text::VertOrientation::BOTTOM:
2293 : case text::VertOrientation::CHAR_BOTTOM:
2294 : case text::VertOrientation::LINE_BOTTOM:
2295 0 : if( pFrmFmt->GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE)
2296 0 : alignV = "top";
2297 : else
2298 0 : alignV = "bottom";
2299 0 : break;
2300 : case text::VertOrientation::CENTER:
2301 : case text::VertOrientation::CHAR_CENTER:
2302 : case text::VertOrientation::LINE_CENTER:
2303 0 : alignV = "center";
2304 0 : break;
2305 : default:
2306 0 : break;
2307 : }
2308 1 : switch (pFrmFmt->GetHoriOrient().GetRelationOrient() )
2309 : {
2310 : case text::RelOrientation::PAGE_PRINT_AREA:
2311 0 : relativeFromH = "margin";
2312 0 : break;
2313 : case text::RelOrientation::PAGE_FRAME:
2314 0 : relativeFromH = "page";
2315 0 : break;
2316 : case text::RelOrientation::CHAR:
2317 0 : relativeFromH = "character";
2318 0 : break;
2319 : case text::RelOrientation::FRAME:
2320 : default:
2321 1 : relativeFromH = "column";
2322 1 : break;
2323 : }
2324 1 : switch (pFrmFmt->GetHoriOrient().GetHoriOrient() )
2325 : {
2326 : case text::HoriOrientation::LEFT:
2327 0 : alignH = "left";
2328 0 : break;
2329 : case text::HoriOrientation::RIGHT:
2330 0 : alignH = "right";
2331 0 : break;
2332 : case text::HoriOrientation::CENTER:
2333 1 : alignH = "center";
2334 1 : break;
2335 : case text::HoriOrientation::INSIDE:
2336 0 : alignH = "inside";
2337 0 : break;
2338 : case text::HoriOrientation::OUTSIDE:
2339 0 : alignH = "outside";
2340 0 : break;
2341 : default:
2342 0 : break;
2343 : }
2344 1 : m_pSerializer->startElementNS( XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND );
2345 1 : if( alignH != NULL )
2346 : {
2347 1 : m_pSerializer->startElementNS( XML_wp, XML_align, FSEND );
2348 1 : m_pSerializer->write( alignH );
2349 1 : m_pSerializer->endElementNS( XML_wp, XML_align );
2350 : }
2351 : else
2352 : {
2353 0 : m_pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND );
2354 0 : m_pSerializer->write( TwipsToEMU( pFrmFmt->GetHoriOrient().GetPos()));
2355 0 : m_pSerializer->endElementNS( XML_wp, XML_posOffset );
2356 : }
2357 1 : m_pSerializer->endElementNS( XML_wp, XML_positionH );
2358 1 : m_pSerializer->startElementNS( XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND );
2359 1 : if( alignV != NULL )
2360 : {
2361 1 : m_pSerializer->startElementNS( XML_wp, XML_align, FSEND );
2362 1 : m_pSerializer->write( alignV );
2363 1 : m_pSerializer->endElementNS( XML_wp, XML_align );
2364 : }
2365 : else
2366 : {
2367 0 : m_pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND );
2368 0 : m_pSerializer->write( TwipsToEMU( pFrmFmt->GetVertOrient().GetPos()));
2369 0 : m_pSerializer->endElementNS( XML_wp, XML_posOffset );
2370 : }
2371 1 : m_pSerializer->endElementNS( XML_wp, XML_positionV );
2372 : }
2373 : else
2374 : {
2375 : m_pSerializer->startElementNS( XML_wp, XML_inline,
2376 : XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
2377 0 : FSEND );
2378 : }
2379 : // now the common parts
2380 : // extent of the image
2381 1 : OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
2382 2 : OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
2383 : m_pSerializer->singleElementNS( XML_wp, XML_extent,
2384 : XML_cx, aWidth.getStr(),
2385 : XML_cy, aHeight.getStr(),
2386 1 : FSEND );
2387 :
2388 : // effectExtent, extent including the effect (shadow only for now)
2389 2 : SvxShadowItem aShadowItem = pFrmFmt->GetShadow();
2390 2 : OString aLeftExt("0"), aRightExt("0"), aTopExt("0"), aBottomExt("0");
2391 1 : if ( aShadowItem.GetLocation() != SVX_SHADOW_NONE )
2392 : {
2393 0 : OString aShadowWidth( OString::valueOf( TwipsToEMU( aShadowItem.GetWidth() ) ) );
2394 0 : switch ( aShadowItem.GetLocation() )
2395 : {
2396 : case SVX_SHADOW_TOPLEFT:
2397 0 : aTopExt = aLeftExt = aShadowWidth;
2398 0 : break;
2399 : case SVX_SHADOW_TOPRIGHT:
2400 0 : aTopExt = aRightExt = aShadowWidth;
2401 0 : break;
2402 : case SVX_SHADOW_BOTTOMLEFT:
2403 0 : aBottomExt = aLeftExt = aShadowWidth;
2404 0 : break;
2405 : case SVX_SHADOW_BOTTOMRIGHT:
2406 0 : aBottomExt = aRightExt = aShadowWidth;
2407 0 : break;
2408 : case SVX_SHADOW_NONE:
2409 : case SVX_SHADOW_END:
2410 0 : break;
2411 0 : }
2412 : }
2413 :
2414 : m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
2415 : XML_l, aLeftExt, XML_t, aTopExt, XML_r, aRightExt, XML_b, aBottomExt,
2416 1 : FSEND );
2417 :
2418 1 : if( isAnchor )
2419 : {
2420 1 : switch( pFrmFmt->GetSurround().GetValue())
2421 : {
2422 : case SURROUND_NONE:
2423 0 : m_pSerializer->singleElementNS( XML_wp, XML_wrapTopAndBottom, FSEND );
2424 0 : break;
2425 : case SURROUND_THROUGHT:
2426 0 : m_pSerializer->singleElementNS( XML_wp, XML_wrapNone, FSEND );
2427 0 : break;
2428 : case SURROUND_PARALLEL:
2429 : m_pSerializer->singleElementNS( XML_wp, XML_wrapSquare,
2430 0 : XML_wrapText, "bothSides", FSEND );
2431 0 : break;
2432 : case SURROUND_IDEAL:
2433 : default:
2434 : m_pSerializer->singleElementNS( XML_wp, XML_wrapSquare,
2435 1 : XML_wrapText, "largest", FSEND );
2436 1 : break;
2437 : }
2438 : }
2439 : // picture description (used for pic:cNvPr later too)
2440 1 : ::sax_fastparser::FastAttributeList* docPrattrList = m_pSerializer->createAttrList();
2441 1 : docPrattrList->add( XML_id, OString::valueOf( sal_Int32( m_anchorId++ )).getStr());
2442 1 : docPrattrList->add( XML_name, "Picture" );
2443 1 : docPrattrList->add( XML_descr, OUStringToOString( pGrfNode ? pGrfNode->GetDescription() : pOLEFrmFmt->GetObjDescription(), RTL_TEXTENCODING_UTF8 ).getStr());
2444 1 : if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT )
2445 1 : docPrattrList->add( XML_title, OUStringToOString( pGrfNode ? pGrfNode->GetTitle() : pOLEFrmFmt->GetObjTitle(), RTL_TEXTENCODING_UTF8 ).getStr());
2446 1 : XFastAttributeListRef docPrAttrListRef( docPrattrList );
2447 1 : m_pSerializer->startElementNS( XML_wp, XML_docPr, docPrAttrListRef );
2448 : // TODO hyperlink
2449 : // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
2450 : // FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
2451 : // FSNS( XML_r, XML_id ), "rId4",
2452 : // FSEND );
2453 1 : m_pSerializer->endElementNS( XML_wp, XML_docPr );
2454 :
2455 : m_pSerializer->startElementNS( XML_wp, XML_cNvGraphicFramePr,
2456 1 : FSEND );
2457 : // TODO change aspect?
2458 : m_pSerializer->singleElementNS( XML_a, XML_graphicFrameLocks,
2459 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
2460 : XML_noChangeAspect, "1",
2461 1 : FSEND );
2462 1 : m_pSerializer->endElementNS( XML_wp, XML_cNvGraphicFramePr );
2463 :
2464 : m_pSerializer->startElementNS( XML_a, XML_graphic,
2465 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
2466 1 : FSEND );
2467 : m_pSerializer->startElementNS( XML_a, XML_graphicData,
2468 : XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/picture",
2469 1 : FSEND );
2470 :
2471 : m_pSerializer->startElementNS( XML_pic, XML_pic,
2472 : FSNS( XML_xmlns, XML_pic ), "http://schemas.openxmlformats.org/drawingml/2006/picture",
2473 1 : FSEND );
2474 :
2475 : m_pSerializer->startElementNS( XML_pic, XML_nvPicPr,
2476 1 : FSEND );
2477 : // It seems pic:cNvpr and wp:docPr are pretty much the same thing with the same attributes
2478 1 : m_pSerializer->startElementNS( XML_pic, XML_cNvPr, docPrAttrListRef );
2479 :
2480 : // TODO hyperlink
2481 : // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
2482 : // FSNS( XML_r, XML_id ), "rId4",
2483 : // FSEND );
2484 1 : m_pSerializer->endElementNS( XML_pic, XML_cNvPr );
2485 :
2486 : m_pSerializer->startElementNS( XML_pic, XML_cNvPicPr,
2487 1 : FSEND );
2488 : // TODO change aspect?
2489 : m_pSerializer->singleElementNS( XML_a, XML_picLocks,
2490 : XML_noChangeAspect, "1", XML_noChangeArrowheads, "1",
2491 1 : FSEND );
2492 1 : m_pSerializer->endElementNS( XML_pic, XML_cNvPicPr );
2493 1 : m_pSerializer->endElementNS( XML_pic, XML_nvPicPr );
2494 :
2495 : // the actual picture
2496 : m_pSerializer->startElementNS( XML_pic, XML_blipFill,
2497 1 : FSEND );
2498 : m_pSerializer->singleElementNS( XML_a, XML_blip,
2499 : FSNS( XML_r, nImageType ), aRelId.getStr(),
2500 1 : FSEND );
2501 : m_pSerializer->singleElementNS( XML_a, XML_srcRect,
2502 1 : FSEND );
2503 : m_pSerializer->startElementNS( XML_a, XML_stretch,
2504 1 : FSEND );
2505 : m_pSerializer->singleElementNS( XML_a, XML_fillRect,
2506 1 : FSEND );
2507 1 : m_pSerializer->endElementNS( XML_a, XML_stretch );
2508 1 : m_pSerializer->endElementNS( XML_pic, XML_blipFill );
2509 :
2510 : // TODO setup the right values below
2511 : m_pSerializer->startElementNS( XML_pic, XML_spPr,
2512 : XML_bwMode, "auto",
2513 1 : FSEND );
2514 : m_pSerializer->startElementNS( XML_a, XML_xfrm,
2515 1 : FSEND );
2516 : m_pSerializer->singleElementNS( XML_a, XML_off,
2517 : XML_x, "0", XML_y, "0",
2518 1 : FSEND );
2519 : m_pSerializer->singleElementNS( XML_a, XML_ext,
2520 : XML_cx, aWidth.getStr(),
2521 : XML_cy, aHeight.getStr(),
2522 1 : FSEND );
2523 1 : m_pSerializer->endElementNS( XML_a, XML_xfrm );
2524 : m_pSerializer->startElementNS( XML_a, XML_prstGeom,
2525 : XML_prst, "rect",
2526 1 : FSEND );
2527 : m_pSerializer->singleElementNS( XML_a, XML_avLst,
2528 1 : FSEND );
2529 1 : m_pSerializer->endElementNS( XML_a, XML_prstGeom );
2530 : m_pSerializer->singleElementNS( XML_a, XML_noFill,
2531 1 : FSEND );
2532 : m_pSerializer->startElementNS( XML_a, XML_ln,
2533 : XML_w, "9525",
2534 1 : FSEND );
2535 : m_pSerializer->singleElementNS( XML_a, XML_noFill,
2536 1 : FSEND );
2537 : m_pSerializer->singleElementNS( XML_a, XML_miter,
2538 : XML_lim, "800000",
2539 1 : FSEND );
2540 : m_pSerializer->singleElementNS( XML_a, XML_headEnd,
2541 1 : FSEND );
2542 : m_pSerializer->singleElementNS( XML_a, XML_tailEnd,
2543 1 : FSEND );
2544 1 : m_pSerializer->endElementNS( XML_a, XML_ln );
2545 :
2546 : // Output effects
2547 1 : if ( aShadowItem.GetLocation() != SVX_SHADOW_NONE )
2548 : {
2549 : // Distance is measured diagonally from corner
2550 0 : double nShadowDist = sqrt((aShadowItem.GetWidth()*aShadowItem.GetWidth())*2.0);
2551 0 : OString aShadowDist( OString::valueOf( TwipsToEMU( nShadowDist ) ) );
2552 0 : OString aShadowColor = msfilter::util::ConvertColor( aShadowItem.GetColor() );
2553 0 : sal_uInt32 nShadowDir = 0;
2554 0 : switch ( aShadowItem.GetLocation() )
2555 : {
2556 0 : case SVX_SHADOW_TOPLEFT: nShadowDir = 13500000; break;
2557 0 : case SVX_SHADOW_TOPRIGHT: nShadowDir = 18900000; break;
2558 0 : case SVX_SHADOW_BOTTOMLEFT: nShadowDir = 8100000; break;
2559 0 : case SVX_SHADOW_BOTTOMRIGHT: nShadowDir = 2700000; break;
2560 : case SVX_SHADOW_NONE:
2561 : case SVX_SHADOW_END:
2562 0 : break;
2563 : }
2564 0 : OString aShadowDir( OString::valueOf( long(nShadowDir) ) );
2565 :
2566 0 : m_pSerializer->startElementNS( XML_a, XML_effectLst, FSEND );
2567 : m_pSerializer->startElementNS( XML_a, XML_outerShdw,
2568 : XML_dist, aShadowDist.getStr(),
2569 0 : XML_dir, aShadowDir.getStr(), FSEND );
2570 : m_pSerializer->singleElementNS( XML_a, XML_srgbClr,
2571 0 : XML_val, aShadowColor.getStr(), FSEND );
2572 0 : m_pSerializer->endElementNS( XML_a, XML_outerShdw );
2573 0 : m_pSerializer->endElementNS( XML_a, XML_effectLst );
2574 : }
2575 :
2576 1 : m_pSerializer->endElementNS( XML_pic, XML_spPr );
2577 :
2578 1 : m_pSerializer->endElementNS( XML_pic, XML_pic );
2579 :
2580 1 : m_pSerializer->endElementNS( XML_a, XML_graphicData );
2581 1 : m_pSerializer->endElementNS( XML_a, XML_graphic );
2582 1 : m_pSerializer->endElementNS( XML_wp, isAnchor ? XML_anchor : XML_inline );
2583 :
2584 2 : m_pSerializer->endElementNS( XML_w, XML_drawing );
2585 : }
2586 :
2587 44 : void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rOLENode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt )
2588 : {
2589 44 : if( WriteOLEChart( pSdrObj, rSize ))
2590 0 : return;
2591 44 : if( WriteOLEMath( pSdrObj, rOLENode, rSize ))
2592 43 : return;
2593 : // Then we fall back to just export the object as a graphic.
2594 1 : FlyFrameGraphic( 0, rSize, pFlyFrmFmt, &rOLENode );
2595 : }
2596 :
2597 44 : bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& rSize )
2598 : {
2599 44 : uno::Reference< chart2::XChartDocument > xChartDoc;
2600 88 : uno::Reference< drawing::XShape > xShape( ((SdrObject*)pSdrObj)->getUnoShape(), uno::UNO_QUERY );
2601 44 : if( xShape.is() )
2602 : {
2603 44 : uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
2604 44 : if( xPropSet.is() )
2605 44 : xChartDoc.set( xPropSet->getPropertyValue( "Model" ), uno::UNO_QUERY );
2606 : }
2607 :
2608 44 : if( xChartDoc.is() )
2609 : {
2610 : OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
2611 : m_pSerializer->startElementNS( XML_w, XML_drawing,
2612 0 : FSEND );
2613 : m_pSerializer->startElementNS( XML_wp, XML_inline,
2614 : XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
2615 0 : FSEND );
2616 :
2617 0 : OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
2618 0 : OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
2619 : m_pSerializer->singleElementNS( XML_wp, XML_extent,
2620 : XML_cx, aWidth.getStr(),
2621 : XML_cy, aHeight.getStr(),
2622 0 : FSEND );
2623 : // TODO - the right effectExtent, extent including the effect
2624 : m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
2625 : XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
2626 0 : FSEND );
2627 :
2628 : // should get the unique id
2629 0 : sal_Int32 nID = 1;
2630 0 : OUString sName("Object 1");
2631 0 : uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
2632 0 : if( xNamed.is() )
2633 0 : sName = xNamed->getName();
2634 :
2635 : m_pSerializer->singleElementNS( XML_wp, XML_docPr,
2636 : XML_id, I32S( nID ),
2637 : XML_name, USS( sName ),
2638 0 : FSEND );
2639 :
2640 : m_pSerializer->singleElementNS( XML_wp, XML_cNvGraphicFramePr,
2641 0 : FSEND );
2642 :
2643 : m_pSerializer->startElementNS( XML_a, XML_graphic,
2644 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
2645 0 : FSEND );
2646 :
2647 : m_pSerializer->startElementNS( XML_a, XML_graphicData,
2648 : XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart",
2649 0 : FSEND );
2650 :
2651 0 : OString aRelId;
2652 : static sal_Int32 nChartCount = 0;
2653 0 : nChartCount++;
2654 0 : uno::Reference< frame::XModel > xModel( xChartDoc, uno::UNO_QUERY );
2655 0 : aRelId = m_rExport.OutputChart( xModel, nChartCount );
2656 :
2657 : m_pSerializer->singleElementNS( XML_c, XML_chart,
2658 : FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
2659 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
2660 : FSNS( XML_r, XML_id ), aRelId.getStr(),
2661 0 : FSEND );
2662 :
2663 0 : m_pSerializer->endElementNS( XML_a, XML_graphicData );
2664 0 : m_pSerializer->endElementNS( XML_a, XML_graphic );
2665 0 : m_pSerializer->endElementNS( XML_wp, XML_inline );
2666 0 : m_pSerializer->endElementNS( XML_w, XML_drawing );
2667 :
2668 0 : return true;
2669 : }
2670 88 : return false;
2671 : }
2672 :
2673 44 : bool DocxAttributeOutput::WriteOLEMath( const SdrObject*, const SwOLENode& rOLENode, const Size& )
2674 : {
2675 44 : uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
2676 44 : sal_Int64 nAspect = rOLENode.GetAspect();
2677 88 : svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
2678 88 : SvGlobalName aObjName(aObjRef->getClassID());
2679 :
2680 44 : if( !SotExchange::IsMath(aObjName) )
2681 1 : return false;
2682 : assert( m_postponedMath == NULL ); // make it a list if there can be more inside one run
2683 43 : m_postponedMath = &rOLENode;
2684 87 : return true;
2685 : }
2686 :
2687 290 : void DocxAttributeOutput::WritePostponedMath()
2688 : {
2689 290 : if( m_postponedMath == NULL )
2690 537 : return;
2691 43 : uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode*>(m_postponedMath)->GetOLEObj().GetOleRef());
2692 86 : uno::Reference< uno::XInterface > xInterface( xObj->getComponent(), uno::UNO_QUERY );
2693 : // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
2694 : // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
2695 : // to RTLD_GLOBAL, so most probably a gcc bug.
2696 43 : oox::FormulaExportBase* formulaexport = dynamic_cast<oox::FormulaExportBase*>(dynamic_cast<SfxBaseModel*>(xInterface.get()));
2697 : assert( formulaexport != NULL );
2698 43 : formulaexport->writeFormulaOoxml( m_pSerializer, GetExport().GetFilter().getVersion());
2699 86 : m_postponedMath = NULL;
2700 : }
2701 :
2702 53 : void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Point& rNdTopLeft )
2703 : {
2704 53 : m_pSerializer->mark();
2705 :
2706 53 : switch ( rFrame.GetWriterType() )
2707 : {
2708 : case sw::Frame::eGraphic:
2709 : {
2710 0 : const SwNode *pNode = rFrame.GetContent();
2711 0 : const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
2712 0 : if ( pGrfNode )
2713 : {
2714 0 : if( m_postponedGraphic == NULL )
2715 0 : FlyFrameGraphic( pGrfNode, rFrame.GetLayoutSize() );
2716 : else // we are writing out attributes, but w:drawing should not be inside w:rPr,
2717 : { // so write it out later
2718 0 : m_postponedGraphic->push_back( PostponedGraphic( pGrfNode, rFrame.GetLayoutSize()));
2719 : }
2720 : }
2721 : }
2722 0 : break;
2723 : case sw::Frame::eDrawing:
2724 : {
2725 1 : const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
2726 1 : if ( pSdrObj )
2727 : {
2728 1 : bool bSwapInPage = false;
2729 1 : if ( !pSdrObj->GetPage() )
2730 : {
2731 0 : if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() )
2732 : {
2733 0 : if ( SdrPage *pPage = pModel->GetPage( 0 ) )
2734 : {
2735 0 : bSwapInPage = true;
2736 0 : const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
2737 : }
2738 : }
2739 : }
2740 :
2741 : m_pSerializer->startElementNS( XML_w, XML_pict,
2742 1 : FSEND );
2743 :
2744 : // See WinwordAnchoring::SetAnchoring(), these are not part of the SdrObject, have to be passed around manually.
2745 1 : const SwFrmFmt& rFrmFmt = rFrame.GetFrmFmt();
2746 1 : SwFmtHoriOrient rHoriOri = rFrmFmt.GetHoriOrient();
2747 2 : SwFmtVertOrient rVertOri = rFrmFmt.GetVertOrient();
2748 1 : m_rExport.VMLExporter().AddSdrObject( *pSdrObj,
2749 2 : rHoriOri.GetHoriOrient(), rVertOri.GetVertOrient(),
2750 1 : rHoriOri.GetRelationOrient(),
2751 5 : rVertOri.GetRelationOrient(), &rNdTopLeft );
2752 :
2753 1 : m_pSerializer->endElementNS( XML_w, XML_pict );
2754 :
2755 1 : if ( bSwapInPage )
2756 1 : const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
2757 : }
2758 : }
2759 1 : break;
2760 : case sw::Frame::eTxtBox:
2761 : {
2762 : // The frame output is postponed to the end of the anchor paragraph
2763 8 : m_pParentFrame = new sw::Frame(rFrame);
2764 : }
2765 8 : break;
2766 : case sw::Frame::eOle:
2767 : {
2768 44 : const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
2769 44 : const SdrObject *pSdrObj = rFrmFmt.FindRealSdrObject();
2770 44 : if ( pSdrObj )
2771 : {
2772 44 : SwNodeIndex aIdx(*rFrmFmt.GetCntnt().GetCntntIdx(), 1);
2773 44 : SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
2774 44 : WriteOLE2Obj( pSdrObj, rOLENd, rFrame.GetLayoutSize(), dynamic_cast<const SwFlyFrmFmt*>( &rFrmFmt ));
2775 : }
2776 : }
2777 44 : break;
2778 : default:
2779 : OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
2780 : rFrame.GetWriterType() == sw::Frame::eTxtBox? "eTxtBox":
2781 : ( rFrame.GetWriterType() == sw::Frame::eOle? "eOle":
2782 : ( rFrame.GetWriterType() == sw::Frame::eFormControl? "eFormControl": "???" ) ) );
2783 0 : break;
2784 : }
2785 :
2786 53 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
2787 53 : }
2788 :
2789 0 : void DocxAttributeOutput::WriteOutliner(const OutlinerParaObject& rParaObj)
2790 : {
2791 0 : const EditTextObject& rEditObj = rParaObj.GetTextObject();
2792 0 : MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
2793 :
2794 0 : sal_Int32 nPara = rEditObj.GetParagraphCount();
2795 :
2796 0 : m_pSerializer->startElementNS( XML_w, XML_textbox, FSEND );
2797 0 : m_pSerializer->startElementNS( XML_w, XML_txbxContent, FSEND );
2798 0 : for (sal_Int32 n = 0; n < nPara; ++n)
2799 : {
2800 0 : if( n )
2801 0 : aAttrIter.NextPara( n );
2802 :
2803 0 : String aStr( rEditObj.GetText( n ));
2804 0 : xub_StrLen nAktPos = 0;
2805 0 : xub_StrLen nEnd = aStr.Len();
2806 :
2807 0 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
2808 0 : do {
2809 0 : xub_StrLen nNextAttr = aAttrIter.WhereNext();
2810 0 : if( nNextAttr > nEnd )
2811 0 : nNextAttr = nEnd;
2812 :
2813 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
2814 0 : bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
2815 0 : if( !bTxtAtr )
2816 : {
2817 0 : String aOut( aStr.Copy( nAktPos, nNextAttr - nAktPos ) );
2818 0 : RunText(aOut);
2819 : }
2820 :
2821 0 : m_pSerializer->endElementNS( XML_w, XML_r );
2822 :
2823 0 : nAktPos = nNextAttr;
2824 0 : aAttrIter.NextPos();
2825 : }
2826 : while( nAktPos < nEnd );
2827 0 : m_pSerializer->endElementNS( XML_w, XML_p );
2828 0 : }
2829 0 : m_pSerializer->endElementNS( XML_w, XML_txbxContent );
2830 0 : m_pSerializer->endElementNS( XML_w, XML_textbox );
2831 0 : }
2832 :
2833 0 : oox::drawingml::DrawingML& DocxAttributeOutput::GetDrawingML()
2834 : {
2835 0 : return m_rDrawingML;
2836 : }
2837 :
2838 372 : void DocxAttributeOutput::StartStyle( const String& rName, bool bPapFmt,
2839 : sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId, bool bAutoUpdate )
2840 : {
2841 372 : OString aStyle( "style" );
2842 :
2843 : m_pSerializer->startElementNS( XML_w, XML_style,
2844 : FSNS( XML_w, XML_type ), bPapFmt? "paragraph": "character", // FIXME is this correct?
2845 744 : FSNS( XML_w, XML_styleId ), OString( aStyle + OString::valueOf( sal_Int32( nId ) ) ).getStr(),
2846 372 : FSEND );
2847 :
2848 : m_pSerializer->singleElementNS( XML_w, XML_name,
2849 : FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
2850 372 : FSEND );
2851 :
2852 372 : if ( nBase != 0x0FFF )
2853 : {
2854 : m_pSerializer->singleElementNS( XML_w, XML_basedOn,
2855 592 : FSNS( XML_w, XML_val ), OString( aStyle + OString::valueOf( sal_Int32( nBase ) ) ).getStr(),
2856 296 : FSEND );
2857 : }
2858 :
2859 : m_pSerializer->singleElementNS( XML_w, XML_next,
2860 744 : FSNS( XML_w, XML_val ), OString( aStyle + OString::valueOf( sal_Int32( nNext ) ) ).getStr(),
2861 372 : FSEND );
2862 :
2863 372 : if ( bAutoUpdate )
2864 0 : m_pSerializer->singleElementNS( XML_w, XML_autoRedefine, FSEND );
2865 372 : }
2866 :
2867 372 : void DocxAttributeOutput::EndStyle()
2868 : {
2869 372 : m_pSerializer->endElementNS( XML_w, XML_style );
2870 372 : }
2871 :
2872 692 : void DocxAttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 /*nStyle*/ )
2873 : {
2874 692 : if ( bParProp )
2875 : {
2876 320 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
2877 320 : InitCollectedParagraphProperties();
2878 : }
2879 : else
2880 : {
2881 372 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
2882 372 : InitCollectedRunProperties();
2883 : }
2884 692 : }
2885 :
2886 692 : void DocxAttributeOutput::EndStyleProperties( bool bParProp )
2887 : {
2888 692 : if ( bParProp )
2889 : {
2890 320 : WriteCollectedParagraphProperties();
2891 320 : m_pSerializer->endElementNS( XML_w, XML_pPr );
2892 : }
2893 : else
2894 : {
2895 372 : WriteCollectedRunProperties();
2896 372 : m_pSerializer->endElementNS( XML_w, XML_rPr );
2897 : }
2898 692 : }
2899 :
2900 0 : void DocxAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
2901 : {
2902 0 : if ( nLvl >= WW8ListManager::nMaxLevel )
2903 0 : nLvl = WW8ListManager::nMaxLevel - 1;
2904 :
2905 : m_pSerializer->singleElementNS( XML_w, XML_outlineLvl,
2906 : FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl ) ).getStr( ),
2907 0 : FSEND );
2908 0 : }
2909 :
2910 9 : void DocxAttributeOutput::PageBreakBefore( bool bBreak )
2911 : {
2912 9 : if ( bBreak )
2913 9 : m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore, FSEND );
2914 : else
2915 : m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore,
2916 : FSNS( XML_w, XML_val ), "false",
2917 0 : FSEND );
2918 9 : }
2919 :
2920 0 : void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
2921 : {
2922 0 : switch ( nC )
2923 : {
2924 : case msword::ColumnBreak:
2925 : // The column break should be output in the next paragraph...
2926 0 : m_nColBreakStatus = COLBRK_POSTPONE;
2927 0 : break;
2928 : case msword::PageBreak:
2929 0 : if ( pSectionInfo )
2930 : {
2931 0 : if ( !m_bParagraphOpened )
2932 : {
2933 : // Create a dummy paragraph if needed
2934 0 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
2935 0 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
2936 :
2937 0 : m_rExport.SectionProperties( *pSectionInfo );
2938 :
2939 0 : m_pSerializer->endElementNS( XML_w, XML_pPr );
2940 0 : m_pSerializer->endElementNS( XML_w, XML_p );
2941 : }
2942 : else
2943 : {
2944 : // postpone the output of this; it has to be done inside the
2945 : // paragraph properties, so remember it until then
2946 0 : m_pSectionInfo.reset( new WW8_SepInfo( *pSectionInfo ));
2947 : }
2948 : }
2949 : else
2950 : {
2951 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
2952 : m_pSerializer->singleElementNS( XML_w, XML_br,
2953 0 : FSNS( XML_w, XML_type ), "page", FSEND );
2954 0 : m_pSerializer->endElementNS( XML_w, XML_r );
2955 : }
2956 0 : break;
2957 : default:
2958 : OSL_TRACE( "Unknown section break to write: %d", nC );
2959 0 : break;
2960 : }
2961 0 : }
2962 :
2963 48 : void DocxAttributeOutput::StartSection()
2964 : {
2965 48 : m_pSerializer->startElementNS( XML_w, XML_sectPr, FSEND );
2966 48 : m_bOpenedSectPr = true;
2967 :
2968 : // Write the elements in the spec order
2969 : static const sal_Int32 aOrder[] =
2970 : {
2971 : FSNS( XML_w, XML_headerReference ),
2972 : FSNS( XML_w, XML_footerReference ),
2973 : FSNS( XML_w, XML_footnotePr ),
2974 : FSNS( XML_w, XML_endnotePr ),
2975 : FSNS( XML_w, XML_type ),
2976 : FSNS( XML_w, XML_pgSz ),
2977 : FSNS( XML_w, XML_pgMar ),
2978 : FSNS( XML_w, XML_paperSrc ),
2979 : FSNS( XML_w, XML_pgBorders ),
2980 : FSNS( XML_w, XML_lnNumType ),
2981 : FSNS( XML_w, XML_pgNumType ),
2982 : FSNS( XML_w, XML_cols ),
2983 : FSNS( XML_w, XML_formProt ),
2984 : FSNS( XML_w, XML_vAlign ),
2985 : FSNS( XML_w, XML_noEndnote ),
2986 : FSNS( XML_w, XML_titlePg ),
2987 : FSNS( XML_w, XML_textDirection ),
2988 : FSNS( XML_w, XML_bidi ),
2989 : FSNS( XML_w, XML_rtlGutter ),
2990 : FSNS( XML_w, XML_docGrid ),
2991 : FSNS( XML_w, XML_printerSettings ),
2992 : FSNS( XML_w, XML_sectPrChange )
2993 : };
2994 :
2995 : // postpone the output so that we can later [in EndParagraphProperties()]
2996 : // prepend the properties before the run
2997 48 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
2998 48 : uno::Sequence< sal_Int32 > aSeqOrder( len );
2999 1104 : for ( sal_Int32 i = 0; i < len; i++ )
3000 1056 : aSeqOrder[i] = aOrder[i];
3001 :
3002 48 : m_pSerializer->mark( aSeqOrder );
3003 48 : }
3004 :
3005 48 : void DocxAttributeOutput::EndSection()
3006 : {
3007 : // Write the section properties
3008 48 : if ( m_pSectionSpacingAttrList )
3009 : {
3010 48 : XFastAttributeListRef xAttrList( m_pSectionSpacingAttrList );
3011 48 : m_pSectionSpacingAttrList = NULL;
3012 :
3013 48 : m_pSerializer->singleElementNS( XML_w, XML_pgMar, xAttrList );
3014 : }
3015 :
3016 : // Order the elements
3017 48 : m_pSerializer->mergeTopMarks( );
3018 :
3019 48 : m_pSerializer->endElementNS( XML_w, XML_sectPr );
3020 48 : m_bOpenedSectPr = false;
3021 48 : }
3022 :
3023 48 : void DocxAttributeOutput::SectionFormProtection( bool bProtected )
3024 : {
3025 48 : if ( bProtected )
3026 0 : m_pSerializer->singleElementNS( XML_w, XML_formProt, FSEND );
3027 : else
3028 : m_pSerializer->singleElementNS( XML_w, XML_formProt,
3029 48 : FSNS( XML_w, XML_val ), "false", FSEND );
3030 48 : }
3031 :
3032 1 : void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo )
3033 : {
3034 1 : FastAttributeList* pAttr = m_pSerializer->createAttrList();
3035 1 : pAttr->add( FSNS( XML_w, XML_countBy ), OString::number(rLnNumInfo.GetCountBy()).getStr());
3036 1 : pAttr->add( FSNS( XML_w, XML_restart ), rLnNumInfo.IsRestartEachPage() ? "newPage" : "continuous" );
3037 1 : if( rLnNumInfo.GetPosFromLeft())
3038 0 : pAttr->add( FSNS( XML_w, XML_distance ), OString::number(rLnNumInfo.GetPosFromLeft()).getStr());
3039 1 : if( nRestartNo )
3040 1 : pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( long( nRestartNo )).getStr());
3041 1 : XFastAttributeListRef xAttrs( pAttr );
3042 1 : m_pSerializer->singleElementNS( XML_w, XML_lnNumType, xAttrs );
3043 1 : }
3044 :
3045 0 : void DocxAttributeOutput::SectionTitlePage()
3046 : {
3047 0 : m_pSerializer->singleElementNS( XML_w, XML_titlePg, FSEND );
3048 0 : }
3049 :
3050 48 : void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
3051 : {
3052 : // Output the margins
3053 :
3054 48 : const SvxBoxItem& rBox = pFmt->GetBox( );
3055 :
3056 48 : const SvxBorderLine* pBottom = rBox.GetBottom( );
3057 48 : const SvxBorderLine* pTop = rBox.GetTop( );
3058 48 : const SvxBorderLine* pLeft = rBox.GetLeft( );
3059 48 : const SvxBorderLine* pRight = rBox.GetRight( );
3060 :
3061 48 : if ( pBottom || pTop || pLeft || pRight )
3062 : {
3063 : // All distances are relative to the text margins
3064 : m_pSerializer->startElementNS( XML_w, XML_pgBorders,
3065 : FSNS( XML_w, XML_display ), "allPages",
3066 : FSNS( XML_w, XML_offsetFrom ), "text",
3067 0 : FSEND );
3068 :
3069 0 : m_pSerializer->mark();
3070 :
3071 0 : m_pSerializer->endElementNS( XML_w, XML_pgBorders );
3072 0 : m_pSerializer->mark();
3073 : }
3074 48 : }
3075 :
3076 0 : void DocxAttributeOutput::SectionBiDi( bool bBiDi )
3077 : {
3078 0 : if ( bBiDi )
3079 0 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
3080 0 : }
3081 :
3082 66 : static OString impl_NumberingType( sal_uInt16 nNumberingType )
3083 : {
3084 66 : OString aType;
3085 :
3086 66 : switch ( nNumberingType )
3087 : {
3088 : case SVX_NUM_CHARS_UPPER_LETTER:
3089 0 : case SVX_NUM_CHARS_UPPER_LETTER_N: aType = "upperLetter"; break;
3090 : case SVX_NUM_CHARS_LOWER_LETTER:
3091 0 : case SVX_NUM_CHARS_LOWER_LETTER_N: aType = "lowerLetter"; break;
3092 0 : case SVX_NUM_ROMAN_UPPER: aType = "upperRoman"; break;
3093 0 : case SVX_NUM_ROMAN_LOWER: aType = "lowerRoman"; break;
3094 :
3095 56 : case SVX_NUM_ARABIC: aType = "decimal"; break;
3096 :
3097 : case SVX_NUM_BITMAP:
3098 1 : case SVX_NUM_CHAR_SPECIAL: aType = "bullet"; break;
3099 :
3100 9 : default: aType = "none"; break;
3101 : }
3102 :
3103 66 : return aType;
3104 : }
3105 :
3106 48 : void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
3107 : {
3108 : // FIXME Not called properly with page styles like "First Page"
3109 :
3110 48 : FastAttributeList* pAttr = m_pSerializer->createAttrList();
3111 :
3112 : // 0 means no restart: then don't output that attribute if 0
3113 48 : if ( nPageRestartNumber > 0 )
3114 0 : pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( sal_Int32( nPageRestartNumber ) ) );
3115 :
3116 : // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
3117 48 : OString aFmt( impl_NumberingType( nNumType ) );
3118 48 : if ( !aFmt.isEmpty() )
3119 48 : pAttr->add( FSNS( XML_w, XML_fmt ), aFmt.getStr() );
3120 :
3121 96 : XFastAttributeListRef xAttrs( pAttr );
3122 48 : m_pSerializer->singleElementNS( XML_w, XML_pgNumType, xAttrs );
3123 :
3124 : // see 2.6.12 pgNumType (Page Numbering Settings)
3125 48 : OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()" );
3126 48 : }
3127 :
3128 48 : void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode )
3129 : {
3130 : /* break code: 0 No break, 1 New column
3131 : 2 New page, 3 Even page, 4 Odd page
3132 : */
3133 48 : const char* pType = NULL;
3134 48 : switch ( nBreakCode )
3135 : {
3136 0 : case 1: pType = "nextColumn"; break;
3137 48 : case 2: pType = "nextPage"; break;
3138 0 : case 3: pType = "evenPage"; break;
3139 0 : case 4: pType = "oddPage"; break;
3140 0 : default: pType = "continuous"; break;
3141 : }
3142 :
3143 48 : if ( pType )
3144 : m_pSerializer->singleElementNS( XML_w, XML_type,
3145 : FSNS( XML_w, XML_val ), pType,
3146 48 : FSEND );
3147 48 : }
3148 :
3149 341 : void DocxAttributeOutput::StartFont( const String& rFamilyName ) const
3150 : {
3151 : m_pSerializer->startElementNS( XML_w, XML_font,
3152 : FSNS( XML_w, XML_name ), OUStringToOString( OUString( rFamilyName ), RTL_TEXTENCODING_UTF8 ).getStr(),
3153 341 : FSEND );
3154 341 : }
3155 :
3156 341 : void DocxAttributeOutput::EndFont() const
3157 : {
3158 341 : m_pSerializer->endElementNS( XML_w, XML_font );
3159 341 : }
3160 :
3161 143 : void DocxAttributeOutput::FontAlternateName( const String& rName ) const
3162 : {
3163 : m_pSerializer->singleElementNS( XML_w, XML_altName,
3164 : FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
3165 143 : FSEND );
3166 143 : }
3167 :
3168 341 : void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet, rtl_TextEncoding nEncoding ) const
3169 : {
3170 341 : FastAttributeList* pAttr = m_pSerializer->createAttrList();
3171 :
3172 341 : OString aCharSet( OString::valueOf( sal_Int32( nCharSet ), 16 ) );
3173 341 : if ( aCharSet.getLength() == 1 )
3174 341 : aCharSet = OString( "0" ) + aCharSet;
3175 341 : pAttr->add( FSNS( XML_w, XML_val ), aCharSet.getStr());
3176 :
3177 341 : if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT )
3178 : {
3179 341 : if( const char* charset = rtl_getMimeCharsetFromTextEncoding( nEncoding ))
3180 157 : pAttr->add( FSNS( XML_w, XML_characterSet ), charset );
3181 : }
3182 :
3183 341 : m_pSerializer->singleElementNS( XML_w, XML_charset, XFastAttributeListRef( pAttr ));
3184 341 : }
3185 :
3186 341 : void DocxAttributeOutput::FontFamilyType( FontFamily eFamily ) const
3187 : {
3188 341 : const char *pFamily = NULL;
3189 341 : switch ( eFamily )
3190 : {
3191 242 : case FAMILY_ROMAN: pFamily = "roman"; break;
3192 97 : case FAMILY_SWISS: pFamily = "swiss"; break;
3193 0 : case FAMILY_MODERN: pFamily = "modern"; break;
3194 0 : case FAMILY_SCRIPT: pFamily = "script"; break;
3195 0 : case FAMILY_DECORATIVE: pFamily = "decorative"; break;
3196 2 : default: pFamily = "auto"; break; // no font family
3197 : }
3198 :
3199 341 : if ( pFamily )
3200 : m_pSerializer->singleElementNS( XML_w, XML_family,
3201 : FSNS( XML_w, XML_val ), pFamily,
3202 341 : FSEND );
3203 341 : }
3204 :
3205 341 : void DocxAttributeOutput::FontPitchType( FontPitch ePitch ) const
3206 : {
3207 341 : const char *pPitch = NULL;
3208 341 : switch ( ePitch )
3209 : {
3210 204 : case PITCH_VARIABLE: pPitch = "variable"; break;
3211 0 : case PITCH_FIXED: pPitch = "fixed"; break;
3212 137 : default: pPitch = "default"; break; // no info about the pitch
3213 : }
3214 :
3215 341 : if ( pPitch )
3216 : m_pSerializer->singleElementNS( XML_w, XML_pitch,
3217 : FSNS( XML_w, XML_val ), pPitch,
3218 341 : FSEND );
3219 341 : }
3220 :
3221 341 : void DocxAttributeOutput::EmbedFont( const OUString& name, FontFamily family, FontPitch pitch, rtl_TextEncoding encoding )
3222 : {
3223 341 : if( !m_rExport.pDoc->get( IDocumentSettingAccess::EMBED_FONTS ))
3224 682 : return; // no font embedding with this document
3225 0 : EmbedFontStyle( name, XML_embedRegular, family, ITALIC_NONE, WEIGHT_NORMAL, pitch, encoding );
3226 0 : EmbedFontStyle( name, XML_embedBold, family, ITALIC_NONE, WEIGHT_BOLD, pitch, encoding );
3227 0 : EmbedFontStyle( name, XML_embedItalic, family, ITALIC_NORMAL, WEIGHT_NORMAL, pitch, encoding );
3228 0 : EmbedFontStyle( name, XML_embedBoldItalic, family, ITALIC_NORMAL, WEIGHT_BOLD, pitch, encoding );
3229 : }
3230 :
3231 0 : static inline char toHexChar( int value )
3232 : {
3233 0 : return value >= 10 ? value + 'A' - 10 : value + '0';
3234 : }
3235 :
3236 0 : void DocxAttributeOutput::EmbedFontStyle( const OUString& name, int tag, FontFamily family, FontItalic italic,
3237 : FontWeight weight, FontPitch pitch, rtl_TextEncoding encoding )
3238 : {
3239 : // Embed font if at least viewing is allowed (in which case the opening app must check
3240 : // the font license rights too and open either read-only or not use the font for editing).
3241 : OUString fontUrl = EmbeddedFontsHelper::fontFileUrl( name, family, italic, weight, pitch, encoding,
3242 0 : EmbeddedFontsHelper::ViewingAllowed );
3243 0 : if( fontUrl.isEmpty())
3244 0 : return;
3245 : // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
3246 0 : if( !fontFilesMap.count( fontUrl ))
3247 : {
3248 0 : osl::File file( fontUrl );
3249 0 : if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None )
3250 0 : return;
3251 0 : uno::Reference< com::sun::star::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream(
3252 0 : OUString( "word/fonts/font" ) + OUString::number(m_nextFontId) + ".odttf",
3253 0 : "application/vnd.openxmlformats-officedocument.obfuscatedFont" );
3254 : // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway,
3255 : // so just alter the first and last part of the key.
3256 0 : char fontKeyStr[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}";
3257 : sal_uInt8 fontKey[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E,
3258 0 : 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 };
3259 0 : fontKey[ 0 ] = fontKey[ 15 ] = m_nextFontId % 256;
3260 0 : fontKeyStr[ 1 ] = fontKeyStr[ 35 ] = toHexChar(( m_nextFontId % 256 ) / 16 );
3261 0 : fontKeyStr[ 2 ] = fontKeyStr[ 36 ] = toHexChar(( m_nextFontId % 256 ) % 16 );
3262 : char buffer[ 4096 ];
3263 : sal_uInt64 readSize;
3264 0 : file.read( buffer, 32, readSize );
3265 0 : if( readSize < 32 )
3266 : {
3267 : SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl << ")" );
3268 0 : xOutStream->closeOutput();
3269 0 : return;
3270 : }
3271 0 : for( int i = 0;
3272 : i < 16;
3273 : ++i )
3274 : {
3275 0 : buffer[ i ] ^= fontKey[ i ];
3276 0 : buffer[ i + 16 ] ^= fontKey[ i ];
3277 : }
3278 0 : xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), 32 ));
3279 : for(;;)
3280 : {
3281 : sal_Bool eof;
3282 0 : if( file.isEndOfFile( &eof ) != osl::File::E_None )
3283 : {
3284 : SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
3285 0 : xOutStream->closeOutput();
3286 0 : return;
3287 : }
3288 0 : if( eof )
3289 0 : break;
3290 0 : if( file.read( buffer, 4096, readSize ) != osl::File::E_None )
3291 : {
3292 : SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
3293 0 : xOutStream->closeOutput();
3294 0 : return;
3295 : }
3296 0 : if( readSize == 0 )
3297 0 : break;
3298 0 : xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize ));
3299 0 : }
3300 0 : xOutStream->closeOutput();
3301 0 : OString relId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
3302 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
3303 0 : OUString( "fonts/font" ) + OUString::number( m_nextFontId ) + ".odttf" ), RTL_TEXTENCODING_UTF8 );
3304 0 : EmbeddedFontRef ref;
3305 0 : ref.relId = relId;
3306 0 : ref.fontKey = fontKeyStr;
3307 0 : fontFilesMap[ fontUrl ] = ref;
3308 0 : ++m_nextFontId;
3309 : }
3310 : m_pSerializer->singleElementNS( XML_w, tag,
3311 0 : FSNS( XML_r, XML_id ), fontFilesMap[ fontUrl ].relId,
3312 0 : FSNS( XML_w, XML_fontKey ), fontFilesMap[ fontUrl ].fontKey,
3313 0 : FSEND );
3314 : }
3315 :
3316 2 : void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
3317 : {
3318 : // nId is the same both for abstract numbering definition as well as the
3319 : // numbering definition itself
3320 : // TODO check that this is actually true & fix if not ;-)
3321 2 : OString aId( OString::valueOf( sal_Int32( nId ) ) );
3322 :
3323 : m_pSerializer->startElementNS( XML_w, XML_num,
3324 : FSNS( XML_w, XML_numId ), aId.getStr(),
3325 2 : FSEND );
3326 :
3327 : m_pSerializer->singleElementNS( XML_w, XML_abstractNumId,
3328 : FSNS( XML_w, XML_val ), aId.getStr(),
3329 2 : FSEND );
3330 :
3331 : #if OSL_DEBUG_LEVEL > 1
3332 : // TODO ww8 version writes this, anything to do about it here?
3333 : if ( rRule.IsContinusNum() )
3334 : OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()" );
3335 : #else
3336 : (void) rRule; // to quiet the warning...
3337 : #endif
3338 :
3339 2 : m_pSerializer->endElementNS( XML_w, XML_num );
3340 2 : }
3341 :
3342 2 : void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
3343 : {
3344 : m_pSerializer->startElementNS( XML_w, XML_abstractNum,
3345 : FSNS( XML_w, XML_abstractNumId ), OString::valueOf( sal_Int32( nId ) ).getStr(),
3346 2 : FSEND );
3347 2 : }
3348 :
3349 2 : void DocxAttributeOutput::EndAbstractNumbering()
3350 : {
3351 2 : m_pSerializer->endElementNS( XML_w, XML_abstractNum );
3352 2 : }
3353 :
3354 18 : void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
3355 : sal_uInt16 nStart,
3356 : sal_uInt16 nNumberingType,
3357 : SvxAdjust eAdjust,
3358 : const sal_uInt8 * /*pNumLvlPos*/,
3359 : sal_uInt8 nFollow,
3360 : const wwFont *pFont,
3361 : const SfxItemSet *pOutSet,
3362 : sal_Int16 nIndentAt,
3363 : sal_Int16 nFirstLineIndex,
3364 : sal_Int16 nListTabPos,
3365 : const String &rNumberingString,
3366 : const SvxBrushItem* pBrush)
3367 : {
3368 : m_pSerializer->startElementNS( XML_w, XML_lvl,
3369 : FSNS( XML_w, XML_ilvl ), OString::valueOf( sal_Int32( nLevel ) ).getStr(),
3370 18 : FSEND );
3371 :
3372 : // start with the nStart value
3373 : m_pSerializer->singleElementNS( XML_w, XML_start,
3374 : FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nStart ) ).getStr(),
3375 18 : FSEND );
3376 :
3377 : // format
3378 18 : OString aFmt( impl_NumberingType( nNumberingType ) );
3379 :
3380 18 : if ( !aFmt.isEmpty() )
3381 : m_pSerializer->singleElementNS( XML_w, XML_numFmt,
3382 : FSNS( XML_w, XML_val ), aFmt.getStr(),
3383 18 : FSEND );
3384 :
3385 : // suffix
3386 18 : const char *pSuffix = NULL;
3387 18 : switch ( nFollow )
3388 : {
3389 0 : case 1: pSuffix = "space"; break;
3390 9 : case 2: pSuffix = "nothing"; break;
3391 9 : default: /*pSuffix = "tab";*/ break;
3392 : }
3393 18 : if ( pSuffix )
3394 : m_pSerializer->singleElementNS( XML_w, XML_suff,
3395 : FSNS( XML_w, XML_val ), pSuffix,
3396 9 : FSEND );
3397 :
3398 : // text
3399 18 : OUString aText( rNumberingString );
3400 36 : OUStringBuffer aBuffer( aText.getLength() + WW8ListManager::nMaxLevel );
3401 :
3402 18 : const sal_Unicode *pPrev = aText.getStr();
3403 18 : const sal_Unicode *pIt = aText.getStr();
3404 53 : while ( pIt < aText.getStr() + aText.getLength() )
3405 : {
3406 : // convert the level values to %NUMBER form
3407 : // (we don't use pNumLvlPos at all)
3408 : // FIXME so far we support the ww8 limit of levels only
3409 17 : if ( *pIt < sal_Unicode( WW8ListManager::nMaxLevel ) )
3410 : {
3411 8 : aBuffer.append( pPrev, pIt - pPrev );
3412 8 : aBuffer.append( '%' );
3413 8 : aBuffer.append( OUString::valueOf( sal_Int32( *pIt ) + 1 ) );
3414 :
3415 8 : pPrev = pIt + 1;
3416 : }
3417 17 : ++pIt;
3418 : }
3419 18 : if ( pPrev < pIt )
3420 9 : aBuffer.append( pPrev, pIt - pPrev );
3421 :
3422 : m_pSerializer->singleElementNS( XML_w, XML_lvlText,
3423 : FSNS( XML_w, XML_val ), OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ).getStr(),
3424 18 : FSEND );
3425 :
3426 : // bullet
3427 18 : if (nNumberingType == SVX_NUM_BITMAP && pBrush)
3428 : {
3429 1 : int nIndex = m_rExport.GetGrfIndex(*pBrush);
3430 1 : if (nIndex != -1)
3431 : {
3432 : m_pSerializer->singleElementNS(XML_w, XML_lvlPicBulletId,
3433 : FSNS(XML_w, XML_val), OString::number(nIndex).getStr(),
3434 1 : FSEND);
3435 : }
3436 : }
3437 :
3438 : // justification
3439 : const char *pJc;
3440 18 : bool ecmaDialect = ( m_rExport.GetFilter().getVersion() == oox::core::ECMA_DIALECT );
3441 18 : switch ( eAdjust )
3442 : {
3443 0 : case SVX_ADJUST_CENTER: pJc = "center"; break;
3444 0 : case SVX_ADJUST_RIGHT: pJc = !ecmaDialect ? "end" : "right"; break;
3445 18 : default: pJc = !ecmaDialect ? "start" : "left"; break;
3446 : }
3447 : m_pSerializer->singleElementNS( XML_w, XML_lvlJc,
3448 : FSNS( XML_w, XML_val ), pJc,
3449 18 : FSEND );
3450 :
3451 : // indentation
3452 18 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
3453 18 : if( nListTabPos != 0 )
3454 : {
3455 17 : m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
3456 : m_pSerializer->singleElementNS( XML_w, XML_tab,
3457 : FSNS( XML_w, XML_val ), "num",
3458 : FSNS( XML_w, XML_pos ), OString::number( nListTabPos ).getStr(),
3459 17 : FSEND );
3460 17 : m_pSerializer->endElementNS( XML_w, XML_tabs );
3461 : }
3462 :
3463 18 : sal_Int32 nToken = ecmaDialect ? XML_left : XML_start;
3464 : m_pSerializer->singleElementNS( XML_w, XML_ind,
3465 : FSNS( XML_w, nToken ), OString::valueOf( sal_Int32( nIndentAt ) ).getStr(),
3466 : FSNS( XML_w, XML_hanging ), OString::valueOf( sal_Int32( -nFirstLineIndex ) ).getStr(),
3467 18 : FSEND );
3468 18 : m_pSerializer->endElementNS( XML_w, XML_pPr );
3469 :
3470 : // font
3471 18 : if ( pOutSet )
3472 : {
3473 1 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
3474 :
3475 1 : if ( pFont )
3476 : {
3477 1 : GetExport().GetId( *pFont ); // ensure font info is written to fontTable.xml
3478 1 : OString aFamilyName( OUStringToOString( OUString( pFont->GetFamilyName() ), RTL_TEXTENCODING_UTF8 ) );
3479 : m_pSerializer->singleElementNS( XML_w, XML_rFonts,
3480 : FSNS( XML_w, XML_ascii ), aFamilyName.getStr(),
3481 : FSNS( XML_w, XML_hAnsi ), aFamilyName.getStr(),
3482 : FSNS( XML_w, XML_cs ), aFamilyName.getStr(),
3483 : FSNS( XML_w, XML_hint ), "default",
3484 1 : FSEND );
3485 : }
3486 1 : m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
3487 :
3488 1 : m_pSerializer->endElementNS( XML_w, XML_rPr );
3489 : }
3490 :
3491 : // TODO anything to do about nListTabPos?
3492 :
3493 36 : m_pSerializer->endElementNS( XML_w, XML_lvl );
3494 18 : }
3495 :
3496 0 : void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
3497 : {
3498 0 : switch ( rCaseMap.GetValue() )
3499 : {
3500 : case SVX_CASEMAP_KAPITAELCHEN:
3501 0 : m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSEND );
3502 0 : break;
3503 : case SVX_CASEMAP_VERSALIEN:
3504 0 : m_pSerializer->singleElementNS( XML_w, XML_caps, FSEND );
3505 0 : break;
3506 : default: // Something that ooxml does not support
3507 0 : m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSNS( XML_w, XML_val ), "false", FSEND );
3508 0 : m_pSerializer->singleElementNS( XML_w, XML_caps, FSNS( XML_w, XML_val ), "false", FSEND );
3509 0 : break;
3510 : }
3511 0 : }
3512 :
3513 61 : void DocxAttributeOutput::CharColor( const SvxColorItem& rColor )
3514 : {
3515 61 : const Color aColor( rColor.GetValue() );
3516 61 : OString aColorString;
3517 :
3518 61 : aColorString = msfilter::util::ConvertColor( aColor );
3519 :
3520 : m_pSerializer->singleElementNS( XML_w, XML_color,
3521 61 : FSNS( XML_w, XML_val ), aColorString.getStr(), FSEND );
3522 61 : }
3523 :
3524 0 : void DocxAttributeOutput::CharContour( const SvxContourItem& rContour )
3525 : {
3526 0 : if ( rContour.GetValue() )
3527 0 : m_pSerializer->singleElementNS( XML_w, XML_outline, FSEND );
3528 : else
3529 0 : m_pSerializer->singleElementNS( XML_w, XML_outline, FSNS( XML_w, XML_val ), "false", FSEND );
3530 0 : }
3531 :
3532 1 : void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
3533 : {
3534 1 : switch ( rCrossedOut.GetStrikeout() )
3535 : {
3536 : case STRIKEOUT_DOUBLE:
3537 0 : m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSEND );
3538 0 : break;
3539 : case STRIKEOUT_NONE:
3540 0 : m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSNS( XML_w, XML_val ), "false", FSEND );
3541 0 : m_pSerializer->singleElementNS( XML_w, XML_strike, FSNS( XML_w, XML_val ), "false", FSEND );
3542 0 : break;
3543 : default:
3544 1 : m_pSerializer->singleElementNS( XML_w, XML_strike, FSEND );
3545 1 : break;
3546 : }
3547 1 : }
3548 :
3549 12 : void DocxAttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )
3550 : {
3551 12 : OString sIss;
3552 12 : short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProp();
3553 12 : if ( !nEsc )
3554 : {
3555 0 : sIss = OString( "baseline" );
3556 0 : nEsc = 0;
3557 0 : nProp = 100;
3558 : }
3559 12 : else if ( DFLT_ESC_PROP == nProp )
3560 : {
3561 12 : if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
3562 0 : sIss = OString( "subscript" );
3563 12 : else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
3564 12 : sIss = OString( "superscript" );
3565 : }
3566 :
3567 12 : if ( !sIss.isEmpty() )
3568 : m_pSerializer->singleElementNS( XML_w, XML_vertAlign,
3569 12 : FSNS( XML_w, XML_val ), sIss.getStr(), FSEND );
3570 :
3571 12 : if ( sIss.isEmpty() || sIss.match( OString( "baseline" ) ) )
3572 : {
3573 : long nHeight = ((SvxFontHeightItem&)m_rExport.GetItem(
3574 0 : RES_CHRATR_FONTSIZE )).GetHeight();
3575 0 : OString sPos = OString::valueOf( ( nHeight * nEsc + 500 ) / 1000 );
3576 : m_pSerializer->singleElementNS( XML_w, XML_position,
3577 0 : FSNS( XML_w, XML_val ), sPos.getStr( ), FSEND );
3578 :
3579 0 : if( 100 != nProp || sIss.match( OString( "baseline" ) ) )
3580 : {
3581 0 : OString sSize = OString::valueOf( ( nHeight * nProp + 500 ) / 1000 );
3582 : m_pSerializer->singleElementNS( XML_w, XML_sz,
3583 0 : FSNS( XML_w, XML_val ), sSize.getStr( ), FSEND );
3584 0 : }
3585 12 : }
3586 12 : }
3587 :
3588 246 : void DocxAttributeOutput::CharFont( const SvxFontItem& rFont)
3589 : {
3590 246 : if (!m_pFontsAttrList)
3591 240 : m_pFontsAttrList = m_pSerializer->createAttrList();
3592 246 : GetExport().GetId( rFont ); // ensure font info is written to fontTable.xml
3593 246 : OUString sFontName(rFont.GetFamilyName());
3594 492 : OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
3595 246 : m_pFontsAttrList->add(FSNS(XML_w, XML_ascii), sFontNameUtf8);
3596 492 : m_pFontsAttrList->add(FSNS(XML_w, XML_hAnsi), sFontNameUtf8);
3597 246 : }
3598 :
3599 421 : void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
3600 : {
3601 421 : OString fontSize = OString::valueOf( sal_Int32( ( rFontSize.GetHeight() + 5 ) / 10 ) );
3602 :
3603 421 : switch ( rFontSize.Which() )
3604 : {
3605 : case RES_CHRATR_FONTSIZE:
3606 : case RES_CHRATR_CJK_FONTSIZE:
3607 210 : m_pSerializer->singleElementNS( XML_w, XML_sz, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
3608 210 : break;
3609 : case RES_CHRATR_CTL_FONTSIZE:
3610 211 : m_pSerializer->singleElementNS( XML_w, XML_szCs, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
3611 211 : break;
3612 421 : }
3613 421 : }
3614 :
3615 0 : void DocxAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
3616 : {
3617 0 : OString aKerning = OString::valueOf( ( sal_Int32 ) rKerning.GetValue() );
3618 0 : m_pSerializer->singleElementNS( XML_w, XML_spacing, FSNS(XML_w, XML_val), aKerning.getStr(), FSEND );
3619 0 : }
3620 :
3621 200 : void DocxAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
3622 : {
3623 200 : if (!m_pCharLangAttrList)
3624 98 : m_pCharLangAttrList = m_pSerializer->createAttrList();
3625 :
3626 200 : ::com::sun::star::lang::Locale xLocale= LanguageTag( rLanguage.GetLanguage( ) ).getLocale();
3627 400 : OString sLanguage = OUStringToOString(xLocale.Language, RTL_TEXTENCODING_UTF8);
3628 400 : OString sCountry = OUStringToOString(xLocale.Country, RTL_TEXTENCODING_UTF8);
3629 :
3630 400 : OString aLanguageCode = sLanguage + "-" + sCountry;
3631 :
3632 200 : switch ( rLanguage.Which() )
3633 : {
3634 : case RES_CHRATR_LANGUAGE:
3635 97 : m_pCharLangAttrList->add(FSNS(XML_w, XML_val), aLanguageCode);
3636 97 : break;
3637 : case RES_CHRATR_CJK_LANGUAGE:
3638 52 : m_pCharLangAttrList->add(FSNS(XML_w, XML_eastAsia), aLanguageCode);
3639 52 : break;
3640 : case RES_CHRATR_CTL_LANGUAGE:
3641 51 : m_pCharLangAttrList->add(FSNS(XML_w, XML_bidi), aLanguageCode);
3642 51 : break;
3643 200 : }
3644 200 : }
3645 :
3646 56 : void DocxAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
3647 : {
3648 56 : if ( rPosture.GetPosture() != ITALIC_NONE )
3649 56 : m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
3650 : else
3651 0 : m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
3652 56 : }
3653 :
3654 0 : void DocxAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
3655 : {
3656 0 : if ( rShadow.GetValue() )
3657 0 : m_pSerializer->singleElementNS( XML_w, XML_shadow, FSEND );
3658 : else
3659 0 : m_pSerializer->singleElementNS( XML_w, XML_shadow, FSNS( XML_w, XML_val ), "false", FSEND );
3660 0 : }
3661 :
3662 10 : void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
3663 : {
3664 : const char *pUnderlineValue;
3665 :
3666 10 : switch ( rUnderline.GetLineStyle() )
3667 : {
3668 9 : case UNDERLINE_SINGLE: pUnderlineValue = "single"; break;
3669 1 : case UNDERLINE_BOLD: pUnderlineValue = "thick"; break;
3670 0 : case UNDERLINE_DOUBLE: pUnderlineValue = "double"; break;
3671 0 : case UNDERLINE_DOTTED: pUnderlineValue = "dotted"; break;
3672 0 : case UNDERLINE_DASH: pUnderlineValue = "dash"; break;
3673 0 : case UNDERLINE_DASHDOT: pUnderlineValue = "dotDash"; break;
3674 0 : case UNDERLINE_DASHDOTDOT: pUnderlineValue = "dotDotDash"; break;
3675 0 : case UNDERLINE_WAVE: pUnderlineValue = "wave"; break;
3676 0 : case UNDERLINE_BOLDDOTTED: pUnderlineValue = "dottedHeavy"; break;
3677 0 : case UNDERLINE_BOLDDASH: pUnderlineValue = "dashedHeavy"; break;
3678 0 : case UNDERLINE_LONGDASH: pUnderlineValue = "dashLongHeavy"; break;
3679 0 : case UNDERLINE_BOLDLONGDASH: pUnderlineValue = "dashLongHeavy"; break;
3680 0 : case UNDERLINE_BOLDDASHDOT: pUnderlineValue = "dashDotHeavy"; break;
3681 0 : case UNDERLINE_BOLDDASHDOTDOT: pUnderlineValue = "dashDotDotHeavy"; break;
3682 0 : case UNDERLINE_BOLDWAVE: pUnderlineValue = "wavyHeavy"; break;
3683 0 : case UNDERLINE_DOUBLEWAVE: pUnderlineValue = "wavyDouble"; break;
3684 : case UNDERLINE_NONE: // fall through
3685 0 : default: pUnderlineValue = "none"; break;
3686 : }
3687 :
3688 10 : Color aUnderlineColor = rUnderline.GetColor();
3689 10 : bool bUnderlineHasColor = aUnderlineColor.GetTransparency() == 0;
3690 10 : if (bUnderlineHasColor)
3691 : {
3692 : // Underline has a color
3693 : m_pSerializer->singleElementNS( XML_w, XML_u,
3694 : FSNS( XML_w, XML_val ), pUnderlineValue,
3695 : FSNS( XML_w, XML_color ), msfilter::util::ConvertColor( aUnderlineColor ).getStr(),
3696 1 : FSEND );
3697 : }
3698 : else
3699 : {
3700 : // Underline has no color
3701 9 : m_pSerializer->singleElementNS( XML_w, XML_u, FSNS( XML_w, XML_val ), pUnderlineValue, FSEND );
3702 : }
3703 10 : }
3704 :
3705 22 : void DocxAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
3706 : {
3707 22 : if ( rWeight.GetWeight() == WEIGHT_BOLD )
3708 22 : m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
3709 : else
3710 0 : m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
3711 22 : }
3712 :
3713 50 : void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem& )
3714 : {
3715 : OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()" );
3716 50 : }
3717 :
3718 0 : void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
3719 : {
3720 0 : if ( rBlink.GetValue() )
3721 0 : m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "blinkBackground", FSEND );
3722 : else
3723 0 : m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "none", FSEND );
3724 0 : }
3725 :
3726 : #define MSWORD_CH_SHADING_FILL "FFFFFF" // The attribute w:fill of w:shd, for MS-Word's character shading,
3727 : #define MSWORD_CH_SHADING_COLOR "auto" // The attribute w:color of w:shd, for MS-Word's character shading,
3728 : #define MSWORD_CH_SHADING_VAL "pct15" // The attribute w:value of w:shd, for MS-Word's character shading,
3729 :
3730 2 : void DocxAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
3731 : {
3732 : // Check if the brush shading pattern is 'PCT15'. If so - write it back to the DOCX
3733 2 : if (rBrush.GetShadingValue() == +ShadingPattern::PCT15)
3734 : {
3735 : m_pSerializer->singleElementNS( XML_w, XML_shd,
3736 : FSNS( XML_w, XML_val ), MSWORD_CH_SHADING_VAL,
3737 : FSNS( XML_w, XML_color ), MSWORD_CH_SHADING_COLOR,
3738 : FSNS( XML_w, XML_fill ), MSWORD_CH_SHADING_FILL,
3739 1 : FSEND );
3740 : }
3741 : else
3742 : {
3743 : m_pSerializer->singleElementNS( XML_w, XML_shd,
3744 1 : FSNS( XML_w, XML_fill ), msfilter::util::ConvertColor( rBrush.GetColor() ).getStr(),
3745 : FSNS( XML_w, XML_val ), "clear",
3746 1 : FSEND );
3747 : }
3748 2 : }
3749 :
3750 221 : void DocxAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
3751 : {
3752 221 : if (!m_pFontsAttrList)
3753 1 : m_pFontsAttrList = m_pSerializer->createAttrList();
3754 221 : OUString sFontName(rFont.GetFamilyName());
3755 442 : OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
3756 442 : m_pFontsAttrList->add(FSNS(XML_w, XML_eastAsia), sFontNameUtf8);
3757 221 : }
3758 :
3759 0 : void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
3760 : {
3761 0 : if ( rPosture.GetPosture() != ITALIC_NONE )
3762 0 : m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
3763 : else
3764 0 : m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
3765 0 : }
3766 :
3767 0 : void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
3768 : {
3769 0 : if ( rWeight.GetWeight() == WEIGHT_BOLD )
3770 0 : m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
3771 : else
3772 0 : m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
3773 0 : }
3774 :
3775 252 : void DocxAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
3776 : {
3777 252 : if (!m_pFontsAttrList)
3778 21 : m_pFontsAttrList = m_pSerializer->createAttrList();
3779 252 : OUString sFontName(rFont.GetFamilyName());
3780 504 : OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
3781 504 : m_pFontsAttrList->add(FSNS(XML_w, XML_cs), sFontNameUtf8);
3782 :
3783 252 : }
3784 :
3785 49 : void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
3786 : {
3787 49 : if ( rPosture.GetPosture() != ITALIC_NONE )
3788 49 : m_pSerializer->singleElementNS( XML_w, XML_iCs, FSEND );
3789 : else
3790 0 : m_pSerializer->singleElementNS( XML_w, XML_iCs, FSNS( XML_w, XML_val ), "false", FSEND );
3791 49 : }
3792 :
3793 7 : void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
3794 : {
3795 7 : if ( rWeight.GetWeight() == WEIGHT_BOLD )
3796 7 : m_pSerializer->singleElementNS( XML_w, XML_bCs, FSEND );
3797 : else
3798 0 : m_pSerializer->singleElementNS( XML_w, XML_bCs, FSNS( XML_w, XML_val ), "false", FSEND );
3799 7 : }
3800 :
3801 3 : void DocxAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
3802 : {
3803 : // Not rorated or we the rotation already handled?
3804 3 : if ( !rRotate.GetValue() || m_bBtLr)
3805 6 : return;
3806 :
3807 0 : if (!m_pEastAsianLayoutAttrList)
3808 0 : m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
3809 0 : OString sTrue((sal_Char *)"true");
3810 0 : m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vert), sTrue);
3811 :
3812 0 : if (rRotate.IsFitToLine())
3813 0 : m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vertCompress), sTrue);
3814 : }
3815 :
3816 0 : void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
3817 : {
3818 : const char *pEmphasis;
3819 :
3820 0 : switch ( rEmphasisMark.GetValue() )
3821 : {
3822 0 : case EMPHASISMARK_NONE: pEmphasis = "none"; break;
3823 0 : case EMPHASISMARK_SIDE_DOTS: pEmphasis = "dot"; break;
3824 0 : case EMPHASISMARK_CIRCLE_ABOVE: pEmphasis = "circle"; break;
3825 0 : case EMPHASISMARK_DOTS_BELOW: pEmphasis = "underDot"; break;
3826 0 : default: pEmphasis = "comma"; break;
3827 : }
3828 :
3829 0 : m_pSerializer->singleElementNS( XML_w, XML_em, FSNS( XML_w, XML_val ), pEmphasis, FSEND );
3830 0 : }
3831 :
3832 0 : void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
3833 : {
3834 0 : if ( !rTwoLines.GetValue() )
3835 0 : return;
3836 :
3837 0 : if (!m_pEastAsianLayoutAttrList)
3838 0 : m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
3839 0 : OString sTrue((sal_Char *)"true");
3840 0 : m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combine), sTrue);
3841 :
3842 0 : sal_Unicode cStart = rTwoLines.GetStartBracket();
3843 0 : sal_Unicode cEnd = rTwoLines.GetEndBracket();
3844 :
3845 0 : if (!cStart && !cEnd)
3846 0 : return;
3847 :
3848 0 : OString sBracket;
3849 0 : if ((cStart == '{') || (cEnd == '}'))
3850 0 : sBracket = (sal_Char *)"curly";
3851 0 : else if ((cStart == '<') || (cEnd == '>'))
3852 0 : sBracket = (sal_Char *)"angle";
3853 0 : else if ((cStart == '[') || (cEnd == ']'))
3854 0 : sBracket = (sal_Char *)"square";
3855 : else
3856 0 : sBracket = (sal_Char *)"round";
3857 0 : m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combineBrackets), sBracket);
3858 : }
3859 :
3860 0 : void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
3861 : {
3862 : m_pSerializer->singleElementNS( XML_w, XML_w,
3863 0 : FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( rScaleWidth.GetValue() ) ).getStr(), FSEND );
3864 0 : }
3865 :
3866 0 : void DocxAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
3867 : {
3868 0 : switch ( rRelief.GetValue() )
3869 : {
3870 : case RELIEF_EMBOSSED:
3871 0 : m_pSerializer->singleElementNS( XML_w, XML_emboss, FSEND );
3872 0 : break;
3873 : case RELIEF_ENGRAVED:
3874 0 : m_pSerializer->singleElementNS( XML_w, XML_imprint, FSEND );
3875 0 : break;
3876 : default:
3877 0 : m_pSerializer->singleElementNS( XML_w, XML_emboss, FSNS( XML_w, XML_val ), "false", FSEND );
3878 0 : m_pSerializer->singleElementNS( XML_w, XML_imprint, FSNS( XML_w, XML_val ), "false", FSEND );
3879 0 : break;
3880 : }
3881 0 : }
3882 :
3883 0 : void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
3884 : {
3885 0 : if ( rHidden.GetValue() )
3886 0 : m_pSerializer->singleElementNS( XML_w, XML_vanish, FSEND );
3887 : else
3888 0 : m_pSerializer->singleElementNS( XML_w, XML_vanish, FSNS( XML_w, XML_val ), "false", FSEND );
3889 0 : }
3890 :
3891 2 : void DocxAttributeOutput::TextINetFormat( const SwFmtINetFmt& rLink )
3892 : {
3893 2 : const SwTxtINetFmt* pINetFmt = rLink.GetTxtINetFmt();
3894 2 : const SwCharFmt* pCharFmt = pINetFmt->GetCharFmt();
3895 :
3896 2 : OString aStyleId( "style" );
3897 2 : aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
3898 :
3899 2 : m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
3900 2 : }
3901 :
3902 1 : void DocxAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
3903 : {
3904 1 : OString aStyleId( "style" );
3905 1 : aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *rCharFmt.GetCharFmt() ) ) );
3906 :
3907 1 : m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
3908 1 : }
3909 :
3910 0 : void DocxAttributeOutput::RefField( const SwField& rFld, const String& rRef )
3911 : {
3912 0 : sal_uInt16 nType = rFld.GetTyp( )->Which( );
3913 0 : if ( nType == RES_GETEXPFLD )
3914 : {
3915 0 : String sCmd = FieldString( ww::eREF );
3916 0 : sCmd.AppendAscii( "\"" );
3917 0 : sCmd += rRef;
3918 0 : sCmd.AppendAscii( "\" " );
3919 :
3920 0 : m_rExport.OutputField( &rFld, ww::eREF, sCmd );
3921 : }
3922 :
3923 : // There is nothing to do here for the set fields
3924 0 : }
3925 :
3926 0 : void DocxAttributeOutput::HiddenField( const SwField& /*rFld*/ )
3927 : {
3928 : OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()" );
3929 0 : }
3930 :
3931 1 : void DocxAttributeOutput::PostitField( const SwField* pFld )
3932 : {
3933 : assert( dynamic_cast< const SwPostItField* >( pFld ));
3934 1 : m_postitFields.push_back( static_cast< const SwPostItField* >( pFld ));
3935 1 : }
3936 :
3937 289 : void DocxAttributeOutput::WritePostitFieldReference()
3938 : {
3939 579 : while( m_postitFieldsMaxId < m_postitFields.size())
3940 : {
3941 1 : OString idstr = OString::valueOf( sal_Int32( m_postitFieldsMaxId ));
3942 1 : m_pSerializer->singleElementNS( XML_w, XML_commentReference, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND );
3943 1 : ++m_postitFieldsMaxId;
3944 1 : }
3945 289 : }
3946 :
3947 1 : void DocxAttributeOutput::WritePostitFieldStart()
3948 : {
3949 1 : m_bPostitStart = true;
3950 1 : }
3951 :
3952 1 : void DocxAttributeOutput::WritePostitFieldEnd()
3953 : {
3954 1 : m_bPostitEnd = true;
3955 1 : }
3956 :
3957 1 : void DocxAttributeOutput::WritePostitFields()
3958 : {
3959 4 : for( unsigned int i = 0;
3960 2 : i < m_postitFields.size();
3961 : ++i )
3962 : {
3963 1 : OString idstr = OString::valueOf( sal_Int32( i ));
3964 1 : const SwPostItField* f = m_postitFields[ i ];
3965 : m_pSerializer->startElementNS( XML_w, XML_comment, FSNS( XML_w, XML_id ), idstr.getStr(),
3966 1 : FSNS( XML_w, XML_author ), OUStringToOString( f->GetPar1(), RTL_TEXTENCODING_UTF8 ).getStr(),
3967 : FSNS( XML_w, XML_date ), msfilter::util::DateTimeToOString(f->GetDateTime()).getStr(),
3968 2 : FSNS( XML_w, XML_initials ), OUStringToOString( f->GetInitials(), RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
3969 : // Check for the text object existing, it seems that it can be NULL when saving a newly created
3970 : // comment without giving focus back to the main document. As GetTxt() is empty in that case as well,
3971 : // that is probably a bug in the Writer core.
3972 1 : if( f->GetTextObject() != NULL )
3973 1 : GetExport().WriteOutliner( *f->GetTextObject(), TXT_ATN );
3974 1 : m_pSerializer->endElementNS( XML_w, XML_comment );
3975 1 : }
3976 1 : }
3977 :
3978 0 : bool DocxAttributeOutput::DropdownField( const SwField* pFld )
3979 : {
3980 0 : bool bExpand = false;
3981 :
3982 0 : ww::eField eType = ww::eFORMDROPDOWN;
3983 0 : String sCmd = FieldString( eType );
3984 0 : GetExport( ).OutputField( pFld, eType, sCmd );
3985 :
3986 0 : return bExpand;
3987 : }
3988 :
3989 0 : bool DocxAttributeOutput::PlaceholderField( const SwField* pFld )
3990 : {
3991 : assert( pendingPlaceholder == NULL );
3992 0 : pendingPlaceholder = pFld;
3993 0 : return false; // do not expand
3994 : }
3995 :
3996 290 : void DocxAttributeOutput::WritePendingPlaceholder()
3997 : {
3998 290 : if( pendingPlaceholder == NULL )
3999 580 : return;
4000 0 : const SwField* pFld = pendingPlaceholder;
4001 0 : pendingPlaceholder = NULL;
4002 0 : m_pSerializer->startElementNS( XML_w, XML_sdt, FSEND );
4003 0 : m_pSerializer->startElementNS( XML_w, XML_sdtPr, FSEND );
4004 0 : if( !pFld->GetPar2().isEmpty())
4005 : m_pSerializer->singleElementNS( XML_w, XML_alias,
4006 0 : FSNS( XML_w, XML_val ), OUStringToOString( pFld->GetPar2(), RTL_TEXTENCODING_UTF8 ), FSEND );
4007 0 : m_pSerializer->singleElementNS( XML_w, XML_temporary, FSEND );
4008 0 : m_pSerializer->singleElementNS( XML_w, XML_showingPlcHdr, FSEND );
4009 0 : m_pSerializer->singleElementNS( XML_w, XML_text, FSEND );
4010 0 : m_pSerializer->endElementNS( XML_w, XML_sdtPr );
4011 0 : m_pSerializer->startElementNS( XML_w, XML_sdtContent, FSEND );
4012 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
4013 0 : RunText( pFld->GetPar1());
4014 0 : m_pSerializer->endElementNS( XML_w, XML_r );
4015 0 : m_pSerializer->endElementNS( XML_w, XML_sdtContent );
4016 0 : m_pSerializer->endElementNS( XML_w, XML_sdt );
4017 : }
4018 :
4019 0 : void DocxAttributeOutput::SetField( const SwField& rFld, ww::eField eType, const String& rCmd )
4020 : {
4021 : // field bookmarks are handled in the EndRun method
4022 0 : GetExport().OutputField(&rFld, eType, rCmd );
4023 0 : }
4024 :
4025 0 : void DocxAttributeOutput::WriteExpand( const SwField* pFld )
4026 : {
4027 : // Will be written in the next End Run
4028 0 : String sCmd;
4029 0 : m_rExport.OutputField( pFld, ww::eUNKNOWN, sCmd );
4030 0 : }
4031 :
4032 2 : void DocxAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode )
4033 : {
4034 2 : struct FieldInfos infos;
4035 2 : if (pFld)
4036 0 : infos.pField = pFld->CopyField();
4037 2 : infos.sCmd = rFldCmd;
4038 2 : infos.eType = eType;
4039 2 : infos.bClose = WRITEFIELD_CLOSE & nMode;
4040 2 : infos.bOpen = WRITEFIELD_START & nMode;
4041 2 : m_Fields.push_back( infos );
4042 :
4043 2 : if ( pFld )
4044 : {
4045 0 : sal_uInt16 nType = pFld->GetTyp( )->Which( );
4046 0 : sal_uInt16 nSubType = pFld->GetSubType();
4047 :
4048 : // TODO Any other field types here ?
4049 0 : if ( ( nType == RES_SETEXPFLD ) && ( nSubType & nsSwGetSetExpType::GSE_STRING ) )
4050 : {
4051 0 : const SwSetExpField *pSet = ( const SwSetExpField* )( pFld );
4052 0 : m_sFieldBkm = pSet->GetPar1( );
4053 : }
4054 0 : else if ( nType == RES_DROPDOWN )
4055 : {
4056 0 : const SwDropDownField* pDropDown = ( const SwDropDownField* )( pFld );
4057 0 : m_sFieldBkm = pDropDown->GetName( );
4058 : }
4059 2 : }
4060 2 : }
4061 :
4062 0 : void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark )
4063 : {
4064 0 : if ( !m_Fields.empty() )
4065 0 : m_Fields.begin()->pFieldmark = &rFieldmark;
4066 0 : }
4067 :
4068 516 : void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
4069 : std::vector< OUString >& rEnds )
4070 : {
4071 532 : for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it != end; ++it )
4072 : {
4073 16 : OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
4074 16 : m_rMarksStart.push_back( rName );
4075 16 : }
4076 516 : rStarts.clear();
4077 :
4078 532 : for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it != end; ++it )
4079 : {
4080 16 : OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
4081 16 : m_rMarksEnd.push_back( rName );
4082 16 : }
4083 516 : rEnds.clear();
4084 516 : }
4085 :
4086 0 : void DocxAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
4087 : {
4088 0 : const SwEndNoteInfo& rInfo = rFootnote.IsEndNote()?
4089 0 : m_rExport.pDoc->GetEndNoteInfo(): m_rExport.pDoc->GetFtnInfo();
4090 :
4091 : // footnote/endnote run properties
4092 0 : const SwCharFmt* pCharFmt = rInfo.GetAnchorCharFmt( *m_rExport.pDoc );
4093 :
4094 0 : OString aStyleId( "style" );
4095 0 : aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
4096 :
4097 0 : m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
4098 :
4099 : // remember the footnote/endnote to
4100 : // 1) write the footnoteReference/endnoteReference in EndRunProperties()
4101 : // 2) be able to dump them all to footnotes.xml/endnotes.xml
4102 0 : if ( !rFootnote.IsEndNote() )
4103 0 : m_pFootnotesList->add( rFootnote );
4104 : else
4105 0 : m_pEndnotesList->add( rFootnote );
4106 0 : }
4107 :
4108 290 : void DocxAttributeOutput::FootnoteEndnoteReference()
4109 : {
4110 : sal_Int32 nId;
4111 290 : const SwFmtFtn *pFootnote = m_pFootnotesList->getCurrent( nId );
4112 :
4113 : // both cannot be set at the same time - if they are, it's a bug
4114 290 : if ( !pFootnote )
4115 290 : pFootnote = m_pEndnotesList->getCurrent( nId );
4116 :
4117 290 : if ( !pFootnote )
4118 580 : return;
4119 :
4120 0 : sal_Int32 nToken = pFootnote->IsEndNote()? XML_endnoteReference: XML_footnoteReference;
4121 :
4122 : // write it
4123 0 : if ( pFootnote->GetNumStr().Len() == 0 )
4124 : {
4125 : // autonumbered
4126 : m_pSerializer->singleElementNS( XML_w, nToken,
4127 : FSNS( XML_w, XML_id ), OString::valueOf( nId ).getStr(),
4128 0 : FSEND );
4129 : }
4130 : else
4131 : {
4132 : // not autonumbered
4133 : m_pSerializer->singleElementNS( XML_w, nToken,
4134 : FSNS( XML_w, XML_customMarkFollows ), "1",
4135 : FSNS( XML_w, XML_id ), OString::valueOf( nId ).getStr(),
4136 0 : FSEND );
4137 :
4138 0 : RunText( pFootnote->GetNumStr() );
4139 : }
4140 : }
4141 :
4142 0 : void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes )
4143 : {
4144 0 : const FootnotesVector& rVector = bFootnotes? m_pFootnotesList->getVector(): m_pEndnotesList->getVector();
4145 :
4146 0 : sal_Int32 nBody = bFootnotes? XML_footnotes: XML_endnotes;
4147 0 : sal_Int32 nItem = bFootnotes? XML_footnote: XML_endnote;
4148 :
4149 : m_pSerializer->startElementNS( XML_w, nBody,
4150 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
4151 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
4152 0 : FSEND );
4153 :
4154 0 : sal_Int32 nIndex = 0;
4155 :
4156 : // separator
4157 : m_pSerializer->startElementNS( XML_w, nItem,
4158 : FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
4159 : FSNS( XML_w, XML_type ), "separator",
4160 0 : FSEND );
4161 0 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
4162 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
4163 0 : m_pSerializer->singleElementNS( XML_w, XML_separator, FSEND );
4164 0 : m_pSerializer->endElementNS( XML_w, XML_r );
4165 0 : m_pSerializer->endElementNS( XML_w, XML_p );
4166 0 : m_pSerializer->endElementNS( XML_w, nItem );
4167 :
4168 : // separator
4169 : m_pSerializer->startElementNS( XML_w, nItem,
4170 : FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
4171 : FSNS( XML_w, XML_type ), "continuationSeparator",
4172 0 : FSEND );
4173 0 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
4174 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
4175 0 : m_pSerializer->singleElementNS( XML_w, XML_continuationSeparator, FSEND );
4176 0 : m_pSerializer->endElementNS( XML_w, XML_r );
4177 0 : m_pSerializer->endElementNS( XML_w, XML_p );
4178 0 : m_pSerializer->endElementNS( XML_w, nItem );
4179 :
4180 : // if new special ones are added, update also WriteFootnoteEndnotePr()
4181 :
4182 : // footnotes/endnotes themselves
4183 0 : for ( FootnotesVector::const_iterator i = rVector.begin(); i != rVector.end(); ++i, ++nIndex )
4184 : {
4185 : m_pSerializer->startElementNS( XML_w, nItem,
4186 : FSNS( XML_w, XML_id ), OString::valueOf( nIndex ).getStr(),
4187 0 : FSEND );
4188 :
4189 0 : const SwNodeIndex* pIndex = (*i)->GetTxtFtn()->GetStartNode();
4190 : // tag required at the start of each footnote/endnote
4191 0 : m_footnoteEndnoteRefTag = bFootnotes ? XML_footnoteRef : XML_endnoteRef;
4192 :
4193 0 : m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
4194 0 : pIndex->GetNode().EndOfSectionIndex(),
4195 0 : bFootnotes? TXT_FTN: TXT_EDN );
4196 :
4197 0 : m_pSerializer->endElementNS( XML_w, nItem );
4198 : }
4199 :
4200 0 : m_pSerializer->endElementNS( XML_w, nBody );
4201 :
4202 0 : }
4203 :
4204 0 : void DocxAttributeOutput::WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr fs, int tag,
4205 : const SwEndNoteInfo& info, int listtag )
4206 : {
4207 0 : fs->startElementNS( XML_w, tag, FSEND );
4208 0 : const char* fmt = NULL;
4209 0 : switch( info.aFmt.GetNumberingType())
4210 : {
4211 : case SVX_NUM_CHARS_UPPER_LETTER_N: // fall through, map to upper letters
4212 : case SVX_NUM_CHARS_UPPER_LETTER:
4213 0 : fmt = "upperLetter";
4214 0 : break;
4215 : case SVX_NUM_CHARS_LOWER_LETTER_N: // fall through, map to lower letters
4216 : case SVX_NUM_CHARS_LOWER_LETTER:
4217 0 : fmt = "lowerLetter";
4218 0 : break;
4219 : case SVX_NUM_ROMAN_UPPER:
4220 0 : fmt = "upperRoman";
4221 0 : break;
4222 : case SVX_NUM_ROMAN_LOWER:
4223 0 : fmt = "lowerRoman";
4224 0 : break;
4225 : case SVX_NUM_ARABIC:
4226 0 : fmt = "decimal";
4227 0 : break;
4228 : case SVX_NUM_NUMBER_NONE:
4229 0 : fmt = "none";
4230 0 : break;
4231 : case SVX_NUM_CHAR_SPECIAL:
4232 0 : fmt = "bullet";
4233 0 : break;
4234 : case SVX_NUM_PAGEDESC:
4235 : case SVX_NUM_BITMAP:
4236 : default:
4237 0 : break; // no format
4238 : }
4239 0 : if( fmt != NULL )
4240 0 : fs->singleElementNS( XML_w, XML_numFmt, FSNS( XML_w, XML_val ), fmt, FSEND );
4241 0 : if( info.nFtnOffset != 0 )
4242 : fs->singleElementNS( XML_w, XML_numStart, FSNS( XML_w, XML_val ),
4243 0 : OString::valueOf( sal_Int32( info.nFtnOffset + 1 )).getStr(), FSEND );
4244 0 : if( listtag != 0 ) // we are writing to settings.xml, write also special footnote/endnote list
4245 : { // there are currently only two hardcoded ones ( see FootnotesEndnotes())
4246 0 : fs->singleElementNS( XML_w, listtag, FSNS( XML_w, XML_id ), "0", FSEND );
4247 0 : fs->singleElementNS( XML_w, listtag, FSNS( XML_w, XML_id ), "1", FSEND );
4248 : }
4249 0 : fs->endElementNS( XML_w, tag );
4250 0 : }
4251 :
4252 48 : void DocxAttributeOutput::SectFootnoteEndnotePr()
4253 : {
4254 48 : if( HasFootnotes())
4255 0 : WriteFootnoteEndnotePr( m_pSerializer, XML_footnotePr, m_rExport.pDoc->GetFtnInfo(), 0 );
4256 48 : if( HasEndnotes())
4257 0 : WriteFootnoteEndnotePr( m_pSerializer, XML_endnotePr, m_rExport.pDoc->GetEndNoteInfo(), 0 );
4258 48 : }
4259 :
4260 91 : void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
4261 : {
4262 91 : if ( !m_pParagraphSpacingAttrList )
4263 91 : m_pParagraphSpacingAttrList = m_pSerializer->createAttrList();
4264 :
4265 91 : if ( nSpace < 0 )
4266 : {
4267 0 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "exact" );
4268 0 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( -nSpace ) ) );
4269 : }
4270 91 : else if( nMulti )
4271 : {
4272 25 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
4273 25 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
4274 : }
4275 66 : else if ( nSpace > 0 )
4276 : {
4277 66 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "atLeast" );
4278 66 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
4279 : }
4280 : else
4281 0 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
4282 91 : }
4283 :
4284 11 : void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
4285 : {
4286 : const char *pAdjustString;
4287 :
4288 11 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
4289 :
4290 11 : const SfxItemSet* pItems = GetExport().GetCurItemSet();
4291 11 : const SvxFrameDirectionItem* rFrameDir = static_cast< const SvxFrameDirectionItem* >( pItems->GetItem( RES_FRAMEDIR ) );
4292 :
4293 11 : short nDir = FRMDIR_ENVIRONMENT;
4294 11 : if( rFrameDir != NULL )
4295 11 : nDir = rFrameDir->GetValue();
4296 11 : if ( nDir == FRMDIR_ENVIRONMENT )
4297 0 : nDir = GetExport( ).GetDefaultFrameDirection( );
4298 11 : bool bRtl = ( nDir == FRMDIR_HORI_RIGHT_TOP );
4299 :
4300 11 : switch ( rAdjust.GetAdjust() )
4301 : {
4302 : case SVX_ADJUST_LEFT:
4303 1 : if ( bEcma )
4304 0 : if ( bRtl )
4305 0 : pAdjustString = "right";
4306 : else
4307 0 : pAdjustString = "left";
4308 1 : else if ( bRtl )
4309 1 : pAdjustString = "end";
4310 : else
4311 0 : pAdjustString = "start";
4312 1 : break;
4313 : case SVX_ADJUST_RIGHT:
4314 2 : if ( bEcma )
4315 0 : if ( bRtl )
4316 0 : pAdjustString = "left";
4317 : else
4318 0 : pAdjustString = "right";
4319 2 : else if ( bRtl )
4320 1 : pAdjustString = "start";
4321 : else
4322 1 : pAdjustString = "end";
4323 2 : break;
4324 : case SVX_ADJUST_BLOCKLINE:
4325 : case SVX_ADJUST_BLOCK:
4326 0 : pAdjustString = "both";
4327 0 : break;
4328 : case SVX_ADJUST_CENTER:
4329 8 : pAdjustString = "center";
4330 8 : break;
4331 : default:
4332 11 : return; // not supported attribute
4333 : }
4334 11 : m_pSerializer->singleElementNS( XML_w, XML_jc, FSNS( XML_w, XML_val ), pAdjustString, FSEND );
4335 : }
4336 :
4337 0 : void DocxAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
4338 : {
4339 0 : if (rSplit.GetValue())
4340 0 : m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSNS( XML_w, XML_val ), "false", FSEND );
4341 : else
4342 0 : m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSEND );
4343 0 : }
4344 :
4345 52 : void DocxAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
4346 : {
4347 52 : if (rWidows.GetValue())
4348 26 : m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSEND );
4349 : else
4350 26 : m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSNS( XML_w, XML_val ), "false", FSEND );
4351 52 : }
4352 :
4353 42 : static void impl_WriteTabElement( FSHelperPtr pSerializer,
4354 : const SvxTabStop& rTab, long /* nCurrentLeft */ )
4355 : {
4356 42 : FastAttributeList *pTabElementAttrList = pSerializer->createAttrList();
4357 :
4358 42 : switch (rTab.GetAdjustment())
4359 : {
4360 : case SVX_TAB_ADJUST_RIGHT:
4361 14 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"right") );
4362 14 : break;
4363 : case SVX_TAB_ADJUST_DECIMAL:
4364 0 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"decimal") );
4365 0 : break;
4366 : case SVX_TAB_ADJUST_CENTER:
4367 14 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"center") );
4368 14 : break;
4369 : case SVX_TAB_ADJUST_DEFAULT:
4370 : case SVX_TAB_ADJUST_LEFT:
4371 : default:
4372 14 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"left") );
4373 14 : break;
4374 : }
4375 :
4376 : // Because GetTabPos already includes indent, we don't need to add nCurrentLeft (CurrentLeft is indentation information)
4377 : //pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
4378 42 : pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() ) );
4379 :
4380 42 : sal_Unicode cFillChar = rTab.GetFill();
4381 :
4382 42 : if (sal_Unicode('.') == cFillChar )
4383 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "dot" ) );
4384 42 : else if ( sal_Unicode('-') == cFillChar )
4385 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "hyphen" ) );
4386 42 : else if ( sal_Unicode(0xB7) == cFillChar ) // middle dot
4387 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "middleDot" ) );
4388 42 : else if ( sal_Unicode('_') == cFillChar )
4389 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "underscore" ) );
4390 : else
4391 42 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "none" ) );
4392 :
4393 42 : pSerializer->singleElementNS( XML_w, XML_tab, pTabElementAttrList );
4394 42 : }
4395 :
4396 62 : void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
4397 : {
4398 62 : const SfxPoolItem* pLR = m_rExport.HasItem( RES_LR_SPACE );
4399 62 : long nCurrentLeft = pLR ? ((const SvxLRSpaceItem*)pLR)->GetTxtLeft() : 0;
4400 :
4401 62 : sal_uInt16 nCount = rTabStop.Count();
4402 :
4403 : // <w:tabs> must contain at least one <w:tab>, so don't write it empty
4404 62 : if( nCount == 0 )
4405 1 : return;
4406 61 : if( nCount == 1 && rTabStop[ 0 ].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
4407 : {
4408 33 : GetExport().setDefaultTabStop( rTabStop[ 0 ].GetTabPos());
4409 33 : return;
4410 : }
4411 :
4412 28 : m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
4413 :
4414 70 : for (sal_uInt16 i = 0; i < nCount; i++ )
4415 : {
4416 42 : if( rTabStop[i].GetAdjustment() != SVX_TAB_ADJUST_DEFAULT )
4417 42 : impl_WriteTabElement( m_pSerializer, rTabStop[i], nCurrentLeft );
4418 : else
4419 0 : GetExport().setDefaultTabStop( rTabStop[i].GetTabPos());
4420 : }
4421 :
4422 28 : m_pSerializer->endElementNS( XML_w, XML_tabs );
4423 : }
4424 :
4425 51 : void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
4426 : {
4427 : m_pSerializer->singleElementNS( XML_w, XML_suppressAutoHyphens,
4428 51 : FSNS( XML_w, XML_val ), rHyphenZone.IsHyphen( ) ? "false" : "true" ,
4429 51 : FSEND );
4430 51 : }
4431 :
4432 2 : void DocxAttributeOutput::ParaNumRule_Impl( const SwTxtNode* /*pTxtNd*/, sal_Int32 nLvl, sal_Int32 nNumId )
4433 : {
4434 2 : if ( USHRT_MAX != nNumId && 0 != nNumId )
4435 : {
4436 1 : m_pSerializer->startElementNS( XML_w, XML_numPr, FSEND );
4437 1 : m_pSerializer->singleElementNS( XML_w, XML_ilvl, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl )).getStr(), FSEND );
4438 1 : m_pSerializer->singleElementNS( XML_w, XML_numId, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nNumId )).getStr(), FSEND );
4439 1 : m_pSerializer->endElementNS( XML_w, XML_numPr );
4440 : }
4441 2 : }
4442 :
4443 28 : void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
4444 : {
4445 28 : sal_uInt16 nXmlElement = 0;
4446 :
4447 28 : switch ( rScriptSpace.Which( ) )
4448 : {
4449 : case RES_PARATR_SCRIPTSPACE:
4450 7 : nXmlElement = XML_autoSpaceDE;
4451 7 : break;
4452 : case RES_PARATR_HANGINGPUNCTUATION:
4453 14 : nXmlElement = XML_overflowPunct;
4454 14 : break;
4455 : case RES_PARATR_FORBIDDEN_RULES:
4456 7 : nXmlElement = XML_kinsoku;
4457 7 : break;
4458 : }
4459 :
4460 28 : if ( nXmlElement )
4461 : {
4462 : m_pSerializer->singleElementNS( XML_w, nXmlElement,
4463 28 : FSNS( XML_w, XML_val ), rScriptSpace.GetValue( ) ? "true": "false",
4464 28 : FSEND );
4465 : }
4466 28 : }
4467 :
4468 0 : void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
4469 : {
4470 : const char *pAlignString;
4471 :
4472 0 : switch ( rAlign.GetValue() )
4473 : {
4474 : case SvxParaVertAlignItem::BASELINE:
4475 0 : pAlignString = "baseline";
4476 0 : break;
4477 : case SvxParaVertAlignItem::TOP:
4478 0 : pAlignString = "top";
4479 0 : break;
4480 : case SvxParaVertAlignItem::CENTER:
4481 0 : pAlignString = "center";
4482 0 : break;
4483 : case SvxParaVertAlignItem::BOTTOM:
4484 0 : pAlignString = "bottom";
4485 0 : break;
4486 : case SvxParaVertAlignItem::AUTOMATIC:
4487 0 : pAlignString = "auto";
4488 0 : break;
4489 : default:
4490 0 : return; // not supported attribute
4491 : }
4492 0 : m_pSerializer->singleElementNS( XML_w, XML_textAlignment, FSNS( XML_w, XML_val ), pAlignString, FSEND );
4493 : }
4494 :
4495 0 : void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
4496 : {
4497 : m_pSerializer->singleElementNS( XML_w, XML_snapToGrid,
4498 0 : FSNS( XML_w, XML_val ), rGrid.GetValue( ) ? "true": "false",
4499 0 : FSEND );
4500 0 : }
4501 :
4502 56 : void DocxAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
4503 : {
4504 56 : if (m_bTextFrameSyntax && m_pFlyFrameSize)
4505 : {
4506 8 : m_aTextFrameStyle.append(";width:").append(double(m_pFlyFrameSize->Width()) / 20);
4507 8 : m_aTextFrameStyle.append("pt;height:").append(double(m_pFlyFrameSize->Height()) / 20).append("pt");
4508 : }
4509 48 : else if ( m_rExport.bOutFlyFrmAttrs )
4510 : {
4511 0 : if ( !m_pFlyAttrList )
4512 0 : m_pFlyAttrList = m_pSerializer->createAttrList( );
4513 :
4514 0 : if ( rSize.GetWidth() && rSize.GetWidthSizeType() == ATT_FIX_SIZE )
4515 : {
4516 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
4517 : }
4518 :
4519 0 : if ( rSize.GetHeight() )
4520 : {
4521 0 : OString sRule( "exact" );
4522 0 : if ( rSize.GetHeightSizeType() == ATT_MIN_SIZE )
4523 0 : sRule = OString( "atLeast" );
4524 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_hRule ), sRule );
4525 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
4526 : }
4527 : }
4528 48 : else if ( m_rExport.bOutPageDescs )
4529 : {
4530 48 : FastAttributeList *attrList = m_pSerializer->createAttrList( );
4531 48 : if ( m_rExport.pAktPageDesc->GetLandscape( ) )
4532 0 : attrList->add( FSNS( XML_w, XML_orient ), "landscape" );
4533 :
4534 48 : attrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
4535 48 : attrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
4536 :
4537 48 : XFastAttributeListRef xAttrList( attrList );
4538 48 : attrList = NULL;
4539 :
4540 48 : m_pSerializer->singleElementNS( XML_w, XML_pgSz, xAttrList );
4541 : }
4542 56 : }
4543 :
4544 0 : void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
4545 : {
4546 : OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()" );
4547 0 : }
4548 :
4549 65 : void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
4550 : {
4551 65 : bool bEcma = m_rExport.GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
4552 :
4553 65 : if (m_bTextFrameSyntax)
4554 : {
4555 : }
4556 57 : else if ( m_rExport.bOutFlyFrmAttrs )
4557 : {
4558 0 : if ( !m_pFlyAttrList )
4559 0 : m_pFlyAttrList = m_pSerializer->createAttrList();
4560 :
4561 : m_pFlyAttrList->add( FSNS( XML_w, XML_hSpace ),
4562 : OString::valueOf(
4563 0 : sal_Int32( ( rLRSpace.GetLeft() + rLRSpace.GetRight() ) / 2 ) ) );
4564 : }
4565 57 : else if ( m_rExport.bOutPageDescs )
4566 : {
4567 48 : if ( !m_pSectionSpacingAttrList )
4568 48 : m_pSectionSpacingAttrList = m_pSerializer->createAttrList();
4569 :
4570 : sal_uInt16 nLDist, nRDist;
4571 48 : const SfxPoolItem* pItem = m_rExport.HasItem( RES_BOX );
4572 48 : if ( pItem )
4573 : {
4574 0 : nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
4575 0 : nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
4576 : }
4577 : else
4578 48 : nLDist = nRDist = 0;
4579 48 : nLDist = nLDist + (sal_uInt16)rLRSpace.GetLeft();
4580 48 : nRDist = nRDist + (sal_uInt16)rLRSpace.GetRight();
4581 :
4582 48 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_left ), OString::valueOf( sal_Int32( nLDist ) ) );
4583 48 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_right ), OString::valueOf( sal_Int32( nRDist ) ) );
4584 : }
4585 : else
4586 : {
4587 9 : FastAttributeList *pLRSpaceAttrList = m_pSerializer->createAttrList();
4588 :
4589 9 : pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_left : XML_start ) ), OString::valueOf( (sal_Int32) rLRSpace.GetTxtLeft() ) );
4590 9 : pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_right : XML_end ) ), OString::valueOf( (sal_Int32) rLRSpace.GetRight() ) );
4591 :
4592 9 : sal_Int32 nFirstLineAdjustment = rLRSpace.GetTxtFirstLineOfst();
4593 9 : if (nFirstLineAdjustment > 0)
4594 0 : pLRSpaceAttrList->add( FSNS( XML_w, XML_firstLine ), OString::valueOf( nFirstLineAdjustment ) );
4595 : else
4596 9 : pLRSpaceAttrList->add( FSNS( XML_w, XML_hanging ), OString::valueOf( - nFirstLineAdjustment ) );
4597 9 : m_pSerializer->singleElementNS( XML_w, XML_ind, pLRSpaceAttrList );
4598 : }
4599 65 : }
4600 :
4601 302 : void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
4602 : {
4603 :
4604 302 : if (m_bTextFrameSyntax)
4605 : {
4606 : }
4607 294 : else if ( m_rExport.bOutFlyFrmAttrs )
4608 : {
4609 0 : if ( !m_pFlyAttrList )
4610 0 : m_pFlyAttrList = m_pSerializer->createAttrList();
4611 :
4612 : m_pFlyAttrList->add( FSNS( XML_w, XML_vSpace ),
4613 : OString::valueOf(
4614 0 : sal_Int32( ( rULSpace.GetLower() + rULSpace.GetUpper() ) / 2 ) ) );
4615 : }
4616 294 : else if (m_rExport.bOutPageDescs )
4617 : {
4618 : OSL_ENSURE( m_rExport.GetCurItemSet(), "Impossible" );
4619 48 : if ( !m_rExport.GetCurItemSet() )
4620 302 : return;
4621 :
4622 48 : if ( !m_pSectionSpacingAttrList )
4623 0 : m_pSectionSpacingAttrList = m_pSerializer->createAttrList();
4624 :
4625 48 : HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
4626 :
4627 48 : sal_Int32 nHeader = 0;
4628 48 : if ( aDistances.HasHeader() )
4629 5 : nHeader = sal_Int32( aDistances.dyaHdrTop );
4630 48 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_header ), OString::valueOf( nHeader ) );
4631 :
4632 : // Page top
4633 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_top ),
4634 48 : OString::valueOf( sal_Int32( aDistances.dyaTop ) ) );
4635 :
4636 48 : sal_Int32 nFooter = 0;
4637 48 : if ( aDistances.HasFooter() )
4638 7 : nFooter = sal_Int32( aDistances.dyaHdrBottom );
4639 48 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_footer ), OString::valueOf( nFooter ) );
4640 :
4641 : // Page Bottom
4642 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_bottom ),
4643 48 : OString::valueOf( sal_Int32( aDistances.dyaBottom ) ) );
4644 :
4645 : // FIXME Page Gutter is not handled ATM, setting to 0 as it's mandatory for OOXML
4646 : m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_gutter ),
4647 48 : OString::valueOf( sal_Int32( 0 ) ) );
4648 :
4649 : }
4650 : else
4651 : {
4652 246 : if ( !m_pParagraphSpacingAttrList )
4653 156 : m_pParagraphSpacingAttrList = m_pSerializer->createAttrList();
4654 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_before ),
4655 246 : OString::valueOf( (sal_Int32)rULSpace.GetUpper() ) );
4656 : m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_after ),
4657 246 : OString::valueOf( (sal_Int32)rULSpace.GetLower() ) );
4658 246 : if (rULSpace.GetContext())
4659 1 : m_pSerializer->singleElementNS( XML_w, XML_contextualSpacing, FSEND );
4660 : else
4661 245 : m_pSerializer->singleElementNS( XML_w, XML_contextualSpacing, FSNS( XML_w, XML_val ), "false", FSEND );
4662 : }
4663 : }
4664 :
4665 8 : void DocxAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
4666 : {
4667 8 : if (m_bTextFrameSyntax)
4668 : {
4669 16 : OString sType, sSide;
4670 8 : switch (rSurround.GetSurround())
4671 : {
4672 : case SURROUND_NONE:
4673 0 : sType = "topAndBottom";
4674 0 : break;
4675 : case SURROUND_PARALLEL:
4676 6 : sType = "square";
4677 6 : break;
4678 : case SURROUND_IDEAL:
4679 0 : sType = "square";
4680 0 : sSide = "largest";
4681 : case SURROUND_LEFT:
4682 0 : sType = "square";
4683 0 : sSide = "left";
4684 : case SURROUND_RIGHT:
4685 0 : sType = "square";
4686 0 : sSide = "right";
4687 0 : break;
4688 : case SURROUND_THROUGHT:
4689 : default:
4690 2 : break;
4691 : }
4692 8 : if (!sType.isEmpty() || !sSide.isEmpty())
4693 : {
4694 6 : m_pFlyWrapAttrList = m_pSerializer->createAttrList();
4695 6 : if (!sType.isEmpty())
4696 6 : m_pFlyWrapAttrList->add(XML_type, sType);
4697 6 : if (!sSide.isEmpty())
4698 0 : m_pFlyWrapAttrList->add(XML_side, sSide);
4699 8 : }
4700 : }
4701 0 : else if ( m_rExport.bOutFlyFrmAttrs )
4702 : {
4703 0 : if ( !m_pFlyAttrList )
4704 0 : m_pFlyAttrList = m_pSerializer->createAttrList();
4705 :
4706 0 : OString sWrap( "auto" );
4707 0 : switch ( rSurround.GetSurround( ) )
4708 : {
4709 : case SURROUND_NONE:
4710 0 : sWrap = OString( "none" );
4711 0 : break;
4712 : case SURROUND_THROUGHT:
4713 0 : sWrap = OString( "through" );
4714 0 : break;
4715 : case SURROUND_IDEAL:
4716 : case SURROUND_PARALLEL:
4717 : case SURROUND_LEFT:
4718 : case SURROUND_RIGHT:
4719 : default:
4720 0 : sWrap = OString( "around" );
4721 : }
4722 :
4723 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_wrap ), sWrap );
4724 : }
4725 8 : }
4726 :
4727 8 : void DocxAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
4728 : {
4729 8 : if (m_bTextFrameSyntax)
4730 : {
4731 8 : m_aTextFrameStyle.append(";margin-top:").append(double(rFlyVert.GetPos()) / 20).append("pt");
4732 : }
4733 0 : else if ( m_rExport.bOutFlyFrmAttrs )
4734 : {
4735 0 : if ( !m_pFlyAttrList )
4736 0 : m_pFlyAttrList = m_pSerializer->createAttrList();
4737 :
4738 0 : OString sAlign;
4739 0 : switch( rFlyVert.GetVertOrient() )
4740 : {
4741 : case text::VertOrientation::NONE:
4742 0 : break;
4743 : case text::VertOrientation::CENTER:
4744 : case text::VertOrientation::LINE_CENTER:
4745 0 : sAlign = OString( "center" );
4746 0 : break;
4747 : case text::VertOrientation::BOTTOM:
4748 : case text::VertOrientation::LINE_BOTTOM:
4749 0 : sAlign = OString( "bottom" );
4750 0 : break;
4751 : case text::VertOrientation::TOP:
4752 : case text::VertOrientation::LINE_TOP:
4753 : default:
4754 0 : sAlign = OString( "top" );
4755 0 : break;
4756 : }
4757 :
4758 0 : if ( !sAlign.isEmpty() )
4759 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_yAlign ), sAlign );
4760 : else
4761 : m_pFlyAttrList->add( FSNS( XML_w, XML_y ),
4762 0 : OString::valueOf( sal_Int32( rFlyVert.GetPos() ) ) );
4763 :
4764 0 : OString sVAnchor( "page" );
4765 0 : switch ( rFlyVert.GetRelationOrient( ) )
4766 : {
4767 : case text::RelOrientation::CHAR:
4768 : case text::RelOrientation::PRINT_AREA:
4769 : case text::RelOrientation::TEXT_LINE:
4770 0 : sVAnchor = OString( "column" );
4771 0 : break;
4772 : case text::RelOrientation::FRAME:
4773 : case text::RelOrientation::PAGE_LEFT:
4774 : case text::RelOrientation::PAGE_RIGHT:
4775 : case text::RelOrientation::FRAME_LEFT:
4776 : case text::RelOrientation::FRAME_RIGHT:
4777 0 : sVAnchor = OString( "margin" );
4778 0 : break;
4779 : case text::RelOrientation::PAGE_FRAME:
4780 : case text::RelOrientation::PAGE_PRINT_AREA:
4781 : default:
4782 0 : break;
4783 : }
4784 :
4785 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_vAnchor ), sVAnchor );
4786 : }
4787 8 : }
4788 :
4789 8 : void DocxAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
4790 : {
4791 8 : if (m_bTextFrameSyntax)
4792 : {
4793 8 : m_aTextFrameStyle.append(";margin-left:").append(double(rFlyHori.GetPos()) / 20).append("pt");
4794 : }
4795 0 : else if ( m_rExport.bOutFlyFrmAttrs )
4796 : {
4797 0 : if ( !m_pFlyAttrList )
4798 0 : m_pFlyAttrList = m_pSerializer->createAttrList();
4799 :
4800 0 : OString sAlign;
4801 0 : switch( rFlyHori.GetHoriOrient() )
4802 : {
4803 : case text::HoriOrientation::NONE:
4804 0 : break;
4805 : case text::HoriOrientation::LEFT:
4806 0 : sAlign = OString( rFlyHori.IsPosToggle( ) ? "inside" : "left" );
4807 0 : break;
4808 : case text::HoriOrientation::RIGHT:
4809 0 : sAlign = OString( rFlyHori.IsPosToggle( ) ? "outside" : "right" );
4810 0 : break;
4811 : case text::HoriOrientation::CENTER:
4812 : case text::HoriOrientation::FULL: // FULL only for tables
4813 : default:
4814 0 : sAlign = OString( "center" );
4815 0 : break;
4816 : }
4817 :
4818 0 : if ( !sAlign.isEmpty() )
4819 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_xAlign ), sAlign );
4820 : else
4821 : m_pFlyAttrList->add( FSNS( XML_w, XML_x ),
4822 0 : OString::valueOf( sal_Int32( rFlyHori.GetPos() ) ) );
4823 :
4824 0 : OString sHAnchor( "page" );
4825 0 : switch ( rFlyHori.GetRelationOrient( ) )
4826 : {
4827 : case text::RelOrientation::CHAR:
4828 : case text::RelOrientation::PRINT_AREA:
4829 0 : sHAnchor = OString( "text" );
4830 0 : break;
4831 : case text::RelOrientation::FRAME:
4832 : case text::RelOrientation::PAGE_LEFT:
4833 : case text::RelOrientation::PAGE_RIGHT:
4834 : case text::RelOrientation::FRAME_LEFT:
4835 : case text::RelOrientation::FRAME_RIGHT:
4836 0 : sHAnchor = OString( "margin" );
4837 0 : break;
4838 : case text::RelOrientation::PAGE_FRAME:
4839 : case text::RelOrientation::PAGE_PRINT_AREA:
4840 : default:
4841 0 : break;
4842 : }
4843 :
4844 0 : m_pFlyAttrList->add( FSNS( XML_w, XML_hAnchor ), sHAnchor );
4845 : }
4846 8 : }
4847 :
4848 8 : void DocxAttributeOutput::FormatAnchor( const SwFmtAnchor& )
4849 : {
4850 : // Fly frames: anchors here aren't matching the anchors in docx
4851 8 : }
4852 :
4853 3 : void DocxAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
4854 : {
4855 3 : OString sColor = msfilter::util::ConvertColor( rBrush.GetColor( ) );
4856 3 : if (m_bTextFrameSyntax)
4857 1 : m_pFlyAttrList->add(XML_fillcolor, "#" + sColor);
4858 2 : else if ( !m_rExport.bOutPageDescs )
4859 : {
4860 : m_pSerializer->singleElementNS( XML_w, XML_shd,
4861 : FSNS( XML_w, XML_fill ), sColor.getStr( ),
4862 : FSNS( XML_w, XML_val ), "clear",
4863 0 : FSEND );
4864 3 : }
4865 3 : }
4866 :
4867 3 : void DocxAttributeOutput::FormatFillStyle( const XFillStyleItem& rFillStyle )
4868 : {
4869 3 : m_oFillStyle.reset(rFillStyle.GetValue());
4870 3 : }
4871 :
4872 2 : void DocxAttributeOutput::FormatFillGradient( const XFillGradientItem& rFillGradient )
4873 : {
4874 2 : if (*m_oFillStyle == XFILL_GRADIENT)
4875 : {
4876 2 : m_pFlyFillAttrList = m_pSerializer->createAttrList();
4877 2 : m_pFlyFillAttrList->add(XML_type, "gradient");
4878 :
4879 2 : const XGradient& rGradient = rFillGradient.GetGradientValue();
4880 2 : OString sStartColor = msfilter::util::ConvertColor(rGradient.GetStartColor());
4881 2 : m_pFlyFillAttrList->add(XML_color2, "#" + sStartColor);
4882 4 : OString sEndColor = msfilter::util::ConvertColor(rGradient.GetEndColor());
4883 2 : m_pFlyAttrList->add(XML_fillcolor, "#" + sEndColor);
4884 :
4885 2 : switch (rGradient.GetGradientStyle())
4886 : {
4887 0 : case XGRAD_LINEAR: break;
4888 : case XGRAD_AXIAL:
4889 2 : m_pFlyFillAttrList->add(XML_focus, "50%");
4890 2 : break;
4891 0 : case XGRAD_RADIAL: break;
4892 0 : case XGRAD_ELLIPTICAL: break;
4893 0 : case XGRAD_SQUARE: break;
4894 0 : case XGRAD_RECT: break;
4895 2 : }
4896 : }
4897 2 : m_oFillStyle.reset();
4898 2 : }
4899 :
4900 8 : void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
4901 : {
4902 8 : if (m_bTextFrameSyntax)
4903 : {
4904 8 : const SvxBorderLine* pLeft = rBox.GetLine(BOX_LINE_LEFT);
4905 8 : const SvxBorderLine* pRight = rBox.GetLine(BOX_LINE_RIGHT);
4906 8 : const SvxBorderLine* pTop = rBox.GetLine(BOX_LINE_TOP);
4907 8 : const SvxBorderLine* pBottom = rBox.GetLine(BOX_LINE_BOTTOM);
4908 24 : if (pLeft && pRight && pTop && pBottom &&
4909 24 : *pLeft == *pRight && *pLeft == *pTop && *pLeft == *pBottom)
4910 : {
4911 8 : OString sColor("#" + msfilter::util::ConvertColor(pTop->GetColor()));
4912 8 : m_pFlyAttrList->add(XML_strokecolor, sColor);
4913 :
4914 8 : double const fConverted(editeng::ConvertBorderWidthToWord(pTop->GetBorderLineStyle(), pTop->GetWidth()));
4915 8 : sal_Int32 nWidth = sal_Int32(fConverted / 20);
4916 8 : m_pFlyAttrList->add(XML_strokeweight, OString::valueOf(nWidth) + "pt");
4917 : }
4918 :
4919 : // v:textbox's inset attribute: inner margin values for textbox text
4920 8 : OStringBuffer aInset;
4921 8 : aInset.append(OString::number(double(rBox.GetDistance(BOX_LINE_LEFT))/20) + "pt,");
4922 8 : aInset.append(OString::number(double(rBox.GetDistance(BOX_LINE_TOP))/20) + "pt,");
4923 8 : aInset.append(OString::number(double(rBox.GetDistance(BOX_LINE_RIGHT))/20) + "pt,");
4924 8 : aInset.append(OString::number(double(rBox.GetDistance(BOX_LINE_BOTTOM))/20) + "pt");
4925 8 : m_pTextboxAttrList->add(XML_inset, aInset.makeStringAndClear());
4926 16 : return;
4927 : }
4928 :
4929 0 : if ( !m_bOpenedSectPr )
4930 : {
4931 : // Normally open the borders tag for paragraphs
4932 0 : m_pSerializer->startElementNS( XML_w, XML_pBdr, FSEND );
4933 : }
4934 :
4935 0 : impl_borders( m_pSerializer, rBox, lcl_getBoxBorderOptions() );
4936 :
4937 0 : if ( m_bOpenedSectPr )
4938 : {
4939 : // Special handling for pgBorder
4940 0 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
4941 0 : m_pSerializer->mergeTopMarks( );
4942 : }
4943 : else
4944 : {
4945 : // Normally close the borders tag for paragraphs
4946 0 : m_pSerializer->endElementNS( XML_w, XML_pBdr );
4947 : }
4948 : }
4949 :
4950 0 : void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
4951 : {
4952 : // Get the columns attributes
4953 0 : FastAttributeList *pColsAttrList = m_pSerializer->createAttrList();
4954 :
4955 : pColsAttrList->add( FSNS( XML_w, XML_num ),
4956 0 : OString::valueOf( sal_Int32( nCols ) ). getStr( ) );
4957 :
4958 0 : const char* pEquals = "false";
4959 0 : if ( bEven )
4960 : {
4961 0 : sal_uInt16 nWidth = rCol.GetGutterWidth( true );
4962 : pColsAttrList->add( FSNS( XML_w, XML_space ),
4963 0 : OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
4964 :
4965 0 : pEquals = "true";
4966 : }
4967 :
4968 0 : pColsAttrList->add( FSNS( XML_w, XML_equalWidth ), pEquals );
4969 :
4970 0 : bool bHasSep = COLADJ_NONE == rCol.GetLineAdj( );
4971 0 : pColsAttrList->add( FSNS( XML_w, XML_sep ), bHasSep ? "true" : "false" );
4972 :
4973 : // Write the element
4974 0 : m_pSerializer->startElementNS( XML_w, XML_cols, pColsAttrList );
4975 :
4976 : // Write the columns width if non-equals
4977 0 : const SwColumns & rColumns = rCol.GetColumns( );
4978 0 : if ( !bEven )
4979 : {
4980 0 : for ( sal_uInt16 n = 0; n < nCols; ++n )
4981 : {
4982 0 : FastAttributeList *pColAttrList = m_pSerializer->createAttrList();
4983 0 : sal_uInt16 nWidth = rCol.CalcPrtColWidth( n, ( sal_uInt16 ) nPageSize );
4984 : pColAttrList->add( FSNS( XML_w, XML_w ),
4985 0 : OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
4986 :
4987 0 : if ( n + 1 != nCols )
4988 : {
4989 0 : sal_uInt16 nSpacing = rColumns[n].GetRight( ) + rColumns[n + 1].GetLeft( );
4990 : pColAttrList->add( FSNS( XML_w, XML_space ),
4991 0 : OString::valueOf( sal_Int32( nSpacing ) ).getStr( ) );
4992 : }
4993 :
4994 0 : m_pSerializer->singleElementNS( XML_w, XML_col, pColAttrList );
4995 : }
4996 : }
4997 :
4998 0 : m_pSerializer->endElementNS( XML_w, XML_cols );
4999 0 : }
5000 :
5001 49 : void DocxAttributeOutput::FormatKeep( const SvxFmtKeepItem& )
5002 : {
5003 49 : m_pSerializer->singleElementNS( XML_w, XML_keepNext, FSEND );
5004 49 : }
5005 :
5006 40 : void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid )
5007 : {
5008 40 : FastAttributeList *pGridAttrList = m_pSerializer->createAttrList();
5009 :
5010 40 : OString sGridType;
5011 40 : switch ( rGrid.GetGridType( ) )
5012 : {
5013 : default:
5014 : case GRID_NONE:
5015 40 : sGridType = OString( "default" );
5016 40 : break;
5017 : case GRID_LINES_ONLY:
5018 0 : sGridType = OString( "lines" );
5019 0 : break;
5020 : case GRID_LINES_CHARS:
5021 0 : if ( rGrid.IsSnapToChars( ) )
5022 0 : sGridType = OString( "snapToChars" );
5023 : else
5024 0 : sGridType = OString( "linesAndChars" );
5025 0 : break;
5026 : }
5027 40 : pGridAttrList->add( FSNS( XML_w, XML_type ), sGridType.getStr( ) );
5028 :
5029 40 : sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
5030 : pGridAttrList->add( FSNS( XML_w, XML_linePitch ),
5031 40 : OString::valueOf( sal_Int32( nHeight ) ).getStr( ) );
5032 :
5033 : pGridAttrList->add( FSNS( XML_w, XML_charSpace ),
5034 40 : OString::valueOf( sal_Int32( GridCharacterPitch( rGrid ) ) ).getStr( ) );
5035 :
5036 40 : m_pSerializer->singleElementNS( XML_w, XML_docGrid, pGridAttrList );
5037 40 : }
5038 :
5039 98 : void DocxAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
5040 : {
5041 98 : if ( !rNumbering.IsCount( ) )
5042 97 : m_pSerializer->singleElementNS( XML_w, XML_suppressLineNumbers, FSEND );
5043 98 : }
5044 :
5045 98 : void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
5046 : {
5047 98 : OString sTextFlow;
5048 98 : bool bBiDi = false;
5049 98 : short nDir = rDirection.GetValue();
5050 :
5051 98 : if ( nDir == FRMDIR_ENVIRONMENT )
5052 7 : nDir = GetExport( ).GetDefaultFrameDirection( );
5053 :
5054 98 : switch ( nDir )
5055 : {
5056 : default:
5057 : case FRMDIR_HORI_LEFT_TOP:
5058 96 : sTextFlow = OString( "lrTb" );
5059 96 : break;
5060 : case FRMDIR_HORI_RIGHT_TOP:
5061 2 : sTextFlow = OString( "lrTb" );
5062 2 : bBiDi = true;
5063 2 : break;
5064 : case FRMDIR_VERT_TOP_LEFT: // many things but not this one
5065 : case FRMDIR_VERT_TOP_RIGHT:
5066 0 : sTextFlow = OString( "tbRl" );
5067 0 : break;
5068 : }
5069 :
5070 98 : if ( m_rExport.bOutPageDescs )
5071 : {
5072 : m_pSerializer->singleElementNS( XML_w, XML_textDirection,
5073 : FSNS( XML_w, XML_val ), sTextFlow.getStr( ),
5074 48 : FSEND );
5075 48 : if ( bBiDi )
5076 0 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
5077 : }
5078 50 : else if ( !m_rExport.bOutFlyFrmAttrs )
5079 : {
5080 50 : if ( bBiDi )
5081 2 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSNS( XML_w, XML_val ), "1", FSEND );
5082 98 : }
5083 98 : }
5084 :
5085 48 : DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML )
5086 : : m_rExport( rExport ),
5087 : m_pSerializer( pSerializer ),
5088 : m_rDrawingML( *pDrawingML ),
5089 : m_pFontsAttrList( NULL ),
5090 : m_pEastAsianLayoutAttrList( NULL ),
5091 : m_pCharLangAttrList( NULL ),
5092 : m_pSectionSpacingAttrList( NULL ),
5093 : m_pParagraphSpacingAttrList( NULL ),
5094 : m_pHyperlinkAttrList( NULL ),
5095 : m_pFlyAttrList( NULL ),
5096 : m_pFlyFillAttrList( NULL ),
5097 : m_pFlyWrapAttrList( NULL ),
5098 : m_pTextboxAttrList( NULL ),
5099 : m_pFlyFrameSize(0),
5100 0 : m_pFootnotesList( new ::docx::FootnotesList() ),
5101 0 : m_pEndnotesList( new ::docx::FootnotesList() ),
5102 : m_footnoteEndnoteRefTag( 0 ),
5103 : m_pSectionInfo( NULL ),
5104 : m_pRedlineData( NULL ),
5105 : m_nRedlineId( 0 ),
5106 : m_bOpenedSectPr( false ),
5107 : m_sFieldBkm( ),
5108 : m_nNextMarkId( 0 ),
5109 : m_bPostitStart(false),
5110 : m_bPostitEnd(false),
5111 : m_pTableWrt( NULL ),
5112 : m_bTableCellOpen( false ),
5113 : m_nTableDepth( 0 ),
5114 : m_bParagraphOpened( false ),
5115 : m_nColBreakStatus( COLBRK_NONE ),
5116 : m_pParentFrame( NULL ),
5117 : m_bTextFrameSyntax( false ),
5118 : m_closeHyperlinkInThisRun( false ),
5119 : m_closeHyperlinkInPreviousRun( false ),
5120 : m_startedHyperlink( false ),
5121 : m_postponedGraphic( NULL ),
5122 : m_postponedMath( NULL ),
5123 : pendingPlaceholder( NULL ),
5124 : m_postitFieldsMaxId( 0 ),
5125 : m_anchorId( 0 ),
5126 : m_nextFontId( 1 ),
5127 48 : m_bBtLr(false)
5128 : {
5129 48 : }
5130 :
5131 144 : DocxAttributeOutput::~DocxAttributeOutput()
5132 : {
5133 48 : delete m_pFontsAttrList, m_pFontsAttrList = NULL;
5134 48 : delete m_pEastAsianLayoutAttrList, m_pEastAsianLayoutAttrList = NULL;
5135 48 : delete m_pCharLangAttrList, m_pCharLangAttrList = NULL;
5136 48 : delete m_pSectionSpacingAttrList, m_pSectionSpacingAttrList = NULL;
5137 48 : delete m_pParagraphSpacingAttrList, m_pParagraphSpacingAttrList = NULL;
5138 48 : delete m_pHyperlinkAttrList, m_pHyperlinkAttrList = NULL;
5139 48 : delete m_pFlyAttrList, m_pFlyAttrList = NULL;
5140 48 : delete m_pTextboxAttrList, m_pTextboxAttrList = NULL;
5141 :
5142 48 : delete m_pFootnotesList, m_pFootnotesList = NULL;
5143 48 : delete m_pEndnotesList, m_pEndnotesList = NULL;
5144 :
5145 48 : delete m_pTableWrt, m_pTableWrt = NULL;
5146 48 : delete m_pParentFrame;
5147 96 : }
5148 :
5149 1057 : DocxExport& DocxAttributeOutput::GetExport()
5150 : {
5151 1057 : return m_rExport;
5152 : }
5153 :
5154 144 : bool DocxAttributeOutput::HasFootnotes() const
5155 : {
5156 144 : return !m_pFootnotesList->isEmpty();
5157 : }
5158 :
5159 144 : bool DocxAttributeOutput::HasEndnotes() const
5160 : {
5161 144 : return !m_pEndnotesList->isEmpty();
5162 : }
5163 :
5164 48 : bool DocxAttributeOutput::HasPostitFields() const
5165 : {
5166 48 : return !m_postitFields.empty();
5167 : }
5168 :
5169 1 : void DocxAttributeOutput::BulletDefinition(int nId, const Graphic& rGraphic, Size aSize)
5170 : {
5171 : m_pSerializer->startElementNS(XML_w, XML_numPicBullet,
5172 : FSNS(XML_w, XML_numPicBulletId), OString::number(nId).getStr(),
5173 1 : FSEND);
5174 :
5175 1 : OStringBuffer aStyle;
5176 : // Size is in twips, we need it in points.
5177 1 : aStyle.append("width:").append(double(aSize.Width()) / 20);
5178 1 : aStyle.append("pt;height:").append(double(aSize.Height()) / 20).append("pt");
5179 1 : m_pSerializer->startElementNS( XML_w, XML_pict, FSEND);
5180 : m_pSerializer->startElementNS( XML_v, XML_shape,
5181 : XML_style, aStyle.getStr(),
5182 : FSNS(XML_o, XML_bullet), "t",
5183 1 : FSEND);
5184 :
5185 1 : m_rDrawingML.SetFS(m_pSerializer);
5186 2 : OUString aRelId = m_rDrawingML.WriteImage(rGraphic);
5187 : m_pSerializer->singleElementNS( XML_v, XML_imagedata,
5188 : FSNS(XML_r, XML_id), OUStringToOString(aRelId, RTL_TEXTENCODING_UTF8),
5189 : FSNS(XML_o, XML_title), "",
5190 1 : FSEND);
5191 :
5192 1 : m_pSerializer->endElementNS(XML_v, XML_shape);
5193 1 : m_pSerializer->endElementNS(XML_w, XML_pict);
5194 :
5195 2 : m_pSerializer->endElementNS(XML_w, XML_numPicBullet);
5196 19 : }
5197 :
5198 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|