blob: 5560f8351448b886e736976b9d52227cbb3caba1 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#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;
}