1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: move.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <sfx2/bindings.hxx>
40 #include <viewopt.hxx>
41 #include <crsskip.hxx>
44 - Zuruecksetzen des Cursorstacks
55 const long nReadOnlyScrollOfst
= 10;
62 inline ShellMoveCrsr( SwWrtShell
* pWrtSh
, BOOL bSel
)
64 bAct
= !pWrtSh
->ActionPend() && (pWrtSh
->GetFrmType(0,FALSE
) & FRMTYPE_FLY_ANY
);
65 ( pSh
= pWrtSh
)->MoveCrsr( BOOL(bSel
) );
66 pWrtSh
->GetView().GetViewFrame()->GetBindings().Invalidate(SID_HYPERLINK_GETLINK
);
68 inline ~ShellMoveCrsr()
72 //Die Action wird fuer das Scrollen in "einabsaetzigen" Rahmen mit
73 //fester Hoehe gebraucht.
74 pSh
->StartAllAction();
80 void SwWrtShell::MoveCrsr( BOOL bWithSelect
)
93 (this->*fnKillSel
)( 0, FALSE
);
97 BOOL
SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove
, BOOL bSelect
)
104 nRet
= (this->*FnSimpleMove
)();
107 else if( 0 != ( nRet
= (this->*FnSimpleMove
)() ) )
113 BOOL
SwWrtShell::Left( USHORT nMode
, BOOL bSelect
,
114 USHORT nCount
, BOOL bBasicCall
, BOOL bVisual
)
116 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
118 Point
aTmp( VisArea().Pos() );
119 aTmp
.X() -= VisArea().Width() * nReadOnlyScrollOfst
/ 100;
120 rView
.SetVisArea( aTmp
);
125 ShellMoveCrsr
aTmp( this, bSelect
);
126 return SwCrsrShell::Left( nCount
, nMode
, bVisual
);
132 BOOL
SwWrtShell::Right( USHORT nMode
, BOOL bSelect
,
133 USHORT nCount
, BOOL bBasicCall
, BOOL bVisual
)
135 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly() )
137 Point
aTmp( VisArea().Pos() );
138 aTmp
.X() += VisArea().Width() * nReadOnlyScrollOfst
/ 100;
139 aTmp
.X() = rView
.SetHScrollMax( aTmp
.X() );
140 rView
.SetVisArea( aTmp
);
145 ShellMoveCrsr
aTmp( this, bSelect
);
146 return SwCrsrShell::Right( nCount
, nMode
, bVisual
);
152 BOOL
SwWrtShell::Up( BOOL bSelect
, USHORT nCount
, BOOL bBasicCall
)
154 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
156 Point
aTmp( VisArea().Pos() );
157 aTmp
.Y() -= VisArea().Height() * nReadOnlyScrollOfst
/ 100;
158 rView
.SetVisArea( aTmp
);
163 ShellMoveCrsr
aTmp( this, bSelect
);
164 return SwCrsrShell::Up( nCount
);
170 BOOL
SwWrtShell::Down( BOOL bSelect
, USHORT nCount
, BOOL bBasicCall
)
172 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
174 Point
aTmp( VisArea().Pos() );
175 aTmp
.Y() += VisArea().Height() * nReadOnlyScrollOfst
/ 100;
176 aTmp
.Y() = rView
.SetVScrollMax( aTmp
.Y() );
177 rView
.SetVisArea( aTmp
);
182 ShellMoveCrsr
aTmp( this, bSelect
);
183 return SwCrsrShell::Down( nCount
);
189 BOOL
SwWrtShell::LeftMargin( BOOL bSelect
, BOOL bBasicCall
)
191 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() )
193 Point
aTmp( VisArea().Pos() );
194 aTmp
.X() = DOCUMENTBORDER
;
195 rView
.SetVisArea( aTmp
);
200 ShellMoveCrsr
aTmp( this, bSelect
);
201 return SwCrsrShell::LeftMargin();
207 BOOL
SwWrtShell::RightMargin( BOOL bSelect
, BOOL bBasicCall
)
209 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() )
211 Point
aTmp( VisArea().Pos() );
212 aTmp
.X() = GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER
;
213 if( DOCUMENTBORDER
> aTmp
.X() )
214 aTmp
.X() = DOCUMENTBORDER
;
215 rView
.SetVisArea( aTmp
);
220 ShellMoveCrsr
aTmp( this, bSelect
);
221 return SwCrsrShell::RightMargin(bBasicCall
);
227 BOOL
SwWrtShell::GoStart( BOOL bKeepArea
, BOOL
*pMoveTable
,
228 BOOL bSelect
, BOOL bDontMoveRegion
)
232 const BOOL bBoxSelection
= HasBoxSelection();
241 if ( !bBoxSelection
&& (MoveSection( fnSectionCurr
, fnSectionStart
)
248 if( MoveTable( fnTableCurr
, fnTableStart
) || bDontMoveRegion
)
254 else if( bBoxSelection
&& pMoveTable
)
256 // JP 09.01.96: wir haben eine Boxselektion (oder leere Zelle)
257 // und wollen selektieren (pMoveTable wird im
258 // SelAll gesetzt). Dann darf die Tabelle nicht
259 // verlassen werden; sonst ist keine Selektion der
260 // gesamten Tabelle moeglich!
273 const USHORT nFrmType
= GetFrmType(0,FALSE
);
274 if ( FRMTYPE_FLY_ANY
& nFrmType
)
276 if( MoveSection( fnSectionCurr
, fnSectionStart
) )
278 else if ( FRMTYPE_FLY_FREE
& nFrmType
|| bDontMoveRegion
)
281 if(( FRMTYPE_HEADER
| FRMTYPE_FOOTER
| FRMTYPE_FOOTNOTE
) & nFrmType
)
283 if ( MoveSection( fnSectionCurr
, fnSectionStart
) )
285 else if ( bKeepArea
)
289 return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip
, fnRegionStart
) ||
290 SwCrsrShell::SttEndDoc(TRUE
);
295 BOOL
SwWrtShell::GoEnd(BOOL bKeepArea
, BOOL
*pMoveTable
)
297 if ( pMoveTable
&& *pMoveTable
)
298 return MoveTable( fnTableCurr
, fnTableEnd
);
302 if ( MoveSection( fnSectionCurr
, fnSectionEnd
) ||
303 MoveTable( fnTableCurr
, fnTableEnd
) )
308 const USHORT nFrmType
= GetFrmType(0,FALSE
);
309 if ( FRMTYPE_FLY_ANY
& nFrmType
)
311 if ( MoveSection( fnSectionCurr
, fnSectionEnd
) )
313 else if ( FRMTYPE_FLY_FREE
& nFrmType
)
316 if(( FRMTYPE_HEADER
| FRMTYPE_FOOTER
| FRMTYPE_FOOTNOTE
) & nFrmType
)
318 if ( MoveSection( fnSectionCurr
, fnSectionEnd
) )
320 else if ( bKeepArea
)
325 return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip
, fnRegionEnd
) ||
326 SwCrsrShell::SttEndDoc(FALSE
);
331 BOOL
SwWrtShell::SttDoc( BOOL bSelect
)
333 ShellMoveCrsr
aTmp( this, bSelect
);
334 return GoStart(FALSE
, 0, bSelect
);
339 BOOL
SwWrtShell::EndDoc( BOOL bSelect
)
341 ShellMoveCrsr
aTmp( this, bSelect
);
346 BOOL
SwWrtShell::SttNxtPg( BOOL bSelect
)
348 ShellMoveCrsr
aTmp( this, bSelect
);
349 return MovePage( fnPageNext
, fnPageStart
);
354 BOOL
SwWrtShell::SttPrvPg( BOOL bSelect
)
356 ShellMoveCrsr
aTmp( this, bSelect
);
357 return MovePage( fnPagePrev
, fnPageStart
);
362 BOOL
SwWrtShell::EndNxtPg( BOOL bSelect
)
364 ShellMoveCrsr
aTmp( this, bSelect
);
365 return MovePage( fnPageNext
, fnPageEnd
);
370 BOOL
SwWrtShell::EndPrvPg( BOOL bSelect
)
372 ShellMoveCrsr
aTmp( this, bSelect
);
373 return MovePage( fnPagePrev
, fnPageEnd
);
378 BOOL
SwWrtShell::SttPg( BOOL bSelect
)
380 ShellMoveCrsr
aTmp( this, bSelect
);
381 return MovePage( fnPageCurr
, fnPageStart
);
386 BOOL
SwWrtShell::EndPg( BOOL bSelect
)
388 ShellMoveCrsr
aTmp( this, bSelect
);
389 return MovePage( fnPageCurr
, fnPageEnd
);
394 BOOL
SwWrtShell::SttPara( BOOL bSelect
)
396 ShellMoveCrsr
aTmp( this, bSelect
);
397 return MovePara( fnParaCurr
, fnParaStart
);
402 BOOL
SwWrtShell::EndPara( BOOL bSelect
)
404 ShellMoveCrsr
aTmp( this, bSelect
);
405 return MovePara(fnParaCurr
,fnParaEnd
);
409 /*------------------------------------------------------------------------
410 Beschreibung: Spaltenweises Springen
411 Parameter: mit oder ohne SSelection
412 Return: Erfolg oder Misserfolg
413 ------------------------------------------------------------------------*/
417 BOOL
SwWrtShell::StartOfColumn( BOOL bSelect
)
419 ShellMoveCrsr
aTmp( this, bSelect
);
420 return MoveColumn(fnColumnCurr
, fnColumnStart
);
425 BOOL
SwWrtShell::EndOfColumn( BOOL bSelect
)
427 ShellMoveCrsr
aTmp( this, bSelect
);
428 return MoveColumn(fnColumnCurr
, fnColumnEnd
);
433 BOOL
SwWrtShell::StartOfNextColumn( BOOL bSelect
)
435 ShellMoveCrsr
aTmp( this, bSelect
);
436 return MoveColumn( fnColumnNext
, fnColumnStart
);
441 BOOL
SwWrtShell::EndOfNextColumn( BOOL bSelect
)
443 ShellMoveCrsr
aTmp( this, bSelect
);
444 return MoveColumn(fnColumnNext
, fnColumnEnd
);
449 BOOL
SwWrtShell::StartOfPrevColumn( BOOL bSelect
)
451 ShellMoveCrsr
aTmp( this, bSelect
);
452 return MoveColumn(fnColumnPrev
, fnColumnStart
);
457 BOOL
SwWrtShell::EndOfPrevColumn( BOOL bSelect
)
459 ShellMoveCrsr
aTmp( this, bSelect
);
460 return MoveColumn(fnColumnPrev
, fnColumnEnd
);
465 BOOL
SwWrtShell::PushCrsr(SwTwips lOffset
, BOOL bSelect
)
468 SwRect
aOldRect( GetCharRect() ), aTmpArea( VisArea() );
470 //bDestOnStack besagt, ob ich den Cursor nicht an die aktuelle Position
471 //setzen konnte, da in diesem Bereich kein Inhalt vorhanden ist.
474 Point
aPt( aOldRect
.Center() );
476 if( !IsCrsrVisible() )
477 // set CrsrPos to top-/bottom left pos. So the pagescroll is not
478 // be dependent on the current cursor, but on the visarea.
479 aPt
.Y() = aTmpArea
.Top() + aTmpArea
.Height() / 2;
482 aDest
= GetCntntPos(aPt
,lOffset
> 0);
487 //falls wir eine Rahmenselektion hatten, muss diese nach dem
488 //fnSetCrsr entfernt werden und damit wir da wieder hinkommen
489 //auf dem Stack gemerkt werden.
490 BOOL bIsFrmSel
= FALSE
;
492 BOOL bIsObjSel
= FALSE
;
494 //Zielposition liegt jetzt innerhalb des sichtbaren Bereiches -->
495 //Cursor an die Zielposition setzen; merken, dass keine Ziel-
496 //position mehr auf dem Stack steht.
497 //Der neue sichtbare Bereich wird zuvor ermittelt.
498 aTmpArea
.Pos().Y() += lOffset
;
499 if( aTmpArea
.IsInside(aDest
) )
506 bIsFrmSel
= IsFrmSelected();
507 bIsObjSel
= 0 != IsObjSelected();
509 // Rahmenselektion aufheben
510 if( bIsFrmSel
|| bIsObjSel
)
516 GetView().SetDrawFuncPtr( NULL
);
517 GetView().LeaveDrawCreate();
523 (this->*fnSetCrsr
)( &aDest
, TRUE
);
525 bDiff
= aOldRect
!= GetCharRect();
530 // bei Frames immer nur die obere Ecke nehmen, damit dieser
531 // wieder selektiert werden kann
532 aOldRect
.SSize( 5, 5 );
535 // Zuruecksetzen des Dest. SPoint Flags
536 bDestOnStack
= FALSE
;
539 // Position auf den Stack; bDiff besagt, ob ein Unterschied zwischen
540 // der alten und der neuen Cursorposition besteht.
541 pCrsrStack
= new CrsrStack( bDiff
, bIsFrmSel
, aOldRect
.Center(),
542 lOffset
, pCrsrStack
);
543 return !bDestOnStack
&& bDiff
;
548 BOOL
SwWrtShell::PopCrsr(BOOL bUpdate
, BOOL bSelect
)
553 const BOOL bValidPos
= pCrsrStack
->bValidCurPos
;
554 if( bUpdate
&& bValidPos
)
556 // falls ein Vorgaenger auf dem Stack steht, dessen Flag fuer eine
557 // gueltige Position verwenden.
558 SwRect
aTmpArea(VisArea());
559 aTmpArea
.Pos().Y() -= pCrsrStack
->lOffset
;
560 if( aTmpArea
.IsInside( pCrsrStack
->aDocPos
) )
567 (this->*fnSetCrsr
)(&pCrsrStack
->aDocPos
, !pCrsrStack
->bIsFrmSel
);
568 if( pCrsrStack
->bIsFrmSel
&& IsObjSelectable(pCrsrStack
->aDocPos
))
571 SelectObj( pCrsrStack
->aDocPos
);
572 EnterSelFrmMode( &pCrsrStack
->aDocPos
);
575 // Falls eine Verschiebung zwischen dem sichtbaren Bereich
576 // und der gemerkten Cursorpositionen auftritt, werden
577 // alle gemerkten Positionen weggeschmissen
584 CrsrStack
*pTmp
= pCrsrStack
;
585 pCrsrStack
= pCrsrStack
->pNext
;
587 if( 0 == pCrsrStack
)
590 bDestOnStack
= FALSE
;
596 * Zuruecksetzen aller gepushten Cursorpositionen; dieser werden nicht
597 * zur Anzeige gebracht ( --> Kein Start-/EndAction!!)
602 void SwWrtShell::_ResetCursorStack()
604 CrsrStack
*pTmp
= pCrsrStack
;
607 pTmp
= pCrsrStack
->pNext
;
612 bDestOnStack
= FALSE
;
616 falls kein Stack existiert --> Selektionen aufheben
617 falls Stack && Richtungswechsel
618 --> Cursor poppen und return
627 BOOL
SwWrtShell::PageCrsr(SwTwips lOffset
, BOOL bSelect
)
629 // nichts tun, wenn ein Offset von 0 angegeben wurde
630 if(!lOffset
) return FALSE
;
631 // Diente mal dazu, eine Neuformatierung fuer das Layout
633 // Hat so nicht funktioniert, da der Cursor nicht gesetzt
634 // wurde, da dies innerhalb einer Start- / EndActionklammerung
636 // Da am Ende nur ViewShell::EndAction() gerufen wird,
637 // findet auch hier keine Aktualisierung der Anzeige
638 // der Cursorposition statt.
639 // Die CrsrShell- Actionklammerung kann nicht verwendet werden,
640 // da sie immer zu einer Anzeige des Cursors fuehrt, also auch,
641 // wenn nach dem Blaettern in einen Bereich ohne gueltige Position
642 // geblaettert wurde.
643 // ViewShell::StartAction();
644 PageMove eDir
= lOffset
> 0? MV_PAGE_DOWN
: MV_PAGE_UP
;
645 // Richtungswechsel und Stack vorhanden
646 if( eDir
!= ePageMove
&& ePageMove
!= MV_NO
&& PopCrsr( TRUE
, bSelect
))
649 const BOOL bRet
= PushCrsr(lOffset
, bSelect
);
656 BOOL
SwWrtShell::GotoPage(USHORT nPage
, BOOL bRecord
)
658 ShellMoveCrsr
aTmp( this, FALSE
);
659 if( SwCrsrShell::GotoPage(nPage
) && bRecord
)
673 BOOL
SwWrtShell::GotoMark( const ::sw::mark::IMark
* const pMark
, BOOL bSelect
, BOOL bStart
)
675 ShellMoveCrsr
aTmp( this, bSelect
);
676 return SwCrsrShell::GotoMark( pMark
, bStart
);
681 BOOL
SwWrtShell::SelectTxtAttr( USHORT nWhich
, const SwTxtAttr
* pAttr
)
687 bRet
= SwCrsrShell::SelectTxtAttr( nWhich
, FALSE
, pAttr
);