diff options
Diffstat (limited to 'sw/source/filter/rtf/rtffly.cxx')
-rw-r--r-- | sw/source/filter/rtf/rtffly.cxx | 1634 |
1 files changed, 1634 insertions, 0 deletions
diff --git a/sw/source/filter/rtf/rtffly.cxx b/sw/source/filter/rtf/rtffly.cxx new file mode 100644 index 000000000000..c6131aa17251 --- /dev/null +++ b/sw/source/filter/rtf/rtffly.cxx @@ -0,0 +1,1634 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: rtffly.cxx,v $ + * $Revision: 1.35 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// 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 <svx/prntitem.hxx> +#include <svx/opaqitem.hxx> +#include <svx/protitem.hxx> +#include <svx/ulspitem.hxx> +#include <svx/lrspitem.hxx> +#include <svx/boxitem.hxx> +#include <svx/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 <deque> +#include <map> +#include <utility> +// --> OD 2004-06-30 #i27767# +#include <fmtwrapinfluenceonobjpos.hxx> +// <-- +#include <svx/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, BOOL bChk ); + +SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* ) + +inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, BOOL bInP=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 FALSE; + + // nur TextNodes zusammenfassen + if( nSttNd == nEndNd && nEndNd.GetNode().IsNoTxtNode() ) + return FALSE; + + // teste auf gleiche / naechste Position + if( rPos.GetPoint()->nNode.GetIndex() == nEndNd.GetIndex() ) + { + if( 1 < (rPos.GetPoint()->nContent.GetIndex() - nEndCnt) ) + return FALSE; + } + else if( rPos.GetPoint()->nContent.GetIndex() ) + return FALSE; + else + { + SwNodeIndex aIdx( nEndNd ); + SwCntntNode* pCNd = rPos.GetDoc()->GetNodes()[ aIdx ]->GetCntntNode(); + if( !GoNextNds( &aIdx, TRUE ) || + aIdx.GetIndex() != rPos.GetPoint()->nNode.GetIndex() || + ( pCNd && pCNd->Len() != nEndCnt )) + { + return FALSE; + } + } + + if( rSet.Count() ) + { + SfxItemIter aIter( rSet ); + const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem(); + while( TRUE ) + { + if( SFX_ITEM_SET != aFlySet.GetItemState( pCurr->Which(), + FALSE, &pItem ) || + // Ankerattribute gesondert behandeln + ( RES_ANCHOR == pCurr->Which() + ? (ANCHOR(pCurr)->GetAnchorId() != ANCHOR(pItem)->GetAnchorId() || + ANCHOR(pCurr)->GetPageNum() != ANCHOR(pItem)->GetPageNum()) + : *pItem != *pCurr )) + return FALSE; + + if( aIter.IsAtEnd() ) + break; + pCurr = aIter.NextItem(); + } + } + return 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() )); +} + +BOOL lcl_HasBreakAttrs( const SwCntntNode& rNd ) +{ + BOOL bRet = FALSE; + const SfxItemSet& rSet = rNd.GetSwAttrSet(); + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK, TRUE, &pItem ) && + SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() ) + bRet = TRUE; + else if( SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, TRUE, &pItem )&& + 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc() ) + bRet = 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, + FALSE, &pBreakItem ) ) + pBreakItem = 0; + + if( SFX_ITEM_SET != pSet->GetItemState( RES_PAGEDESC, + 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( USHORT 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 */ ) + { + ULONG nPos = pSttNd->GetIndex(); + SwDoc * pDoc1 = pSttNd->GetDoc(); + + 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() = (BYTE)pFlySave->nDropLines; + aDropCap.GetChars() = 1; + + SwIndex aIdx( pEndNd ); + pNd->RstAttr( 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( n + 1 < aFlyArr.Count() && pFlySave->nEndCnt && + pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd ) + { + SwCntntNode* pCNd = rNds[ pFlySave->nEndNd ]->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, 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(); + 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, 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, FALSE); + if( pSrcNd && pSrcNd->HasSwAttrSet() ) + aTmpSet.Put( *pSrcNd->GetpSwAttrSet() ); + if (pBackgroundBrush) + { + aTmpSet.Put(*pBackgroundBrush, RES_BACKGROUND); + } + else + { + pBackgroundBrush = (const SvxBrushItem*)aTmpSet.GetItem(RES_BACKGROUND, 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 ); + + USHORT nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0; + SvUShorts aColumns; + + BOOL bChkDropCap = 0 == pSet; + USHORT 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 = TRUE; + int nAppliedProps=0; + do { + USHORT nVal = USHORT(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, 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, 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( TRUE ); + break; + case RTF_POSXO: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); + aHori.SetPosToggle( 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 = USHORT( nTokenValue ); + if( !nDropCapAnchor ) + nDropCapAnchor = 1; + } + break; + case RTF_DROPCAPT: + if( bChkDropCap ) + { + nDropCapAnchor = USHORT( nTokenValue ); + if( !nDropCapLines ) + nDropCapLines = 3; + } + break; + + + // fuer die "alten" Writer - haben die Spaltigkeit falsch heraus- + // geschrieben + case RTF_COLS: nCols = USHORT( nTokenValue ); break; + case RTF_COLSX: nColSpace = USHORT( nTokenValue ); break; + case RTF_COLNO: + nAktCol = USHORT( nTokenValue ); + if( RTF_COLW == GetNextToken() ) + { + USHORT nWidth = USHORT( nTokenValue ), nSpace = 0; + if( RTF_COLSR == GetNextToken() ) + nSpace = USHORT( 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 = USHORT(nTokenValue); + switch( nToken ) + { + // Swg-Frame-Tokens + case RTF_FLYPRINT: + { + pSet->Put( SvxPrintItem( RES_PRINT, FALSE )); + } + break; + case RTF_FLYOPAQUE: + { + pSet->Put( SvxOpaqueItem( RES_OPAQUE, FALSE )); + } + break; + + case RTF_FLYPRTCTD: + { + RTFProtect aP( (BYTE)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( (BYTE)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( USHORT(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 = USHORT( nTokenValue ); break; + case RTF_COLSX: nColSpace = USHORT( nTokenValue ); break; + case RTF_COLNO: + nAktCol = USHORT( nTokenValue ); + if( RTF_COLW == GetNextToken() ) + { + USHORT nWidth = USHORT( nTokenValue ), nSpace = 0; + if( RTF_COLSR == GetNextToken() ) + nSpace = USHORT( 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 = TRUE; + switch( nToken = GetNextToken() ) + { + case RTF_SHADOW: + case RTF_BRDBOX: + ReadAttr( SkipToken( -2 ), &aSet ); + bSkipGrp = FALSE; + break; + + case RTF_BRDRT: + case RTF_BRDRB: + case RTF_BRDRR: + case RTF_BRDRL: + bSkipGrp = 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 = FALSE; + } + } + break; + + default: + --nAppliedProps; //Not sufficient to make a frame + bWeiter = 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( 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; + + ULONG nWidth = USHRT_MAX; + aCol.Init( nCols, nColSpace, USHORT( nWidth ) ); + if( nCols == ( aColumns.Count() / 2 ) ) + { + for( USHORT n = 0, i = 0; n < aColumns.Count(); n += 2, ++i ) + { + SwColumn* pCol = aCol.GetColumns()[ i ]; + ULONG nTmp = aColumns[ n ]; + nTmp *= USHRT_MAX; + nTmp /= nWidth; + pCol->SetWishWidth( USHORT(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( USHORT(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; + USHORT 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( 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) + { + USHORT _index=USHORT(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 + { + 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 = (SwTxtFlyCnt*)pTxtNd->GetTxtAttr( + 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 ); + + BOOL bSet = FALSE; + if( aSz1.GetHeight() && !aSz2.GetHeight() ) + { + bSet = TRUE; + aSz2.SetHeight( aSz1.GetHeight() ); + } + if( aSz1.GetWidth() && !aSz2.GetWidth() ) + { + bSet = 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 ) + // <-- + { + // 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, FALSE); + SwFmtSurround aSurroundItem(SURROUND_THROUGHT); + aFlySet.Put(aOpaqueItem); + aFlySet.Put(aSurroundItem); + } + + SwFrmFmt* 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( 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 = pDoc->GetNodes()[ rAnchor ]; + 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( TRUE ); + + // min. Werte einhalten !! + if( aSize.Width() < MINFLY ) + aSize.Width() = MINFLY; + if( aSize.Height() < MINFLY) + aSize.Height() = MINFLY; + + if( pPicType ) + { + BOOL bChg = 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 = TRUE; + } + + nTmp = pPicType->nHeight * 20; + if( nTmp != aSize.Height() ) + { + // in der Hoehe (also unten) croppen + aCrop.Bottom() = nTmp - aSize.Height(); + aSize.Height() = nTmp; + bChg = TRUE; + } + } +*/ + if( pPicType->nCropT ) + { + aCrop.SetTop( pPicType->nCropT ); + bChg = TRUE; + } + if( pPicType->nCropB ) + { + aCrop.SetBottom( pPicType->nCropB ); + bChg = TRUE; + } + if( pPicType->nCropL ) + { + aCrop.SetLeft( pPicType->nCropL ); + bChg = TRUE; + } + if( pPicType->nCropR ) + { + aCrop.SetRight( pPicType->nCropR ); + bChg = 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 = TRUE, bWeiter = TRUE; + int nOpenBrakets = 1; // die erste wurde schon vorher erkannt !! + + String* pStr = 0; + String sObjClass, sObjName, sObjData; + + while( nOpenBrakets && IsParserWorking() && bWeiter && bValidOle ) + { + nToken = GetNextToken(); + USHORT nVal = USHORT( 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 = 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 = 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 = FALSE; + else + { + aTmpFile.Write( (sal_Char*)aToken.GetBuffer(), nHexLen ); + bValidOle = 0 == aTmpFile.GetError(); + } + } + else + *pStr += aToken; + } + break; + } + } + + if( bValidOle ) + { + bValidOle = 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 = 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: */ |