summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/docxattributeoutput.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/docxattributeoutput.cxx')
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx4172
1 files changed, 4172 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
new file mode 100644
index 000000000000..497f8bc4f07b
--- /dev/null
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -0,0 +1,4172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "docxattributeoutput.hxx"
+#include "docxexport.hxx"
+#include "docxexportfilter.hxx"
+#include "docxfootnotes.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+#include "fmtcntnt.hxx"
+#include "fmtsrnd.hxx"
+#include "fchrfmt.hxx"
+#include "tgrditem.hxx"
+#include "fmtruby.hxx"
+#include "charfmt.hxx"
+#include "breakit.hxx"
+
+#include <oox/token/tokens.hxx>
+#include <oox/export/drawingml.hxx>
+#include <oox/export/utils.hxx>
+#include <oox/export/vmlexport.hxx>
+
+#include <i18npool/mslangid.hxx>
+
+#include <hintids.hxx>
+
+#include <svl/poolitem.hxx>
+
+#include <editeng/fontitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdobj.hxx>
+
+#include <anchoredobject.hxx>
+#include <docufld.hxx>
+#include <flddropdown.hxx>
+#include <format.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclds.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtfld.hxx>
+#include <fmtfsize.hxx>
+#include <fmtftn.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtline.hxx>
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <ftninfo.hxx>
+#include <htmltbl.hxx>
+#include <lineinfo.hxx>
+#include <ndgrf.hxx>
+#include <ndtxt.hxx>
+#include <node.hxx>
+#include <pagedesc.hxx>
+#include <paratr.hxx>
+#include <swmodule.hxx>
+#include <swtable.hxx>
+#include <txtftn.hxx>
+#include <txtinet.hxx>
+#include <numrule.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+
+#include <tools/color.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <IMark.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+using ::editeng::SvxBorderLine;
+using rtl::OString;
+using rtl::OStringBuffer;
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using rtl::OUStringToOString;
+
+using namespace oox;
+using namespace docx;
+using namespace sax_fastparser;
+using namespace nsSwDocInfoSubType;
+using namespace nsFieldFlags;
+using namespace sw::util;
+using namespace ::com::sun::star;
+
+class FFDataWriterHelper
+{
+ ::sax_fastparser::FSHelperPtr m_pSerializer;
+ void writeCommonStart( const rtl::OUString& rName )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_ffData, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_name,
+ FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_enabled, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_calcOnExit,
+ FSNS( XML_w, XML_val ),
+ "0", FSEND );
+ }
+ void writeFinish()
+ {
+ m_pSerializer->endElementNS( XML_w, XML_ffData );
+ }
+public:
+ FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr pSerializer ) : m_pSerializer( pSerializer ){}
+ void WriteFormCheckbox( const rtl::OUString& rName, const rtl::OUString& rDefault, bool bChecked )
+ {
+ writeCommonStart( rName );
+ // Checkbox specific bits
+ m_pSerializer->startElementNS( XML_w, XML_checkBox, FSEND );
+ // currently hardcoding autosize
+ // #TODO check if this defaulted
+ m_pSerializer->startElementNS( XML_w, XML_sizeAuto, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_sizeAuto );
+ if ( rDefault.getLength() )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_default,
+ FSNS( XML_w, XML_val ),
+ rtl::OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
+ }
+ if ( bChecked )
+ m_pSerializer->singleElementNS( XML_w, XML_checked, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_checkBox );
+ writeFinish();
+ }
+ void WriteFormText( const rtl::OUString& rName, const rtl::OUString& rDefault )
+ {
+ writeCommonStart( rName );
+ if ( rDefault.getLength() )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_textInput, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_default,
+ FSNS( XML_w, XML_val ),
+ rtl::OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_textInput );
+ }
+ writeFinish();
+ }
+};
+
+class FieldMarkParamsHelper
+{
+ const sw::mark::IFieldmark& mrFieldmark;
+ public:
+ FieldMarkParamsHelper( const sw::mark::IFieldmark& rFieldmark ) : mrFieldmark( rFieldmark ) {}
+ rtl::OUString getName() { return mrFieldmark.GetName(); }
+ template < typename T >
+ bool extractParam( const rtl::OUString& rKey, T& rResult )
+ {
+ bool bResult = false;
+ if ( mrFieldmark.GetParameters() )
+ {
+ sw::mark::IFieldmark::parameter_map_t::const_iterator it = mrFieldmark.GetParameters()->find( rKey );
+ if ( it != mrFieldmark.GetParameters()->end() )
+ bResult = ( it->second >>= rResult );
+ }
+ return bResult;
+ }
+};
+void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
+{
+ if (bIsRTL)
+ m_pSerializer->singleElementNS( XML_w, XML_rtl, FSNS( XML_w, XML_val ), "true", FSEND );
+}
+
+void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
+{
+ if ( m_nColBreakStatus == COLBRK_POSTPONE )
+ m_nColBreakStatus = COLBRK_WRITE;
+
+ // Output table/table row/table cell starts if needed
+ if ( pTextNodeInfo.get() )
+ {
+ sal_uInt32 nRow = pTextNodeInfo->getRow();
+ sal_uInt32 nCell = pTextNodeInfo->getCell();
+
+ // New cell/row?
+ if ( m_nTableDepth > 0 && !m_bTableCellOpen )
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) );
+ if ( pDeepInner->getCell() == 0 )
+ StartTableRow( pDeepInner );
+
+ StartTableCell( pDeepInner );
+ }
+
+ if ( nRow == 0 && nCell == 0 )
+ {
+ // Do we have to start the table?
+ // [If we are at the rigth depth already, it means that we
+ // continue the table cell]
+ sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
+
+ if ( nCurrentDepth > m_nTableDepth )
+ {
+ // Start all the tables that begin here
+ for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
+
+ StartTable( pInner );
+ StartTableRow( pInner );
+ StartTableCell( pInner );
+ }
+
+ m_nTableDepth = nCurrentDepth;
+ }
+ }
+ }
+
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+
+ // postpone the output of the run (we get it before the paragraph
+ // properties, but must write it after them)
+ m_pSerializer->mark();
+
+ // no section break in this paragraph yet; can be set in SectionBreak()
+ m_pSectionInfo = NULL;
+
+ m_bParagraphOpened = true;
+}
+
+void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
+{
+ // write the paragraph properties + the run, already in the correct order
+ m_pSerializer->mergeTopMarks();
+ m_pSerializer->endElementNS( XML_w, XML_p );
+
+ // Check for end of cell, rows, tables here
+ FinishTableRowCell( pTextNodeInfoInner );
+
+ m_bParagraphOpened = false;
+
+ // Write the anchored frame if any
+ if ( m_pParentFrame )
+ {
+ const SwFrmFmt& rFrmFmt = m_pParentFrame->GetFrmFmt( );
+ const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
+
+ sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
+ sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
+
+ m_rExport.SaveData( nStt, nEnd );
+
+ m_rExport.mpParentFrame = m_pParentFrame;
+ m_pParentFrame = NULL;
+
+ m_rExport.WriteText( );
+
+ m_rExport.RestoreData();
+ }
+}
+
+void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
+{
+ if ( pInner.get() )
+ {
+ // Where are we in the table
+ sal_uInt32 nRow = pInner->getRow( );
+
+ const SwTable *pTable = pInner->getTable( );
+ const SwTableLines& rLines = pTable->GetTabLines( );
+ sal_uInt16 nLinesCount = rLines.Count( );
+ // HACK
+ // msoffice seems to have an internal limitation of 63 columns for tables
+ // and refuses to load .docx with more, even though the spec seems to allow that;
+ // so simply if there are more columns, don't close the last one msoffice will handle
+ // and merge the contents of the remaining ones into it (since we don't close the cell
+ // here, following ones will not be opened)
+ bool limitWorkaround = ( pInner->getCell() >= 62 && !pInner->isEndOfLine());
+
+ if ( pInner->isEndOfCell() && !limitWorkaround )
+ {
+ if ( bForceEmptyParagraph )
+ m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
+
+ EndTableCell();
+ }
+
+ // This is a line end
+ if ( pInner->isEndOfLine() )
+ EndTableRow();
+
+ // This is the end of the table
+ if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
+ EndTable();
+ }
+}
+
+void DocxAttributeOutput::EmptyParagraph()
+{
+ m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
+}
+
+void DocxAttributeOutput::StartParagraphProperties( const SwTxtNode& rNode )
+{
+ // output page/section breaks
+ // Writer can have them at the beginning of a paragraph, or at the end, but
+ // in docx, we have to output them in the paragraph properties of the last
+ // paragraph in a section. To get it right, we have to switch to the next
+ // paragraph, and detect the section breaks there.
+ SwNodeIndex aNextIndex( rNode, 1 );
+ if ( aNextIndex.GetNode().IsTxtNode() )
+ {
+ const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
+ m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode );
+ }
+ else if ( aNextIndex.GetNode().IsTableNode() )
+ {
+ const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
+ const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
+ m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
+ }
+
+ m_pSerializer->mark( );
+
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+
+ // and output the section break now (if it appeared)
+ if ( m_pSectionInfo )
+ {
+ m_rExport.SectionProperties( *m_pSectionInfo );
+ m_pSectionInfo = NULL;
+ }
+
+ InitCollectedParagraphProperties();
+}
+
+void DocxAttributeOutput::InitCollectedParagraphProperties()
+{
+ m_pParagraphSpacingAttrList = NULL;
+
+ // Write the elements in the spec order
+ static const sal_Int32 aOrder[] =
+ {
+ FSNS( XML_w, XML_pStyle ),
+ FSNS( XML_w, XML_keepNext ),
+ FSNS( XML_w, XML_keepLines ),
+ FSNS( XML_w, XML_pageBreakBefore ),
+ FSNS( XML_w, XML_framePr ),
+ FSNS( XML_w, XML_widowControl ),
+ FSNS( XML_w, XML_numPr ),
+ FSNS( XML_w, XML_suppressLineNumbers ),
+ FSNS( XML_w, XML_pBdr ),
+ FSNS( XML_w, XML_shd ),
+ FSNS( XML_w, XML_tabs ),
+ FSNS( XML_w, XML_suppressAutoHyphens ),
+ FSNS( XML_w, XML_kinsoku ),
+ FSNS( XML_w, XML_wordWrap ),
+ FSNS( XML_w, XML_overflowPunct ),
+ FSNS( XML_w, XML_topLinePunct ),
+ FSNS( XML_w, XML_autoSpaceDE ),
+ FSNS( XML_w, XML_autoSpaceDN ),
+ FSNS( XML_w, XML_bidi ),
+ FSNS( XML_w, XML_adjustRightInd ),
+ FSNS( XML_w, XML_snapToGrid ),
+ FSNS( XML_w, XML_spacing ),
+ FSNS( XML_w, XML_ind ),
+ FSNS( XML_w, XML_contextualSpacing ),
+ FSNS( XML_w, XML_mirrorIndents ),
+ FSNS( XML_w, XML_suppressOverlap ),
+ FSNS( XML_w, XML_jc ),
+ FSNS( XML_w, XML_textDirection ),
+ FSNS( XML_w, XML_textAlignment ),
+ FSNS( XML_w, XML_textboxTightWrap ),
+ FSNS( XML_w, XML_outlineLvl ),
+ FSNS( XML_w, XML_divId ),
+ FSNS( XML_w, XML_cnfStyle ),
+ FSNS( XML_w, XML_rPr ),
+ FSNS( XML_w, XML_sectPr ),
+ FSNS( XML_w, XML_pPrChange )
+ };
+
+ // postpone the output so that we can later [in EndParagraphProperties()]
+ // prepend the properties before the run
+ sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
+ uno::Sequence< sal_Int32 > aSeqOrder( len );
+ for ( sal_Int32 i = 0; i < len; i++ )
+ aSeqOrder[i] = aOrder[i];
+
+ m_pSerializer->mark( aSeqOrder );
+}
+
+void DocxAttributeOutput::WriteCollectedParagraphProperties()
+{
+ if ( m_pFlyAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pFlyAttrList );
+ m_pFlyAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_framePr, xAttrList );
+ }
+
+ if ( m_pParagraphSpacingAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pParagraphSpacingAttrList );
+ m_pParagraphSpacingAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_spacing, xAttrList );
+ }
+
+ // Merge the marks for the ordered elements
+ m_pSerializer->mergeTopMarks( );
+}
+
+void DocxAttributeOutput::EndParagraphProperties()
+{
+ WriteCollectedParagraphProperties();
+
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+
+ if ( m_nColBreakStatus == COLBRK_WRITE )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_br,
+ FSNS( XML_w, XML_type ), "column", FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ m_nColBreakStatus = COLBRK_NONE;
+ }
+
+ // merge the properties _before_ the run (strictly speaking, just
+ // after the start of the paragraph)
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
+}
+
+void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData )
+{
+ // if there is some redlining in the document, output it
+ StartRedline( pRedlineData );
+
+ // postpone the output of the start of a run (there are elements that need
+ // to be written before the start of the run, but we learn which they are
+ // _inside_ of the run)
+ m_pSerializer->mark(); // let's call it "postponed run start"
+
+ // postpone the output of the text (we get it before the run properties,
+ // but must write it after them)
+ m_pSerializer->mark(); // let's call it "postponed text"
+}
+
+void DocxAttributeOutput::EndRun()
+{
+ // Write field starts
+ for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt )
+ {
+ // Add the fields starts for all but hyperlinks and TOCs
+ if ( pIt->bOpen && pIt->pField )
+ {
+ StartField_Impl( *pIt );
+
+ // Remove the field from the stack if only the start has to be written
+ // Unknown fields sould be removed too
+ if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) )
+ {
+ m_Fields.erase( pIt );
+ --pIt;
+ }
+ }
+ }
+
+ // write the run properties + the text, already in the correct order
+ m_pSerializer->mergeTopMarks(); // merges with "postponed text", see above
+
+ // level down, to be able to prepend the actual run start attribute (just
+ // before "postponed run start")
+ m_pSerializer->mark(); // let's call it "actual run start"
+
+ // prepend the actual run start
+ if ( m_pHyperlinkAttrList )
+ {
+ XFastAttributeListRef xAttrList ( m_pHyperlinkAttrList );
+
+ m_pSerializer->startElementNS( XML_w, XML_hyperlink, xAttrList );
+ }
+
+ // Write the hyperlink and toc fields starts
+ for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt )
+ {
+ // Add the fields starts for hyperlinks, TOCs and index marks
+ if ( pIt->bOpen && !pIt->pField )
+ {
+ StartField_Impl( *pIt, sal_True );
+
+ // Remove the field if no end needs to be written
+ if ( !pIt->bClose ) {
+ m_Fields.erase( pIt );
+ --pIt;
+ }
+ }
+ }
+
+ DoWriteBookmarks( );
+
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); // merges with "postponed run start", see above
+
+ // write the run start + the run content
+ m_pSerializer->mergeTopMarks(); // merges the "actual run start"
+
+ // append the actual run end
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ if ( m_pHyperlinkAttrList )
+ {
+ m_pSerializer->endElementNS( XML_w, XML_hyperlink );
+ m_pHyperlinkAttrList = NULL;
+ }
+
+ while ( m_Fields.begin() != m_Fields.end() )
+ {
+ EndField_Impl( m_Fields.front( ) );
+ m_Fields.erase( m_Fields.begin( ) );
+ }
+
+ // if there is some redlining in the document, output it
+ EndRedline();
+}
+
+void DocxAttributeOutput::DoWriteBookmarks()
+{
+ // Write the start bookmarks
+ for ( std::vector< OString >::const_iterator it = m_rMarksStart.begin(), end = m_rMarksStart.end();
+ it < end; ++it )
+ {
+ const OString& rName = *it;
+
+ // Output the bookmark
+ sal_uInt16 nId = m_nNextMarkId++;
+ m_rOpenedMarksIds[rName] = nId;
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr( ),
+ FSNS( XML_w, XML_name ), rName.getStr(),
+ FSEND );
+ }
+ m_rMarksStart.clear();
+
+ // export the end bookmarks
+ for ( std::vector< OString >::const_iterator it = m_rMarksEnd.begin(), end = m_rMarksEnd.end();
+ it < end; ++it )
+ {
+ const OString& rName = *it;
+
+ // Get the id of the bookmark
+ std::map< OString, sal_uInt16 >::iterator pPos = m_rOpenedMarksIds.find( rName );
+ if ( pPos != m_rOpenedMarksIds.end( ) )
+ {
+ sal_uInt16 nId = ( *pPos ).second;
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr( ),
+ FSEND );
+ m_rOpenedMarksIds.erase( rName );
+ }
+ }
+ m_rMarksEnd.clear();
+}
+
+void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos )
+{
+ const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
+ if ( rInfos.eType == ww::eFORMDROPDOWN )
+ {
+ uno::Sequence< ::rtl::OUString> vListEntries;
+ rtl::OUString sName, sHelp, sToolTip, sSelected;
+
+ FieldMarkParamsHelper params( rFieldmark );
+ params.extractParam( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_LISTENTRY) ), vListEntries );
+ sName = params.getName();
+ sal_Int32 nSelectedIndex = 0;
+
+ if ( params.extractParam( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_RESULT) ), nSelectedIndex ) )
+ {
+ if (nSelectedIndex < vListEntries.getLength() )
+ sSelected = vListEntries[ nSelectedIndex ];
+ }
+
+ GetExport().DoComboBox( sName, sHelp, sToolTip, sSelected, vListEntries );
+ }
+ else if ( rInfos.eType == ww::eFORMCHECKBOX )
+ {
+ rtl::OUString sName, sDefault;
+ bool bChecked = false;
+
+ FieldMarkParamsHelper params( rFieldmark );
+ params.extractParam( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_FORMCHECKBOX_NAME ) ), sName );
+
+ const sw::mark::ICheckboxFieldmark* pCheckboxFm = dynamic_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
+ if ( pCheckboxFm && pCheckboxFm->IsChecked() )
+ bChecked = true;
+
+ FFDataWriterHelper ffdataOut( m_pSerializer );
+ ffdataOut.WriteFormCheckbox( sName, rtl::OUString(), bChecked );
+ }
+ else if ( rInfos.eType == ww::eFORMTEXT )
+ {
+ FieldMarkParamsHelper params( rFieldmark );
+ FFDataWriterHelper ffdataOut( m_pSerializer );
+ ffdataOut.WriteFormText( params.getName(), rtl::OUString() );
+ }
+}
+
+void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, sal_Bool bWriteRun )
+{
+ if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
+ {
+ // Expand unsupported fields
+ RunText( rInfos.pField->GetFieldName() );
+ }
+ else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
+ {
+ if ( bWriteRun )
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+
+ if ( rInfos.eType == ww::eFORMDROPDOWN )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin",
+ FSEND );
+ if ( rInfos.pFieldmark && !rInfos.pField )
+ WriteFFData( rInfos );
+ if ( rInfos.pField )
+ {
+ const SwDropDownField& rFld2 = *(SwDropDownField*)rInfos.pField;
+ uno::Sequence<rtl::OUString> aItems =
+ rFld2.GetItemSequence();
+ GetExport().DoComboBox(rFld2.GetName(),
+ rFld2.GetHelp(),
+ rFld2.GetToolTip(),
+ rFld2.GetSelectedItem(), aItems);
+ }
+ m_pSerializer->endElementNS( XML_w, XML_fldChar );
+
+ if ( bWriteRun )
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ if ( !rInfos.pField )
+ CmdField_Impl( rInfos );
+
+ }
+ else
+ {
+ // Write the field start
+ m_pSerializer->startElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin",
+ FSEND );
+
+ if ( rInfos.pFieldmark )
+ WriteFFData( rInfos );
+
+ m_pSerializer->endElementNS( XML_w, XML_fldChar );
+
+ if ( bWriteRun )
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ // The hyperlinks fields can't be expanded: the value is
+ // normally in the text run
+ if ( !rInfos.pField )
+ CmdField_Impl( rInfos );
+ }
+ }
+}
+
+void DocxAttributeOutput::DoWriteCmd( String& rCmd )
+{
+ // Write the Field command
+ m_pSerializer->startElementNS( XML_w, XML_instrText, FSEND );
+ m_pSerializer->writeEscaped( OUString( rCmd ) );
+ m_pSerializer->endElementNS( XML_w, XML_instrText );
+
+}
+
+void DocxAttributeOutput::CmdField_Impl( FieldInfos& rInfos )
+{
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ xub_StrLen nNbToken = rInfos.sCmd.GetTokenCount( '\t' );
+
+ for ( xub_StrLen i = 0; i < nNbToken; i++ )
+ {
+ String sToken = rInfos.sCmd.GetToken( i, '\t' );
+ // Write the Field command
+ DoWriteCmd( sToken );
+
+ // Replace tabs by </instrText><tab/><instrText>
+ if ( i < ( nNbToken - 1 ) )
+ RunText( String::CreateFromAscii( "\t" ) );
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ // Write the Field separator
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "separate",
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+}
+
+void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
+{
+ // The command has to be written before for the hyperlinks
+ if ( rInfos.pField )
+ {
+ CmdField_Impl( rInfos );
+ }
+
+ // Write the bookmark start if any
+ OUString aBkmName( m_sFieldBkm );
+ if ( aBkmName.getLength( ) > 0 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
+ FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
+ FSEND );
+ }
+
+ if (rInfos.pField ) // For hyperlinks and TOX
+ {
+ // Write the Field latest value
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+
+ // Find another way for hyperlinks
+ RunText( rInfos.pField->GetFieldName() );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ }
+
+ // Write the bookmark end if any
+ if ( aBkmName.getLength( ) > 0 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
+ FSEND );
+
+ m_nNextMarkId++;
+ }
+
+ // Write the Field end
+ if ( rInfos.bClose )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "end",
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ }
+ // Write the ref field if a bookmark had to be set and the field
+ // should be visible
+ if ( rInfos.pField )
+ {
+ sal_uInt16 nSubType = rInfos.pField->GetSubType( );
+ bool bIsSetField = rInfos.pField->GetTyp( )->Which( ) == RES_SETEXPFLD;
+ bool bShowRef = ( !bIsSetField || ( nSubType & nsSwExtendedSubType::SUB_INVISIBLE ) ) ? false : true;
+
+ if ( ( m_sFieldBkm.Len( ) > 0 ) && bShowRef )
+ {
+ // Write the field beginning
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin",
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ rInfos.sCmd = FieldString( ww::eREF );
+ rInfos.sCmd.APPEND_CONST_ASC( "\"" );
+ rInfos.sCmd += m_sFieldBkm;
+ rInfos.sCmd.APPEND_CONST_ASC( "\" " );
+
+ // Clean the field bookmark data to avoid infinite loop
+ m_sFieldBkm = String( );
+
+ // Write the end of the field
+ EndField_Impl( rInfos );
+ }
+ }
+}
+
+void DocxAttributeOutput::StartRunProperties()
+{
+ // postpone the output so that we can later [in EndRunProperties()]
+ // prepend the properties before the text
+ m_pSerializer->mark();
+
+ m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
+
+ InitCollectedRunProperties();
+}
+
+void DocxAttributeOutput::InitCollectedRunProperties()
+{
+ m_pFontsAttrList = NULL;
+ m_pEastAsianLayoutAttrList = NULL;
+ m_pCharLangAttrList = NULL;
+
+ // Write the elements in the spec order
+ static const sal_Int32 aOrder[] =
+ {
+ FSNS( XML_w, XML_rStyle ),
+ FSNS( XML_w, XML_rFonts ),
+ FSNS( XML_w, XML_b ),
+ FSNS( XML_w, XML_bCs ),
+ FSNS( XML_w, XML_i ),
+ FSNS( XML_w, XML_iCs ),
+ FSNS( XML_w, XML_caps ),
+ FSNS( XML_w, XML_smallCaps ),
+ FSNS( XML_w, XML_strike ),
+ FSNS( XML_w, XML_dstrike ),
+ FSNS( XML_w, XML_outline ),
+ FSNS( XML_w, XML_shadow ),
+ FSNS( XML_w, XML_emboss ),
+ FSNS( XML_w, XML_imprint ),
+ FSNS( XML_w, XML_noProof ),
+ FSNS( XML_w, XML_snapToGrid ),
+ FSNS( XML_w, XML_vanish ),
+ FSNS( XML_w, XML_webHidden ),
+ FSNS( XML_w, XML_color ),
+ FSNS( XML_w, XML_spacing ),
+ FSNS( XML_w, XML_w ),
+ FSNS( XML_w, XML_kern ),
+ FSNS( XML_w, XML_position ),
+ FSNS( XML_w, XML_sz ),
+ FSNS( XML_w, XML_szCs ),
+ FSNS( XML_w, XML_highlight ),
+ FSNS( XML_w, XML_u ),
+ FSNS( XML_w, XML_effect ),
+ FSNS( XML_w, XML_bdr ),
+ FSNS( XML_w, XML_shd ),
+ FSNS( XML_w, XML_fitText ),
+ FSNS( XML_w, XML_vertAlign ),
+ FSNS( XML_w, XML_rtl ),
+ FSNS( XML_w, XML_cs ),
+ FSNS( XML_w, XML_em ),
+ FSNS( XML_w, XML_lang ),
+ FSNS( XML_w, XML_eastAsianLayout ),
+ FSNS( XML_w, XML_specVanish ),
+ FSNS( XML_w, XML_oMath ),
+ FSNS( XML_w, XML_rPrChange )
+ };
+
+ // postpone the output so that we can later [in EndParagraphProperties()]
+ // prepend the properties before the run
+ sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
+ uno::Sequence< sal_Int32 > aSeqOrder( len );
+ for ( sal_Int32 i = 0; i < len; i++ )
+ aSeqOrder[i] = aOrder[i];
+
+ m_pSerializer->mark( aSeqOrder );
+
+}
+
+void DocxAttributeOutput::WriteCollectedRunProperties()
+{
+ // Write all differed properties
+ if ( m_pFontsAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pFontsAttrList );
+ m_pFontsAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_rFonts, xAttrList );
+ }
+
+ if ( m_pEastAsianLayoutAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pEastAsianLayoutAttrList );
+ m_pEastAsianLayoutAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_eastAsianLayout, xAttrList );
+ }
+
+ if ( m_pCharLangAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pCharLangAttrList );
+ m_pCharLangAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_lang, xAttrList );
+ }
+
+ // Merge the marks for the ordered elements
+ m_pSerializer->mergeTopMarks();
+}
+
+void DocxAttributeOutput::EndRunProperties( const SwRedlineData* /*pRedlineData*/ )
+{
+ WriteCollectedRunProperties();
+
+ m_pSerializer->endElementNS( XML_w, XML_rPr );
+
+ // write footnotes/endnotes if we have any
+ FootnoteEndnoteReference();
+
+ // merge the properties _before_ the run text (strictly speaking, just
+ // after the start of the run)
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
+}
+
+void DocxAttributeOutput::FootnoteEndnoteRefTag()
+{
+ if( m_footnoteEndnoteRefTag == 0 )
+ return;
+ m_pSerializer->singleElementNS( XML_w, m_footnoteEndnoteRefTag, FSEND );
+ m_footnoteEndnoteRefTag = 0;
+}
+
+/** Output sal_Unicode* as a run text (<t>the text</t>).
+
+ When bMove is true, update rBegin to point _after_ the end of the text +
+ 1, meaning that it skips one character after the text. This is to make
+ the switch in DocxAttributeOutput::RunText() nicer ;-)
+ */
+static void impl_WriteRunText( FSHelperPtr pSerializer, sal_Int32 nTextToken,
+ const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true )
+{
+ const sal_Unicode *pBegin = rBegin;
+
+ // skip one character after the end
+ if ( bMove )
+ rBegin = pEnd + 1;
+
+ if ( pBegin >= pEnd )
+ return; // we want to write at least one character
+
+ // we have to add 'preserve' when starting/ending with space
+ if ( *pBegin == sal_Unicode( ' ' ) || *( pEnd - 1 ) == sal_Unicode( ' ' ) )
+ {
+ pSerializer->startElementNS( XML_w, nTextToken, FSNS( XML_xml, XML_space ), "preserve", FSEND );
+ }
+ else
+ pSerializer->startElementNS( XML_w, nTextToken, FSEND );
+
+ pSerializer->writeEscaped( OUString( pBegin, pEnd - pBegin ) );
+
+ pSerializer->endElementNS( XML_w, nTextToken );
+}
+
+void DocxAttributeOutput::RunText( const String& rText, rtl_TextEncoding /*eCharSet*/ )
+{
+ OUString aText( rText );
+
+ // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
+ const sal_Unicode *pBegin = aText.getStr();
+ const sal_Unicode *pEnd = pBegin + aText.getLength();
+
+ // the text run is usually XML_t, with the exception of the deleted text
+ sal_Int32 nTextToken = XML_t;
+ if ( m_pRedlineData && m_pRedlineData->GetType() == nsRedlineType_t::REDLINE_DELETE )
+ nTextToken = XML_delText;
+
+ for ( const sal_Unicode *pIt = pBegin; pIt < pEnd; ++pIt )
+ {
+ switch ( *pIt )
+ {
+ case 0x09: // tab
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
+ m_pSerializer->singleElementNS( XML_w, XML_tab, FSEND );
+ break;
+ case 0x0b: // line break
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
+ m_pSerializer->singleElementNS( XML_w, XML_br, FSEND );
+ break;
+ default:
+ if ( *pIt < 0x0020 ) // filter out the control codes
+ {
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
+ OSL_TRACE( "Ignored control code %x in a text run.", *pIt );
+ }
+ break;
+ }
+ }
+
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
+}
+
+void DocxAttributeOutput::RawText( const String& /*rText*/, bool /*bForceUnicode*/, rtl_TextEncoding /*eCharSet*/ )
+{
+ OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )\n" );
+}
+
+void DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby )
+{
+ OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )\n" );
+ m_pSerializer->startElementNS( XML_w, XML_ruby, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_rubyPr, FSEND );
+ // hps
+ // hpsBaseText
+ // hpsRaise
+ // lid
+ lang::Locale aLocale( SwBreakIt::Get()->GetLocale(
+ rNode.GetLang( nPos ) ) );
+ OUString sLang( aLocale.Language );
+ if ( aLocale.Country.getLength( ) > 0 )
+ sLang += OUString(RTL_CONSTASCII_USTRINGPARAM( "-" )) + OUString( aLocale.Country );
+ m_pSerializer->singleElementNS( XML_w, XML_lid,
+ FSNS( XML_w, XML_val ),
+ OUStringToOString( sLang, RTL_TEXTENCODING_UTF8 ).getStr( ), FSEND );
+
+ OString sAlign ( "center" );
+ switch ( rRuby.GetAdjustment( ) )
+ {
+ case 0:
+ sAlign = OString( "left" );
+ break;
+ case 1:
+ // Defaults to center
+ break;
+ case 2:
+ sAlign = OString( "right" );
+ break;
+ case 3:
+ sAlign = OString( "distributeLetter" );
+ break;
+ case 4:
+ sAlign = OString( "distributeSpace" );
+ break;
+ default:
+ break;
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_rubyAlign,
+ FSNS( XML_w, XML_val ), sAlign.getStr(), FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_rubyPr );
+
+ m_pSerializer->startElementNS( XML_w, XML_rt, FSEND );
+ StartRun( NULL );
+ StartRunProperties( );
+ SwWW8AttrIter aAttrIt( m_rExport, rNode );
+ aAttrIt.OutAttr( nPos, true );
+ sal_uInt16 nStyle = m_rExport.GetId( *rRuby.GetTxtRuby()->GetCharFmt() );
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( nStyle ) );
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle,
+ FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+ EndRunProperties( NULL );
+ RunText( rRuby.GetText( ) );
+ EndRun( );
+ m_pSerializer->endElementNS( XML_w, XML_rt );
+
+ m_pSerializer->startElementNS( XML_w, XML_rubyBase, FSEND );
+ StartRun( NULL );
+}
+
+void DocxAttributeOutput::EndRuby()
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()\n" );
+ EndRun( );
+ m_pSerializer->endElementNS( XML_w, XML_rubyBase );
+ m_pSerializer->endElementNS( XML_w, XML_ruby );
+}
+
+bool DocxAttributeOutput::AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark )
+{
+ bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
+
+ String sURL = *pLinkURL;
+ String sMark = *pMark;
+
+ bool bOutputField = sMark.Len();
+
+ if ( bOutputField )
+ {
+ if ( bBookMarkOnly )
+ sURL = FieldString( ww::eHYPERLINK );
+ else
+ {
+ String sFld( FieldString( ww::eHYPERLINK ) );
+ sFld.APPEND_CONST_ASC( "\"" );
+ sURL.Insert( sFld, 0 );
+ sURL += '\"';
+ }
+
+ if ( sMark.Len() )
+ ( ( sURL.APPEND_CONST_ASC( " \\l \"" ) ) += sMark ) += '\"';
+
+ if ( rTarget.Len() )
+ ( sURL.APPEND_CONST_ASC( " \\n " ) ) += rTarget;
+ }
+
+ *pLinkURL = sURL;
+ *pMark = sMark;
+
+ return bBookMarkOnly;
+}
+
+bool DocxAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
+{
+ String sMark;
+ String sUrl;
+
+ bool bBookmarkOnly = AnalyzeURL( rUrl, rTarget, &sUrl, &sMark );
+
+ if ( sMark.Len() && !bBookmarkOnly )
+ {
+ m_rExport.OutputField( NULL, ww::eHYPERLINK, sUrl );
+ }
+ else
+ {
+ // Output a hyperlink XML element
+
+ m_pHyperlinkAttrList = m_pSerializer->createAttrList();
+ if ( !bBookmarkOnly )
+ {
+ OUString osUrl( sUrl );
+
+ ::rtl::OString sId = m_rExport.AddRelation(
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
+ osUrl, S("External") );
+ m_pHyperlinkAttrList->add( FSNS( XML_r, XML_id), sId.getStr());
+ }
+ else
+ m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ),
+ OUStringToOString( OUString( sMark ), RTL_TEXTENCODING_UTF8 ).getStr( ) );
+
+ OUString sTarget( rTarget );
+ if ( sTarget.getLength( ) > 0 )
+ {
+ OString soTarget = OUStringToOString( sTarget, RTL_TEXTENCODING_UTF8 );
+ m_pHyperlinkAttrList->add(FSNS( XML_w, XML_tgtFrame ), soTarget.getStr());
+ }
+ }
+
+ return true;
+}
+
+bool DocxAttributeOutput::EndURL()
+{
+ return true;
+}
+
+void DocxAttributeOutput::FieldVanish( const String& rTxt, ww::eField eType )
+{
+ WriteField_Impl( NULL, eType, rTxt, WRITEFIELD_ALL );
+}
+
+void DocxAttributeOutput::Redline( const SwRedlineData* /*pRedline*/ )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::Redline( const SwRedlineData* pRedline )\n" );
+}
+
+/// Append the number as 2-digit when less than 10.
+static void impl_AppendTwoDigits( OStringBuffer &rBuffer, sal_Int32 nNum )
+{
+ if ( nNum < 0 || nNum > 99 )
+ {
+ rBuffer.append( "00" );
+ return;
+ }
+
+ if ( nNum < 10 )
+ rBuffer.append( '0' );
+
+ rBuffer.append( nNum );
+}
+
+/** Convert DateTime to xsd::dateTime string.
+
+I guess there must be an implementation of this somewhere in OOo, but I failed
+to find it, unfortunately :-(
+*/
+static OString impl_DateTimeToOString( const DateTime& rDateTime )
+{
+ DateTime aInUTC( rDateTime );
+ aInUTC.ConvertToUTC();
+
+ OStringBuffer aBuffer( 25 );
+ aBuffer.append( sal_Int32( aInUTC.GetYear() ) );
+ aBuffer.append( '-' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetMonth() );
+ aBuffer.append( '-' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetDay() );
+ aBuffer.append( 'T' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetHour() );
+ aBuffer.append( ':' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetMin() );
+ aBuffer.append( ':' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetSec() );
+ aBuffer.append( 'Z' ); // we are in UTC
+
+ return aBuffer.makeStringAndClear();
+}
+
+void DocxAttributeOutput::StartRedline( const SwRedlineData* pRedlineData )
+{
+ m_pRedlineData = pRedlineData;
+
+ if ( !m_pRedlineData )
+ return;
+
+ // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
+
+ OString aId( OString::valueOf( m_nRedlineId++ ) );
+
+ const String &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
+ OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
+
+ OString aDate( impl_DateTimeToOString( pRedlineData->GetTimeStamp() ) );
+
+ switch ( pRedlineData->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ m_pSerializer->startElementNS( XML_w, XML_ins,
+ FSNS( XML_w, XML_id ), aId.getStr(),
+ FSNS( XML_w, XML_author ), aAuthor.getStr(),
+ FSNS( XML_w, XML_date ), aDate.getStr(),
+ FSEND );
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ m_pSerializer->startElementNS( XML_w, XML_del,
+ FSNS( XML_w, XML_id ), aId.getStr(),
+ FSNS( XML_w, XML_author ), aAuthor.getStr(),
+ FSNS( XML_w, XML_date ), aDate.getStr(),
+ FSEND );
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()\n" );
+ default:
+ break;
+ }
+}
+
+void DocxAttributeOutput::EndRedline()
+{
+ if ( !m_pRedlineData )
+ return;
+
+ switch ( m_pRedlineData->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ m_pSerializer->endElementNS( XML_w, XML_ins );
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ m_pSerializer->endElementNS( XML_w, XML_del );
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()\n" );
+ break;
+ default:
+ break;
+ }
+
+ m_pRedlineData = NULL;
+}
+
+void DocxAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle )\n" );
+}
+
+void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
+{
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( nStyle ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_pStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+}
+
+static OString impl_ConvertColor( const Color &rColor )
+{
+ OString color( "auto" );
+ if ( rColor.GetColor() != COL_AUTO )
+ {
+ const char pHexDigits[] = "0123456789ABCDEF";
+ char pBuffer[] = "000000";
+
+ pBuffer[0] = pHexDigits[ ( rColor.GetRed() >> 4 ) & 0x0F ];
+ pBuffer[1] = pHexDigits[ rColor.GetRed() & 0x0F ];
+ pBuffer[2] = pHexDigits[ ( rColor.GetGreen() >> 4 ) & 0x0F ];
+ pBuffer[3] = pHexDigits[ rColor.GetGreen() & 0x0F ];
+ pBuffer[4] = pHexDigits[ ( rColor.GetBlue() >> 4 ) & 0x0F ];
+ pBuffer[5] = pHexDigits[ rColor.GetBlue() & 0x0F ];
+
+ color = OString( pBuffer );
+ }
+ return color;
+}
+
+static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist )
+{
+ FastAttributeList* pAttr = pSerializer->createAttrList();
+
+
+ // Compute val attribute value
+ // Can be one of:
+ // single, double,
+ // basicWideOutline, basicWideInline
+ // OOXml also supports those types of borders, but we'll try to play with the first ones.
+ // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
+ // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
+ const char* pVal = "none";
+ if ( !pBorderLine->isEmpty( ) )
+ {
+ switch ( pBorderLine->GetStyle( ) )
+ {
+ case ::editeng::SOLID:
+ pVal = ( sal_Char* )"single";
+ break;
+ case ::editeng::DOTTED:
+ pVal = ( sal_Char* )"dotted";
+ break;
+ case ::editeng::DASHED:
+ pVal = ( sal_Char* )"dashed";
+ break;
+ case ::editeng::DOUBLE:
+ pVal = ( sal_Char* )"double";
+ break;
+ case ::editeng::THINTHICK_SMALLGAP:
+ pVal = ( sal_Char* )"thinThickSmallGap";
+ break;
+ case ::editeng::THINTHICK_MEDIUMGAP:
+ pVal = ( sal_Char* )"thinThickMediumGap";
+ break;
+ case ::editeng::THINTHICK_LARGEGAP:
+ pVal = ( sal_Char* )"thinThickLargeGap";
+ break;
+ case ::editeng::THICKTHIN_SMALLGAP:
+ pVal = ( sal_Char* )"thickThinSmallGap";
+ break;
+ case ::editeng::THICKTHIN_MEDIUMGAP:
+ pVal = ( sal_Char* )"thickThinMediumGap";
+ break;
+ case ::editeng::THICKTHIN_LARGEGAP:
+ pVal = ( sal_Char* )"thickThinLargeGap";
+ break;
+ case ::editeng::EMBOSSED:
+ pVal = ( sal_Char* )"threeDEmboss";
+ break;
+ case ::editeng::ENGRAVED:
+ pVal = ( sal_Char* )"threeDEngrave";
+ break;
+ case ::editeng::OUTSET:
+ pVal = ( sal_Char* )"outset";
+ break;
+ case ::editeng::INSET:
+ pVal = ( sal_Char* )"inset";
+ break;
+ case ::editeng::NO_STYLE:
+ default:
+ break;
+ }
+ }
+
+ pAttr->add( FSNS( XML_w, XML_val ), OString( pVal ) );
+
+ if ( !pBorderLine->isEmpty() )
+ {
+ // Compute the sz attribute
+
+ // The unit is the 8th of point
+ sal_Int32 nWidth = sal_Int32( pBorderLine->GetWidth() / 2.5 );
+ sal_uInt16 nMinWidth = 2;
+ sal_uInt16 nMaxWidth = 96;
+
+ if ( nWidth > nMaxWidth )
+ nWidth = nMaxWidth;
+ else if ( nWidth < nMinWidth )
+ nWidth = nMinWidth;
+
+ pAttr->add( FSNS( XML_w, XML_sz ), OString::valueOf( sal_Int32( nWidth ) ) );
+
+ // Get the distance (in pt)
+ pAttr->add( FSNS( XML_w, XML_space ), OString::valueOf( sal_Int32( nDist / 20 ) ) );
+
+ // Get the color code as an RRGGBB hex value
+ OString sColor( impl_ConvertColor( pBorderLine->GetColor( ) ) );
+ pAttr->add( FSNS( XML_w, XML_color ), sColor );
+ }
+
+ XFastAttributeListRef xAttrs( pAttr );
+ pSerializer->singleElementNS( XML_w, elementToken, xAttrs );
+}
+
+static void impl_pageBorders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, bool bUseStartEnd = false )
+{
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ const sal_Int32 aXmlElements[] =
+ {
+ XML_top,
+ bUseStartEnd ? XML_start : XML_left,
+ XML_bottom,
+ bUseStartEnd ? XML_end : XML_right
+ };
+ const sal_uInt16* pBrd = aBorders;
+ for( int i = 0; i < 4; ++i, ++pBrd )
+ {
+ const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
+ if ( pLn )
+ impl_borderLine( pSerializer, aXmlElements[i], pLn, 0 );
+ }
+}
+
+void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ m_pSerializer->startElementNS( XML_w, XML_tcPr, FSEND );
+
+ const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
+
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ // Cell prefered width
+ SwTwips nWidth = GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() );
+ if ( pTableTextNodeInfoInner->getCell() )
+ nWidth = nWidth - GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() - 1 );
+ m_pSerializer->singleElementNS( XML_w, XML_tcW,
+ FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nWidth ) ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+
+ // Horizontal spans
+ const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
+ SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
+ SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
+
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ if ( nColSpan > 1 )
+ m_pSerializer->singleElementNS( XML_w, XML_gridSpan,
+ FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nColSpan ) ).getStr(),
+ FSEND );
+
+ // Vertical merges
+ long vSpan = pTblBox->getRowSpan( );
+ if ( vSpan > 1 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_vMerge,
+ FSNS( XML_w, XML_val ), "restart",
+ FSEND );
+ }
+ else if ( vSpan < 0 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_vMerge,
+ FSNS( XML_w, XML_val ), "continue",
+ FSEND );
+ }
+
+ // The cell borders
+ m_pSerializer->startElementNS( XML_w, XML_tcBorders, FSEND );
+ SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
+ impl_pageBorders( m_pSerializer, pFmt->GetBox( ), !bEcma );
+ m_pSerializer->endElementNS( XML_w, XML_tcBorders );
+
+ TableBackgrounds( pTableTextNodeInfoInner );
+
+ // Cell margins
+ m_pSerializer->startElementNS( XML_w, XML_tcMar, FSEND );
+ const SvxBoxItem& rBox = pFmt->GetBox( );
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ const sal_Int32 aXmlElements[] =
+ {
+ XML_top,
+ bEcma ? XML_left : XML_start,
+ XML_bottom,
+ bEcma ? XML_right : XML_end
+ };
+ const sal_uInt16* pBrd = aBorders;
+ for( int i = 0; i < 4; ++i, ++pBrd )
+ {
+ sal_Int32 nDist = sal_Int32( rBox.GetDistance( *pBrd ) );
+ m_pSerializer->singleElementNS( XML_w, aXmlElements[i],
+ FSNS( XML_w, XML_w ), OString::valueOf( nDist ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_tcMar );
+
+ TableVerticalCell( pTableTextNodeInfoInner );
+
+ m_pSerializer->endElementNS( XML_w, XML_tcPr );
+}
+
+void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ // Create the SwWriteTable instance to use col spans (and maybe other infos)
+ GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
+
+ const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
+ SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
+
+ const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
+ if( pLayout && pLayout->IsExportable() )
+ m_pTableWrt = new SwWriteTable( pLayout );
+ else
+ m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
+ (sal_uInt16)nTblSz, false);
+}
+
+void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND );
+
+ InitTableHelper( pTableTextNodeInfoInner );
+ TableDefinition( pTableTextNodeInfoInner );
+}
+
+void DocxAttributeOutput::EndTable()
+{
+ m_pSerializer->endElementNS( XML_w, XML_tbl );
+
+ if ( m_nTableDepth > 0 )
+ --m_nTableDepth;
+
+ // We closed the table; if it is a nested table, the cell that contains it
+ // still continues
+ m_bTableCellOpen = true;
+
+ // Cleans the table helper
+ delete m_pTableWrt, m_pTableWrt = NULL;
+}
+
+void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ m_pSerializer->startElementNS( XML_w, XML_tr, FSEND );
+
+ // Output the row properties
+ m_pSerializer->startElementNS( XML_w, XML_trPr, FSEND );
+
+ // Header row: tblHeader
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
+ if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
+ m_pSerializer->singleElementNS( XML_w, XML_tblHeader,
+ FSNS( XML_w, XML_val ), "true",
+ FSEND );
+
+ TableHeight( pTableTextNodeInfoInner );
+ TableCanSplit( pTableTextNodeInfoInner );
+
+ m_pSerializer->endElementNS( XML_w, XML_trPr );
+}
+
+void DocxAttributeOutput::EndTableRow( )
+{
+ m_pSerializer->endElementNS( XML_w, XML_tr );
+}
+
+void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ if ( !m_pTableWrt )
+ InitTableHelper( pTableTextNodeInfoInner );
+
+ m_pSerializer->startElementNS( XML_w, XML_tc, FSEND );
+
+ // Write the cell properties here
+ TableCellProperties( pTableTextNodeInfoInner );
+
+ m_bTableCellOpen = true;
+}
+
+void DocxAttributeOutput::EndTableCell( )
+{
+ m_pSerializer->endElementNS( XML_w, XML_tc );
+
+ m_bTableCellOpen = false;
+}
+
+void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+}
+
+void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
+{
+}
+
+void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ // Write the table properties
+ m_pSerializer->startElementNS( XML_w, XML_tblPr, FSEND );
+
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ // Create the SwWriteTable instance to use col spans (and maybe other infos)
+ GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
+
+ // Output the table prefered width
+ if ( nPageSize != 0 )
+ m_pSerializer->singleElementNS( XML_w, XML_tblW,
+ FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nPageSize ) ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+
+ // Output the table alignement
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable();
+ SwFrmFmt *pTblFmt = pTable->GetFrmFmt( );
+ const char* pJcVal;
+ sal_Int32 nIndent = 0;
+ switch ( pTblFmt->GetHoriOrient( ).GetHoriOrient( ) )
+ {
+ case text::HoriOrientation::CENTER:
+ pJcVal = "center";
+ break;
+ case text::HoriOrientation::RIGHT:
+ if ( bEcma )
+ pJcVal = "right";
+ else
+ pJcVal = "end";
+ break;
+ default:
+ case text::HoriOrientation::NONE:
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ {
+ if ( bEcma )
+ pJcVal = "left";
+ else
+ pJcVal = "start";
+ nIndent = sal_Int32( pTblFmt->GetLRSpace( ).GetLeft( ) );
+ break;
+ }
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_jc,
+ FSNS( XML_w, XML_val ), pJcVal,
+ FSEND );
+
+ // Output the table borders
+ TableDefaultBorders( pTableTextNodeInfoInner );
+ TableBidi( pTableTextNodeInfoInner );
+
+ // Table indent
+ if ( nIndent != 0 )
+ m_pSerializer->singleElementNS( XML_w, XML_tblInd,
+ FSNS( XML_w, XML_w ), OString::valueOf( nIndent ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+
+ m_pSerializer->endElementNS( XML_w, XML_tblPr );
+
+ // Write the table grid infos
+ m_pSerializer->startElementNS( XML_w, XML_tblGrid, FSEND );
+ sal_Int32 nPrv = 0;
+ ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
+ for ( ww8::GridCols::const_iterator it = pGridCols->begin(); it != pGridCols->end(); ++it )
+ {
+ sal_Int32 nWidth = sal_Int32( *it ) - nPrv;
+ m_pSerializer->singleElementNS( XML_w, XML_gridCol,
+ FSNS( XML_w, XML_w ), OString::valueOf( nWidth ).getStr( ),
+ FSEND );
+ nPrv = sal_Int32( *it );
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_tblGrid );
+}
+
+void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
+
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ // the defaults of the table are taken from the top-left cell
+ m_pSerializer->startElementNS( XML_w, XML_tblBorders, FSEND );
+ impl_pageBorders( m_pSerializer, pFrmFmt->GetBox( ), !bEcma );
+ m_pSerializer->endElementNS( XML_w, XML_tblBorders );
+}
+
+void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
+ const SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
+ const SfxPoolItem *pI = NULL;
+
+ Color aColor;
+ if ( SFX_ITEM_ON == pFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
+ aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
+ else
+ aColor = COL_AUTO;
+
+ OString sColor = impl_ConvertColor( aColor );
+ m_pSerializer->singleElementNS( XML_w, XML_shd,
+ FSNS( XML_w, XML_fill ), sColor.getStr( ),
+ FSNS( XML_w, XML_val ), "clear",
+ FSEND );
+}
+
+void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
+ if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
+ {
+ sal_Int32 nHeight = rLSz.GetHeight();
+ const char *pRule = NULL;
+
+ switch ( rLSz.GetHeightSizeType() )
+ {
+ case ATT_FIX_SIZE: pRule = "exact"; break;
+ case ATT_MIN_SIZE: pRule = "atLeast"; break;
+ default: break;
+ }
+
+ if ( pRule )
+ m_pSerializer->singleElementNS( XML_w, XML_trHeight,
+ FSNS( XML_w, XML_val ), OString::valueOf( nHeight ).getStr( ),
+ FSNS( XML_w, XML_hRule ), pRule,
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
+ const char* pCantSplit = ( !rSplittable.GetValue( ) ) ? "true" : "false";
+
+ m_pSerializer->singleElementNS( XML_w, XML_cantSplit,
+ FSNS( XML_w, XML_val ), pCantSplit,
+ FSEND );
+}
+
+void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+ const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+
+ if ( m_rExport.TrueFrameDirection( *pFrmFmt ) == FRMDIR_HORI_RIGHT_TOP )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_bidiVisual,
+ FSNS( XML_w, XML_val ), "true",
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwFrmFmt *pFrmFmt = pTabBox->GetFrmFmt( );
+
+ if ( FRMDIR_VERT_TOP_RIGHT == m_rExport.TrueFrameDirection( *pFrmFmt ) )
+ m_pSerializer->singleElementNS( XML_w, XML_textDirection,
+ FSNS( XML_w, XML_val ), "tbRl",
+ FSEND );
+}
+
+void DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
+{
+ OSL_TRACE( "TODO: DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )\n" );
+}
+
+void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
+{
+ // This is called when the nested table ends in a cell, and there's no
+ // paragraph benhind that; so we must check for the ends of cell, rows,
+ // tables
+ // ['true' to write an empty paragraph, MS Word insists on that]
+ FinishTableRowCell( pNodeInfoInner, true );
+}
+
+void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+ OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
+}
+
+void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
+#endif
+}
+
+void DocxAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
+{
+ OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )\n" );
+}
+
+void DocxAttributeOutput::StartStyles()
+{
+ m_pSerializer->startElementNS( XML_w, XML_styles,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+}
+
+void DocxAttributeOutput::EndStyles( sal_uInt16 /*nNumberOfStyles*/ )
+{
+ m_pSerializer->endElementNS( XML_w, XML_styles );
+}
+
+void DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )
+{
+ // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
+#if OSL_DEBUG_LEVEL > 1
+ OSL_TRACE( "TODO DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )- %d\n", nStyle );
+#else
+ (void) nStyle; // to quiet the warning
+#endif
+}
+
+void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize ) - some stuff still missing\n" );
+ // create the relation ID
+ OString aRelId;
+ sal_Int32 nImageType;
+ if ( rGrfNode.IsLinkedFile() )
+ {
+ // linked image, just create the relation
+ String aFileName;
+ rGrfNode.GetFileFilterNms( &aFileName, 0 );
+
+ // TODO Convert the file name to relative for better interoperability
+
+ aRelId = m_rExport.AddRelation(
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ),
+ OUString( aFileName ),
+ S( "External" ) );
+
+ nImageType = XML_link;
+ }
+ else
+ {
+ // inline, we also have to write the image itself
+ Graphic& rGraphic = const_cast< Graphic& >( rGrfNode.GetGrf() );
+
+ m_rDrawingML.SetFS( m_pSerializer ); // to be sure that we write to the right stream
+ OUString aImageId = m_rDrawingML.WriteImage( rGraphic );
+
+ aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
+
+ nImageType = XML_embed;
+ }
+
+ if ( aRelId.getLength() == 0 )
+ return;
+
+ m_pSerializer->startElementNS( XML_w, XML_drawing,
+ FSEND );
+ bool isAnchor = rGrfNode.GetFlyFmt()->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
+ if( isAnchor )
+ {
+ m_pSerializer->startElementNS( XML_wp, XML_anchor,
+ XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0", XML_simplePos, "0",
+ XML_relativeHeight, "0", // TODO
+ XML_behindDoc, rGrfNode.GetFlyFmt()->GetOpaque().GetValue() ? "0" : "1",
+ XML_locked, "0", XML_layoutInCell, "1", XML_allowOverlap, "1", // TODO
+ FSEND );
+ m_pSerializer->singleElementNS( XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND ); // required, unused
+ const char* relativeFromH;
+ const char* relativeFromV;
+ switch( rGrfNode.GetFlyFmt()->GetAnchor().GetAnchorId())
+ {
+ case FLY_AT_PAGE:
+ relativeFromV = relativeFromH = "page";
+ break;
+ case FLY_AT_PARA:
+ relativeFromH = "column";
+ relativeFromV = "paragraph";
+ break;
+ case FLY_AT_CHAR:
+ default:
+ relativeFromH = "character";
+ relativeFromV = "line";
+ break;
+ };
+ Point pos( 0, 0 );
+ if( SwFlyFrmFmt* flyfmt = dynamic_cast<SwFlyFrmFmt*>(rGrfNode.GetFlyFmt())) // TODO is always true?
+ pos = flyfmt->GetAnchoredObj()->GetCurrRelPos();
+ OString x( OString::valueOf( TwipsToEMU( pos.X())));
+ OString y( OString::valueOf( TwipsToEMU( pos.Y())));
+ m_pSerializer->startElementNS( XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND );
+ m_pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND );
+ m_pSerializer->write( x );
+ m_pSerializer->endElementNS( XML_wp, XML_posOffset );
+ m_pSerializer->endElementNS( XML_wp, XML_positionH );
+ m_pSerializer->startElementNS( XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND );
+ m_pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND );
+ m_pSerializer->write( y );
+ m_pSerializer->endElementNS( XML_wp, XML_posOffset );
+ m_pSerializer->endElementNS( XML_wp, XML_positionV );
+ }
+ else
+ {
+ m_pSerializer->startElementNS( XML_wp, XML_inline,
+ XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
+ FSEND );
+ }
+ // now the common parts
+ // extent of the image
+ OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
+ OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
+ m_pSerializer->singleElementNS( XML_wp, XML_extent,
+ XML_cx, aWidth.getStr(),
+ XML_cy, aHeight.getStr(),
+ FSEND );
+ // TODO - the right effectExtent, extent including the effect
+ m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
+ XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
+ FSEND );
+
+ if( isAnchor )
+ {
+ switch( rGrfNode.GetFlyFmt()->GetSurround().GetValue())
+ {
+ case SURROUND_NONE:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapTopAndBottom, FSEND );
+ break;
+ case SURROUND_THROUGHT:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapNone, FSEND );
+ break;
+ case SURROUND_PARALLEL:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapSquare,
+ XML_wrapText, "bothSides", FSEND );
+ break;
+ case SURROUND_IDEAL:
+ default:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapSquare,
+ XML_wrapText, "largest", FSEND );
+ break;
+ }
+ }
+ // picture description
+ // TODO the right image description
+ m_pSerializer->startElementNS( XML_wp, XML_docPr,
+ XML_id, "1",
+ XML_name, "Picture",
+ XML_descr, "A description...",
+ FSEND );
+ // TODO hyperlink
+ // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
+ // FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ // FSNS( XML_r, XML_id ), "rId4",
+ // FSEND );
+ m_pSerializer->endElementNS( XML_wp, XML_docPr );
+
+ m_pSerializer->startElementNS( XML_wp, XML_cNvGraphicFramePr,
+ FSEND );
+ // TODO change aspect?
+ m_pSerializer->singleElementNS( XML_a, XML_graphicFrameLocks,
+ FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ XML_noChangeAspect, "1",
+ FSEND );
+ m_pSerializer->endElementNS( XML_wp, XML_cNvGraphicFramePr );
+
+ m_pSerializer->startElementNS( XML_a, XML_graphic,
+ FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_graphicData,
+ XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/picture",
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_pic, XML_pic,
+ FSNS( XML_xmlns, XML_pic ), "http://schemas.openxmlformats.org/drawingml/2006/picture",
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_pic, XML_nvPicPr,
+ FSEND );
+ // TODO the right image description
+ m_pSerializer->startElementNS( XML_pic, XML_cNvPr,
+ XML_id, "0",
+ XML_name, "Picture",
+ XML_descr, "A description...",
+ FSEND );
+ // TODO hyperlink
+ // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
+ // FSNS( XML_r, XML_id ), "rId4",
+ // FSEND );
+ m_pSerializer->endElementNS( XML_pic, XML_cNvPr );
+
+ m_pSerializer->startElementNS( XML_pic, XML_cNvPicPr,
+ FSEND );
+ // TODO change aspect?
+ m_pSerializer->singleElementNS( XML_a, XML_picLocks,
+ XML_noChangeAspect, "1", XML_noChangeArrowheads, "1",
+ FSEND );
+ m_pSerializer->endElementNS( XML_pic, XML_cNvPicPr );
+ m_pSerializer->endElementNS( XML_pic, XML_nvPicPr );
+
+ // the actual picture
+ m_pSerializer->startElementNS( XML_pic, XML_blipFill,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_blip,
+ FSNS( XML_r, nImageType ), aRelId.getStr(),
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_srcRect,
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_stretch,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_fillRect,
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_stretch );
+ m_pSerializer->endElementNS( XML_pic, XML_blipFill );
+
+ // TODO setup the right values below
+ m_pSerializer->startElementNS( XML_pic, XML_spPr,
+ XML_bwMode, "auto",
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_xfrm,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_off,
+ XML_x, "0", XML_y, "0",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_ext,
+ XML_cx, aWidth.getStr(),
+ XML_cy, aHeight.getStr(),
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_xfrm );
+ m_pSerializer->startElementNS( XML_a, XML_prstGeom,
+ XML_prst, "rect",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_avLst,
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_prstGeom );
+ m_pSerializer->singleElementNS( XML_a, XML_noFill,
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_ln,
+ XML_w, "9525",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_noFill,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_miter,
+ XML_lim, "800000",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_headEnd,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_tailEnd,
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_ln );
+ m_pSerializer->endElementNS( XML_pic, XML_spPr );
+
+ m_pSerializer->endElementNS( XML_pic, XML_pic );
+
+ m_pSerializer->endElementNS( XML_a, XML_graphicData );
+ m_pSerializer->endElementNS( XML_a, XML_graphic );
+ m_pSerializer->endElementNS( XML_wp, isAnchor ? XML_anchor : XML_inline );
+
+ m_pSerializer->endElementNS( XML_w, XML_drawing );
+}
+
+void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, const Size& rSize )
+{
+ uno::Reference< chart2::XChartDocument > xChartDoc;
+ uno::Reference< drawing::XShape > xShape( ((SdrObject*)pSdrObj)->getUnoShape(), uno::UNO_QUERY );
+ if( xShape.is() )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
+ if( xPropSet.is() )
+ xChartDoc.set( xPropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Model")) ), uno::UNO_QUERY );
+ }
+
+ if( xChartDoc.is() )
+ {
+ OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
+ m_pSerializer->startElementNS( XML_w, XML_drawing,
+ FSEND );
+ m_pSerializer->startElementNS( XML_wp, XML_inline,
+ XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
+ FSEND );
+
+ OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
+ OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
+ m_pSerializer->singleElementNS( XML_wp, XML_extent,
+ XML_cx, aWidth.getStr(),
+ XML_cy, aHeight.getStr(),
+ FSEND );
+ // TODO - the right effectExtent, extent including the effect
+ m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
+ XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
+ FSEND );
+
+ // should get the unique id
+ sal_Int32 nID = 1;
+ OUString sName(RTL_CONSTASCII_USTRINGPARAM("Object 1"));
+ uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
+ if( xNamed.is() )
+ sName = xNamed->getName();
+
+ m_pSerializer->singleElementNS( XML_wp, XML_docPr,
+ XML_id, I32S( nID ),
+ XML_name, USS( sName ),
+ FSEND );
+
+ m_pSerializer->singleElementNS( XML_wp, XML_cNvGraphicFramePr,
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_a, XML_graphic,
+ FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_a, XML_graphicData,
+ XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart",
+ FSEND );
+
+ OString aRelId;
+ static sal_Int32 nChartCount = 0;
+ nChartCount++;
+ uno::Reference< frame::XModel > xModel( xChartDoc, uno::UNO_QUERY );
+ aRelId = m_rExport.OutputChart( xModel, nChartCount );
+
+ m_pSerializer->singleElementNS( XML_c, XML_chart,
+ FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
+ FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+ FSNS( XML_r, XML_id ), aRelId.getStr(),
+ FSEND );
+
+ m_pSerializer->endElementNS( XML_a, XML_graphicData );
+ m_pSerializer->endElementNS( XML_a, XML_graphic );
+ m_pSerializer->endElementNS( XML_wp, XML_inline );
+ m_pSerializer->endElementNS( XML_w, XML_drawing );
+ }
+}
+
+void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Point& /*rNdTopLeft*/ )
+{
+ m_pSerializer->mark();
+
+ switch ( rFrame.GetWriterType() )
+ {
+ case sw::Frame::eGraphic:
+ {
+ const SwNode *pNode = rFrame.GetContent();
+ const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
+ if ( pGrfNode )
+ FlyFrameGraphic( *pGrfNode, rFrame.GetLayoutSize() );
+ }
+ break;
+ case sw::Frame::eDrawing:
+ {
+ const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
+ if ( pSdrObj )
+ {
+ bool bSwapInPage = false;
+ if ( !pSdrObj->GetPage() )
+ {
+ if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() )
+ {
+ if ( SdrPage *pPage = pModel->GetPage( 0 ) )
+ {
+ bSwapInPage = true;
+ const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
+ }
+ }
+ }
+
+ m_pSerializer->startElementNS( XML_w, XML_pict,
+ FSEND );
+
+ m_rExport.VMLExporter().AddSdrObject( *pSdrObj );
+
+ m_pSerializer->endElementNS( XML_w, XML_pict );
+
+ if ( bSwapInPage )
+ const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
+ }
+ }
+ break;
+ case sw::Frame::eTxtBox:
+ {
+ // The frame output is postponed at the end of the anchor paragraph
+ m_pParentFrame = &rFrame;
+ }
+ break;
+ case sw::Frame::eOle:
+ {
+ const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
+ if ( pSdrObj )
+ WriteOLE2Obj( pSdrObj, rFrame.GetLayoutSize() );
+ }
+ break;
+ default:
+ OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
+ rFrame.GetWriterType() == sw::Frame::eTxtBox? "eTxtBox":
+ ( rFrame.GetWriterType() == sw::Frame::eOle? "eOle":
+ ( rFrame.GetWriterType() == sw::Frame::eFormControl? "eFormControl": "???" ) ) );
+ break;
+ }
+
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
+}
+
+void DocxAttributeOutput::StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId, bool bAutoUpdate )
+{
+ OString aStyle( "style" );
+
+ m_pSerializer->startElementNS( XML_w, XML_style,
+ FSNS( XML_w, XML_type ), bPapFmt? "paragraph": "character", // FIXME is this correct?
+ FSNS( XML_w, XML_styleId ), ( aStyle + OString::valueOf( sal_Int32( nId ) ) ).getStr(),
+ FSEND );
+
+ m_pSerializer->singleElementNS( XML_w, XML_name,
+ FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ if ( nBase != 0x0FFF )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_basedOn,
+ FSNS( XML_w, XML_val ), ( aStyle + OString::valueOf( sal_Int32( nBase ) ) ).getStr(),
+ FSEND );
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_next,
+ FSNS( XML_w, XML_val ), ( aStyle + OString::valueOf( sal_Int32( nNext ) ) ).getStr(),
+ FSEND );
+
+ if ( bAutoUpdate )
+ m_pSerializer->singleElementNS( XML_w, XML_autoRedefine, FSEND );
+}
+
+void DocxAttributeOutput::EndStyle()
+{
+ m_pSerializer->endElementNS( XML_w, XML_style );
+}
+
+void DocxAttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 /*nStyle*/ )
+{
+ if ( bParProp )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+ InitCollectedParagraphProperties();
+ }
+ else
+ {
+ m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
+ InitCollectedRunProperties();
+ }
+}
+
+void DocxAttributeOutput::EndStyleProperties( bool bParProp )
+{
+ if ( bParProp )
+ {
+ WriteCollectedParagraphProperties();
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+ }
+ else
+ {
+ WriteCollectedRunProperties();
+ m_pSerializer->endElementNS( XML_w, XML_rPr );
+ }
+}
+
+void DocxAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
+{
+ if ( nLvl >= WW8ListManager::nMaxLevel )
+ nLvl = WW8ListManager::nMaxLevel - 1;
+
+ m_pSerializer->singleElementNS( XML_w, XML_outlineLvl,
+ FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl ) ).getStr( ),
+ FSEND );
+}
+
+void DocxAttributeOutput::PageBreakBefore( bool bBreak )
+{
+ if ( bBreak )
+ m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore,
+ FSNS( XML_w, XML_val ), "false",
+ FSEND );
+}
+
+void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
+{
+ switch ( nC )
+ {
+ case msword::ColumnBreak:
+ // The column break should be output in the next paragraph...
+ m_nColBreakStatus = COLBRK_POSTPONE;
+ break;
+ case msword::PageBreak:
+ if ( pSectionInfo )
+ {
+ if ( !m_bParagraphOpened )
+ {
+ // Create a dummy paragraph if needed
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+
+ m_rExport.SectionProperties( *pSectionInfo );
+
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+ m_pSerializer->endElementNS( XML_w, XML_p );
+ }
+ else
+ {
+ // postpone the output of this; it has to be done inside the
+ // paragraph properties, so remember it until then
+ m_pSectionInfo = pSectionInfo;
+ }
+ }
+ else
+ {
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_br,
+ FSNS( XML_w, XML_type ), "page", FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ }
+ break;
+ default:
+ OSL_TRACE( "Unknown section break to write: %d\n", nC );
+ break;
+ }
+}
+
+void DocxAttributeOutput::StartSection()
+{
+ m_pSerializer->startElementNS( XML_w, XML_sectPr, FSEND );
+ m_bOpenedSectPr = true;
+
+ // Write the elements in the spec order
+ static const sal_Int32 aOrder[] =
+ {
+ FSNS( XML_w, XML_headerReference ),
+ FSNS( XML_w, XML_footerReference ),
+ FSNS( XML_w, XML_footnotePr ),
+ FSNS( XML_w, XML_endnotePr ),
+ FSNS( XML_w, XML_type ),
+ FSNS( XML_w, XML_pgSz ),
+ FSNS( XML_w, XML_pgMar ),
+ FSNS( XML_w, XML_paperSrc ),
+ FSNS( XML_w, XML_pgBorders ),
+ FSNS( XML_w, XML_lnNumType ),
+ FSNS( XML_w, XML_pgNumType ),
+ FSNS( XML_w, XML_cols ),
+ FSNS( XML_w, XML_formProt ),
+ FSNS( XML_w, XML_vAlign ),
+ FSNS( XML_w, XML_noEndnote ),
+ FSNS( XML_w, XML_titlePg ),
+ FSNS( XML_w, XML_textDirection ),
+ FSNS( XML_w, XML_bidi ),
+ FSNS( XML_w, XML_rtlGutter ),
+ FSNS( XML_w, XML_docGrid ),
+ FSNS( XML_w, XML_printerSettings ),
+ FSNS( XML_w, XML_sectPrChange )
+ };
+
+ // postpone the output so that we can later [in EndParagraphProperties()]
+ // prepend the properties before the run
+ sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
+ uno::Sequence< sal_Int32 > aSeqOrder( len );
+ for ( sal_Int32 i = 0; i < len; i++ )
+ aSeqOrder[i] = aOrder[i];
+
+ m_pSerializer->mark( aSeqOrder );
+}
+
+void DocxAttributeOutput::EndSection()
+{
+ // Write the section properties
+ if ( m_pSectionSpacingAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pSectionSpacingAttrList );
+ m_pSectionSpacingAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_pgMar, xAttrList );
+ }
+
+ // Order the elements
+ m_pSerializer->mergeTopMarks( );
+
+ m_pSerializer->endElementNS( XML_w, XML_sectPr );
+ m_bOpenedSectPr = false;
+}
+
+void DocxAttributeOutput::SectionFormProtection( bool bProtected )
+{
+ if ( bProtected )
+ m_pSerializer->singleElementNS( XML_w, XML_formProt, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_formProt,
+ FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo )
+{
+ FastAttributeList* pAttr = m_pSerializer->createAttrList();
+ pAttr->add( FSNS( XML_w, XML_countBy ), OString::valueOf(static_cast<sal_Int32>(rLnNumInfo.GetCountBy())).getStr());
+ pAttr->add( FSNS( XML_w, XML_restart ), rLnNumInfo.IsRestartEachPage() ? "newPage" : "continuous" );
+ if( rLnNumInfo.GetPosFromLeft())
+ pAttr->add( FSNS( XML_w, XML_distance ), OString::valueOf(static_cast<sal_Int32>(rLnNumInfo.GetPosFromLeft())).getStr());
+ if( nRestartNo )
+ pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( long( nRestartNo )).getStr());
+ XFastAttributeListRef xAttrs( pAttr );
+ m_pSerializer->singleElementNS( XML_w, XML_lnNumType, xAttrs );
+}
+
+void DocxAttributeOutput::SectionTitlePage()
+{
+ m_pSerializer->singleElementNS( XML_w, XML_titlePg, FSEND );
+}
+
+void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
+{
+ // Output the margins
+
+ const SvxBoxItem& rBox = pFmt->GetBox( );
+
+ const SvxBorderLine* pBottom = rBox.GetBottom( );
+ const SvxBorderLine* pTop = rBox.GetTop( );
+ const SvxBorderLine* pLeft = rBox.GetLeft( );
+ const SvxBorderLine* pRight = rBox.GetRight( );
+
+ if ( pBottom || pTop || pLeft || pRight )
+ {
+ // All distances are relative to the text margins
+ m_pSerializer->startElementNS( XML_w, XML_pgBorders,
+ FSNS( XML_w, XML_display ), "allPages",
+ FSNS( XML_w, XML_offsetFrom ), "text",
+ FSEND );
+
+ m_pSerializer->mark();
+
+ m_pSerializer->endElementNS( XML_w, XML_pgBorders );
+ m_pSerializer->mark();
+ }
+}
+
+void DocxAttributeOutput::SectionBiDi( bool bBiDi )
+{
+ if ( bBiDi )
+ m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
+}
+
+static OString impl_NumberingType( sal_uInt16 nNumberingType )
+{
+ OString aType;
+
+ switch ( nNumberingType )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: aType = "upperLetter"; break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: aType = "lowerLetter"; break;
+ case SVX_NUM_ROMAN_UPPER: aType = "upperRoman"; break;
+ case SVX_NUM_ROMAN_LOWER: aType = "lowerRoman"; break;
+
+ case SVX_NUM_ARABIC: aType = "decimal"; break;
+
+ case SVX_NUM_BITMAP:
+ case SVX_NUM_CHAR_SPECIAL: aType = "bullet"; break;
+
+ default: aType = "none"; break;
+ }
+
+ return aType;
+}
+
+void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
+{
+ // FIXME Not called properly with page styles like "First Page"
+
+ FastAttributeList* pAttr = m_pSerializer->createAttrList();
+
+ // 0 means no restart: then don't output that attribute if 0
+ if ( nPageRestartNumber > 0 )
+ pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( sal_Int32( nPageRestartNumber ) ) );
+
+ // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
+ OString aFmt( impl_NumberingType( nNumType ) );
+ if ( aFmt.getLength() )
+ pAttr->add( FSNS( XML_w, XML_fmt ), aFmt.getStr() );
+
+ XFastAttributeListRef xAttrs( pAttr );
+ m_pSerializer->singleElementNS( XML_w, XML_pgNumType, xAttrs );
+
+ // see 2.6.12 pgNumType (Page Numbering Settings)
+ OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()\n" );
+}
+
+void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode )
+{
+ /* break code: 0 No break, 1 New column
+ 2 New page, 3 Even page, 4 Odd page
+ */
+ const char* pType = NULL;
+ switch ( nBreakCode )
+ {
+ case 1: pType = "nextColumn"; break;
+ case 2: pType = "nextPage"; break;
+ case 3: pType = "evenPage"; break;
+ case 4: pType = "oddPage"; break;
+ default: pType = "continuous"; break;
+ }
+
+ if ( pType )
+ m_pSerializer->singleElementNS( XML_w, XML_type,
+ FSNS( XML_w, XML_val ), pType,
+ FSEND );
+}
+
+void DocxAttributeOutput::StartFont( const String& rFamilyName ) const
+{
+ m_pSerializer->startElementNS( XML_w, XML_font,
+ FSNS( XML_w, XML_name ), OUStringToOString( OUString( rFamilyName ), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+}
+
+void DocxAttributeOutput::EndFont() const
+{
+ m_pSerializer->endElementNS( XML_w, XML_font );
+}
+
+void DocxAttributeOutput::FontAlternateName( const String& rName ) const
+{
+ m_pSerializer->singleElementNS( XML_w, XML_altName,
+ FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+}
+
+void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet, rtl_TextEncoding nEncoding ) const
+{
+ FastAttributeList* pAttr = m_pSerializer->createAttrList();
+
+ OString aCharSet( OString::valueOf( sal_Int32( nCharSet ), 16 ) );
+ if ( aCharSet.getLength() == 1 )
+ aCharSet = OString( "0" ) + aCharSet;
+ pAttr->add( FSNS( XML_w, XML_val ), aCharSet.getStr());
+
+ if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT )
+ {
+ if( const char* charset = rtl_getMimeCharsetFromTextEncoding( nEncoding ))
+ pAttr->add( FSNS( XML_w, XML_characterSet ), charset );
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_charset, XFastAttributeListRef( pAttr ));
+}
+
+void DocxAttributeOutput::FontFamilyType( FontFamily eFamily ) const
+{
+ const char *pFamily = NULL;
+ switch ( eFamily )
+ {
+ case FAMILY_ROMAN: pFamily = "roman"; break;
+ case FAMILY_SWISS: pFamily = "swiss"; break;
+ case FAMILY_MODERN: pFamily = "modern"; break;
+ case FAMILY_SCRIPT: pFamily = "script"; break;
+ case FAMILY_DECORATIVE: pFamily = "decorative"; break;
+ default: pFamily = "auto"; break; // no font family
+ }
+
+ if ( pFamily )
+ m_pSerializer->singleElementNS( XML_w, XML_family,
+ FSNS( XML_w, XML_val ), pFamily,
+ FSEND );
+}
+
+void DocxAttributeOutput::FontPitchType( FontPitch ePitch ) const
+{
+ const char *pPitch = NULL;
+ switch ( ePitch )
+ {
+ case PITCH_VARIABLE: pPitch = "variable"; break;
+ case PITCH_FIXED: pPitch = "fixed"; break;
+ default: pPitch = "default"; break; // no info about the pitch
+ }
+
+ if ( pPitch )
+ m_pSerializer->singleElementNS( XML_w, XML_pitch,
+ FSNS( XML_w, XML_val ), pPitch,
+ FSEND );
+}
+
+void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
+{
+ // nId is the same both for abstract numbering definition as well as the
+ // numbering definition itself
+ // TODO check that this is actually true & fix if not ;-)
+ OString aId( OString::valueOf( sal_Int32( nId ) ) );
+
+ m_pSerializer->startElementNS( XML_w, XML_num,
+ FSNS( XML_w, XML_numId ), aId.getStr(),
+ FSEND );
+
+ m_pSerializer->singleElementNS( XML_w, XML_abstractNumId,
+ FSNS( XML_w, XML_val ), aId.getStr(),
+ FSEND );
+
+#if OSL_DEBUG_LEVEL > 1
+ // TODO ww8 version writes this, anything to do about it here?
+ if ( rRule.IsContinusNum() )
+ OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()\n" );
+#else
+ (void) rRule; // to quiet the warning...
+#endif
+
+ m_pSerializer->endElementNS( XML_w, XML_num );
+}
+
+void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
+{
+ m_pSerializer->startElementNS( XML_w, XML_abstractNum,
+ FSNS( XML_w, XML_abstractNumId ), OString::valueOf( sal_Int32( nId ) ).getStr(),
+ FSEND );
+}
+
+void DocxAttributeOutput::EndAbstractNumbering()
+{
+ m_pSerializer->endElementNS( XML_w, XML_abstractNum );
+}
+
+void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 * /*pNumLvlPos*/,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString )
+{
+ m_pSerializer->startElementNS( XML_w, XML_lvl,
+ FSNS( XML_w, XML_ilvl ), OString::valueOf( sal_Int32( nLevel ) ).getStr(),
+ FSEND );
+
+ // start with the nStart value
+ m_pSerializer->singleElementNS( XML_w, XML_start,
+ FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nStart ) ).getStr(),
+ FSEND );
+
+ // format
+ OString aFmt( impl_NumberingType( nNumberingType ) );
+
+ if ( aFmt.getLength() )
+ m_pSerializer->singleElementNS( XML_w, XML_numFmt,
+ FSNS( XML_w, XML_val ), aFmt.getStr(),
+ FSEND );
+
+ // suffix
+ const char *pSuffix = NULL;
+ switch ( nFollow )
+ {
+ case 1: pSuffix = "space"; break;
+ case 2: pSuffix = "nothing"; break;
+ default: /*pSuffix = "tab";*/ break;
+ }
+ if ( pSuffix )
+ m_pSerializer->singleElementNS( XML_w, XML_suff,
+ FSNS( XML_w, XML_val ), pSuffix,
+ FSEND );
+
+ // text
+ OUString aText( rNumberingString );
+ OUStringBuffer aBuffer( aText.getLength() + WW8ListManager::nMaxLevel );
+
+ const sal_Unicode *pPrev = aText.getStr();
+ const sal_Unicode *pIt = aText.getStr();
+ while ( pIt < aText.getStr() + aText.getLength() )
+ {
+ // convert the level values to %NUMBER form
+ // (we don't use pNumLvlPos at all)
+ // FIXME so far we support the ww8 limit of levels only
+ if ( *pIt < sal_Unicode( WW8ListManager::nMaxLevel ) )
+ {
+ aBuffer.append( pPrev, pIt - pPrev );
+ aBuffer.appendAscii( "%" );
+ aBuffer.append( OUString::valueOf( sal_Int32( *pIt ) + 1 ) );
+
+ pPrev = pIt + 1;
+ }
+ ++pIt;
+ }
+ if ( pPrev < pIt )
+ aBuffer.append( pPrev, pIt - pPrev );
+
+ m_pSerializer->singleElementNS( XML_w, XML_lvlText,
+ FSNS( XML_w, XML_val ), OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ // justification
+ const char *pJc;
+ bool ecmaDialect = ( m_rExport.GetFilter().getVersion() == oox::core::ECMA_DIALECT );
+ switch ( eAdjust )
+ {
+ case SVX_ADJUST_CENTER: pJc = "center"; break;
+ case SVX_ADJUST_RIGHT: pJc = !ecmaDialect ? "end" : "right"; break;
+ default: pJc = !ecmaDialect ? "start" : "left"; break;
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_lvlJc,
+ FSNS( XML_w, XML_val ), pJc,
+ FSEND );
+
+ // indentation
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+ if( nListTabPos != 0 )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_tab,
+ FSNS( XML_w, XML_val ), "num",
+ FSNS( XML_w, XML_pos ), OString::valueOf( static_cast<sal_Int32>(nListTabPos) ).getStr(),
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_tabs );
+ }
+
+ sal_Int32 nToken = ecmaDialect ? XML_left : XML_start;
+ m_pSerializer->singleElementNS( XML_w, XML_ind,
+ FSNS( XML_w, nToken ), OString::valueOf( sal_Int32( nIndentAt ) ).getStr(),
+ FSNS( XML_w, XML_hanging ), OString::valueOf( sal_Int32( -nFirstLineIndex ) ).getStr(),
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+
+ // font
+ if ( pOutSet )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
+
+ if ( pFont )
+ {
+ GetExport().GetId( *pFont ); // ensure font info is written to fontTable.xml
+ OString aFamilyName( OUStringToOString( OUString( pFont->GetFamilyName() ), RTL_TEXTENCODING_UTF8 ) );
+ m_pSerializer->singleElementNS( XML_w, XML_rFonts,
+ FSNS( XML_w, XML_ascii ), aFamilyName.getStr(),
+ FSNS( XML_w, XML_hAnsi ), aFamilyName.getStr(),
+ FSNS( XML_w, XML_cs ), aFamilyName.getStr(),
+ FSNS( XML_w, XML_hint ), "default",
+ FSEND );
+ }
+ m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
+
+ m_pSerializer->endElementNS( XML_w, XML_rPr );
+ }
+
+ // TODO anything to do about nListTabPos?
+
+ m_pSerializer->endElementNS( XML_w, XML_lvl );
+}
+
+void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
+{
+ switch ( rCaseMap.GetValue() )
+ {
+ case SVX_CASEMAP_KAPITAELCHEN:
+ m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSEND );
+ break;
+ case SVX_CASEMAP_VERSALIEN:
+ m_pSerializer->singleElementNS( XML_w, XML_caps, FSEND );
+ break;
+ default: // Something that ooxml does not support
+ m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSNS( XML_w, XML_val ), "false", FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_caps, FSNS( XML_w, XML_val ), "false", FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharColor( const SvxColorItem& rColor )
+{
+ const Color aColor( rColor.GetValue() );
+ OString aColorString;
+
+ aColorString = impl_ConvertColor( aColor );
+
+ m_pSerializer->singleElementNS( XML_w, XML_color,
+ FSNS( XML_w, XML_val ), aColorString.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::CharContour( const SvxContourItem& rContour )
+{
+ if ( rContour.GetValue() )
+ m_pSerializer->singleElementNS( XML_w, XML_outline, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_outline, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
+{
+ switch ( rCrossedOut.GetStrikeout() )
+ {
+ case STRIKEOUT_DOUBLE:
+ m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSEND );
+ break;
+ case STRIKEOUT_NONE:
+ m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSNS( XML_w, XML_val ), "false", FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_strike, FSNS( XML_w, XML_val ), "false", FSEND );
+ break;
+ default:
+ m_pSerializer->singleElementNS( XML_w, XML_strike, FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )
+{
+ OString sIss;
+ short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProp();
+ if ( !nEsc )
+ {
+ sIss = OString( "baseline" );
+ nEsc = 0;
+ nProp = 100;
+ }
+ else if ( DFLT_ESC_PROP == nProp )
+ {
+ if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
+ sIss = OString( "subscript" );
+ else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
+ sIss = OString( "superscript" );
+ }
+
+ if ( sIss.getLength( ) > 0 )
+ m_pSerializer->singleElementNS( XML_w, XML_vertAlign,
+ FSNS( XML_w, XML_val ), sIss.getStr(), FSEND );
+
+ if ( sIss.getLength() == 0 || sIss.match( OString( "baseline" ) ) )
+ {
+ long nHeight = ((SvxFontHeightItem&)m_rExport.GetItem(
+ RES_CHRATR_FONTSIZE )).GetHeight();
+ OString sPos = OString::valueOf( ( nHeight * nEsc + 500 ) / 1000 );
+ m_pSerializer->singleElementNS( XML_w, XML_position,
+ FSNS( XML_w, XML_val ), sPos.getStr( ), FSEND );
+
+ if( 100 != nProp || sIss.match( OString( "baseline" ) ) )
+ {
+ OString sSize = OString::valueOf( ( nHeight * nProp + 500 ) / 1000 );
+ m_pSerializer->singleElementNS( XML_w, XML_sz,
+ FSNS( XML_w, XML_val ), sSize.getStr( ), FSEND );
+ }
+ }
+}
+
+void DocxAttributeOutput::CharFont( const SvxFontItem& rFont)
+{
+ if (!m_pFontsAttrList)
+ m_pFontsAttrList = m_pSerializer->createAttrList();
+ OUString sFontName(rFont.GetFamilyName());
+ OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_ascii), sFontNameUtf8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_hAnsi), sFontNameUtf8);
+}
+
+void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
+{
+ OString fontSize = OString::valueOf( sal_Int32( ( rFontSize.GetHeight() + 5 ) / 10 ) );
+
+ switch ( rFontSize.Which() )
+ {
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_CJK_FONTSIZE:
+ m_pSerializer->singleElementNS( XML_w, XML_sz, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ m_pSerializer->singleElementNS( XML_w, XML_szCs, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
+{
+ OString aKerning = OString::valueOf( ( sal_Int32 ) rKerning.GetValue() );
+ m_pSerializer->singleElementNS( XML_w, XML_spacing, FSNS(XML_w, XML_val), aKerning.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
+{
+ if (!m_pCharLangAttrList)
+ m_pCharLangAttrList = m_pSerializer->createAttrList();
+
+ ::com::sun::star::lang::Locale xLocale= MsLangId::convertLanguageToLocale( rLanguage.GetLanguage( ) );
+ OString sLanguage = OUStringToOString(xLocale.Language, RTL_TEXTENCODING_UTF8);
+ OString sCountry = OUStringToOString(xLocale.Country, RTL_TEXTENCODING_UTF8);
+
+ OString aLanguageCode = sLanguage + "-" + sCountry;
+
+ switch ( rLanguage.Which() )
+ {
+ case RES_CHRATR_LANGUAGE:
+ m_pCharLangAttrList->add(FSNS(XML_w, XML_val), aLanguageCode);
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ m_pCharLangAttrList->add(FSNS(XML_w, XML_eastAsia), aLanguageCode);
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ m_pCharLangAttrList->add(FSNS(XML_w, XML_bidi), aLanguageCode);
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
+{
+ if ( rPosture.GetPosture() != ITALIC_NONE )
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
+{
+ if ( rShadow.GetValue() )
+ m_pSerializer->singleElementNS( XML_w, XML_shadow, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_shadow, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
+{
+ const char *pUnderline;
+
+ switch ( rUnderline.GetLineStyle() )
+ {
+ case UNDERLINE_SINGLE: pUnderline = "single"; break;
+ case UNDERLINE_BOLD: pUnderline = "thick"; break;
+ case UNDERLINE_DOUBLE: pUnderline = "double"; break;
+ case UNDERLINE_DOTTED: pUnderline = "dotted"; break;
+ case UNDERLINE_DASH: pUnderline = "dash"; break;
+ case UNDERLINE_DASHDOT: pUnderline = "dotDash"; break;
+ case UNDERLINE_DASHDOTDOT: pUnderline = "dotDotDash"; break;
+ case UNDERLINE_WAVE: pUnderline = "wave"; break;
+ case UNDERLINE_BOLDDOTTED: pUnderline = "dottedHeavy"; break;
+ case UNDERLINE_BOLDDASH: pUnderline = "dashedHeavy"; break;
+ case UNDERLINE_LONGDASH: pUnderline = "dashLongHeavy"; break;
+ case UNDERLINE_BOLDLONGDASH: pUnderline = "dashLongHeavy"; break;
+ case UNDERLINE_BOLDDASHDOT: pUnderline = "dashDotHeavy"; break;
+ case UNDERLINE_BOLDDASHDOTDOT: pUnderline = "dashDotDotHeavy"; break;
+ case UNDERLINE_BOLDWAVE: pUnderline = "wavyHeavy"; break;
+ case UNDERLINE_DOUBLEWAVE: pUnderline = "wavyDouble"; break;
+ case UNDERLINE_NONE: // fall through
+ default: pUnderline = "none"; break;
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_u, FSNS( XML_w, XML_val ), pUnderline, FSEND );
+}
+
+void DocxAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
+{
+ if ( rWeight.GetWeight() == WEIGHT_BOLD )
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem& )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()\n" );
+}
+
+void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
+{
+ if ( rBlink.GetValue() )
+ m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "blinkBackground", FSEND );
+ else
+ m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "none", FSEND );
+}
+
+void DocxAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_shd,
+ FSNS( XML_w, XML_fill ), impl_ConvertColor( rBrush.GetColor() ).getStr(),
+ FSNS( XML_w, XML_val ), "clear",
+ FSEND );
+}
+
+void DocxAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
+{
+ if (!m_pFontsAttrList)
+ m_pFontsAttrList = m_pSerializer->createAttrList();
+ OUString sFontName(rFont.GetFamilyName());
+ OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_eastAsia), sFontNameUtf8);
+}
+
+void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
+{
+ if ( rPosture.GetPosture() != ITALIC_NONE )
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
+{
+ if ( rWeight.GetWeight() == WEIGHT_BOLD )
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
+{
+ if (!m_pFontsAttrList)
+ m_pFontsAttrList = m_pSerializer->createAttrList();
+ OUString sFontName(rFont.GetFamilyName());
+ OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_cs), sFontNameUtf8);
+
+}
+
+void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
+{
+ if ( rPosture.GetPosture() != ITALIC_NONE )
+ m_pSerializer->singleElementNS( XML_w, XML_iCs, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_iCs, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
+{
+ if ( rWeight.GetWeight() == WEIGHT_BOLD )
+ m_pSerializer->singleElementNS( XML_w, XML_bCs, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_bCs, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
+{
+ if ( !rRotate.GetValue() )
+ return;
+
+ if (!m_pEastAsianLayoutAttrList)
+ m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
+ OString sTrue((sal_Char *)"true");
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vert), sTrue);
+
+ if (rRotate.IsFitToLine())
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vertCompress), sTrue);
+}
+
+void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
+{
+ const char *pEmphasis;
+
+ switch ( rEmphasisMark.GetValue() )
+ {
+ case EMPHASISMARK_NONE: pEmphasis = "none"; break;
+ case EMPHASISMARK_SIDE_DOTS: pEmphasis = "dot"; break;
+ case EMPHASISMARK_CIRCLE_ABOVE: pEmphasis = "circle"; break;
+ case EMPHASISMARK_DOTS_BELOW: pEmphasis = "underDot"; break;
+ default: pEmphasis = "comma"; break;
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_em, FSNS( XML_w, XML_val ), pEmphasis, FSEND );
+}
+
+void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
+{
+ if ( !rTwoLines.GetValue() )
+ return;
+
+ if (!m_pEastAsianLayoutAttrList)
+ m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
+ OString sTrue((sal_Char *)"true");
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combine), sTrue);
+
+ sal_Unicode cStart = rTwoLines.GetStartBracket();
+ sal_Unicode cEnd = rTwoLines.GetEndBracket();
+
+ if (!cStart && !cEnd)
+ return;
+
+ OString sBracket;
+ if ((cStart == '{') || (cEnd == '}'))
+ sBracket = (sal_Char *)"curly";
+ else if ((cStart == '<') || (cEnd == '>'))
+ sBracket = (sal_Char *)"angle";
+ else if ((cStart == '[') || (cEnd == ']'))
+ sBracket = (sal_Char *)"square";
+ else
+ sBracket = (sal_Char *)"round";
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combineBrackets), sBracket);
+}
+
+void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_w,
+ FSNS( XML_w, XML_val ), rtl::OString::valueOf( sal_Int32( rScaleWidth.GetValue() ) ).getStr(), FSEND );
+}
+
+void DocxAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
+{
+ switch ( rRelief.GetValue() )
+ {
+ case RELIEF_EMBOSSED:
+ m_pSerializer->singleElementNS( XML_w, XML_emboss, FSEND );
+ break;
+ case RELIEF_ENGRAVED:
+ m_pSerializer->singleElementNS( XML_w, XML_imprint, FSEND );
+ break;
+ default:
+ m_pSerializer->singleElementNS( XML_w, XML_emboss, FSNS( XML_w, XML_val ), "false", FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_imprint, FSNS( XML_w, XML_val ), "false", FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
+{
+ if ( rHidden.GetValue() )
+ m_pSerializer->singleElementNS( XML_w, XML_vanish, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_vanish, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::TextINetFormat( const SwFmtINetFmt& rLink )
+{
+ const SwTxtINetFmt* pINetFmt = rLink.GetTxtINetFmt();
+ const SwCharFmt* pCharFmt = pINetFmt->GetCharFmt();
+
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
+{
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *rCharFmt.GetCharFmt() ) ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::RefField( const SwField& rFld, const String& rRef )
+{
+ sal_uInt16 nType = rFld.GetTyp( )->Which( );
+ if ( nType == RES_GETEXPFLD )
+ {
+ String sCmd = FieldString( ww::eREF );
+ sCmd.APPEND_CONST_ASC( "\"" );
+ sCmd += rRef;
+ sCmd.APPEND_CONST_ASC( "\" " );
+
+ m_rExport.OutputField( &rFld, ww::eREF, sCmd );
+ }
+
+ // There is nothing to do here for the set fields
+}
+
+void DocxAttributeOutput::HiddenField( const SwField& /*rFld*/ )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()\n" );
+}
+
+void DocxAttributeOutput::PostitField( const SwField* /* pFld*/ )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::PostitField()\n" );
+}
+
+bool DocxAttributeOutput::DropdownField( const SwField* pFld )
+{
+ bool bExpand = false;
+
+ ww::eField eType = ww::eFORMDROPDOWN;
+ String sCmd = FieldString( eType );
+ GetExport( ).OutputField( pFld, eType, sCmd );
+
+ return bExpand;
+}
+
+void DocxAttributeOutput::SetField( const SwField& rFld, ww::eField eType, const String& rCmd )
+{
+ // field bookmarks are handled in the EndRun method
+ GetExport().OutputField(&rFld, eType, rCmd );
+}
+
+void DocxAttributeOutput::WriteExpand( const SwField* pFld )
+{
+ // Will be written in the next End Run
+ String sCmd;
+ m_rExport.OutputField( pFld, ww::eUNKNOWN, sCmd );
+}
+
+void DocxAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode )
+{
+ struct FieldInfos infos;
+ infos.pField = pFld;
+ infos.sCmd = rFldCmd;
+ infos.eType = eType;
+ infos.bClose = WRITEFIELD_CLOSE & nMode;
+ infos.bOpen = WRITEFIELD_START & nMode;
+ m_Fields.push_back( infos );
+
+ if ( pFld )
+ {
+ sal_uInt16 nType = pFld->GetTyp( )->Which( );
+ sal_uInt16 nSubType = pFld->GetSubType();
+
+ // TODO Any other field types here ?
+ if ( ( nType == RES_SETEXPFLD ) && ( nSubType & nsSwGetSetExpType::GSE_STRING ) )
+ {
+ const SwSetExpField *pSet = ( const SwSetExpField* )( pFld );
+ m_sFieldBkm = pSet->GetPar1( );
+ }
+ else if ( nType == RES_DROPDOWN )
+ {
+ const SwDropDownField* pDropDown = ( const SwDropDownField* )( pFld );
+ m_sFieldBkm = pDropDown->GetName( );
+ }
+ }
+}
+
+void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark )
+{
+ if ( !m_Fields.empty() )
+ m_Fields.begin()->pFieldmark = &rFieldmark;
+}
+
+void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
+ std::vector< OUString >& rEnds )
+{
+ for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it < end; ++it )
+ {
+ OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
+ m_rMarksStart.push_back( rName );
+ }
+ rStarts.clear();
+
+ for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it < end; ++it )
+ {
+ OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
+ m_rMarksEnd.push_back( rName );
+ }
+ rEnds.clear();
+}
+
+void DocxAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
+{
+ const SwEndNoteInfo& rInfo = rFootnote.IsEndNote()?
+ m_rExport.pDoc->GetEndNoteInfo(): m_rExport.pDoc->GetFtnInfo();
+
+ // footnote/endnote run properties
+ const SwCharFmt* pCharFmt = rInfo.GetAnchorCharFmt( *m_rExport.pDoc );
+
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+
+ // remember the footnote/endnote to
+ // 1) write the footnoteReference/endnoteReference in EndRunProperties()
+ // 2) be able to dump them all to footnotes.xml/endnotes.xml
+ if ( !rFootnote.IsEndNote() )
+ m_pFootnotesList->add( rFootnote );
+ else
+ m_pEndnotesList->add( rFootnote );
+}
+
+void DocxAttributeOutput::FootnoteEndnoteReference()
+{
+ sal_Int32 nId;
+ const SwFmtFtn *pFootnote = m_pFootnotesList->getCurrent( nId );
+
+ // both cannot be set at the same time - if they are, it's a bug
+ if ( !pFootnote )
+ pFootnote = m_pEndnotesList->getCurrent( nId );
+
+ if ( !pFootnote )
+ return;
+
+ sal_Int32 nToken = pFootnote->IsEndNote()? XML_endnoteReference: XML_footnoteReference;
+
+ // write it
+ if ( pFootnote->GetNumStr().Len() == 0 )
+ {
+ // autonumbered
+ m_pSerializer->singleElementNS( XML_w, nToken,
+ FSNS( XML_w, XML_id ), ::rtl::OString::valueOf( nId ).getStr(),
+ FSEND );
+ }
+ else
+ {
+ // not autonumbered
+ m_pSerializer->singleElementNS( XML_w, nToken,
+ FSNS( XML_w, XML_customMarkFollows ), "1",
+ FSNS( XML_w, XML_id ), ::rtl::OString::valueOf( nId ).getStr(),
+ FSEND );
+
+ RunText( pFootnote->GetNumStr() );
+ }
+}
+
+void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes )
+{
+ const FootnotesVector& rVector = bFootnotes? m_pFootnotesList->getVector(): m_pEndnotesList->getVector();
+
+ sal_Int32 nBody = bFootnotes? XML_footnotes: XML_endnotes;
+ sal_Int32 nItem = bFootnotes? XML_footnote: XML_endnote;
+
+ m_pSerializer->startElementNS( XML_w, nBody,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+
+ sal_Int32 nIndex = 0;
+
+ // separator
+ m_pSerializer->startElementNS( XML_w, nItem,
+ FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
+ FSNS( XML_w, XML_type ), "separator",
+ FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_separator, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ m_pSerializer->endElementNS( XML_w, XML_p );
+ m_pSerializer->endElementNS( XML_w, nItem );
+
+ // separator
+ m_pSerializer->startElementNS( XML_w, nItem,
+ FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
+ FSNS( XML_w, XML_type ), "continuationSeparator",
+ FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_continuationSeparator, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ m_pSerializer->endElementNS( XML_w, XML_p );
+ m_pSerializer->endElementNS( XML_w, nItem );
+
+ // footnotes/endnotes themselves
+ for ( FootnotesVector::const_iterator i = rVector.begin(); i != rVector.end(); ++i, ++nIndex )
+ {
+ m_pSerializer->startElementNS( XML_w, nItem,
+ FSNS( XML_w, XML_id ), OString::valueOf( nIndex ).getStr(),
+ FSEND );
+
+ const SwNodeIndex* pIndex = (*i)->GetTxtFtn()->GetStartNode();
+ // tag required at the start of each footnote/endnote
+ m_footnoteEndnoteRefTag = bFootnotes ? XML_footnoteRef : XML_endnoteRef;
+
+ m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
+ pIndex->GetNode().EndOfSectionIndex(),
+ bFootnotes? TXT_FTN: TXT_EDN );
+
+ m_pSerializer->endElementNS( XML_w, nItem );
+ }
+
+ m_pSerializer->endElementNS( XML_w, nBody );
+
+}
+
+void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
+{
+ if ( !m_pParagraphSpacingAttrList )
+ m_pParagraphSpacingAttrList = m_pSerializer->createAttrList();
+
+ if ( nSpace < 0 )
+ {
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "exact" );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( -nSpace ) ) );
+ }
+ else if( nMulti )
+ {
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
+ }
+ else if ( nSpace > 0 )
+ {
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "atLeast" );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
+ }
+ else
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
+}
+
+void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
+{
+ const char *pAdjustString;
+
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ const SfxItemSet* pItems = GetExport().GetCurItemSet();
+ const SvxFrameDirectionItem* rFrameDir = static_cast< const SvxFrameDirectionItem* >( pItems->GetItem( RES_FRAMEDIR ) );
+
+ bool bRtl = false;
+ short nDir = rFrameDir->GetValue();
+ bRtl = ( nDir == FRMDIR_HORI_RIGHT_TOP );
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ nDir = GetExport( ).GetDefaultFrameDirection( );
+
+ switch ( rAdjust.GetAdjust() )
+ {
+ case SVX_ADJUST_LEFT:
+ if ( bEcma )
+ pAdjustString = "left";
+ else if ( bRtl )
+ pAdjustString = "end";
+ else
+ pAdjustString = "start";
+ break;
+ case SVX_ADJUST_RIGHT:
+ if ( bEcma )
+ pAdjustString = "right";
+ else if ( bRtl )
+ pAdjustString = "start";
+ else
+ pAdjustString = "end";
+ break;
+ case SVX_ADJUST_BLOCKLINE:
+ case SVX_ADJUST_BLOCK:
+ pAdjustString = "both";
+ break;
+ case SVX_ADJUST_CENTER:
+ pAdjustString = "center";
+ break;
+ default:
+ return; // not supported attribute
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_jc, FSNS( XML_w, XML_val ), pAdjustString, FSEND );
+}
+
+void DocxAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
+{
+ if (rSplit.GetValue())
+ m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSNS( XML_w, XML_val ), "false", FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSEND );
+}
+
+void DocxAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
+{
+ if (rWidows.GetValue())
+ m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+static void impl_WriteTabElement( FSHelperPtr pSerializer,
+ const SvxTabStop& rTab, long nCurrentLeft )
+{
+ FastAttributeList *pTabElementAttrList = pSerializer->createAttrList();
+
+ switch (rTab.GetAdjustment())
+ {
+ case SVX_TAB_ADJUST_RIGHT:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"right") );
+ break;
+ case SVX_TAB_ADJUST_DECIMAL:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"decimal") );
+ break;
+ case SVX_TAB_ADJUST_CENTER:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"center") );
+ break;
+ case SVX_TAB_ADJUST_DEFAULT:
+ case SVX_TAB_ADJUST_LEFT:
+ default:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"left") );
+ break;
+ }
+
+ pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
+
+ sal_Unicode cFillChar = rTab.GetFill();
+
+ if (sal_Unicode('.') == cFillChar )
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "dot" ) );
+ else if ( sal_Unicode('-') == cFillChar )
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "hyphen" ) );
+ else if ( sal_Unicode(0xB7) == cFillChar ) // middle dot
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "middleDot" ) );
+ else if ( sal_Unicode('_') == cFillChar )
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "underscore" ) );
+ else
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "none" ) );
+
+ pSerializer->singleElementNS( XML_w, XML_tab, pTabElementAttrList );
+}
+
+void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
+{
+ const SfxPoolItem* pLR = m_rExport.HasItem( RES_LR_SPACE );
+ long nCurrentLeft = pLR ? ((const SvxLRSpaceItem*)pLR)->GetTxtLeft() : 0;
+
+ m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
+
+ sal_uInt16 nCount = rTabStop.Count();
+ for (sal_uInt16 i = 0; i < nCount; i++ )
+ impl_WriteTabElement( m_pSerializer, rTabStop[i], nCurrentLeft );
+
+ m_pSerializer->endElementNS( XML_w, XML_tabs );
+}
+
+void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_suppressAutoHyphens,
+ FSNS( XML_w, XML_val ), rHyphenZone.IsHyphen( ) ? "false" : "true" ,
+ FSEND );
+}
+
+void DocxAttributeOutput::ParaNumRule_Impl( const SwTxtNode* /*pTxtNd*/, sal_Int32 nLvl, sal_Int32 nNumId )
+{
+ if ( USHRT_MAX != nNumId && 0 != nNumId )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_numPr, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_ilvl, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl )).getStr(), FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_numId, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nNumId )).getStr(), FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_numPr );
+ }
+}
+
+void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
+{
+ sal_uInt16 nXmlElement = 0;
+
+ switch ( rScriptSpace.Which( ) )
+ {
+ case RES_PARATR_SCRIPTSPACE:
+ nXmlElement = XML_autoSpaceDE;
+ break;
+ case RES_PARATR_HANGINGPUNCTUATION:
+ nXmlElement = XML_overflowPunct;
+ break;
+ case RES_PARATR_FORBIDDEN_RULES:
+ nXmlElement = XML_kinsoku;
+ break;
+ }
+
+ if ( nXmlElement )
+ {
+ m_pSerializer->singleElementNS( XML_w, nXmlElement,
+ FSNS( XML_w, XML_val ), rScriptSpace.GetValue( ) ? "true": "false",
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
+{
+ const char *pAlignString;
+
+ switch ( rAlign.GetValue() )
+ {
+ case SvxParaVertAlignItem::BASELINE:
+ pAlignString = "baseline";
+ break;
+ case SvxParaVertAlignItem::TOP:
+ pAlignString = "top";
+ break;
+ case SvxParaVertAlignItem::CENTER:
+ pAlignString = "center";
+ break;
+ case SvxParaVertAlignItem::BOTTOM:
+ pAlignString = "bottom";
+ break;
+ case SvxParaVertAlignItem::AUTOMATIC:
+ pAlignString = "auto";
+ break;
+ default:
+ return; // not supported attribute
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_textAlignment, FSNS( XML_w, XML_val ), pAlignString, FSEND );
+}
+
+void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_snapToGrid,
+ FSNS( XML_w, XML_val ), rGrid.GetValue( ) ? "true": "false",
+ FSEND );
+}
+
+void DocxAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList( );
+
+ if ( rSize.GetWidth() && rSize.GetWidthSizeType() == ATT_FIX_SIZE )
+ {
+ m_pFlyAttrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
+ }
+
+ if ( rSize.GetHeight() )
+ {
+ OString sRule( "exact" );
+ if ( rSize.GetHeightSizeType() == ATT_MIN_SIZE )
+ sRule = OString( "atLeast" );
+ m_pFlyAttrList->add( FSNS( XML_w, XML_hRule ), sRule );
+ m_pFlyAttrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
+ }
+ }
+ else if ( m_rExport.bOutPageDescs )
+ {
+ FastAttributeList *attrList = m_pSerializer->createAttrList( );
+ if ( m_rExport.pAktPageDesc->GetLandscape( ) )
+ attrList->add( FSNS( XML_w, XML_orient ), "landscape" );
+
+ attrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
+ attrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
+
+ XFastAttributeListRef xAttrList( attrList );
+ attrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_pgSz, xAttrList );
+ }
+}
+
+void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()\n" );
+}
+
+void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
+{
+ bool bEcma = m_rExport.GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_hSpace ),
+ OString::valueOf(
+ sal_Int32( ( rLRSpace.GetLeft() + rLRSpace.GetRight() ) / 2 ) ) );
+ }
+ else if ( m_rExport.bOutPageDescs )
+ {
+ if ( !m_pSectionSpacingAttrList )
+ m_pSectionSpacingAttrList = m_pSerializer->createAttrList();
+
+ sal_uInt16 nLDist, nRDist;
+ const SfxPoolItem* pItem = m_rExport.HasItem( RES_BOX );
+ if ( pItem )
+ {
+ nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
+ nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
+ }
+ else
+ nLDist = nRDist = 0;
+ nLDist = nLDist + (sal_uInt16)rLRSpace.GetLeft();
+ nRDist = nRDist + (sal_uInt16)rLRSpace.GetRight();
+
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_left ), OString::valueOf( sal_Int32( nLDist ) ) );
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_right ), OString::valueOf( sal_Int32( nRDist ) ) );
+ }
+ else
+ {
+ FastAttributeList *pLRSpaceAttrList = m_pSerializer->createAttrList();
+
+ pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_left : XML_start ) ), OString::valueOf( (sal_Int32) rLRSpace.GetTxtLeft() ) );
+ pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_right : XML_end ) ), OString::valueOf( (sal_Int32) rLRSpace.GetRight() ) );
+
+ sal_Int32 nFirstLineAdjustment = rLRSpace.GetTxtFirstLineOfst();
+ if (nFirstLineAdjustment > 0)
+ pLRSpaceAttrList->add( FSNS( XML_w, XML_firstLine ), OString::valueOf( nFirstLineAdjustment ) );
+ else
+ pLRSpaceAttrList->add( FSNS( XML_w, XML_hanging ), OString::valueOf( - nFirstLineAdjustment ) );
+ m_pSerializer->singleElementNS( XML_w, XML_ind, pLRSpaceAttrList );
+ }
+}
+
+void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
+{
+
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_vSpace ),
+ OString::valueOf(
+ sal_Int32( ( rULSpace.GetLower() + rULSpace.GetUpper() ) / 2 ) ) );
+ }
+ else if (m_rExport.bOutPageDescs )
+ {
+ OSL_ENSURE( m_rExport.GetCurItemSet(), "Impossible" );
+ if ( !m_rExport.GetCurItemSet() )
+ return;
+
+ if ( !m_pSectionSpacingAttrList )
+ m_pSectionSpacingAttrList = m_pSerializer->createAttrList();
+
+ HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
+
+ sal_Int32 nHeader = 0;
+ if ( aDistances.HasHeader() )
+ nHeader = sal_Int32( aDistances.dyaHdrTop );
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_header ), OString::valueOf( nHeader ) );
+
+ // Page top
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_top ),
+ OString::valueOf( sal_Int32( aDistances.dyaTop ) ) );
+
+ sal_Int32 nFooter = 0;
+ if ( aDistances.HasFooter() )
+ nFooter = sal_Int32( aDistances.dyaHdrBottom );
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_footer ), OString::valueOf( nFooter ) );
+
+ // Page Bottom
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_bottom ),
+ OString::valueOf( sal_Int32( aDistances.dyaBottom ) ) );
+
+ // FIXME Page Gutter is not handled ATM, setting to 0 as it's mandatory for OOXML
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_gutter ),
+ OString::valueOf( sal_Int32( 0 ) ) );
+
+ }
+ else
+ {
+ if ( !m_pParagraphSpacingAttrList )
+ m_pParagraphSpacingAttrList = m_pSerializer->createAttrList();
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_before ),
+ OString::valueOf( (sal_Int32)rULSpace.GetUpper() ) );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_after ),
+ OString::valueOf( (sal_Int32)rULSpace.GetLower() ) );
+ }
+}
+
+void DocxAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ OString sWrap( "auto" );
+ switch ( rSurround.GetSurround( ) )
+ {
+ case SURROUND_NONE:
+ sWrap = OString( "none" );
+ break;
+ case SURROUND_THROUGHT:
+ sWrap = OString( "through" );
+ break;
+ case SURROUND_IDEAL:
+ case SURROUND_PARALLEL:
+ case SURROUND_LEFT:
+ case SURROUND_RIGHT:
+ default:
+ sWrap = OString( "around" );
+ }
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_wrap ), sWrap );
+ }
+}
+
+void DocxAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ OString sAlign;
+ switch( rFlyVert.GetVertOrient() )
+ {
+ case text::VertOrientation::NONE:
+ break;
+ case text::VertOrientation::CENTER:
+ case text::VertOrientation::LINE_CENTER:
+ sAlign = OString( "center" );
+ break;
+ case text::VertOrientation::BOTTOM:
+ case text::VertOrientation::LINE_BOTTOM:
+ sAlign = OString( "bottom" );
+ break;
+ case text::VertOrientation::TOP:
+ case text::VertOrientation::LINE_TOP:
+ default:
+ sAlign = OString( "top" );
+ break;
+ }
+
+ if ( sAlign.getLength() > 0 )
+ m_pFlyAttrList->add( FSNS( XML_w, XML_yAlign ), sAlign );
+ else
+ m_pFlyAttrList->add( FSNS( XML_w, XML_y ),
+ OString::valueOf( sal_Int32( rFlyVert.GetPos() ) ) );
+
+ OString sVAnchor( "page" );
+ switch ( rFlyVert.GetRelationOrient( ) )
+ {
+ case text::RelOrientation::CHAR:
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::TEXT_LINE:
+ sVAnchor = OString( "column" );
+ break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ sVAnchor = OString( "margin" );
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ default:
+ break;
+ }
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_vAnchor ), sVAnchor );
+ }
+}
+
+void DocxAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ OString sAlign;
+ switch( rFlyHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ break;
+ case text::HoriOrientation::LEFT:
+ sAlign = OString( rFlyHori.IsPosToggle( ) ? "inside" : "left" );
+ break;
+ case text::HoriOrientation::RIGHT:
+ sAlign = OString( rFlyHori.IsPosToggle( ) ? "outside" : "right" );
+ break;
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::FULL: // FULL only for tables
+ default:
+ sAlign = OString( "center" );
+ break;
+ }
+
+ if ( sAlign.getLength() > 0 )
+ m_pFlyAttrList->add( FSNS( XML_w, XML_xAlign ), sAlign );
+ else
+ m_pFlyAttrList->add( FSNS( XML_w, XML_x ),
+ OString::valueOf( sal_Int32( rFlyHori.GetPos() ) ) );
+
+ OString sHAnchor( "page" );
+ switch ( rFlyHori.GetRelationOrient( ) )
+ {
+ case text::RelOrientation::CHAR:
+ case text::RelOrientation::PRINT_AREA:
+ sHAnchor = OString( "text" );
+ break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ sHAnchor = OString( "margin" );
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ default:
+ break;
+ }
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_hAnchor ), sHAnchor );
+ }
+}
+
+void DocxAttributeOutput::FormatAnchor( const SwFmtAnchor& )
+{
+ // Fly frames: anchors here aren't matching the anchors in docx
+}
+
+void DocxAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
+{
+ if ( !m_rExport.bOutPageDescs )
+ {
+ OString sColor = impl_ConvertColor( rBrush.GetColor( ) );
+ m_pSerializer->singleElementNS( XML_w, XML_shd,
+ FSNS( XML_w, XML_fill ), sColor.getStr( ),
+ FSNS( XML_w, XML_val ), "clear",
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
+{
+
+ if ( !m_bOpenedSectPr )
+ {
+ // Normally open the borders tag for paragraphs
+ m_pSerializer->startElementNS( XML_w, XML_pBdr, FSEND );
+ }
+
+ impl_pageBorders( m_pSerializer, rBox );
+
+ if ( m_bOpenedSectPr )
+ {
+ // Special handling for pgBorder
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
+ m_pSerializer->mergeTopMarks( );
+ }
+ else
+ {
+ // Normally close the borders tag for paragraphs
+ m_pSerializer->endElementNS( XML_w, XML_pBdr );
+ }
+}
+
+void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
+{
+ // Get the columns attributes
+ FastAttributeList *pColsAttrList = m_pSerializer->createAttrList();
+
+ pColsAttrList->add( FSNS( XML_w, XML_num ),
+ OString::valueOf( sal_Int32( nCols ) ). getStr( ) );
+
+ const char* pEquals = "false";
+ if ( bEven )
+ {
+ sal_uInt16 nWidth = rCol.GetGutterWidth( true );
+ pColsAttrList->add( FSNS( XML_w, XML_space ),
+ OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
+
+ pEquals = "true";
+ }
+
+ pColsAttrList->add( FSNS( XML_w, XML_equalWidth ), pEquals );
+
+ bool bHasSep = COLADJ_NONE == rCol.GetLineAdj( );
+ pColsAttrList->add( FSNS( XML_w, XML_sep ), bHasSep ? "true" : "false" );
+
+ // Write the element
+ m_pSerializer->startElementNS( XML_w, XML_cols, pColsAttrList );
+
+ // Write the columns width if non-equals
+ const SwColumns & rColumns = rCol.GetColumns( );
+ if ( !bEven )
+ {
+ for ( sal_uInt16 n = 0; n < nCols; ++n )
+ {
+ FastAttributeList *pColAttrList = m_pSerializer->createAttrList();
+ sal_uInt16 nWidth = rCol.CalcPrtColWidth( n, ( sal_uInt16 ) nPageSize );
+ pColAttrList->add( FSNS( XML_w, XML_w ),
+ OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
+
+ if ( n + 1 != nCols )
+ {
+ sal_uInt16 nSpacing = rColumns[n]->GetRight( ) + rColumns[n + 1]->GetLeft( );
+ pColAttrList->add( FSNS( XML_w, XML_space ),
+ OString::valueOf( sal_Int32( nSpacing ) ).getStr( ) );
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_col, pColAttrList );
+ }
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_cols );
+}
+
+void DocxAttributeOutput::FormatKeep( const SvxFmtKeepItem& )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_keepNext, FSEND );
+}
+
+void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid )
+{
+ FastAttributeList *pGridAttrList = m_pSerializer->createAttrList();
+
+ OString sGridType;
+ switch ( rGrid.GetGridType( ) )
+ {
+ default:
+ case GRID_NONE:
+ sGridType = OString( "default" );
+ break;
+ case GRID_LINES_ONLY:
+ sGridType = OString( "lines" );
+ break;
+ case GRID_LINES_CHARS:
+ if ( rGrid.IsSnapToChars( ) )
+ sGridType = OString( "snapToChars" );
+ else
+ sGridType = OString( "linesAndChars" );
+ break;
+ }
+ pGridAttrList->add( FSNS( XML_w, XML_type ), sGridType.getStr( ) );
+
+ sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
+ pGridAttrList->add( FSNS( XML_w, XML_linePitch ),
+ OString::valueOf( sal_Int32( nHeight ) ).getStr( ) );
+
+ MSWordStyles * pStyles = m_rExport.pStyles;
+ SwFmt * pSwFmt = pStyles->GetSwFmt();
+
+ sal_uInt32 nPageCharSize = 0;
+
+ if (pSwFmt != NULL)
+ {
+ nPageCharSize = ItemGet<SvxFontHeightItem>
+ (*pSwFmt, RES_CHRATR_FONTSIZE).GetHeight();
+ }
+
+ sal_uInt16 nPitch = rGrid.IsSquaredMode() ? rGrid.GetBaseHeight() :
+ rGrid.GetBaseWidth( );
+ sal_Int32 nCharSpace = ( nPitch - nPageCharSize ) * 4096 / 20;
+
+ pGridAttrList->add( FSNS( XML_w, XML_charSpace ),
+ OString::valueOf( sal_Int32( nCharSpace ) ).getStr( ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_docGrid, pGridAttrList );
+}
+
+void DocxAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
+{
+ if ( !rNumbering.IsCount( ) )
+ m_pSerializer->singleElementNS( XML_w, XML_suppressLineNumbers, FSEND );
+}
+
+void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
+{
+ OString sTextFlow;
+ bool bBiDi = false;
+ short nDir = rDirection.GetValue();
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ nDir = GetExport( ).GetDefaultFrameDirection( );
+
+ switch ( nDir )
+ {
+ default:
+ case FRMDIR_HORI_LEFT_TOP:
+ sTextFlow = OString( "lrTb" );
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ sTextFlow = OString( "lrTb" );
+ bBiDi = true;
+ break;
+ case FRMDIR_VERT_TOP_LEFT: // many things but not this one
+ case FRMDIR_VERT_TOP_RIGHT:
+ sTextFlow = OString( "tbRl" );
+ break;
+ }
+
+ if ( m_rExport.bOutPageDescs )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_textDirection,
+ FSNS( XML_w, XML_val ), sTextFlow.getStr( ),
+ FSEND );
+ if ( bBiDi )
+ m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
+ }
+ else if ( !m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( bBiDi )
+ m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
+ }
+}
+
+DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML )
+ : m_rExport( rExport ),
+ m_pSerializer( pSerializer ),
+ m_rDrawingML( *pDrawingML ),
+ m_pFontsAttrList( NULL ),
+ m_pEastAsianLayoutAttrList( NULL ),
+ m_pCharLangAttrList( NULL ),
+ m_pSectionSpacingAttrList( NULL ),
+ m_pParagraphSpacingAttrList( NULL ),
+ m_pHyperlinkAttrList( NULL ),
+ m_pFlyAttrList( NULL ),
+ m_pFootnotesList( new ::docx::FootnotesList() ),
+ m_pEndnotesList( new ::docx::FootnotesList() ),
+ m_footnoteEndnoteRefTag( 0 ),
+ m_pSectionInfo( NULL ),
+ m_pRedlineData( NULL ),
+ m_nRedlineId( 0 ),
+ m_bOpenedSectPr( false ),
+ m_sFieldBkm( ),
+ m_nNextMarkId( 0 ),
+ m_pTableWrt( NULL ),
+ m_bTableCellOpen( false ),
+ m_nTableDepth( 0 ),
+ m_bParagraphOpened( false ),
+ m_nColBreakStatus( COLBRK_NONE ),
+ m_pParentFrame( NULL )
+{
+}
+
+DocxAttributeOutput::~DocxAttributeOutput()
+{
+ delete m_pFontsAttrList, m_pFontsAttrList = NULL;
+ delete m_pEastAsianLayoutAttrList, m_pEastAsianLayoutAttrList = NULL;
+ delete m_pCharLangAttrList, m_pCharLangAttrList = NULL;
+ delete m_pSectionSpacingAttrList, m_pSectionSpacingAttrList = NULL;
+ delete m_pParagraphSpacingAttrList, m_pParagraphSpacingAttrList = NULL;
+ delete m_pHyperlinkAttrList, m_pHyperlinkAttrList = NULL;
+ delete m_pFlyAttrList, m_pFlyAttrList = NULL;
+
+ delete m_pFootnotesList, m_pFootnotesList = NULL;
+ delete m_pEndnotesList, m_pEndnotesList = NULL;
+
+ delete m_pTableWrt, m_pTableWrt = NULL;
+ m_pParentFrame = NULL;
+}
+
+DocxExport& DocxAttributeOutput::GetExport()
+{
+ return m_rExport;
+}
+
+bool DocxAttributeOutput::HasFootnotes()
+{
+ return !m_pFootnotesList->isEmpty();
+}
+
+bool DocxAttributeOutput::HasEndnotes()
+{
+ return !m_pEndnotesList->isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */