blob: 17c96f45fcb2cc402f91e92df7f3d01197e97ec9 [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.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
#include <vector>
#include <list>
#include <utility>
#include <algorithm>
#include <functional>
#include <iostream>
#if OSL_DEBUG_LEVEL > 0
# include <cstdio>
#endif
#include <hintids.hxx>
#include <tools/urlobj.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/cmapitem.hxx>
#include <editeng/langitem.hxx>
#include <editeng/svxfont.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/keepitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/brkitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/tstpitem.hxx>
#include "svl/urihelper.hxx"
#include <svl/whiter.hxx>
#include <fmtpdsc.hxx>
#include <fmtfsize.hxx>
#include <fmtornt.hxx>
#include <fmtlsplt.hxx>
#include <fmtflcnt.hxx>
#include <fmtanchr.hxx>
#include <fmtcntnt.hxx>
#include <frmatr.hxx>
#include <paratr.hxx>
#include <txatbase.hxx>
#include <fmtinfmt.hxx>
#include <fmtrfmrk.hxx>
#include <fchrfmt.hxx>
#include <fmtautofmt.hxx>
#include <charfmt.hxx>
#include <tox.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <doc.hxx>
#include <docary.hxx>
#include <swtable.hxx>
#include <swtblfmt.hxx>
#include <section.hxx>
#include <pagedesc.hxx>
#include <swrect.hxx>
#include <reffld.hxx>
#include <redline.hxx>
#include <wrtswtbl.hxx>
#include <htmltbl.hxx>
#include <txttxmrk.hxx>
#include <fmtline.hxx>
#include <fmtruby.hxx>
#include <breakit.hxx>
#include <txtatr.hxx>
#include <fmtsrnd.hxx>
#include <fmtrowsplt.hxx>
#include <com/sun/star/i18n/ScriptType.hdl>
#include <com/sun/star/i18n/WordType.hpp>
#include <writerfilter/doctok/sprmids.hxx>
#include "writerhelper.hxx"
#include "writerwordglue.hxx"
#include <numrule.hxx>
#include "wrtww8.hxx"
#include "ww8par.hxx"
#include <IMark.hxx>
#include "ww8attributeoutput.hxx"
#include <ndgrf.hxx>
#include <ndole.hxx>
#include <cstdio>
using namespace ::com::sun::star;
using namespace ::com::sun::star::i18n;
using namespace sw::util;
using namespace sw::types;
using namespace sw::mark;
using namespace nsFieldFlags;
static String lcl_getFieldCode( const IFieldmark* pFieldmark ) {
ASSERT(pFieldmark!=NULL, "where is my fieldmark???");
if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) ) {
return String::CreateFromAscii(" FORMTEXT ");
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) ) {
return String::CreateFromAscii(" FORMDROPDOWN ");
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ) ) {
return String::CreateFromAscii(" FORMCHECKBOX ");
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_TOC ) ) {
return String::CreateFromAscii(" TOC ");
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) ) {
return String::CreateFromAscii(" HYPERLINK ");
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_PAGEREF ) ) {
return String::CreateFromAscii(" PAGEREF ");
} else {
return pFieldmark->GetFieldname();
}
}
ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) {
ASSERT(pFieldmark!=NULL, "where is my fieldmark???");
if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) ) {
return ww::eFORMTEXT;
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) ) {
return ww::eFORMDROPDOWN;
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ) ) {
return ww::eFORMCHECKBOX;
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_TOC ) ) {
return ww::eTOC;
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) ) {
return ww::eHYPERLINK;
} else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_PAGEREF ) ) {
return ww::ePAGEREF;
} else {
return ww::eUNKNOWN;
}
}
/* */
MSWordAttrIter::MSWordAttrIter( MSWordExportBase& rExport )
: pOld( rExport.pChpIter ), m_rExport( rExport )
{
m_rExport.pChpIter = this;
}
MSWordAttrIter::~MSWordAttrIter()
{
m_rExport.pChpIter = pOld;
}
// Die Klasse SwAttrIter ist eine Hilfe zum Aufbauen der Fkp.chpx.
// Dabei werden nur Zeichen-Attribute beachtet; Absatz-Attribute brauchen
// diese Behandlung nicht.
// Die Absatz- und Textattribute des Writers kommen rein, und es wird
// mit Where() die naechste Position geliefert, an der sich die Attribute
// aendern. IsTxtAtr() sagt, ob sich an der mit Where() gelieferten Position
// ein Attribut ohne Ende und mit \xff im Text befindet.
// Mit OutAttr() werden die Attribute an der angegebenen SwPos
// ausgegeben.
class WW8SwAttrIter : public MSWordAttrIter
{
private:
const SwTxtNode& rNd;
CharRuns maCharRuns;
cCharRunIter maCharRunIter;
rtl_TextEncoding meChrSet;
sal_uInt16 mnScript;
bool mbCharIsRTL;
const SwRedline* pCurRedline;
xub_StrLen nAktSwPos;
sal_uInt16 nCurRedlinePos;
bool mbParaIsRTL;
const SwFmtDrop &mrSwFmtDrop;
sw::Frames maFlyFrms; // #i2916#
sw::FrameIter maFlyIter;
xub_StrLen SearchNext( xub_StrLen nStartPos );
void FieldVanish( const String& rTxt );
void OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool bStart);
void IterToCurrent();
//No copying
WW8SwAttrIter(const WW8SwAttrIter&);
WW8SwAttrIter& operator=(const WW8SwAttrIter&);
public:
WW8SwAttrIter( MSWordExportBase& rWr, const SwTxtNode& rNd );
bool IsTxtAttr( xub_StrLen nSwPos );
bool IsRedlineAtEnd( xub_StrLen nPos ) const;
bool IsDropCap( int nSwPos );
bool RequiresImplicitBookmark();
void NextPos() { nAktSwPos = SearchNext( nAktSwPos + 1 ); }
void OutAttr( xub_StrLen nSwPos );
virtual const SfxPoolItem* HasTextItem( sal_uInt16 nWhich ) const;
virtual const SfxPoolItem& GetItem( sal_uInt16 nWhich ) const;
int OutAttrWithRange(xub_StrLen nPos);
const SwRedlineData* GetRedline( xub_StrLen nPos );
void OutFlys(xub_StrLen nSwPos);
xub_StrLen WhereNext() const { return nAktSwPos; }
sal_uInt16 GetScript() const { return mnScript; }
bool IsCharRTL() const { return mbCharIsRTL; }
bool IsParaRTL() const { return mbParaIsRTL; }
rtl_TextEncoding GetCharSet() const { return meChrSet; }
String GetSnippet(const String &rStr, xub_StrLen nAktPos,
xub_StrLen nLen) const;
const SwFmtDrop& GetSwFmtDrop() const { return mrSwFmtDrop; }
};
class sortswflys :
public std::binary_function<const sw::Frame&, const sw::Frame&, bool>
{
public:
bool operator()(const sw::Frame &rOne, const sw::Frame &rTwo) const
{
return rOne.GetPosition() < rTwo.GetPosition();
}
};
void WW8SwAttrIter::IterToCurrent()
{
ASSERT(maCharRuns.begin() != maCharRuns.end(), "Impossible");
mnScript = maCharRunIter->mnScript;
meChrSet = maCharRunIter->meCharSet;
mbCharIsRTL = maCharRunIter->mbRTL;
}
WW8SwAttrIter::WW8SwAttrIter(MSWordExportBase& rWr, const SwTxtNode& rTxtNd) :
MSWordAttrIter(rWr),
rNd(rTxtNd),
maCharRuns(GetPseudoCharRuns(rTxtNd, 0, !rWr.HackIsWW8OrHigher())),
pCurRedline(0),
nAktSwPos(0),
nCurRedlinePos(USHRT_MAX),
mrSwFmtDrop(rTxtNd.GetSwAttrSet().GetDrop())
{
SwPosition aPos(rTxtNd);
if (FRMDIR_HORI_RIGHT_TOP == rWr.pDoc->GetTextDirection(aPos))
mbParaIsRTL = true;
else
mbParaIsRTL = false;
maCharRunIter = maCharRuns.begin();
IterToCurrent();
/*
#i2916#
Get list of any graphics which may be anchored from this paragraph.
*/
maFlyFrms = GetFramesInNode(rWr.maFrames, rNd);
std::sort(maFlyFrms.begin(), maFlyFrms.end(), sortswflys());
/*
#i18480#
If we are inside a frame then anything anchored inside this frame can
only be supported by word anchored inline ("as character"), so force
this in the supportable case.
*/
if (rWr.HackIsWW8OrHigher() && rWr.bInWriteEscher)
{
std::for_each(maFlyFrms.begin(), maFlyFrms.end(),
std::mem_fun_ref(&sw::Frame::ForceTreatAsInline));
}
maFlyIter = maFlyFrms.begin();
if ( m_rExport.pDoc->GetRedlineTbl().Count() )
{
SwPosition aPosition( rNd, SwIndex( (SwTxtNode*)&rNd ) );
pCurRedline = m_rExport.pDoc->GetRedline( aPosition, &nCurRedlinePos );
}
nAktSwPos = SearchNext(1);
}
xub_StrLen lcl_getMinPos( xub_StrLen pos1, xub_StrLen pos2 )
{
xub_StrLen min = STRING_NOTFOUND;
if ( pos1 == STRING_NOTFOUND && pos2 != STRING_NOTFOUND )
min = pos2;
else if ( pos2 == STRING_NOTFOUND && pos1 != STRING_NOTFOUND )
min = pos1;
else if ( pos2 != STRING_NOTFOUND && pos2 != STRING_NOTFOUND )
{
if ( pos1 < pos2 )
min = pos1;
else
min = pos2;
}
return min;
}
xub_StrLen WW8SwAttrIter::SearchNext( xub_StrLen nStartPos )
{
xub_StrLen nPos;
xub_StrLen nMinPos = STRING_MAXLEN;
xub_StrLen i=0;
const String aTxt = rNd.GetTxt();
xub_StrLen fieldEndPos = aTxt.Search(CH_TXT_ATR_FIELDEND, nStartPos);
xub_StrLen fieldStartPos = aTxt.Search(CH_TXT_ATR_FIELDSTART, nStartPos);
xub_StrLen formElementPos = aTxt.Search(CH_TXT_ATR_FORMELEMENT, nStartPos);
xub_StrLen pos = lcl_getMinPos( fieldEndPos, fieldStartPos );
pos = lcl_getMinPos( pos, formElementPos );
if (pos!=STRING_NOTFOUND)
nMinPos=pos;
// first the redline, then the attributes
if( pCurRedline )
{
const SwPosition* pEnd = pCurRedline->End();
if (pEnd->nNode == rNd && ((i = pEnd->nContent.GetIndex()) >= nStartPos) && i < nMinPos )
nMinPos = i;
}
if ( nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count() )
{
// nCurRedlinePos point to the next redline
nPos = nCurRedlinePos;
if( pCurRedline )
++nPos;
for ( ; nPos < m_rExport.pDoc->GetRedlineTbl().Count(); ++nPos )
{
const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nPos ];
const SwPosition* pStt = pRedl->Start();
const SwPosition* pEnd = pStt == pRedl->GetPoint()
? pRedl->GetMark()
: pRedl->GetPoint();
if( pStt->nNode == rNd )
{
if( ( i = pStt->nContent.GetIndex() ) >= nStartPos &&
i < nMinPos )
nMinPos = i;
}
else
break;
if( pEnd->nNode == rNd &&
( i = pEnd->nContent.GetIndex() ) < nMinPos &&
i >= nStartPos )
nMinPos = i;
}
}
if (mrSwFmtDrop.GetWholeWord() && nStartPos <= rNd.GetDropLen(0))
nMinPos = rNd.GetDropLen(0);
else if(nStartPos <= mrSwFmtDrop.GetChars())
nMinPos = mrSwFmtDrop.GetChars();
if(const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
{
// kann noch optimiert werden, wenn ausgenutzt wird, dass die TxtAttrs
// nach der Anfangsposition geordnet sind. Dann muessten
// allerdings noch 2 Indices gemerkt werden
for( i = 0; i < pTxtAttrs->Count(); i++ )
{
const SwTxtAttr* pHt = (*pTxtAttrs)[i];
nPos = *pHt->GetStart(); // gibt erstes Attr-Zeichen
if( nPos >= nStartPos && nPos <= nMinPos )
nMinPos = nPos;
if( pHt->End() ) // Attr mit Ende
{
nPos = *pHt->End(); // gibt letztes Attr-Zeichen + 1
if( nPos >= nStartPos && nPos <= nMinPos )
nMinPos = nPos;
}
if (pHt->HasDummyChar())
{
// pos + 1 because of CH_TXTATR in Text
nPos = *pHt->GetStart() + 1;
if( nPos >= nStartPos && nPos <= nMinPos )
nMinPos = nPos;
}
}
}
if (maCharRunIter != maCharRuns.end())
{
if (maCharRunIter->mnEndPos < nMinPos)
nMinPos = maCharRunIter->mnEndPos;
IterToCurrent();
}
/*
#i2916#
Check to see if there are any graphics anchored to characters in this
paragraph's text. Set nMinPos to 1 past the placement for anchored to
character because anchors in Word appear after the character they are
anchored to.
*/
if (maFlyIter != maFlyFrms.end())
{
const SwPosition &rAnchor = maFlyIter->GetPosition();
nPos = rAnchor.nContent.GetIndex();
if (nPos >= nStartPos && nPos <= nMinPos)
nMinPos = nPos;
if (maFlyIter->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR)
{
++nPos;
if (nPos >= nStartPos && nPos <= nMinPos)
nMinPos = nPos;
}
}
//nMinPos found and not going to change at this point
if (maCharRunIter != maCharRuns.end())
{
if (maCharRunIter->mnEndPos == nMinPos)
++maCharRunIter;
}
return nMinPos;
}
void WW8SwAttrIter::OutAttr( xub_StrLen nSwPos )
{
m_rExport.AttrOutput().RTLAndCJKState( IsCharRTL(), GetScript() );
/*
Depending on whether text is in CTL/CJK or Western, get the id of that
script, the idea is that the font that is actually in use to render this
range of text ends up in pFont
*/
sal_uInt16 nFontId = GetWhichOfScript( RES_CHRATR_FONT, GetScript() );
const SvxFontItem &rParentFont = ItemGet<SvxFontItem>(
(const SwTxtFmtColl&)rNd.GetAnyFmtColl(), nFontId);
const SvxFontItem *pFont = &rParentFont;
SfxItemSet aExportSet(*rNd.GetSwAttrSet().GetPool(),
RES_CHRATR_BEGIN, RES_TXTATR_END - 1);
//The hard formatting properties that affect the entire paragraph
if (rNd.HasSwAttrSet())
{
sal_Bool bDeep = sal_False;
// only copy hard attributes - bDeep = false
aExportSet.Set(rNd.GetSwAttrSet(), bDeep);
// get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
const SvxFontItem &rNdFont = ItemGet<SvxFontItem>(rNd.GetSwAttrSet(), nFontId);
pFont = &rNdFont;
aExportSet.ClearItem(nFontId);
}
//The additional hard formatting properties that affect this range in the
//paragraph
sw::PoolItems aRangeItems;
if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
{
for (xub_StrLen i = 0; i < pTxtAttrs->Count(); ++i)
{
const SwTxtAttr* pHt = (*pTxtAttrs)[i];
const xub_StrLen* pEnd = pHt->End();
if (pEnd ? ( nSwPos >= *pHt->GetStart() && nSwPos < *pEnd)
: nSwPos == *pHt->GetStart() )
{
sal_uInt16 nWhich = pHt->GetAttr().Which();
if (nWhich == RES_TXTATR_AUTOFMT)
{
const SwFmtAutoFmt& rAutoFmt = static_cast<const SwFmtAutoFmt&>(pHt->GetAttr());
const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle();
SfxWhichIter aIter( *pSet );
const SfxPoolItem* pItem;
sal_uInt16 nWhichId = aIter.FirstWhich();
while( nWhichId )
{
if( SFX_ITEM_SET == pSet->GetItemState( nWhichId, sal_False, &pItem ))
{
if (nWhichId == nFontId)
pFont = &(item_cast<SvxFontItem>(*pItem));
else
aRangeItems[nWhichId] = pItem;
}
nWhichId = aIter.NextWhich();
}
}
else
aRangeItems[nWhich] = (&(pHt->GetAttr()));
}
else if (nSwPos < *pHt->GetStart())
break;
}
}
/*
For #i24291# we need to explictly remove any properties from the
aExportSet which a SwCharFmt would override, we can't rely on word doing
this for us like writer does
*/
const SwFmtCharFmt *pCharFmtItem =
HasItem< SwFmtCharFmt >( aRangeItems, RES_TXTATR_CHARFMT );
if ( pCharFmtItem )
ClearOverridesFromSet( *pCharFmtItem, aExportSet );
sw::PoolItems aExportItems;
GetPoolItems( aExportSet, aExportItems, false );
sw::cPoolItemIter aEnd = aRangeItems.end();
for ( sw::cPoolItemIter aI = aRangeItems.begin(); aI != aEnd; ++aI )
aExportItems[aI->first] = aI->second;
if ( !aExportItems.empty() )
{
const SwModify* pOldMod = m_rExport.pOutFmtNode;
m_rExport.pOutFmtNode = &rNd;
m_rExport.m_aCurrentCharPropStarts.push( nSwPos );
m_rExport.ExportPoolItemsToCHP( aExportItems, GetScript() );
// HasTextItem nur in dem obigen Bereich erlaubt
m_rExport.m_aCurrentCharPropStarts.pop();
m_rExport.pOutFmtNode = pOldMod;
}
ASSERT( pFont, "must be *some* font associated with this txtnode" );
if ( pFont )
{
SvxFontItem aFont( *pFont );
/*
If we are a nonunicode aware format then we set the charset we want to
use for export of this range. If necessary this will generate a pseudo
font to use for this range.
So now we are guaranteed to have a font with the correct charset set
for WW6/95 which will match the script we have exported this range in,
this makes older nonunicode aware versions of word display the correct
characters.
*/
if ( !m_rExport.HackIsWW8OrHigher() )
aFont.SetCharSet( GetCharSet() );
if ( rParentFont != aFont )
m_rExport.AttrOutput().OutputItem( aFont );
}
}
void WW8SwAttrIter::OutFlys(xub_StrLen nSwPos)
{
/*
#i2916#
May have an anchored graphic to be placed, loop through sorted array
and output all at this position
*/
while ( maFlyIter != maFlyFrms.end() )
{
const SwPosition &rAnchor = maFlyIter->GetPosition();
xub_StrLen nPos = rAnchor.nContent.GetIndex();
if ( nPos != nSwPos )
break;
else
{
m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter );
++maFlyIter;
}
}
}
bool WW8SwAttrIter::IsTxtAttr( xub_StrLen nSwPos )
{
// search for attrs with dummy character or content
if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
{
for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i)
{
const SwTxtAttr* pHt = (*pTxtAttrs)[i];
if ( ( pHt->HasDummyChar() || pHt->HasContent() )
&& (*pHt->GetStart() == nSwPos) )
{
return true;
}
}
}
return false;
}
bool WW8SwAttrIter::IsDropCap( int nSwPos )
{
// see if the current position falls on a DropCap
int nDropChars = mrSwFmtDrop.GetChars();
bool bWholeWord = mrSwFmtDrop.GetWholeWord();
if (bWholeWord)
{
short nWordLen = rNd.GetDropLen(0);
if(nSwPos == nWordLen && nSwPos != 0)
return true;
}
else
{
if (nSwPos == nDropChars && nSwPos != 0)
return true;
}
return false;
}
bool WW8SwAttrIter::RequiresImplicitBookmark()
{
SwImplBookmarksIter bkmkIterEnd = m_rExport.maImplicitBookmarks.end();
for ( SwImplBookmarksIter aIter = m_rExport.maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter )
{
sal_uLong sample = aIter->second;
if ( sample == rNd.GetIndex() )
return true;
}
return false;
}
// HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
// und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
// die dann ueber HasItem() nach anderen Items an der
// Attribut-Anfangposition fragen kann.
// Es koennen nur Attribute mit Ende abgefragt werden.
// Es wird mit bDeep gesucht
const SfxPoolItem* WW8SwAttrIter::HasTextItem( sal_uInt16 nWhich ) const
{
const SfxPoolItem* pRet = 0;
const SwpHints* pTxtAttrs = rNd.GetpSwpHints();
if (pTxtAttrs)
{
xub_StrLen nTmpSwPos = m_rExport.m_aCurrentCharPropStarts.size() ?
m_rExport.m_aCurrentCharPropStarts.top() : 0;
for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i)
{
const SwTxtAttr* pHt = (*pTxtAttrs)[i];
const SfxPoolItem* pItem = &pHt->GetAttr();
const xub_StrLen* pAtrEnd = 0;
if( 0 != ( pAtrEnd = pHt->End() ) && // nur Attr mit Ende
nWhich == pItem->Which() && //
nTmpSwPos >= *pHt->GetStart() && nTmpSwPos < *pAtrEnd )
{
pRet = pItem; // gefunden
break;
}
else if (nTmpSwPos < *pHt->GetStart())
break; // dann kommt da nichts mehr
}
}
return pRet;
}
void WW8Export::GetCurrentItems(WW8Bytes& rItems) const
{
sal_uInt16 nEnd = pO ? pO->Count() : 0;
for (sal_uInt16 nI = 0; nI < nEnd; ++nI)
rItems.Insert((*pO)[nI], rItems.Count());
}
const SfxPoolItem& WW8SwAttrIter::GetItem(sal_uInt16 nWhich) const
{
const SfxPoolItem* pRet = HasTextItem(nWhich);
return pRet ? *pRet : rNd.SwCntntNode::GetAttr(nWhich);
}
void WW8AttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )
{
String aStr( FieldString( ww::eEQ ) );
aStr.APPEND_CONST_ASC( "\\* jc" );
sal_Int32 nJC = 0;
sal_Char cDirective = 0;
switch ( rRuby.GetAdjustment() )
{
case 0:
nJC = 3;
cDirective = 'l';
break;
case 1:
//defaults to 0
break;
case 2:
nJC = 4;
cDirective = 'r';
break;
case 3:
nJC = 1;
cDirective = 'd';
break;
case 4:
nJC = 2;
cDirective = 'd';
break;
default:
ASSERT( !this,"Unhandled Ruby justication code" );
break;
}
aStr += String::CreateFromInt32( nJC );
/*
MS needs to know the name and size of the font used in the ruby item,
but we coud have written it in a mixture of asian and western
scripts, and each of these can be a different font and size than the
other, so we make a guess based upon the first character of the text,
defaulting to asian.
*/
sal_uInt16 nRubyScript;
if( pBreakIt->GetBreakIter().is() )
nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rRuby.GetText(), 0);
else
nRubyScript = i18n::ScriptType::ASIAN;
const SwTxtRuby* pRubyTxt = rRuby.GetTxtRuby();
const SwCharFmt* pFmt = pRubyTxt ? pRubyTxt->GetCharFmt() : 0;
String sFamilyName;
long nHeight;
if ( pFmt )
{
const SvxFontItem &rFont = ItemGet< SvxFontItem >( *pFmt,
GetWhichOfScript(RES_CHRATR_FONT,nRubyScript) );
sFamilyName = rFont.GetFamilyName();
const SvxFontHeightItem &rHeight = ItemGet< SvxFontHeightItem >( *pFmt,
GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
nHeight = rHeight.GetHeight();
}
else
{
/*Get defaults if no formatting on ruby text*/
const SfxItemPool *pPool = rNode.GetSwAttrSet().GetPool();
const SfxItemPool &rPool = pPool ? *pPool : m_rWW8Export.pDoc->GetAttrPool();
const SvxFontItem &rFont = DefaultItemGet< SvxFontItem >( rPool,
GetWhichOfScript( RES_CHRATR_FONT,nRubyScript ) );
sFamilyName = rFont.GetFamilyName();
const SvxFontHeightItem &rHeight = DefaultItemGet< SvxFontHeightItem >
( rPool, GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
nHeight = rHeight.GetHeight();
}
nHeight = (nHeight + 5)/10;
aStr.APPEND_CONST_ASC( " \\* \"Font:" );
aStr.Append( sFamilyName );
aStr.APPEND_CONST_ASC( "\" \\* hps" );
aStr += String::CreateFromInt32( nHeight );
aStr.APPEND_CONST_ASC( " \\o" );
if ( cDirective )
{
aStr.APPEND_CONST_ASC( "\\a" );
aStr.Append( cDirective );
}
aStr.APPEND_CONST_ASC( "(\\s\\up " );
if ( pBreakIt->GetBreakIter().is() )
nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rNode.GetTxt(),
*( pRubyTxt->GetStart() ) );
else
nRubyScript = i18n::ScriptType::ASIAN;
const SwAttrSet& rSet = rNode.GetSwAttrSet();
const SvxFontHeightItem &rHeightItem =
( const SvxFontHeightItem& )rSet.Get(
GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
nHeight = (rHeightItem.GetHeight() + 10)/20-1;
aStr += String::CreateFromInt32(nHeight);
aStr += '(';
aStr += rRuby.GetText();
aStr.APPEND_CONST_ASC( ");" );
m_rWW8Export.OutputField( 0, ww::eEQ, aStr,
WRITEFIELD_START | WRITEFIELD_CMD_START );
}
void WW8AttributeOutput::EndRuby()
{
m_rWW8Export.WriteChar( ')' );
m_rWW8Export.OutputField( 0, ww::eEQ, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE );
}
/*#i15387# Better ideas welcome*/
String &TruncateBookmark( String &rRet )
{
if ( rRet.Len() > 40 )
rRet.Erase( 40 );
ASSERT( rRet.Len() <= 40, "Word cannot have bookmarks longer than 40 chars" );
return rRet;
}
bool AttributeOutputBase::AnalyzeURL( const String& rUrl, const String& /*rTarget*/, String* pLinkURL, String* pMark )
{
bool bBookMarkOnly = false;
INetURLObject aURL( rUrl );
String sMark;
String sURL;
if ( rUrl.Len() > 1 && rUrl.GetChar(0) == INET_MARK_TOKEN )
{
sMark = BookmarkToWriter( rUrl.Copy(1) );
xub_StrLen nPos = sMark.SearchBackward( cMarkSeperator );
String sRefType( sMark.Copy( nPos+1 ) );
sRefType.EraseAllChars();
// i21465 Only interested in outline references
if ( sRefType.EqualsAscii( pMarkToOutline ) )
{
String sLink = sMark.Copy(0, nPos);
SwImplBookmarksIter bkmkIterEnd = GetExport().maImplicitBookmarks.end();
for ( SwImplBookmarksIter aIter = GetExport().maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter )
{
String bkmkName = aIter->first;
if ( bkmkName == sLink )
{
sMark = String( RTL_CONSTASCII_STRINGPARAM( "_toc" ) );
sMark += String::CreateFromInt32( aIter->second );
}
}
}
}
else
{
sURL = aURL.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS );
sMark = aURL.GetMark( INetURLObject::DECODE_UNAMBIGUOUS );
}
if ( sMark.Len() && !sURL.Len() )
bBookMarkOnly = true;
*pMark = sMark;
*pLinkURL = sURL;
return bBookMarkOnly;
}
bool WW8AttributeOutput::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;
if ( sURL.Len() )
sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
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 WW8AttributeOutput::StartURL( const String &rUrl, const String &rTarget )
{
// hyperlinks only in WW8
if ( !m_rWW8Export.bWrtWW8 )
return false;
INetURLObject aURL( rUrl );
String sURL;
String sMark;
bool bBookMarkOnly = AnalyzeURL( rUrl, rTarget, &sURL, &sMark );
m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_START | WRITEFIELD_CMD_START );
// write the refence to the "picture" structure
sal_uLong nDataStt = m_rWW8Export.pDataStrm->Tell();
m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() );
// WinWord 2000 doesn't write this - so its a temp solution by W97 ?
m_rWW8Export.WriteChar( 0x01 );
static sal_uInt8 aArr1[] = {
0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
0x06, 0x08, 0x01, // sprmCFData
0x55, 0x08, 0x01, // sprmCFSpec
0x02, 0x08, 0x01 // sprmCFFldVanish
};
sal_uInt8* pDataAdr = aArr1 + 2;
Set_UInt32( pDataAdr, nDataStt );
m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), sizeof( aArr1 ), aArr1 );
m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_CMD_END );
// now write the picture structur
sURL = aURL.GetURLNoMark();
//all links end up in the data stream as absolute references.
bool bAbsolute = !bBookMarkOnly;
static sal_uInt8 __READONLY_DATA aURLData1[] = {
0,0,0,0, // len of struct
0x44,0, // the start of "next" data
0,0,0,0,0,0,0,0,0,0, // PIC-Structure!
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
0,0,0,0, // /
};
static sal_uInt8 __READONLY_DATA MAGIC_A[] = {
// start of "next" data
0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
};
m_rWW8Export.pDataStrm->Write( aURLData1, sizeof( aURLData1 ) );
sal_uInt8 nAnchor = 0x00;
if ( sMark.Len() )
nAnchor = 0x08;
m_rWW8Export.pDataStrm->Write( &nAnchor, 1 );
m_rWW8Export.pDataStrm->Write( MAGIC_A, sizeof(MAGIC_A) );
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 0x00000002);
sal_uInt32 nFlag = bBookMarkOnly ? 0 : 0x01;
if ( bAbsolute )
nFlag |= 0x02;
if ( sMark.Len() )
nFlag |= 0x08;
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nFlag );
INetProtocol eProto = aURL.GetProtocol();
if ( eProto == INET_PROT_FILE )
{
// version 1 (for a document)
static sal_uInt8 __READONLY_DATA MAGIC_C[] = {
0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
0x00, 0x00
};
static sal_uInt8 __READONLY_DATA MAGIC_D[] = {
0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// save the links to files as relative
sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
if ( sURL.EqualsAscii( "/", 0, 1 ) )
sURL = aURL.PathToFileName();
// special case for the absolute windows names
// (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
sal_Unicode aDrive = ( sURL.Len() > 1 )? sURL.GetChar( 1 ): 0;
if ( sURL.EqualsAscii( "/", 0, 1 ) &&
( ( aDrive >= 'A' && aDrive <= 'Z' ) || ( aDrive >= 'a' && aDrive <= 'z' ) ) &&
sURL.EqualsAscii( ":", 2, 1 ) )
{
sURL.Erase( 0, 1 );
sURL.SearchAndReplaceAll( '/', '\\' );
}
m_rWW8Export.pDataStrm->Write( MAGIC_C, sizeof(MAGIC_C) );
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sURL.Len()+1 );
SwWW8Writer::WriteString8( *m_rWW8Export.pDataStrm, sURL, true,
RTL_TEXTENCODING_MS_1252 );
m_rWW8Export.pDataStrm->Write( MAGIC_D, sizeof( MAGIC_D ) );
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.Len() + 6 );
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.Len() );
SwWW8Writer::WriteShort( *m_rWW8Export.pDataStrm, 3 );
SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, false );
}
else if ( eProto != INET_PROT_NOT_VALID )
{
// version 2 (simple url)
// an write some data to the data stream, but dont ask
// what the data mean, except for the URL.
// The First piece is the WW8_PIC structure.
//
static sal_uInt8 __READONLY_DATA MAGIC_B[] = {
0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
};
m_rWW8Export.pDataStrm->Write( MAGIC_B, sizeof(MAGIC_B) );
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2 * ( sURL.Len() + 1 ) );
SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, true );
}
if ( sMark.Len() )
{
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sMark.Len()+1 );
SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sMark, true );
}
SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nDataStt,
m_rWW8Export.pDataStrm->Tell() - nDataStt );
return true;
}
bool WW8AttributeOutput::EndURL()
{
// hyperlinks only in WW8
if ( !m_rWW8Export.bWrtWW8 )
return false;
m_rWW8Export.OutputField( 0, ww::eHYPERLINK, aEmptyStr, WRITEFIELD_CLOSE );
return true;
}
String BookmarkToWord(const String &rBookmark)
{
String sRet(INetURLObject::encode(rBookmark,
INetURLObject::PART_REL_SEGMENT_EXTRA, '%',
INetURLObject::ENCODE_ALL, RTL_TEXTENCODING_ASCII_US));
return TruncateBookmark(sRet);
}
String BookmarkToWriter(const String &rBookmark)
{
return INetURLObject::decode(rBookmark, '%',
INetURLObject::DECODE_UNAMBIGUOUS, RTL_TEXTENCODING_ASCII_US);
}
void WW8SwAttrIter::OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool)
{
if ( m_rExport.HasRefToObject( REF_SETREFATTR, &rAttr.GetRefName(), 0 ) )
m_rExport.AppendBookmark( m_rExport.GetBookmarkName( REF_SETREFATTR,
&rAttr.GetRefName(), 0 ));
}
void WW8AttributeOutput::FieldVanish( const String& rTxt, ww::eField /*eType*/ )
{
WW8Bytes aItems;
m_rWW8Export.GetCurrentItems( aItems );
// sprmCFFldVanish
if ( m_rWW8Export.bWrtWW8 )
SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish );
else
aItems.Insert( 67, aItems.Count() );
aItems.Insert( 1, aItems.Count() );
sal_uInt16 nStt_sprmCFSpec = aItems.Count();
// sprmCFSpec -- fSpec-Attribut true
if ( m_rWW8Export.bWrtWW8 )
SwWW8Writer::InsUInt16( aItems, 0x855 );
else
aItems.Insert( 117, aItems.Count() );
aItems.Insert( 1, aItems.Count() );
m_rWW8Export.WriteChar( '\x13' );
m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(),
aItems.GetData() );
m_rWW8Export.OutSwString( rTxt, 0, rTxt.Len(), m_rWW8Export.IsUnicode(),
RTL_TEXTENCODING_MS_1252 );
m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), nStt_sprmCFSpec,
aItems.GetData() );
m_rWW8Export.WriteChar( '\x15' );
m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(),
aItems.GetData() );
}
void AttributeOutputBase::TOXMark( const SwTxtNode& rNode, const SwTOXMark& rAttr )
{
// its a field; so get the Text form the Node and build the field
String sTxt;
ww::eField eType = ww::eNONE;
const SwTxtTOXMark& rTxtTOXMark = *rAttr.GetTxtTOXMark();
const xub_StrLen* pTxtEnd = rTxtTOXMark.End();
if ( pTxtEnd ) // has range?
{
sTxt = rNode.GetExpandTxt( *rTxtTOXMark.GetStart(),
*pTxtEnd - *rTxtTOXMark.GetStart() );
}
else
sTxt = rAttr.GetAlternativeText();
switch ( rAttr.GetTOXType()->GetType() )
{
case TOX_INDEX:
eType = ww::eXE;
if ( rAttr.GetPrimaryKey().Len() )
{
if ( rAttr.GetSecondaryKey().Len() )
{
sTxt.Insert( ':', 0 );
sTxt.Insert( rAttr.GetSecondaryKey(), 0 );
}
sTxt.Insert( ':', 0 );
sTxt.Insert( rAttr.GetPrimaryKey(), 0 );
}
sTxt.InsertAscii( " XE \"", 0 );
sTxt.InsertAscii( "\" " );
break;
case TOX_USER:
( sTxt.APPEND_CONST_ASC( "\" \\f \"" ) )
+= (sal_Char)( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) );
// fall through - no break;
case TOX_CONTENT:
{
eType = ww::eTC;
sTxt.InsertAscii( " TC \"", 0 );
sal_uInt16 nLvl = rAttr.GetLevel();
if (nLvl > WW8ListManager::nMaxLevel)
nLvl = WW8ListManager::nMaxLevel;
((sTxt.APPEND_CONST_ASC( "\" \\l " ))
+= String::CreateFromInt32( nLvl )) += ' ';
}
break;
default:
ASSERT( !this, "Unhandled option for toc export" );
break;
}
if ( sTxt.Len() )
FieldVanish( sTxt, eType );
}
int WW8SwAttrIter::OutAttrWithRange(xub_StrLen nPos)
{
int nRet = 0;
if ( const SwpHints* pTxtAttrs = rNd.GetpSwpHints() )
{
m_rExport.m_aCurrentCharPropStarts.push( nPos );
const xub_StrLen* pEnd;
for ( sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i )
{
const SwTxtAttr* pHt = (*pTxtAttrs)[i];
const SfxPoolItem* pItem = &pHt->GetAttr();
switch ( pItem->Which() )
{
case RES_TXTATR_INETFMT:
if ( nPos == *pHt->GetStart() )
{
const SwFmtINetFmt *rINet = static_cast< const SwFmtINetFmt* >( pItem );
if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) )
++nRet;
}
if ( 0 != ( pEnd = pHt->End() ) && nPos == *pEnd )
{
if ( m_rExport.AttrOutput().EndURL() )
--nRet;
}
break;
case RES_TXTATR_REFMARK:
if ( nPos == *pHt->GetStart() )
{
OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), true );
++nRet;
}
if ( 0 != ( pEnd = pHt->End() ) && nPos == *pEnd )
{
OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), false );
--nRet;
}
break;
case RES_TXTATR_TOXMARK:
if ( nPos == *pHt->GetStart() )
m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) );
break;
case RES_TXTATR_CJK_RUBY:
if ( nPos == *pHt->GetStart() )
{
m_rExport.AttrOutput().StartRuby( rNd, *static_cast< const SwFmtRuby* >( pItem ) );
++nRet;
}
if ( 0 != ( pEnd = pHt->End() ) && nPos == *pEnd )
{
m_rExport.AttrOutput().EndRuby();
--nRet;
}
break;
}
}
m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem nur in dem obigen Bereich erlaubt
}
return nRet;
}
bool WW8SwAttrIter::IsRedlineAtEnd( xub_StrLen nEnd ) const
{
bool bRet = false;
// search next Redline
for( sal_uInt16 nPos = nCurRedlinePos;
nPos < m_rExport.pDoc->GetRedlineTbl().Count(); ++nPos )
{
const SwPosition* pEnd = m_rExport.pDoc->GetRedlineTbl()[ nPos ]->End();
if( pEnd->nNode == rNd )
{
if( pEnd->nContent.GetIndex() == nEnd )
{
bRet = true;
break;
}
}
else
break;
}
return bRet;
}
const SwRedlineData* WW8SwAttrIter::GetRedline( xub_StrLen nPos )
{
if( pCurRedline )
{
const SwPosition* pEnd = pCurRedline->End();
if( pEnd->nNode == rNd &&
pEnd->nContent.GetIndex() <= nPos )
{
pCurRedline = 0;
++nCurRedlinePos;
}
else
{
// write data of current redline
return &( pCurRedline->GetRedlineData() );
}
}
if( !pCurRedline )
{
// search next Redline
for( ; nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count();
++nCurRedlinePos )
{
const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nCurRedlinePos ];
const SwPosition* pStt = pRedl->Start();
const SwPosition* pEnd = pStt == pRedl->GetPoint()
? pRedl->GetMark()
: pRedl->GetPoint();
if( pStt->nNode == rNd )
{
if( pStt->nContent.GetIndex() >= nPos )
{
if( pStt->nContent.GetIndex() == nPos )
{
// write data of this redline
pCurRedline = pRedl;
return &( pCurRedline->GetRedlineData() );
}
break;
}
}
else
break;
if( pEnd->nNode == rNd &&
pEnd->nContent.GetIndex() < nPos )
{
pCurRedline = pRedl;
break;
}
}
}
return NULL;
}
/* */
short MSWordExportBase::GetCurrentPageDirection() const
{
const SwFrmFmt &rFmt = pAktPageDesc
? pAktPageDesc->GetMaster()
: const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 ).GetMaster();
return rFmt.GetFrmDir().GetValue();
}
short MSWordExportBase::GetDefaultFrameDirection( ) const
{
short nDir = FRMDIR_ENVIRONMENT;
if ( bOutPageDescs )
nDir = GetCurrentPageDirection( );
else if ( pOutFmtNode )
{
if ( bOutFlyFrmAttrs ) //frame
{
nDir = TrueFrameDirection( *( const SwFrmFmt * ) pOutFmtNode );
}
else if ( pOutFmtNode->ISA( SwCntntNode ) ) //pagagraph
{
const SwCntntNode *pNd = ( const SwCntntNode * ) pOutFmtNode;
SwPosition aPos( *pNd );
nDir = pDoc->GetTextDirection( aPos );
}
else if ( pOutFmtNode->ISA( SwTxtFmtColl ) )
nDir = FRMDIR_HORI_LEFT_TOP; //what else can we do :-(
}
if ( nDir == FRMDIR_ENVIRONMENT )
nDir = FRMDIR_HORI_LEFT_TOP; //Set something
return nDir;
}
short MSWordExportBase::TrueFrameDirection( const SwFrmFmt &rFlyFmt ) const
{
const SwFrmFmt *pFlyFmt = &rFlyFmt;
const SvxFrameDirectionItem* pItem = 0;
while ( pFlyFmt )
{
pItem = &pFlyFmt->GetFrmDir();
if ( FRMDIR_ENVIRONMENT == pItem->GetValue() )
{
pItem = 0;
const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
pAnchor->GetCntntAnchor() )
{
pFlyFmt = pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
}
else
pFlyFmt = 0;
}
else
pFlyFmt = 0;
}
short nRet;
if ( pItem )
nRet = pItem->GetValue();
else
nRet = GetCurrentPageDirection();
ASSERT( nRet != FRMDIR_ENVIRONMENT, "leaving with environment direction" );
return nRet;
}
const SvxBrushItem* WW8Export::GetCurrentPageBgBrush() const
{
const SwFrmFmt &rFmt = pAktPageDesc
? pAktPageDesc->GetMaster()
: const_cast<const SwDoc *>(pDoc)->GetPageDesc(0).GetMaster();
const SfxPoolItem* pItem = 0;
//If not set, or "no fill", get real bg
SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true, &pItem);
const SvxBrushItem* pRet = (const SvxBrushItem*)pItem;
if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() &&
pRet->GetColor() == COL_TRANSPARENT))
{
pRet = &(DefaultItemGet<SvxBrushItem>(*pDoc,RES_BACKGROUND));
}
return pRet;
}
SvxBrushItem WW8Export::TrueFrameBgBrush(const SwFrmFmt &rFlyFmt) const
{
const SwFrmFmt *pFlyFmt = &rFlyFmt;
const SvxBrushItem* pRet = 0;
while (pFlyFmt)
{
//If not set, or "no fill", get real bg
const SfxPoolItem* pItem = 0;
SfxItemState eState =
pFlyFmt->GetItemState(RES_BACKGROUND, true, &pItem);
pRet = (const SvxBrushItem*)pItem;
if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() &&
pRet->GetColor() == COL_TRANSPARENT))
{
pRet = 0;
const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
pAnchor->GetCntntAnchor())
{
pFlyFmt =
pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
}
else
pFlyFmt = 0;
}
else
pFlyFmt = 0;
}
if (!pRet)
pRet = GetCurrentPageBgBrush();
const Color aTmpColor( COL_WHITE );
SvxBrushItem aRet( aTmpColor, RES_BACKGROUND );
if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
aRet = *pRet;
return aRet;
}
/*
Convert characters that need to be converted, the basic replacements and the
ridicously complicated title case attribute mapping to hardcoded upper case
because word doesn't have the feature
*/
String WW8SwAttrIter::GetSnippet(const String &rStr, xub_StrLen nAktPos,
xub_StrLen nLen) const
{
String aSnippet(rStr, nAktPos, nLen);
if (!nLen)
return aSnippet;
// 0x0a ( Hard Line Break ) -> 0x0b
// 0xad ( soft hyphen ) -> 0x1f
// 0x2011 ( hard hyphen ) -> 0x1e
aSnippet.SearchAndReplaceAll(0x0A, 0x0B);
aSnippet.SearchAndReplaceAll(CHAR_HARDHYPHEN, 0x1e);
aSnippet.SearchAndReplaceAll(CHAR_SOFTHYPHEN, 0x1f);
m_rExport.m_aCurrentCharPropStarts.push( nAktPos );
const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP);
if (SVX_CASEMAP_TITEL == ((const SvxCaseMapItem&)rItem).GetValue())
{
sal_uInt16 nScriptType = i18n::ScriptType::LATIN;
if (pBreakIt->GetBreakIter().is())
nScriptType = pBreakIt->GetBreakIter()->getScriptType(aSnippet, 0);
LanguageType nLanguage;
switch (nScriptType)
{
case i18n::ScriptType::ASIAN:
nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CJK_LANGUAGE)).GetLanguage();
break;
case i18n::ScriptType::COMPLEX:
nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage();
break;
case i18n::ScriptType::LATIN:
default:
nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_LANGUAGE)).GetLanguage();
break;
}
SvxFont aFontHelper;
aFontHelper.SetCaseMap(SVX_CASEMAP_TITEL);
aFontHelper.SetLanguage(nLanguage);
aSnippet = aFontHelper.CalcCaseMap(aSnippet);
//If we weren't at the begin of a word undo the case change.
//not done before doing the casemap because the sequence might start
//with whitespace
if (pBreakIt->GetBreakIter().is() && !pBreakIt->GetBreakIter()->isBeginWord(
rStr, nAktPos, pBreakIt->GetLocale(nLanguage),
i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
{
aSnippet.SetChar(0, rStr.GetChar(nAktPos));
}
}
m_rExport.m_aCurrentCharPropStarts.pop();
return aSnippet;
}
/** Delivers the right paragraph style
Because of the different style handling for delete operations,
the track changes have to be analysed. A deletion, starting in paragraph A
with style A, ending in paragraph B with style B, needs a hack.
*/
static SwTxtFmtColl& lcl_getFormatCollection( MSWordExportBase& rExport, const SwTxtNode* pTxtNode )
{
sal_uInt16 nPos = 0;
sal_uInt16 nMax = rExport.pDoc->GetRedlineTbl().Count();
while( nPos < nMax )
{
const SwRedline* pRedl = rExport.pDoc->GetRedlineTbl()[ nPos++ ];
const SwPosition* pStt = pRedl->Start();
const SwPosition* pEnd = pStt == pRedl->GetPoint()
? pRedl->GetMark()
: pRedl->GetPoint();
// Looking for deletions, which ends in current pTxtNode
if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetRedlineData().GetType() &&
pEnd->nNode == *pTxtNode && pStt->nNode != *pTxtNode &&
pStt->nNode.GetNode().IsTxtNode() )
{
pTxtNode = pStt->nNode.GetNode().GetTxtNode();
nMax = nPos;
nPos = 0;
}
}
return static_cast<SwTxtFmtColl&>( pTxtNode->GetAnyFmtColl() );
}
void WW8AttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop &rSwFmtDrop, sal_uInt16 nStyle,
ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
{
short nDropLines = rSwFmtDrop.GetLines();
short nDistance = rSwFmtDrop.GetDistance();
int rFontHeight, rDropHeight, rDropDescent;
SVBT16 nSty;
ShortToSVBT16( nStyle, nSty );
m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style #
if ( m_rWW8Export.bWrtWW8 )
{
m_rWW8Export.InsUInt16( NS_sprm::LN_PPc ); // Alignment (sprmPPc)
m_rWW8Export.pO->Insert( 0x20, m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt16( NS_sprm::LN_PWr ); // Wrapping (sprmPWr)
m_rWW8Export.pO->Insert( 0x02, m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt16( NS_sprm::LN_PDcs ); // Dropcap (sprmPDcs)
int nDCS = ( nDropLines << 3 ) | 0x01;
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText ); // Distance from text (sprmPDxaFromText)
m_rWW8Export.InsUInt16( nDistance );
if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
{
m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaLine ); // Line spacing
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
m_rWW8Export.InsUInt16( 0 );
}
}
else
{
m_rWW8Export.pO->Insert( 29, m_rWW8Export.pO->Count() ); // Alignment (sprmPPc)
m_rWW8Export.pO->Insert( 0x20, m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( 37, m_rWW8Export.pO->Count() ); // Wrapping (sprmPWr)
m_rWW8Export.pO->Insert( 0x02, m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( 46, m_rWW8Export.pO->Count() ); // Dropcap (sprmPDcs)
int nDCS = ( nDropLines << 3 ) | 0x01;
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
m_rWW8Export.pO->Insert( 49, m_rWW8Export.pO->Count() ); // Distance from text (sprmPDxaFromText)
m_rWW8Export.InsUInt16( nDistance );
if (rNode.GetDropSize(rFontHeight, rDropHeight, rDropDescent))
{
m_rWW8Export.pO->Insert( 20, m_rWW8Export.pO->Count() ); // Line spacing
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
m_rWW8Export.InsUInt16( 0 );
}
}
m_rWW8Export.WriteCR( pTextNodeInfoInner );
if ( pTextNodeInfo.get() != NULL )
{
#ifdef DEBUG
::std::clog << pTextNodeInfo->toString() << ::std::endl;
#endif
TableInfoCell( pTextNodeInfoInner );
}
m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );
if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
{
if ( m_rWW8Export.bWrtWW8 )
{
const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
if ( pSwCharFmt )
{
m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) );
}
m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsPos ); // Lower the chars
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
m_rWW8Export.InsUInt16( NS_sprm::LN_CHps ); // Font Size
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
}
else
{
const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
if ( pSwCharFmt )
{
m_rWW8Export.InsUInt16( 80 );
m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) );
}
m_rWW8Export.pO->Insert( 101, m_rWW8Export.pO->Count() ); // Lower the chars
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
m_rWW8Export.pO->Insert( 99, m_rWW8Export.pO->Count() ); // Font Size
m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
}
}
m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );
}
xub_StrLen MSWordExportBase::GetNextPos( WW8SwAttrIter* aAttrIter, const SwTxtNode& rNode, xub_StrLen nAktPos )
{
// Get the bookmarks for the normal run
xub_StrLen nNextPos = aAttrIter->WhereNext();
xub_StrLen nNextBookmark = nNextPos;
if( nNextBookmark > nAktPos )//no need to search for bookmarks otherwise
{
GetSortedBookmarks( rNode, nAktPos, nNextBookmark - nAktPos );
NearestBookmark( nNextBookmark, nAktPos, false );
}
return std::min( nNextPos, nNextBookmark );
}
void MSWordExportBase::UpdatePosition( WW8SwAttrIter* aAttrIter, xub_StrLen nAktPos, xub_StrLen /*nEnd*/ )
{
xub_StrLen nNextPos;
// go to next attribute if no bookmark is found and if the next attribute position if at the current position
bool bNextBookmark = NearestBookmark( nNextPos, nAktPos, true );
if( !bNextBookmark && nAktPos >= aAttrIter->WhereNext() )
aAttrIter->NextPos();
}
bool MSWordExportBase::GetBookmarks(
const SwTxtNode& rNd,
const xub_StrLen nStt,
const xub_StrLen nEnd,
IMarkVector& rArr )
{
IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
sal_uLong nNd = rNd.GetIndex( );
const sal_Int32 nMarks = pMarkAccess->getAllMarksCount();
for ( sal_Int32 i = 0; i < nMarks; i++ )
{
IMark* pMark = ( pMarkAccess->getAllMarksBegin() + i )->get();
if ( IDocumentMarkAccess::GetType( *(pMark) ) == IDocumentMarkAccess::ANNOTATIONMARK )
{
continue;
}
// Only keep the bookmarks starting or ending in this node
if ( pMark->GetMarkStart().nNode == nNd ||
pMark->GetMarkEnd().nNode == nNd )
{
// Keep only the bookmarks starting or ending in the snippet
const xub_StrLen nBStart = pMark->GetMarkStart().nContent.GetIndex();
const bool bIsStartOk = ( pMark->GetMarkStart().nNode == nNd ) && ( nBStart >= nStt ) && ( nBStart <= nEnd );
const xub_StrLen nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
const bool bIsEndOk = ( pMark->GetMarkEnd().nNode == nNd ) && ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
if ( bIsStartOk || bIsEndOk )
{
rArr.push_back( pMark );
}
}
}
return ( rArr.size() > 0 );
}
class CompareMarksEnd : public std::binary_function < const IMark *, const IMark *, bool >
{
public:
inline bool operator() ( const IMark * pOneB, const IMark * pTwoB ) const
{
xub_StrLen nOEnd = pOneB->GetMarkEnd().nContent.GetIndex();
xub_StrLen nTEnd = pTwoB->GetMarkEnd().nContent.GetIndex();
return nOEnd < nTEnd;
}
};
bool MSWordExportBase::NearestBookmark( xub_StrLen& rNearest, const xub_StrLen nAktPos, bool bNextPositionOnly )
{
bool bHasBookmark = false;
if ( m_rSortedMarksStart.size( ) > 0 )
{
IMark* pMarkStart = m_rSortedMarksStart.front();
xub_StrLen nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
if( !bNextPositionOnly || (nNext > nAktPos ))
{
rNearest = nNext;
bHasBookmark = true;
}
}
if ( m_rSortedMarksEnd.size( ) > 0 )
{
IMark* pMarkEnd = m_rSortedMarksEnd[0];
xub_StrLen nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
if( !bNextPositionOnly || nNext > nAktPos )
{
if ( !bHasBookmark )
rNearest = nNext;
else
rNearest = std::min( rNearest, nNext );
bHasBookmark = true;
}
}
return bHasBookmark;
}
void MSWordExportBase::GetSortedBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
{
IMarkVector aMarksStart;
if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarksStart ) )
{
IMarkVector aSortedEnd;
IMarkVector aSortedStart;
for ( IMarkVector::const_iterator it = aMarksStart.begin(), end = aMarksStart.end();
it < end; ++it )
{
IMark* pMark = (*it);
// Remove the positions egals to the current pos
xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
if ( nStart > nAktPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
aSortedStart.push_back( pMark );
if ( nEnd > nAktPos && nEnd <= ( nAktPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
aSortedEnd.push_back( pMark );
}
// Sort the bookmarks by end position
std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
m_rSortedMarksStart.swap( aSortedStart );
m_rSortedMarksEnd.swap( aSortedEnd );
}
else
{
m_rSortedMarksStart.clear( );
m_rSortedMarksEnd.clear( );
}
}
void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
{
#ifdef DEBUG
::std::clog << "<OutWW8_SwTxtNode>" << ::std::endl;
#endif
ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( mpTableInfo->getTableNodeInfo( &rNode ) );
//For i120928,identify the last node
bool bLastCR = false;
bool bExported = false;
{
SwNodeIndex aNextIdx(rNode,1);
SwNodeIndex aLastIdx(rNode.GetNodes().GetEndOfContent());
if (aNextIdx == aLastIdx)
bLastCR = true;
}
AttrOutput().StartParagraph( pTextNodeInfo );
bool bFlyInTable = mpParentFrame && IsInTable();
if ( !bFlyInTable )
nStyleBeforeFly = GetId( lcl_getFormatCollection( *this, &rNode ) );
// nStyleBeforeFly may change when we recurse into another node, so we
// have to remember it in nStyle
sal_uInt16 nStyle = nStyleBeforeFly;
WW8SwAttrIter aAttrIter( *this, rNode );
rtl_TextEncoding eChrSet = aAttrIter.GetCharSet();
if ( bStartTOX )
{
// ignore TOX header section
const SwSectionNode* pSectNd = rNode.FindSectionNode();
if ( pSectNd && TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
{
AttrOutput().StartTOX( pSectNd->GetSection() );
m_aCurrentCharPropStarts.push( 0 );
}
}
const SwSection* pTOXSect = 0;
if( bInWriteTOX )
{
// check for end of TOX
SwNodeIndex aIdx( rNode, 1 );
if( !aIdx.GetNode().IsTxtNode() )
{
const SwSectionNode* pTOXSectNd = rNode.FindSectionNode();
pTOXSect = &pTOXSectNd->GetSection();
const SwNode* pNxt = rNode.GetNodes().GoNext( &aIdx );
if( pNxt && pNxt->FindSectionNode() == pTOXSectNd )
pTOXSect = 0;
}
}
if ( aAttrIter.RequiresImplicitBookmark() )
{
String sBkmkName = String( RTL_CONSTASCII_STRINGPARAM( "_toc" ) );
sBkmkName += String::CreateFromInt32( rNode.GetIndex() );
AppendWordBookmark( sBkmkName );
}
//Would need to move into WW8Export, probably not worth it
//ASSERT( pO->Count(), " pO ist am Zeilenanfang nicht leer" );
String aStr( rNode.GetTxt() );
xub_StrLen nAktPos = 0;
xub_StrLen const nEnd = aStr.Len();
bool bRedlineAtEnd = false;
int nOpenAttrWithRange = 0;
ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner;
if ( pTextNodeInfo.get() != NULL )
pTextNodeInfoInner = pTextNodeInfo->getFirstInner();
do {
const SwRedlineData* pRedlineData = aAttrIter.GetRedline( nAktPos );
AttrOutput().StartRun( pRedlineData );
xub_StrLen nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos );
if( nNextAttr > nEnd )
nNextAttr = nEnd;
aAttrIter.OutFlys( nAktPos );
//Append bookmarks in this range after flys, exclusive of final
//position of this range
AppendBookmarks( rNode, nAktPos, nNextAttr - nAktPos );
bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nAktPos);
xub_StrLen nLen = nNextAttr - nAktPos;
if ( !bTxtAtr && nLen )
{
sal_Unicode ch = aStr.GetChar( nAktPos );
int ofs = ( ch == CH_TXT_ATR_FIELDSTART || ch == CH_TXT_ATR_FIELDEND || ch == CH_TXT_ATR_FORMELEMENT? 1: 0 );
IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
if ( ch == CH_TXT_ATR_FIELDSTART )
{
SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos + 1 ) );
::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
if ( pFieldmark->GetFieldname().equalsAscii( ODF_FORMTEXT ) )
AppendBookmark( pFieldmark->GetName(), false );
const bool bCommentRange = pFieldmark != NULL && pFieldmark->GetFieldname().equalsAscii( ODF_COMMENTRANGE );
if ( bCommentRange )
{
AttrOutput().WritePostitFieldStart(); // Note: empty for WW8 export
}
else
{
OutputField( NULL, lcl_getFieldId( pFieldmark ), lcl_getFieldCode( pFieldmark ), WRITEFIELD_START | WRITEFIELD_CMD_START );
}
if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) )
WriteFormData( *pFieldmark );
else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) )
WriteHyperlinkData( *pFieldmark );
if ( !bCommentRange )
{
OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CMD_END );
}
}
else if ( ch == CH_TXT_ATR_FIELDEND )
{
SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
if ( pFieldmark && pFieldmark->GetFieldname().equalsAscii( ODF_COMMENTRANGE ) )
{
AttrOutput().WritePostitFieldEnd(); // Note: empty for WW8 export
}
else
{
OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CLOSE );
}
if ( pFieldmark->GetFieldname().equalsAscii( ODF_FORMTEXT ) )
AppendBookmark( pFieldmark->GetName(), false );
}
else if ( ch == CH_TXT_ATR_FORMELEMENT )
{
SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
bool isDropdownOrCheckbox = pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) ||
pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX );
if ( isDropdownOrCheckbox )
AppendBookmark( pFieldmark->GetName(), 0 );
OutputField( NULL, lcl_getFieldId( pFieldmark ),
lcl_getFieldCode( pFieldmark ),
WRITEFIELD_START | WRITEFIELD_CMD_START );
if ( isDropdownOrCheckbox )
WriteFormData( *pFieldmark );
OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CLOSE );
if ( isDropdownOrCheckbox )
AppendBookmark( pFieldmark->GetName(), false );
}
nLen -= static_cast< sal_uInt16 >( ofs );
String aSnippet( aAttrIter.GetSnippet( aStr, nAktPos + static_cast< sal_uInt16 >( ofs ), nLen ) );
if ( ( nTxtTyp == TXT_EDN || nTxtTyp == TXT_FTN ) && nAktPos == 0 && nLen > 0 )
{
// Insert tab for aesthetic puposes #i24762#
if ( aSnippet.GetChar( 0 ) != 0x09 )
aSnippet.Insert( 0x09, 0 );
}
AttrOutput().RunText( aSnippet, eChrSet );
}
if ( aAttrIter.IsDropCap( nNextAttr ) )
AttrOutput().FormatDrop( rNode, aAttrIter.GetSwFmtDrop(), nStyle, pTextNodeInfo, pTextNodeInfoInner );
if (0 != nEnd)
{
// Output the character attributes
// #i51277# do this before writing flys at end of paragraph
AttrOutput().StartRunProperties();
aAttrIter.OutAttr( nAktPos );
AttrOutput().EndRunProperties( pRedlineData );
}
// At the end of line, output the attributes until the CR.
// Exception: footnotes at the end of line
if ( nNextAttr == nEnd )
{
ASSERT( nOpenAttrWithRange >= 0, "odd to see this happening, expected >= 0" );
if ( !bTxtAtr && nOpenAttrWithRange <= 0 )
{
if ( aAttrIter.IsRedlineAtEnd( nEnd ) )
bRedlineAtEnd = true;
else
{
// insert final graphic anchors if any before CR
aAttrIter.OutFlys( nEnd );
// insert final bookmarks if any before CR and after flys
AppendBookmarks( rNode, nEnd, 1 );
if ( pTOXSect )
{
m_aCurrentCharPropStarts.pop();
AttrOutput().EndTOX( *pTOXSect ,false);
}
//For i120928,the position of the bullet's graphic is at end of doc
if (bLastCR && (!bExported))
{
ExportGrfBullet(rNode);
bExported = true;
}
WriteCR( pTextNodeInfoInner );
}
}
}
if (0 == nEnd)
{
// Output the character attributes
// do it after WriteCR for an empty paragraph (otherwise
// WW8_WrFkp::Append throws SPRMs away...)
AttrOutput().StartRunProperties();
aAttrIter.OutAttr( nAktPos );
AttrOutput().EndRunProperties( pRedlineData );
}
// Exception: footnotes at the end of line
if ( nNextAttr == nEnd )
{
ASSERT(nOpenAttrWithRange >= 0,
"odd to see this happening, expected >= 0");
bool bAttrWithRange = (nOpenAttrWithRange > 0);
if ( nAktPos != nEnd )
{
nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nEnd);
ASSERT(nOpenAttrWithRange == 0,
"odd to see this happening, expected 0");
}
AttrOutput().OutputFKP();
if ( bTxtAtr || bAttrWithRange || bRedlineAtEnd )
{
// insert final graphic anchors if any before CR
aAttrIter.OutFlys( nEnd );
// insert final bookmarks if any before CR and after flys
AppendBookmarks( rNode, nEnd, 1 );
WriteCR( pTextNodeInfoInner );
//For i120928,the position of the bullet's graphic is at end of doc
if (bLastCR && (!bExported))
{
ExportGrfBullet(rNode);
bExported = true;
}
if ( pTOXSect )
{
m_aCurrentCharPropStarts.pop();
AttrOutput().EndTOX( *pTOXSect );
}
if ( bRedlineAtEnd )
{
AttrOutput().Redline( aAttrIter.GetRedline( nEnd ) );
AttrOutput().OutputFKP();
}
}
}
AttrOutput().EndRun();
nAktPos = nNextAttr;
UpdatePosition( &aAttrIter, nAktPos, nEnd );
eChrSet = aAttrIter.GetCharSet();
}
while ( nAktPos < nEnd );
AttrOutput().StartParagraphProperties( rNode );
AttrOutput().ParagraphStyle( nStyle );
if ( mpParentFrame && IsInTable() ) // Fly-Attrs
OutputFormat( mpParentFrame->GetFrmFmt(), false, false, true );
if ( pTextNodeInfo.get() != NULL )
{
#ifdef DEBUG
::std::clog << pTextNodeInfo->toString() << ::std::endl;
#endif
AttrOutput().TableInfoCell( pTextNodeInfoInner );
if (pTextNodeInfoInner->isFirstInTable())
{
const SwTable * pTable = pTextNodeInfoInner->getTable();
const SwTableFmt * pTabFmt = pTable->GetTableFmt();
if (pTabFmt != NULL)
{
if (pTabFmt->GetBreak().GetBreak() == SVX_BREAK_PAGE_BEFORE)
AttrOutput().PageBreakBefore(true);
}
}
}
if ( !bFlyInTable )
{
SfxItemSet* pTmpSet = 0;
const sal_uInt8 nPrvNxtNd = rNode.HasPrevNextLayNode();
if( (ND_HAS_PREV_LAYNODE|ND_HAS_NEXT_LAYNODE ) != nPrvNxtNd )
{
const SfxPoolItem* pItem;
if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(
RES_UL_SPACE, true, &pItem ) &&
( ( !( ND_HAS_PREV_LAYNODE & nPrvNxtNd ) &&
((SvxULSpaceItem*)pItem)->GetUpper()) ||
( !( ND_HAS_NEXT_LAYNODE & nPrvNxtNd ) &&
((SvxULSpaceItem*)pItem)->GetLower()) ))
{
pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
SvxULSpaceItem aUL( *(SvxULSpaceItem*)pItem );
// OD, MMAHER 2004-03-01 #i25901#- consider compatibility option
if (!pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES))
{
if( !(ND_HAS_PREV_LAYNODE & nPrvNxtNd ))
aUL.SetUpper( 0 );
}
// OD, MMAHER 2004-03-01 #i25901# - consider compatibility option
if (!pDoc->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS))
{
if( !(ND_HAS_NEXT_LAYNODE & nPrvNxtNd ))
aUL.SetLower( 0 );
}
pTmpSet->Put( aUL );
}
}
sal_Bool bParaRTL = sal_False;
const SvxFrameDirectionItem* pItem = (const SvxFrameDirectionItem*)
rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR);
if ( aAttrIter.IsParaRTL())
bParaRTL = sal_True;
if( rNode.IsNumbered())
{
const SwNumRule* pRule = rNode.GetNumRule();
sal_uInt8 nLvl = static_cast< sal_uInt8 >( rNode.GetActualListLevel() );
const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
if( !pFmt )
pFmt = &pRule->Get( nLvl );
if( !pTmpSet )
pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*pTmpSet, RES_LR_SPACE));
// --> OD 2008-06-03 #i86652#
if ( pFmt->GetPositionAndSpaceMode() ==
SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
{
aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetAbsLSpace() );
}
// <--
if( rNode.IsNumbered() && rNode.IsCountedInList() )
{
// --> OD 2008-06-03 #i86652#
if ( pFmt->GetPositionAndSpaceMode() ==
SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
{
if (bParaRTL)
aLR.SetTxtFirstLineOfstValue(pFmt->GetAbsLSpace() - pFmt->GetFirstLineOffset());
else
aLR.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt));
}
// <--
// --> OD 2009-03-09 #100020#
// correct fix for issue i94187
if (SFX_ITEM_SET !=
pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
{
// List style set via paragraph style - then put it into the itemset.
// This is needed to get list level and list id exported for
// the paragraph.
pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
// Put indent values into the itemset in case that the list
// style is applied via paragraph style and the list level
// indent values are not applicable.
if ( pFmt->GetPositionAndSpaceMode() ==
SvxNumberFormat::LABEL_ALIGNMENT &&
!rNode.AreListLevelIndentsApplicable() )
{
pTmpSet->Put( aLR );
}
}
}
else
pTmpSet->ClearItem(RES_PARATR_NUMRULE);
// --> OD 2008-06-03 #i86652#
if ( pFmt->GetPositionAndSpaceMode() ==
SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
{
pTmpSet->Put(aLR);
//#i21847#
SvxTabStopItem aItem(
ItemGet<SvxTabStopItem>(*pTmpSet, RES_PARATR_TABSTOP));
SvxTabStop aTabStop(pFmt->GetAbsLSpace());
aItem.Insert(aTabStop);
pTmpSet->Put(aItem);
MSWordExportBase::CorrectTabStopInSet(*pTmpSet, pFmt->GetAbsLSpace());
}
}
/*
If a given para is using the FRMDIR_ENVIRONMENT direction we
cannot export that, its its ltr then that's ok as thats word's
default. Otherwise we must add a RTL attribute to our export list
*/
pItem = (const SvxFrameDirectionItem*)
rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR);
if (
(!pItem || pItem->GetValue() == FRMDIR_ENVIRONMENT) &&
aAttrIter.IsParaRTL()
)
{
if ( !pTmpSet )
pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
pTmpSet->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP, RES_FRAMEDIR));
}
// --> OD 2005-10-18 #126238# - move code for handling of numbered,
// but not counted paragraphs to this place. Otherwise, the paragraph
// isn't exported as numbered, but not counted, if no other attribute
// is found in <pTmpSet>
// #i44815# adjust numbering/indents for numbered paragraphs
// without number (NO_NUMLEVEL)
// #i47013# need to check rNode.GetNumRule()!=NULL as well.
if ( ! rNode.IsCountedInList() && rNode.GetNumRule()!=NULL )
{
// WW8 does not know numbered paragraphs without number
// (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
// the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
// no numbering. Here, we will adjust the indents to match
// visually.
if ( !pTmpSet )
pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
// create new LRSpace item, based on the current (if present)
const SfxPoolItem* pPoolItem = NULL;
pTmpSet->GetItemState(RES_LR_SPACE, sal_True, &pPoolItem);
SvxLRSpaceItem aLRSpace(
( pPoolItem == NULL )
? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE)
: *static_cast<const SvxLRSpaceItem*>( pPoolItem ) );
// new left margin = old left + label space
const SwNumRule* pRule = rNode.GetNumRule();
const SwNumFmt& rNumFmt = pRule->Get( static_cast< sal_uInt16 >(rNode.GetActualListLevel()) );
// --> OD 2008-06-03 #i86652#
if ( rNumFmt.GetPositionAndSpaceMode() ==
SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
{
aLRSpace.SetTxtLeft( aLRSpace.GetLeft() + rNumFmt.GetAbsLSpace() );
// new first line indent = 0
// (first line indent is ignored for NO_NUMLEVEL)
if (!bParaRTL)
aLRSpace.SetTxtFirstLineOfst( 0 );
// put back the new item
pTmpSet->Put( aLRSpace );
}
// <--
// assure that numbering rule is in <pTmpSet>
if (SFX_ITEM_SET != pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
{
pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
}
}
// --> OD 2007-04-24 #i75457#
// Export page break after attribute from paragraph style.
// If page break attribute at the text node exist, an existing page
// break after at the paragraph style hasn't got to be considered.
if ( !rNode.GetpSwAttrSet() ||
SFX_ITEM_SET != rNode.GetpSwAttrSet()->GetItemState(RES_BREAK, false) )
{
const SvxFmtBreakItem* pBreakAtParaStyle =
&(ItemGet<SvxFmtBreakItem>(rNode.GetSwAttrSet(), RES_BREAK));
if ( pBreakAtParaStyle &&
pBreakAtParaStyle->GetBreak() == SVX_BREAK_PAGE_AFTER )
{
if ( !pTmpSet )
{
pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
}
pTmpSet->Put( *pBreakAtParaStyle );
}
else if( pTmpSet )
{ // Even a pagedesc item is set, the break item can be set 'NONE',
// this has to be overruled.
const SwFmtPageDesc& rPageDescAtParaStyle =
ItemGet<SwFmtPageDesc>( rNode, RES_PAGEDESC );
if( rPageDescAtParaStyle.KnowsPageDesc() )
pTmpSet->ClearItem( RES_BREAK );
}
}
// --> FME 2007-05-30 #i76520# Emulate non-splitting tables
if ( bOutTable )
{
const SwTableNode* pTableNode = rNode.FindTableNode();
if ( pTableNode )
{
const SwTable& rTable = pTableNode->GetTable();
const SvxFmtKeepItem& rKeep = rTable.GetFrmFmt()->GetKeep();
const bool bKeep = rKeep.GetValue();
const bool bDontSplit = !bKeep ?
!rTable.GetFrmFmt()->GetLayoutSplit().GetValue() :
false;
if ( bKeep || bDontSplit )
{
// bKeep: set keep at first paragraphs in all lines
// bDontSplit : set keep at first paragraphs in all lines except from last line
// but only for non-complex tables
const SwTableBox* pBox = rNode.GetTblBox();
const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0;
if ( pLine && !pLine->GetUpper() )
{
// check if box is first in that line:
if ( 0 == pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() )
{
// check if paragraph is first in that line:
if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
{
bool bSetAtPara = false;
if ( bKeep )
bSetAtPara = true;
else if ( bDontSplit )
{
// check if pLine isn't last line in table
if ( rTable.GetTabLines().Count() - rTable.GetTabLines().GetPos( pLine ) != 1 )
bSetAtPara = true;
}
if ( bSetAtPara )
{
if ( !pTmpSet )
pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
const SvxFmtKeepItem aKeepItem( sal_True, RES_KEEP );
pTmpSet->Put( aKeepItem );
}
}
}
}
}
}
}
// <--
const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet();
if( pNewSet )
{ // Para-Attrs
pStyAttr = &rNode.GetAnyFmtColl().GetAttrSet();
const SwModify* pOldMod = pOutFmtNode;
pOutFmtNode = &rNode;
// Pap-Attrs, so script is not necessary
OutputItemSet( *pNewSet, true, false, i18n::ScriptType::LATIN, false);
pStyAttr = 0;
pOutFmtNode = pOldMod;
if( pNewSet != rNode.GetpSwAttrSet() )
delete pNewSet;
}
}
AttrOutput().EndParagraphProperties();
AttrOutput().EndParagraph( pTextNodeInfoInner );
#ifdef DEBUG
::std::clog << "</OutWW8_SwTxtNode>" << ::std::endl;
#endif
}
void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )
{
SVBT16 nSty;
ShortToSVBT16( GetExport().nStyleBeforeFly, nSty );
ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt( pNodeInfo->getInners().begin() );
ww8::WW8TableNodeInfo::Inners_t::const_iterator aItEnd( pNodeInfo->getInners().end() );
while (aIt != aItEnd)
{
ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
if ( pInner->isEndOfCell() )
{
TableRowEnd( pInner->getDepth() );
m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style #
TableInfoRow( pInner );
m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
m_rWW8Export.pO->GetData() );
m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
}
if ( pInner->isEndOfLine() )
{
}
aIt++;
}
}
#if 0
/* */
sal_uInt16 WW8Export::StartTableFromFrmFmt( WW8Bytes &rAt, const SwFrmFmt *pFmt )
{
// Tell the undocumented table hack that everything between here and
// the last table position is nontable text
if ( WW8_CP nPos = Fc2Cp( Strm().Tell() ) )
pMagicTable->Append(nPos,0);
// sprmPDxaFromText10
if( bWrtWW8 )
{
static sal_uInt8 __READONLY_DATA aTabLineAttr[] = {
0, 0, // Sty # 0
0x16, 0x24, 1, // sprmPFInTable
0x17, 0x24, 1 }; // sprmPFTtp
rAt.Insert( aTabLineAttr, sizeof( aTabLineAttr ), rAt.Count() );
}
else
{
static sal_uInt8 __READONLY_DATA aTabLineAttr[] = {
0, 0, // Sty # 0
24, 1, // sprmPFInTable
25, 1 }; // sprmPFTtp
rAt.Insert( aTabLineAttr, sizeof( aTabLineAttr ), rAt.Count() );
}
ASSERT( pFmt, "No pFmt!" );
if ( pFmt )
{
const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
if (
(text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
text::RelOrientation::FRAME == rHori.GetRelationOrient())
&&
(text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
text::RelOrientation::FRAME == rVert.GetRelationOrient())
)
{
sal_Int16 eHOri = rHori.GetHoriOrient();
switch (eHOri)
{
case text::HoriOrientation::CENTER:
case text::HoriOrientation::RIGHT:
if( bWrtWW8 )
SwWW8Writer::InsUInt16( rAt, NS_sprm::LN_TJc );
else
rAt.Insert( 182, rAt.Count() );
SwWW8Writer::InsUInt16( rAt, (text::HoriOrientation::RIGHT == eHOri ? 2 : 1 ));
break;
default:
break;
}
}
}
return rAt.Count();
}
//See #i19484# for why we need this
static bool CellContainsProblematicGraphic( const SwWriteTableCell *pCell,
const MSWordExportBase &rExport )
{
const SwNode *pStart = pCell ? pCell->GetBox()->GetSttNd() : 0;
const SwNode *pEnd = pStart ? pStart->EndOfSectionNode() : 0;
ASSERT( pStart && pEnd, "No start or end?" );
if ( !pStart || !pEnd )
return false;
bool bHasGraphic = false;
sw::Frames aFrames( GetFramesBetweenNodes( rExport.maFrames, *pStart, *pEnd ) );
sw::FrameIter aEnd = aFrames.end();
for ( sw::FrameIter aIter = aFrames.begin(); aIter != aEnd; ++aIter )
{
const SwFrmFmt &rEntry = aIter->GetFrmFmt();
if ( rEntry.GetSurround().GetSurround() == SURROUND_THROUGHT )
{
bHasGraphic = true;
break;
}
}
return bHasGraphic;
}
static bool RowContainsProblematicGraphic( const SwWriteTableCellPtr *pRow,
sal_uInt16 nCols, const MSWordExportBase &rExport )
{
bool bHasGraphic = false;
for ( sal_uInt16 nI = 0; nI < nCols; ++nI )
{
if ( CellContainsProblematicGraphic( pRow[nI], rExport ) )
{
bHasGraphic = true;
break;
}
}
return bHasGraphic;
}
#endif
//---------------------------------------------------------------------------
// Tabellen
//---------------------------------------------------------------------------
void WW8AttributeOutput::EmptyParagraph()
{
m_rWW8Export.WriteStringAsPara( aEmptyStr );
}
bool MSWordExportBase::NoPageBreakSection( const SfxItemSet* pSet )
{
bool bRet = false;
const SfxPoolItem* pI;
if( pSet)
{
bool bNoPageBreak = false;
if ( SFX_ITEM_ON != pSet->GetItemState(RES_PAGEDESC, true, &pI)
|| 0 == ((SwFmtPageDesc*)pI)->GetPageDesc() )
{
bNoPageBreak = true;
}
if (bNoPageBreak)
{
if (SFX_ITEM_ON != pSet->GetItemState(RES_BREAK, true, &pI))
bNoPageBreak = true;
else
{
SvxBreak eBreak = ((const SvxFmtBreakItem*)pI)->GetBreak();
switch (eBreak)
{
case SVX_BREAK_PAGE_BEFORE:
case SVX_BREAK_PAGE_AFTER:
bNoPageBreak = false;
break;
default:
break;
}
}
}
bRet = bNoPageBreak;
}
return bRet;
}
/* */
void MSWordExportBase::OutputSectionNode( const SwSectionNode& rSectionNode )
{
const SwSection& rSection = rSectionNode.GetSection();
SwNodeIndex aIdx( rSectionNode, 1 );
const SwNode& rNd = aIdx.GetNode();
if ( !rNd.IsSectionNode() && !IsInTable()
&& rSection.GetType() != TOX_CONTENT_SECTION && rSection.GetType() != TOX_HEADER_SECTION) //No sections in table
{
// Bug 74245 - if the first Node inside the section has an own
// PageDesc or PageBreak attribut, then dont write
// here the section break
sal_uLong nRstLnNum = 0;
const SfxItemSet* pSet;
if ( rNd.IsTableNode() )
pSet = &rNd.GetTableNode()->GetTable().GetFrmFmt()->GetAttrSet();
else if ( rNd.IsCntntNode() )
{
pSet = &rNd.GetCntntNode()->GetSwAttrSet();
nRstLnNum = ((SwFmtLineNumber&)pSet->Get(
RES_LINENUMBER )).GetStartValue();
}
else
pSet = 0;
if ( pSet && NoPageBreakSection( pSet ) )
pSet = 0;
if ( !pSet )
{
// new Section with no own PageDesc/-Break
// -> write follow section break;
const SwSectionFmt& rFmt = *rSection.GetFmt();
ReplaceCr( msword::PageBreak ); // Indikator fuer Page/Section-Break
//Get the page in use at the top of this section
SwNodeIndex aIdxTmp(rSectionNode, 1);
const SwPageDesc *pCurrent =
SwPageDesc::GetPageDescOfNode(aIdxTmp.GetNode());
if (!pCurrent)
pCurrent = pAktPageDesc;
AppendSection( pCurrent, &rFmt, nRstLnNum );
}
}
if ( TOX_CONTENT_SECTION == rSection.GetType() )
bStartTOX = true;
}
void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
{
pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFmt, nLnNum);
}
/* */
//---------------------------------------------------------------------------
// Flys
//---------------------------------------------------------------------------
void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode& rNd )
{
ASSERT(!bWrtWW8, "I shouldn't be needed for Word >=8");
if ( bWrtWW8 )
return;
if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
{
for( sal_uInt16 n=0; n < pTxtAttrs->Count(); ++n )
{
const SwTxtAttr* pAttr = (*pTxtAttrs)[ n ];
if( RES_TXTATR_FLYCNT == pAttr->Which() )
{
// zeichengebundenes Attribut
const SwFmtFlyCnt& rFlyCntnt = pAttr->GetFlyCnt();
const SwFlyFrmFmt& rFlyFrmFmt = *(SwFlyFrmFmt*)rFlyCntnt.GetFrmFmt();
const SwNodeIndex* pNodeIndex = rFlyFrmFmt.GetCntnt().GetCntntIdx();
if( pNodeIndex )
{
sal_uLong nStt = pNodeIndex->GetIndex()+1,
nEnd = pNodeIndex->GetNode().EndOfSectionIndex();
if( (nStt < nEnd) && !pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
{
Point aOffset;
// Rechtecke des Flys und des Absatzes besorgen
SwRect aParentRect(rNd.FindLayoutRect(false, &aOffset)),
aFlyRect(rFlyFrmFmt.FindLayoutRect(false, &aOffset ) );
aOffset = aFlyRect.Pos() - aParentRect.Pos();
// PaM umsetzen: auf Inhalt des Fly-Frameformats
SaveData( nStt, nEnd );
// wird in OutputFormat() ausgewertet
pFlyOffset = &aOffset;
eNewAnchorType = rFlyFrmFmt.GetAnchor().GetAnchorId();
sw::Frame aFrm(rFlyFrmFmt, SwPosition(rNd));
mpParentFrame = &aFrm;
// Ok, rausschreiben:
WriteText();
RestoreData();
}
}
}
}
}
}
void WW8AttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft )
{
const SwFrmFmt &rFrmFmt = rFmt.GetFrmFmt();
const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor();
bool bUseEscher = m_rWW8Export.bWrtWW8;
if ( m_rWW8Export.bWrtWW8 && rFmt.IsInline() )
{
sw::Frame::WriterSource eType = rFmt.GetWriterType();
if ((eType == sw::Frame::eGraphic) || (eType == sw::Frame::eOle))
bUseEscher = false;
else
bUseEscher = true;
/*
#110185#
A special case for converting some inline form controls to form fields
when in winword 8+ mode
*/
if ((bUseEscher == true) && (eType == sw::Frame::eFormControl))
{
if ( m_rWW8Export.MiserableFormFieldExportHack( rFrmFmt ) )
return ;
}
}
if (bUseEscher)
{
ASSERT( m_rWW8Export.bWrtWW8, "this has gone horribly wrong" );
// write as escher
m_rWW8Export.AppendFlyInFlys(rFmt, rNdTopLeft);
}
else
{
bool bDone = false;
// Hole vom Node und vom letzten Node die Position in der Section
const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
if( nStt >= nEnd ) // kein Bereich, also kein gueltiger Node
return;
if ( !m_rWW8Export.IsInTable() && rFmt.IsInline() )
{
//Test to see if this textbox contains only a single graphic/ole
SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
if ( pParTxtNode && !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
bDone = true;
}
if( !bDone )
{
// ein NICHT zeichengebundener Rahmen liegt vor
// --> OD 2007-04-19 #i43447# - removed
// const SwFmtFrmSize& rS = rFrmFmt.GetFrmSize();
// nFlyWidth = rS.GetWidth(); // Fuer Anpassung Graphic-Groesse
// nFlyHeight = rS.GetHeight();
// <--
m_rWW8Export.SaveData( nStt, nEnd );
Point aOffset;
if ( m_rWW8Export.mpParentFrame )
{
/*
#90804#
Munge flys in fly into absolutely positioned elements for
word 6
*/
const SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
const SwRect aPageRect = pParTxtNode->FindPageFrmRect( sal_False, 0, sal_False );
aOffset = rFrmFmt.FindLayoutRect().Pos();
aOffset -= aPageRect.Pos();
m_rWW8Export.pFlyOffset = &aOffset;
m_rWW8Export.eNewAnchorType = FLY_AT_PAGE;
}
m_rWW8Export.mpParentFrame = &rFmt;
if (
m_rWW8Export.IsInTable() &&
(FLY_AT_PAGE != rAnch.GetAnchorId()) &&
!m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode()
)
{
// Beachten: Flag bOutTable wieder setzen,
// denn wir geben ja ganz normalen Content der
// Tabelenzelle aus und keinen Rahmen
// (Flag wurde oben in aSaveData() geloescht)
m_rWW8Export.bOutTable = true;
const String& rName = rFrmFmt.GetName();
m_rWW8Export.StartCommentOutput(rName);
m_rWW8Export.WriteText();
m_rWW8Export.EndCommentOutput(rName);
}
else
m_rWW8Export.WriteText();
m_rWW8Export.RestoreData();
}
}
}
void AttributeOutputBase::OutputFlyFrame( const sw::Frame& rFmt )
{
if ( !rFmt.GetCntntNode() )
return;
const SwCntntNode &rNode = *rFmt.GetCntntNode();
Point aNdPos, aPgPos;
Point* pLayPos;
bool bValidNdPos = false, bValidPgPos = false;
if (FLY_AT_PAGE == rFmt.GetFrmFmt().GetAnchor().GetAnchorId())
{
// get the Layout Node-Position.
if ( !bValidPgPos )
{
aPgPos = rNode.FindPageFrmRect(false, &aPgPos).Pos();
bValidPgPos = true;
}
pLayPos = &aPgPos;
}
else
{
// get the Layout Node-Position.
if ( !bValidNdPos )
{
aNdPos = rNode.FindLayoutRect(false, &aNdPos).Pos();
bValidNdPos = true;
}
pLayPos = &aNdPos;
}
OutputFlyFrame_Impl( rFmt, *pLayPos );
}
// write data of any redline
void WW8AttributeOutput::Redline( const SwRedlineData* pRedline )
{
if ( !pRedline )
return;
if ( pRedline->Next() )
Redline( pRedline->Next() );
static sal_uInt16 __READONLY_DATA aSprmIds[ 2 * 2 * 3 ] =
{
// Ids for insert
NS_sprm::LN_CFRMark, NS_sprm::LN_CIbstRMark, NS_sprm::LN_CDttmRMark, // for WW8
0x0042, 0x0045, 0x0046, // for WW6
// Ids for delete
NS_sprm::LN_CFRMarkDel, NS_sprm::LN_CIbstRMarkDel, NS_sprm::LN_CDttmRMarkDel, // for WW8
0x0041, 0x0045, 0x0046 // for WW6
};
const sal_uInt16* pSprmIds = 0;
switch( pRedline->GetType() )
{
case nsRedlineType_t::REDLINE_INSERT:
pSprmIds = aSprmIds;
break;
case nsRedlineType_t::REDLINE_DELETE:
pSprmIds = aSprmIds + (2 * 3);
break;
case nsRedlineType_t::REDLINE_FORMAT:
if( m_rWW8Export.bWrtWW8 )
{
m_rWW8Export.InsUInt16( NS_sprm::LN_CPropRMark );
m_rWW8Export.pO->Insert( 7, m_rWW8Export.pO->Count() ); // len
m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) );
m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
}
break;
default:
ASSERT(!this, "Unhandled redline type for export");
break;
}
if ( pSprmIds )
{
if ( !m_rWW8Export.bWrtWW8 )
pSprmIds += 3;
if ( m_rWW8Export.bWrtWW8 )
m_rWW8Export.InsUInt16( pSprmIds[0] );
else
m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[0]), m_rWW8Export.pO->Count() );
m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
if ( m_rWW8Export.bWrtWW8 )
m_rWW8Export.InsUInt16( pSprmIds[1] );
else
m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[1]), m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) );
if ( m_rWW8Export.bWrtWW8 )
m_rWW8Export.InsUInt16( pSprmIds[2] );
else
m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[2]), m_rWW8Export.pO->Count() );
m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
}
}
/* */
void MSWordExportBase::OutputContentNode( const SwCntntNode& rNode )
{
switch ( rNode.GetNodeType() )
{
case ND_TEXTNODE:
{
const SwTxtNode& rTextNode = *rNode.GetTxtNode();
if( !mbOutOutlineOnly || rTextNode.IsOutline() )
OutputTextNode( rTextNode );
}
break;
case ND_GRFNODE:
OutputGrfNode( *rNode.GetGrfNode() );
break;
case ND_OLENODE:
OutputOLENode( *rNode.GetOLENode() );
break;
default:
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("Unhandled node, type == %d\n", rNode.GetNodeType() );
#endif
break;
}
}
/* vi:set tabstop=4 shiftwidth=4 expandtab: */