Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "docxexport.hxx"
21 : #include "docxexportfilter.hxx"
22 : #include "docxattributeoutput.hxx"
23 :
24 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
25 : #include <com/sun/star/document/XDocumentProperties.hpp>
26 : #include <com/sun/star/i18n/ScriptType.hpp>
27 : #include <com/sun/star/frame/XModel.hpp>
28 :
29 : #include <oox/token/tokens.hxx>
30 : #include <oox/export/drawingml.hxx>
31 : #include <oox/export/vmlexport.hxx>
32 : #include <oox/export/chartexport.hxx>
33 :
34 : #include <map>
35 : #include <algorithm>
36 :
37 : #include <IMark.hxx>
38 : #include <docsh.hxx>
39 : #include <ndtxt.hxx>
40 : #include <wrtww8.hxx>
41 : #include <fltini.hxx>
42 : #include <fmtline.hxx>
43 : #include <fmtpdsc.hxx>
44 : #include <frmfmt.hxx>
45 : #include <section.hxx>
46 : #include <ftninfo.hxx>
47 :
48 : #include <editeng/editobj.hxx>
49 : #include <editeng/outlobj.hxx>
50 :
51 : #include <docary.hxx>
52 : #include <numrule.hxx>
53 : #include <charfmt.hxx>
54 : #include <viewsh.hxx>
55 : #include <viewopt.hxx>
56 :
57 : #include "ww8par.hxx"
58 : #include "ww8scan.hxx"
59 :
60 : #include <comphelper/string.hxx>
61 : #include <rtl/ustrbuf.hxx>
62 : #include <vcl/font.hxx>
63 :
64 : using namespace sax_fastparser;
65 : using namespace ::comphelper;
66 : using namespace ::com::sun::star;
67 : using namespace ::oox;
68 :
69 : using oox::vml::VMLExport;
70 :
71 : using sw::mark::IMark;
72 :
73 4216 : AttributeOutputBase& DocxExport::AttrOutput() const
74 : {
75 4216 : return *m_pAttrOutput;
76 : }
77 :
78 0 : MSWordSections& DocxExport::Sections() const
79 : {
80 0 : return *m_pSections;
81 : }
82 :
83 933 : bool DocxExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
84 : {
85 : // TODO FIXME is this actually true for docx? - this is ~copied from WW8
86 933 : if ( nScript == i18n::ScriptType::ASIAN )
87 : {
88 : // for asian in ww8, there is only one fontsize
89 : // and one fontstyle (posture/weight)
90 0 : switch ( nWhich )
91 : {
92 : case RES_CHRATR_FONTSIZE:
93 : case RES_CHRATR_POSTURE:
94 : case RES_CHRATR_WEIGHT:
95 0 : return false;
96 : default:
97 0 : break;
98 : }
99 : }
100 933 : else if ( nScript != i18n::ScriptType::COMPLEX )
101 : {
102 : // for western in ww8, there is only one fontsize
103 : // and one fontstyle (posture/weight)
104 933 : switch ( nWhich )
105 : {
106 : case RES_CHRATR_CJK_FONTSIZE:
107 : case RES_CHRATR_CJK_POSTURE:
108 : case RES_CHRATR_CJK_WEIGHT:
109 155 : return false;
110 : default:
111 778 : break;
112 : }
113 : }
114 778 : return true;
115 : }
116 :
117 194 : void DocxExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
118 : {
119 194 : std::vector< OUString > aStarts;
120 194 : std::vector< OUString > aEnds;
121 :
122 194 : IMarkVector aMarks;
123 194 : if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
124 : {
125 10 : for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
126 : it != end; ++it )
127 : {
128 5 : IMark* pMark = (*it);
129 :
130 5 : xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
131 5 : xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
132 :
133 5 : if ( nStart == nAktPos )
134 3 : aStarts.push_back( pMark->GetName() );
135 :
136 5 : if ( nEnd == nAktPos )
137 3 : aEnds.push_back( pMark->GetName() );
138 : }
139 : }
140 :
141 194 : m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
142 194 : }
143 :
144 0 : void DocxExport::AppendBookmark( const OUString& rName, bool /*bSkip*/ )
145 : {
146 0 : std::vector< OUString > aStarts;
147 0 : std::vector< OUString > aEnds;
148 :
149 0 : aStarts.push_back( rName );
150 0 : aEnds.push_back( rName );
151 :
152 0 : m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
153 0 : }
154 :
155 0 : ::rtl::OString DocxExport::AddRelation( const OUString& rType, const OUString& rTarget )
156 : {
157 : OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
158 0 : rType, rTarget, true );
159 :
160 0 : return ::rtl::OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
161 : }
162 :
163 149 : bool DocxExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
164 : {
165 149 : bool bRet( false );
166 :
167 149 : if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
168 : {
169 149 : if (const SwFmt *pParent = rFmt.DerivedFrom())
170 : {
171 149 : if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
172 : {
173 0 : ::sax_fastparser::FSHelperPtr pSerializer = m_pAttrOutput->GetSerializer( );
174 : // Level 9 disables the outline
175 : pSerializer->singleElementNS( XML_w, XML_outlineLvl,
176 : FSNS( XML_w, XML_val ), "9" ,
177 0 : FSEND );
178 :
179 0 : bRet = true;
180 : }
181 : }
182 : }
183 :
184 149 : return bRet;
185 : }
186 :
187 24 : void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
188 : const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ )
189 : {
190 : // headers
191 24 : if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
192 0 : WriteHeaderFooter( rLeftFmt, true, "even" );
193 :
194 24 : if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
195 0 : WriteHeaderFooter( rFmt, true, "default" );
196 :
197 24 : if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
198 0 : WriteHeaderFooter( rFirstPageFmt, true, "first" );
199 :
200 : // footers
201 24 : if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
202 0 : WriteHeaderFooter( rLeftFmt, false, "even" );
203 :
204 24 : if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
205 0 : WriteHeaderFooter( rFmt, false, "default" );
206 :
207 24 : if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
208 0 : WriteHeaderFooter( rFirstPageFmt, false, "first" );
209 :
210 24 : if ( nHeadFootFlags & ( nsHdFtFlags::WW8_FOOTER_EVEN | nsHdFtFlags::WW8_HEADER_EVEN ))
211 0 : settings.evenAndOddHeaders = true;
212 :
213 : #if OSL_DEBUG_LEVEL > 1
214 : fprintf( stderr, "DocxExport::WriteHeadersFooters() - nBreakCode introduced, but ignored\n" );
215 : #endif
216 24 : }
217 :
218 2 : void DocxExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
219 : {
220 2 : m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
221 2 : }
222 :
223 0 : void DocxExport::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
224 : {
225 0 : m_pAttrOutput->WriteFormData_Impl( rFieldmark );
226 0 : }
227 :
228 0 : void DocxExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
229 : {
230 : #if OSL_DEBUG_LEVEL > 1
231 : fprintf( stderr, "TODO DocxExport::WriteHyperlinkData()\n" );
232 : #endif
233 0 : }
234 :
235 0 : void DocxExport::DoComboBox(const rtl::OUString& rName,
236 : const rtl::OUString& rHelp,
237 : const rtl::OUString& rToolTip,
238 : const rtl::OUString& rSelected,
239 : uno::Sequence<rtl::OUString>& rListItems)
240 : {
241 0 : m_pDocumentFS->startElementNS( XML_w, XML_ffData, FSEND );
242 :
243 : m_pDocumentFS->singleElementNS( XML_w, XML_name,
244 : FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
245 0 : FSEND );
246 :
247 0 : m_pDocumentFS->singleElementNS( XML_w, XML_enabled, FSEND );
248 :
249 0 : if ( !rHelp.isEmpty() )
250 : m_pDocumentFS->singleElementNS( XML_w, XML_helpText,
251 : FSNS( XML_w, XML_val ), OUStringToOString( rHelp, RTL_TEXTENCODING_UTF8 ).getStr(),
252 0 : FSEND );
253 :
254 0 : if ( !rToolTip.isEmpty() )
255 : m_pDocumentFS->singleElementNS( XML_w, XML_statusText,
256 : FSNS( XML_w, XML_val ), OUStringToOString( rToolTip, RTL_TEXTENCODING_UTF8 ).getStr(),
257 0 : FSEND );
258 :
259 0 : m_pDocumentFS->startElementNS( XML_w, XML_ddList, FSEND );
260 :
261 : // Output the 0-based index of the selected value
262 0 : sal_uInt32 nListItems = rListItems.getLength();
263 0 : sal_Int32 nId = 0;
264 0 : sal_uInt32 nI = 0;
265 0 : while ( ( nI < nListItems ) && ( nId == 0 ) )
266 : {
267 0 : if ( rListItems[nI] == rSelected )
268 0 : nId = nI;
269 0 : nI++;
270 : }
271 :
272 : m_pDocumentFS->singleElementNS( XML_w, XML_result,
273 : FSNS( XML_w, XML_val ), rtl::OString::valueOf( nId ).getStr( ),
274 0 : FSEND );
275 :
276 : // Loop over the entries
277 :
278 0 : for (sal_uInt32 i = 0; i < nListItems; i++)
279 : {
280 : m_pDocumentFS->singleElementNS( XML_w, XML_listEntry,
281 0 : FSNS( XML_w, XML_val ), OUStringToOString( rListItems[i], RTL_TEXTENCODING_UTF8 ).getStr(),
282 0 : FSEND );
283 : }
284 :
285 0 : m_pDocumentFS->endElementNS( XML_w, XML_ddList );
286 :
287 0 : m_pDocumentFS->endElementNS( XML_w, XML_ffData );
288 0 : }
289 :
290 0 : void DocxExport::DoFormText(const SwInputField* /*pFld*/)
291 : {
292 : OSL_TRACE( "TODO DocxExport::ForFormText()" );
293 0 : }
294 :
295 0 : rtl::OString DocxExport::OutputChart( uno::Reference< frame::XModel >& xModel, sal_Int32 nCount )
296 : {
297 0 : OUString aFileName = "charts/chart" + OUString::valueOf(nCount) + ".xml";
298 : OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
299 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
300 0 : aFileName );
301 :
302 0 : aFileName = "word/charts/chart" + OUString::valueOf(nCount) + ".xml";
303 : ::sax_fastparser::FSHelperPtr pChartFS =
304 : m_pFilter->openFragmentStreamWithSerializer( aFileName,
305 0 : "application/vnd.openxmlformats-officedocument.drawingml.chart" );
306 :
307 0 : oox::drawingml::ChartExport aChartExport( XML_w, pChartFS, xModel, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
308 0 : aChartExport.ExportContent();
309 0 : return ::rtl::OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
310 : }
311 :
312 24 : void DocxExport::ExportDocument_Impl()
313 : {
314 24 : InitStyles();
315 :
316 : // init sections
317 24 : m_pSections = new MSWordSections( *this );
318 :
319 24 : WriteMainText();
320 :
321 24 : WriteFootnotesEndnotes();
322 :
323 24 : WritePostitFields();
324 :
325 24 : WriteNumbering();
326 :
327 24 : WriteFonts();
328 :
329 24 : WriteSettings();
330 :
331 24 : delete pStyles, pStyles = NULL;
332 24 : delete m_pSections, m_pSections = NULL;
333 24 : }
334 :
335 0 : void DocxExport::OutputPageSectionBreaks( const SwTxtNode& )
336 : {
337 : OSL_TRACE( "TODO DocxExport::OutputPageSectionBreaks( const SwTxtNode& )" );
338 0 : }
339 :
340 :
341 0 : void DocxExport::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
342 : {
343 0 : AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
344 0 : m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
345 0 : }
346 :
347 67 : void DocxExport::OutputEndNode( const SwEndNode& rEndNode )
348 : {
349 67 : MSWordExportBase::OutputEndNode( rEndNode );
350 :
351 67 : if ( TXT_MAINTEXT == nTxtTyp && rEndNode.StartOfSectionNode()->IsSectionNode() )
352 : {
353 : // this originally comes from WW8Export::WriteText(), and looks like it
354 : // could have some code common with SectionNode()...
355 :
356 0 : const SwSection& rSect = rEndNode.StartOfSectionNode()->GetSectionNode()->GetSection();
357 0 : if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
358 0 : bStartTOX = false;
359 :
360 0 : SwNodeIndex aIdx( rEndNode, 1 );
361 0 : const SwNode& rNd = aIdx.GetNode();
362 0 : if ( rNd.IsEndNode() && rNd.StartOfSectionNode()->IsSectionNode() )
363 67 : return;
364 :
365 0 : bool isInTable = IsInTable();
366 0 : if ( !rNd.IsSectionNode() && isInTable ) // No sections in table
367 : {
368 0 : const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
369 0 : if( !pParentFmt )
370 0 : pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
371 :
372 : sal_uLong nRstLnNum;
373 0 : if( rNd.IsCntntNode() )
374 0 : nRstLnNum = const_cast< SwCntntNode* >( rNd.GetCntntNode() )->GetSwAttrSet().GetLineNumber().GetStartValue();
375 : else
376 0 : nRstLnNum = 0;
377 :
378 0 : AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo( ) );
379 0 : m_pSections->AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
380 0 : }
381 : }
382 : }
383 :
384 0 : void DocxExport::OutputTableNode( const SwTableNode& )
385 : {
386 : OSL_TRACE( "TODO DocxExport::OutputTableNode( const SwTableNode& )" );
387 0 : }
388 :
389 0 : void DocxExport::OutputGrfNode( const SwGrfNode& )
390 : {
391 : OSL_TRACE( "TODO DocxExport::OutputGrfNode( const SwGrfNode& )" );
392 0 : }
393 :
394 0 : void DocxExport::OutputOLENode( const SwOLENode& )
395 : {
396 : OSL_TRACE( "TODO DocxExport::OutputOLENode( const SwOLENode& )" );
397 0 : }
398 :
399 0 : void DocxExport::OutputLinkedOLE( const OUString& )
400 : {
401 : // Nothing to implement here: WW8 only
402 0 : }
403 :
404 0 : sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
405 : {
406 : // Completely unused for Docx export... only here for code sharing
407 : // purpose with binary export
408 0 : return 0;
409 : }
410 :
411 0 : void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
412 : const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
413 : const SwPageDesc* pNewPgDesc )
414 : {
415 : // tell the attribute output that we are ready to write the section
416 : // break [has to be output inside paragraph properties]
417 0 : AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
418 :
419 0 : const SwSectionFmt* pFmt = GetSectionFormat( rNd );
420 0 : const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
421 :
422 : OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
423 :
424 0 : if ( pNewPgDescFmt )
425 : {
426 0 : m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
427 : }
428 0 : else if ( pNewPgDesc )
429 : {
430 0 : m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
431 : }
432 :
433 0 : }
434 :
435 24 : void DocxExport::InitStyles()
436 : {
437 24 : pStyles = new MSWordStyles( *this );
438 :
439 : // setup word/styles.xml and the relations + content type
440 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
441 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
442 24 : "styles.xml" );
443 :
444 : ::sax_fastparser::FSHelperPtr pStylesFS =
445 : m_pFilter->openFragmentStreamWithSerializer( "word/styles.xml",
446 24 : "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" );
447 :
448 : // switch the serializer to redirect the output to word/styles.xml
449 24 : m_pAttrOutput->SetSerializer( pStylesFS );
450 :
451 : // do the work
452 24 : pStyles->OutputStylesTable();
453 :
454 : // switch the serializer back
455 24 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
456 24 : }
457 :
458 24 : void DocxExport::WriteFootnotesEndnotes()
459 : {
460 24 : if ( m_pAttrOutput->HasFootnotes() )
461 : {
462 : // setup word/styles.xml and the relations + content type
463 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
464 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
465 0 : "footnotes.xml" );
466 :
467 : ::sax_fastparser::FSHelperPtr pFootnotesFS =
468 : m_pFilter->openFragmentStreamWithSerializer( "word/footnotes.xml",
469 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" );
470 :
471 : // switch the serializer to redirect the output to word/footnotes.xml
472 0 : m_pAttrOutput->SetSerializer( pFootnotesFS );
473 :
474 : // do the work
475 0 : m_pAttrOutput->FootnotesEndnotes( true );
476 :
477 : // switch the serializer back
478 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
479 : }
480 :
481 24 : if ( m_pAttrOutput->HasEndnotes() )
482 : {
483 : // setup word/styles.xml and the relations + content type
484 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
485 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
486 0 : "endnotes.xml" );
487 :
488 : ::sax_fastparser::FSHelperPtr pEndnotesFS =
489 : m_pFilter->openFragmentStreamWithSerializer( "word/endnotes.xml",
490 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" );
491 :
492 : // switch the serializer to redirect the output to word/endnotes.xml
493 0 : m_pAttrOutput->SetSerializer( pEndnotesFS );
494 :
495 : // do the work
496 0 : m_pAttrOutput->FootnotesEndnotes( false );
497 :
498 : // switch the serializer back
499 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
500 : }
501 24 : }
502 :
503 24 : void DocxExport::WritePostitFields()
504 : {
505 24 : if ( m_pAttrOutput->HasPostitFields() )
506 : {
507 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
508 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
509 1 : "comments.xml" );
510 :
511 : ::sax_fastparser::FSHelperPtr pPostitFS =
512 : m_pFilter->openFragmentStreamWithSerializer( "word/comments.xml",
513 1 : "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" );
514 :
515 1 : pPostitFS->startElementNS( XML_w, XML_comments, MainXmlNamespaces( pPostitFS ));
516 1 : m_pAttrOutput->SetSerializer( pPostitFS );
517 1 : m_pAttrOutput->WritePostitFields();
518 1 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
519 1 : pPostitFS->endElementNS( XML_w, XML_comments );
520 : }
521 24 : }
522 :
523 24 : void DocxExport::WriteNumbering()
524 : {
525 24 : if ( !pUsedNumTbl )
526 24 : return; // no numbering is used
527 :
528 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
529 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
530 0 : "numbering.xml" );
531 :
532 : ::sax_fastparser::FSHelperPtr pNumberingFS = m_pFilter->openFragmentStreamWithSerializer( "word/numbering.xml",
533 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" );
534 :
535 : // switch the serializer to redirect the output to word/nubering.xml
536 0 : m_pAttrOutput->SetSerializer( pNumberingFS );
537 :
538 : pNumberingFS->startElementNS( XML_w, XML_numbering,
539 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
540 0 : FSEND );
541 :
542 0 : AbstractNumberingDefinitions();
543 :
544 0 : NumberingDefinitions();
545 :
546 0 : pNumberingFS->endElementNS( XML_w, XML_numbering );
547 :
548 : // switch the serializer back
549 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
550 : }
551 :
552 0 : void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* pType )
553 : {
554 : // setup the xml stream
555 0 : OUString aRelId;
556 0 : ::sax_fastparser::FSHelperPtr pFS;
557 0 : if ( bHeader )
558 : {
559 0 : OUString aName( OUStringBuffer().append("header").append( ++m_nHeaders ).append(".xml").makeStringAndClear() );
560 :
561 : aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
562 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
563 0 : aName );
564 :
565 0 : pFS = m_pFilter->openFragmentStreamWithSerializer( OUStringBuffer().append("word/").append( aName ).makeStringAndClear(),
566 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" );
567 :
568 0 : pFS->startElementNS( XML_w, XML_hdr, MainXmlNamespaces( pFS ));
569 : }
570 : else
571 : {
572 0 : OUString aName( OUStringBuffer().append("footer").append( ++m_nFooters ).append(".xml").makeStringAndClear() );
573 :
574 : aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
575 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
576 0 : aName );
577 :
578 0 : pFS = m_pFilter->openFragmentStreamWithSerializer( OUStringBuffer().append("word/").append( aName ).makeStringAndClear(),
579 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" );
580 :
581 0 : pFS->startElementNS( XML_w, XML_ftr, MainXmlNamespaces( pFS ));
582 : }
583 :
584 : // switch the serializer to redirect the output to word/styles.xml
585 0 : m_pAttrOutput->SetSerializer( pFS );
586 :
587 : // do the work
588 0 : WriteHeaderFooterText( rFmt, bHeader );
589 :
590 : // switch the serializer back
591 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
592 :
593 : // close the tag
594 : sal_Int32 nReference;
595 0 : if ( bHeader )
596 : {
597 0 : pFS->endElementNS( XML_w, XML_hdr );
598 0 : nReference = XML_headerReference;
599 : }
600 : else
601 : {
602 0 : pFS->endElementNS( XML_w, XML_ftr );
603 0 : nReference = XML_footerReference;
604 : }
605 :
606 : // and write the reference
607 : m_pDocumentFS->singleElementNS( XML_w, nReference,
608 : FSNS( XML_w, XML_type ), pType,
609 : FSNS( XML_r, XML_id ), rtl::OUStringToOString( aRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
610 0 : FSEND );
611 0 : }
612 :
613 24 : void DocxExport::WriteFonts()
614 : {
615 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
616 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
617 24 : "fontTable.xml" );
618 :
619 : ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer(
620 : "word/fontTable.xml",
621 24 : "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" );
622 :
623 : pFS->startElementNS( XML_w, XML_fonts,
624 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
625 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
626 24 : FSEND );
627 :
628 : // switch the serializer to redirect the output to word/styles.xml
629 24 : m_pAttrOutput->SetSerializer( pFS );
630 :
631 : // do the work
632 24 : maFontHelper.WriteFontTable( *m_pAttrOutput );
633 :
634 : // switch the serializer back
635 24 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
636 :
637 24 : pFS->endElementNS( XML_w, XML_fonts );
638 24 : }
639 :
640 :
641 24 : void DocxExport::WriteProperties( )
642 : {
643 : // Write the core properties
644 24 : SwDocShell* pDocShell( pDoc->GetDocShell( ) );
645 24 : uno::Reference<document::XDocumentProperties> xDocProps;
646 24 : if ( pDocShell )
647 : {
648 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
649 24 : pDocShell->GetModel( ), uno::UNO_QUERY );
650 24 : xDocProps = xDPS->getDocumentProperties();
651 : }
652 :
653 24 : m_pFilter->exportDocumentProperties( xDocProps );
654 24 : }
655 :
656 24 : void DocxExport::WriteSettings()
657 : {
658 24 : ViewShell *pViewShell(pDoc->GetCurrentViewShell());
659 24 : if( !pViewShell && !settings.hasData() && !m_pAttrOutput->HasFootnotes() && !m_pAttrOutput->HasEndnotes())
660 24 : return;
661 :
662 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
663 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
664 24 : "settings.xml" );
665 :
666 : ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer(
667 : "word/settings.xml",
668 24 : "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" );
669 :
670 : pFS->startElementNS( XML_w, XML_settings,
671 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
672 24 : FSEND );
673 :
674 : // Zoom
675 24 : rtl::OString aZoom(rtl::OString::valueOf(sal_Int32(pViewShell->GetViewOptions()->GetZoom())));
676 24 : pFS->singleElementNS(XML_w, XML_zoom, FSNS(XML_w, XML_percent), aZoom.getStr(), FSEND);
677 24 : if( pDoc->get( IDocumentSettingAccess::EMBED_FONTS ))
678 0 : pFS->singleElementNS( XML_w, XML_embedTrueTypeFonts, FSEND );
679 24 : if( pDoc->get( IDocumentSettingAccess::EMBED_SYSTEM_FONTS ))
680 1 : pFS->singleElementNS( XML_w, XML_embedSystemFonts, FSEND );
681 24 : if( settings.defaultTabStop != 0 )
682 : pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ),
683 10 : rtl::OString::valueOf( sal_Int32( settings.defaultTabStop )).getStr(), FSEND );
684 24 : if( settings.evenAndOddHeaders )
685 0 : pFS->singleElementNS( XML_w, XML_evenAndOddHeaders, FSEND );
686 :
687 24 : if( m_pAttrOutput->HasFootnotes())
688 0 : m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_footnotePr, pDoc->GetFtnInfo(), XML_footnote );
689 24 : if( m_pAttrOutput->HasEndnotes())
690 0 : m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_endnotePr, pDoc->GetEndNoteInfo(), XML_endnote );
691 :
692 24 : pFS->endElementNS( XML_w, XML_settings );
693 : }
694 :
695 0 : VMLExport& DocxExport::VMLExporter()
696 : {
697 0 : return *m_pVMLExport;
698 : }
699 :
700 24 : void DocxExport::WriteMainText()
701 : {
702 : // setup the namespaces
703 24 : m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces( m_pDocumentFS ));
704 :
705 : // body
706 24 : m_pDocumentFS->startElementNS( XML_w, XML_body, FSEND );
707 :
708 24 : pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
709 :
710 : // the text
711 24 : WriteText();
712 :
713 : // the last section info
714 24 : const WW8_SepInfo *pSectionInfo = m_pSections? m_pSections->CurrentSectionInfo(): NULL;
715 24 : if ( pSectionInfo )
716 24 : SectionProperties( *pSectionInfo );
717 :
718 : // finish body and document
719 24 : m_pDocumentFS->endElementNS( XML_w, XML_body );
720 24 : m_pDocumentFS->endElementNS( XML_w, XML_document );
721 24 : }
722 :
723 25 : XFastAttributeListRef DocxExport::MainXmlNamespaces( FSHelperPtr serializer )
724 : {
725 25 : FastAttributeList* pAttr = serializer->createAttrList();
726 25 : pAttr->add( FSNS( XML_xmlns, XML_o ), "urn:schemas-microsoft-com:office:office" );
727 25 : pAttr->add( FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships" );
728 25 : pAttr->add( FSNS( XML_xmlns, XML_v ), "urn:schemas-microsoft-com:vml" );
729 25 : pAttr->add( FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main" );
730 25 : pAttr->add( FSNS( XML_xmlns, XML_w10 ), "urn:schemas-microsoft-com:office:word" );
731 25 : pAttr->add( FSNS( XML_xmlns, XML_wp ), "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" );
732 25 : return XFastAttributeListRef( pAttr );
733 : }
734 :
735 411 : bool DocxExport::ignoreAttributeForStyles( sal_uInt16 nWhich ) const
736 : {
737 411 : if( nWhich == RES_TEXTGRID )
738 0 : return true; // w:docGrid is written only to document.xml, not to styles.xml
739 411 : return MSWordExportBase::ignoreAttributeForStyles( nWhich );
740 : }
741 :
742 1 : void DocxExport::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp)
743 : {
744 1 : const EditTextObject& rEditObj = rParaObj.GetTextObject();
745 1 : MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
746 :
747 1 : sal_uInt16 nPara = rEditObj.GetParagraphCount();
748 2 : for( sal_uInt16 n = 0; n < nPara; ++n )
749 : {
750 1 : if( n )
751 0 : aAttrIter.NextPara( n );
752 :
753 1 : AttrOutput().StartParagraph( ww8::WW8TableNodeInfo::Pointer_t());
754 1 : rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
755 1 : String aStr( rEditObj.GetText( n ));
756 1 : xub_StrLen nAktPos = 0;
757 1 : xub_StrLen nEnd = aStr.Len();
758 1 : do {
759 1 : AttrOutput().StartRun( NULL );
760 1 : xub_StrLen nNextAttr = aAttrIter.WhereNext();
761 1 : rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
762 :
763 1 : if( nNextAttr > nEnd )
764 1 : nNextAttr = nEnd;
765 :
766 1 : bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
767 1 : if( !bTxtAtr )
768 : {
769 1 : if( nAktPos == 0 && nNextAttr - nAktPos == aStr.Len())
770 1 : AttrOutput().RunText( aStr, eChrSet );
771 : else
772 : {
773 0 : String tmp( aStr.Copy( nAktPos, nNextAttr - nAktPos ));
774 0 : AttrOutput().RunText( tmp, eChrSet );
775 : }
776 : }
777 1 : AttrOutput().StartRunProperties();
778 1 : aAttrIter.OutAttr( nAktPos );
779 1 : AttrOutput().EndRunProperties( NULL );
780 :
781 1 : nAktPos = nNextAttr;
782 1 : eChrSet = eNextChrSet;
783 1 : aAttrIter.NextPos();
784 1 : AttrOutput().EndRun();
785 : } while( nAktPos < nEnd );
786 : // aAttrIter.OutParaAttr(false);
787 1 : AttrOutput().EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t());
788 2 : }
789 1 : }
790 :
791 24 : DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
792 : : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
793 : m_pFilter( pFilter ),
794 : m_pAttrOutput( NULL ),
795 : m_pSections( NULL ),
796 : m_nHeaders( 0 ),
797 : m_nFooters( 0 ),
798 24 : m_pVMLExport( NULL )
799 : {
800 : // Write the document properies
801 24 : WriteProperties( );
802 :
803 : // relations for the document
804 : m_pFilter->addRelation( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
805 24 : "word/document.xml" );
806 :
807 : // the actual document
808 : m_pDocumentFS = m_pFilter->openFragmentStreamWithSerializer( "word/document.xml",
809 24 : "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" );
810 :
811 : // the DrawingML access
812 24 : m_pDrawingML = new oox::drawingml::DrawingML( m_pDocumentFS, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
813 :
814 : // the attribute output for the document
815 24 : m_pAttrOutput = new DocxAttributeOutput( *this, m_pDocumentFS, m_pDrawingML );
816 :
817 : // the related VMLExport
818 24 : m_pVMLExport = new VMLExport( m_pDocumentFS, m_pAttrOutput );
819 24 : }
820 :
821 48 : DocxExport::~DocxExport()
822 : {
823 24 : delete m_pVMLExport, m_pVMLExport = NULL;
824 24 : delete m_pAttrOutput, m_pAttrOutput = NULL;
825 24 : delete m_pDrawingML, m_pDrawingML = NULL;
826 24 : }
827 :
828 24 : DocxSettingsData::DocxSettingsData()
829 : : evenAndOddHeaders( false )
830 24 : , defaultTabStop( 0 )
831 : {
832 24 : }
833 :
834 0 : bool DocxSettingsData::hasData() const
835 : {
836 0 : if( evenAndOddHeaders )
837 0 : return true;
838 0 : if( defaultTabStop != 0 )
839 0 : return true;
840 0 : return false;
841 18 : }
842 :
843 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|