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 8432 : AttributeOutputBase& DocxExport::AttrOutput() const
74 : {
75 8432 : return *m_pAttrOutput;
76 : }
77 :
78 0 : MSWordSections& DocxExport::Sections() const
79 : {
80 0 : return *m_pSections;
81 : }
82 :
83 1866 : 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 1866 : 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 1866 : else if ( nScript != i18n::ScriptType::COMPLEX )
101 : {
102 : // for western in ww8, there is only one fontsize
103 : // and one fontstyle (posture/weight)
104 1866 : switch ( nWhich )
105 : {
106 : case RES_CHRATR_CJK_FONTSIZE:
107 : case RES_CHRATR_CJK_POSTURE:
108 : case RES_CHRATR_CJK_WEIGHT:
109 310 : return false;
110 : default:
111 1556 : break;
112 : }
113 : }
114 1556 : return true;
115 : }
116 :
117 388 : void DocxExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
118 : {
119 388 : std::vector< OUString > aStarts;
120 388 : std::vector< OUString > aEnds;
121 :
122 388 : IMarkVector aMarks;
123 388 : if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
124 : {
125 20 : for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
126 : it != end; ++it )
127 : {
128 10 : IMark* pMark = (*it);
129 :
130 10 : xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
131 10 : xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
132 :
133 10 : if ( nStart == nAktPos )
134 6 : aStarts.push_back( pMark->GetName() );
135 :
136 10 : if ( nEnd == nAktPos )
137 6 : aEnds.push_back( pMark->GetName() );
138 : }
139 : }
140 :
141 388 : m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
142 388 : }
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 298 : bool DocxExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
164 : {
165 298 : bool bRet( false );
166 :
167 298 : if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
168 : {
169 298 : if (const SwFmt *pParent = rFmt.DerivedFrom())
170 : {
171 298 : 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 298 : return bRet;
185 : }
186 :
187 48 : void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
188 : const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ )
189 : {
190 : // headers
191 48 : if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
192 0 : WriteHeaderFooter( rLeftFmt, true, "even" );
193 :
194 48 : if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
195 0 : WriteHeaderFooter( rFmt, true, "default" );
196 :
197 48 : if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
198 0 : WriteHeaderFooter( rFirstPageFmt, true, "first" );
199 :
200 : // footers
201 48 : if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
202 0 : WriteHeaderFooter( rLeftFmt, false, "even" );
203 :
204 48 : if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
205 0 : WriteHeaderFooter( rFmt, false, "default" );
206 :
207 48 : if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
208 0 : WriteHeaderFooter( rFirstPageFmt, false, "first" );
209 :
210 48 : 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 48 : }
217 :
218 4 : void DocxExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
219 : {
220 4 : m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
221 4 : }
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 : rtl::OUString aFileName = rtl::OUStringBuffer().append("charts/chart").append(nCount).append(".xml").makeStringAndClear();
298 :
299 : OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
300 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
301 0 : aFileName );
302 :
303 0 : aFileName = rtl::OUStringBuffer().append("word/charts/chart").append(nCount).append(".xml").makeStringAndClear();
304 :
305 : ::sax_fastparser::FSHelperPtr pChartFS =
306 : m_pFilter->openFragmentStreamWithSerializer( aFileName,
307 0 : "application/vnd.openxmlformats-officedocument.drawingml.chart" );
308 :
309 0 : oox::drawingml::ChartExport aChartExport( XML_w, pChartFS, xModel, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
310 0 : aChartExport.ExportContent();
311 0 : return ::rtl::OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
312 : }
313 :
314 48 : void DocxExport::ExportDocument_Impl()
315 : {
316 48 : InitStyles();
317 :
318 : // init sections
319 48 : m_pSections = new MSWordSections( *this );
320 :
321 48 : WriteMainText();
322 :
323 48 : WriteFootnotesEndnotes();
324 :
325 48 : WritePostitFields();
326 :
327 48 : WriteNumbering();
328 :
329 48 : WriteFonts();
330 :
331 48 : WriteSettings();
332 :
333 48 : delete pStyles, pStyles = NULL;
334 48 : delete m_pSections, m_pSections = NULL;
335 48 : }
336 :
337 0 : void DocxExport::OutputPageSectionBreaks( const SwTxtNode& )
338 : {
339 : OSL_TRACE( "TODO DocxExport::OutputPageSectionBreaks( const SwTxtNode& )" );
340 0 : }
341 :
342 :
343 0 : void DocxExport::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
344 : {
345 0 : AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
346 0 : m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
347 0 : }
348 :
349 134 : void DocxExport::OutputEndNode( const SwEndNode& rEndNode )
350 : {
351 134 : MSWordExportBase::OutputEndNode( rEndNode );
352 :
353 134 : if ( TXT_MAINTEXT == nTxtTyp && rEndNode.StartOfSectionNode()->IsSectionNode() )
354 : {
355 : // this originally comes from WW8Export::WriteText(), and looks like it
356 : // could have some code common with SectionNode()...
357 :
358 0 : const SwSection& rSect = rEndNode.StartOfSectionNode()->GetSectionNode()->GetSection();
359 0 : if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
360 0 : bStartTOX = false;
361 :
362 0 : SwNodeIndex aIdx( rEndNode, 1 );
363 0 : const SwNode& rNd = aIdx.GetNode();
364 0 : if ( rNd.IsEndNode() && rNd.StartOfSectionNode()->IsSectionNode() )
365 134 : return;
366 :
367 0 : bool isInTable = IsInTable();
368 0 : if ( !rNd.IsSectionNode() && isInTable ) // No sections in table
369 : {
370 0 : const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
371 0 : if( !pParentFmt )
372 0 : pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
373 :
374 : sal_uLong nRstLnNum;
375 0 : if( rNd.IsCntntNode() )
376 0 : nRstLnNum = const_cast< SwCntntNode* >( rNd.GetCntntNode() )->GetSwAttrSet().GetLineNumber().GetStartValue();
377 : else
378 0 : nRstLnNum = 0;
379 :
380 0 : AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo( ) );
381 0 : m_pSections->AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
382 0 : }
383 : }
384 : }
385 :
386 0 : void DocxExport::OutputTableNode( const SwTableNode& )
387 : {
388 : OSL_TRACE( "TODO DocxExport::OutputTableNode( const SwTableNode& )" );
389 0 : }
390 :
391 0 : void DocxExport::OutputGrfNode( const SwGrfNode& )
392 : {
393 : OSL_TRACE( "TODO DocxExport::OutputGrfNode( const SwGrfNode& )" );
394 0 : }
395 :
396 0 : void DocxExport::OutputOLENode( const SwOLENode& )
397 : {
398 : OSL_TRACE( "TODO DocxExport::OutputOLENode( const SwOLENode& )" );
399 0 : }
400 :
401 0 : void DocxExport::OutputLinkedOLE( const OUString& )
402 : {
403 : // Nothing to implement here: WW8 only
404 0 : }
405 :
406 0 : sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
407 : {
408 : // Completely unused for Docx export... only here for code sharing
409 : // purpose with binary export
410 0 : return 0;
411 : }
412 :
413 0 : void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
414 : const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
415 : const SwPageDesc* pNewPgDesc )
416 : {
417 : // tell the attribute output that we are ready to write the section
418 : // break [has to be output inside paragraph properties]
419 0 : AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
420 :
421 0 : const SwSectionFmt* pFmt = GetSectionFormat( rNd );
422 0 : const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
423 :
424 : OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
425 :
426 0 : if ( pNewPgDescFmt )
427 : {
428 0 : m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
429 : }
430 0 : else if ( pNewPgDesc )
431 : {
432 0 : m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
433 : }
434 :
435 0 : }
436 :
437 48 : void DocxExport::InitStyles()
438 : {
439 48 : pStyles = new MSWordStyles( *this );
440 :
441 : // setup word/styles.xml and the relations + content type
442 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
443 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
444 48 : "styles.xml" );
445 :
446 : ::sax_fastparser::FSHelperPtr pStylesFS =
447 : m_pFilter->openFragmentStreamWithSerializer( "word/styles.xml",
448 48 : "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" );
449 :
450 : // switch the serializer to redirect the output to word/styles.xml
451 48 : m_pAttrOutput->SetSerializer( pStylesFS );
452 :
453 : // do the work
454 48 : pStyles->OutputStylesTable();
455 :
456 : // switch the serializer back
457 48 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
458 48 : }
459 :
460 48 : void DocxExport::WriteFootnotesEndnotes()
461 : {
462 48 : if ( m_pAttrOutput->HasFootnotes() )
463 : {
464 : // setup word/styles.xml and the relations + content type
465 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
466 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
467 0 : "footnotes.xml" );
468 :
469 : ::sax_fastparser::FSHelperPtr pFootnotesFS =
470 : m_pFilter->openFragmentStreamWithSerializer( "word/footnotes.xml",
471 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" );
472 :
473 : // switch the serializer to redirect the output to word/footnotes.xml
474 0 : m_pAttrOutput->SetSerializer( pFootnotesFS );
475 :
476 : // do the work
477 0 : m_pAttrOutput->FootnotesEndnotes( true );
478 :
479 : // switch the serializer back
480 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
481 : }
482 :
483 48 : if ( m_pAttrOutput->HasEndnotes() )
484 : {
485 : // setup word/styles.xml and the relations + content type
486 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
487 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",
488 0 : "endnotes.xml" );
489 :
490 : ::sax_fastparser::FSHelperPtr pEndnotesFS =
491 : m_pFilter->openFragmentStreamWithSerializer( "word/endnotes.xml",
492 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" );
493 :
494 : // switch the serializer to redirect the output to word/endnotes.xml
495 0 : m_pAttrOutput->SetSerializer( pEndnotesFS );
496 :
497 : // do the work
498 0 : m_pAttrOutput->FootnotesEndnotes( false );
499 :
500 : // switch the serializer back
501 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
502 : }
503 48 : }
504 :
505 48 : void DocxExport::WritePostitFields()
506 : {
507 48 : if ( m_pAttrOutput->HasPostitFields() )
508 : {
509 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
510 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
511 2 : "comments.xml" );
512 :
513 : ::sax_fastparser::FSHelperPtr pPostitFS =
514 : m_pFilter->openFragmentStreamWithSerializer( "word/comments.xml",
515 2 : "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" );
516 :
517 2 : pPostitFS->startElementNS( XML_w, XML_comments, MainXmlNamespaces( pPostitFS ));
518 2 : m_pAttrOutput->SetSerializer( pPostitFS );
519 2 : m_pAttrOutput->WritePostitFields();
520 2 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
521 2 : pPostitFS->endElementNS( XML_w, XML_comments );
522 : }
523 48 : }
524 :
525 48 : void DocxExport::WriteNumbering()
526 : {
527 48 : if ( !pUsedNumTbl )
528 48 : return; // no numbering is used
529 :
530 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
531 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
532 0 : "numbering.xml" );
533 :
534 : ::sax_fastparser::FSHelperPtr pNumberingFS = m_pFilter->openFragmentStreamWithSerializer( "word/numbering.xml",
535 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" );
536 :
537 : // switch the serializer to redirect the output to word/nubering.xml
538 0 : m_pAttrOutput->SetSerializer( pNumberingFS );
539 :
540 : pNumberingFS->startElementNS( XML_w, XML_numbering,
541 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
542 0 : FSEND );
543 :
544 0 : AbstractNumberingDefinitions();
545 :
546 0 : NumberingDefinitions();
547 :
548 0 : pNumberingFS->endElementNS( XML_w, XML_numbering );
549 :
550 : // switch the serializer back
551 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
552 : }
553 :
554 0 : void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* pType )
555 : {
556 : // setup the xml stream
557 0 : OUString aRelId;
558 0 : ::sax_fastparser::FSHelperPtr pFS;
559 0 : if ( bHeader )
560 : {
561 0 : OUString aName( OUStringBuffer().append("header").append( ++m_nHeaders ).append(".xml").makeStringAndClear() );
562 :
563 : aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
564 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
565 0 : aName );
566 :
567 0 : pFS = m_pFilter->openFragmentStreamWithSerializer( OUStringBuffer().append("word/").append( aName ).makeStringAndClear(),
568 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" );
569 :
570 0 : pFS->startElementNS( XML_w, XML_hdr, MainXmlNamespaces( pFS ));
571 : }
572 : else
573 : {
574 0 : OUString aName( OUStringBuffer().append("footer").append( ++m_nFooters ).append(".xml").makeStringAndClear() );
575 :
576 : aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
577 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
578 0 : aName );
579 :
580 0 : pFS = m_pFilter->openFragmentStreamWithSerializer( OUStringBuffer().append("word/").append( aName ).makeStringAndClear(),
581 0 : "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" );
582 :
583 0 : pFS->startElementNS( XML_w, XML_ftr, MainXmlNamespaces( pFS ));
584 : }
585 :
586 : // switch the serializer to redirect the output to word/styles.xml
587 0 : m_pAttrOutput->SetSerializer( pFS );
588 :
589 : // do the work
590 0 : WriteHeaderFooterText( rFmt, bHeader );
591 :
592 : // switch the serializer back
593 0 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
594 :
595 : // close the tag
596 : sal_Int32 nReference;
597 0 : if ( bHeader )
598 : {
599 0 : pFS->endElementNS( XML_w, XML_hdr );
600 0 : nReference = XML_headerReference;
601 : }
602 : else
603 : {
604 0 : pFS->endElementNS( XML_w, XML_ftr );
605 0 : nReference = XML_footerReference;
606 : }
607 :
608 : // and write the reference
609 : m_pDocumentFS->singleElementNS( XML_w, nReference,
610 : FSNS( XML_w, XML_type ), pType,
611 : FSNS( XML_r, XML_id ), rtl::OUStringToOString( aRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
612 0 : FSEND );
613 0 : }
614 :
615 48 : void DocxExport::WriteFonts()
616 : {
617 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
618 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
619 48 : "fontTable.xml" );
620 :
621 : ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer(
622 : "word/fontTable.xml",
623 48 : "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" );
624 :
625 : pFS->startElementNS( XML_w, XML_fonts,
626 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
627 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
628 48 : FSEND );
629 :
630 : // switch the serializer to redirect the output to word/styles.xml
631 48 : m_pAttrOutput->SetSerializer( pFS );
632 :
633 : // do the work
634 48 : maFontHelper.WriteFontTable( *m_pAttrOutput );
635 :
636 : // switch the serializer back
637 48 : m_pAttrOutput->SetSerializer( m_pDocumentFS );
638 :
639 48 : pFS->endElementNS( XML_w, XML_fonts );
640 48 : }
641 :
642 :
643 48 : void DocxExport::WriteProperties( )
644 : {
645 : // Write the core properties
646 48 : SwDocShell* pDocShell( pDoc->GetDocShell( ) );
647 48 : uno::Reference<document::XDocumentProperties> xDocProps;
648 48 : if ( pDocShell )
649 : {
650 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
651 48 : pDocShell->GetModel( ), uno::UNO_QUERY );
652 48 : xDocProps = xDPS->getDocumentProperties();
653 : }
654 :
655 48 : m_pFilter->exportDocumentProperties( xDocProps );
656 48 : }
657 :
658 48 : void DocxExport::WriteSettings()
659 : {
660 48 : ViewShell *pViewShell(pDoc->GetCurrentViewShell());
661 48 : if( !pViewShell && !settings.hasData() && !m_pAttrOutput->HasFootnotes() && !m_pAttrOutput->HasEndnotes())
662 48 : return;
663 :
664 : m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
665 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
666 48 : "settings.xml" );
667 :
668 : ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer(
669 : "word/settings.xml",
670 48 : "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" );
671 :
672 : pFS->startElementNS( XML_w, XML_settings,
673 : FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
674 48 : FSEND );
675 :
676 : // Zoom
677 48 : rtl::OString aZoom(rtl::OString::valueOf(sal_Int32(pViewShell->GetViewOptions()->GetZoom())));
678 48 : pFS->singleElementNS(XML_w, XML_zoom, FSNS(XML_w, XML_percent), aZoom.getStr(), FSEND);
679 48 : if( pDoc->get( IDocumentSettingAccess::EMBED_FONTS ))
680 0 : pFS->singleElementNS( XML_w, XML_embedTrueTypeFonts, FSEND );
681 48 : if( pDoc->get( IDocumentSettingAccess::EMBED_SYSTEM_FONTS ))
682 2 : pFS->singleElementNS( XML_w, XML_embedSystemFonts, FSEND );
683 48 : if( settings.defaultTabStop != 0 )
684 : pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ),
685 20 : rtl::OString::valueOf( sal_Int32( settings.defaultTabStop )).getStr(), FSEND );
686 48 : if( settings.evenAndOddHeaders )
687 0 : pFS->singleElementNS( XML_w, XML_evenAndOddHeaders, FSEND );
688 :
689 48 : if( m_pAttrOutput->HasFootnotes())
690 0 : m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_footnotePr, pDoc->GetFtnInfo(), XML_footnote );
691 48 : if( m_pAttrOutput->HasEndnotes())
692 0 : m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_endnotePr, pDoc->GetEndNoteInfo(), XML_endnote );
693 :
694 48 : pFS->endElementNS( XML_w, XML_settings );
695 : }
696 :
697 0 : VMLExport& DocxExport::VMLExporter()
698 : {
699 0 : return *m_pVMLExport;
700 : }
701 :
702 48 : void DocxExport::WriteMainText()
703 : {
704 : // setup the namespaces
705 48 : m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces( m_pDocumentFS ));
706 :
707 : // body
708 48 : m_pDocumentFS->startElementNS( XML_w, XML_body, FSEND );
709 :
710 48 : pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
711 :
712 : // the text
713 48 : WriteText();
714 :
715 : // the last section info
716 48 : const WW8_SepInfo *pSectionInfo = m_pSections? m_pSections->CurrentSectionInfo(): NULL;
717 48 : if ( pSectionInfo )
718 48 : SectionProperties( *pSectionInfo );
719 :
720 : // finish body and document
721 48 : m_pDocumentFS->endElementNS( XML_w, XML_body );
722 48 : m_pDocumentFS->endElementNS( XML_w, XML_document );
723 48 : }
724 :
725 50 : XFastAttributeListRef DocxExport::MainXmlNamespaces( FSHelperPtr serializer )
726 : {
727 50 : FastAttributeList* pAttr = serializer->createAttrList();
728 50 : pAttr->add( FSNS( XML_xmlns, XML_o ), "urn:schemas-microsoft-com:office:office" );
729 50 : pAttr->add( FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships" );
730 50 : pAttr->add( FSNS( XML_xmlns, XML_v ), "urn:schemas-microsoft-com:vml" );
731 50 : pAttr->add( FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main" );
732 50 : pAttr->add( FSNS( XML_xmlns, XML_w10 ), "urn:schemas-microsoft-com:office:word" );
733 50 : pAttr->add( FSNS( XML_xmlns, XML_wp ), "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" );
734 50 : return XFastAttributeListRef( pAttr );
735 : }
736 :
737 822 : bool DocxExport::ignoreAttributeForStyles( sal_uInt16 nWhich ) const
738 : {
739 822 : if( nWhich == RES_TEXTGRID )
740 0 : return true; // w:docGrid is written only to document.xml, not to styles.xml
741 822 : return MSWordExportBase::ignoreAttributeForStyles( nWhich );
742 : }
743 :
744 2 : void DocxExport::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp)
745 : {
746 2 : const EditTextObject& rEditObj = rParaObj.GetTextObject();
747 2 : MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
748 :
749 2 : sal_uInt16 nPara = rEditObj.GetParagraphCount();
750 4 : for( sal_uInt16 n = 0; n < nPara; ++n )
751 : {
752 2 : if( n )
753 0 : aAttrIter.NextPara( n );
754 :
755 2 : AttrOutput().StartParagraph( ww8::WW8TableNodeInfo::Pointer_t());
756 2 : rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
757 2 : String aStr( rEditObj.GetText( n ));
758 2 : xub_StrLen nAktPos = 0;
759 2 : xub_StrLen nEnd = aStr.Len();
760 2 : do {
761 2 : AttrOutput().StartRun( NULL );
762 2 : xub_StrLen nNextAttr = aAttrIter.WhereNext();
763 2 : rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
764 :
765 2 : if( nNextAttr > nEnd )
766 2 : nNextAttr = nEnd;
767 :
768 2 : bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
769 2 : if( !bTxtAtr )
770 : {
771 2 : if( nAktPos == 0 && nNextAttr - nAktPos == aStr.Len())
772 2 : AttrOutput().RunText( aStr, eChrSet );
773 : else
774 : {
775 0 : String tmp( aStr.Copy( nAktPos, nNextAttr - nAktPos ));
776 0 : AttrOutput().RunText( tmp, eChrSet );
777 : }
778 : }
779 2 : AttrOutput().StartRunProperties();
780 2 : aAttrIter.OutAttr( nAktPos );
781 2 : AttrOutput().EndRunProperties( NULL );
782 :
783 2 : nAktPos = nNextAttr;
784 2 : eChrSet = eNextChrSet;
785 2 : aAttrIter.NextPos();
786 2 : AttrOutput().EndRun();
787 : } while( nAktPos < nEnd );
788 : // aAttrIter.OutParaAttr(false);
789 2 : AttrOutput().EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t());
790 4 : }
791 2 : }
792 :
793 48 : DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
794 : : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
795 : m_pFilter( pFilter ),
796 : m_pAttrOutput( NULL ),
797 : m_pSections( NULL ),
798 : m_nHeaders( 0 ),
799 : m_nFooters( 0 ),
800 48 : m_pVMLExport( NULL )
801 : {
802 : // Write the document properies
803 48 : WriteProperties( );
804 :
805 : // relations for the document
806 : m_pFilter->addRelation( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
807 48 : "word/document.xml" );
808 :
809 : // the actual document
810 : m_pDocumentFS = m_pFilter->openFragmentStreamWithSerializer( "word/document.xml",
811 48 : "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" );
812 :
813 : // the DrawingML access
814 48 : m_pDrawingML = new oox::drawingml::DrawingML( m_pDocumentFS, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
815 :
816 : // the attribute output for the document
817 48 : m_pAttrOutput = new DocxAttributeOutput( *this, m_pDocumentFS, m_pDrawingML );
818 :
819 : // the related VMLExport
820 48 : m_pVMLExport = new VMLExport( m_pDocumentFS, m_pAttrOutput );
821 48 : }
822 :
823 96 : DocxExport::~DocxExport()
824 : {
825 48 : delete m_pVMLExport, m_pVMLExport = NULL;
826 48 : delete m_pAttrOutput, m_pAttrOutput = NULL;
827 48 : delete m_pDrawingML, m_pDrawingML = NULL;
828 48 : }
829 :
830 48 : DocxSettingsData::DocxSettingsData()
831 : : evenAndOddHeaders( false )
832 48 : , defaultTabStop( 0 )
833 : {
834 48 : }
835 :
836 0 : bool DocxSettingsData::hasData() const
837 : {
838 0 : if( evenAndOddHeaders )
839 0 : return true;
840 0 : if( defaultTabStop != 0 )
841 0 : return true;
842 0 : return false;
843 36 : }
844 :
845 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|