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