blob: e5d98a8ba5364ce4cd6fe7baa8549b75ad5b1d63 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "rtfexport.hxx"
#include "rtfexportfilter.hxx"
#include "rtfsdrexport.hxx"
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/i18n/ScriptType.hdl>
#include <com/sun/star/frame/XModel.hpp>
#include <map>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <IMark.hxx>
#include <docsh.hxx>
#include <ndtxt.hxx>
#include <wrtww8.hxx>
#include <fltini.hxx>
#include <fmtline.hxx>
#include <fmtpdsc.hxx>
#include <frmfmt.hxx>
#include <section.hxx>
#include <pagedesc.hxx>
#include <swtable.hxx>
#include <fmtfsize.hxx>
#include <frmatr.hxx>
#include <ftninfo.hxx>
#include <fmthdft.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/shaditem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/paperinf.hxx>
#include <editeng/protitem.hxx>
#include <docary.hxx>
#include <numrule.hxx>
#include <charfmt.hxx>
#include <lineinfo.hxx>
#include <swmodule.hxx>
#include "ww8par.hxx"
#include "ww8scan.hxx"
#include <comphelper/string.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/font.hxx>
#include <svtools/rtfkeywd.hxx>
#include <unotools/configmgr.hxx>
using namespace ::comphelper;
using namespace ::com::sun::star;
using rtl::OString;
using rtl::OUString;
using rtl::OStringBuffer;
using rtl::OUStringBuffer;
using sw::mark::IMark;
#if defined(UNX)
const sal_Char RtfExport::sNewLine = '\012';
#else
const sal_Char __FAR_DATA RtfExport::sNewLine[] = "\015\012";
#endif
// the default text encoding for the export, if it doesn't fit unicode will
// be used
#define DEF_ENCODING RTL_TEXTENCODING_ASCII_US
AttributeOutputBase& RtfExport::AttrOutput() const
{
return *m_pAttrOutput;
}
MSWordSections& RtfExport::Sections() const
{
return *m_pSections;
}
RtfSdrExport& RtfExport::SdrExporter() const
{
return *m_pSdrExport;
}
bool RtfExport::HackIsWW8OrHigher() const
{
return true;
}
bool RtfExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
{
// FIXME is this actually true for rtf? - this is copied from DOCX
if ( nScript == i18n::ScriptType::ASIAN )
{
// for asian in ww8, there is only one fontsize
// and one fontstyle (posture/weight)
switch ( nWhich )
{
case RES_CHRATR_FONTSIZE:
case RES_CHRATR_POSTURE:
case RES_CHRATR_WEIGHT:
return false;
default:
break;
}
}
else if ( nScript != i18n::ScriptType::COMPLEX )
{
// for western in ww8, there is only one fontsize
// and one fontstyle (posture/weight)
switch ( nWhich )
{
case RES_CHRATR_CJK_FONTSIZE:
case RES_CHRATR_CJK_POSTURE:
case RES_CHRATR_CJK_WEIGHT:
return false;
default:
break;
}
}
return true;
}
void RtfExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
std::vector< OUString > aStarts;
std::vector< OUString > aEnds;
IMarkVector aMarks;
if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
{
for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
it < end; ++it )
{
IMark* pMark = (*it);
xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
if ( nStart == nAktPos )
aStarts.push_back( pMark->GetName() );
if ( nEnd == nAktPos )
aEnds.push_back( pMark->GetName() );
}
}
m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
}
void RtfExport::AppendBookmark( const OUString& rName, bool /*bSkip*/ )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
std::vector<OUString> aStarts;
std::vector<OUString> aEnds;
aStarts.push_back(rName);
aEnds.push_back(rName);
m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
}
//For i120928,to export graphic of bullet for RTF filter
void RtfExport::ExportGrfBullet(const SwTxtNode& /* rNd */)
{
//This is for RTF filter on the graphic bullets
}
void RtfExport::WriteChar( sal_Unicode )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
/* WriteChar() has nothing to do for rtf. */
}
static bool IsExportNumRule( const SwNumRule& rRule, sal_uInt8* pEnd = 0 )
{
sal_uInt8 nEnd = MAXLEVEL;
while( nEnd-- && !rRule.GetNumFmt( nEnd ))
;
++nEnd;
const SwNumFmt* pNFmt;
sal_uInt8 nLvl;
for( nLvl = 0; nLvl < nEnd; ++nLvl )
if( SVX_NUM_NUMBER_NONE != ( pNFmt = &rRule.Get( nLvl ))
->GetNumberingType() || pNFmt->GetPrefix().Len() ||
(pNFmt->GetSuffix().Len() && pNFmt->GetSuffix() != aDotStr ))
break;
if( pEnd )
*pEnd = nEnd;
return nLvl != nEnd;
}
void RtfExport::BuildNumbering()
{
const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl();
for( sal_uInt16 n = rListTbl.Count()+1; n; )
{
SwNumRule* pRule;
--n;
if( n == rListTbl.Count() )
pRule = (SwNumRule*)pDoc->GetOutlineNumRule();
else
{
pRule = rListTbl[ n ];
if( !pDoc->IsUsed( *pRule ))
continue;
}
if( IsExportNumRule( *pRule ))
GetId( *pRule );
}
}
void RtfExport::WriteNumbering()
{
OSL_TRACE("%s start", OSL_THIS_FUNC);
if ( !pUsedNumTbl )
return; // no numbering is used
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_LISTTABLE;
AbstractNumberingDefinitions();
Strm() << '}';
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDETABLE;
NumberingDefinitions();
Strm() << '}';
OSL_TRACE("%s end", OSL_THIS_FUNC);
}
void RtfExport::WriteRevTab()
{
OSL_TRACE("%s", OSL_THIS_FUNC);
int nRevAuthors = pDoc->GetRedlineTbl().Count();
if (nRevAuthors < 1)
return;
// RTF always seems to use Unknown as the default first entry
String sUnknown(RTL_CONSTASCII_USTRINGPARAM("Unknown"));
GetRedline(sUnknown);
for( sal_uInt16 i = 0; i < pDoc->GetRedlineTbl().Count(); ++i )
{
const SwRedline* pRedl = pDoc->GetRedlineTbl()[ i ];
GetRedline(SW_MOD()->GetRedlineAuthor(pRedl->GetAuthor()));
}
// Now write the table
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_REVTBL << ' ';
for(sal_uInt16 i = 0; i < m_aRedlineTbl.size(); ++i)
{
const String* pAuthor = GetRedline(i);
Strm() << '{';
if (pAuthor)
Strm() << OutString(*pAuthor, eDefaultEncoding);
Strm() << ";}";
}
Strm() << '}' << sNewLine;
}
void RtfExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
// headers
if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
WriteHeaderFooter( rLeftFmt, true, OOO_STRING_SVTOOLS_RTF_HEADERL );
if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
WriteHeaderFooter( rFmt, true, OOO_STRING_SVTOOLS_RTF_HEADER );
if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
WriteHeaderFooter( rFirstPageFmt, true, OOO_STRING_SVTOOLS_RTF_HEADERF );
// footers
if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
WriteHeaderFooter( rLeftFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTERL );
if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
WriteHeaderFooter( rFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTER );
if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
WriteHeaderFooter( rFirstPageFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTERF );
}
void RtfExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
}
void RtfExport::WriteFormData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
{
OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
}
void RtfExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
{
OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
}
void RtfExport::DoComboBox(const rtl::OUString& /*rName*/,
const rtl::OUString& /*rHelp*/,
const rtl::OUString& /*rToolTip*/,
const rtl::OUString& /*rSelected*/,
uno::Sequence<rtl::OUString>& /*rListItems*/)
{
OSL_TRACE("%s", OSL_THIS_FUNC);
// this is handled in RtfAttributeOutput::OutputFlyFrame_Impl
}
void RtfExport::DoFormText(const SwInputField* pFld )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
::rtl::OUString sResult = pFld->ExpandField(pDoc->IsClipBoard());
::rtl::OUString sHelp( pFld->GetHelp() );
::rtl::OUString sName = pFld->GetPar2();
::rtl::OUString sStatus = pFld->GetToolTip();
m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST "{ FORMTEXT }");
m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD " {" OOO_STRING_SVTOOLS_RTF_FFTYPE "0" );
if( sHelp.getLength() )
m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFOWNHELP );
if( sStatus.getLength() )
m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFOWNSTAT );
m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFTYPETXT "0" );
if( sName.getLength() )
m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ").append( OutString( sName, eDefaultEncoding )).append( "}" );
if( sHelp.getLength() )
m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ").append( OutString( sHelp, eDefaultEncoding )).append( "}" );
m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFDEFTEXT " ").append( OutString( sResult, eDefaultEncoding )).append( "}" );
if( sStatus.getLength() )
m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ").append( OutString( sStatus, eDefaultEncoding )).append( "}");
m_pAttrOutput->RunText().append( "}}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " " );
m_pAttrOutput->RunText().append( OutString( sResult, eDefaultEncoding )).append( "}}" );
}
sal_uLong RtfExport::ReplaceCr( sal_uInt8 )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
// Completely unused for Rtf export... only here for code sharing
// purpose with binary export
return 0;
}
void RtfExport::WriteFonts()
{
Strm() << sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL;
maFontHelper.WriteFontTable( *m_pAttrOutput );
Strm() << '}';
}
void RtfExport::WriteStyles()
{
OSL_TRACE("%s start", OSL_THIS_FUNC);
pStyles->OutputStylesTable();
OSL_TRACE("%s end", OSL_THIS_FUNC);
}
void RtfExport::WriteMainText()
{
OSL_TRACE("%s start", OSL_THIS_FUNC);
SwTableNode* pTableNode = pCurPam->GetNode()->FindTableNode();
if ( m_pWriter && m_pWriter->bWriteOnlyFirstTable
&& pTableNode != 0 )
{
pCurPam->GetPoint()->nNode = *pTableNode;
pCurPam->GetMark()->nNode = *(pTableNode->EndOfSectionNode());
}
else
{
pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
}
WriteText();
OSL_TRACE("%s end", OSL_THIS_FUNC);
}
void RtfExport::WriteInfo()
{
OSL_TRACE("%s", OSL_THIS_FUNC);
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_INFO;
SwDocShell *pDocShell(pDoc->GetDocShell());
uno::Reference<document::XDocumentProperties> xDocProps;
if (pDocShell) {
uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
pDocShell->GetModel(), uno::UNO_QUERY);
xDocProps.set(xDPS->getDocumentProperties());
}
if (xDocProps.is()) {
OutUnicode(OOO_STRING_SVTOOLS_RTF_TITLE, xDocProps->getTitle());
OutUnicode(OOO_STRING_SVTOOLS_RTF_SUBJECT, xDocProps->getSubject());
OutUnicode(OOO_STRING_SVTOOLS_RTF_KEYWORDS,
::comphelper::string::convertCommaSeparated(xDocProps->getKeywords()));
OutUnicode(OOO_STRING_SVTOOLS_RTF_DOCCOMM, xDocProps->getDescription());
OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR, xDocProps->getAuthor());
OutDateTime(OOO_STRING_SVTOOLS_RTF_CREATIM, xDocProps->getCreationDate());
OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR,xDocProps->getModifiedBy());
OutDateTime(OOO_STRING_SVTOOLS_RTF_REVTIM, xDocProps->getModificationDate());
OutDateTime(OOO_STRING_SVTOOLS_RTF_PRINTIM, xDocProps->getPrintDate());
}
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_COMMENT << " ";
OUString sProduct;
utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct;
Strm() << OUStringToOString( sProduct, eCurrentEncoding) << "}{" << OOO_STRING_SVTOOLS_RTF_VERN;
OutULong( SUPD*10 ) << '}';
Strm() << '}';
}
void RtfExport::WritePageDescTable()
{
OSL_TRACE("%s", OSL_THIS_FUNC);
// Write page descriptions (page styles)
sal_uInt16 nSize = pDoc->GetPageDescCnt();
if( !nSize )
return;
Strm() << sNewLine; // a separator
bOutPageDescs = sal_True;
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_PGDSCTBL;
for( sal_uInt16 n = 0; n < nSize; ++n )
{
const SwPageDesc& rPageDesc =
const_cast<const SwDoc*>(pDoc)->GetPageDesc( n );
Strm() << sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_PGDSC;
OutULong( n ) << OOO_STRING_SVTOOLS_RTF_PGDSCUSE;
OutULong( rPageDesc.ReadUseOn() );
OutPageDescription( rPageDesc, sal_False, sal_False );
// search for the next page description
sal_uInt16 i = nSize;
while( i )
if( rPageDesc.GetFollow() ==
&const_cast<const SwDoc *>(pDoc)->GetPageDesc( --i ) )
break;
Strm() << OOO_STRING_SVTOOLS_RTF_PGDSCNXT;
OutULong( i ) << ' ';
Strm() << OutString( rPageDesc.GetName(), eDefaultEncoding) << ";}";
}
Strm() << '}' << sNewLine;
bOutPageDescs = sal_False;
// reset table infos, otherwise the depth of the cells will be incorrect,
// in case the page style (header or footer) had tables
mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
}
void RtfExport::ExportDocument_Impl()
{
#ifdef DEBUG
// MSWordExportBase::WriteText and others write debug messages to std::clog
// which is not interesting while debugging RtfExport
std::ostringstream aOss;
std::streambuf *pOldBuf = std::clog.rdbuf(aOss.rdbuf());
#endif
// Make the header
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_RTF << '1'
<< OOO_STRING_SVTOOLS_RTF_ANSI;
Strm() << OOO_STRING_SVTOOLS_RTF_DEFF;
OutULong( maFontHelper.GetId( (SvxFontItem&)pDoc->GetAttrPool().GetDefaultItem(
RES_CHRATR_FONT ) ));
// If this not exist, MS don't understand our ansi characters (0x80-0xff).
Strm() << "\\adeflang1025";
// Font table
WriteFonts();
pStyles = new MSWordStyles( *this );
// Color and stylesheet table
WriteStyles();
// List table
BuildNumbering();
WriteNumbering();
WriteRevTab();
WriteInfo();
// Default TabSize
Strm() << m_pAttrOutput->m_aTabStop.makeStringAndClear() << sNewLine;
// Page description
WritePageDescTable();
// Enable form protection by default if needed, as there is no switch to
// enable it on a per-section basis. OTOH don't always enable it as it
// breaks moving of drawings - so write it only in case there is really a
// protected section in the document.
{
const SfxItemPool& rPool = pDoc->GetAttrPool();
sal_uInt32 const nMaxItem = rPool.GetItemCount2(RES_PROTECT);
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
const SvxProtectItem* pProtect = (const SvxProtectItem*)rPool.GetItem2(RES_PROTECT, n);
if (pProtect && pProtect->IsCntntProtected())
{
Strm() << OOO_STRING_SVTOOLS_RTF_FORMPROT;
break;
}
}
}
// enable form field shading
Strm() << OOO_STRING_SVTOOLS_RTF_FORMSHADE;
// size and empty margins of the page
if( pDoc->GetPageDescCnt() )
{
//JP 06.04.99: Bug 64361 - Seeking the first SwFmtPageDesc. If
// no set, the default is valid
const SwFmtPageDesc* pSttPgDsc = 0;
{
const SwNode& rSttNd = *pDoc->GetNodes()[
pDoc->GetNodes().GetEndOfExtras().GetIndex() + 2 ];
const SfxItemSet* pSet = 0;
if( rSttNd.IsCntntNode() )
pSet = &rSttNd.GetCntntNode()->GetSwAttrSet();
else if( rSttNd.IsTableNode() )
pSet = &rSttNd.GetTableNode()->GetTable().
GetFrmFmt()->GetAttrSet();
else if( rSttNd.IsSectionNode() )
pSet = &rSttNd.GetSectionNode()->GetSection().
GetFmt()->GetAttrSet();
if( pSet )
{
sal_uInt16 nPosInDoc;
pSttPgDsc = (SwFmtPageDesc*)&pSet->Get( RES_PAGEDESC );
if( !pSttPgDsc->GetPageDesc() )
pSttPgDsc = 0;
else if( pDoc->FindPageDescByName( pSttPgDsc->
GetPageDesc()->GetName(), &nPosInDoc ))
{
Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_PGDSCNO;
OutULong( nPosInDoc ) << '}';
}
}
}
const SwPageDesc& rPageDesc = pSttPgDsc ? *pSttPgDsc->GetPageDesc()
: const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
const SwFrmFmt &rFmtPage = rPageDesc.GetMaster();
{
if( rPageDesc.GetLandscape() )
Strm() << OOO_STRING_SVTOOLS_RTF_LANDSCAPE;
const SwFmtFrmSize& rSz = rFmtPage.GetFrmSize();
// Clipboard document is always created without a printer, then
// the size will be always LONG_MAX! Solution then is to use A4
if( LONG_MAX == rSz.GetHeight() || LONG_MAX == rSz.GetWidth() )
{
Strm() << OOO_STRING_SVTOOLS_RTF_PAPERH;
Size a4 = SvxPaperInfo::GetPaperSize(PAPER_A4);
OutULong( a4.Height() ) << OOO_STRING_SVTOOLS_RTF_PAPERW;
OutULong( a4.Width() );
}
else
{
Strm() << OOO_STRING_SVTOOLS_RTF_PAPERH;
OutULong( rSz.GetHeight() ) << OOO_STRING_SVTOOLS_RTF_PAPERW;
OutULong( rSz.GetWidth() );
}
}
{
const SvxLRSpaceItem& rLR = rFmtPage.GetLRSpace();
Strm() << OOO_STRING_SVTOOLS_RTF_MARGL;
OutLong( rLR.GetLeft() ) << OOO_STRING_SVTOOLS_RTF_MARGR;
OutLong( rLR.GetRight() );
}
{
const SvxULSpaceItem& rUL = rFmtPage.GetULSpace();
Strm() << OOO_STRING_SVTOOLS_RTF_MARGT;
OutLong( rUL.GetUpper() ) << OOO_STRING_SVTOOLS_RTF_MARGB;
OutLong( rUL.GetLower() );
}
Strm() << OOO_STRING_SVTOOLS_RTF_SECTD << OOO_STRING_SVTOOLS_RTF_SBKNONE;
// All sections are unlocked by default
Strm() << OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED;
OutLong(1);
OutPageDescription( rPageDesc, sal_False, sal_True ); // Changed bCheckForFirstPage to sal_True so headers
// following title page are correctly added - i13107
if( pSttPgDsc )
{
pAktPageDesc = &rPageDesc;
}
}
// line numbering
const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo();
if ( rLnNumInfo.IsPaintLineNumbers() )
AttrOutput().SectionLineNumbering( 0, rLnNumInfo );
{
// write the footnotes and endnotes-out Info
const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
const char* pOut = FTNPOS_CHAPTER == rFtnInfo.ePos
? OOO_STRING_SVTOOLS_RTF_ENDDOC
: OOO_STRING_SVTOOLS_RTF_FTNBJ;
Strm() << pOut << OOO_STRING_SVTOOLS_RTF_FTNSTART;
OutLong( rFtnInfo.nFtnOffset + 1 );
switch( rFtnInfo.eNum )
{
case FTNNUM_PAGE: pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTPG; break;
case FTNNUM_DOC: pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTCONT; break;
// case FTNNUM_CHAPTER:
default: pOut = OOO_STRING_SVTOOLS_RTF_FTNRESTART; break;
}
Strm() << pOut;
switch( rFtnInfo.aFmt.GetNumberingType() )
{
case SVX_NUM_CHARS_LOWER_LETTER:
case SVX_NUM_CHARS_LOWER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_FTNNALC; break;
case SVX_NUM_CHARS_UPPER_LETTER:
case SVX_NUM_CHARS_UPPER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_FTNNAUC; break;
case SVX_NUM_ROMAN_LOWER: pOut = OOO_STRING_SVTOOLS_RTF_FTNNRLC; break;
case SVX_NUM_ROMAN_UPPER: pOut = OOO_STRING_SVTOOLS_RTF_FTNNRUC; break;
case SVX_NUM_CHAR_SPECIAL: pOut = OOO_STRING_SVTOOLS_RTF_FTNNCHI; break;
// case SVX_NUM_ARABIC:
default: pOut = OOO_STRING_SVTOOLS_RTF_FTNNAR; break;
}
Strm() << pOut;
const SwEndNoteInfo& rEndNoteInfo = pDoc->GetEndNoteInfo();
Strm() << OOO_STRING_SVTOOLS_RTF_AENDDOC << OOO_STRING_SVTOOLS_RTF_AFTNRSTCONT
<< OOO_STRING_SVTOOLS_RTF_AFTNSTART;
OutLong( rEndNoteInfo.nFtnOffset + 1 );
switch( rEndNoteInfo.aFmt.GetNumberingType() )
{
case SVX_NUM_CHARS_LOWER_LETTER:
case SVX_NUM_CHARS_LOWER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNALC; break;
case SVX_NUM_CHARS_UPPER_LETTER:
case SVX_NUM_CHARS_UPPER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAUC; break;
case SVX_NUM_ROMAN_LOWER: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRLC; break;
case SVX_NUM_ROMAN_UPPER: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRUC; break;
case SVX_NUM_CHAR_SPECIAL: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNCHI; break;
// case SVX_NUM_ARABIC:
default: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAR; break;
}
Strm() << pOut;
}
Strm() << sNewLine;
// Init sections
m_pSections = new MSWordSections( *this );
WriteMainText();
Strm() << '}';
#ifdef DEBUG
std::clog.rdbuf(pOldBuf);
#endif
}
void RtfExport::PrepareNewPageDesc( const SfxItemSet* pSet,
const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
const SwPageDesc* pNewPgDesc )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
const SwSectionFmt* pFmt = GetSectionFormat( rNd );
const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
if ( pNewPgDescFmt )
m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
else if ( pNewPgDesc )
m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
}
bool RtfExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
{
bool bRet( false );
OSL_TRACE("%s", OSL_THIS_FUNC);
if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
{
if (const SwFmt *pParent = rFmt.DerivedFrom())
{
if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
{
// Level 9 disables the outline
Strm() << OOO_STRING_SVTOOLS_RTF_LEVEL << 9;
bRet = true;
}
}
}
return bRet;
}
void RtfExport::OutputGrfNode( const SwGrfNode& )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
/* noop, see RtfAttributeOutput::FlyFrameGraphic */
}
void RtfExport::OutputOLENode( const SwOLENode& )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
/* noop, see RtfAttributeOutput::FlyFrameOLE */
}
void RtfExport::AppendSection( const SwPageDesc* pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
}
RtfExport::RtfExport( RtfExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam, Writer* pWriter )
: MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
m_pFilter( pFilter ),
m_pWriter( pWriter ),
m_pAttrOutput( NULL ),
m_pSections( NULL ),
m_pSdrExport( NULL ),
eDefaultEncoding(
rtl_getTextEncodingFromWindowsCharset(
sw::ms::rtl_TextEncodingToWinCharset(DEF_ENCODING))),
eCurrentEncoding(eDefaultEncoding),
bRTFFlySyntax(false)
{
mbExportModeRTF = true;
// the attribute output for the document
m_pAttrOutput = new RtfAttributeOutput( *this );
// that just causes problems for RTF
bSubstituteBullets = false;
// needed to have a complete font table
maFontHelper.bLoadAllFonts = true;
// the related SdrExport
m_pSdrExport = new RtfSdrExport( *this );
if (!m_pWriter)
m_pWriter = &m_pFilter->m_aWriter;
}
RtfExport::~RtfExport()
{
delete m_pAttrOutput, m_pAttrOutput = NULL;
delete m_pSdrExport, m_pSdrExport = NULL;
}
SvStream& RtfExport::Strm()
{
return m_pWriter->Strm();
}
SvStream& RtfExport::OutULong( sal_uLong nVal )
{
return m_pWriter->OutULong( Strm(), nVal );
}
SvStream& RtfExport::OutLong( long nVal )
{
return m_pWriter->OutLong( Strm(), nVal );
}
void RtfExport::OutUnicode(const sal_Char *pToken, const String &rContent)
{
if (rContent.Len())
{
Strm() << '{' << pToken << ' ';
Strm() << OutString( rContent, eCurrentEncoding ).getStr();
Strm() << '}';
}
}
OString RtfExport::OutHex(sal_uLong nHex, sal_uInt8 nLen)
{
sal_Char aNToABuf[] = "0000000000000000";
OSL_ENSURE( nLen < sizeof(aNToABuf), "nLen is too big" );
if( nLen >= sizeof(aNToABuf) )
nLen = (sizeof(aNToABuf)-1);
// Set pointer to the buffer end
sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
for( sal_uInt8 n = 0; n < nLen; ++n )
{
*(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
if( *pStr > '9' )
*pStr += 39;
nHex >>= 4;
}
return OString(pStr);
}
OString RtfExport::OutChar(sal_Unicode c, int *pUCMode, rtl_TextEncoding eDestEnc)
{
OStringBuffer aBuf;
const sal_Char* pStr = 0;
// 0x0b instead of \n, etc because of the replacements in SwAttrIter::GetSnippet()
switch (c)
{
case 0x0b:
// hard line break
pStr = OOO_STRING_SVTOOLS_RTF_LINE;
break;
case '\t':
pStr = OOO_STRING_SVTOOLS_RTF_TAB;
break;
case '\\':
case '}':
case '{':
aBuf.append('\\');
aBuf.append((sal_Char)c);
break;
case 0xa0:
// non-breaking space
pStr = "\\~";
break;
case 0x1e:
// non-breaking hyphen
pStr = "\\_";
break;
case 0x1f:
// optional hyphen
pStr = "\\-";
break;
default:
if (c >= ' ' && c <= '~')
aBuf.append((sal_Char)c);
else {
//If we can't convert to the dest encoding, or if
//its an uncommon multibyte sequence which most
//readers won't be able to handle correctly, then
//If we can't convert to the dest encoding, then
//export as unicode
OUString sBuf(&c, 1);
OString sConverted;
sal_uInt32 nFlags =
RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
bool bWriteAsUnicode = !(sBuf.convertToString(&sConverted,
eDestEnc, nFlags))
|| (RTL_TEXTENCODING_UTF8==eDestEnc); // #i43933# do not export UTF-8 chars in RTF;
if (bWriteAsUnicode)
sBuf.convertToString(&sConverted,
eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
const sal_Int32 nLen = sConverted.getLength();
if (bWriteAsUnicode && pUCMode)
{
// then write as unicode - character
if (*pUCMode != nLen)
{
aBuf.append("\\uc");
aBuf.append((sal_Int32)nLen);
// #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.
aBuf.append(' ');
*pUCMode = nLen;
}
aBuf.append("\\u");
aBuf.append((sal_Int32)c);
}
for (sal_Int32 nI = 0; nI < nLen; ++nI)
{
aBuf.append("\\'");
aBuf.append(OutHex(sConverted.getStr()[nI], 2));
}
}
}
if (pStr) {
aBuf.append(pStr);
aBuf.append(' ');
}
return aBuf.makeStringAndClear();
}
OString RtfExport::OutString(const String &rStr, rtl_TextEncoding eDestEnc)
{
OSL_TRACE("%s, rStr = '%s'", OSL_THIS_FUNC,
OUStringToOString( OUString( rStr ), eDestEnc ).getStr());
OStringBuffer aBuf;
int nUCMode = 1;
for (xub_StrLen n = 0; n < rStr.Len(); ++n)
aBuf.append(OutChar(rStr.GetChar(n), &nUCMode, eDestEnc));
if (nUCMode != 1) {
aBuf.append(OOO_STRING_SVTOOLS_RTF_UC);
aBuf.append((sal_Int32)1);
aBuf.append(" "); // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
}
return aBuf.makeStringAndClear();
}
void RtfExport::OutDateTime(const sal_Char* pStr, const util::DateTime& rDT )
{
Strm() << '{' << pStr << OOO_STRING_SVTOOLS_RTF_YR;
OutULong( rDT.Year ) << OOO_STRING_SVTOOLS_RTF_MO;
OutULong( rDT.Month ) << OOO_STRING_SVTOOLS_RTF_DY;
OutULong( rDT.Day ) << OOO_STRING_SVTOOLS_RTF_HR;
OutULong( rDT.Hours ) << OOO_STRING_SVTOOLS_RTF_MIN;
OutULong( rDT.Minutes ) << '}';
}
sal_uInt16 RtfExport::GetColor( const Color& rColor ) const
{
for (RtfColorTbl::const_iterator it=m_aColTbl.begin() ; it != m_aColTbl.end(); it++ )
if ((*it).second == rColor) {
OSL_TRACE("%s returning %d (%d,%d,%d)", OSL_THIS_FUNC, (*it).first, rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue());
return (*it).first;
}
OSL_ENSURE( sal_False, "No such Color in m_aColTbl!" );
return 0;
}
void RtfExport::InsColor( const Color& rCol )
{
sal_uInt16 n;
bool bAutoColorInTable = false;
for (RtfColorTbl::iterator it=m_aColTbl.begin() ; it != m_aColTbl.end(); ++it )
{
if ((*it).second == rCol)
return; // Already in the table
else if ((*it).second == COL_AUTO)
bAutoColorInTable = true;
}
if (rCol.GetColor() == COL_AUTO)
// COL_AUTO gets value 0
n = 0;
else
{
// other colors get values >0
n = m_aColTbl.size();
if (!bAutoColorInTable)
// reserve value "0" for COL_AUTO (if COL_AUTO wasn't inserted until now)
n++;
}
m_aColTbl.insert(std::pair<sal_uInt16,Color>( n, rCol ));
}
void RtfExport::InsColorLine( const SvxBoxItem& rBox )
{
const SvxBorderLine* pLine = 0;
if( rBox.GetTop() )
InsColor( (pLine = rBox.GetTop())->GetColor() );
if( rBox.GetBottom() && pLine != rBox.GetBottom() )
InsColor( (pLine = rBox.GetBottom())->GetColor() );
if( rBox.GetLeft() && pLine != rBox.GetLeft() )
InsColor( (pLine = rBox.GetLeft())->GetColor() );
if( rBox.GetRight() && pLine != rBox.GetRight() )
InsColor( rBox.GetRight()->GetColor() );
}
void RtfExport::OutColorTable()
{
// Build the table from rPool since the colors provided to
// RtfAttributeOutput callbacks are too late.
sal_uInt32 nMaxItem;
const SfxItemPool& rPool = pDoc->GetAttrPool();
// char color
{
const SvxColorItem* pCol = (const SvxColorItem*)GetDfltAttr(
RES_CHRATR_COLOR );
InsColor( pCol->GetValue() );
if( 0 != ( pCol = (const SvxColorItem*)rPool.GetPoolDefaultItem(
RES_CHRATR_COLOR ) ))
InsColor( pCol->GetValue() );
nMaxItem = rPool.GetItemCount2(RES_CHRATR_COLOR);
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
if( 0 != (pCol = (const SvxColorItem*)rPool.GetItem2(
RES_CHRATR_COLOR, n ) ) )
InsColor( pCol->GetValue() );
}
const SvxUnderlineItem* pUnder = (const SvxUnderlineItem*)GetDfltAttr( RES_CHRATR_UNDERLINE );
InsColor( pUnder->GetColor() );
nMaxItem = rPool.GetItemCount2(RES_CHRATR_UNDERLINE);
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
if( 0 != (pUnder = (const SvxUnderlineItem*)rPool.GetItem2( RES_CHRATR_UNDERLINE, n ) ) )
InsColor( pUnder->GetColor() );
}
const SvxOverlineItem* pOver = (const SvxOverlineItem*)GetDfltAttr( RES_CHRATR_OVERLINE );
InsColor( pOver->GetColor() );
nMaxItem = rPool.GetItemCount2(RES_CHRATR_OVERLINE);
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
if( 0 != (pOver = (const SvxOverlineItem*)rPool.GetItem2( RES_CHRATR_OVERLINE, n ) ) )
InsColor( pOver->GetColor() );
}
}
// background color
static const sal_uInt16 aBrushIds[] = {
RES_BACKGROUND, RES_CHRATR_BACKGROUND, 0 };
for( const sal_uInt16* pIds = aBrushIds; *pIds; ++pIds )
{
const SvxBrushItem* pBkgrd = (const SvxBrushItem*)GetDfltAttr( *pIds );
InsColor( pBkgrd->GetColor() );
if( 0 != ( pBkgrd = (const SvxBrushItem*)rPool.GetPoolDefaultItem(
*pIds ) ))
{
InsColor( pBkgrd->GetColor() );
}
nMaxItem = rPool.GetItemCount2( *pIds );
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
if( 0 != (pBkgrd = (const SvxBrushItem*)rPool.GetItem2(
*pIds , n ) ))
{
InsColor( pBkgrd->GetColor() );
}
}
}
// shadow color
{
const SvxShadowItem* pShadow = (const SvxShadowItem*)GetDfltAttr(
RES_SHADOW );
InsColor( pShadow->GetColor() );
if( 0 != ( pShadow = (const SvxShadowItem*)rPool.GetPoolDefaultItem(
RES_SHADOW ) ))
{
InsColor( pShadow->GetColor() );
}
nMaxItem = rPool.GetItemCount2(RES_SHADOW);
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
if( 0 != (pShadow = (const SvxShadowItem*)rPool.GetItem2(
RES_SHADOW, n ) ) )
{
InsColor( pShadow->GetColor() );
}
}
}
// frame border color
{
const SvxBoxItem* pBox;
if( 0 != ( pBox = (const SvxBoxItem*)rPool.GetPoolDefaultItem(
RES_BOX ) ))
InsColorLine( *pBox );
nMaxItem = rPool.GetItemCount2(RES_BOX);
for (sal_uInt32 n = 0; n < nMaxItem; ++n)
{
if( 0 != (pBox = (const SvxBoxItem*)rPool.GetItem2( RES_BOX, n ) ))
InsColorLine( *pBox );
}
}
for (size_t n = 0; n < m_aColTbl.size(); ++n)
{
const Color& rCol = m_aColTbl[ n ];
if( n || COL_AUTO != rCol.GetColor() )
{
Strm() << OOO_STRING_SVTOOLS_RTF_RED;
OutULong( rCol.GetRed() ) << OOO_STRING_SVTOOLS_RTF_GREEN;
OutULong( rCol.GetGreen() ) << OOO_STRING_SVTOOLS_RTF_BLUE;
OutULong( rCol.GetBlue() );
}
Strm() << ';';
}
}
void RtfExport::InsStyle( sal_uInt16 nId, const OString& rStyle )
{
m_aStyTbl.insert(std::pair<sal_uInt16,OString>(nId, rStyle) );
}
OString* RtfExport::GetStyle( sal_uInt16 nId )
{
std::map<sal_uInt16,OString>::iterator i = m_aStyTbl.find(nId);
if (i != m_aStyTbl.end())
return &i->second;
return NULL;
}
sal_uInt16 RtfExport::GetRedline( const String& rAuthor )
{
std::map<String,sal_uInt16>::iterator i = m_aRedlineTbl.find(rAuthor);
if (i != m_aRedlineTbl.end())
return i->second;
else
{
int nId = m_aRedlineTbl.size();
m_aRedlineTbl.insert(std::pair<String,sal_uInt16>(rAuthor,nId));
return nId;
}
}
const String* RtfExport::GetRedline( sal_uInt16 nId )
{
for(std::map<String,sal_uInt16>::iterator aIter = m_aRedlineTbl.begin(); aIter != m_aRedlineTbl.end(); ++aIter)
if ((*aIter).second == nId)
return &(*aIter).first;
return NULL;
}
void RtfExport::OutPageDescription( const SwPageDesc& rPgDsc, sal_Bool bWriteReset, sal_Bool bCheckForFirstPage )
{
OSL_TRACE("%s start", OSL_THIS_FUNC);
const SwPageDesc *pSave = pAktPageDesc;
pAktPageDesc = &rPgDsc;
if( bCheckForFirstPage && pAktPageDesc->GetFollow() &&
pAktPageDesc->GetFollow() != pAktPageDesc )
pAktPageDesc = pAktPageDesc->GetFollow();
if( bWriteReset )
{
if( pCurPam->GetPoint()->nNode == pOrigPam->Start()->nNode )
Strm() << OOO_STRING_SVTOOLS_RTF_SECTD << OOO_STRING_SVTOOLS_RTF_SBKNONE;
else
Strm() << OOO_STRING_SVTOOLS_RTF_SECT << OOO_STRING_SVTOOLS_RTF_SECTD;
}
if( pAktPageDesc->GetLandscape() )
Strm() << OOO_STRING_SVTOOLS_RTF_LNDSCPSXN;
const SwFmt *pFmt = &pAktPageDesc->GetMaster(); //GetLeft();
bOutPageDescs = true;
OutputFormat(*pFmt, true, false);
bOutPageDescs = false;
// normal header / footer (without a style)
const SfxPoolItem* pItem;
if( pAktPageDesc->GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False,
&pItem ) == SFX_ITEM_SET)
WriteHeaderFooter(*pItem, true);
if( pAktPageDesc->GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False,
&pItem ) == SFX_ITEM_SET)
WriteHeaderFooter(*pItem, false);
// title page
if( pAktPageDesc != &rPgDsc )
{
pAktPageDesc = &rPgDsc;
Strm() << OOO_STRING_SVTOOLS_RTF_TITLEPG;
if( pAktPageDesc->GetMaster().GetAttrSet().GetItemState( RES_HEADER,
sal_False, &pItem ) == SFX_ITEM_SET )
WriteHeaderFooter(*pItem, true);
if( pAktPageDesc->GetMaster().GetAttrSet().GetItemState( RES_FOOTER,
sal_False, &pItem ) == SFX_ITEM_SET )
WriteHeaderFooter(*pItem, false);
}
// numbering type
AttrOutput().SectionPageNumbering(pAktPageDesc->GetNumType().GetNumberingType(), 0);
pAktPageDesc = pSave;
//bOutPageDesc = bOldOut;
OSL_TRACE("%s end", OSL_THIS_FUNC);
}
void RtfExport::WriteHeaderFooter(const SfxPoolItem& rItem, bool bHeader)
{
if (bHeader)
{
const SwFmtHeader& rHeader = (const SwFmtHeader&)rItem;
if (!rHeader.IsActive())
return;
}
else
{
const SwFmtFooter& rFooter = (const SwFmtFooter&)rItem;
if (!rFooter.IsActive())
return;
}
OSL_TRACE("%s start", OSL_THIS_FUNC);
const sal_Char* pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADER : OOO_STRING_SVTOOLS_RTF_FOOTER);
/* is this a title page? */
if( pAktPageDesc->GetFollow() && pAktPageDesc->GetFollow() != pAktPageDesc )
{
Strm() << OOO_STRING_SVTOOLS_RTF_TITLEPG;
pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERF : OOO_STRING_SVTOOLS_RTF_FOOTERF);
}
Strm() << '{' << pStr;
WriteHeaderFooterText(pAktPageDesc->GetMaster(), bHeader);
Strm() << '}';
OSL_TRACE("%s end", OSL_THIS_FUNC);
}
void RtfExport::WriteHeaderFooter(const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr)
{
OSL_TRACE("%s start", OSL_THIS_FUNC);
m_pAttrOutput->WriteHeaderFooter_Impl( rFmt, bHeader, pStr );
OSL_TRACE("%s end", OSL_THIS_FUNC);
}
class SwRTFWriter : public Writer
{
bool m_bOutOutlineOnly;
public:
SwRTFWriter( const String& rFilterName, const String& rBaseURL );
virtual ~SwRTFWriter();
virtual sal_uLong WriteStream();
};
SwRTFWriter::SwRTFWriter( const String& rFltName, const String & rBaseURL )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
SetBaseURL( rBaseURL );
// export outline nodes, only (send outline to clipboard/presentation)
m_bOutOutlineOnly = 'O' == rFltName.GetChar( 0 );
}
SwRTFWriter::~SwRTFWriter()
{}
sal_uLong SwRTFWriter::WriteStream()
{
OSL_TRACE("%s", OSL_THIS_FUNC);
RtfExport aExport( NULL, pDoc, new SwPaM( *pCurPam->End(), *pCurPam->Start() ), pCurPam, this );
aExport.mbOutOutlineOnly = m_bOutOutlineOnly;
aExport.ExportDocument( true );
return 0;
}
extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportRTF( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
{
OSL_TRACE("%s", OSL_THIS_FUNC);
xRet = new SwRTFWriter( rFltName, rBaseURL );
}
/* vi:set shiftwidth=4 expandtab: */