1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/bindings.hxx>
23 #include <viewopt.hxx>
24 #include <crsskip.hxx>
28 - Reset of the cursor stack
30 - if applicable: GCAttr
39 const long nReadOnlyScrollOfst
= 10;
46 inline ShellMoveCrsr( SwWrtShell
* pWrtSh
, sal_Bool bSel
)
48 bAct
= !pWrtSh
->ActionPend() && (pWrtSh
->GetFrmType(0,sal_False
) & FRMTYPE_FLY_ANY
);
49 ( pSh
= pWrtSh
)->MoveCrsr( sal_Bool(bSel
) );
50 pWrtSh
->GetView().GetViewFrame()->GetBindings().Invalidate(SID_HYPERLINK_GETLINK
);
52 inline ~ShellMoveCrsr()
56 // The action is used for scrolling in "single paragraph"
57 // frames with fixed height.
58 pSh
->StartAllAction();
64 void SwWrtShell::MoveCrsr( sal_Bool bWithSelect
)
77 (this->*fnKillSel
)( 0, sal_False
);
81 sal_Bool
SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove
, sal_Bool bSelect
)
88 nRet
= (this->*FnSimpleMove
)();
91 else if( 0 != ( nRet
= (this->*FnSimpleMove
)() ) )
92 MoveCrsr( sal_False
);
96 sal_Bool
SwWrtShell::Left( sal_uInt16 nMode
, sal_Bool bSelect
,
97 sal_uInt16 nCount
, sal_Bool bBasicCall
, sal_Bool bVisual
)
99 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
101 Point
aTmp( VisArea().Pos() );
102 aTmp
.X() -= VisArea().Width() * nReadOnlyScrollOfst
/ 100;
103 rView
.SetVisArea( aTmp
);
108 ShellMoveCrsr
aTmp( this, bSelect
);
109 return SwCrsrShell::Left( nCount
, nMode
, bVisual
);
113 sal_Bool
SwWrtShell::Right( sal_uInt16 nMode
, sal_Bool bSelect
,
114 sal_uInt16 nCount
, sal_Bool bBasicCall
, sal_Bool bVisual
)
116 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly() )
118 Point
aTmp( VisArea().Pos() );
119 aTmp
.X() += VisArea().Width() * nReadOnlyScrollOfst
/ 100;
120 aTmp
.X() = rView
.SetHScrollMax( aTmp
.X() );
121 rView
.SetVisArea( aTmp
);
126 ShellMoveCrsr
aTmp( this, bSelect
);
127 return SwCrsrShell::Right( nCount
, nMode
, bVisual
);
131 sal_Bool
SwWrtShell::Up( sal_Bool bSelect
, sal_uInt16 nCount
, sal_Bool bBasicCall
)
133 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
135 Point
aTmp( VisArea().Pos() );
136 aTmp
.Y() -= VisArea().Height() * nReadOnlyScrollOfst
/ 100;
137 rView
.SetVisArea( aTmp
);
142 ShellMoveCrsr
aTmp( this, bSelect
);
143 return SwCrsrShell::Up( nCount
);
147 sal_Bool
SwWrtShell::Down( sal_Bool bSelect
, sal_uInt16 nCount
, sal_Bool bBasicCall
)
149 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
151 Point
aTmp( VisArea().Pos() );
152 aTmp
.Y() += VisArea().Height() * nReadOnlyScrollOfst
/ 100;
153 aTmp
.Y() = rView
.SetVScrollMax( aTmp
.Y() );
154 rView
.SetVisArea( aTmp
);
159 ShellMoveCrsr
aTmp( this, bSelect
);
160 return SwCrsrShell::Down( nCount
);
164 sal_Bool
SwWrtShell::LeftMargin( sal_Bool bSelect
, sal_Bool bBasicCall
)
166 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() )
168 Point
aTmp( VisArea().Pos() );
169 aTmp
.X() = DOCUMENTBORDER
;
170 rView
.SetVisArea( aTmp
);
175 ShellMoveCrsr
aTmp( this, bSelect
);
176 return SwCrsrShell::LeftMargin();
180 sal_Bool
SwWrtShell::RightMargin( sal_Bool bSelect
, sal_Bool bBasicCall
)
182 if ( !bSelect
&& !bBasicCall
&& IsCrsrReadonly() )
184 Point
aTmp( VisArea().Pos() );
185 aTmp
.X() = GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER
;
186 if( DOCUMENTBORDER
> aTmp
.X() )
187 aTmp
.X() = DOCUMENTBORDER
;
188 rView
.SetVisArea( aTmp
);
193 ShellMoveCrsr
aTmp( this, bSelect
);
194 return SwCrsrShell::RightMargin(bBasicCall
);
198 sal_Bool
SwWrtShell::GoStart( sal_Bool bKeepArea
, sal_Bool
*pMoveTable
,
199 sal_Bool bSelect
, sal_Bool bDontMoveRegion
)
203 const sal_Bool bBoxSelection
= HasBoxSelection();
212 if ( !bBoxSelection
&& (MoveSection( fnSectionCurr
, fnSectionStart
)
216 *pMoveTable
= sal_False
;
219 if( MoveTable( fnTableCurr
, fnTableStart
) || bDontMoveRegion
)
222 *pMoveTable
= sal_True
;
225 else if( bBoxSelection
&& pMoveTable
)
227 // JP 09.01.96: We have a box selection (or a empty cell)
228 // and we want select (pMoveTable will be
229 // set in SelAll). Then the table must not
230 // be left, otherwise there is no selection
231 // of the entire table possible!
232 *pMoveTable
= sal_True
;
244 const sal_uInt16 nFrmType
= GetFrmType(0,sal_False
);
245 if ( FRMTYPE_FLY_ANY
& nFrmType
)
247 if( MoveSection( fnSectionCurr
, fnSectionStart
) )
249 else if ( FRMTYPE_FLY_FREE
& nFrmType
|| bDontMoveRegion
)
252 if(( FRMTYPE_HEADER
| FRMTYPE_FOOTER
| FRMTYPE_FOOTNOTE
) & nFrmType
)
254 if ( MoveSection( fnSectionCurr
, fnSectionStart
) )
256 else if ( bKeepArea
)
260 return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip
, fnRegionStart
) ||
261 SwCrsrShell::SttEndDoc(sal_True
);
264 sal_Bool
SwWrtShell::GoEnd(sal_Bool bKeepArea
, sal_Bool
*pMoveTable
)
266 if ( pMoveTable
&& *pMoveTable
)
267 return MoveTable( fnTableCurr
, fnTableEnd
);
271 if ( MoveSection( fnSectionCurr
, fnSectionEnd
) ||
272 MoveTable( fnTableCurr
, fnTableEnd
) )
277 const sal_uInt16 nFrmType
= GetFrmType(0,sal_False
);
278 if ( FRMTYPE_FLY_ANY
& nFrmType
)
280 if ( MoveSection( fnSectionCurr
, fnSectionEnd
) )
282 else if ( FRMTYPE_FLY_FREE
& nFrmType
)
285 if(( FRMTYPE_HEADER
| FRMTYPE_FOOTER
| FRMTYPE_FOOTNOTE
) & nFrmType
)
287 if ( MoveSection( fnSectionCurr
, fnSectionEnd
) )
289 else if ( bKeepArea
)
294 return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip
, fnRegionEnd
) ||
295 SwCrsrShell::SttEndDoc(sal_False
);
298 sal_Bool
SwWrtShell::SttDoc( sal_Bool bSelect
)
300 ShellMoveCrsr
aTmp( this, bSelect
);
301 return GoStart(sal_False
, 0, bSelect
);
304 sal_Bool
SwWrtShell::EndDoc( sal_Bool bSelect
)
306 ShellMoveCrsr
aTmp( this, bSelect
);
310 sal_Bool
SwWrtShell::SttNxtPg( sal_Bool bSelect
)
312 ShellMoveCrsr
aTmp( this, bSelect
);
313 return MovePage( fnPageNext
, fnPageStart
);
316 sal_Bool
SwWrtShell::SttPrvPg( sal_Bool bSelect
)
318 ShellMoveCrsr
aTmp( this, bSelect
);
319 return MovePage( fnPagePrev
, fnPageStart
);
322 sal_Bool
SwWrtShell::EndNxtPg( sal_Bool bSelect
)
324 ShellMoveCrsr
aTmp( this, bSelect
);
325 return MovePage( fnPageNext
, fnPageEnd
);
328 sal_Bool
SwWrtShell::EndPrvPg( sal_Bool bSelect
)
330 ShellMoveCrsr
aTmp( this, bSelect
);
331 return MovePage( fnPagePrev
, fnPageEnd
);
334 sal_Bool
SwWrtShell::SttPg( sal_Bool bSelect
)
336 ShellMoveCrsr
aTmp( this, bSelect
);
337 return MovePage( fnPageCurr
, fnPageStart
);
340 sal_Bool
SwWrtShell::EndPg( sal_Bool bSelect
)
342 ShellMoveCrsr
aTmp( this, bSelect
);
343 return MovePage( fnPageCurr
, fnPageEnd
);
346 sal_Bool
SwWrtShell::SttPara( sal_Bool bSelect
)
348 ShellMoveCrsr
aTmp( this, bSelect
);
349 return MovePara( fnParaCurr
, fnParaStart
);
352 sal_Bool
SwWrtShell::EndPara( sal_Bool bSelect
)
354 ShellMoveCrsr
aTmp( this, bSelect
);
355 return MovePara(fnParaCurr
,fnParaEnd
);
358 // Column-by-jumping.
359 // SSelection with or without
360 // returns success or failure
362 sal_Bool
SwWrtShell::StartOfColumn( sal_Bool bSelect
)
364 ShellMoveCrsr
aTmp( this, bSelect
);
365 return MoveColumn(fnColumnCurr
, fnColumnStart
);
368 sal_Bool
SwWrtShell::EndOfColumn( sal_Bool bSelect
)
370 ShellMoveCrsr
aTmp( this, bSelect
);
371 return MoveColumn(fnColumnCurr
, fnColumnEnd
);
374 sal_Bool
SwWrtShell::StartOfNextColumn( sal_Bool bSelect
)
376 ShellMoveCrsr
aTmp( this, bSelect
);
377 return MoveColumn( fnColumnNext
, fnColumnStart
);
380 sal_Bool
SwWrtShell::EndOfNextColumn( sal_Bool bSelect
)
382 ShellMoveCrsr
aTmp( this, bSelect
);
383 return MoveColumn(fnColumnNext
, fnColumnEnd
);
386 sal_Bool
SwWrtShell::StartOfPrevColumn( sal_Bool bSelect
)
388 ShellMoveCrsr
aTmp( this, bSelect
);
389 return MoveColumn(fnColumnPrev
, fnColumnStart
);
392 sal_Bool
SwWrtShell::EndOfPrevColumn( sal_Bool bSelect
)
394 ShellMoveCrsr
aTmp( this, bSelect
);
395 return MoveColumn(fnColumnPrev
, fnColumnEnd
);
398 sal_Bool
SwWrtShell::PushCrsr(SwTwips lOffset
, sal_Bool bSelect
)
400 sal_Bool bDiff
= sal_False
;
401 SwRect
aOldRect( GetCharRect() ), aTmpArea( VisArea() );
403 // bDestOnStack indicates if I could not set the coursor at the current
404 // position, because in this region is no content.
407 Point
aPt( aOldRect
.Center() );
409 if( !IsCrsrVisible() )
410 // set CrsrPos to top-/bottom left pos. So the pagescroll is not
411 // be dependent on the current cursor, but on the visarea.
412 aPt
.Y() = aTmpArea
.Top() + aTmpArea
.Height() / 2;
415 aDest
= GetCntntPos(aPt
,lOffset
> 0);
420 // If we had a frame selection, it must be removed after the fnSetCrsr
421 // and we have to remember the position on the stack to return to it later.
422 sal_Bool bIsFrmSel
= sal_False
;
424 bool bIsObjSel
= false;
426 //Target position is now within the viewable region -->
427 //Place the cursor at the target position; remember that no target
428 //position is longer on the stack.
429 //The new visible region is to be determined beforehand.
430 aTmpArea
.Pos().Y() += lOffset
;
431 if( aTmpArea
.IsInside(aDest
) )
438 bIsFrmSel
= IsFrmSelected();
439 bIsObjSel
= 0 != IsObjSelected();
442 if( bIsFrmSel
|| bIsObjSel
)
448 GetView().SetDrawFuncPtr( NULL
);
449 GetView().LeaveDrawCreate();
455 (this->*fnSetCrsr
)( &aDest
, sal_True
);
457 bDiff
= aOldRect
!= GetCharRect();
461 // In frames take only the upper corner
462 // so that it can be re-selected.
463 aOldRect
.SSize( 5, 5 );
466 // reset Dest. SPoint Flags
467 bDestOnStack
= false;
470 // Position into the stack; bDiff indicates if there is a
471 // difference between the old and the new cursor position.
472 pCrsrStack
= new CrsrStack( bDiff
, bIsFrmSel
, aOldRect
.Center(),
473 lOffset
, pCrsrStack
);
474 return !bDestOnStack
&& bDiff
;
479 sal_Bool
SwWrtShell::PopCrsr(sal_Bool bUpdate
, sal_Bool bSelect
)
484 const sal_Bool bValidPos
= pCrsrStack
->bValidCurPos
;
485 if( bUpdate
&& bValidPos
)
487 // If a predecessor is on the stack,
488 // use the flag for a valid position.
489 SwRect
aTmpArea(VisArea());
490 aTmpArea
.Pos().Y() -= pCrsrStack
->lOffset
;
491 if( aTmpArea
.IsInside( pCrsrStack
->aDocPos
) )
498 (this->*fnSetCrsr
)(&pCrsrStack
->aDocPos
, !pCrsrStack
->bIsFrmSel
);
499 if( pCrsrStack
->bIsFrmSel
&& IsObjSelectable(pCrsrStack
->aDocPos
))
502 SelectObj( pCrsrStack
->aDocPos
);
503 EnterSelFrmMode( &pCrsrStack
->aDocPos
);
506 // If a discrepancy between the visible range and the
507 // remembered cursor position occurs, all of the remembered
508 // positions are thrown away.
515 CrsrStack
*pTmp
= pCrsrStack
;
516 pCrsrStack
= pCrsrStack
->pNext
;
518 if( 0 == pCrsrStack
)
521 bDestOnStack
= false;
526 // Reset of all pushed cursor positions; these will
527 // not be displayed ( --> No Start-/EndAction!!)
529 void SwWrtShell::_ResetCursorStack()
531 CrsrStack
*pTmp
= pCrsrStack
;
534 pTmp
= pCrsrStack
->pNext
;
539 bDestOnStack
= false;
542 if no stack exists --> cancel selection
543 if stack && change of direction
544 --> pop cursor and return
552 sal_Bool
SwWrtShell::PageCrsr(SwTwips lOffset
, sal_Bool bSelect
)
554 // Do nothing if an offset of 0 was indicated
555 if(!lOffset
) return sal_False
;
556 // Was once used to force a reformat of the layout.
557 // This has not work that way, because the cursor was not set
558 // because this does not happen within a
559 // Start-/EndActionParentheses.
560 // Because only ViewShell::EndAction() is called at the end,
561 // no updating of the display of the cursor position takes place.
562 // The CrsrShell-Actionparentheses cannot be used, because it
563 // always leads to displaying the cursor, thus also,
564 // if after the scroll scrolled in a region without a valid postition.
565 // ViewShell::StartAction();
566 PageMove eDir
= lOffset
> 0? MV_PAGE_DOWN
: MV_PAGE_UP
;
567 // Change of direction and stack present
568 if( eDir
!= ePageMove
&& ePageMove
!= MV_NO
&& PopCrsr( sal_True
, bSelect
))
571 const sal_Bool bRet
= PushCrsr(lOffset
, bSelect
);
576 sal_Bool
SwWrtShell::GotoPage(sal_uInt16 nPage
, sal_Bool bRecord
)
578 ShellMoveCrsr
aTmp( this, sal_False
);
579 if( SwCrsrShell::GotoPage(nPage
) && bRecord
)
591 sal_Bool
SwWrtShell::GotoMark( const ::sw::mark::IMark
* const pMark
, sal_Bool bSelect
, sal_Bool bStart
)
593 ShellMoveCrsr
aTmp( this, bSelect
);
594 SwPosition aPos
= *GetCrsr()->GetPoint();
595 bool bRet
= SwCrsrShell::GotoMark( pMark
, bStart
);
597 aNavigationMgr
.addEntry(aPos
);
601 sal_Bool
SwWrtShell::GotoFly( const String
& rName
, FlyCntType eType
, sal_Bool bSelFrame
)
603 SwPosition aPos
= *GetCrsr()->GetPoint();
604 bool bRet
= SwFEShell::GotoFly(rName
, eType
, bSelFrame
);
606 aNavigationMgr
.addEntry(aPos
);
610 bool SwWrtShell::GotoINetAttr( const SwTxtINetFmt
& rAttr
)
612 SwPosition aPos
= *GetCrsr()->GetPoint();
613 bool bRet
= SwCrsrShell::GotoINetAttr(rAttr
);
615 aNavigationMgr
.addEntry(aPos
);
619 void SwWrtShell::GotoOutline( sal_uInt16 nIdx
)
621 addCurrentPosition();
622 SwCrsrShell::GotoOutline (nIdx
);
625 bool SwWrtShell::GotoOutline( const String
& rName
)
627 SwPosition aPos
= *GetCrsr()->GetPoint();
628 bool bRet
= SwCrsrShell::GotoOutline (rName
);
630 aNavigationMgr
.addEntry(aPos
);
634 bool SwWrtShell::GotoRegion( const String
& rName
)
636 SwPosition aPos
= *GetCrsr()->GetPoint();
637 bool bRet
= SwCrsrShell::GotoRegion (rName
);
639 aNavigationMgr
.addEntry(aPos
);
643 sal_Bool
SwWrtShell::GotoRefMark( const String
& rRefMark
, sal_uInt16 nSubType
,
646 SwPosition aPos
= *GetCrsr()->GetPoint();
647 bool bRet
= SwCrsrShell::GotoRefMark(rRefMark
, nSubType
, nSeqNo
);
649 aNavigationMgr
.addEntry(aPos
);
653 sal_Bool
SwWrtShell::GotoNextTOXBase( const String
* pName
)
655 SwPosition aPos
= *GetCrsr()->GetPoint();
656 bool bRet
= SwCrsrShell::GotoNextTOXBase(pName
);
658 aNavigationMgr
.addEntry(aPos
);
662 bool SwWrtShell::GotoTable( const String
& rName
)
664 SwPosition aPos
= *GetCrsr()->GetPoint();
665 bool bRet
= SwCrsrShell::GotoTable(rName
);
667 aNavigationMgr
.addEntry(aPos
);
671 sal_Bool
SwWrtShell::GotoFld( const SwFmtFld
& rFld
) {
672 SwPosition aPos
= *GetCrsr()->GetPoint();
673 bool bRet
= SwCrsrShell::GotoFld(rFld
);
675 aNavigationMgr
.addEntry(aPos
);
679 const SwRedline
* SwWrtShell::GotoRedline( sal_uInt16 nArrPos
, sal_Bool bSelect
) {
680 SwPosition aPos
= *GetCrsr()->GetPoint();
681 const SwRedline
*pRedline
= SwCrsrShell::GotoRedline(nArrPos
, bSelect
);
683 aNavigationMgr
.addEntry(aPos
);
687 sal_Bool
SwWrtShell::SelectTxtAttr( sal_uInt16 nWhich
, const SwTxtAttr
* pAttr
)
691 SwMvContext
aMvContext(this);
693 bRet
= SwCrsrShell::SelectTxtAttr( nWhich
, sal_False
, pAttr
);
699 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */