diff options
Diffstat (limited to 'sw/source/ui/wrtsh/move.cxx')
-rw-r--r-- | sw/source/ui/wrtsh/move.cxx | 691 |
1 files changed, 691 insertions, 0 deletions
diff --git a/sw/source/ui/wrtsh/move.cxx b/sw/source/ui/wrtsh/move.cxx new file mode 100644 index 000000000000..34a9b5554c36 --- /dev/null +++ b/sw/source/ui/wrtsh/move.cxx @@ -0,0 +1,691 @@ +/************************************************************************* + * + * 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 <sfx2/bindings.hxx> +#include <wrtsh.hxx> +#ifndef _VIEW_HXX +#include <view.hxx> +#endif +#include <viewopt.hxx> +#include <crsskip.hxx> + +/* Immer: + - Zuruecksetzen des Cursorstacks + - Timer nachtriggern + - gfs. GCAttr + + bei Selektion + - SttSelect() + + sonst + - EndSelect() + */ + +const long nReadOnlyScrollOfst = 10; + +class ShellMoveCrsr +{ + SwWrtShell* pSh; + sal_Bool bAct; +public: + inline ShellMoveCrsr( SwWrtShell* pWrtSh, sal_Bool bSel ) + { + bAct = !pWrtSh->ActionPend() && (pWrtSh->GetFrmType(0,sal_False) & FRMTYPE_FLY_ANY); + ( pSh = pWrtSh )->MoveCrsr( sal_Bool(bSel) ); + pWrtSh->GetView().GetViewFrame()->GetBindings().Invalidate(SID_HYPERLINK_GETLINK); + } + inline ~ShellMoveCrsr() + { + if( bAct ) + { + //Die Action wird fuer das Scrollen in "einabsaetzigen" Rahmen mit + //fester Hoehe gebraucht. + pSh->StartAllAction(); + pSh->EndAllAction(); + } + } +}; + +void SwWrtShell::MoveCrsr( sal_Bool bWithSelect ) +{ + ResetCursorStack(); + if ( IsGCAttr() ) + { + GCAttr(); + ClearGCAttr(); + } + if ( bWithSelect ) + SttSelect(); + else + { + EndSelect(); + (this->*fnKillSel)( 0, sal_False ); + } +} + +sal_Bool SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove, sal_Bool bSelect ) +{ + sal_Bool nRet; + if( bSelect ) + { + SttCrsrMove(); + MoveCrsr( sal_True ); + nRet = (this->*FnSimpleMove)(); + EndCrsrMove(); + } + else if( 0 != ( nRet = (this->*FnSimpleMove)() ) ) + MoveCrsr( sal_False ); + return nRet; +} + + +sal_Bool SwWrtShell::Left( sal_uInt16 nMode, sal_Bool bSelect, + sal_uInt16 nCount, sal_Bool bBasicCall, sal_Bool bVisual ) +{ + if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly()) + { + Point aTmp( VisArea().Pos() ); + aTmp.X() -= VisArea().Width() * nReadOnlyScrollOfst / 100; + rView.SetVisArea( aTmp ); + return sal_True; + } + else + { + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::Left( nCount, nMode, bVisual ); + } +} + + + +sal_Bool SwWrtShell::Right( sal_uInt16 nMode, sal_Bool bSelect, + sal_uInt16 nCount, sal_Bool bBasicCall, sal_Bool bVisual ) +{ + if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly() ) + { + Point aTmp( VisArea().Pos() ); + aTmp.X() += VisArea().Width() * nReadOnlyScrollOfst / 100; + aTmp.X() = rView.SetHScrollMax( aTmp.X() ); + rView.SetVisArea( aTmp ); + return sal_True; + } + else + { + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::Right( nCount, nMode, bVisual ); + } +} + + + +sal_Bool SwWrtShell::Up( sal_Bool bSelect, sal_uInt16 nCount, sal_Bool bBasicCall ) +{ + if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly()) + { + Point aTmp( VisArea().Pos() ); + aTmp.Y() -= VisArea().Height() * nReadOnlyScrollOfst / 100; + rView.SetVisArea( aTmp ); + return sal_True; + } + else + { + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::Up( nCount ); + } +} + + + +sal_Bool SwWrtShell::Down( sal_Bool bSelect, sal_uInt16 nCount, sal_Bool bBasicCall ) +{ + if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly()) + { + Point aTmp( VisArea().Pos() ); + aTmp.Y() += VisArea().Height() * nReadOnlyScrollOfst / 100; + aTmp.Y() = rView.SetVScrollMax( aTmp.Y() ); + rView.SetVisArea( aTmp ); + return sal_True; + } + else + { + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::Down( nCount ); + } +} + + + +sal_Bool SwWrtShell::LeftMargin( sal_Bool bSelect, sal_Bool bBasicCall ) +{ + if ( !bSelect && !bBasicCall && IsCrsrReadonly() ) + { + Point aTmp( VisArea().Pos() ); + aTmp.X() = DOCUMENTBORDER; + rView.SetVisArea( aTmp ); + return sal_True; + } + else + { + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::LeftMargin(); + } +} + + + +sal_Bool SwWrtShell::RightMargin( sal_Bool bSelect, sal_Bool bBasicCall ) +{ + if ( !bSelect && !bBasicCall && IsCrsrReadonly() ) + { + Point aTmp( VisArea().Pos() ); + aTmp.X() = GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER; + if( DOCUMENTBORDER > aTmp.X() ) + aTmp.X() = DOCUMENTBORDER; + rView.SetVisArea( aTmp ); + return sal_True; + } + else + { + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::RightMargin(bBasicCall); + } +} + + + +sal_Bool SwWrtShell::GoStart( sal_Bool bKeepArea, sal_Bool *pMoveTable, + sal_Bool bSelect, sal_Bool bDontMoveRegion ) +{ + if ( IsCrsrInTbl() ) + { + const sal_Bool bBoxSelection = HasBoxSelection(); + if( !bBlockMode ) + { + if ( !bSelect ) + EnterStdMode(); + else + SttSelect(); + } + // Tabellenzelle? + if ( !bBoxSelection && (MoveSection( fnSectionCurr, fnSectionStart) + || bDontMoveRegion)) + { + if ( pMoveTable ) + *pMoveTable = sal_False; + return sal_True; + } + if( MoveTable( fnTableCurr, fnTableStart ) || bDontMoveRegion ) + { + if ( pMoveTable ) + *pMoveTable = sal_True; + return sal_True; + } + else if( bBoxSelection && pMoveTable ) + { + // JP 09.01.96: wir haben eine Boxselektion (oder leere Zelle) + // und wollen selektieren (pMoveTable wird im + // SelAll gesetzt). Dann darf die Tabelle nicht + // verlassen werden; sonst ist keine Selektion der + // gesamten Tabelle moeglich! + *pMoveTable = sal_True; + return sal_True; + } + } + + if( !bBlockMode ) + { + if ( !bSelect ) + EnterStdMode(); + else + SttSelect(); + } + const sal_uInt16 nFrmType = GetFrmType(0,sal_False); + if ( FRMTYPE_FLY_ANY & nFrmType ) + { + if( MoveSection( fnSectionCurr, fnSectionStart ) ) + return sal_True; + else if ( FRMTYPE_FLY_FREE & nFrmType || bDontMoveRegion ) + return sal_False; + } + if(( FRMTYPE_HEADER | FRMTYPE_FOOTER | FRMTYPE_FOOTNOTE ) & nFrmType ) + { + if ( MoveSection( fnSectionCurr, fnSectionStart ) ) + return sal_True; + else if ( bKeepArea ) + return sal_True; + } + // Bereiche ??? + return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip, fnRegionStart ) || + SwCrsrShell::SttEndDoc(sal_True); +} + + + +sal_Bool SwWrtShell::GoEnd(sal_Bool bKeepArea, sal_Bool *pMoveTable) +{ + if ( pMoveTable && *pMoveTable ) + return MoveTable( fnTableCurr, fnTableEnd ); + + if ( IsCrsrInTbl() ) + { + if ( MoveSection( fnSectionCurr, fnSectionEnd ) || + MoveTable( fnTableCurr, fnTableEnd ) ) + return sal_True; + } + else + { + const sal_uInt16 nFrmType = GetFrmType(0,sal_False); + if ( FRMTYPE_FLY_ANY & nFrmType ) + { + if ( MoveSection( fnSectionCurr, fnSectionEnd ) ) + return sal_True; + else if ( FRMTYPE_FLY_FREE & nFrmType ) + return sal_False; + } + if(( FRMTYPE_HEADER | FRMTYPE_FOOTER | FRMTYPE_FOOTNOTE ) & nFrmType ) + { + if ( MoveSection( fnSectionCurr, fnSectionEnd) ) + return sal_True; + else if ( bKeepArea ) + return sal_True; + } + } + // Bereiche ??? + return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip, fnRegionEnd ) || + SwCrsrShell::SttEndDoc(sal_False); +} + + + +sal_Bool SwWrtShell::SttDoc( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return GoStart(sal_False, 0, bSelect ); +} + + + +sal_Bool SwWrtShell::EndDoc( sal_Bool bSelect) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return GoEnd(); +} + + +sal_Bool SwWrtShell::SttNxtPg( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePage( fnPageNext, fnPageStart ); +} + + + +sal_Bool SwWrtShell::SttPrvPg( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePage( fnPagePrev, fnPageStart ); +} + + + +sal_Bool SwWrtShell::EndNxtPg( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePage( fnPageNext, fnPageEnd ); +} + + + +sal_Bool SwWrtShell::EndPrvPg( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePage( fnPagePrev, fnPageEnd ); +} + + + +sal_Bool SwWrtShell::SttPg( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePage( fnPageCurr, fnPageStart ); +} + + + +sal_Bool SwWrtShell::EndPg( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePage( fnPageCurr, fnPageEnd ); +} + + + +sal_Bool SwWrtShell::SttPara( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePara( fnParaCurr, fnParaStart ); +} + + + +sal_Bool SwWrtShell::EndPara( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return MovePara(fnParaCurr,fnParaEnd); +} + + +/*------------------------------------------------------------------------ + Beschreibung: Spaltenweises Springen + Parameter: mit oder ohne SSelection + Return: Erfolg oder Misserfolg +------------------------------------------------------------------------*/ + + + +sal_Bool SwWrtShell::StartOfColumn( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect); + return MoveColumn(fnColumnCurr, fnColumnStart); +} + + + +sal_Bool SwWrtShell::EndOfColumn( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect); + return MoveColumn(fnColumnCurr, fnColumnEnd); +} + + + +sal_Bool SwWrtShell::StartOfNextColumn( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect); + return MoveColumn( fnColumnNext, fnColumnStart); +} + + + +sal_Bool SwWrtShell::EndOfNextColumn( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect); + return MoveColumn(fnColumnNext, fnColumnEnd); +} + + + +sal_Bool SwWrtShell::StartOfPrevColumn( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect); + return MoveColumn(fnColumnPrev, fnColumnStart); +} + + + +sal_Bool SwWrtShell::EndOfPrevColumn( sal_Bool bSelect ) +{ + ShellMoveCrsr aTmp( this, bSelect); + return MoveColumn(fnColumnPrev, fnColumnEnd); +} + + + +sal_Bool SwWrtShell::PushCrsr(SwTwips lOffset, sal_Bool bSelect) +{ + sal_Bool bDiff = sal_False; + SwRect aOldRect( GetCharRect() ), aTmpArea( VisArea() ); + + //bDestOnStack besagt, ob ich den Cursor nicht an die aktuelle Position + //setzen konnte, da in diesem Bereich kein Inhalt vorhanden ist. + if( !bDestOnStack ) + { + Point aPt( aOldRect.Center() ); + + if( !IsCrsrVisible() ) + // set CrsrPos to top-/bottom left pos. So the pagescroll is not + // be dependent on the current cursor, but on the visarea. + aPt.Y() = aTmpArea.Top() + aTmpArea.Height() / 2; + + aPt.Y() += lOffset; + aDest = GetCntntPos(aPt,lOffset > 0); + aDest.X() = aPt.X(); + bDestOnStack = sal_True; + } + + //falls wir eine Rahmenselektion hatten, muss diese nach dem + //fnSetCrsr entfernt werden und damit wir da wieder hinkommen + //auf dem Stack gemerkt werden. + sal_Bool bIsFrmSel = sal_False; + + sal_Bool bIsObjSel = sal_False; + + //Zielposition liegt jetzt innerhalb des sichtbaren Bereiches --> + //Cursor an die Zielposition setzen; merken, dass keine Ziel- + //position mehr auf dem Stack steht. + //Der neue sichtbare Bereich wird zuvor ermittelt. + aTmpArea.Pos().Y() += lOffset; + if( aTmpArea.IsInside(aDest) ) + { + if( bSelect ) + SttSelect(); + else + EndSelect(); + + bIsFrmSel = IsFrmSelected(); + bIsObjSel = 0 != IsObjSelected(); + + // Rahmenselektion aufheben + if( bIsFrmSel || bIsObjSel ) + { + UnSelectFrm(); + LeaveSelFrmMode(); + if ( bIsObjSel ) + { + GetView().SetDrawFuncPtr( NULL ); + GetView().LeaveDrawCreate(); + } + + CallChgLnk(); + } + + (this->*fnSetCrsr)( &aDest, sal_True ); + + bDiff = aOldRect != GetCharRect(); + + if( bIsFrmSel ) + { +// CallChgLnk(); + // bei Frames immer nur die obere Ecke nehmen, damit dieser + // wieder selektiert werden kann + aOldRect.SSize( 5, 5 ); + } + + // Zuruecksetzen des Dest. SPoint Flags + bDestOnStack = sal_False; + } + + // Position auf den Stack; bDiff besagt, ob ein Unterschied zwischen + // der alten und der neuen Cursorposition besteht. + pCrsrStack = new CrsrStack( bDiff, bIsFrmSel, aOldRect.Center(), + lOffset, pCrsrStack ); + return !bDestOnStack && bDiff; +} + + + +sal_Bool SwWrtShell::PopCrsr(sal_Bool bUpdate, sal_Bool bSelect) +{ + if( 0 == pCrsrStack) + return sal_False; + + const sal_Bool bValidPos = pCrsrStack->bValidCurPos; + if( bUpdate && bValidPos ) + { + // falls ein Vorgaenger auf dem Stack steht, dessen Flag fuer eine + // gueltige Position verwenden. + SwRect aTmpArea(VisArea()); + aTmpArea.Pos().Y() -= pCrsrStack->lOffset; + if( aTmpArea.IsInside( pCrsrStack->aDocPos ) ) + { + if( bSelect ) + SttSelect(); + else + EndSelect(); + + (this->*fnSetCrsr)(&pCrsrStack->aDocPos, !pCrsrStack->bIsFrmSel); + if( pCrsrStack->bIsFrmSel && IsObjSelectable(pCrsrStack->aDocPos)) + { + HideCrsr(); + SelectObj( pCrsrStack->aDocPos ); + EnterSelFrmMode( &pCrsrStack->aDocPos ); + } + } + // Falls eine Verschiebung zwischen dem sichtbaren Bereich + // und der gemerkten Cursorpositionen auftritt, werden + // alle gemerkten Positionen weggeschmissen + else + { + _ResetCursorStack(); + return sal_False; + } + } + CrsrStack *pTmp = pCrsrStack; + pCrsrStack = pCrsrStack->pNext; + delete pTmp; + if( 0 == pCrsrStack ) + { + ePageMove = MV_NO; + bDestOnStack = sal_False; + } + return bValidPos; +} + +/* + * Zuruecksetzen aller gepushten Cursorpositionen; dieser werden nicht + * zur Anzeige gebracht ( --> Kein Start-/EndAction!!) + */ + + + +void SwWrtShell::_ResetCursorStack() +{ + CrsrStack *pTmp = pCrsrStack; + while(pCrsrStack) + { + pTmp = pCrsrStack->pNext; + delete pCrsrStack; + pCrsrStack = pTmp; + } + ePageMove = MV_NO; + bDestOnStack = sal_False; +} +/************** + + falls kein Stack existiert --> Selektionen aufheben + falls Stack && Richtungswechsel + --> Cursor poppen und return + sonst + --> Cursor pushen + Cursor umsetzen + +***************/ + + + +sal_Bool SwWrtShell::PageCrsr(SwTwips lOffset, sal_Bool bSelect) +{ + // nichts tun, wenn ein Offset von 0 angegeben wurde + if(!lOffset) return sal_False; + // Diente mal dazu, eine Neuformatierung fuer das Layout + // zu erzwingen. + // Hat so nicht funktioniert, da der Cursor nicht gesetzt + // wurde, da dies innerhalb einer Start- / EndActionklammerung + // nicht geschieht. + // Da am Ende nur ViewShell::EndAction() gerufen wird, + // findet auch hier keine Aktualisierung der Anzeige + // der Cursorposition statt. + // Die CrsrShell- Actionklammerung kann nicht verwendet werden, + // da sie immer zu einer Anzeige des Cursors fuehrt, also auch, + // wenn nach dem Blaettern in einen Bereich ohne gueltige Position + // geblaettert wurde. + // ViewShell::StartAction(); + PageMove eDir = lOffset > 0? MV_PAGE_DOWN: MV_PAGE_UP; + // Richtungswechsel und Stack vorhanden + if( eDir != ePageMove && ePageMove != MV_NO && PopCrsr( sal_True, bSelect )) + return sal_True; + + const sal_Bool bRet = PushCrsr(lOffset, bSelect); + ePageMove = eDir; + return bRet; +} + + + +sal_Bool SwWrtShell::GotoPage(sal_uInt16 nPage, sal_Bool bRecord) +{ + ShellMoveCrsr aTmp( this, sal_False); + if( SwCrsrShell::GotoPage(nPage) && bRecord) + { + if(IsSelFrmMode()) + { + UnSelectFrm(); + LeaveSelFrmMode(); + } + return sal_True; + } + return sal_False; +} + + + +sal_Bool SwWrtShell::GotoMark( const ::sw::mark::IMark* const pMark, sal_Bool bSelect, sal_Bool bStart ) +{ + ShellMoveCrsr aTmp( this, bSelect ); + return SwCrsrShell::GotoMark( pMark, bStart ); +} + + + +sal_Bool SwWrtShell::SelectTxtAttr( sal_uInt16 nWhich, const SwTxtAttr* pAttr ) +{ + sal_Bool bRet; + { + MV_KONTEXT(this); + SttSelect(); + bRet = SwCrsrShell::SelectTxtAttr( nWhich, sal_False, pAttr ); + } + EndSelect(); + return bRet; +} + + + |