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 "docxhelper.hxx"
22 : #include "docxsdrexport.hxx"
23 : #include "docxexportfilter.hxx"
24 : #include "docxfootnotes.hxx"
25 : #include "writerwordglue.hxx"
26 : #include "ww8par.hxx"
27 : #include "fmtcntnt.hxx"
28 : #include "fmtftn.hxx"
29 : #include "fchrfmt.hxx"
30 : #include "tgrditem.hxx"
31 : #include "fmtruby.hxx"
32 : #include "fmtanchr.hxx"
33 : #include "breakit.hxx"
34 : #include "redline.hxx"
35 : #include "unocoll.hxx"
36 : #include "unoframe.hxx"
37 : #include "unodraw.hxx"
38 : #include "textboxhelper.hxx"
39 : #include "wrtww8.hxx"
40 :
41 : #include <comphelper/random.hxx>
42 : #include <comphelper/string.hxx>
43 : #include <comphelper/flagguard.hxx>
44 : #include <oox/token/tokens.hxx>
45 : #include <oox/export/utils.hxx>
46 : #include <oox/mathml/export.hxx>
47 : #include <oox/drawingml/drawingmltypes.hxx>
48 :
49 : #include <editeng/autokernitem.hxx>
50 : #include <editeng/unoprnms.hxx>
51 : #include <editeng/fontitem.hxx>
52 : #include <editeng/tstpitem.hxx>
53 : #include <editeng/spltitem.hxx>
54 : #include <editeng/widwitem.hxx>
55 : #include <editeng/shaditem.hxx>
56 : #include <editeng/brushitem.hxx>
57 : #include <editeng/postitem.hxx>
58 : #include <editeng/wghtitem.hxx>
59 : #include <editeng/kernitem.hxx>
60 : #include <editeng/crossedoutitem.hxx>
61 : #include <editeng/cmapitem.hxx>
62 : #include <editeng/udlnitem.hxx>
63 : #include <editeng/langitem.hxx>
64 : #include <editeng/lspcitem.hxx>
65 : #include <editeng/escapementitem.hxx>
66 : #include <editeng/fhgtitem.hxx>
67 : #include <editeng/colritem.hxx>
68 : #include <editeng/hyphenzoneitem.hxx>
69 : #include <editeng/ulspitem.hxx>
70 : #include <editeng/boxitem.hxx>
71 : #include <editeng/contouritem.hxx>
72 : #include <editeng/shdditem.hxx>
73 : #include <editeng/emphasismarkitem.hxx>
74 : #include <editeng/twolinesitem.hxx>
75 : #include <editeng/charscaleitem.hxx>
76 : #include <editeng/charrotateitem.hxx>
77 : #include <editeng/charreliefitem.hxx>
78 : #include <editeng/paravertalignitem.hxx>
79 : #include <editeng/pgrditem.hxx>
80 : #include <editeng/frmdiritem.hxx>
81 : #include <editeng/blinkitem.hxx>
82 : #include <editeng/charhiddenitem.hxx>
83 : #include <editeng/editobj.hxx>
84 : #include <svx/xfillit0.hxx>
85 : #include <svx/xflgrit.hxx>
86 : #include <svx/fmglob.hxx>
87 : #include <svx/svdouno.hxx>
88 : #include <svl/grabbagitem.hxx>
89 : #include <sfx2/sfxbasemodel.hxx>
90 : #include <tools/datetimeutils.hxx>
91 : #include <svl/whiter.hxx>
92 :
93 : #include <docufld.hxx>
94 : #include <flddropdown.hxx>
95 : #include <fmtclds.hxx>
96 : #include <fmtinfmt.hxx>
97 : #include <fmtrowsplt.hxx>
98 : #include <fmtline.hxx>
99 : #include <ftninfo.hxx>
100 : #include <htmltbl.hxx>
101 : #include <lineinfo.hxx>
102 : #include <ndgrf.hxx>
103 : #include <ndole.hxx>
104 : #include <ndtxt.hxx>
105 : #include <pagedesc.hxx>
106 : #include <paratr.hxx>
107 : #include <charatr.hxx>
108 : #include <swmodule.hxx>
109 : #include <swtable.hxx>
110 : #include <txtftn.hxx>
111 : #include <txtinet.hxx>
112 : #include <fmtautofmt.hxx>
113 : #include <docsh.hxx>
114 : #include <docary.hxx>
115 : #include <IDocumentSettingAccess.hxx>
116 : #include <IDocumentStylePoolAccess.hxx>
117 : #include <IDocumentRedlineAccess.hxx>
118 :
119 : #include <osl/file.hxx>
120 : #include <vcl/embeddedfontshelper.hxx>
121 : #include <svtools/miscopt.hxx>
122 :
123 : #include <com/sun/star/i18n/ScriptType.hpp>
124 : #include <com/sun/star/chart2/XChartDocument.hpp>
125 : #include <com/sun/star/drawing/ShadingPattern.hpp>
126 : #include <com/sun/star/text/GraphicCrop.hpp>
127 :
128 : #include <algorithm>
129 :
130 : #if OSL_DEBUG_LEVEL > 1
131 : #include <stdio.h>
132 : #endif
133 :
134 : using ::editeng::SvxBorderLine;
135 :
136 : using namespace oox;
137 : using namespace docx;
138 : using namespace sax_fastparser;
139 : using namespace nsSwDocInfoSubType;
140 : using namespace nsFieldFlags;
141 : using namespace sw::util;
142 : using namespace ::com::sun::star;
143 : using namespace ::com::sun::star::drawing;
144 :
145 2 : class FFDataWriterHelper
146 : {
147 : ::sax_fastparser::FSHelperPtr m_pSerializer;
148 2 : void writeCommonStart( const OUString& rName )
149 : {
150 2 : m_pSerializer->startElementNS( XML_w, XML_ffData, FSEND );
151 : m_pSerializer->singleElementNS( XML_w, XML_name,
152 : FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
153 2 : FSEND );
154 2 : m_pSerializer->singleElementNS( XML_w, XML_enabled, FSEND );
155 : m_pSerializer->singleElementNS( XML_w, XML_calcOnExit,
156 : FSNS( XML_w, XML_val ),
157 2 : "0", FSEND );
158 2 : }
159 2 : void writeFinish()
160 : {
161 2 : m_pSerializer->endElementNS( XML_w, XML_ffData );
162 2 : }
163 : public:
164 2 : FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr pSerializer ) : m_pSerializer( pSerializer ){}
165 2 : void WriteFormCheckbox( const OUString& rName, const OUString& rDefault, bool bChecked )
166 : {
167 2 : writeCommonStart( rName );
168 : // Checkbox specific bits
169 2 : m_pSerializer->startElementNS( XML_w, XML_checkBox, FSEND );
170 : // currently hardcoding autosize
171 : // #TODO check if this defaulted
172 2 : m_pSerializer->startElementNS( XML_w, XML_sizeAuto, FSEND );
173 2 : m_pSerializer->endElementNS( XML_w, XML_sizeAuto );
174 2 : if ( !rDefault.isEmpty() )
175 : {
176 : m_pSerializer->singleElementNS( XML_w, XML_default,
177 : FSNS( XML_w, XML_val ),
178 0 : OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
179 : }
180 2 : if ( bChecked )
181 0 : m_pSerializer->singleElementNS( XML_w, XML_checked, FSEND );
182 2 : m_pSerializer->endElementNS( XML_w, XML_checkBox );
183 2 : writeFinish();
184 2 : }
185 0 : void WriteFormText( const OUString& rName, const OUString& rDefault )
186 : {
187 0 : writeCommonStart( rName );
188 0 : if ( !rDefault.isEmpty() )
189 : {
190 0 : m_pSerializer->startElementNS( XML_w, XML_textInput, FSEND );
191 : m_pSerializer->singleElementNS( XML_w, XML_default,
192 : FSNS( XML_w, XML_val ),
193 0 : OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
194 0 : m_pSerializer->endElementNS( XML_w, XML_textInput );
195 : }
196 0 : writeFinish();
197 0 : }
198 : };
199 :
200 : class FieldMarkParamsHelper
201 : {
202 : const sw::mark::IFieldmark& mrFieldmark;
203 : public:
204 2 : FieldMarkParamsHelper( const sw::mark::IFieldmark& rFieldmark ) : mrFieldmark( rFieldmark ) {}
205 0 : OUString getName() { return mrFieldmark.GetName(); }
206 : template < typename T >
207 2 : bool extractParam( const OUString& rKey, T& rResult )
208 : {
209 2 : bool bResult = false;
210 2 : if ( mrFieldmark.GetParameters() )
211 : {
212 2 : sw::mark::IFieldmark::parameter_map_t::const_iterator it = mrFieldmark.GetParameters()->find( rKey );
213 2 : if ( it != mrFieldmark.GetParameters()->end() )
214 0 : bResult = ( it->second >>= rResult );
215 : }
216 2 : return bResult;
217 : }
218 : };
219 18080 : void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
220 : {
221 18080 : if (bIsRTL)
222 14 : m_pSerializer->singleElementNS( XML_w, XML_rtl, FSNS( XML_w, XML_val ), "true", FSEND );
223 18080 : }
224 :
225 : /// Are multiple paragraphs disallowed inside this type of SDT?
226 310 : static bool lcl_isOnelinerSdt(const OUString& rName)
227 : {
228 310 : return rName == "Title" || rName == "Subtitle" || rName == "Company";
229 : }
230 :
231 13046 : void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
232 : {
233 13046 : if ( m_nColBreakStatus == COLBRK_POSTPONE )
234 94 : m_nColBreakStatus = COLBRK_WRITE;
235 :
236 : // Output table/table row/table cell starts if needed
237 13046 : if ( pTextNodeInfo.get() )
238 : {
239 3360 : sal_uInt32 nRow = pTextNodeInfo->getRow();
240 3360 : sal_uInt32 nCell = pTextNodeInfo->getCell();
241 :
242 : // New cell/row?
243 3360 : if ( m_tableReference->m_nTableDepth > 0 && !m_tableReference->m_bTableCellOpen )
244 : {
245 2738 : ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_tableReference->m_nTableDepth ) );
246 2738 : if ( pDeepInner->getCell() == 0 )
247 1018 : StartTableRow( pDeepInner );
248 :
249 2738 : StartTableCell( pDeepInner );
250 : }
251 :
252 3360 : if ( nRow == 0 && nCell == 0 )
253 : {
254 : // Do we have to start the table?
255 : // [If we are at the right depth already, it means that we
256 : // continue the table cell]
257 514 : sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
258 :
259 514 : if ( nCurrentDepth > m_tableReference->m_nTableDepth )
260 : {
261 : // Start all the tables that begin here
262 522 : for ( sal_uInt32 nDepth = m_tableReference->m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
263 : {
264 264 : ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
265 :
266 264 : if (m_tableReference->m_pOldTablepInner && m_tableReference->m_pOldTablepInner->getTable() == pInner->getTable() && nCurrentDepth > 1 && nDepth != 1)
267 : {
268 0 : m_tableReference->m_pOldTablepInner = pInner;
269 0 : break;
270 : }
271 : else
272 : {
273 264 : StartTable( pInner );
274 264 : StartTableRow( pInner );
275 264 : StartTableCell( pInner );
276 264 : m_tableReference->m_pOldTablepInner = pInner;
277 : }
278 264 : }
279 :
280 258 : m_tableReference->m_nTableDepth = nCurrentDepth;
281 : }
282 : }
283 : }
284 :
285 : // Look up the "sdt end before this paragraph" property early, when it
286 : // would normally arrive, it would be too late (would be after the
287 : // paragraph start has been written).
288 13046 : bool bEndParaSdt = false;
289 13046 : SwTxtNode* pTxtNode = m_rExport.pCurPam->GetNode().GetTxtNode();
290 13046 : if (pTxtNode && pTxtNode->GetpSwAttrSet())
291 : {
292 8864 : const SfxItemSet* pSet = pTxtNode->GetpSwAttrSet();
293 8864 : if (const SfxPoolItem* pItem = pSet->GetItem(RES_PARATR_GRABBAG))
294 : {
295 8864 : const SfxGrabBagItem& rParaGrabBag = static_cast<const SfxGrabBagItem&>(*pItem);
296 8864 : const std::map<OUString, com::sun::star::uno::Any>& rMap = rParaGrabBag.GetGrabBag();
297 8864 : bEndParaSdt = m_bStartedParaSdt && rMap.find("ParaSdtEndBefore") != rMap.end();
298 : }
299 : }
300 : // TODO also avoid multiline paragarphs in those SDT types for shape text
301 13046 : bool bOneliner = m_bStartedParaSdt && !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen() && lcl_isOnelinerSdt(m_aStartedParagraphSdtPrAlias);
302 13046 : if (bEndParaSdt || (m_bStartedParaSdt && m_bHadSectPr) || bOneliner)
303 : {
304 : // This is the common case: "close sdt before the current paragraph" was requrested by the next paragraph.
305 80 : EndSdtBlock();
306 80 : bEndParaSdt = false;
307 80 : m_bStartedParaSdt = false;
308 80 : m_aStartedParagraphSdtPrAlias = "";
309 : }
310 13046 : m_bHadSectPr = false;
311 :
312 : // this mark is used to be able to enclose the paragraph inside a sdr tag.
313 : // We will only know if we have to do that later.
314 13046 : m_pSerializer->mark();
315 :
316 13046 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
317 :
318 : // postpone the output of the run (we get it before the paragraph
319 : // properties, but must write it after them)
320 13046 : m_pSerializer->mark();
321 :
322 : // no section break in this paragraph yet; can be set in SectionBreak()
323 13046 : m_pSectionInfo.reset();
324 :
325 13046 : m_bParagraphOpened = true;
326 13046 : m_bIsFirstParagraph = false;
327 13046 : }
328 :
329 306 : static void lcl_deleteAndResetTheLists( ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs, OUString& rSdtPrAlias)
330 : {
331 306 : if( pSdtPrTokenChildren )
332 : {
333 0 : delete pSdtPrTokenChildren ;
334 0 : pSdtPrTokenChildren = NULL;
335 : }
336 306 : if( pSdtPrDataBindingAttrs )
337 : {
338 4 : delete pSdtPrDataBindingAttrs;
339 4 : pSdtPrDataBindingAttrs = NULL;
340 : }
341 306 : if (!rSdtPrAlias.isEmpty())
342 4 : rSdtPrAlias = "";
343 306 : }
344 :
345 10 : void DocxAttributeOutput::PopulateFrameProperties(const SwFrmFmt* pFrmFmt, const Size& rSize)
346 : {
347 :
348 10 : sax_fastparser::FastAttributeList* attrList = m_pSerializer->createAttrList();
349 :
350 10 : awt::Point aPos(pFrmFmt->GetHoriOrient().GetPos(), pFrmFmt->GetVertOrient().GetPos());
351 :
352 10 : attrList->add( FSNS( XML_w, XML_w), OString::number(rSize.Width()));
353 10 : attrList->add( FSNS( XML_w, XML_h), OString::number(rSize.Height()));
354 :
355 10 : attrList->add( FSNS( XML_w, XML_x), OString::number(aPos.X));
356 10 : attrList->add( FSNS( XML_w, XML_y), OString::number(aPos.Y));
357 :
358 : const char* relativeFromH;
359 : const char* relativeFromV;
360 10 : switch (pFrmFmt->GetVertOrient().GetRelationOrient())
361 : {
362 : case text::RelOrientation::PAGE_PRINT_AREA:
363 0 : relativeFromV = "margin";
364 0 : break;
365 : case text::RelOrientation::PAGE_FRAME:
366 10 : relativeFromV = "page";
367 10 : break;
368 : case text::RelOrientation::FRAME:
369 : case text::RelOrientation::TEXT_LINE:
370 : default:
371 0 : relativeFromV = "text";
372 0 : break;
373 : }
374 :
375 10 : switch (pFrmFmt->GetHoriOrient().GetRelationOrient())
376 : {
377 : case text::RelOrientation::PAGE_PRINT_AREA:
378 0 : relativeFromH = "margin";
379 0 : break;
380 : case text::RelOrientation::PAGE_FRAME:
381 10 : relativeFromH = "page";
382 10 : break;
383 : case text::RelOrientation::CHAR:
384 : case text::RelOrientation::PAGE_RIGHT:
385 : case text::RelOrientation::FRAME:
386 : default:
387 0 : relativeFromH = "text";
388 0 : break;
389 : }
390 :
391 10 : switch (pFrmFmt->GetSurround().GetValue())
392 : {
393 : case SURROUND_NONE:
394 10 : attrList->add( FSNS( XML_w, XML_wrap), "none");
395 10 : break;
396 : case SURROUND_THROUGHT:
397 0 : attrList->add( FSNS( XML_w, XML_wrap), "through");
398 0 : break;
399 : case SURROUND_PARALLEL:
400 0 : attrList->add( FSNS( XML_w, XML_wrap), "notBeside");
401 0 : break;
402 : case SURROUND_IDEAL:
403 : default:
404 0 : attrList->add( FSNS( XML_w, XML_wrap), "auto");
405 0 : break;
406 : }
407 10 : attrList->add( FSNS( XML_w, XML_vAnchor), relativeFromV);
408 10 : attrList->add( FSNS( XML_w, XML_hAnchor), relativeFromH);
409 10 : attrList->add( FSNS( XML_w, XML_hRule), "exact");
410 :
411 10 : sax_fastparser::XFastAttributeListRef xAttrList(attrList);
412 10 : m_pSerializer->singleElementNS( XML_w, XML_framePr, xAttrList );
413 10 : }
414 :
415 132 : bool DocxAttributeOutput::TextBoxIsFramePr(const SwFrmFmt& rFrmFmt)
416 : {
417 132 : uno::Reference< drawing::XShape > xShape;
418 132 : const SdrObject* pSdrObj = rFrmFmt.FindRealSdrObject();
419 132 : if (pSdrObj)
420 118 : xShape = uno::Reference< drawing::XShape >(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY);
421 264 : uno::Reference< beans::XPropertySet > xPropertySet(xShape, uno::UNO_QUERY);
422 264 : uno::Reference< beans::XPropertySetInfo > xPropSetInfo;
423 132 : if (xPropertySet.is())
424 118 : xPropSetInfo = xPropertySet->getPropertySetInfo();
425 264 : uno::Any aFrameProperties ;
426 132 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
427 : {
428 118 : uno::Sequence< beans::PropertyValue > propList;
429 118 : xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= propList;
430 174 : for (sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp)
431 : {
432 84 : OUString propName = propList[nProp].Name;
433 84 : if (propName == "ParaFrameProperties")
434 : {
435 28 : aFrameProperties = propList[nProp].Value ;
436 28 : break;
437 : }
438 174 : }
439 : }
440 132 : bool bFrameProperties = false;
441 132 : aFrameProperties >>= bFrameProperties;
442 264 : return bFrameProperties;
443 : }
444 :
445 13046 : void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
446 : {
447 : // write the paragraph properties + the run, already in the correct order
448 13046 : m_pSerializer->mergeTopMarks();
449 13046 : std::vector< boost::shared_ptr <sw::Frame> > aFramePrTextbox;
450 : // Write the anchored frame if any
451 : // Word can't handle nested text boxes, so write them on the same level.
452 13046 : ++m_nTextFrameLevel;
453 13046 : if( m_nTextFrameLevel == 1 && !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen() )
454 : {
455 11252 : comphelper::FlagRestorationGuard aStartedParaSdtGuard(m_bStartedParaSdt, false);
456 :
457 : assert(!m_postponedCustomShape);
458 11252 : m_postponedCustomShape = new std::list< PostponedDrawing >;
459 11374 : for (size_t nIndex = 0; nIndex < m_aFramesOfParagraph.size(); ++nIndex)
460 : {
461 122 : m_bParagraphFrameOpen = true;
462 122 : sw::Frame aFrame = m_aFramesOfParagraph[nIndex];
463 122 : const SwFrmFmt& rFrmFmt = aFrame.GetFrmFmt();
464 :
465 122 : if (!TextBoxIsFramePr(rFrmFmt) || m_bWritingHeaderFooter)
466 : {
467 120 : if (m_bStartedCharSdt)
468 : {
469 : // Run-level SDT still open? Close it befor AlternateContent.
470 2 : EndSdtBlock();
471 2 : m_bStartedCharSdt = false;
472 : }
473 120 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
474 120 : m_pSerializer->startElementNS(XML_mc, XML_AlternateContent, FSEND);
475 : m_pSerializer->startElementNS(XML_mc, XML_Choice,
476 : XML_Requires, "wps",
477 120 : FSEND);
478 : /**
479 : This is to avoid AltenateContent within another AlternateContent.
480 : So when Choice is Open, only write the DML Drawing instead of both DML
481 : and VML Drawing in another AlternateContent.
482 : **/
483 120 : SetAlternateContentChoiceOpen( true );
484 : /** Save the table info's before writing the shape
485 : as there might be a new table that might get
486 : spawned from within the VML & DML block and alter
487 : the contents.
488 : */
489 120 : ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_rExport.mpTableInfo;
490 : //Reset the table infos after saving.
491 120 : m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
492 :
493 : /** FDO#71834 :
494 : Save the table reference attributes before calling WriteDMLTextFrame,
495 : otherwise the StartParagraph function will use the previous existing
496 : table reference attributes since the variable is being shared.
497 : */
498 240 : DocxTableExportContext aDMLTableExportContext;
499 120 : pushToTableExportContext(aDMLTableExportContext);
500 120 : m_rExport.SdrExporter().writeDMLTextFrame(&aFrame, m_anchorId++);
501 120 : popFromTableExportContext(aDMLTableExportContext);
502 120 : m_pSerializer->endElementNS(XML_mc, XML_Choice);
503 120 : SetAlternateContentChoiceOpen( false );
504 :
505 : // Reset table infos, otherwise the depth of the cells will be incorrect,
506 : // in case the text frame had table(s) and we try to export the
507 : // same table second time.
508 120 : m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
509 : //reset the tableReference.
510 :
511 120 : m_pSerializer->startElementNS(XML_mc, XML_Fallback, FSEND);
512 240 : DocxTableExportContext aVMLTableExportContext;
513 120 : pushToTableExportContext(aVMLTableExportContext);
514 120 : m_rExport.SdrExporter().writeVMLTextFrame(&aFrame);
515 120 : popFromTableExportContext(aVMLTableExportContext);
516 120 : m_rExport.mpTableInfo = pOldTableInfo;
517 :
518 120 : m_pSerializer->endElementNS(XML_mc, XML_Fallback);
519 120 : m_pSerializer->endElementNS(XML_mc, XML_AlternateContent);
520 120 : m_pSerializer->endElementNS( XML_w, XML_r );
521 240 : m_bParagraphFrameOpen = false;
522 : }
523 : else
524 : {
525 2 : ::boost::shared_ptr<sw::Frame> pFramePr;
526 2 : pFramePr.reset(new sw::Frame(aFrame));
527 2 : aFramePrTextbox.push_back(pFramePr);
528 : }
529 122 : }
530 11252 : if (!m_postponedCustomShape->empty())
531 : {
532 10 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
533 10 : WritePostponedCustomShape();
534 10 : m_pSerializer->endElementNS( XML_w, XML_r );
535 : }
536 11252 : delete m_postponedCustomShape;
537 11252 : m_postponedCustomShape = NULL;
538 :
539 11252 : m_aFramesOfParagraph.clear();
540 : }
541 :
542 13046 : --m_nTextFrameLevel;
543 :
544 : /* If m_nHyperLinkCount > 0 that means hyperlink tag is not yet colsed.
545 : * This is due to nested hyperlink tags. So close it before end of paragraph.
546 : */
547 13046 : if(m_nHyperLinkCount > 0)
548 : {
549 4 : for(sal_Int32 nHyperLinkToClose = 0; nHyperLinkToClose < m_nHyperLinkCount; ++nHyperLinkToClose)
550 2 : m_pSerializer->endElementNS( XML_w, XML_hyperlink );
551 2 : m_nHyperLinkCount = 0;
552 : }
553 :
554 13046 : if (m_bStartedCharSdt)
555 : {
556 : // Run-level SDT still open? Close it now.
557 36 : EndSdtBlock();
558 36 : m_bStartedCharSdt = false;
559 : }
560 :
561 13046 : m_pSerializer->endElementNS( XML_w, XML_p );
562 : // on export sdt blocks are never nested ATM
563 13046 : if( !m_bAnchorLinkedToNode && !m_bStartedParaSdt )
564 12808 : WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrTokenAttributes, m_pParagraphSdtPrDataBindingAttrs, m_aParagraphSdtPrAlias, /*bPara=*/true );
565 : else
566 : {
567 : //These should be written out to the actual Node and not to the anchor.
568 : //Clear them as they will be repopulated when the node is processed.
569 238 : m_nParagraphSdtPrToken = 0;
570 238 : m_bParagraphSdtHasId = false;
571 238 : lcl_deleteAndResetTheLists( m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs, m_aParagraphSdtPrAlias );
572 : }
573 :
574 : //sdtcontent is written so Set m_bParagraphHasDrawing to false
575 13046 : m_rExport.SdrExporter().setParagraphHasDrawing( false );
576 13046 : m_bRunTextIsOn = false;
577 13046 : if(aFramePrTextbox.empty())
578 13044 : m_pSerializer->mergeTopMarks();
579 : else
580 2 : m_pSerializer->mergeTopMarks(sax_fastparser::MERGE_MARKS_IGNORE );
581 :
582 : // Write framePr
583 13046 : if(!aFramePrTextbox.empty())
584 : {
585 2 : ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_rExport.mpTableInfo;
586 4 : for (std::vector< boost::shared_ptr<sw::Frame> > ::iterator it = aFramePrTextbox.begin() ; it != aFramePrTextbox.end(); ++it)
587 : {
588 2 : m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
589 2 : m_pCurrentFrame = it->get();
590 2 : m_rExport.SdrExporter().writeOnlyTextOfFrame(it->get());
591 2 : m_pCurrentFrame = NULL;
592 : }
593 2 : m_rExport.mpTableInfo = pOldTableInfo;
594 2 : aFramePrTextbox.clear();
595 : }
596 : // Check for end of cell, rows, tables here
597 13046 : FinishTableRowCell( pTextNodeInfoInner );
598 :
599 13046 : if( !m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen() )
600 11286 : m_bParagraphOpened = false;
601 :
602 13046 : }
603 :
604 30898 : void DocxAttributeOutput::WriteSdtBlock( sal_Int32& nSdtPrToken,
605 : ::sax_fastparser::FastAttributeList*& pSdtPrTokenChildren,
606 : ::sax_fastparser::FastAttributeList*& pSdtPrTokenAttributes,
607 : ::sax_fastparser::FastAttributeList*& pSdtPrDataBindingAttrs,
608 : OUString& rSdtPrAlias,
609 : bool bPara )
610 : {
611 30898 : if( nSdtPrToken > 0 || pSdtPrDataBindingAttrs )
612 : {
613 : // sdt start mark
614 234 : m_pSerializer->mark();
615 :
616 234 : m_pSerializer->startElementNS( XML_w, XML_sdt, FSEND );
617 :
618 : // output sdt properties
619 234 : m_pSerializer->startElementNS( XML_w, XML_sdtPr, FSEND );
620 :
621 234 : if( nSdtPrToken > 0 && pSdtPrTokenChildren )
622 : {
623 108 : if (!pSdtPrTokenAttributes)
624 100 : m_pSerializer->startElement( nSdtPrToken, FSEND );
625 : else
626 : {
627 8 : XFastAttributeListRef xAttrList(pSdtPrTokenAttributes);
628 8 : m_pSerializer->startElement(nSdtPrToken, xAttrList);
629 8 : pSdtPrTokenAttributes = 0;
630 : }
631 :
632 108 : if (nSdtPrToken == FSNS( XML_w, XML_date ) || nSdtPrToken == FSNS( XML_w, XML_docPartObj ) || nSdtPrToken == FSNS( XML_w, XML_docPartList ) || nSdtPrToken == FSNS( XML_w14, XML_checkbox )) {
633 106 : uno::Sequence<xml::FastAttribute> aChildren = pSdtPrTokenChildren->getFastAttributes();
634 346 : for( sal_Int32 i=0; i < aChildren.getLength(); ++i )
635 240 : m_pSerializer->singleElement( aChildren[i].Token,
636 : FSNS(XML_w, XML_val),
637 240 : rtl::OUStringToOString( aChildren[i].Value, RTL_TEXTENCODING_UTF8 ).getStr(),
638 586 : FSEND );
639 : }
640 :
641 108 : m_pSerializer->endElement( nSdtPrToken );
642 : }
643 126 : else if( (nSdtPrToken > 0) && nSdtPrToken != FSNS( XML_w, XML_id ) && !(m_bRunTextIsOn && m_rExport.SdrExporter().IsParagraphHasDrawing()))
644 : {
645 92 : if (!pSdtPrTokenAttributes)
646 92 : m_pSerializer->singleElement( nSdtPrToken, FSEND );
647 : else
648 : {
649 0 : XFastAttributeListRef xAttrList(pSdtPrTokenAttributes);
650 0 : m_pSerializer->singleElement(nSdtPrToken, xAttrList);
651 0 : pSdtPrTokenAttributes = 0;
652 : }
653 : }
654 :
655 234 : if( nSdtPrToken == FSNS( XML_w, XML_id ) || ( bPara && m_bParagraphSdtHasId ) )
656 : //Word won't open a document with an empty id tag, we fill it with a random number
657 : m_pSerializer->singleElementNS(XML_w, XML_id, FSNS(XML_w, XML_val),
658 : OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max())),
659 184 : FSEND);
660 :
661 234 : if(( pSdtPrDataBindingAttrs ) && !m_rExport.SdrExporter().IsParagraphHasDrawing())
662 : {
663 56 : XFastAttributeListRef xAttrList( pSdtPrDataBindingAttrs );
664 56 : m_pSerializer->singleElementNS( XML_w, XML_dataBinding, xAttrList );
665 : }
666 :
667 234 : if (!rSdtPrAlias.isEmpty())
668 : m_pSerializer->singleElementNS(XML_w, XML_alias, FSNS(XML_w, XML_val),
669 : OUStringToOString(rSdtPrAlias, RTL_TEXTENCODING_UTF8).getStr(),
670 72 : FSEND);
671 :
672 234 : m_pSerializer->endElementNS( XML_w, XML_sdtPr );
673 :
674 : // sdt contents start tag
675 234 : m_pSerializer->startElementNS( XML_w, XML_sdtContent, FSEND );
676 :
677 : // prepend the tags since the sdt start mark before the paragraph
678 234 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
679 :
680 : // write the ending tags after the paragraph
681 234 : if (bPara)
682 : {
683 164 : m_bStartedParaSdt = true;
684 164 : if (m_tableReference->m_bTableCellOpen)
685 54 : m_tableReference->m_bTableCellParaSdtOpen = true;
686 164 : if (m_rExport.SdrExporter().IsDMLAndVMLDrawingOpen())
687 4 : m_rExport.SdrExporter().setParagraphSdtOpen(true);
688 : }
689 : else
690 : // Support multiple runs inside a run-evel SDT: don't close the SDT block yet.
691 70 : m_bStartedCharSdt = true;
692 :
693 : // clear sdt status
694 234 : nSdtPrToken = 0;
695 234 : delete pSdtPrTokenChildren; pSdtPrTokenChildren = NULL;
696 234 : if( pSdtPrDataBindingAttrs )
697 : {
698 : // do not delete yet; it's in xAttrList inside the parser
699 70 : pSdtPrDataBindingAttrs = NULL;
700 : }
701 234 : rSdtPrAlias = "";
702 : }
703 30898 : }
704 :
705 234 : void DocxAttributeOutput::EndSdtBlock()
706 : {
707 234 : m_pSerializer->endElementNS( XML_w, XML_sdtContent );
708 234 : m_pSerializer->endElementNS( XML_w, XML_sdt );
709 234 : }
710 :
711 20368 : void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
712 : {
713 20368 : if ( pInner.get() )
714 : {
715 : // Where are we in the table
716 10682 : sal_uInt32 nRow = pInner->getRow( );
717 :
718 10682 : const SwTable *pTable = pInner->getTable( );
719 10682 : const SwTableLines& rLines = pTable->GetTabLines( );
720 10682 : sal_uInt16 nLinesCount = rLines.size( );
721 : // HACK
722 : // msoffice seems to have an internal limitation of 63 columns for tables
723 : // and refuses to load .docx with more, even though the spec seems to allow that;
724 : // so simply if there are more columns, don't close the last one msoffice will handle
725 : // and merge the contents of the remaining ones into it (since we don't close the cell
726 : // here, following ones will not be opened)
727 10682 : bool limitWorkaround = ( pInner->getCell() >= 62 && !pInner->isEndOfLine());
728 :
729 10682 : if ( pInner->isEndOfCell() && !limitWorkaround )
730 : {
731 3002 : if ( bForceEmptyParagraph )
732 0 : m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
733 :
734 3002 : EndTableCell();
735 : }
736 :
737 : // This is a line end
738 10682 : if ( pInner->isEndOfLine() )
739 1282 : EndTableRow();
740 :
741 : // This is the end of the table
742 10682 : if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
743 264 : EndTable();
744 : }
745 20368 : }
746 :
747 0 : void DocxAttributeOutput::EmptyParagraph()
748 : {
749 0 : m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
750 0 : }
751 :
752 12482 : void DocxAttributeOutput::SectionBreaks(const SwTxtNode& rNode)
753 : {
754 : // output page/section breaks
755 : // Writer can have them at the beginning of a paragraph, or at the end, but
756 : // in docx, we have to output them in the paragraph properties of the last
757 : // paragraph in a section. To get it right, we have to switch to the next
758 : // paragraph, and detect the section breaks there.
759 12482 : SwNodeIndex aNextIndex( rNode, 1 );
760 12482 : if ( aNextIndex.GetNode().IsTxtNode() )
761 : {
762 7330 : const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
763 7330 : m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode, m_tableReference->m_bTableCellOpen, pTxtNode->GetTxt().isEmpty() );
764 : }
765 5152 : else if ( aNextIndex.GetNode().IsTableNode() )
766 : {
767 84 : const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
768 84 : const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
769 84 : m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
770 12482 : }
771 12482 : }
772 :
773 13028 : void DocxAttributeOutput::StartParagraphProperties()
774 : {
775 13028 : m_pSerializer->mark( );
776 :
777 13028 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
778 :
779 : // and output the section break now (if it appeared)
780 13028 : if ( m_pSectionInfo && (!m_setFootnote))
781 : {
782 44 : m_rExport.SectionProperties( *m_pSectionInfo );
783 44 : m_pSectionInfo.reset();
784 : }
785 :
786 13028 : InitCollectedParagraphProperties();
787 13028 : }
788 :
789 26922 : void DocxAttributeOutput::InitCollectedParagraphProperties()
790 : {
791 26922 : m_pParagraphSpacingAttrList = NULL;
792 :
793 : // Write the elements in the spec order
794 : static const sal_Int32 aOrder[] =
795 : {
796 : FSNS( XML_w, XML_pStyle ),
797 : FSNS( XML_w, XML_keepNext ),
798 : FSNS( XML_w, XML_keepLines ),
799 : FSNS( XML_w, XML_pageBreakBefore ),
800 : FSNS( XML_w, XML_framePr ),
801 : FSNS( XML_w, XML_widowControl ),
802 : FSNS( XML_w, XML_numPr ),
803 : FSNS( XML_w, XML_suppressLineNumbers ),
804 : FSNS( XML_w, XML_pBdr ),
805 : FSNS( XML_w, XML_shd ),
806 : FSNS( XML_w, XML_tabs ),
807 : FSNS( XML_w, XML_suppressAutoHyphens ),
808 : FSNS( XML_w, XML_kinsoku ),
809 : FSNS( XML_w, XML_wordWrap ),
810 : FSNS( XML_w, XML_overflowPunct ),
811 : FSNS( XML_w, XML_topLinePunct ),
812 : FSNS( XML_w, XML_autoSpaceDE ),
813 : FSNS( XML_w, XML_autoSpaceDN ),
814 : FSNS( XML_w, XML_bidi ),
815 : FSNS( XML_w, XML_adjustRightInd ),
816 : FSNS( XML_w, XML_snapToGrid ),
817 : FSNS( XML_w, XML_spacing ),
818 : FSNS( XML_w, XML_ind ),
819 : FSNS( XML_w, XML_contextualSpacing ),
820 : FSNS( XML_w, XML_mirrorIndents ),
821 : FSNS( XML_w, XML_suppressOverlap ),
822 : FSNS( XML_w, XML_jc ),
823 : FSNS( XML_w, XML_textDirection ),
824 : FSNS( XML_w, XML_textAlignment ),
825 : FSNS( XML_w, XML_textboxTightWrap ),
826 : FSNS( XML_w, XML_outlineLvl ),
827 : FSNS( XML_w, XML_divId ),
828 : FSNS( XML_w, XML_cnfStyle ),
829 : FSNS( XML_w, XML_rPr ),
830 : FSNS( XML_w, XML_sectPr ),
831 : FSNS( XML_w, XML_pPrChange )
832 : };
833 :
834 : // postpone the output so that we can later [in EndParagraphProperties()]
835 : // prepend the properties before the run
836 26922 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
837 26922 : uno::Sequence< sal_Int32 > aSeqOrder( len );
838 996114 : for ( sal_Int32 i = 0; i < len; i++ )
839 969192 : aSeqOrder[i] = aOrder[i];
840 :
841 26922 : m_pSerializer->mark( aSeqOrder );
842 26922 : }
843 :
844 26948 : void DocxAttributeOutput::WriteCollectedParagraphProperties()
845 : {
846 26948 : if ( m_rExport.SdrExporter().getFlyAttrList() )
847 : {
848 0 : XFastAttributeListRef xAttrList( m_rExport.SdrExporter().getFlyAttrList() );
849 0 : m_rExport.SdrExporter().setFlyAttrList(NULL);
850 :
851 0 : m_pSerializer->singleElementNS( XML_w, XML_framePr, xAttrList );
852 : }
853 :
854 26948 : if ( m_pParagraphSpacingAttrList )
855 : {
856 12372 : XFastAttributeListRef xAttrList( m_pParagraphSpacingAttrList );
857 12372 : m_pParagraphSpacingAttrList = NULL;
858 :
859 12372 : m_pSerializer->singleElementNS( XML_w, XML_spacing, xAttrList );
860 : }
861 :
862 26948 : if ( m_pBackgroundAttrList )
863 : {
864 172 : XFastAttributeListRef xAttrList( m_pBackgroundAttrList );
865 172 : m_pBackgroundAttrList = NULL;
866 :
867 172 : m_pSerializer->singleElementNS( XML_w, XML_shd, xAttrList );
868 : }
869 26948 : }
870 :
871 : /// Outputs an item set, that contains the formatting of the paragraph marker.
872 17260 : void lcl_writeParagraphMarkerProperties(DocxAttributeOutput& rAttributeOutput, const SfxItemSet& rParagraphMarkerProperties)
873 : {
874 17260 : SfxWhichIter aIter(rParagraphMarkerProperties);
875 17260 : sal_uInt16 nWhichId = aIter.FirstWhich();
876 17260 : const SfxPoolItem* pItem = 0;
877 : // Did we already produce a <w:sz> element?
878 17260 : bool bFontSizeWritten = false;
879 1260576 : while (nWhichId)
880 : {
881 1226056 : if (rParagraphMarkerProperties.GetItemState(nWhichId, true, &pItem) == SfxItemState::SET)
882 : {
883 35226 : if (isCHRATR(nWhichId) || nWhichId == RES_TXTATR_CHARFMT)
884 : {
885 : // Will this item produce a <w:sz> element?
886 28330 : bool bFontSizeItem = nWhichId == RES_CHRATR_FONTSIZE || nWhichId == RES_CHRATR_CJK_FONTSIZE;
887 28330 : if (!bFontSizeWritten || !bFontSizeItem)
888 25230 : rAttributeOutput.OutputItem(*pItem);
889 28330 : if (bFontSizeItem)
890 6204 : bFontSizeWritten = true;
891 : }
892 6896 : else if (nWhichId == RES_TXTATR_AUTOFMT)
893 : {
894 4232 : const SwFmtAutoFmt* pAutoFmt = static_cast<const SwFmtAutoFmt*>(pItem);
895 4232 : lcl_writeParagraphMarkerProperties(rAttributeOutput, *pAutoFmt->GetStyleHandle());
896 : }
897 : }
898 1226056 : nWhichId = aIter.NextWhich();
899 17260 : }
900 17260 : }
901 :
902 13028 : void DocxAttributeOutput::EndParagraphProperties(const SfxItemSet& rParagraphMarkerProperties, const SwRedlineData* pRedlineData, const SwRedlineData* pRedlineParagraphMarkerDeleted, const SwRedlineData* pRedlineParagraphMarkerInserted)
903 : {
904 : // Call the 'Redline' function. This will add redline (change-tracking) information that regards to paragraph properties.
905 : // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
906 :
907 : // If there is RedlineData present, call WriteCollectedParagraphProperties() for writting pPr before calling Redline().
908 : // As there will be another pPr for redline and LO might mix both.
909 13028 : if(pRedlineData)
910 14 : WriteCollectedParagraphProperties();
911 13028 : Redline( pRedlineData );
912 :
913 13028 : WriteCollectedParagraphProperties();
914 :
915 : // Merge the marks for the ordered elements
916 13028 : m_pSerializer->mergeTopMarks( );
917 :
918 : // Write 'Paragraph Mark' properties
919 13028 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
920 : // mark() before paragraph mark properties child elements.
921 13028 : InitCollectedRunProperties();
922 :
923 : // The 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList' are used to hold information
924 : // that should be collected by different properties in the core, and are all flushed together
925 : // to the DOCX when the function 'WriteCollectedRunProperties' gets called.
926 : // So we need to store the current status of these lists, so that we can revert back to them when
927 : // we are done exporting the redline attributes.
928 13028 : ::sax_fastparser::FastAttributeList *pFontsAttrList_Original = m_pFontsAttrList;
929 13028 : ::sax_fastparser::FastAttributeList *pEastAsianLayoutAttrList_Original = m_pEastAsianLayoutAttrList;
930 13028 : ::sax_fastparser::FastAttributeList *pCharLangAttrList_Original = m_pCharLangAttrList;
931 13028 : m_pFontsAttrList = NULL;
932 13028 : m_pEastAsianLayoutAttrList = NULL;
933 13028 : m_pCharLangAttrList = NULL;
934 :
935 13028 : lcl_writeParagraphMarkerProperties(*this, rParagraphMarkerProperties);
936 :
937 : // Write the collected run properties that are stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
938 13028 : WriteCollectedRunProperties();
939 :
940 : // Revert back the original values that were stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
941 13028 : m_pFontsAttrList = pFontsAttrList_Original;
942 13028 : m_pEastAsianLayoutAttrList = pEastAsianLayoutAttrList_Original;
943 13028 : m_pCharLangAttrList = pCharLangAttrList_Original;
944 :
945 13028 : if ( pRedlineParagraphMarkerDeleted )
946 : {
947 2 : StartRedline( pRedlineParagraphMarkerDeleted );
948 2 : EndRedline( pRedlineParagraphMarkerDeleted );
949 : }
950 13028 : if ( pRedlineParagraphMarkerInserted )
951 : {
952 2 : StartRedline( pRedlineParagraphMarkerInserted );
953 2 : EndRedline( pRedlineParagraphMarkerInserted );
954 : }
955 :
956 : // mergeTopMarks() after paragraph mark properties child elements.
957 13028 : m_pSerializer->mergeTopMarks();
958 13028 : m_pSerializer->endElementNS( XML_w, XML_rPr );
959 :
960 13028 : if (!m_bWritingHeaderFooter && m_pCurrentFrame)
961 : {
962 10 : const SwFrmFmt& rFrmFmt = m_pCurrentFrame->GetFrmFmt();
963 10 : if (TextBoxIsFramePr(rFrmFmt))
964 : {
965 10 : const Size aSize = m_pCurrentFrame->GetSize();
966 10 : PopulateFrameProperties(&rFrmFmt, aSize);
967 : }
968 : }
969 :
970 13028 : m_pSerializer->endElementNS( XML_w, XML_pPr );
971 :
972 13028 : if ( m_nColBreakStatus == COLBRK_WRITE )
973 : {
974 90 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
975 : m_pSerializer->singleElementNS( XML_w, XML_br,
976 90 : FSNS( XML_w, XML_type ), "column", FSEND );
977 90 : m_pSerializer->endElementNS( XML_w, XML_r );
978 :
979 90 : m_nColBreakStatus = COLBRK_NONE;
980 : }
981 :
982 : // merge the properties _before_ the run (strictly speaking, just
983 : // after the start of the paragraph)
984 13028 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
985 13028 : }
986 :
987 18080 : void DocxAttributeOutput::SetStateOfFlyFrame( FlyProcessingState nStateOfFlyFrame )
988 : {
989 18080 : m_nStateOfFlyFrame = nStateOfFlyFrame;
990 18080 : }
991 :
992 18132 : void DocxAttributeOutput::SetAnchorIsLinkedToNode( bool bAnchorLinkedToNode )
993 : {
994 18132 : m_bAnchorLinkedToNode = bAnchorLinkedToNode ;
995 18132 : }
996 :
997 52 : void DocxAttributeOutput::ResetFlyProcessingFlag()
998 : {
999 52 : m_bPostponedProcessingFly = false ;
1000 52 : }
1001 :
1002 30550 : bool DocxAttributeOutput::IsFlyProcessingPostponed()
1003 : {
1004 30550 : return m_bPostponedProcessingFly;
1005 : }
1006 :
1007 18158 : void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSingleEmptyRun*/ )
1008 : {
1009 : // Don't start redline data here, possibly there is a hyperlink later, and
1010 : // that has to be started first.
1011 18158 : m_pRedlineData = pRedlineData;
1012 :
1013 : // this mark is used to be able to enclose the run inside a sdr tag.
1014 18158 : m_pSerializer->mark();
1015 :
1016 : // postpone the output of the start of a run (there are elements that need
1017 : // to be written before the start of the run, but we learn which they are
1018 : // _inside_ of the run)
1019 18158 : m_pSerializer->mark(); // let's call it "postponed run start"
1020 :
1021 : // postpone the output of the text (we get it before the run properties,
1022 : // but must write it after them)
1023 18158 : m_pSerializer->mark(); // let's call it "postponed text"
1024 18158 : }
1025 :
1026 18158 : void DocxAttributeOutput::EndRun()
1027 : {
1028 18158 : int nFieldsInPrevHyperlink = m_nFieldsInHyperlink;
1029 : // Reset m_nFieldsInHyperlink if a new hyperlink is about to start
1030 18158 : if ( m_pHyperlinkAttrList )
1031 : {
1032 398 : m_nFieldsInHyperlink = 0;
1033 : }
1034 :
1035 : // Write field starts
1036 36962 : for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
1037 : {
1038 : // Add the fields starts for all but hyperlinks and TOCs
1039 646 : if ( pIt->bOpen && pIt->pField )
1040 : {
1041 198 : StartField_Impl( *pIt );
1042 :
1043 198 : if ( m_pHyperlinkAttrList )
1044 : {
1045 2 : m_nFieldsInHyperlink++;
1046 : }
1047 :
1048 : // Remove the field from the stack if only the start has to be written
1049 : // Unknown fields sould be removed too
1050 198 : if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) )
1051 : {
1052 2 : if (pIt->pField)
1053 2 : delete pIt->pField;
1054 2 : pIt = m_Fields.erase( pIt );
1055 2 : continue;
1056 : }
1057 : }
1058 644 : ++pIt;
1059 : }
1060 :
1061 : // write the run properties + the text, already in the correct order
1062 18158 : m_pSerializer->mergeTopMarks(); // merges with "postponed text", see above
1063 :
1064 : // level down, to be able to prepend the actual run start attribute (just
1065 : // before "postponed run start")
1066 18158 : m_pSerializer->mark(); // let's call it "actual run start"
1067 18158 : bool bCloseEarlierSDT = false;
1068 :
1069 18158 : if (m_bEndCharSdt)
1070 : {
1071 : // This is the common case: "close sdt before the current run" was requrested by the next run.
1072 :
1073 : // if another sdt starts in this run, then wait
1074 : // as closing the sdt now, might cause nesting of sdts
1075 32 : if (m_nRunSdtPrToken > 0)
1076 8 : bCloseEarlierSDT = true;
1077 : else
1078 24 : EndSdtBlock();
1079 32 : m_bEndCharSdt = false;
1080 32 : m_bStartedCharSdt = false;
1081 : }
1082 :
1083 18158 : if ( m_closeHyperlinkInPreviousRun )
1084 : {
1085 194 : if ( m_startedHyperlink )
1086 : {
1087 168 : for ( int i = 0; i < nFieldsInPrevHyperlink; i++ )
1088 : {
1089 : // If fields begin before hyperlink then
1090 : // it should end before hyperlink close
1091 2 : EndField_Impl( m_Fields.back( ) );
1092 2 : if (m_Fields.back().pField)
1093 0 : delete m_Fields.back().pField;
1094 2 : m_Fields.pop_back();
1095 : }
1096 166 : m_pSerializer->endElementNS( XML_w, XML_hyperlink );
1097 166 : m_startedHyperlink = false;
1098 166 : m_endPageRef = false;
1099 166 : m_nHyperLinkCount--;
1100 : }
1101 194 : m_closeHyperlinkInPreviousRun = false;
1102 : }
1103 :
1104 : // Write the hyperlink and toc fields starts
1105 36958 : for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); )
1106 : {
1107 : // Add the fields starts for hyperlinks, TOCs and index marks
1108 642 : if ( pIt->bOpen && !pIt->pField )
1109 : {
1110 234 : StartField_Impl( *pIt, true );
1111 :
1112 : // Remove the field if no end needs to be written
1113 234 : if ( !pIt->bClose ) {
1114 116 : if (pIt->pField)
1115 0 : delete pIt->pField;
1116 116 : pIt = m_Fields.erase( pIt );
1117 116 : continue;
1118 : }
1119 : }
1120 526 : ++pIt;
1121 : }
1122 :
1123 : // Start the hyperlink after the fields separators or we would generate invalid file
1124 18158 : if ( m_pHyperlinkAttrList )
1125 : {
1126 398 : XFastAttributeListRef xAttrList ( m_pHyperlinkAttrList );
1127 :
1128 398 : m_pSerializer->startElementNS( XML_w, XML_hyperlink, xAttrList );
1129 398 : m_pHyperlinkAttrList = NULL;
1130 398 : m_startedHyperlink = true;
1131 398 : m_nHyperLinkCount++;
1132 : }
1133 :
1134 : // if there is some redlining in the document, output it
1135 18158 : StartRedline( m_pRedlineData );
1136 :
1137 18158 : DoWriteBookmarks( );
1138 18158 : DoWriteAnnotationMarks( );
1139 :
1140 18158 : if( m_closeHyperlinkInThisRun && m_startedHyperlink && m_hyperLinkAnchor != "" && m_hyperLinkAnchor.startsWith("_Toc"))
1141 : {
1142 182 : OUString sToken;
1143 182 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1144 182 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1145 182 : m_pSerializer->singleElementNS( XML_w, XML_webHidden, FSEND );
1146 182 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1147 : m_pSerializer->startElementNS( XML_w, XML_fldChar,
1148 : FSNS( XML_w, XML_fldCharType ), "begin",
1149 182 : FSEND );
1150 182 : m_pSerializer->endElementNS( XML_w, XML_fldChar );
1151 182 : m_pSerializer->endElementNS( XML_w, XML_r );
1152 :
1153 :
1154 182 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1155 182 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1156 182 : m_pSerializer->singleElementNS( XML_w, XML_webHidden, FSEND );
1157 182 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1158 182 : sToken = "PAGEREF " + m_hyperLinkAnchor + " \\h"; // '\h' Creates a hyperlink to the bookmarked paragraph.
1159 182 : DoWriteCmd( sToken );
1160 182 : m_pSerializer->endElementNS( XML_w, XML_r );
1161 :
1162 : // Write the Field separator
1163 182 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1164 182 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1165 182 : m_pSerializer->singleElementNS( XML_w, XML_webHidden, FSEND );
1166 182 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1167 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
1168 : FSNS( XML_w, XML_fldCharType ), "separate",
1169 182 : FSEND );
1170 182 : m_pSerializer->endElementNS( XML_w, XML_r );
1171 : // At start of every "PAGEREF" field m_endPageRef value should be true.
1172 182 : m_endPageRef = true;
1173 : }
1174 :
1175 18158 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1176 18158 : if(GetExport().bTabInTOC && m_pHyperlinkAttrList)
1177 : {
1178 0 : RunText(OUString("\t")) ;
1179 : }
1180 18158 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); // merges with "postponed run start", see above
1181 :
1182 : // write the run start + the run content
1183 18158 : m_pSerializer->mergeTopMarks(); // merges the "actual run start"
1184 : // append the actual run end
1185 18158 : m_pSerializer->endElementNS( XML_w, XML_r );
1186 :
1187 : // if there is some redlining in the document, output it
1188 18158 : EndRedline( m_pRedlineData );
1189 :
1190 : // enclose in a sdt block, if necessary: if one is already started, then don't do it for now
1191 : // (so on export sdt blocks are never nested ATM)
1192 18158 : if ( !m_bAnchorLinkedToNode && !m_bStartedCharSdt )
1193 : {
1194 18090 : ::sax_fastparser::FastAttributeList* pRunSdtPrTokenAttributes = 0;
1195 18090 : WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, pRunSdtPrTokenAttributes, m_pRunSdtPrDataBindingAttrs, m_aRunSdtPrAlias, /*bPara=*/false );
1196 : }
1197 : else
1198 : {
1199 : //These should be written out to the actual Node and not to the anchor.
1200 : //Clear them as they will be repopulated when the node is processed.
1201 68 : m_nRunSdtPrToken = 0;
1202 68 : lcl_deleteAndResetTheLists( m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs, m_aRunSdtPrAlias );
1203 : }
1204 :
1205 18158 : if (bCloseEarlierSDT)
1206 : {
1207 8 : m_pSerializer->mark();
1208 8 : EndSdtBlock();
1209 8 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
1210 8 : bCloseEarlierSDT = false;
1211 : }
1212 :
1213 18158 : m_pSerializer->mergeTopMarks();
1214 :
1215 18158 : WritePostponedMath();
1216 :
1217 18178 : for (std::vector<const SdrObject*>::iterator it = m_aPostponedFormControls.begin(); it != m_aPostponedFormControls.end(); ++it)
1218 20 : WritePostponedFormControl(*it);
1219 18158 : m_aPostponedFormControls.clear();
1220 :
1221 18158 : WritePendingPlaceholder();
1222 :
1223 18158 : m_pRedlineData = NULL;
1224 :
1225 18158 : if ( m_closeHyperlinkInThisRun )
1226 : {
1227 426 : if ( m_startedHyperlink )
1228 : {
1229 230 : if( m_endPageRef )
1230 : {
1231 : // Hyperlink is started and fldchar "end" needs to be written for PAGEREF
1232 182 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1233 182 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1234 182 : m_pSerializer->singleElementNS( XML_w, XML_webHidden, FSEND );
1235 182 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1236 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
1237 : FSNS( XML_w, XML_fldCharType ), "end",
1238 182 : FSEND );
1239 182 : m_pSerializer->endElementNS( XML_w, XML_r );
1240 182 : m_endPageRef = false;
1241 182 : m_hyperLinkAnchor = "";
1242 : }
1243 234 : for ( int i = 0; i < m_nFieldsInHyperlink; i++ )
1244 : {
1245 : // If fields begin after hyperlink start then
1246 : // it should end before hyperlink close
1247 4 : EndField_Impl( m_Fields.back( ) );
1248 4 : if (m_Fields.back().pField)
1249 2 : delete m_Fields.back().pField;
1250 4 : m_Fields.pop_back();
1251 : }
1252 :
1253 230 : m_pSerializer->endElementNS( XML_w, XML_hyperlink );
1254 230 : m_startedHyperlink = false;
1255 230 : m_nHyperLinkCount--;
1256 : }
1257 426 : m_closeHyperlinkInThisRun = false;
1258 : }
1259 :
1260 18158 : if(!m_startedHyperlink)
1261 36084 : while ( m_Fields.begin() != m_Fields.end() )
1262 : {
1263 484 : EndField_Impl( m_Fields.front( ) );
1264 484 : if (m_Fields.front().pField)
1265 194 : delete m_Fields.front().pField;
1266 484 : m_Fields.erase( m_Fields.begin( ) );
1267 : }
1268 18158 : }
1269 :
1270 18158 : void DocxAttributeOutput::DoWriteBookmarks()
1271 : {
1272 : // Write the start bookmarks
1273 19814 : for ( std::vector< OString >::const_iterator it = m_rBookmarksStart.begin(), end = m_rBookmarksStart.end();
1274 : it != end; ++it )
1275 : {
1276 1656 : const OString& rName = *it;
1277 :
1278 : // Output the bookmark
1279 1656 : sal_uInt16 nId = m_nNextBookmarkId++;
1280 1656 : m_rOpenedBookmarksIds[rName] = nId;
1281 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
1282 : FSNS( XML_w, XML_id ), OString::number( nId ).getStr( ),
1283 : FSNS( XML_w, XML_name ), rName.getStr(),
1284 1656 : FSEND );
1285 1656 : m_sLastOpenedBookmark = rName;
1286 : }
1287 18158 : m_rBookmarksStart.clear();
1288 :
1289 : // export the end bookmarks
1290 19778 : for ( std::vector< OString >::const_iterator it = m_rBookmarksEnd.begin(), end = m_rBookmarksEnd.end();
1291 : it != end; ++it )
1292 : {
1293 1620 : const OString& rName = *it;
1294 :
1295 : // Get the id of the bookmark
1296 1620 : std::map< OString, sal_uInt16 >::iterator pPos = m_rOpenedBookmarksIds.find( rName );
1297 1620 : if ( pPos != m_rOpenedBookmarksIds.end( ) )
1298 : {
1299 1310 : sal_uInt16 nId = ( *pPos ).second;
1300 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
1301 : FSNS( XML_w, XML_id ), OString::number( nId ).getStr( ),
1302 1310 : FSEND );
1303 1310 : m_rOpenedBookmarksIds.erase( rName );
1304 : }
1305 : }
1306 18158 : m_rBookmarksEnd.clear();
1307 18158 : }
1308 :
1309 18158 : void DocxAttributeOutput::DoWriteAnnotationMarks()
1310 : {
1311 : // Write the start annotation marks
1312 18172 : for ( std::vector< OString >::const_iterator it = m_rAnnotationMarksStart.begin(), end = m_rAnnotationMarksStart.end();
1313 : it != end; ++it )
1314 : {
1315 14 : const OString& rName = *it;
1316 :
1317 : // Output the annotation mark
1318 : /* Ensure that the existing Annotation Marks are not overwritten
1319 : as it causes discrepancy when DocxAttributeOutput::PostitField
1320 : refers to this map & while mapping comment id's in document.xml &
1321 : comment.xml.
1322 : */
1323 14 : if ( m_rOpenedAnnotationMarksIds.end() == m_rOpenedAnnotationMarksIds.find( rName ) )
1324 : {
1325 10 : sal_uInt16 nId = m_nNextAnnotationMarkId++;
1326 10 : m_rOpenedAnnotationMarksIds[rName] = nId;
1327 : m_pSerializer->singleElementNS( XML_w, XML_commentRangeStart,
1328 : FSNS( XML_w, XML_id ), OString::number( nId ).getStr( ),
1329 10 : FSEND );
1330 10 : m_sLastOpenedAnnotationMark = rName;
1331 : }
1332 : }
1333 18158 : m_rAnnotationMarksStart.clear();
1334 :
1335 : // export the end annotation marks
1336 18168 : for ( std::vector< OString >::const_iterator it = m_rAnnotationMarksEnd.begin(), end = m_rAnnotationMarksEnd.end();
1337 : it != end; ++it )
1338 : {
1339 10 : const OString& rName = *it;
1340 :
1341 : // Get the id of the annotation mark
1342 10 : std::map< OString, sal_uInt16 >::iterator pPos = m_rOpenedAnnotationMarksIds.find( rName );
1343 10 : if ( pPos != m_rOpenedAnnotationMarksIds.end( ) )
1344 : {
1345 10 : sal_uInt16 nId = ( *pPos ).second;
1346 : m_pSerializer->singleElementNS( XML_w, XML_commentRangeEnd,
1347 : FSNS( XML_w, XML_id ), OString::number( nId ).getStr( ),
1348 10 : FSEND );
1349 10 : m_rOpenedAnnotationMarksIds.erase( rName );
1350 :
1351 10 : m_pSerializer->startElementNS(XML_w, XML_r, FSEND);
1352 : m_pSerializer->singleElementNS( XML_w, XML_commentReference, FSNS( XML_w, XML_id ),
1353 : OString::number( nId ).getStr(),
1354 10 : FSEND );
1355 10 : m_pSerializer->endElementNS(XML_w, XML_r);
1356 : }
1357 : }
1358 18158 : m_rAnnotationMarksEnd.clear();
1359 18158 : }
1360 :
1361 2 : void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos )
1362 : {
1363 2 : const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
1364 2 : if ( rInfos.eType == ww::eFORMDROPDOWN )
1365 : {
1366 0 : uno::Sequence< OUString> vListEntries;
1367 0 : OUString sName, sHelp, sToolTip, sSelected;
1368 :
1369 0 : FieldMarkParamsHelper params( rFieldmark );
1370 0 : params.extractParam( ODF_FORMDROPDOWN_LISTENTRY, vListEntries );
1371 0 : sName = params.getName();
1372 0 : sal_Int32 nSelectedIndex = 0;
1373 :
1374 0 : if ( params.extractParam( ODF_FORMDROPDOWN_RESULT, nSelectedIndex ) )
1375 : {
1376 0 : if (nSelectedIndex < vListEntries.getLength() )
1377 0 : sSelected = vListEntries[ nSelectedIndex ];
1378 : }
1379 :
1380 0 : GetExport().DoComboBox( sName, sHelp, sToolTip, sSelected, vListEntries );
1381 : }
1382 2 : else if ( rInfos.eType == ww::eFORMCHECKBOX )
1383 : {
1384 2 : OUString sName;
1385 2 : bool bChecked = false;
1386 :
1387 2 : FieldMarkParamsHelper params( rFieldmark );
1388 2 : params.extractParam( ODF_FORMCHECKBOX_NAME, sName );
1389 :
1390 2 : const sw::mark::ICheckboxFieldmark* pCheckboxFm = dynamic_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
1391 2 : if ( pCheckboxFm && pCheckboxFm->IsChecked() )
1392 0 : bChecked = true;
1393 :
1394 4 : FFDataWriterHelper ffdataOut( m_pSerializer );
1395 4 : ffdataOut.WriteFormCheckbox( sName, OUString(), bChecked );
1396 : }
1397 0 : else if ( rInfos.eType == ww::eFORMTEXT )
1398 : {
1399 0 : FieldMarkParamsHelper params( rFieldmark );
1400 0 : FFDataWriterHelper ffdataOut( m_pSerializer );
1401 0 : ffdataOut.WriteFormText( params.getName(), OUString() );
1402 : }
1403 2 : }
1404 :
1405 432 : void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, bool bWriteRun )
1406 : {
1407 432 : if ( m_startedHyperlink )
1408 4 : ++m_nFieldsInHyperlink;
1409 432 : if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
1410 : {
1411 : // Expand unsupported fields
1412 2 : RunText( rInfos.pField->GetFieldName() );
1413 : }
1414 430 : else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
1415 : {
1416 430 : if ( bWriteRun )
1417 234 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1418 :
1419 430 : if ( rInfos.eType == ww::eFORMDROPDOWN )
1420 : {
1421 : m_pSerializer->startElementNS( XML_w, XML_fldChar,
1422 : FSNS( XML_w, XML_fldCharType ), "begin",
1423 0 : FSEND );
1424 0 : if ( rInfos.pFieldmark && !rInfos.pField )
1425 0 : WriteFFData( rInfos );
1426 0 : if ( rInfos.pField )
1427 : {
1428 0 : const SwDropDownField& rFld2 = *(SwDropDownField*)rInfos.pField;
1429 : uno::Sequence<OUString> aItems =
1430 0 : rFld2.GetItemSequence();
1431 0 : GetExport().DoComboBox(rFld2.GetName(),
1432 0 : rFld2.GetHelp(),
1433 0 : rFld2.GetToolTip(),
1434 0 : rFld2.GetSelectedItem(), aItems);
1435 : }
1436 0 : m_pSerializer->endElementNS( XML_w, XML_fldChar );
1437 :
1438 0 : if ( bWriteRun )
1439 0 : m_pSerializer->endElementNS( XML_w, XML_r );
1440 0 : if ( !rInfos.pField )
1441 0 : CmdField_Impl( rInfos );
1442 :
1443 : }
1444 : else
1445 : {
1446 : // Write the field start
1447 : m_pSerializer->startElementNS( XML_w, XML_fldChar,
1448 : FSNS( XML_w, XML_fldCharType ), "begin",
1449 430 : FSEND );
1450 :
1451 430 : if ( rInfos.pFieldmark )
1452 2 : WriteFFData( rInfos );
1453 :
1454 430 : m_pSerializer->endElementNS( XML_w, XML_fldChar );
1455 :
1456 430 : if ( bWriteRun )
1457 234 : m_pSerializer->endElementNS( XML_w, XML_r );
1458 :
1459 : // The hyperlinks fields can't be expanded: the value is
1460 : // normally in the text run
1461 430 : if ( !rInfos.pField )
1462 234 : CmdField_Impl( rInfos );
1463 : }
1464 : }
1465 432 : }
1466 :
1467 624 : void DocxAttributeOutput::DoWriteCmd( const OUString& rCmd )
1468 : {
1469 624 : OUString sCmd = rCmd.trim();
1470 624 : if (sCmd.startsWith("SEQ"))
1471 : {
1472 22 : OUString sSeqName = msfilter::util::findQuotedText(sCmd, "SEQ ", '\\').trim();
1473 22 : m_aSeqBookmarksNames[sSeqName].push_back(m_sLastOpenedBookmark);
1474 : }
1475 : // Write the Field command
1476 624 : m_pSerializer->startElementNS( XML_w, XML_instrText, FSEND );
1477 624 : m_pSerializer->writeEscaped( rCmd );
1478 624 : m_pSerializer->endElementNS( XML_w, XML_instrText );
1479 :
1480 624 : }
1481 :
1482 430 : void DocxAttributeOutput::CmdField_Impl( FieldInfos& rInfos )
1483 : {
1484 430 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1485 430 : sal_Int32 nNbToken = comphelper::string::getTokenCount(rInfos.sCmd, '\t');
1486 :
1487 872 : for ( sal_Int32 i = 0; i < nNbToken; i++ )
1488 : {
1489 442 : OUString sToken = rInfos.sCmd.getToken( i, '\t' );
1490 442 : if ( rInfos.eType == ww::eCREATEDATE
1491 442 : || rInfos.eType == ww::eSAVEDATE
1492 442 : || rInfos.eType == ww::ePRINTDATE
1493 442 : || rInfos.eType == ww::eDATE
1494 440 : || rInfos.eType == ww::eTIME )
1495 : {
1496 2 : sToken = sToken.replaceAll("NNNN", "dddd");
1497 2 : sToken = sToken.replaceAll("NN", "ddd");
1498 : }
1499 :
1500 : // Write the Field command
1501 442 : DoWriteCmd( sToken );
1502 :
1503 : // Replace tabs by </instrText><tab/><instrText>
1504 442 : if ( i < ( nNbToken - 1 ) )
1505 12 : RunText( OUString( "\t" ) );
1506 442 : }
1507 :
1508 430 : m_pSerializer->endElementNS( XML_w, XML_r );
1509 :
1510 : // Write the Field separator
1511 430 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1512 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
1513 : FSNS( XML_w, XML_fldCharType ), "separate",
1514 430 : FSEND );
1515 430 : m_pSerializer->endElementNS( XML_w, XML_r );
1516 430 : }
1517 :
1518 490 : void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
1519 : {
1520 : // The command has to be written before for the hyperlinks
1521 490 : if ( rInfos.pField )
1522 : {
1523 196 : CmdField_Impl( rInfos );
1524 : }
1525 :
1526 : // Write the bookmark start if any
1527 490 : OUString aBkmName( m_sFieldBkm );
1528 490 : if ( !aBkmName.isEmpty() )
1529 : {
1530 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
1531 : FSNS( XML_w, XML_id ), OString::number( m_nNextBookmarkId ).getStr( ),
1532 : FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
1533 2 : FSEND );
1534 : }
1535 :
1536 490 : if (rInfos.pField ) // For hyperlinks and TOX
1537 : {
1538 : // Write the Field latest value
1539 196 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1540 196 : OUString sExpand;
1541 196 : if(rInfos.eType == ww::eCITATION)
1542 : {
1543 14 : sExpand = rInfos.pField->ExpandCitation(AUTH_FIELD_TITLE);
1544 : }
1545 : else
1546 : {
1547 182 : sExpand = rInfos.pField->ExpandField( true );
1548 : }
1549 : // newlines embedded in fields are 0x0B in MSO and 0x0A for us
1550 196 : RunText(sExpand.replace(0x0A, 0x0B));
1551 :
1552 196 : m_pSerializer->endElementNS( XML_w, XML_r );
1553 : }
1554 :
1555 : // Write the bookmark end if any
1556 490 : if ( !aBkmName.isEmpty() )
1557 : {
1558 : m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
1559 : FSNS( XML_w, XML_id ), OString::number( m_nNextBookmarkId ).getStr( ),
1560 2 : FSEND );
1561 :
1562 2 : m_nNextBookmarkId++;
1563 : }
1564 :
1565 : // Write the Field end
1566 490 : if ( rInfos.bClose )
1567 : {
1568 432 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1569 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
1570 : FSNS( XML_w, XML_fldCharType ), "end",
1571 432 : FSEND );
1572 432 : m_pSerializer->endElementNS( XML_w, XML_r );
1573 : }
1574 : // Write the ref field if a bookmark had to be set and the field
1575 : // should be visible
1576 490 : if ( rInfos.pField )
1577 : {
1578 196 : sal_uInt16 nSubType = rInfos.pField->GetSubType( );
1579 196 : bool bIsSetField = rInfos.pField->GetTyp( )->Which( ) == RES_SETEXPFLD;
1580 196 : bool bShowRef = ( !bIsSetField || ( nSubType & nsSwExtendedSubType::SUB_INVISIBLE ) ) ? false : true;
1581 :
1582 196 : if ( ( !m_sFieldBkm.isEmpty() ) && bShowRef )
1583 : {
1584 : // Write the field beginning
1585 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1586 : m_pSerializer->singleElementNS( XML_w, XML_fldChar,
1587 : FSNS( XML_w, XML_fldCharType ), "begin",
1588 0 : FSEND );
1589 0 : m_pSerializer->endElementNS( XML_w, XML_r );
1590 :
1591 0 : rInfos.sCmd = FieldString( ww::eREF );
1592 0 : rInfos.sCmd += "\"";
1593 0 : rInfos.sCmd += m_sFieldBkm;
1594 0 : rInfos.sCmd += "\" ";
1595 :
1596 : // Clean the field bookmark data to avoid infinite loop
1597 0 : m_sFieldBkm = OUString( );
1598 :
1599 : // Write the end of the field
1600 0 : EndField_Impl( rInfos );
1601 : }
1602 490 : }
1603 490 : }
1604 :
1605 18106 : void DocxAttributeOutput::StartRunProperties()
1606 : {
1607 : // postpone the output so that we can later [in EndRunProperties()]
1608 : // prepend the properties before the text
1609 18106 : m_pSerializer->mark();
1610 :
1611 18106 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1612 :
1613 18106 : if(GetExport().bHideTabLeaderAndPageNumbers && m_pHyperlinkAttrList )
1614 : {
1615 178 : m_pSerializer->singleElementNS( XML_w, XML_webHidden, FSEND );
1616 : }
1617 18106 : InitCollectedRunProperties();
1618 :
1619 : OSL_ASSERT( m_postponedGraphic == NULL );
1620 18106 : m_postponedGraphic = new std::list< PostponedGraphic >;
1621 :
1622 : OSL_ASSERT( m_postponedDiagram == NULL );
1623 18106 : m_postponedDiagram = new std::list< PostponedDiagram >;
1624 :
1625 : OSL_ASSERT( m_postponedVMLDrawing == NULL );
1626 18106 : m_postponedVMLDrawing = new std::list< PostponedDrawing >;
1627 :
1628 : assert(!m_postponedDMLDrawing);
1629 18106 : m_postponedDMLDrawing = new std::list< PostponedDrawing >;
1630 :
1631 : assert( !m_postponedOLE );
1632 18106 : m_postponedOLE = new std::list< PostponedOLE >;
1633 18106 : }
1634 :
1635 50906 : void DocxAttributeOutput::InitCollectedRunProperties()
1636 : {
1637 50906 : m_pFontsAttrList = NULL;
1638 50906 : m_pEastAsianLayoutAttrList = NULL;
1639 50906 : m_pCharLangAttrList = NULL;
1640 :
1641 : // Write the elements in the spec order
1642 : static const sal_Int32 aOrder[] =
1643 : {
1644 : FSNS( XML_w, XML_rStyle ),
1645 : FSNS( XML_w, XML_rFonts ),
1646 : FSNS( XML_w, XML_b ),
1647 : FSNS( XML_w, XML_bCs ),
1648 : FSNS( XML_w, XML_i ),
1649 : FSNS( XML_w, XML_iCs ),
1650 : FSNS( XML_w, XML_caps ),
1651 : FSNS( XML_w, XML_smallCaps ),
1652 : FSNS( XML_w, XML_strike ),
1653 : FSNS( XML_w, XML_dstrike ),
1654 : FSNS( XML_w, XML_outline ),
1655 : FSNS( XML_w, XML_shadow ),
1656 : FSNS( XML_w, XML_emboss ),
1657 : FSNS( XML_w, XML_imprint ),
1658 : FSNS( XML_w, XML_noProof ),
1659 : FSNS( XML_w, XML_snapToGrid ),
1660 : FSNS( XML_w, XML_vanish ),
1661 : FSNS( XML_w, XML_webHidden ),
1662 : FSNS( XML_w, XML_color ),
1663 : FSNS( XML_w, XML_spacing ),
1664 : FSNS( XML_w, XML_w ),
1665 : FSNS( XML_w, XML_kern ),
1666 : FSNS( XML_w, XML_position ),
1667 : FSNS( XML_w, XML_sz ),
1668 : FSNS( XML_w, XML_szCs ),
1669 : FSNS( XML_w, XML_highlight ),
1670 : FSNS( XML_w, XML_u ),
1671 : FSNS( XML_w, XML_effect ),
1672 : FSNS( XML_w, XML_bdr ),
1673 : FSNS( XML_w, XML_shd ),
1674 : FSNS( XML_w, XML_fitText ),
1675 : FSNS( XML_w, XML_vertAlign ),
1676 : FSNS( XML_w, XML_rtl ),
1677 : FSNS( XML_w, XML_cs ),
1678 : FSNS( XML_w, XML_em ),
1679 : FSNS( XML_w, XML_lang ),
1680 : FSNS( XML_w, XML_eastAsianLayout ),
1681 : FSNS( XML_w, XML_specVanish ),
1682 : FSNS( XML_w, XML_oMath ),
1683 : FSNS( XML_w, XML_rPrChange ),
1684 : FSNS( XML_w14, XML_glow ),
1685 : FSNS( XML_w14, XML_shadow ),
1686 : FSNS( XML_w14, XML_reflection ),
1687 : FSNS( XML_w14, XML_textOutline ),
1688 : FSNS( XML_w14, XML_textFill ),
1689 : FSNS( XML_w14, XML_scene3d ),
1690 : FSNS( XML_w14, XML_props3d ),
1691 : FSNS( XML_w14, XML_ligatures ),
1692 : FSNS( XML_w14, XML_numForm ),
1693 : FSNS( XML_w14, XML_numSpacing ),
1694 : FSNS( XML_w14, XML_stylisticSets ),
1695 : FSNS( XML_w14, XML_cntxtAlts ),
1696 : };
1697 :
1698 : // postpone the output so that we can later [in EndParagraphProperties()]
1699 : // prepend the properties before the run
1700 50906 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
1701 50906 : uno::Sequence< sal_Int32 > aSeqOrder( len );
1702 2698018 : for ( sal_Int32 i = 0; i < len; i++ )
1703 2647112 : aSeqOrder[i] = aOrder[i];
1704 :
1705 50906 : m_pSerializer->mark( aSeqOrder );
1706 50906 : }
1707 :
1708 : namespace
1709 : {
1710 :
1711 2788 : struct NameToId
1712 : {
1713 : OUString maName;
1714 : sal_Int32 maId;
1715 : };
1716 :
1717 68 : const NameToId constNameToIdMapping[] =
1718 : {
1719 : { OUString("glow"), FSNS( XML_w14, XML_glow ) },
1720 : { OUString("shadow"), FSNS( XML_w14, XML_shadow ) },
1721 : { OUString("reflection"), FSNS( XML_w14, XML_reflection ) },
1722 : { OUString("textOutline"), FSNS( XML_w14, XML_textOutline ) },
1723 : { OUString("textFill"), FSNS( XML_w14, XML_textFill ) },
1724 : { OUString("scene3d"), FSNS( XML_w14, XML_scene3d ) },
1725 : { OUString("props3d"), FSNS( XML_w14, XML_props3d ) },
1726 : { OUString("ligatures"), FSNS( XML_w14, XML_ligatures ) },
1727 : { OUString("numForm"), FSNS( XML_w14, XML_numForm ) },
1728 : { OUString("numSpacing"), FSNS( XML_w14, XML_numSpacing ) },
1729 : { OUString("stylisticSets"),FSNS( XML_w14, XML_stylisticSets ) },
1730 : { OUString("cntxtAlts"), FSNS( XML_w14, XML_cntxtAlts ) },
1731 :
1732 : { OUString("val"), FSNS( XML_w14, XML_val ) },
1733 : { OUString("rad"), FSNS( XML_w14, XML_rad ) },
1734 : { OUString("blurRad"), FSNS( XML_w14, XML_blurRad ) },
1735 : { OUString("stA"), FSNS( XML_w14, XML_stA ) },
1736 : { OUString("stPos"), FSNS( XML_w14, XML_stPos ) },
1737 : { OUString("endA"), FSNS( XML_w14, XML_endA ) },
1738 : { OUString("endPos"), FSNS( XML_w14, XML_endPos ) },
1739 : { OUString("dist"), FSNS( XML_w14, XML_dist ) },
1740 : { OUString("dir"), FSNS( XML_w14, XML_dir ) },
1741 : { OUString("fadeDir"), FSNS( XML_w14, XML_fadeDir ) },
1742 : { OUString("sx"), FSNS( XML_w14, XML_sx ) },
1743 : { OUString("sy"), FSNS( XML_w14, XML_sy ) },
1744 : { OUString("kx"), FSNS( XML_w14, XML_kx ) },
1745 : { OUString("ky"), FSNS( XML_w14, XML_ky ) },
1746 : { OUString("algn"), FSNS( XML_w14, XML_algn ) },
1747 : { OUString("w"), FSNS( XML_w14, XML_w ) },
1748 : { OUString("cap"), FSNS( XML_w14, XML_cap ) },
1749 : { OUString("cmpd"), FSNS( XML_w14, XML_cmpd ) },
1750 : { OUString("pos"), FSNS( XML_w14, XML_pos ) },
1751 : { OUString("ang"), FSNS( XML_w14, XML_ang ) },
1752 : { OUString("scaled"), FSNS( XML_w14, XML_scaled ) },
1753 : { OUString("path"), FSNS( XML_w14, XML_path ) },
1754 : { OUString("l"), FSNS( XML_w14, XML_l ) },
1755 : { OUString("t"), FSNS( XML_w14, XML_t ) },
1756 : { OUString("r"), FSNS( XML_w14, XML_r ) },
1757 : { OUString("b"), FSNS( XML_w14, XML_b ) },
1758 : { OUString("lim"), FSNS( XML_w14, XML_lim ) },
1759 : { OUString("prst"), FSNS( XML_w14, XML_prst ) },
1760 : { OUString("rig"), FSNS( XML_w14, XML_rig ) },
1761 : { OUString("lat"), FSNS( XML_w14, XML_lat ) },
1762 : { OUString("lon"), FSNS( XML_w14, XML_lon ) },
1763 : { OUString("rev"), FSNS( XML_w14, XML_rev ) },
1764 : { OUString("h"), FSNS( XML_w14, XML_h ) },
1765 : { OUString("extrusionH"), FSNS( XML_w14, XML_extrusionH ) },
1766 : { OUString("contourW"), FSNS( XML_w14, XML_contourW ) },
1767 : { OUString("prstMaterial"), FSNS( XML_w14, XML_prstMaterial ) },
1768 : { OUString("id"), FSNS( XML_w14, XML_id ) },
1769 :
1770 : { OUString("schemeClr"), FSNS( XML_w14, XML_schemeClr ) },
1771 : { OUString("srgbClr"), FSNS( XML_w14, XML_srgbClr ) },
1772 : { OUString("tint"), FSNS( XML_w14, XML_tint ) },
1773 : { OUString("shade"), FSNS( XML_w14, XML_shade ) },
1774 : { OUString("alpha"), FSNS( XML_w14, XML_alpha ) },
1775 : { OUString("hueMod"), FSNS( XML_w14, XML_hueMod ) },
1776 : { OUString("sat"), FSNS( XML_w14, XML_sat ) },
1777 : { OUString("satOff"), FSNS( XML_w14, XML_satOff ) },
1778 : { OUString("satMod"), FSNS( XML_w14, XML_satMod ) },
1779 : { OUString("lum"), FSNS( XML_w14, XML_lum ) },
1780 : { OUString("lumOff"), FSNS( XML_w14, XML_lumOff ) },
1781 : { OUString("lumMod"), FSNS( XML_w14, XML_lumMod ) },
1782 : { OUString("noFill"), FSNS( XML_w14, XML_noFill ) },
1783 : { OUString("solidFill"), FSNS( XML_w14, XML_solidFill ) },
1784 : { OUString("gradFill"), FSNS( XML_w14, XML_gradFill ) },
1785 : { OUString("gsLst"), FSNS( XML_w14, XML_gsLst ) },
1786 : { OUString("gs"), FSNS( XML_w14, XML_gs ) },
1787 : { OUString("pos"), FSNS( XML_w14, XML_pos ) },
1788 : { OUString("lin"), FSNS( XML_w14, XML_lin ) },
1789 : { OUString("path"), FSNS( XML_w14, XML_path ) },
1790 : { OUString("fillToRect"), FSNS( XML_w14, XML_fillToRect ) },
1791 : { OUString("prstDash"), FSNS( XML_w14, XML_prstDash ) },
1792 : { OUString("round"), FSNS( XML_w14, XML_round ) },
1793 : { OUString("bevel"), FSNS( XML_w14, XML_bevel ) },
1794 : { OUString("miter"), FSNS( XML_w14, XML_miter ) },
1795 : { OUString("camera"), FSNS( XML_w14, XML_camera ) },
1796 : { OUString("lightRig"), FSNS( XML_w14, XML_lightRig ) },
1797 : { OUString("rot"), FSNS( XML_w14, XML_rot ) },
1798 : { OUString("bevelT"), FSNS( XML_w14, XML_bevelT ) },
1799 : { OUString("bevelB"), FSNS( XML_w14, XML_bevelB ) },
1800 : { OUString("extrusionClr"), FSNS( XML_w14, XML_extrusionClr ) },
1801 : { OUString("contourClr"), FSNS( XML_w14, XML_contourClr ) },
1802 : { OUString("styleSet"), FSNS( XML_w14, XML_styleSet ) },
1803 34 : };
1804 :
1805 3918 : boost::optional<sal_Int32> lclGetElementIdForName(const OUString& rName)
1806 : {
1807 3918 : sal_Int32 aLength = sizeof (constNameToIdMapping) / sizeof(NameToId);
1808 175990 : for (sal_Int32 i=0; i < aLength; ++i)
1809 : {
1810 175008 : if (rName == constNameToIdMapping[i].maName)
1811 : {
1812 2936 : return constNameToIdMapping[i].maId;
1813 : }
1814 : }
1815 982 : return boost::optional<sal_Int32>();
1816 : }
1817 :
1818 1188 : void lclProcessRecursiveGrabBag(sal_Int32 aElementId, const css::uno::Sequence<css::beans::PropertyValue>& rElements, sax_fastparser::FSHelperPtr pSerializer)
1819 : {
1820 1188 : css::uno::Sequence<css::beans::PropertyValue> aAttributes;
1821 1188 : FastAttributeList* pAttributes = pSerializer->createAttrList();
1822 :
1823 3032 : for (sal_Int32 j=0; j < rElements.getLength(); ++j)
1824 : {
1825 1844 : if (rElements[j].Name == "attributes")
1826 : {
1827 982 : rElements[j].Value >>= aAttributes;
1828 : }
1829 : }
1830 :
1831 2936 : for (sal_Int32 j=0; j < aAttributes.getLength(); ++j)
1832 : {
1833 1748 : uno::Any aAny = aAttributes[j].Value;
1834 3496 : OString aValue;
1835 :
1836 1748 : if(aAny.getValueType() == cppu::UnoType<sal_Int32>::get())
1837 : {
1838 944 : aValue = OString::number(aAny.get<sal_Int32>());
1839 : }
1840 804 : else if(aAny.getValueType() == cppu::UnoType<OUString>::get())
1841 : {
1842 804 : aValue = OUStringToOString(aAny.get<OUString>(), RTL_TEXTENCODING_ASCII_US);
1843 : }
1844 :
1845 3496 : boost::optional<sal_Int32> aSubElementId = lclGetElementIdForName(aAttributes[j].Name);
1846 1748 : if(aSubElementId)
1847 1748 : pAttributes->add(*aSubElementId, aValue.getStr());
1848 1748 : }
1849 :
1850 2376 : XFastAttributeListRef xAttributesList( pAttributes );
1851 :
1852 1188 : pSerializer->startElement(aElementId, xAttributesList);
1853 :
1854 3032 : for (sal_Int32 j=0; j < rElements.getLength(); ++j)
1855 : {
1856 1844 : css::uno::Sequence<css::beans::PropertyValue> aSumElements;
1857 :
1858 3688 : boost::optional<sal_Int32> aSubElementId = lclGetElementIdForName(rElements[j].Name);
1859 1844 : if(aSubElementId)
1860 : {
1861 862 : rElements[j].Value >>= aSumElements;
1862 862 : lclProcessRecursiveGrabBag(*aSubElementId, aSumElements, pSerializer);
1863 : }
1864 1844 : }
1865 :
1866 2376 : pSerializer->endElement(aElementId);
1867 1188 : }
1868 :
1869 : }
1870 :
1871 51464 : void DocxAttributeOutput::WriteCollectedRunProperties()
1872 : {
1873 : // Write all differed properties
1874 51464 : if ( m_pFontsAttrList )
1875 : {
1876 16382 : XFastAttributeListRef xAttrList( m_pFontsAttrList );
1877 16382 : m_pFontsAttrList = NULL;
1878 :
1879 16382 : m_pSerializer->singleElementNS( XML_w, XML_rFonts, xAttrList );
1880 : }
1881 :
1882 51464 : if ( m_pColorAttrList )
1883 : {
1884 9636 : XFastAttributeListRef xAttrList( m_pColorAttrList );
1885 9636 : m_pColorAttrList = NULL;
1886 :
1887 9636 : m_pSerializer->singleElementNS( XML_w, XML_color, xAttrList );
1888 : }
1889 :
1890 51464 : if ( m_pEastAsianLayoutAttrList )
1891 : {
1892 0 : XFastAttributeListRef xAttrList( m_pEastAsianLayoutAttrList );
1893 0 : m_pEastAsianLayoutAttrList = NULL;
1894 :
1895 0 : m_pSerializer->singleElementNS( XML_w, XML_eastAsianLayout, xAttrList );
1896 : }
1897 :
1898 51464 : if ( m_pCharLangAttrList )
1899 : {
1900 6942 : XFastAttributeListRef xAttrList( m_pCharLangAttrList );
1901 6942 : m_pCharLangAttrList = NULL;
1902 :
1903 6942 : m_pSerializer->singleElementNS( XML_w, XML_lang, xAttrList );
1904 : }
1905 :
1906 51464 : if (!m_aTextEffectsGrabBag.empty())
1907 : {
1908 470 : for (size_t i = 0; i < m_aTextEffectsGrabBag.size(); ++i)
1909 : {
1910 326 : boost::optional<sal_Int32> aElementId = lclGetElementIdForName(m_aTextEffectsGrabBag[i].Name);
1911 326 : if(aElementId)
1912 : {
1913 326 : uno::Sequence<beans::PropertyValue> aGrabBagSeq;
1914 326 : m_aTextEffectsGrabBag[i].Value >>= aGrabBagSeq;
1915 326 : lclProcessRecursiveGrabBag(*aElementId, aGrabBagSeq, m_pSerializer);
1916 : }
1917 326 : }
1918 144 : m_aTextEffectsGrabBag.clear();
1919 : }
1920 51464 : }
1921 :
1922 18106 : void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
1923 : {
1924 : // Call the 'Redline' function. This will add redline (change-tracking) information that regards to run properties.
1925 : // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
1926 18106 : Redline( pRedlineData );
1927 :
1928 18106 : WriteCollectedRunProperties();
1929 :
1930 : // Merge the marks for the ordered elements
1931 18106 : m_pSerializer->mergeTopMarks();
1932 :
1933 18106 : m_pSerializer->endElementNS( XML_w, XML_rPr );
1934 :
1935 : // write footnotes/endnotes if we have any
1936 18106 : FootnoteEndnoteReference();
1937 :
1938 18106 : WritePostponedGraphic();
1939 :
1940 18106 : WritePostponedDiagram();
1941 : //We need to write w:drawing tag after the w:rPr.
1942 18106 : WritePostponedChart();
1943 :
1944 : //We need to write w:pict tag after the w:rPr.
1945 18106 : WritePostponedVMLDrawing();
1946 18106 : WritePostponedDMLDrawing();
1947 :
1948 18106 : WritePostponedOLE();
1949 :
1950 : // merge the properties _before_ the run text (strictly speaking, just
1951 : // after the start of the run)
1952 18106 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
1953 18106 : }
1954 :
1955 752 : void DocxAttributeOutput::GetSdtEndBefore(const SdrObject* pSdrObj)
1956 : {
1957 752 : if (pSdrObj)
1958 : {
1959 744 : uno::Reference<drawing::XShape> xShape(const_cast<SdrObject*>(pSdrObj)->getUnoShape(), uno::UNO_QUERY_THROW);
1960 744 : if( xShape.is() )
1961 : {
1962 744 : uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1963 1488 : uno::Reference< beans::XPropertySetInfo > xPropSetInfo;
1964 744 : if( xPropSet.is() )
1965 : {
1966 744 : xPropSetInfo = xPropSet->getPropertySetInfo();
1967 744 : uno::Sequence< beans::PropertyValue > aGrabBag;
1968 744 : if (xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("FrameInteropGrabBag"))
1969 : {
1970 104 : xPropSet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag;
1971 : }
1972 640 : else if(xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("InteropGrabBag"))
1973 : {
1974 638 : xPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
1975 : }
1976 :
1977 3336 : for (sal_Int32 nProp=0; nProp < aGrabBag.getLength(); ++nProp)
1978 : {
1979 2598 : if ("SdtEndBefore" == aGrabBag[nProp].Name && m_bStartedCharSdt && !m_bEndCharSdt)
1980 : {
1981 6 : aGrabBag[nProp].Value >>= m_bEndCharSdt;
1982 6 : break;
1983 : }
1984 744 : }
1985 744 : }
1986 744 : }
1987 : }
1988 752 : }
1989 :
1990 18106 : void DocxAttributeOutput::WritePostponedGraphic()
1991 : {
1992 54564 : for( std::list< PostponedGraphic >::const_iterator it = m_postponedGraphic->begin();
1993 36376 : it != m_postponedGraphic->end();
1994 : ++it )
1995 82 : FlyFrameGraphic( it->grfNode, it->size, it->mOLEFrmFmt, it->mOLENode, it->pSdrObj );
1996 18106 : delete m_postponedGraphic;
1997 18106 : m_postponedGraphic = NULL;
1998 18106 : }
1999 :
2000 18106 : void DocxAttributeOutput::WritePostponedDiagram()
2001 : {
2002 54354 : for( std::list< PostponedDiagram >::const_iterator it = m_postponedDiagram->begin();
2003 36236 : it != m_postponedDiagram->end();
2004 : ++it )
2005 12 : m_rExport.SdrExporter().writeDiagram( it->object, *(it->frame), m_anchorId++ );
2006 18106 : delete m_postponedDiagram;
2007 18106 : m_postponedDiagram = NULL;
2008 18106 : }
2009 :
2010 78 : void DocxAttributeOutput::FootnoteEndnoteRefTag()
2011 : {
2012 78 : if( m_footnoteEndnoteRefTag == 0 )
2013 138 : return;
2014 18 : m_pSerializer->singleElementNS( XML_w, m_footnoteEndnoteRefTag, FSEND );
2015 18 : m_footnoteEndnoteRefTag = 0;
2016 : }
2017 :
2018 : /** Output sal_Unicode* as a run text (<t>the text</t>).
2019 :
2020 : When bMove is true, update rBegin to point _after_ the end of the text +
2021 : 1, meaning that it skips one character after the text. This is to make
2022 : the switch in DocxAttributeOutput::RunText() nicer ;-)
2023 : */
2024 16342 : static bool impl_WriteRunText( FSHelperPtr pSerializer, sal_Int32 nTextToken,
2025 : const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true )
2026 : {
2027 16342 : const sal_Unicode *pBegin = rBegin;
2028 :
2029 : // skip one character after the end
2030 16342 : if ( bMove )
2031 3070 : rBegin = pEnd + 1;
2032 :
2033 16342 : if ( pBegin >= pEnd )
2034 2118 : return false; // we want to write at least one character
2035 :
2036 : // we have to add 'preserve' when starting/ending with space
2037 14224 : if ( *pBegin == ' ' || *( pEnd - 1 ) == ' ' )
2038 : {
2039 4178 : pSerializer->startElementNS( XML_w, nTextToken, FSNS( XML_xml, XML_space ), "preserve", FSEND );
2040 : }
2041 : else
2042 10046 : pSerializer->startElementNS( XML_w, nTextToken, FSEND );
2043 :
2044 14224 : pSerializer->writeEscaped( OUString( pBegin, pEnd - pBegin ) );
2045 :
2046 14224 : pSerializer->endElementNS( XML_w, nTextToken );
2047 :
2048 14224 : return true;
2049 : }
2050 :
2051 13272 : void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCharSet*/ )
2052 : {
2053 13272 : if( m_closeHyperlinkInThisRun )
2054 : {
2055 194 : m_closeHyperlinkInPreviousRun = true;
2056 : }
2057 13272 : m_bRunTextIsOn = true;
2058 : // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
2059 13272 : const sal_Unicode *pBegin = rText.getStr();
2060 13272 : const sal_Unicode *pEnd = pBegin + rText.getLength();
2061 :
2062 : // the text run is usually XML_t, with the exception of the deleted text
2063 13272 : sal_Int32 nTextToken = XML_t;
2064 13272 : if ( m_pRedlineData && m_pRedlineData->GetType() == nsRedlineType_t::REDLINE_DELETE )
2065 12 : nTextToken = XML_delText;
2066 :
2067 13272 : sal_Unicode prevUnicode = *pBegin;
2068 :
2069 647232 : for ( const sal_Unicode *pIt = pBegin; pIt < pEnd; ++pIt )
2070 : {
2071 633960 : switch ( *pIt )
2072 : {
2073 : case 0x09: // tab
2074 2980 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
2075 2980 : m_pSerializer->singleElementNS( XML_w, XML_tab, FSEND );
2076 2980 : prevUnicode = *pIt;
2077 2980 : break;
2078 : case 0x0b: // line break
2079 : {
2080 44 : if (impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt ) || (prevUnicode == *pIt))
2081 : {
2082 44 : m_pSerializer->singleElementNS( XML_w, XML_br, FSEND );
2083 44 : prevUnicode = *pIt;
2084 : }
2085 : }
2086 44 : break;
2087 : case 0x1E: //non-breaking hyphen
2088 2 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
2089 2 : m_pSerializer->singleElementNS( XML_w, XML_noBreakHyphen, FSEND );
2090 2 : prevUnicode = *pIt;
2091 2 : break;
2092 : case 0x1F: //soft (on demand) hyphen
2093 20 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
2094 20 : m_pSerializer->singleElementNS( XML_w, XML_softHyphen, FSEND );
2095 20 : prevUnicode = *pIt;
2096 20 : break;
2097 : default:
2098 630914 : if ( *pIt < 0x0020 ) // filter out the control codes
2099 : {
2100 24 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
2101 : OSL_TRACE( "Ignored control code %x in a text run.", *pIt );
2102 : }
2103 630914 : prevUnicode = *pIt;
2104 630914 : break;
2105 : }
2106 : }
2107 :
2108 13272 : impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
2109 13272 : }
2110 :
2111 0 : void DocxAttributeOutput::RawText( const OUString& /*rText*/, bool /*bForceUnicode*/, rtl_TextEncoding /*eCharSet*/ )
2112 : {
2113 : OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )" );
2114 0 : }
2115 :
2116 0 : void DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, sal_Int32 nPos, const SwFmtRuby& rRuby )
2117 : {
2118 : OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )" );
2119 0 : m_pSerializer->startElementNS( XML_w, XML_ruby, FSEND );
2120 0 : m_pSerializer->startElementNS( XML_w, XML_rubyPr, FSEND );
2121 : // hps
2122 : // hpsBaseText
2123 : // hpsRaise
2124 : // lid
2125 : lang::Locale aLocale( SwBreakIt::Get()->GetLocale(
2126 0 : rNode.GetLang( nPos ) ) );
2127 0 : OUString sLang( LanguageTag::convertToBcp47( aLocale) );
2128 : m_pSerializer->singleElementNS( XML_w, XML_lid,
2129 : FSNS( XML_w, XML_val ),
2130 0 : OUStringToOString( sLang, RTL_TEXTENCODING_UTF8 ).getStr( ), FSEND );
2131 :
2132 0 : OString sAlign ( "center" );
2133 0 : switch ( rRuby.GetAdjustment( ) )
2134 : {
2135 : case 0:
2136 0 : sAlign = OString( "left" );
2137 0 : break;
2138 : case 1:
2139 : // Defaults to center
2140 0 : break;
2141 : case 2:
2142 0 : sAlign = OString( "right" );
2143 0 : break;
2144 : case 3:
2145 0 : sAlign = OString( "distributeLetter" );
2146 0 : break;
2147 : case 4:
2148 0 : sAlign = OString( "distributeSpace" );
2149 0 : break;
2150 : default:
2151 0 : break;
2152 : }
2153 : m_pSerializer->singleElementNS( XML_w, XML_rubyAlign,
2154 0 : FSNS( XML_w, XML_val ), sAlign.getStr(), FSEND );
2155 0 : m_pSerializer->endElementNS( XML_w, XML_rubyPr );
2156 :
2157 0 : m_pSerializer->startElementNS( XML_w, XML_rt, FSEND );
2158 0 : StartRun( NULL );
2159 0 : StartRunProperties( );
2160 0 : SwWW8AttrIter aAttrIt( m_rExport, rNode );
2161 0 : aAttrIt.OutAttr( nPos, true );
2162 :
2163 0 : sal_uInt16 nStyle = m_rExport.GetId( rRuby.GetTxtRuby()->GetCharFmt() );
2164 0 : OString aStyleId(m_rExport.pStyles->GetStyleId(nStyle));
2165 : m_pSerializer->singleElementNS( XML_w, XML_rStyle,
2166 0 : FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
2167 :
2168 0 : EndRunProperties( NULL );
2169 0 : RunText( rRuby.GetText( ) );
2170 0 : EndRun( );
2171 0 : m_pSerializer->endElementNS( XML_w, XML_rt );
2172 :
2173 0 : m_pSerializer->startElementNS( XML_w, XML_rubyBase, FSEND );
2174 0 : StartRun( NULL );
2175 0 : }
2176 :
2177 0 : void DocxAttributeOutput::EndRuby()
2178 : {
2179 : OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()" );
2180 0 : EndRun( );
2181 0 : m_pSerializer->endElementNS( XML_w, XML_rubyBase );
2182 0 : m_pSerializer->endElementNS( XML_w, XML_ruby );
2183 0 : }
2184 :
2185 428 : bool DocxAttributeOutput::AnalyzeURL( const OUString& rUrl, const OUString& rTarget, OUString* pLinkURL, OUString* pMark )
2186 : {
2187 428 : bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
2188 :
2189 428 : if ( !pMark->isEmpty() )
2190 : {
2191 226 : OUString sURL = *pLinkURL;
2192 :
2193 226 : if ( bBookMarkOnly )
2194 196 : sURL = FieldString( ww::eHYPERLINK );
2195 : else
2196 30 : sURL = FieldString( ww::eHYPERLINK ) + "\"" + sURL + "\"";
2197 :
2198 226 : sURL += " \\l \"" + *pMark + "\"";
2199 :
2200 226 : if ( !rTarget.isEmpty() )
2201 0 : sURL += " \\n " + rTarget;
2202 :
2203 226 : *pLinkURL = sURL;
2204 : }
2205 :
2206 428 : return bBookMarkOnly;
2207 : }
2208 :
2209 428 : bool DocxAttributeOutput::StartURL( const OUString& rUrl, const OUString& rTarget )
2210 : {
2211 428 : OUString sMark;
2212 856 : OUString sUrl;
2213 :
2214 428 : bool bBookmarkOnly = AnalyzeURL( rUrl, rTarget, &sUrl, &sMark );
2215 :
2216 428 : m_hyperLinkAnchor = sMark;
2217 :
2218 428 : if ( !sMark.isEmpty() && !bBookmarkOnly )
2219 : {
2220 30 : m_rExport.OutputField( NULL, ww::eHYPERLINK, sUrl );
2221 : }
2222 : else
2223 : {
2224 : // Output a hyperlink XML element
2225 398 : m_pHyperlinkAttrList = m_pSerializer->createAttrList();
2226 :
2227 398 : if ( !bBookmarkOnly )
2228 : {
2229 202 : OString sId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
2230 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
2231 404 : sUrl, true ), RTL_TEXTENCODING_UTF8 );
2232 :
2233 202 : m_pHyperlinkAttrList->add( FSNS( XML_r, XML_id), sId.getStr());
2234 : }
2235 : else
2236 : {
2237 : // Is this a link to a sequence? Then try to replace that with a
2238 : // normal bookmark, as Word won't understand our special
2239 : // <seqname>!<index>|sequence syntax.
2240 196 : if (sMark.endsWith("|sequence"))
2241 : {
2242 4 : sal_Int32 nPos = sMark.indexOf('!');
2243 4 : if (nPos != -1)
2244 : {
2245 : // Extract <seqname>, the field instruction text has the name quoted.
2246 4 : OUString aSequenceName = sMark.copy(0, nPos);
2247 : // Extract <index>.
2248 4 : sal_uInt32 nIndex = sMark.copy(nPos + 1, sMark.getLength() - nPos - sizeof("|sequence")).toInt32();
2249 4 : std::map<OUString, std::vector<OString> >::iterator it = m_aSeqBookmarksNames.find(aSequenceName);
2250 4 : if (it != m_aSeqBookmarksNames.end())
2251 : {
2252 4 : std::vector<OString>& rNames = it->second;
2253 4 : if (rNames.size() > nIndex)
2254 : // We know the bookmark name for this sequence and this index, do the replacement.
2255 4 : sMark = OStringToOUString(rNames[nIndex], RTL_TEXTENCODING_UTF8);
2256 4 : }
2257 : }
2258 : }
2259 : m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ),
2260 196 : OUStringToOString( sMark, RTL_TEXTENCODING_UTF8 ).getStr( ) );
2261 : }
2262 :
2263 398 : OUString sTarget( rTarget );
2264 398 : if ( !sTarget.isEmpty() )
2265 : {
2266 0 : OString soTarget = OUStringToOString( sTarget, RTL_TEXTENCODING_UTF8 );
2267 0 : m_pHyperlinkAttrList->add(FSNS( XML_w, XML_tgtFrame ), soTarget.getStr());
2268 398 : }
2269 : }
2270 :
2271 856 : return true;
2272 : }
2273 :
2274 428 : bool DocxAttributeOutput::EndURL(bool const)
2275 : {
2276 428 : m_closeHyperlinkInThisRun = true;
2277 428 : if(m_startedHyperlink && m_hyperLinkAnchor != "" && m_hyperLinkAnchor.startsWith("_Toc"))
2278 : {
2279 176 : m_endPageRef = true;
2280 : }
2281 428 : return true;
2282 : }
2283 :
2284 88 : void DocxAttributeOutput::FieldVanish( const OUString& rTxt, ww::eField eType )
2285 : {
2286 88 : WriteField_Impl( NULL, eType, rTxt, WRITEFIELD_ALL );
2287 88 : }
2288 :
2289 : // The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
2290 : // 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
2291 : // 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
2292 31162 : void DocxAttributeOutput::Redline( const SwRedlineData* pRedlineData)
2293 : {
2294 31162 : if ( !pRedlineData )
2295 62278 : return;
2296 :
2297 46 : OString aId( OString::number( pRedlineData->GetSeqNo() ) );
2298 92 : const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
2299 92 : OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
2300 92 : OString aDate( DateTimeToOString( pRedlineData->GetTimeStamp() ) );
2301 :
2302 46 : switch( pRedlineData->GetType() )
2303 : {
2304 : case nsRedlineType_t::REDLINE_INSERT:
2305 12 : break;
2306 :
2307 : case nsRedlineType_t::REDLINE_DELETE:
2308 16 : break;
2309 :
2310 : case nsRedlineType_t::REDLINE_FORMAT:
2311 : m_pSerializer->startElementNS( XML_w, XML_rPrChange,
2312 : FSNS( XML_w, XML_id ), aId.getStr(),
2313 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
2314 : FSNS( XML_w, XML_date ), aDate.getStr(),
2315 4 : FSEND );
2316 :
2317 : // Check if there is any extra data stored in the redline object
2318 4 : if (pRedlineData->GetExtraData())
2319 : {
2320 4 : const SwRedlineExtraData* pExtraData = pRedlineData->GetExtraData();
2321 4 : const SwRedlineExtraData_FormattingChanges* pFormattingChanges = dynamic_cast<const SwRedlineExtraData_FormattingChanges*>(pExtraData);
2322 :
2323 : // Check if the extra data is of type 'formatting changes'
2324 4 : if (pFormattingChanges)
2325 : {
2326 : // Get the item set that holds all the changes properties
2327 4 : const SfxItemSet *pChangesSet = pFormattingChanges->GetItemSet();
2328 4 : if (pChangesSet)
2329 : {
2330 4 : m_pSerializer->mark();
2331 :
2332 4 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
2333 :
2334 : // The 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList' are used to hold information
2335 : // that should be collected by different properties in the core, and are all flushed together
2336 : // to the DOCX when the function 'WriteCollectedRunProperties' gets called.
2337 : // So we need to store the current status of these lists, so that we can revert back to them when
2338 : // we are done exporting the redline attributes.
2339 4 : ::sax_fastparser::FastAttributeList *pFontsAttrList_Original = m_pFontsAttrList;
2340 4 : ::sax_fastparser::FastAttributeList *pEastAsianLayoutAttrList_Original = m_pEastAsianLayoutAttrList;
2341 4 : ::sax_fastparser::FastAttributeList *pCharLangAttrList_Original = m_pCharLangAttrList;
2342 4 : m_pFontsAttrList = NULL;
2343 4 : m_pEastAsianLayoutAttrList = NULL;
2344 4 : m_pCharLangAttrList = NULL;
2345 :
2346 : // Output the redline item set
2347 4 : m_rExport.OutputItemSet( *pChangesSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
2348 :
2349 : // Write the collected run properties that are stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
2350 4 : WriteCollectedRunProperties();
2351 :
2352 : // Revert back the original values that were stored in 'm_pFontsAttrList', 'm_pEastAsianLayoutAttrList', 'm_pCharLangAttrList'
2353 4 : m_pFontsAttrList = pFontsAttrList_Original;
2354 4 : m_pEastAsianLayoutAttrList = pEastAsianLayoutAttrList_Original;
2355 4 : m_pCharLangAttrList = pCharLangAttrList_Original;
2356 :
2357 4 : m_pSerializer->endElementNS( XML_w, XML_rPr );
2358 :
2359 4 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
2360 : }
2361 : }
2362 : }
2363 4 : m_pSerializer->endElementNS( XML_w, XML_rPrChange );
2364 4 : break;
2365 :
2366 : case nsRedlineType_t::REDLINE_PARAGRAPH_FORMAT:
2367 : m_pSerializer->startElementNS( XML_w, XML_pPrChange,
2368 : FSNS( XML_w, XML_id ), aId.getStr(),
2369 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
2370 : FSNS( XML_w, XML_date ), aDate.getStr(),
2371 14 : FSEND );
2372 :
2373 : // Check if there is any extra data stored in the redline object
2374 14 : if (pRedlineData->GetExtraData())
2375 : {
2376 12 : const SwRedlineExtraData* pExtraData = pRedlineData->GetExtraData();
2377 12 : const SwRedlineExtraData_FormattingChanges* pFormattingChanges = dynamic_cast<const SwRedlineExtraData_FormattingChanges*>(pExtraData);
2378 :
2379 : // Check if the extra data is of type 'formatting changes'
2380 12 : if (pFormattingChanges)
2381 : {
2382 : // Get the item set that holds all the changes properties
2383 12 : const SfxItemSet *pChangesSet = pFormattingChanges->GetItemSet();
2384 12 : if (pChangesSet)
2385 : {
2386 12 : m_pSerializer->mark();
2387 :
2388 12 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
2389 :
2390 : // The 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList' are used to hold information
2391 : // that should be collected by different properties in the core, and are all flushed together
2392 : // to the DOCX when the function 'WriteCollectedParagraphProperties' gets called.
2393 : // So we need to store the current status of these lists, so that we can revert back to them when
2394 : // we are done exporting the redline attributes.
2395 12 : ::sax_fastparser::FastAttributeList *pFlyAttrList_Original = m_rExport.SdrExporter().getFlyAttrList();
2396 12 : ::sax_fastparser::FastAttributeList *pParagraphSpacingAttrList_Original = m_pParagraphSpacingAttrList;
2397 12 : m_rExport.SdrExporter().setFlyAttrList(NULL);
2398 12 : m_pParagraphSpacingAttrList = NULL;
2399 :
2400 : // Output the redline item set
2401 12 : m_rExport.OutputItemSet( *pChangesSet, true, false, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
2402 :
2403 : // Write the collected paragraph properties that are stored in 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList'
2404 12 : WriteCollectedParagraphProperties();
2405 :
2406 : // Revert back the original values that were stored in 'm_rExport.SdrExporter().getFlyAttrList()', 'm_pParagraphSpacingAttrList'
2407 12 : m_rExport.SdrExporter().setFlyAttrList(pFlyAttrList_Original);
2408 12 : m_pParagraphSpacingAttrList = pParagraphSpacingAttrList_Original;
2409 :
2410 12 : m_pSerializer->endElementNS( XML_w, XML_pPr );
2411 :
2412 12 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
2413 : }
2414 : }
2415 : }
2416 14 : m_pSerializer->endElementNS( XML_w, XML_pPrChange );
2417 14 : break;
2418 :
2419 : default:
2420 : SAL_WARN("sw.ww8", "Unhandled redline type for export " << pRedlineData->GetType());
2421 0 : break;
2422 46 : }
2423 : }
2424 :
2425 : // The difference between 'Redline' and 'StartRedline'+'EndRedline' is that:
2426 : // 'Redline' is used for tracked changes of formatting information of a run like Bold, Underline. (the '<w:rPrChange>' is inside the 'run' node)
2427 : // 'StartRedline' is used to output tracked changes of run insertion and deletion (the run is inside the '<w:ins>' node)
2428 18162 : void DocxAttributeOutput::StartRedline( const SwRedlineData * pRedlineData )
2429 : {
2430 18162 : if ( !pRedlineData )
2431 36294 : return;
2432 :
2433 : // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
2434 :
2435 30 : OString aId( OString::number( m_nRedlineId++ ) );
2436 :
2437 60 : const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
2438 60 : OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
2439 :
2440 60 : OString aDate( DateTimeToOString( pRedlineData->GetTimeStamp() ) );
2441 :
2442 30 : switch ( pRedlineData->GetType() )
2443 : {
2444 : case nsRedlineType_t::REDLINE_INSERT:
2445 : m_pSerializer->startElementNS( XML_w, XML_ins,
2446 : FSNS( XML_w, XML_id ), aId.getStr(),
2447 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
2448 : FSNS( XML_w, XML_date ), aDate.getStr(),
2449 12 : FSEND );
2450 12 : break;
2451 :
2452 : case nsRedlineType_t::REDLINE_DELETE:
2453 : m_pSerializer->startElementNS( XML_w, XML_del,
2454 : FSNS( XML_w, XML_id ), aId.getStr(),
2455 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
2456 : FSNS( XML_w, XML_date ), aDate.getStr(),
2457 14 : FSEND );
2458 14 : break;
2459 :
2460 : case nsRedlineType_t::REDLINE_FORMAT:
2461 : OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()" );
2462 : default:
2463 4 : break;
2464 30 : }
2465 : }
2466 :
2467 18162 : void DocxAttributeOutput::EndRedline( const SwRedlineData * pRedlineData )
2468 : {
2469 18162 : if ( !pRedlineData )
2470 36294 : return;
2471 :
2472 30 : switch ( pRedlineData->GetType() )
2473 : {
2474 : case nsRedlineType_t::REDLINE_INSERT:
2475 12 : m_pSerializer->endElementNS( XML_w, XML_ins );
2476 12 : break;
2477 :
2478 : case nsRedlineType_t::REDLINE_DELETE:
2479 14 : m_pSerializer->endElementNS( XML_w, XML_del );
2480 14 : break;
2481 :
2482 : case nsRedlineType_t::REDLINE_FORMAT:
2483 : OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()" );
2484 4 : break;
2485 : default:
2486 0 : break;
2487 : }
2488 : }
2489 :
2490 0 : void DocxAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
2491 : {
2492 : OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle )" );
2493 0 : }
2494 :
2495 12482 : void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
2496 : {
2497 12482 : OString aStyleId(m_rExport.pStyles->GetStyleId(nStyle));
2498 :
2499 12482 : m_pSerializer->singleElementNS( XML_w, XML_pStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
2500 12482 : }
2501 :
2502 20392 : static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist,
2503 : bool bWriteShadow = false, const table::BorderLine2* rStyleProps = NULL )
2504 : {
2505 : // Compute val attribute value
2506 : // Can be one of:
2507 : // single, double,
2508 : // basicWideOutline, basicWideInline
2509 : // OOXml also supports those types of borders, but we'll try to play with the first ones.
2510 : // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
2511 : // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
2512 20392 : const char* pVal = "nil";
2513 20392 : if ( pBorderLine && !pBorderLine->isEmpty( ) )
2514 : {
2515 15778 : switch (pBorderLine->GetBorderLineStyle())
2516 : {
2517 : case table::BorderLineStyle::SOLID:
2518 15622 : pVal = ( sal_Char* )"single";
2519 15622 : break;
2520 : case table::BorderLineStyle::DOTTED:
2521 0 : pVal = ( sal_Char* )"dotted";
2522 0 : break;
2523 : case table::BorderLineStyle::DASHED:
2524 16 : pVal = ( sal_Char* )"dashed";
2525 16 : break;
2526 : case table::BorderLineStyle::DOUBLE:
2527 20 : pVal = ( sal_Char* )"double";
2528 20 : break;
2529 : case table::BorderLineStyle::THINTHICK_SMALLGAP:
2530 10 : pVal = ( sal_Char* )"thinThickSmallGap";
2531 10 : break;
2532 : case table::BorderLineStyle::THINTHICK_MEDIUMGAP:
2533 0 : pVal = ( sal_Char* )"thinThickMediumGap";
2534 0 : break;
2535 : case table::BorderLineStyle::THINTHICK_LARGEGAP:
2536 0 : pVal = ( sal_Char* )"thinThickLargeGap";
2537 0 : break;
2538 : case table::BorderLineStyle::THICKTHIN_SMALLGAP:
2539 14 : pVal = ( sal_Char* )"thickThinSmallGap";
2540 14 : break;
2541 : case table::BorderLineStyle::THICKTHIN_MEDIUMGAP:
2542 0 : pVal = ( sal_Char* )"thickThinMediumGap";
2543 0 : break;
2544 : case table::BorderLineStyle::THICKTHIN_LARGEGAP:
2545 36 : pVal = ( sal_Char* )"thickThinLargeGap";
2546 36 : break;
2547 : case table::BorderLineStyle::EMBOSSED:
2548 0 : pVal = ( sal_Char* )"threeDEmboss";
2549 0 : break;
2550 : case table::BorderLineStyle::ENGRAVED:
2551 0 : pVal = ( sal_Char* )"threeDEngrave";
2552 0 : break;
2553 : case table::BorderLineStyle::OUTSET:
2554 24 : pVal = ( sal_Char* )"outset";
2555 24 : break;
2556 : case table::BorderLineStyle::INSET:
2557 0 : pVal = ( sal_Char* )"inset";
2558 0 : break;
2559 : case table::BorderLineStyle::FINE_DASHED:
2560 36 : pVal = ( sal_Char* )"dashSmallGap";
2561 36 : break;
2562 : case table::BorderLineStyle::NONE:
2563 : default:
2564 0 : break;
2565 : }
2566 : }
2567 4614 : else if( rStyleProps == NULL )
2568 : // no line, and no line set by the style either:
2569 : // there is no need to write the property
2570 15372 : return;
2571 :
2572 : // compare the properties with the theme properties before writing them:
2573 : // if they are equal, it means that they were style-defined and there is
2574 : // no need to write them.
2575 58788 : if( rStyleProps != NULL && pBorderLine && !pBorderLine->isEmpty() &&
2576 24222 : pBorderLine->GetBorderLineStyle() == rStyleProps->LineStyle &&
2577 65404 : pBorderLine->GetColor() == rStyleProps->Color &&
2578 8002 : pBorderLine->GetWidth() == convertMm100ToTwip( rStyleProps->LineWidth ) )
2579 7804 : return;
2580 :
2581 8804 : FastAttributeList* pAttr = pSerializer->createAttrList();
2582 8804 : pAttr->add( FSNS( XML_w, XML_val ), OString( pVal ) );
2583 :
2584 8804 : if ( pBorderLine && !pBorderLine->isEmpty() )
2585 : {
2586 : // Compute the sz attribute
2587 :
2588 : double const fConverted( ::editeng::ConvertBorderWidthToWord(
2589 7974 : pBorderLine->GetBorderLineStyle(), pBorderLine->GetWidth()));
2590 : // The unit is the 8th of point
2591 7974 : sal_Int32 nWidth = sal_Int32( fConverted / 2.5 );
2592 7974 : sal_uInt16 nMinWidth = 2;
2593 7974 : sal_uInt16 nMaxWidth = 96;
2594 :
2595 7974 : if ( nWidth > nMaxWidth )
2596 0 : nWidth = nMaxWidth;
2597 7974 : else if ( nWidth < nMinWidth )
2598 24 : nWidth = nMinWidth;
2599 :
2600 7974 : pAttr->add( FSNS( XML_w, XML_sz ), OString::number( nWidth ) );
2601 :
2602 : // Get the distance (in pt)
2603 7974 : pAttr->add( FSNS( XML_w, XML_space ), OString::number( nDist / 20 ) );
2604 :
2605 : // Get the color code as an RRGGBB hex value
2606 7974 : OString sColor( msfilter::util::ConvertColor( pBorderLine->GetColor( ) ) );
2607 7974 : pAttr->add( FSNS( XML_w, XML_color ), sColor );
2608 : }
2609 :
2610 8804 : if (bWriteShadow)
2611 : {
2612 : // Set the shadow value
2613 44 : pAttr->add( FSNS( XML_w, XML_shadow ), "1" );
2614 : }
2615 :
2616 8804 : XFastAttributeListRef xAttrs( pAttr );
2617 8804 : pSerializer->singleElementNS( XML_w, elementToken, xAttrs );
2618 : }
2619 :
2620 154 : static OutputBorderOptions lcl_getTableDefaultBorderOptions(bool bEcma)
2621 : {
2622 154 : OutputBorderOptions rOptions;
2623 :
2624 154 : rOptions.tag = XML_tblBorders;
2625 154 : rOptions.bUseStartEnd = !bEcma;
2626 154 : rOptions.bWriteTag = true;
2627 154 : rOptions.bWriteInsideHV = true;
2628 154 : rOptions.bWriteDistance = false;
2629 154 : rOptions.aShadowLocation = SVX_SHADOW_NONE;
2630 154 : rOptions.bCheckDistanceSize = false;
2631 :
2632 154 : return rOptions;
2633 : }
2634 :
2635 3002 : static OutputBorderOptions lcl_getTableCellBorderOptions(bool bEcma)
2636 : {
2637 3002 : OutputBorderOptions rOptions;
2638 :
2639 3002 : rOptions.tag = XML_tcBorders;
2640 3002 : rOptions.bUseStartEnd = !bEcma;
2641 3002 : rOptions.bWriteTag = true;
2642 3002 : rOptions.bWriteInsideHV = true;
2643 3002 : rOptions.bWriteDistance = false;
2644 3002 : rOptions.aShadowLocation = SVX_SHADOW_NONE;
2645 3002 : rOptions.bCheckDistanceSize = false;
2646 :
2647 3002 : return rOptions;
2648 : }
2649 :
2650 374 : static OutputBorderOptions lcl_getBoxBorderOptions()
2651 : {
2652 374 : OutputBorderOptions rOptions;
2653 :
2654 374 : rOptions.tag = XML_pBdr;
2655 374 : rOptions.bUseStartEnd = false;
2656 374 : rOptions.bWriteTag = false;
2657 374 : rOptions.bWriteInsideHV = false;
2658 374 : rOptions.bWriteDistance = true;
2659 374 : rOptions.aShadowLocation = SVX_SHADOW_NONE;
2660 374 : rOptions.bCheckDistanceSize = false;
2661 :
2662 374 : return rOptions;
2663 : }
2664 :
2665 32 : static bool boxHasLineLargerThan31(const SvxBoxItem& rBox)
2666 : {
2667 : return (
2668 56 : ( rBox.GetDistance( BOX_LINE_TOP ) / 20 ) > 31 ||
2669 32 : ( rBox.GetDistance( BOX_LINE_LEFT ) / 20 ) > 31 ||
2670 44 : ( rBox.GetDistance( BOX_LINE_BOTTOM ) / 20 ) > 31 ||
2671 4 : ( rBox.GetDistance( BOX_LINE_RIGHT ) / 20 ) > 31
2672 32 : );
2673 : }
2674 :
2675 3514 : static void impl_borders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, const OutputBorderOptions& rOptions, PageMargins* pageMargins,
2676 : std::map<sal_uInt16, css::table::BorderLine2> &rTableStyleConf )
2677 : {
2678 : static const sal_uInt16 aBorders[] =
2679 : {
2680 : BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
2681 : };
2682 :
2683 : const sal_Int32 aXmlElements[] =
2684 : {
2685 : XML_top,
2686 : rOptions.bUseStartEnd ? XML_start : XML_left,
2687 : XML_bottom,
2688 : rOptions.bUseStartEnd ? XML_end : XML_right
2689 3514 : };
2690 3514 : bool tagWritten = false;
2691 3514 : const sal_uInt16* pBrd = aBorders;
2692 :
2693 3514 : bool bExportDistanceFromPageEdge = false;
2694 3514 : if ( rOptions.bCheckDistanceSize == true && boxHasLineLargerThan31(rBox) == true )
2695 : {
2696 : // The distance is larger than '31'. This cannot be exported as 'distance from text'.
2697 : // Instead - it should be exported as 'distance from page edge'.
2698 : // This is based on http://wiki.openoffice.org/wiki/Writer/MSInteroperability/PageBorder
2699 : // Specifically 'export case #2'
2700 14 : bExportDistanceFromPageEdge = true;
2701 : }
2702 :
2703 3514 : bool bWriteInsideH = false;
2704 3514 : bool bWriteInsideV = false;
2705 17570 : for( int i = 0; i < 4; ++i, ++pBrd )
2706 : {
2707 14056 : const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
2708 14056 : const table::BorderLine2 *aStyleProps = NULL;
2709 14056 : if( rTableStyleConf.find( *pBrd ) != rTableStyleConf.end() )
2710 5952 : aStyleProps = &rTableStyleConf[ *pBrd ];
2711 :
2712 14056 : if (!tagWritten && rOptions.bWriteTag)
2713 : {
2714 3156 : pSerializer->startElementNS( XML_w, rOptions.tag, FSEND );
2715 3156 : tagWritten = true;
2716 : }
2717 :
2718 14056 : bool bWriteShadow = false;
2719 14056 : if (rOptions.aShadowLocation == SVX_SHADOW_NONE)
2720 : {
2721 : // The border has no shadow
2722 : }
2723 40 : else if (rOptions.aShadowLocation == SVX_SHADOW_BOTTOMRIGHT)
2724 : {
2725 : // Special case of 'Bottom-Right' shadow:
2726 : // If the shadow location is 'Bottom-Right' - then turn on the shadow
2727 : // for ALL the sides. This is because in Word - if you select a shadow
2728 : // for a border - it turn on the shadow for ALL the sides (but shows only
2729 : // the bottom-right one).
2730 : // This is so that no information will be lost if passed through LibreOffice
2731 40 : bWriteShadow = true;
2732 : }
2733 : else
2734 : {
2735 : // If there is a shadow, and it's not the regular 'Bottom-Right',
2736 : // then write only the 'shadowed' sides of the border
2737 0 : if (
2738 0 : ( ( rOptions.aShadowLocation == SVX_SHADOW_TOPLEFT || rOptions.aShadowLocation == SVX_SHADOW_TOPRIGHT ) && *pBrd == BOX_LINE_TOP ) ||
2739 0 : ( ( rOptions.aShadowLocation == SVX_SHADOW_TOPLEFT || rOptions.aShadowLocation == SVX_SHADOW_BOTTOMLEFT ) && *pBrd == BOX_LINE_LEFT ) ||
2740 0 : ( ( rOptions.aShadowLocation == SVX_SHADOW_BOTTOMLEFT || rOptions.aShadowLocation == SVX_SHADOW_BOTTOMRIGHT ) && *pBrd == BOX_LINE_BOTTOM) ||
2741 0 : ( ( rOptions.aShadowLocation == SVX_SHADOW_TOPRIGHT || rOptions.aShadowLocation == SVX_SHADOW_BOTTOMRIGHT ) && *pBrd == BOX_LINE_RIGHT )
2742 : )
2743 : {
2744 0 : bWriteShadow = true;
2745 : }
2746 : }
2747 :
2748 14056 : sal_uInt16 nDist = 0;
2749 14056 : if (rOptions.bWriteDistance)
2750 : {
2751 1432 : if (bExportDistanceFromPageEdge)
2752 : {
2753 : // Export 'Distance from Page Edge'
2754 56 : if ( *pBrd == BOX_LINE_TOP)
2755 14 : nDist = pageMargins->nPageMarginTop - rBox.GetDistance( *pBrd );
2756 42 : else if ( *pBrd == BOX_LINE_LEFT)
2757 14 : nDist = pageMargins->nPageMarginLeft - rBox.GetDistance( *pBrd );
2758 28 : else if ( *pBrd == BOX_LINE_BOTTOM)
2759 14 : nDist = pageMargins->nPageMarginBottom - rBox.GetDistance( *pBrd );
2760 14 : else if ( *pBrd == BOX_LINE_RIGHT)
2761 14 : nDist = pageMargins->nPageMarginRight - rBox.GetDistance( *pBrd );
2762 : }
2763 : else
2764 : {
2765 : // Export 'Distance from text'
2766 1376 : nDist = rBox.GetDistance( *pBrd );
2767 : }
2768 : }
2769 :
2770 14056 : impl_borderLine( pSerializer, aXmlElements[i], pLn, nDist, bWriteShadow, aStyleProps );
2771 :
2772 : // When exporting default borders, we need to export these 2 attr
2773 14056 : if ( rOptions.bWriteInsideHV) {
2774 12624 : if ( i == 2 )
2775 3156 : bWriteInsideH = true;
2776 9468 : else if ( i == 3 )
2777 3156 : bWriteInsideV = true;
2778 : }
2779 : }
2780 3514 : if (bWriteInsideH)
2781 : {
2782 3156 : const table::BorderLine2 *aStyleProps = NULL;
2783 3156 : if( rTableStyleConf.find( BOX_LINE_BOTTOM ) != rTableStyleConf.end() )
2784 1494 : aStyleProps = &rTableStyleConf[ BOX_LINE_BOTTOM ];
2785 3156 : impl_borderLine( pSerializer, XML_insideH, rBox.GetLine(BOX_LINE_BOTTOM), 0, false, aStyleProps );
2786 : }
2787 3514 : if (bWriteInsideV)
2788 : {
2789 3156 : const table::BorderLine2 *aStyleProps = NULL;
2790 3156 : if( rTableStyleConf.find( BOX_LINE_RIGHT ) != rTableStyleConf.end() )
2791 1482 : aStyleProps = &rTableStyleConf[ BOX_LINE_RIGHT ];
2792 3156 : impl_borderLine( pSerializer, XML_insideV, rBox.GetLine(BOX_LINE_RIGHT), 0, false, aStyleProps );
2793 : }
2794 3514 : if (tagWritten && rOptions.bWriteTag) {
2795 3156 : pSerializer->endElementNS( XML_w, rOptions.tag );
2796 : }
2797 3514 : }
2798 :
2799 3266 : static void impl_cellMargins( FSHelperPtr pSerializer, const SvxBoxItem& rBox, sal_Int32 tag, bool bUseStartEnd = false, const SvxBoxItem* pDefaultMargins = 0)
2800 : {
2801 : static const sal_uInt16 aBorders[] =
2802 : {
2803 : BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
2804 : };
2805 :
2806 : const sal_Int32 aXmlElements[] =
2807 : {
2808 : XML_top,
2809 : bUseStartEnd ? XML_start : XML_left,
2810 : XML_bottom,
2811 : bUseStartEnd ? XML_end : XML_right
2812 3266 : };
2813 3266 : bool tagWritten = false;
2814 3266 : const sal_uInt16* pBrd = aBorders;
2815 16330 : for( int i = 0; i < 4; ++i, ++pBrd )
2816 : {
2817 13064 : sal_Int32 nDist = sal_Int32( rBox.GetDistance( *pBrd ) );
2818 :
2819 13064 : if ( aBorders[i] == BOX_LINE_LEFT ) {
2820 : // Office's cell margin is measured from the right of the border.
2821 : // While LO's cell spacing is measured from the center of the border.
2822 : // So we add half left-border width to tblIndent value
2823 3266 : const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
2824 3266 : if (pLn)
2825 2562 : nDist -= pLn->GetWidth() * 0.5;
2826 : }
2827 :
2828 13064 : if (pDefaultMargins)
2829 : {
2830 : // Skip output if cell margin == table default margin
2831 12008 : if (sal_Int32( pDefaultMargins->GetDistance( *pBrd ) ) == nDist)
2832 9598 : continue;
2833 : }
2834 :
2835 3466 : if (!tagWritten) {
2836 2674 : pSerializer->startElementNS( XML_w, tag, FSEND );
2837 2674 : tagWritten = true;
2838 : }
2839 3466 : pSerializer->singleElementNS( XML_w, aXmlElements[i],
2840 : FSNS( XML_w, XML_w ), OString::number( nDist ).getStr( ),
2841 : FSNS( XML_w, XML_type ), "dxa",
2842 6932 : FSEND );
2843 : }
2844 3266 : if (tagWritten) {
2845 2674 : pSerializer->endElementNS( XML_w, tag );
2846 : }
2847 3266 : }
2848 :
2849 3002 : void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2850 : {
2851 3002 : m_pSerializer->startElementNS( XML_w, XML_tcPr, FSEND );
2852 :
2853 3002 : const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
2854 :
2855 3002 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
2856 :
2857 : // Output any table cell redlines if there are any attached to this specific cell
2858 3002 : TableCellRedline( pTableTextNodeInfoInner );
2859 :
2860 : // Cell preferred width
2861 3002 : SwTwips nWidth = GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() );
2862 3002 : if ( pTableTextNodeInfoInner->getCell() )
2863 1720 : nWidth = nWidth - GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() - 1 );
2864 : m_pSerializer->singleElementNS( XML_w, XML_tcW,
2865 : FSNS( XML_w, XML_w ), OString::number( nWidth ).getStr( ),
2866 : FSNS( XML_w, XML_type ), "dxa",
2867 3002 : FSEND );
2868 :
2869 : // Horizontal spans
2870 3002 : const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
2871 3002 : SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
2872 3002 : sal_uInt32 nCell = pTableTextNodeInfoInner->getCell();
2873 3002 : const SwWriteTableCells *tableCells = &pRow->GetCells();
2874 3002 : if (nCell < tableCells->size() )
2875 : {
2876 3002 : const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
2877 :
2878 3002 : sal_uInt16 nColSpan = pCell->GetColSpan();
2879 3002 : if ( nColSpan > 1 )
2880 : m_pSerializer->singleElementNS( XML_w, XML_gridSpan,
2881 : FSNS( XML_w, XML_val ), OString::number( nColSpan ).getStr(),
2882 118 : FSEND );
2883 : }
2884 :
2885 : // Vertical merges
2886 3002 : long vSpan = pTblBox->getRowSpan( );
2887 3002 : if ( vSpan > 1 )
2888 : {
2889 : m_pSerializer->singleElementNS( XML_w, XML_vMerge,
2890 : FSNS( XML_w, XML_val ), "restart",
2891 12 : FSEND );
2892 : }
2893 2990 : else if ( vSpan < 0 )
2894 : {
2895 : m_pSerializer->singleElementNS( XML_w, XML_vMerge,
2896 : FSNS( XML_w, XML_val ), "continue",
2897 12 : FSEND );
2898 : }
2899 :
2900 3002 : if (const SfxGrabBagItem* pItem = sw::util::HasItem<SfxGrabBagItem>(pTblBox->GetFrmFmt()->GetAttrSet(), RES_FRMATR_GRABBAG))
2901 : {
2902 3002 : const std::map<OUString, uno::Any>& rGrabBag = pItem->GetGrabBag();
2903 3002 : std::map<OUString, uno::Any>::const_iterator it = rGrabBag.find("CellCnfStyle");
2904 3002 : if (it != rGrabBag.end())
2905 : {
2906 16 : uno::Sequence<beans::PropertyValue> aAttributes = it->second.get< uno::Sequence<beans::PropertyValue> >();
2907 16 : m_pTableStyleExport->CnfStyle(aAttributes);
2908 : }
2909 : }
2910 :
2911 :
2912 3002 : const SvxBoxItem& rBox = pTblBox->GetFrmFmt( )->GetBox( );
2913 3002 : const SvxBoxItem& rDefaultBox = (*tableFirstCells.rbegin())->getTableBox( )->GetFrmFmt( )->GetBox( );
2914 : {
2915 : // The cell borders
2916 3002 : impl_borders( m_pSerializer, rBox, lcl_getTableCellBorderOptions(bEcma), NULL, m_aTableStyleConf );
2917 : }
2918 :
2919 3002 : TableBackgrounds( pTableTextNodeInfoInner );
2920 :
2921 : {
2922 : // Cell margins
2923 3002 : impl_cellMargins( m_pSerializer, rBox, XML_tcMar, !bEcma, &rDefaultBox );
2924 : }
2925 :
2926 3002 : TableVerticalCell( pTableTextNodeInfoInner );
2927 :
2928 3002 : m_pSerializer->endElementNS( XML_w, XML_tcPr );
2929 3002 : }
2930 :
2931 274 : void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2932 : {
2933 274 : sal_uInt32 nPageSize = 0;
2934 274 : bool bRelBoxSize = false;
2935 :
2936 : // Create the SwWriteTable instance to use col spans (and maybe other infos)
2937 274 : GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
2938 :
2939 274 : const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
2940 274 : const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
2941 274 : SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
2942 :
2943 274 : const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
2944 274 : if( pLayout && pLayout->IsExportable() )
2945 0 : m_pTableWrt = new SwWriteTable( pLayout );
2946 : else
2947 : m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
2948 274 : (sal_uInt16)nTblSz, false);
2949 274 : }
2950 :
2951 264 : void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2952 : {
2953 : // In case any paragraph SDT's are open, close them here.
2954 264 : EndParaSdtBlock();
2955 :
2956 264 : m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND );
2957 :
2958 264 : tableFirstCells.push_back(pTableTextNodeInfoInner);
2959 :
2960 264 : InitTableHelper( pTableTextNodeInfoInner );
2961 264 : TableDefinition( pTableTextNodeInfoInner );
2962 264 : }
2963 :
2964 264 : void DocxAttributeOutput::EndTable()
2965 : {
2966 264 : m_pSerializer->endElementNS( XML_w, XML_tbl );
2967 :
2968 264 : if ( m_tableReference->m_nTableDepth > 0 )
2969 264 : --m_tableReference->m_nTableDepth;
2970 :
2971 264 : tableFirstCells.pop_back();
2972 :
2973 : // We closed the table; if it is a nested table, the cell that contains it
2974 : // still continues
2975 : // set to true only if we were in a nested table, not otherwise.
2976 264 : if( 0 != tableFirstCells.size() )
2977 28 : m_tableReference->m_bTableCellOpen = true;
2978 :
2979 : // Cleans the table helper
2980 264 : delete m_pTableWrt, m_pTableWrt = NULL;
2981 :
2982 264 : m_aTableStyleConf.clear();
2983 264 : }
2984 :
2985 1282 : void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
2986 : {
2987 1282 : m_pSerializer->startElementNS( XML_w, XML_tr, FSEND );
2988 :
2989 : // Output the row properties
2990 1282 : m_pSerializer->startElementNS( XML_w, XML_trPr, FSEND );
2991 :
2992 : // Header row: tblHeader
2993 1282 : const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
2994 1282 : if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
2995 : m_pSerializer->singleElementNS( XML_w, XML_tblHeader,
2996 : FSNS( XML_w, XML_val ), "true",
2997 4 : FSEND );
2998 :
2999 1282 : TableRowRedline( pTableTextNodeInfoInner );
3000 1282 : TableHeight( pTableTextNodeInfoInner );
3001 1282 : TableCanSplit( pTableTextNodeInfoInner );
3002 :
3003 1282 : const SwTableBox *pTableBox = pTableTextNodeInfoInner->getTableBox();
3004 1282 : const SwTableLine* pTableLine = pTableBox->GetUpper();
3005 1282 : if (const SfxGrabBagItem* pItem = sw::util::HasItem<SfxGrabBagItem>(pTableLine->GetFrmFmt()->GetAttrSet(), RES_FRMATR_GRABBAG))
3006 : {
3007 1282 : const std::map<OUString, uno::Any>& rGrabBag = pItem->GetGrabBag();
3008 1282 : std::map<OUString, uno::Any>::const_iterator it = rGrabBag.find("RowCnfStyle");
3009 1282 : if (it != rGrabBag.end())
3010 : {
3011 38 : uno::Sequence<beans::PropertyValue> aAttributes = it->second.get< uno::Sequence<beans::PropertyValue> >();
3012 38 : m_pTableStyleExport->CnfStyle(aAttributes);
3013 : }
3014 : }
3015 :
3016 :
3017 1282 : m_pSerializer->endElementNS( XML_w, XML_trPr );
3018 1282 : }
3019 :
3020 1282 : void DocxAttributeOutput::EndTableRow( )
3021 : {
3022 1282 : m_pSerializer->endElementNS( XML_w, XML_tr );
3023 1282 : }
3024 :
3025 3002 : void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3026 : {
3027 3002 : if ( !m_pTableWrt )
3028 10 : InitTableHelper( pTableTextNodeInfoInner );
3029 :
3030 3002 : m_pSerializer->startElementNS( XML_w, XML_tc, FSEND );
3031 :
3032 : // Write the cell properties here
3033 3002 : TableCellProperties( pTableTextNodeInfoInner );
3034 :
3035 3002 : m_tableReference->m_bTableCellOpen = true;
3036 3002 : }
3037 :
3038 3002 : void DocxAttributeOutput::EndTableCell( )
3039 : {
3040 3002 : if (m_tableReference->m_bTableCellParaSdtOpen)
3041 52 : EndParaSdtBlock();
3042 :
3043 3002 : m_pSerializer->endElementNS( XML_w, XML_tc );
3044 :
3045 3002 : m_bBtLr = false;
3046 3002 : m_tableReference->m_bTableCellOpen = false;
3047 3002 : m_tableReference->m_bTableCellParaSdtOpen = false;
3048 3002 : }
3049 :
3050 3360 : void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
3051 : {
3052 3360 : }
3053 :
3054 0 : void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
3055 : {
3056 0 : }
3057 :
3058 : /// Does the same as comphelper::string::padToLength(), but extends the start, not the end.
3059 254 : OString lcl_padStartToLength(OString const & aString, sal_Int32 nLen, sal_Char cFill)
3060 : {
3061 254 : if (nLen > aString.getLength())
3062 : {
3063 254 : sal_Int32 nDiff = nLen - aString.getLength();
3064 254 : OStringBuffer aBuffer;
3065 254 : comphelper::string::padToLength(aBuffer, nDiff, cFill);
3066 254 : aBuffer.append(aString);
3067 254 : return aBuffer.makeStringAndClear();
3068 : }
3069 : else
3070 0 : return aString;
3071 : }
3072 :
3073 264 : void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3074 : {
3075 264 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
3076 :
3077 : // Write the table properties
3078 264 : m_pSerializer->startElementNS( XML_w, XML_tblPr, FSEND );
3079 :
3080 : static const sal_Int32 aOrder[] =
3081 : {
3082 : FSNS( XML_w, XML_tblStyle ),
3083 : FSNS( XML_w, XML_tblpPr ),
3084 : FSNS( XML_w, XML_tblOverlap ),
3085 : FSNS( XML_w, XML_bidiVisual ),
3086 : FSNS( XML_w, XML_tblStyleRowBandSize ),
3087 : FSNS( XML_w, XML_tblStyleColBandSize ),
3088 : FSNS( XML_w, XML_tblW ),
3089 : FSNS( XML_w, XML_jc ),
3090 : FSNS( XML_w, XML_tblCellSpacing ),
3091 : FSNS( XML_w, XML_tblInd ),
3092 : FSNS( XML_w, XML_tblBorders ),
3093 : FSNS( XML_w, XML_shd ),
3094 : FSNS( XML_w, XML_tblLayout ),
3095 : FSNS( XML_w, XML_tblCellMar ),
3096 : FSNS( XML_w, XML_tblLook ),
3097 : FSNS( XML_w, XML_tblPrChange )
3098 : };
3099 :
3100 : // postpone the output so that we can later []
3101 : // prepend the properties before the run
3102 264 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
3103 264 : uno::Sequence< sal_Int32 > aSeqOrder( len );
3104 4488 : for ( sal_Int32 i = 0; i < len; i++ )
3105 4224 : aSeqOrder[i] = aOrder[i];
3106 :
3107 264 : m_pSerializer->mark( aSeqOrder );
3108 :
3109 264 : sal_uInt32 nPageSize = 0;
3110 264 : const char* widthType = "dxa";
3111 264 : bool bRelBoxSize = false;
3112 :
3113 : // If actual width of table is relative it should export is as "pct".`
3114 264 : const SwTable *pTable = pTableTextNodeInfoInner->getTable();
3115 264 : SwFrmFmt *pTblFmt = pTable->GetFrmFmt( );
3116 264 : const SwFmtFrmSize &rSize = pTblFmt->GetFrmSize();
3117 264 : int nWidthPercent = rSize.GetWidthPercent();
3118 528 : uno::Reference<beans::XPropertySet> xPropertySet(SwXTextTables::GetObject(const_cast<SwFrmFmt&>(*pTable->GetFrmFmt( ))),uno::UNO_QUERY);
3119 264 : bool isWidthRelative = false;
3120 264 : xPropertySet->getPropertyValue("IsWidthRelative") >>= isWidthRelative;
3121 :
3122 264 : if(isWidthRelative)
3123 : {
3124 : /**
3125 : * As per ECMA Specification : ECMA-376, Second Edition, Part 1 - Fundamentals And Markup Language Reference [ 17.18.90 ST_TblWidth (Table Width Units)]
3126 : * http://www.schemacentral.com/sc/ooxml/a-w_type-7.html
3127 : *
3128 : * Fiftieths of a Percent :
3129 : * http://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/
3130 : * pct Width is in Fiftieths of a Percent
3131 : *
3132 : * ex. If the Table width is 50% then
3133 : * Width in Fiftieths of a percent is (50 * 50) % or 0.5 * 5000 = 2500pct
3134 : **/
3135 46 : nPageSize = nWidthPercent * 50 ;
3136 46 : widthType = "pct" ;
3137 : }
3138 : else
3139 : {
3140 : // Create the SwWriteTable instance to use col spans (and maybe other infos)
3141 218 : GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
3142 218 : if(nPageSize == 0)
3143 0 : widthType = "auto";
3144 : }
3145 :
3146 : // Output the table preferred width
3147 : m_pSerializer->singleElementNS( XML_w, XML_tblW,
3148 : FSNS( XML_w, XML_w ), OString::number( nPageSize ).getStr( ),
3149 : FSNS( XML_w, XML_type ), widthType,
3150 264 : FSEND );
3151 :
3152 : // Look for the table style property in the table grab bag
3153 : std::map<OUString, com::sun::star::uno::Any> aGrabBag =
3154 528 : sw::util::HasItem<SfxGrabBagItem>( pTblFmt->GetAttrSet(), RES_FRMATR_GRABBAG )->GetGrabBag();
3155 :
3156 : // We should clear the TableStyle map. In case of Table inside multiple tables it contains the
3157 : // table border style of the previous table.
3158 264 : if (! m_aTableStyleConf.empty())
3159 6 : m_aTableStyleConf.clear();
3160 :
3161 : // Extract properties from grab bag
3162 264 : std::map<OUString, com::sun::star::uno::Any>::iterator aGrabBagElement;
3163 1120 : for( aGrabBagElement = aGrabBag.begin(); aGrabBagElement != aGrabBag.end(); ++aGrabBagElement )
3164 : {
3165 856 : if( aGrabBagElement->first == "TableStyleName")
3166 : {
3167 120 : OString sStyleName = OUStringToOString( aGrabBagElement->second.get<OUString>(), RTL_TEXTENCODING_UTF8 );
3168 : m_pSerializer->singleElementNS( XML_w, XML_tblStyle,
3169 : FSNS( XML_w, XML_val ), sStyleName.getStr(),
3170 120 : FSEND );
3171 : }
3172 736 : else if( aGrabBagElement->first == "TableStyleTopBorder" )
3173 110 : m_aTableStyleConf[ BOX_LINE_TOP ] = aGrabBagElement->second.get<table::BorderLine2>();
3174 626 : else if( aGrabBagElement->first == "TableStyleBottomBorder" )
3175 110 : m_aTableStyleConf[ BOX_LINE_BOTTOM ] = aGrabBagElement->second.get<table::BorderLine2>();
3176 516 : else if( aGrabBagElement->first == "TableStyleLeftBorder" )
3177 108 : m_aTableStyleConf[ BOX_LINE_LEFT ] = aGrabBagElement->second.get<table::BorderLine2>();
3178 408 : else if( aGrabBagElement->first == "TableStyleRightBorder" )
3179 108 : m_aTableStyleConf[ BOX_LINE_RIGHT ] = aGrabBagElement->second.get<table::BorderLine2>();
3180 300 : else if (aGrabBagElement->first == "TableStyleLook")
3181 : {
3182 254 : FastAttributeList* pAttributeList = m_pSerializer->createAttrList();
3183 254 : uno::Sequence<beans::PropertyValue> aAttributeList = aGrabBagElement->second.get< uno::Sequence<beans::PropertyValue> >();
3184 :
3185 1648 : for (sal_Int32 i = 0; i < aAttributeList.getLength(); ++i)
3186 : {
3187 1394 : if (aAttributeList[i].Name == "val")
3188 254 : pAttributeList->add(FSNS(XML_w, XML_val), lcl_padStartToLength(OString::number(aAttributeList[i].Value.get<sal_Int32>(), 16), 4, '0'));
3189 : else
3190 : {
3191 : static DocxStringTokenMap const aTokens[] =
3192 : {
3193 : {"firstRow", XML_firstRow},
3194 : {"lastRow", XML_lastRow},
3195 : {"firstColumn", XML_firstColumn},
3196 : {"lastColumn", XML_lastColumn},
3197 : {"noHBand", XML_noHBand},
3198 : {"noVBand", XML_noVBand},
3199 : {0, 0}
3200 : };
3201 :
3202 1140 : if (sal_Int32 nToken = DocxStringGetToken(aTokens, aAttributeList[i].Name))
3203 1140 : pAttributeList->add(FSNS(XML_w, nToken), (aAttributeList[i].Value.get<sal_Int32>() ? "1" : "0"));
3204 : }
3205 : }
3206 :
3207 508 : XFastAttributeListRef xAttributeList(pAttributeList);
3208 508 : m_pSerializer->singleElementNS(XML_w, XML_tblLook, xAttributeList);
3209 : }
3210 46 : else if (aGrabBagElement->first == "TablePosition" )
3211 : {
3212 46 : FastAttributeList *attrListTablePos = m_pSerializer->createAttrList( );
3213 46 : uno::Sequence<beans::PropertyValue> aTablePosition = aGrabBagElement->second.get<uno::Sequence<beans::PropertyValue> >();
3214 506 : for (sal_Int32 i = 0; i < aTablePosition.getLength(); ++i)
3215 : {
3216 460 : if (aTablePosition[i].Name == "vertAnchor")
3217 : {
3218 46 : OString strTemp = OUStringToOString(aTablePosition[i].Value.get<OUString>(), RTL_TEXTENCODING_UTF8);
3219 46 : attrListTablePos->add( FSNS( XML_w, XML_vertAnchor ), strTemp.getStr() );
3220 : }
3221 414 : else if (aTablePosition[i].Name == "tblpYSpec")
3222 : {
3223 46 : OString strTemp = OUStringToOString(aTablePosition[i].Value.get<OUString>(), RTL_TEXTENCODING_UTF8);
3224 46 : attrListTablePos->add( FSNS( XML_w, XML_tblpYSpec ), strTemp.getStr() );
3225 : }
3226 368 : else if (aTablePosition[i].Name == "horzAnchor")
3227 : {
3228 46 : OString strTemp = OUStringToOString(aTablePosition[i].Value.get<OUString>(), RTL_TEXTENCODING_UTF8);
3229 46 : attrListTablePos->add( FSNS( XML_w, XML_horzAnchor ), strTemp.getStr() );
3230 : }
3231 322 : else if (aTablePosition[i].Name == "tblpXSpec")
3232 : {
3233 46 : OString strTemp = OUStringToOString(aTablePosition[i].Value.get<OUString>(), RTL_TEXTENCODING_UTF8);
3234 46 : attrListTablePos->add( FSNS( XML_w, XML_tblpXSpec ), strTemp.getStr() );
3235 : }
3236 276 : else if (aTablePosition[i].Name == "bottomFromText")
3237 : {
3238 46 : attrListTablePos->add( FSNS( XML_w, XML_bottomFromText ), OString::number( aTablePosition[i].Value.get<sal_Int32>() ) );
3239 : }
3240 230 : else if (aTablePosition[i].Name == "leftFromText")
3241 : {
3242 46 : attrListTablePos->add( FSNS( XML_w, XML_leftFromText ), OString::number( aTablePosition[i].Value.get<sal_Int32>() ) );
3243 : }
3244 184 : else if (aTablePosition[i].Name == "rightFromText")
3245 : {
3246 46 : attrListTablePos->add( FSNS( XML_w, XML_rightFromText ), OString::number( aTablePosition[i].Value.get<sal_Int32>() ) );
3247 : }
3248 138 : else if (aTablePosition[i].Name == "topFromText")
3249 : {
3250 46 : attrListTablePos->add( FSNS( XML_w, XML_topFromText ), OString::number( aTablePosition[i].Value.get<sal_Int32>() ) );
3251 : }
3252 92 : else if (aTablePosition[i].Name == "tblpX")
3253 : {
3254 46 : attrListTablePos->add( FSNS( XML_w, XML_tblpX ), OString::number( aTablePosition[i].Value.get<sal_Int32>() ) );
3255 : }
3256 46 : else if (aTablePosition[i].Name == "tblpY")
3257 : {
3258 46 : attrListTablePos->add( FSNS( XML_w, XML_tblpY ), OString::number( aTablePosition[i].Value.get<sal_Int32>() ) );
3259 : }
3260 : }
3261 :
3262 92 : XFastAttributeListRef xAttrListTablePosRef( attrListTablePos );
3263 :
3264 46 : m_pSerializer->singleElementNS( XML_w, XML_tblpPr, xAttrListTablePosRef);
3265 92 : attrListTablePos = NULL;
3266 : }
3267 : else
3268 : SAL_WARN("sw.ww8", "DocxAttributeOutput::TableDefinition: unhandled property: " << aGrabBagElement->first);
3269 : }
3270 :
3271 : // Output the table alignement
3272 : const char* pJcVal;
3273 264 : sal_Int32 nIndent = 0;
3274 264 : switch ( pTblFmt->GetHoriOrient( ).GetHoriOrient( ) )
3275 : {
3276 : case text::HoriOrientation::CENTER:
3277 36 : pJcVal = "center";
3278 36 : break;
3279 : case text::HoriOrientation::RIGHT:
3280 6 : if ( bEcma )
3281 4 : pJcVal = "right";
3282 : else
3283 2 : pJcVal = "end";
3284 6 : break;
3285 : default:
3286 : case text::HoriOrientation::NONE:
3287 : case text::HoriOrientation::LEFT_AND_WIDTH:
3288 : {
3289 222 : if ( bEcma )
3290 6 : pJcVal = "left";
3291 : else
3292 216 : pJcVal = "start";
3293 222 : nIndent = sal_Int32( pTblFmt->GetLRSpace( ).GetLeft( ) );
3294 : // Table indentation has different meaning in Word, depending if the table is nested or not.
3295 : // If nested, tblInd is added to parent table's left spacing and defines left edge position
3296 : // If not nested, text position of left-most cell must be at absolute X = tblInd
3297 : // so, table_spacing + table_spacing_to_content = tblInd
3298 222 : if (m_tableReference->m_nTableDepth == 0)
3299 : {
3300 212 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3301 212 : const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
3302 212 : nIndent += sal_Int32( pFrmFmt->GetBox( ).GetDistance( BOX_LINE_LEFT ) );
3303 : }
3304 222 : break;
3305 : }
3306 : }
3307 : m_pSerializer->singleElementNS( XML_w, XML_jc,
3308 : FSNS( XML_w, XML_val ), pJcVal,
3309 264 : FSEND );
3310 :
3311 : // Output the table borders
3312 264 : TableDefaultBorders( pTableTextNodeInfoInner );
3313 :
3314 : // Output the default cell margins
3315 264 : TableDefaultCellMargins( pTableTextNodeInfoInner );
3316 :
3317 264 : TableBidi( pTableTextNodeInfoInner );
3318 :
3319 : // Table indent (need to get written even if == 0)
3320 : m_pSerializer->singleElementNS( XML_w, XML_tblInd,
3321 : FSNS( XML_w, XML_w ), OString::number( nIndent ).getStr( ),
3322 : FSNS( XML_w, XML_type ), "dxa",
3323 264 : FSEND );
3324 :
3325 : // Merge the marks for the ordered elements
3326 264 : m_pSerializer->mergeTopMarks( );
3327 :
3328 264 : m_pSerializer->endElementNS( XML_w, XML_tblPr );
3329 :
3330 : // Write the table grid infos
3331 264 : m_pSerializer->startElementNS( XML_w, XML_tblGrid, FSEND );
3332 264 : sal_Int32 nPrv = 0;
3333 264 : ww8::WidthsPtr pColumnWidths = GetColumnWidths( pTableTextNodeInfoInner );
3334 898 : for ( ww8::Widths::const_iterator it = pColumnWidths->begin(); it != pColumnWidths->end(); ++it )
3335 : {
3336 634 : sal_Int32 nWidth = sal_Int32( *it ) - nPrv;
3337 : m_pSerializer->singleElementNS( XML_w, XML_gridCol,
3338 : FSNS( XML_w, XML_w ), OString::number( nWidth ).getStr( ),
3339 634 : FSEND );
3340 634 : nPrv = sal_Int32( *it );
3341 : }
3342 :
3343 528 : m_pSerializer->endElementNS( XML_w, XML_tblGrid );
3344 264 : }
3345 :
3346 264 : void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3347 : {
3348 264 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3349 264 : const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
3350 :
3351 264 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
3352 :
3353 : // Don't write table defaults based on the top-left cell if we have a table style available.
3354 264 : if (m_aTableStyleConf.empty())
3355 : {
3356 : // the defaults of the table are taken from the top-left cell
3357 154 : impl_borders(m_pSerializer, pFrmFmt->GetBox(), lcl_getTableDefaultBorderOptions(bEcma), NULL, m_aTableStyleConf);
3358 : }
3359 264 : }
3360 :
3361 264 : void DocxAttributeOutput::TableDefaultCellMargins( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3362 : {
3363 264 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3364 264 : const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
3365 264 : const SvxBoxItem& rBox = pFrmFmt->GetBox( );
3366 264 : const bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
3367 :
3368 264 : impl_cellMargins(m_pSerializer, rBox, XML_tblCellMar, !bEcma);
3369 264 : }
3370 :
3371 3002 : void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3372 : {
3373 3002 : const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
3374 3002 : const SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
3375 :
3376 3002 : const SvxBrushItem *aColorProp = sw::util::HasItem<SvxBrushItem>( pFmt->GetAttrSet(), RES_BACKGROUND );
3377 3002 : Color aColor = aColorProp ? aColorProp->GetColor() : COL_AUTO;
3378 3002 : OString sColor = msfilter::util::ConvertColor( aColor );
3379 :
3380 : std::map<OUString, com::sun::star::uno::Any> aGrabBag =
3381 6004 : sw::util::HasItem<SfxGrabBagItem>( pFmt->GetAttrSet(), RES_FRMATR_GRABBAG )->GetGrabBag();
3382 :
3383 6004 : OString sOriginalColor;
3384 3002 : std::map<OUString, com::sun::star::uno::Any>::iterator aGrabBagElement = aGrabBag.find("originalColor");
3385 3002 : if( aGrabBagElement != aGrabBag.end() )
3386 546 : sOriginalColor = OUStringToOString( aGrabBagElement->second.get<OUString>(), RTL_TEXTENCODING_UTF8 );
3387 :
3388 3002 : if ( sOriginalColor != sColor )
3389 : {
3390 : // color changed by the user, or no grab bag: write sColor
3391 : m_pSerializer->singleElementNS( XML_w, XML_shd,
3392 : FSNS( XML_w, XML_fill ), sColor.getStr( ),
3393 : FSNS( XML_w, XML_val ), "clear",
3394 2456 : FSEND );
3395 : }
3396 : else
3397 : {
3398 546 : ::sax_fastparser::FastAttributeList* pAttrList = NULL;
3399 :
3400 2856 : for( aGrabBagElement = aGrabBag.begin(); aGrabBagElement != aGrabBag.end(); ++aGrabBagElement )
3401 : {
3402 2310 : if (!aGrabBagElement->second.has<OUString>())
3403 8 : continue;
3404 :
3405 2302 : OString sValue = OUStringToOString( aGrabBagElement->second.get<OUString>(), RTL_TEXTENCODING_UTF8 );
3406 2302 : if( aGrabBagElement->first == "themeFill")
3407 70 : AddToAttrList( pAttrList, FSNS( XML_w, XML_themeFill ), sValue.getStr() );
3408 2232 : else if( aGrabBagElement->first == "themeFillTint")
3409 18 : AddToAttrList( pAttrList, FSNS( XML_w, XML_themeFillTint ), sValue.getStr() );
3410 2214 : else if( aGrabBagElement->first == "themeFillShade")
3411 50 : AddToAttrList( pAttrList, FSNS( XML_w, XML_themeFillShade ), sValue.getStr() );
3412 2164 : else if( aGrabBagElement->first == "fill" )
3413 546 : AddToAttrList( pAttrList, FSNS( XML_w, XML_fill ), sValue.getStr() );
3414 1618 : else if( aGrabBagElement->first == "themeColor")
3415 2 : AddToAttrList( pAttrList, FSNS( XML_w, XML_themeColor ), sValue.getStr() );
3416 1616 : else if( aGrabBagElement->first == "themeTint")
3417 2 : AddToAttrList( pAttrList, FSNS( XML_w, XML_themeTint ), sValue.getStr() );
3418 1614 : else if( aGrabBagElement->first == "themeShade")
3419 0 : AddToAttrList( pAttrList, FSNS( XML_w, XML_themeShade ), sValue.getStr() );
3420 1614 : else if( aGrabBagElement->first == "color")
3421 522 : AddToAttrList( pAttrList, FSNS( XML_w, XML_color ), sValue.getStr() );
3422 1092 : else if( aGrabBagElement->first == "val")
3423 546 : AddToAttrList( pAttrList, FSNS( XML_w, XML_val ), sValue.getStr() );
3424 2302 : }
3425 : m_pSerializer->singleElementNS( XML_w, XML_shd,
3426 546 : XFastAttributeListRef( pAttrList ) );
3427 3002 : }
3428 3002 : }
3429 :
3430 1282 : void DocxAttributeOutput::TableRowRedline( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3431 : {
3432 1282 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3433 1282 : const SwTableLine * pTabLine = pTabBox->GetUpper();
3434 :
3435 : // search next Redline
3436 1282 : const SwExtraRedlineTbl& aExtraRedlineTbl = m_rExport.pDoc->getIDocumentRedlineAccess().GetExtraRedlineTbl();
3437 1306 : for(sal_uInt16 nCurRedlinePos = 0; nCurRedlinePos < aExtraRedlineTbl.GetSize(); ++nCurRedlinePos )
3438 : {
3439 24 : SwExtraRedline* pExtraRedline = aExtraRedlineTbl.GetRedline(nCurRedlinePos);
3440 24 : const SwTableRowRedline* pTableRowRedline = dynamic_cast<const SwTableRowRedline*>(pExtraRedline);
3441 24 : const SwTableLine *pRedTabLine = pTableRowRedline ? &pTableRowRedline->GetTableLine() : NULL;
3442 24 : if (pRedTabLine == pTabLine)
3443 : {
3444 : // Redline for this table row
3445 4 : const SwRedlineData& aRedlineData = pTableRowRedline->GetRedlineData();
3446 4 : sal_uInt16 nRedlineType = aRedlineData.GetType();
3447 4 : switch (nRedlineType)
3448 : {
3449 : case nsRedlineType_t::REDLINE_TABLE_ROW_INSERT:
3450 : case nsRedlineType_t::REDLINE_TABLE_ROW_DELETE:
3451 : {
3452 4 : OString aId( OString::number( m_nRedlineId++ ) );
3453 8 : const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( aRedlineData.GetAuthor() ) );
3454 8 : OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
3455 :
3456 8 : OString aDate( DateTimeToOString( aRedlineData.GetTimeStamp() ) );
3457 :
3458 4 : if (nRedlineType == nsRedlineType_t::REDLINE_TABLE_ROW_INSERT)
3459 : m_pSerializer->singleElementNS( XML_w, XML_ins,
3460 : FSNS( XML_w, XML_id ), aId.getStr(),
3461 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
3462 : FSNS( XML_w, XML_date ), aDate.getStr(),
3463 2 : FSEND );
3464 2 : else if (nRedlineType == nsRedlineType_t::REDLINE_TABLE_ROW_DELETE)
3465 : m_pSerializer->singleElementNS( XML_w, XML_del,
3466 : FSNS( XML_w, XML_id ), aId.getStr(),
3467 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
3468 : FSNS( XML_w, XML_date ), aDate.getStr(),
3469 6 : FSEND );
3470 : }
3471 4 : break;
3472 : }
3473 : }
3474 : }
3475 1282 : }
3476 :
3477 3002 : void DocxAttributeOutput::TableCellRedline( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3478 : {
3479 3002 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3480 :
3481 : // search next Redline
3482 3002 : const SwExtraRedlineTbl& aExtraRedlineTbl = m_rExport.pDoc->getIDocumentRedlineAccess().GetExtraRedlineTbl();
3483 3050 : for(sal_uInt16 nCurRedlinePos = 0; nCurRedlinePos < aExtraRedlineTbl.GetSize(); ++nCurRedlinePos )
3484 : {
3485 48 : SwExtraRedline* pExtraRedline = aExtraRedlineTbl.GetRedline(nCurRedlinePos);
3486 48 : const SwTableCellRedline* pTableCellRedline = dynamic_cast<const SwTableCellRedline*>(pExtraRedline);
3487 48 : const SwTableBox *pRedTabBox = pTableCellRedline ? &pTableCellRedline->GetTableBox() : NULL;
3488 48 : if (pRedTabBox == pTabBox)
3489 : {
3490 : // Redline for this table cell
3491 4 : const SwRedlineData& aRedlineData = pTableCellRedline->GetRedlineData();
3492 4 : sal_uInt16 nRedlineType = aRedlineData.GetType();
3493 4 : switch (nRedlineType)
3494 : {
3495 : case nsRedlineType_t::REDLINE_TABLE_CELL_INSERT:
3496 : case nsRedlineType_t::REDLINE_TABLE_CELL_DELETE:
3497 : {
3498 4 : OString aId( OString::number( m_nRedlineId++ ) );
3499 8 : const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( aRedlineData.GetAuthor() ) );
3500 8 : OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
3501 :
3502 8 : OString aDate( DateTimeToOString( aRedlineData.GetTimeStamp() ) );
3503 :
3504 4 : if (nRedlineType == nsRedlineType_t::REDLINE_TABLE_CELL_INSERT)
3505 : m_pSerializer->singleElementNS( XML_w, XML_cellIns,
3506 : FSNS( XML_w, XML_id ), aId.getStr(),
3507 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
3508 : FSNS( XML_w, XML_date ), aDate.getStr(),
3509 2 : FSEND );
3510 2 : else if (nRedlineType == nsRedlineType_t::REDLINE_TABLE_CELL_DELETE)
3511 : m_pSerializer->singleElementNS( XML_w, XML_cellDel,
3512 : FSNS( XML_w, XML_id ), aId.getStr(),
3513 : FSNS( XML_w, XML_author ), aAuthor.getStr(),
3514 : FSNS( XML_w, XML_date ), aDate.getStr(),
3515 6 : FSEND );
3516 : }
3517 4 : break;
3518 : }
3519 : }
3520 : }
3521 3002 : }
3522 :
3523 1282 : void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3524 : {
3525 1282 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3526 1282 : const SwTableLine * pTabLine = pTabBox->GetUpper();
3527 1282 : const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
3528 :
3529 1282 : const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
3530 1282 : if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
3531 : {
3532 528 : sal_Int32 nHeight = rLSz.GetHeight();
3533 528 : const char *pRule = NULL;
3534 :
3535 528 : switch ( rLSz.GetHeightSizeType() )
3536 : {
3537 10 : case ATT_FIX_SIZE: pRule = "exact"; break;
3538 518 : case ATT_MIN_SIZE: pRule = "atLeast"; break;
3539 0 : default: break;
3540 : }
3541 :
3542 528 : if ( pRule )
3543 : m_pSerializer->singleElementNS( XML_w, XML_trHeight,
3544 : FSNS( XML_w, XML_val ), OString::number( nHeight ).getStr( ),
3545 : FSNS( XML_w, XML_hRule ), pRule,
3546 528 : FSEND );
3547 : }
3548 1282 : }
3549 :
3550 1282 : void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3551 : {
3552 1282 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3553 1282 : const SwTableLine * pTabLine = pTabBox->GetUpper();
3554 1282 : const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
3555 :
3556 1282 : const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
3557 : // if rSplittable is true then no need to write <w:cantSplit w:val="false"/>
3558 : // as default row prop is allow row to break across page.
3559 1282 : if( !rSplittable.GetValue( ) )
3560 : m_pSerializer->singleElementNS( XML_w, XML_cantSplit,
3561 : FSNS( XML_w, XML_val ), "true",
3562 22 : FSEND );
3563 1282 : }
3564 :
3565 264 : void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3566 : {
3567 264 : const SwTable * pTable = pTableTextNodeInfoInner->getTable();
3568 264 : const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
3569 :
3570 264 : if ( m_rExport.TrueFrameDirection( *pFrmFmt ) == FRMDIR_HORI_RIGHT_TOP )
3571 : {
3572 : m_pSerializer->singleElementNS( XML_w, XML_bidiVisual,
3573 : FSNS( XML_w, XML_val ), "true",
3574 0 : FSEND );
3575 : }
3576 264 : }
3577 :
3578 3002 : void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
3579 : {
3580 3002 : const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
3581 3002 : const SwFrmFmt *pFrmFmt = pTabBox->GetFrmFmt( );
3582 :
3583 3002 : if ( FRMDIR_VERT_TOP_RIGHT == m_rExport.TrueFrameDirection( *pFrmFmt ) )
3584 : m_pSerializer->singleElementNS( XML_w, XML_textDirection,
3585 : FSNS( XML_w, XML_val ), "tbRl",
3586 0 : FSEND );
3587 3002 : else if ( FRMDIR_HORI_LEFT_TOP == m_rExport.TrueFrameDirection( *pFrmFmt ) )
3588 : {
3589 : // Undo the text direction mangling done by the btLr handler in writerfilter::dmapper::DomainMapperTableManager::sprm()
3590 2950 : SwPaM aPam(*pTabBox->GetSttNd(), 0);
3591 2950 : aPam.GetPoint()->nNode++;
3592 2950 : if (aPam.GetPoint()->nNode.GetNode().IsTxtNode())
3593 : {
3594 2938 : const SwTxtNode& rTxtNode = (const SwTxtNode&)aPam.GetPoint()->nNode.GetNode();
3595 2938 : if( const SwAttrSet* pAttrSet = rTxtNode.GetpSwAttrSet())
3596 : {
3597 2488 : const SvxCharRotateItem& rCharRotate = pAttrSet->GetCharRotate();
3598 2488 : if (rCharRotate.GetValue() == 900)
3599 : {
3600 2 : m_pSerializer->singleElementNS( XML_w, XML_textDirection, FSNS( XML_w, XML_val ), "btLr", FSEND );
3601 2 : m_bBtLr = true;
3602 : }
3603 : }
3604 2950 : }
3605 : }
3606 :
3607 3002 : const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
3608 3002 : SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
3609 3002 : sal_uInt32 nCell = pTableTextNodeInfoInner->getCell();
3610 3002 : const SwWriteTableCells *tableCells = &pRow->GetCells();
3611 3002 : if (nCell < tableCells->size() )
3612 : {
3613 3002 : const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
3614 3002 : switch( pCell->GetVertOri())
3615 : {
3616 : case text::VertOrientation::TOP:
3617 2438 : break;
3618 : case text::VertOrientation::CENTER:
3619 : m_pSerializer->singleElementNS( XML_w, XML_vAlign,
3620 420 : FSNS( XML_w, XML_val ), "center", FSEND );
3621 420 : break;
3622 : case text::VertOrientation::BOTTOM:
3623 : m_pSerializer->singleElementNS( XML_w, XML_vAlign,
3624 144 : FSNS( XML_w, XML_val ), "bottom", FSEND );
3625 144 : break;
3626 : }
3627 : }
3628 3002 : }
3629 :
3630 0 : void DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
3631 : {
3632 : OSL_TRACE( "TODO: DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )" );
3633 0 : }
3634 :
3635 7322 : void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
3636 : {
3637 : // This is called when the nested table ends in a cell, and there's no
3638 : // paragraph benhind that; so we must check for the ends of cell, rows,
3639 : // tables
3640 : // ['true' to write an empty paragraph, MS Word insists on that]
3641 7322 : FinishTableRowCell( pNodeInfoInner, true );
3642 7322 : }
3643 :
3644 0 : void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
3645 : {
3646 : OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )" );
3647 0 : }
3648 :
3649 0 : void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
3650 : {
3651 : #if OSL_DEBUG_LEVEL > 1
3652 : fprintf( stderr, "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
3653 : #endif
3654 0 : }
3655 :
3656 0 : void DocxAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
3657 : {
3658 : OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )" );
3659 0 : }
3660 :
3661 860 : void DocxAttributeOutput::StartStyles()
3662 : {
3663 : m_pSerializer->startElementNS( XML_w, XML_styles,
3664 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
3665 : FSNS( XML_xmlns, XML_w14 ), "http://schemas.microsoft.com/office/word/2010/wordml",
3666 : FSNS( XML_xmlns, XML_mc ), "http://schemas.openxmlformats.org/markup-compatibility/2006",
3667 : FSNS( XML_mc, XML_Ignorable ), "w14",
3668 860 : FSEND );
3669 :
3670 860 : DocDefaults();
3671 860 : LatentStyles();
3672 860 : }
3673 :
3674 486524 : sal_Int32 DocxStringGetToken(DocxStringTokenMap const * pMap, const OUString& rName)
3675 : {
3676 486524 : OString sName = OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
3677 2015710 : while (pMap->pToken)
3678 : {
3679 1528414 : if (sName == pMap->pToken)
3680 485752 : return pMap->nToken;
3681 1042662 : ++pMap;
3682 : }
3683 772 : return 0;
3684 : }
3685 :
3686 : DocxStringTokenMap const aDefaultTokens[] = {
3687 : {"defQFormat", XML_defQFormat},
3688 : {"defUnhideWhenUsed", XML_defUnhideWhenUsed},
3689 : {"defSemiHidden", XML_defSemiHidden},
3690 : {"count", XML_count},
3691 : {"defUIPriority", XML_defUIPriority},
3692 : {"defLockedState", XML_defLockedState},
3693 : {0, 0}
3694 : };
3695 :
3696 : DocxStringTokenMap const aExceptionTokens[] = {
3697 : {"name", XML_name},
3698 : {"locked", XML_locked},
3699 : {"uiPriority", XML_uiPriority},
3700 : {"semiHidden", XML_semiHidden},
3701 : {"unhideWhenUsed", XML_unhideWhenUsed},
3702 : {"qFormat", XML_qFormat},
3703 : {0, 0}
3704 : };
3705 :
3706 860 : void DocxAttributeOutput::LatentStyles()
3707 : {
3708 : // Do we have latent styles available?
3709 860 : uno::Reference<beans::XPropertySet> xPropertySet(m_rExport.pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW);
3710 1632 : uno::Sequence<beans::PropertyValue> aInteropGrabBag;
3711 860 : xPropertySet->getPropertyValue("InteropGrabBag") >>= aInteropGrabBag;
3712 1632 : uno::Sequence<beans::PropertyValue> aLatentStyles;
3713 9108 : for (sal_Int32 i = 0; i < aInteropGrabBag.getLength(); ++i)
3714 : {
3715 9020 : if (aInteropGrabBag[i].Name == "latentStyles")
3716 : {
3717 772 : aInteropGrabBag[i].Value >>= aLatentStyles;
3718 772 : break;
3719 : }
3720 : }
3721 860 : if (!aLatentStyles.getLength())
3722 948 : return;
3723 :
3724 : // Extract default attributes first.
3725 772 : sax_fastparser::FastAttributeList* pAttributeList = m_pSerializer->createAttrList();
3726 1544 : uno::Sequence<beans::PropertyValue> aLsdExceptions;
3727 6176 : for (sal_Int32 i = 0; i < aLatentStyles.getLength(); ++i)
3728 : {
3729 5404 : if (sal_Int32 nToken = DocxStringGetToken(aDefaultTokens, aLatentStyles[i].Name))
3730 4632 : pAttributeList->add(FSNS(XML_w, nToken), OUStringToOString(aLatentStyles[i].Value.get<OUString>(), RTL_TEXTENCODING_UTF8));
3731 772 : else if (aLatentStyles[i].Name == "lsdExceptions")
3732 772 : aLatentStyles[i].Value >>= aLsdExceptions;
3733 : }
3734 :
3735 1544 : XFastAttributeListRef xAttributeList(pAttributeList);
3736 772 : m_pSerializer->startElementNS(XML_w, XML_latentStyles, xAttributeList);
3737 772 : pAttributeList = 0;
3738 :
3739 : // Then handle the exceptions.
3740 134538 : for (sal_Int32 i = 0; i < aLsdExceptions.getLength(); ++i)
3741 : {
3742 133766 : pAttributeList = m_pSerializer->createAttrList();
3743 :
3744 133766 : uno::Sequence<beans::PropertyValue> aAttributes;
3745 133766 : aLsdExceptions[i].Value >>= aAttributes;
3746 576986 : for (sal_Int32 j = 0; j < aAttributes.getLength(); ++j)
3747 443220 : if (sal_Int32 nToken = DocxStringGetToken(aExceptionTokens, aAttributes[j].Name))
3748 443220 : pAttributeList->add(FSNS(XML_w, nToken), OUStringToOString(aAttributes[j].Value.get<OUString>(), RTL_TEXTENCODING_UTF8));
3749 :
3750 133766 : xAttributeList = pAttributeList;
3751 133766 : m_pSerializer->singleElementNS(XML_w, XML_lsdException, xAttributeList);
3752 133766 : pAttributeList = 0;
3753 133766 : }
3754 :
3755 1544 : m_pSerializer->endElementNS(XML_w, XML_latentStyles);
3756 : }
3757 :
3758 : /// Should the font size we have written out as a default one?
3759 860 : bool lcl_isDefaultFontSize(const SvxFontHeightItem& rFontHeight, SwDoc* pDoc)
3760 : {
3761 860 : bool bRet = rFontHeight.GetHeight() != 200; // see StyleSheetTable_Impl::StyleSheetTable_Impl() where we set this default
3762 : // Additionally, if the default para style has the same font size, then don't write it here.
3763 860 : SwTxtFmtColl* pDefaultStyle = pDoc->getIDocumentStylePoolAccess().GetTxtCollFromPool(RES_POOLCOLL_STANDARD);
3764 860 : if (pDefaultStyle)
3765 : {
3766 860 : const SfxPoolItem* pItem = 0;
3767 860 : if (pDefaultStyle->GetAttrSet().HasItem(RES_CHRATR_FONTSIZE, &pItem))
3768 188 : return static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != rFontHeight.GetHeight();
3769 : }
3770 672 : return bRet;
3771 : }
3772 :
3773 55040 : void DocxAttributeOutput::OutputDefaultItem(const SfxPoolItem& rHt)
3774 : {
3775 55040 : bool bMustWrite = true;
3776 55040 : switch (rHt.Which())
3777 : {
3778 : case RES_CHRATR_CASEMAP:
3779 860 : bMustWrite = static_cast< const SvxCaseMapItem& >(rHt).GetCaseMap() != SVX_CASEMAP_NOT_MAPPED;
3780 860 : break;
3781 : case RES_CHRATR_COLOR:
3782 860 : bMustWrite = static_cast< const SvxColorItem& >(rHt).GetValue().GetColor() != COL_AUTO;
3783 860 : break;
3784 : case RES_CHRATR_CONTOUR:
3785 860 : bMustWrite = static_cast< const SvxContourItem& >(rHt).GetValue();
3786 860 : break;
3787 : case RES_CHRATR_CROSSEDOUT:
3788 860 : bMustWrite = static_cast< const SvxCrossedOutItem& >(rHt).GetStrikeout() != STRIKEOUT_NONE;
3789 860 : break;
3790 : case RES_CHRATR_ESCAPEMENT:
3791 860 : bMustWrite = static_cast< const SvxEscapementItem& >(rHt).GetEscapement() != SVX_ESCAPEMENT_OFF;
3792 860 : break;
3793 : case RES_CHRATR_FONT:
3794 860 : bMustWrite = true;
3795 860 : break;
3796 : case RES_CHRATR_FONTSIZE:
3797 860 : bMustWrite = lcl_isDefaultFontSize(static_cast< const SvxFontHeightItem& >(rHt), m_rExport.pDoc);
3798 860 : break;
3799 : case RES_CHRATR_KERNING:
3800 860 : bMustWrite = static_cast< const SvxKerningItem& >(rHt).GetValue() != 0;
3801 860 : break;
3802 : case RES_CHRATR_LANGUAGE:
3803 860 : bMustWrite = true;
3804 860 : break;
3805 : case RES_CHRATR_POSTURE:
3806 860 : bMustWrite = static_cast< const SvxPostureItem& >(rHt).GetPosture() != ITALIC_NONE;
3807 860 : break;
3808 : case RES_CHRATR_SHADOWED:
3809 860 : bMustWrite = static_cast< const SvxShadowedItem& >(rHt).GetValue();
3810 860 : break;
3811 : case RES_CHRATR_UNDERLINE:
3812 860 : bMustWrite = static_cast< const SvxUnderlineItem& >(rHt).GetLineStyle() != UNDERLINE_NONE;
3813 860 : break;
3814 : case RES_CHRATR_WEIGHT:
3815 860 : bMustWrite = static_cast< const SvxWeightItem& >(rHt).GetWeight() != WEIGHT_NORMAL;
3816 860 : break;
3817 : case RES_CHRATR_AUTOKERN:
3818 860 : bMustWrite = static_cast< const SvxAutoKernItem& >(rHt).GetValue();
3819 860 : break;
3820 : case RES_CHRATR_BLINK:
3821 860 : bMustWrite = static_cast< const SvxBlinkItem& >(rHt).GetValue();
3822 860 : break;
3823 : case RES_CHRATR_BACKGROUND:
3824 : {
3825 860 : const SvxBrushItem& rBrushItem = static_cast< const SvxBrushItem& >(rHt);
3826 4300 : bMustWrite = (rBrushItem.GetColor() != COL_AUTO ||
3827 2580 : rBrushItem.GetShadingValue() != sal_uInt32(ShadingPattern::CLEAR) ||
3828 6880 : rBrushItem.GetGraphic() != NULL ||
3829 2580 : rBrushItem.GetGraphicObject() != NULL);
3830 : }
3831 860 : break;
3832 :
3833 : case RES_CHRATR_CJK_FONT:
3834 860 : bMustWrite = true;
3835 860 : break;
3836 : case RES_CHRATR_CJK_FONTSIZE:
3837 860 : bMustWrite = false; // we have written it already as RES_CHRATR_FONTSIZE
3838 860 : break;
3839 : case RES_CHRATR_CJK_LANGUAGE:
3840 860 : bMustWrite = true;
3841 860 : break;
3842 : case RES_CHRATR_CJK_POSTURE:
3843 860 : bMustWrite = false; // we have written it already as RES_CHRATR_POSTURE
3844 860 : break;
3845 : case RES_CHRATR_CJK_WEIGHT:
3846 860 : bMustWrite = false; // we have written it already as RES_CHRATR_WEIGHT
3847 860 : break;
3848 :
3849 : case RES_CHRATR_CTL_FONT:
3850 860 : bMustWrite = true;
3851 860 : break;
3852 : case RES_CHRATR_CTL_FONTSIZE:
3853 860 : bMustWrite = static_cast< const SvxFontHeightItem& >(rHt).GetHeight() != 200; // see StyleSheetTable_Impl::StyleSheetTable_Impl() where we set this default
3854 860 : break;
3855 : case RES_CHRATR_CTL_LANGUAGE:
3856 860 : bMustWrite = true;
3857 860 : break;
3858 : case RES_CHRATR_CTL_POSTURE:
3859 860 : bMustWrite = static_cast< const SvxPostureItem& >(rHt).GetPosture() != ITALIC_NONE;
3860 860 : break;
3861 : case RES_CHRATR_CTL_WEIGHT:
3862 860 : bMustWrite = static_cast< const SvxWeightItem& >(rHt).GetWeight() != WEIGHT_NORMAL;
3863 860 : break;
3864 :
3865 : case RES_CHRATR_ROTATE:
3866 860 : bMustWrite = static_cast< const SvxCharRotateItem& >(rHt).GetValue() != 0;
3867 860 : break;
3868 : case RES_CHRATR_EMPHASIS_MARK:
3869 860 : bMustWrite = static_cast< const SvxEmphasisMarkItem& >(rHt).GetValue() != EMPHASISMARK_NONE;
3870 860 : break;
3871 : case RES_CHRATR_TWO_LINES:
3872 860 : bMustWrite = static_cast< const SvxTwoLinesItem& >(rHt).GetValue();
3873 860 : break;
3874 : case RES_CHRATR_SCALEW:
3875 860 : bMustWrite = static_cast< const SvxCharScaleWidthItem& >(rHt).GetValue() != 100;
3876 860 : break;
3877 : case RES_CHRATR_RELIEF:
3878 860 : bMustWrite = static_cast< const SvxCharReliefItem& >(rHt).GetValue() != RELIEF_NONE;
3879 860 : break;
3880 : case RES_CHRATR_HIDDEN:
3881 860 : bMustWrite = static_cast< const SvxCharHiddenItem& >(rHt).GetValue();
3882 860 : break;
3883 : case RES_CHRATR_BOX:
3884 : {
3885 860 : const SvxBoxItem& rBoxItem = static_cast< const SvxBoxItem& >(rHt);
3886 2580 : bMustWrite = rBoxItem.GetTop() || rBoxItem.GetLeft() ||
3887 3440 : rBoxItem.GetBottom() || rBoxItem.GetRight() ||
3888 1720 : rBoxItem.GetDistance();
3889 : }
3890 860 : break;
3891 : case RES_CHRATR_HIGHLIGHT:
3892 : {
3893 860 : const SvxBrushItem& rBrushItem = static_cast< const SvxBrushItem& >(rHt);
3894 4300 : bMustWrite = (rBrushItem.GetColor() != COL_AUTO ||
3895 2580 : rBrushItem.GetShadingValue() != sal_uInt32(ShadingPattern::CLEAR) ||
3896 6880 : rBrushItem.GetGraphic() != NULL ||
3897 2580 : rBrushItem.GetGraphicObject() != NULL);
3898 : }
3899 860 : break;
3900 :
3901 : case RES_PARATR_LINESPACING:
3902 860 : bMustWrite = static_cast< const SvxLineSpacingItem& >(rHt).GetInterLineSpaceRule() != SVX_INTER_LINE_SPACE_OFF;
3903 860 : break;
3904 : case RES_PARATR_ADJUST:
3905 860 : bMustWrite = static_cast< const SvxAdjustItem& >(rHt).GetAdjust() != SVX_ADJUST_LEFT;
3906 860 : break;
3907 : case RES_PARATR_SPLIT:
3908 860 : bMustWrite = !static_cast< const SvxFmtSplitItem& >(rHt).GetValue();
3909 860 : break;
3910 : case RES_PARATR_WIDOWS:
3911 860 : bMustWrite = static_cast< const SvxWidowsItem& >(rHt).GetValue();
3912 860 : break;
3913 : case RES_PARATR_TABSTOP:
3914 860 : bMustWrite = static_cast< const SvxTabStopItem& >(rHt).Count() != 0;
3915 860 : break;
3916 : case RES_PARATR_HYPHENZONE:
3917 860 : bMustWrite = static_cast< const SvxHyphenZoneItem& >(rHt).IsHyphen();
3918 860 : break;
3919 : case RES_PARATR_NUMRULE:
3920 860 : bMustWrite = !static_cast< const SwNumRuleItem& >(rHt).GetValue().isEmpty();
3921 860 : break;
3922 : case RES_PARATR_SCRIPTSPACE:
3923 860 : bMustWrite = !static_cast< const SfxBoolItem& >(rHt).GetValue();
3924 860 : break;
3925 : case RES_PARATR_HANGINGPUNCTUATION:
3926 860 : bMustWrite = !static_cast< const SfxBoolItem& >(rHt).GetValue();
3927 860 : break;
3928 : case RES_PARATR_FORBIDDEN_RULES:
3929 860 : bMustWrite = !static_cast< const SfxBoolItem& >(rHt).GetValue();
3930 860 : break;
3931 : case RES_PARATR_VERTALIGN:
3932 860 : bMustWrite = static_cast< const SvxParaVertAlignItem& >(rHt).GetValue() != SvxParaVertAlignItem::AUTOMATIC;
3933 860 : break;
3934 : case RES_PARATR_SNAPTOGRID:
3935 860 : bMustWrite = !static_cast< const SvxParaGridItem& >(rHt).GetValue();
3936 860 : break;
3937 : case RES_CHRATR_GRABBAG:
3938 860 : bMustWrite = true;
3939 860 : break;
3940 :
3941 : default:
3942 : SAL_INFO("sw.ww8", "Unhandled SfxPoolItem with id " << rHt.Which() );
3943 14620 : break;
3944 : }
3945 :
3946 55040 : if (bMustWrite)
3947 24418 : OutputItem(rHt);
3948 55040 : }
3949 :
3950 860 : void DocxAttributeOutput::DocDefaults( )
3951 : {
3952 : // Write the '<w:docDefaults>' section here
3953 860 : m_pSerializer->startElementNS(XML_w, XML_docDefaults, FSEND);
3954 :
3955 : // Output the default run properties
3956 860 : m_pSerializer->startElementNS(XML_w, XML_rPrDefault, FSEND);
3957 :
3958 860 : StartStyleProperties(false, 0);
3959 :
3960 39560 : for (int i = int(RES_CHRATR_BEGIN); i < int(RES_CHRATR_END); ++i)
3961 38700 : OutputDefaultItem(m_rExport.pDoc->GetDefault(i));
3962 :
3963 860 : EndStyleProperties(false);
3964 :
3965 860 : m_pSerializer->endElementNS(XML_w, XML_rPrDefault);
3966 :
3967 : // Output the default paragraph properties
3968 860 : m_pSerializer->startElementNS(XML_w, XML_pPrDefault, FSEND);
3969 :
3970 860 : StartStyleProperties(true, 0);
3971 :
3972 17200 : for (int i = int(RES_PARATR_BEGIN); i < int(RES_PARATR_END); ++i)
3973 16340 : OutputDefaultItem(m_rExport.pDoc->GetDefault(i));
3974 :
3975 860 : EndStyleProperties(true);
3976 :
3977 860 : m_pSerializer->endElementNS(XML_w, XML_pPrDefault);
3978 :
3979 860 : m_pSerializer->endElementNS(XML_w, XML_docDefaults);
3980 860 : }
3981 :
3982 860 : void DocxAttributeOutput::EndStyles( sal_uInt16 nNumberOfStyles )
3983 : {
3984 : // HACK
3985 : // Ms Office seems to have an internal limitation of 4091 styles
3986 : // and refuses to load .docx with more, even though the spec seems to allow that;
3987 : // so simply if there are more styles, don't export those
3988 860 : sal_uInt16 nCountStylesToWrite = MSWORD_MAX_STYLES_LIMIT - nNumberOfStyles;
3989 860 : m_pTableStyleExport->TableStyles(nCountStylesToWrite);
3990 860 : m_pSerializer->endElementNS( XML_w, XML_styles );
3991 860 : }
3992 :
3993 11032 : void DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )
3994 : {
3995 : // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
3996 : #if OSL_DEBUG_LEVEL > 1
3997 : OSL_TRACE( "TODO DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )- %d", nStyle );
3998 : #else
3999 : (void) nStyle; // to quiet the warning
4000 : #endif
4001 11032 : }
4002 :
4003 : /* Writes <a:srcRect> tag back to document.xml if a file conatins a cropped image.
4004 : * NOTE : Tested on images of type JPEG,EMF/WMF,BMP, PNG and GIF.
4005 : */
4006 104 : void DocxAttributeOutput::WriteSrcRect(const SdrObject* pSdrObj )
4007 : {
4008 104 : uno::Reference< drawing::XShape > xShape( ((SdrObject*)pSdrObj)->getUnoShape(), uno::UNO_QUERY );
4009 208 : uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
4010 :
4011 208 : OUString sUrl;
4012 104 : xPropSet->getPropertyValue("GraphicURL") >>= sUrl;
4013 104 : Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( sUrl ).GetPrefSize() );
4014 :
4015 104 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
4016 104 : xPropSet->getPropertyValue( "GraphicCrop" ) >>= aGraphicCropStruct;
4017 :
4018 208 : const MapMode aMap100mm( MAP_100TH_MM );
4019 104 : const MapMode& mapMode = GraphicObject::CreateGraphicObjectFromURL( sUrl ).GetPrefMapMode();
4020 104 : if( mapMode.GetMapUnit() == MAP_PIXEL )
4021 : {
4022 34 : aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize, aMap100mm );
4023 : }
4024 :
4025 104 : if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
4026 : {
4027 10 : double widthMultiplier = 100000.0/aOriginalSize.Width();
4028 10 : double heightMultiplier = 100000.0/aOriginalSize.Height();
4029 :
4030 10 : double left = aGraphicCropStruct.Left * widthMultiplier;
4031 10 : double right = aGraphicCropStruct.Right * widthMultiplier;
4032 10 : double top = aGraphicCropStruct.Top * heightMultiplier;
4033 10 : double bottom = aGraphicCropStruct.Bottom * heightMultiplier;
4034 :
4035 : m_pSerializer->singleElementNS( XML_a, XML_srcRect,
4036 : XML_l, I32S(left),
4037 : XML_t, I32S(top),
4038 : XML_r, I32S(right),
4039 : XML_b, I32S(bottom),
4040 10 : FSEND );
4041 104 : }
4042 104 : }
4043 :
4044 528 : void DocxAttributeOutput::ClearRelIdCache()
4045 : {
4046 528 : m_aRelIdCache.clear();
4047 528 : }
4048 :
4049 112 : void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode, const SdrObject* pSdrObj )
4050 : {
4051 : OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size& rSize, const SwFlyFrmFmt* pOLEFrmFmt, SwOLENode* pOLENode, const SdrObject* pSdrObj ) - some stuff still missing" );
4052 :
4053 112 : GetSdtEndBefore(pSdrObj);
4054 :
4055 : // detect mis-use of the API
4056 : assert(pGrfNode || (pOLEFrmFmt && pOLENode));
4057 112 : const SwFrmFmt* pFrmFmt = pGrfNode ? pGrfNode->GetFlyFmt() : pOLEFrmFmt;
4058 : // create the relation ID
4059 112 : OString aRelId;
4060 : sal_Int32 nImageType;
4061 112 : if ( pGrfNode && pGrfNode->IsLinkedFile() )
4062 : {
4063 : // linked image, just create the relation
4064 0 : OUString aFileName;
4065 0 : pGrfNode->GetFileFilterNms( &aFileName, 0 );
4066 :
4067 : // TODO Convert the file name to relative for better interoperability
4068 :
4069 0 : aRelId = m_rExport.AddRelation(
4070 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
4071 0 : aFileName );
4072 :
4073 0 : nImageType = XML_link;
4074 : }
4075 : else
4076 : {
4077 : // inline, we also have to write the image itself
4078 112 : const Graphic* pGraphic = 0;
4079 112 : if (pGrfNode)
4080 108 : pGraphic = &pGrfNode->GetGrf();
4081 : else
4082 4 : pGraphic = pOLENode->GetGraphic();
4083 :
4084 112 : if (m_aRelIdCache.find(pGraphic) != m_aRelIdCache.end())
4085 : // We already have a RelId for this Graphic.
4086 22 : aRelId = m_aRelIdCache[pGraphic];
4087 : else
4088 : {
4089 : // Not in cache, then need to write it.
4090 90 : m_rDrawingML.SetFS( m_pSerializer ); // to be sure that we write to the right stream
4091 :
4092 90 : bool bSwapped = pGraphic->IsSwapOut();
4093 90 : if (bSwapped)
4094 : {
4095 0 : if (pGrfNode)
4096 : {
4097 : // always swapin via the Node
4098 0 : const_cast<SwGrfNode*>(pGrfNode)->SwapIn();
4099 : }
4100 : else
4101 0 : const_cast<Graphic*>(pGraphic)->SwapIn();
4102 : }
4103 :
4104 90 : OUString aImageId = m_rDrawingML.WriteImage( *pGraphic );
4105 :
4106 90 : if (bSwapped)
4107 0 : const_cast<Graphic*>(pGraphic)->SwapOut();
4108 :
4109 90 : aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
4110 90 : m_aRelIdCache[pGraphic] = aRelId;
4111 : }
4112 :
4113 112 : nImageType = XML_embed;
4114 : }
4115 :
4116 : // In case there are any grab-bag items on the graphic frame, emit them now.
4117 : // These are always character grab-bags, as graphics are at-char or as-char in Word.
4118 112 : const SfxPoolItem* pItem = 0;
4119 112 : if (pFrmFmt->GetAttrSet().HasItem(RES_FRMATR_GRABBAG, &pItem))
4120 : {
4121 8 : const SfxGrabBagItem* pGrabBag = static_cast<const SfxGrabBagItem*>(pItem);
4122 8 : CharGrabBag(*pGrabBag);
4123 : }
4124 :
4125 112 : m_rExport.SdrExporter().startDMLAnchorInline(pFrmFmt, rSize);
4126 :
4127 : // picture description (used for pic:cNvPr later too)
4128 112 : ::sax_fastparser::FastAttributeList* docPrattrList = m_pSerializer->createAttrList();
4129 112 : docPrattrList->add( XML_id, OString::number( m_anchorId++).getStr());
4130 112 : docPrattrList->add( XML_name, OUStringToOString( pFrmFmt->GetName(), RTL_TEXTENCODING_UTF8 ) );
4131 112 : docPrattrList->add( XML_descr, OUStringToOString( pGrfNode ? pGrfNode->GetDescription() : pOLEFrmFmt->GetObjDescription(), RTL_TEXTENCODING_UTF8 ).getStr());
4132 112 : if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT )
4133 108 : docPrattrList->add( XML_title, OUStringToOString( pGrfNode ? pGrfNode->GetTitle() : pOLEFrmFmt->GetObjTitle(), RTL_TEXTENCODING_UTF8 ).getStr());
4134 224 : XFastAttributeListRef docPrAttrListRef( docPrattrList );
4135 112 : m_pSerializer->startElementNS( XML_wp, XML_docPr, docPrAttrListRef );
4136 : // TODO hyperlink
4137 : // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
4138 : // FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
4139 : // FSNS( XML_r, XML_id ), "rId4",
4140 : // FSEND );
4141 112 : m_pSerializer->endElementNS( XML_wp, XML_docPr );
4142 :
4143 : m_pSerializer->startElementNS( XML_wp, XML_cNvGraphicFramePr,
4144 112 : FSEND );
4145 : // TODO change aspect?
4146 : m_pSerializer->singleElementNS( XML_a, XML_graphicFrameLocks,
4147 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
4148 : XML_noChangeAspect, "1",
4149 112 : FSEND );
4150 112 : m_pSerializer->endElementNS( XML_wp, XML_cNvGraphicFramePr );
4151 :
4152 : m_pSerializer->startElementNS( XML_a, XML_graphic,
4153 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
4154 112 : FSEND );
4155 : m_pSerializer->startElementNS( XML_a, XML_graphicData,
4156 : XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/picture",
4157 112 : FSEND );
4158 :
4159 : m_pSerializer->startElementNS( XML_pic, XML_pic,
4160 : FSNS( XML_xmlns, XML_pic ), "http://schemas.openxmlformats.org/drawingml/2006/picture",
4161 112 : FSEND );
4162 :
4163 : m_pSerializer->startElementNS( XML_pic, XML_nvPicPr,
4164 112 : FSEND );
4165 : // It seems pic:cNvpr and wp:docPr are pretty much the same thing with the same attributes
4166 112 : m_pSerializer->startElementNS( XML_pic, XML_cNvPr, docPrAttrListRef );
4167 :
4168 : // TODO hyperlink
4169 : // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
4170 : // FSNS( XML_r, XML_id ), "rId4",
4171 : // FSEND );
4172 112 : m_pSerializer->endElementNS( XML_pic, XML_cNvPr );
4173 :
4174 : m_pSerializer->startElementNS( XML_pic, XML_cNvPicPr,
4175 112 : FSEND );
4176 : // TODO change aspect?
4177 : m_pSerializer->singleElementNS( XML_a, XML_picLocks,
4178 : XML_noChangeAspect, "1", XML_noChangeArrowheads, "1",
4179 112 : FSEND );
4180 112 : m_pSerializer->endElementNS( XML_pic, XML_cNvPicPr );
4181 112 : m_pSerializer->endElementNS( XML_pic, XML_nvPicPr );
4182 :
4183 : // the actual picture
4184 : m_pSerializer->startElementNS( XML_pic, XML_blipFill,
4185 112 : FSEND );
4186 :
4187 : /* At this point we are certain that, WriteImage returns empty RelId
4188 : for unhandled graphic type. Therefore we write the picture description
4189 : and not the relation( coz there ain't any), so that the user knows
4190 : there is a image/graphic in the doc but it is broken instead of
4191 : completely discarding it.
4192 : */
4193 112 : if ( aRelId.isEmpty() )
4194 : m_pSerializer->singleElementNS( XML_a, XML_blip,
4195 4 : FSEND );
4196 : else
4197 : m_pSerializer->singleElementNS( XML_a, XML_blip,
4198 : FSNS( XML_r, nImageType ), aRelId.getStr(),
4199 108 : FSEND );
4200 :
4201 112 : if (pSdrObj){
4202 104 : WriteSrcRect(pSdrObj);
4203 : }
4204 :
4205 : m_pSerializer->startElementNS( XML_a, XML_stretch,
4206 112 : FSEND );
4207 : m_pSerializer->singleElementNS( XML_a, XML_fillRect,
4208 112 : FSEND );
4209 112 : m_pSerializer->endElementNS( XML_a, XML_stretch );
4210 112 : m_pSerializer->endElementNS( XML_pic, XML_blipFill );
4211 :
4212 : // TODO setup the right values below
4213 : m_pSerializer->startElementNS( XML_pic, XML_spPr,
4214 : XML_bwMode, "auto",
4215 112 : FSEND );
4216 : m_pSerializer->startElementNS( XML_a, XML_xfrm,
4217 112 : FSEND );
4218 : m_pSerializer->singleElementNS( XML_a, XML_off,
4219 : XML_x, "0", XML_y, "0",
4220 112 : FSEND );
4221 224 : OString aWidth( OString::number( TwipsToEMU( rSize.Width() ) ) );
4222 224 : OString aHeight( OString::number( TwipsToEMU( rSize.Height() ) ) );
4223 : m_pSerializer->singleElementNS( XML_a, XML_ext,
4224 : XML_cx, aWidth.getStr(),
4225 : XML_cy, aHeight.getStr(),
4226 112 : FSEND );
4227 112 : m_pSerializer->endElementNS( XML_a, XML_xfrm );
4228 : m_pSerializer->startElementNS( XML_a, XML_prstGeom,
4229 : XML_prst, "rect",
4230 112 : FSEND );
4231 : m_pSerializer->singleElementNS( XML_a, XML_avLst,
4232 112 : FSEND );
4233 112 : m_pSerializer->endElementNS( XML_a, XML_prstGeom );
4234 : m_pSerializer->singleElementNS( XML_a, XML_noFill,
4235 112 : FSEND );
4236 : m_pSerializer->startElementNS( XML_a, XML_ln,
4237 : XML_w, "9525",
4238 112 : FSEND );
4239 : m_pSerializer->singleElementNS( XML_a, XML_noFill,
4240 112 : FSEND );
4241 : m_pSerializer->singleElementNS( XML_a, XML_miter,
4242 : XML_lim, "800000",
4243 112 : FSEND );
4244 : m_pSerializer->singleElementNS( XML_a, XML_headEnd,
4245 112 : FSEND );
4246 : m_pSerializer->singleElementNS( XML_a, XML_tailEnd,
4247 112 : FSEND );
4248 112 : m_pSerializer->endElementNS( XML_a, XML_ln );
4249 :
4250 112 : m_rExport.SdrExporter().writeDMLEffectLst(*pFrmFmt);
4251 :
4252 112 : m_pSerializer->endElementNS( XML_pic, XML_spPr );
4253 :
4254 112 : m_pSerializer->endElementNS( XML_pic, XML_pic );
4255 :
4256 112 : m_pSerializer->endElementNS( XML_a, XML_graphicData );
4257 112 : m_pSerializer->endElementNS( XML_a, XML_graphic );
4258 224 : m_rExport.SdrExporter().endDMLAnchorInline(pFrmFmt);
4259 112 : }
4260 :
4261 242 : void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, SwOLENode& rOLENode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt )
4262 : {
4263 242 : if( WriteOLEChart( pSdrObj, rSize ))
4264 72 : return;
4265 170 : if( WriteOLEMath( pSdrObj, rOLENode, rSize ))
4266 138 : return;
4267 32 : if( PostponeOLE( pSdrObj, rOLENode, rSize, pFlyFrmFmt ))
4268 32 : return;
4269 : // Then we fall back to just export the object as a graphic.
4270 0 : if( m_postponedGraphic == NULL )
4271 0 : FlyFrameGraphic( 0, rSize, pFlyFrmFmt, &rOLENode );
4272 : else
4273 : // w:drawing should not be inside w:rPr, so write it out later
4274 0 : m_postponedGraphic->push_back( PostponedGraphic( 0, rSize, pFlyFrmFmt, &rOLENode, 0 ) );
4275 : }
4276 :
4277 242 : bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& rSize )
4278 : {
4279 242 : uno::Reference< chart2::XChartDocument > xChartDoc;
4280 484 : uno::Reference< drawing::XShape > xShape( ((SdrObject*)pSdrObj)->getUnoShape(), uno::UNO_QUERY );
4281 242 : if( xShape.is() )
4282 : {
4283 242 : uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
4284 242 : if( xPropSet.is() )
4285 242 : xChartDoc.set( xPropSet->getPropertyValue( "Model" ), uno::UNO_QUERY );
4286 : }
4287 :
4288 242 : if( xChartDoc.is() )
4289 : {
4290 72 : m_postponedChart = pSdrObj;
4291 72 : m_postponedChartSize = rSize;
4292 72 : return true;
4293 : }
4294 412 : return false;
4295 : }
4296 :
4297 : /*
4298 : * Write chart hierarchy in w:drawing after end element of w:rPr tag.
4299 : */
4300 18106 : void DocxAttributeOutput::WritePostponedChart()
4301 : {
4302 18106 : if(m_postponedChart == NULL)
4303 18034 : return;
4304 72 : uno::Reference< chart2::XChartDocument > xChartDoc;
4305 144 : uno::Reference< drawing::XShape > xShape( ((SdrObject*)m_postponedChart)->getUnoShape(), uno::UNO_QUERY );
4306 72 : if( xShape.is() )
4307 : {
4308 72 : uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
4309 72 : if( xPropSet.is() )
4310 72 : xChartDoc.set( xPropSet->getPropertyValue( "Model" ), uno::UNO_QUERY );
4311 : }
4312 :
4313 72 : if( xChartDoc.is() )
4314 : {
4315 : OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
4316 : m_pSerializer->startElementNS( XML_w, XML_drawing,
4317 72 : FSEND );
4318 : m_pSerializer->startElementNS( XML_wp, XML_inline,
4319 : XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
4320 72 : FSEND );
4321 :
4322 72 : OString aWidth( OString::number( TwipsToEMU( m_postponedChartSize.Width() ) ) );
4323 144 : OString aHeight( OString::number( TwipsToEMU( m_postponedChartSize.Height() ) ) );
4324 : m_pSerializer->singleElementNS( XML_wp, XML_extent,
4325 : XML_cx, aWidth.getStr(),
4326 : XML_cy, aHeight.getStr(),
4327 72 : FSEND );
4328 : // TODO - the right effectExtent, extent including the effect
4329 : m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
4330 : XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
4331 72 : FSEND );
4332 :
4333 144 : OUString sName("Object 1");
4334 144 : uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
4335 72 : if( xNamed.is() )
4336 72 : sName = xNamed->getName();
4337 :
4338 : /* If there is a scenario where a chart is followed by a shape
4339 : which is being exported as an alternate content then, the
4340 : docPr Id is being repeated, ECMA 20.4.2.5 says that the
4341 : docPr Id should be unique, ensuring the same here.
4342 : */
4343 : m_pSerializer->singleElementNS( XML_wp, XML_docPr,
4344 : XML_id, I32S( m_anchorId++ ),
4345 : XML_name, USS( sName ),
4346 72 : FSEND );
4347 :
4348 : m_pSerializer->singleElementNS( XML_wp, XML_cNvGraphicFramePr,
4349 72 : FSEND );
4350 :
4351 : m_pSerializer->startElementNS( XML_a, XML_graphic,
4352 : FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
4353 72 : FSEND );
4354 :
4355 : m_pSerializer->startElementNS( XML_a, XML_graphicData,
4356 : XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart",
4357 72 : FSEND );
4358 :
4359 144 : OString aRelId;
4360 : static sal_Int32 nChartCount = 0;
4361 72 : nChartCount++;
4362 144 : uno::Reference< frame::XModel > xModel( xChartDoc, uno::UNO_QUERY );
4363 72 : aRelId = m_rExport.OutputChart( xModel, nChartCount, m_pSerializer );
4364 :
4365 : m_pSerializer->singleElementNS( XML_c, XML_chart,
4366 : FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
4367 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
4368 : FSNS( XML_r, XML_id ), aRelId.getStr(),
4369 72 : FSEND );
4370 :
4371 72 : m_pSerializer->endElementNS( XML_a, XML_graphicData );
4372 72 : m_pSerializer->endElementNS( XML_a, XML_graphic );
4373 72 : m_pSerializer->endElementNS( XML_wp, XML_inline );
4374 144 : m_pSerializer->endElementNS( XML_w, XML_drawing );
4375 :
4376 : }
4377 72 : m_postponedChart = NULL;
4378 144 : return;
4379 : }
4380 :
4381 170 : bool DocxAttributeOutput::WriteOLEMath( const SdrObject*, const SwOLENode& rOLENode, const Size& )
4382 : {
4383 170 : uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
4384 340 : SvGlobalName aObjName(xObj->getClassID());
4385 :
4386 170 : if( !SotExchange::IsMath(aObjName) )
4387 32 : return false;
4388 : assert( m_postponedMath == NULL ); // make it a list if there can be more inside one run
4389 138 : m_postponedMath = &rOLENode;
4390 308 : return true;
4391 : }
4392 :
4393 18158 : void DocxAttributeOutput::WritePostponedMath()
4394 : {
4395 18158 : if( m_postponedMath == NULL )
4396 36178 : return;
4397 138 : uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode*>(m_postponedMath)->GetOLEObj().GetOleRef());
4398 276 : uno::Reference< uno::XInterface > xInterface( xObj->getComponent(), uno::UNO_QUERY );
4399 : // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
4400 : // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
4401 : // to RTLD_GLOBAL, so most probably a gcc bug.
4402 138 : oox::FormulaExportBase* formulaexport = dynamic_cast<oox::FormulaExportBase*>(dynamic_cast<SfxBaseModel*>(xInterface.get()));
4403 : assert( formulaexport != NULL );
4404 138 : if (formulaexport)
4405 138 : formulaexport->writeFormulaOoxml( m_pSerializer, GetExport().GetFilter().getVersion());
4406 276 : m_postponedMath = NULL;
4407 : }
4408 :
4409 20 : void DocxAttributeOutput::WritePostponedFormControl(const SdrObject* pObject)
4410 : {
4411 20 : if (pObject && pObject->GetObjInventor() == FmFormInventor)
4412 : {
4413 20 : if (SdrUnoObj *pFormObj = const_cast<SdrUnoObj*>(PTR_CAST(SdrUnoObj,pObject)))
4414 : {
4415 20 : uno::Reference<awt::XControlModel> xControlModel = pFormObj->GetUnoControlModel();
4416 40 : uno::Reference<lang::XServiceInfo> xInfo(xControlModel, uno::UNO_QUERY);
4417 20 : if (xInfo->supportsService("com.sun.star.form.component.DateField"))
4418 : {
4419 : // gather component properties
4420 :
4421 10 : Date aOriginalDate(Date::EMPTY);
4422 20 : OUString sOriginalContent, sDateFormat, sAlias;
4423 20 : OUString sLocale("en-US");
4424 20 : uno::Sequence<beans::PropertyValue> aGrabBag;
4425 20 : uno::Reference<beans::XPropertySet> xShapePropertySet(pFormObj->getUnoShape(), uno::UNO_QUERY);
4426 20 : uno::Sequence<beans::PropertyValue> aCharFormat;
4427 10 : if (xShapePropertySet->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG) >>= aGrabBag)
4428 : {
4429 78 : for (sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
4430 : {
4431 68 : if (aGrabBag[i].Name == "DateFormat")
4432 10 : aGrabBag[i].Value >>= sDateFormat;
4433 58 : else if (aGrabBag[i].Name == "Locale")
4434 10 : aGrabBag[i].Value >>= sLocale;
4435 48 : else if (aGrabBag[i].Name == "OriginalContent")
4436 10 : aGrabBag[i].Value >>= sOriginalContent;
4437 38 : else if (aGrabBag[i].Name == "OriginalDate")
4438 : {
4439 10 : css::util::Date aUNODate;
4440 10 : aGrabBag[i].Value >>= aUNODate;
4441 10 : aOriginalDate.SetDay(aUNODate.Day);
4442 10 : aOriginalDate.SetMonth(aUNODate.Month);
4443 10 : aOriginalDate.SetYear(aUNODate.Year);
4444 : }
4445 28 : else if (aGrabBag[i].Name == "CharFormat")
4446 10 : aGrabBag[i].Value >>= aCharFormat;
4447 18 : else if (aGrabBag[i].Name == "ooxml:CT_SdtPr_alias")
4448 4 : aGrabBag[i].Value >>= sAlias;
4449 : }
4450 : }
4451 20 : uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
4452 :
4453 20 : OString sDate;
4454 20 : OUString aContentText;
4455 10 : bool bHasDate = false;
4456 10 : css::util::Date aUNODate;
4457 10 : if (xPropertySet->getPropertyValue("Date") >>= aUNODate)
4458 : {
4459 6 : bHasDate = true;
4460 6 : Date aDate(aUNODate.Day, aUNODate.Month, aUNODate.Year);
4461 6 : sDate = DateToOString(aDate);
4462 :
4463 6 : if (aOriginalDate == aDate)
4464 : {
4465 6 : aContentText = sOriginalContent;
4466 : // sDateFormat was extracted from the grab bag
4467 : }
4468 : else
4469 : {
4470 0 : aContentText = OUString::createFromAscii(DateToDDMMYYYYOString(aDate).getStr());
4471 0 : sDateFormat = "dd/MM/yyyy";
4472 : }
4473 : }
4474 : else
4475 4 : aContentText = xPropertySet->getPropertyValue("HelpText").get<OUString>();
4476 :
4477 : // output component
4478 :
4479 10 : m_pSerializer->startElementNS(XML_w, XML_sdt, FSEND);
4480 10 : m_pSerializer->startElementNS(XML_w, XML_sdtPr, FSEND);
4481 :
4482 10 : if (!sAlias.isEmpty())
4483 : m_pSerializer->singleElementNS(XML_w, XML_alias,
4484 : FSNS(XML_w, XML_val), OUStringToOString(sAlias, RTL_TEXTENCODING_UTF8),
4485 4 : FSEND);
4486 :
4487 10 : if (bHasDate)
4488 : m_pSerializer->startElementNS(XML_w, XML_date,
4489 : FSNS( XML_w, XML_fullDate ), sDate.getStr(),
4490 6 : FSEND);
4491 : else
4492 4 : m_pSerializer->startElementNS(XML_w, XML_date, FSEND);
4493 :
4494 : m_pSerializer->singleElementNS(XML_w, XML_dateFormat,
4495 : FSNS(XML_w, XML_val),
4496 : rtl::OUStringToOString( sDateFormat, RTL_TEXTENCODING_UTF8 ).getStr(),
4497 10 : FSEND);
4498 : m_pSerializer->singleElementNS(XML_w, XML_lid,
4499 : FSNS(XML_w, XML_val),
4500 : rtl::OUStringToOString( sLocale, RTL_TEXTENCODING_UTF8 ).getStr(),
4501 10 : FSEND);
4502 : m_pSerializer->singleElementNS(XML_w, XML_storeMappedDataAs,
4503 : FSNS(XML_w, XML_val), "dateTime",
4504 10 : FSEND);
4505 : m_pSerializer->singleElementNS(XML_w, XML_calendar,
4506 : FSNS(XML_w, XML_val), "gregorian",
4507 10 : FSEND);
4508 :
4509 10 : m_pSerializer->endElementNS(XML_w, XML_date);
4510 10 : m_pSerializer->endElementNS(XML_w, XML_sdtPr);
4511 :
4512 10 : m_pSerializer->startElementNS(XML_w, XML_sdtContent, FSEND);
4513 10 : m_pSerializer->startElementNS(XML_w, XML_r, FSEND);
4514 :
4515 10 : if (aCharFormat.hasElements())
4516 : {
4517 4 : m_pTableStyleExport->SetSerializer(m_pSerializer);
4518 4 : m_pTableStyleExport->CharFormat(aCharFormat);
4519 : }
4520 :
4521 10 : RunText(aContentText);
4522 10 : m_pSerializer->endElementNS(XML_w, XML_r);
4523 10 : m_pSerializer->endElementNS(XML_w, XML_sdtContent);
4524 :
4525 20 : m_pSerializer->endElementNS(XML_w, XML_sdt);
4526 : }
4527 10 : else if (xInfo->supportsService("com.sun.star.form.component.ComboBox"))
4528 : {
4529 : // gather component properties
4530 :
4531 10 : uno::Reference<beans::XPropertySet> xPropertySet(xControlModel, uno::UNO_QUERY);
4532 20 : OUString sText = xPropertySet->getPropertyValue("Text").get<OUString>();
4533 20 : uno::Sequence<OUString> aItems = xPropertySet->getPropertyValue("StringItemList").get< uno::Sequence<OUString> >();
4534 :
4535 : // output component
4536 :
4537 10 : m_pSerializer->startElementNS(XML_w, XML_sdt, FSEND);
4538 10 : m_pSerializer->startElementNS(XML_w, XML_sdtPr, FSEND);
4539 :
4540 10 : m_pSerializer->startElementNS(XML_w, XML_dropDownList, FSEND);
4541 :
4542 50 : for (sal_Int32 i=0; i < aItems.getLength(); ++i)
4543 : {
4544 : m_pSerializer->singleElementNS(XML_w, XML_listItem,
4545 : FSNS(XML_w, XML_displayText),
4546 40 : rtl::OUStringToOString( aItems[i], RTL_TEXTENCODING_UTF8 ).getStr(),
4547 : FSNS(XML_w, XML_value),
4548 40 : rtl::OUStringToOString( aItems[i], RTL_TEXTENCODING_UTF8 ).getStr(),
4549 80 : FSEND);
4550 : }
4551 :
4552 10 : m_pSerializer->endElementNS(XML_w, XML_dropDownList);
4553 10 : m_pSerializer->endElementNS(XML_w, XML_sdtPr);
4554 :
4555 10 : m_pSerializer->startElementNS(XML_w, XML_sdtContent, FSEND);
4556 10 : m_pSerializer->startElementNS(XML_w, XML_r, FSEND);
4557 10 : RunText(sText);
4558 10 : m_pSerializer->endElementNS(XML_w, XML_r);
4559 10 : m_pSerializer->endElementNS(XML_w, XML_sdtContent);
4560 :
4561 20 : m_pSerializer->endElementNS(XML_w, XML_sdt);
4562 20 : }
4563 : }
4564 : }
4565 20 : }
4566 :
4567 32 : bool DocxAttributeOutput::PostponeOLE( const SdrObject*, SwOLENode& rNode, const Size& rSize, const SwFlyFrmFmt* pFlyFrmFmt )
4568 : {
4569 32 : if( m_postponedOLE == NULL )
4570 : //cannot be postponed, try to write now
4571 2 : WriteOLE( rNode, rSize, pFlyFrmFmt );
4572 : else
4573 30 : m_postponedOLE->push_back( PostponedOLE( &rNode, rSize, pFlyFrmFmt ) );
4574 32 : return true;
4575 : }
4576 :
4577 : /*
4578 : * Write w:object hierarchy for embedded objects after end element of w:rPr tag.
4579 : */
4580 18106 : void DocxAttributeOutput::WritePostponedOLE()
4581 : {
4582 18106 : if( m_postponedOLE == NULL )
4583 18106 : return;
4584 :
4585 54408 : for( std::list< PostponedOLE >::iterator it = m_postponedOLE->begin();
4586 36272 : it != m_postponedOLE->end();
4587 : ++it )
4588 : {
4589 30 : WriteOLE( *it->object, it->size, it->frame );
4590 : }
4591 :
4592 : // clear list of postponed objects
4593 18106 : delete m_postponedOLE;
4594 18106 : m_postponedOLE = NULL;
4595 : }
4596 :
4597 32 : void DocxAttributeOutput::WriteOLE( SwOLENode& rNode, const Size& rSize, const SwFlyFrmFmt* rFlyFrmFmt )
4598 : {
4599 : // get interoperability information about embedded objects
4600 32 : uno::Reference< beans::XPropertySet > xPropSet( m_rExport.pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
4601 60 : OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
4602 60 : uno::Sequence< beans::PropertyValue > aGrabBag, aObjectsInteropList,aObjectInteropAttributes;
4603 32 : xPropSet->getPropertyValue( pName ) >>= aGrabBag;
4604 62 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
4605 60 : if ( aGrabBag[i].Name == "EmbeddedObjects" )
4606 : {
4607 30 : aGrabBag[i].Value >>= aObjectsInteropList;
4608 30 : break;
4609 : }
4610 :
4611 32 : SwOLEObj& aObject = rNode.GetOLEObj();
4612 60 : uno::Reference < embed::XEmbeddedObject > xObj( aObject.GetOleRef() );
4613 32 : comphelper::EmbeddedObjectContainer* aContainer = aObject.GetObject().GetContainer();
4614 60 : OUString sObjectName = aContainer->GetEmbeddedObjectName( xObj );
4615 :
4616 : // set some attributes according to the type of the embedded object
4617 60 : OUString sProgID, sMediaType, sRelationType, sFileExtension, sDrawAspect="Content";
4618 36 : for( sal_Int32 i=0; i < aObjectsInteropList.getLength(); ++i )
4619 34 : if ( aObjectsInteropList[i].Name == sObjectName )
4620 : {
4621 30 : aObjectsInteropList[i].Value >>= aObjectInteropAttributes;
4622 30 : break;
4623 : }
4624 :
4625 92 : for( sal_Int32 i=0; i < aObjectInteropAttributes.getLength(); ++i )
4626 : {
4627 60 : if ( aObjectInteropAttributes[i].Name == "ProgID" )
4628 : {
4629 30 : aObjectInteropAttributes[i].Value >>= sProgID;
4630 : }
4631 30 : else if ( aObjectInteropAttributes[i].Name == "DrawAspect" )
4632 : {
4633 30 : aObjectInteropAttributes[i].Value >>= sDrawAspect;
4634 : }
4635 : }
4636 :
4637 32 : if( sProgID == "Excel.Sheet.12" )
4638 : {
4639 6 : sMediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
4640 6 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4641 6 : sFileExtension = "xlsx";
4642 : }
4643 26 : else if(sProgID.startsWith("Excel.SheetBinaryMacroEnabled.12") )
4644 : {
4645 2 : sMediaType = "application/vnd.ms-excel.sheet.binary.macroEnabled.12";
4646 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4647 2 : sFileExtension = "xlsb";
4648 : }
4649 24 : else if( sProgID.startsWith("Excel.SheetMacroEnabled.12") )
4650 : {
4651 2 : sMediaType = "application/vnd.ms-excel.sheet.macroEnabled.12";
4652 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4653 2 : sFileExtension = "xlsm";
4654 : }
4655 22 : else if( sProgID.startsWith("Excel.Sheet") )
4656 : {
4657 0 : sMediaType = "application/vnd.ms-excel";
4658 0 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
4659 0 : sFileExtension = "xls";
4660 : }
4661 22 : else if( sProgID == "PowerPoint.Show.12" )
4662 : {
4663 0 : sMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
4664 0 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4665 0 : sFileExtension = "pptx";
4666 : }
4667 22 : else if(sProgID == "PowerPoint.ShowMacroEnabled.12")
4668 : {
4669 2 : sMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.12";
4670 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4671 2 : sFileExtension = "pptm";
4672 : }
4673 20 : else if( sProgID.startsWith("PowerPoint.Show") )
4674 : {
4675 0 : sMediaType = "application/vnd.ms-powerpoint";
4676 0 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
4677 0 : sFileExtension = "ppt";
4678 : }
4679 20 : else if (sProgID.startsWith("PowerPoint.Slide.12"))
4680 : {
4681 4 : sMediaType = "application/vnd.openxmlformats-officedocument.presentationml.slide";
4682 4 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4683 4 : sFileExtension = "sldx";
4684 : }
4685 16 : else if( sProgID == "PowerPoint.SlideMacroEnabled.12" )
4686 : {
4687 2 : sMediaType = "application/vnd.ms-powerpoint.slide.macroEnabled.12";
4688 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4689 2 : sFileExtension = "sldm";
4690 : }
4691 14 : else if( sProgID == "Word.DocumentMacroEnabled.12" )
4692 : {
4693 2 : sMediaType = "application/vnd.ms-word.document.macroEnabled.12";
4694 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4695 2 : sFileExtension = "docm";
4696 : }
4697 12 : else if (sProgID == "Word.Document.12")
4698 : {
4699 2 : sMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
4700 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
4701 2 : sFileExtension = "docx";
4702 : }
4703 10 : else if( sProgID == "Word.Document.8" )
4704 : {
4705 2 : sMediaType = "application/msword";
4706 2 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
4707 2 : sFileExtension = "doc";
4708 : }
4709 : else
4710 : {
4711 8 : sMediaType = "application/vnd.openxmlformats-officedocument.oleObject";
4712 8 : sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
4713 8 : sFileExtension = "bin";
4714 : }
4715 :
4716 : // write embedded file
4717 60 : OString sId = m_rExport.WriteOLEObject( aObject, sMediaType, sRelationType, sFileExtension );
4718 :
4719 32 : if( sId.isEmpty() )
4720 : {
4721 : // the embedded file could not be saved
4722 : // fallback: save as an image
4723 4 : FlyFrameGraphic( 0, rSize, rFlyFrmFmt, &rNode );
4724 36 : return;
4725 : }
4726 :
4727 : // write preview image
4728 28 : const Graphic* pGraphic = rNode.GetGraphic();
4729 28 : m_rDrawingML.SetFS(m_pSerializer);
4730 56 : OUString sImageId = m_rDrawingML.WriteImage( *pGraphic );
4731 :
4732 28 : m_pSerializer->startElementNS( XML_w, XML_object, FSEND );
4733 :
4734 56 : OStringBuffer sShapeStyle, sShapeId;
4735 28 : sShapeStyle.append( "width:" ).append( double( rSize.Width() ) / 20 )
4736 56 : .append( "pt;height:" ).append( double( rSize.Height() ) / 20 )
4737 28 : .append( "pt" ); //from VMLExport::AddRectangleDimensions(), it does: value/20
4738 28 : sShapeId.append( "ole_" ).append( sId );
4739 :
4740 : // shape definition
4741 : m_pSerializer->startElementNS( XML_v, XML_shape,
4742 : XML_id, sShapeId.getStr(),
4743 : XML_style, sShapeStyle.getStr(),
4744 : FSNS( XML_o, XML_ole ), "", //compulsory, even if it's empty
4745 28 : FSEND );
4746 :
4747 : // shape filled with the preview image
4748 : m_pSerializer->singleElementNS( XML_v, XML_imagedata,
4749 : FSNS( XML_r, XML_id ), OUStringToOString( sImageId, RTL_TEXTENCODING_UTF8 ).getStr(),
4750 : FSNS( XML_o, XML_title ), "",
4751 28 : FSEND );
4752 :
4753 28 : m_pSerializer->endElementNS( XML_v, XML_shape );
4754 :
4755 : // OLE object definition
4756 : m_pSerializer->singleElementNS( XML_o, XML_OLEObject,
4757 : XML_Type, "Embed",
4758 56 : XML_ProgID, OUStringToOString( sProgID, RTL_TEXTENCODING_UTF8 ).getStr(),
4759 28 : XML_ShapeID, sShapeId.getStr(),
4760 56 : XML_DrawAspect, OUStringToOString( sDrawAspect, RTL_TEXTENCODING_UTF8 ).getStr(),
4761 56 : XML_ObjectID, "_" + OString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max())),
4762 28 : FSNS( XML_r, XML_id ), sId.getStr(),
4763 224 : FSEND );
4764 :
4765 56 : m_pSerializer->endElementNS( XML_w, XML_object );
4766 : }
4767 :
4768 : /*
4769 : * Write w:pict hierarchy end element of w:rPr tag.
4770 : */
4771 18106 : void DocxAttributeOutput::WritePostponedVMLDrawing()
4772 : {
4773 18106 : if(m_postponedVMLDrawing == NULL)
4774 18106 : return;
4775 :
4776 54318 : for( std::list< PostponedDrawing >::iterator it = m_postponedVMLDrawing->begin();
4777 36212 : it != m_postponedVMLDrawing->end();
4778 : ++it )
4779 : {
4780 0 : m_rExport.SdrExporter().writeVMLDrawing(it->object, *(it->frame), *(it->point));
4781 : }
4782 18106 : delete m_postponedVMLDrawing;
4783 18106 : m_postponedVMLDrawing = NULL;
4784 : }
4785 :
4786 10 : void DocxAttributeOutput::WritePostponedCustomShape()
4787 : {
4788 10 : if(m_postponedCustomShape == NULL)
4789 10 : return;
4790 :
4791 10 : bool bStartedParaSdt = m_bStartedParaSdt;
4792 60 : for( std::list< PostponedDrawing >::iterator it = m_postponedCustomShape->begin();
4793 40 : it != m_postponedCustomShape->end();
4794 : ++it )
4795 : {
4796 10 : if ( IsAlternateContentChoiceOpen() )
4797 0 : m_rExport.SdrExporter().writeDMLDrawing(it->object, (it->frame), m_anchorId++);
4798 : else
4799 10 : m_rExport.SdrExporter().writeDMLAndVMLDrawing(it->object, *(it->frame), *(it->point), m_anchorId++);
4800 : }
4801 10 : m_bStartedParaSdt = bStartedParaSdt;
4802 10 : delete m_postponedCustomShape;
4803 10 : m_postponedCustomShape = NULL;
4804 : }
4805 :
4806 18106 : void DocxAttributeOutput::WritePostponedDMLDrawing()
4807 : {
4808 18106 : if(m_postponedDMLDrawing == NULL)
4809 18106 : return;
4810 :
4811 : // Clear the list early, this method may be called recursively.
4812 18106 : std::list<PostponedDrawing>* postponedDMLDrawing = m_postponedDMLDrawing;
4813 18106 : m_postponedDMLDrawing = NULL;
4814 18106 : std::list<PostponedOLE>* postponedOLE = m_postponedOLE;
4815 18106 : m_postponedOLE = 0;
4816 :
4817 18106 : bool bStartedParaSdt = m_bStartedParaSdt;
4818 54678 : for( std::list< PostponedDrawing >::iterator it = postponedDMLDrawing->begin();
4819 36452 : it != postponedDMLDrawing->end();
4820 : ++it )
4821 : {
4822 : // Avoid w:drawing within another w:drawing.
4823 120 : if ( IsAlternateContentChoiceOpen() && !( m_rExport.SdrExporter().IsDrawingOpen()) )
4824 0 : m_rExport.SdrExporter().writeDMLDrawing(it->object, (it->frame), m_anchorId++);
4825 : else
4826 120 : m_rExport.SdrExporter().writeDMLAndVMLDrawing(it->object, *(it->frame), *(it->point), m_anchorId++);
4827 : }
4828 18106 : m_bStartedParaSdt = bStartedParaSdt;
4829 :
4830 18106 : delete postponedDMLDrawing;
4831 18106 : m_postponedOLE = postponedOLE;
4832 : }
4833 :
4834 1400 : void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Point& rNdTopLeft )
4835 : {
4836 1400 : m_pSerializer->mark();
4837 :
4838 1400 : switch ( rFrame.GetWriterType() )
4839 : {
4840 : case sw::Frame::eGraphic:
4841 : {
4842 108 : const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
4843 108 : const SwNode *pNode = rFrame.GetContent();
4844 108 : const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
4845 108 : if ( pGrfNode )
4846 : {
4847 108 : if( m_postponedGraphic == NULL )
4848 : {
4849 26 : m_bPostponedProcessingFly = false ;
4850 26 : FlyFrameGraphic( pGrfNode, rFrame.GetLayoutSize(), 0, 0, pSdrObj);
4851 : }
4852 : else // we are writing out attributes, but w:drawing should not be inside w:rPr,
4853 : { // so write it out later
4854 82 : m_bPostponedProcessingFly = true ;
4855 82 : m_postponedGraphic->push_back( PostponedGraphic( pGrfNode, rFrame.GetLayoutSize(), 0, 0, pSdrObj));
4856 : }
4857 : }
4858 : }
4859 108 : break;
4860 : case sw::Frame::eDrawing:
4861 : {
4862 686 : const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
4863 686 : if ( pSdrObj )
4864 : {
4865 686 : if ( IsDiagram( pSdrObj ) )
4866 : {
4867 14 : if ( m_postponedDiagram == NULL )
4868 : {
4869 2 : m_bPostponedProcessingFly = false ;
4870 2 : m_rExport.SdrExporter().writeDiagram( pSdrObj, rFrame.GetFrmFmt(), m_anchorId++);
4871 : }
4872 : else // we are writing out attributes, but w:drawing should not be inside w:rPr,
4873 : { // so write it out later
4874 12 : m_bPostponedProcessingFly = true ;
4875 12 : m_postponedDiagram->push_back( PostponedDiagram( pSdrObj, &(rFrame.GetFrmFmt()) ));
4876 : }
4877 : }
4878 : else
4879 : {
4880 672 : if ( m_postponedDMLDrawing == NULL )
4881 : {
4882 546 : bool bStartedParaSdt = m_bStartedParaSdt;
4883 546 : if ( IsAlternateContentChoiceOpen() )
4884 : {
4885 : // Do not write w:drawing inside w:drawing. Instead Postpone the Inner Drawing.
4886 4 : if( m_rExport.SdrExporter().IsDrawingOpen() )
4887 4 : m_postponedCustomShape->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft));
4888 : else
4889 0 : m_rExport.SdrExporter().writeDMLDrawing( pSdrObj, &rFrame.GetFrmFmt(), m_anchorId++);
4890 : }
4891 : else
4892 542 : m_rExport.SdrExporter().writeDMLAndVMLDrawing( pSdrObj, rFrame.GetFrmFmt(), rNdTopLeft, m_anchorId++);
4893 546 : m_bStartedParaSdt = bStartedParaSdt;
4894 :
4895 546 : m_bPostponedProcessingFly = false ;
4896 : }
4897 : // IsAlternateContentChoiceOpen() : check is to ensure that only one object is getting added. Without this check, plus one obejct gets added
4898 : // m_bParagraphFrameOpen : Check if the frame is open.
4899 126 : else if (IsAlternateContentChoiceOpen() && m_bParagraphFrameOpen)
4900 : {
4901 6 : m_postponedCustomShape->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft));
4902 : }
4903 : else
4904 : {
4905 : // we are writing out attributes, but w:drawing should not be inside w:rPr, so write it out later
4906 120 : m_bPostponedProcessingFly = true ;
4907 120 : m_postponedDMLDrawing->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft));
4908 : }
4909 : }
4910 : }
4911 : }
4912 686 : break;
4913 : case sw::Frame::eTxtBox:
4914 : {
4915 : // If this is a TextBox of a shape, then ignore: it's handled in WriteTextBox().
4916 344 : if (m_rExport.SdrExporter().isTextBox(rFrame.GetFrmFmt()))
4917 218 : break;
4918 :
4919 : // The frame output is postponed to the end of the anchor paragraph
4920 126 : bool bDuplicate = false;
4921 126 : const OUString& rName = rFrame.GetFrmFmt().GetName();
4922 126 : unsigned nSize = m_aFramesOfParagraph.size();
4923 168 : for( unsigned nIndex = 0; nIndex < nSize; ++nIndex )
4924 : {
4925 42 : const OUString& rNameExisting = m_aFramesOfParagraph[nIndex].GetFrmFmt().GetName();
4926 :
4927 42 : if (!rName.isEmpty() && !rNameExisting.isEmpty())
4928 : {
4929 18 : if (rName == rNameExisting)
4930 4 : bDuplicate = true;
4931 : }
4932 42 : }
4933 :
4934 126 : if( !bDuplicate )
4935 : {
4936 122 : m_bPostponedProcessingFly = true ;
4937 122 : m_aFramesOfParagraph.push_back(sw::Frame(rFrame));
4938 126 : }
4939 : }
4940 126 : break;
4941 : case sw::Frame::eOle:
4942 : {
4943 242 : const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
4944 242 : const SdrObject *pSdrObj = rFrmFmt.FindRealSdrObject();
4945 242 : if ( pSdrObj )
4946 : {
4947 242 : SwNodeIndex aIdx(*rFrmFmt.GetCntnt().GetCntntIdx(), 1);
4948 242 : SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
4949 242 : WriteOLE2Obj( pSdrObj, rOLENd, rFrame.GetLayoutSize(), dynamic_cast<const SwFlyFrmFmt*>( &rFrmFmt ));
4950 242 : m_bPostponedProcessingFly = false ;
4951 : }
4952 : }
4953 242 : break;
4954 : case sw::Frame::eFormControl:
4955 : {
4956 20 : const SdrObject* pObject = rFrame.GetFrmFmt().FindRealSdrObject();
4957 20 : m_aPostponedFormControls.push_back(pObject);
4958 20 : m_bPostponedProcessingFly = true ;
4959 : }
4960 20 : break;
4961 : default:
4962 : OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
4963 : rFrame.GetWriterType() == sw::Frame::eTxtBox? "eTxtBox":
4964 : ( rFrame.GetWriterType() == sw::Frame::eOle? "eOle": "???" ) );
4965 0 : break;
4966 : }
4967 :
4968 1400 : m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
4969 1400 : }
4970 :
4971 686 : bool DocxAttributeOutput::IsDiagram( const SdrObject* sdrObject )
4972 : {
4973 686 : uno::Reference< drawing::XShape > xShape( ((SdrObject*)sdrObject)->getUnoShape(), uno::UNO_QUERY );
4974 686 : if ( !xShape.is() )
4975 0 : return false;
4976 :
4977 1372 : uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
4978 686 : if ( !xPropSet.is() )
4979 0 : return false;
4980 :
4981 : // if the shape doesn't have the InteropGrabBag property, it's not a diagram
4982 1372 : uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
4983 1372 : OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
4984 686 : if ( !xPropSetInfo->hasPropertyByName( pName ) )
4985 2 : return false;
4986 :
4987 1368 : uno::Sequence< beans::PropertyValue > propList;
4988 684 : xPropSet->getPropertyValue( pName ) >>= propList;
4989 3296 : for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp )
4990 : {
4991 : // if we find any of the diagram components, it's a diagram
4992 2626 : OUString propName = propList[nProp].Name;
4993 10504 : if ( propName == "OOXData" || propName == "OOXLayout" || propName == "OOXStyle" ||
4994 7864 : propName == "OOXColor" || propName == "OOXDrawing")
4995 14 : return true;
4996 2612 : }
4997 1356 : return false;
4998 : }
4999 :
5000 486 : void DocxAttributeOutput::WriteOutliner(const OutlinerParaObject& rParaObj)
5001 : {
5002 486 : const EditTextObject& rEditObj = rParaObj.GetTextObject();
5003 486 : MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
5004 :
5005 486 : sal_Int32 nPara = rEditObj.GetParagraphCount();
5006 :
5007 486 : m_pSerializer->startElementNS( XML_w, XML_txbxContent, FSEND );
5008 1032 : for (sal_Int32 n = 0; n < nPara; ++n)
5009 : {
5010 546 : if( n )
5011 60 : aAttrIter.NextPara( n );
5012 :
5013 546 : OUString aStr( rEditObj.GetText( n ));
5014 546 : sal_Int32 nAktPos = 0;
5015 546 : sal_Int32 nEnd = aStr.getLength();
5016 :
5017 546 : StartParagraph(ww8::WW8TableNodeInfo::Pointer_t());
5018 :
5019 : // Write paragraph properties.
5020 546 : StartParagraphProperties();
5021 546 : aAttrIter.OutParaAttr(false);
5022 1092 : SfxItemSet aParagraphMarkerProperties(m_rExport.pDoc->GetAttrPool());
5023 546 : EndParagraphProperties(aParagraphMarkerProperties, 0, 0, 0);
5024 :
5025 554 : do {
5026 554 : const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
5027 :
5028 554 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
5029 :
5030 : // Write run properties.
5031 554 : m_pSerializer->startElementNS(XML_w, XML_rPr, FSEND);
5032 554 : aAttrIter.OutAttr(nAktPos);
5033 554 : WriteCollectedRunProperties();
5034 554 : m_pSerializer->endElementNS(XML_w, XML_rPr);
5035 :
5036 554 : bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
5037 554 : if( !bTxtAtr )
5038 : {
5039 554 : OUString aOut( aStr.copy( nAktPos, nNextAttr - nAktPos ) );
5040 554 : RunText(aOut);
5041 : }
5042 :
5043 554 : m_pSerializer->endElementNS( XML_w, XML_r );
5044 :
5045 554 : nAktPos = nNextAttr;
5046 554 : aAttrIter.NextPos();
5047 : }
5048 554 : while( nAktPos < nEnd );
5049 : // Word can't handle nested text boxes, so write them on the same level.
5050 546 : ++m_nTextFrameLevel;
5051 546 : EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t());
5052 546 : --m_nTextFrameLevel;
5053 546 : }
5054 486 : m_pSerializer->endElementNS( XML_w, XML_txbxContent );
5055 486 : }
5056 :
5057 1116 : void DocxAttributeOutput::pushToTableExportContext(DocxTableExportContext& rContext)
5058 : {
5059 1116 : rContext.m_pTableInfo = m_rExport.mpTableInfo;
5060 1116 : m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
5061 :
5062 1116 : rContext.m_bTableCellOpen = m_tableReference->m_bTableCellOpen;
5063 1116 : m_tableReference->m_bTableCellOpen = false;
5064 :
5065 1116 : rContext.m_nTableDepth = m_tableReference->m_nTableDepth;
5066 1116 : m_tableReference->m_nTableDepth = 0;
5067 1116 : }
5068 :
5069 1116 : void DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext& rContext)
5070 : {
5071 1116 : m_rExport.mpTableInfo = rContext.m_pTableInfo;
5072 1116 : m_tableReference->m_bTableCellOpen = rContext.m_bTableCellOpen;
5073 1116 : m_tableReference->m_nTableDepth = rContext.m_nTableDepth;
5074 1116 : }
5075 :
5076 218 : void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape)
5077 : {
5078 218 : DocxTableExportContext aTableExportContext;
5079 218 : pushToTableExportContext(aTableExportContext);
5080 :
5081 218 : SwFrmFmt* pTextBox = SwTextBoxHelper::findTextBox(xShape);
5082 218 : const SwPosition* pAnchor = pTextBox->GetAnchor().GetCntntAnchor();
5083 436 : sw::Frame aFrame(*pTextBox, *pAnchor);
5084 218 : m_rExport.SdrExporter().writeDMLTextFrame(&aFrame, m_anchorId++, /*bTextBoxOnly=*/true);
5085 :
5086 436 : popFromTableExportContext(aTableExportContext);
5087 218 : }
5088 :
5089 130 : void DocxAttributeOutput::WriteVMLTextBox(uno::Reference<drawing::XShape> xShape)
5090 : {
5091 130 : DocxTableExportContext aTableExportContext;
5092 130 : pushToTableExportContext(aTableExportContext);
5093 :
5094 130 : SwFrmFmt* pTextBox = SwTextBoxHelper::findTextBox(xShape);
5095 130 : const SwPosition* pAnchor = pTextBox->GetAnchor().GetCntntAnchor();
5096 260 : sw::Frame aFrame(*pTextBox, *pAnchor);
5097 130 : m_rExport.SdrExporter().writeVMLTextFrame(&aFrame, /*bTextBoxOnly=*/true);
5098 :
5099 260 : popFromTableExportContext(aTableExportContext);
5100 130 : }
5101 :
5102 106 : oox::drawingml::DrawingML& DocxAttributeOutput::GetDrawingML()
5103 : {
5104 106 : return m_rDrawingML;
5105 : }
5106 :
5107 : /// Functor to do case-insensitive ordering of OUString instances.
5108 : struct OUStringIgnoreCase
5109 : {
5110 74724 : bool operator() (const OUString& lhs, const OUString& rhs) const
5111 : {
5112 74724 : return lhs.compareToIgnoreAsciiCase(rhs) < 0;
5113 : }
5114 : };
5115 :
5116 : /// Guesses if a style created in Writer (no grab-bag) should be qFormat or not.
5117 24830 : static bool lcl_guessQFormat(const OUString& rName, sal_uInt16 nWwId)
5118 : {
5119 : // If the style has no dedicated STI number, then it's probably a custom style -> qFormat.
5120 24830 : if (nWwId == ww::stiUser)
5121 11688 : return true;
5122 :
5123 13142 : static std::set<OUString, OUStringIgnoreCase> aWhitelist;
5124 13142 : if (aWhitelist.empty())
5125 : {
5126 20 : aWhitelist.insert("Normal");
5127 20 : aWhitelist.insert("Heading 1");
5128 20 : aWhitelist.insert("Heading 2");
5129 20 : aWhitelist.insert("Heading 3");
5130 20 : aWhitelist.insert("Heading 4");
5131 20 : aWhitelist.insert("Heading 5");
5132 20 : aWhitelist.insert("Heading 6");
5133 20 : aWhitelist.insert("Heading 7");
5134 20 : aWhitelist.insert("Heading 8");
5135 20 : aWhitelist.insert("Heading 9");
5136 20 : aWhitelist.insert("Caption");
5137 20 : aWhitelist.insert("Title");
5138 20 : aWhitelist.insert("Subtitle");
5139 20 : aWhitelist.insert("Strong");
5140 20 : aWhitelist.insert("Emphasis");
5141 20 : aWhitelist.insert("No Spacing");
5142 20 : aWhitelist.insert("List Paragraph");
5143 20 : aWhitelist.insert("Quote");
5144 20 : aWhitelist.insert("Intense Quote");
5145 20 : aWhitelist.insert("Subtle Emphasis,");
5146 20 : aWhitelist.insert("Intense Emphasis");
5147 20 : aWhitelist.insert("Subtle Reference");
5148 20 : aWhitelist.insert("Intense Reference");
5149 20 : aWhitelist.insert("Book Title");
5150 20 : aWhitelist.insert("TOC Heading");
5151 : }
5152 : // Not custom style? Then we have a list of standard styles which should be qFormat.
5153 13142 : return aWhitelist.find(rName) != aWhitelist.end();
5154 : }
5155 :
5156 27746 : void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType,
5157 : sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nWwId, sal_uInt16 nId, bool bAutoUpdate )
5158 : {
5159 27746 : bool bQFormat = false, bUnhideWhenUsed = false, bSemiHidden = false, bLocked = false, bDefault = false, bCustomStyle = false;
5160 55492 : OUString aLink, aRsid, aUiPriority;
5161 27746 : FastAttributeList* pStyleAttributeList = m_pSerializer->createAttrList();
5162 55492 : uno::Any aAny;
5163 27746 : if (eType == STYLE_TYPE_PARA || eType == STYLE_TYPE_CHAR)
5164 : {
5165 18912 : const SwFmt* pFmt = m_rExport.pStyles->GetSwFmt(nId);
5166 18912 : pFmt->GetGrabBagItem(aAny);
5167 : }
5168 : else
5169 : {
5170 8834 : const SwNumRule* pRule = m_rExport.pStyles->GetSwNumRule(nId);
5171 8834 : pRule->GetGrabBagItem(aAny);
5172 : }
5173 55492 : const uno::Sequence<beans::PropertyValue>& rGrabBag = aAny.get< uno::Sequence<beans::PropertyValue> >();
5174 :
5175 110592 : for (sal_Int32 i = 0; i < rGrabBag.getLength(); ++i)
5176 : {
5177 82846 : if (rGrabBag[i].Name == "uiPriority")
5178 14774 : aUiPriority = rGrabBag[i].Value.get<OUString>();
5179 68072 : else if (rGrabBag[i].Name == "qFormat")
5180 2916 : bQFormat = true;
5181 65156 : else if (rGrabBag[i].Name == "link")
5182 5058 : aLink = rGrabBag[i].Value.get<OUString>();
5183 60098 : else if (rGrabBag[i].Name == "rsid")
5184 19242 : aRsid = rGrabBag[i].Value.get<OUString>();
5185 40856 : else if (rGrabBag[i].Name == "unhideWhenUsed")
5186 11590 : bUnhideWhenUsed = true;
5187 29266 : else if (rGrabBag[i].Name == "semiHidden")
5188 11686 : bSemiHidden = true;
5189 17580 : else if (rGrabBag[i].Name == "locked")
5190 618 : bLocked = true;
5191 16962 : else if (rGrabBag[i].Name == "default")
5192 2322 : bDefault = rGrabBag[i].Value.get<sal_Bool>();
5193 14640 : else if (rGrabBag[i].Name == "customStyle")
5194 14640 : bCustomStyle = rGrabBag[i].Value.get<sal_Bool>();
5195 : else
5196 : SAL_WARN("sw.ww8", "Unhandled style property: " << rGrabBag[i].Name);
5197 : }
5198 :
5199 27746 : const char* pType = 0;
5200 27746 : switch (eType)
5201 : {
5202 13034 : case STYLE_TYPE_PARA: pType = "paragraph"; break;
5203 5878 : case STYLE_TYPE_CHAR: pType = "character"; break;
5204 8834 : case STYLE_TYPE_LIST: pType = "numbering"; break;
5205 : }
5206 27746 : pStyleAttributeList->add(FSNS( XML_w, XML_type ), pType);
5207 27746 : pStyleAttributeList->add(FSNS( XML_w, XML_styleId ), m_rExport.pStyles->GetStyleId(nId).getStr());
5208 27746 : if (bDefault)
5209 2322 : pStyleAttributeList->add(FSNS(XML_w, XML_default), "1");
5210 27746 : if (bCustomStyle)
5211 14640 : pStyleAttributeList->add(FSNS(XML_w, XML_customStyle), "1");
5212 27746 : XFastAttributeListRef xStyleAttributeList(pStyleAttributeList);
5213 27746 : m_pSerializer->startElementNS( XML_w, XML_style, xStyleAttributeList);
5214 :
5215 : m_pSerializer->singleElementNS( XML_w, XML_name,
5216 : FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
5217 27746 : FSEND );
5218 :
5219 27746 : if ( nBase != 0x0FFF && eType != STYLE_TYPE_LIST)
5220 : {
5221 : m_pSerializer->singleElementNS( XML_w, XML_basedOn,
5222 : FSNS( XML_w, XML_val ), m_rExport.pStyles->GetStyleId(nBase).getStr(),
5223 15180 : FSEND );
5224 : }
5225 :
5226 27746 : if ( nNext != nId && eType != STYLE_TYPE_LIST)
5227 : {
5228 : m_pSerializer->singleElementNS( XML_w, XML_next,
5229 : FSNS( XML_w, XML_val ), m_rExport.pStyles->GetStyleId(nNext).getStr(),
5230 3296 : FSEND );
5231 : }
5232 :
5233 27746 : if (!aLink.isEmpty())
5234 : m_pSerializer->singleElementNS(XML_w, XML_link,
5235 : FSNS(XML_w, XML_val), OUStringToOString(aLink, RTL_TEXTENCODING_UTF8).getStr(),
5236 5058 : FSEND);
5237 :
5238 27746 : if ( bAutoUpdate )
5239 790 : m_pSerializer->singleElementNS( XML_w, XML_autoRedefine, FSEND );
5240 :
5241 27746 : if (!aUiPriority.isEmpty())
5242 : m_pSerializer->singleElementNS(XML_w, XML_uiPriority,
5243 : FSNS(XML_w, XML_val), OUStringToOString(aUiPriority, RTL_TEXTENCODING_UTF8).getStr(),
5244 14774 : FSEND);
5245 27746 : if (bSemiHidden)
5246 11686 : m_pSerializer->singleElementNS(XML_w, XML_semiHidden, FSEND);
5247 27746 : if (bUnhideWhenUsed)
5248 11590 : m_pSerializer->singleElementNS(XML_w, XML_unhideWhenUsed, FSEND);
5249 :
5250 27746 : if (bQFormat || lcl_guessQFormat(rName, nWwId))
5251 15698 : m_pSerializer->singleElementNS(XML_w, XML_qFormat, FSEND);
5252 27746 : if (bLocked)
5253 618 : m_pSerializer->singleElementNS(XML_w, XML_locked, FSEND);
5254 27746 : if (!aRsid.isEmpty())
5255 : m_pSerializer->singleElementNS(XML_w, XML_rsid,
5256 : FSNS(XML_w, XML_val), OUStringToOString(aRsid, RTL_TEXTENCODING_UTF8).getStr(),
5257 46988 : FSEND);
5258 27746 : }
5259 :
5260 27746 : void DocxAttributeOutput::EndStyle()
5261 : {
5262 27746 : m_pSerializer->endElementNS( XML_w, XML_style );
5263 27746 : }
5264 :
5265 33666 : void DocxAttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 /*nStyle*/ )
5266 : {
5267 33666 : if ( bParProp )
5268 : {
5269 13894 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
5270 13894 : InitCollectedParagraphProperties();
5271 : }
5272 : else
5273 : {
5274 19772 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
5275 19772 : InitCollectedRunProperties();
5276 : }
5277 33666 : }
5278 :
5279 33666 : void DocxAttributeOutput::EndStyleProperties( bool bParProp )
5280 : {
5281 33666 : if ( bParProp )
5282 : {
5283 13894 : WriteCollectedParagraphProperties();
5284 :
5285 : // Merge the marks for the ordered elements
5286 13894 : m_pSerializer->mergeTopMarks( );
5287 :
5288 13894 : m_pSerializer->endElementNS( XML_w, XML_pPr );
5289 : }
5290 : else
5291 : {
5292 19772 : WriteCollectedRunProperties();
5293 :
5294 : // Merge the marks for the ordered elements
5295 19772 : m_pSerializer->mergeTopMarks();
5296 :
5297 19772 : m_pSerializer->endElementNS( XML_w, XML_rPr );
5298 : }
5299 33666 : }
5300 :
5301 1752 : void lcl_OutlineLevel(sax_fastparser::FSHelperPtr pSerializer, sal_uInt16 nLevel)
5302 : {
5303 1752 : if (nLevel >= WW8ListManager::nMaxLevel)
5304 0 : nLevel = WW8ListManager::nMaxLevel - 1;
5305 :
5306 : pSerializer->singleElementNS(XML_w, XML_outlineLvl,
5307 : FSNS(XML_w, XML_val), OString::number(nLevel).getStr(),
5308 1752 : FSEND);
5309 1752 : }
5310 :
5311 160 : void DocxAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
5312 : {
5313 160 : lcl_OutlineLevel(m_pSerializer, nLvl);
5314 160 : }
5315 :
5316 10166 : void DocxAttributeOutput::ParaOutlineLevel(const SfxUInt16Item& rItem)
5317 : {
5318 10166 : if (rItem.GetValue() > 0)
5319 1592 : lcl_OutlineLevel(m_pSerializer, rItem.GetValue() - 1);
5320 10166 : }
5321 :
5322 48 : void DocxAttributeOutput::PageBreakBefore( bool bBreak )
5323 : {
5324 48 : if ( bBreak )
5325 30 : m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore, FSEND );
5326 : else
5327 : m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore,
5328 : FSNS( XML_w, XML_val ), "false",
5329 18 : FSEND );
5330 48 : }
5331 :
5332 330 : void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
5333 : {
5334 330 : switch ( nC )
5335 : {
5336 : case msword::ColumnBreak:
5337 : // The column break should be output in the next paragraph...
5338 94 : m_nColBreakStatus = COLBRK_POSTPONE;
5339 94 : break;
5340 : case msword::PageBreak:
5341 236 : if ( pSectionInfo )
5342 : {
5343 : // don't add section properties if this will be the first
5344 : // paragraph in the document
5345 72 : if ( !m_bParagraphOpened && !m_bIsFirstParagraph)
5346 : {
5347 : // Create a dummy paragraph if needed
5348 26 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
5349 26 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
5350 :
5351 26 : m_rExport.SectionProperties( *pSectionInfo );
5352 :
5353 26 : m_pSerializer->endElementNS( XML_w, XML_pPr );
5354 26 : m_pSerializer->endElementNS( XML_w, XML_p );
5355 : }
5356 : else
5357 : {
5358 : // postpone the output of this; it has to be done inside the
5359 : // paragraph properties, so remember it until then
5360 46 : m_pSectionInfo.reset( new WW8_SepInfo( *pSectionInfo ));
5361 : }
5362 : }
5363 : else
5364 : {
5365 164 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
5366 : m_pSerializer->singleElementNS( XML_w, XML_br,
5367 164 : FSNS( XML_w, XML_type ), "page", FSEND );
5368 164 : m_pSerializer->endElementNS( XML_w, XML_r );
5369 : }
5370 236 : break;
5371 : default:
5372 : OSL_TRACE( "Unknown section break to write: %d", nC );
5373 0 : break;
5374 : }
5375 330 : }
5376 :
5377 1708 : void DocxAttributeOutput::EndParaSdtBlock()
5378 : {
5379 1708 : if (m_bStartedParaSdt)
5380 : {
5381 : // Paragraph-level SDT still open? Close it now.
5382 84 : EndSdtBlock();
5383 84 : m_bStartedParaSdt = false;
5384 : }
5385 1708 : }
5386 :
5387 930 : void DocxAttributeOutput::StartSection()
5388 : {
5389 930 : m_pSerializer->startElementNS( XML_w, XML_sectPr, FSEND );
5390 930 : m_bOpenedSectPr = true;
5391 :
5392 : // Write the elements in the spec order
5393 : static const sal_Int32 aOrder[] =
5394 : {
5395 : FSNS( XML_w, XML_headerReference ),
5396 : FSNS( XML_w, XML_footerReference ),
5397 : FSNS( XML_w, XML_footnotePr ),
5398 : FSNS( XML_w, XML_endnotePr ),
5399 : FSNS( XML_w, XML_type ),
5400 : FSNS( XML_w, XML_pgSz ),
5401 : FSNS( XML_w, XML_pgMar ),
5402 : FSNS( XML_w, XML_paperSrc ),
5403 : FSNS( XML_w, XML_pgBorders ),
5404 : FSNS( XML_w, XML_lnNumType ),
5405 : FSNS( XML_w, XML_pgNumType ),
5406 : FSNS( XML_w, XML_cols ),
5407 : FSNS( XML_w, XML_formProt ),
5408 : FSNS( XML_w, XML_vAlign ),
5409 : FSNS( XML_w, XML_noEndnote ),
5410 : FSNS( XML_w, XML_titlePg ),
5411 : FSNS( XML_w, XML_textDirection ),
5412 : FSNS( XML_w, XML_bidi ),
5413 : FSNS( XML_w, XML_rtlGutter ),
5414 : FSNS( XML_w, XML_docGrid ),
5415 : FSNS( XML_w, XML_printerSettings ),
5416 : FSNS( XML_w, XML_sectPrChange )
5417 : };
5418 :
5419 : // postpone the output so that we can later [in EndParagraphProperties()]
5420 : // prepend the properties before the run
5421 930 : sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
5422 930 : uno::Sequence< sal_Int32 > aSeqOrder( len );
5423 21390 : for ( sal_Int32 i = 0; i < len; i++ )
5424 20460 : aSeqOrder[i] = aOrder[i];
5425 :
5426 930 : m_pSerializer->mark( aSeqOrder );
5427 930 : m_bHadSectPr = true;
5428 930 : }
5429 :
5430 930 : void DocxAttributeOutput::EndSection()
5431 : {
5432 : // Write the section properties
5433 930 : if ( m_pSectionSpacingAttrList )
5434 : {
5435 930 : XFastAttributeListRef xAttrList( m_pSectionSpacingAttrList );
5436 930 : m_pSectionSpacingAttrList = NULL;
5437 :
5438 930 : m_pSerializer->singleElementNS( XML_w, XML_pgMar, xAttrList );
5439 : }
5440 :
5441 : // Order the elements
5442 930 : m_pSerializer->mergeTopMarks( );
5443 :
5444 930 : m_pSerializer->endElementNS( XML_w, XML_sectPr );
5445 930 : m_bOpenedSectPr = false;
5446 930 : }
5447 :
5448 930 : void DocxAttributeOutput::SectionFormProtection( bool bProtected )
5449 : {
5450 930 : if ( bProtected )
5451 0 : m_pSerializer->singleElementNS( XML_w, XML_formProt, FSEND );
5452 : else
5453 : m_pSerializer->singleElementNS( XML_w, XML_formProt,
5454 930 : FSNS( XML_w, XML_val ), "false", FSEND );
5455 930 : }
5456 :
5457 2 : void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo )
5458 : {
5459 2 : FastAttributeList* pAttr = m_pSerializer->createAttrList();
5460 2 : pAttr->add( FSNS( XML_w, XML_countBy ), OString::number(rLnNumInfo.GetCountBy()).getStr());
5461 2 : pAttr->add( FSNS( XML_w, XML_restart ), rLnNumInfo.IsRestartEachPage() ? "newPage" : "continuous" );
5462 2 : if( rLnNumInfo.GetPosFromLeft())
5463 0 : pAttr->add( FSNS( XML_w, XML_distance ), OString::number(rLnNumInfo.GetPosFromLeft()).getStr());
5464 2 : if( nRestartNo )
5465 2 : pAttr->add( FSNS( XML_w, XML_start ), OString::number( nRestartNo).getStr());
5466 2 : XFastAttributeListRef xAttrs( pAttr );
5467 2 : m_pSerializer->singleElementNS( XML_w, XML_lnNumType, xAttrs );
5468 2 : }
5469 :
5470 80 : void DocxAttributeOutput::SectionTitlePage()
5471 : {
5472 80 : m_pSerializer->singleElementNS( XML_w, XML_titlePg, FSEND );
5473 80 : }
5474 :
5475 908 : void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
5476 : {
5477 : // Output the margins
5478 :
5479 908 : const SvxBoxItem& rBox = pFmt->GetBox( );
5480 :
5481 908 : const SvxBorderLine* pLeft = rBox.GetLeft( );
5482 908 : const SvxBorderLine* pTop = rBox.GetTop( );
5483 908 : const SvxBorderLine* pRight = rBox.GetRight( );
5484 908 : const SvxBorderLine* pBottom = rBox.GetBottom( );
5485 :
5486 908 : if ( pBottom || pTop || pLeft || pRight )
5487 : {
5488 16 : bool bExportDistanceFromPageEdge = false;
5489 16 : if ( boxHasLineLargerThan31(rBox) == true )
5490 : {
5491 : // The distance is larger than '31'. This cannot be exported as 'distance from text'.
5492 : // Instead - it should be exported as 'distance from page edge'.
5493 : // This is based on http://wiki.openoffice.org/wiki/Writer/MSInteroperability/PageBorder
5494 : // Specifically 'export case #2'
5495 14 : bExportDistanceFromPageEdge = true;
5496 : }
5497 :
5498 : // All distances are relative to the text margins
5499 : m_pSerializer->startElementNS( XML_w, XML_pgBorders,
5500 : FSNS( XML_w, XML_display ), "allPages",
5501 : FSNS( XML_w, XML_offsetFrom ), bExportDistanceFromPageEdge ? "page" : "text",
5502 16 : FSEND );
5503 :
5504 16 : OutputBorderOptions aOutputBorderOptions = lcl_getBoxBorderOptions();
5505 :
5506 : // Check if the distance is larger than 31 points
5507 16 : aOutputBorderOptions.bCheckDistanceSize = true;
5508 :
5509 : // Check if there is a shadow item
5510 16 : const SfxPoolItem* pItem = GetExport().HasItem( RES_SHADOW );
5511 16 : if ( pItem )
5512 : {
5513 4 : const SvxShadowItem* pShadowItem = (const SvxShadowItem*)pItem;
5514 4 : aOutputBorderOptions.aShadowLocation = pShadowItem->GetLocation();
5515 : }
5516 :
5517 16 : std::map<sal_uInt16, css::table::BorderLine2> aEmptyMap; // empty styles map
5518 : impl_borders( m_pSerializer, rBox, aOutputBorderOptions, &m_pageMargins,
5519 16 : aEmptyMap );
5520 :
5521 16 : m_pSerializer->endElementNS( XML_w, XML_pgBorders );
5522 : }
5523 908 : }
5524 :
5525 46 : void DocxAttributeOutput::SectionBiDi( bool bBiDi )
5526 : {
5527 46 : if ( bBiDi )
5528 0 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
5529 46 : }
5530 :
5531 2150 : static OString impl_NumberingType( sal_uInt16 nNumberingType )
5532 : {
5533 2150 : OString aType;
5534 :
5535 2150 : switch ( nNumberingType )
5536 : {
5537 : case SVX_NUM_CHARS_UPPER_LETTER:
5538 4 : case SVX_NUM_CHARS_UPPER_LETTER_N: aType = "upperLetter"; break;
5539 : case SVX_NUM_CHARS_LOWER_LETTER:
5540 112 : case SVX_NUM_CHARS_LOWER_LETTER_N: aType = "lowerLetter"; break;
5541 2 : case SVX_NUM_ROMAN_UPPER: aType = "upperRoman"; break;
5542 108 : case SVX_NUM_ROMAN_LOWER: aType = "lowerRoman"; break;
5543 :
5544 1236 : case SVX_NUM_ARABIC: aType = "decimal"; break;
5545 :
5546 : case SVX_NUM_BITMAP:
5547 232 : case SVX_NUM_CHAR_SPECIAL: aType = "bullet"; break;
5548 2 : case style::NumberingType::CHARS_HEBREW: aType = "hebrew1"; break;
5549 :
5550 454 : default: aType = "none"; break;
5551 : }
5552 :
5553 2150 : return aType;
5554 : }
5555 :
5556 908 : void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, ::boost::optional<sal_uInt16> oPageRestartNumber )
5557 : {
5558 : // FIXME Not called properly with page styles like "First Page"
5559 :
5560 908 : FastAttributeList* pAttr = m_pSerializer->createAttrList();
5561 :
5562 : // boost::none means no restart: then don't output that attribute if it is negative
5563 908 : if ( oPageRestartNumber )
5564 60 : pAttr->add( FSNS( XML_w, XML_start ), OString::number( oPageRestartNumber.get() ) );
5565 :
5566 : // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
5567 908 : OString aFmt( impl_NumberingType( nNumType ) );
5568 908 : if ( !aFmt.isEmpty() )
5569 908 : pAttr->add( FSNS( XML_w, XML_fmt ), aFmt.getStr() );
5570 :
5571 1816 : XFastAttributeListRef xAttrs( pAttr );
5572 908 : m_pSerializer->singleElementNS( XML_w, XML_pgNumType, xAttrs );
5573 :
5574 : // see 2.6.12 pgNumType (Page Numbering Settings)
5575 908 : OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()" );
5576 908 : }
5577 :
5578 930 : void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode )
5579 : {
5580 : /* break code: 0 No break, 1 New column
5581 : 2 New page, 3 Even page, 4 Odd page
5582 : */
5583 930 : const char* pType = NULL;
5584 930 : switch ( nBreakCode )
5585 : {
5586 0 : case 1: pType = "nextColumn"; break;
5587 898 : case 2: pType = "nextPage"; break;
5588 0 : case 3: pType = "evenPage"; break;
5589 0 : case 4: pType = "oddPage"; break;
5590 32 : default: pType = "continuous"; break;
5591 : }
5592 :
5593 930 : if ( pType )
5594 : m_pSerializer->singleElementNS( XML_w, XML_type,
5595 : FSNS( XML_w, XML_val ), pType,
5596 930 : FSEND );
5597 930 : }
5598 :
5599 6496 : void DocxAttributeOutput::StartFont( const OUString& rFamilyName ) const
5600 : {
5601 : m_pSerializer->startElementNS( XML_w, XML_font,
5602 : FSNS( XML_w, XML_name ), OUStringToOString( rFamilyName, RTL_TEXTENCODING_UTF8 ).getStr(),
5603 6496 : FSEND );
5604 6496 : }
5605 :
5606 6496 : void DocxAttributeOutput::EndFont() const
5607 : {
5608 6496 : m_pSerializer->endElementNS( XML_w, XML_font );
5609 6496 : }
5610 :
5611 1742 : void DocxAttributeOutput::FontAlternateName( const OUString& rName ) const
5612 : {
5613 : m_pSerializer->singleElementNS( XML_w, XML_altName,
5614 : FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
5615 1742 : FSEND );
5616 1742 : }
5617 :
5618 6496 : void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet, rtl_TextEncoding nEncoding ) const
5619 : {
5620 6496 : FastAttributeList* pAttr = m_pSerializer->createAttrList();
5621 :
5622 6496 : OString aCharSet( OString::number( nCharSet, 16 ) );
5623 6496 : if ( aCharSet.getLength() == 1 )
5624 6496 : aCharSet = OString( "0" ) + aCharSet;
5625 6496 : pAttr->add( FSNS( XML_w, XML_val ), aCharSet.getStr());
5626 :
5627 6496 : if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT )
5628 : {
5629 6386 : if( const char* charset = rtl_getMimeCharsetFromTextEncoding( nEncoding ))
5630 5478 : pAttr->add( FSNS( XML_w, XML_characterSet ), charset );
5631 : }
5632 :
5633 6496 : m_pSerializer->singleElementNS( XML_w, XML_charset, XFastAttributeListRef( pAttr ));
5634 6496 : }
5635 :
5636 6496 : void DocxAttributeOutput::FontFamilyType( FontFamily eFamily ) const
5637 : {
5638 6496 : const char *pFamily = NULL;
5639 6496 : switch ( eFamily )
5640 : {
5641 4774 : case FAMILY_ROMAN: pFamily = "roman"; break;
5642 1644 : case FAMILY_SWISS: pFamily = "swiss"; break;
5643 24 : case FAMILY_MODERN: pFamily = "modern"; break;
5644 0 : case FAMILY_SCRIPT: pFamily = "script"; break;
5645 0 : case FAMILY_DECORATIVE: pFamily = "decorative"; break;
5646 54 : default: pFamily = "auto"; break; // no font family
5647 : }
5648 :
5649 6496 : if ( pFamily )
5650 : m_pSerializer->singleElementNS( XML_w, XML_family,
5651 : FSNS( XML_w, XML_val ), pFamily,
5652 6496 : FSEND );
5653 6496 : }
5654 :
5655 6496 : void DocxAttributeOutput::FontPitchType( FontPitch ePitch ) const
5656 : {
5657 6496 : const char *pPitch = NULL;
5658 6496 : switch ( ePitch )
5659 : {
5660 6408 : case PITCH_VARIABLE: pPitch = "variable"; break;
5661 22 : case PITCH_FIXED: pPitch = "fixed"; break;
5662 66 : default: pPitch = "default"; break; // no info about the pitch
5663 : }
5664 :
5665 6496 : if ( pPitch )
5666 : m_pSerializer->singleElementNS( XML_w, XML_pitch,
5667 : FSNS( XML_w, XML_val ), pPitch,
5668 6496 : FSEND );
5669 6496 : }
5670 :
5671 6496 : void DocxAttributeOutput::EmbedFont( const OUString& name, FontFamily family, FontPitch pitch, rtl_TextEncoding encoding )
5672 : {
5673 6496 : if( !m_rExport.pDoc->getIDocumentSettingAccess().get( IDocumentSettingAccess::EMBED_FONTS ))
5674 12992 : return; // no font embedding with this document
5675 0 : EmbedFontStyle( name, XML_embedRegular, family, ITALIC_NONE, WEIGHT_NORMAL, pitch, encoding );
5676 0 : EmbedFontStyle( name, XML_embedBold, family, ITALIC_NONE, WEIGHT_BOLD, pitch, encoding );
5677 0 : EmbedFontStyle( name, XML_embedItalic, family, ITALIC_NORMAL, WEIGHT_NORMAL, pitch, encoding );
5678 0 : EmbedFontStyle( name, XML_embedBoldItalic, family, ITALIC_NORMAL, WEIGHT_BOLD, pitch, encoding );
5679 : }
5680 :
5681 0 : static inline char toHexChar( int value )
5682 : {
5683 0 : return value >= 10 ? value + 'A' - 10 : value + '0';
5684 : }
5685 :
5686 0 : void DocxAttributeOutput::EmbedFontStyle( const OUString& name, int tag, FontFamily family, FontItalic italic,
5687 : FontWeight weight, FontPitch pitch, rtl_TextEncoding encoding )
5688 : {
5689 : // Embed font if at least viewing is allowed (in which case the opening app must check
5690 : // the font license rights too and open either read-only or not use the font for editing).
5691 : OUString fontUrl = EmbeddedFontsHelper::fontFileUrl( name, family, italic, weight, pitch, encoding,
5692 0 : EmbeddedFontsHelper::ViewingAllowed );
5693 0 : if( fontUrl.isEmpty())
5694 0 : return;
5695 : // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
5696 0 : if( !fontFilesMap.count( fontUrl ))
5697 : {
5698 0 : osl::File file( fontUrl );
5699 0 : if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None )
5700 0 : return;
5701 0 : uno::Reference< com::sun::star::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream(
5702 0 : OUString( "word/fonts/font" ) + OUString::number(m_nextFontId) + ".odttf",
5703 0 : "application/vnd.openxmlformats-officedocument.obfuscatedFont" );
5704 : // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway,
5705 : // so just alter the first and last part of the key.
5706 0 : char fontKeyStr[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}";
5707 : sal_uInt8 fontKey[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E,
5708 0 : 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 };
5709 0 : fontKey[ 0 ] = fontKey[ 15 ] = m_nextFontId % 256;
5710 0 : fontKeyStr[ 1 ] = fontKeyStr[ 35 ] = toHexChar(( m_nextFontId % 256 ) / 16 );
5711 0 : fontKeyStr[ 2 ] = fontKeyStr[ 36 ] = toHexChar(( m_nextFontId % 256 ) % 16 );
5712 : char buffer[ 4096 ];
5713 : sal_uInt64 readSize;
5714 0 : file.read( buffer, 32, readSize );
5715 0 : if( readSize < 32 )
5716 : {
5717 : SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl << ")" );
5718 0 : xOutStream->closeOutput();
5719 0 : return;
5720 : }
5721 0 : for( int i = 0;
5722 : i < 16;
5723 : ++i )
5724 : {
5725 0 : buffer[ i ] ^= fontKey[ i ];
5726 0 : buffer[ i + 16 ] ^= fontKey[ i ];
5727 : }
5728 0 : xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), 32 ));
5729 : for(;;)
5730 : {
5731 : sal_Bool eof;
5732 0 : if( file.isEndOfFile( &eof ) != osl::File::E_None )
5733 : {
5734 : SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
5735 0 : xOutStream->closeOutput();
5736 0 : return;
5737 : }
5738 0 : if( eof )
5739 0 : break;
5740 0 : if( file.read( buffer, 4096, readSize ) != osl::File::E_None )
5741 : {
5742 : SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl );
5743 0 : xOutStream->closeOutput();
5744 0 : return;
5745 : }
5746 0 : if( readSize == 0 )
5747 0 : break;
5748 0 : xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize ));
5749 0 : }
5750 0 : xOutStream->closeOutput();
5751 0 : OString relId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(),
5752 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font",
5753 0 : OUString( "fonts/font" ) + OUString::number( m_nextFontId ) + ".odttf" ), RTL_TEXTENCODING_UTF8 );
5754 0 : EmbeddedFontRef ref;
5755 0 : ref.relId = relId;
5756 0 : ref.fontKey = fontKeyStr;
5757 0 : fontFilesMap[ fontUrl ] = ref;
5758 0 : ++m_nextFontId;
5759 : }
5760 : m_pSerializer->singleElementNS( XML_w, tag,
5761 0 : FSNS( XML_r, XML_id ), fontFilesMap[ fontUrl ].relId,
5762 0 : FSNS( XML_w, XML_fontKey ), fontFilesMap[ fontUrl ].fontKey,
5763 0 : FSEND );
5764 : }
5765 :
5766 0 : OString DocxAttributeOutput::TransHighlightColor( const Color& rColor )
5767 : {
5768 0 : switch (rColor.GetColor())
5769 : {
5770 0 : case 0x000000: return OString("black"); break;
5771 0 : case 0x0000ff: return OString("blue"); break;
5772 0 : case 0x00ffff: return OString("cyan"); break;
5773 0 : case 0x00ff00: return OString("green"); break;
5774 0 : case 0xff00ff: return OString("magenta"); break;
5775 0 : case 0xff0000: return OString("red"); break;
5776 0 : case 0xffff00: return OString("yellow"); break;
5777 0 : case 0xffffff: return OString("white"); break;
5778 0 : case 0x000080: return OString("darkBlue"); break;
5779 0 : case 0x008080: return OString("darkCyan"); break;
5780 0 : case 0x008000: return OString("darkGreen"); break;
5781 0 : case 0x800080: return OString("darkMagenta"); break;
5782 0 : case 0x800000: return OString("darkRed"); break;
5783 0 : case 0x808000: return OString("darkYellow"); break;
5784 0 : case 0x808080: return OString("darkGray"); break;
5785 0 : case 0xC0C0C0: return OString("lightGray"); break;
5786 0 : default: return OString(); break;
5787 : }
5788 : }
5789 :
5790 138 : void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
5791 : {
5792 : // nId is the same both for abstract numbering definition as well as the
5793 : // numbering definition itself
5794 : // TODO check that this is actually true & fix if not ;-)
5795 138 : OString aId( OString::number( nId ) );
5796 :
5797 : m_pSerializer->startElementNS( XML_w, XML_num,
5798 : FSNS( XML_w, XML_numId ), aId.getStr(),
5799 138 : FSEND );
5800 :
5801 : m_pSerializer->singleElementNS( XML_w, XML_abstractNumId,
5802 : FSNS( XML_w, XML_val ), aId.getStr(),
5803 138 : FSEND );
5804 :
5805 : #if OSL_DEBUG_LEVEL > 1
5806 : // TODO ww8 version writes this, anything to do about it here?
5807 : if ( rRule.IsContinusNum() )
5808 : OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()" );
5809 : #else
5810 : (void) rRule; // to quiet the warning...
5811 : #endif
5812 :
5813 138 : m_pSerializer->endElementNS( XML_w, XML_num );
5814 138 : }
5815 :
5816 138 : void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
5817 : {
5818 : m_pSerializer->startElementNS( XML_w, XML_abstractNum,
5819 : FSNS( XML_w, XML_abstractNumId ), OString::number( nId ).getStr(),
5820 138 : FSEND );
5821 138 : }
5822 :
5823 138 : void DocxAttributeOutput::EndAbstractNumbering()
5824 : {
5825 138 : m_pSerializer->endElementNS( XML_w, XML_abstractNum );
5826 138 : }
5827 :
5828 1242 : void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
5829 : sal_uInt16 nStart,
5830 : sal_uInt16 nNumberingType,
5831 : SvxAdjust eAdjust,
5832 : const sal_uInt8 * /*pNumLvlPos*/,
5833 : sal_uInt8 nFollow,
5834 : const wwFont *pFont,
5835 : const SfxItemSet *pOutSet,
5836 : sal_Int16 nIndentAt,
5837 : sal_Int16 nFirstLineIndex,
5838 : sal_Int16 nListTabPos,
5839 : const OUString &rNumberingString,
5840 : const SvxBrushItem* pBrush)
5841 : {
5842 : m_pSerializer->startElementNS( XML_w, XML_lvl,
5843 : FSNS( XML_w, XML_ilvl ), OString::number( nLevel ).getStr(),
5844 1242 : FSEND );
5845 :
5846 : // start with the nStart value. Do not write w:start if Numbered Lists
5847 : // starts from zero.As it's an optional parameter.
5848 : // refer ECMA 376 Second edition Part-1
5849 1242 : if(!(0 == nLevel && 0 == nStart))
5850 : {
5851 : m_pSerializer->singleElementNS( XML_w, XML_start,
5852 : FSNS( XML_w, XML_val ), OString::number( nStart ).getStr(),
5853 1242 : FSEND );
5854 : }
5855 :
5856 : // format
5857 1242 : OString aFmt( impl_NumberingType( nNumberingType ) );
5858 :
5859 1242 : if ( !aFmt.isEmpty() )
5860 : m_pSerializer->singleElementNS( XML_w, XML_numFmt,
5861 : FSNS( XML_w, XML_val ), aFmt.getStr(),
5862 1242 : FSEND );
5863 :
5864 : // suffix
5865 1242 : const char *pSuffix = NULL;
5866 1242 : switch ( nFollow )
5867 : {
5868 0 : case 1: pSuffix = "space"; break;
5869 454 : case 2: pSuffix = "nothing"; break;
5870 788 : default: /*pSuffix = "tab";*/ break;
5871 : }
5872 1242 : if ( pSuffix )
5873 : m_pSerializer->singleElementNS( XML_w, XML_suff,
5874 : FSNS( XML_w, XML_val ), pSuffix,
5875 454 : FSEND );
5876 :
5877 : // text
5878 1242 : OUString aText( rNumberingString );
5879 2484 : OUStringBuffer aBuffer( aText.getLength() + WW8ListManager::nMaxLevel );
5880 :
5881 1242 : const sal_Unicode *pPrev = aText.getStr();
5882 1242 : const sal_Unicode *pIt = aText.getStr();
5883 4748 : while ( pIt < aText.getStr() + aText.getLength() )
5884 : {
5885 : // convert the level values to %NUMBER form
5886 : // (we don't use pNumLvlPos at all)
5887 : // FIXME so far we support the ww8 limit of levels only
5888 2264 : if ( *pIt < sal_Unicode( WW8ListManager::nMaxLevel ) )
5889 : {
5890 1088 : aBuffer.append( pPrev, pIt - pPrev );
5891 1088 : aBuffer.append( '%' );
5892 1088 : aBuffer.append( OUString::number( sal_Int32( *pIt ) + 1 ) );
5893 :
5894 1088 : pPrev = pIt + 1;
5895 : }
5896 2264 : ++pIt;
5897 : }
5898 1242 : if ( pPrev < pIt )
5899 606 : aBuffer.append( pPrev, pIt - pPrev );
5900 :
5901 : // If bullet char is empty, set lvlText as empty
5902 1242 : if ( aText.equals ( OUString(sal_Unicode(0)) ) && nNumberingType == SVX_NUM_CHAR_SPECIAL )
5903 : {
5904 2 : m_pSerializer->singleElementNS( XML_w, XML_lvlText, FSNS( XML_w, XML_val ), "", FSEND );
5905 : }
5906 : else
5907 : {
5908 1240 : m_pSerializer->singleElementNS( XML_w, XML_lvlText,FSNS( XML_w, XML_val ), OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
5909 : }
5910 :
5911 : // bullet
5912 1242 : if (nNumberingType == SVX_NUM_BITMAP && pBrush)
5913 : {
5914 6 : int nIndex = m_rExport.GetGrfIndex(*pBrush);
5915 6 : if (nIndex != -1)
5916 : {
5917 : m_pSerializer->singleElementNS(XML_w, XML_lvlPicBulletId,
5918 : FSNS(XML_w, XML_val), OString::number(nIndex).getStr(),
5919 4 : FSEND);
5920 : }
5921 : }
5922 :
5923 : // justification
5924 : const char *pJc;
5925 1242 : bool ecmaDialect = ( m_rExport.GetFilter().getVersion() == oox::core::ECMA_DIALECT );
5926 1242 : switch ( eAdjust )
5927 : {
5928 0 : case SVX_ADJUST_CENTER: pJc = "center"; break;
5929 96 : case SVX_ADJUST_RIGHT: pJc = !ecmaDialect ? "end" : "right"; break;
5930 1146 : default: pJc = !ecmaDialect ? "start" : "left"; break;
5931 : }
5932 : m_pSerializer->singleElementNS( XML_w, XML_lvlJc,
5933 : FSNS( XML_w, XML_val ), pJc,
5934 1242 : FSEND );
5935 :
5936 : // indentation
5937 1242 : m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
5938 1242 : if( nListTabPos != 0 )
5939 : {
5940 602 : m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
5941 : m_pSerializer->singleElementNS( XML_w, XML_tab,
5942 : FSNS( XML_w, XML_val ), "num",
5943 : FSNS( XML_w, XML_pos ), OString::number( nListTabPos ).getStr(),
5944 602 : FSEND );
5945 602 : m_pSerializer->endElementNS( XML_w, XML_tabs );
5946 : }
5947 :
5948 1242 : sal_Int32 nToken = ecmaDialect ? XML_left : XML_start;
5949 : m_pSerializer->singleElementNS( XML_w, XML_ind,
5950 : FSNS( XML_w, nToken ), OString::number( nIndentAt ).getStr(),
5951 : FSNS( XML_w, XML_hanging ), OString::number( -nFirstLineIndex ).getStr(),
5952 1242 : FSEND );
5953 1242 : m_pSerializer->endElementNS( XML_w, XML_pPr );
5954 :
5955 : // font
5956 1242 : if ( pOutSet )
5957 : {
5958 286 : m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
5959 :
5960 286 : if ( pFont )
5961 : {
5962 232 : GetExport().GetId( *pFont ); // ensure font info is written to fontTable.xml
5963 232 : OString aFamilyName( OUStringToOString( OUString( pFont->GetFamilyName() ), RTL_TEXTENCODING_UTF8 ) );
5964 : m_pSerializer->singleElementNS( XML_w, XML_rFonts,
5965 : FSNS( XML_w, XML_ascii ), aFamilyName.getStr(),
5966 : FSNS( XML_w, XML_hAnsi ), aFamilyName.getStr(),
5967 : FSNS( XML_w, XML_cs ), aFamilyName.getStr(),
5968 : FSNS( XML_w, XML_hint ), "default",
5969 232 : FSEND );
5970 : }
5971 286 : m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
5972 :
5973 286 : m_pSerializer->endElementNS( XML_w, XML_rPr );
5974 : }
5975 :
5976 : // TODO anything to do about nListTabPos?
5977 :
5978 2484 : m_pSerializer->endElementNS( XML_w, XML_lvl );
5979 1242 : }
5980 :
5981 618 : void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
5982 : {
5983 618 : switch ( rCaseMap.GetValue() )
5984 : {
5985 : case SVX_CASEMAP_KAPITAELCHEN:
5986 294 : m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSEND );
5987 294 : break;
5988 : case SVX_CASEMAP_VERSALIEN:
5989 156 : m_pSerializer->singleElementNS( XML_w, XML_caps, FSEND );
5990 156 : break;
5991 : default: // Something that ooxml does not support
5992 168 : m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSNS( XML_w, XML_val ), "false", FSEND );
5993 168 : m_pSerializer->singleElementNS( XML_w, XML_caps, FSNS( XML_w, XML_val ), "false", FSEND );
5994 168 : break;
5995 : }
5996 618 : }
5997 :
5998 9656 : void DocxAttributeOutput::CharColor( const SvxColorItem& rColor )
5999 : {
6000 9656 : const Color aColor( rColor.GetValue() );
6001 9656 : OString aColorString;
6002 :
6003 9656 : aColorString = msfilter::util::ConvertColor( aColor );
6004 :
6005 9656 : AddToAttrList( m_pColorAttrList, FSNS( XML_w, XML_val ), aColorString.getStr() );
6006 9656 : }
6007 :
6008 14 : void DocxAttributeOutput::CharContour( const SvxContourItem& rContour )
6009 : {
6010 14 : if ( rContour.GetValue() )
6011 4 : m_pSerializer->singleElementNS( XML_w, XML_outline, FSEND );
6012 : else
6013 10 : m_pSerializer->singleElementNS( XML_w, XML_outline, FSNS( XML_w, XML_val ), "false", FSEND );
6014 14 : }
6015 :
6016 208 : void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
6017 : {
6018 208 : switch ( rCrossedOut.GetStrikeout() )
6019 : {
6020 : case STRIKEOUT_DOUBLE:
6021 0 : m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSEND );
6022 0 : break;
6023 : case STRIKEOUT_NONE:
6024 180 : m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSNS( XML_w, XML_val ), "false", FSEND );
6025 180 : m_pSerializer->singleElementNS( XML_w, XML_strike, FSNS( XML_w, XML_val ), "false", FSEND );
6026 180 : break;
6027 : default:
6028 28 : m_pSerializer->singleElementNS( XML_w, XML_strike, FSEND );
6029 28 : break;
6030 : }
6031 208 : }
6032 :
6033 490 : void DocxAttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )
6034 : {
6035 490 : OString sIss;
6036 490 : short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProp();
6037 490 : if ( !nEsc )
6038 : {
6039 188 : sIss = OString( "baseline" );
6040 188 : nEsc = 0;
6041 188 : nProp = 100;
6042 : }
6043 302 : else if ( DFLT_ESC_PROP == nProp )
6044 : {
6045 300 : if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
6046 38 : sIss = OString( "subscript" );
6047 262 : else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
6048 262 : sIss = OString( "superscript" );
6049 : }
6050 :
6051 490 : if ( !sIss.isEmpty() )
6052 : m_pSerializer->singleElementNS( XML_w, XML_vertAlign,
6053 488 : FSNS( XML_w, XML_val ), sIss.getStr(), FSEND );
6054 :
6055 490 : const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(m_rExport.GetItem(RES_CHRATR_FONTSIZE));
6056 490 : if (sIss.isEmpty() || sIss.match(OString("baseline")))
6057 : {
6058 190 : long nHeight = rItem.GetHeight();
6059 190 : OString sPos = OString::number( ( nHeight * nEsc + 500 ) / 1000 );
6060 : m_pSerializer->singleElementNS( XML_w, XML_position,
6061 190 : FSNS( XML_w, XML_val ), sPos.getStr( ), FSEND );
6062 :
6063 190 : if( ( 100 != nProp || sIss.match( OString( "baseline" ) ) ) && !m_rExport.mbFontSizeWritten )
6064 : {
6065 32 : OString sSize = OString::number( ( nHeight * nProp + 500 ) / 1000 );
6066 : m_pSerializer->singleElementNS( XML_w, XML_sz,
6067 32 : FSNS( XML_w, XML_val ), sSize.getStr( ), FSEND );
6068 190 : }
6069 490 : }
6070 490 : }
6071 :
6072 14182 : void DocxAttributeOutput::CharFont( const SvxFontItem& rFont)
6073 : {
6074 14182 : GetExport().GetId( rFont ); // ensure font info is written to fontTable.xml
6075 14182 : OUString sFontName(rFont.GetFamilyName());
6076 28364 : OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
6077 : AddToAttrList( m_pFontsAttrList, 2,
6078 : FSNS( XML_w, XML_ascii ), sFontNameUtf8.getStr(),
6079 28364 : FSNS( XML_w, XML_hAnsi ), sFontNameUtf8.getStr() );
6080 14182 : }
6081 :
6082 34318 : void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
6083 : {
6084 34318 : OString fontSize = OString::number( ( rFontSize.GetHeight() + 5 ) / 10 );
6085 :
6086 34318 : switch ( rFontSize.Which() )
6087 : {
6088 : case RES_CHRATR_FONTSIZE:
6089 : case RES_CHRATR_CJK_FONTSIZE:
6090 17970 : m_pSerializer->singleElementNS( XML_w, XML_sz, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
6091 17970 : break;
6092 : case RES_CHRATR_CTL_FONTSIZE:
6093 16348 : m_pSerializer->singleElementNS( XML_w, XML_szCs, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
6094 16348 : break;
6095 34318 : }
6096 34318 : }
6097 :
6098 740 : void DocxAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
6099 : {
6100 740 : OString aKerning = OString::number( rKerning.GetValue() );
6101 740 : m_pSerializer->singleElementNS( XML_w, XML_spacing, FSNS(XML_w, XML_val), aKerning.getStr(), FSEND );
6102 740 : }
6103 :
6104 12792 : void DocxAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
6105 : {
6106 : OString aLanguageCode( OUStringToOString(
6107 25584 : LanguageTag( rLanguage.GetLanguage()).getBcp47(),
6108 12792 : RTL_TEXTENCODING_UTF8));
6109 :
6110 12792 : switch ( rLanguage.Which() )
6111 : {
6112 : case RES_CHRATR_LANGUAGE:
6113 5460 : AddToAttrList( m_pCharLangAttrList, FSNS( XML_w, XML_val ), aLanguageCode.getStr() );
6114 5460 : break;
6115 : case RES_CHRATR_CJK_LANGUAGE:
6116 3946 : AddToAttrList( m_pCharLangAttrList, FSNS( XML_w, XML_eastAsia ), aLanguageCode.getStr() );
6117 3946 : break;
6118 : case RES_CHRATR_CTL_LANGUAGE:
6119 3386 : AddToAttrList( m_pCharLangAttrList, FSNS( XML_w, XML_bidi ), aLanguageCode.getStr() );
6120 3386 : break;
6121 12792 : }
6122 12792 : }
6123 :
6124 3350 : void DocxAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
6125 : {
6126 3350 : if ( rPosture.GetPosture() != ITALIC_NONE )
6127 3004 : m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
6128 : else
6129 346 : m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
6130 3350 : }
6131 :
6132 6 : void DocxAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
6133 : {
6134 6 : if ( rShadow.GetValue() )
6135 0 : m_pSerializer->singleElementNS( XML_w, XML_shadow, FSEND );
6136 : else
6137 6 : m_pSerializer->singleElementNS( XML_w, XML_shadow, FSNS( XML_w, XML_val ), "false", FSEND );
6138 6 : }
6139 :
6140 1140 : void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
6141 : {
6142 : const char *pUnderlineValue;
6143 :
6144 1140 : switch ( rUnderline.GetLineStyle() )
6145 : {
6146 848 : case UNDERLINE_SINGLE: pUnderlineValue = "single"; break;
6147 10 : case UNDERLINE_BOLD: pUnderlineValue = "thick"; break;
6148 4 : case UNDERLINE_DOUBLE: pUnderlineValue = "double"; break;
6149 0 : case UNDERLINE_DOTTED: pUnderlineValue = "dotted"; break;
6150 0 : case UNDERLINE_DASH: pUnderlineValue = "dash"; break;
6151 0 : case UNDERLINE_DASHDOT: pUnderlineValue = "dotDash"; break;
6152 0 : case UNDERLINE_DASHDOTDOT: pUnderlineValue = "dotDotDash"; break;
6153 0 : case UNDERLINE_WAVE: pUnderlineValue = "wave"; break;
6154 0 : case UNDERLINE_BOLDDOTTED: pUnderlineValue = "dottedHeavy"; break;
6155 0 : case UNDERLINE_BOLDDASH: pUnderlineValue = "dashedHeavy"; break;
6156 0 : case UNDERLINE_LONGDASH: pUnderlineValue = "dashLongHeavy"; break;
6157 0 : case UNDERLINE_BOLDLONGDASH: pUnderlineValue = "dashLongHeavy"; break;
6158 0 : case UNDERLINE_BOLDDASHDOT: pUnderlineValue = "dashDotHeavy"; break;
6159 0 : case UNDERLINE_BOLDDASHDOTDOT: pUnderlineValue = "dashDotDotHeavy"; break;
6160 0 : case UNDERLINE_BOLDWAVE: pUnderlineValue = "wavyHeavy"; break;
6161 0 : case UNDERLINE_DOUBLEWAVE: pUnderlineValue = "wavyDouble"; break;
6162 : case UNDERLINE_NONE: // fall through
6163 278 : default: pUnderlineValue = "none"; break;
6164 : }
6165 :
6166 1140 : Color aUnderlineColor = rUnderline.GetColor();
6167 1140 : bool bUnderlineHasColor = aUnderlineColor.GetTransparency() == 0;
6168 1140 : if (bUnderlineHasColor)
6169 : {
6170 : // Underline has a color
6171 : m_pSerializer->singleElementNS( XML_w, XML_u,
6172 : FSNS( XML_w, XML_val ), pUnderlineValue,
6173 : FSNS( XML_w, XML_color ), msfilter::util::ConvertColor( aUnderlineColor ).getStr(),
6174 24 : FSEND );
6175 : }
6176 : else
6177 : {
6178 : // Underline has no color
6179 1116 : m_pSerializer->singleElementNS( XML_w, XML_u, FSNS( XML_w, XML_val ), pUnderlineValue, FSEND );
6180 : }
6181 1140 : }
6182 :
6183 8270 : void DocxAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
6184 : {
6185 8270 : if ( rWeight.GetWeight() == WEIGHT_BOLD )
6186 7702 : m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
6187 : else
6188 568 : m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
6189 8270 : }
6190 :
6191 3244 : void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem& )
6192 : {
6193 : OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()" );
6194 3244 : }
6195 :
6196 16 : void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
6197 : {
6198 16 : if ( rBlink.GetValue() )
6199 16 : m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "blinkBackground", FSEND );
6200 : else
6201 0 : m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "none", FSEND );
6202 16 : }
6203 :
6204 : #define MSWORD_CH_SHADING_FILL "FFFFFF" // The attribute w:fill of w:shd, for MS-Word's character shading,
6205 : #define MSWORD_CH_SHADING_COLOR "auto" // The attribute w:color of w:shd, for MS-Word's character shading,
6206 : #define MSWORD_CH_SHADING_VAL "pct15" // The attribute w:value of w:shd, for MS-Word's character shading,
6207 :
6208 284 : void DocxAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
6209 : {
6210 : // Check if the brush shading pattern is 'PCT15'. If so - write it back to the DOCX
6211 284 : if (rBrush.GetShadingValue() == +ShadingPattern::PCT15)
6212 : {
6213 : m_pSerializer->singleElementNS( XML_w, XML_shd,
6214 : FSNS( XML_w, XML_val ), MSWORD_CH_SHADING_VAL,
6215 : FSNS( XML_w, XML_color ), MSWORD_CH_SHADING_COLOR,
6216 : FSNS( XML_w, XML_fill ), MSWORD_CH_SHADING_FILL,
6217 2 : FSEND );
6218 : }
6219 : else
6220 : {
6221 : m_pSerializer->singleElementNS( XML_w, XML_shd,
6222 282 : FSNS( XML_w, XML_fill ), msfilter::util::ConvertColor( rBrush.GetColor() ).getStr(),
6223 : FSNS( XML_w, XML_val ), "clear",
6224 282 : FSEND );
6225 : }
6226 284 : }
6227 :
6228 7468 : void DocxAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
6229 : {
6230 7468 : OUString sFontName(rFont.GetFamilyName());
6231 14936 : OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
6232 14936 : AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_eastAsia ), sFontNameUtf8.getStr() );
6233 7468 : }
6234 :
6235 536 : void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
6236 : {
6237 536 : if ( rPosture.GetPosture() != ITALIC_NONE )
6238 474 : m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
6239 : else
6240 62 : m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
6241 536 : }
6242 :
6243 2462 : void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
6244 : {
6245 2462 : if ( rWeight.GetWeight() == WEIGHT_BOLD )
6246 2234 : m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
6247 : else
6248 228 : m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
6249 2462 : }
6250 :
6251 12326 : void DocxAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
6252 : {
6253 12326 : OUString sFontName(rFont.GetFamilyName());
6254 24652 : OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
6255 24652 : AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_cs ), sFontNameUtf8.getStr() );
6256 :
6257 12326 : }
6258 :
6259 2038 : void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
6260 : {
6261 2038 : if ( rPosture.GetPosture() != ITALIC_NONE )
6262 1868 : m_pSerializer->singleElementNS( XML_w, XML_iCs, FSEND );
6263 : else
6264 170 : m_pSerializer->singleElementNS( XML_w, XML_iCs, FSNS( XML_w, XML_val ), "false", FSEND );
6265 2038 : }
6266 :
6267 3156 : void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
6268 : {
6269 3156 : if ( rWeight.GetWeight() == WEIGHT_BOLD )
6270 2952 : m_pSerializer->singleElementNS( XML_w, XML_bCs, FSEND );
6271 : else
6272 204 : m_pSerializer->singleElementNS( XML_w, XML_bCs, FSNS( XML_w, XML_val ), "false", FSEND );
6273 3156 : }
6274 :
6275 860 : void DocxAttributeOutput::CharBidiRTL( const SfxPoolItem& )
6276 : {
6277 860 : }
6278 :
6279 908 : void DocxAttributeOutput::CharIdctHint( const SfxPoolItem& )
6280 : {
6281 908 : }
6282 :
6283 32 : void DocxAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
6284 : {
6285 : // Not rorated or we the rotation already handled?
6286 32 : if ( !rRotate.GetValue() || m_bBtLr || m_rExport.SdrExporter().getFrameBtLr())
6287 64 : return;
6288 :
6289 0 : AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_vert ), "true" );
6290 :
6291 0 : if (rRotate.IsFitToLine())
6292 0 : AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_vertCompress ), "true" );
6293 : }
6294 :
6295 16 : void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
6296 : {
6297 : const char *pEmphasis;
6298 :
6299 16 : switch ( rEmphasisMark.GetValue() )
6300 : {
6301 : default:
6302 : case EMPHASISMARK_NONE:
6303 8 : pEmphasis = "none";
6304 8 : break;
6305 : case EMPHASISMARK_DOT | EMPHASISMARK_POS_ABOVE:
6306 2 : pEmphasis = "dot";
6307 2 : break;
6308 : case EMPHASISMARK_ACCENT | EMPHASISMARK_POS_ABOVE:
6309 2 : pEmphasis = "comma";
6310 2 : break;
6311 : case EMPHASISMARK_CIRCLE | EMPHASISMARK_POS_ABOVE:
6312 2 : pEmphasis = "circle";
6313 2 : break;
6314 : case EMPHASISMARK_DOT|EMPHASISMARK_POS_BELOW:
6315 2 : pEmphasis = "underDot";
6316 2 : break;
6317 : }
6318 :
6319 16 : m_pSerializer->singleElementNS( XML_w, XML_em, FSNS( XML_w, XML_val ), pEmphasis, FSEND );
6320 16 : }
6321 :
6322 0 : void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
6323 : {
6324 0 : if ( !rTwoLines.GetValue() )
6325 0 : return;
6326 :
6327 0 : AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_combine ), "true" );
6328 :
6329 0 : sal_Unicode cStart = rTwoLines.GetStartBracket();
6330 0 : sal_Unicode cEnd = rTwoLines.GetEndBracket();
6331 :
6332 0 : if (!cStart && !cEnd)
6333 0 : return;
6334 :
6335 0 : OString sBracket;
6336 0 : if ((cStart == '{') || (cEnd == '}'))
6337 0 : sBracket = (sal_Char *)"curly";
6338 0 : else if ((cStart == '<') || (cEnd == '>'))
6339 0 : sBracket = (sal_Char *)"angle";
6340 0 : else if ((cStart == '[') || (cEnd == ']'))
6341 0 : sBracket = (sal_Char *)"square";
6342 : else
6343 0 : sBracket = (sal_Char *)"round";
6344 0 : AddToAttrList( m_pEastAsianLayoutAttrList, FSNS( XML_w, XML_combineBrackets ), sBracket.getStr() );
6345 : }
6346 :
6347 20 : void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
6348 : {
6349 : m_pSerializer->singleElementNS( XML_w, XML_w,
6350 20 : FSNS( XML_w, XML_val ), OString::number( rScaleWidth.GetValue() ).getStr(), FSEND );
6351 20 : }
6352 :
6353 10 : void DocxAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
6354 : {
6355 10 : switch ( rRelief.GetValue() )
6356 : {
6357 : case RELIEF_EMBOSSED:
6358 0 : m_pSerializer->singleElementNS( XML_w, XML_emboss, FSEND );
6359 0 : break;
6360 : case RELIEF_ENGRAVED:
6361 0 : m_pSerializer->singleElementNS( XML_w, XML_imprint, FSEND );
6362 0 : break;
6363 : default:
6364 10 : m_pSerializer->singleElementNS( XML_w, XML_emboss, FSNS( XML_w, XML_val ), "false", FSEND );
6365 10 : m_pSerializer->singleElementNS( XML_w, XML_imprint, FSNS( XML_w, XML_val ), "false", FSEND );
6366 10 : break;
6367 : }
6368 10 : }
6369 :
6370 284 : void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
6371 : {
6372 284 : if ( rHidden.GetValue() )
6373 88 : m_pSerializer->singleElementNS( XML_w, XML_vanish, FSEND );
6374 : else
6375 196 : m_pSerializer->singleElementNS( XML_w, XML_vanish, FSNS( XML_w, XML_val ), "false", FSEND );
6376 284 : }
6377 :
6378 24 : void DocxAttributeOutput::CharBorder(
6379 : const SvxBorderLine* pAllBorder, const sal_uInt16 nDist, const bool bShadow )
6380 : {
6381 24 : impl_borderLine( m_pSerializer, XML_bdr, pAllBorder, nDist, bShadow );
6382 24 : }
6383 :
6384 0 : void DocxAttributeOutput::CharHighlight( const SvxBrushItem& rHighlight )
6385 : {
6386 0 : const OString sColor = TransHighlightColor( rHighlight.GetColor() );
6387 0 : if ( !sColor.isEmpty() )
6388 : {
6389 : m_pSerializer->singleElementNS( XML_w, XML_highlight,
6390 0 : FSNS( XML_w, XML_val ), sColor.getStr(), FSEND );
6391 0 : }
6392 0 : }
6393 :
6394 586 : void DocxAttributeOutput::TextINetFormat( const SwFmtINetFmt& rLink )
6395 : {
6396 586 : const SwTxtINetFmt* pINetFmt = rLink.GetTxtINetFmt();
6397 586 : const SwCharFmt* pCharFmt = pINetFmt->GetCharFmt();
6398 :
6399 586 : OString aStyleId(m_rExport.pStyles->GetStyleId(m_rExport.GetId(pCharFmt)));
6400 :
6401 586 : m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
6402 586 : }
6403 :
6404 2706 : void DocxAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
6405 : {
6406 2706 : OString aStyleId(m_rExport.pStyles->GetStyleId(m_rExport.GetId(rCharFmt.GetCharFmt())));
6407 :
6408 2706 : m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
6409 2706 : }
6410 :
6411 0 : void DocxAttributeOutput::RefField( const SwField& rFld, const OUString& rRef )
6412 : {
6413 0 : sal_uInt16 nType = rFld.GetTyp( )->Which( );
6414 0 : if ( nType == RES_GETEXPFLD )
6415 : {
6416 0 : OUString sCmd = FieldString( ww::eREF );
6417 0 : sCmd += "\"" + rRef + "\" ";
6418 :
6419 0 : m_rExport.OutputField( &rFld, ww::eREF, sCmd );
6420 : }
6421 :
6422 : // There is nothing to do here for the set fields
6423 0 : }
6424 :
6425 0 : void DocxAttributeOutput::HiddenField( const SwField& /*rFld*/ )
6426 : {
6427 : OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()" );
6428 0 : }
6429 :
6430 16 : void DocxAttributeOutput::PostitField( const SwField* pFld )
6431 : {
6432 : assert( dynamic_cast< const SwPostItField* >( pFld ));
6433 16 : const SwPostItField* pPostItFld = static_cast<const SwPostItField*>(pFld);
6434 16 : OString aName = OUStringToOString(pPostItFld->GetName(), RTL_TEXTENCODING_UTF8);
6435 16 : sal_Int32 nId = 0;
6436 16 : std::map< OString, sal_uInt16 >::iterator it = m_rOpenedAnnotationMarksIds.find(aName);
6437 16 : if (it != m_rOpenedAnnotationMarksIds.end())
6438 : // If the postit field has an annotation mark associated, we already have an id.
6439 10 : nId = it->second;
6440 : else
6441 : // Otherwise get a new one.
6442 6 : nId = m_nNextAnnotationMarkId++;
6443 16 : m_postitFields.push_back(std::make_pair(pPostItFld, nId));
6444 16 : }
6445 :
6446 18080 : void DocxAttributeOutput::WritePostitFieldReference()
6447 : {
6448 36176 : while( m_postitFieldsMaxId < m_postitFields.size())
6449 : {
6450 16 : OString idstr = OString::number(m_postitFields[m_postitFieldsMaxId].second);
6451 :
6452 : // In case this file is inside annotation marks, we want to write the
6453 : // comment reference after the annotation mark is closed, not here.
6454 32 : OString idname = OUStringToOString(m_postitFields[m_postitFieldsMaxId].first->GetName(), RTL_TEXTENCODING_UTF8);
6455 16 : std::map< OString, sal_uInt16 >::iterator it = m_rOpenedAnnotationMarksIds.find( idname );
6456 16 : if ( it == m_rOpenedAnnotationMarksIds.end( ) )
6457 6 : m_pSerializer->singleElementNS( XML_w, XML_commentReference, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND );
6458 16 : ++m_postitFieldsMaxId;
6459 16 : }
6460 18080 : }
6461 :
6462 12 : void DocxAttributeOutput::WritePostitFields()
6463 : {
6464 56 : for( unsigned int i = 0;
6465 28 : i < m_postitFields.size();
6466 : ++i )
6467 : {
6468 16 : OString idstr = OString::number( m_postitFields[ i ].second);
6469 16 : const SwPostItField* f = m_postitFields[ i ].first;
6470 : m_pSerializer->startElementNS( XML_w, XML_comment, FSNS( XML_w, XML_id ), idstr.getStr(),
6471 16 : FSNS( XML_w, XML_author ), OUStringToOString( f->GetPar1(), RTL_TEXTENCODING_UTF8 ).getStr(),
6472 : FSNS( XML_w, XML_date ), DateTimeToOString(f->GetDateTime()).getStr(),
6473 32 : FSNS( XML_w, XML_initials ), OUStringToOString( f->GetInitials(), RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
6474 : // Check for the text object existing, it seems that it can be NULL when saving a newly created
6475 : // comment without giving focus back to the main document. As GetTxt() is empty in that case as well,
6476 : // that is probably a bug in the Writer core.
6477 16 : if( f->GetTextObject() != NULL )
6478 16 : GetExport().WriteOutliner( *f->GetTextObject(), TXT_ATN );
6479 16 : m_pSerializer->endElementNS( XML_w, XML_comment );
6480 16 : }
6481 12 : }
6482 :
6483 0 : bool DocxAttributeOutput::DropdownField( const SwField* pFld )
6484 : {
6485 0 : bool bExpand = false;
6486 :
6487 0 : ww::eField eType = ww::eFORMDROPDOWN;
6488 0 : OUString sCmd = FieldString( eType );
6489 0 : GetExport( ).OutputField( pFld, eType, sCmd );
6490 :
6491 0 : return bExpand;
6492 : }
6493 :
6494 0 : bool DocxAttributeOutput::PlaceholderField( const SwField* pFld )
6495 : {
6496 : assert( pendingPlaceholder == NULL );
6497 0 : pendingPlaceholder = pFld;
6498 0 : return false; // do not expand
6499 : }
6500 :
6501 18158 : void DocxAttributeOutput::WritePendingPlaceholder()
6502 : {
6503 18158 : if( pendingPlaceholder == NULL )
6504 36316 : return;
6505 0 : const SwField* pFld = pendingPlaceholder;
6506 0 : pendingPlaceholder = NULL;
6507 0 : m_pSerializer->startElementNS( XML_w, XML_sdt, FSEND );
6508 0 : m_pSerializer->startElementNS( XML_w, XML_sdtPr, FSEND );
6509 0 : if( !pFld->GetPar2().isEmpty())
6510 : m_pSerializer->singleElementNS( XML_w, XML_alias,
6511 0 : FSNS( XML_w, XML_val ), OUStringToOString( pFld->GetPar2(), RTL_TEXTENCODING_UTF8 ), FSEND );
6512 0 : m_pSerializer->singleElementNS( XML_w, XML_temporary, FSEND );
6513 0 : m_pSerializer->singleElementNS( XML_w, XML_showingPlcHdr, FSEND );
6514 0 : m_pSerializer->singleElementNS( XML_w, XML_text, FSEND );
6515 0 : m_pSerializer->endElementNS( XML_w, XML_sdtPr );
6516 0 : m_pSerializer->startElementNS( XML_w, XML_sdtContent, FSEND );
6517 0 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
6518 0 : RunText( pFld->GetPar1());
6519 0 : m_pSerializer->endElementNS( XML_w, XML_r );
6520 0 : m_pSerializer->endElementNS( XML_w, XML_sdtContent );
6521 0 : m_pSerializer->endElementNS( XML_w, XML_sdt );
6522 : }
6523 :
6524 2 : void DocxAttributeOutput::SetField( const SwField& rFld, ww::eField eType, const OUString& rCmd )
6525 : {
6526 : // field bookmarks are handled in the EndRun method
6527 2 : GetExport().OutputField(&rFld, eType, rCmd );
6528 2 : }
6529 :
6530 2 : void DocxAttributeOutput::WriteExpand( const SwField* pFld )
6531 : {
6532 : // Will be written in the next End Run
6533 2 : OUString sCmd;
6534 2 : m_rExport.OutputField( pFld, ww::eUNKNOWN, sCmd );
6535 2 : }
6536 :
6537 608 : void DocxAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField eType, const OUString& rFldCmd, sal_uInt8 nMode )
6538 : {
6539 608 : struct FieldInfos infos;
6540 608 : if (pFld)
6541 198 : infos.pField = pFld->CopyField();
6542 608 : infos.sCmd = rFldCmd;
6543 608 : infos.eType = eType;
6544 608 : infos.bClose = WRITEFIELD_CLOSE & nMode;
6545 608 : infos.bOpen = WRITEFIELD_START & nMode;
6546 608 : m_Fields.push_back( infos );
6547 :
6548 608 : if ( pFld )
6549 : {
6550 198 : sal_uInt16 nType = pFld->GetTyp( )->Which( );
6551 198 : sal_uInt16 nSubType = pFld->GetSubType();
6552 :
6553 : // TODO Any other field types here ?
6554 198 : if ( ( nType == RES_SETEXPFLD ) && ( nSubType & nsSwGetSetExpType::GSE_STRING ) )
6555 : {
6556 2 : const SwSetExpField *pSet = ( const SwSetExpField* )( pFld );
6557 2 : m_sFieldBkm = pSet->GetPar1( );
6558 : }
6559 196 : else if ( nType == RES_DROPDOWN )
6560 : {
6561 0 : const SwDropDownField* pDropDown = ( const SwDropDownField* )( pFld );
6562 0 : m_sFieldBkm = pDropDown->GetName( );
6563 : }
6564 608 : }
6565 608 : }
6566 :
6567 2 : void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark )
6568 : {
6569 2 : if ( !m_Fields.empty() )
6570 2 : m_Fields.begin()->pFieldmark = &rFieldmark;
6571 2 : }
6572 :
6573 30566 : void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
6574 : std::vector< OUString >& rEnds )
6575 : {
6576 32222 : for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it != end; ++it )
6577 : {
6578 1656 : OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
6579 1656 : m_rBookmarksStart.push_back( rName );
6580 1656 : }
6581 30566 : rStarts.clear();
6582 :
6583 32186 : for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it != end; ++it )
6584 : {
6585 1620 : OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
6586 1620 : m_rBookmarksEnd.push_back( rName );
6587 1620 : }
6588 30566 : rEnds.clear();
6589 30566 : }
6590 :
6591 30562 : void DocxAttributeOutput::WriteAnnotationMarks_Impl( std::vector< OUString >& rStarts,
6592 : std::vector< OUString >& rEnds )
6593 : {
6594 30576 : for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it != end; ++it )
6595 : {
6596 14 : OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
6597 14 : m_rAnnotationMarksStart.push_back( rName );
6598 14 : }
6599 30562 : rStarts.clear();
6600 :
6601 30572 : for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it != end; ++it )
6602 : {
6603 10 : OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
6604 10 : m_rAnnotationMarksEnd.push_back( rName );
6605 10 : }
6606 30562 : rEnds.clear();
6607 30562 : }
6608 :
6609 18 : void DocxAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
6610 : {
6611 18 : const SwEndNoteInfo& rInfo = rFootnote.IsEndNote()?
6612 18 : m_rExport.pDoc->GetEndNoteInfo(): m_rExport.pDoc->GetFtnInfo();
6613 :
6614 : // footnote/endnote run properties
6615 18 : const SwCharFmt* pCharFmt = rInfo.GetAnchorCharFmt( *m_rExport.pDoc );
6616 :
6617 18 : OString aStyleId(m_rExport.pStyles->GetStyleId(m_rExport.GetId(pCharFmt)));
6618 :
6619 18 : m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
6620 :
6621 : // remember the footnote/endnote to
6622 : // 1) write the footnoteReference/endnoteReference in EndRunProperties()
6623 : // 2) be able to dump them all to footnotes.xml/endnotes.xml
6624 18 : if ( !rFootnote.IsEndNote() )
6625 12 : m_pFootnotesList->add( rFootnote );
6626 : else
6627 6 : m_pEndnotesList->add( rFootnote );
6628 18 : }
6629 :
6630 18106 : void DocxAttributeOutput::FootnoteEndnoteReference()
6631 : {
6632 : sal_Int32 nId;
6633 18106 : const SwFmtFtn *pFootnote = m_pFootnotesList->getCurrent( nId );
6634 :
6635 : // both cannot be set at the same time - if they are, it's a bug
6636 18106 : if ( !pFootnote )
6637 18094 : pFootnote = m_pEndnotesList->getCurrent( nId );
6638 :
6639 18106 : if ( !pFootnote )
6640 36194 : return;
6641 :
6642 18 : sal_Int32 nToken = pFootnote->IsEndNote()? XML_endnoteReference: XML_footnoteReference;
6643 :
6644 : // write it
6645 18 : if ( pFootnote->GetNumStr().isEmpty() )
6646 : {
6647 : // autonumbered
6648 : m_pSerializer->singleElementNS( XML_w, nToken,
6649 : FSNS( XML_w, XML_id ), OString::number( nId ).getStr(),
6650 18 : FSEND );
6651 : }
6652 : else
6653 : {
6654 : // not autonumbered
6655 : m_pSerializer->singleElementNS( XML_w, nToken,
6656 : FSNS( XML_w, XML_customMarkFollows ), "1",
6657 : FSNS( XML_w, XML_id ), OString::number( nId ).getStr(),
6658 0 : FSEND );
6659 :
6660 0 : RunText( pFootnote->GetNumStr() );
6661 : }
6662 : }
6663 :
6664 12 : void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes )
6665 : {
6666 12 : m_setFootnote = true;
6667 12 : const FootnotesVector& rVector = bFootnotes? m_pFootnotesList->getVector(): m_pEndnotesList->getVector();
6668 :
6669 12 : sal_Int32 nBody = bFootnotes? XML_footnotes: XML_endnotes;
6670 12 : sal_Int32 nItem = bFootnotes? XML_footnote: XML_endnote;
6671 :
6672 12 : m_pSerializer->startElementNS( XML_w, nBody, m_rExport.MainXmlNamespaces(m_pSerializer) );
6673 :
6674 12 : sal_Int32 nIndex = 0;
6675 :
6676 : // separator
6677 : m_pSerializer->startElementNS( XML_w, nItem,
6678 : FSNS( XML_w, XML_id ), OString::number( nIndex++ ).getStr(),
6679 : FSNS( XML_w, XML_type ), "separator",
6680 12 : FSEND );
6681 12 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
6682 12 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
6683 :
6684 12 : bool bSeparator = true;
6685 12 : if (bFootnotes)
6686 : {
6687 8 : const SwPageFtnInfo& rFtnInfo = m_rExport.pDoc->GetPageDesc(0).GetFtnInfo();
6688 : // Request a separator only in case the width is larger than zero.
6689 8 : bSeparator = double(rFtnInfo.GetWidth()) > 0;
6690 : }
6691 :
6692 12 : if (bSeparator)
6693 10 : m_pSerializer->singleElementNS( XML_w, XML_separator, FSEND );
6694 12 : m_pSerializer->endElementNS( XML_w, XML_r );
6695 12 : m_pSerializer->endElementNS( XML_w, XML_p );
6696 12 : m_pSerializer->endElementNS( XML_w, nItem );
6697 :
6698 : // separator
6699 : m_pSerializer->startElementNS( XML_w, nItem,
6700 : FSNS( XML_w, XML_id ), OString::number( nIndex++ ).getStr(),
6701 : FSNS( XML_w, XML_type ), "continuationSeparator",
6702 12 : FSEND );
6703 12 : m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
6704 12 : m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
6705 12 : m_pSerializer->singleElementNS( XML_w, XML_continuationSeparator, FSEND );
6706 12 : m_pSerializer->endElementNS( XML_w, XML_r );
6707 12 : m_pSerializer->endElementNS( XML_w, XML_p );
6708 12 : m_pSerializer->endElementNS( XML_w, nItem );
6709 :
6710 : // if new special ones are added, update also WriteFootnoteEndnotePr()
6711 :
6712 : // footnotes/endnotes themselves
6713 30 : for ( FootnotesVector::const_iterator i = rVector.begin(); i != rVector.end(); ++i, ++nIndex )
6714 : {
6715 : m_pSerializer->startElementNS( XML_w, nItem,
6716 : FSNS( XML_w, XML_id ), OString::number( nIndex ).getStr(),
6717 18 : FSEND );
6718 :
6719 18 : const SwNodeIndex* pIndex = (*i)->GetTxtFtn()->GetStartNode();
6720 : // tag required at the start of each footnote/endnote
6721 18 : m_footnoteEndnoteRefTag = bFootnotes ? XML_footnoteRef : XML_endnoteRef;
6722 :
6723 18 : m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
6724 18 : pIndex->GetNode().EndOfSectionIndex(),
6725 54 : bFootnotes? TXT_FTN: TXT_EDN );
6726 :
6727 18 : m_pSerializer->endElementNS( XML_w, nItem );
6728 : }
6729 :
6730 12 : m_pSerializer->endElementNS( XML_w, nBody );
6731 :
6732 12 : }
6733 :
6734 28 : void DocxAttributeOutput::WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr fs, int tag,
6735 : const SwEndNoteInfo& info, int listtag )
6736 : {
6737 28 : fs->startElementNS( XML_w, tag, FSEND );
6738 28 : const char* fmt = NULL;
6739 28 : switch( info.aFmt.GetNumberingType())
6740 : {
6741 : case SVX_NUM_CHARS_UPPER_LETTER_N: // fall through, map to upper letters
6742 : case SVX_NUM_CHARS_UPPER_LETTER:
6743 0 : fmt = "upperLetter";
6744 0 : break;
6745 : case SVX_NUM_CHARS_LOWER_LETTER_N: // fall through, map to lower letters
6746 : case SVX_NUM_CHARS_LOWER_LETTER:
6747 0 : fmt = "lowerLetter";
6748 0 : break;
6749 : case SVX_NUM_ROMAN_UPPER:
6750 0 : fmt = "upperRoman";
6751 0 : break;
6752 : case SVX_NUM_ROMAN_LOWER:
6753 10 : fmt = "lowerRoman";
6754 10 : break;
6755 : case SVX_NUM_ARABIC:
6756 18 : fmt = "decimal";
6757 18 : break;
6758 : case SVX_NUM_NUMBER_NONE:
6759 0 : fmt = "none";
6760 0 : break;
6761 : case SVX_NUM_CHAR_SPECIAL:
6762 0 : fmt = "bullet";
6763 0 : break;
6764 : case SVX_NUM_PAGEDESC:
6765 : case SVX_NUM_BITMAP:
6766 : default:
6767 0 : break; // no format
6768 : }
6769 28 : if( fmt != NULL )
6770 28 : fs->singleElementNS( XML_w, XML_numFmt, FSNS( XML_w, XML_val ), fmt, FSEND );
6771 28 : if( info.nFtnOffset != 0 )
6772 : fs->singleElementNS( XML_w, XML_numStart, FSNS( XML_w, XML_val ),
6773 0 : OString::number( info.nFtnOffset + 1).getStr(), FSEND );
6774 28 : if( listtag != 0 ) // we are writing to settings.xml, write also special footnote/endnote list
6775 : { // there are currently only two hardcoded ones ( see FootnotesEndnotes())
6776 12 : fs->singleElementNS( XML_w, listtag, FSNS( XML_w, XML_id ), "0", FSEND );
6777 12 : fs->singleElementNS( XML_w, listtag, FSNS( XML_w, XML_id ), "1", FSEND );
6778 : }
6779 28 : fs->endElementNS( XML_w, tag );
6780 28 : }
6781 :
6782 930 : void DocxAttributeOutput::SectFootnoteEndnotePr()
6783 : {
6784 930 : if( HasFootnotes())
6785 10 : WriteFootnoteEndnotePr( m_pSerializer, XML_footnotePr, m_rExport.pDoc->GetFtnInfo(), 0 );
6786 930 : if( HasEndnotes())
6787 6 : WriteFootnoteEndnotePr( m_pSerializer, XML_endnotePr, m_rExport.pDoc->GetEndNoteInfo(), 0 );
6788 930 : }
6789 :
6790 7368 : void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
6791 : {
6792 7368 : if ( nSpace < 0 )
6793 : {
6794 : AddToAttrList( m_pParagraphSpacingAttrList, 2,
6795 : FSNS( XML_w, XML_lineRule ), "exact",
6796 366 : FSNS( XML_w, XML_line ), OString::number( -nSpace ).getStr() );
6797 : }
6798 7002 : else if( nMulti )
6799 : {
6800 : AddToAttrList( m_pParagraphSpacingAttrList, 2,
6801 : FSNS( XML_w, XML_lineRule ), "auto",
6802 6448 : FSNS( XML_w, XML_line ), OString::number( nSpace ).getStr() );
6803 : }
6804 554 : else if ( nSpace > 0 )
6805 : {
6806 : AddToAttrList( m_pParagraphSpacingAttrList, 2,
6807 : FSNS( XML_w, XML_lineRule ), "atLeast",
6808 548 : FSNS( XML_w, XML_line ), OString::number( nSpace ).getStr() );
6809 : }
6810 : else
6811 6 : AddToAttrList( m_pParagraphSpacingAttrList, FSNS( XML_w, XML_lineRule ), "auto" );
6812 7368 : }
6813 :
6814 5568 : void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
6815 : {
6816 : const char *pAdjustString;
6817 :
6818 5568 : bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
6819 :
6820 5568 : const SfxItemSet* pItems = GetExport().GetCurItemSet();
6821 : const SvxFrameDirectionItem* rFrameDir = pItems?
6822 5568 : static_cast< const SvxFrameDirectionItem* >( pItems->GetItem( RES_FRAMEDIR ) ): NULL;
6823 :
6824 5568 : short nDir = FRMDIR_ENVIRONMENT;
6825 5568 : if( rFrameDir != NULL )
6826 5302 : nDir = rFrameDir->GetValue();
6827 5568 : if ( nDir == FRMDIR_ENVIRONMENT )
6828 328 : nDir = GetExport( ).GetDefaultFrameDirection( );
6829 5568 : bool bRtl = ( nDir == FRMDIR_HORI_RIGHT_TOP );
6830 :
6831 5568 : switch ( rAdjust.GetAdjust() )
6832 : {
6833 : case SVX_ADJUST_LEFT:
6834 1712 : if ( bEcma )
6835 : {
6836 18 : if ( bRtl )
6837 0 : pAdjustString = "right";
6838 : else
6839 18 : pAdjustString = "left";
6840 : }
6841 1694 : else if ( bRtl )
6842 2 : pAdjustString = "end";
6843 : else
6844 1692 : pAdjustString = "start";
6845 1712 : break;
6846 : case SVX_ADJUST_RIGHT:
6847 232 : if ( bEcma )
6848 : {
6849 0 : if ( bRtl )
6850 0 : pAdjustString = "left";
6851 : else
6852 0 : pAdjustString = "right";
6853 : }
6854 232 : else if ( bRtl )
6855 8 : pAdjustString = "start";
6856 : else
6857 224 : pAdjustString = "end";
6858 232 : break;
6859 : case SVX_ADJUST_BLOCKLINE:
6860 : case SVX_ADJUST_BLOCK:
6861 1802 : pAdjustString = "both";
6862 1802 : break;
6863 : case SVX_ADJUST_CENTER:
6864 1822 : pAdjustString = "center";
6865 1822 : break;
6866 : default:
6867 5568 : return; // not supported attribute
6868 : }
6869 5568 : m_pSerializer->singleElementNS( XML_w, XML_jc, FSNS( XML_w, XML_val ), pAdjustString, FSEND );
6870 : }
6871 :
6872 430 : void DocxAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
6873 : {
6874 430 : if (rSplit.GetValue())
6875 14 : m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSNS( XML_w, XML_val ), "false", FSEND );
6876 : else
6877 416 : m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSEND );
6878 430 : }
6879 :
6880 1744 : void DocxAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
6881 : {
6882 1744 : if (rWidows.GetValue())
6883 1380 : m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSEND );
6884 : else
6885 364 : m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSNS( XML_w, XML_val ), "false", FSEND );
6886 1744 : }
6887 :
6888 4090 : static void impl_WriteTabElement( FSHelperPtr pSerializer,
6889 : const SvxTabStop& rTab, long /* nCurrentLeft */ )
6890 : {
6891 4090 : FastAttributeList *pTabElementAttrList = pSerializer->createAttrList();
6892 :
6893 4090 : switch (rTab.GetAdjustment())
6894 : {
6895 : case SVX_TAB_ADJUST_RIGHT:
6896 1404 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( "right" ) );
6897 1404 : break;
6898 : case SVX_TAB_ADJUST_DECIMAL:
6899 2 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( "decimal" ) );
6900 2 : break;
6901 : case SVX_TAB_ADJUST_CENTER:
6902 624 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( "center" ) );
6903 624 : break;
6904 : case SVX_TAB_ADJUST_DEFAULT:
6905 : case SVX_TAB_ADJUST_LEFT:
6906 : default:
6907 2060 : pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( "left" ) );
6908 2060 : break;
6909 : }
6910 :
6911 : // Because GetTabPos already includes indent, we don't need to add nCurrentLeft (CurrentLeft is indentation information)
6912 : //pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
6913 4090 : pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::number( rTab.GetTabPos() ) );
6914 :
6915 4090 : sal_Unicode cFillChar = rTab.GetFill();
6916 :
6917 4090 : if ('.' == cFillChar )
6918 488 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( "dot" ) );
6919 3602 : else if ( '-' == cFillChar )
6920 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( "hyphen" ) );
6921 3602 : else if ( sal_Unicode(0xB7) == cFillChar ) // middle dot
6922 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( "middleDot" ) );
6923 3602 : else if ( '_' == cFillChar )
6924 0 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( "underscore" ) );
6925 : else
6926 3602 : pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( "none" ) );
6927 :
6928 4090 : pSerializer->singleElementNS( XML_w, XML_tab, pTabElementAttrList );
6929 4090 : }
6930 :
6931 4528 : void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
6932 : {
6933 4528 : const SfxPoolItem* pLR = m_rExport.HasItem( RES_LR_SPACE );
6934 4528 : long nCurrentLeft = pLR ? ((const SvxLRSpaceItem*)pLR)->GetTxtLeft() : 0;
6935 :
6936 4528 : sal_uInt16 nCount = rTabStop.Count();
6937 :
6938 : // <w:tabs> must contain at least one <w:tab>, so don't write it empty
6939 4528 : if( nCount == 0 )
6940 66 : return;
6941 4462 : if( nCount == 1 && rTabStop[ 0 ].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
6942 : {
6943 2228 : GetExport().setDefaultTabStop( rTabStop[ 0 ].GetTabPos());
6944 2228 : return;
6945 : }
6946 :
6947 2234 : m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
6948 :
6949 6324 : for (sal_uInt16 i = 0; i < nCount; i++ )
6950 : {
6951 4090 : if( rTabStop[i].GetAdjustment() != SVX_TAB_ADJUST_DEFAULT )
6952 4090 : impl_WriteTabElement( m_pSerializer, rTabStop[i], nCurrentLeft );
6953 : else
6954 0 : GetExport().setDefaultTabStop( rTabStop[i].GetTabPos());
6955 : }
6956 :
6957 2234 : m_pSerializer->endElementNS( XML_w, XML_tabs );
6958 : }
6959 :
6960 1636 : void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
6961 : {
6962 : m_pSerializer->singleElementNS( XML_w, XML_suppressAutoHyphens,
6963 1636 : FSNS( XML_w, XML_val ), OString::boolean( !rHyphenZone.IsHyphen() ),
6964 1636 : FSEND );
6965 1636 : }
6966 :
6967 1118 : void DocxAttributeOutput::ParaNumRule_Impl( const SwTxtNode* /*pTxtNd*/, sal_Int32 nLvl, sal_Int32 nNumId )
6968 : {
6969 1118 : if ( USHRT_MAX != nNumId )
6970 : {
6971 1118 : m_pSerializer->startElementNS( XML_w, XML_numPr, FSEND );
6972 1118 : m_pSerializer->singleElementNS( XML_w, XML_ilvl, FSNS( XML_w, XML_val ), OString::number( nLvl).getStr(), FSEND );
6973 1118 : m_pSerializer->singleElementNS( XML_w, XML_numId, FSNS( XML_w, XML_val ), OString::number( nNumId).getStr(), FSEND );
6974 1118 : m_pSerializer->endElementNS( XML_w, XML_numPr );
6975 : }
6976 1118 : }
6977 :
6978 38 : void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
6979 : {
6980 : m_pSerializer->singleElementNS( XML_w, XML_autoSpaceDE,
6981 38 : FSNS( XML_w, XML_val ), OString::boolean( rScriptSpace.GetValue() ),
6982 38 : FSEND );
6983 38 : }
6984 :
6985 262 : void DocxAttributeOutput::ParaHangingPunctuation( const SfxBoolItem& rItem )
6986 : {
6987 : m_pSerializer->singleElementNS( XML_w, XML_overflowPunct,
6988 262 : FSNS( XML_w, XML_val ), OString::boolean( rItem.GetValue() ),
6989 262 : FSEND );
6990 262 : }
6991 :
6992 38 : void DocxAttributeOutput::ParaForbiddenRules( const SfxBoolItem& rItem )
6993 : {
6994 : m_pSerializer->singleElementNS( XML_w, XML_kinsoku,
6995 38 : FSNS( XML_w, XML_val ), OString::boolean( rItem.GetValue() ),
6996 38 : FSEND );
6997 38 : }
6998 :
6999 162 : void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
7000 : {
7001 : const char *pAlignString;
7002 :
7003 162 : switch ( rAlign.GetValue() )
7004 : {
7005 : case SvxParaVertAlignItem::BASELINE:
7006 136 : pAlignString = "baseline";
7007 136 : break;
7008 : case SvxParaVertAlignItem::TOP:
7009 14 : pAlignString = "top";
7010 14 : break;
7011 : case SvxParaVertAlignItem::CENTER:
7012 8 : pAlignString = "center";
7013 8 : break;
7014 : case SvxParaVertAlignItem::BOTTOM:
7015 0 : pAlignString = "bottom";
7016 0 : break;
7017 : case SvxParaVertAlignItem::AUTOMATIC:
7018 4 : pAlignString = "auto";
7019 4 : break;
7020 : default:
7021 162 : return; // not supported attribute
7022 : }
7023 162 : m_pSerializer->singleElementNS( XML_w, XML_textAlignment, FSNS( XML_w, XML_val ), pAlignString, FSEND );
7024 : }
7025 :
7026 0 : void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
7027 : {
7028 : m_pSerializer->singleElementNS( XML_w, XML_snapToGrid,
7029 0 : FSNS( XML_w, XML_val ), OString::boolean( rGrid.GetValue() ),
7030 0 : FSEND );
7031 0 : }
7032 :
7033 1300 : void DocxAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
7034 : {
7035 1300 : if (m_rExport.SdrExporter().getTextFrameSyntax() && m_rExport.SdrExporter().getFlyFrameSize())
7036 : {
7037 250 : const Size* pSize = m_rExport.SdrExporter().getFlyFrameSize();
7038 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";width:").append(double(pSize->Width()) / 20);
7039 250 : m_rExport.SdrExporter().getTextFrameStyle().append("pt;height:").append(double(pSize->Height()) / 20).append("pt");
7040 : }
7041 1050 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7042 : {
7043 : }
7044 930 : else if ( m_rExport.bOutFlyFrmAttrs )
7045 : {
7046 0 : if ( rSize.GetWidth() && rSize.GetWidthSizeType() == ATT_FIX_SIZE )
7047 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(),
7048 0 : FSNS( XML_w, XML_w ), OString::number( rSize.GetWidth( ) ).getStr() );
7049 :
7050 0 : if ( rSize.GetHeight() )
7051 : {
7052 0 : OString sRule( "exact" );
7053 0 : if ( rSize.GetHeightSizeType() == ATT_MIN_SIZE )
7054 0 : sRule = OString( "atLeast" );
7055 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), 2,
7056 : FSNS( XML_w, XML_hRule ), sRule.getStr(),
7057 0 : FSNS( XML_w, XML_h ), OString::number( rSize.GetHeight( ) ).getStr() );
7058 : }
7059 : }
7060 930 : else if ( m_rExport.bOutPageDescs )
7061 : {
7062 930 : FastAttributeList *attrList = m_pSerializer->createAttrList( );
7063 930 : if ( m_rExport.pAktPageDesc->GetLandscape( ) )
7064 40 : attrList->add( FSNS( XML_w, XML_orient ), "landscape" );
7065 :
7066 930 : attrList->add( FSNS( XML_w, XML_w ), OString::number( rSize.GetWidth( ) ) );
7067 930 : attrList->add( FSNS( XML_w, XML_h ), OString::number( rSize.GetHeight( ) ) );
7068 :
7069 930 : XFastAttributeListRef xAttrList( attrList );
7070 930 : attrList = NULL;
7071 :
7072 930 : m_pSerializer->singleElementNS( XML_w, XML_pgSz, xAttrList );
7073 : }
7074 1300 : }
7075 :
7076 2 : void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
7077 : {
7078 : OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()" );
7079 2 : }
7080 :
7081 5570 : void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
7082 : {
7083 5570 : bool bEcma = m_rExport.GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
7084 :
7085 5570 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7086 : {
7087 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-left:").append(double(rLRSpace.GetLeft()) / 20).append("pt");
7088 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-right:").append(double(rLRSpace.GetRight()) / 20).append("pt");
7089 : }
7090 5320 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7091 : {
7092 : }
7093 5200 : else if ( m_rExport.bOutFlyFrmAttrs )
7094 : {
7095 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_hSpace ),
7096 : OString::number(
7097 0 : ( rLRSpace.GetLeft() + rLRSpace.GetRight() ) / 2 ).getStr() );
7098 : }
7099 5200 : else if ( m_rExport.bOutPageDescs )
7100 : {
7101 930 : m_pageMargins.nPageMarginLeft = 0;
7102 930 : m_pageMargins.nPageMarginRight = 0;
7103 :
7104 930 : const SfxPoolItem* pItem = m_rExport.HasItem( RES_BOX );
7105 930 : if ( pItem )
7106 : {
7107 16 : m_pageMargins.nPageMarginRight = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
7108 16 : m_pageMargins.nPageMarginLeft = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
7109 : }
7110 : else
7111 914 : m_pageMargins.nPageMarginLeft = m_pageMargins.nPageMarginRight = 0;
7112 :
7113 930 : m_pageMargins.nPageMarginLeft = m_pageMargins.nPageMarginLeft + (sal_uInt16)rLRSpace.GetLeft();
7114 930 : m_pageMargins.nPageMarginRight = m_pageMargins.nPageMarginRight + (sal_uInt16)rLRSpace.GetRight();
7115 :
7116 : AddToAttrList( m_pSectionSpacingAttrList, 2,
7117 : FSNS( XML_w, XML_left ), OString::number( m_pageMargins.nPageMarginLeft ).getStr(),
7118 930 : FSNS( XML_w, XML_right ), OString::number( m_pageMargins.nPageMarginRight ).getStr() );
7119 : }
7120 : else
7121 : {
7122 4270 : FastAttributeList *pLRSpaceAttrList = m_pSerializer->createAttrList();
7123 4270 : if((0 != rLRSpace.GetTxtLeft()) || ((0 == rLRSpace.GetTxtLeft()) && rLRSpace.IsExplicitZeroMarginValLeft()))
7124 : {
7125 2988 : pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_left : XML_start ) ), OString::number( rLRSpace.GetTxtLeft() ) );
7126 : }
7127 4270 : if((0 != rLRSpace.GetRight()) || ((0 == rLRSpace.GetRight()) && rLRSpace.IsExplicitZeroMarginValRight()))
7128 : {
7129 1632 : pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_right : XML_end ) ), OString::number( rLRSpace.GetRight() ) );
7130 : }
7131 4270 : sal_Int32 nFirstLineAdjustment = rLRSpace.GetTxtFirstLineOfst();
7132 4270 : if (nFirstLineAdjustment > 0)
7133 206 : pLRSpaceAttrList->add( FSNS( XML_w, XML_firstLine ), OString::number( nFirstLineAdjustment ) );
7134 : else
7135 4064 : pLRSpaceAttrList->add( FSNS( XML_w, XML_hanging ), OString::number( - nFirstLineAdjustment ) );
7136 4270 : m_pSerializer->singleElementNS( XML_w, XML_ind, pLRSpaceAttrList );
7137 : }
7138 5570 : }
7139 :
7140 12320 : void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
7141 : {
7142 :
7143 12320 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7144 : {
7145 248 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-top:").append(double(rULSpace.GetUpper()) / 20).append("pt");
7146 248 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-wrap-distance-bottom:").append(double(rULSpace.GetLower()) / 20).append("pt");
7147 : }
7148 12072 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7149 : {
7150 : }
7151 11954 : else if ( m_rExport.bOutFlyFrmAttrs )
7152 : {
7153 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_vSpace ),
7154 : OString::number(
7155 0 : ( rULSpace.GetLower() + rULSpace.GetUpper() ) / 2 ).getStr() );
7156 : }
7157 11954 : else if (m_rExport.bOutPageDescs )
7158 : {
7159 : OSL_ENSURE( m_rExport.GetCurItemSet(), "Impossible" );
7160 930 : if ( !m_rExport.GetCurItemSet() )
7161 12320 : return;
7162 :
7163 930 : HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
7164 :
7165 930 : sal_Int32 nHeader = 0;
7166 930 : if ( aDistances.HasHeader() )
7167 204 : nHeader = sal_Int32( aDistances.dyaHdrTop );
7168 :
7169 : // Page top
7170 930 : m_pageMargins.nPageMarginTop = aDistances.dyaTop;
7171 :
7172 930 : sal_Int32 nFooter = 0;
7173 930 : if ( aDistances.HasFooter() )
7174 224 : nFooter = sal_Int32( aDistances.dyaHdrBottom );
7175 :
7176 : // Page Bottom
7177 930 : m_pageMargins.nPageMarginBottom = aDistances.dyaBottom;
7178 :
7179 : AddToAttrList( m_pSectionSpacingAttrList, 5,
7180 : FSNS( XML_w, XML_header ), OString::number( nHeader ).getStr(),
7181 : FSNS( XML_w, XML_top ), OString::number( m_pageMargins.nPageMarginTop ).getStr(),
7182 : FSNS( XML_w, XML_footer ), OString::number( nFooter ).getStr(),
7183 : FSNS( XML_w, XML_bottom ), OString::number( m_pageMargins.nPageMarginBottom ).getStr(),
7184 : // FIXME Page Gutter is not handled ATM, setting to 0 as it's mandatory for OOXML
7185 930 : FSNS( XML_w, XML_gutter ), "0" );
7186 : }
7187 : else
7188 : {
7189 : SAL_INFO("sw.ww8", "DocxAttributeOutput::FormatULSpace: setting spacing" << rULSpace.GetUpper() );
7190 : // check if before auto spacing was set during import and spacing we get from actual object is same
7191 : // that we set in import. If yes just write beforeAutoSpacing tag.
7192 11024 : if (m_bParaBeforeAutoSpacing && m_nParaBeforeSpacing == rULSpace.GetUpper())
7193 : {
7194 : AddToAttrList( m_pParagraphSpacingAttrList,
7195 454 : FSNS( XML_w, XML_beforeAutospacing ), "1" );
7196 : }
7197 10570 : else if (m_bParaBeforeAutoSpacing && m_nParaBeforeSpacing == -1)
7198 : {
7199 : AddToAttrList( m_pParagraphSpacingAttrList,
7200 50 : FSNS( XML_w, XML_beforeAutospacing ), "0" );
7201 : AddToAttrList( m_pParagraphSpacingAttrList,
7202 50 : FSNS( XML_w, XML_before ), OString::number( rULSpace.GetUpper() ).getStr() );
7203 : }
7204 : else
7205 : {
7206 : AddToAttrList( m_pParagraphSpacingAttrList,
7207 10520 : FSNS( XML_w, XML_before ), OString::number( rULSpace.GetUpper() ).getStr() );
7208 : }
7209 11024 : m_bParaBeforeAutoSpacing = false;
7210 : // check if after auto spacing was set during import and spacing we get from actual object is same
7211 : // that we set in import. If yes just write afterAutoSpacing tag.
7212 11024 : if (m_bParaAfterAutoSpacing && m_nParaAfterSpacing == rULSpace.GetLower())
7213 : {
7214 : AddToAttrList( m_pParagraphSpacingAttrList,
7215 456 : FSNS( XML_w, XML_afterAutospacing ), "1" );
7216 : }
7217 10568 : else if (m_bParaAfterAutoSpacing && m_nParaAfterSpacing == -1)
7218 : {
7219 : AddToAttrList( m_pParagraphSpacingAttrList,
7220 48 : FSNS( XML_w, XML_afterAutospacing ), "0" );
7221 : AddToAttrList( m_pParagraphSpacingAttrList,
7222 48 : FSNS( XML_w, XML_after ), OString::number( rULSpace.GetLower()).getStr() );
7223 : }
7224 : else
7225 : {
7226 : AddToAttrList( m_pParagraphSpacingAttrList,
7227 10520 : FSNS( XML_w, XML_after ), OString::number( rULSpace.GetLower()).getStr() );
7228 : }
7229 11024 : m_bParaAfterAutoSpacing = false;
7230 :
7231 11024 : if (rULSpace.GetContext())
7232 760 : m_pSerializer->singleElementNS( XML_w, XML_contextualSpacing, FSEND );
7233 : }
7234 : }
7235 :
7236 370 : void DocxAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
7237 : {
7238 370 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7239 : {
7240 500 : OString sType, sSide;
7241 250 : switch (rSurround.GetSurround())
7242 : {
7243 : case SURROUND_NONE:
7244 2 : sType = "topAndBottom";
7245 2 : break;
7246 : case SURROUND_PARALLEL:
7247 44 : sType = "square";
7248 44 : break;
7249 : case SURROUND_IDEAL:
7250 20 : sType = "square";
7251 20 : sSide = "largest";
7252 20 : break;
7253 : case SURROUND_LEFT:
7254 0 : sType = "square";
7255 0 : sSide = "left";
7256 0 : break;
7257 : case SURROUND_RIGHT:
7258 0 : sType = "square";
7259 0 : sSide = "right";
7260 0 : break;
7261 : case SURROUND_THROUGHT:
7262 : /* empty type and side means throught */
7263 : default:
7264 184 : break;
7265 : }
7266 250 : if (!sType.isEmpty() || !sSide.isEmpty())
7267 : {
7268 66 : m_rExport.SdrExporter().setFlyWrapAttrList(m_pSerializer->createAttrList());
7269 66 : if (!sType.isEmpty())
7270 66 : m_rExport.SdrExporter().getFlyWrapAttrList()->add(XML_type, sType);
7271 66 : if (!sSide.isEmpty())
7272 20 : m_rExport.SdrExporter().getFlyWrapAttrList()->add(XML_side, sSide);
7273 250 : }
7274 : }
7275 120 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7276 : {
7277 : }
7278 0 : else if ( m_rExport.bOutFlyFrmAttrs )
7279 : {
7280 0 : OString sWrap( "auto" );
7281 0 : switch ( rSurround.GetSurround( ) )
7282 : {
7283 : case SURROUND_NONE:
7284 0 : sWrap = OString( "none" );
7285 0 : break;
7286 : case SURROUND_THROUGHT:
7287 0 : sWrap = OString( "through" );
7288 0 : break;
7289 : case SURROUND_IDEAL:
7290 : case SURROUND_PARALLEL:
7291 : case SURROUND_LEFT:
7292 : case SURROUND_RIGHT:
7293 : default:
7294 0 : sWrap = OString( "around" );
7295 : }
7296 :
7297 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_wrap ), sWrap.getStr() );
7298 : }
7299 370 : }
7300 :
7301 370 : void DocxAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
7302 : {
7303 370 : OString sAlign;
7304 370 : switch( rFlyVert.GetVertOrient() )
7305 : {
7306 : case text::VertOrientation::NONE:
7307 336 : break;
7308 : case text::VertOrientation::CENTER:
7309 : case text::VertOrientation::LINE_CENTER:
7310 8 : sAlign = OString( "center" );
7311 8 : break;
7312 : case text::VertOrientation::BOTTOM:
7313 0 : sAlign = OString( "bottom" );
7314 0 : break;
7315 : case text::VertOrientation::LINE_BOTTOM:
7316 0 : sAlign = OString( "outside" );
7317 0 : break;
7318 : case text::VertOrientation::TOP:
7319 26 : sAlign = OString( "top" );
7320 26 : break;
7321 : case text::VertOrientation::LINE_TOP:
7322 : default:
7323 0 : sAlign = OString( "inside" );
7324 0 : break;
7325 : }
7326 370 : OString sVAnchor( "page" );
7327 370 : switch ( rFlyVert.GetRelationOrient( ) )
7328 : {
7329 : case text::RelOrientation::CHAR:
7330 : case text::RelOrientation::PRINT_AREA:
7331 : case text::RelOrientation::TEXT_LINE:
7332 : case text::RelOrientation::FRAME:
7333 272 : sVAnchor = OString( "text" );
7334 272 : break;
7335 : case text::RelOrientation::PAGE_LEFT:
7336 : case text::RelOrientation::PAGE_RIGHT:
7337 : case text::RelOrientation::FRAME_LEFT:
7338 : case text::RelOrientation::FRAME_RIGHT:
7339 : case text::RelOrientation::PAGE_PRINT_AREA:
7340 12 : sVAnchor = OString( "margin" );
7341 12 : break;
7342 : case text::RelOrientation::PAGE_FRAME:
7343 : default:
7344 86 : break;
7345 : }
7346 :
7347 370 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7348 : {
7349 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";margin-top:").append(double(rFlyVert.GetPos()) / 20).append("pt");
7350 250 : if ( !sAlign.isEmpty() )
7351 20 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-vertical:").append(sAlign);
7352 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-vertical-relative:").append(sVAnchor);
7353 : }
7354 120 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7355 : {
7356 : }
7357 0 : else if ( m_rExport.bOutFlyFrmAttrs )
7358 : {
7359 0 : if ( !sAlign.isEmpty() )
7360 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_yAlign ), sAlign.getStr() );
7361 : else
7362 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_y ),
7363 0 : OString::number( rFlyVert.GetPos() ).getStr() );
7364 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_vAnchor ), sVAnchor.getStr() );
7365 370 : }
7366 370 : }
7367 :
7368 370 : void DocxAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
7369 : {
7370 370 : OString sAlign;
7371 370 : switch( rFlyHori.GetHoriOrient() )
7372 : {
7373 : case text::HoriOrientation::NONE:
7374 288 : break;
7375 : case text::HoriOrientation::LEFT:
7376 0 : sAlign = OString( rFlyHori.IsPosToggle( ) ? "inside" : "left" );
7377 0 : break;
7378 : case text::HoriOrientation::RIGHT:
7379 22 : sAlign = OString( rFlyHori.IsPosToggle( ) ? "outside" : "right" );
7380 22 : break;
7381 : case text::HoriOrientation::CENTER:
7382 : case text::HoriOrientation::FULL: // FULL only for tables
7383 : default:
7384 60 : sAlign = OString( "center" );
7385 60 : break;
7386 : }
7387 370 : OString sHAnchor( "page" );
7388 370 : switch ( rFlyHori.GetRelationOrient( ) )
7389 : {
7390 : case text::RelOrientation::CHAR:
7391 : case text::RelOrientation::PRINT_AREA:
7392 : case text::RelOrientation::FRAME:
7393 228 : sHAnchor = OString( "text" );
7394 228 : break;
7395 : case text::RelOrientation::PAGE_LEFT:
7396 : case text::RelOrientation::PAGE_RIGHT:
7397 : case text::RelOrientation::FRAME_LEFT:
7398 : case text::RelOrientation::FRAME_RIGHT:
7399 : case text::RelOrientation::PAGE_PRINT_AREA:
7400 64 : sHAnchor = OString( "margin" );
7401 64 : break;
7402 : case text::RelOrientation::PAGE_FRAME:
7403 : default:
7404 78 : break;
7405 : }
7406 :
7407 370 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7408 : {
7409 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";margin-left:").append(double(rFlyHori.GetPos()) / 20).append("pt");
7410 250 : if ( !sAlign.isEmpty() )
7411 46 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-horizontal:").append(sAlign);
7412 250 : m_rExport.SdrExporter().getTextFrameStyle().append(";mso-position-horizontal-relative:").append(sHAnchor);
7413 : }
7414 120 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7415 : {
7416 : }
7417 0 : else if ( m_rExport.bOutFlyFrmAttrs )
7418 : {
7419 0 : if ( !sAlign.isEmpty() )
7420 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_xAlign ), sAlign.getStr() );
7421 : else
7422 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_x ),
7423 0 : OString::number( rFlyHori.GetPos() ).getStr() );
7424 0 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), FSNS( XML_w, XML_hAnchor ), sHAnchor.getStr() );
7425 370 : }
7426 370 : }
7427 :
7428 370 : void DocxAttributeOutput::FormatAnchor( const SwFmtAnchor& )
7429 : {
7430 : // Fly frames: anchors here aren't matching the anchors in docx
7431 370 : }
7432 :
7433 146 : boost::optional<sal_Int32> lcl_getDmlAlpha(const SvxBrushItem& rBrush)
7434 : {
7435 146 : boost::optional<sal_Int32> oRet;
7436 146 : sal_Int32 nTransparency = rBrush.GetColor().GetTransparency();
7437 146 : if (nTransparency)
7438 : {
7439 : // Convert transparency to percent
7440 44 : sal_Int8 nTransparencyPercent = SvxBrushItem::TransparencyToPercent(nTransparency);
7441 :
7442 : // Calculate alpha value
7443 : // Consider oox/source/drawingml/color.cxx : getTransparency() function.
7444 44 : sal_Int32 nAlpha = (::oox::drawingml::MAX_PERCENT - ( ::oox::drawingml::PER_PERCENT * nTransparencyPercent ) );
7445 44 : oRet = nAlpha;
7446 : }
7447 146 : return oRet;
7448 : }
7449 :
7450 146 : void DocxAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
7451 : {
7452 146 : OString sColor = msfilter::util::ConvertColor( rBrush.GetColor().GetRGBColor() );
7453 292 : boost::optional<sal_Int32> oAlpha = lcl_getDmlAlpha(rBrush);
7454 146 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7455 : {
7456 : // Handle 'Opacity'
7457 46 : if (oAlpha)
7458 : {
7459 : // Calculate opacity value
7460 : // Consider oox/source/vml/vmlformatting.cxx : decodeColor() function.
7461 22 : double fOpacity = (double)(*oAlpha) * 65535 / ::oox::drawingml::MAX_PERCENT;
7462 22 : OUString sOpacity = OUString::number(fOpacity) + "f";
7463 :
7464 22 : AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_opacity, OUStringToOString(sOpacity, RTL_TEXTENCODING_UTF8).getStr() );
7465 : }
7466 :
7467 46 : sColor = "#" + sColor;
7468 46 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), XML_fillcolor, sColor.getStr() );
7469 : }
7470 100 : else if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7471 : {
7472 46 : bool bImageBackground = false;
7473 46 : const SfxPoolItem* pItem = GetExport().HasItem(XATTR_FILLSTYLE);
7474 46 : if (pItem)
7475 : {
7476 46 : const XFillStyleItem* pFillStyle = static_cast<const XFillStyleItem*>(pItem);
7477 46 : if(pFillStyle->GetValue() == drawing::FillStyle_BITMAP)
7478 : {
7479 0 : bImageBackground = true;
7480 : }
7481 : }
7482 46 : if (!bImageBackground)
7483 : {
7484 46 : m_pSerializer->startElementNS(XML_a, XML_solidFill, FSEND);
7485 : m_pSerializer->startElementNS(XML_a, XML_srgbClr,
7486 : XML_val, sColor,
7487 46 : FSEND);
7488 46 : if (oAlpha)
7489 : m_pSerializer->singleElementNS(XML_a, XML_alpha,
7490 22 : XML_val, OString::number(*oAlpha),
7491 22 : FSEND);
7492 46 : m_pSerializer->endElementNS(XML_a, XML_srgbClr);
7493 46 : m_pSerializer->endElementNS(XML_a, XML_solidFill);
7494 : }
7495 : }
7496 54 : else if ( !m_rExport.bOutPageDescs )
7497 : {
7498 : // compare fill color with the original fill color
7499 : OString sOriginalFill = rtl::OUStringToOString(
7500 54 : m_sOriginalBackgroundColor, RTL_TEXTENCODING_UTF8 );
7501 :
7502 54 : if( !m_pBackgroundAttrList )
7503 : {
7504 0 : m_pBackgroundAttrList = m_pSerializer->createAttrList();
7505 0 : m_pBackgroundAttrList->add( FSNS( XML_w, XML_fill ), sColor.getStr() );
7506 0 : m_pBackgroundAttrList->add( FSNS( XML_w, XML_val ), "clear" );
7507 : }
7508 54 : else if ( sOriginalFill != sColor )
7509 : {
7510 : // fill was modified during edition, theme fill attribute must be dropped
7511 0 : delete m_pBackgroundAttrList;
7512 0 : m_pBackgroundAttrList = m_pSerializer->createAttrList();
7513 0 : m_pBackgroundAttrList->add( FSNS( XML_w, XML_fill ), sColor.getStr() );
7514 0 : m_pBackgroundAttrList->add( FSNS( XML_w, XML_val ), "clear" );
7515 : }
7516 54 : m_sOriginalBackgroundColor = "";
7517 146 : }
7518 146 : }
7519 :
7520 1538 : void DocxAttributeOutput::FormatFillStyle( const XFillStyleItem& rFillStyle )
7521 : {
7522 1538 : if (!m_bIgnoreNextFill)
7523 1418 : m_oFillStyle.reset(rFillStyle.GetValue());
7524 : else
7525 120 : m_bIgnoreNextFill = false;
7526 1538 : }
7527 :
7528 18 : void DocxAttributeOutput::FormatFillGradient( const XFillGradientItem& rFillGradient )
7529 : {
7530 18 : if (m_oFillStyle && *m_oFillStyle == drawing::FillStyle_GRADIENT && !m_rExport.SdrExporter().getDMLTextFrameSyntax())
7531 : {
7532 6 : AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_type, "gradient" );
7533 :
7534 6 : const XGradient& rGradient = rFillGradient.GetGradientValue();
7535 6 : OString sStartColor = msfilter::util::ConvertColor(rGradient.GetStartColor());
7536 12 : OString sEndColor = msfilter::util::ConvertColor(rGradient.GetEndColor());
7537 :
7538 : // Calculate the angle that was originally in the imported DOCX file
7539 : // (reverse calculate the angle that was converted in the file
7540 : // /oox/source/vml/vmlformatting.cxx :: FillModel::pushToPropMap
7541 : // and also in
7542 : // /oox/source/drawingml/fillproperties.cxx :: FillProperties::pushToPropMap
7543 6 : sal_Int32 nReverseAngle = 4500 - rGradient.GetAngle();
7544 6 : nReverseAngle = nReverseAngle / 10;
7545 6 : nReverseAngle = (270 - nReverseAngle) % 360;
7546 6 : if (nReverseAngle != 0)
7547 2 : AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(),
7548 4 : XML_angle, OString::number( nReverseAngle ).getStr() );
7549 :
7550 12 : OString sColor1 = sStartColor;
7551 12 : OString sColor2 = sEndColor;
7552 :
7553 6 : switch (rGradient.GetGradientStyle())
7554 : {
7555 : case XGRAD_AXIAL:
7556 6 : AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_focus, "50%" );
7557 : // If it is an 'axial' gradient - swap the colors
7558 : // (because in the import process they were imported swapped)
7559 6 : sColor1 = sEndColor;
7560 6 : sColor2 = sStartColor;
7561 6 : break;
7562 0 : case XGRAD_LINEAR: break;
7563 0 : case XGRAD_RADIAL: break;
7564 0 : case XGRAD_ELLIPTICAL: break;
7565 0 : case XGRAD_SQUARE: break;
7566 0 : case XGRAD_RECT: break;
7567 : }
7568 :
7569 6 : sColor1 = "#" + sColor1;
7570 6 : sColor2 = "#" + sColor2;
7571 6 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), XML_fillcolor, sColor1.getStr() );
7572 12 : AddToAttrList( m_rExport.SdrExporter().getFlyFillAttrList(), XML_color2, sColor2.getStr() );
7573 : }
7574 12 : else if (m_oFillStyle && *m_oFillStyle == drawing::FillStyle_GRADIENT && m_rExport.SdrExporter().getDMLTextFrameSyntax())
7575 : {
7576 : SwFrmFmt & rFormat(
7577 6 : const_cast<SwFrmFmt&>(m_rExport.mpParentFrame->GetFrmFmt()));
7578 : uno::Reference<beans::XPropertySet> const xPropertySet(
7579 6 : SwXTextFrame::CreateXTextFrame(*rFormat.GetDoc(), &rFormat),
7580 6 : uno::UNO_QUERY);
7581 6 : m_rDrawingML.SetFS(m_pSerializer);
7582 6 : m_rDrawingML.WriteGradientFill(xPropertySet);
7583 : }
7584 18 : m_oFillStyle.reset();
7585 18 : }
7586 :
7587 728 : void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
7588 : {
7589 728 : if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7590 : {
7591 : // <a:gradFill> should be before <a:ln>.
7592 120 : const SfxPoolItem* pItem = GetExport().HasItem(XATTR_FILLSTYLE);
7593 120 : if (pItem)
7594 : {
7595 120 : const XFillStyleItem* pFillStyle = static_cast<const XFillStyleItem*>(pItem);
7596 120 : FormatFillStyle(*pFillStyle);
7597 120 : if (m_oFillStyle && *m_oFillStyle == drawing::FillStyle_BITMAP)
7598 : {
7599 0 : const SdrObject* pSdrObj = m_rExport.mpParentFrame->GetFrmFmt().FindRealSdrObject();
7600 0 : if (pSdrObj)
7601 : {
7602 0 : uno::Reference< drawing::XShape > xShape( ((SdrObject*)pSdrObj)->getUnoShape(), uno::UNO_QUERY );
7603 0 : uno::Reference< beans::XPropertySet > xPropertySet( xShape, uno::UNO_QUERY );
7604 0 : m_rDrawingML.SetFS(m_pSerializer);
7605 0 : m_rDrawingML.WriteBlipFill( xPropertySet, "BackGraphicURL" );
7606 : }
7607 : }
7608 : }
7609 :
7610 120 : pItem = GetExport().HasItem(XATTR_FILLGRADIENT);
7611 120 : if (pItem)
7612 : {
7613 6 : const XFillGradientItem* pFillGradient = static_cast<const XFillGradientItem*>(pItem);
7614 6 : FormatFillGradient(*pFillGradient);
7615 : }
7616 120 : m_bIgnoreNextFill = true;
7617 : }
7618 728 : if (m_rExport.SdrExporter().getTextFrameSyntax() || m_rExport.SdrExporter().getDMLTextFrameSyntax())
7619 : {
7620 370 : const SvxBorderLine* pLeft = rBox.GetLeft( );
7621 370 : const SvxBorderLine* pTop = rBox.GetTop( );
7622 370 : const SvxBorderLine* pRight = rBox.GetRight( );
7623 370 : const SvxBorderLine* pBottom = rBox.GetBottom( );
7624 :
7625 690 : if (pLeft && pRight && pTop && pBottom &&
7626 690 : *pLeft == *pRight && *pLeft == *pTop && *pLeft == *pBottom)
7627 : {
7628 : // Check border style
7629 160 : editeng::SvxBorderStyle eBorderStyle = pTop->GetBorderLineStyle();
7630 160 : if (eBorderStyle == table::BorderLineStyle::NONE)
7631 : {
7632 76 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7633 : {
7634 38 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), 2,
7635 38 : XML_stroked, "f", XML_strokeweight, "0pt" );
7636 : }
7637 : }
7638 : else
7639 : {
7640 84 : OString sColor(msfilter::util::ConvertColor(pTop->GetColor()));
7641 84 : double const fConverted(editeng::ConvertBorderWidthToWord(pTop->GetBorderLineStyle(), pTop->GetWidth()));
7642 :
7643 84 : if (m_rExport.SdrExporter().getTextFrameSyntax())
7644 : {
7645 42 : sColor = "#" + sColor;
7646 42 : sal_Int32 nWidth = sal_Int32(fConverted / 20);
7647 42 : OString sWidth = OString::number(nWidth) + "pt";
7648 42 : AddToAttrList( m_rExport.SdrExporter().getFlyAttrList(), 2,
7649 : XML_strokecolor, sColor.getStr(),
7650 84 : XML_strokeweight, sWidth.getStr() );
7651 42 : if( LineStyle_DASH == pTop->GetBorderLineStyle() ) // Line Style is Dash type
7652 0 : AddToAttrList( m_rExport.SdrExporter().getDashLineStyle(),
7653 0 : XML_dashstyle, "dash" );
7654 : }
7655 : else
7656 : {
7657 42 : OString sWidth(OString::number(TwipsToEMU(fConverted)));
7658 : m_pSerializer->startElementNS(XML_a, XML_ln,
7659 : XML_w, sWidth.getStr(),
7660 42 : FSEND);
7661 42 : m_pSerializer->startElementNS(XML_a, XML_solidFill, FSEND);
7662 : m_pSerializer->singleElementNS(XML_a, XML_srgbClr,
7663 : XML_val, sColor,
7664 42 : FSEND);
7665 42 : m_pSerializer->endElementNS(XML_a, XML_solidFill);
7666 42 : if( LineStyle_DASH == pTop->GetBorderLineStyle() ) // Line Style is Dash type
7667 0 : m_pSerializer->singleElementNS(XML_a, XML_prstDash, XML_val, "dash", FSEND);
7668 42 : m_pSerializer->endElementNS(XML_a, XML_ln);
7669 84 : }
7670 : }
7671 : }
7672 :
7673 370 : if (m_rExport.SdrExporter().getDMLTextFrameSyntax())
7674 : {
7675 120 : m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_lIns, OString::number(TwipsToEMU(rBox.GetDistance(BOX_LINE_LEFT))));
7676 120 : m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_tIns, OString::number(TwipsToEMU(rBox.GetDistance(BOX_LINE_TOP))));
7677 120 : m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_rIns, OString::number(TwipsToEMU(rBox.GetDistance(BOX_LINE_RIGHT))));
7678 120 : m_rExport.SdrExporter().getBodyPrAttrList()->add(XML_bIns, OString::number(TwipsToEMU(rBox.GetDistance(BOX_LINE_BOTTOM))));
7679 120 : return;
7680 : }
7681 :
7682 : // v:textbox's inset attribute: inner margin values for textbox text - write only non-default values
7683 250 : double fDistanceLeftTwips = double(rBox.GetDistance(BOX_LINE_LEFT));
7684 250 : double fDistanceTopTwips = double(rBox.GetDistance(BOX_LINE_TOP));
7685 250 : double fDistanceRightTwips = double(rBox.GetDistance(BOX_LINE_RIGHT));
7686 250 : double fDistanceBottomTwips = double(rBox.GetDistance(BOX_LINE_BOTTOM));
7687 :
7688 : // Convert 'TWIPS' to 'INCH' (because in Word the default values are in Inches)
7689 250 : double fDistanceLeftInch = fDistanceLeftTwips / 1440;
7690 250 : double fDistanceTopInch = fDistanceTopTwips / 1440;
7691 250 : double fDistanceRightInch = fDistanceRightTwips / 1440;
7692 250 : double fDistanceBottomInch = fDistanceBottomTwips / 1440;
7693 :
7694 : // This code will write ONLY the non-default values. The values are in 'left','top','right','bottom' order.
7695 : // so 'bottom' is checked if it is default and if it is non-default - all the values will be written
7696 : // otherwise - 'right' is checked if it is default and if it is non-default - all the values except for 'bottom' will be written
7697 : // and so on.
7698 250 : OStringBuffer aInset;
7699 250 : if(!aInset.isEmpty() || fDistanceBottomInch != double(0.05))
7700 212 : aInset.insert(0, "," + OString::number(fDistanceBottomInch) + "in");
7701 :
7702 250 : if(!aInset.isEmpty() || fDistanceRightInch != double(0.1))
7703 212 : aInset.insert(0, "," + OString::number(fDistanceRightInch) + "in");
7704 :
7705 250 : if(!aInset.isEmpty() || fDistanceTopInch != double(0.05))
7706 212 : aInset.insert(0, "," + OString::number(fDistanceTopInch) + "in");
7707 :
7708 250 : if(!aInset.isEmpty() || fDistanceLeftInch != double(0.1))
7709 212 : aInset.insert(0, OString::number(fDistanceLeftInch) + "in");
7710 :
7711 250 : if (!aInset.isEmpty())
7712 212 : m_rExport.SdrExporter().getTextboxAttrList()->add(XML_inset, aInset.makeStringAndClear());
7713 :
7714 250 : return;
7715 : }
7716 :
7717 358 : OutputBorderOptions aOutputBorderOptions = lcl_getBoxBorderOptions();
7718 : // Check if there is a shadow item
7719 358 : const SfxPoolItem* pItem = GetExport().HasItem( RES_SHADOW );
7720 358 : if ( pItem )
7721 : {
7722 10 : const SvxShadowItem* pShadowItem = (const SvxShadowItem*)pItem;
7723 10 : aOutputBorderOptions.aShadowLocation = pShadowItem->GetLocation();
7724 : }
7725 :
7726 358 : if ( !m_bOpenedSectPr || GetWritingHeaderFooter())
7727 : {
7728 : // Not inside a section
7729 :
7730 : // Open the paragraph's borders tag
7731 342 : m_pSerializer->startElementNS( XML_w, XML_pBdr, FSEND );
7732 :
7733 342 : std::map<sal_uInt16, css::table::BorderLine2> aEmptyMap; // empty styles map
7734 : impl_borders( m_pSerializer, rBox, aOutputBorderOptions, &m_pageMargins,
7735 342 : aEmptyMap );
7736 :
7737 : // Close the paragraph's borders tag
7738 342 : m_pSerializer->endElementNS( XML_w, XML_pBdr );
7739 : }
7740 : }
7741 :
7742 26 : void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
7743 : {
7744 : // Get the columns attributes
7745 26 : FastAttributeList *pColsAttrList = m_pSerializer->createAttrList();
7746 :
7747 : pColsAttrList->add( FSNS( XML_w, XML_num ),
7748 26 : OString::number( nCols ). getStr( ) );
7749 :
7750 26 : const char* pEquals = "false";
7751 26 : if ( bEven )
7752 : {
7753 14 : sal_uInt16 nWidth = rCol.GetGutterWidth( true );
7754 : pColsAttrList->add( FSNS( XML_w, XML_space ),
7755 14 : OString::number( nWidth ).getStr( ) );
7756 :
7757 14 : pEquals = "true";
7758 : }
7759 :
7760 26 : pColsAttrList->add( FSNS( XML_w, XML_equalWidth ), pEquals );
7761 :
7762 26 : bool bHasSep = (COLADJ_NONE != rCol.GetLineAdj());
7763 :
7764 26 : pColsAttrList->add( FSNS( XML_w, XML_sep ), OString::boolean( bHasSep ) );
7765 :
7766 : // Write the element
7767 26 : m_pSerializer->startElementNS( XML_w, XML_cols, pColsAttrList );
7768 :
7769 : // Write the columns width if non-equals
7770 26 : const SwColumns & rColumns = rCol.GetColumns( );
7771 26 : if ( !bEven )
7772 : {
7773 50 : for ( sal_uInt16 n = 0; n < nCols; ++n )
7774 : {
7775 38 : FastAttributeList *pColAttrList = m_pSerializer->createAttrList();
7776 38 : sal_uInt16 nWidth = rCol.CalcPrtColWidth( n, ( sal_uInt16 ) nPageSize );
7777 : pColAttrList->add( FSNS( XML_w, XML_w ),
7778 38 : OString::number( nWidth ).getStr( ) );
7779 :
7780 38 : if ( n + 1 != nCols )
7781 : {
7782 26 : sal_uInt16 nSpacing = rColumns[n].GetRight( ) + rColumns[n + 1].GetLeft( );
7783 : pColAttrList->add( FSNS( XML_w, XML_space ),
7784 26 : OString::number( nSpacing ).getStr( ) );
7785 : }
7786 :
7787 38 : m_pSerializer->singleElementNS( XML_w, XML_col, pColAttrList );
7788 : }
7789 : }
7790 :
7791 26 : m_pSerializer->endElementNS( XML_w, XML_cols );
7792 26 : }
7793 :
7794 1858 : void DocxAttributeOutput::FormatKeep( const SvxFmtKeepItem& )
7795 : {
7796 1858 : m_pSerializer->singleElementNS( XML_w, XML_keepNext, FSEND );
7797 1858 : }
7798 :
7799 892 : void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid )
7800 : {
7801 892 : FastAttributeList *pGridAttrList = m_pSerializer->createAttrList();
7802 :
7803 892 : OString sGridType;
7804 892 : switch ( rGrid.GetGridType( ) )
7805 : {
7806 : default:
7807 : case GRID_NONE:
7808 888 : sGridType = OString( "default" );
7809 888 : break;
7810 : case GRID_LINES_ONLY:
7811 4 : sGridType = OString( "lines" );
7812 4 : break;
7813 : case GRID_LINES_CHARS:
7814 0 : if ( rGrid.IsSnapToChars( ) )
7815 0 : sGridType = OString( "snapToChars" );
7816 : else
7817 0 : sGridType = OString( "linesAndChars" );
7818 0 : break;
7819 : }
7820 892 : pGridAttrList->add( FSNS( XML_w, XML_type ), sGridType.getStr( ) );
7821 :
7822 892 : sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
7823 : pGridAttrList->add( FSNS( XML_w, XML_linePitch ),
7824 892 : OString::number( nHeight ).getStr( ) );
7825 :
7826 : pGridAttrList->add( FSNS( XML_w, XML_charSpace ),
7827 892 : OString::number( GridCharacterPitch( rGrid ) ).getStr( ) );
7828 :
7829 892 : m_pSerializer->singleElementNS( XML_w, XML_docGrid, pGridAttrList );
7830 892 : }
7831 :
7832 1772 : void DocxAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
7833 : {
7834 1772 : if ( !rNumbering.IsCount( ) )
7835 1766 : m_pSerializer->singleElementNS( XML_w, XML_suppressLineNumbers, FSEND );
7836 1772 : }
7837 :
7838 2530 : void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
7839 : {
7840 2530 : OString sTextFlow;
7841 2530 : bool bBiDi = false;
7842 2530 : short nDir = rDirection.GetValue();
7843 :
7844 2530 : if ( nDir == FRMDIR_ENVIRONMENT )
7845 32 : nDir = GetExport( ).GetDefaultFrameDirection( );
7846 :
7847 2530 : switch ( nDir )
7848 : {
7849 : default:
7850 : case FRMDIR_HORI_LEFT_TOP:
7851 2512 : sTextFlow = OString( "lrTb" );
7852 2512 : break;
7853 : case FRMDIR_HORI_RIGHT_TOP:
7854 18 : sTextFlow = OString( "lrTb" );
7855 18 : bBiDi = true;
7856 18 : break;
7857 : case FRMDIR_VERT_TOP_LEFT: // many things but not this one
7858 : case FRMDIR_VERT_TOP_RIGHT:
7859 0 : sTextFlow = OString( "tbRl" );
7860 0 : break;
7861 : }
7862 :
7863 2530 : if ( m_rExport.bOutPageDescs )
7864 : {
7865 : m_pSerializer->singleElementNS( XML_w, XML_textDirection,
7866 : FSNS( XML_w, XML_val ), sTextFlow.getStr( ),
7867 930 : FSEND );
7868 930 : if ( bBiDi )
7869 8 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
7870 : }
7871 1600 : else if ( !m_rExport.bOutFlyFrmAttrs )
7872 : {
7873 1600 : if ( bBiDi )
7874 10 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSNS( XML_w, XML_val ), "1", FSEND );
7875 : else
7876 1590 : m_pSerializer->singleElementNS( XML_w, XML_bidi, FSNS( XML_w, XML_val ), "0", FSEND );
7877 2530 : }
7878 2530 : }
7879 :
7880 1802 : void DocxAttributeOutput::ParaGrabBag(const SfxGrabBagItem& rItem)
7881 : {
7882 1802 : const std::map<OUString, com::sun::star::uno::Any>& rMap = rItem.GetGrabBag();
7883 3314 : for (std::map<OUString, com::sun::star::uno::Any>::const_iterator i = rMap.begin(); i != rMap.end(); ++i)
7884 : {
7885 1512 : if (i->first == "MirrorIndents")
7886 2 : m_pSerializer->singleElementNS(XML_w, XML_mirrorIndents, FSEND);
7887 1510 : else if (i->first == "ParaTopMarginBeforeAutoSpacing")
7888 : {
7889 510 : m_bParaBeforeAutoSpacing = true;
7890 : // get fixed value which was set during import
7891 510 : i->second >>= m_nParaBeforeSpacing;
7892 510 : m_nParaBeforeSpacing = convertMm100ToTwip(m_nParaBeforeSpacing);
7893 : SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: property =" << i->first << " : m_nParaBeforeSpacing= " << m_nParaBeforeSpacing);
7894 : }
7895 1000 : else if (i->first == "ParaBottomMarginAfterAutoSpacing")
7896 : {
7897 510 : m_bParaAfterAutoSpacing = true;
7898 : // get fixed value which was set during import
7899 510 : i->second >>= m_nParaAfterSpacing;
7900 510 : m_nParaAfterSpacing = convertMm100ToTwip(m_nParaAfterSpacing);
7901 : SAL_INFO("sw.ww8", "DocxAttributeOutput::ParaGrabBag: property =" << i->first << " : m_nParaBeforeSpacing= " << m_nParaAfterSpacing);
7902 : }
7903 490 : else if (i->first == "CharThemeFill")
7904 : {
7905 172 : uno::Sequence<beans::PropertyValue> aGrabBagSeq;
7906 172 : i->second >>= aGrabBagSeq;
7907 :
7908 894 : for (sal_Int32 j=0; j < aGrabBagSeq.getLength(); ++j)
7909 : {
7910 722 : OString sVal = OUStringToOString(aGrabBagSeq[j].Value.get<OUString>(), RTL_TEXTENCODING_UTF8);
7911 :
7912 722 : if (sVal.isEmpty())
7913 0 : continue;
7914 :
7915 722 : if (aGrabBagSeq[j].Name == "val")
7916 172 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_val), sVal.getStr());
7917 550 : else if (aGrabBagSeq[j].Name == "color")
7918 172 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_color), sVal.getStr());
7919 378 : else if (aGrabBagSeq[j].Name == "themeColor")
7920 2 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeColor), sVal.getStr());
7921 376 : else if (aGrabBagSeq[j].Name == "themeTint")
7922 0 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeTint), sVal.getStr());
7923 376 : else if (aGrabBagSeq[j].Name == "themeShade")
7924 2 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeShade), sVal.getStr());
7925 374 : else if (aGrabBagSeq[j].Name == "fill")
7926 172 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_fill), sVal.getStr());
7927 202 : else if (aGrabBagSeq[j].Name == "themeFill")
7928 24 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeFill), sVal.getStr());
7929 178 : else if (aGrabBagSeq[j].Name == "themeFillTint")
7930 6 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeFillTint), sVal.getStr());
7931 172 : else if (aGrabBagSeq[j].Name == "themeFillShade")
7932 0 : AddToAttrList(m_pBackgroundAttrList, FSNS(XML_w, XML_themeFillShade), sVal.getStr());
7933 172 : else if (aGrabBagSeq[j].Name == "originalColor")
7934 172 : aGrabBagSeq[j].Value >>= m_sOriginalBackgroundColor;
7935 894 : }
7936 : }
7937 318 : else if (i->first == "SdtPr")
7938 : {
7939 : uno::Sequence<beans::PropertyValue> aGrabBagSdt =
7940 178 : i->second.get< uno::Sequence<beans::PropertyValue> >();
7941 620 : for (sal_Int32 k=0; k < aGrabBagSdt.getLength(); ++k)
7942 : {
7943 442 : beans::PropertyValue aPropertyValue = aGrabBagSdt[k];
7944 792 : if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartObj" ||
7945 350 : aPropertyValue.Name == "ooxml:CT_SdtPr_docPartList")
7946 : {
7947 92 : if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartObj")
7948 92 : m_nParagraphSdtPrToken = FSNS( XML_w, XML_docPartObj );
7949 0 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_docPartList")
7950 0 : m_nParagraphSdtPrToken = FSNS( XML_w, XML_docPartList );
7951 :
7952 92 : uno::Sequence<beans::PropertyValue> aGrabBag;
7953 92 : aPropertyValue.Value >>= aGrabBag;
7954 276 : for (sal_Int32 j=0; j < aGrabBag.getLength(); ++j)
7955 : {
7956 184 : OUString sValue = aGrabBag[j].Value.get<OUString>();
7957 184 : if (aGrabBag[j].Name == "ooxml:CT_SdtDocPart_docPartGallery")
7958 : AddToAttrList( m_pParagraphSdtPrTokenChildren,
7959 : FSNS( XML_w, XML_docPartGallery ),
7960 92 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
7961 92 : else if (aGrabBag[j].Name == "ooxml:CT_SdtDocPart_docPartCategory")
7962 : AddToAttrList( m_pParagraphSdtPrTokenChildren,
7963 : FSNS( XML_w, XML_docPartCategory ),
7964 0 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
7965 92 : else if (aGrabBag[j].Name == "ooxml:CT_SdtDocPart_docPartUnique")
7966 92 : AddToAttrList( m_pParagraphSdtPrTokenChildren, FSNS( XML_w, XML_docPartUnique ), "" );
7967 276 : }
7968 : }
7969 350 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_equation")
7970 0 : m_nParagraphSdtPrToken = FSNS( XML_w, XML_equation );
7971 350 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_picture")
7972 2 : m_nParagraphSdtPrToken = FSNS( XML_w, XML_picture );
7973 348 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_citation")
7974 0 : m_nParagraphSdtPrToken = FSNS( XML_w, XML_citation );
7975 348 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_group")
7976 2 : m_nParagraphSdtPrToken = FSNS( XML_w, XML_group );
7977 346 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_text")
7978 58 : m_nParagraphSdtPrToken = FSNS(XML_w, XML_text);
7979 288 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_dataBinding" && !m_pParagraphSdtPrDataBindingAttrs)
7980 : {
7981 42 : uno::Sequence<beans::PropertyValue> aGrabBag;
7982 42 : aPropertyValue.Value >>= aGrabBag;
7983 168 : for (sal_Int32 j = 0; j < aGrabBag.getLength(); ++j)
7984 : {
7985 126 : OUString sValue = aGrabBag[j].Value.get<OUString>();
7986 126 : if (aGrabBag[j].Name == "ooxml:CT_DataBinding_prefixMappings")
7987 : AddToAttrList( m_pParagraphSdtPrDataBindingAttrs,
7988 : FSNS( XML_w, XML_prefixMappings ),
7989 42 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
7990 84 : else if (aGrabBag[j].Name == "ooxml:CT_DataBinding_xpath")
7991 : AddToAttrList( m_pParagraphSdtPrDataBindingAttrs,
7992 : FSNS( XML_w, XML_xpath ),
7993 42 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
7994 42 : else if (aGrabBag[j].Name == "ooxml:CT_DataBinding_storeItemID")
7995 : AddToAttrList( m_pParagraphSdtPrDataBindingAttrs,
7996 : FSNS( XML_w, XML_storeItemID ),
7997 42 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
7998 168 : }
7999 : }
8000 246 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_alias" && m_aParagraphSdtPrAlias.isEmpty())
8001 : {
8002 42 : if (!(aPropertyValue.Value >>= m_aParagraphSdtPrAlias))
8003 : SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unexpected sdt alias value");
8004 42 : m_aStartedParagraphSdtPrAlias = m_aParagraphSdtPrAlias;
8005 : }
8006 204 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_checkbox")
8007 : {
8008 12 : m_nParagraphSdtPrToken = FSNS( XML_w14, XML_checkbox );
8009 12 : uno::Sequence<beans::PropertyValue> aGrabBag;
8010 12 : aPropertyValue.Value >>= aGrabBag;
8011 48 : for (sal_Int32 j=0; j < aGrabBag.getLength(); ++j)
8012 : {
8013 36 : OUString sValue = aGrabBag[j].Value.get<OUString>();
8014 36 : if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_checked")
8015 : AddToAttrList( m_pParagraphSdtPrTokenChildren,
8016 : FSNS( XML_w14, XML_checked ),
8017 12 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8018 24 : else if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_checkedState")
8019 : AddToAttrList( m_pParagraphSdtPrTokenChildren,
8020 : FSNS( XML_w14, XML_checkedState ),
8021 12 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8022 12 : else if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_uncheckedState")
8023 : AddToAttrList( m_pParagraphSdtPrTokenChildren,
8024 : FSNS( XML_w14, XML_uncheckedState ),
8025 12 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8026 48 : }
8027 : }
8028 192 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id")
8029 184 : m_bParagraphSdtHasId = true;
8030 8 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_date")
8031 : {
8032 8 : m_nParagraphSdtPrToken = FSNS(XML_w, XML_date);
8033 8 : uno::Sequence<beans::PropertyValue> aGrabBag = aPropertyValue.Value.get< uno::Sequence<beans::PropertyValue> >();
8034 48 : for (sal_Int32 j=0; j < aGrabBag.getLength(); ++j)
8035 : {
8036 40 : OString sValue = OUStringToOString(aGrabBag[j].Value.get<OUString>(), RTL_TEXTENCODING_UTF8);
8037 :
8038 40 : if (aGrabBag[j].Name == "ooxml:CT_SdtDate_fullDate")
8039 8 : AddToAttrList(m_pParagraphSdtPrTokenAttributes, FSNS(XML_w, XML_fullDate), sValue.getStr());
8040 32 : else if (aGrabBag[j].Name == "ooxml:CT_SdtDate_dateFormat")
8041 8 : AddToAttrList(m_pParagraphSdtPrTokenChildren, FSNS(XML_w, XML_dateFormat), sValue.getStr());
8042 24 : else if (aGrabBag[j].Name == "ooxml:CT_SdtDate_lid")
8043 8 : AddToAttrList(m_pParagraphSdtPrTokenChildren, FSNS(XML_w, XML_lid), sValue.getStr());
8044 16 : else if (aGrabBag[j].Name == "ooxml:CT_SdtDate_storeMappedDataAs")
8045 8 : AddToAttrList(m_pParagraphSdtPrTokenChildren, FSNS(XML_w, XML_storeMappedDataAs), sValue.getStr());
8046 8 : else if (aGrabBag[j].Name == "ooxml:CT_SdtDate_calendar")
8047 8 : AddToAttrList(m_pParagraphSdtPrTokenChildren, FSNS(XML_w, XML_calendar), sValue.getStr());
8048 : else
8049 : SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled SdtPr / ooxml:CT_SdtPr_date grab bag property " << aGrabBag[j].Name);
8050 48 : }
8051 : }
8052 : else
8053 : SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled SdtPr grab bag property " << aPropertyValue.Name);
8054 620 : }
8055 : }
8056 140 : else if (i->first == "ParaCnfStyle")
8057 : {
8058 14 : uno::Sequence<beans::PropertyValue> aAttributes = i->second.get< uno::Sequence<beans::PropertyValue> >();
8059 14 : m_pTableStyleExport->CnfStyle(aAttributes);
8060 : }
8061 126 : else if (i->first == "ParaSdtEndBefore")
8062 : {
8063 : // Handled already in StartParagraph().
8064 : }
8065 : else
8066 : SAL_WARN("sw.ww8", "DocxAttributeOutput::ParaGrabBag: unhandled grab bag property " << i->first );
8067 : }
8068 1802 : }
8069 :
8070 10892 : void DocxAttributeOutput::CharGrabBag( const SfxGrabBagItem& rItem )
8071 : {
8072 10892 : const std::map< OUString, com::sun::star::uno::Any >& rMap = rItem.GetGrabBag();
8073 :
8074 : // get original values of theme-derived properties to check if they have changed during the edition
8075 10892 : bool bWriteCSTheme = true;
8076 10892 : bool bWriteAsciiTheme = true;
8077 10892 : bool bWriteEastAsiaTheme = true;
8078 10892 : bool bWriteThemeFontColor = true;
8079 10892 : OUString sOriginalValue;
8080 44942 : for ( std::map< OUString, com::sun::star::uno::Any >::const_iterator i = rMap.begin(); i != rMap.end(); ++i )
8081 : {
8082 34050 : if ( m_pFontsAttrList && i->first == "CharThemeFontNameCs" )
8083 : {
8084 3330 : if ( i->second >>= sOriginalValue )
8085 : bWriteCSTheme =
8086 3330 : ( m_pFontsAttrList->getOptionalValue( FSNS( XML_w, XML_cs ) ) == sOriginalValue );
8087 : }
8088 30720 : else if ( m_pFontsAttrList && i->first == "CharThemeFontNameAscii" )
8089 : {
8090 3382 : if ( i->second >>= sOriginalValue )
8091 : bWriteAsciiTheme =
8092 3382 : ( m_pFontsAttrList->getOptionalValue( FSNS( XML_w, XML_ascii ) ) == sOriginalValue );
8093 : }
8094 27338 : else if ( m_pFontsAttrList && i->first == "CharThemeFontNameEastAsia" )
8095 : {
8096 3422 : if ( i->second >>= sOriginalValue )
8097 : bWriteEastAsiaTheme =
8098 3422 : ( m_pFontsAttrList->getOptionalValue( FSNS( XML_w, XML_eastAsia ) ) == sOriginalValue );
8099 : }
8100 23916 : else if ( m_pColorAttrList && i->first == "CharThemeOriginalColor" )
8101 : {
8102 7310 : if ( i->second >>= sOriginalValue )
8103 : bWriteThemeFontColor =
8104 7310 : ( m_pColorAttrList->getOptionalValue( FSNS( XML_w, XML_val ) ) == sOriginalValue );
8105 : }
8106 : }
8107 :
8108 : // save theme attributes back to the run properties
8109 21784 : OUString str;
8110 44942 : for ( std::map< OUString, com::sun::star::uno::Any >::const_iterator i = rMap.begin(); i != rMap.end(); ++i )
8111 : {
8112 34050 : if ( i->first == "CharThemeNameAscii" && bWriteAsciiTheme )
8113 : {
8114 3282 : i->second >>= str;
8115 : AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_asciiTheme ),
8116 3282 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8117 : }
8118 30768 : else if ( i->first == "CharThemeNameCs" && bWriteCSTheme )
8119 : {
8120 3274 : i->second >>= str;
8121 : AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_cstheme ),
8122 3274 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8123 : }
8124 27494 : else if ( i->first == "CharThemeNameEastAsia" && bWriteEastAsiaTheme )
8125 : {
8126 3376 : i->second >>= str;
8127 : AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_eastAsiaTheme ),
8128 3376 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8129 : }
8130 24118 : else if ( i->first == "CharThemeNameHAnsi" && bWriteAsciiTheme )
8131 : // this is not a mistake: in LibO we don't directly support the hAnsi family
8132 : // of attributes so we save the same value from ascii attributes instead
8133 : {
8134 3278 : i->second >>= str;
8135 : AddToAttrList( m_pFontsAttrList, FSNS( XML_w, XML_hAnsiTheme ),
8136 3278 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8137 : }
8138 20840 : else if ( i->first == "CharThemeColor" && bWriteThemeFontColor )
8139 : {
8140 1766 : i->second >>= str;
8141 : AddToAttrList( m_pColorAttrList, FSNS( XML_w, XML_themeColor ),
8142 1766 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8143 : }
8144 19074 : else if ( i->first == "CharThemeColorShade" )
8145 : {
8146 598 : i->second >>= str;
8147 : AddToAttrList( m_pColorAttrList, FSNS( XML_w, XML_themeShade ),
8148 598 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8149 : }
8150 18476 : else if ( i->first == "CharThemeColorTint" )
8151 : {
8152 254 : i->second >>= str;
8153 : AddToAttrList( m_pColorAttrList, FSNS( XML_w, XML_themeTint ),
8154 254 : OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
8155 : }
8156 51332 : else if( i->first == "CharThemeFontNameCs" ||
8157 26386 : i->first == "CharThemeFontNameAscii" ||
8158 37792 : i->first == "CharThemeFontNameEastAsia" ||
8159 8072 : i->first == "CharThemeOriginalColor" )
8160 : {
8161 : // just skip these, they were processed before
8162 : }
8163 2262 : else if(i->first == "CharGlowTextEffect" ||
8164 1442 : i->first == "CharShadowTextEffect" ||
8165 1384 : i->first == "CharReflectionTextEffect" ||
8166 1318 : i->first == "CharTextOutlineTextEffect" ||
8167 1238 : i->first == "CharTextFillTextEffect" ||
8168 1200 : i->first == "CharScene3DTextEffect" ||
8169 1176 : i->first == "CharProps3DTextEffect" ||
8170 1114 : i->first == "CharLigaturesTextEffect" ||
8171 1022 : i->first == "CharNumFormTextEffect" ||
8172 956 : i->first == "CharNumSpacingTextEffect" ||
8173 1680 : i->first == "CharStylisticSetsTextEffect" ||
8174 446 : i->first == "CharCntxtAltsTextEffect")
8175 : {
8176 326 : beans::PropertyValue aPropertyValue;
8177 326 : i->second >>= aPropertyValue;
8178 326 : m_aTextEffectsGrabBag.push_back(aPropertyValue);
8179 : }
8180 436 : else if (i->first == "SdtEndBefore")
8181 : {
8182 40 : if (m_bStartedCharSdt)
8183 30 : m_bEndCharSdt = true;
8184 : }
8185 396 : else if (i->first == "SdtPr" && FLY_NOT_PROCESSED != m_nStateOfFlyFrame )
8186 : {
8187 : uno::Sequence<beans::PropertyValue> aGrabBagSdt =
8188 70 : i->second.get< uno::Sequence<beans::PropertyValue> >();
8189 262 : for (sal_Int32 k=0; k < aGrabBagSdt.getLength(); ++k)
8190 : {
8191 192 : beans::PropertyValue aPropertyValue = aGrabBagSdt[k];
8192 192 : if (aPropertyValue.Name == "ooxml:CT_SdtPr_checkbox")
8193 : {
8194 0 : m_nRunSdtPrToken = FSNS( XML_w14, XML_checkbox );
8195 0 : uno::Sequence<beans::PropertyValue> aGrabBag;
8196 0 : aPropertyValue.Value >>= aGrabBag;
8197 0 : for (sal_Int32 j=0; j < aGrabBag.getLength(); ++j)
8198 : {
8199 0 : OUString sValue = aGrabBag[j].Value.get<OUString>();
8200 0 : if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_checked")
8201 : AddToAttrList( m_pRunSdtPrTokenChildren,
8202 : FSNS( XML_w14, XML_checked ),
8203 0 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8204 0 : else if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_checkedState")
8205 : AddToAttrList( m_pRunSdtPrTokenChildren,
8206 : FSNS( XML_w14, XML_checkedState ),
8207 0 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8208 0 : else if (aGrabBag[j].Name == "ooxml:CT_SdtCheckbox_uncheckedState")
8209 : AddToAttrList( m_pRunSdtPrTokenChildren,
8210 : FSNS( XML_w14, XML_uncheckedState ),
8211 0 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8212 0 : }
8213 : }
8214 192 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_dataBinding" && m_pRunSdtPrDataBindingAttrs == NULL)
8215 : {
8216 32 : uno::Sequence<beans::PropertyValue> aGrabBag;
8217 32 : aPropertyValue.Value >>= aGrabBag;
8218 128 : for (sal_Int32 j=0; j < aGrabBag.getLength(); ++j)
8219 : {
8220 96 : OUString sValue = aGrabBag[j].Value.get<OUString>();
8221 96 : if (aGrabBag[j].Name == "ooxml:CT_DataBinding_prefixMappings")
8222 : AddToAttrList( m_pRunSdtPrDataBindingAttrs,
8223 : FSNS( XML_w, XML_prefixMappings ),
8224 32 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8225 64 : else if (aGrabBag[j].Name == "ooxml:CT_DataBinding_xpath")
8226 : AddToAttrList( m_pRunSdtPrDataBindingAttrs,
8227 : FSNS( XML_w, XML_xpath ),
8228 32 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8229 32 : else if (aGrabBag[j].Name == "ooxml:CT_DataBinding_storeItemID")
8230 : AddToAttrList( m_pRunSdtPrDataBindingAttrs,
8231 : FSNS( XML_w, XML_storeItemID ),
8232 32 : rtl::OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr() );
8233 128 : }
8234 : }
8235 160 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_alias" && m_aRunSdtPrAlias.isEmpty())
8236 : {
8237 34 : if (!(aPropertyValue.Value >>= m_aRunSdtPrAlias))
8238 : SAL_WARN("sw.ww8", "DocxAttributeOutput::CharGrabBag: unexpected sdt alias value");
8239 : }
8240 : //do not overwrite the parent node.
8241 126 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_text" && !m_pRunSdtPrTokenChildren)
8242 36 : m_nRunSdtPrToken = FSNS( XML_w, XML_text );
8243 90 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_id" && m_nRunSdtPrToken == 0)
8244 : // only write id token as a marker if no other exist
8245 70 : m_nRunSdtPrToken = FSNS( XML_w, XML_id );
8246 20 : else if (aPropertyValue.Name == "ooxml:CT_SdtPr_citation")
8247 14 : m_nRunSdtPrToken = FSNS( XML_w, XML_citation );
8248 262 : }
8249 : }
8250 : else
8251 : SAL_INFO("sw.ww8", "DocxAttributeOutput::CharGrabBag: unhandled grab bag property " << i->first);
8252 10892 : }
8253 10892 : }
8254 :
8255 860 : DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML )
8256 : : m_rExport( rExport ),
8257 : m_pSerializer( pSerializer ),
8258 : m_rDrawingML( *pDrawingML ),
8259 : m_pFontsAttrList( NULL ),
8260 : m_pEastAsianLayoutAttrList( NULL ),
8261 : m_pCharLangAttrList( NULL ),
8262 : m_pSectionSpacingAttrList( NULL ),
8263 : m_pParagraphSpacingAttrList( NULL ),
8264 : m_pHyperlinkAttrList( NULL ),
8265 : m_bEndCharSdt(false),
8266 : m_bStartedCharSdt(false),
8267 : m_bStartedParaSdt(false),
8268 : m_pColorAttrList( NULL ),
8269 : m_pBackgroundAttrList( NULL ),
8270 : m_endPageRef( false ),
8271 : m_pFootnotesList( new ::docx::FootnotesList() ),
8272 : m_pEndnotesList( new ::docx::FootnotesList() ),
8273 : m_footnoteEndnoteRefTag( 0 ),
8274 : m_pSectionInfo( NULL ),
8275 : m_pRedlineData( NULL ),
8276 : m_nRedlineId( 0 ),
8277 : m_bOpenedSectPr( false ),
8278 : m_bHadSectPr(false),
8279 : m_bRunTextIsOn( false ),
8280 : m_bWritingHeaderFooter( false ),
8281 : m_bAnchorLinkedToNode(false),
8282 : m_sFieldBkm( ),
8283 : m_nNextBookmarkId( 0 ),
8284 : m_nNextAnnotationMarkId( 0 ),
8285 : m_pTableWrt( NULL ),
8286 : m_pCurrentFrame( NULL ),
8287 : m_bParagraphOpened( false ),
8288 : m_bParagraphFrameOpen( false ),
8289 : m_bIsFirstParagraph( true ),
8290 : m_bAlternateContentChoiceOpen( false ),
8291 : m_bPostponedProcessingFly( false ),
8292 : m_nColBreakStatus( COLBRK_NONE ),
8293 : m_nTextFrameLevel( 0 ),
8294 : m_closeHyperlinkInThisRun( false ),
8295 : m_closeHyperlinkInPreviousRun( false ),
8296 : m_startedHyperlink( false ),
8297 : m_nHyperLinkCount(0),
8298 : m_nFieldsInHyperlink( 0 ),
8299 : m_postponedGraphic( NULL ),
8300 : m_postponedDiagram( NULL ),
8301 : m_postponedVMLDrawing(NULL),
8302 : m_postponedDMLDrawing(NULL),
8303 : m_postponedCustomShape(NULL),
8304 : m_postponedOLE( NULL ),
8305 : m_postponedMath( NULL ),
8306 : m_postponedChart( NULL ),
8307 : pendingPlaceholder( NULL ),
8308 : m_postitFieldsMaxId( 0 ),
8309 : m_anchorId( 1 ),
8310 : m_nextFontId( 1 ),
8311 : m_tableReference(new TableReference()),
8312 : m_bIgnoreNextFill(false),
8313 : m_bBtLr(false),
8314 860 : m_pTableStyleExport(new DocxTableStyleExport(rExport.pDoc, pSerializer)),
8315 : m_bParaBeforeAutoSpacing(false),
8316 : m_bParaAfterAutoSpacing(false),
8317 : m_nParaBeforeSpacing(0),
8318 : m_nParaAfterSpacing(0),
8319 : m_setFootnote(false)
8320 : , m_nParagraphSdtPrToken(0)
8321 : , m_pParagraphSdtPrTokenChildren(NULL)
8322 : , m_pParagraphSdtPrTokenAttributes(NULL)
8323 : , m_pParagraphSdtPrDataBindingAttrs(NULL)
8324 : , m_nRunSdtPrToken(0)
8325 : , m_nStateOfFlyFrame( FLY_NOT_PROCESSED )
8326 : , m_pRunSdtPrTokenChildren(NULL)
8327 : , m_pRunSdtPrDataBindingAttrs(NULL)
8328 1720 : , m_bParagraphSdtHasId(false)
8329 : {
8330 860 : }
8331 :
8332 2580 : DocxAttributeOutput::~DocxAttributeOutput()
8333 : {
8334 860 : delete m_pFontsAttrList, m_pFontsAttrList = NULL;
8335 860 : delete m_pEastAsianLayoutAttrList, m_pEastAsianLayoutAttrList = NULL;
8336 860 : delete m_pCharLangAttrList, m_pCharLangAttrList = NULL;
8337 860 : delete m_pSectionSpacingAttrList, m_pSectionSpacingAttrList = NULL;
8338 860 : delete m_pParagraphSpacingAttrList, m_pParagraphSpacingAttrList = NULL;
8339 860 : delete m_pHyperlinkAttrList, m_pHyperlinkAttrList = NULL;
8340 860 : delete m_pColorAttrList, m_pColorAttrList = NULL;
8341 860 : delete m_pBackgroundAttrList, m_pBackgroundAttrList = NULL;
8342 :
8343 860 : delete m_pFootnotesList, m_pFootnotesList = NULL;
8344 860 : delete m_pEndnotesList, m_pEndnotesList = NULL;
8345 :
8346 860 : delete m_pTableWrt, m_pTableWrt = NULL;
8347 860 : delete m_pParagraphSdtPrTokenChildren; m_pParagraphSdtPrTokenChildren = NULL;
8348 860 : delete m_pParagraphSdtPrTokenAttributes; m_pParagraphSdtPrTokenAttributes = NULL;
8349 860 : delete m_pParagraphSdtPrDataBindingAttrs; m_pParagraphSdtPrDataBindingAttrs = NULL;
8350 860 : delete m_pRunSdtPrTokenChildren; m_pRunSdtPrTokenChildren = NULL;
8351 860 : delete m_pRunSdtPrDataBindingAttrs; m_pRunSdtPrDataBindingAttrs = NULL;
8352 1720 : }
8353 :
8354 113562 : DocxExport& DocxAttributeOutput::GetExport()
8355 : {
8356 113562 : return m_rExport;
8357 : }
8358 :
8359 4680 : void DocxAttributeOutput::SetSerializer( ::sax_fastparser::FSHelperPtr pSerializer )
8360 : {
8361 4680 : m_pSerializer = pSerializer;
8362 4680 : m_pTableStyleExport->SetSerializer(pSerializer);
8363 4680 : }
8364 :
8365 2650 : bool DocxAttributeOutput::HasFootnotes() const
8366 : {
8367 2650 : return !m_pFootnotesList->isEmpty();
8368 : }
8369 :
8370 2650 : bool DocxAttributeOutput::HasEndnotes() const
8371 : {
8372 2650 : return !m_pEndnotesList->isEmpty();
8373 : }
8374 :
8375 860 : bool DocxAttributeOutput::HasPostitFields() const
8376 : {
8377 860 : return !m_postitFields.empty();
8378 : }
8379 :
8380 8 : void DocxAttributeOutput::BulletDefinition(int nId, const Graphic& rGraphic, Size aSize)
8381 : {
8382 : m_pSerializer->startElementNS(XML_w, XML_numPicBullet,
8383 : FSNS(XML_w, XML_numPicBulletId), OString::number(nId).getStr(),
8384 8 : FSEND);
8385 :
8386 8 : OStringBuffer aStyle;
8387 : // Size is in twips, we need it in points.
8388 8 : aStyle.append("width:").append(double(aSize.Width()) / 20);
8389 8 : aStyle.append("pt;height:").append(double(aSize.Height()) / 20).append("pt");
8390 8 : m_pSerializer->startElementNS( XML_w, XML_pict, FSEND);
8391 : m_pSerializer->startElementNS( XML_v, XML_shape,
8392 : XML_style, aStyle.getStr(),
8393 : FSNS(XML_o, XML_bullet), "t",
8394 8 : FSEND);
8395 :
8396 8 : m_rDrawingML.SetFS(m_pSerializer);
8397 16 : OUString aRelId = m_rDrawingML.WriteImage(rGraphic);
8398 : m_pSerializer->singleElementNS( XML_v, XML_imagedata,
8399 : FSNS(XML_r, XML_id), OUStringToOString(aRelId, RTL_TEXTENCODING_UTF8),
8400 : FSNS(XML_o, XML_title), "",
8401 8 : FSEND);
8402 :
8403 8 : m_pSerializer->endElementNS(XML_v, XML_shape);
8404 8 : m_pSerializer->endElementNS(XML_w, XML_pict);
8405 :
8406 16 : m_pSerializer->endElementNS(XML_w, XML_numPicBullet);
8407 8 : }
8408 :
8409 83104 : void DocxAttributeOutput::AddToAttrList( ::sax_fastparser::FastAttributeList* &pAttrList, sal_Int32 nAttrName, const sal_Char* sAttrValue )
8410 : {
8411 83104 : AddToAttrList( pAttrList, 1, nAttrName, sAttrValue );
8412 83104 : }
8413 :
8414 106588 : void DocxAttributeOutput::AddToAttrList( ::sax_fastparser::FastAttributeList* &pAttrList, sal_Int32 nAttrs, ... )
8415 : {
8416 106588 : if( !pAttrList )
8417 47228 : pAttrList = m_pSerializer->createAttrList();
8418 :
8419 : va_list args;
8420 106588 : va_start( args, nAttrs );
8421 239450 : for( sal_Int32 i = 0; i<nAttrs; i++)
8422 : {
8423 132862 : sal_Int32 nName = va_arg( args, sal_Int32 );
8424 132862 : const char* pValue = va_arg( args, const char* );
8425 132862 : if( pValue && !pAttrList->hasAttribute(nName) )
8426 132694 : pAttrList->add( nName, pValue );
8427 : }
8428 106588 : va_end( args );
8429 106588 : }
8430 :
8431 1056 : void DocxAttributeOutput::SetStartedParaSdt(bool bStartedParaSdt)
8432 : {
8433 1056 : m_bStartedParaSdt = bStartedParaSdt;
8434 1056 : }
8435 :
8436 528 : bool DocxAttributeOutput::IsStartedParaSdt()
8437 : {
8438 528 : return m_bStartedParaSdt;
8439 102 : }
8440 :
8441 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|