bump product version to 4.1.6.2
[LibreOffice.git] / sw / source / ui / wrtsh / move.cxx
blob6b998f35a43960c5d6204c300f6857bfed99979f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
21 #include <wrtsh.hxx>
22 #include <view.hxx>
23 #include <viewopt.hxx>
24 #include <crsskip.hxx>
26 /**
27 Always:
28 - Reset of the cursor stack
29 - retrigger timer
30 - if applicable: GCAttr
32 on selection
33 - SttSelect()
35 else
36 - EndSelect()
39 const long nReadOnlyScrollOfst = 10;
41 class ShellMoveCrsr
43 SwWrtShell* pSh;
44 bool bAct;
45 public:
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()
54 if( bAct )
56 // The action is used for scrolling in "single paragraph"
57 // frames with fixed height.
58 pSh->StartAllAction();
59 pSh->EndAllAction();
64 void SwWrtShell::MoveCrsr( sal_Bool bWithSelect )
66 ResetCursorStack();
67 if ( IsGCAttr() )
69 GCAttr();
70 ClearGCAttr();
72 if ( bWithSelect )
73 SttSelect();
74 else
76 EndSelect();
77 (this->*fnKillSel)( 0, sal_False );
81 sal_Bool SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove, sal_Bool bSelect )
83 sal_Bool nRet;
84 if( bSelect )
86 SttCrsrMove();
87 MoveCrsr( sal_True );
88 nRet = (this->*FnSimpleMove)();
89 EndCrsrMove();
91 else if( 0 != ( nRet = (this->*FnSimpleMove)() ) )
92 MoveCrsr( sal_False );
93 return nRet;
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 );
104 return sal_True;
106 else
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 );
122 return sal_True;
124 else
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 );
138 return sal_True;
140 else
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 );
155 return sal_True;
157 else
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 );
171 return sal_True;
173 else
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 );
189 return sal_True;
191 else
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 )
201 if ( IsCrsrInTbl() )
203 const sal_Bool bBoxSelection = HasBoxSelection();
204 if( !bBlockMode )
206 if ( !bSelect )
207 EnterStdMode();
208 else
209 SttSelect();
211 // Table cell ?
212 if ( !bBoxSelection && (MoveSection( fnSectionCurr, fnSectionStart)
213 || bDontMoveRegion))
215 if ( pMoveTable )
216 *pMoveTable = sal_False;
217 return sal_True;
219 if( MoveTable( fnTableCurr, fnTableStart ) || bDontMoveRegion )
221 if ( pMoveTable )
222 *pMoveTable = sal_True;
223 return 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;
233 return sal_True;
237 if( !bBlockMode )
239 if ( !bSelect )
240 EnterStdMode();
241 else
242 SttSelect();
244 const sal_uInt16 nFrmType = GetFrmType(0,sal_False);
245 if ( FRMTYPE_FLY_ANY & nFrmType )
247 if( MoveSection( fnSectionCurr, fnSectionStart ) )
248 return sal_True;
249 else if ( FRMTYPE_FLY_FREE & nFrmType || bDontMoveRegion )
250 return sal_False;
252 if(( FRMTYPE_HEADER | FRMTYPE_FOOTER | FRMTYPE_FOOTNOTE ) & nFrmType )
254 if ( MoveSection( fnSectionCurr, fnSectionStart ) )
255 return sal_True;
256 else if ( bKeepArea )
257 return sal_True;
259 // Regions ???
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 );
269 if ( IsCrsrInTbl() )
271 if ( MoveSection( fnSectionCurr, fnSectionEnd ) ||
272 MoveTable( fnTableCurr, fnTableEnd ) )
273 return sal_True;
275 else
277 const sal_uInt16 nFrmType = GetFrmType(0,sal_False);
278 if ( FRMTYPE_FLY_ANY & nFrmType )
280 if ( MoveSection( fnSectionCurr, fnSectionEnd ) )
281 return sal_True;
282 else if ( FRMTYPE_FLY_FREE & nFrmType )
283 return sal_False;
285 if(( FRMTYPE_HEADER | FRMTYPE_FOOTER | FRMTYPE_FOOTNOTE ) & nFrmType )
287 if ( MoveSection( fnSectionCurr, fnSectionEnd) )
288 return sal_True;
289 else if ( bKeepArea )
290 return sal_True;
293 // Regions ???
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 );
307 return GoEnd();
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.
405 if( !bDestOnStack )
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;
414 aPt.Y() += lOffset;
415 aDest = GetCntntPos(aPt,lOffset > 0);
416 aDest.X() = aPt.X();
417 bDestOnStack = true;
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) )
433 if( bSelect )
434 SttSelect();
435 else
436 EndSelect();
438 bIsFrmSel = IsFrmSelected();
439 bIsObjSel = 0 != IsObjSelected();
441 // unselect frame
442 if( bIsFrmSel || bIsObjSel )
444 UnSelectFrm();
445 LeaveSelFrmMode();
446 if ( bIsObjSel )
448 GetView().SetDrawFuncPtr( NULL );
449 GetView().LeaveDrawCreate();
452 CallChgLnk();
455 (this->*fnSetCrsr)( &aDest, sal_True );
457 bDiff = aOldRect != GetCharRect();
459 if( bIsFrmSel )
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)
481 if( 0 == pCrsrStack)
482 return sal_False;
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 ) )
493 if( bSelect )
494 SttSelect();
495 else
496 EndSelect();
498 (this->*fnSetCrsr)(&pCrsrStack->aDocPos, !pCrsrStack->bIsFrmSel);
499 if( pCrsrStack->bIsFrmSel && IsObjSelectable(pCrsrStack->aDocPos))
501 HideCrsr();
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.
509 else
511 _ResetCursorStack();
512 return sal_False;
515 CrsrStack *pTmp = pCrsrStack;
516 pCrsrStack = pCrsrStack->pNext;
517 delete pTmp;
518 if( 0 == pCrsrStack )
520 ePageMove = MV_NO;
521 bDestOnStack = false;
523 return bValidPos;
526 // Reset of all pushed cursor positions; these will
527 // not be displayed ( --> No Start-/EndAction!!)
529 void SwWrtShell::_ResetCursorStack()
531 CrsrStack *pTmp = pCrsrStack;
532 while(pCrsrStack)
534 pTmp = pCrsrStack->pNext;
535 delete pCrsrStack;
536 pCrsrStack = pTmp;
538 ePageMove = MV_NO;
539 bDestOnStack = false;
542 if no stack exists --> cancel selection
543 if stack && change of direction
544 --> pop cursor and return
545 else
546 --> push cursor
547 transpose cursor
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 ))
569 return sal_True;
571 const sal_Bool bRet = PushCrsr(lOffset, bSelect);
572 ePageMove = eDir;
573 return bRet;
576 sal_Bool SwWrtShell::GotoPage(sal_uInt16 nPage, sal_Bool bRecord)
578 ShellMoveCrsr aTmp( this, sal_False);
579 if( SwCrsrShell::GotoPage(nPage) && bRecord)
581 if(IsSelFrmMode())
583 UnSelectFrm();
584 LeaveSelFrmMode();
586 return sal_True;
588 return sal_False;
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 );
596 if (bRet)
597 aNavigationMgr.addEntry(aPos);
598 return bRet;
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);
605 if (bRet)
606 aNavigationMgr.addEntry(aPos);
607 return bRet;
610 bool SwWrtShell::GotoINetAttr( const SwTxtINetFmt& rAttr )
612 SwPosition aPos = *GetCrsr()->GetPoint();
613 bool bRet = SwCrsrShell::GotoINetAttr(rAttr);
614 if (bRet)
615 aNavigationMgr.addEntry(aPos);
616 return bRet;
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);
629 if (bRet)
630 aNavigationMgr.addEntry(aPos);
631 return bRet;
634 bool SwWrtShell::GotoRegion( const String& rName )
636 SwPosition aPos = *GetCrsr()->GetPoint();
637 bool bRet = SwCrsrShell::GotoRegion (rName);
638 if (bRet)
639 aNavigationMgr.addEntry(aPos);
640 return bRet;
643 sal_Bool SwWrtShell::GotoRefMark( const String& rRefMark, sal_uInt16 nSubType,
644 sal_uInt16 nSeqNo )
646 SwPosition aPos = *GetCrsr()->GetPoint();
647 bool bRet = SwCrsrShell::GotoRefMark(rRefMark, nSubType, nSeqNo);
648 if (bRet)
649 aNavigationMgr.addEntry(aPos);
650 return bRet;
653 sal_Bool SwWrtShell::GotoNextTOXBase( const String* pName )
655 SwPosition aPos = *GetCrsr()->GetPoint();
656 bool bRet = SwCrsrShell::GotoNextTOXBase(pName);
657 if (bRet)
658 aNavigationMgr.addEntry(aPos);
659 return bRet;
662 bool SwWrtShell::GotoTable( const String& rName )
664 SwPosition aPos = *GetCrsr()->GetPoint();
665 bool bRet = SwCrsrShell::GotoTable(rName);
666 if (bRet)
667 aNavigationMgr.addEntry(aPos);
668 return bRet;
671 sal_Bool SwWrtShell::GotoFld( const SwFmtFld& rFld ) {
672 SwPosition aPos = *GetCrsr()->GetPoint();
673 bool bRet = SwCrsrShell::GotoFld(rFld);
674 if (bRet)
675 aNavigationMgr.addEntry(aPos);
676 return bRet;
679 const SwRedline* SwWrtShell::GotoRedline( sal_uInt16 nArrPos, sal_Bool bSelect ) {
680 SwPosition aPos = *GetCrsr()->GetPoint();
681 const SwRedline *pRedline = SwCrsrShell::GotoRedline(nArrPos, bSelect);
682 if (pRedline)
683 aNavigationMgr.addEntry(aPos);
684 return pRedline;
687 sal_Bool SwWrtShell::SelectTxtAttr( sal_uInt16 nWhich, const SwTxtAttr* pAttr )
689 sal_Bool bRet;
691 SwMvContext aMvContext(this);
692 SttSelect();
693 bRet = SwCrsrShell::SelectTxtAttr( nWhich, sal_False, pAttr );
695 EndSelect();
696 return bRet;
699 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */