xref: /trunk/main/sw/source/filter/ww8/docxexport.cxx (revision 68128652)
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 "docxexport.hxx"
25 #include "docxexportfilter.hxx"
26 
27 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
28 #include <com/sun/star/document/XDocumentProperties.hpp>
29 #include <com/sun/star/i18n/ScriptType.hdl>
30 
31 #include <oox/token/tokens.hxx>
32 #include <oox/export/drawingml.hxx>
33 #include <oox/export/vmlexport.hxx>
34 
35 #include <map>
36 #include <algorithm>
37 
38 #include <IMark.hxx>
39 #include <docsh.hxx>
40 #include <ndtxt.hxx>
41 #include <wrtww8.hxx>
42 #include <fltini.hxx>
43 #include <fmtline.hxx>
44 #include <fmtpdsc.hxx>
45 #include <frmfmt.hxx>
46 #include <section.hxx>
47 
48 #include <docary.hxx>
49 #include <numrule.hxx>
50 #include <charfmt.hxx>
51 
52 #include "ww8par.hxx"
53 #include "ww8scan.hxx"
54 
55 #include <comphelper/string.hxx>
56 #include <rtl/ustrbuf.hxx>
57 #include <vcl/font.hxx>
58 
59 using namespace ::comphelper;
60 using namespace ::com::sun::star;
61 using namespace ::oox;
62 
63 using oox::vml::VMLExport;
64 
65 using rtl::OUString;
66 using rtl::OUStringBuffer;
67 
68 using sw::mark::IMark;
69 
70 #define S( x ) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
71 
AttrOutput() const72 AttributeOutputBase& DocxExport::AttrOutput() const
73 {
74 	return *m_pAttrOutput;
75 }
76 
Sections() const77 MSWordSections& DocxExport::Sections() const
78 {
79 	return *m_pSections;
80 }
81 
CollapseScriptsforWordOk(sal_uInt16 nScript,sal_uInt16 nWhich)82 bool DocxExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
83 {
84 	// TODO FIXME is this actually true for docx? - this is ~copied from WW8
85 	if ( nScript == i18n::ScriptType::ASIAN )
86 	{
87 		// for asian in ww8, there is only one fontsize
88 		// and one fontstyle (posture/weight)
89 		switch ( nWhich )
90 		{
91 			case RES_CHRATR_FONTSIZE:
92 			case RES_CHRATR_POSTURE:
93 			case RES_CHRATR_WEIGHT:
94 				return false;
95 			default:
96 				break;
97 		}
98 	}
99 	else if ( nScript != i18n::ScriptType::COMPLEX )
100 	{
101 		// for western in ww8, there is only one fontsize
102 		// and one fontstyle (posture/weight)
103 		switch ( nWhich )
104 		{
105 			case RES_CHRATR_CJK_FONTSIZE:
106 			case RES_CHRATR_CJK_POSTURE:
107 			case RES_CHRATR_CJK_WEIGHT:
108 				return false;
109 			default:
110 				break;
111 		}
112 	}
113 	return true;
114 }
115 
AppendBookmarks(const SwTxtNode & rNode,xub_StrLen nAktPos,xub_StrLen nLen)116 void DocxExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
117 {
118 	std::vector< OUString > aStarts;
119 	std::vector< OUString > aEnds;
120 
121 	IMarkVector aMarks;
122 	if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
123 	{
124 		for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
125 			  it < end; ++it )
126 		{
127 			IMark* pMark = (*it);
128 
129 			xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
130 			xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
131 
132 			if ( nStart == nAktPos )
133 				aStarts.push_back( pMark->GetName() );
134 
135 			if ( nEnd == nAktPos )
136 				aEnds.push_back( pMark->GetName() );
137 		}
138 	}
139 
140 	m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
141 }
142 
AppendBookmark(const OUString & rName,bool)143 void DocxExport::AppendBookmark( const OUString& rName, bool /*bSkip*/ )
144 {
145 	std::vector< OUString > aStarts;
146 	std::vector< OUString > aEnds;
147 
148 	aStarts.push_back( rName );
149 	aEnds.push_back( rName );
150 
151 	m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
152 }
153 
AddRelation(const OUString & rType,const OUString & rTarget,const OUString & rMode)154 ::rtl::OString DocxExport::AddRelation( const OUString& rType, const OUString& rTarget, const OUString& rMode )
155 {
156 	OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
157 		   rType, rTarget, rMode );
158 
159 	return ::rtl::OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
160 }
161 
DisallowInheritingOutlineNumbering(const SwFmt & rFmt)162 bool DocxExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
163 {
164 	bool bRet( false );
165 
166 	if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
167 	{
168 		if (const SwFmt *pParent = rFmt.DerivedFrom())
169 		{
170 			if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
171 			{
172 				::sax_fastparser::FSHelperPtr pSerializer = m_pAttrOutput->GetSerializer( );
173 				// Level 9 disables the outline
174 				pSerializer->singleElementNS( XML_w, XML_outlineLvl,
175 						FSNS( XML_w, XML_val ), "9" ,
176 						FSEND );
177 
178 				bRet = true;
179 			}
180 		}
181 	}
182 
183 	return bRet;
184 }
185 
WriteHeadersFooters(sal_uInt8 nHeadFootFlags,const SwFrmFmt & rFmt,const SwFrmFmt & rLeftFmt,const SwFrmFmt & rFirstPageFmt)186 void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
187 		const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt )
188 {
189 	// headers
190 	if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
191 		WriteHeaderFooter( rLeftFmt, true, "even" );
192 
193 	if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
194 		WriteHeaderFooter( rFmt, true, "default" );
195 
196 	if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
197 		WriteHeaderFooter( rFirstPageFmt, true, "first" );
198 
199 	// footers
200 	if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
201 		WriteHeaderFooter( rLeftFmt, false, "even" );
202 
203 	if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
204 		WriteHeaderFooter( rFmt, false, "default" );
205 
206 	if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
207 		WriteHeaderFooter( rFirstPageFmt, false, "first" );
208 }
209 
OutputField(const SwField * pFld,ww::eField eFldType,const String & rFldCmd,sal_uInt8 nMode)210 void DocxExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
211 {
212 	m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
213 }
214 
WriteFormData(const::sw::mark::IFieldmark &)215 void DocxExport::WriteFormData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
216 {
217 	OSL_TRACE( "TODO DocxExport::WriteFormData()\n" );
218 }
219 
DoComboBox(const rtl::OUString & rName,const rtl::OUString & rHelp,const rtl::OUString & rToolTip,const rtl::OUString & rSelected,uno::Sequence<rtl::OUString> & rListItems)220 void DocxExport::DoComboBox(const rtl::OUString& rName,
221 							 const rtl::OUString& rHelp,
222 							 const rtl::OUString& rToolTip,
223 							 const rtl::OUString& rSelected,
224 							 uno::Sequence<rtl::OUString>& rListItems)
225 {
226 	m_pDocumentFS->startElementNS( XML_w, XML_ffData, FSEND );
227 
228 	m_pDocumentFS->singleElementNS( XML_w, XML_name,
229 			FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
230 			FSEND );
231 
232 	m_pDocumentFS->singleElementNS( XML_w, XML_enabled, FSEND );
233 
234 	if ( rHelp.getLength( ) > 0 )
235 		m_pDocumentFS->singleElementNS( XML_w, XML_helpText,
236 			FSNS( XML_w, XML_val ), OUStringToOString( rHelp, RTL_TEXTENCODING_UTF8 ).getStr(),
237 			FSEND );
238 
239 	if ( rToolTip.getLength( ) > 0 )
240 		m_pDocumentFS->singleElementNS( XML_w, XML_statusText,
241 			FSNS( XML_w, XML_val ), OUStringToOString( rToolTip, RTL_TEXTENCODING_UTF8 ).getStr(),
242 			FSEND );
243 
244 	m_pDocumentFS->startElementNS( XML_w, XML_ddList, FSEND );
245 
246 	// Output the 0-based index of the selected value
247 	sal_uInt32 nListItems = rListItems.getLength();
248 	sal_Int32 nId = 0;
249 	sal_uInt32 nI = 0;
250 	while ( ( nI < nListItems ) && ( nId == 0 ) )
251 	{
252 		if ( rListItems[nI] == rSelected )
253 			nId = nI;
254 		nI++;
255 	}
256 
257 	m_pDocumentFS->singleElementNS( XML_w, XML_result,
258 			FSNS( XML_w, XML_val ), rtl::OString::valueOf( nId ).getStr( ),
259 			FSEND );
260 
261 	// Loop over the entries
262 
263 	for (sal_uInt32 i = 0; i < nListItems; i++)
264 	{
265 		m_pDocumentFS->singleElementNS( XML_w, XML_listEntry,
266 				FSNS( XML_w, XML_val ), OUStringToOString( rListItems[i], RTL_TEXTENCODING_UTF8 ).getStr(),
267 			   FSEND );
268 	}
269 
270 	m_pDocumentFS->endElementNS( XML_w, XML_ddList );
271 
272 	m_pDocumentFS->endElementNS( XML_w, XML_ffData );
273 }
274 
DoFormText(const SwInputField *)275 void DocxExport::DoFormText(const SwInputField* /*pFld*/)
276 {
277 	OSL_TRACE( "TODO DocxExport::ForFormText()\n" );
278 }
279 
ExportDocument_Impl()280 void DocxExport::ExportDocument_Impl()
281 {
282 	InitStyles();
283 
284 	// init sections
285 	m_pSections = new MSWordSections( *this );
286 
287 	WriteMainText();
288 
289 	WriteFootnotesEndnotes();
290 
291 	WriteNumbering();
292 
293 	WriteFonts();
294 
295 	delete pStyles, pStyles = NULL;
296 	delete m_pSections, m_pSections = NULL;
297 }
298 
OutputPageSectionBreaks(const SwTxtNode &)299 void DocxExport::OutputPageSectionBreaks( const SwTxtNode& )
300 {
301 	OSL_TRACE( "TODO DocxExport::OutputPageSectionBreaks( const SwTxtNode& )\n" );
302 }
303 
304 
AppendSection(const SwPageDesc * pPageDesc,const SwSectionFmt * pFmt,sal_uLong nLnNum)305 void DocxExport::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
306 {
307 	AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
308 	m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
309 }
310 
OutputEndNode(const SwEndNode & rEndNode)311 void DocxExport::OutputEndNode( const SwEndNode& rEndNode )
312 {
313 	MSWordExportBase::OutputEndNode( rEndNode );
314 
315 	if ( TXT_MAINTEXT == nTxtTyp && rEndNode.StartOfSectionNode()->IsSectionNode() )
316 	{
317 		// this originally comes from WW8Export::WriteText(), and looks like it
318 		// could have some code common with SectionNode()...
319 
320 		const SwSection& rSect = rEndNode.StartOfSectionNode()->GetSectionNode()->GetSection();
321 		if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
322 			bStartTOX = false;
323 
324 		SwNodeIndex aIdx( rEndNode, 1 );
325 		const SwNode& rNd = aIdx.GetNode();
326 		if ( rNd.IsEndNode() && rNd.StartOfSectionNode()->IsSectionNode() )
327 			return;
328 
329 		if ( !rNd.IsSectionNode() && !bIsInTable ) // No sections in table
330 		{
331 			const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
332 			if( !pParentFmt )
333 				pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
334 
335 			sal_uLong nRstLnNum;
336 			if( rNd.IsCntntNode() )
337 				nRstLnNum = const_cast< SwCntntNode* >( rNd.GetCntntNode() )->GetSwAttrSet().GetLineNumber().GetStartValue();
338 			else
339 				nRstLnNum = 0;
340 
341 			AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo( ) );
342 			m_pSections->AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
343 		}
344 	}
345 }
346 
OutputTableNode(const SwTableNode &)347 void DocxExport::OutputTableNode( const SwTableNode& )
348 {
349 	OSL_TRACE( "TODO DocxExport::OutputTableNode( const SwTableNode& )\n" );
350 }
351 
OutputGrfNode(const SwGrfNode &)352 void DocxExport::OutputGrfNode( const SwGrfNode& )
353 {
354 	OSL_TRACE( "TODO DocxExport::OutputGrfNode( const SwGrfNode& )\n" );
355 }
356 
OutputOLENode(const SwOLENode &)357 void DocxExport::OutputOLENode( const SwOLENode& )
358 {
359 	OSL_TRACE( "TODO DocxExport::OutputOLENode( const SwOLENode& )\n" );
360 }
361 
ReplaceCr(sal_uInt8)362 sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
363 {
364 	// Completely unused for Docx export... only here for code sharing
365 	// purpose with binary export
366 	return 0;
367 }
368 
PrepareNewPageDesc(const SfxItemSet * pSet,const SwNode & rNd,const SwFmtPageDesc * pNewPgDescFmt,const SwPageDesc * pNewPgDesc)369 void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
370 		const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
371 		const SwPageDesc* pNewPgDesc )
372 {
373 	// tell the attribute output that we are ready to write the section
374 	// break [has to be output inside paragraph properties]
375 	AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
376 
377 	const SwSectionFmt* pFmt = GetSectionFormat( rNd );
378 	const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
379 
380 	ASSERT( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
381 
382 	if ( pNewPgDescFmt )
383 	{
384 		m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
385 	}
386 	else if ( pNewPgDesc )
387 	{
388 		m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
389 	}
390 
391 }
392 
InitStyles()393 void DocxExport::InitStyles()
394 {
395 	pStyles = new MSWordStyles( *this );
396 
397 	// setup word/styles.xml and the relations + content type
398 	m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
399 			S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" ),
400 			S( "styles.xml" ) );
401 
402 	::sax_fastparser::FSHelperPtr pStylesFS =
403 		m_pFilter->openOutputStreamWithSerializer( S( "word/styles.xml" ),
404 			S( "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" ) );
405 
406 	// switch the serializer to redirect the output to word/styles.xml
407 	m_pAttrOutput->SetSerializer( pStylesFS );
408 
409 	// do the work
410 	pStyles->OutputStylesTable();
411 
412 	// switch the serializer back
413 	m_pAttrOutput->SetSerializer( m_pDocumentFS );
414 }
415 
WriteFootnotesEndnotes()416 void DocxExport::WriteFootnotesEndnotes()
417 {
418 	if ( m_pAttrOutput->HasFootnotes() )
419 	{
420 		// setup word/styles.xml and the relations + content type
421 		m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
422 				S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" ),
423 				S( "footnotes.xml" ) );
424 
425 		::sax_fastparser::FSHelperPtr pFootnotesFS =
426 			m_pFilter->openOutputStreamWithSerializer( S( "word/footnotes.xml" ),
427 					S( "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" ) );
428 
429 		// switch the serializer to redirect the output to word/footnotes.xml
430 		m_pAttrOutput->SetSerializer( pFootnotesFS );
431 
432 		// do the work
433 		m_pAttrOutput->FootnotesEndnotes( true );
434 
435 		// switch the serializer back
436 		m_pAttrOutput->SetSerializer( m_pDocumentFS );
437 	}
438 
439 	if ( m_pAttrOutput->HasEndnotes() )
440 	{
441 		// setup word/styles.xml and the relations + content type
442 		m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
443 				S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes" ),
444 				S( "endnotes.xml" ) );
445 
446 		::sax_fastparser::FSHelperPtr pEndnotesFS =
447 			m_pFilter->openOutputStreamWithSerializer( S( "word/endnotes.xml" ),
448 					S( "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" ) );
449 
450 		// switch the serializer to redirect the output to word/endnotes.xml
451 		m_pAttrOutput->SetSerializer( pEndnotesFS );
452 
453 		// do the work
454 		m_pAttrOutput->FootnotesEndnotes( false );
455 
456 		// switch the serializer back
457 		m_pAttrOutput->SetSerializer( m_pDocumentFS );
458 	}
459 }
460 
WriteNumbering()461 void DocxExport::WriteNumbering()
462 {
463 	if ( !pUsedNumTbl )
464 		return; // no numbering is used
465 
466 	m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
467 		S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" ),
468 		S( "numbering.xml" ) );
469 
470 	::sax_fastparser::FSHelperPtr pNumberingFS = m_pFilter->openOutputStreamWithSerializer( S( "word/numbering.xml" ),
471 		S( "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" ) );
472 
473 	// switch the serializer to redirect the output to word/nubering.xml
474 	m_pAttrOutput->SetSerializer( pNumberingFS );
475 
476 	pNumberingFS->startElementNS( XML_w, XML_numbering,
477 			FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
478 			FSEND );
479 
480 	AbstractNumberingDefinitions();
481 
482 	NumberingDefinitions();
483 
484 	pNumberingFS->endElementNS( XML_w, XML_numbering );
485 
486 	// switch the serializer back
487 	m_pAttrOutput->SetSerializer( m_pDocumentFS );
488 }
489 
WriteHeaderFooter(const SwFmt & rFmt,bool bHeader,const char * pType)490 void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* pType )
491 {
492 	// setup the xml stream
493 	OUString aRelId;
494 	::sax_fastparser::FSHelperPtr pFS;
495 	if ( bHeader )
496 	{
497 		OUString aName( OUStringBuffer().appendAscii( "header" ).append( ++m_nHeaders ).appendAscii( ".xml" ).makeStringAndClear() );
498 
499 		aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
500 				S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" ),
501 				aName );
502 
503 		pFS = m_pFilter->openOutputStreamWithSerializer( OUStringBuffer().appendAscii( "word/" ).append( aName ).makeStringAndClear(),
504 					S( "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" ) );
505 
506 		pFS->startElementNS( XML_w, XML_hdr,
507 				FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
508 				FSEND );
509 	}
510 	else
511 	{
512 		OUString aName( OUStringBuffer().appendAscii( "footer" ).append( ++m_nFooters ).appendAscii( ".xml" ).makeStringAndClear() );
513 
514 		aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
515 				S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" ),
516 				aName );
517 
518 		pFS = m_pFilter->openOutputStreamWithSerializer( OUStringBuffer().appendAscii( "word/" ).append( aName ).makeStringAndClear(),
519 					S( "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" ) );
520 
521 		pFS->startElementNS( XML_w, XML_ftr,
522 				FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
523 				FSEND );
524 	}
525 
526 	// switch the serializer to redirect the output to word/styles.xml
527 	m_pAttrOutput->SetSerializer( pFS );
528 
529 	// do the work
530 	WriteHeaderFooterText( rFmt, bHeader );
531 
532 	// switch the serializer back
533 	m_pAttrOutput->SetSerializer( m_pDocumentFS );
534 
535 	// close the tag
536 	sal_Int32 nReference;
537 	if ( bHeader )
538 	{
539 		pFS->endElementNS( XML_w, XML_hdr );
540 		nReference = XML_headerReference;
541 	}
542 	else
543 	{
544 		pFS->endElementNS( XML_w, XML_ftr );
545 		nReference = XML_footerReference;
546 	}
547 
548 	// and write the reference
549 	m_pDocumentFS->singleElementNS( XML_w, nReference,
550 			FSNS( XML_w, XML_type ), pType,
551 			FSNS( XML_r, XML_id ), rtl::OUStringToOString( aRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
552 			FSEND );
553 }
554 
WriteFonts()555 void DocxExport::WriteFonts()
556 {
557 	m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
558 			S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" ),
559 			S( "fontTable.xml" ) );
560 
561 	::sax_fastparser::FSHelperPtr pFS = m_pFilter->openOutputStreamWithSerializer(
562 			S( "word/fontTable.xml" ),
563 			S( "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" ) );
564 
565 	pFS->startElementNS( XML_w, XML_fonts,
566 			FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
567 			FSEND );
568 
569 	// switch the serializer to redirect the output to word/styles.xml
570 	m_pAttrOutput->SetSerializer( pFS );
571 
572 	// do the work
573 	maFontHelper.WriteFontTable( *m_pAttrOutput );
574 
575 	// switch the serializer back
576 	m_pAttrOutput->SetSerializer( m_pDocumentFS );
577 
578 	pFS->endElementNS( XML_w, XML_fonts );
579 }
580 
581 
WriteProperties()582 void DocxExport::WriteProperties( )
583 {
584 	// Write the core properties
585 	SwDocShell* pDocShell( pDoc->GetDocShell( ) );
586 	uno::Reference<document::XDocumentProperties> xDocProps;
587 	if ( pDocShell )
588 	{
589 		uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
590 			   pDocShell->GetModel( ), uno::UNO_QUERY );
591 		xDocProps = xDPS->getDocumentProperties();
592 	}
593 
594 	m_pFilter->exportDocumentProperties( xDocProps );
595 }
596 
VMLExporter()597 VMLExport& DocxExport::VMLExporter()
598 {
599 	return *m_pVMLExport;
600 }
601 
WriteMainText()602 void DocxExport::WriteMainText()
603 {
604 	// setup the namespaces
605 	m_pDocumentFS->startElementNS( XML_w, XML_document,
606 			FSNS( XML_xmlns, XML_o ), "urn:schemas-microsoft-com:office:office",
607 			FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
608 			FSNS( XML_xmlns, XML_v ), "urn:schemas-microsoft-com:vml",
609 			FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
610 			FSNS( XML_xmlns, XML_w10 ), "urn:schemas-microsoft-com:office:word",
611 			FSNS( XML_xmlns, XML_wp ), "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
612 			FSEND );
613 
614 	// body
615 	m_pDocumentFS->startElementNS( XML_w, XML_body, FSEND );
616 
617 	pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
618 
619 	// the text
620 	WriteText();
621 
622 	// the last section info
623 	const WW8_SepInfo *pSectionInfo = m_pSections? m_pSections->CurrentSectionInfo(): NULL;
624 	if ( pSectionInfo )
625 		SectionProperties( *pSectionInfo );
626 
627 	// finish body and document
628 	m_pDocumentFS->endElementNS( XML_w, XML_body );
629 	m_pDocumentFS->endElementNS( XML_w, XML_document );
630 }
631 
DocxExport(DocxExportFilter * pFilter,SwDoc * pDocument,SwPaM * pCurrentPam,SwPaM * pOriginalPam)632 DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
633 	: MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
634 	  m_pFilter( pFilter ),
635 	  m_pAttrOutput( NULL ),
636 	  m_pSections( NULL ),
637 	  m_nHeaders( 0 ),
638 	  m_nFooters( 0 ),
639 	  m_pVMLExport( NULL )
640 {
641 	// Write the document properies
642 	WriteProperties( );
643 
644 	// relations for the document
645 	m_pFilter->addRelation( S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ),
646 			S( "word/document.xml" ) );
647 
648 	// the actual document
649 	m_pDocumentFS = m_pFilter->openOutputStreamWithSerializer( S( "word/document.xml" ),
650 			S( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ) );
651 
652 	// the DrawingML access
653 	m_pDrawingML = new oox::drawingml::DrawingML( m_pDocumentFS, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
654 
655 	// the attribute output for the document
656 	m_pAttrOutput = new DocxAttributeOutput( *this, m_pDocumentFS, m_pDrawingML );
657 
658 	// the related VMLExport
659 	m_pVMLExport = new VMLExport( m_pDocumentFS );
660 }
661 
~DocxExport()662 DocxExport::~DocxExport()
663 {
664 	delete m_pVMLExport, m_pVMLExport = NULL;
665 	delete m_pAttrOutput, m_pAttrOutput = NULL;
666 	delete m_pDrawingML, m_pDrawingML = NULL;
667 }
668 
669 /* vim: set noet sw=4 ts=4: */
670