summaryrefslogtreecommitdiff
path: root/sw/source/core/crsr/crsrsh.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/crsr/crsrsh.cxx')
-rw-r--r--sw/source/core/crsr/crsrsh.cxx3439
1 files changed, 3439 insertions, 0 deletions
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
new file mode 100644
index 000000000000..a91ccd2ee847
--- /dev/null
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -0,0 +1,3439 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * 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/util/SearchOptions.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <hintids.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/frmdiritem.hxx>
+
+#include <SwSmartTagMgr.hxx>
+#include <doc.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewimp.hxx>
+#include <pam.hxx>
+#include <swselectionlist.hxx>
+#include <IBlockCursor.hxx>
+#include "BlockCursor.hxx"
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <dview.hxx>
+#include <viewopt.hxx>
+#include <frmtool.hxx>
+#include <crsrsh.hxx>
+#include <tabfrm.hxx>
+#include <txtfrm.hxx>
+#include <sectfrm.hxx>
+#include <swtable.hxx>
+#include <callnk.hxx>
+#include <viscrs.hxx>
+#include <section.hxx>
+#include <docsh.hxx>
+#include <scriptinfo.hxx>
+#include <globdoc.hxx>
+#include <pamtyp.hxx>
+#include <mdiexp.hxx> // ...Percent()
+#include <fmteiro.hxx>
+#include <wrong.hxx> // SMARTTAGS
+#include <unotextrange.hxx> // SMARTTAGS
+#include <vcl/svapp.hxx>
+#include <numrule.hxx>
+#include <IGrammarContact.hxx>
+
+#include <globals.hrc>
+
+#include <comcore.hrc>
+
+using namespace com::sun::star;
+using namespace util;
+
+TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
+
+
+// Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
+void CheckRange( SwCursor* );
+
+//-----------------------------------------------------------------------
+
+/*
+ * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
+ * Wenn ja, dann hebe den alten Bereich auf.
+ */
+
+
+void CheckRange( SwCursor* pCurCrsr )
+{
+ const SwPosition *pStt = pCurCrsr->Start(),
+ *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
+
+ SwPaM *pTmpDel = 0,
+ *pTmp = (SwPaM*)pCurCrsr->GetNext();
+
+ // durchsuche den gesamten Ring
+ while( pTmp != pCurCrsr )
+ {
+ const SwPosition *pTmpStt = pTmp->Start(),
+ *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
+ pTmp->GetMark() : pTmp->GetPoint();
+ if( *pStt <= *pTmpStt )
+ {
+ if( *pEnd > *pTmpStt ||
+ ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
+ pTmpDel = pTmp;
+ }
+ else
+ if( *pStt < *pTmpEnd )
+ pTmpDel = pTmp;
+ /*
+ * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
+ * muss der alte Bereich aufgehoben werden.
+ * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
+ * Bereich gehoert !
+ */
+ pTmp = (SwPaM*)pTmp->GetNext();
+ if( pTmpDel )
+ {
+ delete pTmpDel; // hebe alten Bereich auf
+ pTmpDel = 0;
+ }
+ }
+}
+
+// -------------- Methoden von der SwCrsrShell -------------
+
+SwPaM * SwCrsrShell::CreateCrsr()
+{
+ // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
+ OSL_ENSURE( !IsTableMode(), "in Tabellen SSelection" );
+
+ // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
+ // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+
+ // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
+ // vom kopierten Pam aufgehoben wird !!
+
+ // #i75172#
+ pNew->swapContent(*pCurCrsr);
+
+ pCurCrsr->DeleteMark();
+
+ UpdateCrsr( SwCrsrShell::SCROLLWIN );
+// return pCurCrsr;
+ return pNew;
+}
+
+// loesche den aktuellen Cursor und der folgende wird zum Aktuellen
+
+
+sal_Bool SwCrsrShell::DestroyCrsr()
+{
+ // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
+ OSL_ENSURE( !IsTableMode(), "in Tabellen SSelection" );
+
+ // ist ueberhaupt ein naechtser vorhanden ?
+ if(pCurCrsr->GetNext() == pCurCrsr)
+ return sal_False;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
+ delete pCurCrsr;
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
+ UpdateCrsr();
+ return sal_True;
+}
+
+
+SwPaM & SwCrsrShell::CreateNewShellCursor()
+{
+ if (HasSelection())
+ {
+ (void) CreateCrsr(); // n.b. returns old cursor
+ }
+ return *GetCrsr();
+}
+
+SwPaM & SwCrsrShell::GetCurrentShellCursor()
+{
+ return *GetCrsr();
+}
+
+
+// gebe den aktuellen zurueck
+
+SwPaM* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr ) const
+{
+ if( pTblCrsr )
+ {
+ if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
+ {
+ // geparkte Cursor werden nicht wieder erzeugt
+ const SwCntntNode* pCNd;
+ if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
+ pTblCrsr->GetMark()->nNode.GetIndex() &&
+ 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) &&
+ 0 != ( pCNd = pTblCrsr->GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( GetLayout() ) )
+ {
+ SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
+ GetLayout()->MakeTblCrsrs( *pTC );
+ }
+ }
+
+ if( pTblCrsr->IsChgd() )
+ {
+ const_cast<SwCrsrShell*>(this)->pCurCrsr =
+ dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
+ }
+ }
+ return pCurCrsr;
+}
+
+
+void SwCrsrShell::StartAction()
+{
+ if( !ActionPend() )
+ {
+ // fuer das Update des Ribbon-Bars merken
+ const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
+ nAktNode = rNd.GetIndex();
+ nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
+ nAktNdTyp = rNd.GetNodeType();
+ bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
+ if( ND_TEXTNODE & nAktNdTyp )
+ nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, nAktCntnt, sal_True );
+ else
+ nLeftFrmPos = 0;
+ }
+ ViewShell::StartAction(); // zur ViewShell
+}
+
+
+void SwCrsrShell::EndAction( const sal_Bool bIdleEnd )
+{
+
+ sal_Bool bVis = bSVCrsrVis;
+
+ // Idle-Formatierung ?
+ if( bIdleEnd && Imp()->GetRegion() )
+ {
+ pCurCrsr->Hide();
+ }
+
+ // vor der letzten Action alle invaliden Numerierungen updaten
+ if( 1 == nStartAction )
+ GetDoc()->UpdateNumRule();
+
+ // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
+ // Only the UpdateCrsr shows the cursor.
+ sal_Bool bSavSVCrsrVis = bSVCrsrVis;
+ bSVCrsrVis = sal_False;
+
+ ViewShell::EndAction( bIdleEnd ); //der ViewShell den Vortritt lassen
+
+ bSVCrsrVis = bSavSVCrsrVis;
+
+ if( ActionPend() )
+ {
+ if( bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+
+ // falls noch ein ChgCall vorhanden ist und nur noch die Basic
+ // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
+ // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
+ if( !BasicActionPend() )
+ {
+ // es muss innerhalb einer BasicAction
+ // der Cursor geupdatet werden; um z.B. den
+ // TabellenCursor zu erzeugen. Im UpdateCrsr wird
+ // das jetzt beruecksichtigt!
+ UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
+
+ {
+ // Crsr-Moves ueberwachen, evt. Link callen
+ // der DTOR ist das interressante!!
+ SwCallLink aLk( *this, nAktNode, nAktCntnt, (sal_uInt8)nAktNdTyp,
+ nLeftFrmPos, bAktSelection );
+
+ }
+ if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
+ {
+ aChgLnk.Call( this );
+ bChgCallFlag = sal_False; // Flag zuruecksetzen
+ }
+ }
+ return;
+ }
+
+ sal_uInt16 nParm = SwCrsrShell::CHKRANGE;
+ if ( !bIdleEnd )
+ nParm |= SwCrsrShell::SCROLLWIN;
+// if( !IsViewLocked() )
+ UpdateCrsr( nParm, bIdleEnd ); // Cursor-Aenderungen anzeigen
+
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ aLk.nNode = nAktNode; // evt. Link callen
+ aLk.nNdTyp = (sal_uInt8)nAktNdTyp;
+ aLk.nCntnt = nAktCntnt;
+ aLk.nLeftFrmPos = nLeftFrmPos;
+
+ if( !nCrsrMove ||
+ ( 1 == nCrsrMove && bInCMvVisportChgd ) )
+ ShowCrsrs( bSVCrsrVis ? sal_True : sal_False ); // Cursor & Selektionen wieder anzeigen
+ }
+ // falls noch ein ChgCall vorhanden ist, dann rufe ihn
+ if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
+ {
+ aChgLnk.Call( this );
+ bChgCallFlag = sal_False; // Flag zuruecksetzen
+ }
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwCrsrShell::SttCrsrMove()
+{
+ OSL_ENSURE( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
+ ++nCrsrMove;
+ StartAction();
+}
+
+void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd )
+{
+ OSL_ENSURE( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
+ EndAction( bIdleEnd );
+ if( !--nCrsrMove )
+ bInCMvVisportChgd = sal_False;
+}
+
+#endif
+
+
+sal_Bool SwCrsrShell::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
+ sal_Bool bVisualAllowed )
+{
+ if( IsTableMode() )
+ return bLeft ? GoPrevCell() : GoNextCell();
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_Bool bRet = sal_False;
+
+ // #i27615# Handle cursor in front of label.
+ const SwTxtNode* pTxtNd = 0;
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ //
+ // 1. CASE: Cursor is in front of label. A move to the right
+ // will simply reset the bInFrontOfLabel flag:
+ //
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
+ {
+ SetInFrontOfLabel( sal_False );
+ bRet = sal_True;
+ }
+ //
+ // 2. CASE: Cursor is at beginning of numbered paragraph. A move
+ // to the left will simply set the bInFrontOfLabel flag:
+ //
+ else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
+ !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
+ 0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
+ pTxtNd->HasVisibleNumberingOrBullet() )
+ {
+ SetInFrontOfLabel( sal_True );
+ bRet = sal_True;
+ }
+ //
+ // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
+ //
+ else
+ {
+ const sal_Bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
+ // #i107447#
+ // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
+ // reflected in the return value <bRet>.
+ const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( sal_False );
+ bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
+ bSkipHidden, !IsOverwriteCrsr() );
+ if ( !bRet && bLeft && bResetOfInFrontOfLabel )
+ {
+ // undo reset of <bInFrontOfLabel> flag
+ SetInFrontOfLabel( sal_True );
+ }
+ }
+
+ if( bRet )
+ {
+ UpdateCrsr();
+ }
+ return bRet;
+}
+
+void SwCrsrShell::MarkListLevel( const String& sListId,
+ const int nListLevel )
+{
+ if ( sListId != sMarkedListId ||
+ nListLevel != nMarkedListLevel)
+ {
+ if ( sMarkedListId.Len() > 0 )
+ pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, sal_False );
+
+ if ( sListId.Len() > 0 )
+ {
+ pDoc->MarkListLevel( sListId, nListLevel, sal_True );
+ }
+
+ sMarkedListId = sListId;
+ nMarkedListLevel = nListLevel;
+ }
+}
+
+void SwCrsrShell::UpdateMarkedListLevel()
+{
+ SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
+
+ if ( pTxtNd )
+ {
+ if ( !pTxtNd->IsNumbered() )
+ {
+ pCurCrsr->_SetInFrontOfLabel( sal_False );
+ MarkListLevel( String(), 0 );
+ }
+ else if ( pCurCrsr->IsInFrontOfLabel() )
+ {
+ if ( pTxtNd->IsInList() )
+ {
+ OSL_ENSURE( pTxtNd->GetActualListLevel() >= 0 &&
+ pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?");
+ MarkListLevel( pTxtNd->GetListId(),
+ pTxtNd->GetActualListLevel() );
+ }
+ }
+ else
+ {
+ MarkListLevel( String(), 0 );
+ }
+ }
+}
+// <--
+
+sal_Bool SwCrsrShell::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ sal_Bool bTableMode = IsTableMode();
+ SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+
+ sal_Bool bRet = pTmpCrsr->UpDown( bUp, nCnt );
+ // #i40019# UpDown should always reset the bInFrontOfLabel flag:
+ bRet = SetInFrontOfLabel(sal_False) || bRet;
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ if( bRet )
+ {
+ eMvState = MV_UPDOWN; // Status fuers Crsr-Travelling - GetCrsrOfst
+ if( !ActionPend() )
+ {
+ CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
+ if( !bTableMode )
+ eUpdtMode = (CrsrFlag) (eUpdtMode
+ | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
+ UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) );
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::LRMargin( sal_Bool bLeft, sal_Bool bAPI)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SET_CURR_SHELL( this );
+ eMvState = MV_LEFTMARGIN; // Status fuers Crsr-Travelling - GetCrsrOfst
+
+ const sal_Bool bTableMode = IsTableMode();
+ SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ const sal_Bool bWasAtLM =
+ ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
+
+ sal_Bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
+
+ if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
+ {
+ const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
+ if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
+ SetInFrontOfLabel( sal_True );
+ }
+ else if ( !bLeft )
+ {
+ bRet = SetInFrontOfLabel( sal_False ) || bRet;
+ }
+
+ if( bRet )
+ {
+ UpdateCrsr();
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::IsAtLRMargin( sal_Bool bLeft, sal_Bool bAPI ) const
+{
+ const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+ return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
+}
+
+
+sal_Bool SwCrsrShell::SttEndDoc( sal_Bool bStt )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
+ sal_Bool bRet = pTmpCrsr->SttEndDoc( bStt );
+ if( bRet )
+ {
+ if( bStt )
+ pTmpCrsr->GetPtPos().Y() = 0; // expl. 0 setzen (TabellenHeader)
+ if( pBlockCrsr )
+ {
+ pBlockCrsr->clearPoints();
+ RefreshBlockCursor();
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+void SwCrsrShell::ExtendedSelectAll()
+{
+ SwNodes& rNodes = GetDoc()->GetNodes();
+ SwPosition* pPos = pCurCrsr->GetPoint();
+ pPos->nNode = rNodes.GetEndOfPostIts();
+ pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
+ pPos = pCurCrsr->GetMark();
+ pPos->nNode = rNodes.GetEndOfContent();
+ SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
+ pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
+}
+
+sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
+{
+ sal_Bool bRet = sal_False;
+
+ // Springe beim Selektieren nie ueber Section-Grenzen !!
+ if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SET_CURR_SHELL( this );
+
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ Point& rPt = pCurCrsr->GetPtPos();
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
+ getLayoutFrm( GetLayout(), &rPt, pCurCrsr->GetPoint(), sal_False );
+ if( pFrm && sal_True == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
+ fnPosPage, pCurCrsr ) ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
+ UpdateCrsr();
+ else
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCursor* pTmpCrsr = getShellCrsr( true );
+ sal_Bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
+ SwPosSection fnPosSect)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCursor* pTmpCrsr = getShellCrsr( true );
+ sal_Bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+
+}
+
+
+// Positionieren des Cursors
+
+
+SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
+{
+ SwFrm* pFrm = 0;
+ SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False )->GetUpper();
+ while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
+ pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
+ : pFrm->GetUpper();
+ }
+ return pFrm;
+}
+
+sal_Bool SwCrsrShell::IsInHeaderFooter( sal_Bool* pbInHeader ) const
+{
+ Point aPt;
+ SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
+ if( pFrm && pbInHeader )
+ *pbInHeader = pFrm->IsHeaderFrm();
+ return 0 != pFrm;
+}
+
+int SwCrsrShell::SetCrsr( const Point &rLPt, sal_Bool bOnlyText, bool bBlock )
+{
+ SET_CURR_SHELL( this );
+
+ SwShellCrsr* pCrsr = getShellCrsr( bBlock );
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( rLPt );
+ Point & rAktCrsrPt = pCrsr->GetPtPos();
+ SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
+ bOnlyText ? MV_SETONLYTEXT : MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
+
+ if ( pTxtNd && !IsTableMode() &&
+ // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
+ !pCrsr->HasMark() &&
+ // <--
+ pTxtNd->HasVisibleNumberingOrBullet() )
+ {
+ aTmpState.bInFrontOfLabel = sal_True; // #i27615#
+ }
+ else
+ {
+ aTmpState.bInFrontOfLabel = sal_False;
+ }
+
+ int bRet = CRSR_POSOLD |
+ ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
+ ? 0 : CRSR_POSCHG );
+
+ const bool bOldInFrontOfLabel = IsInFrontOfLabel();
+ const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
+
+ pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
+
+ if( MV_RIGHTMARGIN == aTmpState.eState )
+ eMvState = MV_RIGHTMARGIN;
+ // steht neu Pos im Header/Footer ?
+ SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
+ if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
+ pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
+ // gleiche Tabellenzelle und nicht im Header/Footer
+ // -> zurueck
+ return bRet;
+
+ if( pBlockCrsr && bBlock )
+ {
+ pBlockCrsr->setEndPoint( rLPt );
+ if( !pCrsr->HasMark() )
+ pBlockCrsr->setStartPoint( rLPt );
+ else if( !pBlockCrsr->getStartPoint() )
+ pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
+ }
+ if( !pCrsr->HasMark() )
+ {
+ // steht an der gleichen Position und wenn im Header/Footer,
+ // dann im gleichen
+ if( aPos == *pCrsr->GetPoint() &&
+ bOldInFrontOfLabel == bNewInFrontOfLabel )
+ {
+ if( pFrm )
+ {
+ if( pFrm->Frm().IsInside( rAktCrsrPt ))
+ return bRet;
+ }
+ else if( aPos.nNode.GetNode().IsCntntNode() )
+ {
+ // im gleichen Frame gelandet?
+ SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
+ GetLayout(), &aCharRect.Pos(), 0, sal_False );
+ SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
+ GetLayout(), &aPt, 0, sal_False );
+ if( pNew == pOld )
+ return bRet;
+ }
+ }
+ }
+ else
+ {
+ // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
+ // dann in verschiedene
+ if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, sal_True )
+ || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
+ return bRet;
+
+ // steht an der gleichen Position und nicht im Header/Footer
+ if( aPos == *pCrsr->GetPoint() )
+ return bRet;
+ }
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ *pCrsr->GetPoint() = aPos;
+ rAktCrsrPt = aPt;
+
+ // #i41424# Only update the marked number levels if necessary
+ // Force update of marked number levels if necessary.
+ if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
+ pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
+ SetInFrontOfLabel( bNewInFrontOfLabel );
+
+ if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ {
+ sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
+ UpdateCrsr( nFlag );
+ bRet &= ~CRSR_POSOLD;
+ }
+ else if( bOnlyText && !pCurCrsr->HasMark() )
+ {
+ if( FindValidCntntNode( bOnlyText ) )
+ {
+ // Cursor in einen gueltigen Content stellen
+ if( aPos == *pCrsr->GetPoint() )
+ bRet = CRSR_POSOLD;
+ else
+ {
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
+ bRet &= ~CRSR_POSOLD;
+ }
+ }
+ else
+ {
+ // es gibt keinen gueltigen Inhalt -> Cursor verstecken
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = sal_True;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ }
+ }
+
+ return bRet;
+}
+
+
+void SwCrsrShell::TblCrsrToCursor()
+{
+ OSL_ENSURE( pTblCrsr, "TblCrsrToCursor: Why?" );
+ delete pTblCrsr, pTblCrsr = 0;
+}
+
+void SwCrsrShell::BlockCrsrToCrsr()
+{
+ OSL_ENSURE( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
+ if( pBlockCrsr && !HasSelection() )
+ {
+ SwPaM& rPam = pBlockCrsr->getShellCrsr();
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetPoint() = *rPam.GetPoint();
+ if( rPam.HasMark() )
+ *pCurCrsr->GetMark() = *rPam.GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ }
+ delete pBlockCrsr, pBlockCrsr = 0;
+}
+
+void SwCrsrShell::CrsrToBlockCrsr()
+{
+ if( !pBlockCrsr )
+ {
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ pBlockCrsr = createBlockCursor( *this, aPos );
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ rBlock.GetPtPos() = pCurCrsr->GetPtPos();
+ if( pCurCrsr->HasMark() )
+ {
+ rBlock.SetMark();
+ *rBlock.GetMark() = *pCurCrsr->GetMark();
+ rBlock.GetMkPos() = pCurCrsr->GetMkPos();
+ }
+ }
+ pBlockCrsr->clearPoints();
+ RefreshBlockCursor();
+}
+
+void SwCrsrShell::ClearMark()
+{
+ // ist ueberhaupt ein GetMark gesetzt ?
+ if( pTblCrsr )
+ {
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pTblCrsr->DeleteMark();
+
+ if( pCurCrsr->HasMark() )
+ {
+ // falls doch nicht alle Indizies richtig verschoben werden
+ // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
+ // Mark aufs Nodes-Array setzen
+ SwPosition& rPos = *pCurCrsr->GetMark();
+ rPos.nNode.Assign( pDoc->GetNodes(), 0 );
+ rPos.nContent.Assign( 0, 0 );
+ pCurCrsr->DeleteMark();
+ }
+
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr, pTblCrsr = 0;
+ pCurCrsr->SwSelPaintRects::Show();
+ }
+ else
+ {
+ if( !pCurCrsr->HasMark() )
+ return;
+ // falls doch nicht alle Indizies richtig verschoben werden
+ // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
+ // Mark aufs Nodes-Array setzen
+ SwPosition& rPos = *pCurCrsr->GetMark();
+ rPos.nNode.Assign( pDoc->GetNodes(), 0 );
+ rPos.nContent.Assign( 0, 0 );
+ pCurCrsr->DeleteMark();
+ if( !nCrsrMove )
+ pCurCrsr->SwSelPaintRects::Show();
+ }
+}
+
+
+void SwCrsrShell::NormalizePam(sal_Bool bPointFirst)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->Normalize(bPointFirst);
+}
+
+void SwCrsrShell::SwapPam()
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->Exchange();
+}
+
+
+// suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
+// den angebenen SPoint umschliesst
+// Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
+// SSelection besteht; des akt. Cursr wird nicht umgesetzt!
+// Ansonsten wird er auf die gewaehlte SSelection gesetzt.
+
+
+sal_Bool SwCrsrShell::ChgCurrPam( const Point & rPt,
+ sal_Bool bTstOnly, sal_Bool bTstHit )
+{
+ SET_CURR_SHELL( this );
+
+ // Pruefe ob der SPoint in einer Tabellen-Selektion liegt
+ if( bTstOnly && pTblCrsr )
+ return pTblCrsr->IsInside( rPt );
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ // Suche die Position rPt im Dokument
+ SwPosition aPtPos( *pCurCrsr->GetPoint() );
+ Point aPt( rPt );
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
+ return sal_False;
+
+ // suche in allen Selektionen nach dieser Position
+ SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr; // sicher den Pointer auf Cursor
+ do {
+ if( pCmp->HasMark() &&
+ *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
+ {
+ if( bTstOnly || pCurCrsr == pCmp ) // ist der aktuelle.
+ return sal_True; // return ohne Update
+
+ pCurCrsr = pCmp;
+ UpdateCrsr(); // Cursor steht schon richtig
+ return sal_True;
+ }
+ } while( pCurCrsr !=
+ ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
+ return sal_False;
+}
+
+
+void SwCrsrShell::KillPams()
+{
+ // keiner zum loeschen vorhanden?
+ if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
+ return;
+
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pCurCrsr->SetColumnSelection( false );
+
+ if( pTblCrsr )
+ {
+ // Cursor Ring loeschen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr;
+ pTblCrsr = 0;
+ }
+ else if( pBlockCrsr )
+ {
+ // delete the ring of cursors
+ pCurCrsr->DeleteMark();
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ *pCurCrsr->GetPoint() = *rBlock.GetPoint();
+ pCurCrsr->GetPtPos() = rBlock.GetPtPos();
+ rBlock.DeleteMark();
+ pBlockCrsr->clearPoints();
+ }
+ UpdateCrsr( SwCrsrShell::SCROLLWIN );
+}
+
+
+int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
+{
+ int nRet = 0;
+ const SwPosition *pFirst = 0, *pSecond = 0;
+ const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
+ if( CurrPtCurrMk != eType && pStk )
+ {
+ switch ( eType)
+ {
+ case StackPtStackMk:
+ pFirst = pStk->GetPoint();
+ pSecond = pStk->GetMark();
+ break;
+ case StackPtCurrPt:
+ pFirst = pStk->GetPoint();
+ pSecond = pCur->GetPoint();
+ break;
+ case StackPtCurrMk:
+ pFirst = pStk->GetPoint();
+ pSecond = pCur->GetMark();
+ break;
+ case StackMkCurrPt:
+ pFirst = pStk->GetMark();
+ pSecond = pCur->GetPoint();
+ break;
+ case StackMkCurrMk:
+ pFirst = pStk->GetMark();
+ pSecond = pStk->GetMark();
+ break;
+ case CurrPtCurrMk:
+ pFirst = pCur->GetPoint();
+ pSecond = pCur->GetMark();
+ break;
+ }
+ }
+ if( !pFirst || !pSecond )
+ nRet = INT_MAX;
+ else if( *pFirst < *pSecond )
+ nRet = -1;
+ else if( *pFirst == *pSecond )
+ nRet = 0;
+ else
+ nRet = 1;
+ return nRet;
+}
+
+
+sal_Bool SwCrsrShell::IsSttPara() const
+{ return( pCurCrsr->GetPoint()->nContent == 0 ? sal_True : sal_False ); }
+
+
+sal_Bool SwCrsrShell::IsEndPara() const
+{ return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? sal_True : sal_False ); }
+
+
+sal_Bool SwCrsrShell::IsInFrontOfLabel() const
+{
+ return pCurCrsr->IsInFrontOfLabel();
+}
+
+bool SwCrsrShell::SetInFrontOfLabel( sal_Bool bNew )
+{
+ if ( bNew != IsInFrontOfLabel() )
+ {
+ pCurCrsr->_SetInFrontOfLabel( bNew );
+ UpdateMarkedListLevel();
+ return true;
+ }
+ return false;
+}
+
+sal_Bool SwCrsrShell::GotoPage( sal_uInt16 nPage )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ sal_Bool bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
+ sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm )
+{
+ SET_CURR_SHELL( this );
+ // Seitennummer: die erste sichtbare Seite oder die am Cursor
+ const SwCntntFrm* pCFrm;
+ const SwPageFrm *pPg = 0;
+
+ if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
+ 0 == (pPg = pCFrm->FindPageFrm()) )
+ {
+ pPg = Imp()->GetFirstVisPage();
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
+ // standard.vor sein.
+ rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
+ rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
+}
+
+
+sal_uInt16 SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext )
+{
+ SET_CURR_SHELL( this );
+
+ // Seitennummer: die erste sichtbare Seite oder die am Cursor
+ const SwPageFrm *pPg = Imp()->GetFirstVisPage();
+ if( pPg )
+ {
+ const SwTwips nPageTop = pPg->Frm().Top();
+
+ if( bNext )
+ {
+ // go to next view layout row:
+ do
+ {
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ while( pPg && pPg->Frm().Top() == nPageTop );
+
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ else
+ {
+ // go to previous view layout row:
+ do
+ {
+ pPg = (const SwPageFrm *)pPg->GetPrev();
+ }
+ while( pPg && pPg->Frm().Top() == nPageTop );
+
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetPrev();
+ }
+ }
+ // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
+ // standard.vor sein.
+ return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
+}
+
+
+sal_uInt16 SwCrsrShell::GetPageCnt()
+{
+ SET_CURR_SHELL( this );
+ // gebe die Anzahl der Seiten zurueck
+ return GetLayout()->GetPageNum();
+}
+
+// Gehe zur naechsten SSelection
+
+
+sal_Bool SwCrsrShell::GoNextCrsr()
+{
+ // besteht ueberhaupt ein Ring ?
+ if( pCurCrsr->GetNext() == pCurCrsr )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
+
+ // Bug 24086: auch alle anderen anzeigen
+ if( !ActionPend() )
+ {
+ UpdateCrsr();
+ pCurCrsr->Show();
+ }
+ return sal_True;
+}
+
+// gehe zur vorherigen SSelection
+
+
+sal_Bool SwCrsrShell::GoPrevCrsr()
+{
+ // besteht ueberhaupt ein Ring ?
+ if( pCurCrsr->GetNext() == pCurCrsr )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
+
+ // Bug 24086: auch alle anderen anzeigen
+ if( !ActionPend() )
+ {
+ UpdateCrsr();
+ pCurCrsr->Show();
+ }
+
+ return sal_True;
+}
+
+
+void SwCrsrShell::Paint( const Rectangle &rRect)
+{
+ SET_CURR_SHELL( this );
+
+ // beim Painten immer alle Cursor ausschalten
+ SwRect aRect( rRect );
+
+ sal_Bool bVis = sal_False;
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ???
+ {
+ bVis = sal_True;
+ pVisCrsr->Hide();
+ }
+
+ // Bereich neu painten
+ ViewShell::Paint( rRect );
+
+ if( bHasFocus && !bBasicHideCrsr )
+ {
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+// pAktCrsr->Invalidate( aRect );
+ if( !ActionPend() )
+ {
+ // damit nicht rechts/unten die Raender abgeschnitten werden
+ pAktCrsr->Invalidate( VisArea() );
+ pAktCrsr->Show();
+ }
+ else
+ pAktCrsr->Invalidate( aRect );
+
+ }
+ if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+}
+
+
+
+void SwCrsrShell::VisPortChgd( const SwRect & rRect )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bVis; // beim Scrollen immer alle Cursor ausschalten
+
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
+ pVisCrsr->Hide();
+
+ bVisPortChgd = sal_True;
+ aOldRBPos.X() = VisArea().Right();
+ aOldRBPos.Y() = VisArea().Bottom();
+
+ //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
+ //ViewShell::VisPo.. ein Update() auf das Window gerufen.
+ //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
+ //angezeigt werden, deshalb wird der Aufruf hier geklammert.
+ ViewShell::VisPortChgd( rRect ); // Bereich verschieben
+
+ if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+
+ if( nCrsrMove )
+ bInCMvVisportChgd = sal_True;
+
+ bVisPortChgd = sal_False;
+}
+
+// aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
+// Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
+// Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
+// ergibt sich aus seiner aktuellen Position im Layout !!
+
+
+void SwCrsrShell::UpdateCrsrPos()
+{
+ SET_CURR_SHELL( this );
+ ++nStartAction;
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ Size aOldSz( GetDocSize() );
+ SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
+ SwCntntFrm *pFrm = pCNode ?
+ pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
+ if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
+ &aTmpState );
+ if( pShellCrsr->HasMark())
+ pShellCrsr->DeleteMark();
+ }
+ IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
+ if( pGrammarContact )
+ pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
+ --nStartAction;
+ if( aOldSz != GetDocSize() )
+ SizeChgNotify();
+}
+
+// JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
+// stehen, so mussen diese daraus verschoben werden
+static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
+{
+ const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
+ if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
+ {
+ SwNodeIndex aTmp( *pSectNd );
+#if OSL_DEBUG_LEVEL > 1
+ const SwNode* pFrmNd =
+#endif
+ rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
+
+#if OSL_DEBUG_LEVEL > 1
+ (void) pFrmNd;
+ OSL_ENSURE( pFrmNd, "keinen Node mit Frames gefunden" );
+#endif
+ rIdx = aTmp;
+ }
+}
+
+// Try to set the cursor to the next visible content node.
+static void lcl_CheckHiddenPara( SwPosition& rPos )
+{
+ SwNodeIndex aTmp( rPos.nNode );
+ SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
+ while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
+ {
+ SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
+ if ( pCntnt && pCntnt->IsTxtNode() )
+ pTxtNd = (SwTxtNode*)pCntnt;
+ else
+ pTxtNd = 0;
+ }
+
+ if ( pTxtNd )
+ rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
+}
+
+// #i27301# - helper class, which notifies the accessibility about invalid text
+// selections in its destructor
+class SwNotifyAccAboutInvalidTextSelections
+{
+ private:
+ SwCrsrShell& mrCrsrSh;
+
+ public:
+ SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
+ : mrCrsrSh( _rCrsrSh )
+ {}
+
+ ~SwNotifyAccAboutInvalidTextSelections()
+ {
+ mrCrsrSh.InvalidateAccessibleParaTextSelection();
+ }
+};
+// <--
+void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
+{
+ SET_CURR_SHELL( this );
+
+ ClearUpCrsrs();
+
+ // es muss innerhalb einer BasicAction der
+ // Cursor geupdatet werden; um z.B. den TabellenCursor zu
+ // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
+ if( ActionPend() && BasicActionPend() )
+ {
+ if ( eFlags & SwCrsrShell::READONLY )
+ bIgnoreReadonly = sal_True;
+ return; // wenn nicht, dann kein Update !!
+ }
+
+ // #i27301#
+ SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
+
+ if ( bIgnoreReadonly )
+ {
+ bIgnoreReadonly = sal_False;
+ eFlags |= SwCrsrShell::READONLY;
+ }
+
+ if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf
+ CheckRange( pCurCrsr ); // ueberlappende Bereiche testen
+
+ if( !bIdleEnd )
+ CheckTblBoxCntnt();
+
+ // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
+ // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
+ SwPaM* pTstCrsr = getShellCrsr( true );
+ if( pTstCrsr->HasMark() && !pBlockCrsr &&
+ pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
+ ( pTblCrsr ||
+ pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
+ pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
+ {
+ SwShellCrsr* pITmpCrsr = getShellCrsr( true );
+ Point aTmpPt( pITmpCrsr->GetPtPos() );
+ Point aTmpMk( pITmpCrsr->GetMkPos() );
+ SwPosition* pPos = pITmpCrsr->GetPoint();
+
+ // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
+ // stehen, so mussen diese daraus verschoben werden
+ lcl_CheckHiddenSection( pPos->nNode );
+ lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
+
+ // Move cursor out of hidden paragraphs
+ if ( !GetViewOptions()->IsShowHiddenChar() )
+ {
+ lcl_CheckHiddenPara( *pPos );
+ lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
+ }
+
+ SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
+ getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
+
+ OSL_ENSURE( pTblFrm, "Tabelle Crsr nicht im Content ??" );
+
+ // --> Make code robust. The table cursor may point
+ // to a table in a currently inactive header.
+ SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
+ // <--
+
+ if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
+ {
+ // First check if point is in repeated headline:
+ bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
+
+ // Second check if mark is in repeated headline:
+ if ( !bInRepeatedHeadline )
+ {
+ SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
+ getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
+ OSL_ENSURE( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
+
+ if ( pMarkTblFrm )
+ {
+ SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
+ OSL_ENSURE( pMarkTab, "Tabelle Crsr nicht im Content ??" );
+
+ // Make code robust:
+ if ( pMarkTab )
+ {
+ bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
+ }
+ }
+ }
+
+ // No table cursor in repeaded headlines:
+ if ( bInRepeatedHeadline )
+ {
+ pTblFrm = 0;
+
+ SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
+ ? fnSectionStart
+ : fnSectionEnd;
+
+ // dann nur innerhalb der Box selektieren
+ if( pTblCrsr )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
+ pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
+ pTblCrsr->DeleteMark();
+ pTblCrsr->SwSelPaintRects::Hide();
+ }
+
+ *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
+ (*fnSectionCurr)( *pCurCrsr, fnPosSect );
+ }
+ }
+
+ // wir wollen wirklich eine Tabellen-Selektion
+ if( pTab && pTblFrm )
+ {
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this,
+ *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
+ *pPos, aTmpPt );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+
+ CheckTblBoxCntnt();
+ }
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bRealHeight = sal_True;
+ if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
+ {
+ Point aCentrPt( aCharRect.Center() );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
+#if OSL_DEBUG_LEVEL > 1
+ if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
+ OSL_ENSURE( !this, "GetCharRect failed." );
+#else
+ pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
+#endif
+ }
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ // Curosr in den sichtbaren Bereich scrollen
+ if( (eFlags & SwCrsrShell::SCROLLWIN) &&
+ (HasSelection() || eFlags & SwCrsrShell::READONLY ||
+ !IsCrsrReadonly()) )
+ {
+ SwFrm* pBoxFrm = pTblFrm;
+ while( pBoxFrm && !pBoxFrm->IsCellFrm() )
+ pBoxFrm = pBoxFrm->GetUpper();
+ if( pBoxFrm && pBoxFrm->Frm().HasArea() )
+ MakeVisible( pBoxFrm->Frm() );
+ else
+ MakeVisible( aCharRect );
+ }
+
+ // lasse vom Layout die Crsr in den Boxen erzeugen
+ if( pTblCrsr->IsCrsrMovedUpdt() )
+ GetLayout()->MakeTblCrsrs( *pTblCrsr );
+ if( bHasFocus && !bBasicHideCrsr )
+ pTblCrsr->Show();
+
+ // Cursor-Points auf die neuen Positionen setzen
+ pTblCrsr->GetPtPos().X() = aCharRect.Left();
+ pTblCrsr->GetPtPos().Y() = aCharRect.Top();
+
+ if( bSVCrsrVis )
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
+ -aCharRect.Width() : aCharRect.Height();
+ pVisCrsr->Show(); // wieder anzeigen
+ }
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
+ if( pTblFrm && Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
+ return;
+ }
+ }
+
+ if( pTblCrsr )
+ {
+ // Cursor Ring loeschen
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr, pTblCrsr = 0;
+ }
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+
+ // sind wir vielleicht in einer geschuetzten/versteckten Section ?
+ {
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ sal_Bool bChgState = sal_True;
+ const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
+ if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() &&
+ ( !pDoc->GetDocShell() ||
+ !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
+ {
+ if( !FindValidCntntNode( !HasDrawView() ||
+ 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
+ {
+ // alles ist geschuetzt / versteckt -> besonderer Mode
+ if( bAllProtect && !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() )
+ bChgState = sal_False;
+ else
+ {
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = sal_True;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ return;
+ }
+ }
+ }
+ if( bChgState )
+ {
+ sal_Bool bWasAllProtect = bAllProtect;
+ bAllProtect = sal_False;
+ if( bWasAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ }
+ }
+
+ UpdateCrsrPos();
+
+ // The cursor must always point into content; there's some code
+ // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
+ // loops _behind_ the last node in the selection, which always works if you
+ // are in content.) To achieve this, we'll force cursor(s) to point into
+ // content, if UpdateCrsrPos() hasn't already done so.
+ SwPaM* pCmp = pCurCrsr;
+ do
+ {
+ // start will move forwards, end will move backwards
+ bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
+
+ // move point; forward if it's the start, backwards if it's the end
+ if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
+ pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
+ fnGoCntnt );
+
+ // move mark (if exists); forward if it's the start, else backwards
+ if( pCmp->HasMark() )
+ {
+ if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
+ {
+ pCmp->Exchange();
+ pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
+ fnGoCntnt );
+ pCmp->Exchange();
+ }
+ }
+
+ // iterate to next PaM in ring
+ pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
+ }
+ while( pCmp != pCurCrsr );
+
+
+ SwRect aOld( aCharRect );
+ sal_Bool bFirst = sal_True;
+ SwCntntFrm *pFrm;
+ int nLoopCnt = 100;
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+
+ do {
+ sal_Bool bAgainst;
+ do {
+ bAgainst = sal_False;
+ pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
+ &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
+ // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
+ // erzeugt werden, weil ja mal hier einer vorhanden war !!
+ if ( !pFrm )
+ {
+ do
+ {
+ CalcLayout();
+ pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
+ &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
+ } while( !pFrm );
+ }
+ else if ( Imp()->IsIdleAction() )
+ //Wir stellen sicher, dass anstaendig Formatiert wurde
+ pFrm->PrepareCrsr();
+
+ // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
+ if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
+ ( !Imp()->GetDrawView() ||
+ !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
+ (!pDoc->GetDocShell() ||
+ !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
+ {
+ // dann suche eine gueltige Position
+ sal_Bool bChgState = sal_True;
+ if( !FindValidCntntNode(!HasDrawView() ||
+ 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
+ {
+ // alles ist geschuetzt / versteckt -> besonderer Mode
+ if( bAllProtect )
+ bChgState = sal_False;
+ else
+ {
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = sal_True;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ return;
+ }
+ }
+
+ if( bChgState )
+ {
+ sal_Bool bWasAllProtect = bAllProtect;
+ bAllProtect = sal_False;
+ if( bWasAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ bAllProtect = sal_False;
+ bAgainst = sal_True; // nochmal den richigen Frm suchen
+ }
+ }
+ } while( bAgainst );
+
+ if( !( eFlags & SwCrsrShell::NOCALRECT ))
+ {
+ SwCrsrMoveState aTmpState( eMvState );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.bRealHeight = sal_True;
+ aTmpState.bRealWidth = IsOverwriteCrsr();
+ aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
+
+ // #i27615#,#i30453#
+ SwSpecialPos aSpecialPos;
+ aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
+ if (pShellCrsr->IsInFrontOfLabel())
+ {
+ aTmpState.pSpecialPos = &aSpecialPos;
+ }
+
+ if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
+ {
+ Point& rPt = pShellCrsr->GetPtPos();
+ rPt = aCharRect.Center();
+ pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
+ }
+
+ if( !pShellCrsr->HasMark() )
+ aCrsrHeight = aTmpState.aRealHeight;
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
+ -aCharRect.Width() : aCharRect.Height();
+ }
+ }
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aCharRect.Height();
+ }
+
+ if( !bFirst && aOld == aCharRect )
+ break;
+
+ // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
+ // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
+ // siehe Bug: 29658
+ if( !--nLoopCnt )
+ {
+ OSL_ENSURE( !this, "Endlosschleife? CharRect != OldCharRect ");
+ break;
+ }
+ aOld = aCharRect;
+ bFirst = sal_False;
+
+ // Cursor-Points auf die neuen Positionen setzen
+ pShellCrsr->GetPtPos().X() = aCharRect.Left();
+ pShellCrsr->GetPtPos().Y() = aCharRect.Top();
+
+ if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen
+ {
+ pFrm->Calc();
+ nUpDownX = pFrm->IsVertical() ?
+ aCharRect.Top() - pFrm->Frm().Top() :
+ aCharRect.Left() - pFrm->Frm().Left();
+ }
+
+ // Curosr in den sichtbaren Bereich scrollen
+ if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
+ (HasSelection() || eFlags & SwCrsrShell::READONLY ||
+ !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
+ {
+ //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den
+ // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
+ // gesichert und zurueckgesetzt.
+ sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
+ MakeSelVisible();
+ bSVCrsrVis = bSav;
+ }
+
+ } while( eFlags & SwCrsrShell::SCROLLWIN );
+
+ if( pBlockCrsr )
+ RefreshBlockCursor();
+
+ if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
+ {
+ if( pTblCrsr )
+ pTblCrsr->SwSelPaintRects::Show();
+ else
+ {
+ pCurCrsr->SwSelPaintRects::Show();
+ if( pBlockCrsr )
+ {
+ SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
+ while( pNxt && pNxt != pCurCrsr )
+ {
+ pNxt->SwSelPaintRects::Show();
+ pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
+ }
+ }
+ }
+ }
+
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
+
+ if( pFrm && Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleCursorPosition( pFrm );
+
+ // switch from blinking cursor to read-only-text-selection cursor
+ static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
+ const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
+ GetCursorBlinkTime();
+
+ if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
+ ( nBlinkTime != nNoBlinkTime ) )
+ {
+ // non blinking cursor in read only - text selection mode
+ AllSettings aSettings = GetOut()->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
+ Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
+ nNoBlinkTime;
+ aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
+ aSettings.SetStyleSettings( aStyleSettings );
+ GetOut()->SetSettings( aSettings );
+ }
+
+ if( bSVCrsrVis )
+ pVisCrsr->Show(); // wieder anzeigen
+}
+
+void SwCrsrShell::RefreshBlockCursor()
+{
+ OSL_ENSURE( pBlockCrsr, "Don't call me without a block cursor" );
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ Point aPt = rBlock.GetPtPos();
+ SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
+ Point aMk;
+ if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
+ {
+ aPt = *pBlockCrsr->getStartPoint();
+ aMk = *pBlockCrsr->getEndPoint();
+ }
+ else
+ {
+ aPt = rBlock.GetPtPos();
+ if( pFrm )
+ {
+ if( pFrm->IsVertical() )
+ aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
+ else
+ aPt.X() = pFrm->Frm().Left() + GetUpDownX();
+ }
+ aMk = rBlock.GetMkPos();
+ }
+ SwRect aRect( aMk, aPt );
+ aRect.Justify();
+ SwSelectionList aSelList( pFrm );
+
+ if( GetLayout()->FillSelection( aSelList, aRect ) )
+ {
+ SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
+ while( pNxt != pCurCrsr )
+ {
+ delete pNxt;
+ pNxt = (SwCursor*)pCurCrsr->GetNext();
+ }
+
+ std::list<SwPaM*>::iterator pStart = aSelList.getStart();
+ std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
+ OSL_ENSURE( pPam != pStart, "FillSelection should deliver at least one PaM" );
+ pCurCrsr->SetMark();
+ --pPam;
+ // If there is only one text portion inside the rectangle, a simple
+ // selection is created
+ if( pPam == pStart )
+ {
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
+ if( (*pPam)->HasMark() )
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ delete *pPam;
+ pCurCrsr->SetColumnSelection( false );
+ }
+ else
+ {
+ // The order of the SwSelectionList has to be preserved but
+ // the order inside the ring created by CreateCrsr() is not like
+ // exspected => First create the selections before the last one
+ // downto the first selection.
+ // At least create the cursor for the last selection
+ --pPam;
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
+ if( (*pPam)->HasMark() )
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ delete *pPam;
+ pCurCrsr->SetColumnSelection( true );
+ while( pPam != pStart )
+ {
+ --pPam;
+
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+ pNew->Insert( pCurCrsr, 0 );
+ pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pCurCrsr->DeleteMark();
+
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
+ if( (*pPam)->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ }
+ else
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetColumnSelection( true );
+ delete *pPam;
+ }
+ {
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+ pNew->Insert( pCurCrsr, 0 );
+ pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pCurCrsr->DeleteMark();
+ }
+ pPam = aSelList.getEnd();
+ --pPam;
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
+ if( (*pPam)->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ }
+ else
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetColumnSelection( true );
+ delete *pPam;
+ }
+ }
+}
+
+// erzeuge eine Kopie vom Cursor und speicher diese im Stack
+
+
+void SwCrsrShell::Push()
+{
+ pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
+ pCurCrsr->GetPtPos(), pCrsrStk );
+
+ if( pCurCrsr->HasMark() )
+ {
+ pCrsrStk->SetMark();
+ *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
+ }
+}
+
+/*
+ * Loescht einen Cursor (gesteuert durch bOldCrsr)
+ * - vom Stack oder ( bOldCrsr = sal_True )
+ * - den aktuellen und der auf dem Stack stehende wird zum aktuellen
+ *
+ * Return: es war auf dem Stack noch einer vorhanden
+ */
+
+
+sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ // noch weitere vorhanden ?
+ if( 0 == pCrsrStk )
+ return sal_False;
+
+ SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
+
+ // der Nachfolger wird der Aktuelle
+ if( pCrsrStk->GetNext() != pCrsrStk )
+ {
+ pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
+ }
+
+ if( bOldCrsr ) // loesche vom Stack
+ delete pCrsrStk; //
+
+ pCrsrStk = pTmp; // neu zuweisen
+
+ if( !bOldCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // wurde die sichtbare SSelection nicht veraendert
+ if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
+ pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
+ {
+ // "Selektions-Rechtecke" verschieben
+ pCurCrsr->Insert( pOldStk, 0 );
+ pOldStk->Remove( 0, pOldStk->Count() );
+ }
+
+ if( pOldStk->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pOldStk->GetMark();
+ pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
+ }
+ else
+ // keine Selection also alte aufheben und auf die alte Pos setzen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
+ pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
+ delete pOldStk;
+
+ if( !pCurCrsr->IsInProtectTable( sal_True ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ UpdateCrsr(); // akt. Cursor Updaten
+ }
+ return sal_True;
+}
+
+/*
+ * Verbinde zwei Cursor miteinander.
+ * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
+ */
+
+
+void SwCrsrShell::Combine()
+{
+ // noch weitere vorhanden ?
+ if( 0 == pCrsrStk )
+ return;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
+ OSL_ENSURE( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
+#else
+ CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
+#endif
+ // kopiere das GetMark
+ if( !pCurCrsr->HasMark() )
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
+ pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
+ }
+
+ SwShellCrsr * pTmp = 0;
+ if( pCrsrStk->GetNext() != pCrsrStk )
+ {
+ pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
+ }
+ delete pCrsrStk;
+ pCrsrStk = pTmp;
+ if( !pCurCrsr->IsInProtectTable( sal_True ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ UpdateCrsr(); // akt. Cursor Updaten
+}
+
+
+void SwCrsrShell::HideCrsrs()
+{
+ if( !bHasFocus || bBasicHideCrsr )
+ return;
+
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( pVisCrsr->IsVisible() )
+ {
+ SET_CURR_SHELL( this );
+ pVisCrsr->Hide();
+ }
+ // hebe die Invertierung der SSelection auf
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ pAktCrsr->Hide();
+}
+
+
+
+void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
+{
+ if( !bHasFocus || bAllProtect || bBasicHideCrsr )
+ return;
+
+ SET_CURR_SHELL( this );
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ pAktCrsr->Show();
+
+ if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+}
+
+// Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
+
+
+void SwCrsrShell::ShowCrsr()
+{
+ if( !bBasicHideCrsr )
+ {
+ bSVCrsrVis = sal_True;
+ UpdateCrsr();
+ }
+}
+
+
+void SwCrsrShell::HideCrsr()
+{
+ if( !bBasicHideCrsr )
+ {
+ bSVCrsrVis = sal_False;
+ // evt. die sel. Bereiche aufheben !!
+ SET_CURR_SHELL( this );
+ pVisCrsr->Hide();
+ }
+}
+
+
+void SwCrsrShell::ShLooseFcs()
+{
+ if( !bBasicHideCrsr )
+ HideCrsrs();
+ bHasFocus = sal_False;
+}
+
+
+void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
+{
+ bHasFocus = sal_True;
+ if( !bBasicHideCrsr && VisArea().Width() )
+ {
+ UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
+ SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
+ : SwCrsrShell::CHKRANGE ) );
+ ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
+ }
+}
+
+// gebe den aktuellen Frame, in dem der Cursor steht, zurueck
+
+SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
+{
+ SET_CURR_SHELL( (ViewShell*)this );
+ SwCntntFrm *pRet = 0;
+ SwCntntNode *pNd = pCurCrsr->GetCntntNode();
+ if ( pNd )
+ {
+ if ( bCalcFrm )
+ {
+ const sal_uInt16* pST = &nStartAction;
+ ++(*((sal_uInt16*)pST));
+ const Size aOldSz( GetDocSize() );
+ pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
+ --(*((sal_uInt16*)pST));
+ if( aOldSz != GetDocSize() )
+ ((SwCrsrShell*)this)->SizeChgNotify();
+ }
+ else
+ pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
+ }
+ return pRet;
+}
+
+
+// alle Attribut/Format-Aenderungen am akt. Node werden an den
+// Link weitergeleitet.
+
+
+void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ const sal_uInt16 nWhich = pOld ?
+ pOld->Which() :
+ pNew ?
+ pNew->Which() :
+ sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
+
+ if( bCallChgLnk &&
+ ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
+ nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
+ nWhich == RES_ATTRSET_CHG ))
+ // die Messages werden nicht weitergemeldet
+ //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
+ //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
+ //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
+ CallChgLnk();
+
+ if( aGrfArrivedLnk.IsSet() &&
+ ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
+ aGrfArrivedLnk.Call( this );
+}
+
+
+// Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
+// also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
+
+
+sal_Bool SwCrsrShell::HasSelection() const
+{
+ const SwPaM* pCrsr = getShellCrsr( true );
+ return( IsTableMode() || ( pCrsr->HasMark() &&
+ *pCrsr->GetPoint() != *pCrsr->GetMark())
+ ? sal_True : sal_False );
+}
+
+
+void SwCrsrShell::CallChgLnk()
+{
+ // innerhalb von Start-/End-Action kein Call, sondern nur merken,
+ // das sich etwas geaendert hat. Wird bei EndAction beachtet.
+ if( BasicActionPend() )
+ bChgCallFlag = sal_True; // das Change merken
+ else if( aChgLnk.IsSet() )
+ {
+ if( bCallChgLnk )
+ aChgLnk.Call( this );
+ bChgCallFlag = sal_False; // Flag zuruecksetzen
+ }
+}
+
+// returne den am akt.Cursor selektierten Text eines Nodes.
+
+
+String SwCrsrShell::GetSelTxt() const
+{
+ String aTxt;
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() )
+ {
+ SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ {
+ xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
+ aTxt = pTxtNd->GetExpandTxt( nStt,
+ pCurCrsr->End()->nContent.GetIndex() - nStt );
+ }
+ }
+ return aTxt;
+}
+
+// gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
+
+
+String SwCrsrShell::GetText() const
+{
+ String aTxt;
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() )
+ {
+ SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ aTxt = pTxtNd->GetTxt().Copy(
+ pCurCrsr->GetPoint()->nContent.GetIndex() );
+ }
+ return aTxt;
+}
+
+// hole vom Start/Ende der akt. SSelection das nte Zeichen
+sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
+{
+ if( IsTableMode() ) // im TabelleMode nicht moeglich
+ return 0;
+
+ const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
+ : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return 0;
+
+ xub_StrLen nPos = pPos->nContent.GetIndex();
+ const String& rStr = pTxtNd->GetTxt();
+ sal_Unicode cCh = 0;
+
+ if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
+ cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
+
+ return cCh;
+}
+
+// erweiter die akt. SSelection am Anfang/Ende um n Zeichen
+
+
+sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
+{
+ if( !pCurCrsr->HasMark() || IsTableMode() )
+ return sal_False; // keine Selektion
+
+ SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
+
+ xub_StrLen nPos = pPos->nContent.GetIndex();
+ if( bEnd )
+ {
+ if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
+ nPos = nPos + nCount;
+ else
+ return sal_False; // nicht mehr moeglich
+ }
+ else if( nPos >= nCount )
+ nPos = nPos - nCount;
+ else
+ return sal_False; // nicht mehr moeglich
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+
+ pPos->nContent = nPos;
+ UpdateCrsr();
+
+ return sal_True;
+}
+
+// setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
+// returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
+
+sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
+{
+ SET_CURR_SHELL( this );
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.bRealHeight = sal_True;
+
+ sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
+
+ SetInFrontOfLabel( sal_False ); // #i27615#
+
+ // nur in TextNodes anzeigen !!
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return sal_False;
+
+ const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
+ if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag())) )
+ return sal_False;
+
+ SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
+ if ( Imp()->IsIdleAction() )
+ pFrm->PrepareCrsr();
+ SwRect aTmp( aCharRect );
+
+ pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
+
+ if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der
+ pVisCrsr->IsVisible() ) // Position nicht hidden & showen
+ return sal_True;
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ if( IsScrollMDI( this, aCharRect ))
+ {
+ MakeVisible( aCharRect );
+ pCurCrsr->Show();
+ }
+
+ {
+ if( aTmpState.bRealHeight )
+ aCrsrHeight = aTmpState.aRealHeight;
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aCharRect.Height();
+ }
+
+ pVisCrsr->SetDragCrsr( sal_True );
+ pVisCrsr->Show(); // wieder anzeigen
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
+{
+ Point aPt( rPt );
+ SwPaM aPam( *pCurCrsr->GetPoint() );
+ GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
+ // Formular view
+ return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
+}
+
+
+ // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
+ // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
+sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
+{
+ Ring* pTmp = GetCrsr()->GetNext();
+ sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
+ *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
+ while( pTmp != pCurCrsr )
+ {
+ if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
+ *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
+ ++n;
+ pTmp = pTmp->GetNext();
+ }
+ return n;
+}
+
+
+sal_Bool SwCrsrShell::IsStartOfDoc() const
+{
+ if( pCurCrsr->GetPoint()->nContent.GetIndex() )
+ return sal_False;
+
+ // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
+ SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
+ if( !aIdx.GetNode().IsCntntNode() )
+ GetDoc()->GetNodes().GoNext( &aIdx );
+ return aIdx == pCurCrsr->GetPoint()->nNode;
+}
+
+
+sal_Bool SwCrsrShell::IsEndOfDoc() const
+{
+ SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
+
+ return aIdx == pCurCrsr->GetPoint()->nNode &&
+ pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
+}
+
+
+// loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
+// Cursor auf seinen TextNode (oder StartNode?).
+// Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
+// Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
+sal_Bool SwCrsrShell::ParkTblCrsr()
+{
+ if( !pTblCrsr )
+ return sal_False;
+
+ pTblCrsr->ParkCrsr();
+
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+
+ // vom Cursor !immer! SPoint und Mark umsetzen
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->DeleteMark();
+
+ return sal_True;
+}
+
+/***********************************************************************
+#* Class : SwCrsrShell
+#* Methode : ParkCrsr
+#* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der
+#* verbleibende Crsr der Shell wird geparkt.
+#***********************************************************************/
+
+void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
+{
+ const SwPosition *pStt = pDelRg->Start(),
+ *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
+
+ SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
+
+ // durchsuche den gesamten Ring
+ sal_Bool bGoNext;
+ do {
+ const SwPosition *pTmpStt = pTmp->Start(),
+ *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
+ pTmp->GetMark() : pTmp->GetPoint();
+ /*
+ * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
+ * muss der alte Bereich aufgehoben werden.
+ * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
+ * Bereich gehoert !
+ */
+ if( *pStt <= *pTmpStt )
+ {
+ if( *pEnd > *pTmpStt ||
+ ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
+ pTmpDel = pTmp;
+ }
+ else
+ if( *pStt < *pTmpEnd )
+ pTmpDel = pTmp;
+
+ bGoNext = sal_True;
+ if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn
+ {
+ sal_Bool bDelete = sal_True;
+ if( *ppDelRing == pTmpDel )
+ {
+ if( *ppDelRing == pCurCrsr )
+ {
+ if( sal_True == ( bDelete = GoNextCrsr() ))
+ {
+ bGoNext = sal_False;
+ pTmp = (SwPaM*)pTmp->GetNext();
+ }
+ }
+ else
+ bDelete = sal_False; // StackCrsr nie loeschen !!
+ }
+
+ if( bDelete )
+ delete pTmpDel; // hebe alten Bereich auf
+ else
+ {
+ pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
+ pTmpDel->GetPoint()->nNode = 0;
+ pTmpDel->SetMark();
+ pTmpDel->DeleteMark();
+ }
+ pTmpDel = 0;
+ }
+ else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das
+ { // nicht benutzte Indizies beachtet werden!
+ pTmp->SetMark(); // SPoint liegt nicht im Bereich,
+ pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen
+ }
+ if( bGoNext )
+ pTmp = (SwPaM*)pTmp->GetNext();
+ } while( !bGoNext || *ppDelRing != pTmp );
+}
+
+void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
+{
+ SwNode *pNode = &rIdx.GetNode();
+
+ // erzeuge einen neuen Pam
+ SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
+ if( pNode->GetStartNode() )
+ {
+ if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
+ {
+ // der angegebene Node steht in einer Tabelle, also Parke
+ // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
+ pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ }
+ else // also auf dem StartNode selbst.
+ // Dann immer ueber seinen EndNode den StartNode erfragen !!!
+ // (StartOfSection vom StartNode ist der Parent !)
+ pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
+ }
+ else
+ pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ pNew->SetMark();
+ pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
+
+ //Alle Shells wollen etwas davon haben.
+ ViewShell *pTmp = this;
+ do {
+ if( pTmp->IsA( TYPE( SwCrsrShell )))
+ {
+ SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
+ if( pSh->pCrsrStk )
+ pSh->_ParkPams( pNew, &pSh->pCrsrStk );
+
+ pSh->_ParkPams( pNew, &pSh->pCurCrsr );
+ if( pSh->pTblCrsr )
+ {
+ // setze den Tabellen Cursor immer auf 0, den aktuellen
+ // immer auf den Anfang der Tabelle
+ SwPaM* pTCrsr = pSh->GetTblCrs();
+ SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
+ if ( pTblNd )
+ {
+ pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
+ pTCrsr->GetPoint()->nNode = 0;
+ pTCrsr->SetMark();
+ pTCrsr->DeleteMark();
+ pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
+ }
+ }
+ }
+ } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
+ delete pNew;
+}
+
+//=========================================================================
+
+/*
+ * der Copy-Constructor
+ * Cursor-Position kopieren, in den Ring eingetragen.
+ * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
+ */
+
+SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
+ : ViewShell( rShell, pInitWin ),
+ SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
+ pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
+ eMvState( MV_NONE ),
+ sMarkedListId(),
+ nMarkedListLevel( 0 )
+{
+ SET_CURR_SHELL( this );
+ // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
+ pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
+ pCurCrsr->GetCntntNode()->Add( this );
+
+ bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
+ bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
+ bOverwriteCrsr = sal_False;
+ bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
+ bSetCrsrInReadOnly = sal_True;
+ pVisCrsr = new SwVisCrsr( this );
+ mbMacroExecAllowed = rShell.IsMacroExecAllowed();
+}
+
+
+/*
+ * der normale Constructor
+ */
+
+SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
+ const SwViewOption *pInitOpt )
+ : ViewShell( rDoc, pInitWin, pInitOpt ),
+ SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
+ pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
+ eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
+ sMarkedListId(),
+ nMarkedListLevel( 0 )
+{
+ SET_CURR_SHELL( this );
+ /*
+ * Erzeugen des initialen Cursors, wird auf die erste
+ * Inhaltsposition gesetzt
+ */
+ SwNodes& rNds = rDoc.GetNodes();
+
+ SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
+ SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
+
+ pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
+
+ // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
+ // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
+ pCNd->Add( this );
+
+ bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
+ bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
+ bOverwriteCrsr = sal_False;
+ bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
+ bSetCrsrInReadOnly = sal_True;
+
+ pVisCrsr = new SwVisCrsr( this );
+ mbMacroExecAllowed = true;
+}
+
+
+
+SwCrsrShell::~SwCrsrShell()
+{
+ // wenn es nicht die letzte View so sollte zu mindest das
+ // Feld noch geupdatet werden.
+ if( GetNext() != this )
+ CheckTblBoxCntnt( pCurCrsr->GetPoint() );
+ else
+ ClearTblBoxCntnt();
+
+ delete pVisCrsr;
+ delete pBlockCrsr;
+ delete pTblCrsr;
+
+ /*
+ * Freigabe der Cursor
+ */
+ while(pCurCrsr->GetNext() != pCurCrsr)
+ delete pCurCrsr->GetNext();
+ delete pCurCrsr;
+
+ // Stack freigeben
+ if( pCrsrStk )
+ {
+ while( pCrsrStk->GetNext() != pCrsrStk )
+ delete pCrsrStk->GetNext();
+ delete pCrsrStk;
+ }
+
+ // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
+ // der CursorShell haengt keine Chance geben, sich an den
+ // TextNode zu haengen.
+ if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+}
+
+SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
+{
+ if( pTblCrsr )
+ return pTblCrsr;
+ if( pBlockCrsr && bBlock )
+ return &pBlockCrsr->getShellCrsr();
+ return pCurCrsr;
+}
+
+//Sollte fuer das Clipboard der WaitPtr geschaltet werden?
+//Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
+
+sal_Bool SwCrsrShell::ShouldWait() const
+{
+ if ( IsTableMode() || GetCrsrCnt() > 1 )
+ return sal_True;
+
+ if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ return sal_True;
+
+ SwPaM* pPam = GetCrsr();
+ return pPam->Start()->nNode.GetIndex() + 10 <
+ pPam->End()->nNode.GetIndex();
+}
+
+
+sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
+{
+ if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
+ GetLayout()->MakeTblCrsrs( *pTblCrsr );
+ return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
+}
+
+// zeige das akt. selektierte "Object" an
+void SwCrsrShell::MakeSelVisible()
+{
+ OSL_ENSURE( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
+ if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
+ {
+ SwRect aTmp( aCharRect );
+ long nDiff = aCharRect.Height() - VisArea().Height();
+ if( nDiff < aCrsrHeight.X() )
+ aTmp.Top( nDiff + aCharRect.Top() );
+ else
+ {
+ aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
+ aTmp.Height( aCrsrHeight.Y() );
+ }
+ if( !aTmp.HasArea() )
+ {
+ aTmp.SSize().Height() += 1;
+ aTmp.SSize().Width() += 1;
+ }
+ MakeVisible( aTmp );
+ }
+ else
+ {
+ if( aCharRect.HasArea() )
+ MakeVisible( aCharRect );
+ else
+ {
+ SwRect aTmp( aCharRect );
+ aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
+ MakeVisible( aTmp );
+ }
+ }
+}
+
+
+// suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
+sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
+{
+ if( pTblCrsr ) // was soll ich jetzt machen ??
+ {
+ OSL_ENSURE( !this, "TabellenSelection nicht aufgehoben!" );
+ return sal_False;
+ }
+
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ if( !bAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ return sal_True;
+
+ // dann raus da!
+ if( pCurCrsr->HasMark() )
+ ClearMark();
+
+ // als erstes mal auf Rahmen abpruefen
+ SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
+ sal_uLong nNdIdx = rNdIdx.GetIndex(); // sichern
+ SwNodes& rNds = pDoc->GetNodes();
+ SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
+ const SwCntntFrm * pFrm;
+
+ if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
+ !IsReadOnlyAvailable() && pFrm->IsProtected() &&
+ nNdIdx < rNds.GetEndOfExtras().GetIndex() )
+ {
+ // geschuetzter Rahmen ueberspringen
+ SwPaM aPam( *pCurCrsr->GetPoint() );
+ aPam.SetMark();
+ aPam.GetMark()->nNode = rNds.GetEndOfContent();
+ aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
+
+ sal_Bool bFirst = sal_False;
+ if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
+ {
+ aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
+ pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
+ }
+
+ if( !pCNd ) // sollte nie passieren !!!
+ {
+ rNdIdx = nNdIdx; // alten Node zurueck
+ return sal_False;
+ }
+ *pCurCrsr->GetPoint() = *aPam.GetPoint();
+ }
+ else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
+ {
+ // dann auf den Anfang vom Doc stellen
+ rNdIdx = pDoc->GetNodes().GetEndOfExtras();
+ pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
+ &rNdIdx ), 0 );
+ nNdIdx = rNdIdx.GetIndex();
+ }
+
+ sal_Bool bOk = sal_True;
+
+ // #i9059# cursor may not stand in protected cells
+ // (unless cursor in protected areas is OK.)
+ const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
+ if( !IsReadOnlyAvailable() &&
+ pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
+ {
+ // we're in a table, and we're in a protected area, so we're
+ // probably in a protected cell.
+
+ // move forward into non-protected area.
+ SwPaM aPam( rNdIdx.GetNode(), 0 );
+ while( aPam.GetNode()->IsProtect() &&
+ aPam.Move( fnMoveForward, fnGoCntnt ) )
+ ; // nothing to do in the loop; the aPam.Move does the moving!
+
+ // didn't work? then go backwards!
+ if( aPam.GetNode()->IsProtect() )
+ {
+ SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
+ aPam = aTmpPaM;
+ while( aPam.GetNode()->IsProtect() &&
+ aPam.Move( fnMoveBackward, fnGoCntnt ) )
+ ; // nothing to do in the loop; the aPam.Move does the moving!
+ }
+
+ // if we're successful, set the new position
+ if( ! aPam.GetNode()->IsProtect() )
+ {
+ *pCurCrsr->GetPoint() = *aPam.GetPoint();
+ }
+ }
+
+ // in einem geschuetzten Bereich
+ const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
+ if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() )) )
+ {
+ typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
+ FNGoSection funcGoSection = &SwNodes::GoNextSection;
+
+ bOk = sal_False;
+
+ for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
+ {
+ sal_Bool bWeiter;
+ do {
+ bWeiter = sal_False;
+ while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
+ sal_True, !IsReadOnlyAvailable() )) )
+ {
+ // in eine Tabelle verschoben -> pruefe ob die
+ // vielleicht geschuetzt ist
+ if( pCNd->FindTableNode() )
+ {
+ SwCallLink aTmp( *this );
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ aTmp.nNdTyp = 0; // im DTOR nichts machen!
+ if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
+ {
+ const SwSectionNode* pSNd = pCNd->FindSectionNode();
+ if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
+ || (!IsReadOnlyAvailable() &&
+ pSNd->GetSection().IsProtectFlag() ))
+ {
+ bOk = sal_True;
+ break; // eine nicht geschuetzte Zelle gef.
+ }
+ continue; // dann weiter suchen
+ }
+ }
+ else
+ {
+ bOk = sal_True;
+ break; // eine nicht geschuetzte Zelle gef.
+ }
+ }
+
+ if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
+ {
+ // Teste mal auf Fly - kann auch noch geschuetzt sein!!
+ if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
+ ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
+ ( bOnlyText && pCNd->IsNoTxtNode() ) )
+ {
+ // dann weiter suchen!
+ bOk = sal_False;
+ bWeiter = sal_True;
+ }
+ }
+ } while( bWeiter );
+
+ if( !bOk )
+ {
+ if( !nLoopCnt )
+ funcGoSection = &SwNodes::GoPrevSection;
+ rNdIdx = nNdIdx;
+ }
+ }
+ }
+ if( bOk )
+ {
+ pCNd = rNdIdx.GetNode().GetCntntNode();
+ xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
+ }
+ else
+ {
+ pCNd = rNdIdx.GetNode().GetCntntNode();
+
+ // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
+ // verschieben!!
+ if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
+ &aTmpState );
+ }
+ }
+ return bOk;
+}
+
+
+void SwCrsrShell::NewCoreSelection()
+{
+}
+
+
+sal_Bool SwCrsrShell::IsCrsrReadonly() const
+{
+ if ( GetViewOptions()->IsReadonly() ||
+ // Formular view
+ GetViewOptions()->IsFormView() )
+ {
+ SwFrm *pFrm = GetCurrFrm( sal_False );
+ const SwFlyFrm* pFly;
+ const SwSection* pSection;
+
+ if( pFrm && pFrm->IsInFly() &&
+ (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
+ pFly->Lower() &&
+ !pFly->Lower()->IsNoTxtFrm() &&
+ !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ {
+ return sal_False;
+ }
+ // edit in readonly sections
+ else if ( pFrm && pFrm->IsInSct() &&
+ 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
+ pSection->IsEditInReadonlyFlag() )
+ {
+ return sal_False;
+ }
+
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+// darf der Cursor in ReadOnlyBereiche?
+void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
+{
+ // im GlobalDoc darf NIE umgeschaltet werden
+ if( (!GetDoc()->GetDocShell() ||
+ !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
+ bFlag != bSetCrsrInReadOnly )
+ {
+ // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
+ // Selektionen aufgehoben werden. Denn sonst wird sich darauf
+ // verlassen, das nichts geschuetztes selektiert ist!
+ if( !bFlag )
+ {
+ ClearMark();
+ }
+ bSetCrsrInReadOnly = bFlag;
+ UpdateCrsr();
+ }
+}
+
+sal_Bool SwCrsrShell::HasReadonlySel() const
+{
+ sal_Bool bRet = sal_False;
+ if( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
+ {
+ if( pTblCrsr )
+ bRet = pTblCrsr->HasReadOnlyBoxSel() ||
+ pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() );
+ else
+ {
+ const SwPaM* pCrsr = pCurCrsr;
+
+ do {
+ if( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ) )
+ bRet = sal_True;
+ } while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::IsSelFullPara() const
+{
+ sal_Bool bRet = sal_False;
+
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
+ {
+ xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
+ nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
+ if( nStt > nEnd )
+ {
+ xub_StrLen nTmp = nStt;
+ nStt = nEnd;
+ nEnd = nTmp;
+ }
+ const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
+ bRet = pCNd && !nStt && nEnd == pCNd->Len();
+ }
+ return bRet;
+}
+
+short SwCrsrShell::GetTextDirection( const Point* pPt ) const
+{
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
+ if( pPt )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
+ }
+
+ return pDoc->GetTextDirection( aPos, &aPt );
+}
+
+sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( pPt );
+ return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
+}
+
+sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( pPt );
+ // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
+ // vertical environment
+ return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
+}
+
+//
+// If the current cursor position is inside a hidden range, the hidden range
+// is selected:
+//
+bool SwCrsrShell::SelectHiddenRange()
+{
+ bool bRet = false;
+ if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
+ {
+ SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
+ const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
+ if ( pNode )
+ {
+ const xub_StrLen nPos = rPt.nContent.GetIndex();
+
+ // check if nPos is in hidden range
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
+ if ( STRING_LEN != nHiddenStart )
+ {
+ // make selection:
+ pCurCrsr->SetMark();
+ pCurCrsr->GetMark()->nContent = nHiddenEnd;
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+ // die Suchfunktionen
+sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ sal_Bool& bCancel,
+ FindRanges eRng, int bReplace )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
+ if( nRet || bCancel )
+ UpdateCrsr();
+ return nRet;
+}
+
+sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ sal_Bool& bCancel,
+ FindRanges eRng, const SwTxtFmtColl* pReplFmt )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
+ if( nRet )
+ UpdateCrsr();
+ return nRet;
+}
+
+sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ sal_Bool& bCancel,
+ FindRanges eRng, const SearchOptions* pSearchOpt,
+ const SfxItemSet* rReplSet )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
+ eRng, pSearchOpt, rReplSet );
+ if( nRet )
+ UpdateCrsr();
+ return nRet;
+}
+
+void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
+{
+ StartAction();
+ SwPaM* pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = *rCrsr.GetPoint();
+ if(rCrsr.HasMark())
+ {
+ pCrsr->SetMark();
+ *pCrsr->GetMark() = *rCrsr.GetMark();
+ }
+ if((SwPaM*)rCrsr.GetNext() != &rCrsr)
+ {
+ const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
+ do
+ {
+ SwPaM* pCurrentCrsr = CreateCrsr();
+ *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
+ if(_pStartCrsr->HasMark())
+ {
+ pCurrentCrsr->SetMark();
+ *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
+ }
+ } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
+ }
+ EndAction();
+}
+
+void lcl_RemoveMark( SwPaM* pPam )
+{
+ OSL_ENSURE( pPam->HasMark(), "Don't remove pPoint!" );
+ pPam->GetMark()->nContent.Assign( 0, 0 );
+ pPam->GetMark()->nNode = 0;
+ pPam->DeleteMark();
+}
+
+const SwStartNode* lcl_NodeContext( const SwNode& rNode )
+{
+ const SwStartNode *pRet = rNode.StartOfSectionNode();
+ while( pRet->IsSectionNode() || pRet->IsTableNode() ||
+ pRet->GetStartNodeType() == SwTableBoxStartNode )
+ {
+ pRet = pRet->StartOfSectionNode();
+ }
+ return pRet;
+}
+
+/**
+ Checks if a position is valid. To be valid the position's node must
+ be a content node and the content must not be unregistered.
+
+ @param aPos the position to check.
+*/
+bool lcl_PosOk(const SwPosition & aPos)
+{
+ return NULL != aPos.nNode.GetNode().GetCntntNode() &&
+ SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
+}
+
+/**
+ Checks if a PaM is valid. For a PaM to be valid its point must be
+ valid. Additionaly if the PaM has a mark this has to be valid, too.
+
+ @param aPam the PaM to check
+*/
+static bool lcl_CrsrOk(SwPaM & aPam)
+{
+ return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
+ || lcl_PosOk(*aPam.GetMark()));
+}
+
+void SwCrsrShell::ClearUpCrsrs()
+{
+ // start of the ring
+ SwPaM * pStartCrsr = GetCrsr();
+ // start loop with second entry of the ring
+ SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
+ SwPaM * pTmpCrsr;
+ bool bChanged = false;
+
+ /*
+ For all entries in the ring except the start entry delete the
+ entry if it is invalid.
+ */
+ while (pCrsr != pStartCrsr)
+ {
+ pTmpCrsr = (SwPaM *) pCrsr->GetNext();
+
+ if ( ! lcl_CrsrOk(*pCrsr))
+ {
+ delete pCrsr;
+
+ bChanged = true;
+ }
+
+ pCrsr = pTmpCrsr;
+ }
+
+ if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
+ {
+ lcl_RemoveMark( pStartCrsr );
+ bChanged = true;
+ }
+ if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
+ {
+ SwNodes & aNodes = GetDoc()->GetNodes();
+ const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
+ SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
+ SwNode * pNode = aNodes.GoPrevious(&aIdx);
+ if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
+ aNodes.GoNext( &aIdx );
+ if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
+ {
+ /*
+ If the start entry of the ring is invalid replace it with a
+ cursor pointing to the beginning of the first content node in
+ the document.
+ */
+ aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
+ pNode = aNodes.GoNext( &aIdx );
+ }
+ bool bFound = (pNode != NULL);
+
+ OSL_ENSURE(bFound, "no content node found");
+
+ if (bFound)
+ {
+ SwPaM aTmpPam(*pNode);
+ *pStartCrsr = aTmpPam;
+ }
+
+ bChanged = true;
+ }
+
+ /*
+ If at least one of the cursors in the ring have been deleted or
+ replaced, remove the table cursor.
+ */
+ if (pTblCrsr != NULL && bChanged)
+ TblCrsrToCursor();
+}
+
+String SwCrsrShell::GetCrsrDescr() const
+{
+ String aResult;
+
+ if (IsMultiSelection())
+ aResult += String(SW_RES(STR_MULTISEL));
+ else
+ aResult = GetDoc()->GetPaMDescr(*GetCrsr());
+
+ return aResult;
+}
+
+// SMARTTAGS
+
+void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
+{
+ // Insert smart tag information
+ std::vector< rtl::OUString > aSmartTagTypes;
+ std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
+
+ for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
+ {
+ const xub_StrLen nSTPos = rSmartTagList.Pos( i );
+ const xub_StrLen nSTLen = rSmartTagList.Len( i );
+
+ if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
+ {
+ const SwWrongArea* pArea = rSmartTagList.GetElement( i );
+ if ( pArea )
+ {
+ aSmartTagTypes.push_back( pArea->maType );
+ aStringKeyMaps.push_back( pArea->mxPropertyBag );
+ }
+ }
+ }
+
+ if ( aSmartTagTypes.size() )
+ {
+ rSmartTagTypes.realloc( aSmartTagTypes.size() );
+ rStringKeyMaps.realloc( aSmartTagTypes.size() );
+
+ std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
+ sal_uInt16 i = 0;
+ for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
+ rSmartTagTypes[i++] = *aTypesIter;
+
+ std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
+ i = 0;
+ for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
+ rStringKeyMaps[i++] = *aMapsIter;
+ }
+}
+
+void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
+ SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
+{
+ // create SwPosition for nStartIndex
+ SwIndex aIndex( &rNode, nBegin );
+ SwPosition aStartPos( rNode, aIndex );
+
+ // create SwPosition for nEndIndex
+ SwPosition aEndPos( aStartPos );
+ aEndPos.nContent = nBegin + nLen;
+
+ const uno::Reference<text::XTextRange> xRange =
+ SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
+
+ rRange = xRange;
+}
+
+void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ uno::Reference< text::XTextRange>& rRange ) const
+{
+ if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
+ if ( pNode && !pNode->IsInProtectSect() )
+ {
+ const SwWrongList *pSmartTagList = pNode->GetSmartTags();
+ if ( pSmartTagList )
+ {
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
+ {
+ const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ pSmartTagList = pSubList;
+ nCurrent = 0;
+ }
+
+ lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
+ lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
+ }
+ }
+ }
+}
+
+// see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
+void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
+ uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ uno::Reference<text::XTextRange>& rRange )
+{
+ if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( rPt );
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ SwSpecialPos aSpecialPos;
+ eTmpState.pSpecialPos = &aSpecialPos;
+ SwTxtNode *pNode;
+ const SwWrongList *pSmartTagList;
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
+ 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
+ 0 != (pSmartTagList = pNode->GetSmartTags()) &&
+ !pNode->IsInProtectSect() )
+ {
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
+ {
+ const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ pSmartTagList = pSubList;
+ nCurrent = eTmpState.pSpecialPos->nCharOfst;
+ }
+
+ lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
+ lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
+
+ // get smarttag word
+ String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
+
+ //save the start and end positons of the line and the starting point
+ Push();
+ LeftMargin();
+ xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
+ RightMargin();
+ xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
+ Pop(sal_False);
+
+ // make sure the selection build later from the
+ // data below does not include footnotes and other
+ // "in word" character to the left and right in order
+ // to preserve those. Therefore count those "in words"
+ // in order to modify the selection accordingly.
+ const sal_Unicode* pChar = aText.GetBuffer();
+ xub_StrLen nLeft = 0;
+ while (pChar && *pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
+ xub_StrLen nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ aPos.nContent = nBegin + nLeft;
+ pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = aPos;
+ pCrsr->SetMark();
+ ExtendSelection( sal_True, nLen - nLeft - nRight );
+ //no determine the rectangle in the current line
+ xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
+ //take one less than the line end - otherwise the next line would be calculated
+ xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd : (nBegin + nLen - nLeft - nRight);
+ Push();
+ pCrsr->DeleteMark();
+ SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
+ rContent = nWordStart;
+ SwRect aStartRect;
+ SwCrsrMoveState aState;
+ aState.bRealWidth = sal_True;
+ SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
+ SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
+
+ pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
+ rContent = nWordEnd - 1;
+ SwRect aEndRect;
+ pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
+ rSelectRect = aStartRect.Union( aEndRect );
+ Pop(sal_False);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */