diff options
Diffstat (limited to 'sw/source/core/frmedt')
-rw-r--r-- | sw/source/core/frmedt/fecopy.cxx | 1551 | ||||
-rw-r--r-- | sw/source/core/frmedt/fedesc.cxx | 291 | ||||
-rw-r--r-- | sw/source/core/frmedt/fefly1.cxx | 2156 | ||||
-rw-r--r-- | sw/source/core/frmedt/feflyole.cxx | 150 | ||||
-rw-r--r-- | sw/source/core/frmedt/feshview.cxx | 3237 | ||||
-rw-r--r-- | sw/source/core/frmedt/fetab.cxx | 2593 | ||||
-rw-r--r-- | sw/source/core/frmedt/fews.cxx | 1296 | ||||
-rw-r--r-- | sw/source/core/frmedt/makefile.mk | 76 | ||||
-rw-r--r-- | sw/source/core/frmedt/tblsel.cxx | 2728 |
9 files changed, 14078 insertions, 0 deletions
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx new file mode 100644 index 000000000000..9fe5c9a22204 --- /dev/null +++ b/sw/source/core/frmedt/fecopy.cxx @@ -0,0 +1,1551 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <hintids.hxx> + +#include <vcl/graph.hxx> +#include <sot/formats.hxx> +#include <sot/storage.hxx> +#include <unotools/pathoptions.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewsh.hxx> +#include <svx/xexch.hxx> +#include <svx/xflasit.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <editeng/brshitem.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdouno.hxx> +#include <svx/xfillit.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdogrp.hxx> +#include <svx/xoutbmp.hxx> +#include <svx/svdoole2.hxx> +#include <svx/fmmodel.hxx> +#include <svx/unomodel.hxx> +// --> OD 2005-08-03 #i50824# +#include <svx/svditer.hxx> +// <-- +// --> OD 2006-03-01 #b6382898# +#include <svx/svdograf.hxx> +// <-- +#include <unotools/streamwrap.hxx> +#include <fmtanchr.hxx> +#include <fmtcntnt.hxx> +#include <fmtornt.hxx> +#include <fmtflcnt.hxx> +#include <frmfmt.hxx> +#include <docary.hxx> +#include <txtfrm.hxx> +#include <txtflcnt.hxx> +#include <fesh.hxx> +#include <doc.hxx> +#include <rootfrm.hxx> +#include <ndtxt.hxx> +#include <pam.hxx> +#include <tblsel.hxx> +#include <swtable.hxx> +#include <flyfrm.hxx> +#include <pagefrm.hxx> +#include <fldbas.hxx> +#include <edimp.hxx> +#include <swundo.hxx> +#include <viewimp.hxx> +#include <dview.hxx> +#include <dcontact.hxx> +#include <dflyobj.hxx> +#include <docsh.hxx> +#include <pagedesc.hxx> +#include <mvsave.hxx> +#include <vcl/virdev.hxx> + + +using namespace ::com::sun::star; + +/************************************************************************* +|* +|* SwFEShell::Copy() Copy fuer das Interne Clipboard. +|* Kopiert alle Selektionen in das Clipboard. +|* +|* Ersterstellung JP ?? +|* Letzte Aenderung MA 22. Feb. 95 +| +|*************************************************************************/ + +BOOL SwFEShell::Copy( SwDoc* pClpDoc, const String* pNewClpTxt ) +{ + ASSERT( pClpDoc, "kein Clipboard-Dokument" ); + + pClpDoc->DoUndo( FALSE ); // immer auf FALSE !! + + // steht noch Inhalt im ClpDocument, dann muss dieser geloescht werden + SwNodeIndex aSttIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 ); + SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode(); + if( !pTxtNd || pTxtNd->GetTxt().Len() || + aSttIdx.GetIndex()+1 != pClpDoc->GetNodes().GetEndOfContent().GetIndex() ) + { + pClpDoc->GetNodes().Delete( aSttIdx, + pClpDoc->GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() ); + pTxtNd = pClpDoc->GetNodes().MakeTxtNode( aSttIdx, + (SwTxtFmtColl*)pClpDoc->GetDfltTxtFmtColl() ); + aSttIdx--; + } + + // stehen noch FlyFrames rum, loesche auch diese + for( USHORT n = 0; n < pClpDoc->GetSpzFrmFmts()->Count(); ++n ) + { + SwFlyFrmFmt* pFly = (SwFlyFrmFmt*)(*pClpDoc->GetSpzFrmFmts())[n]; + pClpDoc->DelLayoutFmt( pFly ); + } + pClpDoc->GCFieldTypes(); // loesche die FieldTypes + + // wurde ein String uebergeben, so kopiere diesen in das Clipboard- + // Dokument. Somit kann auch der Calculator das interne Clipboard + // benutzen. + if( pNewClpTxt ) + { + pTxtNd->InsertText( *pNewClpTxt, SwIndex( pTxtNd ) ); + return TRUE; // das wars. + } + + pClpDoc->LockExpFlds(); + pClpDoc->SetRedlineMode_intern( nsRedlineMode_t::REDLINE_DELETE_REDLINES ); + BOOL bRet; + + // soll ein FlyFrame kopiert werden ? + if( IsFrmSelected() ) + { + // hole das FlyFormat + SwFlyFrm* pFly = FindFlyFrm(); + SwFrmFmt* pFlyFmt = pFly->GetFmt(); + SwFmtAnchor aAnchor( pFlyFmt->GetAnchor() ); + + if ((FLY_AT_PARA == aAnchor.GetAnchorId()) || + (FLY_AT_CHAR == aAnchor.GetAnchorId()) || + (FLY_AT_FLY == aAnchor.GetAnchorId()) || + (FLY_AS_CHAR == aAnchor.GetAnchorId())) + { + SwPosition aPos( aSttIdx ); + if ( FLY_AS_CHAR == aAnchor.GetAnchorId() ) + { + aPos.nContent.Assign( pTxtNd, 0 ); + } + aAnchor.SetAnchor( &aPos ); + } + pFlyFmt = pClpDoc->CopyLayoutFmt( *pFlyFmt, aAnchor, true, true ); + + // sorge dafuer das das "RootFmt" als erstes im SpzArray-steht + // (Es wurden ggf. Flys in Flys kopiert. + SwSpzFrmFmts& rSpzFrmFmts = *(SwSpzFrmFmts*)pClpDoc->GetSpzFrmFmts(); + if( rSpzFrmFmts[ 0 ] != pFlyFmt ) + { + USHORT nPos = rSpzFrmFmts.GetPos( pFlyFmt ); + ASSERT( nPos != USHRT_MAX, "Fly steht nicht im Spz-Array" ); + + rSpzFrmFmts.Remove( nPos ); + rSpzFrmFmts.Insert( pFlyFmt, 0 ); + } + + if ( FLY_AS_CHAR == aAnchor.GetAnchorId() ) + { + // JP 13.02.99 Bug 61863: wenn eine Rahmenselektion ins Clipboard + // gestellt wird, so muss beim Pasten auch wieder + // eine solche vorgefunden werden. Also muss im Node + // das kopierte TextAttribut wieder entfernt werden, + // sonst wird es als TextSelektion erkannt + const SwIndex& rIdx = pFlyFmt->GetAnchor().GetCntntAnchor()->nContent; + SwTxtFlyCnt *const pTxtFly = static_cast<SwTxtFlyCnt *>( + pTxtNd->GetTxtAttrForCharAt( + rIdx.GetIndex(), RES_TXTATR_FLYCNT)); + if( pTxtFly ) + { + ((SwFmtFlyCnt&)pTxtFly->GetFlyCnt()).SetFlyFmt( 0 ); + pTxtNd->EraseText( rIdx, 1 ); + } + } + bRet = TRUE; + } + else if ( IsObjSelected() ) + { + SwPosition aPos( aSttIdx, SwIndex( pTxtNd, 0 )); + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + + if( Imp()->GetDrawView()->IsGroupEntered() || + ( !pObj->GetUserCall() && pObj->GetUpGroup()) ) + { + SfxItemSet aSet( pClpDoc->GetAttrPool(), aFrmFmtSetRange ); + + SwFmtAnchor aAnchor( FLY_AT_PARA ); + aAnchor.SetAnchor( &aPos ); + aSet.Put( aAnchor ); + + SdrObject *const pNew = + pClpDoc->CloneSdrObj( *pObj, FALSE, TRUE ); + + SwPaM aTemp(aPos); + pClpDoc->Insert(aTemp, *pNew, &aSet, NULL); + } + else + { + SwDrawContact *pContact = (SwDrawContact*)GetUserCall( pObj ); + SwFrmFmt *pFmt = pContact->GetFmt(); + SwFmtAnchor aAnchor( pFmt->GetAnchor() ); + if ((FLY_AT_PARA == aAnchor.GetAnchorId()) || + (FLY_AT_CHAR == aAnchor.GetAnchorId()) || + (FLY_AT_FLY == aAnchor.GetAnchorId()) || + (FLY_AS_CHAR == aAnchor.GetAnchorId())) + { + aAnchor.SetAnchor( &aPos ); + } + + pClpDoc->CopyLayoutFmt( *pFmt, aAnchor, true, true ); + } + } + bRet = TRUE; + } + else + bRet = _CopySelToDoc( pClpDoc, 0 ); // kopiere die Selectionen + + pClpDoc->SetRedlineMode_intern((RedlineMode_t)0 ); + pClpDoc->UnlockExpFlds(); + if( !pClpDoc->IsExpFldsLocked() ) + pClpDoc->UpdateExpFlds(NULL, true); + + return bRet; +} + +const Point &lcl_FindBasePos( const SwFrm *pFrm, const Point &rPt ) +{ + const SwFrm *pF = pFrm; + while ( pF && !pF->Frm().IsInside( rPt ) ) + { + if ( pF->IsCntntFrm() ) + pF = ((SwCntntFrm*)pF)->GetFollow(); + else + pF = 0; + } + if ( pF ) + return pF->Frm().Pos(); + else + return pFrm->Frm().Pos(); +} + +BOOL lcl_SetAnchor( const SwPosition& rPos, const SwNode& rNd, SwFlyFrm* pFly, + const Point& rInsPt, SwFEShell& rDestShell, SwFmtAnchor& rAnchor, + Point& rNewPos, BOOL bCheckFlyRecur ) +{ + BOOL bRet = TRUE; + rAnchor.SetAnchor( &rPos ); + SwCntntFrm* pTmpFrm = rNd.GetCntntNode()->GetFrm( &rInsPt, 0, FALSE ); + SwFlyFrm *pTmpFly = pTmpFrm->FindFlyFrm(); + if( pTmpFly && bCheckFlyRecur && pFly->IsUpperOf( *pTmpFly ) ) + { + bRet = FALSE; + } + else if ( FLY_AT_FLY == rAnchor.GetAnchorId() ) + { + if( pTmpFly ) + { + const SwNodeIndex& rIdx = *pTmpFly->GetFmt()->GetCntnt().GetCntntIdx(); + SwPosition aPos( rIdx ); + rAnchor.SetAnchor( &aPos ); + rNewPos = pTmpFly->Frm().Pos(); + } + else + { + rAnchor.SetType( FLY_AT_PAGE ); + rAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) ); + const SwFrm *pPg = pTmpFrm->FindPageFrm(); + rNewPos = pPg->Frm().Pos(); + } + } + else + rNewPos = ::lcl_FindBasePos( pTmpFrm, rInsPt ); + return bRet; +} + +BOOL SwFEShell::CopyDrawSel( SwFEShell* pDestShell, const Point& rSttPt, + const Point& rInsPt, BOOL bIsMove, BOOL bSelectInsert ) +{ + BOOL bRet = TRUE; + + //Die Liste muss kopiert werden, weil unten die neuen Objekte + //selektiert werden. + const SdrMarkList aMrkList( Imp()->GetDrawView()->GetMarkedObjectList() ); + ULONG nMarkCount = aMrkList.GetMarkCount(); + if( !pDestShell->Imp()->GetDrawView() ) + // sollte mal eine erzeugt werden + pDestShell->MakeDrawView(); + else if( bSelectInsert ) + pDestShell->Imp()->GetDrawView()->UnmarkAll(); + + SdrPageView *pDestPgView = pDestShell->Imp()->GetPageView(), + *pSrcPgView = Imp()->GetPageView(); + SwDrawView *pDestDrwView = pDestShell->Imp()->GetDrawView(), + *pSrcDrwView = Imp()->GetDrawView(); + SwDoc* pDestDoc = pDestShell->GetDoc(); + + Size aSiz( rInsPt.X() - rSttPt.X(), rInsPt.Y() - rSttPt.Y() ); + for( USHORT i = 0; i < nMarkCount; ++i ) + { + SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj(); + + SwDrawContact *pContact = (SwDrawContact*)GetUserCall( pObj ); + SwFrmFmt *pFmt = pContact->GetFmt(); + const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); + + BOOL bInsWithFmt = TRUE; + + if( pDestDrwView->IsGroupEntered() ) + { + // in die Gruppe einfuegen, wenns aus einer betretenen Gruppe + // kommt oder das Object nicht zeichengebunden ist + if( pSrcDrwView->IsGroupEntered() || + (FLY_AS_CHAR != rAnchor.GetAnchorId()) ) + + { + SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove && + GetDoc() == pDestDoc, FALSE ); + pNew->NbcMove( aSiz ); + pDestDrwView->InsertObjectAtView( pNew, *pDestPgView ); + bInsWithFmt = FALSE; + } + } + + if( bInsWithFmt ) + { + SwFmtAnchor aAnchor( rAnchor ); + Point aNewAnch; + + if ((FLY_AT_PARA == aAnchor.GetAnchorId()) || + (FLY_AT_CHAR == aAnchor.GetAnchorId()) || + (FLY_AT_FLY == aAnchor.GetAnchorId()) || + (FLY_AS_CHAR == aAnchor.GetAnchorId())) + { + if ( this == pDestShell ) + { + //gleiche Shell? Dann erfrage die Position an der + //uebergebenen DokumentPosition + SwPosition aPos( *GetCrsr()->GetPoint() ); + Point aPt( rInsPt ); + aPt -= rSttPt - pObj->GetSnapRect().TopLeft(); + SwCrsrMoveState aState( MV_SETONLYTEXT ); + GetLayout()->GetCrsrOfst( &aPos, aPt, &aState ); + const SwNode *pNd; + if( (pNd = &aPos.nNode.GetNode())->IsNoTxtNode() ) + bRet = FALSE; + else + bRet = ::lcl_SetAnchor( aPos, *pNd, 0, rInsPt, + *pDestShell, aAnchor, aNewAnch, FALSE ); + } + else + { + SwPaM *pCrsr = pDestShell->GetCrsr(); + if( pCrsr->GetNode()->IsNoTxtNode() ) + bRet = FALSE; + else + bRet = ::lcl_SetAnchor( *pCrsr->GetPoint(), + *pCrsr->GetNode(), 0, rInsPt, + *pDestShell, aAnchor, + aNewAnch, FALSE ); + } + } + else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() ) + { + aAnchor.SetPageNum( pDestShell->GetPageNumber( rInsPt ) ); + const SwRootFrm* pTmpRoot = pDestShell->GetLayout(); + const SwFrm* pPg = pTmpRoot->GetPageAtPos( rInsPt, 0, true ); + if ( pPg ) + aNewAnch = pPg->Frm().Pos(); + } + + if( bRet ) + { + if( pSrcDrwView->IsGroupEntered() || + ( !pObj->GetUserCall() && pObj->GetUpGroup()) ) + { + SfxItemSet aSet( pDestDoc->GetAttrPool(),aFrmFmtSetRange); + aSet.Put( aAnchor ); + SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove && + GetDoc() == pDestDoc, TRUE ); + pFmt = pDestDoc->Insert( *pDestShell->GetCrsr(), + *pNew, &aSet, NULL ); + } + else + pFmt = pDestDoc->CopyLayoutFmt( *pFmt, aAnchor, true, true ); + + //Kann 0 sein, weil Draws in Kopf-/Fusszeilen nicht erlaubt sind. + if ( pFmt ) + { + SdrObject* pNew = pFmt->FindSdrObject(); + if ( FLY_AS_CHAR != aAnchor.GetAnchorId() ) + { + Point aPos( rInsPt ); + aPos -= aNewAnch; + aPos -= rSttPt - pObj->GetSnapRect().TopLeft(); + // OD 2004-04-05 #i26791# - change attributes instead of + // direct positioning + pFmt->SetFmtAttr( SwFmtHoriOrient( aPos.X(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ) ); + pFmt->SetFmtAttr( SwFmtVertOrient( aPos.Y(), text::VertOrientation::NONE, text::RelOrientation::FRAME ) ); + // --> OD 2005-04-15 #i47455# - notify draw frame format + // that position attributes are already set. + if ( pFmt->ISA(SwDrawFrmFmt) ) + { + static_cast<SwDrawFrmFmt*>(pFmt)->PosAttrSet(); + } + // <-- + } + if( bSelectInsert ) + pDestDrwView->MarkObj( pNew, pDestPgView ); + } + } + } + } + + if ( bIsMove && bRet ) + { + if( pDestShell == this ) + { + const SdrMarkList aList( pSrcDrwView->GetMarkedObjectList() ); + pSrcDrwView->UnmarkAll(); + + ULONG nMrkCnt = aMrkList.GetMarkCount(); + USHORT i; + for ( i = 0; i < nMrkCnt; ++i ) + { + SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj(); + pSrcDrwView->MarkObj( pObj, pSrcPgView ); + } + DelSelectedObj(); + nMrkCnt = aList.GetMarkCount(); + for ( i = 0; i < nMrkCnt; ++i ) + { + SdrObject *pObj = aList.GetMark( i )->GetMarkedSdrObj(); + pSrcDrwView->MarkObj( pObj, pSrcPgView ); + } + } + else + DelSelectedObj(); + } + + return bRet; +} + +BOOL SwFEShell::Copy( SwFEShell* pDestShell, const Point& rSttPt, + const Point& rInsPt, BOOL bIsMove, BOOL bSelectInsert ) +{ + BOOL bRet = FALSE; + + ASSERT( pDestShell, "Copy ohne DestShell." ); + ASSERT( this == pDestShell || !pDestShell->IsObjSelected(), + "Dest-Shell darf nie im Obj-Modus sein" ); + + SET_CURR_SHELL( pDestShell ); + + pDestShell->StartAllAction(); + pDestShell->GetDoc()->LockExpFlds(); + + // Referenzen sollen verschoben werden. + BOOL bCopyIsMove = pDoc->IsCopyIsMove(); + if( bIsMove ) + // am Doc ein Flag setzen, damit in den TextNodes + pDoc->SetCopyIsMove( TRUE ); + + RedlineMode_t eOldRedlMode = pDestShell->GetDoc()->GetRedlineMode(); + pDestShell->GetDoc()->SetRedlineMode_intern( (RedlineMode_t)(eOldRedlMode | nsRedlineMode_t::REDLINE_DELETE_REDLINES)); + + // sind Tabellen-Formeln im Bereich, dann muss erst die Tabelle + // angezeigt werden, damit die Tabellen-Formel den neuen Wert errechnen + // kann (bei Bereichen wird sich ueber das Layout die einzelnen Boxen + // besorgt) + SwFieldType* pTblFldTyp = pDestShell->GetDoc()->GetSysFldType( RES_TABLEFLD ); + + if( IsFrmSelected() ) + { + SwFlyFrm* pFly = FindFlyFrm(); + SwFrmFmt* pFlyFmt = pFly->GetFmt(); + SwFmtAnchor aAnchor( pFlyFmt->GetAnchor() ); + bRet = TRUE; + Point aNewAnch; + + if ((FLY_AT_PARA == aAnchor.GetAnchorId()) || + (FLY_AT_CHAR == aAnchor.GetAnchorId()) || + (FLY_AT_FLY == aAnchor.GetAnchorId()) || + (FLY_AS_CHAR == aAnchor.GetAnchorId())) + { + if ( this == pDestShell ) + { + // gleiche Shell? Dann erfrage die Position an der + // uebergebenen DokumentPosition + SwPosition aPos( *GetCrsr()->GetPoint() ); + Point aPt( rInsPt ); + aPt -= rSttPt - pFly->Frm().Pos(); + SwCrsrMoveState aState( MV_SETONLYTEXT ); + GetLayout()->GetCrsrOfst( &aPos, aPt, &aState ); + const SwNode *pNd; + if( (pNd = &aPos.nNode.GetNode())->IsNoTxtNode() ) + bRet = FALSE; + else + { //Nicht in sich selbst kopieren + const SwNodeIndex *pTmp = pFlyFmt->GetCntnt().GetCntntIdx(); + if ( aPos.nNode > *pTmp && aPos.nNode < + pTmp->GetNode().EndOfSectionIndex() ) + { + bRet = FALSE; + } + else + bRet = ::lcl_SetAnchor( aPos, *pNd, pFly, rInsPt, + *pDestShell, aAnchor, aNewAnch, TRUE ); + } + } + else + { + const SwPaM *pCrsr = pDestShell->GetCrsr(); + if( pCrsr->GetNode()->IsNoTxtNode() ) + bRet = FALSE; + else + bRet = ::lcl_SetAnchor( *pCrsr->GetPoint(), *pCrsr->GetNode(), + pFly, rInsPt, *pDestShell, aAnchor, + aNewAnch, GetDoc() == pDestShell->GetDoc()); + } + } + else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() ) + { + aAnchor.SetPageNum( pDestShell->GetPageNumber( rInsPt ) ); + const SwRootFrm* pTmpRoot = pDestShell->GetLayout(); + const SwFrm* pPg = pTmpRoot->GetPageAtPos( rInsPt, 0, true ); + if ( pPg ) + aNewAnch = pPg->Frm().Pos(); + } + else { + ASSERT( !this, "was fuer ein Anchor ist es denn?" ); + } + + if( bRet ) + { + SwFrmFmt *pOldFmt = pFlyFmt; + pFlyFmt = pDestShell->GetDoc()->CopyLayoutFmt( *pFlyFmt, aAnchor, true, true ); + + if ( FLY_AS_CHAR != aAnchor.GetAnchorId() ) + { + Point aPos( rInsPt ); + aPos -= aNewAnch; + aPos -= rSttPt - pFly->Frm().Pos(); + pFlyFmt->SetFmtAttr( SwFmtHoriOrient( aPos.X(),text::HoriOrientation::NONE, text::RelOrientation::FRAME ) ); + pFlyFmt->SetFmtAttr( SwFmtVertOrient( aPos.Y(),text::VertOrientation::NONE, text::RelOrientation::FRAME ) ); + } + + const Point aPt( pDestShell->GetCrsrDocPos() ); + + if( bIsMove ) + GetDoc()->DelLayoutFmt( pOldFmt ); + + // nur selektieren wenn es in der gleichen Shell verschoben/ + // kopiert wird + if( bSelectInsert ) + { + SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aPt, FALSE ); + if( pFlyFrm ) + { + //JP 12.05.98: sollte das nicht im SelectFlyFrm stehen??? + pDestShell->Imp()->GetDrawView()->UnmarkAll(); + pDestShell->SelectFlyFrm( *pFlyFrm, TRUE ); + } + } + + if( this != pDestShell && !pDestShell->HasShFcs() ) + pDestShell->Imp()->GetDrawView()->hideMarkHandles(); + } + } + else if ( IsObjSelected() ) + bRet = CopyDrawSel( pDestShell, rSttPt, rInsPt, bIsMove, bSelectInsert ); + else if( IsTableMode() ) + { + // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der Breite + // von der Originalen an und kopiere die selectierten Boxen. + // Die Groessen werden prozentual korrigiert. + + // lasse ueber das Layout die Boxen suchen + const SwTableNode* pTblNd; + SwSelBoxes aBoxes; + GetTblSel( *this, aBoxes ); + if( aBoxes.Count() && + 0 != (pTblNd = aBoxes[0]->GetSttNd()->FindTableNode()) ) + { + SwPosition* pDstPos = 0; + if( this == pDestShell ) + { + // gleiche Shell? Dann erzeuge einen Crsr an der + // uebergebenen DokumentPosition + pDstPos = new SwPosition( *GetCrsr()->GetPoint() ); + Point aPt( rInsPt ); + GetLayout()->GetCrsrOfst( pDstPos, aPt ); + if( !pDstPos->nNode.GetNode().IsNoTxtNode() ) + bRet = TRUE; + } + else if( !pDestShell->GetCrsr()->GetNode()->IsNoTxtNode() ) + { + pDstPos = new SwPosition( *pDestShell->GetCrsr()->GetPoint() ); + bRet = TRUE; + } + + if( bRet ) + { + if( GetDoc() == pDestShell->GetDoc() ) + ParkTblCrsr(); + + bRet = pDestShell->GetDoc()->InsCopyOfTbl( *pDstPos, aBoxes,0, + bIsMove && this == pDestShell && + aBoxes.Count() == pTblNd->GetTable(). + GetTabSortBoxes().Count(), + this != pDestShell ); + + if( this != pDestShell ) + *pDestShell->GetCrsr()->GetPoint() = *pDstPos; + + // wieder alle geparkten Crsr erzeugen? + if( GetDoc() == pDestShell->GetDoc() ) + GetCrsr(); + + // JP 16.04.99: Bug 64908 - InsPos setzen, damit der geparkte + // Cursor auf die EinfuegePos. positioniert wird + if( this == pDestShell ) + GetCrsrDocPos() = rInsPt; + } + delete pDstPos; + } + } + else + { + bRet = TRUE; + if( this == pDestShell ) + { + // gleiche Shell? Dann erfrage die Position an der + // uebergebenen DokumentPosition + SwPosition aPos( *GetCrsr()->GetPoint() ); + Point aPt( rInsPt ); + GetLayout()->GetCrsrOfst( &aPos, aPt ); + bRet = !aPos.nNode.GetNode().IsNoTxtNode(); + } + else if( pDestShell->GetCrsr()->GetNode()->IsNoTxtNode() ) + bRet = FALSE; + + if( bRet ) + bRet = 0 != SwEditShell::Copy( pDestShell ); + } + + pDestShell->GetDoc()->SetRedlineMode_intern( eOldRedlMode ); + pDoc->SetCopyIsMove( bCopyIsMove ); + + // wurden neue Tabellenformeln eingefuegt ? + if( pTblFldTyp->GetDepends() ) + { + // alte Actions beenden; die Tabellen-Frames werden angelegt und + // eine SSelection kann erzeugt werden + USHORT nActCnt; + for( nActCnt = 0; pDestShell->ActionPend(); ++nActCnt ) + pDestShell->EndAllAction(); + + for( ; nActCnt; --nActCnt ) + pDestShell->StartAllAction(); + } + pDestShell->GetDoc()->UnlockExpFlds(); + pDestShell->GetDoc()->UpdateFlds(NULL, false); + + pDestShell->EndAllAction(); + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::Paste() Paste fuer das Interne Clipboard. +|* Kopiert den Inhalt vom Clipboard in das Dokument. +|* +|* Ersterstellung JP ?? +|* Letzte Aenderung MA 22. Feb. 95 +| +|*************************************************************************/ + +namespace { + typedef boost::shared_ptr<SwPaM> PaMPtr; + typedef boost::shared_ptr<SwPosition> PositionPtr; + typedef std::pair< PaMPtr, PositionPtr > Insertion; +} + +BOOL SwFEShell::Paste( SwDoc* pClpDoc, BOOL bIncludingPageFrames ) +{ + SET_CURR_SHELL( this ); + ASSERT( pClpDoc, "kein Clipboard-Dokument" ); + const USHORT nStartPageNumber = GetPhyPageNum(); + // dann bis zum Ende vom Nodes Array + SwNodeIndex aIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 ); + SwPaM aCpyPam( aIdx ); //DocStart + + // sind Tabellen-Formeln im Bereich, dann muss erst die Tabelle + // angezeigt werden, damit die Tabellen-Formel den neuen Wert errechnen + // kann (bei Bereichen wird sich ueber das Layout die einzelnen Boxen + // besorgt) + SwFieldType* pTblFldTyp = GetDoc()->GetSysFldType( RES_TABLEFLD ); + + SwTableNode *pDestNd, *pSrcNd = aCpyPam.GetNode()->GetTableNode(); + if( !pSrcNd ) // TabellenNode ? + { // nicht ueberspringen!! + SwCntntNode* pCNd = aCpyPam.GetNode()->GetCntntNode(); + if( pCNd ) + aCpyPam.GetPoint()->nContent.Assign( pCNd, 0 ); + else if( !aCpyPam.Move( fnMoveForward, fnGoNode )) + aCpyPam.Move( fnMoveBackward, fnGoNode ); + } + + aCpyPam.SetMark(); + aCpyPam.Move( fnMoveForward, fnGoDoc ); + + BOOL bRet = TRUE, bDelTbl = TRUE; + StartAllAction(); + GetDoc()->StartUndo( UNDO_INSGLOSSARY, NULL ); + GetDoc()->LockExpFlds(); + + // When the clipboard content has been created by a rectangular selection + // the pasting is more sophisticated: + // every paragraph will be inserted into another position. + // The first positions are given by the actual cursor ring, + // if there are more text portions to insert than cursor in this ring, + // the additional insert positions will be created by moving the last + // cursor position into the next line (like pressing the cursor down key) + if( pClpDoc->IsColumnSelection() && !IsTableMode() ) + { + // Creation of the list of insert positions + std::list< Insertion > aCopyList; + // The number of text portions of the rectangular selection + const sal_uInt32 nSelCount = aCpyPam.GetPoint()->nNode.GetIndex() + - aCpyPam.GetMark()->nNode.GetIndex(); + sal_uInt32 nCount = nSelCount; + SwNodeIndex aClpIdx( aIdx ); + SwPaM* pStartCursor = GetCrsr(); + SwPaM* pCurrCrsr = pStartCursor; + sal_uInt32 nCursorCount = pStartCursor->numberOf(); + // If the target selection is a multi-selection, often the last and first + // cursor of the ring points to identical document positions. Then + // we should avoid double insertion of text portions... + while( nCursorCount > 1 && *pCurrCrsr->GetPoint() == + *(dynamic_cast<SwPaM*>(pCurrCrsr->GetPrev())->GetPoint()) ) + { + --nCursorCount; + pCurrCrsr = dynamic_cast<SwPaM*>(pCurrCrsr->GetNext()); + pStartCursor = pCurrCrsr; + } + SwPosition aStartPos( *pStartCursor->GetPoint() ); + SwPosition aInsertPos( aStartPos ); // first insertion position + bool bCompletePara = false; + USHORT nMove = 0; + while( nCount ) + { + --nCount; + ASSERT( aIdx.GetNode().GetCntntNode(), "Who filled the clipboard?!" ) + if( aIdx.GetNode().GetCntntNode() ) // robust + { + Insertion aInsertion( PaMPtr( new SwPaM( aIdx ) ), + PositionPtr( new SwPosition( aInsertPos ) ) ); + ++aIdx; + aInsertion.first->SetMark(); + if( pStartCursor == pCurrCrsr->GetNext() ) + { // Now we have to look for insertion positions... + if( !nMove ) // Annotate the last given insert position + aStartPos = aInsertPos; + SwCursor aCrsr( aStartPos, 0, false); + // Check if we find another insert position by moving + // down the last given position + if( aCrsr.UpDown( FALSE, ++nMove, 0, 0 ) ) + aInsertPos = *aCrsr.GetPoint(); + else // if there is no paragraph we have to create it + bCompletePara = nCount > 0; + nCursorCount = 0; + } + else // as long as we find more insert positions in the cursor ring + { // we'll take them + pCurrCrsr = dynamic_cast<SwPaM*>(pCurrCrsr->GetNext()); + aInsertPos = *pCurrCrsr->GetPoint(); + --nCursorCount; + } + // If there are no more paragraphs e.g. at the end of a document, + // we insert complete paragraphs instead of text portions + if( bCompletePara ) + aInsertion.first->GetPoint()->nNode = aIdx; + else + aInsertion.first->GetPoint()->nContent = + aInsertion.first->GetCntntNode()->Len(); + aCopyList.push_back( aInsertion ); + } + // If there are no text portions left but there are some more + // cursor positions to fill we have to restart with the first + // text portion + if( !nCount && nCursorCount ) + { + nCount = std::min( nSelCount, nCursorCount ); + aIdx = aClpIdx; // Start of clipboard content + } + } + std::list< Insertion >::const_iterator pCurr = aCopyList.begin(); + std::list< Insertion >::const_iterator pEnd = aCopyList.end(); + while( pCurr != pEnd ) + { + SwPosition& rInsPos = *pCurr->second; + SwPaM& rCopy = *pCurr->first; + const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().FindTableBoxStartNode(); + if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() - pBoxNd->GetIndex() && + rCopy.GetPoint()->nNode != rCopy.GetMark()->nNode ) + { + // if more than one node will be copied into a cell + // the box attributes have to be removed + GetDoc()->ClearBoxNumAttrs( rInsPos.nNode ); + } + { + SwNodeIndex aIndexBefore(rInsPos.nNode); + aIndexBefore--; + pClpDoc->CopyRange( rCopy, rInsPos, false ); + { + aIndexBefore++; + SwPaM aPaM(SwPosition(aIndexBefore), + SwPosition(rInsPos.nNode)); + aPaM.GetDoc()->MakeUniqueNumRules(aPaM); + } + } + SaveTblBoxCntnt( &rInsPos ); + ++pCurr; + } + } + else + { + FOREACHPAM_START(this) + + if( pSrcNd && + 0 != ( pDestNd = GetDoc()->IsIdxInTbl( PCURCRSR->GetPoint()->nNode ))) + { + SwPosition aDestPos( *PCURCRSR->GetPoint() ); + + BOOL bParkTblCrsr = FALSE; + const SwStartNode* pSttNd = PCURCRSR->GetNode()->FindTableBoxStartNode(); + + // TABLE IN TABLE: Tabelle in Tabelle kopieren + // lasse ueber das Layout die Boxen suchen + SwSelBoxes aBoxes; + if( IsTableMode() ) // Tabellen-Selecktion ?? + { + GetTblSel( *this, aBoxes ); + ParkTblCrsr(); + bParkTblCrsr = TRUE; + } + else if( !PCURCRSR->HasMark() && PCURCRSR->GetNext() == PCURCRSR && + ( !pSrcNd->GetTable().IsTblComplex() || + pDestNd->GetTable().IsNewModel() ) ) + { + // dann die Tabelle "relativ" kopieren + SwTableBox* pBox = pDestNd->GetTable().GetTblBox( + pSttNd->GetIndex() ); + ASSERT( pBox, "Box steht nicht in dieser Tabelle" ); + aBoxes.Insert( pBox ); + } + + SwNodeIndex aNdIdx( *pDestNd->EndOfSectionNode()); + if( !bParkTblCrsr ) + { + // erstmal aus der gesamten Tabelle raus +// ????? was ist mit Tabelle alleine im Rahmen ??????? + SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx ); + SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 )); + // #i59539: Don't remove all redline + ::PaMCorrAbs( SwNodeIndex( *pDestNd ), + SwNodeIndex( *pDestNd->EndOfSectionNode() ), + aPos ); + } + + bRet = GetDoc()->InsCopyOfTbl( aDestPos, aBoxes, &pSrcNd->GetTable(), + FALSE, FALSE ); + + if( bParkTblCrsr ) + GetCrsr(); + else + { + // und wieder in die Box zurueck + aNdIdx = *pSttNd; + SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx ); + SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 )); + // #i59539: Don't remove all redline + ::PaMCorrAbs( PCURCRSR->GetPoint()->nNode, aPos ); + } + + break; // aus der "while"-Schleife heraus + } + else if( *aCpyPam.GetPoint() == *aCpyPam.GetMark() && + pClpDoc->GetSpzFrmFmts()->Count() ) + { + // so langsam sollte mal eine DrawView erzeugt werden + if( !Imp()->GetDrawView() ) + MakeDrawView(); + + for ( USHORT i = 0; i < pClpDoc->GetSpzFrmFmts()->Count(); ++i ) + { + BOOL bInsWithFmt = TRUE; + const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i]; + + if( Imp()->GetDrawView()->IsGroupEntered() && + RES_DRAWFRMFMT == rCpyFmt.Which() && + (FLY_AS_CHAR != rCpyFmt.GetAnchor().GetAnchorId()) ) + { + const SdrObject* pSdrObj = rCpyFmt.FindSdrObject(); + if( pSdrObj ) + { + SdrObject* pNew = GetDoc()->CloneSdrObj( *pSdrObj, + FALSE, FALSE ); + + // Insert object sets any anchor position to 0. + // Therefore we calculate the absolute position here + // and after the insert the anchor of the object + // is set to the anchor of the group object. + Rectangle aSnapRect = pNew->GetSnapRect(); + if( pNew->GetAnchorPos().X() || pNew->GetAnchorPos().Y() ) + { + const Point aPoint( 0, 0 ); + // OD 2004-04-05 #i26791# - direct drawing object + // positioning for group members + pNew->NbcSetAnchorPos( aPoint ); + pNew->NbcSetSnapRect( aSnapRect ); + } + + Imp()->GetDrawView()->InsertObjectAtView( pNew, *Imp()->GetPageView() ); + + Point aGrpAnchor( 0, 0 ); + SdrObjList* pList = pNew->GetObjList(); + if ( pList ) + { + SdrObject* pOwner = pList->GetOwnerObj(); + if ( pOwner ) + { + SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pOwner); + aGrpAnchor = pThisGroup->GetAnchorPos(); + } + } + + // OD 2004-04-05 #i26791# - direct drawing object + // positioning for group members + pNew->NbcSetAnchorPos( aGrpAnchor ); + pNew->SetSnapRect( aSnapRect ); + + bInsWithFmt = FALSE; + } + } + + if( bInsWithFmt ) + { + SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() ); + if ((FLY_AT_PARA == aAnchor.GetAnchorId()) || + (FLY_AT_CHAR == aAnchor.GetAnchorId()) || + (FLY_AS_CHAR == aAnchor.GetAnchorId())) + { + SwPosition* pPos = PCURCRSR->GetPoint(); + // #108784# allow shapes (no controls) in header/footer + if( RES_DRAWFRMFMT == rCpyFmt.Which() && + GetDoc()->IsInHeaderFooter( pPos->nNode ) && + CheckControlLayer( rCpyFmt.FindSdrObject() ) ) + continue; + + aAnchor.SetAnchor( pPos ); + } + else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() ) + { + aAnchor.SetPageNum( GetPhyPageNum() ); + } + else if( FLY_AT_FLY == aAnchor.GetAnchorId() ) + { + Point aPt; + lcl_SetAnchor( *PCURCRSR->GetPoint(), *PCURCRSR->GetNode(), + 0, aPt, *this, aAnchor, aPt, FALSE ); + } + + SwFrmFmt * pNew = GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true ); + + if( pNew ) + { + if( RES_FLYFRMFMT == pNew->Which() ) + { + const Point aPt( GetCrsrDocPos() ); + SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pNew)-> + GetFrm( &aPt, FALSE ); + if( pFlyFrm ) + SelectFlyFrm( *pFlyFrm, TRUE ); + // immer nur den ersten Fly-Frame nehmen; die anderen + // wurden ueber Fly in Fly ins ClipBoard kopiert ! + break; + } + else + { + ASSERT( RES_DRAWFRMFMT == pNew->Which(), "Neues Format."); + // --> OD 2005-09-01 #i52780# - drawing object has + // to be made visible on paste. + { + SwDrawContact* pContact = + static_cast<SwDrawContact*>(pNew->FindContactObj()); + pContact->MoveObjToVisibleLayer( pContact->GetMaster() ); + } + // <-- + SdrObject *pObj = pNew->FindSdrObject(); + SwDrawView *pDV = Imp()->GetDrawView(); + pDV->MarkObj( pObj, pDV->GetSdrPageView() ); + // --> OD 2005-04-15 #i47455# - notify draw frame format + // that position attributes are already set. + if ( pNew->ISA(SwDrawFrmFmt) ) + { + static_cast<SwDrawFrmFmt*>(pNew)->PosAttrSet(); + } + // <-- + } + } + } + } + } + else + { + if( bDelTbl && IsTableMode() ) + { + SwEditShell::Delete(); + bDelTbl = FALSE; + } + + SwPosition& rInsPos = *PCURCRSR->GetPoint(); + const SwStartNode* pBoxNd = rInsPos.nNode.GetNode(). + FindTableBoxStartNode(); + if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() - + pBoxNd->GetIndex() && + aCpyPam.GetPoint()->nNode != aCpyPam.GetMark()->nNode ) + { + // es wird mehr als 1 Node in die akt. Box kopiert. Dann + // muessen die BoxAttribute aber entfernt werden. + GetDoc()->ClearBoxNumAttrs( rInsPos.nNode ); + } + //find out if the clipboard document starts with a table + bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode(); + SwPosition aInsertPosition( rInsPos ); + + { + SwNodeIndex aIndexBefore(rInsPos.nNode); + + aIndexBefore--; + + pClpDoc->CopyRange( aCpyPam, rInsPos, false ); + + { + aIndexBefore++; + SwPaM aPaM(SwPosition(aIndexBefore), + SwPosition(rInsPos.nNode)); + + aPaM.GetDoc()->MakeUniqueNumRules(aPaM); + } + } + + SaveTblBoxCntnt( &rInsPos ); + if(bIncludingPageFrames && bStartWithTable) + { + //remove the paragraph in front of the table + SwPaM aPara(aInsertPosition); + GetDoc()->DelFullPara(aPara); + } + //additionally copy page bound frames + if( bIncludingPageFrames && pClpDoc->GetSpzFrmFmts()->Count() ) + { + // create a draw view if necessary + if( !Imp()->GetDrawView() ) + MakeDrawView(); + + for ( USHORT i = 0; i < pClpDoc->GetSpzFrmFmts()->Count(); ++i ) + { + BOOL bInsWithFmt = TRUE; + const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i]; + if( bInsWithFmt ) + { + SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() ); + if ( FLY_AT_PAGE == aAnchor.GetAnchorId() ) + { + aAnchor.SetPageNum( aAnchor.GetPageNum() + nStartPageNumber - 1 ); + } + else + continue; + GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true ); + } + } + } + } + + FOREACHPAM_END() + } + + GetDoc()->EndUndo( UNDO_INSGLOSSARY, NULL ); + + // wurden neue Tabellenformeln eingefuegt ? + if( pTblFldTyp->GetDepends() ) + { + // alte Actions beenden; die Tabellen-Frames werden angelegt und + // eine Selection kann erzeugt werden + USHORT nActCnt; + for( nActCnt = 0; ActionPend(); ++nActCnt ) + EndAllAction(); + + for( ; nActCnt; --nActCnt ) + StartAllAction(); + } + GetDoc()->UnlockExpFlds(); + GetDoc()->UpdateFlds(NULL, false); + EndAllAction(); + + return bRet; +} + +/*-- 14.06.2004 13:31:17--------------------------------------------------- + + -----------------------------------------------------------------------*/ +BOOL SwFEShell::PastePages( SwFEShell& rToFill, USHORT nStartPage, USHORT nEndPage) +{ + Push(); + if(!GotoPage(nStartPage)) + { + Pop(sal_False); + return FALSE; + } + MovePage( fnPageCurr, fnPageStart ); + SwPaM aCpyPam( *GetCrsr()->GetPoint() ); + String sStartingPageDesc = GetPageDesc( GetCurPageDesc()).GetName(); + SwPageDesc* pDesc = rToFill.FindPageDescByName( sStartingPageDesc, TRUE ); + if( pDesc ) + rToFill.ChgCurPageDesc( *pDesc ); + + if(!GotoPage(nEndPage)) + { + Pop(sal_False); + return FALSE; + } + //if the page starts with a table a paragraph has to be inserted before + SwNode* pTableNode = aCpyPam.GetNode()->FindTableNode(); + if(pTableNode) + { + //insert a paragraph + StartUndo(UNDO_INSERT); + SwNodeIndex aTblIdx( *pTableNode, -1 ); + SwPosition aBefore(aTblIdx); + if(GetDoc()->AppendTxtNode( aBefore )) + { + SwPaM aTmp(aBefore); + aCpyPam = aTmp; + } + EndUndo(UNDO_INSERT); + } + + MovePage( fnPageCurr, fnPageEnd ); + aCpyPam.SetMark(); + *aCpyPam.GetMark() = *GetCrsr()->GetPoint(); + + SET_CURR_SHELL( this ); + + StartAllAction(); + GetDoc()->LockExpFlds(); + SetSelection(aCpyPam); + // copy the text of the selection + SwEditShell::Copy(&rToFill); + + if(pTableNode) + { + //remove the inserted paragraph + Undo(); + //remove the paragraph in the second doc, too + SwNodeIndex aIdx( rToFill.GetDoc()->GetNodes().GetEndOfExtras(), 2 ); + SwPaM aPara( aIdx ); //DocStart + rToFill.GetDoc()->DelFullPara(aPara); + } + // now the page bound objects + //additionally copy page bound frames + if( GetDoc()->GetSpzFrmFmts()->Count() ) + { + // create a draw view if necessary + if( !rToFill.Imp()->GetDrawView() ) + rToFill.MakeDrawView(); + + for ( USHORT i = 0; i < GetDoc()->GetSpzFrmFmts()->Count(); ++i ) + { + const SwFrmFmt& rCpyFmt = *(*GetDoc()->GetSpzFrmFmts())[i]; + SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() ); + if ((FLY_AT_PAGE == aAnchor.GetAnchorId()) && + aAnchor.GetPageNum() >= nStartPage && aAnchor.GetPageNum() <= nEndPage) + { + aAnchor.SetPageNum( aAnchor.GetPageNum() - nStartPage + 1); + } + else + continue; + rToFill.GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true ); + } + } + GetDoc()->UnlockExpFlds(); + GetDoc()->UpdateFlds(NULL, false); + Pop(sal_False); + EndAllAction(); + + return TRUE; +} + +BOOL SwFEShell::GetDrawObjGraphic( ULONG nFmt, Graphic& rGrf ) const +{ + ASSERT( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" ); + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + BOOL bConvert = TRUE; + if( rMrkList.GetMarkCount() ) + { + if( rMrkList.GetMarkCount() == 1 && + rMrkList.GetMark( 0 )->GetMarkedSdrObj()->ISA(SwVirtFlyDrawObj) ) + { + // Rahmen selektiert + if( CNT_GRF == GetCntType() ) + { + // --> OD 2005-02-09 #119353# - robust + const Graphic* pGrf( GetGraphic() ); + if ( pGrf ) + { + Graphic aGrf( *pGrf ); + if( SOT_FORMAT_GDIMETAFILE == nFmt ) + { + if( GRAPHIC_BITMAP != aGrf.GetType() ) + { + rGrf = aGrf; + bConvert = FALSE; + } + else if( GetWin() ) + { + Size aSz; + Point aPt; + GetGrfSize( aSz ); + + VirtualDevice aVirtDev; + aVirtDev.EnableOutput( FALSE ); + + MapMode aTmp( GetWin()->GetMapMode() ); + aTmp.SetOrigin( aPt ); + aVirtDev.SetMapMode( aTmp ); + + GDIMetaFile aMtf; + aMtf.Record( &aVirtDev ); + aGrf.Draw( &aVirtDev, aPt, aSz ); + aMtf.Stop(); + aMtf.SetPrefMapMode( aTmp ); + aMtf.SetPrefSize( aSz ); + rGrf = aMtf; + } + } + else if( GRAPHIC_BITMAP == aGrf.GetType() ) + { + rGrf = aGrf; + bConvert = FALSE; + } + else + { + //fix(23806): Nicht die Originalgroesse, sondern die + //aktuelle. Anderfalls kann es passieren, dass z.B. bei + //Vektorgrafiken mal eben zig MB angefordert werden. + const Size aSz( FindFlyFrm()->Prt().SSize() ); + VirtualDevice aVirtDev( *GetWin() ); + + MapMode aTmp( MAP_TWIP ); + aVirtDev.SetMapMode( aTmp ); + if( aVirtDev.SetOutputSize( aSz ) ) + { + aGrf.Draw( &aVirtDev, Point(), aSz ); + rGrf = aVirtDev.GetBitmap( Point(), aSz ); + } + else + { + rGrf = aGrf; + bConvert = FALSE; + } + } + } + // <-- + } + } + else if( SOT_FORMAT_GDIMETAFILE == nFmt ) + rGrf = Imp()->GetDrawView()->GetAllMarkedMetaFile(); + else if( SOT_FORMAT_BITMAP == nFmt ) + rGrf = Imp()->GetDrawView()->GetAllMarkedBitmap(); + } + return bConvert; +} + +// --> OD 2005-08-03 #i50824# +// --> OD 2006-03-01 #b6382898# +// replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs> +void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel* _pModel ) +{ + for ( sal_uInt16 nPgNum = 0; nPgNum < _pModel->GetPageCount(); ++nPgNum ) + { + // setup object iterator in order to iterate through all objects + // including objects in group objects, but exclusive group objects. + SdrObjListIter aIter(*(_pModel->GetPage( nPgNum ))); + while( aIter.IsMore() ) + { + SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( aIter.Next() ); + if( pOle2Obj ) + { + // found an ole2 shape + SdrObjList* pObjList = pOle2Obj->GetObjList(); + + // get its graphic + Graphic aGraphic; + pOle2Obj->Connect(); + Graphic* pGraphic = pOle2Obj->GetGraphic(); + if( pGraphic ) + aGraphic = *pGraphic; + pOle2Obj->Disconnect(); + + // create new graphic shape with the ole graphic and shape size + SdrGrafObj* pGraphicObj = new SdrGrafObj( aGraphic, pOle2Obj->GetCurrentBoundRect() ); + // apply layer of ole2 shape at graphic shape + pGraphicObj->SetLayer( pOle2Obj->GetLayer() ); + + // replace ole2 shape with the new graphic object and delete the ol2 shape + SdrObject* pRemovedObject = pObjList->ReplaceObject( pGraphicObj, pOle2Obj->GetOrdNum() ); + SdrObject::Free( pRemovedObject ); + } + } + } +} +// <-- +void SwFEShell::Paste( SvStream& rStrm, USHORT nAction, const Point* pPt ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + StartUndo(); + + SvtPathOptions aPathOpt; + FmFormModel* pModel = new FmFormModel( aPathOpt.GetPalettePath(), + 0, GetDoc()->GetDocShell() ); + pModel->GetItemPool().FreezeIdRanges(); + + rStrm.Seek(0); + + uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rStrm ) ); + SvxDrawingLayerImport( pModel, xInputStream ); + + if ( !Imp()->HasDrawView() ) + Imp()->MakeDrawView(); + + Point aPos( pPt ? *pPt : GetCharRect().Pos() ); + SdrView *pView = Imp()->GetDrawView(); + + //Drop auf bestehendes Objekt: Objekt ersetzen oder neu Attributieren. + if( pModel->GetPageCount() > 0 && + 1 == pModel->GetPage(0)->GetObjCount() && + 1 == pView->GetMarkedObjectList().GetMarkCount() ) + { + // OD 10.07.2003 #110742# - replace a marked 'virtual' drawing object + // by its corresponding 'master' drawing object in the mark list. + SwDrawView::ReplaceMarkedDrawVirtObjs( *pView ); + + SdrObject* pClpObj = pModel->GetPage(0)->GetObj(0); + SdrObject* pOldObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj(); + + if( SW_PASTESDR_SETATTR == nAction && pOldObj->ISA(SwVirtFlyDrawObj) ) + nAction = SW_PASTESDR_REPLACE; + + switch( nAction ) + { + case SW_PASTESDR_REPLACE: + { + const SwFrmFmt* pFmt(0); + const SwFrm* pAnchor(0); + if( pOldObj->ISA(SwVirtFlyDrawObj) ) + { + pFmt = FindFrmFmt( pOldObj ); + + Point aNullPt; + SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pFmt)->GetFrm( &aNullPt ); + pAnchor = pFlyFrm->GetAnchorFrm(); + + if( pAnchor->FindFooterOrHeader() ) + { + // wenn TextRahmen in der Kopf/Fusszeile steht, dann + // nicht ersetzen, sondern nur einfuegen + nAction = SW_PASTESDR_INSERT; + break; + } + } + + SdrObject* pNewObj = pClpObj->Clone(); + Rectangle aOldObjRect( pOldObj->GetCurrentBoundRect() ); + Size aOldObjSize( aOldObjRect.GetSize() ); + Rectangle aNewRect( pNewObj->GetCurrentBoundRect() ); + Size aNewSize( aNewRect.GetSize() ); + + Fraction aScaleWidth( aOldObjSize.Width(), aNewSize.Width() ); + Fraction aScaleHeight( aOldObjSize.Height(), aNewSize.Height()); + pNewObj->NbcResize( aNewRect.TopLeft(), aScaleWidth, aScaleHeight); + + Point aVec = aOldObjRect.TopLeft() - aNewRect.TopLeft(); + pNewObj->NbcMove(Size(aVec.X(), aVec.Y())); + + if( pNewObj->ISA( SdrUnoObj ) ) + pNewObj->SetLayer( GetDoc()->GetControlsId() ); + else if( pOldObj->ISA( SdrUnoObj ) ) + pNewObj->SetLayer( GetDoc()->GetHeavenId() ); + else + pNewObj->SetLayer( pOldObj->GetLayer() ); + + if( pOldObj->ISA(SwVirtFlyDrawObj) ) + { + // Attribute sichern und dam SdrObject setzen + SfxItemSet aFrmSet( pDoc->GetAttrPool(), + RES_SURROUND, RES_ANCHOR ); + aFrmSet.Set( pFmt->GetAttrSet() ); + + Point aNullPt; + if( pAnchor->IsTxtFrm() && ((SwTxtFrm*)pAnchor)->IsFollow() ) + { + const SwTxtFrm* pTmp = (SwTxtFrm*)pAnchor; + do { + pTmp = pTmp->FindMaster(); + ASSERT( pTmp, "Where's my Master?" ); + } while( pTmp->IsFollow() ); + pAnchor = pTmp; + } + if( pOldObj->ISA( SdrCaptionObj )) + aNullPt = ((SdrCaptionObj*)pOldObj)->GetTailPos(); + else + aNullPt = aOldObjRect.TopLeft(); + + Point aNewAnchor = pAnchor->GetFrmAnchorPos( ::HasWrap( pOldObj ) ); + // OD 2004-04-05 #i26791# - direct positioning of Writer + // fly frame object for <SwDoc::Insert(..)> + pNewObj->NbcSetRelativePos( aNullPt - aNewAnchor ); + pNewObj->NbcSetAnchorPos( aNewAnchor ); + + pOldObj->GetOrdNum(); + + DelSelectedObj(); + + pFmt = GetDoc()->Insert( *GetCrsr(), *pNewObj, &aFrmSet, NULL ); + } + else + pView->ReplaceObjectAtView( pOldObj, *Imp()->GetPageView(), pNewObj, TRUE ); + } + break; + + case SW_PASTESDR_SETATTR: + { + SfxItemSet aSet( GetAttrPool() ); + aSet.Put(pClpObj->GetMergedItemSet()); + pView->SetAttributes( aSet, FALSE ); + } + break; + + default: + nAction = SW_PASTESDR_INSERT; + break; + } + } + else + nAction = SW_PASTESDR_INSERT; + + if( SW_PASTESDR_INSERT == nAction ) + { + GetDoc()->SetNoDrawUndoObj( TRUE ); + + sal_Bool bDesignMode = pView->IsDesignMode(); + if( !bDesignMode ) + pView->SetDesignMode( sal_True ); + + // --> OD 2005-08-03 #i50824# + // --> OD 2006-03-01 #b6382898# + // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs> + lcl_ConvertSdrOle2ObjsToSdrGrafObjs( pModel ); + // <-- + pView->Paste( *pModel, aPos ); + + ULONG nCnt = pView->GetMarkedObjectList().GetMarkCount(); + if( nCnt ) + { + const Point aNull( 0, 0 ); + for( ULONG i=0; i < nCnt; ++i ) + { + SdrObject *pObj = pView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj(); + pObj->ImpSetAnchorPos( aNull ); + } + + pView->SetCurrentObj( OBJ_GRUP, SdrInventor ); + if ( nCnt > 1 ) + pView->GroupMarked(); + SdrObject *pObj = pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + if( pObj->ISA( SdrUnoObj ) ) + { + pObj->SetLayer( GetDoc()->GetControlsId() ); + bDesignMode = sal_True; + } + else + pObj->SetLayer( GetDoc()->GetHeavenId() ); + const Rectangle &rSnap = pObj->GetSnapRect(); + const Size aDiff( rSnap.GetWidth()/2, rSnap.GetHeight()/2 ); + pView->MoveMarkedObj( aDiff ); + ImpEndCreate(); + if( !bDesignMode ) + pView->SetDesignMode( sal_False ); + } + GetDoc()->SetNoDrawUndoObj( FALSE ); + } + EndUndo(); + EndAllAction(); + delete pModel; +} + +BOOL SwFEShell::Paste( const Graphic &rGrf ) +{ + SET_CURR_SHELL( this ); + SdrObject* pObj; + SdrView *pView = Imp()->GetDrawView(); + + BOOL bRet = 1 == pView->GetMarkedObjectList().GetMarkCount() && + (pObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj())->IsClosedObj() && + !pObj->ISA( SdrOle2Obj ); + + if( bRet ) + { + XOBitmap aXOBitmap( rGrf.GetBitmap() ); + SfxItemSet aSet( GetAttrPool(), XATTR_FILLSTYLE, XATTR_FILLBITMAP ); + aSet.Put( XFillStyleItem( XFILL_BITMAP )); + aSet.Put( XFillBitmapItem( aEmptyStr, aXOBitmap )); + pView->SetAttributes( aSet, FALSE ); + } + return bRet; +} diff --git a/sw/source/core/frmedt/fedesc.cxx b/sw/source/core/frmedt/fedesc.cxx new file mode 100644 index 000000000000..fe73c36016a0 --- /dev/null +++ b/sw/source/core/frmedt/fedesc.cxx @@ -0,0 +1,291 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <hintids.hxx> +#include <tools/ref.hxx> +#include <fesh.hxx> +#include <doc.hxx> +#include <pagefrm.hxx> +#include <rootfrm.hxx> +#include <cntfrm.hxx> +#include <pam.hxx> +#include <fmtpdsc.hxx> +#include <pagedesc.hxx> +#include <tabfrm.hxx> +#include <edimp.hxx> +#include <SwStyleNameMapper.hxx> +/************************************************************************* +|* +|* SwFEShell::GetPageDescCnt() +|* +|* Ersterstellung MA 25. Jan. 93 +|* Letzte Aenderung MA 25. Jan. 93 +|* +|*************************************************************************/ + +USHORT SwFEShell::GetPageDescCnt() const +{ + return GetDoc()->GetPageDescCnt(); +} + +/************************************************************************* +|* +|* SwFEShell::ChgCurPageDesc() +|* +|* Ersterstellung ST ?? +|* Letzte Aenderung MA 01. Aug. 94 +|* +|*************************************************************************/ + +void SwFEShell::ChgCurPageDesc( const SwPageDesc& rDesc ) +{ +#ifdef DBG_UTIL + //Die SS veraendert keinen PageDesc, sondern setzt nur das Attribut. + //Der Pagedesc muss im Dokument vorhanden sein! + BOOL bFound = FALSE; + for ( USHORT nTst = 0; nTst < GetPageDescCnt(); ++nTst ) + if ( &rDesc == &GetPageDesc( nTst ) ) + bFound = TRUE; + ASSERT( bFound, "ChgCurPageDesc mit ungueltigem Descriptor." ); +#endif + + StartAllAction(); + + SwPageFrm *pPage = GetCurrFrm()->FindPageFrm(); + const SwFrm *pFlow = 0; + USHORT nPageNmOffset = 0; + + ASSERT( !GetCrsr()->HasMark(), "ChgCurPageDesc nur ohne Selektion!"); + + SET_CURR_SHELL( this ); + while ( pPage ) + { + pFlow = pPage->FindFirstBodyCntnt(); + if ( pFlow ) + { + if ( pFlow->IsInTab() ) + pFlow = pFlow->FindTabFrm(); + const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc(); + if( rPgDesc.GetPageDesc() ) + { + // wir haben ihn den Schlingel + nPageNmOffset = rPgDesc.GetNumOffset(); + break; + } + } + pPage = (SwPageFrm*) pPage->GetPrev(); + } + if ( !pPage ) + { + pPage = (SwPageFrm*) (GetLayout()->Lower()); + pFlow = pPage->FindFirstBodyCntnt(); + if ( !pFlow ) + { + pPage = (SwPageFrm*)pPage->GetNext(); + pFlow = pPage->FindFirstBodyCntnt(); + ASSERT( pFlow, "Dokuemnt ohne Inhalt?!?" ); + } + } + + // Seitennummer mitnehmen + SwFmtPageDesc aNew( &rDesc ); + aNew.SetNumOffset( nPageNmOffset ); + + if ( pFlow->IsInTab() ) + GetDoc()->SetAttr( aNew, *(SwFmt*)pFlow->FindTabFrm()->GetFmt() ); + else + { + SwPaM aPaM( *((SwCntntFrm*)pFlow)->GetNode() ); + GetDoc()->InsertPoolItem( aPaM, aNew, 0 ); + } + EndAllActionAndCall(); +} + +/************************************************************************* +|* +|* SwFEShell::ChgPageDesc() +|* +|* Ersterstellung MA 25. Jan. 93 +|* Letzte Aenderung MA 24. Jan. 95 +|* +|*************************************************************************/ + +void SwFEShell::ChgPageDesc( USHORT i, const SwPageDesc &rChged ) +{ + StartAllAction(); + SET_CURR_SHELL( this ); + //Fix i64842: because Undo has a very special way to handle header/footer content + // we have to copy the page descriptor before calling ChgPageDesc. + const sal_Bool bDoesUndo( GetDoc()->DoesUndo() ); + SwPageDesc aDesc( rChged ); + GetDoc()->DoUndo( sal_False ); + GetDoc()->CopyPageDesc(rChged, aDesc); + GetDoc()->DoUndo( bDoesUndo ); + GetDoc()->ChgPageDesc( i, aDesc ); + EndAllActionAndCall(); +} + +/************************************************************************* +|* +|* SwFEShell::GetPageDesc(), GetCurPageDesc() +|* +|* Ersterstellung MA 25. Jan. 93 +|* Letzte Aenderung MA 23. Apr. 93 +| +|*************************************************************************/ + +const SwPageDesc& SwFEShell::GetPageDesc( USHORT i ) const +{ + return const_cast<const SwDoc *>(GetDoc())->GetPageDesc( i ); +} + +SwPageDesc* SwFEShell::FindPageDescByName( const String& rName, + BOOL bGetFromPool, + USHORT* pPos ) +{ + SwPageDesc* pDesc = GetDoc()->FindPageDescByName( rName, pPos ); + if( !pDesc && bGetFromPool ) + { + USHORT nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( rName, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC ); + if( USHRT_MAX != nPoolId && + 0 != (pDesc = GetDoc()->GetPageDescFromPool( nPoolId )) + && pPos ) + // werden immer hinten angehaengt + *pPos = GetDoc()->GetPageDescCnt() - 1 ; + } + return pDesc; +} + +USHORT SwFEShell::GetMousePageDesc( const Point &rPt ) const +{ + if( GetLayout() ) + { + const SwPageFrm* pPage = + static_cast<const SwPageFrm*>( GetLayout()->Lower() ); + if( pPage ) + { + while( pPage->GetNext() && rPt.Y() > pPage->Frm().Bottom() ) + pPage = static_cast<const SwPageFrm*>( pPage->GetNext() ); + SwDoc *pMyDoc = GetDoc(); + for ( USHORT i = 0; i < GetDoc()->GetPageDescCnt(); ++i ) + { + if ( pPage->GetPageDesc() == &const_cast<const SwDoc *>(pMyDoc) + ->GetPageDesc(i) ) + return i; + } + } + } + return 0; +} + +USHORT SwFEShell::GetCurPageDesc( const BOOL bCalcFrm ) const +{ + const SwFrm *pFrm = GetCurrFrm( bCalcFrm ); + if ( pFrm ) + { + const SwPageFrm *pPage = pFrm->FindPageFrm(); + if ( pPage ) + { + SwDoc *pMyDoc = GetDoc(); + for ( USHORT i = 0; i < GetDoc()->GetPageDescCnt(); ++i ) + { + if ( pPage->GetPageDesc() == &const_cast<const SwDoc *>(pMyDoc) + ->GetPageDesc(i) ) + return i; + } + } + } + return 0; +} + +// if inside all selection only one PageDesc, return this. +// Otherwise return 0 pointer +const SwPageDesc* SwFEShell::GetSelectedPageDescs() const +{ + const SwCntntNode* pCNd; + const SwFrm* pMkFrm, *pPtFrm; + const SwPageDesc* pFnd, *pRetDesc = (SwPageDesc*)0xffffffff; + const Point aNulPt; + + FOREACHPAM_START(this) + + if( 0 != (pCNd = PCURCRSR->GetCntntNode() ) && + 0 != ( pPtFrm = pCNd->GetFrm( &aNulPt, 0, FALSE )) ) + pPtFrm = pPtFrm->FindPageFrm(); + else + pPtFrm = 0; + + if( PCURCRSR->HasMark() && + 0 != (pCNd = PCURCRSR->GetCntntNode( FALSE ) ) && + 0 != ( pMkFrm = pCNd->GetFrm( &aNulPt, 0, FALSE )) ) + pMkFrm = pMkFrm->FindPageFrm(); + else + pMkFrm = pPtFrm; + + + if( !pMkFrm || !pPtFrm ) + pFnd = 0; + else if( pMkFrm == pPtFrm ) + pFnd = ((SwPageFrm*)pMkFrm)->GetPageDesc(); + else + { + // swap pointer if PtFrm before MkFrm + if( ((SwPageFrm*)pMkFrm)->GetPhyPageNum() > + ((SwPageFrm*)pPtFrm)->GetPhyPageNum() ) + { + const SwFrm* pTmp = pMkFrm; pMkFrm = pPtFrm; pPtFrm = pTmp; + } + + // now check from MkFrm to PtFrm for equal PageDescs + pFnd = ((SwPageFrm*)pMkFrm)->GetPageDesc(); + while( pFnd && pMkFrm != pPtFrm ) + { + pMkFrm = pMkFrm->GetNext(); + if( !pMkFrm || pFnd != ((SwPageFrm*)pMkFrm)->GetPageDesc() ) + pFnd = 0; + } + } + + if( (SwPageDesc*)0xffffffff == pRetDesc ) + pRetDesc = pFnd; + else if( pFnd != pRetDesc ) + { + pRetDesc = 0; + break; + } + + FOREACHPAM_END() + + return pRetDesc; +} + + + diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx new file mode 100644 index 000000000000..0dc721a62f12 --- /dev/null +++ b/sw/source/core/frmedt/fefly1.cxx @@ -0,0 +1,2156 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <hintids.hxx> +#include <svl/itemiter.hxx> +#include <svtools/imapobj.hxx> +#include <svtools/soerr.hxx> +#include <editeng/protitem.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdouno.hxx> +#include <svx/fmglob.hxx> +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <fmtanchr.hxx> +#include <txtflcnt.hxx> +#include <fmtcntnt.hxx> +#include <fmtornt.hxx> +#include <fmtflcnt.hxx> +#include <fmturl.hxx> +#include <fmtclds.hxx> +#include <fmtfsize.hxx> +#include <docary.hxx> +#include <fesh.hxx> +#include <rootfrm.hxx> +#include <pagefrm.hxx> +#include <cntfrm.hxx> +#include <txtfrm.hxx> +#include <viewimp.hxx> +#include <viscrs.hxx> +#include <doc.hxx> +#include <dview.hxx> +#include <dflyobj.hxx> +#include <dcontact.hxx> +#include <frmfmt.hxx> +#include <flyfrm.hxx> +#include <ndtxt.hxx> +#include <edimp.hxx> +#include <swtable.hxx> +#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete +#include <ndgrf.hxx> +#include <flyfrms.hxx> +#include <flypos.hxx> +#include <fldbas.hxx> +#include <fmtfld.hxx> +#include <swundo.hxx> +// --> OD 2006-03-06 #125892# +#include <HandleAnchorNodeChg.hxx> +// <-- +#include <frmatr.hxx> +// --> OD 2009-12-29 #i89920# +#include <fmtsrnd.hxx> +#include <editeng/opaqitem.hxx> +// <-- + +using ::rtl::OUString; +using namespace ::com::sun::star; + +//Zum anmelden von Flys in Flys in ... +//definiert in layout/frmtool.cxx +void RegistFlys( SwPageFrm*, const SwLayoutFrm* ); + +/*********************************************************************** +#* Class : SwDoc +#* Methode : UseSpzLayoutFmt +#* Beschreibung: Anhand des Request werden zu dem Format entsprechende +#* Aenderungen an den Spezifischen Layouts vorgenommen. +#* Datum : MA 23. Sep. 92 +#* Update : JP 09.03.98 +#***********************************************************************/ + +sal_Bool lcl_SetNewFlyPos( const SwNode& rNode, SwFmtAnchor& rAnchor, + const Point& rPt ) +{ + sal_Bool bRet = sal_False; + const SwStartNode* pStNode = rNode.FindFlyStartNode(); + if( pStNode ) + { + SwPosition aPos( *pStNode ); + rAnchor.SetAnchor( &aPos ); + bRet = sal_True; + } + else + { + const SwCntntNode *pCntNd = rNode.GetCntntNode(); + const SwCntntFrm* pCFrm = pCntNd ? pCntNd->GetFrm( &rPt, 0, sal_False ) : 0; + const SwPageFrm *pPg = pCFrm ? pCFrm->FindPageFrm() : 0; + + rAnchor.SetPageNum( pPg ? pPg->GetPhyPageNum() : 1 ); + rAnchor.SetType( FLY_AT_PAGE ); + } + return bRet; +} + +BOOL lcl_FindAnchorPos( SwDoc& rDoc, const Point& rPt, const SwFrm& rFrm, + SfxItemSet& rSet ) +{ + BOOL bRet = TRUE; + SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) ); + RndStdIds nNew = aNewAnch.GetAnchorId(); + const SwFrm *pNewAnch; + + //Neuen Anker ermitteln + Point aTmpPnt( rPt ); + switch( nNew ) + { + case FLY_AS_CHAR: // sollte der nicht auch mit hinein? + case FLY_AT_PARA: + case FLY_AT_CHAR: // LAYER_IMPL + { + //Ausgehend von der linken oberen Ecke des Fly den + //dichtesten CntntFrm suchen. + const SwFrm* pFrm = rFrm.IsFlyFrm() ? ((SwFlyFrm&)rFrm).GetAnchorFrm() + : &rFrm; + pNewAnch = ::FindAnchor( pFrm, aTmpPnt ); + if( pNewAnch->IsProtected() ) + { + bRet = FALSE; + break; + } + + SwPosition aPos( *((SwCntntFrm*)pNewAnch)->GetNode() ); + if ((FLY_AT_CHAR == nNew) || (FLY_AS_CHAR == nNew)) + { + // es muss ein TextNode gefunden werden, denn nur in diesen + // ist ein Inhaltsgebundene Frames zu verankern + SwCrsrMoveState aState( MV_SETONLYTEXT ); + aTmpPnt.X() -= 1; //nicht im Fly landen!! + if( !pNewAnch->GetCrsrOfst( &aPos, aTmpPnt, &aState ) ) + { + SwCntntNode* pCNd = ((SwCntntFrm*)pNewAnch)->GetNode(); + if( pNewAnch->Frm().Bottom() < aTmpPnt.Y() ) + pCNd->MakeStartIndex( &aPos.nContent ); + else + pCNd->MakeEndIndex( &aPos.nContent ); + } + } + aNewAnch.SetAnchor( &aPos ); + } + break; + + case FLY_AT_FLY: // LAYER_IMPL + { + //Ausgehend von der linken oberen Ecke des Fly den + //dichtesten SwFlyFrm suchen. + SwCrsrMoveState aState( MV_SETONLYTEXT ); + SwPosition aPos( rDoc.GetNodes() ); + aTmpPnt.X() -= 1; //nicht im Fly landen!! + rDoc.GetRootFrm()->GetCrsrOfst( &aPos, aTmpPnt, &aState ); + pNewAnch = ::FindAnchor( + aPos.nNode.GetNode().GetCntntNode()->GetFrm( 0, 0, sal_False ), + aTmpPnt )->FindFlyFrm(); + + if( pNewAnch && &rFrm != pNewAnch && !pNewAnch->IsProtected() ) + { + aPos.nNode = *((SwFlyFrm*)pNewAnch)->GetFmt()->GetCntnt(). + GetCntntIdx(); + aNewAnch.SetAnchor( &aPos ); + break; + } + } + + aNewAnch.SetType( nNew = FLY_AT_PAGE ); + // no break + + case FLY_AT_PAGE: + pNewAnch = rFrm.FindPageFrm(); + aNewAnch.SetPageNum( pNewAnch->GetPhyPageNum() ); + break; + + default: + ASSERT( !&rDoc, "Falsche ID fuer neuen Anker." ); + } + + rSet.Put( aNewAnch ); + return bRet; +} + +// +//! also used in unoframe.cxx +// +sal_Bool lcl_ChkAndSetNewAnchor( const SwFlyFrm& rFly, SfxItemSet& rSet ) +{ + const SwFrmFmt& rFmt = *rFly.GetFmt(); + const SwFmtAnchor &rOldAnch = rFmt.GetAnchor(); + const RndStdIds nOld = rOldAnch.GetAnchorId(); + + RndStdIds nNew = ((SwFmtAnchor&)rSet.Get( RES_ANCHOR )).GetAnchorId(); + + if( nOld == nNew ) + return sal_False; + + SwDoc* pDoc = (SwDoc*)rFmt.GetDoc(); + +#ifdef DBG_UTIL + ASSERT( !(nNew == FLY_AT_PAGE && + (FLY_AT_PARA==nOld || FLY_AT_CHAR==nOld || FLY_AS_CHAR==nOld ) && + pDoc->IsInHeaderFooter( rOldAnch.GetCntntAnchor()->nNode )), + "Unerlaubter Ankerwechsel in Head/Foot." ); +#endif + + return ::lcl_FindAnchorPos( *pDoc, rFly.Frm().Pos(), rFly, rSet ); +} + +void SwFEShell::SelectFlyFrm( SwFlyFrm& rFrm, sal_Bool bNew ) +{ + SET_CURR_SHELL( this ); + + // Wenn es ein neuer Rahmen ist, so soll er selektiert sein. + // !!Rahmen immer selektieren, wenn sie nicht selektiert sind. + // - Es kann ein neuer 'alter' sein weil der Anker gewechselt wurde. + // - 'alte' Rahmen sind vorher immer selektiert denn sonst wird nix + // an ihnen veraendert. + // Der Rahmen darf nicht per Dokumentposition selektiert werden, weil er + // auf jedenfall selektiert sein muss! + SwViewImp *pImpl = Imp(); + if( GetWin() && (bNew || !pImpl->GetDrawView()->AreObjectsMarked()) ) + { + ASSERT( rFrm.IsFlyFrm(), "SelectFlyFrm will einen Fly" ); + + //Wenn der Fly bereits selektiert ist gibt es hier ja wohl nichts + //zu tun. + if ( FindFlyFrm() == &rFrm ) + return; + + //Damit der Anker ueberhaupt noch gepaintet wird. + if( rFrm.IsFlyInCntFrm() && rFrm.GetAnchorFrm() ) + rFrm.GetAnchorFrm()->SetCompletePaint(); + + // --> OD 2004-06-11 #i28701# - no format at all. +// //Hier wurde immer kalkuliert. Leider ist der Sonderfall Fly in Fly mit +// //Spalten u.U. sehr kritisch wenn der innenliegende zuerst formatiert +// //wird. Um kein Risiko einzugehen entschaerfen wir nur diesen Sonderfall. +// if( !rFrm.GetAnchorFrm()->IsInFly() ) +// rFrm.Calc(); + + if( pImpl->GetDrawView()->AreObjectsMarked() ) + pImpl->GetDrawView()->UnmarkAll(); + + pImpl->GetDrawView()->MarkObj( rFrm.GetVirtDrawObj(), + pImpl->GetPageView(), sal_False, sal_False ); + KillPams(); + ClearMark(); + SelFlyGrabCrsr(); + } +} + +/************************************************************************* +|* +|* SwFEShell::FindFlyFrm() +|* +|* Beschreibung Liefert den Fly wenn einer Selektiert ist. +|* Ersterstellung MA 03. Nov. 92 +|* Letzte Aenderung MA 05. Mar. 96 +|* +*************************************************************************/ + +SwFlyFrm *SwFEShell::FindFlyFrm() const +{ + if ( Imp()->HasDrawView() ) + { + // Ein Fly ist genau dann erreichbar, wenn er selektiert ist. + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + if( rMrkList.GetMarkCount() != 1 ) + return 0; + + SdrObject *pO = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); + return pO->ISA(SwVirtFlyDrawObj) ? ((SwVirtFlyDrawObj*)pO)->GetFlyFrm() : 0; + } + return 0; +} + +/************************************************************************* +|* +|* SwFEShell::IsFlyInFly() +|* +|* Beschreibung Liefert sal_True, wenn der aktuelle Fly an einem anderen +|* verankert werden koennte (also innerhalb ist) +|* Ersterstellung AMA 11. Sep. 97 +|* Letzte Aenderung AMA 14. Jan. 98 +|* +*************************************************************************/ + +const SwFrmFmt* SwFEShell::IsFlyInFly() +{ + SET_CURR_SHELL( this ); + + if ( !Imp()->HasDrawView() ) + return NULL; + + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + if ( !rMrkList.GetMarkCount() ) + { + SwCntntFrm *pCntnt = GetCurrFrm( sal_False ); + if( !pCntnt ) + return NULL; + SwFlyFrm *pFly = pCntnt->FindFlyFrm(); + if ( !pFly ) + return NULL; + return pFly->GetFmt(); + } + else if ( rMrkList.GetMarkCount() != 1 || + !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) ) + return NULL; + + SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); + + SwFrmFmt *pFmt = FindFrmFmt( pObj ); + if( pFmt && FLY_AT_FLY == pFmt->GetAnchor().GetAnchorId() ) + { + const SwFrm* pFly = pObj->ISA(SwVirtFlyDrawObj) ? + ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm() : + ((SwDrawContact*)GetUserCall(pObj))->GetAnchorFrm( pObj ); + ASSERT( pFly, "IsFlyInFly: Where's my anchor?" ); + ASSERT( pFly->IsFlyFrm(), "IsFlyInFly: Funny anchor!" ); + return ((SwFlyFrm*)pFly)->GetFmt(); + } + + Point aTmpPos = pObj->GetCurrentBoundRect().TopLeft(); + + SwFrm *pTxtFrm; + { + SwCrsrMoveState aState( MV_SETONLYTEXT ); + SwNodeIndex aSwNodeIndex( GetDoc()->GetNodes() ); + SwPosition aPos( aSwNodeIndex ); + Point aPoint( aTmpPos ); + aPoint.X() -= 1; //nicht im Fly landen!! + GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState ); + // OD 01.07.2003 #108784# - determine text frame by left-top-corner + // of object + //pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->GetFrm( 0, 0, sal_False ); + pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->GetFrm( &aTmpPos, 0, sal_False ); + } + const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aTmpPos ); + const SwFlyFrm *pFly = pTmp->FindFlyFrm(); + if( pFly ) + return pFly->GetFmt(); + return NULL; +} + +/************************************************************************* +|* +|* SwFEShell::SetFlyPos +|* +|* Ersterstellung MA 14. Jan. 93 +|* Letzte Aenderung MA 14. Feb. 95 +|* +*************************************************************************/ + +void SwFEShell::SetFlyPos( const Point& rAbsPos ) +{ + SET_CURR_SHELL( this ); + + //Bezugspunkt in Dokumentkoordinaten bestimmen + SwCntntFrm *pCntnt = GetCurrFrm( sal_False ); + if( !pCntnt ) + return; + SwFlyFrm *pFly = pCntnt->FindFlyFrm(); + if ( !pFly ) + return; + + //SwSaveHdl aSaveX( Imp() ); + + //Bei Absatzgebundenen Flys muss ausgehend von der absoluten + //Position ein neuer Anker gesetzt werden. Anker und neue RelPos werden + //vom Fly selbst berechnet und gesetzt. + if ( pFly->IsFlyAtCntFrm() ) + ((SwFlyAtCntFrm*)pFly)->SetAbsPos( rAbsPos ); + else + { + const SwFrm *pAnch = pFly->GetAnchorFrm(); + // --> OD 2004-06-11 #i28701# - no format here +// pAnch->Calc(); + Point aOrient( pAnch->Frm().Pos() ); + + if ( pFly->IsFlyInCntFrm() ) + aOrient.X() = rAbsPos.X(); + + //RelPos errechnen. + aOrient.X() = rAbsPos.X() - aOrient.X(); + aOrient.Y() = rAbsPos.Y() - aOrient.Y(); + pFly->ChgRelPos( aOrient ); + } + // --> OD 2004-06-11 #i28701# - no format here +// pFly->Calc(); + CallChgLnk(); // rufe das AttrChangeNotify auf der UI-Seite. +} + +/************************************************************************* +|* +|* SwFEShell::FindAnchorPos +|* +|* Ersterstellung AMA 24. Sep. 97 +|* Letzte Aenderung AMA 24. Sep. 97 +|* +*************************************************************************/ + +Point SwFEShell::FindAnchorPos( const Point& rAbsPos, sal_Bool bMoveIt ) +{ + Point aRet; + + SET_CURR_SHELL( this ); + + if ( !Imp()->HasDrawView() ) + return aRet; + + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + if ( rMrkList.GetMarkCount() != 1 || + !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) ) + return aRet; + + SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); + // --> OD 2004-07-16 #i28701# + SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj ); + SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt(); + RndStdIds nAnchorId = rFmt.GetAnchor().GetAnchorId(); + + if ( FLY_AS_CHAR == nAnchorId ) + return aRet; + + sal_Bool bFlyFrame = pObj->ISA(SwVirtFlyDrawObj); + + SwFlyFrm* pFly = 0L; + const SwFrm* pOldAnch; + const SwFrm* pFooterOrHeader = NULL; + + if( bFlyFrame ) + { + //Bezugspunkt in Dokumentkoordinaten bestimmen + SwCntntFrm *pCntnt = GetCurrFrm( sal_False ); + if( !pCntnt ) + return aRet; + pFly = pCntnt->FindFlyFrm(); + if ( !pFly ) + return aRet; + pOldAnch = pFly->GetAnchorFrm(); + if( !pOldAnch ) + return aRet; + if ( FLY_AT_PAGE != nAnchorId ) + { + pFooterOrHeader = pCntnt->FindFooterOrHeader(); + } + } + // OD 26.06.2003 #108784# - set <pFooterOrHeader> also for drawing + // objects, but not for control objects. + // Necessary for moving 'anchor symbol' at the user interface inside header/footer. + else if ( !::CheckControlLayer( pObj ) ) + { + SwCntntFrm *pCntnt = GetCurrFrm( sal_False ); + if( !pCntnt ) + return aRet; + pFooterOrHeader = pCntnt->FindFooterOrHeader(); + } + + //Ausgehend von der linken oberen Ecke des Fly den + //dichtesten SwFlyFrm suchen. + SwCntntFrm *pTxtFrm; + { + SwCrsrMoveState aState( MV_SETONLYTEXT ); + SwPosition aPos( GetDoc()->GetNodes().GetEndOfExtras() ); + Point aTmpPnt( rAbsPos ); + GetLayout()->GetCrsrOfst( &aPos, aTmpPnt, &aState ); + pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->GetFrm(0,&aPos,FALSE ); + } + const SwFrm *pNewAnch; + if( pTxtFrm ) + { + if ( FLY_AT_PAGE == nAnchorId ) + { + pNewAnch = pTxtFrm->FindPageFrm(); + } + else + { + pNewAnch = ::FindAnchor( pTxtFrm, rAbsPos ); + + if( FLY_AT_FLY == nAnchorId ) // LAYER_IMPL + { + pNewAnch = pNewAnch->FindFlyFrm(); + } + } + } + else + pNewAnch = 0; + + if( pNewAnch && !pNewAnch->IsProtected() ) + { + const SwFlyFrm* pCheck = bFlyFrame ? pNewAnch->FindFlyFrm() : 0; + // Falls wir innerhalb eines Rahmens landen, muss sichergestellt werden, + // dass der Rahmen nicht in seinem eigenen Inhalt landet! + while( pCheck ) + { + if( pCheck == pFly ) + break; + const SwFrm *pTmp = pCheck->GetAnchorFrm(); + pCheck = pTmp ? pTmp->FindFlyFrm() : NULL; + } + // Es darf nicht aus einer Kopf-/Fusszeile in einen anderen Bereich + // gewechselt werden, es darf nicht in eine Kopf-/Fusszeile hinein- + // gewechselt werden. + if( !pCheck && + pFooterOrHeader == pNewAnch->FindFooterOrHeader() ) + { + aRet = pNewAnch->GetFrmAnchorPos( ::HasWrap( pObj ) ); + + if ( bMoveIt || (nAnchorId == FLY_AT_CHAR) ) + { + SwFmtAnchor aAnch( rFmt.GetAnchor() ); + switch ( nAnchorId ) + { + case FLY_AT_PARA: + { + SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor(); + pPos->nNode = *pTxtFrm->GetNode(); + pPos->nContent.Assign(0,0); + break; + } + case FLY_AT_PAGE: + { + aAnch.SetPageNum( ((const SwPageFrm*)pNewAnch)-> + GetPhyPageNum() ); + break; + } + case FLY_AT_FLY: + { + SwPosition aPos( *((SwFlyFrm*)pNewAnch)->GetFmt()-> + GetCntnt().GetCntntIdx() ); + aAnch.SetAnchor( &aPos ); + break; + } + case FLY_AT_CHAR: + { + SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor(); + Point aTmpPnt( rAbsPos ); + if( pTxtFrm->GetCrsrOfst( pPos, aTmpPnt, NULL ) ) + { + SwRect aTmpRect; + pTxtFrm->GetCharRect( aTmpRect, *pPos ); + aRet = aTmpRect.Pos(); + } + else + { + pPos->nNode = *pTxtFrm->GetNode(); + pPos->nContent.Assign(0,0); + } + break; + } + default: + break; + } + if( bMoveIt ) + { + StartAllAction(); + // --> OD 2006-02-28 #125892# + // handle change of anchor node: + // if count of the anchor frame also change, the fly frames have to be + // re-created. Thus, delete all fly frames except the <this> before the + // anchor attribute is change and re-create them afterwards. + { + SwHandleAnchorNodeChg* pHandleAnchorNodeChg( 0L ); + SwFlyFrmFmt* pFlyFrmFmt( dynamic_cast<SwFlyFrmFmt*>(&rFmt) ); + if ( pFlyFrmFmt ) + { + pHandleAnchorNodeChg = + new SwHandleAnchorNodeChg( *pFlyFrmFmt, aAnch ); + } + rFmt.GetDoc()->SetAttr( aAnch, rFmt ); + delete pHandleAnchorNodeChg; + } + // <-- + // --> OD 2004-06-24 #i28701# - no call of method + // <CheckCharRectAndTopOfLine()> for to-character anchored + // Writer fly frame needed. This method call can cause a + // format of the anchor frame, which is no longer intended. + // Instead clear the anchor character rectangle and + // the top of line values for all to-character anchored objects. + pAnchoredObj->ClearCharRectAndTopOfLine(); + // <-- + EndAllAction(); + } + } + + SwRect aTmpRect( aRet, rAbsPos ); + if( aTmpRect.HasArea() ) + MakeVisible( aTmpRect ); +#ifdef DBG_UTIL + //TODO: That doesn't seem to be intended + if( Color(COL_TRANSPARENT) != GetOut()->GetLineColor() ) + { + ASSERT( FALSE, "Hey, Joe: Where's my Null Pen?" ); + GetOut()->SetLineColor( Color(COL_TRANSPARENT) ); + } +#endif + } + } + + return aRet; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : NewFlyFrm +#* Beschreibung: +#* Datum : MA 03. Nov. 92 +#* Update : JP 11. Aug. 93 +#***********************************************************************/ + +const SwFrmFmt *SwFEShell::NewFlyFrm( const SfxItemSet& rSet, sal_Bool bAnchValid, + SwFrmFmt *pParent ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + + SwPaM* pCrsr = GetCrsr(); + const Point aPt( GetCrsrDocPos() ); + + SwSelBoxes aBoxes; + sal_Bool bMoveCntnt = sal_True; + if( IsTableMode() ) + { + GetTblSel( *this, aBoxes ); + if( aBoxes.Count() ) + { + // die Crsr muessen noch aus dem Loeschbereich entfernt + // werden. Setze sie immer hinter/auf die Tabelle; ueber die + // Dokument-Position werden sie dann immer an die alte + // Position gesetzt. + ParkCrsr( SwNodeIndex( *aBoxes[0]->GetSttNd() )); + + // --> FME 2005-12-01 #i127787# pCurCrsr will be deleted in ParkCrsr, + // we better get the current pCurCrsr instead of working with the + // deleted one: + pCrsr = GetCrsr(); + // <-- + +// KillPams(); + } + else + bMoveCntnt = sal_False; + } + else if( !pCrsr->HasMark() && pCrsr->GetNext() == pCrsr ) + bMoveCntnt = sal_False; + + const SwPosition& rPos = *pCrsr->Start(); + + SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR ); + RndStdIds eRndId = rAnch.GetAnchorId(); + switch( eRndId ) + { + case FLY_AT_PAGE: + if( !rAnch.GetPageNum() ) //HotFix: Bug in UpdateByExample + rAnch.SetPageNum( 1 ); + break; + + case FLY_AT_FLY: + case FLY_AT_PARA: + case FLY_AT_CHAR: + case FLY_AS_CHAR: + if( !bAnchValid ) + { + if( FLY_AT_FLY != eRndId ) + { + rAnch.SetAnchor( &rPos ); + } + else if( lcl_SetNewFlyPos( rPos.nNode.GetNode(), rAnch, aPt ) ) + { + eRndId = FLY_AT_PAGE; + } + } + break; + + default: + ASSERT( !this, "Was sollte das fuer ein Fly werden?" ) + break; + } + + SwFlyFrmFmt *pRet; + if( bMoveCntnt ) + { + GetDoc()->StartUndo( UNDO_INSLAYFMT, NULL ); + SwFmtAnchor* pOldAnchor = 0; + sal_Bool bHOriChgd = sal_False, bVOriChgd = sal_False; + SwFmtVertOrient aOldV; + SwFmtHoriOrient aOldH; + + if ( FLY_AT_PAGE != eRndId ) + { + // erstmal als mit Seitenbindung, Absatz/Zeichenbindung erst wenn + // alles verschoben ist. Dann ist die Position gueltig! + // JP 13.05.98: ggfs. auch noch die Hori/Vert-Orientierung + // umsetzen, damit diese beim Umanker NICHT + // korrigiert wird + pOldAnchor = new SwFmtAnchor( rAnch ); + const_cast<SfxItemSet&>(rSet).Put( SwFmtAnchor( FLY_AT_PAGE, 1 ) ); + + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == rSet.GetItemState( RES_HORI_ORIENT, sal_False, &pItem ) + && text::HoriOrientation::NONE == ((SwFmtHoriOrient*)pItem)->GetHoriOrient() ) + { + bHOriChgd = sal_True; + aOldH = *((SwFmtHoriOrient*)pItem); + ((SfxItemSet&)rSet).Put( SwFmtHoriOrient( 0, text::HoriOrientation::LEFT ) ); + } + if( SFX_ITEM_SET == rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ) + && text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() ) + { + bVOriChgd = sal_True; + aOldV = *((SwFmtVertOrient*)pItem); + ((SfxItemSet&)rSet).Put( SwFmtVertOrient( 0, text::VertOrientation::TOP ) ); + } + } + + pRet = GetDoc()->MakeFlyAndMove( *pCrsr, rSet, &aBoxes, pParent ); + + KillPams(); + + if( pOldAnchor ) + { + if( pRet ) + { + // neue Position bestimmen + //JP 24.03.97: immer ueber die Seitenbindung gehen - der + // chaos::Anchor darf nie im verschobenen Bereich + // liegen + pRet->DelFrms(); + + const SwFrm* pAnch = ::FindAnchor( GetLayout(), aPt, sal_False ); + SwPosition aPos( *((SwCntntFrm*)pAnch)->GetNode() ); + if ( FLY_AS_CHAR == eRndId ) + { + aPos.nContent.Assign( ((SwCntntFrm*)pAnch)->GetNode(), 0 ); + } + pOldAnchor->SetAnchor( &aPos ); + + // das verschieben von TabelleSelektion ist noch nicht + // Undofaehig - also darf das UmAnkern auch nicht + // aufgezeichnet werden. + sal_Bool bDoesUndo = GetDoc()->DoesUndo(); + if( bDoesUndo && UNDO_INSLAYFMT == GetDoc()->GetUndoIds(NULL, NULL) ) + GetDoc()->DoUndo( sal_False ); + + ((SfxItemSet&)rSet).Put( *pOldAnchor ); + + if( bHOriChgd ) + ((SfxItemSet&)rSet).Put( aOldH ); + if( bVOriChgd ) + ((SfxItemSet&)rSet).Put( aOldV ); + + GetDoc()->SetFlyFrmAttr( *pRet, (SfxItemSet&)rSet ); + GetDoc()->DoUndo( bDoesUndo ); + } + delete pOldAnchor; + } + GetDoc()->EndUndo( UNDO_INSLAYFMT, NULL ); + } + else + /* #109161# If called from a shell try to propagate an + existing adjust item from rPos to the content node of the + new frame. */ + pRet = GetDoc()->MakeFlySection( eRndId, &rPos, &rSet, pParent, TRUE ); + + if( pRet ) + { + SwFlyFrm* pFrm = pRet->GetFrm( &aPt ); + if( pFrm ) + SelectFlyFrm( *pFrm, sal_True ); + else + { + GetLayout()->SetAssertFlyPages(); + pRet = 0; + } + } + EndAllActionAndCall(); + + return pRet; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : Insert +#* Datum : ?? +#* Update : MA 12. Sep. 94 +#***********************************************************************/ + +void SwFEShell::Insert( const String& rGrfName, const String& rFltName, + const Graphic* pGraphic, + const SfxItemSet* pFlyAttrSet, + const SfxItemSet* pGrfAttrSet, + SwFrmFmt* pFrmFmt ) +{ + SwFlyFrmFmt* pFmt = 0; + SET_CURR_SHELL( this ); + StartAllAction(); + SwShellCrsr *pStartCursor = dynamic_cast<SwShellCrsr*>(this->GetSwCrsr()); + SwShellCrsr *pCursor = pStartCursor; + do { + + // Anker noch nicht oder unvollstaendig gesetzt ? + if( pFlyAttrSet ) + { + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False, + &pItem ) ) + { + SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem; + switch( pAnchor->GetAnchorId()) + { + case FLY_AT_PARA: + case FLY_AT_CHAR: // LAYER_IMPL + case FLY_AS_CHAR: + if( !pAnchor->GetCntntAnchor() ) + { + pAnchor->SetAnchor( pCursor->GetPoint() ); + } + break; + case FLY_AT_FLY: + if( !pAnchor->GetCntntAnchor() ) + { + lcl_SetNewFlyPos( *pCursor->GetNode(), + *pAnchor, GetCrsrDocPos() ); + } + break; + case FLY_AT_PAGE: + if( !pAnchor->GetPageNum() ) + { + pAnchor->SetPageNum( pCursor->GetPageNum( + sal_True, &pCursor->GetPtPos() ) ); + } + break; + default : + break; + } + } + } + pFmt = GetDoc()->Insert(*pCursor, rGrfName, + rFltName, pGraphic, + pFlyAttrSet, + pGrfAttrSet, pFrmFmt ); + ASSERT( pFmt, "Doc->Insert(notxt) failed." ); + + } while( (pCursor = dynamic_cast<SwShellCrsr*>(pCursor->GetNext())) + != pStartCursor ); + + EndAllAction(); + + if( pFmt ) + { + const Point aPt( GetCrsrDocPos() ); + SwFlyFrm* pFrm = pFmt->GetFrm( &aPt ); + + if( pFrm ) + SelectFlyFrm( *pFrm, sal_True ); + else + GetLayout()->SetAssertFlyPages(); + } +} + +SwFlyFrmFmt* SwFEShell::InsertObject( const svt::EmbeddedObjectRef& xObj, + const SfxItemSet* pFlyAttrSet, + const SfxItemSet* pGrfAttrSet, + SwFrmFmt* pFrmFmt ) +{ + SwFlyFrmFmt* pFmt = 0; + SET_CURR_SHELL( this ); + StartAllAction(); + FOREACHPAM_START( this ) + pFmt = GetDoc()->Insert(*PCURCRSR, xObj, + pFlyAttrSet, pGrfAttrSet, pFrmFmt ); + ASSERT( pFmt, "Doc->Insert(notxt) failed." ); + + FOREACHPAM_END() + EndAllAction(); + + if( pFmt ) + { + const Point aPt( GetCrsrDocPos() ); + SwFlyFrm* pFrm = pFmt->GetFrm( &aPt ); + + if( pFrm ) + SelectFlyFrm( *pFrm, sal_True ); + else + GetLayout()->SetAssertFlyPages(); + } + + return pFmt; +} + + +void SwFEShell::InsertDrawObj( SdrObject& rDrawObj, + const Point& rInsertPosition ) +{ + SET_CURR_SHELL( this ); + + SfxItemSet rFlyAttrSet( GetDoc()->GetAttrPool(), aFrmFmtSetRange ); + rFlyAttrSet.Put( SwFmtAnchor( FLY_AT_PARA )); + // --> OD 2009-12-29 #i89920# + rFlyAttrSet.Put( SwFmtSurround( SURROUND_THROUGHT ) ); + rDrawObj.SetLayer( getIDocumentDrawModelAccess()->GetHeavenId() ); + // <-- + + // find anchor position + SwPaM aPam( pDoc->GetNodes() ); + { + SwCrsrMoveState aState( MV_SETONLYTEXT ); + Point aTmpPt( rInsertPosition ); + getIDocumentLayoutAccess()->GetRootFrm()->GetCrsrOfst( aPam.GetPoint(), aTmpPt, &aState ); + const SwFrm* pFrm = aPam.GetCntntNode()->GetFrm( 0, 0, sal_False ); + const Point aRelPos( rInsertPosition.X() - pFrm->Frm().Left(), + rInsertPosition.Y() - pFrm->Frm().Top() ); + rDrawObj.SetRelativePos( aRelPos ); + ::lcl_FindAnchorPos( *GetDoc(), rInsertPosition, *pFrm, rFlyAttrSet ); + } + // insert drawing object into the document creating a new <SwDrawFrmFmt> instance + SwDrawFrmFmt* pFmt = GetDoc()->Insert( aPam, rDrawObj, &rFlyAttrSet, 0 ); + + // move object to visible layer + SwContact* pContact = static_cast<SwContact*>(rDrawObj.GetUserCall()); + if ( pContact ) + { + pContact->MoveObjToVisibleLayer( &rDrawObj ); + } + + if ( pFmt ) + { + // select drawing object + Imp()->GetDrawView()->MarkObj( &rDrawObj, Imp()->GetPageView(), + sal_False, sal_False ); + } + else + { + GetLayout()->SetAssertFlyPages(); + } +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : GetPageObjs +#* Datum : ?? +#* Update : MA 11. Jan. 95 +#***********************************************************************/ + +void SwFEShell::GetPageObjs( SvPtrarr& rFillArr ) +{ + if( rFillArr.Count() ) + rFillArr.Remove( 0, rFillArr.Count() ); + + const SwFrmFmt* pFmt; + for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n ) + { + pFmt = (const SwFrmFmt*)(*pDoc->GetSpzFrmFmts())[n]; + if (FLY_AT_PAGE == pFmt->GetAnchor().GetAnchorId()) + { + rFillArr.Insert( (VoidPtr)pFmt, rFillArr.Count() ); + } + } +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : SetPageFlysNewPage +#* Datum : ?? +#* Update : MA 14. Feb. 95 +#***********************************************************************/ + +void SwFEShell::SetPageObjsNewPage( SvPtrarr& rFillArr, int nOffset ) +{ + if( !rFillArr.Count() || !nOffset ) + return; + + StartAllAction(); + StartUndo(); + + SwFrmFmt* pFmt; + long nNewPage; + SwRootFrm* pTmpRootFrm = getIDocumentLayoutAccess()->GetRootFrm(); + sal_uInt16 nMaxPage = pTmpRootFrm->GetPageNum(); + sal_Bool bTmpAssert = sal_False; + for( sal_uInt16 n = 0; n < rFillArr.Count(); ++n ) + { + pFmt = (SwFrmFmt*)rFillArr[n]; + if( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( pFmt )) + { + // FlyFmt ist noch gueltig, also behandeln + SwFmtAnchor aNewAnchor( pFmt->GetAnchor() ); + if ((FLY_AT_PAGE != aNewAnchor.GetAnchorId()) || + 0 >= ( nNewPage = aNewAnchor.GetPageNum() + nOffset ) ) + // chaos::Anchor wurde veraendert oder ungueltige SeitenNummer, + // also nicht veraendern !! + continue; + + if( sal_uInt16(nNewPage) > nMaxPage ) + { + if ( RES_DRAWFRMFMT == pFmt->Which() ) + { + SwContact *pCon = pFmt->FindContactObj(); + if( pCon ) + ((SwDrawContact*)pCon)->DisconnectFromLayout(); + } + else + pFmt->DelFrms(); + bTmpAssert = sal_True; + } + aNewAnchor.SetPageNum( sal_uInt16(nNewPage) ); + pDoc->SetAttr( aNewAnchor, *pFmt ); + } + } + + if( bTmpAssert ) + pTmpRootFrm->SetAssertFlyPages(); + + EndUndo(); + EndAllAction(); +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : GetFlyFrmAttr +#* Beschreibung: Alle Attribute in dem 'Koerbchen' werden mit den +#* Attributen des aktuellen FlyFrms gefuellt. +#* Sind Attribute nicht zu fuellen weil fehl am Platz oder +#* uneindeutig (Mehrfachtselektionen) so werden sie entfernt. +#* Datum : MA 03. Nov. 92 +#* Update : MA 03. Feb. 94 +#***********************************************************************/ + +sal_Bool SwFEShell::GetFlyFrmAttr( SfxItemSet &rSet ) const +{ + SwFlyFrm *pFly = FindFlyFrm(); + if ( !pFly ) + { + // --> OD 2006-11-08 #139670# - make code robust + SwFrm* pCurrFrm( GetCurrFrm() ); + if ( !pCurrFrm ) + { + ASSERT( false, + "<SwFEShell::GetFlyFrmAttr(..)> - missing current frame. This is a serious defect, please inform OD." ); + return sal_False; + } + // <-- + pFly = GetCurrFrm()->FindFlyFrm(); + if ( !pFly ) + { + ASSERT( !this, "GetFlyFrmAttr, no Fly selected." ); + return sal_False; + } + } + + SET_CURR_SHELL( (ViewShell*)this ); + + if( !rSet.Set( pFly->GetFmt()->GetAttrSet(), sal_True ) ) + return sal_False; + + //Und die Attribute durchschaufeln. Unerlaubte Attribute entfernen, dann + //alle restlichen Attribute besorgen und eintragen. + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False, &pItem ) ) + { + SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem; + RndStdIds eType = pAnchor->GetAnchorId(); + + if ( FLY_AT_PAGE != eType ) + { + // OD 12.11.2003 #i22341# - content anchor of anchor item is needed. + // Thus, don't overwrite anchor item by default contructed anchor item. + //rSet.Put( SwFmtAnchor( eType ) ); + if ( FLY_AS_CHAR == eType ) + { + rSet.ClearItem( RES_OPAQUE ); + rSet.ClearItem( RES_SURROUND ); + } + } + } + rSet.SetParent( pFly->GetFmt()->GetAttrSet().GetParent() ); + //JP 11.02.97: Bug #35894#: die Attribute MUESSEN entfern werden! + rSet.ClearItem( RES_FILL_ORDER ); + rSet.ClearItem( RES_CNTNT ); + //MA: Ersteinmal entfernen (Template by example usw.) + rSet.ClearItem( RES_CHAIN ); + return sal_True; +} +/*********************************************************************** +#* Class : SwFEShell +#* Methode : SetFlyFrmAttr +#* Beschreibung: Die Attribute des aktuellen Flys aendern sich. +#* Datum : MA 03. Nov. 92 +#* Update : MA 01. Aug. 95 +#***********************************************************************/ + +sal_Bool SwFEShell::SetFlyFrmAttr( SfxItemSet& rSet ) +{ + SET_CURR_SHELL( this ); + sal_Bool bRet = sal_False; + + if( rSet.Count() ) + { + SwFlyFrm *pFly = FindFlyFrm(); + if( !pFly ) + { + ASSERT( GetCurrFrm(), "Crsr in parking zone" ); + pFly = GetCurrFrm()->FindFlyFrm(); + ASSERT( pFly, "SetFlyFrmAttr, no Fly selected." ); + } + if( pFly ) + { + StartAllAction(); + const Point aPt( pFly->Frm().Pos() ); + + if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False )) + ::lcl_ChkAndSetNewAnchor( *pFly, rSet ); + SwFlyFrmFmt* pFlyFmt = (SwFlyFrmFmt*)pFly->GetFmt(); + + if( GetDoc()->SetFlyFrmAttr( *pFlyFmt, rSet )) + { + bRet = sal_True; + SwFlyFrm* pFrm = pFlyFmt->GetFrm( &aPt ); + if( pFrm ) + SelectFlyFrm( *pFrm, sal_True ); + else + GetLayout()->SetAssertFlyPages(); + } + + EndAllActionAndCall(); + } + } + return bRet; +} +/*-- 30.03.2004 15:05:07--------------------------------------------------- + + -----------------------------------------------------------------------*/ +sal_Bool SwFEShell::SetDrawingAttr( SfxItemSet& rSet ) +{ + sal_Bool bRet = sal_False; + SET_CURR_SHELL( this ); + if ( !rSet.Count() || + !Imp()->HasDrawView() ) + return bRet; + + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + if ( rMrkList.GetMarkCount() != 1 ) + return bRet; + + StartUndo(); + SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); + SwFrmFmt *pFmt = FindFrmFmt( pObj ); + StartAllAction(); + if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False )) + { + RndStdIds nNew = ((SwFmtAnchor&)rSet.Get( RES_ANCHOR )).GetAnchorId(); + if ( nNew != pFmt->GetAnchor().GetAnchorId() ) + { + ChgAnchor( nNew ); + // --> OD 2004-06-17 #i26791# - clear anchor attribute in item set, + // because method <ChgAnchor(..)> takes care of it. + rSet.ClearItem( RES_ANCHOR ); + } + } + + if( GetDoc()->SetFlyFrmAttr( *pFmt, rSet )) + { + bRet = sal_True; + Point aTmp; + SelectObj( aTmp, 0, pObj ); + } + EndAllActionAndCall(); + EndUndo(); + return bRet; +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : ResetFlyFrmAttr +#* Beschreibung: Das gewuenschte Attribut oder die im Set befindlichen +#* werden zurueckgesetzt. +#* Datum : MA 14. Mar. 97 +#* Update : MA 14. Mar. 97 +#***********************************************************************/ + +sal_Bool SwFEShell::ResetFlyFrmAttr( sal_uInt16 nWhich, const SfxItemSet* pSet ) +{ + sal_Bool bRet = sal_False; + + if( RES_ANCHOR != nWhich && RES_CHAIN != nWhich && RES_CNTNT != nWhich ) + { + SET_CURR_SHELL( this ); + + SwFlyFrm *pFly = FindFlyFrm(); + if( !pFly ) + { + ASSERT( GetCurrFrm(), "Crsr in parking zone" ); + pFly = GetCurrFrm()->FindFlyFrm(); + ASSERT( pFly, "SetFlyFrmAttr, no Fly selected." ); + } + + if( pFly ) + { + StartAllAction(); + + if( pSet ) + { + SfxItemIter aIter( *pSet ); + const SfxPoolItem* pItem = aIter.FirstItem(); + while( pItem ) + { + if( !IsInvalidItem( pItem ) && + RES_ANCHOR != ( nWhich = pItem->Which() ) && + RES_CHAIN != nWhich && RES_CNTNT != nWhich ) + pFly->GetFmt()->ResetFmtAttr( nWhich ); + pItem = aIter.NextItem(); + } + } + else + pFly->GetFmt()->ResetFmtAttr( nWhich ); + + bRet = sal_True; + EndAllActionAndCall(); + GetDoc()->SetModified(); + } + } + return bRet; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : GetCurFrmFmt +#* Beschreibung: liefert wenn Rahmen, dann Rahmenvorlage, sonst 0 +#* Datum : ST 04. Jun. 93 +#* Update : +#***********************************************************************/ + +SwFrmFmt* SwFEShell::GetCurFrmFmt() const +{ + SwFrmFmt* pRet = 0; + SwLayoutFrm *pFly = FindFlyFrm(); + if( pFly && ( pRet = (SwFrmFmt*)pFly->GetFmt()->DerivedFrom() ) == + GetDoc()->GetDfltFrmFmt() ) + pRet = 0; + return pRet; +} + +/****************************************************************************** + * Methode : void SwFEShell::SetFrmFmt(SwFrmFmt *pNewFmt) + * Beschreibung: + * Erstellt : OK 14.04.94 15:40 + * Aenderung : MA 23. Apr. 97 + ******************************************************************************/ + +void SwFEShell::SetFrmFmt( SwFrmFmt *pNewFmt, sal_Bool bKeepOrient, Point* pDocPos ) +{ + SwFlyFrm *pFly = 0; + if(pDocPos) + { + const SwFrmFmt* pFmt = GetFmtFromObj( *pDocPos ); + + if(PTR_CAST(SwFlyFrmFmt, pFmt)) + pFly = ((SwFlyFrmFmt*)pFmt)->GetFrm(); + } + else + pFly = FindFlyFrm(); + ASSERT( pFly, "SetFrmFmt: kein Frame" ); + if( pFly ) + { + StartAllAction(); + SET_CURR_SHELL( this ); + + SwFlyFrmFmt* pFlyFmt = (SwFlyFrmFmt*)pFly->GetFmt(); + const Point aPt( pFly->Frm().Pos() ); + + SfxItemSet* pSet = 0; + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == pNewFmt->GetItemState( RES_ANCHOR, sal_False, &pItem )) + { + pSet = new SfxItemSet( GetDoc()->GetAttrPool(), aFrmFmtSetRange ); + pSet->Put( *pItem ); + if( !::lcl_ChkAndSetNewAnchor( *pFly, *pSet )) + delete pSet, pSet = 0; + } + + if( GetDoc()->SetFrmFmtToFly( *pFlyFmt, *pNewFmt, pSet, bKeepOrient )) + { + SwFlyFrm* pFrm = pFlyFmt->GetFrm( &aPt ); + if( pFrm ) + SelectFlyFrm( *pFrm, sal_True ); + else + GetLayout()->SetAssertFlyPages(); + } + if( pSet ) + delete pSet; + + EndAllActionAndCall(); + } +} + +/************************************************************************* +|* +|* SwFEShell::GetFlyFrmFmt() +|* +|* Ersterstellung OK 23.06.93 13:15 +|* Letzte Aenderung OK 23.06.93 13:15 +|* +*************************************************************************/ + +const SwFrmFmt* SwFEShell::GetFlyFrmFmt() const +{ + const SwFlyFrm* pFly = FindFlyFrm(); + if ( !pFly ) + { + SwFrm* pCurrFrm = GetCurrFrm(); + pFly = pCurrFrm ? pCurrFrm->FindFlyFrm() : 0; + } + if( pFly ) + return pFly->GetFmt(); + return 0; +} + +SwFrmFmt* SwFEShell::GetFlyFrmFmt() +{ + SwFlyFrm* pFly = FindFlyFrm(); + if ( !pFly ) + { + SwFrm* pCurrFrm = GetCurrFrm(); + pFly = pCurrFrm ? pCurrFrm->FindFlyFrm() : 0; + } + if( pFly ) + return pFly->GetFmt(); + return 0; +} + +/************************************************************************* +|* +|* SwFEShell::GetFlyRect() +|* +|* Ersterstellung AMA 6. Mae. 97 +|* Letzte Aenderung AMA 6. Mae. 97 +|* +*************************************************************************/ + +SwRect SwFEShell::GetFlyRect() const +{ + SwCntntFrm *pCntnt = GetCurrFrm( sal_False ); + SwFlyFrm *pFly = pCntnt ? pCntnt->FindFlyFrm() : 0; + if ( !pFly ) + { + SwRect aRect; + return aRect; + } + else + return pFly->Frm(); +} + +/************************************************************************* +|* +|* SwFEShell::GetObjRect() +|* +|* Ersterstellung MA 22. Aug. 93 +|* Letzte Aenderung MA 11. Jan. 95 +|* +*************************************************************************/ + +SwRect SwFEShell::GetObjRect() const +{ + if( Imp()->HasDrawView() ) + return Imp()->GetDrawView()->GetAllMarkedRect(); + else + { + SwRect aRect; + return aRect; + } +} + +void SwFEShell::SetObjRect( const SwRect& rRect ) +{ + if ( Imp()->HasDrawView() ) + { + Imp()->GetDrawView()->SetAllMarkedRect( rRect.SVRect() ); + CallChgLnk(); // rufe das AttrChangeNotify auf der UI-Seite. + } +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : RequestObjectResize() +#* Datum : MA 10. Feb. 95 +#* Update : MA 13. Jul. 95 +#***********************************************************************/ + +Size SwFEShell::RequestObjectResize( const SwRect &rRect, const uno::Reference < embed::XEmbeddedObject >& xObj ) +{ + Size aResult; + + SwFlyFrm *pFly = FindFlyFrm( xObj ); + if ( !pFly ) + { + aResult = rRect.SSize(); + return aResult; + } + + aResult = pFly->Prt().SSize(); + + sal_Bool bPosProt = pFly->GetFmt()->GetProtect().IsPosProtected(); + sal_Bool bSizeProt = pFly->GetFmt()->GetProtect().IsSizeProtected(); + + StartAllAction(); + + //MA wir lassen den Fly nicht Clippen, damit die Ole-Server mit + //beliebigen Wuenschen kommen koennen. Die Formatierung uebernimmt das + //Clippen. Die richtige Darstellung wird per Scalierung erledigt. + //Die Scalierung wird von SwNoTxtFrm::Format durch einen Aufruf von + //SwWrtShell::CalcAndSetScale() erledigt. + if ( rRect.SSize() != pFly->Prt().SSize() && !bSizeProt ) + { + Size aSz( rRect.SSize() ); + + //JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size + // + const SwFrm* pAnchor; + const SwTxtNode* pTNd; + const SwpHints* pHts; + const SwFmtFrmSize& rFrmSz = pFly->GetFmt()->GetFrmSize(); + if( bCheckForOLEInCaption && + 0 != rFrmSz.GetWidthPercent() && + 0 != (pAnchor = pFly->GetAnchorFrm()) && + pAnchor->IsTxtFrm() && + !pAnchor->GetNext() && !pAnchor->GetPrev() && + pAnchor->GetUpper()->IsFlyFrm() && + 0 != ( pTNd = ((SwTxtFrm*)pAnchor)->GetNode()->GetTxtNode()) && + 0 != ( pHts = pTNd->GetpSwpHints() )) + { + // search for a sequence field: + const SfxPoolItem* pItem; + for( USHORT n = 0, nEnd = pHts->Count(); n < nEnd; ++n ) + if( RES_TXTATR_FIELD == ( pItem = + &(*pHts)[ n ]->GetAttr())->Which() && + TYP_SEQFLD == ((SwFmtFld*)pItem)->GetFld()->GetTypeId() ) + { + // sequence field found + SwFlyFrm* pChgFly = (SwFlyFrm*)pAnchor->GetUpper(); + // calculate the changed size: + // width must change, height can change + Size aNewSz( aSz.Width() + pChgFly->Frm().Width() - + pFly->Prt().Width(), aSz.Height() ); + + SwFrmFmt *pFmt = pChgFly->GetFmt(); + SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() ); + aFrmSz.SetWidth( aNewSz.Width() ); + if( ATT_MIN_SIZE != aFrmSz.GetHeightSizeType() ) + { + aNewSz.Height() += pChgFly->Frm().Height() - + pFly->Prt().Height(); + if( Abs( aNewSz.Height() - pChgFly->Frm().Height()) > 1 ) + aFrmSz.SetHeight( aNewSz.Height() ); + } + // uebers Doc fuers Undo! + pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt ); + break; + } + } + + // set the new Size at the fly themself + if ( pFly->Prt().Height() > 0 && pFly->Prt().Width() > 0 ) + { + aSz.Width() += pFly->Frm().Width() - pFly->Prt().Width(); + aSz.Height()+= pFly->Frm().Height()- pFly->Prt().Height(); + } + aResult = pFly->ChgSize( aSz ); + + //Wenn sich das Objekt aendert ist die Kontur hoechstwahrscheinlich daneben. + ASSERT( pFly->Lower()->IsNoTxtFrm(), "Request ohne NoTxt" ); + SwNoTxtNode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetNoTxtNode(); + ASSERT( pNd, "Request ohne Node" ); + pNd->SetContour( 0 ); + ClrContourCache(); + } + + //Wenn nur die Size angepasst werden soll, so wird eine Pos mit + //ausgezeichneten Werten transportiert. + Point aPt( pFly->Prt().Pos() ); + aPt += pFly->Frm().Pos(); + if ( rRect.Top() != LONG_MIN && rRect.Pos() != aPt && !bPosProt ) + { + aPt = rRect.Pos(); + aPt.X() -= pFly->Prt().Left(); + aPt.Y() -= pFly->Prt().Top(); + //Bei Absatzgebundenen Flys muss ausgehend von der neuen Position ein + //neuer Anker gesetzt werden. Anker und neue RelPos werden vom Fly + //selbst berechnet und gesetzt. + if( pFly->IsFlyAtCntFrm() ) + ((SwFlyAtCntFrm*)pFly)->SetAbsPos( aPt ); + else + { + const SwFrmFmt *pFmt = pFly->GetFmt(); + const SwFmtVertOrient &rVert = pFmt->GetVertOrient(); + const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient(); + const long lXDiff = aPt.X() - pFly->Frm().Left(); + const long lYDiff = aPt.Y() - pFly->Frm().Top(); + const Point aTmp( rHori.GetPos() + lXDiff, + rVert.GetPos() + lYDiff ); + pFly->ChgRelPos( aTmp ); + } + } + EndAllAction(); + + return aResult; +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : WizzardFindCurFrmFmt +#* Datum : JP 31.07.95 +#* Update : JP 31.07.95 +#***********************************************************************/ + +SwFrmFmt* SwFEShell::WizzardGetFly() +{ + // mal nicht uebers Layout den Fly suchen. Dann kann auch ohne gueltiges + // Layout ein Rahmen geloescht werden. ( z.B.: fuer die Wizard's ) + SwSpzFrmFmts& rSpzArr = *pDoc->GetSpzFrmFmts(); + sal_uInt16 nCnt = rSpzArr.Count(); + if( nCnt ) + { + SwNodeIndex& rCrsrNd = GetCrsr()->GetPoint()->nNode; + if( rCrsrNd.GetIndex() > pDoc->GetNodes().GetEndOfExtras().GetIndex() ) + // Cusor steht im Body-Bereich! + return 0; + + for( sal_uInt16 n = 0; n < nCnt; ++n ) + { + SwFrmFmt* pFmt = rSpzArr[ n ]; + const SwNodeIndex* pIdx = pFmt->GetCntnt( sal_False ).GetCntntIdx(); + SwStartNode* pSttNd; + if( pIdx && + 0 != ( pSttNd = pIdx->GetNode().GetStartNode() ) && + pSttNd->GetIndex() < rCrsrNd.GetIndex() && + rCrsrNd.GetIndex() < pSttNd->EndOfSectionIndex() ) + { + // gefunden: also raus damit + return pFmt; + } + } + } + return 0; +} + +void SwFEShell::SetFlyName( const String& rName ) +{ + SwLayoutFrm *pFly = FindFlyFrm(); + if( pFly ) + GetDoc()->SetFlyName( *(SwFlyFrmFmt*)pFly->GetFmt(), rName ); + else { + ASSERT( !this, "kein FlyFrame selektiert" ) + } +} + +const String& SwFEShell::GetFlyName() const +{ + SwLayoutFrm *pFly = FindFlyFrm(); + if( pFly ) + return pFly->GetFmt()->GetName(); + + ASSERT( !this, "kein FlyFrame selektiert" ) + return aEmptyStr; +} + + +String SwFEShell::GetUniqueGrfName() const +{ + return GetDoc()->GetUniqueGrfName(); +} + +const SwFrmFmt* SwFEShell::IsURLGrfAtPos( const Point& rPt, String* pURL, + String *pTargetFrameName, + String *pDescription ) const +{ + if( !Imp()->HasDrawView() ) + return 0; + + SdrObject* pObj; + SdrPageView* pPV; + const SwFrmFmt* pRet = 0; + SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView(); + + sal_uInt16 nOld = pDView->GetHitTolerancePixel(); + pDView->SetHitTolerancePixel( 2 ); + + if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV,SDRSEARCH_PICKMACRO ) && + pObj->ISA(SwVirtFlyDrawObj) ) + { + SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); + const SwFmtURL &rURL = pFly->GetFmt()->GetURL(); + if( rURL.GetURL().Len() || rURL.GetMap() ) + { + BOOL bSetTargetFrameName = pTargetFrameName != 0; + BOOL bSetDescription = pDescription != 0; + if ( rURL.GetMap() ) + { + IMapObject *pObject = pFly->GetFmt()->GetIMapObject( rPt, pFly ); + if ( pObject && pObject->GetURL().Len() ) + { + if( pURL ) + *pURL = pObject->GetURL(); + if ( bSetTargetFrameName && pObject->GetTarget().Len() ) + { + bSetTargetFrameName = sal_False; + *pTargetFrameName = pObject->GetTarget(); + } + if ( bSetDescription ) + { + bSetDescription = sal_False; + *pDescription = pObject->GetAltText(); + } + pRet = pFly->GetFmt(); + } + } + else + { + if( pURL ) + { + *pURL = rURL.GetURL(); + if( rURL.IsServerMap() ) + { + // dann die rel. Pixel Position anhaengen !! + Point aPt( rPt ); + aPt -= pFly->Frm().Pos(); + // ohne MapMode-Offset, ohne Offset, o ... !!!!! + aPt = GetOut()->LogicToPixel( + aPt, MapMode( MAP_TWIP ) ); + ((( *pURL += '?' ) += String::CreateFromInt32( aPt.X() )) + += ',' ) += String::CreateFromInt32(aPt.Y() ); + } + } + pRet = pFly->GetFmt(); + } + if ( bSetTargetFrameName ) + *pTargetFrameName = rURL.GetTargetFrameName(); + if ( bSetDescription ) + *pDescription = pFly->GetFmt()->GetName(); + } + } + pDView->SetHitTolerancePixel( nOld ); + return pRet; +} + +const Graphic *SwFEShell::GetGrfAtPos( const Point &rPt, + String &rName, sal_Bool &rbLink ) const +{ + if( !Imp()->HasDrawView() ) + return 0; + + SdrObject* pObj; + SdrPageView* pPV; + SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView(); + + if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV ) && pObj->ISA(SwVirtFlyDrawObj) ) + { + SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); + if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() ) + { + SwGrfNode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode(); + if ( pNd ) + { + if ( pNd->IsGrfLink() ) + { + //Halbfertige Grafik? + ::sfx2::SvLinkSource* pLnkObj = pNd->GetLink()->GetObj(); + if( pLnkObj && pLnkObj->IsPending() ) + return 0; + rbLink = sal_True; + } + + pNd->GetFileFilterNms( &rName, 0 ); + if ( !rName.Len() ) + rName = pFly->GetFmt()->GetName(); + pNd->SwapIn( sal_True ); + return &pNd->GetGrf(); + } + } + } + return 0; +} + + +const SwFrmFmt* SwFEShell::GetFmtFromObj( const Point& rPt, SwRect** pRectToFill ) const +{ + SwFrmFmt* pRet = 0; + + if( Imp()->HasDrawView() ) + { + SdrObject* pObj; + SdrPageView* pPView; + + SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView(); + + sal_uInt16 nOld = pDView->GetHitTolerancePixel(); + // Tattergrenze fuer Drawing-SS + pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 ); + + if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) ) + { + // dann teste mal was es ist: + if ( pObj->ISA(SwVirtFlyDrawObj) ) + pRet = ((SwVirtFlyDrawObj*)pObj)->GetFmt(); + else if ( pObj->GetUserCall() ) //nicht fuer Gruppenobjekte + pRet = ((SwDrawContact*)pObj->GetUserCall())->GetFmt(); + if(pRet && pRectToFill) + **pRectToFill = pObj->GetCurrentBoundRect(); + } + pDView->SetHitTolerancePixel( nOld ); + } + return pRet; +} + +// returns a format too, if the point is over the text of any fly +const SwFrmFmt* SwFEShell::GetFmtFromAnyObj( const Point& rPt ) const +{ + const SwFrmFmt* pRet = GetFmtFromObj( rPt ); + if( !pRet || RES_FLYFRMFMT == pRet->Which() ) + { + SwPosition aPos( *GetCrsr()->GetPoint() ); + Point aPt( rPt ); + GetLayout()->GetCrsrOfst( &aPos, aPt ); + SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode(); + SwFrm* pFrm = pNd->GetFrm( &rPt )->FindFlyFrm(); + pRet = pFrm ? ((SwLayoutFrm*)pFrm)->GetFmt() : 0; + } + return pRet; +} + +ObjCntType SwFEShell::GetObjCntType( const SdrObject& rObj ) const +{ + ObjCntType eType = OBJCNT_NONE; + + // OD 23.06.2003 #108784# - investigate 'master' drawing object, if method + // is called for a 'virtual' drawing object. + const SdrObject* pInvestigatedObj; + if ( rObj.ISA(SwDrawVirtObj) ) + { + const SwDrawVirtObj* pDrawVirtObj = static_cast<const SwDrawVirtObj*>(&rObj); + pInvestigatedObj = &(pDrawVirtObj->GetReferencedObj()); + } + else + { + pInvestigatedObj = &rObj; + } + + if( FmFormInventor == pInvestigatedObj->GetObjInventor() ) + { + eType = OBJCNT_CONTROL; + uno::Reference< awt::XControlModel > xModel = + ((SdrUnoObj&)(*pInvestigatedObj)).GetUnoControlModel(); + if( xModel.is() ) + { + uno::Any aVal; + OUString sName = OUString::createFromAscii("ButtonType"); + uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY); + + uno::Reference< beans::XPropertySetInfo > xInfo = xSet->getPropertySetInfo(); + if(xInfo->hasPropertyByName( sName )) + { + beans::Property xProperty = xInfo->getPropertyByName( sName ); + aVal = xSet->getPropertyValue( sName ); + if( aVal.getValue() && form::FormButtonType_URL == *((form::FormButtonType*)aVal.getValue()) ) + eType = OBJCNT_URLBUTTON; + } + } + } + else if( pInvestigatedObj->ISA(SwVirtFlyDrawObj) ) + { + SwFlyFrm *pFly = ((SwVirtFlyDrawObj&)(*pInvestigatedObj)).GetFlyFrm(); + if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() ) + { + if ( ((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode() ) + eType = OBJCNT_GRF; + else + eType = OBJCNT_OLE; + } + else + eType = OBJCNT_FLY; + } + else if ( pInvestigatedObj->ISA( SdrObjGroup ) ) + { + SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(GetUserCall( pInvestigatedObj ) ) ); + if ( !pDrawContact ) + { + ASSERT( false, + "<SwFEShell::GetObjCntType(..)> - missing draw contact object" ); + eType = OBJCNT_NONE; + } + else + { + SwFrmFmt* pFrmFmt( pDrawContact->GetFmt() ); + if ( !pFrmFmt ) + { + ASSERT( false, + "<SwFEShell::GetObjCntType(..)> - missing frame format" ); + eType = OBJCNT_NONE; + } + else if ( FLY_AS_CHAR != pFrmFmt->GetAnchor().GetAnchorId() ) + { + eType = OBJCNT_GROUPOBJ; + } + } + } + else + eType = OBJCNT_SIMPLE; + return eType; +} + +ObjCntType SwFEShell::GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const +{ + ObjCntType eType = OBJCNT_NONE; + + if( Imp()->HasDrawView() ) + { + SdrObject* pObj; + SdrPageView* pPView; + + SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView(); + + sal_uInt16 nOld = pDView->GetHitTolerancePixel(); + // Tattergrenze fuer Drawing-SS + pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 ); + + if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) ) + eType = GetObjCntType( *(rpObj = pObj) ); + + pDView->SetHitTolerancePixel( nOld ); + } + return eType; +} + +ObjCntType SwFEShell::GetObjCntTypeOfSelection( SdrObject** ppObj ) const +{ + ObjCntType eType = OBJCNT_NONE; + + if( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for( sal_uInt32 i = 0, nE = rMrkList.GetMarkCount(); i < nE; ++i ) + { + SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + ObjCntType eTmp = GetObjCntType( *pObj ); + if( !i ) + { + eType = eTmp; + if( ppObj ) *ppObj = pObj; + } + else if( eTmp != eType ) + { + eType = OBJCNT_DONTCARE; + // einmal DontCare, immer DontCare! + break; + } + } + } + return eType; +} + + +sal_Bool SwFEShell::ReplaceSdrObj( const String& rGrfName, const String& rFltName, + const Graphic* pGrf ) +{ + SET_CURR_SHELL( this ); + + sal_Bool bRet = sal_False; + const SdrMarkList *pMrkList; + if( Imp()->HasDrawView() && 1 == + ( pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList())->GetMarkCount() ) + { + SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + SwFrmFmt *pFmt = FindFrmFmt( pObj ); + + // Attribute sichern und dann an der Grafik setzen + SfxItemSet aFrmSet( pDoc->GetAttrPool(), + pFmt->GetAttrSet().GetRanges() ); + aFrmSet.Set( pFmt->GetAttrSet() ); + + // Groesse und Position setzen ?? + if( !pObj->ISA(SwVirtFlyDrawObj) ) + { + // dann mal los: + const Rectangle &rBound = pObj->GetSnapRect(); + Point aRelPos( pObj->GetRelativePos() ); + + const long nWidth = rBound.Right() - rBound.Left(); + const long nHeight= rBound.Bottom() - rBound.Top(); + aFrmSet.Put( SwFmtFrmSize( ATT_MIN_SIZE, + Max( nWidth, long(MINFLY) ), + Max( nHeight, long(MINFLY) ))); + + if( SFX_ITEM_SET != aFrmSet.GetItemState( RES_HORI_ORIENT )) + aFrmSet.Put( SwFmtHoriOrient( aRelPos.X(), text::HoriOrientation::NONE, text::RelOrientation::FRAME )); + + if( SFX_ITEM_SET != aFrmSet.GetItemState( RES_VERT_ORIENT )) + aFrmSet.Put( SwFmtVertOrient( aRelPos.Y(), text::VertOrientation::NONE, text::RelOrientation::FRAME )); + + } + + pObj->GetOrdNum(); + + StartAllAction(); + StartUndo(); + + // das "Sdr-Object" loeschen und dafuer die Grafik einfuegen + DelSelectedObj(); + + pFmt = GetDoc()->Insert( *GetCrsr(), rGrfName, rFltName, pGrf, &aFrmSet, NULL, NULL ); + + // die Ordnungsnummer (Z-Order) noch uebertragen + // JP 04.07.98: klappt aber nicht richtig! + //SdrObject* pNewObj = ::FindSdrObject( pFmt ); + //pNewObj->SetOrdNum( nOrdNum ); + + EndUndo(); + EndAllAction(); + bRet = sal_True; + } + return bRet; +} + +static USHORT SwFmtGetPageNum(const SwFlyFrmFmt * pFmt) +{ + ASSERT(pFmt != NULL, "invalid argument"); + + SwFlyFrm * pFrm = pFmt->GetFrm(); + + USHORT aResult; + + if (pFrm != NULL) + aResult = pFrm->GetPhyPageNum(); + else + aResult = pFmt->GetAnchor().GetPageNum(); + + return aResult; +} + +#include <fmtcnct.hxx> + +void SwFEShell::GetConnectableFrmFmts(SwFrmFmt & rFmt, + const String & rReference, + BOOL bSuccessors, + ::std::vector< String > & aPrevPageVec, + ::std::vector< String > & aThisPageVec, + ::std::vector< String > & aNextPageVec, + ::std::vector< String > & aRestVec) +{ + StartAction(); + + SwFmtChain rChain = rFmt.GetChain(); + SwFrmFmt * pOldChainNext = (SwFrmFmt *) rChain.GetNext(); + SwFrmFmt * pOldChainPrev = (SwFrmFmt *) rChain.GetPrev(); + + if (pOldChainNext) + pDoc->Unchain(rFmt); + + if (pOldChainPrev) + pDoc->Unchain(*pOldChainPrev); + + sal_uInt16 nCnt = pDoc->GetFlyCount(FLYCNTTYPE_FRM); + + /* potential successors resp. predecessors */ + ::std::vector< const SwFrmFmt * > aTmpSpzArray; + + (SwFrmFmt *) pDoc->FindFlyByName(rReference); + + for (sal_uInt16 n = 0; n < nCnt; n++) + { + const SwFrmFmt & rFmt1 = *(pDoc->GetFlyNum(n, FLYCNTTYPE_FRM)); + + /* + pFmt is a potential successor of rFmt if it is chainable after + rFmt. + + pFmt is a potential predecessor of rFmt if rFmt is chainable + after pFmt. + */ + + int nChainState; + + if (bSuccessors) + nChainState = pDoc->Chainable(rFmt, rFmt1); + else + nChainState = pDoc->Chainable(rFmt1, rFmt); + + if (nChainState == SW_CHAIN_OK) + { + aTmpSpzArray.push_back(&rFmt1); + + } + + } + + if (aTmpSpzArray.size() > 0) + { + aPrevPageVec.clear(); + aThisPageVec.clear(); + aNextPageVec.clear(); + aRestVec.clear(); + + /* number of page rFmt resides on */ + USHORT nPageNum = SwFmtGetPageNum((SwFlyFrmFmt *) &rFmt); + + ::std::vector< const SwFrmFmt * >::const_iterator aIt; + + for (aIt = aTmpSpzArray.begin(); aIt != aTmpSpzArray.end(); aIt++) + { + String aString = (*aIt)->GetName(); + + /* rFmt is not a vaild successor or predecessor of + itself */ + if (aString != rReference && aString != rFmt.GetName()) + { + USHORT nNum1 = + SwFmtGetPageNum((SwFlyFrmFmt *) *aIt); + + if (nNum1 == nPageNum -1) + aPrevPageVec.push_back(aString); + else if (nNum1 == nPageNum) + aThisPageVec.push_back(aString); + else if (nNum1 == nPageNum + 1) + aNextPageVec.push_back(aString); + else + aRestVec.push_back(aString); + } + } + + } + + if (pOldChainNext) + pDoc->Chain(rFmt, *pOldChainNext); + + if (pOldChainPrev) + pDoc->Chain(*pOldChainPrev, rFmt); + + EndAction(); +} + +// --> OD 2009-07-13 #i73249# +const String SwFEShell::GetObjTitle() const +{ + String aTitle; + + if ( Imp()->HasDrawView() ) + { + const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + if ( pMrkList->GetMarkCount() == 1 ) + { + const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + const SwFrmFmt* pFmt = FindFrmFmt( pObj ); + if ( pFmt->Which() == RES_FLYFRMFMT ) + { + aTitle = dynamic_cast<const SwFlyFrmFmt*>(pFmt)->GetObjTitle(); + } + else + { + aTitle = pObj->GetTitle(); + } + } + } + + return aTitle; +} + +void SwFEShell::SetObjTitle( const String& rTitle ) +{ + if ( Imp()->HasDrawView() ) + { + const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + if ( pMrkList->GetMarkCount() == 1 ) + { + SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + SwFrmFmt* pFmt = FindFrmFmt( pObj ); + if ( pFmt->Which() == RES_FLYFRMFMT ) + { + GetDoc()->SetFlyFrmTitle( *(dynamic_cast<SwFlyFrmFmt*>(pFmt)), + rTitle ); + } + else + { + pObj->SetTitle( rTitle ); + } + } + } +} + +const String SwFEShell::GetObjDescription() const +{ + String aDescription; + + if ( Imp()->HasDrawView() ) + { + const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + if ( pMrkList->GetMarkCount() == 1 ) + { + const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + const SwFrmFmt* pFmt = FindFrmFmt( pObj ); + if ( pFmt->Which() == RES_FLYFRMFMT ) + { + aDescription = dynamic_cast<const SwFlyFrmFmt*>(pFmt)->GetObjDescription(); + } + else + { + aDescription = pObj->GetDescription(); + } + } + } + + return aDescription; +} + +void SwFEShell::SetObjDescription( const String& rDescription ) +{ + if ( Imp()->HasDrawView() ) + { + const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + if ( pMrkList->GetMarkCount() == 1 ) + { + SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + SwFrmFmt* pFmt = FindFrmFmt( pObj ); + if ( pFmt->Which() == RES_FLYFRMFMT ) + { + GetDoc()->SetFlyFrmDescription( *(dynamic_cast<SwFlyFrmFmt*>(pFmt)), + rDescription ); + } + else + { + pObj->SetDescription( rDescription ); + } + } + } +} +// <-- diff --git a/sw/source/core/frmedt/feflyole.cxx b/sw/source/core/frmedt/feflyole.cxx new file mode 100644 index 000000000000..070a031e83d3 --- /dev/null +++ b/sw/source/core/frmedt/feflyole.cxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <com/sun/star/embed/EmbedStates.hpp> + +#ifndef _SFX_CLIENTSH_HXX +#include <sfx2/ipclient.hxx> +#endif +#include <sfx2/viewsh.hxx> +#include <sfx2/app.hxx> +#include <unotools/moduleoptions.hxx> +#include <sfx2/viewfrm.hxx> + +#include <sot/exchange.hxx> +#include <fmtcntnt.hxx> +#include <fmtanchr.hxx> +#include <fesh.hxx> +#include <cntfrm.hxx> +#include <frmfmt.hxx> +#include <flyfrm.hxx> +#include <pam.hxx> +#include <doc.hxx> +#include <ndtxt.hxx> +#include <notxtfrm.hxx> +#include <ndole.hxx> +#include <swcli.hxx> + +using namespace com::sun::star; + +SwFlyFrm *SwFEShell::FindFlyFrm( const uno::Reference < embed::XEmbeddedObject >& xObj ) const +{ + SwFlyFrm *pFly = FindFlyFrm(); + if ( pFly && pFly->Lower() && pFly->Lower()->IsNoTxtFrm() ) + { + SwOLENode *pNd = ((SwNoTxtFrm*)pFly->Lower())->GetNode()->GetOLENode(); + if ( !pNd || pNd->GetOLEObj().GetOleRef() != xObj ) + pFly = 0; + } + else + pFly = 0; + + if ( !pFly ) + { + //Kein Fly oder der falsche selektiert. Ergo muessen wir leider suchen. + BOOL bExist = FALSE; + SwStartNode *pStNd; + ULONG nSttIdx = GetNodes().GetEndOfAutotext().StartOfSectionIndex() + 1, + nEndIdx = GetNodes().GetEndOfAutotext().GetIndex(); + while( nSttIdx < nEndIdx && + 0 != (pStNd = GetNodes()[ nSttIdx ]->GetStartNode()) ) + { + SwNode *pNd = GetNodes()[ nSttIdx+1 ]; + if ( pNd->IsOLENode() && + ((SwOLENode*)pNd)->GetOLEObj().GetOleRef() == xObj ) + { + bExist = TRUE; + SwFrm *pFrm = ((SwOLENode*)pNd)->GetFrm(); + if ( pFrm ) + pFly = pFrm->FindFlyFrm(); + break; + } + nSttIdx = pStNd->EndOfSectionIndex() + 1; + } + + ASSERT( bExist, "OLE-Object unknown and FlyFrm not found." ); + } + return pFly; +} + + +String SwFEShell::GetUniqueOLEName() const +{ + return GetDoc()->GetUniqueOLEName(); +} + + +String SwFEShell::GetUniqueFrameName() const +{ + return GetDoc()->GetUniqueFrameName(); +} + + +void SwFEShell::MakeObjVisible( const uno::Reference < embed::XEmbeddedObject >& xObj ) const +{ + SwFlyFrm *pFly = FindFlyFrm( xObj ); + if ( pFly ) + { + SwRect aTmp( pFly->Prt() ); + aTmp += pFly->Frm().Pos(); + if ( !aTmp.IsOver( VisArea() ) ) + { + ((SwFEShell*)this)->StartAction(); + ((SwFEShell*)this)->MakeVisible( aTmp ); + ((SwFEShell*)this)->EndAction(); + } + } +} + +BOOL SwFEShell::FinishOLEObj() // Server wird beendet +{ + SfxInPlaceClient* pIPClient = GetSfxViewShell()->GetIPClient(); + if ( !pIPClient ) + return FALSE; + + BOOL bRet = pIPClient->IsObjectInPlaceActive(); + if( bRet ) + { + uno::Reference < embed::XEmbeddedObject > xObj = pIPClient->GetObject(); + if( CNT_OLE == GetCntType() ) + ClearAutomaticContour(); + + if( ((SwOleClient*)pIPClient)->IsCheckForOLEInCaption() != + IsCheckForOLEInCaption() ) + SetCheckForOLEInCaption( !IsCheckForOLEInCaption() ); + + // leave UIActive state + pIPClient->DeactivateObject(); + } + return bRet; +} + + + + diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx new file mode 100644 index 000000000000..f334ddcaee2f --- /dev/null +++ b/sw/source/core/frmedt/feshview.cxx @@ -0,0 +1,3237 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <com/sun/star/embed/EmbedMisc.hpp> +#include "hintids.hxx" + +#include <svx/sdrobjectfilter.hxx> +#include <svx/svditer.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdopath.hxx> +#include <svx/sxciaitm.hxx> +#include <svx/xfillit.hxx> +#include <svx/svdocapt.hxx> +#include <sfx2/app.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/opaqitem.hxx> +#include <editeng/protitem.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> + +#ifndef _POOLFMT_HRC +#include <poolfmt.hrc> // fuer InitFldTypes +#endif +#include <frmfmt.hxx> +#include <frmatr.hxx> +#include <fmtfsize.hxx> +#include <fmtanchr.hxx> +#include <fmtornt.hxx> +#include <fmtsrnd.hxx> +#include <fmtcntnt.hxx> +#include <fmtflcnt.hxx> +#include <fmtcnct.hxx> +#include <docary.hxx> +#include <tblsel.hxx> +#include <swtable.hxx> +#include <flyfrms.hxx> +#include "fesh.hxx" +#include "rootfrm.hxx" +#include "pagefrm.hxx" +#include "sectfrm.hxx" +#include "doc.hxx" +#include "dview.hxx" +#include "dflyobj.hxx" +#include "dcontact.hxx" +#include "viewimp.hxx" +#include "flyfrm.hxx" +#include "pam.hxx" +#include "ndole.hxx" +#include "ndgrf.hxx" +#include "ndtxt.hxx" +#include "viewopt.hxx" // fuer GetHTMLMode +#include "swundo.hxx" +#include "notxtfrm.hxx" +#include "txtfrm.hxx" +#include "txatbase.hxx" +#include "mdiexp.hxx" // fuer Update der Statuszeile bei drag +// OD 2004-05-24 #i28701# +#include <sortedobjs.hxx> +// --> OD 2006-03-06 #125892# +#include <HandleAnchorNodeChg.hxx> +// <-- +#include <basegfx/polygon/b2dpolygon.hxx> + +#define SCROLLVAL 75 + +using namespace com::sun::star; + +//Tattergrenze fuer Drawing-SS +#define MINMOVE ((USHORT)GetOut()->PixelToLogic(Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width()) + +SwFlyFrm *GetFlyFromMarked( const SdrMarkList *pLst, ViewShell *pSh ) +{ + if ( !pLst ) + pLst = pSh->HasDrawView() ? &pSh->Imp()->GetDrawView()->GetMarkedObjectList():0; + + if ( pLst && pLst->GetMarkCount() == 1 ) + { + SdrObject *pO = pLst->GetMark( 0 )->GetMarkedSdrObj(); + if ( pO->ISA(SwVirtFlyDrawObj) ) + return ((SwVirtFlyDrawObj*)pO)->GetFlyFrm(); + } + return 0; +} + +void lcl_GrabCursor( SwFEShell* pSh, SwFlyFrm* pOldSelFly) +{ + const SwFrmFmt *pFlyFmt = pSh->SelFlyGrabCrsr(); + if( pFlyFmt && !pSh->ActionPend() && + (!pOldSelFly || pOldSelFly->GetFmt() != pFlyFmt) ) + { + // dann das evt. gesetzte Macro rufen + pSh->GetFlyMacroLnk().Call( (void*)pFlyFmt ); +extern BOOL bNoInterrupt; // in swapp.cxx + // wir in dem Makro ein Dialog gestartet, dann kommt das + // MouseButtonUp zu diesem und nicht zu uns. Dadurch ist + // Flag bei uns immer gesetzt und schaltet nie die auf die + // entsp. Shell um !!!!!!! + bNoInterrupt = FALSE; + } + else if( !pFlyFmt || RES_DRAWFRMFMT == pFlyFmt->Which() ) + { + // --> OD 2007-07-25 #136039# + // assure consistent cursor + pSh->KillPams(); + pSh->ClearMark(); + // <-- + pSh->SetCrsr( pSh->Imp()->GetDrawView()->GetAllMarkedRect().TopLeft(), TRUE); + } +} + +/************************************************************************* +|* +|* SwFEShell::SelectObj() +|* +|* Ersterstellung MA 16. Nov. 92 +|* Letzte Aenderung MA 22. Oct. 96 +|* +*************************************************************************/ + +BOOL SwFEShell::SelectObj( const Point& rPt, BYTE nFlag, SdrObject *pObj ) +{ + SwDrawView *pDView = Imp()->GetDrawView(); + if(!pDView) + return sal_False; + SET_CURR_SHELL( this ); + StartAction(); //Aktion ist Notwendig, damit nicht mehrere + //AttrChgdNotify (etwa durch Unmark->MarkListHasChgd) + //durchkommen + + const SdrMarkList &rMrkList = pDView->GetMarkedObjectList(); + const BOOL bHadSelection = rMrkList.GetMarkCount() ? TRUE : FALSE; + const BOOL bAddSelect = 0 != (SW_ADD_SELECT & nFlag); + const BOOL bEnterGroup = 0 != (SW_ENTER_GROUP & nFlag); + SwFlyFrm* pOldSelFly = 0; + const Point aOldPos( pDView->GetAllMarkedRect().TopLeft() ); + + if( bHadSelection ) + { + //Unmark rufen wenn !bAddSelect oder wenn ein Fly selektiert ist. + BOOL bUnmark = !bAddSelect; + + if ( rMrkList.GetMarkCount() == 1 ) + { + //Wenn ein Fly selektiert ist, so muss er erst deselektiert werden. + pOldSelFly = ::GetFlyFromMarked( &rMrkList, this ); + if ( pOldSelFly ) + { + const USHORT nType = GetCntType(); + if( nType != CNT_TXT || (SW_LEAVE_FRAME & nFlag) || + ( pOldSelFly->GetFmt()->GetProtect().IsCntntProtected() + && !IsReadOnlyAvailable() )) + { + //Wenn ein Fly deselektiert wird, der Grafik, Ole o.ae. + //enthaelt, so muss der Crsr aus diesem entfernt werden. + //Desgleichen wenn ein Fly mit geschuetztem Inhalt deselektiert + //wird. Der Einfachheit halber wire der Crsr 'grad so neben die + //linke obere Ecke gesetzt. + Point aPt( pOldSelFly->Frm().Pos() ); + aPt.X() -= 1; + BOOL bUnLockView = !IsViewLocked(); + LockView( TRUE ); + SetCrsr( aPt, TRUE ); + if( bUnLockView ) + LockView( FALSE ); + } + if ( nType & CNT_GRF && + ((SwNoTxtFrm*)pOldSelFly->Lower())->HasAnimation() ) + { + GetWin()->Invalidate( pOldSelFly->Frm().SVRect() ); + } + bUnmark = TRUE; + } + } + if ( bUnmark ) + pDView->UnmarkAll(); + } + else + { + KillPams(); + ClearMark(); + } + + if ( pObj ) + { + ASSERT( !bEnterGroup, "SW_ENTER_GROUP is not supported" ); + pDView->MarkObj( pObj, Imp()->GetPageView() ); + } + else + { + pDView->MarkObj( rPt, MINMOVE, bAddSelect, bEnterGroup ); + } + + const BOOL bRet = 0 != rMrkList.GetMarkCount(); + + if ( rMrkList.GetMarkCount() > 1 ) + { + //Ganz dumm ist es, wenn Zeichenobjekte Selektiert waren und + //nun ein Fly hinzuselektiert wird. + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pTmpObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + BOOL bForget = pTmpObj->ISA(SwVirtFlyDrawObj); + if( bForget ) + { + pDView->UnmarkAll(); + pDView->MarkObj( pTmpObj, Imp()->GetPageView(), bAddSelect, bEnterGroup ); + break; + } + } + } + + if ( bRet ) + { + ::lcl_GrabCursor(this, pOldSelFly); + if ( GetCntType() & CNT_GRF ) + { + const SwFlyFrm *pTmp = GetFlyFromMarked( &rMrkList, this ); + ASSERT( pTmp, "Graphic without Fly" ); + if ( ((SwNoTxtFrm*)pTmp->Lower())->HasAnimation() ) + ((SwNoTxtFrm*)pTmp->Lower())->StopAnimation( GetOut() ); + } + } + else if ( !pOldSelFly && bHadSelection ) + SetCrsr( aOldPos, TRUE); + + if( bRet || !bHadSelection ) + CallChgLnk(); + + // update der Statuszeile + ::FrameNotify( this, bRet ? FLY_DRAG_START : FLY_DRAG_END ); + + EndAction(); + return bRet; +} + +/************************************************************************* +|* +|* sal_Bool SwFEShell::MoveAnchor( USHORT nDir ) +|* +|* Created AMA 05/28/2002 +|* Last modify AMA 05/30/2002 +|* +|* Description: MoveAnchor( nDir ) looked for an another Anchor for +|* the selected drawing object (or fly frame) in the given direction. +|* An object "as character" doesn't moves anyway. +|* A page bounded object could move to the previous/next page with up/down, +|* an object bounded "at paragraph" moves to the previous/next paragraph, too. +|* An object bounded "at character" moves to the previous/next paragraph +|* with up/down and to the previous/next character with left/right. +|* If the anchor for at paragraph/character bounded objects has vertical or +|* right_to_left text direction, the directions for up/down/left/right will +|* interpreted accordingly. +|* An object bounded "at fly" takes the center of the actual anchor and looks +|* for the nearest fly frame in the given direction. +|* +*************************************************************************/ + +#define LESS_X( aPt1, aPt2, bOld ) ( aPt1.X() < aPt2.X() || \ + ( aPt1.X() == aPt2.X() && ( aPt1.Y() < aPt2.Y() || \ + ( aPt1.Y() == aPt2.Y() && bOld ) ) ) ) +#define LESS_Y( aPt1, aPt2, bOld ) ( aPt1.Y() < aPt2.Y() || \ + ( aPt1.Y() == aPt2.Y() && ( aPt1.X() < aPt2.X() || \ + ( aPt1.X() == aPt2.X() && bOld ) ) ) ) + +sal_Bool SwFEShell::MoveAnchor( USHORT nDir ) +{ + const SdrMarkList* pMrkList; + if( !Imp()->GetDrawView() || + 0 == (pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList()) || + 1 != pMrkList->GetMarkCount()) + return sal_False; + SwFrm* pOld; + SwFlyFrm* pFly = NULL; + SdrObject *pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + if( pObj->ISA(SwVirtFlyDrawObj) ) + { + pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); + pOld = pFly->AnchorFrm(); + } + else + pOld = ((SwDrawContact*)GetUserCall(pObj))->GetAnchorFrm( pObj ); + sal_Bool bRet = sal_False; + if( pOld ) + { + SwFrm* pNew = pOld; + // --> OD 2004-07-16 #i28701# + SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj ); + SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt(); + SwFmtAnchor aAnch( rFmt.GetAnchor() ); + RndStdIds nAnchorId = aAnch.GetAnchorId(); + if ( FLY_AS_CHAR == nAnchorId ) + return sal_False; + if( pOld->IsVertical() ) + { + if( pOld->IsTxtFrm() ) + { + switch( nDir ) { + case SW_MOVE_UP: nDir = SW_MOVE_LEFT; break; + case SW_MOVE_DOWN: nDir = SW_MOVE_RIGHT; break; + case SW_MOVE_LEFT: nDir = SW_MOVE_DOWN; break; + case SW_MOVE_RIGHT: nDir = SW_MOVE_UP; break; + } + if( pOld->IsRightToLeft() ) + { + if( nDir == SW_MOVE_LEFT ) + nDir = SW_MOVE_RIGHT; + else if( nDir == SW_MOVE_RIGHT ) + nDir = SW_MOVE_LEFT; + } + } + } + switch ( nAnchorId ) { + case FLY_AT_PAGE: + { + ASSERT( pOld->IsPageFrm(), "Wrong anchor, page exspected." ); + if( SW_MOVE_UP == nDir ) + pNew = pOld->GetPrev(); + else if( SW_MOVE_DOWN == nDir ) + pNew = pOld->GetNext(); + if( pNew && pNew != pOld ) + { + aAnch.SetPageNum( ((SwPageFrm*)pNew)->GetPhyPageNum() ); + bRet = sal_True; + } + break; + } + case FLY_AT_CHAR: + { + ASSERT( pOld->IsCntntFrm(), "Wrong anchor, page exspected." ); + if( SW_MOVE_LEFT == nDir || SW_MOVE_RIGHT == nDir ) + { + SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor(); + SwTxtNode* pTxtNd = ((SwTxtFrm*)pOld)->GetTxtNode(); + xub_StrLen nAct = pPos->nContent.GetIndex(); + if( SW_MOVE_LEFT == nDir ) + { + bRet = sal_True; + if( nAct ) + { + --nAct; + pPos->nContent.Assign( pTxtNd, nAct ); + } + else + nDir = SW_MOVE_UP; + } + else + { + xub_StrLen nMax = + ((SwTxtFrm*)pOld)->GetTxtNode()->GetTxt().Len(); + if( nAct < nMax ) + { + ++nAct; + bRet = sal_True; + pPos->nContent.Assign( pTxtNd, nAct ); + } + else + nDir = SW_MOVE_DOWN; + } + } + } // no break! + case FLY_AT_PARA: + { + ASSERT( pOld->IsCntntFrm(), "Wrong anchor, page exspected." ); + if( SW_MOVE_UP == nDir ) + pNew = pOld->FindPrev(); + else if( SW_MOVE_DOWN == nDir ) + pNew = pOld->FindNext(); + if( pNew && pNew != pOld && pNew->IsCntntFrm() ) + { + SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor(); + SwTxtNode* pTxtNd = ((SwTxtFrm*)pNew)->GetTxtNode(); + pPos->nNode = *pTxtNd; + xub_StrLen nTmp = 0; + if( bRet ) + { + nTmp = ((SwTxtFrm*)pNew)->GetTxtNode()->GetTxt().Len(); + if( nTmp ) + --nTmp; + } + pPos->nContent.Assign( pTxtNd, nTmp ); + bRet = sal_True; + } + else if( SW_MOVE_UP == nDir || SW_MOVE_DOWN == nDir ) + bRet = sal_False; + break; + } + case FLY_AT_FLY: + { + ASSERT( pOld->IsFlyFrm(), "Wrong anchor, fly frame exspected."); + SwPageFrm* pPage = pOld->FindPageFrm(); + ASSERT( pPage, "Where's my page?" ); + SwFlyFrm* pNewFly = NULL; + if( pPage->GetSortedObjs() ) + { + int i; + sal_Bool bOld = sal_False; + Point aCenter( pOld->Frm().Left() + pOld->Frm().Width()/2, + pOld->Frm().Top() + pOld->Frm().Height()/2 ); + Point aBest; + for( i = 0; (USHORT)i<pPage->GetSortedObjs()->Count(); ++i ) + { + SwAnchoredObject* pAnchObj = + (*pPage->GetSortedObjs())[i]; + if( pAnchObj->ISA(SwFlyFrm) ) + { + SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(pAnchObj); + if( pTmp == pOld ) + bOld = sal_True; + else + { + const SwFlyFrm* pCheck = pFly ? pTmp : 0; + while( pCheck ) + { + if( pCheck == pFly ) + break; + const SwFrm *pNxt = pCheck->GetAnchorFrm(); + pCheck = pNxt ? pNxt->FindFlyFrm() : NULL; + } + if( pCheck || pTmp->IsProtected() ) + continue; + Point aNew( pTmp->Frm().Left() + + pTmp->Frm().Width()/2, + pTmp->Frm().Top() + + pTmp->Frm().Height()/2 ); + sal_Bool bAccept = sal_False; + switch( nDir ) { + case SW_MOVE_RIGHT: + { + bAccept = LESS_X( aCenter, aNew, bOld ) + && ( !pNewFly || + LESS_X( aNew, aBest, sal_False ) ); + break; + } + case SW_MOVE_LEFT: + { + bAccept = LESS_X( aNew, aCenter, !bOld ) + && ( !pNewFly || + LESS_X( aBest, aNew, sal_True ) ); + break; + } + case SW_MOVE_UP: + { + bAccept = LESS_Y( aNew, aCenter, !bOld ) + && ( !pNewFly || + LESS_Y( aBest, aNew, sal_True ) ); + break; + } + case SW_MOVE_DOWN: + { + bAccept = LESS_Y( aCenter, aNew, bOld ) + && ( !pNewFly || + LESS_Y( aNew, aBest, sal_False ) ); + break; + } + } + if( bAccept ) + { + pNewFly = pTmp; + aBest = aNew; + } + } + } + } + } + + if( pNewFly ) + { + SwPosition aPos( *pNewFly->GetFmt()-> + GetCntnt().GetCntntIdx()); + aAnch.SetAnchor( &aPos ); + bRet = sal_True; + } + break; + } + default: break; + } + if( bRet ) + { + StartAllAction(); + // --> OD 2006-02-28 #125892# + // handle change of anchor node: + // if count of the anchor frame also change, the fly frames have to be + // re-created. Thus, delete all fly frames except the <this> before the + // anchor attribute is change and re-create them afterwards. + { + SwHandleAnchorNodeChg* pHandleAnchorNodeChg( 0L ); + SwFlyFrmFmt* pFlyFrmFmt( dynamic_cast<SwFlyFrmFmt*>(&rFmt) ); + if ( pFlyFrmFmt ) + { + pHandleAnchorNodeChg = + new SwHandleAnchorNodeChg( *pFlyFrmFmt, aAnch ); + } + rFmt.GetDoc()->SetAttr( aAnch, rFmt ); + delete pHandleAnchorNodeChg; + } + // <-- + // --> OD 2004-06-24 #i28701# - no call of method + // <CheckCharRectAndTopOfLine()> for to-character anchored + // Writer fly frame needed. This method call can cause a + // format of the anchor frame, which is no longer intended. + // Instead clear the anchor character rectangle and + // the top of line values for all to-character anchored objects. + pAnchoredObj->ClearCharRectAndTopOfLine(); + EndAllAction(); + } + } + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::GetSelFrmType() +|* +|* Ersterstellung MA 12. Jan. 93 +|* Letzte Aenderung JP 19.03.96 +|* +*************************************************************************/ + +const SdrMarkList* SwFEShell::_GetMarkList() const +{ + const SdrMarkList* pMarkList = NULL; + if( Imp()->GetDrawView() != NULL ) + pMarkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + return pMarkList; +} + +USHORT SwFEShell::GetSelFrmType() const +{ + USHORT eType; + + // get marked frame list, and check if anything is selected + const SdrMarkList* pMarkList = _GetMarkList(); + if( pMarkList == NULL || pMarkList->GetMarkCount() == 0 ) + eType = FRMTYPE_NONE; + else + { + // obtain marked item as fly frame; if no fly frame, it must + // be a draw object + const SwFlyFrm* pFly = ::GetFlyFromMarked(pMarkList, (ViewShell*)this); + if ( pFly != NULL ) + { + if( pFly->IsFlyLayFrm() ) + eType = FRMTYPE_FLY_FREE; + else if( pFly->IsFlyAtCntFrm() ) + eType = FRMTYPE_FLY_ATCNT; + else + { + ASSERT( pFly->IsFlyInCntFrm(), "Neuer Rahmentyp?" ); + eType = FRMTYPE_FLY_INCNT; + } + } + else + eType = FRMTYPE_DRAWOBJ; + } + + return eType; +} + +// #108784# does the draw selection contain a control? +bool SwFEShell::IsSelContainsControl() const +{ + bool bRet = false; + + // basically, copy the mechanism from GetSelFrmType(), but call + // CheckControl... if you get a drawing object + const SdrMarkList* pMarkList = _GetMarkList(); + if( pMarkList != NULL && pMarkList->GetMarkCount() == 1 ) + { + // if we have one marked object, get the SdrObject and check + // whether it contains a control + const SdrObject* pSdrObject = pMarkList->GetMark( 0 )->GetMarkedSdrObj(); + bRet = ::CheckControlLayer( pSdrObject ); + } + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::Scroll() +|* +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung MA 27. Jul. 95 +|* +*************************************************************************/ + +void SwFEShell::ScrollTo( const Point &rPt ) +{ + const SwRect aRect( rPt, rPt ); + if ( IsScrollMDI( this, aRect ) && + (!Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() || + Imp()->IsDragPossible( rPt )) ) + { + //SwSaveHdl aSave( Imp() ); + ScrollMDI( this, aRect, SCROLLVAL, SCROLLVAL ); + } +} + +/************************************************************************* +|* +|* SwFEShell::SetDragMode() +|* +|* Ersterstellung MA 30. Jan. 95 +|* Letzte Aenderung MA 30. Jan. 95 +|* +*************************************************************************/ + +void SwFEShell::SetDragMode( UINT16 eDragMode ) +{ + if ( Imp()->HasDrawView() ) + Imp()->GetDrawView()->SetDragMode( (SdrDragMode)eDragMode ); +} + +/************************************************************************* +|* +|* SwFEShell::BeginDrag() +|* +|* Ersterstellung MS 10.06.92 +|* Letzte Aenderung MA 13. Mar. 96 +|* +*************************************************************************/ + +long SwFEShell::BeginDrag( const Point* pPt, BOOL ) +{ + SdrView *pView = Imp()->GetDrawView(); + if ( pView && pView->AreObjectsMarked() ) + { + delete pChainFrom; delete pChainTo; pChainFrom = pChainTo = 0; + SdrHdl* pHdl = pView->PickHandle( *pPt ); + pView->BegDragObj( *pPt, 0 /*GetWin()*/, pHdl ); + ::FrameNotify( this, FLY_DRAG ); + return 1; + } + return 0; +} +/************************************************************************* +|* +|* SwFEShell::Drag() +|* +|* Ersterstellung MS 10.06.92 +|* Letzte Aenderung MA 13. Mar. 96 +|* +*************************************************************************/ + +long SwFEShell::Drag( const Point *pPt, BOOL ) +{ + ASSERT( Imp()->HasDrawView(), "Drag without DrawView?" ); + if ( Imp()->GetDrawView()->IsDragObj() ) + { + ScrollTo( *pPt ); + Imp()->GetDrawView()->MovDragObj( *pPt ); + Imp()->GetDrawView()->ShowDragAnchor(); + ::FrameNotify( this, FLY_DRAG ); + return 1; + } + return 0; +} + +/************************************************************************* +|* +|* SwFEShell::EndDrag() +|* +|* Ersterstellung MS 10.06.92 +|* Letzte Aenderung MA 13. Mar. 96 +|* +*************************************************************************/ + +long SwFEShell::EndDrag( const Point *, BOOL ) +{ + ASSERT( Imp()->HasDrawView(), "EndDrag without DrawView?" ); + SdrView *pView = Imp()->GetDrawView(); + if ( pView->IsDragObj() ) + { + //Start-/EndActions nur an der ViewShell aufsetzen + ViewShell *pSh = this; + do { + pSh->StartAction(); + } while ( this != (pSh = (ViewShell*)pSh->GetNext()) ); + + StartUndo( UNDO_START ); + + //#50778# Bug im Draging: Im StartAction wird ein HideShowXor gerufen. + //Im EndDragObj() wird dies unsinniger und faelschlicherweise wieder + //Rueckgaengig gemacht. Um Konsistenz herzustellen muessen wir das + //Xor also wieder zur Anzeige bringen. + + // Reanimation from the hack #50778 to fix bug #97057 + // May be not the best solution, but the one with lowest risc at the moment. + //pView->ShowShownXor( GetOut() ); + + pView->EndDragObj(); + // JP 18.08.95: DrawUndo-Action auf FlyFrames werden nicht gespeichert + // Die Fly aendern das Flag + GetDoc()->SetNoDrawUndoObj( FALSE ); + ChgAnchor( 0, TRUE ); + + EndUndo( UNDO_END ); + + do { + pSh->EndAction(); + if( pSh->IsA( TYPE( SwCrsrShell ) ) ) + ((SwCrsrShell*)pSh)->CallChgLnk(); + } while ( this != (pSh = (ViewShell*)pSh->GetNext()) ); + + GetDoc()->SetModified(); + ::FrameNotify( this, FLY_DRAG ); + return 1; + } + return 0; +} + +/************************************************************************* +|* +|* SwFEShell::BreakDrag() +|* +|* Ersterstellung OM 02. Okt. 95 +|* Letzte Aenderung OM 02. Okt. 95 +|* +*************************************************************************/ + +void SwFEShell::BreakDrag() +{ + ASSERT( Imp()->HasDrawView(), "BreakDrag without DrawView?" ); + if ( Imp()->GetDrawView()->IsDragObj() ) + Imp()->GetDrawView()->BrkDragObj(); + SetChainMarker(); +} + +/************************************************************************* +|* +|* SwFEShell::SelFlyGrabCrsr() +|* +|* Beschreibung Wenn ein Fly selektiert ist, zieht er den Crsr in +|* den ersten CntntFrm +|* Ersterstellung MA 11. Dec. 92 +|* Letzte Aenderung MA 07. Oct. 96 +|* +*************************************************************************/ + +const SwFrmFmt* SwFEShell::SelFlyGrabCrsr() +{ + if ( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + SwFlyFrm *pFly = ::GetFlyFromMarked( &rMrkList, this ); + + if( pFly ) + { + // --> OD 2004-06-11 #i28701# - no format here +// pFly->GetAnchorFrm()->Calc(); + SwCntntFrm *pCFrm = pFly->ContainsCntnt(); + if ( pCFrm ) + { + SwCntntNode *pCNode = pCFrm->GetNode(); + // --> OD 2007-07-25 #126039# + // assure, that the cursor is consistent. + KillPams(); + ClearMark(); + // <-- + SwPaM *pCrsr = GetCrsr(); + + pCrsr->GetPoint()->nNode = *pCNode; + pCrsr->GetPoint()->nContent.Assign( pCNode, 0 ); + + SwRect& rChrRect = (SwRect&)GetCharRect(); + rChrRect = pFly->Prt(); + rChrRect.Pos() += pFly->Frm().Pos(); + GetCrsrDocPos() = rChrRect.Pos(); + } + return pFly->GetFmt(); + } + } + return 0; +} + + +/************************************************************************* +|* +|* SwFEShell::SelectionToTop(), SelectionToBottom() +|* +|* Beschreibung Selektion nach oben/unten (Z-Order) +|* +|* Ersterstellung MA 05. Nov. 92 +|* Letzte Aenderung MA 03. Jun. 96 +|* +*************************************************************************/ + +void lcl_NotifyNeighbours( const SdrMarkList *pLst ) +{ + //Die Regeln fuer die Ausweichmanoever haben sich veraendert. + //1. Die Umgebung des Fly und aller innenliegenden muss benachrichtigt + // werden. + //2. Der Inhalt des Rahmen selbst muss benachrichtigt werden. + //3. Rahmen die dem Rahmen ausweichen bzw. wichen muessen benachrichtigt werden. + //4. Auch Zeichenobjekte koennen Rahmen verdraengen + + for( USHORT j = 0; j < pLst->GetMarkCount(); ++j ) + { + SwPageFrm *pPage; + BOOL bCheckNeighbours = FALSE; + sal_Int16 aHori = text::HoriOrientation::NONE; + SwRect aRect; + SdrObject *pO = pLst->GetMark( 0 )->GetMarkedSdrObj(); + if ( pO->ISA(SwVirtFlyDrawObj) ) + { + SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm(); + + const SwFmtHoriOrient &rHori = pFly->GetFmt()->GetHoriOrient(); + aHori = rHori.GetHoriOrient(); + if( text::HoriOrientation::NONE != aHori && text::HoriOrientation::CENTER != aHori && + pFly->IsFlyAtCntFrm() ) + { + bCheckNeighbours = TRUE; + pFly->InvalidatePos(); + pFly->Frm().Pos().Y() += 1; + } + + pPage = pFly->FindPageFrm(); + aRect = pFly->Frm(); + } + else + { + SwFrm* pAnch = ( (SwDrawContact*)GetUserCall(pO) )->GetAnchorFrm( pO ); + if( !pAnch ) + continue; + pPage = pAnch->FindPageFrm(); + // --> OD 2006-08-15 #i68520# - naming changed + aRect = GetBoundRectOfAnchoredObj( pO ); + // <-- + } + + sal_uInt32 nCount = pPage->GetSortedObjs() ? pPage->GetSortedObjs()->Count() : 0; + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i]; + if ( !pAnchoredObj->ISA(SwFlyFrm) ) + continue; + + SwFlyFrm* pAct = static_cast<SwFlyFrm*>(pAnchoredObj); + SwRect aTmpCalcPnt( pAct->Prt() ); + aTmpCalcPnt += pAct->Frm().Pos(); + if ( aRect.IsOver( aTmpCalcPnt ) ) + { + SwCntntFrm *pCnt = pAct->ContainsCntnt(); + while ( pCnt ) + { + aTmpCalcPnt = pCnt->Prt(); + aTmpCalcPnt += pCnt->Frm().Pos(); + if ( aRect.IsOver( aTmpCalcPnt ) ) + ((SwFrm*)pCnt)->Prepare( PREP_FLY_ATTR_CHG ); + pCnt = pCnt->GetNextCntntFrm(); + } + } + if ( bCheckNeighbours && pAct->IsFlyAtCntFrm() ) + { + const SwFmtHoriOrient &rH = pAct->GetFmt()->GetHoriOrient(); + if ( rH.GetHoriOrient() == aHori && + pAct->Frm().Top() <= aRect.Bottom() && + pAct->Frm().Bottom() >= aRect.Top() ) + { + pAct->InvalidatePos(); + pAct->Frm().Pos().Y() += 1; + } + } + } + } +} + +void SwFEShell::SelectionToTop( BOOL bTop ) +{ + ASSERT( Imp()->HasDrawView(), "SelectionToTop without DrawView?" ); + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + ASSERT( rMrkList.GetMarkCount(), "Kein Object Selektiert." ); + + SwFlyFrm *pFly = ::GetFlyFromMarked( &rMrkList, this ); + if ( pFly && pFly->IsFlyInCntFrm() ) + return; + + StartAllAction(); + if ( bTop ) + Imp()->GetDrawView()->PutMarkedToTop(); + else + Imp()->GetDrawView()->MovMarkedToTop(); + ::lcl_NotifyNeighbours( &rMrkList ); + GetDoc()->SetModified(); + EndAllAction(); +} + +void SwFEShell::SelectionToBottom( BOOL bBottom ) +{ + ASSERT( Imp()->HasDrawView(), "SelectionToBottom without DrawView?" ); + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + ASSERT( rMrkList.GetMarkCount(), "Kein Object Selektiert." ); + + SwFlyFrm *pFly = ::GetFlyFromMarked( &rMrkList, this ); + if ( pFly && pFly->IsFlyInCntFrm() ) + return; + + StartAllAction(); + if ( bBottom ) + Imp()->GetDrawView()->PutMarkedToBtm(); + else + Imp()->GetDrawView()->MovMarkedToBtm(); + ::lcl_NotifyNeighbours( &rMrkList ); + GetDoc()->SetModified(); + EndAllAction(); +} + +/************************************************************************* +|* +|* SwFEShell::GetLayerId() +|* +|* Beschreibung Objekt ueber/unter dem Dokument? +|* 2 Controls, 1 Heaven, 0 Hell, -1 Uneindeutig +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung MA 20. Dec. 94 +|* +*************************************************************************/ + +short SwFEShell::GetLayerId() const +{ + short nRet = SHRT_MAX; + if ( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + if ( nRet == SHRT_MAX ) + nRet = pObj->GetLayer(); + else if ( nRet != pObj->GetLayer() ) + { + nRet = -1; + break; + } + } + } + if ( nRet == SHRT_MAX ) + nRet = -1; + return nRet; +} + +/************************************************************************* +|* +|* SwFEShell::SelectionToHeaven(), SelectionToHell() +|* +|* Beschreibung Objekt ueber/unter dem Dokument +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung AMA 04. Jun. 98 +|* +*************************************************************************/ +// OD 25.06.2003 #108784# +// Note: only visible objects can be marked. Thus, objects with invisible +// layer IDs have not to be considered. +// If <SwFEShell> exists, layout exists!! +void SwFEShell::ChangeOpaque( SdrLayerID nLayerId ) +{ + if ( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess(); + // OD 25.06.2003 #108784# - correct type of <nControls> + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + // OD 21.08.2003 #i18447# - no change of layer for controls + // or group objects containing controls. + // --> OD 2010-09-14 #i113730# + // consider that a member of a drawing group has been selected. + const SwContact* pContact = ::GetUserCall( pObj ); + ASSERT( pContact && pContact->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" ); + const bool bControlObj = ( pContact && pContact->GetMaster() ) + ? ::CheckControlLayer( pContact->GetMaster() ) + : ::CheckControlLayer( pObj ); + // <-- + if ( !bControlObj && pObj->GetLayer() != nLayerId ) + { + pObj->SetLayer( nLayerId ); + InvalidateWindows( SwRect( pObj->GetCurrentBoundRect() ) ); + if ( pObj->ISA(SwVirtFlyDrawObj) ) + { + SwFmt *pFmt = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt(); + SvxOpaqueItem aOpa( pFmt->GetOpaque() ); + aOpa.SetValue( nLayerId == pIDDMA->GetHellId() ); + pFmt->SetFmtAttr( aOpa ); + } + } + } + GetDoc()->SetModified(); + } +} + +void SwFEShell::SelectionToHeaven() +{ + ChangeOpaque( getIDocumentDrawModelAccess()->GetHeavenId() ); +} + +void SwFEShell::SelectionToHell() +{ + ChangeOpaque( getIDocumentDrawModelAccess()->GetHellId() ); +} + +/************************************************************************* +|* +|* SwFEShell::IsObjSelected(), IsFrmSelected() +|* +|* Ersterstellung MA 16. Nov. 92 +|* Letzte Aenderung MA 17. Jan. 95 +|* +*************************************************************************/ + +USHORT SwFEShell::IsObjSelected() const +{ + if ( IsFrmSelected() || !Imp()->HasDrawView() ) + return 0; + else + return USHORT( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ); +} + +BOOL SwFEShell::IsFrmSelected() const +{ + if ( !Imp()->HasDrawView() ) + return FALSE; + else + return 0 != ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(), + (ViewShell*)this ); +} + +sal_Bool SwFEShell::IsObjSelected( const SdrObject& rObj ) const +{ + if ( IsFrmSelected() || !Imp()->HasDrawView() ) + return sal_False; + else + return Imp()->GetDrawView() + ->IsObjMarked( const_cast< SdrObject * >( &rObj ) ); +} + +/************************************************************************* +|* +|* SwFEShell::EndTextEdit() +|* +|* Ersterstellung MA 19. Feb. 96 +|* Letzte Aenderung MA 19. Feb. 96 +|* +*************************************************************************/ + +void SwFEShell::EndTextEdit() +{ + //Beenden des TextEditModus. Wenn gewuenscht (default wenn das Objekt + //keinen Text mehr enthaelt und keine Attribute traegt) wird das + //Objekt gel�scht. Alle anderen markierten Objekte bleiben erhalten. + + ASSERT( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(), + "EndTextEdit an no Object" ); + + StartAllAction(); + SdrView *pView = Imp()->GetDrawView(); + SdrObject *pObj = pView->GetTextEditObject(); + SdrObjUserCall* pUserCall; + if( 0 != ( pUserCall = GetUserCall(pObj) ) ) + { + SdrObject *pTmp = ((SwContact*)pUserCall)->GetMaster(); + if( !pTmp ) + pTmp = pObj; + pUserCall->Changed( *pTmp, SDRUSERCALL_RESIZE, pTmp->GetLastBoundRect() ); + } + if ( !pObj->GetUpGroup() ) + { + if ( SDRENDTEXTEDIT_SHOULDBEDELETED == pView->SdrEndTextEdit(sal_True) ) + { + if ( pView->GetMarkedObjectList().GetMarkCount() > 1 ) + { + { + SdrMarkList aSave( pView->GetMarkedObjectList() ); + aSave.DeleteMark( aSave.FindObject( pObj ) ); + if ( aSave.GetMarkCount() ) + { + pView->UnmarkAll(); + pView->MarkObj( pObj, Imp()->GetPageView() ); + } + DelSelectedObj(); + if ( aSave.GetMarkCount() ) + { + for ( USHORT i = 0; i < aSave.GetMarkCount(); ++i ) + pView->MarkObj( aSave.GetMark( i )->GetMarkedSdrObj(), + Imp()->GetPageView() ); + } + } + } + else + DelSelectedObj(); + } + } + else + pView->SdrEndTextEdit(); + EndAllAction(); +} + +/************************************************************************* +|* +|* SwFEShell::IsInsideSelectedObj() +|* +|* Ersterstellung MA 16. Nov. 92 +|* Letzte Aenderung MA 08. Nov. 96 +|* +*************************************************************************/ + +int SwFEShell::IsInsideSelectedObj( const Point &rPt ) +{ + if( Imp()->HasDrawView() ) + { + SwDrawView *pDView = Imp()->GetDrawView(); + + if( pDView->GetMarkedObjectList().GetMarkCount() && + pDView->IsMarkedObjHit( rPt ) ) + { + return SDRHIT_OBJECT; + } + } + return SDRHIT_NONE; +} + +/************************************************************************* +|* +|* SwFEShell::IsObjSelectable() +|* +|* Ersterstellung MA 16. Nov. 92 +|* Letzte Aenderung MA 02. Feb. 95 +|* +*************************************************************************/ + +bool SwFEShell::IsObjSelectable( const Point& rPt ) +{ + SET_CURR_SHELL(this); +#ifdef OLD + if( Imp()->HasDrawView() ) + return Imp()->GetDrawView()->PickSomething( rPt, MINMOVE ); + return 0; +#else + SwDrawView *pDView = Imp()->GetDrawView(); + bool bRet = false; + if( pDView ) + { + SdrObject* pObj; + SdrPageView* pPV; + USHORT nOld = pDView->GetHitTolerancePixel(); + pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 ); + + bRet = 0 != pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMARKABLE ); + pDView->SetHitTolerancePixel( nOld ); + } + return bRet; +#endif +} + +// #107513# +// Test if there is a object at that position and if it should be selected. +sal_Bool SwFEShell::ShouldObjectBeSelected(const Point& rPt) +{ + SET_CURR_SHELL(this); + SwDrawView *pDrawView = Imp()->GetDrawView(); + sal_Bool bRet(sal_False); + + if(pDrawView) + { + SdrObject* pObj; + SdrPageView* pPV; + sal_uInt16 nOld(pDrawView->GetHitTolerancePixel()); + + pDrawView->SetHitTolerancePixel(pDrawView->GetMarkHdlSizePixel()/2); + bRet = pDrawView->PickObj(rPt, pDrawView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMARKABLE); + pDrawView->SetHitTolerancePixel(nOld); + + if ( bRet && pObj ) + { + const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess(); + // --> OD 2009-12-30 #i89920# + // Do not select object in background which is overlapping this text + // at the given position. + bool bObjInBackground( false ); + { + if ( pObj->GetLayer() == pIDDMA->GetHellId() ) + { + const SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj ); + const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt(); + const SwFmtSurround& rSurround = rFmt.GetSurround(); + if ( rSurround.GetSurround() == SURROUND_THROUGHT ) + { + bObjInBackground = true; + } + } + } + if ( bObjInBackground ) + { + const SwPageFrm* pPageFrm = GetLayout()->GetPageAtPos( rPt ); + if( pPageFrm ) + { + const SwCntntFrm* pCntntFrm( pPageFrm->ContainsCntnt() ); + while ( pCntntFrm ) + { + if ( pCntntFrm->UnionFrm().IsInside( rPt ) ) + { + const SwTxtFrm* pTxtFrm = + dynamic_cast<const SwTxtFrm*>(pCntntFrm); + if ( pTxtFrm ) + { + SwPosition* pPos = + new SwPosition( *(pTxtFrm->GetTxtNode()) ); + Point aTmpPt( rPt ); + if ( pTxtFrm->GetKeyCrsrOfst( pPos, aTmpPt ) ) + { + SwRect aCursorCharRect; + if ( pTxtFrm->GetCharRect( aCursorCharRect, *pPos ) ) + { + if ( aCursorCharRect.IsOver( SwRect( pObj->GetLastBoundRect() ) ) ) + { + bRet = sal_False; + } + } + } + } + else + { + bRet = sal_False; + } + break; + } + + pCntntFrm = pCntntFrm->GetNextCntntFrm(); + } + } + } + // <-- + + if ( bRet ) + { + const SdrPage* pPage = pIDDMA->GetDrawModel()->GetPage(0); + for(sal_uInt32 a(pObj->GetOrdNum() + 1); bRet && a < pPage->GetObjCount(); a++) + { + SdrObject *pCandidate = pPage->GetObj(a); + + if (pCandidate->ISA(SwVirtFlyDrawObj) && + ( (SwVirtFlyDrawObj*)pCandidate)->GetCurrentBoundRect().IsInside(rPt) ) + { + bRet = sal_False; + } + } + } + } + } + + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::GotoObj() +|* +|* Beschreibung Wenn ein Obj selektiert ist, gehen wir von dessen +|* TopLeft aus, andernfalls von der Mitte des aktuellen CharRects. +|* Ersterstellung MA 01. Jun. 95 +|* Letzte Aenderung MA 30. Apr. 96 +|* +*************************************************************************/ +/* -----------------23.09.98 10:29------------------- + * Beinhaltet das Objekt ein Control oder Gruppen, + * die nur aus Controls bestehen + * --------------------------------------------------*/ +BOOL lcl_IsControlGroup( const SdrObject *pObj ) +{ + BOOL bRet = FALSE; + if(pObj->ISA(SdrUnoObj)) + bRet = TRUE; + else if( pObj->ISA( SdrObjGroup ) ) + { + bRet = TRUE; + const SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList(); + for ( USHORT i = 0; i < pLst->GetObjCount(); ++i ) + if( !::lcl_IsControlGroup( pLst->GetObj( i ) ) ) + return FALSE; + } + return bRet; +} + +namespace +{ + class MarkableObjectsOnly : public ::svx::ISdrObjectFilter + { + public: + MarkableObjectsOnly( SdrPageView* i_pPV ) + :m_pPV( i_pPV ) + { + } + + virtual bool includeObject( const SdrObject& i_rObject ) const + { + return m_pPV && m_pPV->GetView().IsObjMarkable( const_cast< SdrObject* >( &i_rObject ), m_pPV ); + } + + private: + SdrPageView* m_pPV; + }; +} + +const SdrObject* SwFEShell::GetBestObject( BOOL bNext, USHORT /*GOTOOBJ_...*/ eType, BOOL bFlat, const ::svx::ISdrObjectFilter* pFilter ) +{ + if( !Imp()->HasDrawView() ) + return NULL; + + const SdrObject *pBest = 0, + *pTop = 0; + + const long nTmp = bNext ? LONG_MAX : 0; + Point aBestPos( nTmp, nTmp ); + Point aTopPos( nTmp, nTmp ); + Point aCurPos; + Point aPos; + BOOL bNoDraw = 0 == (GOTOOBJ_DRAW_ANY & eType); + BOOL bNoFly = 0 == (GOTOOBJ_FLY_ANY & eType); + + if( !bNoFly && bNoDraw ) + { + SwFlyFrm *pFly = GetCurrFrm( FALSE )->FindFlyFrm(); + if( pFly ) + pBest = pFly->GetVirtDrawObj(); + } + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + SdrPageView* pPV = Imp()->GetDrawView()->GetSdrPageView(); + + MarkableObjectsOnly aDefaultFilter( pPV ); + if ( !pFilter ) + pFilter = &aDefaultFilter; + + if( !pBest || rMrkList.GetMarkCount() == 1 ) + { + // Ausgangspunkt bestimmen. + SdrObjList* pList = NULL; + if ( rMrkList.GetMarkCount() ) + { + const SdrObject* pStartObj = rMrkList.GetMark(0)->GetMarkedSdrObj(); + if( pStartObj->ISA(SwVirtFlyDrawObj) ) + aPos = ((SwVirtFlyDrawObj*)pStartObj)->GetFlyFrm()->Frm().Pos(); + else + aPos = pStartObj->GetSnapRect().TopLeft(); + + // If an object inside a group is selected, we want to + // iterate over the group members. + if ( ! pStartObj->GetUserCall() ) + pList = pStartObj->GetObjList(); + } + else + { + // If no object is selected, we check if we just entered a group. + // In this case we want to iterate over the group members. + aPos = GetCharRect().Center(); + const SdrObject* pStartObj = pPV ? pPV->GetAktGroup() : 0; + if ( pStartObj && pStartObj->ISA( SdrObjGroup ) ) + pList = pStartObj->GetSubList(); + } + + if ( ! pList ) + { + // Here we are if + // A No object has been selected and no group has been entered or + // B An object has been selected and it is not inside a group + pList = getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 ); + } + + + ASSERT( pList, "No object list to iterate" ) + + SdrObjListIter aObjIter( *pList, bFlat ? IM_FLAT : IM_DEEPNOGROUPS ); + while ( aObjIter.IsMore() ) + { + SdrObject* pObj = aObjIter.Next(); + BOOL bFlyFrm = pObj->ISA(SwVirtFlyDrawObj); + if( ( bNoFly && bFlyFrm ) || + ( bNoDraw && !bFlyFrm ) || + ( eType == GOTOOBJ_DRAW_SIMPLE && lcl_IsControlGroup( pObj ) ) || + ( eType == GOTOOBJ_DRAW_CONTROL && !lcl_IsControlGroup( pObj ) ) || + ( pFilter && !pFilter->includeObject( *pObj ) ) ) + continue; + if( bFlyFrm ) + { + SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pObj; + SwFlyFrm *pFly = pO->GetFlyFrm(); + if( GOTOOBJ_FLY_ANY != ( GOTOOBJ_FLY_ANY & eType ) ) + { + switch ( eType ) + { + case GOTOOBJ_FLY_FRM: + if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() ) + continue; + break; + case GOTOOBJ_FLY_GRF: + if ( pFly->Lower() && + (pFly->Lower()->IsLayoutFrm() || + !((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode())) + continue; + break; + case GOTOOBJ_FLY_OLE: + if ( pFly->Lower() && + (pFly->Lower()->IsLayoutFrm() || + !((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode())) + continue; + break; + } + } + aCurPos = pFly->Frm().Pos(); + } + else + aCurPos = pObj->GetCurrentBoundRect().TopLeft(); + + // Sonderfall wenn ein anderes Obj auf selber Y steht. + if( aCurPos != aPos && // nur wenn ich es nicht selber bin + aCurPos.Y() == aPos.Y() && // ist die Y Position gleich + (bNext? (aCurPos.X() > aPos.X()) : // liegt neben mir + (aCurPos.X() < aPos.X())) ) // " reverse + { + aBestPos = Point( nTmp, nTmp ); + SdrObjListIter aTmpIter( *pList, bFlat ? IM_FLAT : IM_DEEPNOGROUPS ); + while ( aTmpIter.IsMore() ) + { + SdrObject* pTmpObj = aTmpIter.Next(); + bFlyFrm = pTmpObj->ISA(SwVirtFlyDrawObj); + if( ( bNoFly && bFlyFrm ) || ( bNoDraw && !bFlyFrm ) ) + continue; + if( bFlyFrm ) + { + SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pTmpObj; + aCurPos = pO->GetFlyFrm()->Frm().Pos(); + } + else + aCurPos = pTmpObj->GetCurrentBoundRect().TopLeft(); + + if( aCurPos != aPos && aCurPos.Y() == aPos.Y() && + (bNext? (aCurPos.X() > aPos.X()) : // liegt neben mir + (aCurPos.X() < aPos.X())) && // " reverse + (bNext? (aCurPos.X() < aBestPos.X()) : // besser als Beste + (aCurPos.X() > aBestPos.X())) ) // " reverse + { + aBestPos = aCurPos; + pBest = pTmpObj; + } + } + break; + } + + if( (bNext? (aPos.Y() < aCurPos.Y()) : // nur unter mir + (aPos.Y() > aCurPos.Y())) && // " reverse + (bNext? (aBestPos.Y() > aCurPos.Y()) : // naeher drunter + (aBestPos.Y() < aCurPos.Y())) || // " reverse + (aBestPos.Y() == aCurPos.Y() && + (bNext? (aBestPos.X() > aCurPos.X()) : // weiter links + (aBestPos.X() < aCurPos.X())))) // " reverse + + { + aBestPos = aCurPos; + pBest = pObj; + } + + if( (bNext? (aTopPos.Y() > aCurPos.Y()) : // hoeher als Beste + (aTopPos.Y() < aCurPos.Y())) || // " reverse + (aTopPos.Y() == aCurPos.Y() && + (bNext? (aTopPos.X() > aCurPos.X()) : // weiter links + (aTopPos.X() < aCurPos.X())))) // " reverse + { + aTopPos = aCurPos; + pTop = pObj; + } + } + // leider nichts gefunden + if( (bNext? (aBestPos.X() == LONG_MAX) : (aBestPos.X() == 0)) ) + pBest = pTop; + } + + return pBest; +} + +BOOL SwFEShell::GotoObj( BOOL bNext, USHORT /*GOTOOBJ_...*/ eType ) +{ + const SdrObject* pBest = GetBestObject( bNext, eType ); + + if ( !pBest ) + return FALSE; + + BOOL bFlyFrm = pBest->ISA(SwVirtFlyDrawObj); + if( bFlyFrm ) + { + SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pBest; + const SwRect& rFrm = pO->GetFlyFrm()->Frm(); + SelectObj( rFrm.Pos(), 0, (SdrObject*)pBest ); + if( !ActionPend() ) + MakeVisible( rFrm ); + } + else + { + SelectObj( Point(), 0, (SdrObject*)pBest ); + if( !ActionPend() ) + MakeVisible( pBest->GetCurrentBoundRect() ); + } + CallChgLnk(); + return TRUE; +} + +/************************************************************************* +|* +|* SwFEShell::BeginCreate() +|* +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung MA 21. Mar. 95 +|* +*************************************************************************/ + +BOOL SwFEShell::BeginCreate( UINT16 /*SdrObjKind ?*/ eSdrObjectKind, const Point &rPos ) +{ + BOOL bRet = FALSE; + + if ( !Imp()->HasDrawView() ) + Imp()->MakeDrawView(); + + if ( GetPageNumber( rPos ) ) + { + Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind ); + if ( eSdrObjectKind == OBJ_CAPTION ) + bRet = Imp()->GetDrawView()->BegCreateCaptionObj( + rPos, Size( lMinBorder - MINFLY, lMinBorder - MINFLY ), + GetOut() ); + else + bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() ); + } + if ( bRet ) + { + ::FrameNotify( this, FLY_DRAG_START ); + } + return bRet; +} + +BOOL SwFEShell::BeginCreate( UINT16 /*SdrObjKind ?*/ eSdrObjectKind, UINT32 eObjInventor, + const Point &rPos ) +{ + BOOL bRet = FALSE; + + if ( !Imp()->HasDrawView() ) + Imp()->MakeDrawView(); + + if ( GetPageNumber( rPos ) ) + { + Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind, eObjInventor ); + bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() ); + } + if ( bRet ) + ::FrameNotify( this, FLY_DRAG_START ); + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::MoveCreate() +|* +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung MA 24. Jan. 95 +|* +*************************************************************************/ + +void SwFEShell::MoveCreate( const Point &rPos ) +{ + ASSERT( Imp()->HasDrawView(), "MoveCreate without DrawView?" ); + if ( GetPageNumber( rPos ) ) + { + ScrollTo( rPos ); + Imp()->GetDrawView()->MovCreateObj( rPos ); + ::FrameNotify( this, FLY_DRAG ); + } +} + +/************************************************************************* +|* +|* SwFEShell::EndCreate(), ImpEndCreate() +|* +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung MA 14. Oct. 96 +|* +*************************************************************************/ + +BOOL SwFEShell::EndCreate( UINT16 eSdrCreateCmd ) +{ + // JP 18.08.95: Damit das Undo-Object aus der DrawEngine nicht bei uns + // gespeichert wird, (wir erzeugen ein eigenes Undo-Object!) hier kurz + // das Undo abschalten + ASSERT( Imp()->HasDrawView(), "EndCreate without DrawView?" ); + if( !Imp()->GetDrawView()->IsGroupEntered() ) + GetDoc()->SetNoDrawUndoObj( TRUE ); + BOOL bCreate = Imp()->GetDrawView()->EndCreateObj( + SdrCreateCmd( eSdrCreateCmd ) ); + GetDoc()->SetNoDrawUndoObj( FALSE ); + + if ( !bCreate ) + { + ::FrameNotify( this, FLY_DRAG_END ); + return FALSE; + } + + if ( (SdrCreateCmd)eSdrCreateCmd == SDRCREATE_NEXTPOINT ) + { + ::FrameNotify( this, FLY_DRAG ); + return TRUE; + } + return ImpEndCreate(); +} + + +BOOL SwFEShell::ImpEndCreate() +{ + ASSERT( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1, + "Neues Object nicht selektiert." ); + + SdrObject& rSdrObj = *Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + + if( rSdrObj.GetSnapRect().IsEmpty() ) + { + //JP 10.04.95: das Object vergessen wir lieber, fuerht nur + // zu Problemen + Imp()->GetDrawView()->DeleteMarked(); + Imp()->GetDrawView()->UnmarkAll(); + ::FrameNotify( this, FLY_DRAG_END ); + return FALSE; + } + + if( rSdrObj.GetUpGroup() ) + { + Point aTmpPos( rSdrObj.GetSnapRect().TopLeft() ); + Point aNewAnchor( rSdrObj.GetUpGroup()->GetAnchorPos() ); + // OD 2004-04-05 #i26791# - direct object positioning for group members + rSdrObj.NbcSetRelativePos( aTmpPos - aNewAnchor ); + rSdrObj.NbcSetAnchorPos( aNewAnchor ); + ::FrameNotify( this, FLY_DRAG ); + return TRUE; + } + + LockPaint(); + StartAllAction(); + + Imp()->GetDrawView()->UnmarkAll(); + + const Rectangle &rBound = rSdrObj.GetSnapRect(); + Point aPt( rBound.TopRight() ); + + //Fremde Identifier sollen in den Default laufen. + //Ueberschneidungen sind moeglich!! + UINT16 nIdent = SdrInventor == rSdrObj.GetObjInventor() + ? rSdrObj.GetObjIdentifier() + : 0xFFFF; + + //Default fuer Controls ist Zeichengebunden, Absatzgebunden sonst. + SwFmtAnchor aAnch; + const SwFrm *pAnch = 0; + BOOL bCharBound = FALSE; + if( rSdrObj.ISA( SdrUnoObj ) ) + { + SwPosition aPos( GetDoc()->GetNodes() ); + SwCrsrMoveState aState( MV_SETONLYTEXT ); + Point aPoint( aPt.X(), aPt.Y() + rBound.GetHeight()/2 ); + getIDocumentLayoutAccess()->GetRootFrm()->GetCrsrOfst( &aPos, aPoint, &aState ); + + //JP 22.01.99: Zeichenbindung ist im ReadnOnly-Inhalt nicht erlaubt + if( !aPos.nNode.GetNode().IsProtect() ) + { + pAnch = aPos.nNode.GetNode().GetCntntNode()->GetFrm( &aPoint, &aPos ); + SwRect aTmp; + pAnch->GetCharRect( aTmp, aPos ); + + //Der Crsr darf nicht zu weit entfernt sein. + bCharBound = TRUE; + Rectangle aRect( aTmp.SVRect() ); + aRect.Left() -= MM50*2; + aRect.Top() -= MM50*2; + aRect.Right() += MM50*2; + aRect.Bottom()+= MM50*2; + + if( !aRect.IsOver( rBound ) && !::GetHtmlMode( GetDoc()->GetDocShell() )) + bCharBound = FALSE; + + //Bindung in Kopf-/Fusszeilen ist ebenfalls nicht erlaubt. + if( bCharBound ) + bCharBound = !GetDoc()->IsInHeaderFooter( aPos.nNode ); + + if( bCharBound ) + { + aAnch.SetType( FLY_AS_CHAR ); + aAnch.SetAnchor( &aPos ); + } + } + } + + if( !bCharBound ) + { + // OD 16.05.2003 #108784# - allow native drawing objects in header/footer. + // Thus, set <bBodyOnly> to <false> for these objects using value + // of <nIdent> - value <0xFFFF> indicates control objects, which aren't + // allowed in header/footer. + //bool bBodyOnly = OBJ_NONE != nIdent; + bool bBodyOnly = 0xFFFF == nIdent; + bool bAtPage = false; + const SwFrm* pPage = 0; + SwCrsrMoveState aState( MV_SETONLYTEXT ); + Point aPoint( aPt ); + SwPosition aPos( GetDoc()->GetNodes() ); + GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState ); + + //JP 22.01.99: nicht in ReadnOnly-Inhalt setzen + if( aPos.nNode.GetNode().IsProtect() ) + // dann darf er nur seitengebunden sein. Oder sollte man + // die naechste nicht READONLY Position suchen? + bAtPage = true; + + pAnch = aPos.nNode.GetNode().GetCntntNode()->GetFrm( &aPoint, 0, FALSE ); + + if( !bAtPage ) + { + const SwFlyFrm *pTmp = pAnch->FindFlyFrm(); + if( pTmp ) + { + const SwFrm* pTmpFrm = pAnch; + SwRect aBound( rBound ); + while( pTmp ) + { + if( pTmp->Frm().IsInside( aBound ) ) + { + if( !bBodyOnly || !pTmp->FindFooterOrHeader() ) + pPage = pTmpFrm; + break; + } + pTmp = pTmp->GetAnchorFrm() + ? pTmp->GetAnchorFrm()->FindFlyFrm() + : 0; + pTmpFrm = pTmp; + } + } + + if( !pPage ) + pPage = pAnch->FindPageFrm(); + + // immer ueber FindAnchor gehen, damit der Frame immer an den + // davorgehen gebunden wird. Beim GetCrsOfst kann man auch zum + // nachfolgenden kommen. DAS IST FALSCH + pAnch = ::FindAnchor( pPage, aPt, bBodyOnly ); + aPos.nNode = *((SwCntntFrm*)pAnch)->GetNode(); + + //JP 22.01.99: nicht in ReadnOnly-Inhalt setzen + if( aPos.nNode.GetNode().IsProtect() ) + // dann darf er nur seitengebunden sein. Oder sollte man + // die naechste nicht READONLY Position suchen? + bAtPage = true; + else + { + aAnch.SetType( FLY_AT_PARA ); + aAnch.SetAnchor( &aPos ); + } + } + + if( bAtPage ) + { + pPage = pAnch->FindPageFrm(); + + aAnch.SetType( FLY_AT_PAGE ); + aAnch.SetPageNum( pPage->GetPhyPageNum() ); + pAnch = pPage; // die Page wird jetzt zum Anker + } + } + + SfxItemSet aSet( GetDoc()->GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE, + RES_SURROUND, RES_ANCHOR, 0 ); + aSet.Put( aAnch ); + + // OD 2004-03-30 #i26791# - determine relative object position + SwTwips nXOffset; + SwTwips nYOffset = rBound.Top() - pAnch->Frm().Top(); + { + if( pAnch->IsVertical() ) + { + nXOffset = nYOffset; + nYOffset = pAnch->Frm().Left()+pAnch->Frm().Width()-rBound.Right(); + } + else if( pAnch->IsRightToLeft() ) + nXOffset = pAnch->Frm().Left()+pAnch->Frm().Width()-rBound.Right(); + else + nXOffset = rBound.Left() - pAnch->Frm().Left(); + if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() ) + { + SwTxtFrm* pTmp = (SwTxtFrm*)pAnch; + do { + pTmp = pTmp->FindMaster(); + ASSERT( pTmp, "Where's my Master?" ); + // OD 2004-03-30 #i26791# - correction: add frame area height + // of master frames. + nYOffset += pTmp->IsVertical() ? + pTmp->Frm().Width() : pTmp->Frm().Height(); + } while ( pTmp->IsFollow() ); + } + } + + if( OBJ_NONE == nIdent ) + { + //Bei OBJ_NONE wird ein Fly eingefuegt. + const long nWidth = rBound.Right() - rBound.Left(); + const long nHeight= rBound.Bottom() - rBound.Top(); + aSet.Put( SwFmtFrmSize( ATT_MIN_SIZE, Max( nWidth, long(MINFLY) ), + Max( nHeight, long(MINFLY) ))); + + SwFmtHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME ); + SwFmtVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME ); + aSet.Put( SwFmtSurround( SURROUND_PARALLEL ) ); + aSet.Put( aHori ); + aSet.Put( aVert ); + + //Schnell noch das Rechteck merken + const SwRect aFlyRect( rBound ); + + //Erzeugtes Object wegwerfen, so kann der Fly am elegentesten + //ueber vorhandene SS erzeugt werden. + GetDoc()->SetNoDrawUndoObj( TRUE ); // siehe oben + // --> OD 2005-08-08 #i52858# - method name changed + SdrPage *pPg = getIDocumentDrawModelAccess()->GetOrCreateDrawModel()->GetPage( 0 ); + // <-- + if( !pPg ) + { + SdrModel* pTmpSdrModel = getIDocumentDrawModelAccess()->GetDrawModel(); + pPg = pTmpSdrModel->AllocPage( FALSE ); + pTmpSdrModel->InsertPage( pPg ); + } + pPg->RecalcObjOrdNums(); + SdrObject* pRemovedObject = pPg->RemoveObject( rSdrObj.GetOrdNumDirect() ); + SdrObject::Free( pRemovedObject ); + GetDoc()->SetNoDrawUndoObj( FALSE ); + + SwFlyFrm* pFlyFrm; + if( NewFlyFrm( aSet, TRUE ) && + ::GetHtmlMode( GetDoc()->GetDocShell() ) && + 0 != ( pFlyFrm = FindFlyFrm() )) + { + SfxItemSet aHtmlSet( GetDoc()->GetAttrPool(), RES_VERT_ORIENT, RES_HORI_ORIENT ); + //Horizontale Ausrichtung: + const BOOL bLeftFrm = aFlyRect.Left() < + pAnch->Frm().Left() + pAnch->Prt().Left(), + bLeftPrt = aFlyRect.Left() + aFlyRect.Width() < + pAnch->Frm().Left() + pAnch->Prt().Width()/2; + if( bLeftFrm || bLeftPrt ) + { + aHori.SetHoriOrient( text::HoriOrientation::LEFT ); + aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA ); + } + else + { + const BOOL bRightFrm = aFlyRect.Left() > + pAnch->Frm().Left() + pAnch->Prt().Width(); + aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); + aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA ); + } + aHtmlSet.Put( aHori ); + aVert.SetVertOrient( text::VertOrientation::TOP ); + aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA ); + aHtmlSet.Put( aVert ); + + GetDoc()->SetAttr( aHtmlSet, *pFlyFrm->GetFmt() ); + } + } + else + { + Point aRelNullPt; + if( OBJ_CAPTION == nIdent ) + aRelNullPt = ((SdrCaptionObj&)rSdrObj).GetTailPos(); + else + aRelNullPt = rBound.TopLeft(); + + aSet.Put( aAnch ); + aSet.Put( SwFmtSurround( SURROUND_THROUGHT ) ); + // OD 2004-03-30 #i26791# - set horizontal position + SwFmtHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME ); + aSet.Put( aHori ); + // OD 2004-03-30 #i26791# - set vertical position + if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() ) + { + SwTxtFrm* pTmp = (SwTxtFrm*)pAnch; + do { + pTmp = pTmp->FindMaster(); + ASSERT( pTmp, "Where's my Master?" ); + nYOffset += pTmp->IsVertical() ? + pTmp->Prt().Width() : pTmp->Prt().Height(); + } while ( pTmp->IsFollow() ); + } + SwFmtVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME ); + aSet.Put( aVert ); + SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)getIDocumentLayoutAccess()->MakeLayoutFmt( RND_DRAW_OBJECT, &aSet ); + // --> OD 2004-10-25 #i36010# - set layout direction of the position + pFmt->SetPositionLayoutDir( + text::PositionLayoutDir::PositionInLayoutDirOfAnchor ); + // <-- + // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set + pFmt->PosAttrSet(); + // <-- + + SwDrawContact *pContact = new SwDrawContact( pFmt, &rSdrObj ); + // --> OD 2004-11-22 #i35635# + pContact->MoveObjToVisibleLayer( &rSdrObj ); + // <-- + if( bCharBound ) + { + ASSERT( aAnch.GetAnchorId() == FLY_AS_CHAR, "wrong AnchorType" ); + SwTxtNode *pNd = aAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode(); + SwFmtFlyCnt aFmt( pFmt ); + pNd->InsertItem(aFmt, + aAnch.GetCntntAnchor()->nContent.GetIndex(), 0 ); + SwFmtVertOrient aVertical( pFmt->GetVertOrient() ); + aVertical.SetVertOrient( text::VertOrientation::LINE_CENTER ); + pFmt->SetFmtAttr( aVertical ); + } + if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() ) + { + SwTxtFrm* pTmp = (SwTxtFrm*)pAnch; + do { + pTmp = pTmp->FindMaster(); + ASSERT( pTmp, "Where's my Master?" ); + } while( pTmp->IsFollow() ); + pAnch = pTmp; + } + + pContact->ConnectToLayout(); + + // OD 25.06.2003 #108784# - mark object at frame the object is inserted at. + { + SdrObject* pMarkObj = pContact->GetDrawObjectByAnchorFrm( *pAnch ); + if ( pMarkObj ) + { + Imp()->GetDrawView()->MarkObj( pMarkObj, Imp()->GetPageView(), + FALSE, FALSE ); + } + else + { + Imp()->GetDrawView()->MarkObj( &rSdrObj, Imp()->GetPageView(), + FALSE, FALSE ); + } + } + } + + GetDoc()->SetModified(); + + KillPams(); + EndAllActionAndCall(); + UnlockPaint(); + return TRUE; +} + + +/************************************************************************* +|* +|* SwFEShell::BreakCreate() +|* +|* Ersterstellung MA 20. Dec. 94 +|* Letzte Aenderung MA 09. Jan. 95 +|* +*************************************************************************/ + +void SwFEShell::BreakCreate() +{ + ASSERT( Imp()->HasDrawView(), "BreakCreate without DrawView?" ); + Imp()->GetDrawView()->BrkCreateObj(); + ::FrameNotify( this, FLY_DRAG_END ); +} + +/************************************************************************* +|* +|* SwFEShell::IsDrawCreate() +|* +|* Ersterstellung OM 16. Mar. 95 +|* Letzte Aenderung OM 16. Mar. 95 +|* +*************************************************************************/ + +BOOL SwFEShell::IsDrawCreate() const +{ + return Imp()->HasDrawView() ? Imp()->GetDrawView()->IsCreateObj() : FALSE; +} + +/************************************************************************* +|* +|* SwFEShell::BeginMark() +|* +|* Ersterstellung OM 07. Feb. 95 +|* Letzte Aenderung OM 07. Feb. 95 +|* +*************************************************************************/ + +BOOL SwFEShell::BeginMark( const Point &rPos ) +{ + if ( !Imp()->HasDrawView() ) + Imp()->MakeDrawView(); + + if ( GetPageNumber( rPos ) ) + { + SwDrawView* pDView = Imp()->GetDrawView(); + + if (pDView->HasMarkablePoints()) + return pDView->BegMarkPoints( rPos ); + else + return pDView->BegMarkObj( rPos ); + } + else + return FALSE; +} + +/************************************************************************* +|* +|* SwFEShell::MoveMark() +|* +|* Ersterstellung OM 07. Feb. 95 +|* Letzte Aenderung OM 07. Feb. 95 +|* +*************************************************************************/ + +void SwFEShell::MoveMark( const Point &rPos ) +{ + ASSERT( Imp()->HasDrawView(), "MoveMark without DrawView?" ); + + if ( GetPageNumber( rPos ) ) + { + ScrollTo( rPos ); + SwDrawView* pDView = Imp()->GetDrawView(); +// Imp()->GetDrawView()->MovMarkObj( rPos ); + + if (pDView->IsInsObjPoint()) + pDView->MovInsObjPoint( rPos ); + else if (pDView->IsMarkPoints()) + pDView->MovMarkPoints( rPos ); + else + pDView->MovAction( rPos ); + } +} + +/************************************************************************* +|* +|* SwFEShell::EndMark() +|* +|* Ersterstellung OM 07. Feb. 95 +|* Letzte Aenderung MA 08. Feb. 95 +|* +*************************************************************************/ + +BOOL SwFEShell::EndMark() +{ + BOOL bRet = FALSE; + ASSERT( Imp()->HasDrawView(), "EndMark without DrawView?" ); + + if (Imp()->GetDrawView()->IsMarkObj()) + { + bRet = Imp()->GetDrawView()->EndMarkObj(); + + if ( bRet ) + { + BOOL bShowHdl = FALSE; + SwDrawView* pDView = Imp()->GetDrawView(); + //Rahmen werden auf diese Art nicht Selektiert, es sein denn es + //ist nur ein Rahmen. + SdrMarkList &rMrkList = (SdrMarkList&)pDView->GetMarkedObjectList(); + SwFlyFrm* pOldSelFly = ::GetFlyFromMarked( &rMrkList, this ); + + if ( rMrkList.GetMarkCount() > 1 ) + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + if( pObj->ISA(SwVirtFlyDrawObj) ) + { + if ( !bShowHdl ) + { + //HMHpDView->HideMarkHdl(); + bShowHdl = TRUE; + } + rMrkList.DeleteMark( i ); + --i; //keinen auslassen. + } + } + + if( bShowHdl ) + { + pDView->MarkListHasChanged(); + pDView->AdjustMarkHdl(); + //HMHpDView->ShowMarkHdl(); + } + + if ( rMrkList.GetMarkCount() ) + ::lcl_GrabCursor(this, pOldSelFly); + else + bRet = FALSE; + } + if ( bRet ) + ::FrameNotify( this, FLY_DRAG_START ); + } + else + { + if (Imp()->GetDrawView()->IsMarkPoints()) + bRet = Imp()->GetDrawView()->EndMarkPoints(); + } + + SetChainMarker(); + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::BreakSelect() +|* +|* Ersterstellung OM 07. Feb. 95 +|* Letzte Aenderung OM 07. Feb. 95 +|* +*************************************************************************/ + +void SwFEShell::BreakMark() +{ + ASSERT( Imp()->HasDrawView(), "BreakMark without DrawView?" ); + Imp()->GetDrawView()->BrkMarkObj(); +} + +/************************************************************************* +|* +|* SwFEShell::GetAnchorId() +|* +|* Ersterstellung MA 30. Jan. 95 +|* Letzte Aenderung MA 30. Jan. 95 +|* +*************************************************************************/ + +short SwFEShell::GetAnchorId() const +{ + short nRet = SHRT_MAX; + if ( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + if ( pObj->ISA(SwVirtFlyDrawObj) ) + { + nRet = -1; + break; + } + SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj); + short nId = static_cast<short>(pContact->GetFmt()->GetAnchor().GetAnchorId()); + if ( nRet == SHRT_MAX ) + nRet = nId; + else if ( nRet != nId ) + { + nRet = -1; + break; + } + } + } + if ( nRet == SHRT_MAX ) + nRet = -1; + return nRet; +} + +/************************************************************************* +|* +|* SwFEShell::ChgAnchor() +|* +|* Ersterstellung MA 10. Jan. 95 +|* Letzte Aenderung MA 30. May. 96 +|* +*************************************************************************/ + +void SwFEShell::ChgAnchor( int eAnchorId, BOOL bSameOnly, BOOL bPosCorr ) +{ + ASSERT( Imp()->HasDrawView(), "ChgAnchor without DrawView?" ); + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + if( rMrkList.GetMarkCount() && + !rMrkList.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() ) + { + StartAllAction(); + + if( GetDoc()->ChgAnchor( rMrkList, (RndStdIds)eAnchorId, bSameOnly, bPosCorr )) + Imp()->GetDrawView()->UnmarkAll(); + + EndAllAction(); + + ::FrameNotify( this, FLY_DRAG ); + } +} + +/************************************************************************* +|* +|* SwFEShell::DelSelectedObj() +|* +|* Ersterstellung MA 03. Nov. 92 +|* Letzte Aenderung MA 14. Nov. 95 +|* +*************************************************************************/ + +void SwFEShell::DelSelectedObj() +{ + ASSERT( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" ); + if ( Imp()->HasDrawView() ) + { + StartAllAction(); + Imp()->GetDrawView()->DeleteMarked(); + EndAllAction(); + ::FrameNotify( this, FLY_DRAG_END ); + } +} + +/************************************************************************* +|* +|* SwFEShell::GetObjSize(), GetAnchorObjDiff() +|* +|* Beschreibung Fuer die Statuszeile zum Erfragen der aktuellen +|* Verhaeltnisse +|* Ersterstellung MA 25. Apr. 95 +|* Letzte Aenderung MA 25. Apr. 95 +|* +*************************************************************************/ + +Size SwFEShell::GetObjSize() const +{ + Rectangle aRect; + if ( Imp()->HasDrawView() ) + { + if ( Imp()->GetDrawView()->IsAction() ) + Imp()->GetDrawView()->TakeActionRect( aRect ); + else + aRect = Imp()->GetDrawView()->GetAllMarkedRect(); + } + return aRect.GetSize(); +} + +Point SwFEShell::GetAnchorObjDiff() const +{ + const SdrView *pView = Imp()->GetDrawView(); + ASSERT( pView, "GetAnchorObjDiff without DrawView?" ); + + Rectangle aRect; + if ( Imp()->GetDrawView()->IsAction() ) + Imp()->GetDrawView()->TakeActionRect( aRect ); + else + aRect = Imp()->GetDrawView()->GetAllMarkedRect(); + + Point aRet( aRect.TopLeft() ); + + if ( IsFrmSelected() ) + { + SwFlyFrm *pFly = FindFlyFrm(); + aRet -= pFly->GetAnchorFrm()->Frm().Pos(); + } + else + { + const SdrObject *pObj = pView->GetMarkedObjectList().GetMarkCount() == 1 ? + pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj() : 0; + if ( pObj ) + aRet -= pObj->GetAnchorPos(); + } + + return aRet; +} + +Point SwFEShell::GetObjAbsPos() const +{ + ASSERT( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" ); + return Imp()->GetDrawView()->GetDragStat().GetActionRect().TopLeft(); +} + + + +/************************************************************************* +|* +|* SwFEShell::IsGroupSelected() +|* +|* Ersterstellung MA 30. Jan. 95 +|* Letzte Aenderung MA 30. May. 96 +|* +*************************************************************************/ + +BOOL SwFEShell::IsGroupSelected() +{ + if ( IsObjSelected() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + // OD 30.06.2003 #108784# - consider 'virtual' drawing objects. + // Thus, use corresponding method instead of checking type. + if ( pObj->IsGroupObject() && + // --> FME 2004-12-08 #i38505# No ungroup allowed for 3d objects + !pObj->Is3DObj() && + // <-- + FLY_AS_CHAR != ((SwDrawContact*)GetUserCall(pObj))-> + GetFmt()->GetAnchor().GetAnchorId() ) + { + return TRUE; + } + } + } + return FALSE; +} + +// OD 27.06.2003 #108784# - change return type. +// OD 27.06.2003 #108784# - adjustments for drawing objects in header/footer: +// allow group, only if all selected objects are in the same header/footer +// or not in header/footer. +bool SwFEShell::IsGroupAllowed() const +{ + bool bIsGroupAllowed = false; + if ( IsObjSelected() > 1 ) + { + bIsGroupAllowed = true; + const SdrObject* pUpGroup = 0L; + const SwFrm* pHeaderFooterFrm = 0L; + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; bIsGroupAllowed && i < rMrkList.GetMarkCount(); ++i ) + { + const SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + if ( i ) + bIsGroupAllowed = pObj->GetUpGroup() == pUpGroup; + else + pUpGroup = pObj->GetUpGroup(); + + if ( bIsGroupAllowed ) + { + SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) ); + if ( !pFrmFmt ) + { + ASSERT( false, + "<SwFEShell::IsGroupAllowed()> - missing frame format" ); + bIsGroupAllowed = false; + } + else if ( FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() ) + { + bIsGroupAllowed = false; + } + } + + // OD 27.06.2003 #108784# - check, if all selected objects are in the + // same header/footer or not in header/footer. + if ( bIsGroupAllowed ) + { + const SwFrm* pAnchorFrm = 0L; + if ( pObj->ISA(SwVirtFlyDrawObj) ) + { + const SwFlyFrm* pFlyFrm = + static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm(); + if ( pFlyFrm ) + { + pAnchorFrm = pFlyFrm->GetAnchorFrm(); + } + } + else + { + SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall( pObj )); + if ( pDrawContact ) + { + pAnchorFrm = pDrawContact->GetAnchorFrm( pObj ); + } + } + if ( pAnchorFrm ) + { + if ( i ) + { + bIsGroupAllowed = + ( pAnchorFrm->FindFooterOrHeader() == pHeaderFooterFrm ); + } + else + { + pHeaderFooterFrm = pAnchorFrm->FindFooterOrHeader(); + } + } + } + + } + } + + return bIsGroupAllowed; +} + +/************************************************************************* +|* +|* SwFEShell::GroupSelection() +|* +|* Beschreibung Die Gruppe bekommt den Anker und das Contactobjekt +|* des ersten in der Selektion +|* Ersterstellung MA 30. Jan. 95 +|* Letzte Aenderung MA 23. Apr. 95 +|* +*************************************************************************/ + +void SwFEShell::GroupSelection() +{ + if ( IsGroupAllowed() ) + { + StartAllAction(); + StartUndo( UNDO_START ); + + GetDoc()->GroupSelection( *Imp()->GetDrawView() ); + + EndUndo( UNDO_END ); + EndAllAction(); + } +} + +/************************************************************************* +|* +|* SwFEShell::UnGroupSelection() +|* +|* Beschreibung Die Einzelobjekte bekommen eine Kopie vom Anker und +|* Contactobjekt der Gruppe. +|* Ersterstellung MA 30. Jan. 95 +|* Letzte Aenderung MA 01. Feb. 95 +|* +*************************************************************************/ + +void SwFEShell::UnGroupSelection() +{ + if ( IsGroupSelected() ) + { + StartAllAction(); + StartUndo( UNDO_START ); + + GetDoc()->UnGroupSelection( *Imp()->GetDrawView() ); + + EndUndo( UNDO_END ); + EndAllAction(); + } +} + +/************************************************************************* +|* +|* SwFEShell::MirrorSelection() +|* +|* Ersterstellung MA 06. Aug. 95 +|* Letzte Aenderung MA 06. Aug. 95 +|* +*************************************************************************/ + +void SwFEShell::MirrorSelection( BOOL bHorizontal ) +{ + SdrView *pView = Imp()->GetDrawView(); + if ( IsObjSelected() && pView->IsMirrorAllowed() ) + { + if ( bHorizontal ) + pView->MirrorAllMarkedHorizontal(); + else + pView->MirrorAllMarkedVertical(); + } +} + +// springe zum benannten Rahmen (Grafik/OLE) + +BOOL SwFEShell::GotoFly( const String& rName, FlyCntType eType, BOOL bSelFrm ) +{ + BOOL bRet = FALSE; +static BYTE __READONLY_DATA aChkArr[ 4 ] = { + /* FLYCNTTYPE_ALL */ 0, + /* FLYCNTTYPE_FRM */ ND_TEXTNODE, + /* FLYCNTTYPE_GRF */ ND_GRFNODE, + /* FLYCNTTYPE_OLE */ ND_OLENODE + }; + + const SwFlyFrmFmt* pFlyFmt = pDoc->FindFlyByName( rName, aChkArr[ eType]); + if( pFlyFmt ) + { + SET_CURR_SHELL( this ); + + SwClientIter aIter( *(SwModify*)pFlyFmt ); + SwFlyFrm* pFrm = (SwFlyFrm*)aIter.First( TYPE( SwFlyFrm )); + if( pFrm ) + { + ASSERT( pFrm->IsFlyFrm(), "Wrong FrmType" ); + if( bSelFrm ) + { + SelectObj( pFrm->Frm().Pos(), 0, ((SwFlyFrm*)pFrm)->GetVirtDrawObj() ); + if( !ActionPend() ) + MakeVisible( pFrm->Frm() ); + } + else + { + // --> OD 2004-06-11 #i28701# - no format here +// pFrm->GetAnchorFrm()->Calc(); + SwCntntFrm *pCFrm = pFrm->ContainsCntnt(); + if ( pCFrm ) + { + SwCntntNode *pCNode = pCFrm->GetNode(); + ClearMark(); + SwPaM* pCrsr = GetCrsr(); + + pCrsr->GetPoint()->nNode = *pCNode; + pCrsr->GetPoint()->nContent.Assign( pCNode, 0 ); + + SwRect& rChrRect = (SwRect&)GetCharRect(); + rChrRect = pFrm->Prt(); + rChrRect.Pos() += pFrm->Frm().Pos(); + GetCrsrDocPos() = rChrRect.Pos(); + } + } + bRet = TRUE; + } + } + return bRet; +} + +USHORT SwFEShell::GetFlyCount( FlyCntType eType ) const +{ + return GetDoc()->GetFlyCount(eType); +} + + +const SwFrmFmt* SwFEShell::GetFlyNum(USHORT nIdx, FlyCntType eType ) const +{ + return GetDoc()->GetFlyNum(nIdx, eType ); +} + +// zeige das akt. selektierte "Object" an +void SwFEShell::MakeSelVisible() +{ + if( Imp()->HasDrawView() && + Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) + { + MakeVisible( Imp()->GetDrawView()->GetAllMarkedRect() ); + } + else + SwCrsrShell::MakeSelVisible(); +} + + +//Welcher Schutz ist am selektierten Objekt gesetzt? +BYTE SwFEShell::IsSelObjProtected( USHORT eType ) const +{ + int nChk = 0; + const bool bParent = (eType & FLYPROTECT_PARENT); + if( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for( ULONG i = rMrkList.GetMarkCount(); i; ) + { + SdrObject *pObj = rMrkList.GetMark( --i )->GetMarkedSdrObj(); + if( !bParent ) + { + nChk |= ( pObj->IsMoveProtect() ? FLYPROTECT_POS : 0 ) | + ( pObj->IsResizeProtect()? FLYPROTECT_SIZE : 0 ); + + if( FLYPROTECT_CONTENT & eType && pObj->ISA(SwVirtFlyDrawObj) ) + { + SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); + if ( pFly->GetFmt()->GetProtect().IsCntntProtected() ) + nChk |= FLYPROTECT_CONTENT; + + if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() ) + { + SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode(); + if ( pNd ) + { + uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef(); + + // TODO/LATER: use correct aspect + if ( xObj.is() && + embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) + { + nChk |= FLYPROTECT_SIZE; + nChk |= FLYPROTECT_FIXED; + } + } + } + } + nChk &= eType; + if( nChk == eType ) + return static_cast<BYTE>(eType); + } + const SwFrm* pAnch; + if( pObj->ISA(SwVirtFlyDrawObj) ) + pAnch = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm()->GetAnchorFrm(); + else + { + SwDrawContact* pTmp = (SwDrawContact*)GetUserCall(pObj); + pAnch = pTmp ? pTmp->GetAnchorFrm( pObj ) : NULL; + } + if( pAnch && pAnch->IsProtected() ) + return static_cast<BYTE>(eType); + } + } + return static_cast<BYTE>(nChk); +} + +BOOL SwFEShell::GetObjAttr( SfxItemSet &rSet ) const +{ + if ( !IsObjSelected() ) + return FALSE; + + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj); + // --> OD 2007-07-24 #143008# - make code robust + ASSERT( pContact, "<SwFEShell::GetObjAttr(..)> - missing <pContact> - please inform OD." ); + if ( pContact ) + { + if ( i ) + rSet.MergeValues( pContact->GetFmt()->GetAttrSet() ); + else + rSet.Put( pContact->GetFmt()->GetAttrSet() ); + } + // <-- + } + return TRUE; +} + +BOOL SwFEShell::SetObjAttr( const SfxItemSet& rSet ) +{ + SET_CURR_SHELL( this ); + + if ( !rSet.Count() ) + { ASSERT( !this, "SetObjAttr, empty set." ); + return FALSE; + } + + StartAllAction(); + StartUndo( UNDO_INSATTR ); + + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj); + GetDoc()->SetAttr( rSet, *pContact->GetFmt() ); + } + + EndUndo( UNDO_INSATTR ); + EndAllActionAndCall(); + GetDoc()->SetModified(); + return TRUE; +} + +BOOL SwFEShell::IsAlignPossible() const +{ + USHORT nCnt; + if ( 0 < (nCnt = IsObjSelected()) ) + { + BOOL bRet = TRUE; + if ( nCnt == 1 ) + { + SdrObject *pO = Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + SwDrawContact *pC = (SwDrawContact*)GetUserCall(pO); + //only as character bound drawings can be aligned + bRet = (pC->GetFmt()->GetAnchor().GetAnchorId() == FLY_AS_CHAR); + } + if ( bRet ) + return Imp()->GetDrawView()->IsAlignPossible(); + } + return FALSE; +} + + +//Temporaerer Fix bis SS von JOE da ist +void SwFEShell::CheckUnboundObjects() +{ + SET_CURR_SHELL( this ); + + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj(); + if ( !GetUserCall(pObj) ) + { + const Rectangle &rBound = pObj->GetSnapRect(); + const Point aPt( rBound.TopLeft() ); + const SwFrm *pPage = GetLayout()->Lower(); + const SwFrm *pLast = pPage; + while ( pPage && !pPage->Frm().IsInside( aPt ) ) + { + if ( aPt.Y() > pPage->Frm().Bottom() ) + pLast = pPage; + pPage = pPage->GetNext(); + } + if ( !pPage ) + pPage = pLast; + ASSERT( pPage, "Page not found." ); + + //Fremde Identifier sollen in den Default laufen. + //Ueberschneidungen sind moeglich!! + UINT16 nIdent = + Imp()->GetDrawView()->GetCurrentObjInventor() == SdrInventor ? + Imp()->GetDrawView()->GetCurrentObjIdentifier() : 0xFFFF; + + SwFmtAnchor aAnch; + const SwFrm *pAnch = 0; + { + pAnch = ::FindAnchor( pPage, aPt, TRUE ); + SwPosition aPos( *((SwCntntFrm*)pAnch)->GetNode() ); + aAnch.SetType( FLY_AT_PARA ); + aAnch.SetAnchor( &aPos ); + ((SwRect&)GetCharRect()).Pos() = aPt; + } + + //Erst hier die Action, damit das GetCharRect aktuelle Werte liefert. + StartAllAction(); + + SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE, + RES_SURROUND, RES_ANCHOR, 0 ); + aSet.Put( aAnch ); + + Point aRelNullPt; + + if( OBJ_CAPTION == nIdent ) + aRelNullPt = ((SdrCaptionObj*)pObj)->GetTailPos(); + else + aRelNullPt = rBound.TopLeft(); + + aSet.Put( aAnch ); + aSet.Put( SwFmtSurround( SURROUND_THROUGHT ) ); + SwFrmFmt* pFmt = getIDocumentLayoutAccess()->MakeLayoutFmt( RND_DRAW_OBJECT, &aSet ); + + SwDrawContact *pContact = new SwDrawContact( + (SwDrawFrmFmt*)pFmt, pObj ); + + // --> OD 2004-11-22 #i35635# + pContact->MoveObjToVisibleLayer( pObj ); + // <-- + pContact->ConnectToLayout(); + + EndAllAction(); + } + } +} + +void SwFEShell::SetCalcFieldValueHdl(Outliner* pOutliner) +{ + GetDoc()->SetCalcFieldValueHdl(pOutliner); +} + + + +int SwFEShell::Chainable( SwRect &rRect, const SwFrmFmt &rSource, + const Point &rPt ) const +{ + rRect.Clear(); + + //Die Source darf noch keinen Follow haben. + const SwFmtChain &rChain = rSource.GetChain(); + if ( rChain.GetNext() ) + return SW_CHAIN_SOURCE_CHAINED; + + if( Imp()->HasDrawView() ) + { + SdrObject* pObj; + SdrPageView* pPView; + SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView(); + const USHORT nOld = pDView->GetHitTolerancePixel(); + pDView->SetHitTolerancePixel( 0 ); + if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) && + pObj->ISA(SwVirtFlyDrawObj) ) + { + SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); + rRect = pFly->Frm(); + + //Ziel darf natuerlich nicht gleich Source sein und es + //darf keine geschlossene Kette entstehen. + SwFrmFmt *pFmt = pFly->GetFmt(); + return GetDoc()->Chainable(rSource, *pFmt); + } + pDView->SetHitTolerancePixel( nOld ); + } + return SW_CHAIN_NOT_FOUND; +} +/* -----------------------------09.08.2002 07:40------------------------------ + + ---------------------------------------------------------------------------*/ +int SwFEShell::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest ) +{ + return GetDoc()->Chain(rSource, rDest); +} + +int SwFEShell::Chain( SwFrmFmt &rSource, const Point &rPt ) +{ + SwRect aDummy; + int nErr = Chainable( aDummy, rSource, rPt ); + if ( !nErr ) + { + StartAllAction(); + SdrObject* pObj; + SdrPageView* pPView; + SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView(); + const USHORT nOld = pDView->GetHitTolerancePixel(); + pDView->SetHitTolerancePixel( 0 ); + pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ); + pDView->SetHitTolerancePixel( nOld ); + SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); + + SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)pFly->GetFmt(); + GetDoc()->Chain(rSource, *pFmt); + EndAllAction(); + SetChainMarker(); + } + return nErr; +} + +void SwFEShell::Unchain( SwFrmFmt &rFmt ) +{ + StartAllAction(); + GetDoc()->Unchain(rFmt); + EndAllAction(); +} + + +void SwFEShell::HideChainMarker() +{ + if ( pChainFrom ) + { + delete pChainFrom; + pChainFrom = 0L; + } + if ( pChainTo ) + { + delete pChainTo; + pChainTo = 0L; + } +} + +void SwFEShell::SetChainMarker() +{ + BOOL bDelFrom = TRUE, + bDelTo = TRUE; + if ( IsFrmSelected() ) + { + SwFlyFrm *pFly = FindFlyFrm(); + + if ( pFly->GetPrevLink() ) + { + bDelFrom = FALSE; + const SwFrm *pPre = pFly->GetPrevLink(); + + Point aStart( pPre->Frm().Right(), pPre->Frm().Bottom()); + Point aEnd(pFly->Frm().Pos()); + + if ( !pChainFrom ) + { + pChainFrom = new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd ); + } + } + if ( pFly->GetNextLink() ) + { + bDelTo = FALSE; + const SwFlyFrm *pNxt = pFly->GetNextLink(); + + Point aStart( pFly->Frm().Right(), pFly->Frm().Bottom()); + Point aEnd(pNxt->Frm().Pos()); + + if ( !pChainTo ) + { + pChainTo = new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd ); + } + } + } + + if ( bDelFrom ) + { + delete pChainFrom, pChainFrom = 0; + } + + if ( bDelTo ) + { + delete pChainTo, pChainTo = 0; + } +} + +long SwFEShell::GetSectionWidth( SwFmt& rFmt ) const +{ + SwFrm *pFrm = GetCurrFrm(); + // Steht der Cursor z.Z. in einem SectionFrm? + if( pFrm && pFrm->IsInSct() ) + { + SwSectionFrm* pSect = pFrm->FindSctFrm(); + do + { + // Ist es der Gewuenschte? + if( pSect->GetRegisteredIn() == &rFmt ) + return pSect->Frm().Width(); + // fuer geschachtelte Bereiche + pSect = pSect->GetUpper()->FindSctFrm(); + } + while( pSect ); + } + SwClientIter aIter( rFmt ); + SwClient *pLast = aIter.GoStart(); + while ( pLast ) + { + if ( pLast->IsA( TYPE(SwFrm) ) ) + { + SwSectionFrm* pSct = (SwSectionFrm*)pLast; + if( !pSct->IsFollow() ) + return pSct->Frm().Width(); + } + pLast = aIter++; + } + return 0; +} +/* -----------------------------2002/06/24 15:07------------------------------ + + ---------------------------------------------------------------------------*/ +void SwFEShell::CreateDefaultShape( UINT16 /*SdrObjKind ?*/ eSdrObjectKind, const Rectangle& rRect, + USHORT nSlotId) +{ + SdrView* pDrawView = GetDrawView(); + SdrModel* pDrawModel = pDrawView->GetModel(); + SdrObject* pObj = SdrObjFactory::MakeNewObject( + SdrInventor, eSdrObjectKind, + 0L, pDrawModel); + + if(pObj) + { + Rectangle aRect(rRect); + if(OBJ_CARC == eSdrObjectKind || OBJ_CCUT == eSdrObjectKind) + { + // force quadratic + if(aRect.GetWidth() > aRect.GetHeight()) + { + aRect = Rectangle( + Point(aRect.Left() + ((aRect.GetWidth() - aRect.GetHeight()) / 2), aRect.Top()), + Size(aRect.GetHeight(), aRect.GetHeight())); + } + else + { + aRect = Rectangle( + Point(aRect.Left(), aRect.Top() + ((aRect.GetHeight() - aRect.GetWidth()) / 2)), + Size(aRect.GetWidth(), aRect.GetWidth())); + } + } + pObj->SetLogicRect(aRect); + + if(pObj->ISA(SdrCircObj)) + { + SfxItemSet aAttr(pDrawModel->GetItemPool()); + aAttr.Put(SdrCircStartAngleItem(9000)); + aAttr.Put(SdrCircEndAngleItem(0)); + pObj->SetMergedItemSet(aAttr); + } + else if(pObj->ISA(SdrPathObj)) + { + basegfx::B2DPolyPolygon aPoly; + + switch(eSdrObjectKind) + { + case OBJ_PATHLINE: + { + basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom())); + + const basegfx::B2DPoint aCenterBottom(aRect.Center().X(), aRect.Bottom()); + aInnerPoly.appendBezierSegment( + aCenterBottom, + aCenterBottom, + basegfx::B2DPoint(aRect.Center().X(), aRect.Center().Y())); + + const basegfx::B2DPoint aCenterTop(aRect.Center().X(), aRect.Top()); + aInnerPoly.appendBezierSegment( + aCenterTop, + aCenterTop, + basegfx::B2DPoint(aRect.Right(), aRect.Top())); + + aInnerPoly.setClosed(true); + aPoly.append(aInnerPoly); + } + break; + case OBJ_FREELINE: + { + basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom())); + + aInnerPoly.appendBezierSegment( + basegfx::B2DPoint(aRect.Left(), aRect.Top()), + basegfx::B2DPoint(aRect.Center().X(), aRect.Top()), + basegfx::B2DPoint(aRect.Center().X(), aRect.Center().Y())); + + aInnerPoly.appendBezierSegment( + basegfx::B2DPoint(aRect.Center().X(), aRect.Bottom()), + basegfx::B2DPoint(aRect.Right(), aRect.Bottom()), + basegfx::B2DPoint(aRect.Right(), aRect.Top())); + + aInnerPoly.append(basegfx::B2DPoint(aRect.Right(), aRect.Bottom())); + aInnerPoly.setClosed(true); + aPoly.append(aInnerPoly); + } + break; + case OBJ_POLY: + case OBJ_PLIN: + { + basegfx::B2DPolygon aInnerPoly; + sal_Int32 nWdt(aRect.GetWidth()); + sal_Int32 nHgt(aRect.GetHeight()); + + aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom())); + aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 30) / 100, aRect.Top() + (nHgt * 70) / 100)); + aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Top() + (nHgt * 15) / 100)); + aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 65) / 100, aRect.Top())); + aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + nWdt, aRect.Top() + (nHgt * 30) / 100)); + aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 50) / 100)); + aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 75) / 100)); + aInnerPoly.append(basegfx::B2DPoint(aRect.Bottom(), aRect.Right())); + + if(OBJ_PLIN == eSdrObjectKind) + { + aInnerPoly.append(basegfx::B2DPoint(aRect.Center().X(), aRect.Bottom())); + } + else + { + aInnerPoly.setClosed(true); + } + + aPoly.append(aInnerPoly); + } + break; + case OBJ_LINE : + { + sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2); + basegfx::B2DPolygon aTempPoly; + aTempPoly.append(basegfx::B2DPoint(aRect.TopLeft().X(), nYMiddle)); + aTempPoly.append(basegfx::B2DPoint(aRect.BottomRight().X(), nYMiddle)); + aPoly.append(aTempPoly); + } + break; + } + + ((SdrPathObj*)pObj)->SetPathPoly(aPoly); + } + else if(pObj->ISA(SdrCaptionObj)) + { + BOOL bVerticalText = ( SID_DRAW_TEXT_VERTICAL == nSlotId || + SID_DRAW_CAPTION_VERTICAL == nSlotId ); + ((SdrTextObj*)pObj)->SetVerticalWriting(bVerticalText); + if(bVerticalText) + { + SfxItemSet aSet(pObj->GetMergedItemSet()); + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + pObj->SetMergedItemSet(aSet); + } + + ((SdrCaptionObj*)pObj)->SetLogicRect(aRect); + ((SdrCaptionObj*)pObj)->SetTailPos( + aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2)); + } + else if(pObj->ISA(SdrTextObj)) + { + SdrTextObj* pText = (SdrTextObj*)pObj; + pText->SetLogicRect(aRect); + + sal_Bool bVertical = (SID_DRAW_TEXT_VERTICAL == nSlotId); + sal_Bool bMarquee = (SID_DRAW_TEXT_MARQUEE == nSlotId); + + pText->SetVerticalWriting(bVertical); + + if(bVertical) + { + SfxItemSet aSet(pDrawModel->GetItemPool()); + aSet.Put(SdrTextAutoGrowWidthItem(TRUE)); + aSet.Put(SdrTextAutoGrowHeightItem(FALSE)); + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + pText->SetMergedItemSet(aSet); + } + + if(bMarquee) + { + SfxItemSet aSet(pDrawModel->GetItemPool(), SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST); + aSet.Put( SdrTextAutoGrowWidthItem( FALSE ) ); + aSet.Put( SdrTextAutoGrowHeightItem( FALSE ) ); + aSet.Put( SdrTextAniKindItem( SDRTEXTANI_SLIDE ) ); + aSet.Put( SdrTextAniDirectionItem( SDRTEXTANI_LEFT ) ); + aSet.Put( SdrTextAniCountItem( 1 ) ); + aSet.Put( SdrTextAniAmountItem( (INT16)GetWin()->PixelToLogic(Size(2,1)).Width()) ); + pObj->SetMergedItemSetAndBroadcast(aSet); + } + } + SdrPageView* pPageView = pDrawView->GetSdrPageView(); + pDrawView->InsertObjectAtView(pObj, *pPageView); + } + ImpEndCreate(); +} + +/** SwFEShell::GetShapeBackgrd + + OD 02.09.2002 for #102450#: + method determines background color of the page the selected drawing + object is on and returns this color. + If no color is found, because no drawing object is selected or ..., + color COL_BLACK (default color on constructing object of class Color) + is returned. + + @author OD + + @returns an object of class Color +*/ +const Color SwFEShell::GetShapeBackgrd() const +{ + Color aRetColor; + + // check, if a draw view exists + ASSERT( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!"); + if( Imp()->GetDrawView() ) + { + // determine list of selected objects + const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + // check, if exactly one object is selected. + ASSERT( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!"); + if ( pMrkList->GetMarkCount() == 1) + { + // get selected object + const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + // check, if selected object is a shape (drawing object) + ASSERT( !pSdrObj->ISA(SwVirtFlyDrawObj), "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!"); + if ( !pSdrObj->ISA(SwVirtFlyDrawObj) ) + { + // determine page frame of the frame the shape is anchored. + const SwFrm* pAnchorFrm = + static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrm( pSdrObj ); + ASSERT( pAnchorFrm, "inconsistent modell - no anchor at shape!"); + if ( pAnchorFrm ) + { + const SwPageFrm* pPageFrm = pAnchorFrm->FindPageFrm(); + ASSERT( pPageFrm, "inconsistent modell - no page!"); + if ( pPageFrm ) + { + aRetColor = pPageFrm->GetDrawBackgrdColor(); + } + } + } + } + } + + return aRetColor; +} + +/** Is default horizontal text direction for selected drawing object right-to-left + + OD 09.12.2002 #103045# + Because drawing objects only painted for each page only, the default + horizontal text direction of a drawing object is given by the corresponding + page property. + + @author OD + + @returns boolean, indicating, if the horizontal text direction of the + page, the selected drawing object is on, is right-to-left. +*/ +bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const +{ + bool bRet = false; + + // check, if a draw view exists + ASSERT( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!"); + if( Imp()->GetDrawView() ) + { + // determine list of selected objects + const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList(); + // check, if exactly one object is selected. + ASSERT( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!"); + if ( pMrkList->GetMarkCount() == 1) + { + // get selected object + const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj(); + // check, if selected object is a shape (drawing object) + ASSERT( !pSdrObj->ISA(SwVirtFlyDrawObj), "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!"); + if ( !pSdrObj->ISA(SwVirtFlyDrawObj) ) + { + // determine page frame of the frame the shape is anchored. + const SwFrm* pAnchorFrm = + static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrm( pSdrObj ); + ASSERT( pAnchorFrm, "inconsistent modell - no anchor at shape!"); + if ( pAnchorFrm ) + { + const SwPageFrm* pPageFrm = pAnchorFrm->FindPageFrm(); + ASSERT( pPageFrm, "inconsistent modell - no page!"); + if ( pPageFrm ) + { + bRet = pPageFrm->IsRightToLeft() ? true : false; + } + } + } + } + } + + return bRet; +} +/* -----------------20.03.2003 14:35----------------- + + --------------------------------------------------*/ +Point SwFEShell::GetRelativePagePosition(const Point& rDocPos) +{ + Point aRet(-1, -1); + const SwFrm *pPage = GetLayout()->Lower(); + while ( pPage && !pPage->Frm().IsInside( rDocPos ) ) + { + pPage = pPage->GetNext(); + } + if(pPage) + { + aRet = rDocPos - pPage->Frm().TopLeft(); + } + return aRet; +} + diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx new file mode 100644 index 000000000000..ad2e077e5d7c --- /dev/null +++ b/sw/source/core/frmedt/fetab.cxx @@ -0,0 +1,2593 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <hintids.hxx> + +#include <tools/errinf.hxx> +#include <vcl/svapp.hxx> +#include <basegfx/vector/b2dvector.hxx> +#ifndef _SVX_SVXIDS_HRC +#include <svx/svxids.hrc> +#endif +#include <editeng/protitem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svtools/ruler.hxx> +#include <swwait.hxx> +#include <fmtfsize.hxx> +#include <fmtornt.hxx> +#include <frmatr.hxx> +#include <docary.hxx> +#include <fesh.hxx> +#include <doc.hxx> +#include <cntfrm.hxx> +#include <rootfrm.hxx> +#include <pagefrm.hxx> +#include <tabfrm.hxx> +#include <rowfrm.hxx> +#include <cellfrm.hxx> +#include <flyfrm.hxx> +#include <dflyobj.hxx> +#include <swtable.hxx> +#include <swddetbl.hxx> +#include <ndtxt.hxx> +#include <calc.hxx> +#include <tabcol.hxx> +#include <cellatr.hxx> +#include <pam.hxx> +#include <viscrs.hxx> +#include <tblsel.hxx> +#include <swtblfmt.hxx> +#include <swerror.h> +#include <swundo.hxx> +#include <frmtool.hxx> + +#include <node.hxx> // #i23726# +// OD 2004-05-24 #i28701# +#include <sortedobjs.hxx> + +using namespace ::com::sun::star; + + +//siehe auch swtable.cxx +#define COLFUZZY 20L + +inline BOOL IsSame( long nA, long nB ) { return Abs(nA-nB) <= COLFUZZY; } +inline BOOL IsNear( long nA, long nB, long nTolerance ) { return Abs( nA - nB ) <= nTolerance; } + +// table column cache +SwTabCols *pLastCols = 0; +const SwTable *pColumnCacheLastTable = 0; +const SwTabFrm *pColumnCacheLastTabFrm = 0; +const SwFrm *pColumnCacheLastCellFrm = 0; + +// table row cache +SwTabCols *pLastRows = 0; +const SwTable *pRowCacheLastTable = 0; +const SwTabFrm *pRowCacheLastTabFrm = 0; +const SwFrm *pRowCacheLastCellFrm = 0; + + +class TblWait +{ + SwWait *pWait; +public: + TblWait( USHORT nCnt, SwFrm *pFrm, SwDocShell &rDocShell, USHORT nCnt2 = 0); + ~TblWait() { delete pWait; } +}; + +TblWait::TblWait( USHORT nCnt, SwFrm *pFrm, SwDocShell &rDocShell, USHORT nCnt2): + pWait( 0 ) +{ + BOOL bWait = 20 < nCnt || 20 < nCnt2 || (pFrm && + 20 < pFrm->ImplFindTabFrm()->GetTable()->GetTabLines().Count()); + if( bWait ) + pWait = new SwWait( rDocShell, TRUE ); +} + + +void SwFEShell::ParkCursorInTab() +{ + SwCursor * pSwCrsr = GetSwCrsr(); + + ASSERT(pSwCrsr, "no SwCursor"); + + SwPosition aStartPos = *pSwCrsr->GetPoint(), aEndPos = aStartPos; + + SwCursor * pTmpCrsr = (SwCursor *) pSwCrsr; + + /* Search least and greatest position in current cursor ring. + */ + do + { + const SwPosition * pPt = pTmpCrsr->GetPoint(), + * pMk = pTmpCrsr->GetMark(); + + if (*pPt < aStartPos) + aStartPos = *pPt; + + if (*pPt > aEndPos) + aEndPos = *pPt; + + if (*pMk < aStartPos) + aStartPos = *pMk; + + if (*pMk > aEndPos) + aEndPos = *pMk; + + pTmpCrsr = (SwCursor *) pTmpCrsr->GetNext(); + } + while (pTmpCrsr != pSwCrsr); + + KillPams(); + + /* @@@ semantic: SwCursor::operator=() is not implemented @@@ */ + + /* Set cursor to end of selection to ensure IsLastCellInRow works + properly. */ + { + SwCursor aTmpCrsr( aEndPos, 0, false ); + *pSwCrsr = aTmpCrsr; + } + + /* Move the cursor out of the columns to delete and stay in the + same row. If the table has only one column the cursor will + stay in the row and the shell will take care of it. */ + if (IsLastCellInRow()) + { + /* If the cursor is in the last row of the table, first + try to move it to the previous cell. If that fails move + it to the next cell. */ + + { + SwCursor aTmpCrsr( aStartPos, 0, false ); + *pSwCrsr = aTmpCrsr; + } + + if (! pSwCrsr->GoPrevCell()) + { + SwCursor aTmpCrsr( aEndPos, 0, false ); + *pSwCrsr = aTmpCrsr; + pSwCrsr->GoNextCell(); + } + } + else + { + /* If the cursor is not in the last row of the table, first + try to move it to the next cell. If that fails move it + to the previous cell. */ + + { + SwCursor aTmpCrsr( aEndPos, 0, false ); + *pSwCrsr = aTmpCrsr; + } + + if (! pSwCrsr->GoNextCell()) + { + SwCursor aTmpCrsr( aStartPos, 0, false ); + *pSwCrsr = aTmpCrsr; + pSwCrsr->GoPrevCell(); + } + } +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : InsertRow(), InsertCol +#* Datum : MA 03. May. 93 +#* Update : MA 19. Apr. 95 +#***********************************************************************/ +BOOL SwFEShell::InsertRow( USHORT nCnt, BOOL bBehind ) +{ + // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + StartAllAction(); + + // lasse ueber das Layout die Boxen suchen + SwSelBoxes aBoxes; + GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW ); + + TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() ); + + BOOL bRet = FALSE; + if ( aBoxes.Count() ) + bRet = GetDoc()->InsertRow( aBoxes, nCnt, bBehind ); + + EndAllActionAndCall(); + return bRet; +} + +BOOL SwFEShell::InsertCol( USHORT nCnt, BOOL bBehind ) +{ + // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + + if( !CheckSplitCells( *this, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) ) + { + ErrorHandler::HandleError( ERR_TBLINSCOL_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + StartAllAction(); + // lasse ueber das Layout die Boxen suchen + SwSelBoxes aBoxes; + GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL ); + + TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() ); + + BOOL bRet = FALSE; + if( aBoxes.Count() ) + bRet = GetDoc()->InsertCol( aBoxes, nCnt, bBehind ); + + EndAllActionAndCall(); + return bRet; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : DeleteRow(), DeleteCol() +#* Datum : MA 03. May. 93 +#* Update : MA 19. Apr. 95 +#***********************************************************************/ + +/** + Determines if the current cursor is in the last row of the table. +*/ +BOOL SwFEShell::IsLastCellInRow() const +{ + SwTabCols aTabCols; + GetTabCols( aTabCols ); + BOOL bResult = FALSE; + + if (IsTableRightToLeft()) + /* If the table is right-to-left the last row is the most left one. */ + bResult = 0 == GetCurTabColNum(); + else + /* If the table is left-to-right the last row is the most right one. */ + bResult = aTabCols.Count() == GetCurTabColNum(); + + return bResult; +} + +BOOL SwFEShell::DeleteCol() +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + StartAllAction(); + + // lasse ueber das Layout die Boxen suchen + BOOL bRet; + SwSelBoxes aBoxes; + GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL ); + if ( aBoxes.Count() ) + { + TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() ); + + // die Crsr muessen noch aus dem Loesch Bereich entfernt + // werden. Setze sie immer hinter/auf die Tabelle; ueber die + // Dokument-Position werden sie dann immer an die alte Position gesetzt. + while( !pFrm->IsCellFrm() ) + pFrm = pFrm->GetUpper(); + + ParkCursorInTab(); + + // dann loesche doch die Spalten + StartUndo(UNDO_COL_DELETE); + bRet = GetDoc()->DeleteRowCol( aBoxes, true ); + EndUndo(UNDO_COL_DELETE); + + } + else + bRet = FALSE; + + EndAllActionAndCall(); + return bRet; +} + +BOOL SwFEShell::DeleteRow() +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + StartAllAction(); + + // lasse ueber das Layout die Boxen suchen + BOOL bRet; + SwSelBoxes aBoxes; + GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW ); + + if( aBoxes.Count() ) + { + TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() ); + + // die Crsr aus dem Loeschbereich entfernen. + // Der Cursor steht danach: + // - es folgt noch eine Zeile, in dieser + // - vorher steht noch eine Zeile, in dieser + // - sonst immer dahinter + { + SwTableNode* pTblNd = ((SwCntntFrm*)pFrm)->GetNode()->FindTableNode(); + + // suche alle Boxen / Lines + _FndBox aFndBox( 0, 0 ); + { + _FndPara aPara( aBoxes, &aFndBox ); + pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); + } + + if( !aFndBox.GetLines().Count() ) + { + EndAllActionAndCall(); + return FALSE; + } + + KillPams(); + + _FndBox* pFndBox = &aFndBox; + while( 1 == pFndBox->GetLines().Count() && + 1 == pFndBox->GetLines()[0]->GetBoxes().Count() ) + { + _FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0]; + if( pTmp->GetBox()->GetSttNd() ) + break; // das ist sonst zu weit + pFndBox = pTmp; + } + + SwTableLine* pDelLine = pFndBox->GetLines()[ + pFndBox->GetLines().Count()-1 ]->GetLine(); + SwTableBox* pDelBox = pDelLine->GetTabBoxes()[ + pDelLine->GetTabBoxes().Count() - 1 ]; + while( !pDelBox->GetSttNd() ) + { + SwTableLine* pLn = pDelBox->GetTabLines()[ + pDelBox->GetTabLines().Count()-1 ]; + pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ]; + } + SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(), + pDelBox, TRUE ); + while( pNextBox && + pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) + pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox ); + + if( !pNextBox ) // keine nachfolgende? dann die vorhergehende + { + pDelLine = pFndBox->GetLines()[ 0 ]->GetLine(); + pDelBox = pDelLine->GetTabBoxes()[ 0 ]; + while( !pDelBox->GetSttNd() ) + pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0]; + pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(), + pDelBox, TRUE ); + while( pNextBox && + pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) + pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox ); + } + + ULONG nIdx; + if( pNextBox ) // dann den Cursor hier hinein + nIdx = pNextBox->GetSttIdx() + 1; + else // ansonsten hinter die Tabelle + nIdx = pTblNd->EndOfSectionIndex() + 1; + + SwNodeIndex aIdx( GetDoc()->GetNodes(), nIdx ); + SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); + if( !pCNd ) + pCNd = GetDoc()->GetNodes().GoNext( &aIdx ); + + if( pCNd ) + { + SwPaM* pPam = GetCrsr(); + pPam->GetPoint()->nNode = aIdx; + pPam->GetPoint()->nContent.Assign( pCNd, 0 ); + pPam->SetMark(); // beide wollen etwas davon haben + pPam->DeleteMark(); + } + } + + // dann loesche doch die Zeilen + StartUndo(UNDO_ROW_DELETE); + bRet = GetDoc()->DeleteRowCol( aBoxes ); + EndUndo(UNDO_ROW_DELETE); + } + else + bRet = FALSE; + + EndAllActionAndCall(); + return bRet; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : MergeTab(), SplitTab() +#* Datum : MA 03. May. 93 +#* Update : MA 19. Apr. 95 +#***********************************************************************/ + +USHORT SwFEShell::MergeTab() +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + USHORT nRet = TBLMERGE_NOSELECTION; + if( IsTableMode() ) + { + SwShellTableCrsr* pTableCrsr = GetTableCrsr(); + const SwTableNode* pTblNd = pTableCrsr->GetNode()->FindTableNode(); + if( pTblNd->GetTable().ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + } + else + { + SET_CURR_SHELL( this ); + StartAllAction(); + + TblWait( pTableCrsr->GetBoxesCount(), 0, *GetDoc()->GetDocShell(), + pTblNd->GetTable().GetTabLines().Count() ); + + nRet = GetDoc()->MergeTbl( *pTableCrsr ); + + KillPams(); + + EndAllActionAndCall(); + } + } + return nRet; +} + +BOOL SwFEShell::SplitTab( BOOL bVert, USHORT nCnt, BOOL bSameHeight ) +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + + if( bVert && !CheckSplitCells( *this, nCnt + 1 ) ) + { + ErrorHandler::HandleError( ERR_TBLSPLIT_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + StartAllAction(); + // lasse ueber das Layout die Boxen suchen + BOOL bRet; + SwSelBoxes aBoxes; + GetTblSel( *this, aBoxes ); + if( aBoxes.Count() ) + { + TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() ); + + // dann loesche doch die Spalten + bRet = GetDoc()->SplitTbl( aBoxes, bVert, nCnt, bSameHeight ); + + DELETEZ( pLastCols ); + DELETEZ( pLastRows ); + } + else + bRet = FALSE; + EndAllActionAndCall(); + return bRet; +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : _GetTabCols +#* Datum : MA 30. Nov. 95 +#* Update : MA 08. Jan. 97 +#***********************************************************************/ +void SwFEShell::_GetTabCols( SwTabCols &rToFill, const SwFrm *pBox ) const +{ + const SwTabFrm *pTab = pBox->FindTabFrm(); + if ( pLastCols ) + { + //Paar Kleinigkeiten muessen wir schon noch sicherstellen + BOOL bDel = TRUE; + if ( pColumnCacheLastTable == pTab->GetTable() ) + { + bDel = FALSE; + SWRECTFN( pTab ) + + const SwPageFrm* pPage = pTab->FindPageFrm(); + const ULONG nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() - + (pPage->Frm().*fnRect->fnGetLeft)(); + const ULONG nRightMax = (pTab->Frm().*fnRect->fnGetRight)() - + (pPage->Frm().*fnRect->fnGetLeft)(); + + if ( pColumnCacheLastTabFrm != pTab ) + { + //Wenn der TabFrm gewechselt hat, brauchen wir bei gleicher + //Breite nur ein wenig shiften. + SWRECTFNX( pColumnCacheLastTabFrm ) + if( (pColumnCacheLastTabFrm->Frm().*fnRectX->fnGetWidth)() == + (pTab->Frm().*fnRect->fnGetWidth)() ) + { + pLastCols->SetLeftMin( nLeftMin ); + + //ASSERT( bVert || + // pLastCols->GetLeftMin() == (pTab->Frm().*fnRect->fnGetLeft)(), + // "GetTabCols: wrong result" ) + + pColumnCacheLastTabFrm = pTab; + } + else + bDel = TRUE; + } + + if ( !bDel && + pLastCols->GetLeftMin () == (USHORT)nLeftMin && + pLastCols->GetLeft () == (USHORT)(pTab->Prt().*fnRect->fnGetLeft)() && + pLastCols->GetRight () == (USHORT)(pTab->Prt().*fnRect->fnGetRight)()&& + pLastCols->GetRightMax() == (USHORT)nRightMax - pLastCols->GetLeftMin() ) + { + if ( pColumnCacheLastCellFrm != pBox ) + { + pTab->GetTable()->GetTabCols( *pLastCols, + ((SwCellFrm*)pBox)->GetTabBox(), TRUE); + pColumnCacheLastCellFrm = pBox; + } + rToFill = *pLastCols; + } + else + bDel = TRUE; + } + if ( bDel ) + DELETEZ(pLastCols); + } + if ( !pLastCols ) + { + GetDoc()->GetTabCols( rToFill, 0, (SwCellFrm*)pBox ); + + pLastCols = new SwTabCols( rToFill ); + pColumnCacheLastTable = pTab->GetTable(); + pColumnCacheLastTabFrm = pTab; + pColumnCacheLastCellFrm= pBox; + } + +#if OSL_DEBUG_LEVEL > 1 + SwTabColsEntry aEntry; + for ( USHORT i = 0; i < rToFill.Count(); ++i ) + { + aEntry = rToFill.GetEntry( i ); + (void)aEntry; + } +#endif +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : _GetTabRows +#* Datum : FME 2004-01-14 +#* Update : +#***********************************************************************/ +void SwFEShell::_GetTabRows( SwTabCols &rToFill, const SwFrm *pBox ) const +{ + const SwTabFrm *pTab = pBox->FindTabFrm(); + if ( pLastRows ) + { + //Paar Kleinigkeiten muessen wir schon noch sicherstellen + BOOL bDel = TRUE; + if ( pRowCacheLastTable == pTab->GetTable() ) + { + bDel = FALSE; + SWRECTFN( pTab ) + const SwPageFrm* pPage = pTab->FindPageFrm(); + const long nLeftMin = ( bVert ? + pTab->GetPrtLeft() - pPage->Frm().Left() : + pTab->GetPrtTop() - pPage->Frm().Top() ); + const long nLeft = bVert ? LONG_MAX : 0; + const long nRight = (pTab->Prt().*fnRect->fnGetHeight)(); + const long nRightMax = bVert ? nRight : LONG_MAX; + + if ( pRowCacheLastTabFrm != pTab || + pRowCacheLastCellFrm != pBox ) + bDel = TRUE; + + if ( !bDel && + pLastRows->GetLeftMin () == nLeftMin && + pLastRows->GetLeft () == nLeft && + pLastRows->GetRight () == nRight && + pLastRows->GetRightMax() == nRightMax ) + { + rToFill = *pLastRows; + } + else + bDel = TRUE; + } + if ( bDel ) + DELETEZ(pLastRows); + } + if ( !pLastRows ) + { + GetDoc()->GetTabRows( rToFill, 0, (SwCellFrm*)pBox ); + + pLastRows = new SwTabCols( rToFill ); + pRowCacheLastTable = pTab->GetTable(); + pRowCacheLastTabFrm = pTab; + pRowCacheLastCellFrm= pBox; + } +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetTabCols(), GetTabCols() +#* Datum : MA 03. May. 93 +#* Update : MA 18. May. 93 +#***********************************************************************/ +void SwFEShell::SetTabCols( const SwTabCols &rNew, BOOL bCurRowOnly ) +{ + SwFrm *pBox = GetCurrFrm(); + if( !pBox || !pBox->IsInTab() ) + return; + + SET_CURR_SHELL( this ); + StartAllAction(); + + do { + pBox = pBox->GetUpper(); + } while ( !pBox->IsCellFrm() ); + + GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox ); + EndAllActionAndCall(); +} + +void SwFEShell::GetTabCols( SwTabCols &rToFill ) const +{ + const SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return; + do + { pFrm = pFrm->GetUpper(); + } while ( !pFrm->IsCellFrm() ); + + _GetTabCols( rToFill, pFrm ); +} + +/*-- 19.01.2004 08:56:42--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void SwFEShell::GetTabRows( SwTabCols &rToFill ) const +{ + const SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return; + do + { pFrm = pFrm->GetUpper(); + } while ( !pFrm->IsCellFrm() ); + + _GetTabRows( rToFill, pFrm ); +} +/*-- 19.01.2004 08:56:44--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void SwFEShell::SetTabRows( const SwTabCols &rNew, BOOL bCurColOnly ) +{ + SwFrm *pBox = GetCurrFrm(); + if( !pBox || !pBox->IsInTab() ) + return; + + SET_CURR_SHELL( this ); + StartAllAction(); + + do { + pBox = pBox->GetUpper(); + } while ( !pBox->IsCellFrm() ); + + GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox ); + EndAllActionAndCall(); +} +/*-- 19.01.2004 08:59:45--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void SwFEShell::GetMouseTabRows( SwTabCols &rToFill, const Point &rPt ) const +{ + const SwFrm *pBox = GetBox( rPt ); + if ( pBox ) + _GetTabRows( rToFill, pBox ); +} +/*-- 19.01.2004 08:59:45--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void SwFEShell::SetMouseTabRows( const SwTabCols &rNew, BOOL bCurColOnly, const Point &rPt ) +{ + const SwFrm *pBox = GetBox( rPt ); + if( pBox ) + { + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox ); + EndAllActionAndCall(); + } +} + +/*********************************************************************** + * Class : SwFEShell + * Methoden : SetRowSplit(), GetRowSplit() + * Datum : FME 13.11.2003 + ***********************************************************************/ + +void SwFEShell::SetRowSplit( const SwFmtRowSplit& rNew ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetRowSplit( *getShellCrsr( false ), rNew ); + EndAllActionAndCall(); +} + +void SwFEShell::GetRowSplit( SwFmtRowSplit*& rpSz ) const +{ + GetDoc()->GetRowSplit( *getShellCrsr( false ), rpSz ); +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetRowHeight(), GetRowHeight() +#* Datum : MA 17. May. 93 +#* Update : JP 29.04.98 +#***********************************************************************/ + +void SwFEShell::SetRowHeight( const SwFmtFrmSize &rNew ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetRowHeight( *getShellCrsr( false ), rNew ); + EndAllActionAndCall(); +} + +/****************************************************************************** + * SwTwips SwFEShell::GetRowHeight() const + ******************************************************************************/ +void SwFEShell::GetRowHeight( SwFmtFrmSize *& rpSz ) const +{ + GetDoc()->GetRowHeight( *getShellCrsr( false ), rpSz ); +} + +BOOL SwFEShell::BalanceRowHeight( BOOL bTstOnly ) +{ + SET_CURR_SHELL( this ); + if( !bTstOnly ) + StartAllAction(); + BOOL bRet = GetDoc()->BalanceRowHeight( *getShellCrsr( false ), bTstOnly ); + if( !bTstOnly ) + EndAllActionAndCall(); + return bRet; +} + +/****************************************************************************** + * void SwFEShell::SetRowBackground() + ******************************************************************************/ +void SwFEShell::SetRowBackground( const SvxBrushItem &rNew ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetRowBackground( *getShellCrsr( false ), rNew ); + EndAllActionAndCall(); +} + +/****************************************************************************** + * SwTwips SwFEShell::GetRowBackground() const + ******************************************************************************/ +BOOL SwFEShell::GetRowBackground( SvxBrushItem &rToFill ) const +{ + return GetDoc()->GetRowBackground( *getShellCrsr( false ), rToFill ); +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetTabBorders(), GetTabBorders() +#* Datum : MA 18. May. 93 +#* Update : JP 29.04.98 +#***********************************************************************/ + +void SwFEShell::SetTabBorders( const SfxItemSet& rSet ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetTabBorders( *getShellCrsr( false ), rSet ); + EndAllActionAndCall(); +} + +void SwFEShell::SetTabLineStyle( const Color* pColor, BOOL bSetLine, + const SvxBorderLine* pBorderLine ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetTabLineStyle( *getShellCrsr( false ), + pColor, bSetLine, pBorderLine ); + EndAllActionAndCall(); +} + +void SwFEShell::GetTabBorders( SfxItemSet& rSet ) const +{ + GetDoc()->GetTabBorders( *getShellCrsr( false ), rSet ); +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetBoxBackground(), GetBoxBackground() +#* Datum : MA 01. Jun. 93 +#* Update : MA 03. Jul. 96 +#***********************************************************************/ +void SwFEShell::SetBoxBackground( const SvxBrushItem &rNew ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew ); + EndAllActionAndCall(); +} + +BOOL SwFEShell::GetBoxBackground( SvxBrushItem &rToFill ) const +{ + return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill ); +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetBoxDirection(), GetBoxDirection() +#* Datum : FME 2004-02-03 +#* Update : FME 2004-02-03 +#***********************************************************************/ +void SwFEShell::SetBoxDirection( const SvxFrameDirectionItem& rNew ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew ); + EndAllActionAndCall(); +} + +BOOL SwFEShell::GetBoxDirection( SvxFrameDirectionItem& rToFill ) const +{ + return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill ); +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetBoxAlign, SetBoxAlign +#* Datum : MA 18. Dec. 96 +#* Update : JP 29.04.98 +#***********************************************************************/ +void SwFEShell::SetBoxAlign( USHORT nAlign ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetBoxAlign( *getShellCrsr( false ), nAlign ); + EndAllActionAndCall(); +} + +USHORT SwFEShell::GetBoxAlign() const +{ + return GetDoc()->GetBoxAlign( *getShellCrsr( false ) ); +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : SetTabBackground(), GetTabBackground() +#* Datum : MA 08. Jul. 96 +#* Update : MA 08. Jul. 96 +#***********************************************************************/ +void SwFEShell::SetTabBackground( const SvxBrushItem &rNew ) +{ + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return; + + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetAttr( rNew, *pFrm->ImplFindTabFrm()->GetFmt() ); + EndAllAction(); //Kein Call, denn es veraendert sich nichts! + GetDoc()->SetModified(); +} + +void SwFEShell::GetTabBackground( SvxBrushItem &rToFill ) const +{ + SwFrm *pFrm = GetCurrFrm(); + if( pFrm && pFrm->IsInTab() ) + rToFill = pFrm->ImplFindTabFrm()->GetFmt()->GetBackground(); +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : HasWholeTabSelection() +#* Datum : MA 18. May. 93 +#* Update : MA 20. Jul. 93 +#***********************************************************************/ +BOOL SwFEShell::HasWholeTabSelection() const +{ + //Ist die ganze Tabelle Selektiert? + if ( IsTableMode() ) + { + SwSelBoxes aBoxes; + ::GetTblSelCrs( *this, aBoxes ); + if( aBoxes.Count() ) + { + const SwTableNode *pTblNd = IsCrsrInTbl(); + return ( pTblNd && aBoxes[0]->GetSttIdx()-1 == pTblNd-> + EndOfSectionNode()->StartOfSectionIndex() && + aBoxes[aBoxes.Count()-1]->GetSttNd()->EndOfSectionIndex()+1 + == pTblNd->EndOfSectionIndex() ); + } + } + return FALSE; +} + +BOOL SwFEShell::HasBoxSelection() const +{ + if(!IsCrsrInTbl()) + return FALSE; + //Ist die ganze Tabelle Selektiert? + if( IsTableMode() ) + return TRUE; + SwPaM* pPam = GetCrsr(); + // leere Boxen gelten auch ohne Selektion als selektiert +// if( !pPam->HasMark() ) +// return FALSE; + BOOL bChg = FALSE; + if( pPam->GetPoint() == pPam->End()) + { + bChg = TRUE; + pPam->Exchange(); + } + SwNode* pNd; + if( pPam->GetPoint()->nNode.GetIndex() -1 == + ( pNd = pPam->GetNode())->StartOfSectionIndex() && + !pPam->GetPoint()->nContent.GetIndex() && + pPam->GetMark()->nNode.GetIndex() + 1 == + pNd->EndOfSectionIndex()) + { + SwNodeIndex aIdx( *pNd->EndOfSectionNode(), -1 ); + SwCntntNode* pCNd = GetDoc()->GetNodes()[ aIdx ]->GetCntntNode(); + if( !pCNd ) + { + pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx ); + ASSERT( pCNd, "kein ContentNode in der Box ??" ); + } + if( pPam->GetMark()->nContent == pCNd->Len() ) + { + if( bChg ) + pPam->Exchange(); + return TRUE; + } + } + if( bChg ) + pPam->Exchange(); + return FALSE; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : ProtectCells(), UnProtectCells() +#* Datum : MA 20. Jul. 93 +#* Update : JP 25. Sep. 93 +#***********************************************************************/ +void SwFEShell::ProtectCells() +{ + SvxProtectItem aProt( RES_PROTECT ); + aProt.SetCntntProtect( TRUE ); + + SET_CURR_SHELL( this ); + StartAllAction(); + + GetDoc()->SetBoxAttr( *getShellCrsr( false ), aProt ); + + if( !IsCrsrReadonly() ) + { + if( IsTableMode() ) + ClearMark(); + ParkCursorInTab(); + } + EndAllActionAndCall(); +} + +// die Tabellenselektion aufheben +void SwFEShell::UnProtectCells() +{ + SET_CURR_SHELL( this ); + StartAllAction(); + + SwSelBoxes aBoxes; + if( IsTableMode() ) + ::GetTblSelCrs( *this, aBoxes ); + else + { + SwFrm *pFrm = GetCurrFrm(); + do { + pFrm = pFrm->GetUpper(); + } while ( pFrm && !pFrm->IsCellFrm() ); + if( pFrm ) + { + SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); + aBoxes.Insert( pBox ); + } + } + + if( aBoxes.Count() ) + GetDoc()->UnProtectCells( aBoxes ); + + EndAllActionAndCall(); +} + +void SwFEShell::UnProtectTbls() +{ + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->UnProtectTbls( *GetCrsr() ); + EndAllActionAndCall(); +} + +BOOL SwFEShell::HasTblAnyProtection( const String* pTblName, + BOOL* pFullTblProtection ) +{ + return GetDoc()->HasTblAnyProtection( GetCrsr()->GetPoint(), pTblName, + pFullTblProtection ); +} + +BOOL SwFEShell::CanUnProtectCells() const +{ + BOOL bUnProtectAvailable = FALSE; + const SwTableNode *pTblNd = IsCrsrInTbl(); + if( pTblNd && !pTblNd->IsProtect() ) + { + SwSelBoxes aBoxes; + if( IsTableMode() ) + ::GetTblSelCrs( *this, aBoxes ); + else + { + SwFrm *pFrm = GetCurrFrm(); + do { + pFrm = pFrm->GetUpper(); + } while ( pFrm && !pFrm->IsCellFrm() ); + if( pFrm ) + { + SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); + aBoxes.Insert( pBox ); + } + } + if( aBoxes.Count() ) + bUnProtectAvailable = ::HasProtectedCells( aBoxes ); + } + return bUnProtectAvailable; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : GetRowsToRepeat(), SetRowsToRepeat() +#***********************************************************************/ +USHORT SwFEShell::GetRowsToRepeat() const +{ + const SwFrm *pFrm = GetCurrFrm(); + const SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0; + if( pTab ) + return pTab->GetTable()->GetRowsToRepeat(); + return 0; +} + +void SwFEShell::SetRowsToRepeat( USHORT nSet ) +{ + SwFrm *pFrm = GetCurrFrm(); + SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0; + if( pTab && pTab->GetTable()->GetRowsToRepeat() != nSet ) + { + SwWait aWait( *GetDoc()->GetDocShell(), TRUE ); + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetRowsToRepeat( *pTab->GetTable(), nSet ); + EndAllActionAndCall(); + } +} +/*-- 30.06.2004 08:46:35--------------------------------------------------- + returns the number of rows consecutively selected from top + -----------------------------------------------------------------------*/ +USHORT lcl_GetRowNumber( const SwPosition& rPos ) +{ + USHORT nRet = USHRT_MAX; + Point aTmpPt; + const SwCntntNode *pNd; + const SwCntntFrm *pFrm; + + if( 0 != ( pNd = rPos.nNode.GetNode().GetCntntNode() )) + pFrm = pNd->GetFrm( &aTmpPt, &rPos, FALSE ); + else + pFrm = 0; + + if ( pFrm && pFrm->IsInTab() ) + { + const SwFrm* pRow = pFrm->GetUpper(); + while ( !pRow->GetUpper()->IsTabFrm() ) + pRow = pRow->GetUpper(); + + const SwTabFrm* pTabFrm = (const SwTabFrm*)pRow->GetUpper(); + const SwTableLine* pTabLine = static_cast<const SwRowFrm*>(pRow)->GetTabLine(); + + USHORT nI = 0; + while ( nI < pTabFrm->GetTable()->GetTabLines().Count() ) + { + if ( pTabFrm->GetTable()->GetTabLines()[ nI ] == pTabLine ) + { + nRet = nI; + break; + } + ++nI; + } + } + + return nRet; +} +USHORT SwFEShell::GetRowSelectionFromTop() const +{ + USHORT nRet = 0; + const SwPaM* pPaM = IsTableMode() ? GetTableCrsr() : _GetCrsr(); + const USHORT nPtLine = lcl_GetRowNumber( *pPaM->GetPoint() ); + + if ( !IsTableMode() ) + { + nRet = 0 == nPtLine ? 1 : 0; + } + else + { + const USHORT nMkLine = lcl_GetRowNumber( *pPaM->GetMark() ); + + if ( ( nPtLine == 0 && nMkLine != USHRT_MAX ) || + ( nMkLine == 0 && nPtLine != USHRT_MAX ) ) + { + nRet = Max( nPtLine, nMkLine ) + 1; + } + } + + return nRet; +} + +/* + * 1. case: bRepeat = true + * returns true if the current frame is located inside a table headline in + * a follow frame + * + * 2. case: bRepeat = false + * returns true if the current frame is localed inside a table headline OR + * inside the first line of a table!!! + */ +BOOL SwFEShell::CheckHeadline( bool bRepeat ) const +{ + BOOL bRet = FALSE; + if ( !IsTableMode() ) + { + SwFrm *pFrm = GetCurrFrm(); // DONE MULTIIHEADER + if ( pFrm && pFrm->IsInTab() ) + { + SwTabFrm* pTab = pFrm->FindTabFrm(); + if ( bRepeat ) + { + bRet = pTab->IsFollow() && pTab->IsInHeadline( *pFrm ); + } + else + { + bRet = ((SwLayoutFrm*)pTab->Lower())->IsAnLower( pFrm ) || + pTab->IsInHeadline( *pFrm ); + } + } + } + return bRet; +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : AdjustCellWidth() +#* Datum : MA 20. Feb. 95 +#* Update : MA 27. Jul. 95 +#***********************************************************************/ + +void SwFEShell::AdjustCellWidth( BOOL bBalance ) +{ + SET_CURR_SHELL( this ); + StartAllAction(); + + //WarteCrsr immer einschalten, weil sich im vorraus nicht so recht + //ermitteln laesst wieviel Inhalt betroffen ist. + TblWait aWait( USHRT_MAX, 0, *GetDoc()->GetDocShell() ); + + GetDoc()->AdjustCellWidth( *getShellCrsr( false ), bBalance ); + EndAllActionAndCall(); +} + +BOOL SwFEShell::IsAdjustCellWidthAllowed( BOOL bBalance ) const +{ + //Es muss mindestens eine Zelle mit Inhalt in der Selektion enthalten + //sein. + + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + SwSelBoxes aBoxes; + ::GetTblSelCrs( *this, aBoxes ); + + if ( bBalance ) + return aBoxes.Count() > 1; + + if ( !aBoxes.Count() ) + { + do + { pFrm = pFrm->GetUpper(); + } while ( !pFrm->IsCellFrm() ); + SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); + aBoxes.Insert( pBox ); + } + + for ( USHORT i = 0; i < aBoxes.Count(); ++i ) + { + SwTableBox *pBox = aBoxes[i]; + if ( pBox->GetSttNd() ) + { + SwNodeIndex aIdx( *pBox->GetSttNd(), 1 ); + SwTxtNode* pCNd = aIdx.GetNode().GetTxtNode(); + if( !pCNd ) + pCNd = (SwTxtNode*)GetDoc()->GetNodes().GoNext( &aIdx ); + + while ( pCNd ) + { + if ( pCNd->GetTxt().Len() ) + return TRUE; + ++aIdx; + pCNd = GetDoc()->GetNodes()[ aIdx ]->GetTxtNode(); + } + } + } + return FALSE; +} + + // AutoFormat fuer die Tabelle/TabellenSelection +BOOL SwFEShell::SetTableAutoFmt( const SwTableAutoFmt& rNew ) +{ + SwTableNode *pTblNd = (SwTableNode*)IsCrsrInTbl(); + if( !pTblNd || pTblNd->GetTable().IsTblComplex() ) + return FALSE; + + SwSelBoxes aBoxes; + + if ( !IsTableMode() ) // falls Crsr noch nicht akt. sind + GetCrsr(); + + // gesamte Tabelle oder nur auf die akt. Selektion + if( IsTableMode() ) + ::GetTblSelCrs( *this, aBoxes ); + else + { + const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes(); + for( USHORT n = 0; n < rTBoxes.Count(); ++n ) + { + SwTableBox* pBox = rTBoxes[ n ]; + aBoxes.Insert( pBox ); + } + } + + BOOL bRet; + if( aBoxes.Count() ) + { + SET_CURR_SHELL( this ); + StartAllAction(); + bRet = GetDoc()->SetTableAutoFmt( aBoxes, rNew ); + DELETEZ( pLastCols ); + DELETEZ( pLastRows ); + EndAllActionAndCall(); + } + else + bRet = FALSE; + return bRet; +} + +BOOL SwFEShell::GetTableAutoFmt( SwTableAutoFmt& rGet ) +{ + const SwTableNode *pTblNd = IsCrsrInTbl(); + if( !pTblNd || pTblNd->GetTable().IsTblComplex() ) + return FALSE; + + SwSelBoxes aBoxes; + + if ( !IsTableMode() ) // falls Crsr noch nicht akt. sind + GetCrsr(); + + // gesamte Tabelle oder nur auf die akt. Selektion + if( IsTableMode() ) + ::GetTblSelCrs( *this, aBoxes ); + else + { + const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes(); + for( USHORT n = 0; n < rTBoxes.Count(); ++n ) + { + SwTableBox* pBox = rTBoxes[ n ]; + aBoxes.Insert( pBox ); + } + } + + return GetDoc()->GetTableAutoFmt( aBoxes, rGet ); +} + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : DeleteTblSel() +#* Datum : MA 03. May. 93 +#* Update : MA 19. Apr. 95 +#***********************************************************************/ +BOOL SwFEShell::DeleteTblSel() +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + StartAllAction(); + + // lasse ueber das Layout die Boxen suchen + BOOL bRet; + SwSelBoxes aBoxes; + GetTblSelCrs( *this, aBoxes ); + if( aBoxes.Count() ) + { + TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() ); + + // die Crsr muessen noch aus dem Loesch Bereich entfernt + // werden. Setze sie immer hinter/auf die Tabelle; ueber die + // Dokument-Position werden sie dann immer an die alte Position gesetzt. + while( !pFrm->IsCellFrm() ) + pFrm = pFrm->GetUpper(); + ParkCrsr( SwNodeIndex( *((SwCellFrm*)pFrm)->GetTabBox()->GetSttNd() )); + + bRet = GetDoc()->DeleteRowCol( aBoxes ); + + DELETEZ( pLastCols ); + DELETEZ( pLastRows ); + } + else + bRet = FALSE; + EndAllActionAndCall(); + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::GetCurTabColNum() +|* +|* Ersterstellung MA 03. Feb. 95 +|* Letzte Aenderung MA 21. May. 95 +| +|*************************************************************************/ +USHORT SwFEShell::GetCurTabColNum() const +{ + //!!!GetCurMouseTabColNum() mitpflegen!!!! + USHORT nRet = 0; + + SwFrm *pFrm = GetCurrFrm(); + ASSERT( pFrm, "Crsr geparkt?" ); + + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + if( pFrm && pFrm->IsInTab() ) + { + do { // JP 26.09.95: warum mit dem CntntFrame und nicht mit + // dem CellFrame vergleichen???? + pFrm = pFrm->GetUpper(); + } while ( !pFrm->IsCellFrm() ); + SWRECTFN( pFrm ) + + const SwPageFrm* pPage = pFrm->FindPageFrm(); + + //TabCols besorgen, den nur ueber diese erreichen wir die Position. + SwTabCols aTabCols; + GetTabCols( aTabCols ); + + if( pFrm->FindTabFrm()->IsRightToLeft() ) + { + long nX = (pFrm->Frm().*fnRect->fnGetRight)() - (pPage->Frm().*fnRect->fnGetLeft)(); + + const long nRight = aTabCols.GetLeftMin() + aTabCols.GetRight();; + + if ( !::IsSame( nX, nRight ) ) + { + nX = nRight - nX + aTabCols.GetLeft(); + for ( USHORT i = 0; i < aTabCols.Count(); ++i ) + if ( ::IsSame( nX, aTabCols[i] ) ) + { + nRet = i + 1; + break; + } + } + } + else + { + const long nX = (pFrm->Frm().*fnRect->fnGetLeft)() - + (pPage->Frm().*fnRect->fnGetLeft)(); + + const long nLeft = aTabCols.GetLeftMin(); + + if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) ) + { + for ( USHORT i = 0; i < aTabCols.Count(); ++i ) + if ( ::IsSame( nX, nLeft + aTabCols[i] ) ) + { + nRet = i + 1; + break; + } + } + } + } + return nRet; +} + +/************************************************************************* +|* +|* SwFEShell::GetBox() +|* +|* Ersterstellung MA 22. Jun. 95 +|* Letzte Aenderung MA 21. Nov. 96 +|* +|*************************************************************************/ + +const SwFrm *lcl_FindFrmInTab( const SwLayoutFrm *pLay, const Point &rPt, SwTwips nFuzzy ) +{ + const SwFrm *pFrm = pLay->Lower(); + + while( pFrm && pLay->IsAnLower( pFrm ) ) + { + if ( pFrm->Frm().IsNear( rPt, nFuzzy ) ) + { + if ( pFrm->IsLayoutFrm() ) + { + const SwFrm *pTmp = ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, rPt, nFuzzy ); + if ( pTmp ) + return pTmp; + } + + return pFrm; + } + + pFrm = pFrm->FindNext(); + } + + return 0; +} + +const SwCellFrm *lcl_FindFrm( const SwLayoutFrm *pLay, const Point &rPt, + SwTwips nFuzzy, bool* pbRow, bool* pbCol ) +{ + // bMouseMoveRowCols : + // Method is called for + // - Moving columns/rows with the mouse or + // - Enhanced table selection + const bool bMouseMoveRowCols = 0 == pbCol; + + bool bCloseToRow = false; + bool bCloseToCol = false; + + const SwFrm *pFrm = pLay->ContainsCntnt(); + const SwFrm* pRet = 0; + + if ( pFrm ) + { + do + { + if ( pFrm->IsInTab() ) + pFrm = ((SwFrm*)pFrm)->ImplFindTabFrm(); + + if ( pFrm->IsTabFrm() ) + { + Point aPt( rPt ); + bool bSearchForFrmInTab = true; + SwTwips nTmpFuzzy = nFuzzy; + + if ( !bMouseMoveRowCols ) + { + // We ignore nested tables for the enhanced table selection: + while ( pFrm->GetUpper()->IsInTab() ) + pFrm = pFrm->GetUpper()->FindTabFrm(); + + // We first check if the given point is 'close' to the left or top + // border of the table frame: + ASSERT( pFrm, "Nested table frame without outer table" ) + SWRECTFN( pFrm ) + const bool bRTL = pFrm->IsRightToLeft(); + + SwRect aTabRect = pFrm->Prt(); + aTabRect.Pos() += pFrm->Frm().Pos(); + + const SwTwips nLeft = bRTL ? + (aTabRect.*fnRect->fnGetRight)() : + (aTabRect.*fnRect->fnGetLeft)(); + const SwTwips nTop = (aTabRect.*fnRect->fnGetTop)(); + + SwTwips& rPointX = bVert ? aPt.Y() : aPt.X(); + SwTwips& rPointY = bVert ? aPt.X() : aPt.Y(); + + const SwTwips nXDiff = (*fnRect->fnXDiff)( nLeft, rPointX ) * ( bRTL ? (-1) : 1 ); + const SwTwips nYDiff = (*fnRect->fnYDiff)( nTop, rPointY ); + + bCloseToRow = nXDiff >= 0 && nXDiff < nFuzzy; + bCloseToCol = nYDiff >= 0 && nYDiff < nFuzzy; + + if ( bCloseToCol && 2 * nYDiff > nFuzzy ) + { + const SwFrm* pPrev = pFrm->GetPrev(); + if ( pPrev ) + { + SwRect aPrevRect = pPrev->Prt(); + aPrevRect.Pos() += pPrev->Frm().Pos(); + + if( aPrevRect.IsInside( rPt ) ) + { + bCloseToCol = false; + } + } + + } + + // If we found the point to be 'close' to the left or top border + // of the table frame, we adjust the point to be on that border: + if ( bCloseToRow && bCloseToCol ) + aPt = bRTL ? aTabRect.TopRight() : (aTabRect.*fnRect->fnGetPos)(); + else if ( bCloseToRow ) + rPointX = nLeft; + else if ( bCloseToCol ) + rPointY = nTop; + + if ( !bCloseToRow && !bCloseToCol ) + bSearchForFrmInTab = false; + + // Since the point has been adjusted, we call lcl_FindFrmInTab() + // with a fuzzy value of 1: + nTmpFuzzy = 1; + } + + const SwFrm* pTmp = bSearchForFrmInTab ? + ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, aPt, nTmpFuzzy ) : + 0; + + if ( pTmp ) + { + pFrm = pTmp; + break; + } + } + pFrm = pFrm->FindNextCnt(); + + } while ( pFrm && pLay->IsAnLower( pFrm ) ); + } + + if ( pFrm && pFrm->IsInTab() && pLay->IsAnLower( pFrm ) ) + { + do + { + // We allow mouse drag of table borders within nested tables, + // but disallow hotspot selection of nested tables. + if ( bMouseMoveRowCols ) + { + // find the next cell frame + while ( pFrm && !pFrm->IsCellFrm() ) + pFrm = pFrm->GetUpper(); + } + else + { + // find the most upper cell frame: + while ( pFrm && + ( !pFrm->IsCellFrm() || + !pFrm->GetUpper()->GetUpper()->IsTabFrm() || + pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) ) + pFrm = pFrm->GetUpper(); + } + + if ( pFrm ) // Note: this condition should be the same like the while condition!!! + { + // --> FME 2004-07-30 #i32329# Enhanced table selection + // used for hotspot selection of tab/cols/rows + if ( !bMouseMoveRowCols ) + { + + ASSERT( pbCol && pbRow, "pbCol or pbRow missing" ) + + if ( bCloseToRow || bCloseToCol ) + { + *pbRow = bCloseToRow; + *pbCol = bCloseToCol; + pRet = pFrm; + break; + } + } + // <-- + else + { + // used for mouse move of columns/rows + const SwTabFrm* pTabFrm = pFrm->FindTabFrm(); + SwRect aTabRect = pTabFrm->Prt(); + aTabRect.Pos() += pTabFrm->Frm().Pos(); + + SWRECTFN( pTabFrm ) + + const SwTwips nTabTop = (aTabRect.*fnRect->fnGetTop)(); + const SwTwips nMouseTop = bVert ? rPt.X() : rPt.Y(); + + // Do not allow to drag upper table border: + if ( !::IsSame( nTabTop, nMouseTop ) ) + { + if ( ::IsSame( pFrm->Frm().Left(), rPt.X() ) || + ::IsSame( pFrm->Frm().Right(),rPt.X() ) ) + { + if ( pbRow ) *pbRow = false; + pRet = pFrm; + break; + } + if ( ::IsSame( pFrm->Frm().Top(), rPt.Y() ) || + ::IsSame( pFrm->Frm().Bottom(),rPt.Y() ) ) + { + if ( pbRow ) *pbRow = true; + pRet = pFrm; + break; + } + } + } + + pFrm = pFrm->GetUpper(); + } + } while ( pFrm ); + } + + // robust: + ASSERT( !pRet || pRet->IsCellFrm(), "lcl_FindFrm() is supposed to find a cell frame!" ) + return pRet && pRet->IsCellFrm() ? static_cast<const SwCellFrm*>(pRet) : 0; +} + +// +// pbCol = 0 => Used for moving table rows/cols with mouse +// pbCol != 0 => Used for selecting table/rows/cols +// +#define ENHANCED_TABLE_SELECTION_FUZZY 10 + +const SwFrm* SwFEShell::GetBox( const Point &rPt, bool* pbRow, bool* pbCol ) const +{ + const SwPageFrm *pPage = (SwPageFrm*)GetLayout()->Lower(); + Window* pOutWin = GetWin(); + SwTwips nFuzzy = COLFUZZY; + if( pOutWin ) + { + // --> FME 2004-07-30 #i32329# Enhanced table selection + SwTwips nSize = pbCol ? ENHANCED_TABLE_SELECTION_FUZZY : RULER_MOUSE_MARGINWIDTH; + // <-- + Size aTmp( nSize, nSize ); + aTmp = pOutWin->PixelToLogic( aTmp ); + nFuzzy = aTmp.Width(); + } + + while ( pPage && !pPage->Frm().IsNear( rPt, nFuzzy ) ) + pPage = (SwPageFrm*)pPage->GetNext(); + + const SwCellFrm *pFrm = 0; + if ( pPage ) + { + //Per GetCrsrOfst oder GetCntntPos koennen wir hier die Box leider + //nicht suchen. Das wuerde zu einem Performance-Zusammenbruch bei + //Dokumenten mit vielen Absaetzen/Tabellen auf einer Seite fuehren + //(BrowseMode!) + + //Erst die Flys checken. + if ( pPage->GetSortedObjs() ) + { + for ( USHORT i = 0; !pFrm && i < pPage->GetSortedObjs()->Count(); ++i ) + { + SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i]; + if ( pObj->ISA(SwFlyFrm) ) + { + pFrm = lcl_FindFrm( static_cast<SwFlyFrm*>(pObj), + rPt, nFuzzy, pbRow, pbCol ); + } + } + } + const SwLayoutFrm *pLay = (SwLayoutFrm*)pPage->Lower(); + while ( pLay && !pFrm ) + { + pFrm = lcl_FindFrm( pLay, rPt, nFuzzy, pbRow, pbCol ); + pLay = (SwLayoutFrm*)pLay->GetNext(); + } + } + return pFrm; +} + +/* Helper function*/ +/* calculated the distance between Point rC and Line Segment (rA, rB) */ +double lcl_DistancePoint2Segment( const Point& rA, const Point& rB, const Point& rC ) +{ + double nRet = 0; + + const basegfx::B2DVector aBC( rC.X() - rB.X(), rC.Y() - rB.Y() ); + const basegfx::B2DVector aAB( rB.X() - rA.X(), rB.Y() - rA.Y() ); + const double nDot1 = aBC.scalar( aAB ); + + if ( nDot1 > 0 ) // check outside case 1 + nRet = aBC.getLength(); + else + { + const basegfx::B2DVector aAC( rC.X() - rA.X(), rC.Y() - rA.Y() ); + const basegfx::B2DVector aBA( rA.X() - rB.X(), rA.Y() - rB.Y() ); + const double nDot2 = aAC.scalar( aBA ); + + if ( nDot2 > 0 ) // check outside case 2 + nRet = aAC.getLength(); + else + { + const double nDiv = aAB.getLength(); + nRet = nDiv ? aAB.cross( aAC ) / nDiv : 0; + } + } + + return Abs(nRet); +} + +/* Helper function*/ +Point lcl_ProjectOntoClosestTableFrm( const SwTabFrm& rTab, const Point& rPoint, bool bRowDrag ) +{ + Point aRet( rPoint ); + const SwTabFrm* pCurrentTab = &rTab; + const bool bVert = pCurrentTab->IsVertical(); + const bool bRTL = pCurrentTab->IsRightToLeft(); + + // Western Layout: + // bRowDrag = true => compare to left border of table + // bRowDrag = false => compare to top border of table + + // Asian Layout: + // bRowDrag = true => compare to right border of table + // bRowDrag = false => compare to top border of table + + // RTL Layout: + // bRowDrag = true => compare to right border of table + // bRowDrag = false => compare to top border of table + bool bLeft = false; + bool bRight = false; + + if ( bRowDrag ) + { + if ( bVert || bRTL ) + bRight = true; + else + bLeft = true; + } + + // used to find the minimal distance + double nMin = -1; + Point aMin1; + Point aMin2; + + Point aS1; + Point aS2; + + while ( pCurrentTab ) + { + SwRect aTabRect( pCurrentTab->Prt() ); + aTabRect += pCurrentTab->Frm().Pos(); + + if ( bLeft ) + { + // distance to left table border + aS1 = aTabRect.TopLeft(); + aS2 = aTabRect.BottomLeft(); + } + else if ( bRight ) + { + // distance to right table border + aS1 = aTabRect.TopRight(); + aS2 = aTabRect.BottomRight(); + } + else //if ( bTop ) + { + // distance to top table border + aS1 = aTabRect.TopLeft(); + aS2 = aTabRect.TopRight(); + } + + const double nDist = lcl_DistancePoint2Segment( aS1, aS2, rPoint ); + + if ( nDist < nMin || -1 == nMin ) + { + aMin1 = aS1; + aMin2 = aS2; + nMin = nDist; + } + + pCurrentTab = pCurrentTab->GetFollow(); + } + + // project onto closest line: + if ( bLeft || bRight ) + { + aRet.X() = aMin1.X(); + if ( aRet.Y() > aMin2.Y() ) + aRet.Y() = aMin2.Y(); + else if ( aRet.Y() < aMin1.Y() ) + aRet.Y() = aMin1.Y(); + } + else //if ( bTop ) + { + aRet.Y() = aMin1.Y(); + if ( aRet.X() > aMin2.X() ) + aRet.X() = aMin2.X(); + else if ( aRet.X() < aMin1.X() ) + aRet.X() = aMin1.X(); + } + + return aRet; +} + +// --> FME 2004-07-30 #i32329# Enhanced table selection +bool SwFEShell::SelTblRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag ) +{ + bool bRet = false; + Point aEndPt; + if ( pEnd ) + aEndPt = *pEnd; + + SwPosition* ppPos[2] = { 0, 0 }; + Point paPt [2] = { rPt, aEndPt }; + bool pbRow[2] = { 0, 0 }; + bool pbCol[2] = { 0, 0 }; + + // pEnd is set during dragging. + for ( USHORT i = 0; i < ( pEnd ? 2 : 1 ); ++i ) + { + const SwCellFrm* pFrm = + static_cast<const SwCellFrm*>(GetBox( paPt[i], &pbRow[i], &pbCol[i] ) ); + + if( pFrm ) + { + while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() ) + pFrm = static_cast<const SwCellFrm*>( static_cast<const SwLayoutFrm*>( pFrm->Lower() )->Lower() ); + if( pFrm && pFrm->GetTabBox()->GetSttNd() && + pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() ) + pFrm = 0; + } + + if ( pFrm ) + { + const SwCntntFrm* pCntnt = ::GetCellCntnt( *pFrm ); + + if ( pCntnt && pCntnt->IsTxtFrm() ) + { + ppPos[i] = new SwPosition( *pCntnt->GetNode() ); + ppPos[i]->nContent.Assign( const_cast<SwCntntNode*>(pCntnt->GetNode()), 0 ); + + // paPt[i] will not be used any longer, now we use it to store + // a position inside the content frame + paPt[i] = pCntnt->Frm().Center(); + } + } + + // no calculation of end frame if start frame has not been found. + if ( 1 == i || !ppPos[0] || !pEnd ) + break; + + // find 'closest' table frame to pEnd: + const SwTabFrm* pCurrentTab = pFrm->FindTabFrm(); + if ( pCurrentTab->IsFollow() ) + pCurrentTab = pCurrentTab->FindMaster( true ); + + const Point aProjection = lcl_ProjectOntoClosestTableFrm( *pCurrentTab, *pEnd, bRowDrag ); + paPt[1] = aProjection; + } + + if ( ppPos[0] ) + { + SwShellCrsr* pCrsr = _GetCrsr(); + SwCrsrSaveState aSaveState( *pCrsr ); + SwPosition aOldPos( *pCrsr->GetPoint() ); + + pCrsr->DeleteMark(); + *pCrsr->GetPoint() = *ppPos[0]; + pCrsr->GetPtPos() = paPt[0]; + + if ( !pCrsr->IsInProtectTable( FALSE, TRUE ) ) + { + bool bNewSelection = true; + + if ( ppPos[1] ) + { + if ( ppPos[1]->nNode.GetNode().StartOfSectionNode() != + aOldPos.nNode.GetNode().StartOfSectionNode() ) + { + pCrsr->SetMark(); + SwCrsrSaveState aSaveState2( *pCrsr ); + *pCrsr->GetPoint() = *ppPos[1]; + pCrsr->GetPtPos() = paPt[1]; + + if ( pCrsr->IsInProtectTable( FALSE, FALSE ) ) + { + pCrsr->RestoreSavePos(); + bNewSelection = false; + } + } + else + { + pCrsr->RestoreSavePos(); + bNewSelection = false; + } + } + + if ( bNewSelection ) + { + // --> FME 2004-10-20 #i35543# SelTblRowCol should remove any existing + // table cursor: + if ( IsTableMode() ) + TblCrsrToCursor(); + // <-- + + if ( pbRow[0] && pbCol[0] ) + bRet = SwCrsrShell::SelTbl(); + else if ( pbRow[0] ) + bRet = SwCrsrShell::_SelTblRowOrCol( true, true ); + else if ( pbCol[0] ) + bRet = SwCrsrShell::_SelTblRowOrCol( false, true ); + } + else + bRet = true; + } + + delete ppPos[0]; + delete ppPos[1]; + } + + return bRet; +} +// <-- + + +/************************************************************************* +|* +|* SwFEShell::WhichMouseTabCol() +|* +|* Ersterstellung MA 22. Jun. 95 +|* Last change AMA 12. Jun. 02 +| +|*************************************************************************/ +BYTE SwFEShell::WhichMouseTabCol( const Point &rPt ) const +{ + BYTE nRet = SW_TABCOL_NONE; + bool bRow = false; + bool bCol = false; + bool bSelect = false; + + // First try: Do we get the row/col move cursor? + SwCellFrm* pFrm = (SwCellFrm*)GetBox( rPt, &bRow, 0 ); + + if ( !pFrm ) + { + // Second try: Do we get the row/col/tab selection cursor? + pFrm = (SwCellFrm*)GetBox( rPt, &bRow, &bCol ); + bSelect = true; + } + + if( pFrm ) + { + while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() ) + pFrm = (SwCellFrm*)((SwLayoutFrm*)pFrm->Lower())->Lower(); + if( pFrm && pFrm->GetTabBox()->GetSttNd() && + pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() ) + pFrm = 0; + } + + if( pFrm ) + { + if ( !bSelect ) + { + if ( pFrm->IsVertical() ) + nRet = bRow ? SW_TABCOL_VERT : SW_TABROW_VERT; + else + nRet = bRow ? SW_TABROW_HORI : SW_TABCOL_HORI; + } + else + { + const SwTabFrm* pTabFrm = pFrm->FindTabFrm(); + if ( pTabFrm->IsVertical() ) + { + if ( bRow && bCol ) + { + nRet = SW_TABSEL_VERT; + } + else if ( bRow ) + { + nRet = SW_TABROWSEL_VERT; + } + else if ( bCol ) + { + nRet = SW_TABCOLSEL_VERT; + } + } + else + { + if ( bRow && bCol ) + { + nRet = pTabFrm->IsRightToLeft() ? + SW_TABSEL_HORI_RTL : + SW_TABSEL_HORI; + } + else if ( bRow ) + { + nRet = pTabFrm->IsRightToLeft() ? + SW_TABROWSEL_HORI_RTL : + SW_TABROWSEL_HORI; + } + else if ( bCol ) + { + nRet = SW_TABCOLSEL_HORI; + } + } + } + } + + return nRet; +} + +// -> #i23726# +SwTxtNode * SwFEShell::GetNumRuleNodeAtPos( const Point &rPt) +{ + SwTxtNode * pResult = NULL; + + SwContentAtPos aCntntAtPos + (SwContentAtPos::SW_NUMLABEL); + + if( GetContentAtPos(rPt, aCntntAtPos) && aCntntAtPos.aFnd.pNode) + pResult = aCntntAtPos.aFnd.pNode->GetTxtNode(); + + return pResult; +} + +BOOL SwFEShell::IsNumLabel( const Point &rPt, int nMaxOffset ) +{ + BOOL bResult = FALSE; + + SwContentAtPos aCntntAtPos + (SwContentAtPos::SW_NUMLABEL); + + if( GetContentAtPos(rPt, aCntntAtPos)) + { + if ((nMaxOffset >= 0 && aCntntAtPos.nDist <= nMaxOffset) || + (nMaxOffset < 0)) + bResult = TRUE; + } + + return bResult; +} +// <- #i23726# + +// --> OD 2005-02-21 #i42921# +bool SwFEShell::IsVerticalModeAtNdAndPos( const SwTxtNode& _rTxtNode, + const Point& _rDocPos ) const +{ + bool bRet( false ); + + const short nTextDir = + _rTxtNode.GetTextDirection( SwPosition(_rTxtNode), &_rDocPos ); + switch ( nTextDir ) + { + case -1: + case FRMDIR_HORI_RIGHT_TOP: + case FRMDIR_HORI_LEFT_TOP: + { + bRet = false; + } + break; + case FRMDIR_VERT_TOP_LEFT: + case FRMDIR_VERT_TOP_RIGHT: + { + bRet = true; + } + break; + } + + return bRet; +} +// <-- + +/************************************************************************* +|* +|* SwFEShell::GetMouseTabCols() +|* +|* Ersterstellung MA 22. Jun. 95 +|* Letzte Aenderung MA 27. Aug. 96 +| +|*************************************************************************/ +void SwFEShell::GetMouseTabCols( SwTabCols &rToFill, const Point &rPt ) const +{ + const SwFrm *pBox = GetBox( rPt ); + if ( pBox ) + _GetTabCols( rToFill, pBox ); +} + +void SwFEShell::SetMouseTabCols( const SwTabCols &rNew, BOOL bCurRowOnly, + const Point &rPt ) +{ + const SwFrm *pBox = GetBox( rPt ); + if( pBox ) + { + SET_CURR_SHELL( this ); + StartAllAction(); + GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox ); + EndAllActionAndCall(); + } +} + +/************************************************************************* +|* +|* SwFEShell::GetMouseColNum(), GetMouseTabColNum() +|* +|* Ersterstellung MA 04. Jul. 95 +|* Letzte Aenderung MA 04. Jul. 95 +| +|*************************************************************************/ +USHORT SwFEShell::GetCurMouseColNum( const Point &rPt, + SwGetCurColNumPara* pPara ) const +{ + return _GetCurColNum( GetBox( rPt ), pPara ); +} + +USHORT SwFEShell::GetCurMouseTabColNum( const Point &rPt ) const +{ + //!!!GetCurTabColNum() mitpflegen!!!! + USHORT nRet = 0; + + const SwFrm *pFrm = GetBox( rPt ); + ASSERT( pFrm, "Table not found" ); + if( pFrm ) + { + const long nX = pFrm->Frm().Left(); + + //TabCols besorgen, den nur ueber diese erreichen wir die Position. + SwTabCols aTabCols; + GetMouseTabCols( aTabCols, rPt ); + + const long nLeft = aTabCols.GetLeftMin(); + + if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) ) + { + for ( USHORT i = 0; i < aTabCols.Count(); ++i ) + if ( ::IsSame( nX, nLeft + aTabCols[i] ) ) + { + nRet = i + 1; + break; + } + } + } + return nRet; +} + +void ClearFEShellTabCols() +{ + DELETEZ( pLastCols ); + DELETEZ( pLastRows ); +} + +/************************************************************************* +|* +|* SwFEShell::GetTblAttr(), SetTblAttr() +|* +|* Ersterstellung MA 09. Dec. 96 +|* Letzte Aenderung MA 09. Dec. 96 +| +|*************************************************************************/ +void SwFEShell::GetTblAttr( SfxItemSet &rSet ) const +{ + SwFrm *pFrm = GetCurrFrm(); + if( pFrm && pFrm->IsInTab() ) + rSet.Put( pFrm->ImplFindTabFrm()->GetFmt()->GetAttrSet() ); +} + +void SwFEShell::SetTblAttr( const SfxItemSet &rNew ) +{ + SwFrm *pFrm = GetCurrFrm(); + if( pFrm && pFrm->IsInTab() ) + { + SET_CURR_SHELL( this ); + StartAllAction(); + SwTabFrm *pTab = pFrm->FindTabFrm(); + pTab->GetTable()->SetHTMLTableLayout( 0 ); + GetDoc()->SetAttr( rNew, *pTab->GetFmt() ); + GetDoc()->SetModified(); + EndAllActionAndCall(); + } +} + +/** move cursor within a table into previous/next row (same column) + * @param pShell cursor shell whose cursor is to be moved + * @param bUp true: move up, false: move down + * @returns true if successful + */ +bool lcl_GoTableRow( SwCrsrShell* pShell, bool bUp ) +{ + ASSERT( pShell != NULL, "need shell" ); + + bool bRet = false; + + SwPaM* pPam = pShell->GetCrsr(); + const SwStartNode* pTableBox = pPam->GetNode()->FindTableBoxStartNode(); + ASSERT( pTableBox != NULL, "I'm living in a box... NOT!" ); + + // move cursor to start node of table box + pPam->GetPoint()->nNode = pTableBox->GetIndex(); + pPam->GetPoint()->nContent.Assign( NULL, 0 ); + GoInCntnt( *pPam, fnMoveForward ); + + // go to beginning end of table box + SwPosSection fnPosSect = bUp ? fnSectionStart : fnSectionEnd; + pShell->MoveSection( fnSectionCurr, fnPosSect ); + + // and go up/down into next content + bRet = bUp ? pShell->Up() : pShell->Down(); + + return bRet; +} + + // aender eine Zellenbreite/-Hoehe/Spaltenbreite/Zeilenhoehe +BOOL SwFEShell::SetColRowWidthHeight( USHORT eType, USHORT nDiff ) +{ + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType && + pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable )) + { + ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR, + ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK ); + return FALSE; + } + + SET_CURR_SHELL( this ); + StartAllAction(); + + do { + pFrm = pFrm->GetUpper(); + } while( !pFrm->IsCellFrm() ); + + SwTabFrm *pTab = pFrm->ImplFindTabFrm(); + + // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen + // dann muss es jetzt auf absolute umgerechnet werden. + const SwFmtFrmSize& rTblFrmSz = pTab->GetFmt()->GetFrmSize(); + SWRECTFN( pTab ) + long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)(); + if( TBLVAR_CHGABS == pTab->GetTable()->GetTblChgMode() && + ( eType & nsTblChgWidthHeightType::WH_COL_LEFT || eType & nsTblChgWidthHeightType::WH_COL_RIGHT ) && + text::HoriOrientation::NONE == pTab->GetFmt()->GetHoriOrient().GetHoriOrient() && + nPrtWidth != rTblFrmSz.GetWidth() ) + { + SwFmtFrmSize aSz( rTblFrmSz ); + aSz.SetWidth( pTab->Prt().Width() ); + pTab->GetFmt()->SetFmtAttr( aSz ); + } + + if( (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) == + (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL) ) + { + nDiff = USHORT((pFrm->Frm().*fnRect->fnGetWidth)()); + + // we must move the cursor outside the current cell before + // deleting the cells. + TblChgWidthHeightType eTmp = + static_cast<TblChgWidthHeightType>( eType & 0xfff ); + switch( eTmp ) + { + case nsTblChgWidthHeightType::WH_ROW_TOP: + lcl_GoTableRow( this, true ); + break; + case nsTblChgWidthHeightType::WH_ROW_BOTTOM: + lcl_GoTableRow( this, false ); + break; + case nsTblChgWidthHeightType::WH_COL_LEFT: + GoPrevCell(); + break; + case nsTblChgWidthHeightType::WH_COL_RIGHT: + GoNextCell(); + break; + default: + break; + } + } + + SwTwips nLogDiff = nDiff; + nLogDiff *= pTab->GetFmt()->GetFrmSize().GetWidth(); + nLogDiff /= nPrtWidth; + + /** The cells are destroyed in here */ + BOOL bRet = GetDoc()->SetColRowWidthHeight( + *(SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(), + eType, nDiff, nLogDiff ); + + delete pLastCols, pLastCols = 0; + EndAllActionAndCall(); + + if( bRet && (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) == nsTblChgWidthHeightType::WH_FLAG_INSDEL ) + { + switch(eType & ~(nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) + { + case nsTblChgWidthHeightType::WH_CELL_LEFT: + case nsTblChgWidthHeightType::WH_COL_LEFT: + GoPrevCell(); + break; + + case nsTblChgWidthHeightType::WH_CELL_RIGHT: + case nsTblChgWidthHeightType::WH_COL_RIGHT: + GoNextCell(); + break; + + case nsTblChgWidthHeightType::WH_CELL_TOP: + case nsTblChgWidthHeightType::WH_ROW_TOP: + lcl_GoTableRow( this, true ); + break; + + case nsTblChgWidthHeightType::WH_CELL_BOTTOM: + case nsTblChgWidthHeightType::WH_ROW_BOTTOM: + lcl_GoTableRow( this, false ); + break; + } + } + + return bRet; +} + +BOOL lcl_IsFormulaSelBoxes( const SwTable& rTbl, const SwTblBoxFormula& rFml, + SwCellFrms& rCells ) +{ + SwTblBoxFormula aTmp( rFml ); + SwSelBoxes aBoxes; + for( USHORT nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes ); nSelBoxes; ) + { + SwTableBox* pBox = aBoxes[ --nSelBoxes ]; + USHORT i; + for( i = 0; i < rCells.Count(); ++i ) + if( rCells[ i ]->GetTabBox() == pBox ) + break; // gefunden + + if( i == rCells.Count() ) + return FALSE; + } + + return TRUE; +} + + // erfrage die Formel fuer die Autosumme +BOOL SwFEShell::GetAutoSum( String& rFml ) const +{ + SwFrm *pFrm = GetCurrFrm(); + SwTabFrm *pTab = pFrm ? pFrm->ImplFindTabFrm() : 0; + if( !pTab ) + return FALSE; + + rFml = String::CreateFromAscii( sCalc_Sum ); + + SwCellFrms aCells; + if( ::GetAutoSumSel( *this, aCells )) + { + USHORT nW = 0, nInsPos = 0; + for( USHORT n = aCells.Count(); n; ) + { + SwCellFrm* pCFrm = aCells[ --n ]; + USHORT nBoxW = pCFrm->GetTabBox()->IsFormulaOrValueBox(); + if( !nBoxW ) + break; + + if( !nW ) + { + if( USHRT_MAX == nBoxW ) + continue; // leere am Anfang ueberspringen + + rFml += '('; + nInsPos = rFml.Len(); + + // Formeln nur wenn diese Boxen enthalten + if( RES_BOXATR_FORMULA == nBoxW && + !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm-> + GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells)) + { + nW = RES_BOXATR_VALUE; + // alle vorhierigen Leere wieder mit aufnehmen ! + for( USHORT i = aCells.Count(); n+1 < i; ) + { + String sTmp( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "|<" )) ); + sTmp += aCells[ --i ]->GetTabBox()->GetName(); + sTmp += '>'; + rFml.Insert( sTmp, nInsPos ); + } + } + else + nW = nBoxW; + } + else if( RES_BOXATR_VALUE == nW ) + { + // values werden gesucht, Value/Formel/Text gefunden -> aufn. + if( RES_BOXATR_FORMULA == nBoxW && + ::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm-> + GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells )) + break; + else if( USHRT_MAX != nBoxW ) + rFml.Insert( cListDelim, nInsPos ); + else + break; + } + else if( RES_BOXATR_FORMULA == nW ) + { + // bei Formeln nur weiter suchen, wenn die akt. Formel auf + // alle Boxen verweist, die sich in der Selektion befinden + if( RES_BOXATR_FORMULA == nBoxW ) + { + if( !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm-> + GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells )) + { + // dann noch mal von vorne und nur die Values! + + nW = RES_BOXATR_VALUE; + rFml.Erase( nInsPos ); + // alle vorhierigen Leere wieder mit aufnehmen ! + for( USHORT i = aCells.Count(); n+1 < i; ) + { + String sTmp( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "|<" )) ); + sTmp += aCells[ --i ]->GetTabBox()->GetName(); + sTmp += '>'; + rFml.Insert( sTmp, nInsPos ); + } + } + else + rFml.Insert( cListDelim, nInsPos ); + } + else if( USHRT_MAX == nBoxW ) + break; + else + continue; // diese Boxen ignorieren + } + else + // alles andere beendet die Schleife +// evt. Texte noch zu lassen?? + break; + + String sTmp( '<' ); + sTmp += pCFrm->GetTabBox()->GetName(); + sTmp += '>'; + rFml.Insert( sTmp, nInsPos ); + } + if( nW ) + { + rFml += ')'; + +/* + // TabellenSelektion erzeugen?? + SwTblBoxFormula aTmp( rFml ); + SwSelBoxes aBoxes; + for( USHORT nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes ); + nSelBoxes; ) + { + } +*/ + } + } + + return TRUE; +} +/* -----------------------------22.08.2002 12:50------------------------------ + + ---------------------------------------------------------------------------*/ +BOOL SwFEShell::IsTableRightToLeft() const +{ + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + return pFrm->ImplFindTabFrm()->IsRightToLeft(); +} + +/* -----------------------------22.08.2002 12:50------------------------------ + + ---------------------------------------------------------------------------*/ +BOOL SwFEShell::IsMouseTableRightToLeft(const Point &rPt) const +{ + SwFrm *pFrm = (SwFrm *)GetBox( rPt ); + const SwTabFrm* pTabFrm = pFrm ? pFrm->ImplFindTabFrm() : 0; + ASSERT( pTabFrm, "Table not found" ); + return pTabFrm ? pTabFrm->IsRightToLeft() : FALSE; +} + +/* -----------------------------11.02.2004 12:50------------------------------ + + ---------------------------------------------------------------------------*/ +BOOL SwFEShell::IsTableVertical() const +{ + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm || !pFrm->IsInTab() ) + return FALSE; + + return pFrm->ImplFindTabFrm()->IsVertical(); +} + + + diff --git a/sw/source/core/frmedt/fews.cxx b/sw/source/core/frmedt/fews.cxx new file mode 100644 index 000000000000..02baddd201bd --- /dev/null +++ b/sw/source/core/frmedt/fews.cxx @@ -0,0 +1,1296 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <tools/list.hxx> +#include <svx/svdobj.hxx> +#include <init.hxx> +#include <fesh.hxx> +#include <pagefrm.hxx> +#include <rootfrm.hxx> +#include <cntfrm.hxx> +#include <doc.hxx> +#include <frmtool.hxx> +#include <swtable.hxx> +#include <viewimp.hxx> +#include <dview.hxx> +#include <flyfrm.hxx> +#include <node.hxx> +#include <pam.hxx> +#include <sectfrm.hxx> +#include <fmtpdsc.hxx> +#include <fmtsrnd.hxx> +#include <fmtcntnt.hxx> +#include <tabfrm.hxx> +#include <cellfrm.hxx> +#include <flyfrms.hxx> +#include <txtfrm.hxx> // SwTxtFrm +#include <mdiexp.hxx> +#include <edimp.hxx> +#include <pagedesc.hxx> +#include <fmtanchr.hxx> +// OD 29.10.2003 #113049# +#include <environmentofanchoredobject.hxx> +// OD 12.11.2003 #i22341# +#include <ndtxt.hxx> +// OD 27.11.2003 #112045# +#include <dflyobj.hxx> +// OD 2004-03-29 #i26791# +#include <dcontact.hxx> + + +using namespace com::sun::star; + + +TYPEINIT1(SwFEShell,SwEditShell) + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : EndAllActionAndCall() +#* +#* Datum : MA 03. May. 93 +#* Update : MA 31. Oct. 95 +#***********************************************************************/ + +void SwFEShell::EndAllActionAndCall() +{ + ViewShell *pTmp = this; + do { + if( pTmp->IsA( TYPE(SwCrsrShell) ) ) + { + ((SwFEShell*)pTmp)->EndAction(); + ((SwFEShell*)pTmp)->CallChgLnk(); + } + else + pTmp->EndAction(); + } while( this != ( pTmp = (ViewShell*)pTmp->GetNext() )); +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methode : GetCntntPos +#* Beschreibung: Ermitteln des Cntnt's der dem Punkt am naechsten liegt +#* Datum : MA 02. Jun. 92 +#* Update : MA 02. May. 95 +#***********************************************************************/ + +Point SwFEShell::GetCntntPos( const Point& rPoint, BOOL bNext ) const +{ + SET_CURR_SHELL( (ViewShell*)this ); + return GetLayout()->GetNextPrevCntntPos( rPoint, bNext ); +} + + +const SwRect& SwFEShell::GetAnyCurRect( CurRectType eType, const Point* pPt, + const uno::Reference < embed::XEmbeddedObject >& xObj ) const +{ + const SwFrm *pFrm = Imp()->HasDrawView() + ? ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(), + (ViewShell*)this) + : 0; + + if( !pFrm ) + { + if( pPt ) + { + SwPosition aPos( *GetCrsr()->GetPoint() ); + Point aPt( *pPt ); + GetLayout()->GetCrsrOfst( &aPos, aPt ); + SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode(); + pFrm = pNd->GetFrm( pPt ); + } + else + pFrm = GetCurrFrm(); + } + + if( !pFrm ) + return GetLayout()->Frm(); + + BOOL bFrm = TRUE; + switch ( eType ) + { + case RECT_PAGE_PRT: bFrm = FALSE; /* no break */ + case RECT_PAGE : pFrm = pFrm->FindPageFrm(); + break; + + case RECT_PAGE_CALC: pFrm->Calc(); + pFrm = pFrm->FindPageFrm(); + pFrm->Calc(); + break; + + case RECT_FLY_PRT_EMBEDDED: bFrm = FALSE; /* no break */ + case RECT_FLY_EMBEDDED: pFrm = xObj.is() ? FindFlyFrm( xObj ) + : pFrm->IsFlyFrm() + ? pFrm + : pFrm->FindFlyFrm(); + break; + + case RECT_OUTTABSECTION_PRT: + case RECT_OUTTABSECTION : if( pFrm->IsInTab() ) + pFrm = pFrm->FindTabFrm(); + else { + ASSERT( FALSE, "Missing Table" ); + } + /* KEIN BREAK */ + case RECT_SECTION_PRT: + case RECT_SECTION: if( pFrm->IsInSct() ) + pFrm = pFrm->FindSctFrm(); + else { + ASSERT( FALSE, "Missing section" ); + } + + if( RECT_OUTTABSECTION_PRT == eType || + RECT_SECTION_PRT == eType ) + bFrm = FALSE; + break; + + case RECT_HEADERFOOTER_PRT: bFrm = FALSE; /* no break */ + case RECT_HEADERFOOTER: if( 0 == (pFrm = pFrm->FindFooterOrHeader()) ) + return GetLayout()->Frm(); + break; + + case RECT_PAGES_AREA: return GetLayout()->GetPagesArea(); + + default: break; + } + return bFrm ? pFrm->Frm() : pFrm->Prt(); +} + + +USHORT SwFEShell::GetPageNumber( const Point &rPoint ) const +{ + const SwFrm *pPage = GetLayout()->Lower(); + while ( pPage && !pPage->Frm().IsInside( rPoint ) ) + pPage = pPage->GetNext(); + if ( pPage ) + return ((const SwPageFrm*)pPage)->GetPhyPageNum(); + else + return 0; +} + + +BOOL SwFEShell::GetPageNumber( long nYPos, BOOL bAtCrsrPos, USHORT& rPhyNum, USHORT& rVirtNum, String &rDisplay) const +{ + const SwFrm *pPage; + + if ( bAtCrsrPos ) //Seite vom Crsr besorgen + { + pPage = GetCurrFrm( FALSE ); + if ( pPage ) + pPage = pPage->FindPageFrm(); + } + else if ( nYPos > -1 ) //Seite ueber die Positon ermitteln + { + pPage = GetLayout()->Lower(); + while( pPage && (pPage->Frm().Bottom() < nYPos || + nYPos < pPage->Frm().Top() ) ) + pPage = pPage->GetNext(); + } + else //Die erste sichtbare Seite + { + pPage = Imp()->GetFirstVisPage(); + if ( pPage && ((SwPageFrm*)pPage)->IsEmptyPage() ) + pPage = pPage->GetNext(); + } + + if( pPage ) + { + rPhyNum = ((const SwPageFrm*)pPage)->GetPhyPageNum(); + rVirtNum = ((const SwPageFrm*)pPage)->GetVirtPageNum(); + const SvxNumberType& rNum = ((const SwPageFrm*)pPage)->GetPageDesc()->GetNumType(); + rDisplay = rNum.GetNumStr( rVirtNum ); + } + + return 0 != pPage; +} + +/************************************************************************* +|* +|* SwFEShell::IsDirectlyInSection() +|* +|* Hack for OS: +|* +*************************************************************************/ + +bool SwFEShell::IsDirectlyInSection() const +{ + SwFrm* pFrm = GetCurrFrm( FALSE ); + return pFrm && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm(); +} + +/************************************************************************* +|* +|* SwFEShell::GetFrmType() +|* +|* Ersterstellung MA 12. Jan. 93 +|* Letzte Aenderung AMA 25. Nov. 98 +|* +*************************************************************************/ + +USHORT SwFEShell::GetFrmType( const Point *pPt, BOOL bStopAtFly ) const +{ + USHORT nReturn = FRMTYPE_NONE; + const SwFrm *pFrm; + if ( pPt ) + { + SwPosition aPos( *GetCrsr()->GetPoint() ); + Point aPt( *pPt ); + GetLayout()->GetCrsrOfst( &aPos, aPt ); + SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode(); + pFrm = pNd->GetFrm( pPt ); + } + else + pFrm = GetCurrFrm( FALSE ); + while ( pFrm ) + { + switch ( pFrm->GetType() ) + { + case FRM_COLUMN: if( pFrm->GetUpper()->IsSctFrm() ) + { + // Check, if isn't not only a single column + // from a section with footnotes at the end. + if( pFrm->GetNext() || pFrm->GetPrev() ) + // Sectioncolumns + nReturn |= ( nReturn & FRMTYPE_TABLE ) ? + FRMTYPE_COLSECTOUTTAB : FRMTYPE_COLSECT; + } + else // nur Seiten und Rahmenspalten + nReturn |= FRMTYPE_COLUMN; + break; + case FRM_PAGE: nReturn |= FRMTYPE_PAGE; + if( ((SwPageFrm*)pFrm)->IsFtnPage() ) + nReturn |= FRMTYPE_FTNPAGE; + break; + case FRM_HEADER: nReturn |= FRMTYPE_HEADER; break; + case FRM_FOOTER: nReturn |= FRMTYPE_FOOTER; break; + case FRM_BODY: if( pFrm->GetUpper()->IsPageFrm() ) // nicht bei ColumnFrms + nReturn |= FRMTYPE_BODY; + break; + case FRM_FTN: nReturn |= FRMTYPE_FOOTNOTE; break; + case FRM_FLY: if( ((SwFlyFrm*)pFrm)->IsFlyLayFrm() ) + nReturn |= FRMTYPE_FLY_FREE; + else if ( ((SwFlyFrm*)pFrm)->IsFlyAtCntFrm() ) + nReturn |= FRMTYPE_FLY_ATCNT; + else + { + ASSERT( ((SwFlyFrm*)pFrm)->IsFlyInCntFrm(), + "Neuer Rahmentyp?" ); + nReturn |= FRMTYPE_FLY_INCNT; + } + nReturn |= FRMTYPE_FLY_ANY; + if( bStopAtFly ) + return nReturn; + break; + case FRM_TAB: + case FRM_ROW: + case FRM_CELL: nReturn |= FRMTYPE_TABLE; break; + default: /* do nothing */ break; + } + if ( pFrm->IsFlyFrm() ) + pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm(); + else + pFrm = pFrm->GetUpper(); + } + return nReturn; +} + +/************************************************************************* +|* +|* SwFEShell::ShLooseFcs(), ShGetFcs() +|* +|* Ersterstellung MA 10. May. 93 +|* Letzte Aenderung MA 09. Sep. 98 +|* +*************************************************************************/ + +void SwFEShell::ShGetFcs( BOOL bUpdate ) +{ + ::SetShell( this ); + SwCrsrShell::ShGetFcs( bUpdate ); + + if ( HasDrawView() ) + { + Imp()->GetDrawView()->showMarkHandles(); + if ( Imp()->GetDrawView()->AreObjectsMarked() ) + FrameNotify( this, FLY_DRAG_START ); + } +} + +void SwFEShell::ShLooseFcs() +{ + SwCrsrShell::ShLooseFcs(); + + if ( HasDrawView() && Imp()->GetDrawView()->AreObjectsMarked() ) + { + Imp()->GetDrawView()->hideMarkHandles(); + FrameNotify( this, FLY_DRAG_END ); + } +// ::ResetShell(); +} + +/************************************************************************* +|* +|* SwFEShell::GetPhyPageNum() +|* SwFEShell::GetVirtPageNum() +|* +|* Ersterstellung OK 07.07.93 08:20 +|* Letzte Aenderung MA 03. Jan. 94 +|* +*************************************************************************/ + +USHORT SwFEShell::GetPhyPageNum() +{ + SwFrm *pFrm = GetCurrFrm(); + if ( pFrm ) + return pFrm->GetPhyPageNum(); + return 0; +} + +USHORT SwFEShell::GetVirtPageNum( const BOOL bCalcFrm ) +{ + SwFrm *pFrm = GetCurrFrm( bCalcFrm ); + if ( pFrm ) + return pFrm->GetVirtPageNum(); + return 0; +} + +/************************************************************************* +|* +|* void lcl_SetAPageOffset() +|* void SwFEShell::SetNewPageOffset() +|* void SwFEShell::SetPageOffset() +|* USHORT SwFEShell::GetPageOffset() const +|* +|* Ersterstellung OK 07.07.93 08:20 +|* Letzte Aenderung MA 30. Mar. 95 +|* +*************************************************************************/ + +void lcl_SetAPageOffset( USHORT nOffset, SwPageFrm* pPage, SwFEShell* pThis ) +{ + pThis->StartAllAction(); + ASSERT( pPage->FindFirstBodyCntnt(), + "SwFEShell _SetAPageOffset() ohne CntntFrm" ); + + SwFmtPageDesc aDesc( pPage->GetPageDesc() ); + aDesc.SetNumOffset( nOffset ); + + SwFrm *pFrm = pThis->GetCurrFrm( FALSE ); + if ( pFrm->IsInTab() ) + pThis->GetDoc()->SetAttr( aDesc, *pFrm->FindTabFrm()->GetFmt() ); + else + { + pThis->GetDoc()->InsertPoolItem( *pThis->GetCrsr(), aDesc, 0 ); + } + + pThis->EndAllAction(); +} + +void SwFEShell::SetNewPageOffset( USHORT nOffset ) +{ + GetLayout()->SetVirtPageNum( TRUE ); + const SwPageFrm *pPage = GetCurrFrm( FALSE )->FindPageFrm(); + lcl_SetAPageOffset( nOffset, (SwPageFrm*)pPage, this ); +} + +void SwFEShell::SetPageOffset( USHORT nOffset ) +{ + const SwPageFrm *pPage = GetCurrFrm( FALSE )->FindPageFrm(); + const SwRootFrm* pLayout = GetLayout(); + while ( pPage ) + { + const SwFrm *pFlow = pPage->FindFirstBodyCntnt(); + if ( pFlow ) + { + if ( pFlow->IsInTab() ) + pFlow = pFlow->FindTabFrm(); + const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc(); + if ( rPgDesc.GetNumOffset() ) + { + pLayout->SetVirtPageNum( TRUE ); + lcl_SetAPageOffset( nOffset, (SwPageFrm*)pPage, this ); + break; + } + } + pPage = (SwPageFrm*)pPage->GetPrev(); + } +} + +USHORT SwFEShell::GetPageOffset() const +{ + const SwPageFrm *pPage = GetCurrFrm()->FindPageFrm(); + while ( pPage ) + { + const SwFrm *pFlow = pPage->FindFirstBodyCntnt(); + if ( pFlow ) + { + if ( pFlow->IsInTab() ) + pFlow = pFlow->FindTabFrm(); + const USHORT nOffset = pFlow->GetAttrSet()->GetPageDesc().GetNumOffset(); + if ( nOffset ) + return nOffset; + } + pPage = (SwPageFrm*)pPage->GetPrev(); + } + return 0; +} + +/************************************************************************* +|* +|* SwFEShell::InsertLabel() +|* +|* Ersterstellung MA 10. Feb. 94 +|* Letzte Aenderung MA 10. Feb. 94 +|* +*************************************************************************/ + +void SwFEShell::InsertLabel( const SwLabelType eType, const String &rTxt, const String& rSeparator, + const String& rNumberSeparator, + const BOOL bBefore, const USHORT nId, + const String& rCharacterStyle, + const BOOL bCpyBrd ) +{ + //NodeIndex der CrsrPosition besorgen, den Rest kann das Dokument + //selbst erledigen. + SwCntntFrm *pCnt = LTYPE_DRAW==eType ? 0 : GetCurrFrm( FALSE ); + if( LTYPE_DRAW==eType || pCnt ) + { + StartAllAction(); + + ULONG nIdx = 0; + SwFlyFrmFmt* pFlyFmt = 0; + switch( eType ) + { + case LTYPE_OBJECT: + case LTYPE_FLY: + if( pCnt->IsInFly() ) + { + //Bei Flys den Index auf den StartNode herunterreichen. + nIdx = pCnt->FindFlyFrm()-> + GetFmt()->GetCntnt().GetCntntIdx()->GetIndex(); +//warum?? Bug 61913 ParkCrsr( GetCrsr()->GetPoint()->nNode ); + } + break; + case LTYPE_TABLE: + if( pCnt->IsInTab() ) + { + //Bei Tabellen den Index auf den TblNode herunterreichen. + const SwTable& rTbl = *pCnt->FindTabFrm()->GetTable(); + nIdx = rTbl.GetTabSortBoxes()[ 0 ] + ->GetSttNd()->FindTableNode()->GetIndex(); + } + break; + case LTYPE_DRAW: + if( Imp()->GetDrawView() ) + { + SwDrawView *pDView = Imp()->GetDrawView(); + const SdrMarkList& rMrkList = pDView->GetMarkedObjectList(); + StartUndo(); + + // OD 27.11.2003 #112045# - copy marked drawing objects to + // local list to perform the corresponding action for each object + std::vector<SdrObject*> aDrawObjs; + { + for ( USHORT i = 0; i < rMrkList.GetMarkCount(); ++i ) + { + SdrObject* pDrawObj = rMrkList.GetMark(i)->GetMarkedSdrObj(); + aDrawObjs.push_back( pDrawObj ); + } + } + // loop on marked drawing objects + while ( !aDrawObjs.empty() ) + { + SdrObject* pDrawObj = aDrawObjs.back(); + if ( !pDrawObj->ISA(SwVirtFlyDrawObj) && + !pDrawObj->ISA(SwFlyDrawObj) ) + { + SwFlyFrmFmt *pFmt = + GetDoc()->InsertDrawLabel( rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, *pDrawObj ); + if( !pFlyFmt ) + pFlyFmt = pFmt; + } + + aDrawObjs.pop_back(); + } + + EndUndo(); + } + break; + default: + ASSERT( !this, "Crsr weder in Tabelle noch in Fly." ); + } + + if( nIdx ) + pFlyFmt = GetDoc()->InsertLabel( eType, rTxt, rSeparator, rNumberSeparator, bBefore, nId, + nIdx, rCharacterStyle, bCpyBrd ); + + SwFlyFrm* pFrm; + const Point aPt( GetCrsrDocPos() ); + if( pFlyFmt && 0 != ( pFrm = pFlyFmt->GetFrm( &aPt ))) + SelectFlyFrm( *pFrm, TRUE ); + + EndAllActionAndCall(); + } +} + + +/*********************************************************************** +#* Class : SwFEShell +#* Methoden : Sort +#* Datum : ?? +#* Update : ?? +#***********************************************************************/ + +BOOL SwFEShell::Sort(const SwSortOptions& rOpt) +{ + if( !HasSelection() ) + return FALSE; + + SET_CURR_SHELL( this ); + BOOL bRet; + StartAllAction(); + if(IsTableMode()) + { + // Tabelle sortieren + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm( FALSE ); + ASSERT( pFrm->FindTabFrm(), "Crsr nicht in Tabelle." ); + + // lasse ueber das Layout die Boxen suchen + SwSelBoxes aBoxes; + GetTblSel(*this, aBoxes); + + // die Crsr muessen noch aus dem Loesch Bereich entfernt + // werden. Setze sie immer hinter/auf die Tabelle; ueber die + // Dokument-Position werden sie dann immer an die alte Position gesetzt. + while( !pFrm->IsCellFrm() ) + pFrm = pFrm->GetUpper(); + { + /* #107993# ParkCursor->ParkCursorTab */ + ParkCursorInTab(); + } + + // Sorting am Dokument aufrufen + bRet = pDoc->SortTbl(aBoxes, rOpt); + } + else + { + // Text sortieren und nichts anderes + FOREACHPAM_START(this) + + SwPaM* pPam = PCURCRSR; + + SwPosition* pStart = pPam->Start(); + SwPosition* pEnd = pPam->End(); + + SwNodeIndex aPrevIdx( pStart->nNode, -1 ); + ULONG nOffset = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex(); + xub_StrLen nCntStt = pStart->nContent.GetIndex(); + + // Das Sortieren + bRet = pDoc->SortText(*pPam, rOpt); + + // Selektion wieder setzen + pPam->DeleteMark(); + pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 ); + SwCntntNode* pCNd = pPam->GetCntntNode(); + xub_StrLen nLen = pCNd->Len(); + if( nLen > nCntStt ) + nLen = nCntStt; + pPam->GetPoint()->nContent.Assign(pCNd, nLen ); + pPam->SetMark(); + + pPam->GetPoint()->nNode += nOffset; + pCNd = pPam->GetCntntNode(); + pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); + + FOREACHPAM_END() + } + + EndAllAction(); + return bRet; +} + +/************************************************************************* +|* +|* SwFEShell::GetCurColNum(), _GetColNum() +|* +|* Ersterstellung MA 03. Feb. 95 +|* Letzte Aenderung MA 20. Apr. 95 +| +|*************************************************************************/ + +USHORT SwFEShell::_GetCurColNum( const SwFrm *pFrm, + SwGetCurColNumPara* pPara ) const +{ + USHORT nRet = 0; + while ( pFrm ) + { + pFrm = pFrm->GetUpper(); + if( pFrm && pFrm->IsColumnFrm() ) + { + const SwFrm *pCurFrm = pFrm; + do { + ++nRet; + pFrm = pFrm->GetPrev(); + } while ( pFrm ); + + if( pPara ) + { + // dann suche mal das Format, was diese Spaltigkeit bestimmt + pFrm = pCurFrm->GetUpper(); + while( pFrm ) + { + if( ( FRM_PAGE | FRM_FLY | FRM_SECTION ) & pFrm->GetType() ) + { + pPara->pFrmFmt = ((SwLayoutFrm*)pFrm)->GetFmt(); + pPara->pPrtRect = &pFrm->Prt(); + pPara->pFrmRect = &pFrm->Frm(); + break; + } + pFrm = pFrm->GetUpper(); + } + if( !pFrm ) + { + pPara->pFrmFmt = 0; + pPara->pPrtRect = 0; + pPara->pFrmRect = 0; + } + } + break; + } + } + return nRet; +} + +USHORT SwFEShell::GetCurColNum( SwGetCurColNumPara* pPara ) const +{ + ASSERT( GetCurrFrm(), "Crsr geparkt?" ); + return _GetCurColNum( GetCurrFrm(), pPara ); +} + +USHORT SwFEShell::GetCurOutColNum( SwGetCurColNumPara* pPara ) const +{ + USHORT nRet = 0; + SwFrm* pFrm = GetCurrFrm(); + ASSERT( pFrm, "Crsr geparkt?" ); + if( pFrm ) + { + pFrm = pFrm->IsInTab() ? (SwFrm*)pFrm->FindTabFrm() + : (SwFrm*)pFrm->FindSctFrm(); + ASSERT( pFrm, "No Tab, no Sect" ); + if( pFrm ) + nRet = _GetCurColNum( pFrm, pPara ); + } + return nRet; +} + +SwFEShell::SwFEShell( SwDoc& rDoc, Window *pWindow, const SwViewOption *pOptions ) + : SwEditShell( rDoc, pWindow, pOptions ), + pChainFrom( 0 ), pChainTo( 0 ), bCheckForOLEInCaption( FALSE ) +{ +} + +SwFEShell::SwFEShell( SwEditShell& rShell, Window *pWindow ) + : SwEditShell( rShell, pWindow ), + pChainFrom( 0 ), pChainTo( 0 ), bCheckForOLEInCaption( FALSE ) +{ +} + +SwFEShell::~SwFEShell() +{ + delete pChainFrom; + delete pChainTo; +} + +// OD 18.09.2003 #i17567#, #108749#, #110354# - adjustments for allowing +// negative vertical positions for fly frames anchored to paragraph/to character. +// OD 06.11.2003 #i22305# - adjustments for option 'Follow text flow' +// for to frame anchored objects. +// OD 12.11.2003 #i22341# - adjustments for vertical alignment at top of line +// for to character anchored objects. +void SwFEShell::CalcBoundRect( SwRect& _orRect, + const RndStdIds _nAnchorId, + const sal_Int16 _eHoriRelOrient, + const sal_Int16 _eVertRelOrient, + const SwPosition* _pToCharCntntPos, + const bool _bFollowTextFlow, + bool _bMirror, + Point* _opRef, + Size* _opPercent ) const +{ + const SwFrm* pFrm; + const SwFlyFrm* pFly; + if( _opRef ) + { + pFrm = GetCurrFrm(); + if( 0 != ( pFly = pFrm->FindFlyFrm() ) ) + pFrm = pFly->GetAnchorFrm(); + } + else + { + pFly = FindFlyFrm(); + pFrm = pFly ? pFly->GetAnchorFrm() : GetCurrFrm(); + } + + sal_Bool bWrapThrough = sal_False; + if ( pFly ) + { + SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)pFly->GetFmt(); + const SwFmtSurround& rSurround = pFmt->GetSurround(); + bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT; + } + + const SwPageFrm* pPage = pFrm->FindPageFrm(); + _bMirror = _bMirror && !pPage->OnRightPage(); + + Point aPos; + BOOL bVertic = FALSE; + BOOL bRTL = FALSE; + + if ((FLY_AT_PAGE == _nAnchorId) || (FLY_AT_FLY == _nAnchorId)) // LAYER_IMPL + { + const SwFrm* pTmp = pFrm; + // OD 06.11.2003 #i22305# + if ((FLY_AT_PAGE == _nAnchorId) || + ((FLY_AT_FLY == _nAnchorId) && !_bFollowTextFlow)) + { + pFrm = pPage; + } + else + { + pFrm = pFrm->FindFlyFrm(); + } + if ( !pFrm ) + pFrm = pTmp; + _orRect = pFrm->Frm(); + SWRECTFN( pFrm ) + bRTL = pFrm->IsRightToLeft(); + if ( bRTL ) + aPos = pFrm->Frm().TopRight(); + else + aPos = (pFrm->Frm().*fnRect->fnGetPos)(); + + if( bVert ) + { + bVertic = TRUE; + _bMirror = false; // no mirroring in vertical environment + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::PAGE_RIGHT: + case text::RelOrientation::FRAME_RIGHT: aPos.Y() += pFrm->Prt().Height(); + // no break! + case text::RelOrientation::PRINT_AREA: + case text::RelOrientation::PAGE_PRINT_AREA: aPos.Y() += pFrm->Prt().Top(); break; + default: break; + } + } + else if ( _bMirror ) + { + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::PRINT_AREA: + case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Width(); + // kein break + case text::RelOrientation::PAGE_RIGHT: + case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Left(); break; + default: aPos.X() += pFrm->Frm().Width(); + } + } + else if ( bRTL ) + { + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::PRINT_AREA: + case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Width(); + // kein break! + case text::RelOrientation::PAGE_LEFT: + case text::RelOrientation::FRAME_LEFT: aPos.X() += pFrm->Prt().Left() - + pFrm->Frm().Width(); break; + default: break; + } + } + else + { + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::PAGE_RIGHT: + case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Width(); + // kein break! + case text::RelOrientation::PRINT_AREA: + case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Left(); break; + default:break; + } + } + // --> OD 2006-12-12 #i67221# - proposed patch + if( bVert ) + { + switch ( _eVertRelOrient ) + { + case text::RelOrientation::PRINT_AREA: + case text::RelOrientation::PAGE_PRINT_AREA: + { + aPos.X() -= pFrm->GetRightMargin(); + } + break; + } + } + else + { + switch ( _eVertRelOrient ) + { + case text::RelOrientation::PRINT_AREA: + case text::RelOrientation::PAGE_PRINT_AREA: + { + if ( pFrm->IsPageFrm() ) + { + aPos.Y() = + static_cast<const SwPageFrm*>(pFrm)->PrtWithoutHeaderAndFooter().Top(); + } + else + { + aPos.Y() += pFrm->Prt().Top(); + } + } + break; + } + } + // <-- + if ( _opPercent ) + *_opPercent = pFrm->Prt().SSize(); + } + else + { + const SwFrm* pUpper = ( pFrm->IsPageFrm() || pFrm->IsFlyFrm() ) ? + pFrm : pFrm->GetUpper(); + SWRECTFN( pUpper ); + if ( _opPercent ) + *_opPercent = pUpper->Prt().SSize(); + + bRTL = pFrm->IsRightToLeft(); + if ( bRTL ) + aPos = pFrm->Frm().TopRight(); + else + aPos = (pFrm->Frm().*fnRect->fnGetPos)(); + // OD 08.09.2003 #i17567#, #108749#, #110354# - allow negative positions + // for fly frames anchor to paragraph/to character. + if ((_nAnchorId == FLY_AT_PARA) || (_nAnchorId == FLY_AT_CHAR)) + { + // The rectangle, the fly frame can be positioned in, is determined + // horizontally by the frame area of the horizontal environment + // and vertically by the printing area of the vertical environment, + // if the object follows the text flow, or by the frame area of the + // vertical environment, if the object doesn't follow the text flow. + // OD 29.10.2003 #113049# - new class <SwEnvironmentOfAnchoredObject> + objectpositioning::SwEnvironmentOfAnchoredObject aEnvOfObj( + _bFollowTextFlow ); + const SwLayoutFrm& rHoriEnvironLayFrm = + aEnvOfObj.GetHoriEnvironmentLayoutFrm( *pFrm ); + const SwLayoutFrm& rVertEnvironLayFrm = + aEnvOfObj.GetVertEnvironmentLayoutFrm( *pFrm ); + SwRect aHoriEnvironRect( rHoriEnvironLayFrm.Frm() ); + SwRect aVertEnvironRect; + if ( _bFollowTextFlow ) + { + aVertEnvironRect = rVertEnvironLayFrm.Prt(); + aVertEnvironRect.Pos() += rVertEnvironLayFrm.Frm().Pos(); + // OD 19.09.2003 #i18732# - adjust vertical 'virtual' anchor position + // (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned + // to page areas. + if ( _eVertRelOrient == text::RelOrientation::PAGE_FRAME || _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA ) + { + if ( bVert ) + { + aPos.X() = aVertEnvironRect.Right(); + } + else + { + aPos.Y() = aVertEnvironRect.Top(); + } + } + } + else + { + ASSERT( rVertEnvironLayFrm.IsPageFrm(), + "<SwFEShell::CalcBoundRect(..)> - not following text flow, but vertical environment *not* page!" ); + aVertEnvironRect = rVertEnvironLayFrm.Frm(); + // OD 19.09.2003 #i18732# - adjustment vertical 'virtual' anchor position + // (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned + // to page areas. + if ( _eVertRelOrient == text::RelOrientation::PAGE_FRAME || _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA ) + { + if ( bVert ) + { + aPos.X() = aVertEnvironRect.Right(); + if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA ) + { + aPos.X() -= rVertEnvironLayFrm.GetRightMargin(); + } + } + else + { + aPos.Y() = aVertEnvironRect.Top(); + if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA ) + { + aPos.Y() += rVertEnvironLayFrm.GetTopMargin(); + // add height of page header + const SwFrm* pTmpFrm = rVertEnvironLayFrm.Lower(); + if ( pTmpFrm->IsHeaderFrm() ) + { + aPos.Y() += pTmpFrm->Frm().Height(); + } + } + } + } + } + + // OD 12.11.2003 #i22341# - adjust vertical 'virtual' anchor position + // (<aPos.Y()> respectively <aPos.X()>), if object is anchored to + // character and vertical aligned at character or top of line + // --> OD 2005-12-29 #125800# + // <pFrm>, which is the anchor frame or the proposed anchor frame, + // doesn't have to be a text frame (e.g. edit a to-page anchored + // fly frame). Thus, assure this. + const SwTxtFrm* pTxtFrm( dynamic_cast<const SwTxtFrm*>(pFrm) ); + if ( pTxtFrm && + (_nAnchorId == FLY_AT_CHAR) && + ( _eVertRelOrient == text::RelOrientation::CHAR || + _eVertRelOrient == text::RelOrientation::TEXT_LINE ) ) + { + SwTwips nTop = 0L; + if ( _eVertRelOrient == text::RelOrientation::CHAR ) + { + SwRect aChRect; + if ( _pToCharCntntPos ) + { + pTxtFrm->GetAutoPos( aChRect, *_pToCharCntntPos ); + } + else + { + // No content position provided. Thus, use a default one. + SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) ); + pTxtFrm->GetAutoPos( aChRect, aDefaultCntntPos ); + } + nTop = (aChRect.*fnRect->fnGetBottom)(); + } + else + { + if ( _pToCharCntntPos ) + { + pTxtFrm->GetTopOfLine( nTop, *_pToCharCntntPos ); + } + else + { + // No content position provided. Thus, use a default one. + SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) ); + pTxtFrm->GetTopOfLine( nTop, aDefaultCntntPos ); + } + } + if ( bVert ) + { + aPos.X() = nTop; + } + else + { + aPos.Y() = nTop; + } + } + + // --> OD 2004-10-05 #i26945# - adjust horizontal 'virtual' anchor + // position (<aPos.X()> respectively <aPos.Y()>), if object is + // anchored to character and horizontal aligned at character. + if ( pTxtFrm && + (_nAnchorId == FLY_AT_CHAR) && + _eHoriRelOrient == text::RelOrientation::CHAR ) + { + SwTwips nLeft = 0L; + SwRect aChRect; + if ( _pToCharCntntPos ) + { + pTxtFrm->GetAutoPos( aChRect, *_pToCharCntntPos ); + } + else + { + // No content position provided. Thus, use a default one. + SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) ); + pTxtFrm->GetAutoPos( aChRect, aDefaultCntntPos ); + } + nLeft = (aChRect.*fnRect->fnGetLeft)(); + if ( bVert ) + { + aPos.Y() = nLeft; + } + else + { + aPos.X() = nLeft; + } + } + // <-- + + if ( bVert ) + { + _orRect = SwRect( aVertEnvironRect.Left(), + aHoriEnvironRect.Top(), + aVertEnvironRect.Width(), + aHoriEnvironRect.Height() ); + } + else + { + _orRect = SwRect( aHoriEnvironRect.Left(), + aVertEnvironRect.Top(), + aHoriEnvironRect.Width(), + aVertEnvironRect.Height() ); + } + } + else + { + if( _opRef && pFly && pFly->IsFlyInCntFrm() ) + *_opRef = ( (SwFlyInCntFrm*)pFly )->GetRefPoint(); + + _orRect = pUpper->Frm(); + if( !pUpper->IsBodyFrm() ) + { + _orRect += pUpper->Prt().Pos(); + _orRect.SSize( pUpper->Prt().SSize() ); + if ( pUpper->IsCellFrm() )//MA_FLY_HEIGHT + { + const SwFrm* pTab = pUpper->FindTabFrm(); + long nBottom = (pTab->GetUpper()->*fnRect->fnGetPrtBottom)(); + (_orRect.*fnRect->fnSetBottom)( nBottom ); + } + } + // bei zeichengebundenen lieber nur 90% der Hoehe ausnutzen + { + if( bVert ) + _orRect.Width( (_orRect.Width()*9)/10 ); + else + _orRect.Height( (_orRect.Height()*9)/10 ); + } + } + + const SwTwips nBaseOfstForFly = ( pFrm->IsTxtFrm() && pFly ) ? + ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( !bWrapThrough ) : + 0; + if( bVert ) + { + bVertic = TRUE; + _bMirror = false; + + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::FRAME_RIGHT: aPos.Y() += pFrm->Prt().Height(); + aPos += (pFrm->Prt().*fnRect->fnGetPos)(); + break; + case text::RelOrientation::PRINT_AREA: aPos += (pFrm->Prt().*fnRect->fnGetPos)(); + aPos.Y() += nBaseOfstForFly; + break; + case text::RelOrientation::PAGE_RIGHT: aPos.Y() = pPage->Frm().Top() + + pPage->Prt().Bottom(); break; + case text::RelOrientation::PAGE_PRINT_AREA: aPos.Y() = pPage->Frm().Top() + + pPage->Prt().Top(); break; + case text::RelOrientation::PAGE_LEFT: + case text::RelOrientation::PAGE_FRAME: aPos.Y() = pPage->Frm().Top(); break; + case text::RelOrientation::FRAME: aPos.Y() += nBaseOfstForFly; break; + default: break; + } + } + else if( _bMirror ) + { + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Left(); break; + case text::RelOrientation::FRAME: + case text::RelOrientation::FRAME_LEFT: aPos.X() += pFrm->Frm().Width(); break; + case text::RelOrientation::PRINT_AREA: aPos.X() += pFrm->Prt().Right(); break; + case text::RelOrientation::PAGE_LEFT: + case text::RelOrientation::PAGE_FRAME: aPos.X() = pPage->Frm().Right(); break; + case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() = pPage->Frm().Left() + + pPage->Prt().Left(); break; + default: break; + } + } + else if ( bRTL ) + { + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::FRAME_LEFT: + aPos.X() = pFrm->Frm().Left() + + pFrm->Prt().Left(); + break; + + case text::RelOrientation::PRINT_AREA: + aPos.X() = pFrm->Frm().Left() + pFrm->Prt().Left() + + pFrm->Prt().Width(); + aPos.X() += nBaseOfstForFly; + break; + + case text::RelOrientation::PAGE_LEFT: + aPos.X() = pPage->Frm().Left() + pPage->Prt().Left(); + break; + + case text::RelOrientation::PAGE_PRINT_AREA: + aPos.X() = pPage->Frm().Left() + pPage->Prt().Left() + + pPage->Prt().Width() ; + break; + + case text::RelOrientation::PAGE_RIGHT: + case text::RelOrientation::PAGE_FRAME: + aPos.X() = pPage->Frm().Right(); + break; + + case text::RelOrientation::FRAME: + aPos.X() += nBaseOfstForFly; + break; + default: break; + } + } + else + { + switch ( _eHoriRelOrient ) + { + case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Width(); + aPos += pFrm->Prt().Pos(); + break; + case text::RelOrientation::PRINT_AREA: aPos += pFrm->Prt().Pos(); + aPos.X() += nBaseOfstForFly; + break; + case text::RelOrientation::PAGE_RIGHT: aPos.X() = pPage->Frm().Left() + + pPage->Prt().Right(); break; + case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() = pPage->Frm().Left() + + pPage->Prt().Left(); break; + case text::RelOrientation::PAGE_LEFT: + case text::RelOrientation::PAGE_FRAME: aPos.X() = pPage->Frm().Left(); break; + case text::RelOrientation::FRAME: aPos.X() += nBaseOfstForFly; break; + default: break; + } + } + + } + if( !_opRef ) + { + if( bVertic ) + _orRect.Pos( aPos.X() - _orRect.Width() - _orRect.Left(), _orRect.Top() - aPos.Y() ); + else if ( bRTL ) + _orRect.Pos( - ( _orRect.Right() - aPos.X() ), _orRect.Top() - aPos.Y() ); + else + _orRect.Pos( _orRect.Left() - aPos.X(), _orRect.Top() - aPos.Y() ); + if( _bMirror ) + _orRect.Pos( -_orRect.Right(), _orRect.Top() ); + } +} + +Size SwFEShell::GetGraphicDefaultSize() const +{ + Size aRet; + SwFlyFrm *pFly = FindFlyFrm(); + if ( pFly ) + { + // --> OD 2004-09-24 #i32951# - due to issue #i28701# no format of a + // newly inserted Writer fly frame or its anchor frame is performed + // any more. Thus, it could be possible (e.g. on insert of a horizontal + // line) that the anchor frame isn't formatted and its printing area + // size is (0,0). If this is the case the printing area of the upper + // of the anchor frame is taken. + const SwFrm* pAnchorFrm = pFly->GetAnchorFrm(); + aRet = pAnchorFrm->Prt().SSize(); + if ( aRet.Width() == 0 && aRet.Height() == 0 && + pAnchorFrm->GetUpper() ) + { + aRet = pAnchorFrm->GetUpper()->Prt().SSize(); + } + // <-- + + SwRect aBound; + CalcBoundRect( aBound, pFly->GetFmt()->GetAnchor().GetAnchorId()); + if ( pFly->GetAnchorFrm()->IsVertical() ) + aRet.Width() = aBound.Width(); + else + aRet.Height() = aBound.Height(); + } + return aRet; +} +/* -----------------------------12.08.2002 12:51------------------------------ + + ---------------------------------------------------------------------------*/ +BOOL SwFEShell::IsFrmVertical(BOOL bEnvironment, BOOL& bRTL) const +{ + BOOL bVert = FALSE; + bRTL = FALSE; + + if ( Imp()->HasDrawView() ) + { + const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList(); + if( rMrkList.GetMarkCount() != 1 ) + return bVert; + + SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj(); + // --> OD 2006-01-06 #123831# - make code robust: + if ( !pObj ) + { + ASSERT( false, + "<SwFEShell::IsFrmVertical(..)> - missing SdrObject instance in marked object list -> This is a serious situation, please inform OD" ); + return bVert; + } + // <-- + // OD 2004-03-29 #i26791# + SwContact* pContact = static_cast<SwContact*>(GetUserCall( pObj )); + // --> OD 2006-01-06 #123831# - make code robust: + if ( !pContact ) + { + ASSERT( false, + "<SwFEShell::IsFrmVertical(..)> - missing SwContact instance at marked object -> This is a serious situation, please inform OD" ); + return bVert; + } + // <-- + const SwFrm* pRef = pContact->GetAnchoredObj( pObj )->GetAnchorFrm(); + // --> OD 2006-01-06 #123831# - make code robust: + if ( !pRef ) + { + ASSERT( false, + "<SwFEShell::IsFrmVertical(..)> - missing anchor frame at marked object -> This is a serious situation, please inform OD" ); + return bVert; + } + // <-- + + if ( pObj->ISA(SwVirtFlyDrawObj) && !bEnvironment ) + pRef = static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm(); + + bVert = pRef->IsVertical(); + bRTL = pRef->IsRightToLeft(); + } + + return bVert; +} + +void SwFEShell::MoveObjectIfActive( svt::EmbeddedObjectRef&, const Point& ) +{ + // does not do anything, only avoids crash if the method is used for wrong shell +} + diff --git a/sw/source/core/frmedt/makefile.mk b/sw/source/core/frmedt/makefile.mk new file mode 100644 index 000000000000..8b277f899425 --- /dev/null +++ b/sw/source/core/frmedt/makefile.mk @@ -0,0 +1,76 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=sw +TARGET=frmedt + +AUTOSEG=true + +# --- Settings ----------------------------------------------------- + +.INCLUDE : $(PRJ)$/inc$/swpre.mk +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/inc$/sw.mk + + +.IF "$(mydebug)" != "" +CDEFS+=-Dmydebug +.ENDIF + +# --- Files -------------------------------------------------------- + +CXXFILES = \ + fecopy.cxx \ + fedesc.cxx \ + fefly1.cxx \ + feflyole.cxx \ + feshview.cxx \ + fetab.cxx \ + fews.cxx \ + tblsel.cxx + + + +SLOFILES = $(EXCEPTIONSFILES) \ + $(SLO)$/fedesc.obj \ + $(SLO)$/feflyole.obj \ + $(SLO)$/feshview.obj \ + $(SLO)$/fetab.obj \ + $(SLO)$/tblsel.obj + +EXCEPTIONSFILES=\ + $(SLO)$/fecopy.obj \ + $(SLO)$/fefly1.obj \ + $(SLO)$/fews.obj + + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sw/source/core/frmedt/tblsel.cxx b/sw/source/core/frmedt/tblsel.cxx new file mode 100644 index 000000000000..8cabf285e12b --- /dev/null +++ b/sw/source/core/frmedt/tblsel.cxx @@ -0,0 +1,2728 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +#include <hintids.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/protitem.hxx> +#include <fmtanchr.hxx> +#include <fmtfsize.hxx> +#include <frmatr.hxx> +#include <tblsel.hxx> +#include <crsrsh.hxx> +#include <doc.hxx> +#include <docary.hxx> +#include <pam.hxx> +#include <ndtxt.hxx> +#include <ndole.hxx> +#include <swtable.hxx> +#include <cntfrm.hxx> +#include <tabfrm.hxx> +#include <rowfrm.hxx> +#include <cellfrm.hxx> +#include <pagefrm.hxx> +#include <rootfrm.hxx> +#include <viscrs.hxx> +#include <swtblfmt.hxx> +#include <undobj.hxx> +#include <mvsave.hxx> +// OD 26.08.2003 #i18103# +#include <sectfrm.hxx> +#include <frmtool.hxx> + +//siehe auch swtable.cxx +#define COLFUZZY 20L + +// defines, die bestimmen, wie Tabellen Boxen gemergt werden: +// - 1. alle leeren Zeilen entfernen, alle Boxen werden mit Blank, +// alle Lines mit ParaBreak getrennt +// - 2. alle leeren Zeilen und alle leeren Boxen am Anfang und Ende +// entfernen, alle Boxen werden mit Blank, +// alle Lines mit ParaBreak getrennt +// - 3. alle leeren Boxen entfernen, alle Boxen werden mit Blank, +// alle Lines mit ParaBreak getrennt + +#undef DEL_ONLY_EMPTY_LINES +#undef DEL_EMPTY_BOXES_AT_START_AND_END +#define DEL_ALL_EMPTY_BOXES + + +_SV_IMPL_SORTAR_ALG( SwSelBoxes, SwTableBoxPtr ) +BOOL SwSelBoxes::Seek_Entry( const SwTableBoxPtr rSrch, USHORT* pFndPos ) const +{ + ULONG nIdx = rSrch->GetSttIdx(); + + USHORT nO = Count(), nM, nU = 0; + if( nO > 0 ) + { + nO--; + while( nU <= nO ) + { + nM = nU + ( nO - nU ) / 2; + if( (*this)[ nM ]->GetSttNd() == rSrch->GetSttNd() ) + { + if( pFndPos ) + *pFndPos = nM; + return TRUE; + } + else if( (*this)[ nM ]->GetSttIdx() < nIdx ) + nU = nM + 1; + else if( nM == 0 ) + { + if( pFndPos ) + *pFndPos = nU; + return FALSE; + } + else + nO = nM - 1; + } + } + if( pFndPos ) + *pFndPos = nU; + return FALSE; +} + + +SV_IMPL_PTRARR( SwCellFrms, SwCellFrm* ) + +struct _CmpLPt +{ + Point aPos; + const SwTableBox* pSelBox; + BOOL bVert; + + _CmpLPt( const Point& rPt, const SwTableBox* pBox, BOOL bVertical ); + + BOOL operator==( const _CmpLPt& rCmp ) const + { return X() == rCmp.X() && Y() == rCmp.Y() ? TRUE : FALSE; } + + BOOL operator<( const _CmpLPt& rCmp ) const + { + if ( bVert ) + return X() > rCmp.X() || ( X() == rCmp.X() && Y() < rCmp.Y() ) + ? TRUE : FALSE; + else + return Y() < rCmp.Y() || ( Y() == rCmp.Y() && X() < rCmp.X() ) + ? TRUE : FALSE; + } + + long X() const { return aPos.X(); } + long Y() const { return aPos.Y(); } +}; + + +SV_DECL_VARARR_SORT( _MergePos, _CmpLPt, 0, 40 ) +SV_IMPL_VARARR_SORT( _MergePos, _CmpLPt ) + +SV_IMPL_PTRARR( _FndBoxes, _FndBox* ) +SV_IMPL_PTRARR( _FndLines, _FndLine* ) + + +struct _Sort_CellFrm +{ + const SwCellFrm* pFrm; + + _Sort_CellFrm( const SwCellFrm& rCFrm ) + : pFrm( &rCFrm ) {} +}; + +SV_DECL_VARARR( _Sort_CellFrms, _Sort_CellFrm, 16, 16 ) +SV_IMPL_VARARR( _Sort_CellFrms, _Sort_CellFrm ) + +SV_IMPL_PTRARR( SwChartBoxes, SwTableBoxPtr ); +SV_IMPL_PTRARR( SwChartLines, SwChartBoxes* ); + +const SwLayoutFrm *lcl_FindCellFrm( const SwLayoutFrm *pLay ) +{ + while ( pLay && !pLay->IsCellFrm() ) + pLay = pLay->GetUpper(); + return pLay; +} + +const SwLayoutFrm *lcl_FindNextCellFrm( const SwLayoutFrm *pLay ) +{ + //Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche) + const SwLayoutFrm *pTmp = pLay; + do { + pTmp = pTmp->GetNextLayoutLeaf(); + } while( pLay->IsAnLower( pTmp ) ); + + while( pTmp && !pTmp->IsCellFrm() ) + pTmp = pTmp->GetUpper(); + return pTmp; +} + +void GetTblSelCrs( const SwCrsrShell &rShell, SwSelBoxes& rBoxes ) +{ + if( rBoxes.Count() ) + rBoxes.Remove( USHORT(0), rBoxes.Count() ); + if( rShell.IsTableMode() && ((SwCrsrShell&)rShell).UpdateTblSelBoxes()) + rBoxes.Insert( &rShell.GetTableCrsr()->GetBoxes() ); +} + +void GetTblSelCrs( const SwTableCursor& rTblCrsr, SwSelBoxes& rBoxes ) +{ + if( rBoxes.Count() ) + rBoxes.Remove( USHORT(0), rBoxes.Count() ); + + if( rTblCrsr.IsChgd() || !rTblCrsr.GetBoxesCount() ) + { + SwTableCursor* pTCrsr = (SwTableCursor*)&rTblCrsr; + pTCrsr->GetDoc()->GetRootFrm()->MakeTblCrsrs( *pTCrsr ); + } + + if( rTblCrsr.GetBoxesCount() ) + rBoxes.Insert( &rTblCrsr.GetBoxes() ); +} + +void GetTblSel( const SwCrsrShell& rShell, SwSelBoxes& rBoxes, + const SwTblSearchType eSearchType ) +{ + //Start- und Endzelle besorgen und den naechsten fragen. + if ( !rShell.IsTableMode() ) + rShell.GetCrsr(); + + GetTblSel( *rShell.getShellCrsr(false), rBoxes, eSearchType ); +} + +void GetTblSel( const SwCursor& rCrsr, SwSelBoxes& rBoxes, + const SwTblSearchType eSearchType ) +{ + //Start- und Endzelle besorgen und den naechsten fragen. + ASSERT( rCrsr.GetCntntNode() && rCrsr.GetCntntNode( FALSE ), + "Tabselection nicht auf Cnt." ); + + // Zeilen-Selektion: + // teste ob Tabelle komplex ist. Wenn ja, dann immer uebers Layout + // die selektierten Boxen zusammen suchen. Andernfalls ueber die + // Tabellen-Struktur (fuer Makros !!) + const SwCntntNode* pContentNd = rCrsr.GetNode()->GetCntntNode(); + const SwTableNode* pTblNd = pContentNd ? pContentNd->FindTableNode() : 0; + if( pTblNd && pTblNd->GetTable().IsNewModel() ) + { + SwTable::SearchType eSearch; + switch( nsSwTblSearchType::TBLSEARCH_COL & eSearchType ) + { + case nsSwTblSearchType::TBLSEARCH_ROW: eSearch = SwTable::SEARCH_ROW; break; + case nsSwTblSearchType::TBLSEARCH_COL: eSearch = SwTable::SEARCH_COL; break; + default: eSearch = SwTable::SEARCH_NONE; break; + } + const bool bChkP = 0 != ( nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType ); + pTblNd->GetTable().CreateSelection( rCrsr, rBoxes, eSearch, bChkP ); + return; + } + if( nsSwTblSearchType::TBLSEARCH_ROW == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) && + pTblNd && !pTblNd->GetTable().IsTblComplex() ) + { + const SwTable& rTbl = pTblNd->GetTable(); + const SwTableLines& rLines = rTbl.GetTabLines(); + + const SwNode* pMarkNode = rCrsr.GetNode( FALSE ); + const ULONG nMarkSectionStart = pMarkNode->StartOfSectionIndex(); + const SwTableBox* pMarkBox = rTbl.GetTblBox( nMarkSectionStart ); + + ASSERT( pMarkBox, "Point in table, mark outside?" ) + + const SwTableLine* pLine = pMarkBox ? pMarkBox->GetUpper() : 0; + USHORT nSttPos = rLines.GetPos( pLine ); + ASSERT( USHRT_MAX != nSttPos, "Wo ist meine Zeile in der Tabelle?" ); + pLine = rTbl.GetTblBox( rCrsr.GetNode( TRUE )->StartOfSectionIndex() )->GetUpper(); + USHORT nEndPos = rLines.GetPos( pLine ); + ASSERT( USHRT_MAX != nEndPos, "Wo ist meine Zeile in der Tabelle?" ); + // pb: #i20193# if tableintable then nSttPos == nEndPos == USHRT_MAX + if ( nSttPos != USHRT_MAX && nEndPos != USHRT_MAX ) + { + if( nEndPos < nSttPos ) // vertauschen + { + USHORT nTmp = nSttPos; nSttPos = nEndPos; nEndPos = nTmp; + } + + int bChkProtected = nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType; + for( ; nSttPos <= nEndPos; ++nSttPos ) + { + pLine = rLines[ nSttPos ]; + for( USHORT n = pLine->GetTabBoxes().Count(); n ; ) + { + SwTableBox* pBox = pLine->GetTabBoxes()[ --n ]; + // Zellenschutzt beachten ?? + if( !bChkProtected || + !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) + rBoxes.Insert( pBox ); + } + } + } + } + else + { + Point aPtPos, aMkPos; + const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr); + if( pShCrsr ) + { + aPtPos = pShCrsr->GetPtPos(); + aMkPos = pShCrsr->GetMkPos(); + } + const SwCntntNode *pCntNd = rCrsr.GetCntntNode(); + const SwLayoutFrm *pStart = pCntNd ? + pCntNd->GetFrm( &aPtPos )->GetUpper() : 0; + pCntNd = rCrsr.GetCntntNode(FALSE); + const SwLayoutFrm *pEnd = pCntNd ? + pCntNd->GetFrm( &aMkPos )->GetUpper() : 0; + if( pStart && pEnd ) + GetTblSel( pStart, pEnd, rBoxes, 0, eSearchType ); + } +} + +void GetTblSel( const SwLayoutFrm* pStart, const SwLayoutFrm* pEnd, + SwSelBoxes& rBoxes, SwCellFrms* pCells, + const SwTblSearchType eSearchType ) +{ + // #112697# Robust: + const SwTabFrm* pStartTab = pStart->FindTabFrm(); + if ( !pStartTab ) + { + ASSERT( false, "GetTblSel without start table" ) + return; + } + + int bChkProtected = nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType; + + BOOL bTblIsValid; + // --> FME 2006-01-25 #i55421# Reduced value 10 + int nLoopMax = 10; //JP 28.06.99: max 100 loops - Bug 67292 + // <-- + USHORT i; + + do { + bTblIsValid = TRUE; + + //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen. + SwSelUnions aUnions; + ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType ); + + Point aCurrentTopLeft( LONG_MAX, LONG_MAX ); + Point aCurrentTopRight( 0, LONG_MAX ); + Point aCurrentBottomLeft( LONG_MAX, 0 ); + Point aCurrentBottomRight( 0, 0 ); + const SwCellFrm* pCurrentTopLeftFrm = 0; + const SwCellFrm* pCurrentTopRightFrm = 0; + const SwCellFrm* pCurrentBottomLeftFrm = 0; + const SwCellFrm* pCurrentBottomRightFrm = 0; + + //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen. + for( i = 0; i < aUnions.Count() && bTblIsValid; ++i ) + { + SwSelUnion *pUnion = aUnions[i]; + const SwTabFrm *pTable = pUnion->GetTable(); + if( !pTable->IsValid() && nLoopMax ) + { + bTblIsValid = FALSE; + break; + } + + // Skip any repeated headlines in the follow: + const SwLayoutFrm* pRow = pTable->IsFollow() ? + pTable->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTable->Lower(); + + while( pRow && bTblIsValid ) + { + if( !pRow->IsValid() && nLoopMax ) + { + bTblIsValid = FALSE; + break; + } + + if ( pRow->Frm().IsOver( pUnion->GetUnion() ) ) + { + const SwLayoutFrm *pCell = pRow->FirstCell(); + + while( bTblIsValid && pCell && pRow->IsAnLower( pCell ) ) + { + if( !pCell->IsValid() && nLoopMax ) + { + bTblIsValid = FALSE; + break; + } + + ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" ); + if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) ) + { + SwTableBox* pBox = (SwTableBox*) + ((SwCellFrm*)pCell)->GetTabBox(); + // Zellenschutzt beachten ?? + if( !bChkProtected || + !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) + rBoxes.Insert( pBox ); + + if ( pCells ) + { + const Point aTopLeft( pCell->Frm().TopLeft() ); + const Point aTopRight( pCell->Frm().TopRight() ); + const Point aBottomLeft( pCell->Frm().BottomLeft() ); + const Point aBottomRight( pCell->Frm().BottomRight() ); + + if ( aTopLeft.Y() < aCurrentTopLeft.Y() || + ( aTopLeft.Y() == aCurrentTopLeft.Y() && + aTopLeft.X() < aCurrentTopLeft.X() ) ) + { + aCurrentTopLeft = aTopLeft; + pCurrentTopLeftFrm = static_cast<const SwCellFrm*>( pCell ); + } + + if ( aTopRight.Y() < aCurrentTopRight.Y() || + ( aTopRight.Y() == aCurrentTopRight.Y() && + aTopRight.X() > aCurrentTopRight.X() ) ) + { + aCurrentTopRight = aTopRight; + pCurrentTopRightFrm = static_cast<const SwCellFrm*>( pCell ); + } + + if ( aBottomLeft.Y() > aCurrentBottomLeft.Y() || + ( aBottomLeft.Y() == aCurrentBottomLeft.Y() && + aBottomLeft.X() < aCurrentBottomLeft.X() ) ) + { + aCurrentBottomLeft = aBottomLeft; + pCurrentBottomLeftFrm = static_cast<const SwCellFrm*>( pCell ); + } + + if ( aBottomRight.Y() > aCurrentBottomRight.Y() || + ( aBottomRight.Y() == aCurrentBottomRight.Y() && + aBottomRight.X() > aCurrentBottomRight.X() ) ) + { + aCurrentBottomRight = aBottomRight; + pCurrentBottomRightFrm = static_cast<const SwCellFrm*>( pCell ); + } + + } + } + if ( pCell->GetNext() ) + { + pCell = (const SwLayoutFrm*)pCell->GetNext(); + if ( pCell->Lower() && pCell->Lower()->IsRowFrm() ) + pCell = pCell->FirstCell(); + } + else + pCell = ::lcl_FindNextCellFrm( pCell ); + } + } + pRow = (const SwLayoutFrm*)pRow->GetNext(); + } + } + + if ( pCells ) + { + pCells->Remove( 0, pCells->Count() ); + pCells->Insert( pCurrentTopLeftFrm, 0 ); + pCells->Insert( pCurrentTopRightFrm, 1 ); + pCells->Insert( pCurrentBottomLeftFrm, 2 ); + pCells->Insert( pCurrentBottomRightFrm, 3 ); + } + + if( bTblIsValid ) + break; + + SwDeletionChecker aDelCheck( pStart ); + + // ansonsten das Layout der Tabelle kurz "kalkulieren" lassen + // und nochmals neu aufsetzen + SwTabFrm *pTable = aUnions[0]->GetTable(); + while( pTable ) + { + if( pTable->IsValid() ) + pTable->InvalidatePos(); + pTable->SetONECalcLowers(); + pTable->Calc(); + pTable->SetCompletePaint(); + if( 0 == (pTable = pTable->GetFollow()) ) + break; + } + + // --> FME 2005-10-13 #125337# Make code robust, check if pStart has + // been deleted due to the formatting of the table: + if ( aDelCheck.HasBeenDeleted() ) + { + ASSERT( false, "Current box has been deleted during GetTblSel()" ) + break; + } + // <-- + + i = 0; + rBoxes.Remove( i, rBoxes.Count() ); + --nLoopMax; + + } while( TRUE ); + ASSERT( nLoopMax, "das Layout der Tabelle wurde nicht valide!" ); +} + + + +BOOL ChkChartSel( const SwNode& rSttNd, const SwNode& rEndNd, + SwChartLines* pGetCLines ) +{ + const SwTableNode* pTNd = rSttNd.FindTableNode(); + if( !pTNd ) + return FALSE; + + Point aNullPos; + SwNodeIndex aIdx( rSttNd ); + const SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); + if( !pCNd ) + pCNd = aIdx.GetNodes().GoNextSection( &aIdx, FALSE, FALSE ); + + // #109394# if table is invisible, return + // (layout needed for forming table selection further down, so we can't + // continue with invisible tables) + // OD 07.11.2003 #i22135# - Also the content of the table could be + // invisible - e.g. in a hidden section + // Robust: check, if content was found (e.g. empty table cells) + if ( !pCNd || pCNd->GetFrm() == NULL ) + return FALSE; + + const SwLayoutFrm *pStart = pCNd ? pCNd->GetFrm( &aNullPos )->GetUpper() : 0; + ASSERT( pStart, "ohne Frame geht gar nichts" ); + + aIdx = rEndNd; + pCNd = aIdx.GetNode().GetCntntNode(); + if( !pCNd ) + pCNd = aIdx.GetNodes().GoNextSection( &aIdx, FALSE, FALSE ); + + // OD 07.11.2003 #i22135# - Robust: check, if content was found and if it's visible + if ( !pCNd || pCNd->GetFrm() == NULL ) + { + return FALSE; + } + + const SwLayoutFrm *pEnd = pCNd ? pCNd->GetFrm( &aNullPos )->GetUpper() : 0; + ASSERT( pEnd, "ohne Frame geht gar nichts" ); + + + BOOL bTblIsValid, bValidChartSel; + // --> FME 2006-01-25 #i55421# Reduced value 10 + int nLoopMax = 10; //JP 28.06.99: max 100 loops - Bug 67292 + // <-- + USHORT i = 0; + + do { + bTblIsValid = TRUE; + bValidChartSel = TRUE; + + USHORT nRowCells = USHRT_MAX; + + //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen. + SwSelUnions aUnions; + ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT ); + + //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen. + for( i = 0; i < aUnions.Count() && bTblIsValid && + bValidChartSel; ++i ) + { + SwSelUnion *pUnion = aUnions[i]; + const SwTabFrm *pTable = pUnion->GetTable(); + + SWRECTFN( pTable ) + sal_Bool bRTL = pTable->IsRightToLeft(); + + if( !pTable->IsValid() && nLoopMax ) + { + bTblIsValid = FALSE; + break; + } + + _Sort_CellFrms aCellFrms; + + // Skip any repeated headlines in the follow: + const SwLayoutFrm* pRow = pTable->IsFollow() ? + pTable->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTable->Lower(); + + while( pRow && bTblIsValid && bValidChartSel ) + { + if( !pRow->IsValid() && nLoopMax ) + { + bTblIsValid = FALSE; + break; + } + + if( pRow->Frm().IsOver( pUnion->GetUnion() ) ) + { + const SwLayoutFrm *pCell = pRow->FirstCell(); + + while( bValidChartSel && bTblIsValid && pCell && + pRow->IsAnLower( pCell ) ) + { + if( !pCell->IsValid() && nLoopMax ) + { + bTblIsValid = FALSE; + break; + } + + ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" ); + const SwRect& rUnion = pUnion->GetUnion(), + & rFrmRect = pCell->Frm(); + + const long nUnionRight = rUnion.Right(); + const long nUnionBottom = rUnion.Bottom(); + const long nFrmRight = rFrmRect.Right(); + const long nFrmBottom = rFrmRect.Bottom(); + + // liegt das FrmRect ausserhalb der Union, kann es + // ignoriert werden. + + const long nXFuzzy = bVert ? 0 : 20; + const long nYFuzzy = bVert ? 20 : 0; + + if( !( rUnion.Top() + nYFuzzy > nFrmBottom || + nUnionBottom < rFrmRect.Top() + nYFuzzy || + rUnion.Left() + nXFuzzy > nFrmRight || + nUnionRight < rFrmRect.Left() + nXFuzzy )) + { + // ok, rUnion is _not_ completely outside of rFrmRect + + // wenn es aber nicht komplett in der Union liegt, + // dann ist es fuers Chart eine ungueltige + // Selektion. + if( rUnion.Left() <= rFrmRect.Left() + nXFuzzy && + rFrmRect.Left() <= nUnionRight && + rUnion.Left() <= nFrmRight && + nFrmRight <= nUnionRight + nXFuzzy && + rUnion.Top() <= rFrmRect.Top() + nYFuzzy && + rFrmRect.Top() <= nUnionBottom && + rUnion.Top() <= nFrmBottom && + nFrmBottom <= nUnionBottom+ nYFuzzy ) + + aCellFrms.Insert( + _Sort_CellFrm( *(SwCellFrm*)pCell ), + aCellFrms.Count() ); + else + { + bValidChartSel = FALSE; + break; + } + } + if ( pCell->GetNext() ) + { + pCell = (const SwLayoutFrm*)pCell->GetNext(); + if ( pCell->Lower() && pCell->Lower()->IsRowFrm() ) + pCell = pCell->FirstCell(); + } + else + pCell = ::lcl_FindNextCellFrm( pCell ); + } + } + pRow = (const SwLayoutFrm*)pRow->GetNext(); + } + + if( !bValidChartSel ) + break; + + // alle Zellen der (Teil-)Tabelle zusammen. Dann teste mal ob + // all huebsch nebeneinander liegen. + USHORT n, nEnd, nCellCnt = 0; + long nYPos = LONG_MAX; + long nXPos = 0; + long nHeight = 0; + + for( n = 0, nEnd = aCellFrms.Count(); n < nEnd; ++n ) + { + const _Sort_CellFrm& rCF = aCellFrms[ n ]; + if( (rCF.pFrm->Frm().*fnRect->fnGetTop)() != nYPos ) + { + // neue Zeile + if( n ) + { + if( USHRT_MAX == nRowCells ) // 1. Zeilenwechsel + nRowCells = nCellCnt; + else if( nRowCells != nCellCnt ) + { + bValidChartSel = FALSE; + break; + } + } + nCellCnt = 1; + nYPos = (rCF.pFrm->Frm().*fnRect->fnGetTop)(); + nHeight = (rCF.pFrm->Frm().*fnRect->fnGetHeight)(); + + nXPos = bRTL ? + (rCF.pFrm->Frm().*fnRect->fnGetLeft)() : + (rCF.pFrm->Frm().*fnRect->fnGetRight)(); + } + else if( nXPos == ( bRTL ? + (rCF.pFrm->Frm().*fnRect->fnGetRight)() : + (rCF.pFrm->Frm().*fnRect->fnGetLeft)() ) && + nHeight == (rCF.pFrm->Frm().*fnRect->fnGetHeight)() ) + { + nXPos += ( bRTL ? (-1) : 1 ) * + (rCF.pFrm->Frm().*fnRect->fnGetWidth)(); + ++nCellCnt; + } + else + { + bValidChartSel = FALSE; + break; + } + } + if( bValidChartSel ) + { + if( USHRT_MAX == nRowCells ) + nRowCells = nCellCnt; + else if( nRowCells != nCellCnt ) + bValidChartSel = FALSE; + } + + if( bValidChartSel && pGetCLines ) + { + nYPos = LONG_MAX; + SwChartBoxes* pBoxes = 0; + for( n = 0, nEnd = aCellFrms.Count(); n < nEnd; ++n ) + { + const _Sort_CellFrm& rCF = aCellFrms[ n ]; + if( (rCF.pFrm->Frm().*fnRect->fnGetTop)() != nYPos ) + { + pBoxes = new SwChartBoxes( 255 < nRowCells + ? 255 : (BYTE)nRowCells); + pGetCLines->C40_INSERT( SwChartBoxes, pBoxes, pGetCLines->Count() ); + nYPos = (rCF.pFrm->Frm().*fnRect->fnGetTop)(); + } + SwTableBoxPtr pBox = (SwTableBox*)rCF.pFrm->GetTabBox(); + pBoxes->Insert( pBox, pBoxes->Count() ); + } + } + } + + if( bTblIsValid ) + break; + + // ansonsten das Layout der Tabelle kurz "kalkulieren" lassen + // und nochmals neu aufsetzen + SwTabFrm *pTable = aUnions[0]->GetTable(); + for( i = 0; i < aUnions.Count(); ++i ) + { + if( pTable->IsValid() ) + pTable->InvalidatePos(); + pTable->SetONECalcLowers(); + pTable->Calc(); + pTable->SetCompletePaint(); + if( 0 == (pTable = pTable->GetFollow()) ) + break; + } + --nLoopMax; + if( pGetCLines ) + pGetCLines->DeleteAndDestroy( 0, pGetCLines->Count() ); + } while( TRUE ); + + ASSERT( nLoopMax, "das Layout der Tabelle wurde nicht valide!" ); + + if( !bValidChartSel && pGetCLines ) + pGetCLines->DeleteAndDestroy( 0, pGetCLines->Count() ); + + return bValidChartSel; +} + + +BOOL IsFrmInTblSel( const SwRect& rUnion, const SwFrm* pCell ) +{ + ASSERT( pCell->IsCellFrm(), "Frame ohne Gazelle" ); + + if( pCell->FindTabFrm()->IsVertical() ) + return ( rUnion.Right() >= pCell->Frm().Right() && + rUnion.Left() <= pCell->Frm().Left() && + (( rUnion.Top() <= pCell->Frm().Top()+20 && + rUnion.Bottom() > pCell->Frm().Top() ) || + ( rUnion.Top() >= pCell->Frm().Top() && + rUnion.Bottom() < pCell->Frm().Bottom() )) ? TRUE : FALSE ); + + return ( + rUnion.Top() <= pCell->Frm().Top() && + rUnion.Bottom() >= pCell->Frm().Bottom() && + + (( rUnion.Left() <= pCell->Frm().Left()+20 && + rUnion.Right() > pCell->Frm().Left() ) || + + ( rUnion.Left() >= pCell->Frm().Left() && + rUnion.Right() < pCell->Frm().Right() )) ? TRUE : FALSE ); +} + +BOOL GetAutoSumSel( const SwCrsrShell& rShell, SwCellFrms& rBoxes ) +{ + SwShellCrsr* pCrsr = rShell.pCurCrsr; + if ( rShell.IsTableMode() ) + pCrsr = rShell.pTblCrsr; + + const SwLayoutFrm *pStart = pCrsr->GetCntntNode()->GetFrm( + &pCrsr->GetPtPos() )->GetUpper(), + *pEnd = pCrsr->GetCntntNode(FALSE)->GetFrm( + &pCrsr->GetMkPos() )->GetUpper(); + + const SwLayoutFrm* pSttCell = pStart; + while( pSttCell && !pSttCell->IsCellFrm() ) + pSttCell = pSttCell->GetUpper(); + + //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen. + SwSelUnions aUnions; + + // default erstmal nach oben testen, dann nach links + ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_COL ); + + BOOL bTstRow = TRUE, bFound = FALSE; + USHORT i; + + // 1. teste ob die darueber liegende Box Value/Formel enhaelt: + for( i = 0; i < aUnions.Count(); ++i ) + { + SwSelUnion *pUnion = aUnions[i]; + const SwTabFrm *pTable = pUnion->GetTable(); + + // Skip any repeated headlines in the follow: + const SwLayoutFrm* pRow = pTable->IsFollow() ? + pTable->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTable->Lower(); + + while( pRow ) + { + if( pRow->Frm().IsOver( pUnion->GetUnion() ) ) + { + const SwCellFrm* pUpperCell = 0; + const SwLayoutFrm *pCell = pRow->FirstCell(); + + while( pCell && pRow->IsAnLower( pCell ) ) + { + if( pCell == pSttCell ) + { + USHORT nWhichId = 0; + for( USHORT n = rBoxes.Count(); n; ) + if( USHRT_MAX != ( nWhichId = rBoxes[ --n ] + ->GetTabBox()->IsFormulaOrValueBox() )) + break; + + // alle Boxen zusammen, nicht mehr die Zeile + // pruefen, wenn eine Formel oder Value gefunden wurde + bTstRow = 0 == nWhichId || USHRT_MAX == nWhichId; + bFound = TRUE; + break; + } + + ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" ); + if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) ) + pUpperCell = (SwCellFrm*)pCell; + + if( pCell->GetNext() ) + { + pCell = (const SwLayoutFrm*)pCell->GetNext(); + if ( pCell->Lower() && pCell->Lower()->IsRowFrm() ) + pCell = pCell->FirstCell(); + } + else + pCell = ::lcl_FindNextCellFrm( pCell ); + } + + if( pUpperCell ) + rBoxes.Insert( pUpperCell, rBoxes.Count() ); + } + if( bFound ) + { + i = aUnions.Count(); + break; + } + pRow = (const SwLayoutFrm*)pRow->GetNext(); + } + } + + + // 2. teste ob die links liegende Box Value/Formel enhaelt: + if( bTstRow ) + { + bFound = FALSE; + + rBoxes.Remove( 0, rBoxes.Count() ); + aUnions.DeleteAndDestroy( 0, aUnions.Count() ); + ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_ROW ); + + for( i = 0; i < aUnions.Count(); ++i ) + { + SwSelUnion *pUnion = aUnions[i]; + const SwTabFrm *pTable = pUnion->GetTable(); + + // Skip any repeated headlines in the follow: + const SwLayoutFrm* pRow = pTable->IsFollow() ? + pTable->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTable->Lower(); + + while( pRow ) + { + if( pRow->Frm().IsOver( pUnion->GetUnion() ) ) + { + const SwLayoutFrm *pCell = pRow->FirstCell(); + + while( pCell && pRow->IsAnLower( pCell ) ) + { + if( pCell == pSttCell ) + { + USHORT nWhichId = 0; + for( USHORT n = rBoxes.Count(); n; ) + if( USHRT_MAX != ( nWhichId = rBoxes[ --n ] + ->GetTabBox()->IsFormulaOrValueBox() )) + break; + + // alle Boxen zusammen, nicht mehr die Zeile + // pruefen, wenn eine Formel oder Value gefunden wurde + bFound = 0 != nWhichId && USHRT_MAX != nWhichId; + bTstRow = FALSE; + break; + } + + ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" ); + if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) ) + { + const SwCellFrm* pC = (SwCellFrm*)pCell; + rBoxes.Insert( pC, rBoxes.Count() ); + } + if( pCell->GetNext() ) + { + pCell = (const SwLayoutFrm*)pCell->GetNext(); + if ( pCell->Lower() && pCell->Lower()->IsRowFrm() ) + pCell = pCell->FirstCell(); + } + else + pCell = ::lcl_FindNextCellFrm( pCell ); + } + } + if( !bTstRow ) + { + i = aUnions.Count(); + break; + } + + pRow = (const SwLayoutFrm*)pRow->GetNext(); + } + } + } + + return bFound; +} + +BOOL HasProtectedCells( const SwSelBoxes& rBoxes ) +{ + BOOL bRet = FALSE; + for( USHORT n = 0, nCnt = rBoxes.Count(); n < nCnt; ++n ) + if( rBoxes[ n ]->GetFrmFmt()->GetProtect().IsCntntProtected() ) + { + bRet = TRUE; + break; + } + return bRet; +} + + +_CmpLPt::_CmpLPt( const Point& rPt, const SwTableBox* pBox, BOOL bVertical ) + : aPos( rPt ), pSelBox( pBox ), bVert( bVertical ) +{} + +void lcl_InsTblBox( SwTableNode* pTblNd, SwDoc* pDoc, SwTableBox* pBox, + USHORT nInsPos, USHORT nCnt = 1 ) +{ + ASSERT( pBox->GetSttNd(), "Box ohne Start-Node" ); + SwCntntNode* pCNd = pDoc->GetNodes()[ pBox->GetSttIdx() + 1 ] + ->GetCntntNode(); + if( pCNd && pCNd->IsTxtNode() ) + pDoc->GetNodes().InsBoxen( pTblNd, pBox->GetUpper(), + (SwTableBoxFmt*)pBox->GetFrmFmt(), + ((SwTxtNode*)pCNd)->GetTxtColl(), + pCNd->GetpSwAttrSet(), + nInsPos, nCnt ); + else + pDoc->GetNodes().InsBoxen( pTblNd, pBox->GetUpper(), + (SwTableBoxFmt*)pBox->GetFrmFmt(), + (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0, + nInsPos, nCnt ); +} + +BOOL IsEmptyBox( const SwTableBox& rBox, SwPaM& rPam ) +{ + rPam.GetPoint()->nNode = *rBox.GetSttNd()->EndOfSectionNode(); + rPam.Move( fnMoveBackward, fnGoCntnt ); + rPam.SetMark(); + rPam.GetPoint()->nNode = *rBox.GetSttNd(); + rPam.Move( fnMoveForward, fnGoCntnt ); + BOOL bRet = *rPam.GetMark() == *rPam.GetPoint() + && ( rBox.GetSttNd()->GetIndex() + 1 == rPam.GetPoint()->nNode.GetIndex() ); + + if( bRet ) + { + // dann teste mal auf absatzgebundenen Flys + const SwSpzFrmFmts& rFmts = *rPam.GetDoc()->GetSpzFrmFmts(); + ULONG nSttIdx = rPam.GetPoint()->nNode.GetIndex(), + nEndIdx = rBox.GetSttNd()->EndOfSectionIndex(), + nIdx; + + for( USHORT n = 0; n < rFmts.Count(); ++n ) + { + const SwFmtAnchor& rAnchor = rFmts[n]->GetAnchor(); + const SwPosition* pAPos = rAnchor.GetCntntAnchor(); + if (pAPos && + ((FLY_AT_PARA == rAnchor.GetAnchorId()) || + (FLY_AT_CHAR == rAnchor.GetAnchorId())) && + nSttIdx <= ( nIdx = pAPos->nNode.GetIndex() ) && + nIdx < nEndIdx ) + { + bRet = FALSE; + break; + } + } + } + return bRet; +} + + +void GetMergeSel( const SwPaM& rPam, SwSelBoxes& rBoxes, + SwTableBox** ppMergeBox, SwUndoTblMerge* pUndo ) +{ + if( rBoxes.Count() ) + rBoxes.Remove( USHORT(0), rBoxes.Count() ); + + //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen. + ASSERT( rPam.GetCntntNode() && rPam.GetCntntNode( FALSE ), + "Tabselection nicht auf Cnt." ); + +//JP 24.09.96: Merge mit wiederholenden TabellenHeadline funktioniert nicht +// richtig. Warum nicht Point 0,0 benutzen? Dann ist garantiert, +// das die 1. Headline mit drin ist. +// Point aPt( rShell.GetCharRect().Pos() ); + Point aPt( 0, 0 ); + const SwLayoutFrm *pStart = rPam.GetCntntNode()->GetFrm( + &aPt )->GetUpper(), + *pEnd = rPam.GetCntntNode(FALSE)->GetFrm( + &aPt )->GetUpper(); + + SwSelUnions aUnions; + ::MakeSelUnions( aUnions, pStart, pEnd ); + if( !aUnions.Count() ) + return; + + const SwTable *pTable = aUnions[0]->GetTable()->GetTable(); + SwDoc* pDoc = (SwDoc*)pStart->GetFmt()->GetDoc(); + SwTableNode* pTblNd = (SwTableNode*)pTable->GetTabSortBoxes()[ 0 ]-> + GetSttNd()->FindTableNode(); + + _MergePos aPosArr; // Sort-Array mit den Positionen der Frames + long nWidth; + SwTableBox* pLastBox = 0; + + SWRECTFN( pStart->GetUpper() ) + + for ( USHORT i = 0; i < aUnions.Count(); ++i ) + { + const SwTabFrm *pTabFrm = aUnions[i]->GetTable(); + + SwRect &rUnion = aUnions[i]->GetUnion(); + + // Skip any repeated headlines in the follow: + const SwLayoutFrm* pRow = pTabFrm->IsFollow() ? + pTabFrm->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTabFrm->Lower(); + + while ( pRow ) + { + if ( pRow->Frm().IsOver( rUnion ) ) + { + const SwLayoutFrm *pCell = pRow->FirstCell(); + + while ( pCell && pRow->IsAnLower( pCell ) ) + { + ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" ); + // in der vollen Breite ueberlappend ? + if( rUnion.Top() <= pCell->Frm().Top() && + rUnion.Bottom() >= pCell->Frm().Bottom() ) + { + SwTableBox* pBox =(SwTableBox*)((SwCellFrm*)pCell)->GetTabBox(); + + // nur nach rechts ueberlappend + if( ( rUnion.Left() - COLFUZZY ) <= pCell->Frm().Left() && + ( rUnion.Right() - COLFUZZY ) > pCell->Frm().Left() ) + { + if( ( rUnion.Right() + COLFUZZY ) < pCell->Frm().Right() ) + { + USHORT nInsPos = pBox->GetUpper()-> + GetTabBoxes().C40_GETPOS( SwTableBox, pBox )+1; + lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos ); + pBox->ClaimFrmFmt(); + SwFmtFrmSize aNew( + pBox->GetFrmFmt()->GetFrmSize() ); + nWidth = rUnion.Right() - pCell->Frm().Left(); + nWidth = nWidth * aNew.GetWidth() / + pCell->Frm().Width(); + long nTmpWidth = aNew.GetWidth() - nWidth; + aNew.SetWidth( nWidth ); + pBox->GetFrmFmt()->SetFmtAttr( aNew ); + // diese Box ist selektiert + pLastBox = pBox; + rBoxes.Insert( pBox ); + aPosArr.Insert( + _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(), + pBox, bVert ) ); + + pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ]; + aNew.SetWidth( nTmpWidth ); + pBox->ClaimFrmFmt(); + pBox->GetFrmFmt()->SetFmtAttr( aNew ); + + if( pUndo ) + pUndo->AddNewBox( pBox->GetSttIdx() ); + } + else + { + // diese Box ist selektiert + pLastBox = pBox; + rBoxes.Insert( pBox ); +#if OSL_DEBUG_LEVEL > 1 + Point aInsPoint( (pCell->Frm().*fnRect->fnGetPos)() ); +#endif + aPosArr.Insert( + _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(), + pBox, bVert ) ); + } + } + // oder rechts und links ueberlappend + else if( ( rUnion.Left() - COLFUZZY ) >= pCell->Frm().Left() && + ( rUnion.Right() + COLFUZZY ) < pCell->Frm().Right() ) + { + USHORT nInsPos = pBox->GetUpper()->GetTabBoxes(). + C40_GETPOS( SwTableBox, pBox )+1; + lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos, 2 ); + pBox->ClaimFrmFmt(); + SwFmtFrmSize aNew( + pBox->GetFrmFmt()->GetFrmSize() ); + long nLeft = rUnion.Left() - pCell->Frm().Left(); + nLeft = nLeft * aNew.GetWidth() / + pCell->Frm().Width(); + long nRight = pCell->Frm().Right() - rUnion.Right(); + nRight = nRight * aNew.GetWidth() / + pCell->Frm().Width(); + nWidth = aNew.GetWidth() - nLeft - nRight; + + aNew.SetWidth( nLeft ); + pBox->GetFrmFmt()->SetFmtAttr( aNew ); + + { + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet() + .GetItemState( RES_BOX, FALSE, &pItem )) + { + SvxBoxItem aBox( *(SvxBoxItem*)pItem ); + aBox.SetLine( 0, BOX_LINE_RIGHT ); + pBox->GetFrmFmt()->SetFmtAttr( aBox ); + } + } + + pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ]; + aNew.SetWidth( nWidth ); + pBox->ClaimFrmFmt(); + pBox->GetFrmFmt()->SetFmtAttr( aNew ); + + if( pUndo ) + pUndo->AddNewBox( pBox->GetSttIdx() ); + + // diese Box ist selektiert + pLastBox = pBox; + rBoxes.Insert( pBox ); + aPosArr.Insert( + _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(), + pBox, bVert ) ); + + pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos+1 ]; + aNew.SetWidth( nRight ); + pBox->ClaimFrmFmt(); + pBox->GetFrmFmt()->SetFmtAttr( aNew ); + + if( pUndo ) + pUndo->AddNewBox( pBox->GetSttIdx() ); + } + // oder reicht die rechte Kante der Box in den + // selektierten Bereich? + else if( ( pCell->Frm().Right() - COLFUZZY ) < rUnion.Right() && + ( pCell->Frm().Right() - COLFUZZY ) > rUnion.Left() && + ( pCell->Frm().Left() + COLFUZZY ) < rUnion.Left() ) + { + // dann muss eine neue Box einfuegt und die + // Breiten angepasst werden + USHORT nInsPos = pBox->GetUpper()->GetTabBoxes(). + C40_GETPOS( SwTableBox, pBox )+1; + lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos, 1 ); + + SwFmtFrmSize aNew(pBox->GetFrmFmt()->GetFrmSize() ); + long nLeft = rUnion.Left() - pCell->Frm().Left(), + nRight = pCell->Frm().Right() - rUnion.Left(); + + nLeft = nLeft * aNew.GetWidth() / + pCell->Frm().Width(); + nRight = nRight * aNew.GetWidth() / + pCell->Frm().Width(); + + aNew.SetWidth( nLeft ); + pBox->ClaimFrmFmt()->SetFmtAttr( aNew ); + + // diese Box ist selektiert + pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ]; + aNew.SetWidth( nRight ); + pBox->ClaimFrmFmt(); + pBox->GetFrmFmt()->SetFmtAttr( aNew ); + + pLastBox = pBox; + rBoxes.Insert( pBox ); + aPosArr.Insert( _CmpLPt( Point( rUnion.Left(), + pCell->Frm().Top()), pBox, bVert )); + + if( pUndo ) + pUndo->AddNewBox( pBox->GetSttIdx() ); + } + } + if ( pCell->GetNext() ) + { + pCell = (const SwLayoutFrm*)pCell->GetNext(); + // --> FME 2005-11-03 #125288# Check if table cell is not empty + if ( pCell->Lower() && pCell->Lower()->IsRowFrm() ) + pCell = pCell->FirstCell(); + } + else + pCell = ::lcl_FindNextCellFrm( pCell ); + } + } + pRow = (const SwLayoutFrm*)pRow->GetNext(); + } + } + + // keine SSelection / keine gefundenen Boxen + if( 1 >= rBoxes.Count() ) + return; + + // dann suche mal alle Boxen, die nebeneinander liegen, und verbinde + // deren Inhalte mit Blanks. Alle untereinander liegende werden als + // Absaetze zusammengefasst + + // 1. Loesung: gehe ueber das Array und + // alle auf der gleichen Y-Ebene werden mit Blanks getrennt + // alle anderen werden als Absaetze getrennt. + BOOL bCalcWidth = TRUE; + const SwTableBox* pFirstBox = aPosArr[ 0 ].pSelBox; + + // JP 27.03.98: Optimierung - falls die Boxen einer Line leer sind, + // dann werden jetzt dafuer keine Blanks und + // kein Umbruch mehr eingefuegt. + //Block damit SwPaM, SwPosition vom Stack geloescht werden + { + SwPaM aPam( pDoc->GetNodes() ); + +#if defined( DEL_ONLY_EMPTY_LINES ) + nWidth = pFirstBox->GetFrmFmt()->GetFrmSize().GetWidth(); + BOOL bEmptyLine = TRUE; + USHORT n, nSttPos = 0; + + for( n = 0; n < aPosArr.Count(); ++n ) + { + const _CmpLPt& rPt = aPosArr[ n ]; + if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // gleiche Ebene ? + { + if( bEmptyLine && !IsEmptyBox( *rPt.pSelBox, aPam )) + bEmptyLine = FALSE; + if( bCalcWidth ) + nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth(); + } + else + { + if( bCalcWidth && n ) + bCalcWidth = FALSE; // eine Zeile fertig + + if( bEmptyLine && nSttPos < n ) + { + // dann ist die gesamte Line leer und braucht + // nicht mit Blanks aufgefuellt und als Absatz + // eingefuegt werden. + if( pUndo ) + for( USHORT i = nSttPos; i < n; ++i ) + pUndo->SaveCollection( *aPosArr[ i ].pSelBox ); + + aPosArr.Remove( nSttPos, n - nSttPos ); + n = nSttPos; + } + else + nSttPos = n; + + bEmptyLine = IsEmptyBox( *aPosArr[n].pSelBox, aPam ); + } + } + if( bEmptyLine && nSttPos < n ) + { + if( pUndo ) + for( USHORT i = nSttPos; i < n; ++i ) + pUndo->SaveCollection( *aPosArr[ i ].pSelBox ); + aPosArr.Remove( nSttPos, n - nSttPos ); + } +#elsif defined( DEL_EMPTY_BOXES_AT_START_AND_END ) + + nWidth = pFirstBox->GetFrmFmt()->GetFrmSize().GetWidth(); + USHORT n, nSttPos = 0, nSEndPos = 0, nESttPos = 0; + + for( n = 0; n < aPosArr.Count(); ++n ) + { + const _CmpLPt& rPt = aPosArr[ n ]; + if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // gleiche Ebene ? + { + BOOL bEmptyBox = IsEmptyBox( *rPt.pSelBox, aPam ); + if( bEmptyBox ) + { + if( nSEndPos == n ) // der Anfang ist leer + nESttPos = ++nSEndPos; + } + else // das Ende kann leer sein + nESttPos = n+1; + + if( bCalcWidth ) + nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth(); + } + else + { + if( bCalcWidth && n ) + bCalcWidth = FALSE; // eine Zeile fertig + + // zuerst die vom Anfang + if( nSttPos < nSEndPos ) + { + // dann ist der vorder Teil der Line leer und braucht + // nicht mit Blanks aufgefuellt werden. + if( pUndo ) + for( USHORT i = nSttPos; i < nSEndPos; ++i ) + pUndo->SaveCollection( *aPosArr[ i ].pSelBox ); + + USHORT nCnt = nSEndPos - nSttPos; + aPosArr.Remove( nSttPos, nCnt ); + nESttPos -= nCnt; + n -= nCnt; + } + + if( nESttPos < n ) + { + // dann ist der vorder Teil der Line leer und braucht + // nicht mit Blanks aufgefuellt werden. + if( pUndo ) + for( USHORT i = nESttPos; i < n; ++i ) + pUndo->SaveCollection( *aPosArr[ i ].pSelBox ); + + USHORT nCnt = n - nESttPos; + aPosArr.Remove( nESttPos, nCnt ); + n -= nCnt; + } + + nSttPos = nSEndPos = nESttPos = n; + if( IsEmptyBox( *aPosArr[n].pSelBox, aPam )) + ++nSEndPos; + else + ++nESttPos; + } + } + + // zuerst die vom Anfang + if( nSttPos < nSEndPos ) + { + // dann ist der vorder Teil der Line leer und braucht + // nicht mit Blanks aufgefuellt werden. + if( pUndo ) + for( USHORT i = nSttPos; i < nSEndPos; ++i ) + pUndo->SaveCollection( *aPosArr[ i ].pSelBox ); + + USHORT nCnt = nSEndPos - nSttPos; + aPosArr.Remove( nSttPos, nCnt ); + nESttPos -= nCnt; + n -= nCnt; + } + if( nESttPos < n ) + { + // dann ist der vorder Teil der Line leer und braucht + // nicht mit Blanks aufgefuellt werden. + if( pUndo ) + for( USHORT i = nESttPos; i < n; ++i ) + pUndo->SaveCollection( *aPosArr[ i ].pSelBox ); + + USHORT nCnt = n - nESttPos; + aPosArr.Remove( nESttPos, nCnt ); + } +#else +// DEL_ALL_EMPTY_BOXES + + nWidth = 0; + long nY = aPosArr.Count() ? + ( bVert ? + aPosArr[ 0 ].X() : + aPosArr[ 0 ].Y() ) : + 0; + + for( USHORT n = 0; n < aPosArr.Count(); ++n ) + { + const _CmpLPt& rPt = aPosArr[ n ]; + if( bCalcWidth ) + { + if( nY == ( bVert ? rPt.X() : rPt.Y() ) ) // gleiche Ebene ? + nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth(); + else + bCalcWidth = FALSE; // eine Zeile fertig + } + + if( IsEmptyBox( *rPt.pSelBox, aPam ) ) + { + if( pUndo ) + pUndo->SaveCollection( *rPt.pSelBox ); + + aPosArr.Remove( n, 1 ); + --n; + } + } +#endif + } + + // lege schon mal die neue Box an + { + SwTableBox* pTmpBox = rBoxes[0]; + SwTableLine* pInsLine = pTmpBox->GetUpper(); + USHORT nInsPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pTmpBox ); + + lcl_InsTblBox( pTblNd, pDoc, pTmpBox, nInsPos ); + (*ppMergeBox) = pInsLine->GetTabBoxes()[ nInsPos ]; + pInsLine->GetTabBoxes().Remove( nInsPos ); // wieder austragen + (*ppMergeBox)->SetUpper( 0 ); + (*ppMergeBox)->ClaimFrmFmt(); + + // setze die Umrandung: von der 1. Box die linke/obere von der + // letzten Box die rechte/untere Kante: + if( pLastBox && pFirstBox ) + { + SvxBoxItem aBox( pFirstBox->GetFrmFmt()->GetBox() ); + const SvxBoxItem& rBox = pLastBox->GetFrmFmt()->GetBox(); + aBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT ); + aBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM ); + if( aBox.GetLeft() || aBox.GetTop() || + aBox.GetRight() || aBox.GetBottom() ) + (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( aBox ); + } + } + + //Block damit SwPaM, SwPosition vom Stack geloescht werden + if( aPosArr.Count() ) + { + SwTxtNode* pTxtNd = 0; + SwPosition aInsPos( *(*ppMergeBox)->GetSttNd() ); + SwNodeIndex& rInsPosNd = aInsPos.nNode; + + SwPaM aPam( aInsPos ); + + for( USHORT n = 0; n < aPosArr.Count(); ++n ) + { + const _CmpLPt& rPt = aPosArr[ n ]; + aPam.GetPoint()->nNode.Assign( *rPt.pSelBox->GetSttNd()-> + EndOfSectionNode(), -1 ); + SwCntntNode* pCNd = aPam.GetCntntNode(); + USHORT nL = pCNd ? pCNd->Len() : 0; + aPam.GetPoint()->nContent.Assign( pCNd, nL ); + + SwNodeIndex aSttNdIdx( *rPt.pSelBox->GetSttNd(), 1 ); + // ein Node muss in der Box erhalten bleiben (sonst wird beim + // Move die gesamte Section geloescht) + if( pUndo ) + pDoc->DoUndo( FALSE ); + pDoc->AppendTxtNode( *aPam.GetPoint() ); + if( pUndo ) + pDoc->DoUndo( TRUE ); + SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode ); + rInsPosNd++; + if( pUndo ) + pUndo->MoveBoxCntnt( pDoc, aRg, rInsPosNd ); + else + { + pDoc->MoveNodeRange( aRg, rInsPosNd, + IDocumentContentOperations::DOC_MOVEDEFAULT ); + } + // wo steht jetzt aInsPos ?? + + if( bCalcWidth ) + bCalcWidth = FALSE; // eine Zeile fertig + + // den initialen TextNode ueberspringen + rInsPosNd.Assign( pDoc->GetNodes(), + rInsPosNd.GetNode().EndOfSectionIndex() - 2 ); + pTxtNd = rInsPosNd.GetNode().GetTxtNode(); + if( pTxtNd ) + aInsPos.nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() ); + } + + // in der MergeBox sollte jetzt der gesamte Text stehen + // loesche jetzt noch den initialen TextNode + ASSERT( (*ppMergeBox)->GetSttIdx()+2 < + (*ppMergeBox)->GetSttNd()->EndOfSectionIndex(), + "leere Box" ); + SwNodeIndex aIdx( *(*ppMergeBox)->GetSttNd()->EndOfSectionNode(), -1 ); + pDoc->GetNodes().Delete( aIdx, 1 ); + } + + // setze die Breite der Box + (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 )); + if( pUndo ) + pUndo->AddNewBox( (*ppMergeBox)->GetSttIdx() ); +} + + +static BOOL lcl_CheckCol( const _FndBox*& rpFndBox, void* pPara ); + +static BOOL lcl_CheckRow( const _FndLine*& rpFndLine, void* pPara ) +{ + ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CheckCol, pPara ); + return *(BOOL*)pPara; +} + +static BOOL lcl_CheckCol( const _FndBox*& rpFndBox, void* pPara ) +{ + if( !rpFndBox->GetBox()->GetSttNd() ) + { + if( rpFndBox->GetLines().Count() != + rpFndBox->GetBox()->GetTabLines().Count() ) + *((BOOL*)pPara) = FALSE; + else + ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CheckRow, pPara ); + } + // Box geschuetzt ?? + else if( rpFndBox->GetBox()->GetFrmFmt()->GetProtect().IsCntntProtected() ) + *((BOOL*)pPara) = FALSE; + return *(BOOL*)pPara; +} + + +USHORT CheckMergeSel( const SwPaM& rPam ) +{ + SwSelBoxes aBoxes; +//JP 24.09.96: Merge mit wiederholenden TabellenHeadline funktioniert nicht +// richtig. Warum nicht Point 0,0 benutzen? Dann ist garantiert, +// das die 1. Headline mit drin ist. + Point aPt; + const SwLayoutFrm *pStart = rPam.GetCntntNode()->GetFrm( + &aPt )->GetUpper(), + *pEnd = rPam.GetCntntNode(FALSE)->GetFrm( + &aPt )->GetUpper(); + GetTblSel( pStart, pEnd, aBoxes, 0 ); + return CheckMergeSel( aBoxes ); +} + +USHORT CheckMergeSel( const SwSelBoxes& rBoxes ) +{ + USHORT eRet = TBLMERGE_NOSELECTION; + if( rBoxes.Count() ) + { + eRet = TBLMERGE_OK; + + _FndBox aFndBox( 0, 0 ); + _FndPara aPara( rBoxes, &aFndBox ); + const SwTableNode* pTblNd = aPara.rBoxes[0]->GetSttNd()->FindTableNode(); + ((SwTable&)pTblNd->GetTable()).GetTabLines().ForEach( + &_FndLineCopyCol, &aPara ); + if( aFndBox.GetLines().Count() ) + { + BOOL bMergeSelOk = TRUE; + _FndBox* pFndBox = &aFndBox; + _FndLine* pFndLine = 0; + while( pFndBox && 1 == pFndBox->GetLines().Count() ) + { + pFndLine = pFndBox->GetLines()[0]; + if( 1 == pFndLine->GetBoxes().Count() ) + pFndBox = pFndLine->GetBoxes()[0]; + else + pFndBox = 0; + } + if( pFndBox ) + pFndBox->GetLines().ForEach( &lcl_CheckRow, &bMergeSelOk ); + else if( pFndLine ) + pFndLine->GetBoxes().ForEach( &lcl_CheckCol, &bMergeSelOk ); + if( !bMergeSelOk ) + eRet = TBLMERGE_TOOCOMPLEX; + } + else + eRet = TBLMERGE_NOSELECTION; + } + return eRet; +} + +//Ermittelt die von einer Tabellenselektion betroffenen Tabellen und die +//Union-Rechteckte der Selektionen - auch fuer aufgespaltene Tabellen. +SV_IMPL_PTRARR( SwSelUnions, SwSelUnion* ); + +SwTwips lcl_CalcWish( const SwLayoutFrm *pCell, long nWish, + const long nAct ) +{ + const SwLayoutFrm *pTmp = pCell; + if ( !nWish ) + nWish = 1; + + const sal_Bool bRTL = pCell->IsRightToLeft(); + SwTwips nRet = bRTL ? + nAct - pCell->Frm().Width() : + 0; + + while ( pTmp ) + { + while ( pTmp->GetPrev() ) + { + pTmp = (SwLayoutFrm*)pTmp->GetPrev(); + long nTmp = pTmp->GetFmt()->GetFrmSize().GetWidth(); + nRet += ( bRTL ? ( -1 ) : 1 ) * nTmp * nAct / nWish; + } + pTmp = pTmp->GetUpper()->GetUpper(); + if ( pTmp && !pTmp->IsCellFrm() ) + pTmp = 0; + } + return nRet; +} + +/* MA: 20. Sep. 93 wird nicht mehr gebraucht. +static const SwLayoutFrm *GetPrevCell( const SwLayoutFrm *pCell ) +{ + const SwLayoutFrm *pLay = pCell->GetPrevLayoutLeaf(); + if ( pLay && pLay->IsLayoutFrm() && !pLay->IsTab() ) + { + //GetPrevLayoutLeaf() liefert ggf. auch die Umgebung einer Tab zurueck + //(naehmlich genau dann, wenn die Zelle noch Vorgaenger hat). + const SwFrm *pFrm = pLay->Lower(); + while ( pFrm->GetNext() ) + pFrm = pFrm->GetNext(); + pLay = pFrm->IsTabFrm() ? (SwLayoutFrm*)pFrm : 0; + } + if ( pLay && pLay->IsTabFrm() ) + { + //GetPrevLayoutLeaf() liefert ggf. auch Tabellen zurueck die letzte + //Zelle dieser Tabelle ist das das gesuchte Blatt. + pLay = ((SwTabFrm*)pLay)->FindLastCntnt()->GetUpper(); + while ( !pLay->IsCellFrm() ) + pLay = pLay->GetUpper(); + } + return pLay; +} +*/ + +void lcl_FindStartEndRow( const SwLayoutFrm *&rpStart, + const SwLayoutFrm *&rpEnd, + const int bChkProtected ) +{ + //Start an den Anfang seiner Zeile setzen. + //End an das Ende seiner Zeile setzen. + rpStart = (SwLayoutFrm*)rpStart->GetUpper()->Lower(); + while ( rpEnd->GetNext() ) + rpEnd = (SwLayoutFrm*)rpEnd->GetNext(); + + SvPtrarr aSttArr( 8, 8 ), aEndArr( 8, 8 ); + const SwLayoutFrm *pTmp; + for( pTmp = rpStart; (FRM_CELL|FRM_ROW) & pTmp->GetType(); + pTmp = pTmp->GetUpper() ) + { + void* p = (void*)pTmp; + aSttArr.Insert( p, 0 ); + } + for( pTmp = rpEnd; (FRM_CELL|FRM_ROW) & pTmp->GetType(); + pTmp = pTmp->GetUpper() ) + { + void* p = (void*)pTmp; + aEndArr.Insert( p, 0 ); + } + + for( USHORT n = 0; n < aEndArr.Count() && n < aSttArr.Count(); ++n ) + if( aSttArr[ n ] != aEndArr[ n ] ) + { + // first unequal line or box - all odds are + if( n & 1 ) // 1, 3, 5, ... are boxes + { + rpStart = (SwLayoutFrm*)aSttArr[ n ]; + rpEnd = (SwLayoutFrm*)aEndArr[ n ]; + } + else // 0, 2, 4, ... are lines + { + // check if start & end line are the first & last Line of the + // box. If not return these cells. + // Else the hole line with all Boxes has to be deleted. + rpStart = (SwLayoutFrm*)aSttArr[ n+1 ]; + rpEnd = (SwLayoutFrm*)aEndArr[ n+1 ]; + if( n ) + { + const SwCellFrm* pCellFrm = (SwCellFrm*)aSttArr[ n-1 ]; + const SwTableLines& rLns = pCellFrm-> + GetTabBox()->GetTabLines(); + if( rLns[ 0 ] == ((SwRowFrm*)aSttArr[ n ])->GetTabLine() && + rLns[ rLns.Count() - 1 ] == + ((SwRowFrm*)aEndArr[ n ])->GetTabLine() ) + { + rpStart = rpEnd = pCellFrm; + while ( rpStart->GetPrev() ) + rpStart = (SwLayoutFrm*)rpStart->GetPrev(); + while ( rpEnd->GetNext() ) + rpEnd = (SwLayoutFrm*)rpEnd->GetNext(); + } + } + } + break; + } + + if( !bChkProtected ) // geschuetzte Zellen beachten ? + return; + + + //Anfang und Ende duerfen nicht auf geschuetzten Zellen liegen. + while ( rpStart->GetFmt()->GetProtect().IsCntntProtected() ) + rpStart = (SwLayoutFrm*)rpStart->GetNext(); + while ( rpEnd->GetFmt()->GetProtect().IsCntntProtected() ) + rpEnd = (SwLayoutFrm*)rpEnd->GetPrev(); +} + + +void lcl_FindStartEndCol( const SwLayoutFrm *&rpStart, + const SwLayoutFrm *&rpEnd, + const int bChkProtected ) +{ + //Start und End senkrecht bis an den Rand der Tabelle denken; es muss + //die Gesamttabelle betrachtet werden, also inklusive Masters und + //Follows. + //Fuer den Start brauchen wir den Mutter-TabellenFrm. + if( !rpStart ) + return; + const SwTabFrm *pOrg = rpStart->FindTabFrm(); + const SwTabFrm *pTab = pOrg; + + SWRECTFN( pTab ) + + sal_Bool bRTL = pTab->IsRightToLeft(); + const long nTmpWish = pOrg->GetFmt()->GetFrmSize().GetWidth(); + const long nWish = ( nTmpWish > 0 ) ? nTmpWish : 1; + + while ( pTab->IsFollow() ) + { + const SwFrm *pTmp = pTab->FindPrev(); + ASSERT( pTmp->IsTabFrm(), "Vorgaenger vom Follow nicht der Master." ); + pTab = (const SwTabFrm*)pTmp; + } + + SwTwips nSX = 0; + SwTwips nSX2 = 0; + + if ( pTab->GetTable()->IsNewModel() ) + { + nSX = (rpStart->Frm().*fnRect->fnGetLeft )(); + nSX2 = (rpStart->Frm().*fnRect->fnGetRight)(); + } + else + { + const SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)(); + nSX = ::lcl_CalcWish( rpStart, nWish, nPrtWidth ) + (pTab->*fnRect->fnGetPrtLeft)(); + nSX2 = nSX + (rpStart->GetFmt()->GetFrmSize().GetWidth() * nPrtWidth / nWish); + } + + const SwLayoutFrm *pTmp = pTab->FirstCell(); + + while ( pTmp && + (!pTmp->IsCellFrm() || + ( ( ! bRTL && (pTmp->Frm().*fnRect->fnGetLeft)() < nSX && + (pTmp->Frm().*fnRect->fnGetRight)()< nSX2 ) || + bRTL && (pTmp->Frm().*fnRect->fnGetLeft)() > nSX && + (pTmp->Frm().*fnRect->fnGetRight)()> nSX2 ) ) ) + pTmp = pTmp->GetNextLayoutLeaf(); + + if ( pTmp ) + rpStart = pTmp; + + pTab = pOrg; + + const SwTabFrm* pLastValidTab = pTab; + while ( pTab->GetFollow() ) + { + // + // Check if pTab->GetFollow() is a valid follow table: + // Only follow tables with at least on non-FollowFlowLine + // should be considered. + // + if ( pTab->HasFollowFlowLine() ) + { + pTab = pTab->GetFollow(); + const SwFrm* pTmpRow = pTab->GetFirstNonHeadlineRow(); + if ( pTmpRow && pTmpRow->GetNext() ) + pLastValidTab = pTab; + } + else + pLastValidTab = pTab = pTab->GetFollow(); + } + pTab = pLastValidTab; + + SwTwips nEX = 0; + + if ( pTab->GetTable()->IsNewModel() ) + { + nEX = (rpEnd->Frm().*fnRect->fnGetLeft )(); + } + else + { + const SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)(); + nEX = ::lcl_CalcWish( rpEnd, nWish, nPrtWidth ) + (pTab->*fnRect->fnGetPrtLeft)(); + } + + const SwCntntFrm* pLastCntnt = pTab->FindLastCntnt(); + rpEnd = pLastCntnt ? pLastCntnt->GetUpper() : 0; + // --> FME 2006-07-17 #134385# Made code robust. If pTab does not have a lower, + // we would crash here. + if ( !pLastCntnt ) return; + // <-- + + while( !rpEnd->IsCellFrm() ) + rpEnd = rpEnd->GetUpper(); + + while ( ( bRTL && (rpEnd->Frm().*fnRect->fnGetLeft)() < nEX ) || + ( ! bRTL && (rpEnd->Frm().*fnRect->fnGetLeft)() > nEX ) ) + { + const SwLayoutFrm* pTmpLeaf = rpEnd->GetPrevLayoutLeaf(); + if( !pTmpLeaf || !pTab->IsAnLower( pTmpLeaf ) ) + break; + rpEnd = pTmpLeaf; + } + + if( !bChkProtected ) // geschuetzte Zellen beachten ? + return; + + //Anfang und Ende duerfen nicht auf geschuetzten Zellen liegen. + //Also muss ggf. nocheinmal rueckwaerts gesucht werden. + while ( rpStart->GetFmt()->GetProtect().IsCntntProtected() ) + { + const SwLayoutFrm *pTmpLeaf = rpStart; + pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf(); + while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() > nEX )//erstmal die Zeile ueberspr. + pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf(); + while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() < nSX && + (pTmpLeaf->Frm().*fnRect->fnGetRight)()< nSX2 ) + pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf(); + const SwTabFrm *pTmpTab = rpStart->FindTabFrm(); + if ( !pTmpTab->IsAnLower( pTmpLeaf ) ) + { + pTmpTab = pTmpTab->GetFollow(); + rpStart = pTmpTab->FirstCell(); + while ( (rpStart->Frm().*fnRect->fnGetLeft)() < nSX && + (rpStart->Frm().*fnRect->fnGetRight)()< nSX2 ) + rpStart = rpStart->GetNextLayoutLeaf(); + } + else + rpStart = pTmpLeaf; + } + while ( rpEnd->GetFmt()->GetProtect().IsCntntProtected() ) + { + const SwLayoutFrm *pTmpLeaf = rpEnd; + pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf(); + while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() < nEX )//erstmal die Zeile ueberspr. + pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf(); + while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() > nEX ) + pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf(); + const SwTabFrm *pTmpTab = rpEnd->FindTabFrm(); + if ( !pTmpLeaf || !pTmpTab->IsAnLower( pTmpLeaf ) ) + { + pTmpTab = (const SwTabFrm*)pTmpTab->FindPrev(); + ASSERT( pTmpTab->IsTabFrm(), "Vorgaenger vom Follow nicht der Master."); + rpEnd = pTmpTab->FindLastCntnt()->GetUpper(); + while( !rpEnd->IsCellFrm() ) + rpEnd = rpEnd->GetUpper(); + while ( (rpEnd->Frm().*fnRect->fnGetLeft)() > nEX ) + rpEnd = rpEnd->GetPrevLayoutLeaf(); + } + else + rpEnd = pTmpLeaf; + } +} + + +void MakeSelUnions( SwSelUnions& rUnions, const SwLayoutFrm *pStart, + const SwLayoutFrm *pEnd, const SwTblSearchType eSearchType ) +{ + while ( pStart && !pStart->IsCellFrm() ) + pStart = pStart->GetUpper(); + while ( pEnd && !pEnd->IsCellFrm() ) + pEnd = pEnd->GetUpper(); + + // #112697# Robust: + if ( !pStart || !pEnd ) + { + ASSERT( false, "MakeSelUnions with pStart or pEnd not in CellFrm" ) + return; + } + + const SwTabFrm *pTable = pStart->FindTabFrm(); + const SwTabFrm *pEndTable = pEnd->FindTabFrm(); + if( !pTable || !pEndTable ) + return; + BOOL bExchange = FALSE; + + if ( pTable != pEndTable ) + { + if ( !pTable->IsAnFollow( pEndTable ) ) + { + ASSERT( pEndTable->IsAnFollow( pTable ), "Tabkette verknotet." ); + bExchange = TRUE; + } + } + else + { + SWRECTFN( pTable ) + long nSttTop = (pStart->Frm().*fnRect->fnGetTop)(); + long nEndTop = (pEnd->Frm().*fnRect->fnGetTop)(); + if( nSttTop == nEndTop ) + { + if( (pStart->Frm().*fnRect->fnGetLeft)() > + (pEnd->Frm().*fnRect->fnGetLeft)() ) + bExchange = TRUE; + } + else if( bVert == ( nSttTop < nEndTop ) ) + bExchange = TRUE; + } + if ( bExchange ) + { + const SwLayoutFrm *pTmp = pStart; + pStart = pEnd; + pEnd = pTmp; + //pTable und pEndTable nicht umsortieren, werden unten neu gesetzt. + //MA: 28. Dec. 93 Bug: 5190 + } + + //Start und End sind jetzt huebsch sortiert, jetzt muessen sie falls + //erwuenscht noch versetzt werden. + if( nsSwTblSearchType::TBLSEARCH_ROW == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) ) + ::lcl_FindStartEndRow( pStart, pEnd, nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType ); + else if( nsSwTblSearchType::TBLSEARCH_COL == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) ) + ::lcl_FindStartEndCol( pStart, pEnd, nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType ); + + // --> FME 2006-07-17 #134385# Made code robust. + if ( !pEnd ) return; + // <-- + + //neu besorgen, da sie jetzt verschoben sind. MA: 28. Dec. 93 Bug 5190 + pTable = pStart->FindTabFrm(); + pEndTable = pEnd->FindTabFrm(); + + const long nStSz = pStart->GetFmt()->GetFrmSize().GetWidth(); + const long nEdSz = pEnd->GetFmt()->GetFrmSize().GetWidth(); + const long nWish = Max( 1L, pTable->GetFmt()->GetFrmSize().GetWidth() ); + while ( pTable ) + { + SWRECTFN( pTable ) + const long nOfst = (pTable->*fnRect->fnGetPrtLeft)(); + const long nPrtWidth = (pTable->Prt().*fnRect->fnGetWidth)(); + long nSt1 = ::lcl_CalcWish( pStart, nWish, nPrtWidth ) + nOfst; + long nEd1 = ::lcl_CalcWish( pEnd, nWish, nPrtWidth ) + nOfst; + + if ( nSt1 <= nEd1 ) + nEd1 += (long)((nEdSz * nPrtWidth) / nWish) - 1; + else + nSt1 += (long)((nStSz * nPrtWidth) / nWish) - 1; + + long nSt2; + long nEd2; + if( pTable->IsAnLower( pStart ) ) + nSt2 = (pStart->Frm().*fnRect->fnGetTop)(); + else + nSt2 = (pTable->Frm().*fnRect->fnGetTop)(); + if( pTable->IsAnLower( pEnd ) ) + nEd2 = (pEnd->Frm().*fnRect->fnGetBottom)(); + else + nEd2 = (pTable->Frm().*fnRect->fnGetBottom)(); + Point aSt, aEd; + if( nSt1 > nEd1 ) + { + long nTmp = nSt1; + nSt1 = nEd1; + nEd1 = nTmp; + } + if( nSt2 > nEd2 ) + { + long nTmp = nSt2; + nSt2 = nEd2; + nEd2 = nTmp; + } + if( bVert ) + { + aSt = Point( nSt2, nSt1 ); + aEd = Point( nEd2, nEd1 ); + } + else + { + aSt = Point( nSt1, nSt2 ); + aEd = Point( nEd1, nEd2 ); + } + + const Point aDiff( aEd - aSt ); + SwRect aUnion( aSt, Size( aDiff.X(), aDiff.Y() ) ); + aUnion.Justify(); + + // fuers + if( !(nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT & eSearchType )) + { + //Leider ist die Union jetzt mit Rundungsfehlern behaftet und dadurch + //wuerden beim Split/Merge fehlertraechtige Umstaende entstehen. + //Um dies zu vermeiden werden jetzt fuer die Table die erste und + //letzte Zelle innerhalb der Union ermittelt und aus genau deren + //Werten wird die Union neu gebildet. + const SwLayoutFrm* pRow = pTable->IsFollow() ? + pTable->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTable->Lower(); + + while ( pRow && !pRow->Frm().IsOver( aUnion ) ) + pRow = (SwLayoutFrm*)pRow->GetNext(); + + // --> FME 2004-07-26 #i31976# + // A follow flow row may contain emtpy cells. These are not + // considered by FirstCell(). Therefore we have to find + // the first cell manually: + const SwFrm* pTmpCell = 0; + if ( pTable->IsFollow() && pRow && pRow->IsInFollowFlowRow() ) + { + const SwFrm* pTmpRow = pRow; + while ( pTmpRow && pTmpRow->IsRowFrm() ) + { + pTmpCell = static_cast<const SwRowFrm*>(pTmpRow)->Lower(); + pTmpRow = static_cast<const SwCellFrm*>(pTmpCell)->Lower(); + } + ASSERT( !pTmpCell || pTmpCell->IsCellFrm(), "Lower of rowframe != cellframe?!" ) + } + // <-- + + const SwLayoutFrm* pFirst = pTmpCell ? + static_cast<const SwLayoutFrm*>(pTmpCell) : + pRow ? + pRow->FirstCell() : + 0; + + while ( pFirst && !::IsFrmInTblSel( aUnion, pFirst ) ) + { + if ( pFirst->GetNext() ) + { + pFirst = (const SwLayoutFrm*)pFirst->GetNext(); + if ( pFirst->Lower() && pFirst->Lower()->IsRowFrm() ) + pFirst = pFirst->FirstCell(); + } + else + pFirst = ::lcl_FindNextCellFrm( pFirst ); + } + const SwLayoutFrm* pLast = 0; + const SwFrm* pLastCntnt = pTable->FindLastCntnt(); + if ( pLastCntnt ) + pLast = ::lcl_FindCellFrm( pLastCntnt->GetUpper() ); + + while ( pLast && !::IsFrmInTblSel( aUnion, pLast ) ) + pLast = ::lcl_FindCellFrm( pLast->GetPrevLayoutLeaf() ); + + if ( pFirst && pLast ) //Robust + { + aUnion = pFirst->Frm(); + aUnion.Union( pLast->Frm() ); + } + else + aUnion.Width( 0 ); + } + + if( (aUnion.*fnRect->fnGetWidth)() ) + { + SwSelUnion *pTmp = new SwSelUnion( aUnion, (SwTabFrm*)pTable ); + rUnions.C40_INSERT( SwSelUnion, pTmp, rUnions.Count() ); + } + + pTable = pTable->GetFollow(); + if ( pTable != pEndTable && pEndTable->IsAnFollow( pTable ) ) + pTable = 0; + } +} + +BOOL CheckSplitCells( const SwCrsrShell& rShell, USHORT nDiv, + const SwTblSearchType eSearchType ) +{ + if( !rShell.IsTableMode() ) + rShell.GetCrsr(); + + return CheckSplitCells( *rShell.getShellCrsr(false), nDiv, eSearchType ); +} + +BOOL CheckSplitCells( const SwCursor& rCrsr, USHORT nDiv, + const SwTblSearchType eSearchType ) +{ + if( 1 >= nDiv ) + return FALSE; + + USHORT nMinValue = nDiv * MINLAY; + + //Start- und Endzelle besorgen und den naechsten fragen. + Point aPtPos, aMkPos; + const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr); + if( pShCrsr ) + { + aPtPos = pShCrsr->GetPtPos(); + aMkPos = pShCrsr->GetMkPos(); + } + const SwLayoutFrm *pStart = rCrsr.GetCntntNode()->GetFrm( + &aPtPos )->GetUpper(), + *pEnd = rCrsr.GetCntntNode(FALSE)->GetFrm( + &aMkPos )->GetUpper(); + + SWRECTFN( pStart->GetUpper() ) + + //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen. + SwSelUnions aUnions; + + ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType ); + + //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen. + for ( USHORT i = 0; i < aUnions.Count(); ++i ) + { + SwSelUnion *pUnion = aUnions[i]; + const SwTabFrm *pTable = pUnion->GetTable(); + + // Skip any repeated headlines in the follow: + const SwLayoutFrm* pRow = pTable->IsFollow() ? + pTable->GetFirstNonHeadlineRow() : + (const SwLayoutFrm*)pTable->Lower(); + + while ( pRow ) + { + if ( pRow->Frm().IsOver( pUnion->GetUnion() ) ) + { + const SwLayoutFrm *pCell = pRow->FirstCell(); + + while ( pCell && pRow->IsAnLower( pCell ) ) + { + ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" ); + if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) ) + { + if( (pCell->Frm().*fnRect->fnGetWidth)() < nMinValue ) + return FALSE; + } + + if ( pCell->GetNext() ) + { + pCell = (const SwLayoutFrm*)pCell->GetNext(); + if ( pCell->Lower() && pCell->Lower()->IsRowFrm() ) + pCell = pCell->FirstCell(); + } + else + pCell = ::lcl_FindNextCellFrm( pCell ); + } + } + pRow = (const SwLayoutFrm*)pRow->GetNext(); + } + } + return TRUE; +} + +// ------------------------------------------------------------------- +// Diese Klassen kopieren die aktuelle Tabellen-Selektion (rBoxes) +// unter Beibehaltung der Tabellen-Struktur in eine eigene Struktur +// neu: SS zum gezielten Loeschen/Retaurieren des Layouts. + +void lcl_InsertRow( SwTableLine &rLine, SwLayoutFrm *pUpper, SwFrm *pSibling ) +{ + SwRowFrm *pRow = new SwRowFrm( rLine ); + if ( pUpper->IsTabFrm() && ((SwTabFrm*)pUpper)->IsFollow() ) + { + SwTabFrm* pTabFrm = (SwTabFrm*)pUpper; + pTabFrm->FindMaster()->InvalidatePos(); //kann die Zeile vielleicht aufnehmen + + if ( pSibling && pTabFrm->IsInHeadline( *pSibling ) ) + { + // Skip any repeated headlines in the follow: + pSibling = pTabFrm->GetFirstNonHeadlineRow(); + } + } + pRow->Paste( pUpper, pSibling ); + pRow->RegistFlys(); +} + + +BOOL _FndBoxCopyCol( const SwTableBox*& rpBox, void* pPara ) +{ + _FndPara* pFndPara = (_FndPara*)pPara; + _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine ); + if( rpBox->GetTabLines().Count() ) + { + _FndPara aPara( *pFndPara, pFndBox ); + pFndBox->GetBox()->GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); + if( !pFndBox->GetLines().Count() ) + { + delete pFndBox; + return TRUE; + } + } + else + { + SwTableBoxPtr pSrch = (SwTableBoxPtr)rpBox; + USHORT nFndPos; + if( !pFndPara->rBoxes.Seek_Entry( pSrch, &nFndPos )) + { + delete pFndBox; + return TRUE; + } + } + pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, + pFndPara->pFndLine->GetBoxes().Count() ); + return TRUE; +} + +BOOL _FndLineCopyCol( const SwTableLine*& rpLine, void* pPara ) +{ + _FndPara* pFndPara = (_FndPara*)pPara; + _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox ); + _FndPara aPara( *pFndPara, pFndLine ); + pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxCopyCol, &aPara ); + if( pFndLine->GetBoxes().Count() ) + { + pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine, + pFndPara->pFndBox->GetLines().Count() ); + } + else + delete pFndLine; + return TRUE; +} + +void _FndBox::SetTableLines( const SwSelBoxes &rBoxes, const SwTable &rTable ) +{ + //Pointer auf die Lines vor und hinter den zu verarbeitenden Bereich + //setzen. Wenn die erste/letzte Zeile in den Bereich eingeschlossen + //sind, so bleiben die Pointer eben einfach 0. + //Gesucht werden zunachst die Positionen der ersten/letzten betroffenen + //Line im Array der SwTable. Damit die 0 fuer 'keine Line' verwand werden + //kann werden die Positionen um 1 nach oben versetzt! + + USHORT nStPos = USHRT_MAX; + USHORT nEndPos= 0; + + for ( USHORT i = 0; i < rBoxes.Count(); ++i ) + { + SwTableLine *pLine = rBoxes[i]->GetUpper(); + while ( pLine->GetUpper() ) + pLine = pLine->GetUpper()->GetUpper(); + const USHORT nPos = rTable.GetTabLines().GetPos( + (const SwTableLine*&)pLine ) + 1; + + ASSERT( nPos != USHRT_MAX, "TableLine not found." ); + + if( nStPos > nPos ) + nStPos = nPos; + + if( nEndPos < nPos ) + nEndPos = nPos; + } + if ( nStPos > 1 ) + pLineBefore = rTable.GetTabLines()[nStPos - 2]; + if ( nEndPos < rTable.GetTabLines().Count() ) + pLineBehind = rTable.GetTabLines()[nEndPos]; +} + +void _FndBox::SetTableLines( const SwTable &rTable ) +{ + // Pointer auf die Lines vor und hinter den zu verarbeitenden Bereich + // setzen. Wenn die erste/letzte Zeile in den Bereich eingeschlossen + // sind, so bleiben die Pointer eben einfach 0. + // Die Positionen der ersten/letzten betroffenen Line im Array der + // SwTable steht in der FndBox. Damit die 0 fuer 'keine Line' verwand + // werdenkann werden die Positionen um 1 nach oben versetzt! + + if( !GetLines().Count() ) + return; + + SwTableLine* pTmpLine = GetLines()[0]->GetLine(); + USHORT nPos = rTable.GetTabLines().C40_GETPOS( SwTableLine, pTmpLine ); + ASSERT( USHRT_MAX != nPos, "Line steht nicht in der Tabelle" ); + if( nPos ) + pLineBefore = rTable.GetTabLines()[ nPos - 1 ]; + + pTmpLine = GetLines()[GetLines().Count()-1]->GetLine(); + nPos = rTable.GetTabLines().C40_GETPOS( SwTableLine, pTmpLine ); + ASSERT( USHRT_MAX != nPos, "Line steht nicht in der Tabelle" ); + if( ++nPos < rTable.GetTabLines().Count() ) + pLineBehind = rTable.GetTabLines()[nPos]; +} + +inline void UnsetFollow( SwFlowFrm *pTab ) +{ + pTab->bIsFollow = FALSE; +} + +void _FndBox::DelFrms( SwTable &rTable ) +{ + //Alle Lines zwischen pLineBefore und pLineBehind muessen aus dem + //Layout ausgeschnitten und geloescht werden. + //Entstehen dabei leere Follows so muessen diese vernichtet werden. + //Wird ein Master vernichtet, so muss der Follow Master werden. + //Ein TabFrm muss immer uebrigbleiben. + + USHORT nStPos = 0; + USHORT nEndPos= rTable.GetTabLines().Count() - 1; + if( rTable.IsNewModel() && pLineBefore ) + rTable.CheckRowSpan( pLineBefore, true ); + if ( pLineBefore ) + { + nStPos = rTable.GetTabLines().GetPos( + (const SwTableLine*&)pLineBefore ); + ASSERT( nStPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" ); + ++nStPos; + } + if( rTable.IsNewModel() && pLineBehind ) + rTable.CheckRowSpan( pLineBehind, false ); + if ( pLineBehind ) + { + nEndPos = rTable.GetTabLines().GetPos( + (const SwTableLine*&)pLineBehind ); + ASSERT( nEndPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" ); + --nEndPos; + } + + for ( USHORT i = nStPos; i <= nEndPos; ++i) + { + SwFrmFmt *pFmt = rTable.GetTabLines()[i]->GetFrmFmt(); + SwClientIter aIter( *pFmt ); + SwClient* pLast = aIter.GoStart(); + if( pLast ) + { + do { + SwFrm *pFrm = PTR_CAST( SwFrm, pLast ); + if ( pFrm && + ((SwRowFrm*)pFrm)->GetTabLine() == rTable.GetTabLines()[i] ) + { + BOOL bDel = TRUE; + SwTabFrm *pUp = !pFrm->GetPrev() && !pFrm->GetNext() ? + (SwTabFrm*)pFrm->GetUpper() : 0; + if ( !pUp ) + { + const USHORT nRepeat = + ((SwTabFrm*)pFrm->GetUpper())->GetTable()->GetRowsToRepeat(); + if ( nRepeat > 0 && + ((SwTabFrm*)pFrm->GetUpper())->IsFollow() ) + { + if ( !pFrm->GetNext() ) + { + SwRowFrm* pFirstNonHeadline = + ((SwTabFrm*)pFrm->GetUpper())->GetFirstNonHeadlineRow(); + if ( pFirstNonHeadline == pFrm ) + { + pUp = (SwTabFrm*)pFrm->GetUpper(); + } + } + } + } + if ( pUp ) + { + SwTabFrm *pFollow = pUp->GetFollow(); + SwTabFrm *pPrev = pUp->IsFollow() ? pUp : 0; + if ( pPrev ) + { + SwFrm *pTmp = pPrev->FindPrev(); + ASSERT( pTmp->IsTabFrm(), + "Vorgaenger vom Follow kein Master."); + pPrev = (SwTabFrm*)pTmp; + } + if ( pPrev ) + { + pPrev->SetFollow( pFollow ); + // --> FME 2006-01-31 #i60340# Do not transfer the + // flag from pUp to pPrev. pUp may still have the + // flag set although there is not more follow flow + // line associated with pUp. + pPrev->SetFollowFlowLine( FALSE ); + // <-- + } + else if ( pFollow ) + ::UnsetFollow( pFollow ); + + //Ein TabellenFrm muss immer stehenbleiben! + if ( pPrev || pFollow ) + { + // OD 26.08.2003 #i18103# - if table is in a section, + // lock the section, to avoid its delete. + { + SwSectionFrm* pSctFrm = pUp->FindSctFrm(); + bool bOldSectLock = false; + if ( pSctFrm ) + { + bOldSectLock = pSctFrm->IsColLocked(); + pSctFrm->ColLock(); + } + pUp->Cut(); + if ( pSctFrm && !bOldSectLock ) + { + pSctFrm->ColUnlock(); + } + } + delete pUp; + bDel = FALSE;//Die Row wird mit in den Abgrund + //gerissen. + } + } + if ( bDel ) + { + SwFrm* pTabFrm = pFrm->GetUpper(); + if ( pTabFrm->IsTabFrm() && + !pFrm->GetNext() && + ((SwTabFrm*)pTabFrm)->GetFollow() ) + { + // We do not delete the follow flow line, + // this will be done automatically in the + // next turn. + ((SwTabFrm*)pTabFrm)->SetFollowFlowLine( FALSE ); + } + + pFrm->Cut(); + delete pFrm; + } + } + } while( 0 != ( pLast = aIter++ )); + } + } +} + +BOOL lcl_IsLineOfTblFrm( const SwTabFrm& rTable, const SwFrm& rChk ) +{ + const SwTabFrm* pTblFrm = rChk.FindTabFrm(); + if( pTblFrm->IsFollow() ) + pTblFrm = pTblFrm->FindMaster( true ); + return &rTable == pTblFrm; +} + +/* + * lcl_UpdateRepeatedHeadlines + */ +void lcl_UpdateRepeatedHeadlines( SwTabFrm& rTabFrm, bool bCalcLowers ) +{ + ASSERT( rTabFrm.IsFollow(), "lcl_UpdateRepeatedHeadlines called for non-follow tab" ) + + // Delete remaining headlines: + SwRowFrm* pLower = 0; + while ( 0 != ( pLower = (SwRowFrm*)rTabFrm.Lower() ) && pLower->IsRepeatedHeadline() ) + { + pLower->Cut(); + delete pLower; + } + + // Insert fresh set of headlines: + pLower = (SwRowFrm*)rTabFrm.Lower(); + SwTable& rTable = *rTabFrm.GetTable(); + const USHORT nRepeat = rTable.GetRowsToRepeat(); + for ( USHORT nIdx = 0; nIdx < nRepeat; ++nIdx ) + { + SwRowFrm* pHeadline = new SwRowFrm( + *rTable.GetTabLines()[ nIdx ] ); + pHeadline->SetRepeatedHeadline( true ); + pHeadline->Paste( &rTabFrm, pLower ); + pHeadline->RegistFlys(); + } + + if ( bCalcLowers ) + rTabFrm.SetCalcLowers(); +} + +void _FndBox::MakeFrms( SwTable &rTable ) +{ + //Alle Lines zwischen pLineBefore und pLineBehind muessen im Layout + //wieder neu erzeugt werden. + //Und Zwar fuer alle Auspraegungen der Tabelle (mehrere z.B. im Kopf/Fuss). + + USHORT nStPos = 0; + USHORT nEndPos= rTable.GetTabLines().Count() - 1; + if ( pLineBefore ) + { + nStPos = rTable.GetTabLines().GetPos( + (const SwTableLine*&)pLineBefore ); + ASSERT( nStPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" ); + ++nStPos; + + } + if ( pLineBehind ) + { + nEndPos = rTable.GetTabLines().GetPos( + (const SwTableLine*&)pLineBehind ); + ASSERT( nEndPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" ); + --nEndPos; + } + //Jetzt die grosse Einfuegeoperation fuer alle Tabllen. + SwClientIter aTabIter( *rTable.GetFrmFmt() ); + for ( SwTabFrm *pTable = (SwTabFrm*)aTabIter.First( TYPE(SwFrm) ); pTable; + pTable = (SwTabFrm*)aTabIter.Next() ) + { + if ( !pTable->IsFollow() ) + { + SwFrm *pSibling = 0; + SwFrm *pUpperFrm = 0; + int i; + for ( i = rTable.GetTabLines().Count()-1; + i >= 0 && !pSibling; --i ) + { + SwTableLine *pLine = pLineBehind ? pLineBehind : + rTable.GetTabLines()[static_cast<USHORT>(i)]; + SwClientIter aIter( *pLine->GetFrmFmt() ); + pSibling = (SwFrm*)aIter.First( TYPE(SwFrm) ); + while ( pSibling && ( + static_cast<SwRowFrm*>(pSibling)->GetTabLine() != pLine || + !lcl_IsLineOfTblFrm( *pTable, *pSibling ) || + static_cast<SwRowFrm*>(pSibling)->IsRepeatedHeadline() || + // --> FME 2005-08-24 #i53647# If !pLineBehind, + // IsInSplitTableRow() should be checked. + ( pLineBehind && pSibling->IsInFollowFlowRow() ) || + (!pLineBehind && pSibling->IsInSplitTableRow() ) ) ) + // <-- + { + pSibling = (SwFrm*)aIter.Next(); + } + } + if ( pSibling ) + { + pUpperFrm = pSibling->GetUpper(); + if ( !pLineBehind ) + pSibling = 0; + } + else +// ???? oder das der Letzte Follow der Tabelle ???? + pUpperFrm = pTable; + + for ( i = nStPos; (USHORT)i <= nEndPos; ++i ) + ::lcl_InsertRow( *rTable.GetTabLines()[static_cast<USHORT>(i)], + (SwLayoutFrm*)pUpperFrm, pSibling ); + if ( pUpperFrm->IsTabFrm() ) + ((SwTabFrm*)pUpperFrm)->SetCalcLowers(); + } + else if ( rTable.GetRowsToRepeat() > 0 ) + { + // Insert new headlines: + lcl_UpdateRepeatedHeadlines( *pTable, true ); + } + } +} + +void _FndBox::MakeNewFrms( SwTable &rTable, const USHORT nNumber, + const BOOL bBehind ) +{ + //Frms fuer neu eingefuege Zeilen erzeugen. + //bBehind == TRUE: vor pLineBehind + // == FALSE: hinter pLineBefore + const USHORT nBfPos = pLineBefore ? + rTable.GetTabLines().GetPos( (const SwTableLine*&)pLineBefore ) : + USHRT_MAX; + const USHORT nBhPos = pLineBehind ? + rTable.GetTabLines().GetPos( (const SwTableLine*&)pLineBehind ) : + USHRT_MAX; + + //nNumber: wie oft ist eingefuegt worden. + //nCnt: wieviele sind nNumber mal eingefuegt worden. + + const USHORT nCnt = + ((nBhPos != USHRT_MAX ? nBhPos : rTable.GetTabLines().Count()) - + (nBfPos != USHRT_MAX ? nBfPos + 1 : 0)) / (nNumber + 1); + + //Den Master-TabFrm suchen + SwClientIter aTabIter( *rTable.GetFrmFmt() ); + SwTabFrm *pTable; + for ( pTable = (SwTabFrm*)aTabIter.First( TYPE(SwFrm) ); pTable; + pTable = (SwTabFrm*)aTabIter.Next() ) + { + if( !pTable->IsFollow() ) + { + SwFrm *pSibling = 0; + SwLayoutFrm *pUpperFrm = 0; + if ( bBehind ) + { + if ( pLineBehind ) + { + SwClientIter aIter( *pLineBehind->GetFrmFmt() ); + pSibling = (SwFrm*)aIter.First( TYPE(SwFrm) ); + while ( pSibling && ( + // only consider row frames associated with pLineBehind: + static_cast<SwRowFrm*>(pSibling)->GetTabLine() != pLineBehind || + // only consider row frames that are in pTables Master-Follow chain: + !lcl_IsLineOfTblFrm( *pTable, *pSibling ) || + // only consider row frames that are not repeated headlines: + static_cast<SwRowFrm*>(pSibling)->IsRepeatedHeadline() || + // only consider row frames that are not follow flow rows + pSibling->IsInFollowFlowRow() ) ) + { + pSibling = (SwFrm*)aIter.Next(); + } + } + if ( pSibling ) + pUpperFrm = pSibling->GetUpper(); + else + { + while( pTable->GetFollow() ) + pTable = pTable->GetFollow(); + pUpperFrm = pTable; + } + const USHORT nMax = nBhPos != USHRT_MAX ? + nBhPos : rTable.GetTabLines().Count(); + + USHORT i = nBfPos != USHRT_MAX ? nBfPos + 1 + nCnt : nCnt; + + for ( ; i < nMax; ++i ) + ::lcl_InsertRow( *rTable.GetTabLines()[i], pUpperFrm, pSibling ); + if ( pUpperFrm->IsTabFrm() ) + ((SwTabFrm*)pUpperFrm)->SetCalcLowers(); + } + else //davor einfuegen + { + USHORT i; + + // We are looking for the frame that is behind the row frame + // that should be inserted. + for ( i = 0; !pSibling; ++i ) + { + SwTableLine* pLine = pLineBefore ? pLineBefore : rTable.GetTabLines()[i]; + + SwClientIter aIter( *pLine->GetFrmFmt() ); + pSibling = (SwFrm*)aIter.First( TYPE(SwFrm) ); + + while ( pSibling && ( + // only consider row frames associated with pLineBefore: + static_cast<SwRowFrm*>(pSibling)->GetTabLine() != pLine || + // only consider row frames that are in pTables Master-Follow chain: + !lcl_IsLineOfTblFrm( *pTable, *pSibling ) || + // only consider row frames that are not repeated headlines: + static_cast<SwRowFrm*>(pSibling)->IsRepeatedHeadline() || + // 1. case: pLineBefore == 0: + // only consider row frames that are not follow flow rows + // 2. case: pLineBefore != 0: + // only consider row frames that are not split table rows + // --> FME 2004-11-23 #i37476# If !pLineBefore, + // check IsInFollowFlowRow instead of IsInSplitTableRow. + ( ( !pLineBefore && pSibling->IsInFollowFlowRow() ) || + ( pLineBefore && pSibling->IsInSplitTableRow() ) ) ) ) + // <-- + { + pSibling = (SwFrm*)aIter.Next(); + } + } + + pUpperFrm = pSibling->GetUpper(); + if ( pLineBefore ) + pSibling = pSibling->GetNext(); + + USHORT nMax = nBhPos != USHRT_MAX ? + nBhPos - nCnt : + rTable.GetTabLines().Count() - nCnt; + + i = nBfPos != USHRT_MAX ? nBfPos + 1 : 0; + for ( ; i < nMax; ++i ) + ::lcl_InsertRow( *rTable.GetTabLines()[i], + pUpperFrm, pSibling ); + if ( pUpperFrm->IsTabFrm() ) + ((SwTabFrm*)pUpperFrm)->SetCalcLowers(); + } + } + } + + //Die Headlines mussen ggf. auch verarbeitet werden. Um gut arbeitenden + //Code nicht zu zerfasern wird hier nochmals iteriert. + const USHORT nRowsToRepeat = rTable.GetRowsToRepeat(); + if ( nRowsToRepeat > 0 && + ( ( !bBehind && ( nBfPos == USHRT_MAX || nBfPos + 1 < nRowsToRepeat ) ) || + ( bBehind && ( ( nBfPos == USHRT_MAX && nRowsToRepeat > 1 ) || nBfPos + 2 < nRowsToRepeat ) ) ) ) + { + for ( pTable = (SwTabFrm*)aTabIter.First( TYPE(SwFrm) ); pTable; + pTable = (SwTabFrm*)aTabIter.Next() ) + { + if ( pTable->Lower() ) + { + if ( pTable->IsFollow() ) + { + lcl_UpdateRepeatedHeadlines( *pTable, true ); + } + + ASSERT( ((SwRowFrm*)pTable->Lower())->GetTabLine() == + rTable.GetTabLines()[0], "MakeNewFrms: Table corruption!" ) + } + } + } +} + +BOOL _FndBox::AreLinesToRestore( const SwTable &rTable ) const +{ + //Lohnt es sich MakeFrms zu rufen? + + if ( !pLineBefore && !pLineBehind && rTable.GetTabLines().Count() ) + return TRUE; + + USHORT nBfPos; + if(pLineBefore) + { + const SwTableLine* rLBefore = (const SwTableLine*)pLineBefore; + nBfPos = rTable.GetTabLines().GetPos( rLBefore ); + } + else + nBfPos = USHRT_MAX; + + USHORT nBhPos; + if(pLineBehind) + { + const SwTableLine* rLBehind = (const SwTableLine*)pLineBehind; + nBhPos = rTable.GetTabLines().GetPos( rLBehind ); + } + else + nBhPos = USHRT_MAX; + + if ( nBfPos == nBhPos ) //Duerfte eigentlich nie vorkommen. + { + ASSERT( FALSE, "Table, Loeschen auf keinem Bereich !?!" ); + return FALSE; + } + + if ( rTable.GetRowsToRepeat() > 0 ) + { + // ups. sollte unsere zu wiederholende Kopfzeile geloescht worden + // sein?? + SwClientIter aIter( *rTable.GetFrmFmt() ); + for( SwTabFrm* pTable = (SwTabFrm*)aIter.First( TYPE( SwFrm )); + pTable; pTable = (SwTabFrm*)aIter.Next() ) + { + if( pTable->IsFollow() ) + { + // Insert new headlines: + lcl_UpdateRepeatedHeadlines( *pTable, false ); + } + } + } + + // Some adjacent lines at the beginning of the table have been deleted: + if ( nBfPos == USHRT_MAX && nBhPos == 0 ) + return FALSE; + + // Some adjacent lines at the end of the table have been deleted: + if ( nBhPos == USHRT_MAX && nBfPos == (rTable.GetTabLines().Count() - 1) ) + return FALSE; + + // Some adjacent lines in the middle of the table have been deleted: + if ( nBfPos != USHRT_MAX && nBhPos != USHRT_MAX && (nBfPos + 1) == nBhPos ) + return FALSE; + + // The structure of the deleted lines is more complex due to split lines. + // A call of MakeFrms() is necessary. + return TRUE; +} + + |