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 <com/sun/star/util/SearchOptions.hpp>
21 #include <com/sun/star/text/XTextRange.hpp>
22 #include <hintids.hxx>
23 #include <svx/svdmodel.hxx>
24 #include <editeng/frmdiritem.hxx>
26 #include <SwSmartTagMgr.hxx>
28 #include <rootfrm.hxx>
29 #include <pagefrm.hxx>
31 #include <viewimp.hxx>
33 #include <swselectionlist.hxx>
34 #include <IBlockCursor.hxx>
35 #include "BlockCursor.hxx"
39 #include <viewopt.hxx>
40 #include <frmtool.hxx>
44 #include <sectfrm.hxx>
45 #include <swtable.hxx>
48 #include <section.hxx>
50 #include <scriptinfo.hxx>
51 #include <globdoc.hxx>
54 #include <fmteiro.hxx>
56 #include <unotextrange.hxx>
57 #include <vcl/svapp.hxx>
58 #include <numrule.hxx>
59 #include <IGrammarContact.hxx>
61 #include <globals.hrc>
63 #include <comcore.hrc>
65 using namespace com::sun::star
;
68 TYPEINIT2(SwCrsrShell
,ViewShell
,SwModify
);
72 * Delete all overlapping Cursors from a Cursor ring.
73 * @param pointer to SwCursor (ring)
75 void CheckRange( SwCursor
* );
79 * Check if pCurCrsr points into already existing ranges and delete those.
80 * @param Pointer to SwCursor object
82 void CheckRange( SwCursor
* pCurCrsr
)
84 const SwPosition
*pStt
= pCurCrsr
->Start(),
85 *pEnd
= pCurCrsr
->GetPoint() == pStt
? pCurCrsr
->GetMark() : pCurCrsr
->GetPoint();
88 *pTmp
= (SwPaM
*)pCurCrsr
->GetNext();
90 // Search the complete ring
91 while( pTmp
!= pCurCrsr
)
93 const SwPosition
*pTmpStt
= pTmp
->Start(),
94 *pTmpEnd
= pTmp
->GetPoint() == pTmpStt
?
95 pTmp
->GetMark() : pTmp
->GetPoint();
96 if( *pStt
<= *pTmpStt
)
98 if( *pEnd
> *pTmpStt
||
99 ( *pEnd
== *pTmpStt
&& *pEnd
== *pTmpEnd
))
103 if( *pStt
< *pTmpEnd
)
106 // If Point or Mark is within the Crsr range, we need to remove the old
107 // range. Take note that Point does not belong to the range anymore.
108 pTmp
= (SwPaM
*)pTmp
->GetNext();
109 delete pTmpDel
; // Remove old range
121 SwPaM
* SwCrsrShell::CreateCrsr()
123 // don't create Crsr in a table Selection (sic!)
124 OSL_ENSURE( !IsTableMode(), "in table Selection" );
126 // New cursor as copy of current one. Add to the ring.
127 // Links point to previously created one, ie forward.
128 SwShellCrsr
* pNew
= new SwShellCrsr( *pCurCrsr
);
130 // Hide PaM logically, to avoid undoing the inverting from
131 // copied PaM (#i75172#)
132 pNew
->swapContent(*pCurCrsr
);
134 pCurCrsr
->DeleteMark();
136 UpdateCrsr( SwCrsrShell::SCROLLWIN
);
142 * Delete current Cursor, making the following one the current.
143 * Note, this function does not delete anything if there is no other cursor.
144 * @return - returns true if there was another cursor and we deleted one.
146 bool SwCrsrShell::DestroyCrsr()
148 // don't delete Crsr within table selection
149 OSL_ENSURE( !IsTableMode(), "in table Selection" );
151 // Is there a next one? Don't do anything if not.
152 if(pCurCrsr
->GetNext() == pCurCrsr
)
155 SwCallLink
aLk( *this ); // watch Crsr-Moves
156 SwCursor
* pNextCrsr
= (SwCursor
*)pCurCrsr
->GetNext();
158 pCurCrsr
= dynamic_cast<SwShellCrsr
*>(pNextCrsr
);
165 * Create and return a new shell cursor.
166 * Simply returns the current shell cursor if there is no selection
169 SwPaM
& SwCrsrShell::CreateNewShellCursor()
173 (void) CreateCrsr(); // n.b. returns old cursor
179 * Return the current shell cursor
180 * @return - returns current `SwPaM` shell cursor
182 SwPaM
& SwCrsrShell::GetCurrentShellCursor()
188 * Return pointer to the current shell cursor
189 * @return - returns pointer to current `SwPaM` shell cursor
191 SwPaM
* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr
) const
195 if( bMakeTblCrsr
&& pTblCrsr
->IsCrsrMovedUpdt() )
197 //don't re-create 'parked' cursors
198 const SwCntntNode
* pCNd
;
199 if( pTblCrsr
->GetPoint()->nNode
.GetIndex() &&
200 pTblCrsr
->GetMark()->nNode
.GetIndex() &&
201 0 != ( pCNd
= pTblCrsr
->GetCntntNode() ) && pCNd
->getLayoutFrm( GetLayout() ) &&
202 0 != ( pCNd
= pTblCrsr
->GetCntntNode(sal_False
) ) && pCNd
->getLayoutFrm( GetLayout() ) )
204 SwShellTableCrsr
* pTC
= (SwShellTableCrsr
*)pTblCrsr
;
205 GetLayout()->MakeTblCrsrs( *pTC
);
209 if( pTblCrsr
->IsChgd() )
211 const_cast<SwCrsrShell
*>(this)->pCurCrsr
=
212 dynamic_cast<SwShellCrsr
*>(pTblCrsr
->MakeBoxSels( pCurCrsr
));
219 void SwCrsrShell::StartAction()
223 // save for update of the ribbon bar
224 const SwNode
& rNd
= pCurCrsr
->GetPoint()->nNode
.GetNode();
225 nAktNode
= rNd
.GetIndex();
226 nAktCntnt
= pCurCrsr
->GetPoint()->nContent
.GetIndex();
227 nAktNdTyp
= rNd
.GetNodeType();
228 bAktSelection
= *pCurCrsr
->GetPoint() != *pCurCrsr
->GetMark();
229 if( rNd
.IsTxtNode() )
230 nLeftFrmPos
= SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode
&)rNd
, nAktCntnt
, sal_True
);
234 ViewShell::StartAction(); // to the ViewShell
238 void SwCrsrShell::EndAction( const sal_Bool bIdleEnd
)
240 sal_Bool bVis
= bSVCrsrVis
;
243 if( bIdleEnd
&& Imp()->GetRegion() )
248 // Update all invalid numberings before the last action
249 if( 1 == nStartAction
)
250 GetDoc()->UpdateNumRule();
252 // #i76923#: Don't show the cursor in the ViewShell::EndAction() - call.
253 // Only the UpdateCrsr shows the cursor.
254 sal_Bool bSavSVCrsrVis
= bSVCrsrVis
;
255 bSVCrsrVis
= sal_False
;
257 ViewShell::EndAction( bIdleEnd
); // have ViewShell go first
259 bSVCrsrVis
= bSavSVCrsrVis
;
263 if( bVis
) // display SV-Cursor again
266 // If there is still a ChgCall and just the "basic
267 // parenthiszing(?) (Basic-Klammerung)" exists, call it. This
268 // decouples the internal with the Basic-parenthising, the
269 // Shells are switched.
270 if( !BasicActionPend() )
272 // Within a Basic action, one needs to update the cursor,
273 // to e.g. create the table cursos. This is being done in
275 UpdateCrsr( SwCrsrShell::CHKRANGE
, bIdleEnd
);
278 // watch Crsr-Moves, call Link if needed, the DTOR is key here!
279 SwCallLink
aLk( *this, nAktNode
, nAktCntnt
, (sal_uInt8
)nAktNdTyp
,
280 nLeftFrmPos
, bAktSelection
);
283 if( bCallChgLnk
&& bChgCallFlag
&& aChgLnk
.IsSet() )
285 aChgLnk
.Call( this );
286 bChgCallFlag
= sal_False
; // reset flag
292 sal_uInt16 nParm
= SwCrsrShell::CHKRANGE
;
294 nParm
|= SwCrsrShell::SCROLLWIN
;
296 UpdateCrsr( nParm
, bIdleEnd
); // Show Cursor changes
299 SwCallLink
aLk( *this ); // watch Crsr-Moves
300 aLk
.nNode
= nAktNode
; // call Link if needed
301 aLk
.nNdTyp
= (sal_uInt8
)nAktNdTyp
;
302 aLk
.nCntnt
= nAktCntnt
;
303 aLk
.nLeftFrmPos
= nLeftFrmPos
;
306 ( 1 == nCrsrMove
&& bInCMvVisportChgd
) )
307 // display Cursor & Selektions again
308 ShowCrsrs( bSVCrsrVis
? sal_True
: sal_False
);
310 // call ChgCall if there is still one
311 if( bCallChgLnk
&& bChgCallFlag
&& aChgLnk
.IsSet() )
313 aChgLnk
.Call( this );
314 bChgCallFlag
= sal_False
; // reset flag
321 void SwCrsrShell::SttCrsrMove()
323 OSL_ENSURE( nCrsrMove
< USHRT_MAX
, "To many nested CrsrMoves." );
328 void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd
)
330 OSL_ENSURE( nCrsrMove
, "EndCrsrMove() without SttCrsrMove()." );
331 EndAction( bIdleEnd
);
333 bInCMvVisportChgd
= sal_False
;
339 sal_Bool
SwCrsrShell::LeftRight( sal_Bool bLeft
, sal_uInt16 nCnt
, sal_uInt16 nMode
,
340 sal_Bool bVisualAllowed
)
343 return bLeft
? GoPrevCell() : GoNextCell();
345 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
346 sal_Bool bRet
= sal_False
;
348 // #i27615# Handle cursor in front of label.
349 const SwTxtNode
* pTxtNd
= 0;
352 pBlockCrsr
->clearPoints();
354 // 1. CASE: Cursor is in front of label. A move to the right
355 // will simply reset the bInFrontOfLabel flag:
356 SwShellCrsr
* pShellCrsr
= getShellCrsr( true );
357 if ( !bLeft
&& pShellCrsr
->IsInFrontOfLabel() )
359 SetInFrontOfLabel( false );
362 // 2. CASE: Cursor is at beginning of numbered paragraph. A move
363 // to the left will simply set the bInFrontOfLabel flag:
364 else if ( bLeft
&& 0 == pShellCrsr
->GetPoint()->nContent
.GetIndex() &&
365 !pShellCrsr
->IsInFrontOfLabel() && !pShellCrsr
->HasMark() &&
366 0 != ( pTxtNd
= pShellCrsr
->GetNode()->GetTxtNode() ) &&
367 pTxtNd
->HasVisibleNumberingOrBullet() )
369 SetInFrontOfLabel( true );
372 // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
375 const sal_Bool bSkipHidden
= !GetViewOptions()->IsShowHiddenChar();
377 // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
378 // reflected in the return value <bRet>.
379 const bool bResetOfInFrontOfLabel
= SetInFrontOfLabel( false );
380 bRet
= pShellCrsr
->LeftRight( bLeft
, nCnt
, nMode
, bVisualAllowed
,
381 bSkipHidden
, !IsOverwriteCrsr() );
382 if ( !bRet
&& bLeft
&& bResetOfInFrontOfLabel
)
384 // undo reset of <bInFrontOfLabel> flag
385 SetInFrontOfLabel( true );
396 void SwCrsrShell::MarkListLevel( const String
& sListId
,
397 const int nListLevel
)
399 if ( sListId
!= sMarkedListId
||
400 nListLevel
!= nMarkedListLevel
)
402 if ( sMarkedListId
.Len() > 0 )
403 pDoc
->MarkListLevel( sMarkedListId
, nMarkedListLevel
, false );
405 if ( sListId
.Len() > 0 )
407 pDoc
->MarkListLevel( sListId
, nListLevel
, true );
410 sMarkedListId
= sListId
;
411 nMarkedListLevel
= nListLevel
;
415 void SwCrsrShell::UpdateMarkedListLevel()
417 SwTxtNode
* pTxtNd
= _GetCrsr()->GetNode()->GetTxtNode();
421 if ( !pTxtNd
->IsNumbered() )
423 pCurCrsr
->_SetInFrontOfLabel( false );
424 MarkListLevel( String(), 0 );
426 else if ( pCurCrsr
->IsInFrontOfLabel() )
428 if ( pTxtNd
->IsInList() )
430 OSL_ENSURE( pTxtNd
->GetActualListLevel() >= 0 &&
431 pTxtNd
->GetActualListLevel() < MAXLEVEL
, "Which level?");
432 MarkListLevel( pTxtNd
->GetListId(),
433 pTxtNd
->GetActualListLevel() );
438 MarkListLevel( String(), 0 );
443 sal_Bool
SwCrsrShell::UpDown( sal_Bool bUp
, sal_uInt16 nCnt
)
445 SET_CURR_SHELL( this );
446 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
448 sal_Bool bTableMode
= IsTableMode();
449 SwShellCrsr
* pTmpCrsr
= getShellCrsr( true );
451 sal_Bool bRet
= pTmpCrsr
->UpDown( bUp
, nCnt
);
452 // #i40019# UpDown should always reset the bInFrontOfLabel flag:
453 bRet
= SetInFrontOfLabel(false) || bRet
;
456 pBlockCrsr
->clearPoints();
460 eMvState
= MV_UPDOWN
; // status for Crsr travelling - GetCrsrOfst
463 CrsrFlag eUpdtMode
= SwCrsrShell::SCROLLWIN
;
465 eUpdtMode
= (CrsrFlag
) (eUpdtMode
466 | SwCrsrShell::UPDOWN
| SwCrsrShell::CHKRANGE
);
467 UpdateCrsr( static_cast<sal_uInt16
>(eUpdtMode
) );
473 sal_Bool
SwCrsrShell::LRMargin( sal_Bool bLeft
, sal_Bool bAPI
)
475 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
476 SET_CURR_SHELL( this );
477 eMvState
= MV_LEFTMARGIN
; // status for Crsr travelling - GetCrsrOfst
479 const sal_Bool bTableMode
= IsTableMode();
480 SwShellCrsr
* pTmpCrsr
= getShellCrsr( true );
483 pBlockCrsr
->clearPoints();
485 const bool bWasAtLM
=
486 ( 0 == _GetCrsr()->GetPoint()->nContent
.GetIndex() );
488 sal_Bool bRet
= pTmpCrsr
->LeftRightMargin( bLeft
, bAPI
);
490 if ( bLeft
&& !bTableMode
&& bRet
&& bWasAtLM
&& !_GetCrsr()->HasMark() )
492 const SwTxtNode
* pTxtNd
= _GetCrsr()->GetNode()->GetTxtNode();
493 if ( pTxtNd
&& pTxtNd
->HasVisibleNumberingOrBullet() )
494 SetInFrontOfLabel( true );
498 bRet
= SetInFrontOfLabel( false ) || bRet
;
508 sal_Bool
SwCrsrShell::IsAtLRMargin( sal_Bool bLeft
, sal_Bool bAPI
) const
510 const SwShellCrsr
* pTmpCrsr
= getShellCrsr( true );
511 return pTmpCrsr
->IsAtLeftRightMargin( bLeft
, bAPI
);
515 sal_Bool
SwCrsrShell::SttEndDoc( sal_Bool bStt
)
517 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
519 SwShellCrsr
* pTmpCrsr
= pBlockCrsr
? &pBlockCrsr
->getShellCrsr() : pCurCrsr
;
520 sal_Bool bRet
= pTmpCrsr
->SttEndDoc( bStt
);
524 pTmpCrsr
->GetPtPos().Y() = 0; // set to 0 explicitly (table header)
527 pBlockCrsr
->clearPoints();
528 RefreshBlockCursor();
531 UpdateCrsr(SwCrsrShell::SCROLLWIN
|SwCrsrShell::CHKRANGE
|SwCrsrShell::READONLY
);
536 void SwCrsrShell::ExtendedSelectAll()
538 SwNodes
& rNodes
= GetDoc()->GetNodes();
539 SwPosition
* pPos
= pCurCrsr
->GetPoint();
540 pPos
->nNode
= rNodes
.GetEndOfPostIts();
541 pPos
->nContent
.Assign( rNodes
.GoNext( &pPos
->nNode
), 0 );
542 pPos
= pCurCrsr
->GetMark();
543 pPos
->nNode
= rNodes
.GetEndOfContent();
544 SwCntntNode
* pCNd
= rNodes
.GoPrevious( &pPos
->nNode
);
545 pPos
->nContent
.Assign( pCNd
, pCNd
? pCNd
->Len() : 0 );
548 sal_Bool
SwCrsrShell::MovePage( SwWhichPage fnWhichPage
, SwPosPage fnPosPage
)
550 sal_Bool bRet
= sal_False
;
552 // never jump of section borders at selection
553 if( !pCurCrsr
->HasMark() || !pCurCrsr
->IsNoCntnt() )
555 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
556 SET_CURR_SHELL( this );
558 SwCrsrSaveState
aSaveState( *pCurCrsr
);
559 Point
& rPt
= pCurCrsr
->GetPtPos();
560 SwCntntFrm
* pFrm
= pCurCrsr
->GetCntntNode()->
561 getLayoutFrm( GetLayout(), &rPt
, pCurCrsr
->GetPoint(), sal_False
);
562 if( pFrm
&& sal_True
== ( bRet
= GetFrmInPage( pFrm
, fnWhichPage
,
563 fnPosPage
, pCurCrsr
) ) &&
564 !pCurCrsr
->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
565 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
))
574 sal_Bool
SwCrsrShell::MovePara(SwWhichPara fnWhichPara
, SwPosPara fnPosPara
)
576 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
577 SwCursor
* pTmpCrsr
= getShellCrsr( true );
578 sal_Bool bRet
= pTmpCrsr
->MovePara( fnWhichPara
, fnPosPara
);
585 sal_Bool
SwCrsrShell::MoveSection( SwWhichSection fnWhichSect
,
586 SwPosSection fnPosSect
)
588 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
589 SwCursor
* pTmpCrsr
= getShellCrsr( true );
590 sal_Bool bRet
= pTmpCrsr
->MoveSection( fnWhichSect
, fnPosSect
);
601 static SwFrm
* lcl_IsInHeaderFooter( const SwNodeIndex
& rIdx
, Point
& rPt
)
604 SwCntntNode
* pCNd
= rIdx
.GetNode().GetCntntNode();
607 SwCntntFrm
*pCntFrm
= pCNd
->getLayoutFrm( pCNd
->GetDoc()->GetCurrentLayout(), &rPt
, 0, sal_False
);
608 pFrm
= pCntFrm
? pCntFrm
->GetUpper() : NULL
;
609 while( pFrm
&& !pFrm
->IsHeaderFrm() && !pFrm
->IsFooterFrm() )
610 pFrm
= pFrm
->IsFlyFrm() ? ((SwFlyFrm
*)pFrm
)->AnchorFrm()
616 bool SwCrsrShell::IsInHeaderFooter( sal_Bool
* pbInHeader
) const
619 SwFrm
* pFrm
= ::lcl_IsInHeaderFooter( pCurCrsr
->GetPoint()->nNode
, aPt
);
620 if( pFrm
&& pbInHeader
)
621 *pbInHeader
= pFrm
->IsHeaderFrm();
625 int SwCrsrShell::SetCrsr( const Point
&rLPt
, sal_Bool bOnlyText
, bool bBlock
)
627 SET_CURR_SHELL( this );
629 SwShellCrsr
* pCrsr
= getShellCrsr( bBlock
);
630 SwPosition
aPos( *pCrsr
->GetPoint() );
632 Point
& rAktCrsrPt
= pCrsr
->GetPtPos();
633 SwCrsrMoveState
aTmpState( IsTableMode() ? MV_TBLSEL
:
634 bOnlyText
? MV_SETONLYTEXT
: MV_NONE
);
635 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
637 SwTxtNode
* pTxtNd
= pCrsr
->GetNode()->GetTxtNode();
639 if ( pTxtNd
&& !IsTableMode() &&
640 // #i37515# No bInFrontOfLabel during selection
642 pTxtNd
->HasVisibleNumberingOrBullet() )
644 aTmpState
.bInFrontOfLabel
= sal_True
; // #i27615#
648 aTmpState
.bInFrontOfLabel
= sal_False
;
651 int bRet
= CRSR_POSOLD
|
652 ( GetLayout()->GetCrsrOfst( &aPos
, aPt
, &aTmpState
)
655 const bool bOldInFrontOfLabel
= IsInFrontOfLabel();
656 const bool bNewInFrontOfLabel
= aTmpState
.bInFrontOfLabel
;
658 pCrsr
->SetCrsrBidiLevel( aTmpState
.nCursorBidiLevel
);
660 if( MV_RIGHTMARGIN
== aTmpState
.eState
)
661 eMvState
= MV_RIGHTMARGIN
;
662 // is the new position in header or footer?
663 SwFrm
* pFrm
= lcl_IsInHeaderFooter( aPos
.nNode
, aPt
);
664 if( IsTableMode() && !pFrm
&& aPos
.nNode
.GetNode().StartOfSectionNode() ==
665 pCrsr
->GetPoint()->nNode
.GetNode().StartOfSectionNode() )
666 // same table column and not in header/footer -> back
669 if( pBlockCrsr
&& bBlock
)
671 pBlockCrsr
->setEndPoint( rLPt
);
672 if( !pCrsr
->HasMark() )
673 pBlockCrsr
->setStartPoint( rLPt
);
674 else if( !pBlockCrsr
->getStartPoint() )
675 pBlockCrsr
->setStartPoint( pCrsr
->GetMkPos() );
677 if( !pCrsr
->HasMark() )
679 // is at the same position and if in header/footer -> in the same
680 if( aPos
== *pCrsr
->GetPoint() &&
681 bOldInFrontOfLabel
== bNewInFrontOfLabel
)
685 if( pFrm
->Frm().IsInside( rAktCrsrPt
))
688 else if( aPos
.nNode
.GetNode().IsCntntNode() )
690 // in the same frame?
691 SwFrm
* pOld
= ((SwCntntNode
&)aPos
.nNode
.GetNode()).getLayoutFrm(
692 GetLayout(), &aCharRect
.Pos(), 0, sal_False
);
693 SwFrm
* pNew
= ((SwCntntNode
&)aPos
.nNode
.GetNode()).getLayoutFrm(
694 GetLayout(), &aPt
, 0, sal_False
);
702 // SSelection over not allowed sections or if in header/footer -> different
703 if( !CheckNodesRange( aPos
.nNode
, pCrsr
->GetMark()->nNode
, sal_True
)
704 || ( pFrm
&& !pFrm
->Frm().IsInside( pCrsr
->GetMkPos() ) ))
707 // is at same position but not in header/footer
708 if( aPos
== *pCrsr
->GetPoint() )
712 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
713 SwCrsrSaveState
aSaveState( *pCrsr
);
715 *pCrsr
->GetPoint() = aPos
;
718 // #i41424# Only update the marked number levels if necessary
719 // Force update of marked number levels if necessary.
720 if ( bNewInFrontOfLabel
|| bOldInFrontOfLabel
)
721 pCurCrsr
->_SetInFrontOfLabel( !bNewInFrontOfLabel
);
722 SetInFrontOfLabel( bNewInFrontOfLabel
);
724 if( !pCrsr
->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
) )
726 sal_uInt16 nFlag
= SwCrsrShell::SCROLLWIN
| SwCrsrShell::CHKRANGE
;
728 bRet
&= ~CRSR_POSOLD
;
730 else if( bOnlyText
&& !pCurCrsr
->HasMark() )
732 if( FindValidCntntNode( bOnlyText
) )
734 // position cursor in a valid content
735 if( aPos
== *pCrsr
->GetPoint() )
739 UpdateCrsr( SwCrsrShell::SCROLLWIN
| SwCrsrShell::CHKRANGE
);
740 bRet
&= ~CRSR_POSOLD
;
745 // there is no valid content -> hide cursor
746 pVisCrsr
->Hide(); // always hide visible cursor
747 eMvState
= MV_NONE
; // status for Crsr travelling
748 bAllProtect
= sal_True
;
749 if( GetDoc()->GetDocShell() )
751 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True
);
752 CallChgLnk(); // notify UI
761 void SwCrsrShell::TblCrsrToCursor()
763 OSL_ENSURE( pTblCrsr
, "TblCrsrToCursor: Why?" );
764 delete pTblCrsr
, pTblCrsr
= 0;
767 void SwCrsrShell::BlockCrsrToCrsr()
769 OSL_ENSURE( pBlockCrsr
, "BlockCrsrToCrsr: Why?" );
770 if( pBlockCrsr
&& !HasSelection() )
772 SwPaM
& rPam
= pBlockCrsr
->getShellCrsr();
774 *pCurCrsr
->GetPoint() = *rPam
.GetPoint();
776 *pCurCrsr
->GetMark() = *rPam
.GetMark();
778 pCurCrsr
->DeleteMark();
780 delete pBlockCrsr
, pBlockCrsr
= 0;
783 void SwCrsrShell::CrsrToBlockCrsr()
787 SwPosition
aPos( *pCurCrsr
->GetPoint() );
788 pBlockCrsr
= createBlockCursor( *this, aPos
);
789 SwShellCrsr
&rBlock
= pBlockCrsr
->getShellCrsr();
790 rBlock
.GetPtPos() = pCurCrsr
->GetPtPos();
791 if( pCurCrsr
->HasMark() )
794 *rBlock
.GetMark() = *pCurCrsr
->GetMark();
795 rBlock
.GetMkPos() = pCurCrsr
->GetMkPos();
798 pBlockCrsr
->clearPoints();
799 RefreshBlockCursor();
802 void SwCrsrShell::ClearMark()
804 // is there any GetMark?
807 while( pCurCrsr
->GetNext() != pCurCrsr
)
808 delete pCurCrsr
->GetNext();
809 pTblCrsr
->DeleteMark();
811 if( pCurCrsr
->HasMark() )
813 // move content part from mark to nodes array if not all indices
814 // were moved correctly (e.g. when deleting header/footer)
815 SwPosition
& rPos
= *pCurCrsr
->GetMark();
816 rPos
.nNode
.Assign( pDoc
->GetNodes(), 0 );
817 rPos
.nContent
.Assign( 0, 0 );
818 pCurCrsr
->DeleteMark();
821 *pCurCrsr
->GetPoint() = *pTblCrsr
->GetPoint();
822 pCurCrsr
->GetPtPos() = pTblCrsr
->GetPtPos();
823 delete pTblCrsr
, pTblCrsr
= 0;
824 pCurCrsr
->SwSelPaintRects::Show();
828 if( !pCurCrsr
->HasMark() )
830 // move content part from mark to nodes array if not all indices
831 // were moved correctly (e.g. when deleting header/footer)
832 SwPosition
& rPos
= *pCurCrsr
->GetMark();
833 rPos
.nNode
.Assign( pDoc
->GetNodes(), 0 );
834 rPos
.nContent
.Assign( 0, 0 );
835 pCurCrsr
->DeleteMark();
837 pCurCrsr
->SwSelPaintRects::Show();
842 void SwCrsrShell::NormalizePam(sal_Bool bPointFirst
)
844 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
845 pCurCrsr
->Normalize(bPointFirst
);
848 void SwCrsrShell::SwapPam()
850 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
851 pCurCrsr
->Exchange();
854 //TODO: provide documentation
855 /** Search in the selected area for a Selection that covers the given point.
857 If only a test run is made, then it checks if a SSelection exists but does
858 not move the current cursor. In a normal run the cursor will be moved to the
861 @param rPt The point to search at.
862 @param bTstOnly Should I only do a test run? If true so do not move cursor.
865 sal_Bool
SwCrsrShell::ChgCurrPam( const Point
& rPt
,
866 sal_Bool bTstOnly
, sal_Bool bTstHit
)
868 SET_CURR_SHELL( this );
870 // check if the SPoint is in a table selection
871 if( bTstOnly
&& pTblCrsr
)
872 return pTblCrsr
->IsInside( rPt
);
874 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
875 // search position <rPt> in document
876 SwPosition
aPtPos( *pCurCrsr
->GetPoint() );
879 SwCrsrMoveState
aTmpState( MV_NONE
);
880 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
881 if ( !GetLayout()->GetCrsrOfst( &aPtPos
, aPt
, &aTmpState
) && bTstHit
)
884 // search in all selections for this position
885 SwShellCrsr
* pCmp
= (SwShellCrsr
*)pCurCrsr
; // keep the pointer on cursor
887 if( pCmp
->HasMark() &&
888 *pCmp
->Start() <= aPtPos
&& *pCmp
->End() > aPtPos
)
890 if( bTstOnly
|| pCurCrsr
== pCmp
) // is the current
891 return sal_True
; // return without update
894 UpdateCrsr(); // cursor is already at the right position
898 ( pCmp
= dynamic_cast<SwShellCrsr
*>(pCmp
->GetNext()) ) );
903 void SwCrsrShell::KillPams()
905 // Does any exist for deletion?
906 if( !pTblCrsr
&& !pBlockCrsr
&& pCurCrsr
->GetNext() == pCurCrsr
)
909 while( pCurCrsr
->GetNext() != pCurCrsr
)
910 delete pCurCrsr
->GetNext();
911 pCurCrsr
->SetColumnSelection( false );
915 // delete the ring of cursors
916 pCurCrsr
->DeleteMark();
917 *pCurCrsr
->GetPoint() = *pTblCrsr
->GetPoint();
918 pCurCrsr
->GetPtPos() = pTblCrsr
->GetPtPos();
922 else if( pBlockCrsr
)
924 // delete the ring of cursors
925 pCurCrsr
->DeleteMark();
926 SwShellCrsr
&rBlock
= pBlockCrsr
->getShellCrsr();
927 *pCurCrsr
->GetPoint() = *rBlock
.GetPoint();
928 pCurCrsr
->GetPtPos() = rBlock
.GetPtPos();
930 pBlockCrsr
->clearPoints();
932 UpdateCrsr( SwCrsrShell::SCROLLWIN
);
936 int SwCrsrShell::CompareCursor( CrsrCompareType eType
) const
939 const SwPosition
*pFirst
= 0, *pSecond
= 0;
940 const SwPaM
*pCur
= GetCrsr(), *pStk
= pCrsrStk
;
941 if( CurrPtCurrMk
!= eType
&& pStk
)
946 pFirst
= pStk
->GetPoint();
947 pSecond
= pStk
->GetMark();
950 pFirst
= pStk
->GetPoint();
951 pSecond
= pCur
->GetPoint();
954 pFirst
= pStk
->GetPoint();
955 pSecond
= pCur
->GetMark();
958 pFirst
= pStk
->GetMark();
959 pSecond
= pCur
->GetPoint();
962 pFirst
= pStk
->GetMark();
963 pSecond
= pStk
->GetMark();
966 pFirst
= pCur
->GetPoint();
967 pSecond
= pCur
->GetMark();
971 if( !pFirst
|| !pSecond
)
973 else if( *pFirst
< *pSecond
)
975 else if( *pFirst
== *pSecond
)
983 bool SwCrsrShell::IsSttPara() const
984 { return pCurCrsr
->GetPoint()->nContent
== 0; }
987 bool SwCrsrShell::IsEndPara() const
988 { return pCurCrsr
->GetPoint()->nContent
== pCurCrsr
->GetCntntNode()->Len(); }
991 bool SwCrsrShell::IsInFrontOfLabel() const
993 return pCurCrsr
->IsInFrontOfLabel();
996 bool SwCrsrShell::SetInFrontOfLabel( bool bNew
)
998 if ( bNew
!= IsInFrontOfLabel() )
1000 pCurCrsr
->_SetInFrontOfLabel( bNew
);
1001 UpdateMarkedListLevel();
1007 sal_Bool
SwCrsrShell::GotoPage( sal_uInt16 nPage
)
1009 SET_CURR_SHELL( this );
1010 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
1011 SwCrsrSaveState
aSaveState( *pCurCrsr
);
1012 sal_Bool bRet
= GetLayout()->SetCurrPage( pCurCrsr
, nPage
) &&
1013 !pCurCrsr
->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
1014 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
);
1016 UpdateCrsr(SwCrsrShell::SCROLLWIN
|SwCrsrShell::CHKRANGE
|SwCrsrShell::READONLY
);
1021 void SwCrsrShell::GetPageNum( sal_uInt16
&rnPhyNum
, sal_uInt16
&rnVirtNum
,
1022 sal_Bool bAtCrsrPos
, const sal_Bool bCalcFrm
)
1024 SET_CURR_SHELL( this );
1025 // page number: first visible page or the one at the cursor
1026 const SwCntntFrm
* pCFrm
;
1027 const SwPageFrm
*pPg
= 0;
1029 if( !bAtCrsrPos
|| 0 == (pCFrm
= GetCurrFrm( bCalcFrm
)) ||
1030 0 == (pPg
= pCFrm
->FindPageFrm()) )
1032 pPg
= Imp()->GetFirstVisPage();
1033 while( pPg
&& pPg
->IsEmptyPage() )
1034 pPg
= (const SwPageFrm
*)pPg
->GetNext();
1036 // pPg has to exist with a default of 1 for the special case "Writerstart"
1037 rnPhyNum
= pPg
? pPg
->GetPhyPageNum() : 1;
1038 rnVirtNum
= pPg
? pPg
->GetVirtPageNum() : 1;
1042 sal_uInt16
SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext
)
1044 SET_CURR_SHELL( this );
1046 // page number: first visible page or the one at the cursor
1047 const SwPageFrm
*pPg
= Imp()->GetFirstVisPage();
1050 const SwTwips nPageTop
= pPg
->Frm().Top();
1054 // go to next view layout row:
1057 pPg
= (const SwPageFrm
*)pPg
->GetNext();
1059 while( pPg
&& pPg
->Frm().Top() == nPageTop
);
1061 while( pPg
&& pPg
->IsEmptyPage() )
1062 pPg
= (const SwPageFrm
*)pPg
->GetNext();
1066 // go to previous view layout row:
1069 pPg
= (const SwPageFrm
*)pPg
->GetPrev();
1071 while( pPg
&& pPg
->Frm().Top() == nPageTop
);
1073 while( pPg
&& pPg
->IsEmptyPage() )
1074 pPg
= (const SwPageFrm
*)pPg
->GetPrev();
1077 // pPg has to exist with a default of 1 for the special case "Writerstart"
1078 return pPg
? pPg
->GetPhyPageNum() : USHRT_MAX
;
1082 sal_uInt16
SwCrsrShell::GetPageCnt()
1084 SET_CURR_SHELL( this );
1085 // return number of pages
1086 return GetLayout()->GetPageNum();
1089 /// go to the next SSelection
1090 sal_Bool
SwCrsrShell::GoNextCrsr()
1092 // is there a ring of cursors?
1093 if( pCurCrsr
->GetNext() == pCurCrsr
)
1096 SET_CURR_SHELL( this );
1097 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
1098 pCurCrsr
= dynamic_cast<SwShellCrsr
*>(pCurCrsr
->GetNext());
1100 // #i24086#: show also all others
1109 /// go to the previous SSelection
1110 sal_Bool
SwCrsrShell::GoPrevCrsr()
1112 // is there a ring of cursors?
1113 if( pCurCrsr
->GetNext() == pCurCrsr
)
1116 SET_CURR_SHELL( this );
1117 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
1118 pCurCrsr
= dynamic_cast<SwShellCrsr
*>(pCurCrsr
->GetPrev());
1120 // #i24086#: show also all others
1131 void SwCrsrShell::Paint( const Rectangle
&rRect
)
1133 SET_CURR_SHELL( this );
1135 // always switch off all cursors when painting
1136 SwRect
aRect( rRect
);
1139 // if a cursor is visible then hide the SV cursor
1140 if( pVisCrsr
->IsVisible() && !aRect
.IsOver( aCharRect
) )
1147 ViewShell::Paint( rRect
);
1149 if( bHasFocus
&& !bBasicHideCrsr
)
1151 SwShellCrsr
* pAktCrsr
= pTblCrsr
? pTblCrsr
: pCurCrsr
;
1155 // so that right/bottom borders will not be cropped
1156 pAktCrsr
->Invalidate( VisArea() );
1160 pAktCrsr
->Invalidate( aRect
);
1163 if( bSVCrsrVis
&& bVis
) // also show SV cursor again
1169 void SwCrsrShell::VisPortChgd( const SwRect
& rRect
)
1171 SET_CURR_SHELL( this );
1172 bool bVis
; // switch off all cursors when scrolling
1174 // if a cursor is visible then hide the SV cursor
1175 if( ( bVis
= pVisCrsr
->IsVisible() ) )
1178 bVisPortChgd
= sal_True
;
1179 aOldRBPos
.X() = VisArea().Right();
1180 aOldRBPos
.Y() = VisArea().Bottom();
1182 // For not having problems with the SV cursor, Update() is called for the
1183 // Window in ViewShell::VisPo...
1184 // During painting no selections should be shown, thus the call is encapsulated. <- TODO: old artefact?
1185 ViewShell::VisPortChgd( rRect
); // move area
1187 if( bSVCrsrVis
&& bVis
) // show SV cursor again
1191 bInCMvVisportChgd
= sal_True
;
1193 bVisPortChgd
= sal_False
;
1196 /** Set the cursor back into content.
1198 This should only be called if the cursor was move somewhere else (e.g. when
1199 deleting a border). The new position is calculated from its current position
1202 void SwCrsrShell::UpdateCrsrPos()
1204 SET_CURR_SHELL( this );
1206 SwShellCrsr
* pShellCrsr
= getShellCrsr( true );
1207 Size
aOldSz( GetDocSize() );
1208 SwCntntNode
*pCNode
= pShellCrsr
->GetCntntNode();
1209 SwCntntFrm
*pFrm
= pCNode
?
1210 pCNode
->getLayoutFrm( GetLayout(), &pShellCrsr
->GetPtPos(), pShellCrsr
->GetPoint(), sal_False
) :0;
1211 if( !pFrm
|| (pFrm
->IsTxtFrm() && ((SwTxtFrm
*)pFrm
)->IsHiddenNow()) )
1213 SwCrsrMoveState
aTmpState( MV_NONE
);
1214 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
1215 GetLayout()->GetCrsrOfst( pShellCrsr
->GetPoint(), pShellCrsr
->GetPtPos(),
1217 if( pShellCrsr
->HasMark())
1218 pShellCrsr
->DeleteMark();
1220 IGrammarContact
*pGrammarContact
= GetDoc() ? GetDoc()->getGrammarContact() : 0;
1221 if( pGrammarContact
)
1222 pGrammarContact
->updateCursorPosition( *pCurCrsr
->GetPoint() );
1224 if( aOldSz
!= GetDocSize() )
1228 // #i65475# - if Point/Mark in hidden sections, move them out
1229 static void lcl_CheckHiddenSection( SwNodeIndex
& rIdx
)
1231 const SwSectionNode
* pSectNd
= rIdx
.GetNode().FindSectionNode();
1232 if( pSectNd
&& pSectNd
->GetSection().IsHiddenFlag() )
1234 SwNodeIndex
aTmp( *pSectNd
);
1235 const SwNode
* pFrmNd
=
1236 rIdx
.GetNodes().FindPrvNxtFrmNode( aTmp
, pSectNd
->EndOfSectionNode() );
1237 SAL_WARN_IF( !pFrmNd
, "sw", "found no Node with Frames" );
1242 /// Try to set the cursor to the next visible content node.
1243 static void lcl_CheckHiddenPara( SwPosition
& rPos
)
1245 SwNodeIndex
aTmp( rPos
.nNode
);
1246 SwTxtNode
* pTxtNd
= aTmp
.GetNode().GetTxtNode();
1247 while( pTxtNd
&& pTxtNd
->HasHiddenCharAttribute( true ) )
1249 SwCntntNode
* pCntnt
= aTmp
.GetNodes().GoNext( &aTmp
);
1250 if ( pCntnt
&& pCntnt
->IsTxtNode() )
1251 pTxtNd
= (SwTxtNode
*)pCntnt
;
1257 rPos
= SwPosition( aTmp
, SwIndex( pTxtNd
, 0 ) );
1260 // #i27301# - helper class that notifies the accessibility about invalid text
1261 // selections in its destructor
1262 class SwNotifyAccAboutInvalidTextSelections
1265 SwCrsrShell
& mrCrsrSh
;
1268 SwNotifyAccAboutInvalidTextSelections( SwCrsrShell
& _rCrsrSh
)
1269 : mrCrsrSh( _rCrsrSh
)
1272 ~SwNotifyAccAboutInvalidTextSelections()
1274 mrCrsrSh
.InvalidateAccessibleParaTextSelection();
1277 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags
, sal_Bool bIdleEnd
)
1279 SET_CURR_SHELL( this );
1283 // In a BasicAction the cursor must be updated, e.g. to create the
1284 // TableCursor. EndAction now calls UpdateCrsr!
1285 if( ActionPend() && BasicActionPend() )
1287 if ( eFlags
& SwCrsrShell::READONLY
)
1288 bIgnoreReadonly
= sal_True
;
1289 return; // if not then no update
1293 SwNotifyAccAboutInvalidTextSelections
aInvalidateTextSelections( *this );
1295 if ( bIgnoreReadonly
)
1297 bIgnoreReadonly
= sal_False
;
1298 eFlags
|= SwCrsrShell::READONLY
;
1301 if( eFlags
& SwCrsrShell::CHKRANGE
) // check all cursor moves for
1302 CheckRange( pCurCrsr
); // overlapping ranges
1307 // If the current cursor is in a table and point/mark in different boxes,
1308 // then the table mode is active (also if it is already active: pTblCrsr)
1309 SwPaM
* pTstCrsr
= getShellCrsr( true );
1310 if( pTstCrsr
->HasMark() && !pBlockCrsr
&&
1311 pDoc
->IsIdxInTbl( pTstCrsr
->GetPoint()->nNode
) &&
1313 pTstCrsr
->GetNode( sal_True
)->StartOfSectionNode() !=
1314 pTstCrsr
->GetNode( sal_False
)->StartOfSectionNode() ) )
1316 SwShellCrsr
* pITmpCrsr
= getShellCrsr( true );
1317 Point
aTmpPt( pITmpCrsr
->GetPtPos() );
1318 Point
aTmpMk( pITmpCrsr
->GetMkPos() );
1319 SwPosition
* pPos
= pITmpCrsr
->GetPoint();
1321 // Bug 65475 (1999) - if Point/Mark in hidden sections, move them out
1322 lcl_CheckHiddenSection( pPos
->nNode
);
1323 lcl_CheckHiddenSection( pITmpCrsr
->GetMark()->nNode
);
1325 // Move cursor out of hidden paragraphs
1326 if ( !GetViewOptions()->IsShowHiddenChar() )
1328 lcl_CheckHiddenPara( *pPos
);
1329 lcl_CheckHiddenPara( *pITmpCrsr
->GetMark() );
1332 SwCntntFrm
*pTblFrm
= pPos
->nNode
.GetNode().GetCntntNode()->
1333 getLayoutFrm( GetLayout(), &aTmpPt
, pPos
, sal_False
);
1335 OSL_ENSURE( pTblFrm
, "Tabelle Crsr nicht im Content ??" );
1337 // --> Make code robust. The table cursor may point
1338 // to a table in a currently inactive header.
1339 SwTabFrm
*pTab
= pTblFrm
? pTblFrm
->FindTabFrm() : 0;
1341 if ( pTab
&& pTab
->GetTable()->GetRowsToRepeat() > 0 )
1343 // First check if point is in repeated headline:
1344 bool bInRepeatedHeadline
= pTab
->IsFollow() && pTab
->IsInHeadline( *pTblFrm
);
1346 // Second check if mark is in repeated headline:
1347 if ( !bInRepeatedHeadline
)
1349 SwCntntFrm
* pMarkTblFrm
= pITmpCrsr
->GetCntntNode( sal_False
)->
1350 getLayoutFrm( GetLayout(), &aTmpMk
, pITmpCrsr
->GetMark(), sal_False
);
1351 OSL_ENSURE( pMarkTblFrm
, "Tabelle Crsr nicht im Content ??" );
1355 SwTabFrm
* pMarkTab
= pMarkTblFrm
->FindTabFrm();
1356 OSL_ENSURE( pMarkTab
, "Tabelle Crsr nicht im Content ??" );
1358 // Make code robust:
1361 bInRepeatedHeadline
= pMarkTab
->IsFollow() && pMarkTab
->IsInHeadline( *pMarkTblFrm
);
1366 // No table cursor in repeaded headlines:
1367 if ( bInRepeatedHeadline
)
1371 SwPosSection fnPosSect
= *pPos
< *pITmpCrsr
->GetMark()
1375 // then only select inside the Box
1378 pCurCrsr
->SetMark();
1379 *pCurCrsr
->GetMark() = *pTblCrsr
->GetMark();
1380 pCurCrsr
->GetMkPos() = pTblCrsr
->GetMkPos();
1381 pTblCrsr
->DeleteMark();
1382 pTblCrsr
->SwSelPaintRects::Hide();
1385 *pCurCrsr
->GetPoint() = *pCurCrsr
->GetMark();
1386 (*fnSectionCurr
)( *pCurCrsr
, fnPosSect
);
1390 // we really want a table selection
1391 if( pTab
&& pTblFrm
)
1395 pTblCrsr
= new SwShellTableCrsr( *this,
1396 *pCurCrsr
->GetMark(), pCurCrsr
->GetMkPos(),
1398 pCurCrsr
->DeleteMark();
1399 pCurCrsr
->SwSelPaintRects::Hide();
1404 SwCrsrMoveState
aTmpState( MV_NONE
);
1405 aTmpState
.bRealHeight
= sal_True
;
1406 if( !pTblFrm
->GetCharRect( aCharRect
, *pTblCrsr
->GetPoint(), &aTmpState
) )
1408 Point
aCentrPt( aCharRect
.Center() );
1409 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
1410 pTblFrm
->GetCrsrOfst( pTblCrsr
->GetPoint(), aCentrPt
, &aTmpState
);
1411 bool const bResult
=
1412 pTblFrm
->GetCharRect( aCharRect
, *pTblCrsr
->GetPoint() );
1413 OSL_ENSURE( bResult
, "GetCharRect failed." );
1414 (void) bResult
; // non-debug: unused
1417 pVisCrsr
->Hide(); // always hide visible Cursor
1418 // scroll Cursor to visible area
1419 if( (eFlags
& SwCrsrShell::SCROLLWIN
) &&
1420 (HasSelection() || eFlags
& SwCrsrShell::READONLY
||
1421 !IsCrsrReadonly()) )
1423 SwFrm
* pBoxFrm
= pTblFrm
;
1424 while( pBoxFrm
&& !pBoxFrm
->IsCellFrm() )
1425 pBoxFrm
= pBoxFrm
->GetUpper();
1426 if( pBoxFrm
&& pBoxFrm
->Frm().HasArea() )
1427 MakeVisible( pBoxFrm
->Frm() );
1429 MakeVisible( aCharRect
);
1432 // let Layout create the Cursors in the Boxes
1433 if( pTblCrsr
->IsCrsrMovedUpdt() )
1434 GetLayout()->MakeTblCrsrs( *pTblCrsr
);
1435 if( bHasFocus
&& !bBasicHideCrsr
)
1438 // set Cursor-Points to the new Positions
1439 pTblCrsr
->GetPtPos().X() = aCharRect
.Left();
1440 pTblCrsr
->GetPtPos().Y() = aCharRect
.Top();
1444 aCrsrHeight
.X() = 0;
1445 aCrsrHeight
.Y() = aTmpState
.aRealHeight
.Y() < 0 ?
1446 -aCharRect
.Width() : aCharRect
.Height();
1447 pVisCrsr
->Show(); // show again
1449 eMvState
= MV_NONE
; // state for cursor travelling - GetCrsrOfst
1450 if( pTblFrm
&& Imp()->IsAccessible() )
1451 Imp()->InvalidateAccessibleCursorPosition( pTblFrm
);
1459 while( pCurCrsr
->GetNext() != pCurCrsr
)
1460 delete pCurCrsr
->GetNext();
1461 pCurCrsr
->DeleteMark();
1462 *pCurCrsr
->GetPoint() = *pTblCrsr
->GetPoint();
1463 pCurCrsr
->GetPtPos() = pTblCrsr
->GetPtPos();
1464 delete pTblCrsr
, pTblCrsr
= 0;
1467 pVisCrsr
->Hide(); // always hide visible Cursor
1469 // are we perhaps in a protected / hidden Section ?
1471 SwShellCrsr
* pShellCrsr
= getShellCrsr( true );
1472 bool bChgState
= true;
1473 const SwSectionNode
* pSectNd
= pShellCrsr
->GetNode()->FindSectionNode();
1474 if( pSectNd
&& ( pSectNd
->GetSection().IsHiddenFlag() ||
1475 ( !IsReadOnlyAvailable() &&
1476 pSectNd
->GetSection().IsProtectFlag() &&
1477 ( !pDoc
->GetDocShell() ||
1478 !pDoc
->GetDocShell()->IsReadOnly() || bAllProtect
)) ) )
1480 if( !FindValidCntntNode( !HasDrawView() ||
1481 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1483 // everything protected/hidden -> special mode
1484 if( bAllProtect
&& !IsReadOnlyAvailable() &&
1485 pSectNd
->GetSection().IsProtectFlag() )
1489 eMvState
= MV_NONE
; // state for cursor travelling
1490 bAllProtect
= sal_True
;
1491 if( GetDoc()->GetDocShell() )
1493 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True
);
1494 CallChgLnk(); // notify UI!
1502 sal_Bool bWasAllProtect
= bAllProtect
;
1503 bAllProtect
= sal_False
;
1504 if( bWasAllProtect
&& GetDoc()->GetDocShell() &&
1505 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1507 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False
);
1508 CallChgLnk(); // notify UI!
1515 // The cursor must always point into content; there's some code
1516 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1517 // loops _behind_ the last node in the selection, which always works if you
1518 // are in content.) To achieve this, we'll force cursor(s) to point into
1519 // content, if UpdateCrsrPos() hasn't already done so.
1520 SwPaM
* pCmp
= pCurCrsr
;
1523 // start will move forwards, end will move backwards
1524 bool bPointIsStart
= ( pCmp
->Start() == pCmp
->GetPoint() );
1526 // move point; forward if it's the start, backwards if it's the end
1527 if( ! pCmp
->GetPoint()->nNode
.GetNode().IsCntntNode() )
1528 pCmp
->Move( bPointIsStart
? fnMoveForward
: fnMoveBackward
,
1531 // move mark (if exists); forward if it's the start, else backwards
1532 if( pCmp
->HasMark() )
1534 if( ! pCmp
->GetMark()->nNode
.GetNode().IsCntntNode() )
1537 pCmp
->Move( !bPointIsStart
? fnMoveForward
: fnMoveBackward
,
1543 // iterate to next PaM in ring
1544 pCmp
= static_cast<SwPaM
*>( pCmp
->GetNext() );
1546 while( pCmp
!= pCurCrsr
);
1549 SwRect
aOld( aCharRect
);
1553 SwShellCrsr
* pShellCrsr
= getShellCrsr( true );
1559 pFrm
= pShellCrsr
->GetCntntNode()->getLayoutFrm( GetLayout(),
1560 &pShellCrsr
->GetPtPos(), pShellCrsr
->GetPoint(), sal_False
);
1561 // if the Frm doesn't exist anymore, the complete Layout has to be
1562 // created, because there used to be a Frm here!
1568 pFrm
= pShellCrsr
->GetCntntNode()->getLayoutFrm( GetLayout(),
1569 &pShellCrsr
->GetPtPos(), pShellCrsr
->GetPoint(), sal_False
);
1572 else if ( Imp()->IsIdleAction() )
1573 // Guarantee everything's properly formatted
1574 pFrm
->PrepareCrsr();
1576 // In protected Fly? but ignore in case of frame selection
1577 if( !IsReadOnlyAvailable() && pFrm
->IsProtected() &&
1578 ( !Imp()->GetDrawView() ||
1579 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1580 (!pDoc
->GetDocShell() ||
1581 !pDoc
->GetDocShell()->IsReadOnly() || bAllProtect
) )
1583 // look for a valid position
1584 bool bChgState
= true;
1585 if( !FindValidCntntNode(!HasDrawView() ||
1586 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1588 // everything is protected / hidden -> special Mode
1593 eMvState
= MV_NONE
; // state for crusor travelling
1594 bAllProtect
= sal_True
;
1595 if( GetDoc()->GetDocShell() )
1597 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True
);
1598 CallChgLnk(); // notify UI!
1606 sal_Bool bWasAllProtect
= bAllProtect
;
1607 bAllProtect
= sal_False
;
1608 if( bWasAllProtect
&& GetDoc()->GetDocShell() &&
1609 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1611 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False
);
1612 CallChgLnk(); // notify UI!
1614 bAllProtect
= sal_False
;
1615 bAgainst
= true; // look for the right Frm again
1618 } while( bAgainst
);
1620 if( !( eFlags
& SwCrsrShell::NOCALRECT
))
1622 SwCrsrMoveState
aTmpState( eMvState
);
1623 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
1624 aTmpState
.bRealHeight
= sal_True
;
1625 aTmpState
.bRealWidth
= IsOverwriteCrsr();
1626 aTmpState
.nCursorBidiLevel
= pShellCrsr
->GetCrsrBidiLevel();
1628 // #i27615#,#i30453#
1629 SwSpecialPos aSpecialPos
;
1630 aSpecialPos
.nExtendRange
= SP_EXTEND_RANGE_BEFORE
;
1631 if (pShellCrsr
->IsInFrontOfLabel())
1633 aTmpState
.pSpecialPos
= &aSpecialPos
;
1636 if( !pFrm
->GetCharRect( aCharRect
, *pShellCrsr
->GetPoint(), &aTmpState
) )
1638 Point
& rPt
= pShellCrsr
->GetPtPos();
1639 rPt
= aCharRect
.Center();
1640 pFrm
->GetCrsrOfst( pShellCrsr
->GetPoint(), rPt
, &aTmpState
);
1643 if( !pShellCrsr
->HasMark() )
1644 aCrsrHeight
= aTmpState
.aRealHeight
;
1647 aCrsrHeight
.X() = 0;
1648 aCrsrHeight
.Y() = aTmpState
.aRealHeight
.Y() < 0 ?
1649 -aCharRect
.Width() : aCharRect
.Height();
1654 aCrsrHeight
.X() = 0;
1655 aCrsrHeight
.Y() = aCharRect
.Height();
1658 if( !bFirst
&& aOld
== aCharRect
)
1661 // if the layout says that we are after the 100th iteration still in
1662 // flow then we should always take the current position for granted.
1666 OSL_ENSURE( !this, "endless loop? CharRect != OldCharRect ");
1672 // update cursor Points to the new Positions
1673 pShellCrsr
->GetPtPos().X() = aCharRect
.Left();
1674 pShellCrsr
->GetPtPos().Y() = aCharRect
.Top();
1676 if( !(eFlags
& SwCrsrShell::UPDOWN
)) // delete old Pos. of Up/Down
1679 nUpDownX
= pFrm
->IsVertical() ?
1680 aCharRect
.Top() - pFrm
->Frm().Top() :
1681 aCharRect
.Left() - pFrm
->Frm().Left();
1684 // scroll Cursor to visible area
1685 if( bHasFocus
&& eFlags
& SwCrsrShell::SCROLLWIN
&&
1686 (HasSelection() || eFlags
& SwCrsrShell::READONLY
||
1687 !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1689 // in case of scrolling this EndAction doesn't show the SV cursor
1690 // again, thus save and reset the flag here
1691 sal_Bool bSav
= bSVCrsrVis
; bSVCrsrVis
= sal_False
;
1696 } while( eFlags
& SwCrsrShell::SCROLLWIN
);
1699 RefreshBlockCursor();
1701 if( !bIdleEnd
&& bHasFocus
&& !bBasicHideCrsr
)
1704 pTblCrsr
->SwSelPaintRects::Show();
1707 pCurCrsr
->SwSelPaintRects::Show();
1710 SwShellCrsr
* pNxt
= dynamic_cast<SwShellCrsr
*>(pCurCrsr
->GetNext());
1711 while( pNxt
&& pNxt
!= pCurCrsr
)
1713 pNxt
->SwSelPaintRects::Show();
1714 pNxt
= dynamic_cast<SwShellCrsr
*>(pNxt
->GetNext());
1720 eMvState
= MV_NONE
; // state for cursor tavelling - GetCrsrOfst
1722 if( pFrm
&& Imp()->IsAccessible() )
1723 Imp()->InvalidateAccessibleCursorPosition( pFrm
);
1725 // switch from blinking cursor to read-only-text-selection cursor
1726 static const long nNoBlinkTime
= STYLE_CURSOR_NOBLINKTIME
;
1727 const long nBlinkTime
= GetOut()->GetSettings().GetStyleSettings().
1728 GetCursorBlinkTime();
1730 if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1731 ( nBlinkTime
!= nNoBlinkTime
) )
1733 // non blinking cursor in read only - text selection mode
1734 AllSettings aSettings
= GetOut()->GetSettings();
1735 StyleSettings aStyleSettings
= aSettings
.GetStyleSettings();
1736 const long nNewBlinkTime
= nBlinkTime
== nNoBlinkTime
?
1737 Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1739 aStyleSettings
.SetCursorBlinkTime( nNewBlinkTime
);
1740 aSettings
.SetStyleSettings( aStyleSettings
);
1741 GetOut()->SetSettings( aSettings
);
1745 pVisCrsr
->Show(); // show again
1748 void SwCrsrShell::RefreshBlockCursor()
1750 OSL_ENSURE( pBlockCrsr
, "Don't call me without a block cursor" );
1751 SwShellCrsr
&rBlock
= pBlockCrsr
->getShellCrsr();
1752 Point aPt
= rBlock
.GetPtPos();
1753 SwCntntFrm
* pFrm
= rBlock
.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt
, rBlock
.GetPoint(), sal_False
);
1755 if( pBlockCrsr
->getEndPoint() && pBlockCrsr
->getStartPoint() )
1757 aPt
= *pBlockCrsr
->getStartPoint();
1758 aMk
= *pBlockCrsr
->getEndPoint();
1762 aPt
= rBlock
.GetPtPos();
1765 if( pFrm
->IsVertical() )
1766 aPt
.Y() = pFrm
->Frm().Top() + GetUpDownX();
1768 aPt
.X() = pFrm
->Frm().Left() + GetUpDownX();
1770 aMk
= rBlock
.GetMkPos();
1772 SwRect
aRect( aMk
, aPt
);
1774 SwSelectionList
aSelList( pFrm
);
1776 if( GetLayout()->FillSelection( aSelList
, aRect
) )
1778 SwCursor
* pNxt
= (SwCursor
*)pCurCrsr
->GetNext();
1779 while( pNxt
!= pCurCrsr
)
1782 pNxt
= (SwCursor
*)pCurCrsr
->GetNext();
1785 std::list
<SwPaM
*>::iterator pStart
= aSelList
.getStart();
1786 std::list
<SwPaM
*>::iterator pPam
= aSelList
.getEnd();
1787 OSL_ENSURE( pPam
!= pStart
, "FillSelection should deliver at least one PaM" );
1788 pCurCrsr
->SetMark();
1790 // If there is only one text portion inside the rectangle, a simple
1791 // selection is created
1792 if( pPam
== pStart
)
1794 *pCurCrsr
->GetPoint() = *(*pPam
)->GetPoint();
1795 if( (*pPam
)->HasMark() )
1796 *pCurCrsr
->GetMark() = *(*pPam
)->GetMark();
1798 pCurCrsr
->DeleteMark();
1800 pCurCrsr
->SetColumnSelection( false );
1804 // The order of the SwSelectionList has to be preserved but
1805 // the order inside the ring created by CreateCrsr() is not like
1806 // exspected => First create the selections before the last one
1807 // downto the first selection.
1808 // At least create the cursor for the last selection
1810 *pCurCrsr
->GetPoint() = *(*pPam
)->GetPoint(); // n-1 (if n == number of selections)
1811 if( (*pPam
)->HasMark() )
1812 *pCurCrsr
->GetMark() = *(*pPam
)->GetMark();
1814 pCurCrsr
->DeleteMark();
1816 pCurCrsr
->SetColumnSelection( true );
1817 while( pPam
!= pStart
)
1821 SwShellCrsr
* pNew
= new SwShellCrsr( *pCurCrsr
);
1822 pNew
->insert( pNew
->begin(), pCurCrsr
->begin(), pCurCrsr
->end());
1824 pCurCrsr
->DeleteMark();
1826 *pCurCrsr
->GetPoint() = *(*pPam
)->GetPoint(); // n-2, n-3, .., 2, 1
1827 if( (*pPam
)->HasMark() )
1829 pCurCrsr
->SetMark();
1830 *pCurCrsr
->GetMark() = *(*pPam
)->GetMark();
1833 pCurCrsr
->DeleteMark();
1834 pCurCrsr
->SetColumnSelection( true );
1838 SwShellCrsr
* pNew
= new SwShellCrsr( *pCurCrsr
);
1839 pNew
->insert( pNew
->begin(), pCurCrsr
->begin(), pCurCrsr
->end() );
1841 pCurCrsr
->DeleteMark();
1843 pPam
= aSelList
.getEnd();
1845 *pCurCrsr
->GetPoint() = *(*pPam
)->GetPoint(); // n, the last selection
1846 if( (*pPam
)->HasMark() )
1848 pCurCrsr
->SetMark();
1849 *pCurCrsr
->GetMark() = *(*pPam
)->GetMark();
1852 pCurCrsr
->DeleteMark();
1853 pCurCrsr
->SetColumnSelection( true );
1859 /// create a copy of the cursor and save it in the stack
1860 void SwCrsrShell::Push()
1862 pCrsrStk
= new SwShellCrsr( *this, *pCurCrsr
->GetPoint(),
1863 pCurCrsr
->GetPtPos(), pCrsrStk
);
1865 if( pCurCrsr
->HasMark() )
1867 pCrsrStk
->SetMark();
1868 *pCrsrStk
->GetMark() = *pCurCrsr
->GetMark();
1874 @param bOldCrsr If <true> so delete from stack, if <false> delete current
1875 and assign the one from stack as the new current cursor.
1876 @return <true> if there was one on the stack, <false> otherwise
1878 sal_Bool
SwCrsrShell::Pop( sal_Bool bOldCrsr
)
1880 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
1882 // are there any left?
1886 SwShellCrsr
*pTmp
= 0, *pOldStk
= pCrsrStk
;
1888 // the successor becomes the current one
1889 if( pCrsrStk
->GetNext() != pCrsrStk
)
1891 pTmp
= dynamic_cast<SwShellCrsr
*>(pCrsrStk
->GetNext());
1894 if( bOldCrsr
) // delete from stack
1897 pCrsrStk
= pTmp
; // assign new one
1901 SwCrsrSaveState
aSaveState( *pCurCrsr
);
1903 // If the visible SSelection was not changed
1904 if( pOldStk
->GetPtPos() == pCurCrsr
->GetPtPos() ||
1905 pOldStk
->GetPtPos() == pCurCrsr
->GetMkPos() )
1907 // move "Selections Rectangles"
1908 pCurCrsr
->insert( pCurCrsr
->begin(), pOldStk
->begin(), pOldStk
->end() );
1912 if( pOldStk
->HasMark() )
1914 pCurCrsr
->SetMark();
1915 *pCurCrsr
->GetMark() = *pOldStk
->GetMark();
1916 pCurCrsr
->GetMkPos() = pOldStk
->GetMkPos();
1919 // no selection so revoke old one and set to old position
1920 pCurCrsr
->DeleteMark();
1921 *pCurCrsr
->GetPoint() = *pOldStk
->GetPoint();
1922 pCurCrsr
->GetPtPos() = pOldStk
->GetPtPos();
1925 if( !pCurCrsr
->IsInProtectTable( sal_True
) &&
1926 !pCurCrsr
->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
1927 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
) )
1928 UpdateCrsr(); // update current cursor
1933 /** Combine two cursors
1935 Delete topmost from stack and use its GetMark in the current.
1937 void SwCrsrShell::Combine()
1943 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
1944 // rhbz#689053: IsSelOvr must restore the saved stack position, not the
1945 // current one, because current point + stack mark may be invalid PaM
1946 SwCrsrSaveState
aSaveState(*pCrsrStk
);
1947 // stack cursor & current cursor in same Section?
1948 assert(!pCrsrStk
->HasMark() ||
1949 CheckNodesRange(pCrsrStk
->GetMark()->nNode
,
1950 pCurCrsr
->GetPoint()->nNode
, true));
1951 *pCrsrStk
->GetPoint() = *pCurCrsr
->GetPoint();
1952 pCrsrStk
->GetPtPos() = pCurCrsr
->GetPtPos();
1954 SwShellCrsr
* pTmp
= 0;
1955 if( pCrsrStk
->GetNext() != pCrsrStk
)
1957 pTmp
= dynamic_cast<SwShellCrsr
*>(pCrsrStk
->GetNext());
1960 pCurCrsr
= pCrsrStk
;
1961 pCrsrStk
->MoveTo(0); // remove from ring
1963 if( !pCurCrsr
->IsInProtectTable( sal_True
) &&
1964 !pCurCrsr
->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
1965 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
) )
1967 UpdateCrsr(); // update current cursor
1972 void SwCrsrShell::HideCrsrs()
1974 if( !bHasFocus
|| bBasicHideCrsr
)
1977 // if cursor is visible then hide SV cursor
1978 if( pVisCrsr
->IsVisible() )
1980 SET_CURR_SHELL( this );
1983 // revoke inversion of SSelection
1984 SwShellCrsr
* pAktCrsr
= pTblCrsr
? pTblCrsr
: pCurCrsr
;
1990 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis
)
1992 if( !bHasFocus
|| bAllProtect
|| bBasicHideCrsr
)
1995 SET_CURR_SHELL( this );
1996 SwShellCrsr
* pAktCrsr
= pTblCrsr
? pTblCrsr
: pCurCrsr
;
1999 if( bSVCrsrVis
&& bCrsrVis
) // also show SV cursor again
2005 void SwCrsrShell::ShowCrsr()
2007 if( !bBasicHideCrsr
)
2009 bSVCrsrVis
= sal_True
;
2015 void SwCrsrShell::HideCrsr()
2017 if( !bBasicHideCrsr
)
2019 bSVCrsrVis
= sal_False
;
2020 // evt. die sel. Bereiche aufheben !!
2021 SET_CURR_SHELL( this );
2027 void SwCrsrShell::ShLooseFcs()
2029 if( !bBasicHideCrsr
)
2031 bHasFocus
= sal_False
;
2035 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate
)
2037 bHasFocus
= sal_True
;
2038 if( !bBasicHideCrsr
&& VisArea().Width() )
2040 UpdateCrsr( static_cast<sal_uInt16
>( bUpdate
?
2041 SwCrsrShell::CHKRANGE
|SwCrsrShell::SCROLLWIN
2042 : SwCrsrShell::CHKRANGE
) );
2043 ShowCrsrs( bSVCrsrVis
? sal_True
: sal_False
);
2047 /** Get current frame in which the cursor is positioned. */
2048 SwCntntFrm
*SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm
) const
2050 SET_CURR_SHELL( (ViewShell
*)this );
2051 SwCntntFrm
*pRet
= 0;
2052 SwCntntNode
*pNd
= pCurCrsr
->GetCntntNode();
2057 const sal_uInt16
* pST
= &nStartAction
;
2058 ++(*((sal_uInt16
*)pST
));
2059 const Size
aOldSz( GetDocSize() );
2060 pRet
= pNd
->getLayoutFrm( GetLayout(), &pCurCrsr
->GetPtPos(), pCurCrsr
->GetPoint() );
2061 --(*((sal_uInt16
*)pST
));
2062 if( aOldSz
!= GetDocSize() )
2063 ((SwCrsrShell
*)this)->SizeChgNotify();
2066 pRet
= pNd
->getLayoutFrm( GetLayout(), &pCurCrsr
->GetPtPos(), pCurCrsr
->GetPoint(), sal_False
);
2071 //TODO: provide documentation
2072 /** forward all attribute/format changes at the current node to the Link
2077 void SwCrsrShell::Modify( const SfxPoolItem
* pOld
, const SfxPoolItem
* pNew
)
2079 const sal_uInt16 nWhich
= pOld
?
2083 sal::static_int_cast
<sal_uInt16
>(RES_MSG_BEGIN
);
2086 ( nWhich
< RES_MSG_BEGIN
|| nWhich
>= RES_MSG_END
||
2087 nWhich
== RES_FMT_CHG
|| nWhich
== RES_UPDATE_ATTR
||
2088 nWhich
== RES_ATTRSET_CHG
))
2089 // messages are not forwarded
2090 // #i6681#: RES_UPDATE_ATTR is implicitly unset in
2091 // SwTxtNode::Insert(SwTxtHint*, sal_uInt16); we react here and thus do
2092 // not need to send the expensive RES_FMT_CHG in Insert.
2095 if( aGrfArrivedLnk
.IsSet() &&
2096 ( RES_GRAPHIC_ARRIVED
== nWhich
|| RES_GRAPHIC_SWAPIN
== nWhich
))
2097 aGrfArrivedLnk
.Call( this );
2100 /** Does the current cursor create a selection?
2102 This means checking if GetMark is set and if SPoint and GetMark differ.
2104 sal_Bool
SwCrsrShell::HasSelection() const
2106 const SwPaM
* pCrsr
= getShellCrsr( true );
2107 return( IsTableMode() || ( pCrsr
->HasMark() &&
2108 *pCrsr
->GetPoint() != *pCrsr
->GetMark())
2109 ? sal_True
: sal_False
);
2113 void SwCrsrShell::CallChgLnk()
2115 // Do not make any call in start/end action but just remember the change.
2116 // This will be taken care of in the end action.
2117 if( BasicActionPend() )
2118 bChgCallFlag
= sal_True
; // remember change
2119 else if( aChgLnk
.IsSet() )
2122 aChgLnk
.Call( this );
2123 bChgCallFlag
= sal_False
; // reset flag
2127 /// get selected text of a node at current cursor
2128 String
SwCrsrShell::GetSelTxt() const
2131 if( pCurCrsr
->GetPoint()->nNode
.GetIndex() ==
2132 pCurCrsr
->GetMark()->nNode
.GetIndex() )
2134 SwTxtNode
* pTxtNd
= pCurCrsr
->GetNode()->GetTxtNode();
2137 xub_StrLen nStt
= pCurCrsr
->Start()->nContent
.GetIndex();
2138 aTxt
= pTxtNd
->GetExpandTxt( nStt
,
2139 pCurCrsr
->End()->nContent
.GetIndex() - nStt
);
2145 /// get text only from current cursor position (until end of node)
2146 String
SwCrsrShell::GetText() const
2149 if( pCurCrsr
->GetPoint()->nNode
.GetIndex() ==
2150 pCurCrsr
->GetMark()->nNode
.GetIndex() )
2152 SwTxtNode
* pTxtNd
= pCurCrsr
->GetNode()->GetTxtNode();
2154 aTxt
= pTxtNd
->GetTxt().Copy(
2155 pCurCrsr
->GetPoint()->nContent
.GetIndex() );
2160 /** get the nth character of the current SSelection
2162 @param bEnd Start counting from the end? From start otherwise.
2163 @param nOffset position of the character
2165 sal_Unicode
SwCrsrShell::GetChar( sal_Bool bEnd
, long nOffset
)
2167 if( IsTableMode() ) // not possible in table mode
2170 const SwPosition
* pPos
= !pCurCrsr
->HasMark() ? pCurCrsr
->GetPoint()
2171 : bEnd
? pCurCrsr
->End() : pCurCrsr
->Start();
2172 SwTxtNode
* pTxtNd
= pPos
->nNode
.GetNode().GetTxtNode();
2176 xub_StrLen nPos
= pPos
->nContent
.GetIndex();
2177 const String
& rStr
= pTxtNd
->GetTxt();
2178 sal_Unicode cCh
= 0;
2180 if( ((nPos
+nOffset
) >= 0 ) && (nPos
+nOffset
) < rStr
.Len() )
2181 cCh
= rStr
.GetChar( static_cast<xub_StrLen
>(nPos
+nOffset
) );
2186 /** extend current SSelection by n characters
2188 @param bEnd Start counting from the end? From start otherwise.
2189 @param nCount Number of characters.
2191 sal_Bool
SwCrsrShell::ExtendSelection( sal_Bool bEnd
, xub_StrLen nCount
)
2193 if( !pCurCrsr
->HasMark() || IsTableMode() )
2194 return sal_False
; // no selection
2196 SwPosition
* pPos
= bEnd
? pCurCrsr
->End() : pCurCrsr
->Start();
2197 SwTxtNode
* pTxtNd
= pPos
->nNode
.GetNode().GetTxtNode();
2198 OSL_ENSURE( pTxtNd
, "no text node; how should this then be extended?" );
2200 xub_StrLen nPos
= pPos
->nContent
.GetIndex();
2203 if( ( nPos
+ nCount
) <= pTxtNd
->GetTxt().Len() )
2204 nPos
= nPos
+ nCount
;
2206 return sal_False
; // not possible
2208 else if( nPos
>= nCount
)
2209 nPos
= nPos
- nCount
;
2211 return sal_False
; // not possible anymore
2213 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
2215 pPos
->nContent
= nPos
;
2221 /** Move visible cursor to given position in document.
2223 @param rPt The position to move the visible cursor to.
2224 @return <sal_False> if SPoint was corrected by the layout.
2226 sal_Bool
SwCrsrShell::SetVisCrsr( const Point
&rPt
)
2228 SET_CURR_SHELL( this );
2230 SwPosition
aPos( *pCurCrsr
->GetPoint() );
2231 SwCrsrMoveState
aTmpState( MV_SETONLYTEXT
);
2232 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
2233 aTmpState
.bRealHeight
= sal_True
;
2235 sal_Bool bRet
= GetLayout()->GetCrsrOfst( &aPos
, aPt
/*, &aTmpState*/ );
2237 SetInFrontOfLabel( false ); // #i27615#
2239 // show only in TextNodes
2240 SwTxtNode
* pTxtNd
= aPos
.nNode
.GetNode().GetTxtNode();
2244 const SwSectionNode
* pSectNd
= pTxtNd
->FindSectionNode();
2245 if( pSectNd
&& (pSectNd
->GetSection().IsHiddenFlag() ||
2246 ( !IsReadOnlyAvailable() &&
2247 pSectNd
->GetSection().IsProtectFlag())) )
2250 SwCntntFrm
*pFrm
= pTxtNd
->getLayoutFrm( GetLayout(), &aPt
, &aPos
);
2251 if ( Imp()->IsIdleAction() )
2252 pFrm
->PrepareCrsr();
2253 SwRect
aTmp( aCharRect
);
2255 pFrm
->GetCharRect( aCharRect
, aPos
, &aTmpState
);
2258 if( aTmp
== aCharRect
&& pVisCrsr
->IsVisible() )
2261 pVisCrsr
->Hide(); // always hide visible cursor
2262 if( IsScrollMDI( this, aCharRect
))
2264 MakeVisible( aCharRect
);
2269 if( aTmpState
.bRealHeight
)
2270 aCrsrHeight
= aTmpState
.aRealHeight
;
2273 aCrsrHeight
.X() = 0;
2274 aCrsrHeight
.Y() = aCharRect
.Height();
2277 pVisCrsr
->SetDragCrsr( true );
2278 pVisCrsr
->Show(); // show again
2283 sal_Bool
SwCrsrShell::IsOverReadOnlyPos( const Point
& rPt
) const
2286 SwPaM
aPam( *pCurCrsr
->GetPoint() );
2287 GetLayout()->GetCrsrOfst( aPam
.GetPoint(), aPt
);
2289 return aPam
.HasReadonlySel( GetViewOptions()->IsFormView() );
2292 sal_Bool
SwCrsrShell::IsOverHeaderFooterPos( const Point
& rPt
) const
2295 SwPaM
aPam( *pCurCrsr
->GetPoint() );
2296 GetLayout()->GetCrsrOfst( aPam
.GetPoint(), aPt
);
2298 return GetDoc()->IsInHeaderFooter( aPam
.GetPoint()->nNode
);
2301 /** Get the number of elements in the ring of cursors
2303 @param bAll If <false> get only spanned ones (= with selections) (Basic).
2305 sal_uInt16
SwCrsrShell::GetCrsrCnt( sal_Bool bAll
) const
2307 Ring
* pTmp
= GetCrsr()->GetNext();
2308 sal_uInt16 n
= (bAll
|| ( pCurCrsr
->HasMark() &&
2309 *pCurCrsr
->GetPoint() != *pCurCrsr
->GetMark())) ? 1 : 0;
2310 while( pTmp
!= pCurCrsr
)
2312 if( bAll
|| ( ((SwPaM
*)pTmp
)->HasMark() &&
2313 *((SwPaM
*)pTmp
)->GetPoint() != *((SwPaM
*)pTmp
)->GetMark()))
2315 pTmp
= pTmp
->GetNext();
2321 sal_Bool
SwCrsrShell::IsStartOfDoc() const
2323 if( pCurCrsr
->GetPoint()->nContent
.GetIndex() )
2326 // after EndOfIcons comes the content selection (EndNd+StNd+CntntNd)
2327 SwNodeIndex
aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2328 if( !aIdx
.GetNode().IsCntntNode() )
2329 GetDoc()->GetNodes().GoNext( &aIdx
);
2330 return aIdx
== pCurCrsr
->GetPoint()->nNode
;
2334 sal_Bool
SwCrsrShell::IsEndOfDoc() const
2336 SwNodeIndex
aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2337 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
2339 pCNd
= GetDoc()->GetNodes().GoPrevious( &aIdx
);
2341 return aIdx
== pCurCrsr
->GetPoint()->nNode
&&
2342 pCNd
->Len() == pCurCrsr
->GetPoint()->nContent
.GetIndex();
2345 /** Invalidate cursors
2347 Delete all created cursors, set table crsr and last crsr to their TextNode
2348 (or StartNode?). They will then all re-created at the next ::GetCrsr() call.
2350 This is needed for Drag&Drop/ Clipboard-paste in tables.
2352 sal_Bool
SwCrsrShell::ParkTblCrsr()
2357 pTblCrsr
->ParkCrsr();
2359 while( pCurCrsr
->GetNext() != pCurCrsr
)
2360 delete pCurCrsr
->GetNext();
2362 // *always* move cursor's SPoint and Mark
2363 pCurCrsr
->SetMark();
2364 *pCurCrsr
->GetMark() = *pCurCrsr
->GetPoint() = *pTblCrsr
->GetPoint();
2365 pCurCrsr
->DeleteMark();
2370 void SwCrsrShell::_ParkPams( SwPaM
* pDelRg
, SwShellCrsr
** ppDelRing
)
2372 const SwPosition
*pStt
= pDelRg
->Start(),
2373 *pEnd
= pDelRg
->GetPoint() == pStt
? pDelRg
->GetMark() : pDelRg
->GetPoint();
2375 SwPaM
*pTmpDel
= 0, *pTmp
= *ppDelRing
;
2377 // search over the whole ring
2380 const SwPosition
*pTmpStt
= pTmp
->Start(),
2381 *pTmpEnd
= pTmp
->GetPoint() == pTmpStt
?
2382 pTmp
->GetMark() : pTmp
->GetPoint();
2383 // If a SPoint or GetMark are in a cursor area than cancel the old area.
2384 // During comparison keep in mind that End() is outside the area.
2385 if( *pStt
<= *pTmpStt
)
2387 if( *pEnd
> *pTmpStt
||
2388 ( *pEnd
== *pTmpStt
&& *pEnd
== *pTmpEnd
))
2392 if( *pStt
< *pTmpEnd
)
2396 if( pTmpDel
) // is the pam in area -> delete
2398 sal_Bool bDelete
= sal_True
;
2399 if( *ppDelRing
== pTmpDel
)
2401 if( *ppDelRing
== pCurCrsr
)
2403 if( sal_True
== ( bDelete
= GoNextCrsr() ))
2406 pTmp
= (SwPaM
*)pTmp
->GetNext();
2410 bDelete
= sal_False
; // never delete the StackCrsr
2414 delete pTmpDel
; // invalidate old area
2417 pTmpDel
->GetPoint()->nContent
.Assign( 0, 0 );
2418 pTmpDel
->GetPoint()->nNode
= 0;
2420 pTmpDel
->DeleteMark();
2424 else if( !pTmp
->HasMark() )
2426 // Take care that not used indices are considered.
2427 // SPoint is not in area but maybe GetMark is, thus set it.
2432 pTmp
= (SwPaM
*)pTmp
->GetNext();
2433 } while( !bGoNext
|| *ppDelRing
!= pTmp
);
2436 //TODO: provide documentation
2437 /** Remove selections and additional cursors of all shells.
2439 The remaining cursor of the shell is parked.
2443 void SwCrsrShell::ParkCrsr( const SwNodeIndex
&rIdx
)
2445 SwNode
*pNode
= &rIdx
.GetNode();
2448 SwPaM
* pNew
= new SwPaM( *GetCrsr()->GetPoint() );
2449 if( pNode
->GetStartNode() )
2451 if( ( pNode
= pNode
->StartOfSectionNode())->IsTableNode() )
2453 // the given node is in a table, thus park cursor to table node
2454 // (outside of the table)
2455 pNew
->GetPoint()->nNode
= *pNode
->StartOfSectionNode();
2458 // Also on the start node itself. Then we need to request the start
2459 // node always via its end node! (StartOfSelection of StartNode is
2461 pNew
->GetPoint()->nNode
= *pNode
->EndOfSectionNode()->StartOfSectionNode();
2464 pNew
->GetPoint()->nNode
= *pNode
->StartOfSectionNode();
2466 pNew
->GetPoint()->nNode
= *pNode
->EndOfSectionNode();
2468 // take care of all shells
2469 ViewShell
*pTmp
= this;
2471 if( pTmp
->IsA( TYPE( SwCrsrShell
)))
2473 SwCrsrShell
* pSh
= (SwCrsrShell
*)pTmp
;
2475 pSh
->_ParkPams( pNew
, &pSh
->pCrsrStk
);
2477 pSh
->_ParkPams( pNew
, &pSh
->pCurCrsr
);
2480 // set table cursor always to 0 and the current one always to
2481 // the beginning of the table
2482 SwPaM
* pTCrsr
= pSh
->GetTblCrs();
2483 SwNode
* pTblNd
= pTCrsr
->GetPoint()->nNode
.GetNode().FindTableNode();
2486 pTCrsr
->GetPoint()->nContent
.Assign( 0, 0 );
2487 pTCrsr
->GetPoint()->nNode
= 0;
2489 pTCrsr
->DeleteMark();
2490 pSh
->pCurCrsr
->GetPoint()->nNode
= *pTblNd
;
2494 } while ( this != (pTmp
= (ViewShell
*)pTmp
->GetNext() ));
2499 /** Copy constructor
2501 Copy cursor position and add it to the ring.
2502 All views of a document are in the ring of the shell.
2504 SwCrsrShell::SwCrsrShell( SwCrsrShell
& rShell
, Window
*pInitWin
)
2505 : ViewShell( rShell
, pInitWin
),
2506 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2507 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2508 eMvState( MV_NONE
),
2510 nMarkedListLevel( 0 )
2512 SET_CURR_SHELL( this );
2513 // only keep the position of the current cursor of the copy shell
2514 pCurCrsr
= new SwShellCrsr( *this, *(rShell
.pCurCrsr
->GetPoint()) );
2515 pCurCrsr
->GetCntntNode()->Add( this );
2517 bAllProtect
= bVisPortChgd
= bChgCallFlag
= bInCMvVisportChgd
=
2518 bGCAttr
= bIgnoreReadonly
= bSelTblCells
= bBasicHideCrsr
=
2519 bOverwriteCrsr
= sal_False
;
2520 bCallChgLnk
= bHasFocus
= bSVCrsrVis
= bAutoUpdateCells
= sal_True
;
2521 bSetCrsrInReadOnly
= sal_True
;
2522 pVisCrsr
= new SwVisCrsr( this );
2523 mbMacroExecAllowed
= rShell
.IsMacroExecAllowed();
2526 /// default constructor
2527 SwCrsrShell::SwCrsrShell( SwDoc
& rDoc
, Window
*pInitWin
,
2528 const SwViewOption
*pInitOpt
)
2529 : ViewShell( rDoc
, pInitWin
, pInitOpt
),
2530 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2531 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2532 eMvState( MV_NONE
), // state for crsr-travelling - GetCrsrOfst
2534 nMarkedListLevel( 0 )
2536 SET_CURR_SHELL( this );
2537 // create initial cursor and set it to first content position
2538 SwNodes
& rNds
= rDoc
.GetNodes();
2540 SwNodeIndex
aNodeIdx( *rNds
.GetEndOfContent().StartOfSectionNode() );
2541 SwCntntNode
* pCNd
= rNds
.GoNext( &aNodeIdx
); // gehe zum 1. ContentNode
2543 pCurCrsr
= new SwShellCrsr( *this, SwPosition( aNodeIdx
, SwIndex( pCNd
, 0 )));
2545 // Register shell as dependent at current node. As a result all attribute
2546 // changes can be forwarded via the Link.
2549 bAllProtect
= bVisPortChgd
= bChgCallFlag
= bInCMvVisportChgd
=
2550 bGCAttr
= bIgnoreReadonly
= bSelTblCells
= bBasicHideCrsr
=
2551 bOverwriteCrsr
= sal_False
;
2552 bCallChgLnk
= bHasFocus
= bSVCrsrVis
= bAutoUpdateCells
= sal_True
;
2553 bSetCrsrInReadOnly
= sal_True
;
2555 pVisCrsr
= new SwVisCrsr( this );
2556 mbMacroExecAllowed
= true;
2561 SwCrsrShell::~SwCrsrShell()
2563 // if it is not the last view then at least the field should be updated
2564 if( GetNext() != this )
2565 CheckTblBoxCntnt( pCurCrsr
->GetPoint() );
2574 while(pCurCrsr
->GetNext() != pCurCrsr
)
2575 delete pCurCrsr
->GetNext();
2581 while( pCrsrStk
->GetNext() != pCrsrStk
)
2582 delete pCrsrStk
->GetNext();
2586 // #i54025# - do not give a HTML parser that might potentially hang as
2587 // a client at the cursor shell the chance to hang itself on a TextNode
2588 if( GetRegisteredIn() )
2589 GetRegisteredInNonConst()->Remove( this );
2592 SwShellCrsr
* SwCrsrShell::getShellCrsr( bool bBlock
)
2596 if( pBlockCrsr
&& bBlock
)
2597 return &pBlockCrsr
->getShellCrsr();
2601 /** Should WaitPtr be switched on for the clipboard?
2603 Wait for TableMode, multiple selections and more than x selected paragraphs.
2605 bool SwCrsrShell::ShouldWait() const
2607 if ( IsTableMode() || GetCrsrCnt() > 1 )
2610 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2613 SwPaM
* pPam
= GetCrsr();
2614 return pPam
->Start()->nNode
.GetIndex() + 10 <
2615 pPam
->End()->nNode
.GetIndex();
2618 size_t SwCrsrShell::UpdateTblSelBoxes()
2620 if (pTblCrsr
&& (pTblCrsr
->IsChgd() || !pTblCrsr
->GetSelectedBoxesCount()))
2622 GetLayout()->MakeTblCrsrs( *pTblCrsr
);
2624 return (pTblCrsr
) ? pTblCrsr
->GetSelectedBoxesCount() : 0;
2627 /// show the current selected "object"
2628 void SwCrsrShell::MakeSelVisible()
2630 OSL_ENSURE( bHasFocus
, "no focus but cursor should be made visible?" );
2631 if( aCrsrHeight
.Y() < aCharRect
.Height() && aCharRect
.Height() > VisArea().Height() )
2633 SwRect
aTmp( aCharRect
);
2634 long nDiff
= aCharRect
.Height() - VisArea().Height();
2635 if( nDiff
< aCrsrHeight
.X() )
2636 aTmp
.Top( nDiff
+ aCharRect
.Top() );
2639 aTmp
.Top( aCrsrHeight
.X() + aCharRect
.Top() );
2640 aTmp
.Height( aCrsrHeight
.Y() );
2642 if( !aTmp
.HasArea() )
2644 aTmp
.SSize().Height() += 1;
2645 aTmp
.SSize().Width() += 1;
2647 MakeVisible( aTmp
);
2651 if( aCharRect
.HasArea() )
2652 MakeVisible( aCharRect
);
2655 SwRect
aTmp( aCharRect
);
2656 aTmp
.SSize().Height() += 1; aTmp
.SSize().Width() += 1;
2657 MakeVisible( aTmp
);
2662 /// search a valid content position (not protected/hidden)
2663 sal_Bool
SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText
)
2667 OSL_ENSURE( !this, "Did not remove table selection!" );
2671 // #i45129# - everything is allowed in UI-readonly
2672 if( !bAllProtect
&& GetDoc()->GetDocShell() &&
2673 GetDoc()->GetDocShell()->IsReadOnlyUI() )
2676 if( pCurCrsr
->HasMark() )
2679 // first check for frames
2680 SwNodeIndex
& rNdIdx
= pCurCrsr
->GetPoint()->nNode
;
2681 sal_uLong nNdIdx
= rNdIdx
.GetIndex(); // keep backup
2682 SwNodes
& rNds
= pDoc
->GetNodes();
2683 SwCntntNode
* pCNd
= rNdIdx
.GetNode().GetCntntNode();
2684 const SwCntntFrm
* pFrm
;
2686 if( pCNd
&& 0 != (pFrm
= pCNd
->getLayoutFrm( GetLayout(),0,pCurCrsr
->GetPoint(),sal_False
)) &&
2687 !IsReadOnlyAvailable() && pFrm
->IsProtected() &&
2688 nNdIdx
< rNds
.GetEndOfExtras().GetIndex() )
2690 // skip protected frame
2691 SwPaM
aPam( *pCurCrsr
->GetPoint() );
2693 aPam
.GetMark()->nNode
= rNds
.GetEndOfContent();
2694 aPam
.GetPoint()->nNode
= *pCNd
->EndOfSectionNode();
2696 sal_Bool bFirst
= sal_False
;
2697 if( 0 == (pCNd
= ::GetNode( aPam
, bFirst
, fnMoveForward
, sal_False
)))
2699 aPam
.GetMark()->nNode
= *rNds
.GetEndOfPostIts().StartOfSectionNode();
2700 pCNd
= ::GetNode( aPam
, bFirst
, fnMoveBackward
, sal_False
);
2703 if( !pCNd
) // should *never* happen
2705 rNdIdx
= nNdIdx
; // back to old node
2708 *pCurCrsr
->GetPoint() = *aPam
.GetPoint();
2710 else if( bOnlyText
&& pCNd
&& pCNd
->IsNoTxtNode() )
2712 // set to beginning of document
2713 rNdIdx
= pDoc
->GetNodes().GetEndOfExtras();
2714 pCurCrsr
->GetPoint()->nContent
.Assign( pDoc
->GetNodes().GoNext(
2716 nNdIdx
= rNdIdx
.GetIndex();
2719 sal_Bool bOk
= sal_True
;
2721 // #i9059# cursor may not stand in protected cells
2722 // (unless cursor in protected areas is OK.)
2723 const SwTableNode
* pTableNode
= rNdIdx
.GetNode().FindTableNode();
2724 if( !IsReadOnlyAvailable() &&
2725 pTableNode
!= NULL
&& rNdIdx
.GetNode().IsProtect() )
2727 // we're in a table, and we're in a protected area, so we're
2728 // probably in a protected cell.
2730 // move forward into non-protected area.
2731 SwPaM
aPam( rNdIdx
.GetNode(), 0 );
2732 while( aPam
.GetNode()->IsProtect() &&
2733 aPam
.Move( fnMoveForward
, fnGoCntnt
) )
2734 ; // nothing to do in the loop; the aPam.Move does the moving!
2736 // didn't work? then go backwards!
2737 if( aPam
.GetNode()->IsProtect() )
2739 SwPaM
aTmpPaM( rNdIdx
.GetNode(), 0 );
2741 while( aPam
.GetNode()->IsProtect() &&
2742 aPam
.Move( fnMoveBackward
, fnGoCntnt
) )
2743 ; // nothing to do in the loop; the aPam.Move does the moving!
2746 // if we're successful, set the new position
2747 if( ! aPam
.GetNode()->IsProtect() )
2749 *pCurCrsr
->GetPoint() = *aPam
.GetPoint();
2753 // in a protected frame
2754 const SwSectionNode
* pSectNd
= rNdIdx
.GetNode().FindSectionNode();
2755 if( pSectNd
&& ( pSectNd
->GetSection().IsHiddenFlag() ||
2756 ( !IsReadOnlyAvailable() &&
2757 pSectNd
->GetSection().IsProtectFlag() )) )
2759 typedef SwCntntNode
* (SwNodes:: *FNGoSection
)( SwNodeIndex
*, int, int ) const;
2760 FNGoSection funcGoSection
= &SwNodes::GoNextSection
;
2764 for( int nLoopCnt
= 0; !bOk
&& nLoopCnt
< 2; ++nLoopCnt
)
2769 while( 0 != ( pCNd
= (rNds
.*funcGoSection
)( &rNdIdx
,
2770 sal_True
, !IsReadOnlyAvailable() )) )
2772 // moved inside a table -> check if it is protected
2773 if( pCNd
->FindTableNode() )
2775 SwCallLink
aTmp( *this );
2776 SwCrsrSaveState
aSaveState( *pCurCrsr
);
2777 aTmp
.nNdTyp
= 0; // don't do anything in DTOR
2778 if( !pCurCrsr
->IsInProtectTable( sal_True
, sal_True
) )
2780 const SwSectionNode
* pSNd
= pCNd
->FindSectionNode();
2781 if( !pSNd
|| !pSNd
->GetSection().IsHiddenFlag()
2782 || (!IsReadOnlyAvailable() &&
2783 pSNd
->GetSection().IsProtectFlag() ))
2786 break; // found non-protected cell
2788 continue; // continue search
2794 break; // found non-protected cell
2798 if( bOk
&& rNdIdx
.GetIndex() < rNds
.GetEndOfExtras().GetIndex() )
2800 // also check for Fly - might be protected as well
2801 if( 0 == (pFrm
= pCNd
->getLayoutFrm( GetLayout(),0,0,sal_False
)) ||
2802 ( !IsReadOnlyAvailable() && pFrm
->IsProtected() ) ||
2803 ( bOnlyText
&& pCNd
->IsNoTxtNode() ) )
2810 } while( bContinue
);
2815 funcGoSection
= &SwNodes::GoPrevSection
;
2822 pCNd
= rNdIdx
.GetNode().GetCntntNode();
2823 xub_StrLen nCntnt
= rNdIdx
.GetIndex() < nNdIdx
? pCNd
->Len() : 0;
2824 pCurCrsr
->GetPoint()->nContent
.Assign( pCNd
, nCntnt
);
2828 pCNd
= rNdIdx
.GetNode().GetCntntNode();
2829 // if cursor in hidden frame, always move it
2830 if( !pCNd
|| !pCNd
->getLayoutFrm( GetLayout(),0,0,sal_False
) )
2832 SwCrsrMoveState
aTmpState( MV_NONE
);
2833 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
2834 GetLayout()->GetCrsrOfst( pCurCrsr
->GetPoint(), pCurCrsr
->GetPtPos(),
2842 sal_Bool
SwCrsrShell::IsCrsrReadonly() const
2844 if ( GetViewOptions()->IsReadonly() ||
2845 GetViewOptions()->IsFormView() /* Formular view */ )
2847 SwFrm
*pFrm
= GetCurrFrm( sal_False
);
2848 const SwFlyFrm
* pFly
;
2849 const SwSection
* pSection
;
2851 if( pFrm
&& pFrm
->IsInFly() &&
2852 (pFly
= pFrm
->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
2854 !pFly
->Lower()->IsNoTxtFrm() &&
2855 !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2859 // edit in readonly sections
2860 else if ( pFrm
&& pFrm
->IsInSct() &&
2861 0 != ( pSection
= pFrm
->FindSctFrm()->GetSection() ) &&
2862 pSection
->IsEditInReadonlyFlag() )
2872 /// is the cursor allowed to enter ReadOnly sections?
2873 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag
)
2875 // *never* switch in GlobalDoc
2876 if( (!GetDoc()->GetDocShell() ||
2877 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
2878 bFlag
!= bSetCrsrInReadOnly
)
2880 // If the flag is switched off then all selections need to be
2881 // invalidated. Otherwise we would trust that nothing protected is selected.
2886 bSetCrsrInReadOnly
= bFlag
;
2891 sal_Bool
SwCrsrShell::HasReadonlySel(bool bAnnotationMode
) const
2893 sal_Bool bRet
= sal_False
;
2894 if( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
2897 bRet
= pTblCrsr
->HasReadOnlyBoxSel() ||
2898 pTblCrsr
->HasReadonlySel( GetViewOptions()->IsFormView() );
2901 const SwPaM
* pCrsr
= pCurCrsr
;
2904 if( pCrsr
->HasReadonlySel( GetViewOptions()->IsFormView(), bAnnotationMode
) )
2906 } while( !bRet
&& pCurCrsr
!= ( pCrsr
= (SwPaM
*)pCrsr
->GetNext() ));
2912 sal_Bool
SwCrsrShell::IsSelFullPara() const
2914 sal_Bool bRet
= sal_False
;
2916 if( pCurCrsr
->GetPoint()->nNode
.GetIndex() ==
2917 pCurCrsr
->GetMark()->nNode
.GetIndex() && pCurCrsr
== pCurCrsr
->GetNext() )
2919 xub_StrLen nStt
= pCurCrsr
->GetPoint()->nContent
.GetIndex(),
2920 nEnd
= pCurCrsr
->GetMark()->nContent
.GetIndex();
2923 xub_StrLen nTmp
= nStt
;
2927 const SwCntntNode
* pCNd
= pCurCrsr
->GetCntntNode();
2928 bRet
= pCNd
&& !nStt
&& nEnd
== pCNd
->Len();
2933 short SwCrsrShell::GetTextDirection( const Point
* pPt
) const
2935 SwPosition
aPos( *pCurCrsr
->GetPoint() );
2936 Point
aPt( pPt
? *pPt
: pCurCrsr
->GetPtPos() );
2939 SwCrsrMoveState
aTmpState( MV_NONE
);
2940 aTmpState
.bSetInReadOnly
= IsReadOnlyAvailable();
2942 GetLayout()->GetCrsrOfst( &aPos
, aPt
, &aTmpState
);
2945 return pDoc
->GetTextDirection( aPos
, &aPt
);
2948 bool SwCrsrShell::IsInVerticalText( const Point
* pPt
) const
2950 const short nDir
= GetTextDirection( pPt
);
2951 return FRMDIR_VERT_TOP_RIGHT
== nDir
|| FRMDIR_VERT_TOP_LEFT
== nDir
;
2954 sal_Bool
SwCrsrShell::IsInRightToLeftText( const Point
* pPt
) const
2956 const short nDir
= GetTextDirection( pPt
);
2957 // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
2958 // vertical environment
2959 return FRMDIR_VERT_TOP_LEFT
== nDir
|| FRMDIR_HORI_RIGHT_TOP
== nDir
;
2962 /// If the current cursor position is inside a hidden range, the hidden range
2964 bool SwCrsrShell::SelectHiddenRange()
2967 if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr
->HasMark() )
2969 SwPosition
& rPt
= *(SwPosition
*)pCurCrsr
->GetPoint();
2970 const SwTxtNode
* pNode
= rPt
.nNode
.GetNode().GetTxtNode();
2973 const xub_StrLen nPos
= rPt
.nContent
.GetIndex();
2975 // check if nPos is in hidden range
2976 xub_StrLen nHiddenStart
;
2977 xub_StrLen nHiddenEnd
;
2978 SwScriptInfo::GetBoundsOfHiddenRange( *pNode
, nPos
, nHiddenStart
, nHiddenEnd
);
2979 if ( STRING_LEN
!= nHiddenStart
)
2982 pCurCrsr
->SetMark();
2983 pCurCrsr
->GetMark()->nContent
= nHiddenEnd
;
2992 sal_uLong
SwCrsrShell::Find( const SearchOptions
& rSearchOpt
,
2993 sal_Bool bSearchInNotes
,
2994 SwDocPositions eStart
, SwDocPositions eEnd
,
3001 delete pTblCrsr
, pTblCrsr
= 0;
3002 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
3003 sal_uLong nRet
= pCurCrsr
->Find( rSearchOpt
, bSearchInNotes
, eStart
, eEnd
,
3004 bCancel
, eRng
, bReplace
);
3005 if( nRet
|| bCancel
)
3010 sal_uLong
SwCrsrShell::Find( const SwTxtFmtColl
& rFmtColl
,
3011 SwDocPositions eStart
, SwDocPositions eEnd
,
3014 const SwTxtFmtColl
* pReplFmt
)
3018 delete pTblCrsr
, pTblCrsr
= 0;
3019 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
3020 sal_uLong nRet
= pCurCrsr
->Find( rFmtColl
, eStart
, eEnd
, bCancel
, eRng
,
3027 sal_uLong
SwCrsrShell::Find( const SfxItemSet
& rSet
,
3028 sal_Bool bNoCollections
,
3029 SwDocPositions eStart
, SwDocPositions eEnd
,
3032 const SearchOptions
* pSearchOpt
,
3033 const SfxItemSet
* rReplSet
)
3037 delete pTblCrsr
, pTblCrsr
= 0;
3038 SwCallLink
aLk( *this ); // watch Crsr-Moves; call Link if needed
3039 sal_uLong nRet
= pCurCrsr
->Find( rSet
, bNoCollections
, eStart
, eEnd
,
3040 bCancel
, eRng
, pSearchOpt
, rReplSet
);
3046 void SwCrsrShell::SetSelection( const SwPaM
& rCrsr
)
3049 SwPaM
* pCrsr
= GetCrsr();
3050 *pCrsr
->GetPoint() = *rCrsr
.GetPoint();
3054 *pCrsr
->GetMark() = *rCrsr
.GetMark();
3056 if((SwPaM
*)rCrsr
.GetNext() != &rCrsr
)
3058 const SwPaM
*_pStartCrsr
= (SwPaM
*)rCrsr
.GetNext();
3061 SwPaM
* pCurrentCrsr
= CreateCrsr();
3062 *pCurrentCrsr
->GetPoint() = *_pStartCrsr
->GetPoint();
3063 if(_pStartCrsr
->HasMark())
3065 pCurrentCrsr
->SetMark();
3066 *pCurrentCrsr
->GetMark() = *_pStartCrsr
->GetMark();
3068 } while( (_pStartCrsr
=(SwPaM
*)_pStartCrsr
->GetNext()) != &rCrsr
);
3073 static void lcl_RemoveMark( SwPaM
* pPam
)
3075 OSL_ENSURE( pPam
->HasMark(), "Don't remove pPoint!" );
3076 pPam
->GetMark()->nContent
.Assign( 0, 0 );
3077 pPam
->GetMark()->nNode
= 0;
3081 static const SwStartNode
* lcl_NodeContext( const SwNode
& rNode
)
3083 const SwStartNode
*pRet
= rNode
.StartOfSectionNode();
3084 while( pRet
->IsSectionNode() || pRet
->IsTableNode() ||
3085 pRet
->GetStartNodeType() == SwTableBoxStartNode
)
3087 pRet
= pRet
->StartOfSectionNode();
3093 Checks if a position is valid. To be valid the position's node must
3094 be a content node and the content must not be unregistered.
3096 @param aPos the position to check.
3098 bool sw_PosOk(const SwPosition
& aPos
)
3100 return NULL
!= aPos
.nNode
.GetNode().GetCntntNode() &&
3101 aPos
.nContent
.GetIdxReg();
3105 Checks if a PaM is valid. For a PaM to be valid its point must be
3106 valid. Additionaly if the PaM has a mark this has to be valid, too.
3108 @param aPam the PaM to check
3110 static bool lcl_CrsrOk(SwPaM
& aPam
)
3112 return sw_PosOk(*aPam
.GetPoint()) && (! aPam
.HasMark()
3113 || sw_PosOk(*aPam
.GetMark()));
3116 void SwCrsrShell::ClearUpCrsrs()
3118 // start of the ring
3119 SwPaM
* pStartCrsr
= GetCrsr();
3120 // start loop with second entry of the ring
3121 SwPaM
* pCrsr
= (SwPaM
*) pStartCrsr
->GetNext();
3123 bool bChanged
= false;
3125 // For all entries in the ring except the start entry delete the entry if
3127 while (pCrsr
!= pStartCrsr
)
3129 pTmpCrsr
= (SwPaM
*) pCrsr
->GetNext();
3131 if ( ! lcl_CrsrOk(*pCrsr
))
3141 if( pStartCrsr
->HasMark() && !sw_PosOk( *pStartCrsr
->GetMark() ) )
3143 lcl_RemoveMark( pStartCrsr
);
3146 if( !sw_PosOk( *pStartCrsr
->GetPoint() ) )
3148 SwNodes
& aNodes
= GetDoc()->GetNodes();
3149 const SwNode
* pStart
= lcl_NodeContext( pStartCrsr
->GetPoint()->nNode
.GetNode() );
3150 SwNodeIndex
aIdx( pStartCrsr
->GetPoint()->nNode
);
3151 SwNode
* pNode
= aNodes
.GoPrevious(&aIdx
);
3152 if( pNode
== NULL
|| lcl_NodeContext( *pNode
) != pStart
)
3153 aNodes
.GoNext( &aIdx
);
3154 if( pNode
== NULL
|| lcl_NodeContext( *pNode
) != pStart
)
3156 // If the start entry of the ring is invalid replace it with a
3157 // cursor pointing to the beginning of the first content node in the
3159 aIdx
= (*(aNodes
.GetEndOfContent().StartOfSectionNode()));
3160 pNode
= aNodes
.GoNext( &aIdx
);
3162 bool bFound
= (pNode
!= NULL
);
3164 OSL_ENSURE(bFound
, "no content node found");
3168 SwPaM
aTmpPam(*pNode
);
3169 *pStartCrsr
= aTmpPam
;
3175 // If at least one of the cursors in the ring have been deleted or replaced,
3176 // remove the table cursor.
3177 if (pTblCrsr
!= NULL
&& bChanged
)
3181 String
SwCrsrShell::GetCrsrDescr() const
3185 if (IsMultiSelection())
3186 aResult
+= String(SW_RES(STR_MULTISEL
));
3188 aResult
= GetDoc()->GetPaMDescr(*GetCrsr());
3195 static void lcl_FillRecognizerData( uno::Sequence
< rtl::OUString
>& rSmartTagTypes
,
3196 uno::Sequence
< uno::Reference
< container::XStringKeyMap
> >& rStringKeyMaps
,
3197 const SwWrongList
& rSmartTagList
, xub_StrLen nCurrent
)
3199 // Insert smart tag information
3200 std::vector
< rtl::OUString
> aSmartTagTypes
;
3201 std::vector
< uno::Reference
< container::XStringKeyMap
> > aStringKeyMaps
;
3203 for ( sal_uInt16 i
= 0; i
< rSmartTagList
.Count(); ++i
)
3205 const xub_StrLen nSTPos
= rSmartTagList
.Pos( i
);
3206 const xub_StrLen nSTLen
= rSmartTagList
.Len( i
);
3208 if ( nSTPos
<= nCurrent
&& nCurrent
< nSTPos
+ nSTLen
)
3210 const SwWrongArea
* pArea
= rSmartTagList
.GetElement( i
);
3213 aSmartTagTypes
.push_back( pArea
->maType
);
3214 aStringKeyMaps
.push_back( pArea
->mxPropertyBag
);
3219 if ( !aSmartTagTypes
.empty() )
3221 rSmartTagTypes
.realloc( aSmartTagTypes
.size() );
3222 rStringKeyMaps
.realloc( aSmartTagTypes
.size() );
3224 std::vector
< rtl::OUString
>::const_iterator aTypesIter
= aSmartTagTypes
.begin();
3226 for ( aTypesIter
= aSmartTagTypes
.begin(); aTypesIter
!= aSmartTagTypes
.end(); ++aTypesIter
)
3227 rSmartTagTypes
[i
++] = *aTypesIter
;
3229 std::vector
< uno::Reference
< container::XStringKeyMap
> >::const_iterator aMapsIter
= aStringKeyMaps
.begin();
3231 for ( aMapsIter
= aStringKeyMaps
.begin(); aMapsIter
!= aStringKeyMaps
.end(); ++aMapsIter
)
3232 rStringKeyMaps
[i
++] = *aMapsIter
;
3236 static void lcl_FillTextRange( uno::Reference
<text::XTextRange
>& rRange
,
3237 SwTxtNode
& rNode
, xub_StrLen nBegin
, xub_StrLen nLen
)
3239 // create SwPosition for nStartIndex
3240 SwIndex
aIndex( &rNode
, nBegin
);
3241 SwPosition
aStartPos( rNode
, aIndex
);
3243 // create SwPosition for nEndIndex
3244 SwPosition
aEndPos( aStartPos
);
3245 aEndPos
.nContent
= nBegin
+ nLen
;
3247 const uno::Reference
<text::XTextRange
> xRange
=
3248 SwXTextRange::CreateXTextRange(*rNode
.GetDoc(), aStartPos
, &aEndPos
);
3253 void SwCrsrShell::GetSmartTagTerm( uno::Sequence
< rtl::OUString
>& rSmartTagTypes
,
3254 uno::Sequence
< uno::Reference
< container::XStringKeyMap
> >& rStringKeyMaps
,
3255 uno::Reference
< text::XTextRange
>& rRange
) const
3257 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3260 SwPaM
* pCrsr
= GetCrsr();
3261 SwPosition
aPos( *pCrsr
->GetPoint() );
3262 SwTxtNode
*pNode
= aPos
.nNode
.GetNode().GetTxtNode();
3263 if ( pNode
&& !pNode
->IsInProtectSect() )
3265 const SwWrongList
*pSmartTagList
= pNode
->GetSmartTags();
3266 if ( pSmartTagList
)
3268 xub_StrLen nCurrent
= aPos
.nContent
.GetIndex();
3269 xub_StrLen nBegin
= nCurrent
;
3270 xub_StrLen nLen
= 1;
3272 if( pSmartTagList
->InWrongWord( nBegin
, nLen
) && !pNode
->IsSymbol(nBegin
) )
3274 const sal_uInt16 nIndex
= pSmartTagList
->GetWrongPos( nBegin
);
3275 const SwWrongList
* pSubList
= pSmartTagList
->SubList( nIndex
);
3278 pSmartTagList
= pSubList
;
3282 lcl_FillRecognizerData( rSmartTagTypes
, rStringKeyMaps
, *pSmartTagList
, nCurrent
);
3283 lcl_FillTextRange( rRange
, *pNode
, nBegin
, nLen
);
3289 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
3290 void SwCrsrShell::GetSmartTagTerm( const Point
& rPt
, SwRect
& rSelectRect
,
3291 uno::Sequence
< rtl::OUString
>& rSmartTagTypes
,
3292 uno::Sequence
< uno::Reference
< container::XStringKeyMap
> >& rStringKeyMaps
,
3293 uno::Reference
<text::XTextRange
>& rRange
)
3295 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3298 SwPaM
* pCrsr
= GetCrsr();
3299 SwPosition
aPos( *pCrsr
->GetPoint() );
3301 SwCrsrMoveState
eTmpState( MV_SETONLYTEXT
);
3302 SwSpecialPos aSpecialPos
;
3303 eTmpState
.pSpecialPos
= &aSpecialPos
;
3305 const SwWrongList
*pSmartTagList
;
3307 if( GetLayout()->GetCrsrOfst( &aPos
, aPt
, &eTmpState
) &&
3308 0 != (pNode
= aPos
.nNode
.GetNode().GetTxtNode()) &&
3309 0 != (pSmartTagList
= pNode
->GetSmartTags()) &&
3310 !pNode
->IsInProtectSect() )
3312 xub_StrLen nCurrent
= aPos
.nContent
.GetIndex();
3313 xub_StrLen nBegin
= nCurrent
;
3314 xub_StrLen nLen
= 1;
3316 if( pSmartTagList
->InWrongWord( nBegin
, nLen
) && !pNode
->IsSymbol(nBegin
) )
3318 const sal_uInt16 nIndex
= pSmartTagList
->GetWrongPos( nBegin
);
3319 const SwWrongList
* pSubList
= pSmartTagList
->SubList( nIndex
);
3322 pSmartTagList
= pSubList
;
3323 nCurrent
= eTmpState
.pSpecialPos
->nCharOfst
;
3326 lcl_FillRecognizerData( rSmartTagTypes
, rStringKeyMaps
, *pSmartTagList
, nCurrent
);
3327 lcl_FillTextRange( rRange
, *pNode
, nBegin
, nLen
);
3329 // get smarttag word
3330 String
aText( pNode
->GetTxt().Copy( nBegin
, nLen
) );
3332 //save the start and end positons of the line and the starting point
3335 xub_StrLen nLineStart
= GetCrsr()->GetPoint()->nContent
.GetIndex();
3337 xub_StrLen nLineEnd
= GetCrsr()->GetPoint()->nContent
.GetIndex();
3340 // make sure the selection build later from the data below does not
3341 // include "in word" character to the left and right in order to
3342 // preserve those. Therefore count those "in words" in order to
3343 // modify the selection accordingly.
3344 const sal_Unicode
* pChar
= aText
.GetBuffer();
3345 xub_StrLen nLeft
= 0;
3346 while (pChar
&& *pChar
++ == CH_TXTATR_INWORD
)
3348 pChar
= aText
.Len() ? aText
.GetBuffer() + aText
.Len() - 1 : 0;
3349 xub_StrLen nRight
= 0;
3350 while (pChar
&& *pChar
-- == CH_TXTATR_INWORD
)
3353 aPos
.nContent
= nBegin
+ nLeft
;
3355 *pCrsr
->GetPoint() = aPos
;
3357 ExtendSelection( sal_True
, nLen
- nLeft
- nRight
);
3358 // do not determine the rectangle in the current line
3359 xub_StrLen nWordStart
= (nBegin
+ nLeft
) < nLineStart
? nLineStart
: nBegin
+ nLeft
;
3360 // take one less than the line end - otherwise the next line would
3362 xub_StrLen nWordEnd
= (nBegin
+ nLen
- nLeft
- nRight
) > nLineEnd
? nLineEnd
: (nBegin
+ nLen
- nLeft
- nRight
);
3364 pCrsr
->DeleteMark();
3365 SwIndex
& rContent
= GetCrsr()->GetPoint()->nContent
;
3366 rContent
= nWordStart
;
3368 SwCrsrMoveState aState
;
3369 aState
.bRealWidth
= sal_True
;
3370 SwCntntNode
* pCntntNode
= pCrsr
->GetCntntNode();
3371 SwCntntFrm
*pCntntFrame
= pCntntNode
->getLayoutFrm( GetLayout(), &rPt
, pCrsr
->GetPoint(), sal_False
);
3373 pCntntFrame
->GetCharRect( aStartRect
, *pCrsr
->GetPoint(), &aState
);
3374 rContent
= nWordEnd
- 1;
3376 pCntntFrame
->GetCharRect( aEndRect
, *pCrsr
->GetPoint(),&aState
);
3377 rSelectRect
= aStartRect
.Union( aEndRect
);
3384 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */