1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "docxattributeoutput.hxx"
25 #include "docxexport.hxx"
26 #include "docxfootnotes.hxx"
27 #include "writerwordglue.hxx"
28 #include "wrtww8.hxx"
29 #include "ww8par.hxx"
30 
31 #include <oox/token/tokens.hxx>
32 #include <oox/export/drawingml.hxx>
33 #include <oox/export/utils.hxx>
34 #include <oox/export/vmlexport.hxx>
35 
36 #include <i18npool/mslangid.hxx>
37 
38 #include <hintids.hxx>
39 
40 #include <svl/poolitem.hxx>
41 
42 #include <editeng/fontitem.hxx>
43 #include <editeng/tstpitem.hxx>
44 #include <editeng/adjitem.hxx>
45 #include <editeng/spltitem.hxx>
46 #include <editeng/widwitem.hxx>
47 #include <editeng/lspcitem.hxx>
48 #include <editeng/keepitem.hxx>
49 #include <editeng/shaditem.hxx>
50 #include <editeng/brshitem.hxx>
51 #include <editeng/postitem.hxx>
52 #include <editeng/wghtitem.hxx>
53 #include <editeng/kernitem.hxx>
54 #include <editeng/crsditem.hxx>
55 #include <editeng/cmapitem.hxx>
56 #include <editeng/wrlmitem.hxx>
57 #include <editeng/udlnitem.hxx>
58 #include <editeng/langitem.hxx>
59 #include <editeng/escpitem.hxx>
60 #include <editeng/fhgtitem.hxx>
61 #include <editeng/colritem.hxx>
62 #include <editeng/hyznitem.hxx>
63 #include <editeng/brkitem.hxx>
64 #include <editeng/lrspitem.hxx>
65 #include <editeng/ulspitem.hxx>
66 #include <editeng/boxitem.hxx>
67 #include <editeng/cntritem.hxx>
68 #include <editeng/shdditem.hxx>
69 #include <editeng/akrnitem.hxx>
70 #include <editeng/pbinitem.hxx>
71 #include <editeng/emphitem.hxx>
72 #include <editeng/twolinesitem.hxx>
73 #include <editeng/charscaleitem.hxx>
74 #include <editeng/charrotateitem.hxx>
75 #include <editeng/charreliefitem.hxx>
76 #include <editeng/paravertalignitem.hxx>
77 #include <editeng/pgrditem.hxx>
78 #include <editeng/frmdiritem.hxx>
79 #include <editeng/blnkitem.hxx>
80 #include <editeng/charhiddenitem.hxx>
81 #include <svx/svdmodel.hxx>
82 #include <svx/svdobj.hxx>
83 
84 #include <docufld.hxx>
85 #include <flddropdown.hxx>
86 #include <format.hxx>
87 #include <fmtclds.hxx>
88 #include <fmtinfmt.hxx>
89 #include <fmtfld.hxx>
90 #include <fmtfsize.hxx>
91 #include <fmtftn.hxx>
92 #include <fmtrowsplt.hxx>
93 #include <fmtline.hxx>
94 #include <frmfmt.hxx>
95 #include <frmatr.hxx>
96 #include <ftninfo.hxx>
97 #include <htmltbl.hxx>
98 #include <ndgrf.hxx>
99 #include <ndtxt.hxx>
100 #include <node.hxx>
101 #include <pagedesc.hxx>
102 #include <paratr.hxx>
103 #include <swmodule.hxx>
104 #include <swtable.hxx>
105 #include <txtftn.hxx>
106 #include <txtinet.hxx>
107 #include <numrule.hxx>
108 
109 #include <rtl/strbuf.hxx>
110 #include <rtl/ustrbuf.hxx>
111 #include <rtl/ustring.hxx>
112 
113 #include <tools/color.hxx>
114 
115 #include <com/sun/star/i18n/ScriptType.hdl>
116 
117 #if OSL_DEBUG_LEVEL > 0
118 #include <stdio.h>
119 #endif
120 
121 using rtl::OString;
122 using rtl::OStringBuffer;
123 using rtl::OUString;
124 using rtl::OUStringBuffer;
125 using rtl::OUStringToOString;
126 
127 using namespace oox;
128 using namespace docx;
129 using namespace sax_fastparser;
130 using namespace nsSwDocInfoSubType;
131 using namespace nsFieldFlags;
132 using namespace sw::util;
133 
RTLAndCJKState(bool bIsRTL,sal_uInt16)134 void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
135 {
136     if (bIsRTL)
137         m_pSerializer->singleElementNS( XML_w, XML_rtl, FSNS( XML_w, XML_val ), "true", FSEND );
138 }
139 
StartParagraph(ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo)140 void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
141 {
142     if ( m_nColBreakStatus == COLBRK_POSTPONE )
143         m_nColBreakStatus = COLBRK_WRITE;
144 
145     // Output table/table row/table cell starts if needed
146     if ( pTextNodeInfo.get() )
147     {
148         sal_uInt32 nRow = pTextNodeInfo->getRow();
149         sal_uInt32 nCell = pTextNodeInfo->getCell();
150 
151         // New cell/row?
152         if ( m_nTableDepth > 0 && !m_bTableCellOpen )
153         {
154             ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) );
155             if ( pDeepInner->getCell() == 0 )
156                 StartTableRow( pDeepInner );
157 
158             StartTableCell( pDeepInner );
159         }
160 
161         if ( nRow == 0 && nCell == 0 )
162         {
163             // Do we have to start the table?
164             // [If we are at the right depth already, it means that we
165             // continue the table cell]
166             sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
167 
168             if ( nCurrentDepth > m_nTableDepth )
169             {
170                 // Start all the tables that begin here
171                 for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
172                 {
173                     ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
174 
175                     StartTable( pInner );
176                     StartTableRow( pInner );
177                     StartTableCell( pInner );
178                 }
179 
180                 m_nTableDepth = nCurrentDepth;
181             }
182         }
183     }
184 
185     m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
186 
187     // postpone the output of the run (we get it before the paragraph
188     // properties, but must write it after them)
189     m_pSerializer->mark();
190 
191     // no section break in this paragraph yet; can be set in SectionBreak()
192     m_pSectionInfo = NULL;
193 
194     m_bParagraphOpened = true;
195 }
196 
EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner)197 void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
198 {
199     // write the paragraph properties + the run, already in the correct order
200     m_pSerializer->mergeTopMarks();
201     m_pSerializer->endElementNS( XML_w, XML_p );
202 
203     // Check for end of cell, rows, tables here
204     FinishTableRowCell( pTextNodeInfoInner );
205 
206     m_bParagraphOpened = false;
207 }
208 
FinishTableRowCell(ww8::WW8TableNodeInfoInner::Pointer_t pInner,bool bForceEmptyParagraph)209 void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
210 {
211     if ( pInner.get() )
212     {
213         // Where are we in the table
214         sal_uInt32 nRow = pInner->getRow( );
215 
216         const SwTable *pTable = pInner->getTable( );
217         const SwTableLines& rLines = pTable->GetTabLines( );
218         sal_uInt16 nLinesCount = rLines.Count( );
219 
220         if ( pInner->isEndOfCell() )
221         {
222             if ( bForceEmptyParagraph )
223                 m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
224 
225             EndTableCell();
226         }
227 
228         // This is a line end
229         if ( pInner->isEndOfLine() )
230             EndTableRow();
231 
232         // This is the end of the table
233         if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
234             EndTable();
235     }
236 }
237 
EmptyParagraph()238 void DocxAttributeOutput::EmptyParagraph()
239 {
240     m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
241 }
242 
StartParagraphProperties(const SwTxtNode & rNode)243 void DocxAttributeOutput::StartParagraphProperties( const SwTxtNode& rNode )
244 {
245     // output page/section breaks
246     // Writer can have them at the beginning of a paragraph, or at the end, but
247     // in docx, we have to output them in the paragraph properties of the last
248     // paragraph in a section. To get it right, we have to switch to the next
249     // paragraph, and detect the section breaks there.
250     SwNodeIndex aNextIndex( rNode, 1 );
251     if ( aNextIndex.GetNode().IsTxtNode() )
252     {
253         const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
254         m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode );
255     }
256     else if ( aNextIndex.GetNode().IsTableNode() )
257     {
258         const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
259         const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
260         m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
261     }
262 
263     // postpone the output so that we can later [in EndParagraphProperties()]
264     // prepend the properties before the run
265     m_pSerializer->mark();
266 
267     m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
268 
269     // and output the section break now (if it appeared)
270     if ( m_pSectionInfo )
271     {
272         m_rExport.SectionProperties( *m_pSectionInfo );
273         m_pSectionInfo = NULL;
274     }
275 
276     InitCollectedParagraphProperties();
277 }
278 
InitCollectedParagraphProperties()279 void DocxAttributeOutput::InitCollectedParagraphProperties()
280 {
281     m_pSpacingAttrList = NULL;
282 }
283 
WriteCollectedParagraphProperties()284 void DocxAttributeOutput::WriteCollectedParagraphProperties()
285 {
286     if ( m_pSpacingAttrList )
287     {
288         XFastAttributeListRef xAttrList( m_pSpacingAttrList );
289         m_pSpacingAttrList = NULL;
290 
291         m_pSerializer->singleElementNS( XML_w, XML_spacing, xAttrList );
292     }
293 }
294 
EndParagraphProperties()295 void DocxAttributeOutput::EndParagraphProperties()
296 {
297     WriteCollectedParagraphProperties();
298 
299     m_pSerializer->endElementNS( XML_w, XML_pPr );
300 
301     if ( m_nColBreakStatus == COLBRK_WRITE )
302     {
303         m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
304         m_pSerializer->singleElementNS( XML_w, XML_br,
305                 FSNS( XML_w, XML_type ), "column", FSEND );
306         m_pSerializer->endElementNS( XML_w, XML_r );
307 
308         m_nColBreakStatus = COLBRK_NONE;
309     }
310 
311     // merge the properties _before_ the run (strictly speaking, just
312     // after the start of the paragraph)
313     m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
314 }
315 
StartRun(const SwRedlineData * pRedlineData)316 void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData )
317 {
318     // if there is some redlining in the document, output it
319     StartRedline( pRedlineData );
320 
321     // postpone the output of the start of a run (there are elements that need
322     // to be written before the start of the run, but we learn which they are
323     // _inside_ of the run)
324     m_pSerializer->mark(); // let's call it "postponed run start"
325 
326     // postpone the output of the text (we get it before the run properties,
327     // but must write it after them)
328     m_pSerializer->mark(); // let's call it "postponed text"
329 }
330 
EndRun()331 void DocxAttributeOutput::EndRun()
332 {
333     // Write field starts
334     for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt )
335     {
336         // Add the fields starts for all but hyperlinks and TOCs
337         if ( pIt->bOpen && pIt->pField )
338         {
339             StartField_Impl( *pIt );
340 
341             // Remove the field from the stack if only the start has to be written
342             // Unknown fields should be removed too
343             if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) )
344             {
345                 m_Fields.erase( pIt );
346                 --pIt;
347             }
348         }
349     }
350 
351 
352     // write the run properties + the text, already in the correct order
353     m_pSerializer->mergeTopMarks(); // merges with "postponed text", see above
354 
355     // level down, to be able to prepend the actual run start attribute (just
356     // before "postponed run start")
357     m_pSerializer->mark(); // let's call it "actual run start"
358 
359     // prepend the actual run start
360     if ( m_pHyperlinkAttrList )
361     {
362         XFastAttributeListRef xAttrList ( m_pHyperlinkAttrList );
363 
364         m_pSerializer->startElementNS( XML_w, XML_hyperlink, xAttrList );
365     }
366 
367     // Write the hyperlink and toc fields starts
368     for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt )
369     {
370         // Add the fields starts for hyperlinks, TOCs and index marks
371         if ( pIt->bOpen )
372         {
373             StartField_Impl( *pIt, sal_True );
374 
375             // Remove the field if no end needs to be written
376             if ( !pIt->bClose ) {
377                 m_Fields.erase( pIt );
378                 --pIt;
379             }
380         }
381     }
382 
383     DoWriteBookmarks( );
384     WriteCommentRanges();
385 
386     m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
387     m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); // merges with "postponed run start", see above
388 
389     // write the run start + the run content
390     m_pSerializer->mergeTopMarks(); // merges the "actual run start"
391 
392     // append the actual run end
393     m_pSerializer->endElementNS( XML_w, XML_r );
394 
395     if ( m_pHyperlinkAttrList )
396     {
397         m_pSerializer->endElementNS( XML_w, XML_hyperlink );
398         m_pHyperlinkAttrList = NULL;
399     }
400 
401     while ( m_Fields.begin() != m_Fields.end() )
402     {
403         EndField_Impl( m_Fields.front( ) );
404         m_Fields.erase( m_Fields.begin( ) );
405     }
406 
407     // if there is some redlining in the document, output it
408     EndRedline();
409 }
410 
WriteCommentRanges()411 void DocxAttributeOutput::WriteCommentRanges()
412 {
413     if (m_bPostitStart)
414     {
415         m_bPostitStart = false;
416         OString idstr = OString::valueOf( sal_Int32( m_postitFieldsMaxId ));
417         m_pSerializer->singleElementNS( XML_w, XML_commentRangeStart, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND );
418     }
419     if (m_bPostitEnd)
420     {
421         m_bPostitEnd = false;
422         OString idstr = OString::valueOf( sal_Int32( m_postitFieldsMaxId ));
423         m_pSerializer->singleElementNS( XML_w, XML_commentRangeEnd, FSNS( XML_w, XML_id ), idstr.getStr(), FSEND );
424     }
425 }
426 
WritePostitFieldStart()427 void DocxAttributeOutput::WritePostitFieldStart()
428 {
429     m_bPostitStart = true;
430 }
431 
WritePostitFieldEnd()432 void DocxAttributeOutput::WritePostitFieldEnd()
433 {
434     m_bPostitEnd = true;
435 }
436 
437 
DoWriteBookmarks()438 void DocxAttributeOutput::DoWriteBookmarks()
439 {
440     // Write the start bookmarks
441     for ( std::vector< OString >::const_iterator it = m_rMarksStart.begin(), end = m_rMarksStart.end();
442           it < end; ++it )
443     {
444         const OString& rName = *it;
445 
446         // Output the bookmark
447         sal_uInt16 nId = m_nNextMarkId++;
448         m_rOpenedMarksIds[rName] = nId;
449         m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
450             FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr(  ),
451             FSNS( XML_w, XML_name ), rName.getStr(),
452             FSEND );
453     }
454     m_rMarksStart.clear();
455 
456     // export the end bookmarks
457     for ( std::vector< OString >::const_iterator it = m_rMarksEnd.begin(), end = m_rMarksEnd.end();
458           it < end; ++it )
459     {
460         const OString& rName = *it;
461 
462         // Get the id of the bookmark
463         std::map< OString, sal_uInt16 >::iterator pPos = m_rOpenedMarksIds.find( rName );
464         if ( pPos != m_rOpenedMarksIds.end(  ) )
465         {
466             sal_uInt16 nId = ( *pPos ).second;
467             m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
468                 FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr(  ),
469                 FSEND );
470             m_rOpenedMarksIds.erase( rName );
471         }
472     }
473     m_rMarksEnd.clear();
474 }
475 
StartField_Impl(FieldInfos & rInfos,sal_Bool bWriteRun)476 void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, sal_Bool bWriteRun )
477 {
478     if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
479     {
480         // Expand unsupported fields
481         RunText( rInfos.pField->Expand( ) );
482     }
483     else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
484     {
485         if ( bWriteRun )
486             m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
487 
488         if ( rInfos.eType == ww::eFORMDROPDOWN )
489         {
490                 m_pSerializer->startElementNS( XML_w, XML_fldChar,
491                     FSNS( XML_w, XML_fldCharType ), "begin",
492                     FSEND );
493 
494                 const SwDropDownField& rFld2 = *(SwDropDownField*)rInfos.pField;
495                 uno::Sequence<rtl::OUString> aItems =
496                     rFld2.GetItemSequence();
497                 GetExport().DoComboBox(rFld2.GetName(),
498                            rFld2.GetHelp(),
499                            rFld2.GetToolTip(),
500                            rFld2.GetSelectedItem(), aItems);
501 
502                 m_pSerializer->endElementNS( XML_w, XML_fldChar );
503 
504                 if ( bWriteRun )
505                     m_pSerializer->endElementNS( XML_w, XML_r );
506 
507         }
508         else
509         {
510             // Write the field start
511             m_pSerializer->singleElementNS( XML_w, XML_fldChar,
512                 FSNS( XML_w, XML_fldCharType ), "begin",
513                 FSEND );
514 
515             if ( bWriteRun )
516                 m_pSerializer->endElementNS( XML_w, XML_r );
517 
518             // The hyperlinks fields can't be expanded: the value is
519             // normally in the text run
520             if ( !rInfos.pField )
521                 CmdField_Impl( rInfos );
522         }
523     }
524 }
525 
DoWriteCmd(String & rCmd)526 void DocxAttributeOutput::DoWriteCmd( String& rCmd )
527 {
528     // Write the Field command
529     m_pSerializer->startElementNS( XML_w, XML_instrText, FSEND );
530     m_pSerializer->writeEscaped( OUString( rCmd ) );
531     m_pSerializer->endElementNS( XML_w, XML_instrText );
532 
533 }
534 
CmdField_Impl(FieldInfos & rInfos)535 void DocxAttributeOutput::CmdField_Impl( FieldInfos& rInfos )
536 {
537     m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
538     xub_StrLen nNbToken = rInfos.sCmd.GetTokenCount( '\t' );
539 
540     for ( xub_StrLen i = 0; i < nNbToken; i++ )
541     {
542         String sToken = rInfos.sCmd.GetToken( i, '\t' );
543         // Write the Field command
544         DoWriteCmd( sToken );
545 
546         // Replace tabs by </instrText><tab/><instrText>
547         if ( i < ( nNbToken - 1 ) )
548             RunText( String::CreateFromAscii( "\t" ) );
549     }
550 
551     m_pSerializer->endElementNS( XML_w, XML_r );
552 
553 
554     // Write the Field separator
555     m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
556     m_pSerializer->singleElementNS( XML_w, XML_fldChar,
557           FSNS( XML_w, XML_fldCharType ), "separate",
558           FSEND );
559     m_pSerializer->endElementNS( XML_w, XML_r );
560 }
561 
EndField_Impl(FieldInfos & rInfos)562 void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
563 {
564     // The command has to be written before for the hyperlinks
565     if ( rInfos.pField )
566     {
567         CmdField_Impl( rInfos );
568     }
569 
570     // Write the bookmark start if any
571     OUString aBkmName( m_sFieldBkm );
572     if ( aBkmName.getLength( ) > 0 )
573     {
574         m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
575                FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
576                FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
577                FSEND );
578     }
579 
580     if (rInfos.pField ) // For hyperlinks and TOX
581     {
582         // Write the Field latest value
583         m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
584 
585         // Find another way for hyperlinks
586         RunText( rInfos.pField->Expand( ) );
587         m_pSerializer->endElementNS( XML_w, XML_r );
588     }
589 
590     // Write the bookmark end if any
591     if ( aBkmName.getLength( ) > 0 )
592     {
593         m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
594                FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
595                FSEND );
596 
597         m_nNextMarkId++;
598     }
599 
600     // Write the Field end
601     m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
602     m_pSerializer->singleElementNS( XML_w, XML_fldChar,
603           FSNS( XML_w, XML_fldCharType ), "end",
604           FSEND );
605     m_pSerializer->endElementNS( XML_w, XML_r );
606 
607 
608     // Write the ref field if a bookmark had to be set and the field
609     // should be visible
610     if ( rInfos.pField )
611     {
612         sal_uInt16 nSubType = rInfos.pField->GetSubType( );
613         bool bIsSetField = rInfos.pField->GetTyp( )->Which( ) == RES_SETEXPFLD;
614         bool bShowRef = ( !bIsSetField || ( nSubType & nsSwExtendedSubType::SUB_INVISIBLE ) ) ? false : true;
615 
616         if ( ( m_sFieldBkm.Len( ) > 0 ) && bShowRef )
617         {
618             // Write the field beginning
619             m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
620             m_pSerializer->singleElementNS( XML_w, XML_fldChar,
621                 FSNS( XML_w, XML_fldCharType ), "begin",
622                 FSEND );
623             m_pSerializer->endElementNS( XML_w, XML_r );
624 
625             rInfos.sCmd = FieldString( ww::eREF );
626             rInfos.sCmd.APPEND_CONST_ASC( "\"" );
627             rInfos.sCmd += m_sFieldBkm;
628             rInfos.sCmd.APPEND_CONST_ASC( "\" " );
629 
630             // Clean the field bookmark data to avoid infinite loop
631             m_sFieldBkm = String( );
632 
633             // Write the end of the field
634             EndField_Impl( rInfos );
635         }
636     }
637 }
638 
StartRunProperties()639 void DocxAttributeOutput::StartRunProperties()
640 {
641     // postpone the output so that we can later [in EndRunProperties()]
642     // prepend the properties before the text
643     m_pSerializer->mark();
644 
645     m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
646 
647     InitCollectedRunProperties();
648 }
649 
InitCollectedRunProperties()650 void DocxAttributeOutput::InitCollectedRunProperties()
651 {
652     m_pFontsAttrList = NULL;
653     m_pEastAsianLayoutAttrList = NULL;
654     m_pCharLangAttrList = NULL;
655 }
656 
WriteCollectedRunProperties()657 void DocxAttributeOutput::WriteCollectedRunProperties()
658 {
659     // Write all differed properties
660     if ( m_pFontsAttrList )
661     {
662         XFastAttributeListRef xAttrList( m_pFontsAttrList );
663         m_pFontsAttrList = NULL;
664 
665         m_pSerializer->singleElementNS( XML_w, XML_rFonts, xAttrList );
666     }
667 
668     if ( m_pEastAsianLayoutAttrList )
669     {
670         XFastAttributeListRef xAttrList( m_pEastAsianLayoutAttrList );
671         m_pEastAsianLayoutAttrList = NULL;
672 
673         m_pSerializer->singleElementNS( XML_w, XML_eastAsianLayout, xAttrList );
674     }
675 
676     if ( m_pCharLangAttrList )
677     {
678         XFastAttributeListRef xAttrList( m_pCharLangAttrList );
679         m_pCharLangAttrList = NULL;
680 
681         m_pSerializer->singleElementNS( XML_w, XML_lang, xAttrList );
682     }
683 }
684 
EndRunProperties(const SwRedlineData *)685 void DocxAttributeOutput::EndRunProperties( const SwRedlineData* /*pRedlineData*/ )
686 {
687     WriteCollectedRunProperties();
688 
689     m_pSerializer->endElementNS( XML_w, XML_rPr );
690 
691     // write footnotes/endnotes if we have any
692     FootnoteEndnoteReference();
693 
694     // merge the properties _before_ the run text (strictly speaking, just
695     // after the start of the run)
696     m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
697 }
698 
699 /** Output sal_Unicode* as a run text (<t>the text</t>).
700 
701     When bMove is true, update rBegin to point _after_ the end of the text +
702     1, meaning that it skips one character after the text. This is to make
703     the switch in DocxAttributeOutput::RunText() nicer ;-)
704  */
impl_WriteRunText(FSHelperPtr pSerializer,sal_Int32 nTextToken,const sal_Unicode * & rBegin,const sal_Unicode * pEnd,bool bMove=true)705 static void impl_WriteRunText( FSHelperPtr pSerializer, sal_Int32 nTextToken,
706         const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true )
707 {
708     const sal_Unicode *pBegin = rBegin;
709 
710     // skip one character after the end
711     if ( bMove )
712         rBegin = pEnd + 1;
713 
714     if ( pBegin >= pEnd )
715         return; // we want to write at least one character
716 
717     // we have to add 'preserve' when starting/ending with space
718     if ( *pBegin == sal_Unicode( ' ' ) || *( pEnd - 1 ) == sal_Unicode( ' ' ) )
719     {
720         pSerializer->startElementNS( XML_w, nTextToken, FSNS( XML_xml, XML_space ), "preserve", FSEND );
721     }
722     else
723         pSerializer->startElementNS( XML_w, nTextToken, FSEND );
724 
725     pSerializer->writeEscaped( OUString( pBegin, pEnd - pBegin ) );
726 
727     pSerializer->endElementNS( XML_w, nTextToken );
728 }
729 
RunText(const String & rText,rtl_TextEncoding)730 void DocxAttributeOutput::RunText( const String& rText, rtl_TextEncoding /*eCharSet*/ )
731 {
732     OUString aText( rText );
733 
734     // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
735     const sal_Unicode *pBegin = aText.getStr();
736     const sal_Unicode *pEnd = pBegin + aText.getLength();
737 
738     // the text run is usually XML_t, with the exception of the deleted text
739     sal_Int32 nTextToken = XML_t;
740     if ( m_pRedlineData && m_pRedlineData->GetType() == nsRedlineType_t::REDLINE_DELETE )
741         nTextToken = XML_delText;
742 
743     for ( const sal_Unicode *pIt = pBegin; pIt < pEnd; ++pIt )
744     {
745         switch ( *pIt )
746         {
747             case 0x09: // tab
748                 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
749                 m_pSerializer->singleElementNS( XML_w, XML_tab, FSEND );
750                 break;
751             case 0x0b: // line break
752                 impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
753                 m_pSerializer->singleElementNS( XML_w, XML_br, FSEND );
754                 break;
755             default:
756                 if ( *pIt < 0x0020 ) // filter out the control codes
757                 {
758                     impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
759                     OSL_TRACE( "Ignored control code %x in a text run.", *pIt );
760                 }
761                 break;
762         }
763     }
764 
765     impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
766 }
767 
RawText(const String &,bool,rtl_TextEncoding)768 void DocxAttributeOutput::RawText( const String& /*rText*/, bool /*bForceUnicode*/, rtl_TextEncoding /*eCharSet*/ )
769 {
770     OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )\n" );
771 }
772 
StartRuby(const SwTxtNode &,const SwFmtRuby &)773 void DocxAttributeOutput::StartRuby( const SwTxtNode& /*rNode*/, const SwFmtRuby& /*rRuby*/ )
774 {
775     OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )\n" );
776 }
777 
EndRuby()778 void DocxAttributeOutput::EndRuby()
779 {
780     OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()\n" );
781 }
782 
AnalyzeURL(const String & rUrl,const String & rTarget,String * pLinkURL,String * pMark)783 bool DocxAttributeOutput::AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark )
784 {
785     bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
786 
787     String sURL = *pLinkURL;
788     String sMark = *pMark;
789 
790     bool bOutputField = sMark.Len();
791 
792     if ( bOutputField )
793     {
794         if ( bBookMarkOnly )
795             sURL = FieldString( ww::eHYPERLINK );
796         else
797         {
798             String sFld( FieldString( ww::eHYPERLINK ) );
799             sFld.APPEND_CONST_ASC( "\"" );
800             sURL.Insert( sFld, 0 );
801             sURL += '\"';
802         }
803 
804         if ( sMark.Len() )
805             ( ( sURL.APPEND_CONST_ASC( " \\l \"" ) ) += sMark ) += '\"';
806 
807         if ( rTarget.Len() )
808             ( sURL.APPEND_CONST_ASC( " \\n " ) ) += rTarget;
809     }
810 
811     *pLinkURL = sURL;
812     *pMark = sMark;
813 
814     return bBookMarkOnly;
815 }
816 
StartURL(const String & rUrl,const String & rTarget)817 bool DocxAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
818 {
819     String sMark;
820     String sUrl;
821 
822     bool bBookmarkOnly = AnalyzeURL( rUrl, rTarget, &sUrl, &sMark );
823 
824     if ( sMark.Len() && !bBookmarkOnly )
825     {
826         m_rExport.OutputField( NULL, ww::eHYPERLINK, sUrl );
827     }
828     else
829     {
830         // Output a hyperlink XML element
831 
832         m_pHyperlinkAttrList = m_pSerializer->createAttrList();
833         if ( !bBookmarkOnly )
834         {
835             OUString osUrl( sUrl );
836 
837             ::rtl::OString sId = m_rExport.AddRelation(
838                 S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
839                 osUrl, S("External") );
840             m_pHyperlinkAttrList->add( FSNS( XML_r, XML_id), sId.getStr());
841         }
842         else
843             m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ),
844                     OUStringToOString( OUString( sMark ), RTL_TEXTENCODING_UTF8 ).getStr( ) );
845 
846         OUString sTarget( rTarget );
847         if ( sTarget.getLength( ) > 0 )
848         {
849             OString soTarget = OUStringToOString( sTarget, RTL_TEXTENCODING_UTF8 );
850             m_pHyperlinkAttrList->add(FSNS( XML_w, XML_tgtFrame ), soTarget.getStr());
851         }
852     }
853 
854     return true;
855 }
856 
EndURL()857 bool DocxAttributeOutput::EndURL()
858 {
859     return true;
860 }
861 
FieldVanish(const String & rTxt,ww::eField eType)862 void DocxAttributeOutput::FieldVanish( const String& rTxt, ww::eField eType )
863 {
864     WriteField_Impl( NULL, eType, rTxt, WRITEFIELD_ALL );
865 }
866 
Redline(const SwRedlineData *)867 void DocxAttributeOutput::Redline( const SwRedlineData* /*pRedline*/ )
868 {
869     OSL_TRACE( "TODO DocxAttributeOutput::Redline( const SwRedlineData* pRedline )\n" );
870 }
871 
872 /// Append the number as 2-digit when less than 10.
impl_AppendTwoDigits(OStringBuffer & rBuffer,sal_Int32 nNum)873 static void impl_AppendTwoDigits( OStringBuffer &rBuffer, sal_Int32 nNum )
874 {
875     if ( nNum < 0 || nNum > 99 )
876     {
877         rBuffer.append( "00" );
878         return;
879     }
880 
881     if ( nNum < 10 )
882         rBuffer.append( '0' );
883 
884     rBuffer.append( nNum );
885 }
886 
887 /** Convert DateTime to xsd::dateTime string.
888 
889 I guess there must be an implementation of this somewhere in AOO, but I failed
890 to find it, unfortunately :-(
891 */
impl_DateTimeToOString(const DateTime & rDateTime)892 static OString impl_DateTimeToOString( const DateTime& rDateTime )
893 {
894     DateTime aInUTC( rDateTime );
895     aInUTC.ConvertToUTC();
896 
897     OStringBuffer aBuffer( 25 );
898     aBuffer.append( sal_Int32( aInUTC.GetYear() ) );
899     aBuffer.append( '-' );
900 
901     impl_AppendTwoDigits( aBuffer, aInUTC.GetMonth() );
902     aBuffer.append( '-' );
903 
904     impl_AppendTwoDigits( aBuffer, aInUTC.GetDay() );
905     aBuffer.append( 'T' );
906 
907     impl_AppendTwoDigits( aBuffer, aInUTC.GetHour() );
908     aBuffer.append( ':' );
909 
910     impl_AppendTwoDigits( aBuffer, aInUTC.GetMin() );
911     aBuffer.append( ':' );
912 
913     impl_AppendTwoDigits( aBuffer, aInUTC.GetSec() );
914     aBuffer.append( 'Z' ); // we are in UTC
915 
916     return aBuffer.makeStringAndClear();
917 }
918 
StartRedline(const SwRedlineData * pRedlineData)919 void DocxAttributeOutput::StartRedline( const SwRedlineData* pRedlineData )
920 {
921     m_pRedlineData = pRedlineData;
922 
923     if ( !m_pRedlineData )
924         return;
925 
926     // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
927 
928     OString aId( OString::valueOf( m_nRedlineId++ ) );
929 
930     const String &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
931     OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
932 
933     OString aDate( impl_DateTimeToOString( pRedlineData->GetTimeStamp() ) );
934 
935     switch ( pRedlineData->GetType() )
936     {
937         case nsRedlineType_t::REDLINE_INSERT:
938             m_pSerializer->startElementNS( XML_w, XML_ins,
939                     FSNS( XML_w, XML_id ), aId.getStr(),
940                     FSNS( XML_w, XML_author ), aAuthor.getStr(),
941                     FSNS( XML_w, XML_date ), aDate.getStr(),
942                     FSEND );
943             break;
944 
945         case nsRedlineType_t::REDLINE_DELETE:
946             m_pSerializer->startElementNS( XML_w, XML_del,
947                     FSNS( XML_w, XML_id ), aId.getStr(),
948                     FSNS( XML_w, XML_author ), aAuthor.getStr(),
949                     FSNS( XML_w, XML_date ), aDate.getStr(),
950                     FSEND );
951             break;
952 
953         case nsRedlineType_t::REDLINE_FORMAT:
954             OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()\n" );
955         default:
956             break;
957     }
958 }
959 
EndRedline()960 void DocxAttributeOutput::EndRedline()
961 {
962     if ( !m_pRedlineData )
963         return;
964 
965     switch ( m_pRedlineData->GetType() )
966     {
967         case nsRedlineType_t::REDLINE_INSERT:
968             m_pSerializer->endElementNS( XML_w, XML_ins );
969             break;
970 
971         case nsRedlineType_t::REDLINE_DELETE:
972             m_pSerializer->endElementNS( XML_w, XML_del );
973             break;
974 
975         case nsRedlineType_t::REDLINE_FORMAT:
976             OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()\n" );
977             break;
978         default:
979             break;
980     }
981 
982     m_pRedlineData = NULL;
983 }
984 
FormatDrop(const SwTxtNode &,const SwFmtDrop &,sal_uInt16,ww8::WW8TableNodeInfo::Pointer_t,ww8::WW8TableNodeInfoInner::Pointer_t)985 void DocxAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
986 {
987     OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle )\n" );
988 }
989 
ParagraphStyle(sal_uInt16 nStyle)990 void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
991 {
992     OString aStyleId( "style" );
993     aStyleId += OString::valueOf( sal_Int32( nStyle ) );
994 
995     m_pSerializer->singleElementNS( XML_w, XML_pStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
996 }
997 
998 #if 0
999 void DocxAttributeOutput::InTable()
1000 {
1001 #if OSL_DEBUG_LEVEL > 0
1002     OSL_TRACE( "TODO DocxAttributeOutput::InTable()\n" );
1003 #endif
1004 }
1005 
1006 
1007 void DocxAttributeOutput::TableRowProperties( bool /*bHeader*/, long /*nCellHeight*/, bool /*bCannotSplit*/, bool /*bRightToLeft*/ )
1008 {
1009 #if OSL_DEBUG_LEVEL > 0
1010     OSL_TRACE( "TODO DocxAttributeOutput::TableRowProperties()\n" );
1011 #endif
1012 }
1013 #endif
1014 
impl_ConvertColor(const Color & rColor)1015 static OString impl_ConvertColor( const Color &rColor )
1016 {
1017     OString color( "auto" );
1018     if ( rColor.GetColor() != COL_AUTO )
1019     {
1020         const char pHexDigits[] = "0123456789ABCDEF";
1021         char pBuffer[] = "000000";
1022 
1023         pBuffer[0] = pHexDigits[ ( rColor.GetRed()   >> 4 ) & 0x0F ];
1024         pBuffer[1] = pHexDigits[   rColor.GetRed()          & 0x0F ];
1025         pBuffer[2] = pHexDigits[ ( rColor.GetGreen() >> 4 ) & 0x0F ];
1026         pBuffer[3] = pHexDigits[   rColor.GetGreen()        & 0x0F ];
1027         pBuffer[4] = pHexDigits[ ( rColor.GetBlue()  >> 4 ) & 0x0F ];
1028         pBuffer[5] = pHexDigits[   rColor.GetBlue()         & 0x0F ];
1029 
1030         color = OString( pBuffer );
1031     }
1032     return color;
1033 }
1034 
impl_borderLine(FSHelperPtr pSerializer,sal_Int32 elementToken,const SvxBorderLine * pBorderLine,sal_uInt16 nDist)1035 static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist )
1036 {
1037     FastAttributeList* pAttr = pSerializer->createAttrList();
1038 
1039     sal_uInt16 inW = pBorderLine->GetInWidth();
1040     sal_uInt16 outW = pBorderLine->GetOutWidth();
1041     sal_uInt16 nWidth = inW + outW;
1042 
1043     // Compute val attribute value
1044     // Can be one of:
1045     //      single, double,
1046     //      basicWideOutline, basicWideInline
1047     // OOXml also supports those types of borders, but we'll try to play with the first ones.
1048     //      thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
1049     //      thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
1050     const char* pVal = "single";
1051     if ( pBorderLine->isDouble() )
1052     {
1053         if ( inW == outW )
1054             pVal = ( sal_Char* )"double";
1055         else if ( inW > outW )
1056         {
1057             pVal = ( sal_Char* )"thinThickMediumGap";
1058         }
1059         else if ( inW < outW )
1060         {
1061             pVal = ( sal_Char* )"thickThinMediumGap";
1062         }
1063     }
1064 
1065     pAttr->add( FSNS( XML_w, XML_val ), OString( pVal ) );
1066 
1067     // Compute the sz attribute
1068 
1069     // The unit is the 8th of point
1070     nWidth = sal_Int32( nWidth / 2.5 );
1071     sal_uInt16 nMinWidth = 2;
1072     sal_uInt16 nMaxWidth = 96;
1073 
1074     if ( nWidth > nMaxWidth )
1075         nWidth = nMaxWidth;
1076     else if ( nWidth < nMinWidth )
1077         nWidth = nMinWidth;
1078 
1079     pAttr->add( FSNS( XML_w, XML_sz ), OString::valueOf( sal_Int32( nWidth ) ) );
1080 
1081     // Get the distance (in pt)
1082     pAttr->add( FSNS( XML_w, XML_space ), OString::valueOf( sal_Int32( nDist / 20 ) ) );
1083 
1084     // Get the color code as an RRGGBB hex value
1085     OString sColor( impl_ConvertColor( pBorderLine->GetColor( ) ) );
1086     pAttr->add( FSNS( XML_w, XML_color ), sColor );
1087 
1088     XFastAttributeListRef xAttrs( pAttr );
1089     pSerializer->singleElementNS( XML_w, elementToken, xAttrs );
1090 }
1091 
impl_pageBorders(FSHelperPtr pSerializer,const SvxBoxItem & rBox)1092 static void impl_pageBorders( FSHelperPtr pSerializer, const SvxBoxItem& rBox )
1093 {
1094     static const sal_uInt16 aBorders[] =
1095     {
1096         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
1097     };
1098 
1099     static const sal_uInt16 aXmlElements[] =
1100     {
1101         XML_top, XML_left, XML_bottom, XML_right
1102     };
1103     const sal_uInt16* pBrd = aBorders;
1104     for( int i = 0; i < 4; ++i, ++pBrd )
1105     {
1106         const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
1107         if ( pLn )
1108             impl_borderLine( pSerializer, aXmlElements[i], pLn, 0 );
1109     }
1110 }
1111 
TableCellProperties(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1112 void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1113 {
1114     m_pSerializer->startElementNS( XML_w, XML_tcPr, FSEND );
1115 
1116     const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
1117 
1118     // The cell borders
1119     m_pSerializer->startElementNS( XML_w, XML_tcBorders, FSEND );
1120     SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
1121     impl_pageBorders( m_pSerializer, pFmt->GetBox( ) );
1122     m_pSerializer->endElementNS( XML_w, XML_tcBorders );
1123 
1124     // Vertical merges
1125     long vSpan = pTblBox->getRowSpan( );
1126     if ( vSpan > 1 )
1127     {
1128         m_pSerializer->singleElementNS( XML_w, XML_vMerge,
1129                 FSNS( XML_w, XML_val ), "restart",
1130                 FSEND );
1131     }
1132     else if ( vSpan < 0 )
1133     {
1134         m_pSerializer->singleElementNS( XML_w, XML_vMerge,
1135                 FSNS( XML_w, XML_val ), "continue",
1136                 FSEND );
1137     }
1138 
1139     // Horizontal spans
1140     const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
1141     SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
1142     SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
1143 
1144     sal_uInt16 nColSpan = pCell->GetColSpan();
1145     if ( nColSpan > 1 )
1146         m_pSerializer->singleElementNS( XML_w, XML_gridSpan,
1147                 FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nColSpan ) ).getStr(),
1148                 FSEND );
1149 
1150     TableBackgrounds( pTableTextNodeInfoInner );
1151 
1152     // Cell preferred width
1153     SwTwips nWidth = GetGridCols( pTableTextNodeInfoInner )[ pTableTextNodeInfoInner->getCell() ];
1154     m_pSerializer->singleElementNS( XML_w, XML_tcW,
1155            FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nWidth ) ).getStr( ),
1156            FSNS( XML_w, XML_type ), "dxa",
1157            FSEND );
1158 
1159     // Cell margins
1160     m_pSerializer->startElementNS( XML_w, XML_tcMar, FSEND );
1161     const SvxBoxItem& rBox = pFmt->GetBox( );
1162     static const sal_uInt16 aBorders[] =
1163     {
1164         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
1165     };
1166 
1167     static const sal_uInt16 aXmlElements[] =
1168     {
1169         XML_top, XML_left, XML_bottom, XML_right
1170     };
1171     const sal_uInt16* pBrd = aBorders;
1172     for( int i = 0; i < 4; ++i, ++pBrd )
1173     {
1174         sal_Int32 nDist = sal_Int32( rBox.GetDistance( *pBrd ) );
1175         m_pSerializer->singleElementNS( XML_w, aXmlElements[i],
1176                FSNS( XML_w, XML_w ), OString::valueOf( nDist ).getStr( ),
1177                FSNS( XML_w, XML_type ), "dxa",
1178                FSEND );
1179     }
1180 
1181     m_pSerializer->endElementNS( XML_w, XML_tcMar );
1182 
1183     TableVerticalCell( pTableTextNodeInfoInner );
1184 
1185     m_pSerializer->endElementNS( XML_w, XML_tcPr );
1186 }
1187 
InitTableHelper(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1188 void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1189 {
1190     sal_uInt32 nPageSize = 0;
1191     bool bRelBoxSize = false;
1192 
1193     // Create the SwWriteTable instance to use col spans (and maybe other infos)
1194     GetTablePageSize( pTableTextNodeInfoInner, nPageSize, bRelBoxSize );
1195 
1196     const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
1197     const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
1198     SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
1199 
1200     const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
1201     if( pLayout && pLayout->IsExportable() )
1202         m_pTableWrt = new SwWriteTable( pLayout );
1203     else
1204         m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
1205                 (sal_uInt16)nTblSz, false);
1206 }
1207 
StartTable(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1208 void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1209 {
1210     m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND );
1211 
1212     InitTableHelper( pTableTextNodeInfoInner );
1213     TableDefinition( pTableTextNodeInfoInner );
1214 }
1215 
EndTable()1216 void DocxAttributeOutput::EndTable()
1217 {
1218     m_pSerializer->endElementNS( XML_w, XML_tbl );
1219 
1220     if ( m_nTableDepth > 0 )
1221         --m_nTableDepth;
1222 
1223     // We closed the table; if it is a nested table, the cell that contains it
1224     // still continues
1225     m_bTableCellOpen = true;
1226 
1227     // Cleans the table helper
1228     delete m_pTableWrt, m_pTableWrt = NULL;
1229 }
1230 
StartTableRow(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1231 void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1232 {
1233     m_pSerializer->startElementNS( XML_w, XML_tr, FSEND );
1234 
1235     // Output the row properties
1236     m_pSerializer->startElementNS( XML_w, XML_trPr, FSEND );
1237 
1238     // Header row: tblHeader
1239     const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
1240     if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
1241         m_pSerializer->singleElementNS( XML_w, XML_tblHeader,
1242                FSNS( XML_w, XML_val ), "true",
1243                FSEND );
1244 
1245     TableHeight( pTableTextNodeInfoInner );
1246     TableCanSplit( pTableTextNodeInfoInner );
1247 
1248     m_pSerializer->endElementNS( XML_w, XML_trPr );
1249 }
1250 
EndTableRow()1251 void DocxAttributeOutput::EndTableRow( )
1252 {
1253     m_pSerializer->endElementNS( XML_w, XML_tr );
1254 }
1255 
1256 
StartTableCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1257 void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1258 {
1259     if ( !m_pTableWrt )
1260         InitTableHelper( pTableTextNodeInfoInner );
1261 
1262     m_pSerializer->startElementNS( XML_w, XML_tc, FSEND );
1263 
1264     // Write the cell properties here
1265     TableCellProperties( pTableTextNodeInfoInner );
1266 
1267     m_bTableCellOpen = true;
1268 }
1269 
EndTableCell()1270 void DocxAttributeOutput::EndTableCell( )
1271 {
1272     m_pSerializer->endElementNS( XML_w, XML_tc );
1273 
1274     m_bTableCellOpen = false;
1275 }
1276 
TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t)1277 void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
1278 {
1279 }
1280 
TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t)1281 void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
1282 {
1283 }
1284 
TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1285 void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1286 {
1287     // Write the table properties
1288     m_pSerializer->startElementNS( XML_w, XML_tblPr, FSEND );
1289 
1290     sal_uInt32 nPageSize = 0;
1291     bool bRelBoxSize = false;
1292 
1293     // Create the SwWriteTable instance to use col spans (and maybe other infos)
1294     GetTablePageSize( pTableTextNodeInfoInner, nPageSize, bRelBoxSize );
1295 
1296     // Output the table preferred width
1297     if ( nPageSize != 0 )
1298         m_pSerializer->singleElementNS( XML_w, XML_tblW,
1299                 FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nPageSize ) ).getStr( ),
1300                 FSNS( XML_w, XML_type ), "dxa",
1301                 FSEND );
1302 
1303     // Output the table borders
1304     TableDefaultBorders( pTableTextNodeInfoInner );
1305     TableBidi( pTableTextNodeInfoInner );
1306 
1307     // Output the table alignement
1308     const SwTable *pTable = pTableTextNodeInfoInner->getTable();
1309     SwFrmFmt *pTblFmt = pTable->GetFrmFmt( );
1310     const char* pJcVal;
1311     sal_Int32 nIndent = 0;
1312     switch ( pTblFmt->GetHoriOrient( ).GetHoriOrient( ) )
1313     {
1314         case text::HoriOrientation::CENTER:
1315             pJcVal = "center";
1316             break;
1317         case text::HoriOrientation::RIGHT:
1318             pJcVal = "right";
1319             break;
1320         default:
1321         case text::HoriOrientation::NONE:
1322         case text::HoriOrientation::LEFT_AND_WIDTH:
1323         {
1324             pJcVal = "left";
1325             nIndent = sal_Int32( pTblFmt->GetLRSpace( ).GetLeft( ) );
1326             break;
1327         }
1328     }
1329     m_pSerializer->singleElementNS( XML_w, XML_jc,
1330             FSNS( XML_w, XML_val ), pJcVal,
1331             FSEND );
1332 
1333     // Table indent
1334     if ( nIndent != 0 )
1335         m_pSerializer->singleElementNS( XML_w, XML_tblInd,
1336                 FSNS( XML_w, XML_w ), OString::valueOf( nIndent ).getStr( ),
1337                 FSNS( XML_w, XML_type ), "dxa",
1338                 FSEND );
1339 
1340     m_pSerializer->endElementNS( XML_w, XML_tblPr );
1341 
1342 
1343     // Write the table grid infos
1344     m_pSerializer->startElementNS( XML_w, XML_tblGrid, FSEND );
1345 
1346     std::vector<SwTwips> gridCols = GetGridCols( pTableTextNodeInfoInner );
1347     for ( std::vector<SwTwips>::const_iterator it = gridCols.begin(); it != gridCols.end(); ++it )
1348         m_pSerializer->singleElementNS( XML_w, XML_gridCol,
1349                FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( *it ) ).getStr( ),
1350                FSEND );
1351 
1352     m_pSerializer->endElementNS( XML_w, XML_tblGrid );
1353 }
1354 
TableDefaultBorders(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1355 void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1356 {
1357     const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1358     const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
1359 
1360     // the defaults of the table are taken from the top-left cell
1361     m_pSerializer->startElementNS( XML_w, XML_tblBorders, FSEND );
1362     impl_pageBorders( m_pSerializer, pFrmFmt->GetBox( ) );
1363     m_pSerializer->endElementNS( XML_w, XML_tblBorders );
1364 }
1365 
TableBackgrounds(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1366 void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1367 {
1368     const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
1369     const SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
1370     const SfxPoolItem *pI = NULL;
1371 
1372     Color aColor;
1373     if ( SFX_ITEM_ON == pFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
1374         aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
1375     else
1376         aColor = COL_AUTO;
1377 
1378         OString sColor = impl_ConvertColor( aColor );
1379         m_pSerializer->singleElementNS( XML_w, XML_shd,
1380                 FSNS( XML_w, XML_fill ), sColor.getStr( ),
1381                 FSEND );
1382 }
1383 
TableHeight(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1384 void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1385 {
1386     const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1387     const SwTableLine * pTabLine = pTabBox->GetUpper();
1388     const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
1389 
1390     const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
1391     if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
1392     {
1393         sal_Int32 nHeight = rLSz.GetHeight();
1394         const char *pRule = NULL;
1395 
1396         switch ( rLSz.GetHeightSizeType() )
1397         {
1398             case ATT_FIX_SIZE: pRule = "exact"; break;
1399             case ATT_MIN_SIZE: pRule = "atLeast"; break;
1400             default:           break;
1401         }
1402 
1403         if ( pRule )
1404             m_pSerializer->singleElementNS( XML_w, XML_trHeight,
1405                     FSNS( XML_w, XML_val ), OString::valueOf( nHeight ).getStr( ),
1406                     FSNS( XML_w, XML_hRule ), pRule,
1407                     FSEND );
1408     }
1409 }
1410 
TableCanSplit(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1411 void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1412 {
1413     const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1414     const SwTableLine * pTabLine = pTabBox->GetUpper();
1415     const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
1416 
1417     const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
1418     const char* pCantSplit = ( !rSplittable.GetValue( ) ) ? "on" : "off";
1419 
1420     m_pSerializer->singleElementNS( XML_w, XML_cantSplit,
1421            FSNS( XML_w, XML_val ), pCantSplit,
1422            FSEND );
1423 }
1424 
TableBidi(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1425 void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1426 {
1427     const SwTable * pTable = pTableTextNodeInfoInner->getTable();
1428     const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
1429 
1430     if ( m_rExport.TrueFrameDirection( *pFrmFmt ) == FRMDIR_HORI_RIGHT_TOP )
1431     {
1432         m_pSerializer->singleElementNS( XML_w, XML_bidiVisual,
1433                 FSNS( XML_w, XML_val ), "on",
1434                 FSEND );
1435     }
1436 }
1437 
TableVerticalCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)1438 void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
1439 {
1440     const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
1441     const SwFrmFmt *pFrmFmt = pTabBox->GetFrmFmt( );
1442 
1443     if ( FRMDIR_VERT_TOP_RIGHT == m_rExport.TrueFrameDirection( *pFrmFmt ) )
1444         m_pSerializer->singleElementNS( XML_w, XML_textDirection,
1445                FSNS( XML_w, XML_val ), "tbRl",
1446                FSEND );
1447 }
1448 
TableNodeInfo(ww8::WW8TableNodeInfo::Pointer_t)1449 void DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
1450 {
1451     OSL_TRACE( "TODO: DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )\n" );
1452 }
1453 
TableNodeInfoInner(ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner)1454 void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
1455 {
1456     // This is called when the nested table ends in a cell, and there's no
1457     // paragraph behind that; so we must check for the ends of cell, rows,
1458     // tables
1459     // ['true' to write an empty paragraph, MS Word insists on that]
1460     FinishTableRowCell( pNodeInfoInner, true );
1461 }
1462 
TableOrientation(ww8::WW8TableNodeInfoInner::Pointer_t)1463 void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
1464 {
1465     OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
1466 }
1467 
TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t)1468 void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
1469 {
1470 #if OSL_DEBUG_LEVEL > 0
1471     fprintf( stderr, "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
1472 #endif
1473 }
1474 
TableRowEnd(sal_uInt32)1475 void DocxAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
1476 {
1477     OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )\n" );
1478 }
1479 
StartStyles()1480 void DocxAttributeOutput::StartStyles()
1481 {
1482     m_pSerializer->startElementNS( XML_w, XML_styles,
1483             FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
1484             FSEND );
1485 }
1486 
EndStyles(sal_uInt16)1487 void DocxAttributeOutput::EndStyles( sal_uInt16 /*nNumberOfStyles*/ )
1488 {
1489     m_pSerializer->endElementNS( XML_w, XML_styles );
1490 }
1491 
DefaultStyle(sal_uInt16 nStyle)1492 void DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )
1493 {
1494     // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
1495 #if OSL_DEBUG_LEVEL > 0
1496     OSL_TRACE( "TODO DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )- %d\n", nStyle );
1497 #else
1498     (void) nStyle; // to quiet the warning
1499 #endif
1500 }
1501 
FlyFrameGraphic(const SwGrfNode & rGrfNode,const Size & rSize)1502 void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize )
1503 {
1504 #if OSL_DEBUG_LEVEL > 0
1505     OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize ) - some stuff still missing\n" );
1506 #endif
1507     // create the relation ID
1508     OString aRelId;
1509     sal_Int32 nImageType;
1510     if ( rGrfNode.IsLinkedFile() )
1511     {
1512         // linked image, just create the relation
1513         String aFileName;
1514         rGrfNode.GetFileFilterNms( &aFileName, 0 );
1515 
1516         // TODO Convert the file name to relative for better interoperability
1517 
1518         aRelId = m_rExport.AddRelation(
1519                     S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ),
1520                     OUString( aFileName ),
1521                     S( "External" ) );
1522 
1523         nImageType = XML_link;
1524     }
1525     else
1526     {
1527         // inline, we also have to write the image itself
1528         Graphic& rGraphic = const_cast< Graphic& >( rGrfNode.GetGrf() );
1529 
1530         m_rDrawingML.SetFS( m_pSerializer ); // to be sure that we write to the right stream
1531         OUString aImageId = m_rDrawingML.WriteImage( rGraphic );
1532 
1533         aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
1534 
1535         nImageType = XML_embed;
1536     }
1537 
1538     if ( aRelId.getLength() == 0 )
1539         return;
1540 
1541     m_pSerializer->startElementNS( XML_w, XML_drawing,
1542             FSEND );
1543     m_pSerializer->startElementNS( XML_wp, XML_inline,
1544             XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
1545             FSEND );
1546 
1547     // extent of the image
1548     OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
1549     OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
1550     m_pSerializer->singleElementNS( XML_wp, XML_extent,
1551             XML_cx, aWidth.getStr(),
1552             XML_cy, aHeight.getStr(),
1553             FSEND );
1554     // TODO - the right effectExtent, extent including the effect
1555     m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
1556             XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
1557             FSEND );
1558 
1559     // picture description
1560     // TODO the right image description
1561     m_pSerializer->startElementNS( XML_wp, XML_docPr,
1562             XML_id, "1",
1563             XML_name, "Picture",
1564             XML_descr, "A description...",
1565             FSEND );
1566     // TODO hyperlink
1567     // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
1568     //         FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
1569     //         FSNS( XML_r, XML_id ), "rId4",
1570     //         FSEND );
1571     m_pSerializer->endElementNS( XML_wp, XML_docPr );
1572 
1573     m_pSerializer->startElementNS( XML_wp, XML_cNvGraphicFramePr,
1574             FSEND );
1575     // TODO change aspect?
1576     m_pSerializer->singleElementNS( XML_a, XML_graphicFrameLocks,
1577             FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
1578             XML_noChangeAspect, "1",
1579             FSEND );
1580     m_pSerializer->endElementNS( XML_wp, XML_cNvGraphicFramePr );
1581 
1582     m_pSerializer->startElementNS( XML_a, XML_graphic,
1583             FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
1584             FSEND );
1585     m_pSerializer->startElementNS( XML_a, XML_graphicData,
1586             XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/picture",
1587             FSEND );
1588 
1589     m_pSerializer->startElementNS( XML_pic, XML_pic,
1590             FSNS( XML_xmlns, XML_pic ), "http://schemas.openxmlformats.org/drawingml/2006/picture",
1591             FSEND );
1592 
1593     m_pSerializer->startElementNS( XML_pic, XML_nvPicPr,
1594             FSEND );
1595     // TODO the right image description
1596     m_pSerializer->startElementNS( XML_pic, XML_cNvPr,
1597             XML_id, "0",
1598             XML_name, "Picture",
1599             XML_descr, "A description...",
1600             FSEND );
1601     // TODO hyperlink
1602     // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
1603     //     FSNS( XML_r, XML_id ), "rId4",
1604     //     FSEND );
1605     m_pSerializer->endElementNS( XML_pic, XML_cNvPr );
1606 
1607     m_pSerializer->startElementNS( XML_pic, XML_cNvPicPr,
1608             FSEND );
1609     // TODO change aspect?
1610     m_pSerializer->singleElementNS( XML_a, XML_picLocks,
1611             XML_noChangeAspect, "1", XML_noChangeArrowheads, "1",
1612             FSEND );
1613     m_pSerializer->endElementNS( XML_pic, XML_cNvPicPr );
1614     m_pSerializer->endElementNS( XML_pic, XML_nvPicPr );
1615 
1616     // the actual picture
1617     m_pSerializer->startElementNS( XML_pic, XML_blipFill,
1618             FSEND );
1619     m_pSerializer->singleElementNS( XML_a, XML_blip,
1620             FSNS( XML_r, nImageType ), aRelId.getStr(),
1621             FSEND );
1622     m_pSerializer->singleElementNS( XML_a, XML_srcRect,
1623             FSEND );
1624     m_pSerializer->startElementNS( XML_a, XML_stretch,
1625             FSEND );
1626     m_pSerializer->singleElementNS( XML_a, XML_fillRect,
1627             FSEND );
1628     m_pSerializer->endElementNS( XML_a, XML_stretch );
1629     m_pSerializer->endElementNS( XML_pic, XML_blipFill );
1630 
1631     // TODO setup the right values below
1632     m_pSerializer->startElementNS( XML_pic, XML_spPr,
1633             XML_bwMode, "auto",
1634             FSEND );
1635     m_pSerializer->startElementNS( XML_a, XML_xfrm,
1636             FSEND );
1637     m_pSerializer->singleElementNS( XML_a, XML_off,
1638             XML_x, "0", XML_y, "0",
1639             FSEND );
1640     m_pSerializer->singleElementNS( XML_a, XML_ext,
1641             XML_cx, aWidth.getStr(),
1642             XML_cy, aHeight.getStr(),
1643             FSEND );
1644     m_pSerializer->endElementNS( XML_a, XML_xfrm );
1645     m_pSerializer->startElementNS( XML_a, XML_prstGeom,
1646             XML_prst, "rect",
1647             FSEND );
1648     m_pSerializer->singleElementNS( XML_a, XML_avLst,
1649             FSEND );
1650     m_pSerializer->endElementNS( XML_a, XML_prstGeom );
1651     m_pSerializer->singleElementNS( XML_a, XML_noFill,
1652             FSEND );
1653     m_pSerializer->startElementNS( XML_a, XML_ln,
1654             XML_w, "9525",
1655             FSEND );
1656     m_pSerializer->singleElementNS( XML_a, XML_noFill,
1657             FSEND );
1658     m_pSerializer->singleElementNS( XML_a, XML_miter,
1659             XML_lim, "800000",
1660             FSEND );
1661     m_pSerializer->singleElementNS( XML_a, XML_headEnd,
1662             FSEND );
1663     m_pSerializer->singleElementNS( XML_a, XML_tailEnd,
1664             FSEND );
1665     m_pSerializer->endElementNS( XML_a, XML_ln );
1666     m_pSerializer->endElementNS( XML_pic, XML_spPr );
1667 
1668     m_pSerializer->endElementNS( XML_pic, XML_pic );
1669 
1670     m_pSerializer->endElementNS( XML_a, XML_graphicData );
1671     m_pSerializer->endElementNS( XML_a, XML_graphic );
1672     m_pSerializer->endElementNS( XML_wp, XML_inline );
1673 
1674     m_pSerializer->endElementNS( XML_w, XML_drawing );
1675 }
1676 
OutputFlyFrame_Impl(const sw::Frame & rFrame,const Point &)1677 void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Point& /*rNdTopLeft*/ )
1678 {
1679     m_pSerializer->mark();
1680 
1681     switch ( rFrame.GetWriterType() )
1682     {
1683         case sw::Frame::eGraphic:
1684             {
1685                 const SwNode *pNode = rFrame.GetContent();
1686                 const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
1687                 if ( pGrfNode )
1688                     FlyFrameGraphic( *pGrfNode, rFrame.GetLayoutSize() );
1689             }
1690             break;
1691         case sw::Frame::eDrawing:
1692             {
1693                 const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
1694                 if ( pSdrObj )
1695                 {
1696                     bool bSwapInPage = false;
1697                     if ( !pSdrObj->GetPage() )
1698                     {
1699                         if ( SwDrawModel* pModel = m_rExport.pDoc->GetDrawModel() )
1700                         {
1701                             if ( SdrPage *pPage = pModel->GetPage( 0 ) )
1702                             {
1703                                 bSwapInPage = true;
1704                                 const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
1705                             }
1706                         }
1707                     }
1708 
1709                     m_pSerializer->startElementNS( XML_w, XML_pict,
1710                             FSEND );
1711 
1712                     m_rExport.VMLExporter().AddSdrObject( *pSdrObj );
1713 
1714                     m_pSerializer->endElementNS( XML_w, XML_pict );
1715 
1716                     if ( bSwapInPage )
1717                         const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
1718                 }
1719             }
1720             break;
1721         default:
1722 #if OSL_DEBUG_LEVEL > 0
1723             OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
1724                     rFrame.GetWriterType() == sw::Frame::eTxtBox? "eTxtBox":
1725                     ( rFrame.GetWriterType() == sw::Frame::eOle? "eOle":
1726                       ( rFrame.GetWriterType() == sw::Frame::eFormControl? "eFormControl": "???" ) ) );
1727 #endif
1728             break;
1729     }
1730 
1731     m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
1732 }
1733 
StartStyle(const String & rName,bool bPapFmt,sal_uInt16 nBase,sal_uInt16 nNext,sal_uInt16,sal_uInt16 nId)1734 void DocxAttributeOutput::StartStyle( const String& rName, bool bPapFmt,
1735         sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId )
1736 {
1737     OString aStyle( "style" );
1738 
1739     m_pSerializer->startElementNS( XML_w, XML_style,
1740             FSNS( XML_w, XML_type ), bPapFmt? "paragraph": "character", // FIXME is this correct?
1741             FSNS( XML_w, XML_styleId ), ( aStyle + OString::valueOf( sal_Int32( nId ) ) ).getStr(),
1742             FSEND );
1743 
1744     m_pSerializer->singleElementNS( XML_w, XML_name,
1745             FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
1746             FSEND );
1747 
1748     if ( nBase != 0x0FFF )
1749     {
1750         m_pSerializer->singleElementNS( XML_w, XML_basedOn,
1751                 FSNS( XML_w, XML_val ), ( aStyle + OString::valueOf( sal_Int32( nBase ) ) ).getStr(),
1752                 FSEND );
1753     }
1754 
1755     m_pSerializer->singleElementNS( XML_w, XML_next,
1756             FSNS( XML_w, XML_val ), ( aStyle + OString::valueOf( sal_Int32( nNext ) ) ).getStr(),
1757             FSEND );
1758 }
1759 
EndStyle()1760 void DocxAttributeOutput::EndStyle()
1761 {
1762     m_pSerializer->endElementNS( XML_w, XML_style );
1763 }
1764 
StartStyleProperties(bool bParProp,sal_uInt16)1765 void DocxAttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 /*nStyle*/ )
1766 {
1767     if ( bParProp )
1768     {
1769         m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
1770         InitCollectedParagraphProperties();
1771     }
1772     else
1773     {
1774         m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
1775         InitCollectedRunProperties();
1776     }
1777 }
1778 
EndStyleProperties(bool bParProp)1779 void DocxAttributeOutput::EndStyleProperties( bool bParProp )
1780 {
1781     if ( bParProp )
1782     {
1783         WriteCollectedParagraphProperties();
1784         m_pSerializer->endElementNS( XML_w, XML_pPr );
1785     }
1786     else
1787     {
1788         WriteCollectedRunProperties();
1789         m_pSerializer->endElementNS( XML_w, XML_rPr );
1790     }
1791 }
1792 
OutlineNumbering(sal_uInt8 nLvl,const SwNumFmt &,const SwFmt &)1793 void DocxAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
1794 {
1795     if ( nLvl >= WW8ListManager::nMaxLevel )
1796         nLvl = WW8ListManager::nMaxLevel - 1;
1797 
1798     m_pSerializer->singleElementNS( XML_w, XML_outlineLvl,
1799             FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl ) ).getStr( ),
1800             FSEND );
1801 }
1802 
PageBreakBefore(bool bBreak)1803 void DocxAttributeOutput::PageBreakBefore( bool bBreak )
1804 {
1805     if ( bBreak )
1806         m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore, FSEND );
1807     else
1808         m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore,
1809                 FSNS( XML_w, XML_val ), "off",
1810                 FSEND );
1811 }
1812 
SectionBreak(sal_uInt8 nC,const WW8_SepInfo * pSectionInfo)1813 void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
1814 {
1815     switch ( nC )
1816     {
1817         case msword::ColumnBreak:
1818             // The column break should be output in the next paragraph...
1819             m_nColBreakStatus = COLBRK_POSTPONE;
1820             break;
1821         case msword::PageBreak:
1822             if ( pSectionInfo )
1823             {
1824                 if ( !m_bParagraphOpened )
1825                 {
1826                     // Create a dummy paragraph if needed
1827                     m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
1828                     m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
1829 
1830                     m_rExport.SectionProperties( *pSectionInfo );
1831 
1832                     m_pSerializer->endElementNS( XML_w, XML_pPr );
1833                     m_pSerializer->endElementNS( XML_w, XML_p );
1834                 }
1835                 else
1836                 {
1837                     // postpone the output of this; it has to be done inside the
1838                     // paragraph properties, so remember it until then
1839                     m_pSectionInfo = pSectionInfo;
1840                 }
1841             }
1842             else
1843             {
1844                 m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
1845                 m_pSerializer->singleElementNS( XML_w, XML_br,
1846                         FSNS( XML_w, XML_type ), "page", FSEND );
1847                 m_pSerializer->endElementNS( XML_w, XML_r );
1848             }
1849             break;
1850         default:
1851 #if OSL_DEBUG_LEVEL > 0
1852             OSL_TRACE( "Unknown section break to write: %d\n", nC );
1853 #endif
1854             break;
1855     }
1856 }
1857 
StartSection()1858 void DocxAttributeOutput::StartSection()
1859 {
1860     m_pSerializer->startElementNS( XML_w, XML_sectPr, FSEND );
1861     m_bOpenedSectPr = true;
1862 }
1863 
EndSection()1864 void DocxAttributeOutput::EndSection()
1865 {
1866     // Write the section properties
1867     if ( m_pSpacingAttrList )
1868     {
1869         XFastAttributeListRef xAttrList( m_pSpacingAttrList );
1870         m_pSpacingAttrList = NULL;
1871 
1872         m_pSerializer->singleElementNS( XML_w, XML_pgMar, xAttrList );
1873     }
1874 
1875     m_pSerializer->endElementNS( XML_w, XML_sectPr );
1876     m_bOpenedSectPr = false;
1877 }
1878 
SectionFormProtection(bool bProtected)1879 void DocxAttributeOutput::SectionFormProtection( bool bProtected )
1880 {
1881     if ( bProtected )
1882         m_pSerializer->singleElementNS( XML_w, XML_formProt, FSEND );
1883     else
1884         m_pSerializer->singleElementNS( XML_w, XML_formProt,
1885                 FSNS( XML_w, XML_val ), "off", FSEND );
1886 }
1887 
SectionLineNumbering(sal_uLong,const SwLineNumberInfo &)1888 void DocxAttributeOutput::SectionLineNumbering( sal_uLong /*nRestartNo*/, const SwLineNumberInfo& /*rLnNumInfo*/ )
1889 {
1890     // see 2.6.8 lnNumType (Line Numbering Settings)
1891 #if OSL_DEBUG_LEVEL > 0
1892     OSL_TRACE( "TODO DocxAttributeOutput::SectionLineNumbering()\n" );
1893 #endif
1894 }
1895 
SectionTitlePage()1896 void DocxAttributeOutput::SectionTitlePage()
1897 {
1898     m_pSerializer->singleElementNS( XML_w, XML_titlePg, FSEND );
1899 }
1900 
SectionPageBorders(const SwFrmFmt * pFmt,const SwFrmFmt *)1901 void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
1902 {
1903     // Output the margins
1904 
1905 
1906     const SvxBoxItem& rBox = pFmt->GetBox( );
1907 
1908     const SvxBorderLine* pBottom = rBox.GetBottom( );
1909     const SvxBorderLine* pTop = rBox.GetTop( );
1910     const SvxBorderLine* pLeft = rBox.GetLeft( );
1911     const SvxBorderLine* pRight = rBox.GetRight( );
1912 
1913     if ( pBottom || pTop || pLeft || pRight )
1914     {
1915         // All distances are relative to the text margins
1916         m_pSerializer->startElementNS( XML_w, XML_pgBorders,
1917                FSNS( XML_w, XML_display ), "allPages",
1918                FSNS( XML_w, XML_offsetFrom ), "text",
1919                FSEND );
1920 
1921         m_pSerializer->mark();
1922 
1923         m_pSerializer->endElementNS( XML_w, XML_pgBorders );
1924         m_pSerializer->mark();
1925     }
1926 }
1927 
SectionBiDi(bool bBiDi)1928 void DocxAttributeOutput::SectionBiDi( bool bBiDi )
1929 {
1930     if ( bBiDi )
1931         m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
1932 }
1933 
impl_NumberingType(sal_uInt16 nNumberingType)1934 static OString impl_NumberingType( sal_uInt16 nNumberingType )
1935 {
1936     OString aType;
1937 
1938     switch ( nNumberingType )
1939     {
1940         case SVX_NUM_CHARS_UPPER_LETTER:
1941         case SVX_NUM_CHARS_UPPER_LETTER_N:  aType = "upperLetter"; break;
1942         case SVX_NUM_CHARS_LOWER_LETTER:
1943         case SVX_NUM_CHARS_LOWER_LETTER_N:  aType = "lowerLetter"; break;
1944         case SVX_NUM_ROMAN_UPPER:           aType = "upperRoman";  break;
1945         case SVX_NUM_ROMAN_LOWER:           aType = "lowerRoman";  break;
1946 
1947         case SVX_NUM_ARABIC:                aType = "decimal";     break;
1948 
1949         case SVX_NUM_BITMAP:
1950         case SVX_NUM_CHAR_SPECIAL:          aType = "bullet";      break;
1951 
1952         default:                            aType = "none";        break;
1953     }
1954 
1955     return aType;
1956 }
1957 
SectionPageNumbering(sal_uInt16 nNumType,sal_uInt16 nPageRestartNumber)1958 void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
1959 {
1960     // FIXME Not called properly with page styles like "First Page"
1961 
1962     FastAttributeList* pAttr = m_pSerializer->createAttrList();
1963 
1964     // 0 means no restart: then don't output that attribute if 0
1965     if ( nPageRestartNumber > 0 )
1966        pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( sal_Int32( nPageRestartNumber ) ) );
1967 
1968     // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
1969     OString aFmt( impl_NumberingType( nNumType ) );
1970     if ( aFmt.getLength() )
1971         pAttr->add( FSNS( XML_w, XML_fmt ), aFmt.getStr() );
1972 
1973     XFastAttributeListRef xAttrs( pAttr );
1974     m_pSerializer->singleElementNS( XML_w, XML_pgNumType, xAttrs );
1975 
1976     // see 2.6.12 pgNumType (Page Numbering Settings)
1977 #if OSL_DEBUG_LEVEL > 0
1978     OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()\n" );
1979 #endif
1980 }
1981 
SectionType(sal_uInt8 nBreakCode)1982 void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode )
1983 {
1984     /*  break code:   0 No break, 1 New column
1985         2 New page, 3 Even page, 4 Odd page
1986         */
1987     const char* pType = NULL;
1988     switch ( nBreakCode )
1989     {
1990         case 1:  pType = "nextColumn"; break;
1991         case 2:  pType = "nextPage";   break;
1992         case 3:  pType = "evenPage";   break;
1993         case 4:  pType = "oddPage";    break;
1994         default: pType = "continuous"; break;
1995     }
1996 
1997     if ( pType )
1998         m_pSerializer->singleElementNS( XML_w, XML_type,
1999                 FSNS( XML_w, XML_val ), pType,
2000                 FSEND );
2001 }
2002 
StartFont(const String & rFamilyName) const2003 void DocxAttributeOutput::StartFont( const String& rFamilyName ) const
2004 {
2005     m_pSerializer->startElementNS( XML_w, XML_font,
2006             FSNS( XML_w, XML_name ), OUStringToOString( OUString( rFamilyName ), RTL_TEXTENCODING_UTF8 ).getStr(),
2007             FSEND );
2008 }
2009 
EndFont() const2010 void DocxAttributeOutput::EndFont() const
2011 {
2012     m_pSerializer->endElementNS( XML_w, XML_font );
2013 }
2014 
FontAlternateName(const String & rName) const2015 void DocxAttributeOutput::FontAlternateName( const String& rName ) const
2016 {
2017     m_pSerializer->singleElementNS( XML_w, XML_altName,
2018             FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
2019             FSEND );
2020 }
2021 
FontCharset(sal_uInt8 nCharSet) const2022 void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet ) const
2023 {
2024     OString aCharSet( OString::valueOf( sal_Int32( nCharSet ), 16 ) );
2025     if ( aCharSet.getLength() == 1 )
2026         aCharSet = OString( "0" ) + aCharSet;
2027 
2028     m_pSerializer->singleElementNS( XML_w, XML_charset,
2029             FSNS( XML_w, XML_val ), aCharSet.getStr(),
2030             FSEND );
2031 }
2032 
FontFamilyType(FontFamily eFamily) const2033 void DocxAttributeOutput::FontFamilyType( FontFamily eFamily ) const
2034 {
2035     const char *pFamily = NULL;
2036     switch ( eFamily )
2037     {
2038         case FAMILY_ROMAN:      pFamily = "roman"; break;
2039         case FAMILY_SWISS:      pFamily = "swiss"; break;
2040         case FAMILY_MODERN:     pFamily = "modern"; break;
2041         case FAMILY_SCRIPT:     pFamily = "script"; break;
2042         case FAMILY_DECORATIVE: pFamily = "decorative"; break;
2043         default:                pFamily = "auto"; break; // no font family
2044     }
2045 
2046     if ( pFamily )
2047         m_pSerializer->singleElementNS( XML_w, XML_family,
2048                 FSNS( XML_w, XML_val ), pFamily,
2049                 FSEND );
2050 }
2051 
FontPitchType(FontPitch ePitch) const2052 void DocxAttributeOutput::FontPitchType( FontPitch ePitch ) const
2053 {
2054     const char *pPitch = NULL;
2055     switch ( ePitch )
2056     {
2057         case PITCH_VARIABLE: pPitch = "variable"; break;
2058         case PITCH_FIXED:    pPitch = "fixed"; break;
2059         default:             pPitch = "default"; break; // no info about the pitch
2060     }
2061 
2062     if ( pPitch )
2063         m_pSerializer->singleElementNS( XML_w, XML_pitch,
2064                 FSNS( XML_w, XML_val ), pPitch,
2065                 FSEND );
2066 }
2067 
NumberingDefinition(sal_uInt16 nId,const SwNumRule & rRule)2068 void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
2069 {
2070     // nId is the same both for abstract numbering definition as well as the
2071     // numbering definition itself
2072     // TODO check that this is actually true & fix if not ;-)
2073     OString aId( OString::valueOf( sal_Int32( nId ) ) );
2074 
2075     m_pSerializer->startElementNS( XML_w, XML_num,
2076             FSNS( XML_w, XML_numId ), aId.getStr(),
2077             FSEND );
2078 
2079     m_pSerializer->singleElementNS( XML_w, XML_abstractNumId,
2080             FSNS( XML_w, XML_val ), aId.getStr(),
2081             FSEND );
2082 
2083 #if OSL_DEBUG_LEVEL > 0
2084     // TODO ww8 version writes this, anything to do about it here?
2085     if ( rRule.IsContinusNum() )
2086         OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()\n" );
2087 #else
2088     (void) rRule; // to quiet the warning...
2089 #endif
2090 
2091     m_pSerializer->endElementNS( XML_w, XML_num );
2092 }
2093 
StartAbstractNumbering(sal_uInt16 nId)2094 void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
2095 {
2096     m_pSerializer->startElementNS( XML_w, XML_abstractNum,
2097             FSNS( XML_w, XML_abstractNumId ), OString::valueOf( sal_Int32( nId ) ).getStr(),
2098             FSEND );
2099 }
2100 
EndAbstractNumbering()2101 void DocxAttributeOutput::EndAbstractNumbering()
2102 {
2103     m_pSerializer->endElementNS( XML_w, XML_abstractNum );
2104 }
2105 
NumberingLevel(sal_uInt8 nLevel,sal_uInt16 nStart,sal_uInt16 nNumberingType,SvxAdjust eAdjust,const sal_uInt8 *,sal_uInt8 nFollow,const wwFont * pFont,const SfxItemSet * pOutSet,sal_Int16 nIndentAt,sal_Int16 nFirstLineIndex,sal_Int16,const String & rNumberingString)2106 void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
2107         sal_uInt16 nStart,
2108         sal_uInt16 nNumberingType,
2109         SvxAdjust eAdjust,
2110         const sal_uInt8 * /*pNumLvlPos*/,
2111         sal_uInt8 nFollow,
2112         const wwFont *pFont,
2113         const SfxItemSet *pOutSet,
2114         sal_Int16 nIndentAt,
2115         sal_Int16 nFirstLineIndex,
2116         sal_Int16 /*nListTabPos*/,
2117         const String &rNumberingString )
2118 {
2119     m_pSerializer->startElementNS( XML_w, XML_lvl,
2120             FSNS( XML_w, XML_ilvl ), OString::valueOf( sal_Int32( nLevel ) ).getStr(),
2121             FSEND );
2122 
2123     // start with the nStart value
2124     m_pSerializer->singleElementNS( XML_w, XML_start,
2125             FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nStart ) ).getStr(),
2126             FSEND );
2127 
2128     // format
2129     OString aFmt( impl_NumberingType( nNumberingType ) );
2130 
2131     if ( aFmt.getLength() )
2132         m_pSerializer->singleElementNS( XML_w, XML_numFmt,
2133                 FSNS( XML_w, XML_val ), aFmt.getStr(),
2134                 FSEND );
2135 
2136     // justification
2137     const char *pJc;
2138     switch ( eAdjust )
2139     {
2140         case SVX_ADJUST_CENTER: pJc = "center"; break;
2141         case SVX_ADJUST_RIGHT:  pJc = "right";  break;
2142         default:                pJc = "left";   break;
2143     }
2144     m_pSerializer->singleElementNS( XML_w, XML_lvlJc,
2145             FSNS( XML_w, XML_val ), pJc,
2146             FSEND );
2147 
2148     // suffix
2149     const char *pSuffix = NULL;
2150     switch ( nFollow )
2151     {
2152         case 1:  pSuffix = "space";   break;
2153         case 2:  pSuffix = "nothing"; break;
2154         default: /*pSuffix = "tab";*/ break;
2155     }
2156     if ( pSuffix )
2157         m_pSerializer->singleElementNS( XML_w, XML_suff,
2158                 FSNS( XML_w, XML_val ), pSuffix,
2159                 FSEND );
2160 
2161     // text
2162     OUString aText( rNumberingString );
2163     OUStringBuffer aBuffer( aText.getLength() + WW8ListManager::nMaxLevel );
2164 
2165     const sal_Unicode *pPrev = aText.getStr();
2166     const sal_Unicode *pIt = aText.getStr();
2167     while ( pIt < aText.getStr() + aText.getLength() )
2168     {
2169         // convert the level values to %NUMBER form
2170         // (we don't use pNumLvlPos at all)
2171         // FIXME so far we support the ww8 limit of levels only
2172         if ( *pIt < sal_Unicode( WW8ListManager::nMaxLevel ) )
2173         {
2174             aBuffer.append( pPrev, pIt - pPrev );
2175             aBuffer.appendAscii( "%" );
2176             aBuffer.append( OUString::valueOf( sal_Int32( *pIt ) + 1 ) );
2177 
2178             pPrev = pIt + 1;
2179         }
2180         ++pIt;
2181     }
2182     if ( pPrev < pIt )
2183         aBuffer.append( pPrev, pIt - pPrev );
2184 
2185     m_pSerializer->singleElementNS( XML_w, XML_lvlText,
2186             FSNS( XML_w, XML_val ), OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ).getStr(),
2187             FSEND );
2188 
2189     // indentation
2190     m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
2191     m_pSerializer->singleElementNS( XML_w, XML_ind,
2192             FSNS( XML_w, XML_left ), OString::valueOf( sal_Int32( nIndentAt ) ).getStr(),
2193             FSNS( XML_w, XML_hanging ), OString::valueOf( sal_Int32( -nFirstLineIndex ) ).getStr(),
2194             FSEND );
2195     m_pSerializer->endElementNS( XML_w, XML_pPr );
2196 
2197     // font
2198     if ( pOutSet )
2199     {
2200         m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
2201 
2202         if ( pFont )
2203         {
2204             OString aFamilyName( OUStringToOString( OUString( pFont->GetFamilyName() ), RTL_TEXTENCODING_UTF8 ) );
2205             m_pSerializer->singleElementNS( XML_w, XML_rFonts,
2206                     FSNS( XML_w, XML_ascii ), aFamilyName.getStr(),
2207                     FSNS( XML_w, XML_hAnsi ), aFamilyName.getStr(),
2208                     FSNS( XML_w, XML_cs ), aFamilyName.getStr(),
2209                     FSNS( XML_w, XML_hint ), "default",
2210                     FSEND );
2211         }
2212         m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN );
2213 
2214         m_pSerializer->endElementNS( XML_w, XML_rPr );
2215     }
2216 
2217     // TODO anything to do about nListTabPos?
2218 
2219     m_pSerializer->endElementNS( XML_w, XML_lvl );
2220 }
2221 
CharCaseMap(const SvxCaseMapItem & rCaseMap)2222 void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
2223 {
2224     switch ( rCaseMap.GetValue() )
2225     {
2226         case SVX_CASEMAP_KAPITAELCHEN:
2227             m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSEND );
2228             break;
2229         case SVX_CASEMAP_VERSALIEN:
2230             m_pSerializer->singleElementNS( XML_w, XML_caps, FSEND );
2231             break;
2232         default: // Something that ooxml does not support
2233             m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSNS( XML_w, XML_val ), "off", FSEND );
2234             m_pSerializer->singleElementNS( XML_w, XML_caps, FSNS( XML_w, XML_val ), "off", FSEND );
2235             break;
2236     }
2237 }
2238 
CharColor(const SvxColorItem & rColor)2239 void DocxAttributeOutput::CharColor( const SvxColorItem& rColor )
2240 {
2241     const Color aColor( rColor.GetValue() );
2242     OString aColorString;
2243 
2244     aColorString = impl_ConvertColor( aColor );
2245 
2246     m_pSerializer->singleElementNS( XML_w, XML_color,
2247             FSNS( XML_w, XML_val ), aColorString.getStr(), FSEND );
2248 }
2249 
CharContour(const SvxContourItem & rContour)2250 void DocxAttributeOutput::CharContour( const SvxContourItem& rContour )
2251 {
2252     if ( rContour.GetValue() )
2253         m_pSerializer->singleElementNS( XML_w, XML_outline, FSEND );
2254     else
2255         m_pSerializer->singleElementNS( XML_w, XML_outline, FSNS( XML_w, XML_val ), "off", FSEND );
2256 }
2257 
CharCrossedOut(const SvxCrossedOutItem & rCrossedOut)2258 void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
2259 {
2260     switch ( rCrossedOut.GetStrikeout() )
2261     {
2262         case STRIKEOUT_DOUBLE:
2263             m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSEND );
2264             break;
2265         case STRIKEOUT_NONE:
2266             m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSNS( XML_w, XML_val ), "off", FSEND );
2267             m_pSerializer->singleElementNS( XML_w, XML_strike, FSNS( XML_w, XML_val ), "off", FSEND );
2268             break;
2269         default:
2270             m_pSerializer->singleElementNS( XML_w, XML_strike, FSEND );
2271             break;
2272     }
2273 }
2274 
CharEscapement(const SvxEscapementItem &)2275 void DocxAttributeOutput::CharEscapement( const SvxEscapementItem& /*rEscapement*/ )
2276 {
2277 #if OSL_DEBUG_LEVEL > 0
2278     OSL_TRACE( "TODO DocxAttributeOutput::CharEscapement()\n" );
2279 #endif
2280 }
2281 
CharFont(const SvxFontItem & rFont)2282 void DocxAttributeOutput::CharFont( const SvxFontItem& rFont)
2283 {
2284     if (!m_pFontsAttrList)
2285         m_pFontsAttrList = m_pSerializer->createAttrList();
2286     OUString sFontName(rFont.GetFamilyName());
2287     OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
2288     m_pFontsAttrList->add(FSNS(XML_w, XML_ascii), sFontNameUtf8);
2289     m_pFontsAttrList->add(FSNS(XML_w, XML_hAnsi), sFontNameUtf8);
2290 }
2291 
CharFontSize(const SvxFontHeightItem & rFontSize)2292 void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
2293 {
2294     OString fontSize = OString::valueOf( sal_Int32( ( rFontSize.GetHeight() + 5 ) / 10 ) );
2295 
2296     switch ( rFontSize.Which() )
2297     {
2298         case RES_CHRATR_FONTSIZE:
2299         case RES_CHRATR_CJK_FONTSIZE:
2300             m_pSerializer->singleElementNS( XML_w, XML_sz, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
2301             break;
2302         case RES_CHRATR_CTL_FONTSIZE:
2303             m_pSerializer->singleElementNS( XML_w, XML_szCs, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
2304             break;
2305     }
2306 }
2307 
CharKerning(const SvxKerningItem & rKerning)2308 void DocxAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
2309 {
2310     OString aKerning = OString::valueOf( ( sal_Int32 ) rKerning.GetValue() );
2311     m_pSerializer->singleElementNS( XML_w, XML_kern, FSNS(XML_w, XML_val), aKerning.getStr(), FSEND );
2312 }
2313 
CharLanguage(const SvxLanguageItem & rLanguage)2314 void DocxAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
2315 {
2316     if (!m_pCharLangAttrList)
2317         m_pCharLangAttrList = m_pSerializer->createAttrList();
2318 
2319     ::com::sun::star::lang::Locale xLocale= MsLangId::convertLanguageToLocale( rLanguage.GetLanguage( ) );
2320     OString sLanguage = OUStringToOString(xLocale.Language, RTL_TEXTENCODING_UTF8);
2321     OString sCountry = OUStringToOString(xLocale.Country, RTL_TEXTENCODING_UTF8);
2322 
2323     OString aLanguageCode = sLanguage + "-" + sCountry;
2324 
2325     switch ( rLanguage.Which() )
2326     {
2327         case RES_CHRATR_LANGUAGE:
2328             m_pCharLangAttrList->add(FSNS(XML_w, XML_val), aLanguageCode);
2329             break;
2330         case RES_CHRATR_CJK_LANGUAGE:
2331             m_pCharLangAttrList->add(FSNS(XML_w, XML_eastAsia), aLanguageCode);
2332             break;
2333         case RES_CHRATR_CTL_LANGUAGE:
2334             m_pCharLangAttrList->add(FSNS(XML_w, XML_bidi), aLanguageCode);
2335             break;
2336     }
2337 }
2338 
CharPosture(const SvxPostureItem & rPosture)2339 void DocxAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
2340 {
2341     if ( rPosture.GetPosture() != ITALIC_NONE )
2342         m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
2343     else
2344         m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "off", FSEND );
2345 }
2346 
CharShadow(const SvxShadowedItem & rShadow)2347 void DocxAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
2348 {
2349     if ( rShadow.GetValue() )
2350         m_pSerializer->singleElementNS( XML_w, XML_shadow, FSEND );
2351     else
2352         m_pSerializer->singleElementNS( XML_w, XML_shadow, FSNS( XML_w, XML_val ), "off", FSEND );
2353 }
2354 
CharUnderline(const SvxUnderlineItem & rUnderline)2355 void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
2356 {
2357     const char *pUnderline;
2358 
2359     switch ( rUnderline.GetLineStyle() )
2360     {
2361         case UNDERLINE_SINGLE:         pUnderline = "single";          break;
2362         case UNDERLINE_BOLD:           pUnderline = "thick";           break;
2363         case UNDERLINE_DOUBLE:         pUnderline = "double";          break;
2364         case UNDERLINE_DOTTED:         pUnderline = "dotted";          break;
2365         case UNDERLINE_DASH:           pUnderline = "dash";            break;
2366         case UNDERLINE_DASHDOT:        pUnderline = "dotDash";         break;
2367         case UNDERLINE_DASHDOTDOT:     pUnderline = "dotDotDash";      break;
2368         case UNDERLINE_WAVE:           pUnderline = "wave";            break;
2369         case UNDERLINE_BOLDDOTTED:     pUnderline = "dottedHeavy";     break;
2370         case UNDERLINE_BOLDDASH:       pUnderline = "dashedHeavy";     break;
2371         case UNDERLINE_LONGDASH:       pUnderline = "dashLongHeavy";   break;
2372         case UNDERLINE_BOLDLONGDASH:   pUnderline = "dashLongHeavy";   break;
2373         case UNDERLINE_BOLDDASHDOT:    pUnderline = "dashDotHeavy";    break;
2374         case UNDERLINE_BOLDDASHDOTDOT: pUnderline = "dashDotDotHeavy"; break;
2375         case UNDERLINE_BOLDWAVE:       pUnderline = "wavyHeavy";       break;
2376         case UNDERLINE_DOUBLEWAVE:     pUnderline = "wavyDouble";      break;
2377         case UNDERLINE_NONE:           // fall through
2378         default:                       pUnderline = "none";            break;
2379     }
2380 
2381     m_pSerializer->singleElementNS( XML_w, XML_u, FSNS( XML_w, XML_val ), pUnderline, FSEND );
2382 }
2383 
CharWeight(const SvxWeightItem & rWeight)2384 void DocxAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
2385 {
2386     if ( rWeight.GetWeight() == WEIGHT_BOLD )
2387         m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
2388     else
2389         m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "off", FSEND );
2390 }
2391 
CharAutoKern(const SvxAutoKernItem &)2392 void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem& )
2393 {
2394 #if OSL_DEBUG_LEVEL > 0
2395     OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()\n" );
2396 #endif
2397 }
2398 
CharAnimatedText(const SvxBlinkItem & rBlink)2399 void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
2400 {
2401     if ( rBlink.GetValue() )
2402         m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "blinkBackground", FSEND );
2403     else
2404         m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "none", FSEND );
2405 }
2406 
CharBackground(const SvxBrushItem & rBrush)2407 void DocxAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
2408 {
2409     m_pSerializer->singleElementNS( XML_w, XML_shd,
2410             FSNS( XML_w, XML_fill ), impl_ConvertColor( rBrush.GetColor() ).getStr(), FSEND );
2411 }
2412 
CharFontCJK(const SvxFontItem & rFont)2413 void DocxAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
2414 {
2415     if (!m_pFontsAttrList)
2416         m_pFontsAttrList = m_pSerializer->createAttrList();
2417     OUString sFontName(rFont.GetFamilyName());
2418     OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
2419     m_pFontsAttrList->add(FSNS(XML_w, XML_eastAsia), sFontNameUtf8);
2420 }
2421 
CharPostureCJK(const SvxPostureItem & rPosture)2422 void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
2423 {
2424     if ( rPosture.GetPosture() != ITALIC_NONE )
2425         m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
2426     else
2427         m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "off", FSEND );
2428 }
2429 
CharWeightCJK(const SvxWeightItem & rWeight)2430 void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
2431 {
2432     if ( rWeight.GetWeight() == WEIGHT_BOLD )
2433         m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
2434     else
2435         m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "off", FSEND );
2436 }
2437 
CharFontCTL(const SvxFontItem & rFont)2438 void DocxAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
2439 {
2440     if (!m_pFontsAttrList)
2441         m_pFontsAttrList = m_pSerializer->createAttrList();
2442     OUString sFontName(rFont.GetFamilyName());
2443     OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
2444     m_pFontsAttrList->add(FSNS(XML_w, XML_cs), sFontNameUtf8);
2445 
2446 }
2447 
CharPostureCTL(const SvxPostureItem & rPosture)2448 void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
2449 {
2450     if ( rPosture.GetPosture() != ITALIC_NONE )
2451         m_pSerializer->singleElementNS( XML_w, XML_iCs, FSEND );
2452     else
2453         m_pSerializer->singleElementNS( XML_w, XML_iCs, FSNS( XML_w, XML_val ), "off", FSEND );
2454 }
2455 
CharWeightCTL(const SvxWeightItem & rWeight)2456 void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
2457 {
2458     if ( rWeight.GetWeight() == WEIGHT_BOLD )
2459         m_pSerializer->singleElementNS( XML_w, XML_bCs, FSEND );
2460     else
2461         m_pSerializer->singleElementNS( XML_w, XML_bCs, FSNS( XML_w, XML_val ), "off", FSEND );
2462 }
2463 
CharRotate(const SvxCharRotateItem & rRotate)2464 void DocxAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
2465 {
2466     if ( !rRotate.GetValue() )
2467         return;
2468 
2469     if (!m_pEastAsianLayoutAttrList)
2470         m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
2471     OString sTrue((sal_Char *)"true");
2472     m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vert), sTrue);
2473 
2474     if (rRotate.IsFitToLine())
2475         m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vertCompress), sTrue);
2476 }
2477 
CharEmphasisMark(const SvxEmphasisMarkItem & rEmphasisMark)2478 void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
2479 {
2480     const char *pEmphasis;
2481 
2482     switch ( rEmphasisMark.GetValue() )
2483     {
2484         case EMPHASISMARK_NONE:         pEmphasis = "none";     break;
2485         case EMPHASISMARK_SIDE_DOTS:    pEmphasis = "dot";      break;
2486         case EMPHASISMARK_CIRCLE_ABOVE: pEmphasis = "circle";   break;
2487         case EMPHASISMARK_DOTS_BELOW:   pEmphasis = "underDot"; break;
2488         default:                        pEmphasis = "comma";    break;
2489     }
2490 
2491     m_pSerializer->singleElementNS( XML_w, XML_em, FSNS( XML_w, XML_val ), pEmphasis, FSEND );
2492 }
2493 
CharTwoLines(const SvxTwoLinesItem & rTwoLines)2494 void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
2495 {
2496     if ( !rTwoLines.GetValue() )
2497         return;
2498 
2499     if (!m_pEastAsianLayoutAttrList)
2500         m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
2501     OString sTrue((sal_Char *)"true");
2502     m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combine), sTrue);
2503 
2504     sal_Unicode cStart = rTwoLines.GetStartBracket();
2505     sal_Unicode cEnd = rTwoLines.GetEndBracket();
2506 
2507     if (!cStart && !cEnd)
2508         return;
2509 
2510     OString sBracket;
2511     if ((cStart == '{') || (cEnd == '}'))
2512         sBracket = (sal_Char *)"curly";
2513     else if ((cStart == '<') || (cEnd == '>'))
2514         sBracket = (sal_Char *)"angle";
2515     else if ((cStart == '[') || (cEnd == ']'))
2516         sBracket = (sal_Char *)"square";
2517     else
2518         sBracket = (sal_Char *)"round";
2519     m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combineBrackets), sBracket);
2520 }
2521 
CharScaleWidth(const SvxCharScaleWidthItem & rScaleWidth)2522 void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
2523 {
2524     m_pSerializer->singleElementNS( XML_w, XML_w,
2525             FSNS( XML_w, XML_val ), rtl::OString::valueOf( sal_Int32( rScaleWidth.GetValue() ) ).getStr(), FSEND );
2526 }
2527 
CharRelief(const SvxCharReliefItem & rRelief)2528 void DocxAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
2529 {
2530     switch ( rRelief.GetValue() )
2531     {
2532         case RELIEF_EMBOSSED:
2533             m_pSerializer->singleElementNS( XML_w, XML_emboss, FSEND );
2534             break;
2535         case RELIEF_ENGRAVED:
2536             m_pSerializer->singleElementNS( XML_w, XML_imprint, FSEND );
2537             break;
2538         default:
2539             m_pSerializer->singleElementNS( XML_w, XML_emboss, FSNS( XML_w, XML_val ), "off", FSEND );
2540             m_pSerializer->singleElementNS( XML_w, XML_imprint, FSNS( XML_w, XML_val ), "off", FSEND );
2541             break;
2542     }
2543 }
2544 
CharHidden(const SvxCharHiddenItem & rHidden)2545 void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
2546 {
2547     if ( rHidden.GetValue() )
2548         m_pSerializer->singleElementNS( XML_w, XML_vanish, FSEND );
2549     else
2550         m_pSerializer->singleElementNS( XML_w, XML_vanish, FSNS( XML_w, XML_val ), "off", FSEND );
2551 }
2552 
TextINetFormat(const SwFmtINetFmt & rLink)2553 void DocxAttributeOutput::TextINetFormat( const SwFmtINetFmt& rLink )
2554 {
2555     const SwTxtINetFmt* pINetFmt = rLink.GetTxtINetFmt();
2556     const SwCharFmt* pCharFmt = pINetFmt->GetCharFmt();
2557 
2558     OString aStyleId( "style" );
2559     aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
2560 
2561     m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
2562 }
2563 
TextCharFormat(const SwFmtCharFmt &)2564 void DocxAttributeOutput::TextCharFormat( const SwFmtCharFmt& )
2565 {
2566 #if OSL_DEBUG_LEVEL > 0
2567     OSL_TRACE( "TODO DocxAttributeOutput::TextCharFormat()\n" );
2568 #endif
2569 }
2570 
RefField(const SwField & rFld,const String & rRef)2571 void DocxAttributeOutput::RefField( const SwField&  rFld, const String& rRef )
2572 {
2573     sal_uInt16 nType = rFld.GetTyp( )->Which( );
2574     if ( nType == RES_GETEXPFLD )
2575     {
2576         String sCmd = FieldString( ww::eREF );
2577         sCmd.APPEND_CONST_ASC( "\"" );
2578         sCmd += rRef;
2579         sCmd.APPEND_CONST_ASC( "\" " );
2580 
2581         m_rExport.OutputField( &rFld, ww::eREF, sCmd );
2582     }
2583 
2584     // There is nothing to do here for the set fields
2585 }
2586 
HiddenField(const SwField &)2587 void DocxAttributeOutput::HiddenField( const SwField& /*rFld*/ )
2588 {
2589 #if OSL_DEBUG_LEVEL > 0
2590     OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()\n" );
2591 #endif
2592 }
2593 
PostitField(const SwField *)2594 void DocxAttributeOutput::PostitField( const SwField* /* pFld*/ )
2595 {
2596 #if OSL_DEBUG_LEVEL > 0
2597     OSL_TRACE( "TODO DocxAttributeOutput::PostitField()\n" );
2598 #endif
2599 }
2600 
DropdownField(const SwField * pFld)2601 bool DocxAttributeOutput::DropdownField( const SwField* pFld )
2602 {
2603     bool bExpand = false;
2604 
2605     ww::eField eType = ww::eFORMDROPDOWN;
2606     String sCmd = FieldString( eType );
2607     GetExport( ).OutputField( pFld, eType, sCmd );
2608 
2609     return bExpand;
2610 }
2611 
SetField(const SwField & rFld,ww::eField eType,const String & rCmd)2612 void DocxAttributeOutput::SetField( const SwField& rFld, ww::eField eType, const String& rCmd )
2613 {
2614     // field bookmarks are handled in the EndRun method
2615     GetExport().OutputField(&rFld, eType, rCmd );
2616 }
2617 
WriteExpand(const SwField * pFld)2618 void DocxAttributeOutput::WriteExpand( const SwField* pFld )
2619 {
2620     // Will be written in the next End Run
2621     String sCmd;
2622     m_rExport.OutputField( pFld, ww::eUNKNOWN, sCmd );
2623 }
2624 
WriteField_Impl(const SwField * pFld,ww::eField eType,const String & rFldCmd,sal_uInt8 nMode)2625 void DocxAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode )
2626 {
2627     struct FieldInfos infos;
2628     infos.pField = pFld;
2629     infos.sCmd = rFldCmd;
2630     infos.eType = eType;
2631     infos.bClose = WRITEFIELD_CLOSE & nMode;
2632     infos.bOpen = WRITEFIELD_START & nMode;
2633 
2634     m_Fields.push_back( infos );
2635 
2636     if ( pFld )
2637     {
2638         sal_uInt16 nType = pFld->GetTyp( )->Which( );
2639         sal_uInt16 nSubType = pFld->GetSubType();
2640 
2641         // TODO Any other field types here ?
2642         if ( ( nType == RES_SETEXPFLD ) && ( nSubType & nsSwGetSetExpType::GSE_STRING ) )
2643         {
2644             const SwSetExpField *pSet = ( const SwSetExpField* )( pFld );
2645             m_sFieldBkm = pSet->GetPar1( );
2646         }
2647         else if ( nType == RES_DROPDOWN )
2648         {
2649             const SwDropDownField* pDropDown = ( const SwDropDownField* )( pFld );
2650             m_sFieldBkm = pDropDown->GetName( );
2651         }
2652     }
2653 }
2654 
WriteBookmarks_Impl(std::vector<OUString> & rStarts,std::vector<OUString> & rEnds)2655 void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
2656         std::vector< OUString >& rEnds )
2657 {
2658     for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it < end; ++it )
2659     {
2660         OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
2661         m_rMarksStart.push_back( rName );
2662     }
2663     rStarts.clear();
2664 
2665     for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it < end; ++it )
2666     {
2667         OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
2668         m_rMarksEnd.push_back( rName );
2669     }
2670     rEnds.clear();
2671 }
2672 
TextFootnote_Impl(const SwFmtFtn & rFootnote)2673 void DocxAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
2674 {
2675     const SwEndNoteInfo& rInfo = rFootnote.IsEndNote()?
2676         m_rExport.pDoc->GetEndNoteInfo(): m_rExport.pDoc->GetFtnInfo();
2677 
2678     // footnote/endnote run properties
2679     const SwCharFmt* pCharFmt = rInfo.GetAnchorCharFmt( *m_rExport.pDoc );
2680 
2681     OString aStyleId( "style" );
2682     aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
2683 
2684     m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
2685 
2686     // remember the footnote/endnote to
2687     // 1) write the footnoteReference/endnoteReference in EndRunProperties()
2688     // 2) be able to dump them all to footnotes.xml/endnotes.xml
2689     if ( !rFootnote.IsEndNote() )
2690         m_pFootnotesList->add( rFootnote );
2691     else
2692         m_pEndnotesList->add( rFootnote );
2693 }
2694 
FootnoteEndnoteReference()2695 void DocxAttributeOutput::FootnoteEndnoteReference()
2696 {
2697     sal_Int32 nId;
2698     const SwFmtFtn *pFootnote = m_pFootnotesList->getCurrent( nId );
2699 
2700     // both cannot be set at the same time - if they are, it's a bug
2701     if ( !pFootnote )
2702         pFootnote = m_pEndnotesList->getCurrent( nId );
2703 
2704     if ( !pFootnote )
2705         return;
2706 
2707     sal_Int32 nToken = pFootnote->IsEndNote()? XML_endnoteReference: XML_footnoteReference;
2708 
2709     // write it
2710     if ( pFootnote->GetNumStr().Len() == 0 )
2711     {
2712         // autonumbered
2713         m_pSerializer->singleElementNS( XML_w, nToken,
2714                 FSNS( XML_w, XML_id ), ::rtl::OString::valueOf( nId ).getStr(),
2715                 FSEND );
2716     }
2717     else
2718     {
2719         // not autonumbered
2720         m_pSerializer->singleElementNS( XML_w, nToken,
2721                 FSNS( XML_w, XML_customMarkFollows ), "1",
2722                 FSNS( XML_w, XML_id ), ::rtl::OString::valueOf( nId ).getStr(),
2723                 FSEND );
2724 
2725         RunText( pFootnote->GetNumStr() );
2726     }
2727 }
2728 
FootnotesEndnotes(bool bFootnotes)2729 void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes )
2730 {
2731     const FootnotesVector& rVector = bFootnotes? m_pFootnotesList->getVector(): m_pEndnotesList->getVector();
2732 
2733     sal_Int32 nBody = bFootnotes? XML_footnotes: XML_endnotes;
2734     sal_Int32 nItem = bFootnotes? XML_footnote:  XML_endnote;
2735 
2736     m_pSerializer->startElementNS( XML_w, nBody,
2737             FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
2738             FSEND );
2739 
2740     sal_Int32 nIndex = 0;
2741 
2742     // separator
2743     m_pSerializer->startElementNS( XML_w, nItem,
2744             FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
2745             FSNS( XML_w, XML_type ), "separator",
2746             FSEND );
2747     m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
2748     m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
2749     m_pSerializer->singleElementNS( XML_w, XML_separator, FSEND );
2750     m_pSerializer->endElementNS( XML_w, XML_r );
2751     m_pSerializer->endElementNS( XML_w, XML_p );
2752     m_pSerializer->endElementNS( XML_w, nItem );
2753 
2754     // separator
2755     m_pSerializer->startElementNS( XML_w, nItem,
2756             FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
2757             FSNS( XML_w, XML_type ), "continuationSeparator",
2758             FSEND );
2759     m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
2760     m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
2761     m_pSerializer->singleElementNS( XML_w, XML_continuationSeparator, FSEND );
2762     m_pSerializer->endElementNS( XML_w, XML_r );
2763     m_pSerializer->endElementNS( XML_w, XML_p );
2764     m_pSerializer->endElementNS( XML_w, nItem );
2765 
2766     // footnotes/endnotes themselves
2767     for ( FootnotesVector::const_iterator i = rVector.begin(); i != rVector.end(); ++i, ++nIndex )
2768     {
2769         m_pSerializer->startElementNS( XML_w, nItem,
2770                 FSNS( XML_w, XML_id ), OString::valueOf( nIndex ).getStr(),
2771                 FSEND );
2772 
2773         const SwNodeIndex* pIndex = (*i)->GetTxtFtn()->GetStartNode();
2774 
2775         m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
2776                 pIndex->GetNode().EndOfSectionIndex(),
2777                 bFootnotes? TXT_FTN: TXT_EDN );
2778 
2779         m_pSerializer->endElementNS( XML_w, nItem );
2780     }
2781 
2782     m_pSerializer->endElementNS( XML_w, nBody );
2783 
2784 }
2785 
ParaLineSpacing_Impl(short nSpace,short)2786 void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace, short /*nMulti*/ )
2787 {
2788     if ( !m_pSpacingAttrList )
2789         m_pSpacingAttrList = m_pSerializer->createAttrList();
2790 
2791     if ( nSpace < 0 )
2792     {
2793         m_pSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "exact" );
2794         m_pSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( -nSpace ) ) );
2795     }
2796     else if ( nSpace > 0 )
2797     {
2798         m_pSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "atLeast" );
2799         m_pSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
2800     }
2801     else
2802         m_pSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
2803 }
2804 
ParaAdjust(const SvxAdjustItem & rAdjust)2805 void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
2806 {
2807     const char *pAdjustString;
2808 
2809     switch ( rAdjust.GetAdjust() )
2810     {
2811         case SVX_ADJUST_LEFT:
2812             pAdjustString = "left";
2813             break;
2814         case SVX_ADJUST_RIGHT:
2815             pAdjustString = "right";
2816             break;
2817         case SVX_ADJUST_BLOCKLINE:
2818         case SVX_ADJUST_BLOCK:
2819             pAdjustString = "both";
2820             break;
2821         case SVX_ADJUST_CENTER:
2822             pAdjustString = "center";
2823             break;
2824         default:
2825             return; // not supported attribute
2826     }
2827     m_pSerializer->singleElementNS( XML_w, XML_jc, FSNS( XML_w, XML_val ), pAdjustString, FSEND );
2828 }
2829 
ParaSplit(const SvxFmtSplitItem & rSplit)2830 void DocxAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
2831 {
2832     if (rSplit.GetValue())
2833         m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSNS( XML_w, XML_val ), "off", FSEND );
2834     else
2835         m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSEND );
2836 }
2837 
ParaWidows(const SvxWidowsItem & rWidows)2838 void DocxAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
2839 {
2840     if (rWidows.GetValue())
2841         m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSEND );
2842     else
2843         m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSNS( XML_w, XML_val ), "off", FSEND );
2844 }
2845 
impl_WriteTabElement(FSHelperPtr pSerializer,const SvxTabStop & rTab,long nCurrentLeft)2846 static void impl_WriteTabElement( FSHelperPtr pSerializer,
2847         const SvxTabStop& rTab, long nCurrentLeft )
2848 {
2849     FastAttributeList *pTabElementAttrList = pSerializer->createAttrList();
2850 
2851     switch (rTab.GetAdjustment())
2852     {
2853     case SVX_TAB_ADJUST_RIGHT:
2854         pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"right") );
2855         break;
2856     case SVX_TAB_ADJUST_DECIMAL:
2857         pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"decimal") );
2858         break;
2859     case SVX_TAB_ADJUST_CENTER:
2860         pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"center") );
2861         break;
2862     case SVX_TAB_ADJUST_DEFAULT:
2863     case SVX_TAB_ADJUST_LEFT:
2864     default:
2865         pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"left") );
2866         break;
2867     }
2868 
2869     pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
2870 
2871     sal_Unicode cFillChar = rTab.GetFill();
2872 
2873     if (sal_Unicode('.') == cFillChar )
2874         pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "dot" ) );
2875     else if ( sal_Unicode('-') == cFillChar )
2876         pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "hyphen" ) );
2877     else if ( sal_Unicode(0xB7) == cFillChar ) // middle dot
2878         pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "middleDot" ) );
2879     else if ( sal_Unicode('_') == cFillChar )
2880         pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "underscore" ) );
2881     else
2882         pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "none" ) );
2883 
2884     pSerializer->singleElementNS( XML_w, XML_tab, pTabElementAttrList );
2885 }
2886 
ParaTabStop(const SvxTabStopItem & rTabStop)2887 void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
2888 {
2889     const SfxPoolItem* pLR = m_rExport.HasItem( RES_LR_SPACE );
2890     long nCurrentLeft = pLR ? ((const SvxLRSpaceItem*)pLR)->GetTxtLeft() : 0;
2891 
2892     m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
2893 
2894     sal_uInt16 nCount = rTabStop.Count();
2895     for (sal_uInt16 i = 0; i < nCount; i++ )
2896         impl_WriteTabElement( m_pSerializer, rTabStop[i], nCurrentLeft );
2897 
2898     m_pSerializer->endElementNS( XML_w, XML_tabs );
2899 }
2900 
ParaHyphenZone(const SvxHyphenZoneItem & rHyphenZone)2901 void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
2902 {
2903     m_pSerializer->singleElementNS( XML_w, XML_suppressAutoHyphens,
2904             FSNS( XML_w, XML_val ), rHyphenZone.IsHyphen( ) ? "false" : "true" ,
2905             FSEND );
2906 }
2907 
ParaNumRule_Impl(const SwTxtNode *,sal_Int32 nLvl,sal_Int32 nNumId)2908 void DocxAttributeOutput::ParaNumRule_Impl( const SwTxtNode* /*pTxtNd*/, sal_Int32 nLvl, sal_Int32 nNumId )
2909 {
2910     if ( USHRT_MAX != nNumId && 0 != nNumId )
2911     {
2912         m_pSerializer->startElementNS( XML_w, XML_numPr, FSEND );
2913         m_pSerializer->singleElementNS( XML_w, XML_ilvl, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl )).getStr(), FSEND );
2914         m_pSerializer->singleElementNS( XML_w, XML_numId, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nNumId )).getStr(), FSEND );
2915         m_pSerializer->endElementNS( XML_w, XML_numPr );
2916     }
2917 }
2918 
ParaScriptSpace(const SfxBoolItem & rScriptSpace)2919 void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
2920 {
2921     sal_uInt16 nXmlElement = 0;
2922 
2923     switch ( rScriptSpace.Which( ) )
2924     {
2925         case RES_PARATR_SCRIPTSPACE:
2926             nXmlElement = XML_autoSpaceDE;
2927             break;
2928         case RES_PARATR_HANGINGPUNCTUATION:
2929             nXmlElement = XML_overflowPunct;
2930             break;
2931         case RES_PARATR_FORBIDDEN_RULES:
2932             nXmlElement = XML_kinsoku;
2933             break;
2934     }
2935 
2936     if ( nXmlElement )
2937     {
2938         m_pSerializer->singleElementNS( XML_w, nXmlElement,
2939                FSNS( XML_w, XML_val ), rScriptSpace.GetValue( ) ? "true": "false",
2940                FSEND );
2941     }
2942 }
2943 
ParaVerticalAlign(const SvxParaVertAlignItem & rAlign)2944 void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
2945 {
2946     const char *pAlignString;
2947 
2948     switch ( rAlign.GetValue() )
2949     {
2950         case SvxParaVertAlignItem::BASELINE:
2951             pAlignString = "baseline";
2952             break;
2953         case SvxParaVertAlignItem::TOP:
2954             pAlignString = "top";
2955             break;
2956         case SvxParaVertAlignItem::CENTER:
2957             pAlignString = "center";
2958             break;
2959         case SvxParaVertAlignItem::BOTTOM:
2960             pAlignString = "bottom";
2961             break;
2962         case SvxParaVertAlignItem::AUTOMATIC:
2963             pAlignString = "auto";
2964             break;
2965         default:
2966             return; // not supported attribute
2967     }
2968     m_pSerializer->singleElementNS( XML_w, XML_textAlignment, FSNS( XML_w, XML_val ), pAlignString, FSEND );
2969 }
2970 
ParaSnapToGrid(const SvxParaGridItem & rGrid)2971 void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
2972 {
2973     m_pSerializer->singleElementNS( XML_w, XML_snapToGrid,
2974             FSNS( XML_w, XML_val ), rGrid.GetValue( ) ? "true": "false",
2975             FSEND );
2976 }
2977 
FormatFrameSize(const SwFmtFrmSize & rSize)2978 void DocxAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
2979 {
2980     if ( m_rExport.bOutFlyFrmAttrs )
2981     {
2982  #if OSL_DEBUG_LEVEL > 0
2983     OSL_TRACE( "TODO DocxAttributeOutput::FormatFrameSize() - Fly frames\n" );
2984  #endif
2985     }
2986     else if ( m_rExport.bOutPageDescs )
2987     {
2988         FastAttributeList *attrList = m_pSerializer->createAttrList( );
2989         if ( m_rExport.pAktPageDesc->GetLandscape( ) )
2990             attrList->add( FSNS( XML_w, XML_orient ), "landscape" );
2991 
2992 
2993         attrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
2994         attrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
2995 
2996         XFastAttributeListRef xAttrList( attrList );
2997         attrList = NULL;
2998 
2999         m_pSerializer->singleElementNS( XML_w, XML_pgSz, xAttrList );
3000     }
3001 }
3002 
FormatPaperBin(const SvxPaperBinItem &)3003 void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
3004 {
3005 #if OSL_DEBUG_LEVEL > 0
3006     OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()\n" );
3007 #endif
3008 }
3009 
FormatLRSpace(const SvxLRSpaceItem & rLRSpace)3010 void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
3011 {
3012     if ( m_rExport.bOutFlyFrmAttrs )
3013     {
3014 #if OSL_DEBUG_LEVEL > 0
3015         OSL_TRACE( "DocxAttributeOutput::FormatLRSpace() - Fly frames\n" );
3016 #endif
3017     }
3018     else if ( m_rExport.bOutPageDescs )
3019     {
3020         if ( !m_pSpacingAttrList )
3021             m_pSpacingAttrList = m_pSerializer->createAttrList();
3022 
3023 
3024         sal_uInt16 nLDist, nRDist;
3025         const SfxPoolItem* pItem = m_rExport.HasItem( RES_BOX );
3026         if ( pItem )
3027         {
3028             nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
3029             nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
3030         }
3031         else
3032             nLDist = nRDist = 0;
3033         nLDist = nLDist + (sal_uInt16)rLRSpace.GetLeft();
3034         nRDist = nRDist + (sal_uInt16)rLRSpace.GetRight();
3035 
3036         m_pSpacingAttrList->add( FSNS( XML_w, XML_left ), OString::valueOf( sal_Int32( nLDist ) ) );
3037         m_pSpacingAttrList->add( FSNS( XML_w, XML_right ), OString::valueOf( sal_Int32( nRDist ) ) );
3038     }
3039     else
3040     {
3041         FastAttributeList *pLRSpaceAttrList = m_pSerializer->createAttrList();
3042 
3043         pLRSpaceAttrList->add( FSNS( XML_w, XML_left ), OString::valueOf( (sal_Int32) rLRSpace.GetTxtLeft() ) );
3044         pLRSpaceAttrList->add( FSNS( XML_w, XML_right ), OString::valueOf( (sal_Int32) rLRSpace.GetRight() ) );
3045 
3046         sal_Int32 nFirstLineAdjustment = rLRSpace.GetTxtFirstLineOfst();
3047         if (nFirstLineAdjustment > 0)
3048             pLRSpaceAttrList->add( FSNS( XML_w, XML_firstLine ), OString::valueOf( nFirstLineAdjustment ) );
3049         else
3050             pLRSpaceAttrList->add( FSNS( XML_w, XML_hanging ), OString::valueOf( - nFirstLineAdjustment ) );
3051         m_pSerializer->singleElementNS( XML_w, XML_ind, pLRSpaceAttrList );
3052     }
3053 }
3054 
FormatULSpace(const SvxULSpaceItem & rULSpace)3055 void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
3056 {
3057     if (!m_pSpacingAttrList)
3058         m_pSpacingAttrList = m_pSerializer->createAttrList();
3059 
3060     if ( m_rExport.bOutFlyFrmAttrs )
3061     {
3062     }
3063     else if (m_rExport.bOutPageDescs )
3064     {
3065         ASSERT( m_rExport.GetCurItemSet(), "Impossible" );
3066         if ( !m_rExport.GetCurItemSet() )
3067             return;
3068 
3069         HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
3070 
3071         if ( aDistances.HasHeader() )
3072         {
3073             // Header top
3074             m_pSpacingAttrList->add( FSNS( XML_w, XML_header ),
3075                     OString::valueOf( sal_Int32( aDistances.dyaHdrTop ) ) );
3076         }
3077 
3078         // Page top
3079         m_pSpacingAttrList->add( FSNS( XML_w, XML_top ),
3080                 OString::valueOf( sal_Int32( aDistances.dyaTop ) ) );
3081 
3082         if ( aDistances.HasFooter() )
3083         {
3084             // Footer bottom
3085             m_pSpacingAttrList->add( FSNS( XML_w, XML_footer ),
3086                     OString::valueOf( sal_Int32( aDistances.dyaHdrBottom ) ) );
3087         }
3088 
3089         // Page Bottom
3090         m_pSpacingAttrList->add( FSNS( XML_w, XML_bottom ),
3091                 OString::valueOf( sal_Int32( aDistances.dyaBottom ) ) );
3092 
3093     }
3094     else
3095     {
3096         m_pSpacingAttrList->add( FSNS( XML_w, XML_before ),
3097                 OString::valueOf( (sal_Int32)rULSpace.GetUpper() ) );
3098         m_pSpacingAttrList->add( FSNS( XML_w, XML_after ),
3099                 OString::valueOf( (sal_Int32)rULSpace.GetLower() ) );
3100     }
3101 }
3102 
FormatSurround(const SwFmtSurround &)3103 void DocxAttributeOutput::FormatSurround( const SwFmtSurround& )
3104 {
3105 #if OSL_DEBUG_LEVEL > 0
3106     OSL_TRACE( "TODO DocxAttributeOutput::FormatSurround()\n" );
3107 #endif
3108 }
3109 
FormatVertOrientation(const SwFmtVertOrient &)3110 void DocxAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& )
3111 {
3112 #if OSL_DEBUG_LEVEL > 0
3113     OSL_TRACE( "TODO DocxAttributeOutput::FormatVertOrientation()\n" );
3114 #endif
3115 }
3116 
FormatHorizOrientation(const SwFmtHoriOrient &)3117 void DocxAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& )
3118 {
3119 #if OSL_DEBUG_LEVEL > 0
3120     OSL_TRACE( "TODO DocxAttributeOutput::FormatHorizOrientation()\n" );
3121 #endif
3122 }
3123 
FormatAnchor(const SwFmtAnchor &)3124 void DocxAttributeOutput::FormatAnchor( const SwFmtAnchor& )
3125 {
3126 #if OSL_DEBUG_LEVEL > 0
3127     OSL_TRACE( "TODO DocxAttributeOutput::FormatAnchor()\n" );
3128 #endif
3129 }
3130 
FormatBackground(const SvxBrushItem & rBrush)3131 void DocxAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
3132 {
3133     if ( !m_rExport.bOutPageDescs )
3134     {
3135         OString sColor = impl_ConvertColor( rBrush.GetColor( ) );
3136         m_pSerializer->singleElementNS( XML_w, XML_shd,
3137                 FSNS( XML_w, XML_fill ), sColor.getStr( ),
3138                 FSEND );
3139     }
3140 
3141 #if OSL_DEBUG_LEVEL > 0
3142     OSL_TRACE( "TODO DocxAttributeOutput::FormatBackground()\n" );
3143 #endif
3144 }
3145 
FormatBox(const SvxBoxItem & rBox)3146 void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
3147 {
3148 
3149     if ( !m_bOpenedSectPr )
3150     {
3151         // Normally open the borders tag for paragraphs
3152         m_pSerializer->startElementNS( XML_w, XML_pBdr, FSEND );
3153     }
3154 
3155     impl_pageBorders( m_pSerializer, rBox );
3156 
3157     if ( m_bOpenedSectPr )
3158     {
3159         // Special handling for pgBorder
3160         m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
3161         m_pSerializer->mergeTopMarks( );
3162     }
3163     else
3164     {
3165         // Normally close the borders tag for paragraphs
3166         m_pSerializer->endElementNS( XML_w, XML_pBdr );
3167     }
3168 }
3169 
FormatColumns_Impl(sal_uInt16 nCols,const SwFmtCol & rCol,bool bEven,SwTwips nPageSize)3170 void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
3171 {
3172     // Get the columns attributes
3173     FastAttributeList *pColsAttrList = m_pSerializer->createAttrList();
3174 
3175     pColsAttrList->add( FSNS( XML_w, XML_num ),
3176             OString::valueOf( sal_Int32( nCols ) ). getStr( ) );
3177 
3178     const char* pEquals = "false";
3179     if ( bEven )
3180     {
3181         sal_uInt16 nWidth = rCol.GetGutterWidth( true );
3182         pColsAttrList->add( FSNS( XML_w, XML_space ),
3183                OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
3184 
3185         pEquals = "true";
3186     }
3187 
3188     pColsAttrList->add( FSNS( XML_w, XML_equalWidth ), pEquals );
3189 
3190     bool bHasSep = COLADJ_NONE == rCol.GetLineAdj( );
3191     pColsAttrList->add( FSNS( XML_w, XML_sep ), bHasSep ? "true" : "false" );
3192 
3193     // Write the element
3194     m_pSerializer->startElementNS( XML_w, XML_cols, pColsAttrList );
3195 
3196     // Write the columns width if non-equals
3197     const SwColumns & rColumns = rCol.GetColumns(  );
3198     if ( !bEven )
3199     {
3200         for ( sal_uInt16 n = 0; n < nCols; ++n )
3201         {
3202             FastAttributeList *pColAttrList = m_pSerializer->createAttrList();
3203             sal_uInt16 nWidth = rCol.CalcPrtColWidth( n, ( sal_uInt16 ) nPageSize );
3204             pColAttrList->add( FSNS( XML_w, XML_w ),
3205                     OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
3206 
3207             if ( n + 1 != nCols )
3208             {
3209                 sal_uInt16 nSpacing = rColumns[n]->GetRight( ) + rColumns[n + 1]->GetLeft( );
3210                 pColAttrList->add( FSNS( XML_w, XML_space ),
3211                     OString::valueOf( sal_Int32( nSpacing ) ).getStr( ) );
3212             }
3213 
3214             m_pSerializer->singleElementNS( XML_w, XML_col, pColAttrList );
3215         }
3216     }
3217 
3218     m_pSerializer->endElementNS( XML_w, XML_cols );
3219 }
3220 
FormatKeep(const SvxFmtKeepItem &)3221 void DocxAttributeOutput::FormatKeep( const SvxFmtKeepItem& )
3222 {
3223     m_pSerializer->singleElementNS( XML_w, XML_keepNext, FSEND );
3224 }
3225 
FormatTextGrid(const SwTextGridItem &)3226 void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem& )
3227 {
3228     OSL_TRACE( "TODO DocxAttributeOutput::FormatTextGrid()\n" );
3229 }
3230 
FormatLineNumbering(const SwFmtLineNumber & rNumbering)3231 void DocxAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
3232 {
3233     if ( !rNumbering.IsCount( ) )
3234         m_pSerializer->singleElementNS( XML_w, XML_suppressLineNumbers, FSEND );
3235 }
3236 
FormatFrameDirection(const SvxFrameDirectionItem & rDirection)3237 void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
3238 {
3239     OString sTextFlow;
3240     bool bBiDi = false;
3241     short nDir = rDirection.GetValue();
3242 
3243     if ( nDir == FRMDIR_ENVIRONMENT )
3244         nDir = GetExport( ).GetDefaultFrameDirection( );
3245 
3246     switch ( nDir )
3247     {
3248         default:
3249         case FRMDIR_HORI_LEFT_TOP:
3250             sTextFlow = OString( "lrTb" );
3251             break;
3252         case FRMDIR_HORI_RIGHT_TOP:
3253             sTextFlow = OString( "lrTb" );
3254             bBiDi = true;
3255             break;
3256         case FRMDIR_VERT_TOP_LEFT: // many things but not this one
3257         case FRMDIR_VERT_TOP_RIGHT:
3258             sTextFlow = OString( "tbRl" );
3259             break;
3260     }
3261 
3262     if ( m_rExport.bOutPageDescs )
3263     {
3264         m_pSerializer->singleElementNS( XML_w, XML_textDirection,
3265                FSNS( XML_w, XML_val ), sTextFlow.getStr( ),
3266                FSEND );
3267         if ( bBiDi )
3268             m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
3269     }
3270     else if ( !m_rExport.bOutFlyFrmAttrs )
3271     {
3272         if ( bBiDi )
3273             m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
3274     }
3275 }
3276 
DocxAttributeOutput(DocxExport & rExport,FSHelperPtr pSerializer,oox::drawingml::DrawingML * pDrawingML)3277 DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML )
3278     : m_rExport( rExport ),
3279       m_pSerializer( pSerializer ),
3280       m_rDrawingML( *pDrawingML ),
3281       m_pFontsAttrList( NULL ),
3282       m_pEastAsianLayoutAttrList( NULL ),
3283       m_pCharLangAttrList( NULL ),
3284       m_pSpacingAttrList( NULL ),
3285       m_pHyperlinkAttrList( NULL ),
3286       m_pFootnotesList( new ::docx::FootnotesList() ),
3287       m_pEndnotesList( new ::docx::FootnotesList() ),
3288       m_pSectionInfo( NULL ),
3289       m_pRedlineData( NULL ),
3290       m_nRedlineId( 0 ),
3291       m_bOpenedSectPr( false ),
3292       m_sFieldBkm( ),
3293       m_nNextMarkId( 0 ),
3294       m_bPostitStart(false),
3295       m_bPostitEnd(false),
3296       m_pTableWrt( NULL ),
3297       m_bTableCellOpen( false ),
3298       m_nTableDepth( 0 ),
3299       m_bParagraphOpened( false ),
3300       m_nColBreakStatus( COLBRK_NONE )
3301 {
3302 }
3303 
~DocxAttributeOutput()3304 DocxAttributeOutput::~DocxAttributeOutput()
3305 {
3306     delete m_pFontsAttrList, m_pFontsAttrList = NULL;
3307     delete m_pEastAsianLayoutAttrList, m_pEastAsianLayoutAttrList = NULL;
3308     delete m_pCharLangAttrList, m_pCharLangAttrList = NULL;
3309     delete m_pSpacingAttrList, m_pSpacingAttrList = NULL;
3310     delete m_pHyperlinkAttrList, m_pHyperlinkAttrList = NULL;
3311 
3312     delete m_pFootnotesList, m_pFootnotesList = NULL;
3313     delete m_pEndnotesList, m_pEndnotesList = NULL;
3314 
3315     delete m_pTableWrt, m_pTableWrt = NULL;
3316 }
3317 
GetExport()3318 MSWordExportBase& DocxAttributeOutput::GetExport()
3319 {
3320     return m_rExport;
3321 }
3322 
HasFootnotes()3323 bool DocxAttributeOutput::HasFootnotes()
3324 {
3325     return !m_pFootnotesList->isEmpty();
3326 }
3327 
HasEndnotes()3328 bool DocxAttributeOutput::HasEndnotes()
3329 {
3330     return !m_pEndnotesList->isEmpty();
3331 }
3332