blob: bc70f8532247221e6992993099ed83466220d416 [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 <hintids.hxx>
#include <tools/list.hxx>
#include <tools/cachestr.hxx>
#include <svtools/rtftoken.h>
#include <svl/itemiter.hxx>
#include <editeng/prntitem.hxx>
#include <editeng/opaqitem.hxx>
#include <editeng/protitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <fmtfsize.hxx>
#include <fmtanchr.hxx>
#include <fmtpdsc.hxx>
#include <fmtsrnd.hxx>
#include <fmtclds.hxx>
#include <fmtcntnt.hxx>
#include <frmatr.hxx>
#include <doc.hxx>
#include <pam.hxx>
#include <ndtxt.hxx>
#include <shellio.hxx>
#include <swparrtf.hxx>
#include <grfatr.hxx>
#include <paratr.hxx>
#include <rtf.hxx>
#include <ndgrf.hxx>
#include <pagedesc.hxx>
#include <swtable.hxx>
#include <txtflcnt.hxx>
#include <fmtflcnt.hxx>
#include <fltini.hxx>
#include <unoframe.hxx>
#include <deque>
#include <map>
#include <utility>
// --> OD 2004-06-30 #i27767#
#include <fmtwrapinfluenceonobjpos.hxx>
// <--
#include <editeng/brshitem.hxx>
#include <fmtfollowtextflow.hxx>
// --> OD, FLR 2006-02-16 #131205#
#include "dcontact.hxx"
// <--
using namespace ::com::sun::star;
#define ANCHOR(p) ((SwFmtAnchor*)p)
// steht in shellio.hxx
extern SwCntntNode* GoNextNds( SwNodeIndex * pIdx, sal_Bool bChk );
SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* )
inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, sal_Bool bInP=sal_True)
{
return (const SwFmtFrmSize&)rSet.Get(RES_FRM_SIZE,bInP);
}
SwFlySave::SwFlySave(const SwPaM& rPam, SfxItemSet& rSet)
: aFlySet(rSet), nSttNd(rPam.GetPoint()->nNode), nEndNd(nSttNd), nEndCnt(0),
nPageWidth(ATT_MIN_SIZE), nDropLines(0), nDropAnchor(0)
{
}
int SwFlySave::IsEqualFly( const SwPaM& rPos, SfxItemSet& rSet )
{
if( rSet.Count() != aFlySet.Count() || nDropAnchor )
return sal_False;
// nur TextNodes zusammenfassen
if( nSttNd == nEndNd && nEndNd.GetNode().IsNoTxtNode() )
return sal_False;
// teste auf gleiche / naechste Position
if( rPos.GetPoint()->nNode.GetIndex() == nEndNd.GetIndex() )
{
if( 1 < (rPos.GetPoint()->nContent.GetIndex() - nEndCnt) )
return sal_False;
}
else if( rPos.GetPoint()->nContent.GetIndex() )
return sal_False;
else
{
SwNodeIndex aIdx( nEndNd );
SwCntntNode *const pCNd = aIdx.GetNode().GetCntntNode();
if( !GoNextNds( &aIdx, sal_True ) ||
aIdx.GetIndex() != rPos.GetPoint()->nNode.GetIndex() ||
( pCNd && pCNd->Len() != nEndCnt ))
{
return sal_False;
}
}
if( rSet.Count() )
{
SfxItemIter aIter( rSet );
const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem();
while( sal_True )
{
if( SFX_ITEM_SET != aFlySet.GetItemState( pCurr->Which(),
sal_False, &pItem ) ||
// Ankerattribute gesondert behandeln
( RES_ANCHOR == pCurr->Which()
? (ANCHOR(pCurr)->GetAnchorId() != ANCHOR(pItem)->GetAnchorId() ||
ANCHOR(pCurr)->GetPageNum() != ANCHOR(pItem)->GetPageNum())
: *pItem != *pCurr ))
return sal_False;
if( aIter.IsAtEnd() )
break;
pCurr = aIter.NextItem();
}
}
return sal_True;
}
void SwFlySave::SetFlySize( const SwTableNode& rTblNd )
{
// sollte der Fly kleiner als diese Tabelle sein, dann
// korrigiere diesen (nur bei abs. Angaben!)
SwTwips nWidth = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
const SwFmtFrmSize& rSz = GetFrmSize( aFlySet );
if( nWidth > rSz.GetWidth() )
aFlySet.Put( SwFmtFrmSize( rSz.GetHeightSizeType(), nWidth, rSz.GetHeight() ));
}
sal_Bool lcl_HasBreakAttrs( const SwCntntNode& rNd )
{
sal_Bool bRet = sal_False;
const SfxItemSet& rSet = rNd.GetSwAttrSet();
const SfxPoolItem* pItem;
if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK, sal_True, &pItem ) &&
SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() )
bRet = sal_True;
else if( SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, sal_True, &pItem )&&
0 != ((SwFmtPageDesc*)pItem)->GetPageDesc() )
bRet = sal_True;
return bRet;
}
void lcl_CpyBreakAttrs( SwCntntNode* pSrcNd, SwCntntNode* pDstNd,
SwNodeIndex* pNewIdx )
{
const SfxItemSet* pSet;
if( pSrcNd && pDstNd && 0 != ( pSet = pSrcNd->GetpSwAttrSet() ) )
{
const SfxPoolItem *pDescItem, *pBreakItem;
if( SFX_ITEM_SET != pSet->GetItemState( RES_BREAK,
sal_False, &pBreakItem ) )
pBreakItem = 0;
if( SFX_ITEM_SET != pSet->GetItemState( RES_PAGEDESC,
sal_False, &pDescItem ) )
pDescItem = 0;
if( pDescItem || pBreakItem )
{
if( lcl_HasBreakAttrs( *pDstNd ))
{
SwPosition aPos( *pDstNd, SwIndex( pDstNd ));
aPos.nNode--;
pDstNd->GetDoc()->AppendTxtNode( aPos );
if( pNewIdx )
*pNewIdx = aPos.nNode;
SwCntntNode* pOldNd = pDstNd;
pDstNd = aPos.nNode.GetNode().GetCntntNode();
pDstNd->ChgFmtColl( pOldNd->GetFmtColl() );
if( pDstNd->HasSwAttrSet() )
{
SfxItemSet aSet( *pDstNd->GetpSwAttrSet() );
aSet.ClearItem( RES_BREAK );
aSet.ClearItem( RES_PAGEDESC );
pDstNd->SetAttr( aSet );
}
}
if( pBreakItem )
{
pDstNd->SetAttr( *pBreakItem );
pSrcNd->ResetAttr( RES_BREAK );
}
if( pDescItem )
{
pDstNd->SetAttr( *pDescItem );
pSrcNd->ResetAttr( RES_PAGEDESC );
}
}
}
}
void SwRTFParser::SetFlysInDoc()
{
// !! von Oben abarbeiten, CntntPos ist kein Index !
SwNodes & rNds = pDoc->GetNodes();
typedef std::pair<SwFlyFrmFmt*, SwFmtAnchor> frameEntry;
typedef std::deque<frameEntry> rtfframesAtIndex;
typedef std::map<const SwNode*, rtfframesAtIndex> rtfFmtMap;
rtfFmtMap aPrevFmts;
SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME );
for( sal_uInt16 n = 0; n < aFlyArr.Count(); ++n )
{
SwFlySave* pFlySave = aFlyArr[ n ];
ASSERT( !pFlySave->nSttNd.GetNode().FindFlyStartNode(),
"Content vom Fly steht in einem Fly" );
ASSERT( pFlySave->nSttNd.GetIndex() <= pFlySave->nEndNd.GetIndex(),
"Fly hat falschen Bereich" );
//JP 21.09.98: wenn ein DropCap ist, dann Text im Node belassen, am
// Absatz das Absatz Attribut setzen. Ggfs noch die
// FontSize zuruecksetzen, damit das DropCap nicht zu
// gro? wird.
if( pFlySave->nDropAnchor )
{
SwTxtNode* pSttNd = pFlySave->nSttNd.GetNode().GetTxtNode();
SwTxtNode* pEndNd = pFlySave->nEndNd.GetNode().GetTxtNode();
if( pSttNd && pEndNd &&
pSttNd->GetIndex() + 1 == pEndNd->GetIndex()
&& pSttNd->GetTxt().Len()>0 /* #i38227# leave drop caps with no content as fly frames */ )
{
sal_uLong nPos = pSttNd->GetIndex();
SwDoc * pDoc1 = pSttNd->GetDoc();
sal_Bool bJoined;
{
SwPaM aTmp( *pSttNd, pSttNd->GetTxt().Len(), *pEndNd, 0 );
bJoined = pDoc1->DeleteAndJoin( aTmp );
}
SwTxtNode * pNd = (pDoc1->GetNodes()[nPos])->GetTxtNode();
if( bJoined && pNd != NULL)
{
SwFmtDrop aDropCap;
aDropCap.GetLines() = (sal_uInt8)pFlySave->nDropLines;
aDropCap.GetChars() = 1;
SwIndex aIdx( pEndNd );
pNd->RstTxtAttr( aIdx, 1, RES_CHRATR_FONTSIZE );
pNd->SetAttr( aDropCap );
}
delete pFlySave;
continue;
}
}
// liegt Ende und Start vom Naechsten im gleichen Node, dann muss
// gesplittet werden
if (((static_cast<size_t>(n) + 1) < aFlyArr.Count()) &&
pFlySave->nEndCnt &&
pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd )
{
SwCntntNode *const pCNd = pFlySave->nEndNd.GetNode().GetCntntNode();
if( pCNd )
{
SwPosition aPos( pFlySave->nEndNd,
SwIndex( pCNd, pFlySave->nEndCnt ));
pDoc->SplitNode( aPos, false );
pFlySave->nEndNd--;
}
else
pFlySave->nEndCnt = 0;
}
// verschiebe den Inhalt von diesem Anchor in den Auto-TextBereich
// und erzeuge dadurch den richtigen SwG-Rahmen
SwNodeRange aRg(pFlySave->nSttNd, 0, pFlySave->nEndNd, 0);
//Make a new section, unless there is no content at all
const bool bMakeEmptySection = aRg.aStart < aRg.aEnd || ((aRg.aStart == aRg.aEnd) && pFlySave->nEndCnt);
{
// Nur TextNodes koennen in Tabellen stehen !!
const SwNode* pNd = &pFlySave->nSttNd.GetNode();
if( pNd->IsNoTxtNode() )
{
// die Size muss noch korrigiert werden!
nAktPageDesc = 0; // Standart PageDesc
if( SFX_ITEM_SET != pFlySave->aFlySet.GetItemState(
RES_FRM_SIZE, sal_False ) )
_SetPictureSize( *(SwNoTxtNode*)pNd, aRg.aStart,
pFlySave->aFlySet );
if( 0 != ( pNd = pNd->FindTableNode() ) )
pFlySave->SetFlySize( *(SwTableNode*)pNd );
}
else
{
// Take care for table nodes
pNd = pNd->GetNodes()[ pNd->GetIndex() - 2 ]->GetTableNode();
if( pNd ) // if the table starts imediately before aRg -> expand aRg
aRg.aStart = *pNd;
if( bMakeEmptySection )
{
pNd = &aRg.aEnd.GetNode();
sal_uLong nSectEnd = pNd->EndOfSectionIndex()+1;
if (!pNd->IsTableNode() && 0 !=(pNd = pNd->FindTableNode())
&& (pNd->GetIndex() >= aRg.aStart.GetNode().GetIndex()) )
{
const SwNode* pTblBxNd;
// Ende der Tabelle ist hinter dieser Box ??
if( pNd->EndOfSectionIndex() == nSectEnd )
aRg.aEnd = nSectEnd+1;
// is the end in the first box of the table, then
// move before the table (Bug 67663)
// but the range must not become emtpy, i.e. aStart==aEnd
// because otherwise we will get a crash (126506) later on
else if( 0 != ( pTblBxNd = aRg.aEnd.GetNode().
FindTableBoxStartNode()) &&
pTblBxNd->GetIndex() - 1 == pNd->GetIndex() &&
&aRg.aStart.GetNode() != pNd )
aRg.aEnd = *pNd;
else
{
// Tabelle ist noch groesser, also splitte sie hier.
rNds.SplitTable( aRg.aEnd, sal_True );
aRg.aEnd = pNd->EndOfSectionIndex() + 1;
}
}
}
}
}
// vorm verschieben muss sich der Index auf die alte Position
// gemerkt werden, der Index wird mit verschoben !!!
SwNodeIndex aTmpIdx( rNds.GetEndOfAutotext() );
SwStartNode* pSttNd = bMakeEmptySection
? rNds.MakeEmptySection( aTmpIdx, SwFlyStartNode )
: rNds.MakeTextSection( aTmpIdx, SwFlyStartNode,
(SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
// das ist die Verankerungs-Position (fuers Layout!)
pFlySave->nSttNd = aRg.aStart.GetIndex()-1;
if( bMakeEmptySection )
{
// check: the move does not clear the surrounded section. If all
// nodes moved away, then create a new TxtNode
{
// i76403: an empty selection is not a good idea
if( aRg.aStart == aRg.aEnd && aRg.aStart.GetNode().GetTxtNode() )
aRg.aEnd++;
SwNodeIndex aPrev( aRg.aStart, -1 );
if( aPrev.GetNode().IsStartNode() &&
aPrev.GetNode().EndOfSectionNode() == &aRg.aEnd.GetNode())
{
// create new txtnode, because the section does never be empty
pDoc->GetNodes().MakeTxtNode( aRg.aEnd,
(SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
aRg.aEnd--;
}
}
aTmpIdx = *pSttNd->EndOfSectionNode();
pDoc->MoveNodeRange( aRg, aTmpIdx,
IDocumentContentOperations::DOC_MOVEDEFAULT );
}
// patch from cmc for #i52542#
if (pSttNd->GetIndex() + 1 == pSttNd->EndOfSectionIndex())
{
ASSERT(!this, "nothing in this frame, not legal");
delete pFlySave;
continue;
}
pFlySave->aFlySet.Put( SwFmtCntnt( pSttNd ));
CalculateFlySize( pFlySave->aFlySet, pFlySave->nSttNd,
pFlySave->nPageWidth );
// THIS >>>>>
// if the section only contains one Node and this has a
// border or backgorund, then put it to the frame
// Not in our own RTF-Format!
// <<<<< DOES NOT MAKE SENSE TO ME (flr)
// #102781#. Added support for transparent frames.
if( pSttNd->GetIndex() + 1 != pSttNd->EndOfSectionIndex() &&
!bSwPageDesc )
{
SwCntntNode* pSrcNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetCntntNode();
SfxItemSet aTmpSet( pDoc->GetAttrPool(),
RES_BACKGROUND, RES_BOX );
const SvxBrushItem* pBackgroundBrush = (const SvxBrushItem*)pFlySave->aFlySet.GetItem(RES_BACKGROUND, sal_False);
if( pSrcNd && pSrcNd->HasSwAttrSet() )
aTmpSet.Put( *pSrcNd->GetpSwAttrSet() );
if (pBackgroundBrush)
{
aTmpSet.Put(*pBackgroundBrush, RES_BACKGROUND);
}
else
{
pBackgroundBrush = (const SvxBrushItem*)aTmpSet.GetItem(RES_BACKGROUND, sal_False);
if (pBackgroundBrush)
{
Color& rBackgroundColor = const_cast<SvxBrushItem*>(pBackgroundBrush)->GetColor();
rBackgroundColor.SetTransparency(0xFE);
}
else
{
Color aColor = Color(0xff, 0xff, 0xff);
aColor.SetTransparency( 0xFE);
SvxBrushItem aBrush(aColor, RES_BACKGROUND);
aTmpSet.Put(aBrush, RES_BACKGROUND);
}
}
// #117914# Topic 6.
pFlySave->aFlySet.Put( aTmpSet );
if( pSrcNd && pSrcNd->HasSwAttrSet() )
{
pSrcNd->ResetAttr( RES_BACKGROUND, RES_BOX );
}
}
SwFlyFrmFmt* pFmt = pDoc->MakeFlyFrmFmt( aEmptyStr, pParent );
pFmt->SetFmtAttr( pFlySave->aFlySet );
const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
if (FLY_AS_CHAR != rAnchor.GetAnchorId())
{
// korrigiere noch den Absatz, ist immer der vorhergehende !
// JP 20.09.95: wenn es diesen gibt! (DocAnfang!)
//JP 02.08.99: that is wrong. The anchor is ever the NEXT!
//JP 05.08.99: there are an Bug in the ExportFilter which will
// be fixed in the Version 517 - by SWG-Export
// the fly will be after the paragraph - but in RTF
// the flys will be before the paragraph.
if( !bSwPageDesc || 5430 < GetVersionNo() )
pFlySave->nSttNd++;
// if( !pFlySave->nSttNd.GetNode().IsCntntNode() )
{
// Seitenumbrueche in den Bodybereich verschieben!
SwCntntNode* pSrcNd = aRg.aStart.GetNode().GetCntntNode();
SwCntntNode* pDstNd = pFlySave->nSttNd.GetNode().GetCntntNode();
if( !pDstNd )
pDstNd = pDoc->GetNodes().GoNext( &pFlySave->nSttNd );
::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nSttNd );
}
const SwNodeIndex aSttNd(*pSttNd);
SwNodeIndex aEndNd(*pSttNd->EndOfSectionNode());
aEndNd--;
SwPosition aPos( pFlySave->nSttNd );
SwFmtAnchor aAnchor(rAnchor);
aAnchor.SetAnchor(&aPos);
const SwNode *pCurrentAnchor = &(pFlySave->nSttNd.GetNode());
aPrevFmts[pCurrentAnchor].push_back(frameEntry(pFmt, aAnchor));
while (aEndNd > aSttNd)
{
typedef rtfframesAtIndex::iterator myIter;
rtfframesAtIndex &rDeque = aPrevFmts[&(aEndNd.GetNode())];
myIter aEnd = rDeque.end();
for (myIter aIter = rDeque.begin(); aIter != aEnd; ++aIter)
{
aIter->second.SetAnchor(&aPos);
// --> OD 2004-06-30 #i27767# - push on front to keep order
// of objects for the correct object positioning
//aPrevFmts[pCurrentAnchor].push_back(*aIter);
aPrevFmts[pCurrentAnchor].push_front(*aIter);
}
rDeque.clear();
aEndNd--;
}
}
// --> OD, FLR 2006-02-16 #131205#
// Create draw contact object, which also creates a <SdrObject> instance,
// in order to set the order number.
// The order number is assumed to be the order of the text flow.
SwFlyDrawContact* pContact =
new SwFlyDrawContact( pFmt,
pFmt->GetDoc()->GetOrCreateDrawModel() );
pContact->GetMaster()->SetOrdNum( n );
// <--
delete pFlySave;
}
typedef rtfFmtMap::reverse_iterator myriter;
myriter aEnd = aPrevFmts.rend();
for(myriter aIter = aPrevFmts.rbegin(); aIter != aEnd; ++aIter)
{
rtfframesAtIndex &rDeque = aIter->second;
typedef rtfframesAtIndex::iterator myIter;
myIter aQEnd = rDeque.end();
for (myIter aQIter = rDeque.begin(); aQIter != aQEnd; ++aQIter)
{
frameEntry &rEntry = *aQIter;
SwFlyFrmFmt *pFrm = rEntry.first;
SwFmtAnchor &rAnchor = rEntry.second;
pFrm->SetFmtAttr(rAnchor);
}
}
aFlyArr.Remove(0, aFlyArr.Count());
}
// clips the text box to the min or max position if it is outside our min or max boundry
long SwRTFParser::GetSafePos(long nPos)
{
if(nPos > SHRT_MAX)
nPos = SHRT_MAX;
else if(nPos < SHRT_MIN)
nPos = SHRT_MIN;
return nPos;
}
void SwRTFParser::ReadFly( int nToken, SfxItemSet* pSet )
{
// ein Set fuer die FrmFmt-Attribute
SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
if( !IsNewDoc() )
Reader::ResetFrmFmtAttrs( aSet );
// der Fly beginnt immer in einem neuen Absatz
if( pPam->GetPoint()->nContent.GetIndex() )
InsertPara();
// RTF-Defaults setzen:
// --> OD 2004-06-24 #i27767#
SwFmtAnchor aAnchor( FLY_AT_PARA );
SwFmtHoriOrient aHori( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME );
SwFmtVertOrient aVert( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME );
// <--
SvxFrameDirectionItem aFrmDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
sal_uInt16 nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0;
SvUShorts aColumns;
sal_Bool bChkDropCap = 0 == pSet;
sal_uInt16 nDropCapLines = 0, nDropCapAnchor = 0;
int nNumOpenBrakets = GetOpenBrakets();
if( !pSet )
{
pSet = &aSet;
}
else
{
// die Werte aus dem uebergebenen!
aAnchor = (SwFmtAnchor&)pSet->Get( RES_ANCHOR );
aHori = (SwFmtHoriOrient&)pSet->Get( RES_HORI_ORIENT );
aVert = (SwFmtVertOrient&)pSet->Get( RES_VERT_ORIENT );
}
// dann sammel mal alle Attribute zusammen
int bWeiter = sal_True;
int nAppliedProps=0;
do {
sal_uInt16 nVal = sal_uInt16(nTokenValue);
/*
#i5263#
Assume that a property genuinely contributes towards creating a frame,
and if turns out to be a non contributing one reduce the count.
*/
++nAppliedProps;
switch( nToken )
{
case RTF_ABSW:
{
SwFmtFrmSize aSz( ATT_MIN_SIZE, nTokenValue, 0 );
const SfxPoolItem* pItem;
if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, sal_True,
&pItem ))
{
aSz.SetHeightSizeType( ((SwFmtFrmSize*)pItem)->GetHeightSizeType() );
aSz.SetHeight( ((SwFmtFrmSize*)pItem)->GetHeight() );
}
if( MINFLY > nTokenValue ) nTokenValue = MINFLY;
aSet.Put( aSz );
}
break;
case RTF_ABSH:
{
SwFmtFrmSize aSz( ATT_MIN_SIZE, 0, MINFLY );
const SfxPoolItem* pItem;
if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, sal_True,
&pItem ))
{
aSz.SetWidth( ((SwFmtFrmSize*)pItem)->GetWidth() );
}
if( 0 > nTokenValue )
{
nTokenValue = -nTokenValue;
aSz.SetHeightSizeType( ATT_FIX_SIZE );
}
if( MINFLY > nTokenValue ) nTokenValue = MINFLY;
aSz.SetHeight( nTokenValue );
aSet.Put( aSz );
}
break;
case RTF_NOWRAP:
{
pSet->Put( SwFmtSurround( SURROUND_NONE ));
}
break;
case RTF_DXFRTEXT:
{
SvxULSpaceItem aUL( RES_UL_SPACE );
SvxLRSpaceItem aLR( RES_LR_SPACE );
aUL.SetUpper( nVal ); aUL.SetLower( nVal );
aLR.SetLeft( nVal ); aLR.SetRight( nVal );
pSet->Put( aUL );
pSet->Put( aLR );
}
break;
case RTF_DFRMTXTX:
{
SvxLRSpaceItem aLR( RES_LR_SPACE );
aLR.SetLeft( nVal ); aLR.SetRight( nVal );
pSet->Put( aLR );
}
break;
case RTF_DFRMTXTY:
{
SvxULSpaceItem aUL( RES_UL_SPACE );
aUL.SetUpper( nVal ); aUL.SetLower( nVal );
pSet->Put( aUL );
}
break;
case RTF_POSNEGX:
case RTF_POSX: aHori.SetHoriOrient( text::HoriOrientation::NONE );
aHori.SetPos( GetSafePos((long)nTokenValue) );
break;
case RTF_POSXC: aHori.SetHoriOrient( text::HoriOrientation::CENTER ); break;
case RTF_POSXI: aHori.SetHoriOrient( text::HoriOrientation::LEFT );
aHori.SetPosToggle( sal_True );
break;
case RTF_POSXO: aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
aHori.SetPosToggle( sal_True );
break;
case RTF_POSXL: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); break;
case RTF_POSXR: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); break;
case RTF_POSNEGY:
case RTF_POSY: aVert.SetVertOrient( text::VertOrientation::NONE );
aVert.SetPos( GetSafePos((long)nTokenValue) );
break;
case RTF_POSYT: aVert.SetVertOrient( text::VertOrientation::TOP ); break;
case RTF_POSYB: aVert.SetVertOrient( text::VertOrientation::BOTTOM ); break;
case RTF_POSYC: aVert.SetVertOrient( text::VertOrientation::CENTER ); break;
case RTF_PHMRG: aHori.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break;
case RTF_PVMRG: aVert.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break;
case RTF_PHPG: aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME ); break;
case RTF_PVPG: aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );break;
case RTF_PHCOL: aHori.SetRelationOrient( text::RelOrientation::FRAME ); break;
case RTF_PVPARA: aVert.SetRelationOrient( text::RelOrientation::FRAME ); break;
case RTF_POSYIL:
break;
case RTF_ABSLOCK:
/*
#i5263#
Not sufficient to make a frame at least word won't do it with just
an abslock
*/
--nAppliedProps;
break;
case RTF_FRMTXLRTB:
aFrmDir.SetValue( FRMDIR_HORI_LEFT_TOP );
break;
case RTF_FRMTXTBRL:
aFrmDir.SetValue( FRMDIR_HORI_RIGHT_TOP );
break;
case RTF_FRMTXLRTBV:
aFrmDir.SetValue( FRMDIR_VERT_TOP_LEFT );
break;
case RTF_FRMTXTBRLV:
aFrmDir.SetValue( FRMDIR_VERT_TOP_RIGHT );
break;
case RTF_DROPCAPLI: // Dropcaps !!
if( bChkDropCap )
{
nDropCapLines = sal_uInt16( nTokenValue );
if( !nDropCapAnchor )
nDropCapAnchor = 1;
}
break;
case RTF_DROPCAPT:
if( bChkDropCap )
{
nDropCapAnchor = sal_uInt16( nTokenValue );
if( !nDropCapLines )
nDropCapLines = 3;
}
break;
// fuer die "alten" Writer - haben die Spaltigkeit falsch heraus-
// geschrieben
case RTF_COLS: nCols = sal_uInt16( nTokenValue ); break;
case RTF_COLSX: nColSpace = sal_uInt16( nTokenValue ); break;
case RTF_COLNO:
nAktCol = sal_uInt16( nTokenValue );
if( RTF_COLW == GetNextToken() )
{
sal_uInt16 nWidth = sal_uInt16( nTokenValue ), nSpace = 0;
if( RTF_COLSR == GetNextToken() )
nSpace = sal_uInt16( nTokenValue );
else
SkipToken( -1 ); // wieder zurueck
if( --nAktCol == ( aColumns.Count() / 2 ) )
{
aColumns.Insert( nWidth + nSpace, aColumns.Count() );
aColumns.Insert( nSpace, aColumns.Count() );
}
}
break;
case '{':
{
short nSkip = 0;
if( RTF_IGNOREFLAG != ( nToken = GetNextToken() ))
{
if( RTF_SHADINGDEF == (nToken & ~0xff) )
{
ReadBackgroundAttr( nToken, aSet );
GetNextToken(); // Klammer ueberlesen
}
else
nSkip = -1;
}
else if( RTF_APOCTL ==
((nToken = GetNextToken() ) & ~(0xff | RTF_SWGDEFS)) )
{
bReadSwFly = true; // alles kommt in den akt. Fly
SvxLRSpaceItem aLR( RES_LR_SPACE );
SvxULSpaceItem aUL( RES_UL_SPACE );
nCols = USHRT_MAX; // neu aufsetzen
nColSpace = USHRT_MAX;
do {
nVal = sal_uInt16(nTokenValue);
switch( nToken )
{
// Swg-Frame-Tokens
case RTF_FLYPRINT:
{
pSet->Put( SvxPrintItem( RES_PRINT, sal_False ));
}
break;
case RTF_FLYOPAQUE:
{
pSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_False ));
}
break;
case RTF_FLYPRTCTD:
{
RTFProtect aP( (sal_uInt8)nTokenValue );
SvxProtectItem aProtectItem( RES_PROTECT );
aProtectItem.SetCntntProtect( aP.GetCntnt() );
aProtectItem.SetSizeProtect( aP.GetSize() );
aProtectItem.SetPosProtect( aP.GetPos() );
pSet->Put( aProtectItem );
}
break;
case RTF_FLYMAINCNT:
{
RTFSurround aMC( (sal_uInt8)nTokenValue );
SwFmtSurround aSurr( (SwSurround)aMC.GetOrder());
if( aMC.GetGoldCut() )
aSurr.SetSurround( SURROUND_IDEAL );
pSet->Put( aSurr );
}
break;
case RTF_FLYVERT:
{
RTFVertOrient aVO( nVal );
aVert.SetVertOrient( aVO.GetOrient() );
aVert.SetRelationOrient( aVO.GetRelation() );
}
break;
case RTF_FLYHORZ:
{
RTFHoriOrient aHO( nVal );
aHori.SetHoriOrient( aHO.GetOrient() );
aHori.SetRelationOrient( aHO.GetRelation() );
}
break;
case RTF_FLYOUTLEFT: aLR.SetLeft( nVal ); break;
case RTF_FLYOUTRIGHT: aLR.SetRight( nVal ); break;
case RTF_FLYOUTUPPER: aUL.SetUpper( nVal ); break;
case RTF_FLYOUTLOWER: aUL.SetLower( nVal ); break;
case RTF_FLYANCHOR:
switch( GetNextToken() )
{
case RTF_FLY_PAGE:
aAnchor.SetType( FLY_AT_PAGE );
aAnchor.SetPageNum( sal_uInt16(nTokenValue));
aAnchor.SetAnchor( 0 );
break;
case RTF_FLY_CNTNT:
{
SwNodeIndex aIdx( pPam->GetPoint()->nNode );
pDoc->GetNodes().GoPrevious( &aIdx );
SwPosition aPos( aIdx );
aAnchor.SetType( FLY_AT_PARA );
aAnchor.SetAnchor( &aPos );
}
break;
// JP 26.09.94: die Bindung an die Spalte gibt es nicht mehr !!
// case RTF_FLY_COLUMN:
}
break;
case RTF_COLS: nCols = sal_uInt16( nTokenValue ); break;
case RTF_COLSX: nColSpace = sal_uInt16( nTokenValue ); break;
case RTF_COLNO:
nAktCol = sal_uInt16( nTokenValue );
if( RTF_COLW == GetNextToken() )
{
sal_uInt16 nWidth = sal_uInt16( nTokenValue ), nSpace = 0;
if( RTF_COLSR == GetNextToken() )
nSpace = sal_uInt16( nTokenValue );
else
SkipToken( -1 ); // wieder zurueck
if( --nAktCol == ( aColumns.Count() / 2 ) )
{
aColumns.Insert( nWidth + nSpace, aColumns.Count() );
aColumns.Insert( nSpace, aColumns.Count() );
}
}
break;
case '{':
if( RTF_BRDBOX == ( nToken = GetNextToken() ) )
ReadBorderAttr( nToken, aSet );
else if( RTF_SHADINGDEF == (nToken & ~0xff ) )
ReadBackgroundAttr( nToken, aSet );
else if( RTF_IGNOREFLAG == nToken )
{
int bSkipGrp = sal_True;
switch( nToken = GetNextToken() )
{
case RTF_SHADOW:
case RTF_BRDBOX:
ReadAttr( SkipToken( -2 ), &aSet );
bSkipGrp = sal_False;
break;
case RTF_BRDRT:
case RTF_BRDRB:
case RTF_BRDRR:
case RTF_BRDRL:
bSkipGrp = sal_False;
ReadBorderAttr( SkipToken( -2 ), aSet );
break;
}
// keine weitere Klammer mehr ueberlesen!!!
if( !bSkipGrp )
break;
SkipGroup();
}
else
SkipGroup();
GetNextToken(); // Klammer ueberlesen
break;
}
} while( IsParserWorking() &&
'}' != ( nToken = GetNextToken() ));
if( aUL.GetUpper() || aUL.GetLower() )
pSet->Put( aUL );
if( aLR.GetLeft() || aLR.GetRight() )
pSet->Put( aLR );
}
else if( RTF_BRDBOX == nToken )
ReadBorderAttr( nToken, aSet );
else if( RTF_SHADOW == nToken )
ReadAttr( SkipToken( -2 ), &aSet );
else if( RTF_SHADINGDEF == (nToken & ~0xff ) )
ReadBackgroundAttr( nToken, aSet );
else if( RTF_UNKNOWNCONTROL == nToken )
SkipGroup();
else
nSkip = -2;
if( nSkip )
{
nToken = SkipToken( nSkip );
bWeiter = sal_False;
}
}
break;
default:
--nAppliedProps; //Not sufficient to make a frame
bWeiter = sal_False;
}
if( bWeiter )
nToken = GetNextToken();
} while( bWeiter && IsParserWorking() );
pSet->Put( aAnchor );
pSet->Put( aHori );
pSet->Put( aVert );
// --> OD 2004-06-30 #i27767# - set wrapping style influence
// --> OD 2004-10-18 #i35017# - constant name has changed
pSet->Put( SwFmtWrapInfluenceOnObjPos(
text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ));
// <--
SwFmtFollowTextFlow aFollowTextFlow( sal_False );
pSet->Put( aFollowTextFlow );
if( !( aFrmDir == pSet->Get( RES_FRAMEDIR )) )
pSet->Put( aFrmDir );
if( nCols && USHRT_MAX != nCols )
{
SwFmtCol aCol;
if( USHRT_MAX == nColSpace )
nColSpace = 720;
sal_uLong nWidth = USHRT_MAX;
aCol.Init( nCols, nColSpace, sal_uInt16( nWidth ) );
if( nCols == ( aColumns.Count() / 2 ) )
{
for( sal_uInt16 n = 0, i = 0; n < aColumns.Count(); n += 2, ++i )
{
SwColumn* pCol = aCol.GetColumns()[ i ];
sal_uLong nTmp = aColumns[ n ];
nTmp *= USHRT_MAX;
nTmp /= nWidth;
pCol->SetWishWidth( sal_uInt16(nTmp) );
/*
JP 07.07.95: der Dialog kennt nur eine Breite fuer alle Spalten
darum hier nicht weiter beachten
nTmp = aColumns[ n+1 ];
if( nTmp )
pCol->SetRight( sal_uInt16(nTmp) );
else
pCol->SetRight( 0 );
pCol->SetLeft( 0 );
*/
}
}
pSet->Put( aCol );
}
if( pSet != &aSet ) // wurde der Set uebergeben, dann wars das
return ;
// ein neues FlyFormat anlegen oder das alte benutzen ?
// (teste ob es die selben Attribute besitzt!)
SwFlySave* pFlySave = 0;
sal_uInt16 nFlyArrCnt = aFlyArr.Count();
/*
#i5263#
There were not enough frame properties found to actually justify creating
an absolutely positioned frame.
*/
if (nAppliedProps)
{
if( !nFlyArrCnt ||
!( pFlySave = aFlyArr[ nFlyArrCnt-1 ])->IsEqualFly( *pPam, aSet ))
{
pFlySave = new SwFlySave( *pPam, aSet );
Size aPgSize;
GetPageSize( aPgSize );
pFlySave->nPageWidth = aPgSize.Width();
if( nDropCapAnchor )
{
pFlySave->nDropAnchor = nDropCapAnchor;
pFlySave->nDropLines = nDropCapLines;
}
if (nFlyArrCnt >0){
SwFlySave* pFlySavePrev = aFlyArr[nFlyArrCnt-1];
if (pFlySave->nSttNd.GetIndex() < pFlySavePrev->nEndNd.GetIndex())
{
pFlySavePrev->nEndNd=pFlySave->nSttNd;
}
}
aFlyArr.Insert( pFlySave, nFlyArrCnt++ );
// --> OD 2008-12-22 #i83368# - reset
mbReadCellWhileReadSwFly = false;
// <--
}
}
SetPardTokenRead( sal_False );
const SwTableNode* pTblNd = pPam->GetNode()->FindTableNode();
while( !IsPardTokenRead() && IsParserWorking() )
{
if( RTF_PARD == nToken || nNumOpenBrakets > GetOpenBrakets() )
break;
NextToken( nToken );
if( !IsPardTokenRead() )
{
// #102781#. Added support for transparent frames.
if (nToken == RTF_CBPAT && nFlyArrCnt > 0)
{
sal_uInt16 _index=sal_uInt16(nTokenValue);
const Color& rColor = GetColor(_index);
SvxBrushItem aBrush(rColor, RES_BACKGROUND);
SwFlySave* pFS = aFlyArr[nFlyArrCnt-1];
pFS->aFlySet.Put(aBrush, RES_BACKGROUND);
}
nToken = GetNextToken();
// BUG 22036: kommt zwischen Fly-Attributen ein unbekanntes,
// dann erzeuge nie 2 FlyFrames, sondern fasse
// beide zusammen !!!
while( RTF_APOCTL == ( nToken & ~(0xff | RTF_SWGDEFS) ))
{
if( RTF_FLY_INPARA == nToken )
break;
if( RTF_IGNOREFLAG == SkipToken( -1 ) )
{
if( '{' == SkipToken( -1 ) )
nToken = '{';
else
SkipToken( 2 );
}
else
SkipToken( 1 );
ReadFly( nToken, pFlySave ? &pFlySave->aFlySet : 0);
nToken = GetNextToken();
}
}
}
/*
#i5263#
There were enough frame properties found to actually justify creating
an absolutely positioned frame.
*/
if (!nAppliedProps)
{
bReadSwFly = false;
SkipToken( -1 );
return;
}
if( pTblNd && !pPam->GetPoint()->nContent.GetIndex() &&
pTblNd->EndOfSectionIndex() + 1 ==
pPam->GetPoint()->nNode.GetIndex() )
{
// nicht mehr in der Tabelle, sondern dahinter ?
// Dann aber wieder zurueck in die Tabelle
pPam->Move( fnMoveBackward );
}
else
pTblNd = 0;
// wurde garnichts eingefuegt?
if( !pTblNd &&
pPam->GetPoint()->nNode == pFlySave->nSttNd &&
!pPam->GetPoint()->nContent.GetIndex() )
{
// // dann erzeuge mindestens einen leeren TextNode
// pDoc->AppendTxtNode(*pPam);
// dann zerstoere den FlySave wieder.
aFlyArr.DeleteAndDestroy( --nFlyArrCnt );
}
else
{
sal_Bool bMovePaM = 0 != pTblNd;
pFlySave->nEndNd = pPam->GetPoint()->nNode;
pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex();
if( bMovePaM )
pPam->Move( fnMoveForward );
pTblNd = pFlySave->nSttNd.GetNode().FindTableNode();
if( pTblNd && !pFlySave->nEndCnt &&
pTblNd == pFlySave->nEndNd.GetNode().FindTableNode() )
{
// dann teste mal, ob das \pard nicht zu spaet kam und
// eigentlich in die vorherige Zelle gehoert
const SwStartNode* pSttBoxNd = pFlySave->nSttNd.GetNode().
FindTableBoxStartNode(),
* pEndBoxNd = pFlySave->nEndNd.GetNode().
FindTableBoxStartNode();
if( pSttBoxNd && pEndBoxNd &&
bMovePaM ? ( pSttBoxNd == pEndBoxNd )
: ( pSttBoxNd->EndOfSectionIndex() + 1 ==
pEndBoxNd->GetIndex() &&
pEndBoxNd->GetIndex() + 1 ==
pFlySave->nEndNd.GetIndex() ))
{
// dann gehoert das Ende in die vorherige Box!
SwPosition aPos( *pPam->GetPoint() );
pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode();
pPam->Move( fnMoveBackward, fnGoNode );
DelLastNode();
pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode();
pPam->Move( fnMoveBackward, fnGoNode );
pFlySave->nEndNd = pPam->GetPoint()->nNode;
pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex();
*pPam->GetPoint() = aPos;
}
}
else if( !bReadSwFly && !pFlySave->nEndCnt &&
pFlySave->nSttNd.GetIndex() + 1 == pFlySave->nEndNd.GetIndex() &&
pFlySave->nSttNd.GetNode().IsTxtNode() )
{
SwTxtNode* pTxtNd = pFlySave->nSttNd.GetNode().GetTxtNode();
SwTxtFlyCnt* pFlyCnt = 0;
if( 1 == pTxtNd->GetTxt().Len() &&
0 != (pFlyCnt = static_cast<SwTxtFlyCnt*>(
pTxtNd->GetTxtAttrForCharAt(0, RES_TXTATR_FLYCNT))) &&
pFlyCnt->GetFlyCnt().GetFrmFmt() )
{
// then move the content into the surrounded fly
SwFrmFmt* pFlyFmt = pFlyCnt->GetFlyCnt().GetFrmFmt();
const SwNodeIndex* pFlySNd = pFlyFmt->GetCntnt().GetCntntIdx();
SwNodeRange aRg( *pFlySNd, 1,
*pFlySNd->GetNode().EndOfSectionNode(), 0 );
// merge the itemsets
SwFmtFrmSize aSz1( (SwFmtFrmSize&)pFlyFmt->GetAttrSet().
Get( RES_FRM_SIZE ));
SwFmtFrmSize aSz2( (SwFmtFrmSize&)pFlySave->aFlySet.
Get( RES_FRM_SIZE ));
// if
if( !aRg.aStart.GetNode().IsNoTxtNode() ||
!aSz1.GetHeight() || !aSz1.GetWidth() ||
!aSz2.GetHeight() || !aSz2.GetWidth() ||
( aSz1.GetHeight() == aSz2.GetHeight() &&
aSz1.GetWidth() == aSz2.GetWidth() ) )
{
SfxItemSet aDiffs( pFlyFmt->GetAttrSet() );
aDiffs.ClearItem( RES_ANCHOR );
aDiffs.ClearItem( RES_FRM_SIZE );
aDiffs.ClearItem( RES_CNTNT );
aDiffs.Differentiate( pFlySave->aFlySet );
pFlySave->aFlySet.Put( aDiffs );
sal_Bool bSet = sal_False;
if( aSz1.GetHeight() && !aSz2.GetHeight() )
{
bSet = sal_True;
aSz2.SetHeight( aSz1.GetHeight() );
}
if( aSz1.GetWidth() && !aSz2.GetWidth() )
{
bSet = sal_True;
aSz2.SetWidth( aSz1.GetWidth() );
}
if( bSet )
pFlySave->aFlySet.Put( aSz2 );
// move any PageBreak/Desc Attr to the next Para
{
SwCntntNode* pSrcNd = pFlySave->nSttNd.GetNode().GetCntntNode();
SwCntntNode* pDstNd = pFlySave->nEndNd.GetNode().GetCntntNode();
::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nEndNd );
}
// create new txtnode, because the section does never be empty
pDoc->GetNodes().MakeTxtNode( aRg.aStart,
(SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
SwNodeIndex aTmp( pFlySave->nSttNd, +1 );
pDoc->MoveNodeRange( aRg, aTmp,
IDocumentContentOperations::DOC_MOVEDEFAULT );
// now delete the redundant txtnode
pDoc->GetNodes().Delete( pFlySave->nSttNd, 1 );
}
}
}
}
bReadSwFly = false;
SkipToken( -1 );
}
void SwRTFParser::InsPicture( const String& rGrfNm, const Graphic* pGrf,
const SvxRTFPictureType* pPicType )
{
// kennzeichen fuer Swg-Dokumente:
// (dann ist das FlyFmt fuer die Grafik!)
SwGrfNode * pGrfNd;
// --> OD 2008-12-22 #i83368#
// Assure that graphic node is enclosed by fly frame node.
// if( bReadSwFly )
if ( bReadSwFly && !mbReadCellWhileReadSwFly )
// <--
{
OSL_ENSURE(aFlyArr.Count(),
"SwRTFParser::InsPicture: fly array empty.");
if (aFlyArr.Count())
{
// erzeuge nur einen normalen GrafikNode und ersetze diesen gegen
// den vorhandenen Textnode
SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx,
rGrfNm, aEmptyStr, // Name der Graphic !!
pGrf,
(SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl() );
if( pGrfAttrSet )
pGrfNd->SetAttr( *pGrfAttrSet );
SwFlySave* pFlySave = aFlyArr[ aFlyArr.Count()-1 ];
pFlySave->nSttNd = rIdx.GetIndex() - 1;
if( 1 < aFlyArr.Count() )
{
pFlySave = aFlyArr[ aFlyArr.Count() - 2 ];
if( pFlySave->nEndNd == rIdx )
pFlySave->nEndNd = rIdx.GetIndex() - 1;
}
}
}
else
{
// wenn normale RTF-Grafik, dann steht diese im Textfluss !
SwAttrSet aFlySet( pDoc->GetAttrPool(), RES_OPAQUE, /*RES_OPAQUE,
RES_VERT_ORIENT,*/ RES_ANCHOR );
const SwPosition* pPos = pPam->GetPoint();
SwFmtAnchor aAnchor( FLY_AS_CHAR );
aAnchor.SetAnchor( pPos );
aFlySet.Put( aAnchor );
aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP ));
if (pDoc->IsInHeaderFooter(pPos->nNode))
{
SvxOpaqueItem aOpaqueItem(RES_OPAQUE, sal_False);
SwFmtSurround aSurroundItem(SURROUND_THROUGHT);
aFlySet.Put(aOpaqueItem);
aFlySet.Put(aSurroundItem);
}
SwFlyFrmFmt* pFlyFmt = pDoc->Insert( *pPam,
rGrfNm, aEmptyStr, // Name der Graphic !!
pGrf,
&aFlySet, // Attribute fuer den FlyFrm
pGrfAttrSet, NULL ); // Attribute fuer die Grafik
pGrfNd = pDoc->GetNodes()[ pFlyFmt->GetCntnt().GetCntntIdx()->
GetIndex()+1 ]->GetGrfNode();
_SetPictureSize( *pGrfNd, pPos->nNode,
(SfxItemSet&)pFlyFmt->GetAttrSet(),
pPicType );
if( pPicType )
{
PictPropertyNameValuePairs::const_iterator aIt = pPicType->aPropertyPairs.begin();
PictPropertyNameValuePairs::const_iterator aEnd = pPicType->aPropertyPairs.end();
while( aIt != aEnd)
{
if( aIt->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "wzDescription") ))
{
SwXFrame::GetOrCreateSdrObject( pFlyFmt );
pDoc->SetFlyFrmDescription( *(pFlyFmt), aIt->second );
}
else if( aIt->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "wzName") ))
{
SwXFrame::GetOrCreateSdrObject( pFlyFmt );
pDoc->SetFlyFrmTitle( *(pFlyFmt), aIt->second );
}
++aIt;
}
}
}
if( pGrfAttrSet )
DELETEZ( pGrfAttrSet );
}
void SwRTFParser::_SetPictureSize( const SwNoTxtNode& rNd,
const SwNodeIndex& rAnchor,
SfxItemSet& rSet,
const SvxRTFPictureType* pPicType )
{
Size aSize( ((SwNoTxtNode&)rNd).GetTwipSize() );
if( pPicType )
{
if( rNd.IsGrfNode() )
{
if( SvxRTFPictureType::WIN_METAFILE != pPicType->eStyle &&
pPicType->nGoalWidth && pPicType->nGoalHeight )
{
aSize.Width() = pPicType->nGoalWidth;
aSize.Height() =pPicType->nGoalHeight;
}
else if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle )
{
// IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !!
aSize.Width() = pPicType->nWidth * 20;
aSize.Height() = pPicType->nHeight * 20;
}
else
{
// von 100TH_MM nach TWIP umrechenen!
// #117879# when \picwgoal resp \pichgoal are present, then use them.
// The values of \picwgoal and \picwgoal are already given in twips.
aSize.Width() = (pPicType->nGoalWidth?pPicType->nGoalWidth:(pPicType->nWidth*144)/254);
aSize.Height() = (pPicType->nGoalHeight?pPicType->nGoalHeight:(pPicType->nHeight*144)/254);
}
((SwGrfNode&)rNd).SetTwipSize( aSize );
}
if( 100 != pPicType->nScalX )
aSize.Width() = (((long)pPicType->nScalX) * ( aSize.Width() -
( pPicType->nCropL + pPicType->nCropR ))) / 100L;
if( 100 != pPicType->nScalY )
aSize.Height() = (((long)pPicType->nScalY) * ( aSize.Height() -
( pPicType->nCropT + pPicType->nCropB ))) / 100L;
}
//steht der Fly etwa in einer Tabelle ?
const SwNode* pAnchorNd = & rAnchor.GetNode();
const SwTableNode* pTblNd = pAnchorNd->FindTableNode();
if( pTblNd )
{
// Box feststellen:
const SwTableBox* pBox = pTblNd->GetTable().GetTblBox(
pAnchorNd->StartOfSectionIndex() );
if( pBox )
{
long nBoxWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
if( aSize.Width() > nBoxWidth )
aSize.Width() = nBoxWidth;
}
}
//JP 8.11.2001: bug 94450 - if no size exist, then the size is set by
// the swapin of the graphic.
SwGrfNode* pGrfNd;
if( !aSize.Width() && !aSize.Height() &&
0 != (pGrfNd = (SwGrfNode*)rNd.GetGrfNode() ) && pGrfNd->IsGrfLink() )
pGrfNd->SetChgTwipSize( sal_True );
// min. Werte einhalten !!
if( aSize.Width() < MINFLY )
aSize.Width() = MINFLY;
if( aSize.Height() < MINFLY)
aSize.Height() = MINFLY;
if( pPicType )
{
sal_Bool bChg = sal_False;
SwCropGrf aCrop;
/*
JP 28.07.99: Bug 67800 - no crop by MAC_QUICKDRAW. At time i dont know why
it has been coded. But this has used for any
RTF-File, but i dont found them.
if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle )
{
// evt. ein wenig Croppen ??
// IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !!
long nTmp = pPicType->nWidth * 20;
if( nTmp != aSize.Width() )
{
// in der Breite (also rechts) croppen
aCrop.Right() = nTmp - aSize.Width();
aSize.Width() = nTmp;
bChg = sal_True;
}
nTmp = pPicType->nHeight * 20;
if( nTmp != aSize.Height() )
{
// in der Hoehe (also unten) croppen
aCrop.Bottom() = nTmp - aSize.Height();
aSize.Height() = nTmp;
bChg = sal_True;
}
}
*/
if( pPicType->nCropT )
{
aCrop.SetTop( pPicType->nCropT );
bChg = sal_True;
}
if( pPicType->nCropB )
{
aCrop.SetBottom( pPicType->nCropB );
bChg = sal_True;
}
if( pPicType->nCropL )
{
aCrop.SetLeft( pPicType->nCropL );
bChg = sal_True;
}
if( pPicType->nCropR )
{
aCrop.SetRight( pPicType->nCropR );
bChg = sal_True;
}
if( bChg )
{
// dann mal an die CropWerte an die GrafikSize anpassen.
((SwNoTxtNode&)rNd).SetAttr( aCrop );
}
}
rSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aSize.Width(), aSize.Height() ));
}
void SwRTFParser::GetPageSize( Size& rSize )
{
ASSERT(!maSegments.empty(), "not possible");
if (maSegments.empty())
{
rSize.Width() = 12240 - 1800 - 1800;
rSize.Height() = 15840 - 1440 - 1440;
return;
}
const rtfSection &rSect = maSegments.back();
rSize.Width() = rSect.maPageInfo.mnPgwsxn - rSect.maPageInfo.mnMarglsxn - rSect.maPageInfo.mnMargrsxn;
rSize.Height() = rSect.maPageInfo.mnPghsxn - rSect.maPageInfo.mnMargtsxn - rSect.maPageInfo.mnMargbsxn;
long nCols = rSect.NoCols();
if (1 < nCols)
{
rSize.Width() /= nCols;
rSize.Height() /= nCols;
}
}
void SwRTFParser::ReadBitmapData()
{
Graphic aGrf;
SvxRTFPictureType aPicType;
if( ReadBmpData( aGrf, aPicType ) )
InsPicture( aEmptyStr, &aGrf, &aPicType );
}
#ifdef READ_OLE_OBJECT
void SwRTFParser::ReadOLEData()
{
SvCacheStream aTmpFile( 0xA000 );
Graphic aGrf;
SvxRTFPictureType aPicType, aOleType;
int nToken, bValidOle = sal_True, bWeiter = sal_True;
int nOpenBrakets = 1; // die erste wurde schon vorher erkannt !!
String* pStr = 0;
String sObjClass, sObjName, sObjData;
while( nOpenBrakets && IsParserWorking() && bWeiter && bValidOle )
{
nToken = GetNextToken();
sal_uInt16 nVal = sal_uInt16( nTokenValue );
switch( nToken )
{
case '}': --nOpenBrakets; pStr = 0; break;
case '{':
{
if( RTF_IGNOREFLAG != GetNextToken() )
nToken = SkipToken( -1 );
else if( RTF_UNKNOWNCONTROL != GetNextToken() )
nToken = SkipToken( -2 );
else
{
// gleich herausfiltern
ReadUnknownData();
nToken = GetNextToken();
if( '}' != nToken )
eState = SVPAR_ERROR;
break;
}
++nOpenBrakets;
}
break;
case RTF_OBJECT:
case RTF_OBJEMB: // default ist embedded
case RTF_LINKSELF: // ??
case RTF_OBJLOCK: // ??
case RTF_OBJUPDATE: // ??
case RTF_OBJTIME: // ??
case RTF_OBJSETSIZE:
case RTF_OBJALIGN:
case RTF_OBJTRANSY:
case RTF_OBJATTPH:
break;
case RTF_OBJLINK: // ?? welche Daten sind das ??
case RTF_OBJAUTLINK: // ?? -""- ??
case RTF_OBJSUB:
case RTF_OBJPUB:
case RTF_OBJICEMB:
case RTF_OBJOCX:
case RTF_OBJHTML:
case RTF_OBJALIAS:
case RTF_OBJSECT:
bValidOle = sal_False; // diese Typen koennen wir nicht
break;
case RTF_OBJCLASS:
// Daten lesen
pStr = &sObjClass;
break;
case RTF_OBJNAME:
// Daten lesen
pStr = &sObjName;
break;
case RTF_OBJDATA:
pStr = &sObjData;
break;
case RTF_RESULT:
{
// hier weitermachen, wenn das OLE-Object ungueltig ist
bWeiter = sal_False;
}
break;
case RTF_RSLTBMP: // diese sollten wir ignorieren
case RTF_RSLTMERGE:
case RTF_RSLTPICT:
case RTF_RSLTRTF:
case RTF_RSLTTXT:
break;
case RTF_OBJW: aOleType.nWidth = nVal; break;
case RTF_OBJH: aOleType.nHeight = nVal; break;
case RTF_OBJCROPT: aOleType.nCropT = (short)nTokenValue; break;
case RTF_OBJCROPB: aOleType.nCropB = (short)nTokenValue; break;
case RTF_OBJCROPL: aOleType.nCropL = (short)nTokenValue; break;
case RTF_OBJCROPR: aOleType.nCropR = (short)nTokenValue; break;
case RTF_OBJSCALEX: aOleType.nScalX = nVal; break;
case RTF_OBJSCALEY: aOleType.nScalY = nVal; break;
case RTF_TEXTTOKEN:
if( 1 < nOpenBrakets && pStr )
{
if( pStr == &sObjData )
{
xub_StrLen nHexLen = HexToBin( aToken );
if( STRING_NOTFOUND != nHexLen )
bValidOle = sal_False;
else
{
aTmpFile.Write( (sal_Char*)aToken.GetBuffer(), nHexLen );
bValidOle = 0 == aTmpFile.GetError();
}
}
else
*pStr += aToken;
}
break;
}
}
if( bValidOle )
{
bValidOle = sal_False; // erstmal
}
if( !bWeiter ) // dann stehen wir noch im Result
{
// ist das Ole-Object Ok?
// -> dann solange SkipGroup rufen, bis zur letzten
// schliessenden Klammer
// ansonsten alle Token verarbeiten, bis zur letzten
// schliessenden Klammer
bWeiter = sal_True;
while( nOpenBrakets && IsParserWorking() && bWeiter )
{
switch( nToken = GetNextToken() )
{
case '}': --nOpenBrakets; break;
case '{': ++nOpenBrakets; break;
}
if( nOpenBrakets && !bValidOle )
NextToken( nToken );
}
}
if( !bValidOle && '}' != nToken )
SkipGroup();
SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
}
#endif
/* vi:set tabstop=4 shiftwidth=4 expandtab: */