nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / uibase / wrtsh / move.cxx
blob491a2fcbdb2ae3093fc8b13e70b830d024620741
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 <sfx2/viewfrm.hxx>
22 #include <wrtsh.hxx>
23 #include <view.hxx>
24 #include <viewopt.hxx>
25 #include <drawbase.hxx>
27 /**
28 Always:
29 - Reset of the cursor stack
30 - retrigger timer
31 - if applicable: GCAttr
33 on selection
34 - SttSelect()
36 else
37 - EndSelect()
40 const tools::Long nReadOnlyScrollOfst = 10;
42 namespace {
44 class ShellMoveCursor
46 SwWrtShell* pSh;
47 bool bAct;
48 public:
49 ShellMoveCursor( SwWrtShell* pWrtSh, bool bSel )
51 bAct = !pWrtSh->ActionPend() && (pWrtSh->GetFrameType(nullptr,false) & FrameTypeFlags::FLY_ANY);
52 pSh = pWrtSh;
53 pSh->MoveCursor( bSel );
54 pWrtSh->GetView().GetViewFrame()->GetBindings().Invalidate(SID_HYPERLINK_GETLINK);
56 ~ShellMoveCursor() COVERITY_NOEXCEPT_FALSE
58 if( bAct )
60 // The action is used for scrolling in "single paragraph"
61 // frames with fixed height.
62 pSh->StartAllAction();
63 pSh->EndAllAction();
70 void SwWrtShell::MoveCursor( bool bWithSelect )
72 ResetCursorStack();
73 if ( IsGCAttr() )
75 GCAttr();
76 ClearGCAttr();
78 if ( bWithSelect )
79 SttSelect();
80 else
82 EndSelect();
83 (this->*m_fnKillSel)( nullptr, false );
87 bool SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove, bool bSelect )
89 bool bRet;
90 if( bSelect )
92 SttCursorMove();
93 MoveCursor( true );
94 bRet = (this->*FnSimpleMove)();
95 EndCursorMove();
97 else
99 bRet = (this->*FnSimpleMove)();
100 if( bRet )
101 MoveCursor();
103 return bRet;
106 bool SwWrtShell::Left( sal_uInt16 nMode, bool bSelect,
107 sal_uInt16 nCount, bool bBasicCall, bool bVisual )
109 if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
111 Point aTmp( VisArea().Pos() );
112 aTmp.AdjustX( -(VisArea().Width() * nReadOnlyScrollOfst / 100) );
113 m_rView.SetVisArea( aTmp );
114 return true;
116 else
118 ShellMoveCursor aTmp( this, bSelect );
119 return SwCursorShell::Left( nCount, nMode, bVisual );
123 bool SwWrtShell::Right( sal_uInt16 nMode, bool bSelect,
124 sal_uInt16 nCount, bool bBasicCall, bool bVisual )
126 if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly() )
128 Point aTmp( VisArea().Pos() );
129 aTmp.AdjustX(VisArea().Width() * nReadOnlyScrollOfst / 100 );
130 aTmp.setX( m_rView.SetHScrollMax( aTmp.X() ) );
131 m_rView.SetVisArea( aTmp );
132 return true;
134 else
136 ShellMoveCursor aTmp( this, bSelect );
137 return SwCursorShell::Right( nCount, nMode, bVisual );
141 bool SwWrtShell::Up( bool bSelect, sal_uInt16 nCount, bool bBasicCall )
143 if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
145 Point aTmp( VisArea().Pos() );
146 aTmp.AdjustY( -(VisArea().Height() * nReadOnlyScrollOfst / 100) );
147 m_rView.SetVisArea( aTmp );
148 return true;
151 ShellMoveCursor aTmp( this, bSelect );
152 return SwCursorShell::Up(nCount);
155 bool SwWrtShell::Down( bool bSelect, sal_uInt16 nCount, bool bBasicCall )
157 if ( !bSelect && !bBasicCall && IsCursorReadonly() && !GetViewOptions()->IsSelectionInReadonly())
159 Point aTmp( VisArea().Pos() );
160 aTmp.AdjustY(VisArea().Height() * nReadOnlyScrollOfst / 100 );
161 aTmp.setY( m_rView.SetVScrollMax( aTmp.Y() ) );
162 m_rView.SetVisArea( aTmp );
163 return true;
166 ShellMoveCursor aTmp( this, bSelect );
167 return SwCursorShell::Down(nCount);
170 bool SwWrtShell::LeftMargin( bool bSelect, bool bBasicCall )
172 if ( !bSelect && !bBasicCall && IsCursorReadonly() )
174 Point aTmp( VisArea().Pos() );
175 aTmp.setX( DOCUMENTBORDER );
176 m_rView.SetVisArea( aTmp );
177 return true;
179 else
181 ShellMoveCursor aTmp( this, bSelect );
182 return SwCursorShell::LeftMargin();
186 bool SwWrtShell::RightMargin( bool bSelect, bool bBasicCall )
188 if ( !bSelect && !bBasicCall && IsCursorReadonly() )
190 Point aTmp( VisArea().Pos() );
191 aTmp.setX( GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER );
192 if( DOCUMENTBORDER > aTmp.X() )
193 aTmp.setX( DOCUMENTBORDER );
194 m_rView.SetVisArea( aTmp );
195 return true;
197 else
199 ShellMoveCursor aTmp( this, bSelect );
200 return SwCursorShell::RightMargin(bBasicCall);
204 bool SwWrtShell::GoStart( bool bKeepArea, bool *pMoveTable,
205 bool bSelect, bool bDontMoveRegion )
207 if ( IsCursorInTable() )
209 const bool bBoxSelection = HasBoxSelection();
210 if( !m_bBlockMode )
212 if ( !bSelect )
213 EnterStdMode();
214 else
215 SttSelect();
217 // Table cell ?
218 if ( !bBoxSelection && (MoveSection( GoCurrSection, fnSectionStart)
219 || bDontMoveRegion))
221 if ( pMoveTable )
222 *pMoveTable = false;
223 return true;
225 if( MoveTable( GotoCurrTable, fnTableStart ) || bDontMoveRegion )
227 if ( pMoveTable )
228 *pMoveTable = true;
229 return true;
231 else if( bBoxSelection && pMoveTable )
233 // JP 09.01.96: We have a box selection (or an empty cell)
234 // and we want select (pMoveTable will be
235 // set in SelAll). Then the table must not
236 // be left, otherwise there is no selection
237 // of the entire table possible!
238 *pMoveTable = true;
239 return true;
243 if( !m_bBlockMode )
245 if ( !bSelect )
246 EnterStdMode();
247 else
248 SttSelect();
250 const FrameTypeFlags nFrameType = GetFrameType(nullptr,false);
251 if ( FrameTypeFlags::FLY_ANY & nFrameType )
253 if( MoveSection( GoCurrSection, fnSectionStart ) )
254 return true;
255 else if ( FrameTypeFlags::FLY_FREE & nFrameType || bDontMoveRegion )
256 return false;
258 if(( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE ) & nFrameType )
260 if ( MoveSection( GoCurrSection, fnSectionStart ) )
261 return true;
262 else if ( bKeepArea )
263 return true;
265 // Regions ???
266 return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip, fnRegionStart ) ||
267 SwCursorShell::SttEndDoc(true);
270 bool SwWrtShell::GoEnd(bool bKeepArea, const bool *pMoveTable)
272 if ( pMoveTable && *pMoveTable )
273 return MoveTable( GotoCurrTable, fnTableEnd );
275 if ( IsCursorInTable() )
277 if ( MoveSection( GoCurrSection, fnSectionEnd ) ||
278 MoveTable( GotoCurrTable, fnTableEnd ) )
279 return true;
281 else
283 const FrameTypeFlags nFrameType = GetFrameType(nullptr,false);
284 if ( FrameTypeFlags::FLY_ANY & nFrameType )
286 if ( MoveSection( GoCurrSection, fnSectionEnd ) )
287 return true;
288 else if ( FrameTypeFlags::FLY_FREE & nFrameType )
289 return false;
291 if(( FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE ) & nFrameType )
293 if ( MoveSection( GoCurrSection, fnSectionEnd) )
294 return true;
295 else if ( bKeepArea )
296 return true;
299 // Regions ???
300 return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip, fnRegionEnd ) ||
301 SwCursorShell::SttEndDoc(false);
304 bool SwWrtShell::StartOfSection(bool const bSelect)
306 ShellMoveCursor aTmp( this, bSelect );
307 return GoStart(false, nullptr, bSelect );
310 bool SwWrtShell::EndOfSection(bool const bSelect)
312 ShellMoveCursor aTmp( this, bSelect );
313 return GoEnd();
316 bool SwWrtShell::SttNxtPg( bool bSelect )
318 ShellMoveCursor aTmp( this, bSelect );
319 return MovePage( GetNextFrame, GetFirstSub );
322 void SwWrtShell::SttPrvPg( bool bSelect )
324 ShellMoveCursor aTmp( this, bSelect );
325 MovePage( GetPrevFrame, GetFirstSub );
328 void SwWrtShell::EndNxtPg( bool bSelect )
330 ShellMoveCursor aTmp( this, bSelect );
331 MovePage( GetNextFrame, GetLastSub );
334 bool SwWrtShell::EndPrvPg( bool bSelect )
336 ShellMoveCursor aTmp( this, bSelect );
337 return MovePage( GetPrevFrame, GetLastSub );
340 bool SwWrtShell::SttPg( bool bSelect )
342 ShellMoveCursor aTmp( this, bSelect );
343 return MovePage( GetThisFrame, GetFirstSub );
346 bool SwWrtShell::EndPg( bool bSelect )
348 ShellMoveCursor aTmp( this, bSelect );
349 return MovePage( GetThisFrame, GetLastSub );
352 bool SwWrtShell::SttPara( bool bSelect )
354 ShellMoveCursor aTmp( this, bSelect );
355 return MovePara( GoCurrPara, fnParaStart );
358 void SwWrtShell::EndPara( bool bSelect )
360 ShellMoveCursor aTmp( this, bSelect );
361 MovePara(GoCurrPara,fnParaEnd);
364 // Column-by-jumping.
365 // SSelection with or without
366 // returns success or failure
368 void SwWrtShell::StartOfColumn()
370 ShellMoveCursor aTmp( this, false/*bSelect*/);
371 MoveColumn(GetCurrColumn, GetColumnStt);
374 void SwWrtShell::EndOfColumn()
376 ShellMoveCursor aTmp( this, false/*bSelect*/);
377 MoveColumn(GetCurrColumn, GetColumnEnd);
380 void SwWrtShell::StartOfNextColumn()
382 ShellMoveCursor aTmp( this, false/*bSelect*/);
383 MoveColumn( GetNextColumn, GetColumnStt);
386 void SwWrtShell::EndOfNextColumn()
388 ShellMoveCursor aTmp( this, false/*bSelect*/);
389 MoveColumn(GetNextColumn, GetColumnEnd);
392 void SwWrtShell::StartOfPrevColumn()
394 ShellMoveCursor aTmp( this, false/*bSelect*/);
395 MoveColumn(GetPrevColumn, GetColumnStt);
398 void SwWrtShell::EndOfPrevColumn()
400 ShellMoveCursor aTmp( this, false/*bSelect*/);
401 MoveColumn(GetPrevColumn, GetColumnEnd);
404 bool SwWrtShell::PushCursor(SwTwips lOffset, bool bSelect)
406 bool bDiff = false;
407 SwRect aOldRect( GetCharRect() ), aTmpArea( VisArea() );
409 // m_bDestOnStack indicates if I could not set the coursor at the current
410 // position, because in this region is no content.
411 if( !m_bDestOnStack )
413 Point aPt( aOldRect.Center() );
415 if( !IsCursorVisible() )
416 // set CursorPos to top-/bottom left pos. So the pagescroll is not
417 // be dependent on the current cursor, but on the visarea.
418 aPt.setY( aTmpArea.Top() + aTmpArea.Height() / 2 );
420 aPt.AdjustY(lOffset );
421 m_aDest = GetContentPos(aPt,lOffset > 0);
422 m_aDest.setX( aPt.X() );
423 m_bDestOnStack = true;
426 // If we had a frame selection, it must be removed after the m_fnSetCursor
427 // and we have to remember the position on the stack to return to it later.
428 bool bIsFrameSel = false;
430 //Target position is now within the viewable region -->
431 //Place the cursor at the target position; remember that no target
432 //position is longer on the stack.
433 //The new visible region is to be determined beforehand.
434 aTmpArea.Pos().AdjustY(lOffset );
435 if( aTmpArea.IsInside(m_aDest) )
437 if( bSelect )
438 SttSelect();
439 else
440 EndSelect();
442 bIsFrameSel = IsFrameSelected();
443 bool bIsObjSel = 0 != IsObjSelected();
445 // unselect frame
446 if( bIsFrameSel || bIsObjSel )
448 UnSelectFrame();
449 LeaveSelFrameMode();
450 if ( bIsObjSel )
452 GetView().SetDrawFuncPtr( nullptr );
453 GetView().LeaveDrawCreate();
456 CallChgLnk();
459 (this->*m_fnSetCursor)( &m_aDest, true );
461 bDiff = aOldRect != GetCharRect();
463 if( bIsFrameSel )
465 // In frames take only the upper corner
466 // so that it can be re-selected.
467 aOldRect.SSize( 5, 5 );
470 // reset Dest. SPoint Flags
471 m_bDestOnStack = false;
474 // Position into the stack; bDiff indicates if there is a
475 // difference between the old and the new cursor position.
476 m_pCursorStack.reset( new CursorStack( bDiff, bIsFrameSel, aOldRect.Center(),
477 lOffset, std::move(m_pCursorStack) ) );
478 return !m_bDestOnStack && bDiff;
481 bool SwWrtShell::PopCursor(bool bUpdate, bool bSelect)
483 if( nullptr == m_pCursorStack)
484 return false;
486 const bool bValidPos = m_pCursorStack->bValidCurPos;
487 if( bUpdate && bValidPos )
489 // If a predecessor is on the stack,
490 // use the flag for a valid position.
491 SwRect aTmpArea(VisArea());
492 aTmpArea.Pos().AdjustY( -(m_pCursorStack->lOffset) );
493 if( aTmpArea.IsInside( m_pCursorStack->aDocPos ) )
495 if( bSelect )
496 SttSelect();
497 else
498 EndSelect();
500 (this->*m_fnSetCursor)(&m_pCursorStack->aDocPos, !m_pCursorStack->bIsFrameSel);
501 if( m_pCursorStack->bIsFrameSel && IsObjSelectable(m_pCursorStack->aDocPos))
503 HideCursor();
504 SelectObj( m_pCursorStack->aDocPos );
505 EnterSelFrameMode( &m_pCursorStack->aDocPos );
508 // If a discrepancy between the visible range and the
509 // remembered cursor position occurs, all of the remembered
510 // positions are thrown away.
511 else
513 ResetCursorStack_();
514 return false;
517 m_pCursorStack = std::move(m_pCursorStack->pNext);
518 if( nullptr == m_pCursorStack )
520 m_ePageMove = MV_NO;
521 m_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 while(m_pCursorStack)
532 m_pCursorStack = std::move(m_pCursorStack->pNext);
533 m_ePageMove = MV_NO;
534 m_bDestOnStack = false;
537 if no stack exists --> cancel selection
538 if stack && change of direction
539 --> pop cursor and return
540 else
541 --> push cursor
542 transpose cursor
545 bool SwWrtShell::PageCursor(SwTwips lOffset, bool bSelect)
547 // Do nothing if an offset of 0 was indicated
548 if(!lOffset) return false;
549 // Was once used to force a reformat of the layout.
550 // This has not work that way, because the cursor was not set
551 // because this does not happen within a
552 // Start-/EndActionParentheses.
553 // Because only SwViewShell::EndAction() is called at the end,
554 // no updating of the display of the cursor position takes place.
555 // The CursorShell-Actionparentheses cannot be used, because it
556 // always leads to displaying the cursor, thus also,
557 // if after the scroll scrolled in a region without a valid position.
558 // SwViewShell::StartAction();
559 PageMove eDir = lOffset > 0? MV_PAGE_DOWN: MV_PAGE_UP;
560 // Change of direction and stack present
561 if( eDir != m_ePageMove && m_ePageMove != MV_NO && PopCursor( true, bSelect ))
562 return true;
564 const bool bRet = PushCursor(lOffset, bSelect);
565 m_ePageMove = eDir;
566 return bRet;
569 bool SwWrtShell::GotoPage(sal_uInt16 nPage, bool bRecord)
571 ShellMoveCursor aTmp( this, false);
572 if( SwCursorShell::GotoPage(nPage) && bRecord)
574 if(IsSelFrameMode())
576 UnSelectFrame();
577 LeaveSelFrameMode();
579 return true;
581 return false;
584 bool SwWrtShell::GotoMark( const ::sw::mark::IMark* const pMark, bool bSelect )
586 ShellMoveCursor aTmp( this, bSelect );
587 SwPosition aPos = *GetCursor()->GetPoint();
588 bool bRet = SwCursorShell::GotoMark( pMark, true/*bStart*/ );
589 if (bRet)
590 m_aNavigationMgr.addEntry(aPos);
591 return bRet;
594 bool SwWrtShell::GotoFly( const OUString& rName, FlyCntType eType, bool bSelFrame )
596 SwPosition aPos = *GetCursor()->GetPoint();
597 bool bRet = SwFEShell::GotoFly(rName, eType, bSelFrame);
598 if (bRet)
599 m_aNavigationMgr.addEntry(aPos);
600 return bRet;
603 bool SwWrtShell::GotoINetAttr( const SwTextINetFormat& rAttr )
605 SwPosition aPos = *GetCursor()->GetPoint();
606 bool bRet = SwCursorShell::GotoINetAttr(rAttr);
607 if (bRet)
608 m_aNavigationMgr.addEntry(aPos);
609 return bRet;
612 void SwWrtShell::GotoOutline( SwOutlineNodes::size_type nIdx )
614 addCurrentPosition();
615 SwCursorShell::GotoOutline (nIdx);
618 bool SwWrtShell::GotoOutline( const OUString& rName )
620 SwPosition aPos = *GetCursor()->GetPoint();
621 bool bRet = SwCursorShell::GotoOutline (rName);
622 if (bRet)
623 m_aNavigationMgr.addEntry(aPos);
624 return bRet;
627 bool SwWrtShell::GotoRegion( const OUString& rName )
629 SwPosition aPos = *GetCursor()->GetPoint();
630 bool bRet = SwCursorShell::GotoRegion (rName);
631 if (bRet)
632 m_aNavigationMgr.addEntry(aPos);
633 return bRet;
636 bool SwWrtShell::GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType,
637 sal_uInt16 nSeqNo )
639 SwPosition aPos = *GetCursor()->GetPoint();
640 bool bRet = SwCursorShell::GotoRefMark(rRefMark, nSubType, nSeqNo);
641 if (bRet)
642 m_aNavigationMgr.addEntry(aPos);
643 return bRet;
646 bool SwWrtShell::GotoNextTOXBase( const OUString* pName )
648 SwPosition aPos = *GetCursor()->GetPoint();
649 bool bRet = SwCursorShell::GotoNextTOXBase(pName);
650 if (bRet)
651 m_aNavigationMgr.addEntry(aPos);
652 return bRet;
655 bool SwWrtShell::GotoTable( const OUString& rName )
657 SwPosition aPos = *GetCursor()->GetPoint();
658 bool bRet = SwCursorShell::GotoTable(rName);
659 if (bRet)
660 m_aNavigationMgr.addEntry(aPos);
661 return bRet;
664 void SwWrtShell::GotoFormatField( const SwFormatField& rField ) {
665 SwPosition aPos = *GetCursor()->GetPoint();
666 bool bRet = SwCursorShell::GotoFormatField(rField);
667 if (bRet)
668 m_aNavigationMgr.addEntry(aPos);
671 const SwRangeRedline* SwWrtShell::GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect ) {
672 SwPosition aPos = *GetCursor()->GetPoint();
673 const SwRangeRedline *pRedline = SwCursorShell::GotoRedline(nArrPos, bSelect);
674 if (pRedline)
675 m_aNavigationMgr.addEntry(aPos);
676 return pRedline;
679 bool SwWrtShell::SelectTextAttr( sal_uInt16 nWhich, const SwTextAttr* pAttr )
681 bool bRet;
683 SwMvContext aMvContext(this);
684 SttSelect();
685 bRet = SwCursorShell::SelectTextAttr( nWhich, false, pAttr );
687 EndSelect();
688 return bRet;
691 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */