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 <hintids.hxx>
21 #include <editeng/protitem.hxx>
22 #include <com/sun/star/i18n/WordType.hpp>
23 #include <com/sun/star/i18n/CharType.hpp>
24 #include <unotools/charclass.hxx>
25 #include <svl/ctloptions.hxx>
26 #include <swmodule.hxx>
27 #include <fmtcntnt.hxx>
28 #include <swtblfmt.hxx>
30 #include <unocrsr.hxx>
32 #include <IDocumentUndoRedo.hxx>
35 #include <section.hxx>
36 #include <swtable.hxx>
38 #include <rootfrm.hxx>
40 #include <scriptinfo.hxx>
41 #include <crstate.hxx>
45 #include <breakit.hxx>
46 #include <crsskip.hxx>
47 #include <vcl/msgbox.hxx>
49 #include <statstr.hrc>
50 #include <redline.hxx>
51 #include <xmloff/odffields.hxx>
53 using namespace ::com::sun::star::i18n
;
56 static const sal_uInt16 coSrchRplcThreshold
= 60000;
64 _PercentHdl( sal_uLong nStt
, sal_uLong nEnd
, SwDocShell
* pSh
)
68 if( 0 != ( bBack
= (nStt
> nEnd
)) )
70 sal_uLong n
= nStt
; nStt
= nEnd
; nEnd
= n
;
72 ::StartProgress( STR_STATSTR_SEARCH
, nStt
, nEnd
, 0 );
75 _PercentHdl( const SwPaM
& rPam
)
76 : pDSh( (SwDocShell
*)rPam
.GetDoc()->GetDocShell() )
79 if( rPam
.GetPoint()->nNode
== rPam
.GetMark()->nNode
)
82 nStt
= rPam
.GetMark()->nContent
.GetIndex();
83 nEnd
= rPam
.GetPoint()->nContent
.GetIndex();
88 nStt
= rPam
.GetMark()->nNode
.GetIndex();
89 nEnd
= rPam
.GetPoint()->nNode
.GetIndex();
92 if( 0 != ( bBack
= (nStt
> nEnd
)) )
94 sal_uLong n
= nStt
; nStt
= nEnd
; nEnd
= n
;
96 ::StartProgress( STR_STATSTR_SEARCH
, nStt
, nEnd
, pDSh
);
99 ~_PercentHdl() { ::EndProgress( pDSh
); }
101 void NextPos( sal_uLong nPos
) const
102 { ::SetProgressState( bBack
? nActPos
- nPos
: nPos
, pDSh
); }
104 void NextPos( SwPosition
& rPos
) const
108 nPos
= rPos
.nNode
.GetIndex();
110 nPos
= rPos
.nContent
.GetIndex();
111 ::SetProgressState( bBack
? nActPos
- nPos
: nPos
, pDSh
);
115 SwCursor::SwCursor( const SwPosition
&rPos
, SwPaM
* pRing
, bool bColumnSel
)
116 : SwPaM( rPos
, pRing
), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ),
117 mbColumnSelection( bColumnSel
)
121 // @@@ semantic: no copy ctor.
122 SwCursor::SwCursor( SwCursor
& rCpy
)
123 : SwPaM( rCpy
), pSavePos( 0 ), mnRowSpanOffset( rCpy
.mnRowSpanOffset
),
124 nCursorBidiLevel( rCpy
.nCursorBidiLevel
), mbColumnSelection( rCpy
.mbColumnSelection
)
128 SwCursor::~SwCursor()
132 _SwCursor_SavePos
* pNxt
= pSavePos
->pNext
;
138 SwCursor
* SwCursor::Create( SwPaM
* pRing
) const
140 return new SwCursor( *GetPoint(), pRing
, false );
143 bool SwCursor::IsReadOnlyAvailable() const
148 sal_Bool
SwCursor::IsSkipOverHiddenSections() const
153 sal_Bool
SwCursor::IsSkipOverProtectSections() const
155 return !IsReadOnlyAvailable();
158 // CreateNewSavePos is virtual so that derived classes of cursor can implement
159 // own SaveObjects if needed and validate them in the virtual check routines.
160 void SwCursor::SaveState()
162 _SwCursor_SavePos
* pNew
= CreateNewSavePos();
163 pNew
->pNext
= pSavePos
;
167 void SwCursor::RestoreState()
169 if( pSavePos
) // Robust
171 _SwCursor_SavePos
* pDel
= pSavePos
;
172 pSavePos
= pSavePos
->pNext
;
177 _SwCursor_SavePos
* SwCursor::CreateNewSavePos() const
179 return new _SwCursor_SavePos( *this );
182 /// determine if point is outside of the node-array's content area
183 sal_Bool
SwCursor::IsNoCntnt() const
185 return GetPoint()->nNode
.GetIndex() <
186 GetDoc()->GetNodes().GetEndOfExtras().GetIndex();
189 bool SwCursor::IsSelOvrCheck(int)
194 // extracted from IsSelOvr()
195 bool SwTableCursor::IsSelOvrCheck(int eFlags
)
197 SwNodes
& rNds
= GetDoc()->GetNodes();
198 // check sections of nodes array
199 if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION
& eFlags
)
202 SwNodeIndex
aOldPos( rNds
, GetSavePos()->nNode
);
203 if( !CheckNodesRange( aOldPos
, GetPoint()->nNode
, sal_True
))
205 GetPoint()->nNode
= aOldPos
;
206 GetPoint()->nContent
.Assign( GetCntntNode(), GetSavePos()->nCntnt
);
210 return SwCursor::IsSelOvrCheck(eFlags
);
213 sal_Bool
SwCursor::IsSelOvr( int eFlags
)
215 SwDoc
* pDoc
= GetDoc();
216 SwNodes
& rNds
= pDoc
->GetNodes();
218 sal_Bool bSkipOverHiddenSections
= IsSkipOverHiddenSections();
219 sal_Bool bSkipOverProtectSections
= IsSkipOverProtectSections();
221 if ( IsSelOvrCheck( eFlags
) )
226 if( pSavePos
->nNode
!= GetPoint()->nNode
.GetIndex() &&
227 // (1997) in UI-ReadOnly everything is allowed
228 ( !pDoc
->GetDocShell() || !pDoc
->GetDocShell()->IsReadOnlyUI() ))
230 // check new sections
231 SwNodeIndex
& rPtIdx
= GetPoint()->nNode
;
232 const SwSectionNode
* pSectNd
= rPtIdx
.GetNode().FindSectionNode();
234 ((bSkipOverHiddenSections
&& pSectNd
->GetSection().IsHiddenFlag() ) ||
235 (bSkipOverProtectSections
&& pSectNd
->GetSection().IsProtectFlag() )))
237 if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
& eFlags
) )
239 // then we're already done
244 // set cursor to new position:
245 SwNodeIndex
aIdx( rPtIdx
);
246 xub_StrLen nCntntPos
= pSavePos
->nCntnt
;
247 int bGoNxt
= pSavePos
->nNode
< rPtIdx
.GetIndex();
248 SwCntntNode
* pCNd
= bGoNxt
249 ? rNds
.GoNextSection( &rPtIdx
, bSkipOverHiddenSections
, bSkipOverProtectSections
)
250 : rNds
.GoPrevSection( &rPtIdx
, bSkipOverHiddenSections
, bSkipOverProtectSections
);
251 if( !pCNd
&& ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION
& eFlags
))
254 pCNd
= bGoNxt
? rNds
.GoNextSection( &rPtIdx
, bSkipOverHiddenSections
, bSkipOverProtectSections
)
255 : rNds
.GoPrevSection( &rPtIdx
, bSkipOverHiddenSections
, bSkipOverProtectSections
);
258 int bIsValidPos
= 0 != pCNd
;
259 sal_Bool bValidNodesRange
= bIsValidPos
&&
260 ::CheckNodesRange( rPtIdx
, aIdx
, sal_True
);
261 if( !bValidNodesRange
)
263 rPtIdx
= pSavePos
->nNode
;
264 if( 0 == ( pCNd
= rPtIdx
.GetNode().GetCntntNode() ) )
266 bIsValidPos
= sal_False
;
269 if( 0 == ( pCNd
= rPtIdx
.GetNode().GetCntntNode() ) )
271 // then to the beginning of the document
272 rPtIdx
= rNds
.GetEndOfExtras();
273 pCNd
= rNds
.GoNext( &rPtIdx
);
278 // register ContentIndex:
279 xub_StrLen nTmpPos
= bIsValidPos
? (bGoNxt
? 0 : pCNd
->Len()) : nCntntPos
;
280 GetPoint()->nContent
.Assign( pCNd
, nTmpPos
);
281 if( !bIsValidPos
|| !bValidNodesRange
||
282 IsInProtectTable( sal_True
) )
286 // is there a protected section in the section?
287 if( HasMark() && bSkipOverProtectSections
)
289 sal_uLong nSttIdx
= GetMark()->nNode
.GetIndex(),
290 nEndIdx
= GetPoint()->nNode
.GetIndex();
291 if( nEndIdx
<= nSttIdx
)
293 sal_uLong nTmp
= nSttIdx
;
298 const SwSectionFmts
& rFmts
= pDoc
->GetSections();
299 for( sal_uInt16 n
= 0; n
< rFmts
.size(); ++n
)
301 const SwSectionFmt
* pFmt
= rFmts
[n
];
302 const SvxProtectItem
& rProtect
= pFmt
->GetProtect();
303 if( rProtect
.IsCntntProtected() )
305 const SwFmtCntnt
& rCntnt
= pFmt
->GetCntnt(sal_False
);
306 OSL_ENSURE( rCntnt
.GetCntntIdx(), "No SectionNode?" );
307 sal_uLong nIdx
= rCntnt
.GetCntntIdx()->GetIndex();
308 if( nSttIdx
<= nIdx
&& nEndIdx
>= nIdx
)
310 // if it is no linked section then we cannot select it
311 const SwSection
& rSect
= *pFmt
->GetSection();
312 if( CONTENT_SECTION
== rSect
.GetType() )
324 const SwNode
* pNd
= &GetPoint()->nNode
.GetNode();
325 if( pNd
->IsCntntNode() && !dynamic_cast<SwUnoCrsr
*>(this) )
327 const SwCntntFrm
* pFrm
= ((SwCntntNode
*)pNd
)->getLayoutFrm( pDoc
->GetCurrentLayout() );
328 if( pFrm
&& pFrm
->IsValid() && 0 == pFrm
->Frm().Height() &&
329 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
& eFlags
) )
331 // skip to the next/prev valid paragraph with a layout
332 SwNodeIndex
& rPtIdx
= GetPoint()->nNode
;
333 int bGoNxt
= pSavePos
->nNode
< rPtIdx
.GetIndex();
334 while( 0 != ( pFrm
= ( bGoNxt
? pFrm
->GetNextCntntFrm()
335 : pFrm
->GetPrevCntntFrm() )) &&
336 0 == pFrm
->Frm().Height() )
339 // #i72394# skip to prev/next valid paragraph with a layout in case
340 // the first search did not succeed:
344 pFrm
= ((SwCntntNode
*)pNd
)->getLayoutFrm( pDoc
->GetCurrentLayout() );
345 while ( pFrm
&& 0 == pFrm
->Frm().Height() )
347 pFrm
= bGoNxt
? pFrm
->GetNextCntntFrm()
348 : pFrm
->GetPrevCntntFrm();
353 if( pFrm
&& 0 != (pCNd
= (SwCntntNode
*)pFrm
->GetNode()) )
355 // set this CntntNode as new position
359 // register ContentIndex:
360 xub_StrLen nTmpPos
= bGoNxt
? 0 : pCNd
->Len();
361 GetPoint()->nContent
.Assign( pCNd
, nTmpPos
);
363 if( IsInProtectTable( sal_True
) )
372 return sal_True
; // we need a frame
376 // is the cursor allowed to be in a protected node?
377 if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
& eFlags
) && !IsAtValidPos() )
387 // check for invalid sections
388 if( !::CheckNodesRange( GetMark()->nNode
, GetPoint()->nNode
, sal_True
))
392 return sal_True
; // we need a frame
395 const SwTableNode
* pPtNd
= pNd
->FindTableNode();
397 if( (pNd
= &GetMark()->nNode
.GetNode())->IsCntntNode() &&
398 !((SwCntntNode
*)pNd
)->getLayoutFrm( pDoc
->GetCurrentLayout() ) && !dynamic_cast<SwUnoCrsr
*>(this) )
402 return sal_True
; // we need a frame
405 const SwTableNode
* pMrkNd
= pNd
->FindTableNode();
407 // both in no or in same table node
408 if( ( !pMrkNd
&& !pPtNd
) || pPtNd
== pMrkNd
)
411 // in different tables or only mark in table
412 if( ( pPtNd
&& pMrkNd
) || pMrkNd
)
414 // not allowed, so go back to old position
416 // Crsr stays at old position
420 // Note: this cannot happen in TableMode
421 if( pPtNd
) // if only Point in Table then go behind/in front of table
423 if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
& eFlags
)
425 sal_Bool bSelTop
= GetPoint()->nNode
.GetIndex() <
426 (( nsSwCursorSelOverFlags::SELOVER_TOGGLE
& eFlags
) ? pSavePos
->nNode
427 : GetMark()->nNode
.GetIndex());
429 do { // loop for table after table
430 sal_uLong nSEIdx
= pPtNd
->EndOfSectionIndex();
431 sal_uLong nSttEndTbl
= nSEIdx
+ 1;
434 nSttEndTbl
= rNds
[ nSEIdx
]->StartOfSectionIndex() - 1;
436 GetPoint()->nNode
= nSttEndTbl
;
437 const SwNode
* pMyNd
= GetNode();
439 if( pMyNd
->IsSectionNode() || ( pMyNd
->IsEndNode() &&
440 pMyNd
->StartOfSectionNode()->IsSectionNode() ) )
443 ? rNds
.GoPrevSection( &GetPoint()->nNode
,sal_True
,sal_False
)
444 : rNds
.GoNextSection( &GetPoint()->nNode
,sal_True
,sal_False
);
446 /* #i12312# Handle failure of Go{Prev|Next}Section */
450 if( 0 != ( pPtNd
= pMyNd
->FindTableNode() ))
455 if( pMyNd
->IsCntntNode() &&
456 ::CheckNodesRange( GetMark()->nNode
,
457 GetPoint()->nNode
, sal_True
))
460 const SwTableNode
* pOuterTableNd
= pMyNd
->FindTableNode();
462 pMyNd
= pOuterTableNd
;
465 SwCntntNode
* pCNd
= (SwCntntNode
*)pMyNd
;
466 xub_StrLen nTmpPos
= bSelTop
? pCNd
->Len() : 0;
467 GetPoint()->nContent
.Assign( pCNd
, nTmpPos
);
472 ? ( !pMyNd
->IsEndNode() || 0 == ( pPtNd
= pMyNd
->FindTableNode() ))
473 : 0 == ( pPtNd
= pMyNd
->GetTableNode() ))
478 // stay on old position
486 #define IDX (*pCellStt)
492 sal_Bool
SwCursor::IsInProtectTable( sal_Bool bMove
, sal_Bool bChgCrsr
)
494 SwCntntNode
* pCNd
= GetCntntNode();
498 // No table, no protected cell:
499 const SwTableNode
* pTableNode
= pCNd
->FindTableNode();
503 // Current position == last save position?
504 if ( pSavePos
->nNode
== GetPoint()->nNode
.GetIndex() )
507 // Check for convered cell:
508 bool bInCoveredCell
= false;
509 const SwStartNode
* pTmpSttNode
= pCNd
->FindTableBoxStartNode();
510 OSL_ENSURE( pTmpSttNode
, "In table, therefore I expect to get a SwTableBoxStartNode" );
511 const SwTableBox
* pBox
= pTmpSttNode
? pTableNode
->GetTable().GetTblBox( pTmpSttNode
->GetIndex() ) : 0; //Robust #151355
512 if ( pBox
&& pBox
->getRowSpan() < 1 ) // Robust #151270
513 bInCoveredCell
= true;
515 // Positions of covered cells are not acceptable:
516 if ( !bInCoveredCell
)
518 // Position not protected?
519 if ( !pCNd
->IsProtect() )
522 // Cursor in protected cells allowed?
523 if ( IsReadOnlyAvailable() )
527 // If we reach this point, we are in a protected or covered table cell!
532 // restore the last save position
534 return sal_True
; // Crsr stays at old position
537 // We are in a protected table cell. Traverse top to bottom?
538 if( pSavePos
->nNode
< GetPoint()->nNode
.GetIndex() )
540 // search next valid box
541 // if there is another StartNode after the EndNode of a cell then
542 // there is another cell
544 SwNodeIndex
* pCellStt
= new SwNodeIndex( *GetNode()->
545 FindTableBoxStartNode()->EndOfSectionNode(), 1 );
547 SwNodeIndex
aCellStt( *GetNode()->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
549 sal_Bool bProt
= sal_True
;
552 if( !IDX
.GetNode().IsStartNode() )
555 if( 0 == ( pCNd
= IDX
.GetNode().GetCntntNode() ))
556 pCNd
= IDX
.GetNodes().GoNext( &IDX
);
557 if( 0 == ( bProt
= pCNd
->IsProtect() ))
559 IDX
.Assign( *pCNd
->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
563 if( !bProt
) // found free cell
565 GetPoint()->nNode
= IDX
;
569 SwCntntNode
* pTmpCNd
= GetCntntNode();
572 GetPoint()->nContent
.Assign( pTmpCNd
, 0 );
575 return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
576 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
);
578 // end of table, so go to next node
581 if( ( pNd
= &IDX
.GetNode())->IsEndNode() || HasMark())
583 // if only table in FlyFrame or SSelection then stay on old position
591 else if( pNd
->IsTableNode() && IDX
++ )
594 bProt
= sal_False
; // index is now on a content node
598 // search for the previous valid box
600 // if there is another EndNode in front of the StartNode than there
601 // exists a previous cell
603 SwNodeIndex
* pCellStt
= new SwNodeIndex(
604 *GetNode()->FindTableBoxStartNode(), -1 );
606 SwNodeIndex
aCellStt( *GetNode()->FindTableBoxStartNode(), -1 );
609 sal_Bool bProt
= sal_True
;
612 if( !( pNd
= &IDX
.GetNode())->IsEndNode() )
614 IDX
.Assign( *pNd
->StartOfSectionNode(), +1 );
615 if( 0 == ( pCNd
= IDX
.GetNode().GetCntntNode() ))
616 pCNd
= pNd
->GetNodes().GoNext( &IDX
);
617 if( 0 == ( bProt
= pCNd
->IsProtect() ))
619 IDX
.Assign( *pNd
->FindTableBoxStartNode(), -1 );
623 if( !bProt
) // found free cell
625 GetPoint()->nNode
= IDX
;
629 SwCntntNode
* pTmpCNd
= GetCntntNode();
632 GetPoint()->nContent
.Assign( pTmpCNd
, 0 );
635 return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
636 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
);
638 // at the beginning of a table, so go to next node
640 if( ( pNd
= &IDX
.GetNode())->IsStartNode() || HasMark() )
642 // if only table in FlyFrame or SSelection then stay on old position
650 else if( pNd
->StartOfSectionNode()->IsTableNode() && IDX
-- )
653 bProt
= sal_False
; // index is now on a content node
658 /// Return <true> if cursor can be set to this position
659 sal_Bool
SwCursor::IsAtValidPos( sal_Bool bPoint
) const
661 const SwDoc
* pDoc
= GetDoc();
662 const SwPosition
* pPos
= bPoint
? GetPoint() : GetMark();
663 const SwNode
* pNd
= &pPos
->nNode
.GetNode();
665 if( pNd
->IsCntntNode() && !((SwCntntNode
*)pNd
)->getLayoutFrm( pDoc
->GetCurrentLayout() ) &&
666 !dynamic_cast<const SwUnoCrsr
*>(this) )
671 // #i45129# - in UI-ReadOnly everything is allowed
672 if( !pDoc
->GetDocShell() || !pDoc
->GetDocShell()->IsReadOnlyUI() )
675 sal_Bool bCrsrInReadOnly
= IsReadOnlyAvailable();
676 if( !bCrsrInReadOnly
&& pNd
->IsProtect() )
679 const SwSectionNode
* pSectNd
= pNd
->FindSectionNode();
680 if( pSectNd
&& (pSectNd
->GetSection().IsHiddenFlag() ||
681 ( !bCrsrInReadOnly
&& pSectNd
->GetSection().IsProtectFlag() )))
687 void SwCursor::SaveTblBoxCntnt( const SwPosition
* ) {}
689 /// set range for search in document
690 SwMoveFnCollection
* SwCursor::MakeFindRange( SwDocPositions nStart
,
691 SwDocPositions nEnd
, SwPaM
* pRange
) const
694 FillFindPos( nStart
, *pRange
->GetMark() );
695 FillFindPos( nEnd
, *pRange
->GetPoint() );
697 // determine direction of search
698 return ( DOCPOS_START
== nStart
|| DOCPOS_OTHERSTART
== nStart
||
699 (DOCPOS_CURR
== nStart
&&
700 (DOCPOS_END
== nEnd
|| DOCPOS_OTHEREND
== nEnd
) ))
701 ? fnMoveForward
: fnMoveBackward
;
705 static sal_uLong
lcl_FindSelection( SwFindParas
& rParas
, SwCursor
* pCurCrsr
,
706 SwMoveFn fnMove
, SwCursor
*& pFndRing
,
707 SwPaM
& aRegion
, FindRanges eFndRngs
,
708 sal_Bool bInReadOnly
, sal_Bool
& bCancel
)
710 SwDoc
* pDoc
= pCurCrsr
->GetDoc();
711 bool const bDoesUndo
= pDoc
->GetIDocumentUndoRedo().DoesUndo();
713 sal_uLong nFound
= 0;
714 int bSrchBkwrd
= fnMove
== fnMoveBackward
, bEnde
= sal_False
;
715 SwPaM
*pTmpCrsr
= pCurCrsr
, *pSaveCrsr
= pCurCrsr
;
717 // only create progress bar for ShellCrsr
718 bool bIsUnoCrsr
= 0 != dynamic_cast<SwUnoCrsr
*>(pCurCrsr
);
719 _PercentHdl
* pPHdl
= 0;
720 sal_uInt16 nCrsrCnt
= 0;
721 if( FND_IN_SEL
& eFndRngs
)
723 while( pCurCrsr
!= ( pTmpCrsr
= (SwPaM
*)pTmpCrsr
->GetNext() ))
725 if( nCrsrCnt
&& !bIsUnoCrsr
)
726 pPHdl
= new _PercentHdl( 0, nCrsrCnt
, pDoc
->GetDocShell() );
729 pSaveCrsr
= (SwPaM
*)pSaveCrsr
->GetPrev();
733 // independent from search direction: SPoint is always bigger than mark
734 // if the search area is valid
735 SwPosition
*pSttPos
= aRegion
.GetMark(),
736 *pEndPos
= aRegion
.GetPoint();
737 *pSttPos
= *pTmpCrsr
->Start();
738 *pEndPos
= *pTmpCrsr
->End();
742 if( !nCrsrCnt
&& !pPHdl
&& !bIsUnoCrsr
)
743 pPHdl
= new _PercentHdl( aRegion
);
745 // as long as found and not at same position
746 while( *pSttPos
<= *pEndPos
&&
747 0 != ( nFndRet
= rParas
.Find( pCurCrsr
, fnMove
,
748 &aRegion
, bInReadOnly
)) &&
750 *pFndRing
->GetPoint() != *pCurCrsr
->GetPoint() ||
751 *pFndRing
->GetMark() != *pCurCrsr
->GetMark() ))
753 if( !( FIND_NO_RING
& nFndRet
))
755 // #i24084# - create ring similar to the one in CreateCrsr
756 SwCursor
* pNew
= pCurCrsr
->Create( pFndRing
);
761 *pNew
->GetMark() = *pCurCrsr
->GetMark();
766 if( !( eFndRngs
& FND_IN_SELALL
) )
772 if ((coSrchRplcThreshold
== nFound
)
773 && pDoc
->GetIDocumentUndoRedo().DoesUndo()
774 && rParas
.IsReplaceMode())
776 short nRet
= pCurCrsr
->MaxReplaceArived();
777 if( RET_YES
== nRet
)
779 pDoc
->GetIDocumentUndoRedo().DelAllUndoObj();
780 pDoc
->GetIDocumentUndoRedo().DoUndo(false);
785 if(RET_CANCEL
== nRet
)
794 // move pEndPos in front of the found area
795 *pEndPos
= *pCurCrsr
->Start();
797 // move pSttPos behind the found area
798 *pSttPos
= *pCurCrsr
->End();
800 if( *pSttPos
== *pEndPos
)
801 // in area but at the end => done
804 if( !nCrsrCnt
&& pPHdl
)
806 pPHdl
->NextPos( *aRegion
.GetMark() );
810 if( bEnde
|| !( eFndRngs
& ( FND_IN_SELALL
| FND_IN_SEL
)) )
813 pTmpCrsr
= ((SwPaM
*)pTmpCrsr
->GetNext());
814 if( nCrsrCnt
&& pPHdl
)
816 pPHdl
->NextPos( ++pPHdl
->nActPos
);
819 } while( pTmpCrsr
!= pSaveCrsr
);
821 if( nFound
&& !pFndRing
) // if no ring should be created
822 pFndRing
= pCurCrsr
->Create();
825 pDoc
->GetIDocumentUndoRedo().DoUndo(bDoesUndo
);
830 static int lcl_MakeSelFwrd( const SwNode
& rSttNd
, const SwNode
& rEndNd
,
831 SwPaM
& rPam
, int bFirst
)
833 if( rSttNd
.GetIndex() + 1 == rEndNd
.GetIndex() )
836 SwNodes
& rNds
= rPam
.GetDoc()->GetNodes();
841 rPam
.GetPoint()->nNode
= rSttNd
;
842 pCNd
= rNds
.GoNext( &rPam
.GetPoint()->nNode
);
845 pCNd
->MakeStartIndex( &rPam
.GetPoint()->nContent
);
847 else if( rSttNd
.GetIndex() > rPam
.GetPoint()->nNode
.GetIndex() ||
848 rPam
.GetPoint()->nNode
.GetIndex() >= rEndNd
.GetIndex() )
849 // not in this section
853 rPam
.GetPoint()->nNode
= rEndNd
;
854 pCNd
= rNds
.GoPrevious( &rPam
.GetPoint()->nNode
);
857 pCNd
->MakeEndIndex( &rPam
.GetPoint()->nContent
);
859 return *rPam
.GetMark() < *rPam
.GetPoint();
863 static int lcl_MakeSelBkwrd( const SwNode
& rSttNd
, const SwNode
& rEndNd
,
864 SwPaM
& rPam
, int bFirst
)
866 if( rEndNd
.GetIndex() + 1 == rSttNd
.GetIndex() )
869 SwNodes
& rNds
= rPam
.GetDoc()->GetNodes();
874 rPam
.GetPoint()->nNode
= rSttNd
;
875 pCNd
= rNds
.GoPrevious( &rPam
.GetPoint()->nNode
);
878 pCNd
->MakeEndIndex( &rPam
.GetPoint()->nContent
);
880 else if( rEndNd
.GetIndex() > rPam
.GetPoint()->nNode
.GetIndex() ||
881 rPam
.GetPoint()->nNode
.GetIndex() >= rSttNd
.GetIndex() )
882 return sal_False
; // not in this section
885 rPam
.GetPoint()->nNode
= rEndNd
;
886 pCNd
= rNds
.GoNext( &rPam
.GetPoint()->nNode
);
889 pCNd
->MakeStartIndex( &rPam
.GetPoint()->nContent
);
891 return *rPam
.GetPoint() < *rPam
.GetMark();
894 // this method "searches" for all use cases because in SwFindParas is always the
895 // correct parameters and respective search method
896 sal_uLong
SwCursor::FindAll( SwFindParas
& rParas
,
897 SwDocPositions nStart
, SwDocPositions nEnde
,
898 FindRanges eFndRngs
, sal_Bool
& bCancel
)
901 SwCrsrSaveState
aSaveState( *this );
903 // create region without adding it to the ring
904 SwPaM
aRegion( *GetPoint() );
905 SwMoveFn fnMove
= MakeFindRange( nStart
, nEnde
, &aRegion
);
907 sal_uLong nFound
= 0;
908 int bMvBkwrd
= fnMove
== fnMoveBackward
;
909 sal_Bool bInReadOnly
= IsReadOnlyAvailable();
911 SwCursor
* pFndRing
= 0;
912 SwNodes
& rNds
= GetDoc()->GetNodes();
914 // search in sections?
915 if( FND_IN_SEL
& eFndRngs
)
917 // if string was not found in region then get all sections (cursors
919 if( 0 == ( nFound
= lcl_FindSelection( rParas
, this, fnMove
,
920 pFndRing
, aRegion
, eFndRngs
,
921 bInReadOnly
, bCancel
) ))
924 // found string at least once; it's all in new Crsr ring thus delete old one
925 while( GetNext() != this )
928 *GetPoint() = *pFndRing
->GetPoint();
930 *GetMark() = *pFndRing
->GetMark();
931 pFndRing
->MoveRingTo( this );
934 else if( FND_IN_OTHER
& eFndRngs
)
936 // put cursor as copy of current into ring
937 // chaining points always to first created, so forward
938 SAL_WNODEPRECATED_DECLARATIONS_PUSH
939 std::auto_ptr
< SwCursor
> pSav( Create( this ) ); // save the current cursor
940 SAL_WNODEPRECATED_DECLARATIONS_POP
942 // if already outside of body text search from this position or start at
945 ? lcl_MakeSelBkwrd( rNds
.GetEndOfExtras(),
946 *rNds
.GetEndOfPostIts().StartOfSectionNode(),
947 *this, rNds
.GetEndOfExtras().GetIndex() >=
948 GetPoint()->nNode
.GetIndex() )
949 : lcl_MakeSelFwrd( *rNds
.GetEndOfPostIts().StartOfSectionNode(),
950 rNds
.GetEndOfExtras(), *this,
951 rNds
.GetEndOfExtras().GetIndex() >=
952 GetPoint()->nNode
.GetIndex() ))
954 nFound
= lcl_FindSelection( rParas
, this, fnMove
, pFndRing
,
955 aRegion
, eFndRngs
, bInReadOnly
, bCancel
);
960 // put back the old one
961 *GetPoint() = *pSav
->GetPoint();
962 if( pSav
->HasMark() )
965 *GetMark() = *pSav
->GetMark();
973 if( !( FND_IN_SELALL
& eFndRngs
))
975 // there should only be a single one, thus add it
976 // independent from search direction: SPoint is always bigger than
977 // mark if the search area is valid
978 *GetPoint() = *pFndRing
->GetPoint();
980 *GetMark() = *pFndRing
->GetMark();
984 // found string at least once; it's all in new Crsr ring thus delete old one
985 while( GetNext() != this )
988 *GetPoint() = *pFndRing
->GetPoint();
990 *GetMark() = *pFndRing
->GetMark();
991 pFndRing
->MoveRingTo( this );
995 else if( FND_IN_SELALL
& eFndRngs
)
997 SAL_WNODEPRECATED_DECLARATIONS_PUSH
998 ::std::auto_ptr
< SwCursor
> pSav( Create( this ) ); // save the current cursor
999 SAL_WNODEPRECATED_DECLARATIONS_POP
1001 const SwNode
* pSttNd
= ( FND_IN_BODYONLY
& eFndRngs
)
1002 ? rNds
.GetEndOfContent().StartOfSectionNode()
1003 : rNds
.GetEndOfPostIts().StartOfSectionNode();
1006 ? lcl_MakeSelBkwrd( rNds
.GetEndOfContent(), *pSttNd
,*this, sal_False
)
1007 : lcl_MakeSelFwrd( *pSttNd
, rNds
.GetEndOfContent(), *this, sal_False
))
1009 nFound
= lcl_FindSelection( rParas
, this, fnMove
, pFndRing
,
1010 aRegion
, eFndRngs
, bInReadOnly
, bCancel
);
1015 // put back the old one
1016 *GetPoint() = *pSav
->GetPoint();
1017 if( pSav
->HasMark() )
1020 *GetMark() = *pSav
->GetMark();
1027 while( GetNext() != this )
1030 *GetPoint() = *pFndRing
->GetPoint();
1032 *GetMark() = *pFndRing
->GetMark();
1033 pFndRing
->MoveRingTo( this );
1038 // if a GetMark is set then keep the GetMark of the found object
1039 // This allows spanning an area with this search.
1040 SwPosition
aMarkPos( *GetMark() );
1041 int bMarkPos
= HasMark() && !eFndRngs
;
1043 if( 0 != (nFound
= rParas
.Find( this, fnMove
,
1044 &aRegion
, bInReadOnly
) ? 1 : 0)
1046 *GetMark() = aMarkPos
;
1049 if( nFound
&& SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
) )
1055 void SwCursor::FillFindPos( SwDocPositions ePos
, SwPosition
& rPos
) const
1057 bool bIsStart
= true;
1058 SwCntntNode
* pCNd
= 0;
1059 SwNodes
& rNds
= GetDoc()->GetNodes();
1064 rPos
.nNode
= *rNds
.GetEndOfContent().StartOfSectionNode();
1065 pCNd
= rNds
.GoNext( &rPos
.nNode
);
1069 rPos
.nNode
= rNds
.GetEndOfContent();
1070 pCNd
= rNds
.GoPrevious( &rPos
.nNode
);
1074 case DOCPOS_OTHERSTART
:
1075 rPos
.nNode
= *rNds
[ sal_uLong(0) ];
1076 pCNd
= rNds
.GoNext( &rPos
.nNode
);
1079 case DOCPOS_OTHEREND
:
1080 rPos
.nNode
= *rNds
.GetEndOfContent().StartOfSectionNode();
1081 pCNd
= rNds
.GoPrevious( &rPos
.nNode
);
1090 xub_StrLen nCPos
= 0;
1092 nCPos
= pCNd
->Len();
1093 rPos
.nContent
.Assign( pCNd
, nCPos
);
1097 short SwCursor::MaxReplaceArived()
1103 sal_Bool
SwCursor::IsStartWord( sal_Int16 nWordType
) const
1105 return IsStartWordWT( nWordType
);
1108 sal_Bool
SwCursor::IsEndWord( sal_Int16 nWordType
) const
1110 return IsEndWordWT( nWordType
);
1113 sal_Bool
SwCursor::IsInWord( sal_Int16 nWordType
) const
1115 return IsInWordWT( nWordType
);
1118 sal_Bool
SwCursor::GoStartWord()
1120 return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES
);
1123 sal_Bool
SwCursor::GoEndWord()
1125 return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES
);
1128 sal_Bool
SwCursor::GoNextWord()
1130 return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES
);
1133 sal_Bool
SwCursor::GoPrevWord()
1135 return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES
);
1138 sal_Bool
SwCursor::SelectWord( ViewShell
* pViewShell
, const Point
* pPt
)
1140 return SelectWordWT( pViewShell
, WordType::ANYWORD_IGNOREWHITESPACES
, pPt
);
1143 sal_Bool
SwCursor::IsStartWordWT( sal_Int16 nWordType
) const
1145 sal_Bool bRet
= sal_False
;
1146 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1147 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1149 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1150 bRet
= pBreakIt
->GetBreakIter()->isBeginWord(
1151 pTxtNd
->GetTxt(), nPtPos
,
1152 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
)),
1158 sal_Bool
SwCursor::IsEndWordWT( sal_Int16 nWordType
) const
1160 sal_Bool bRet
= sal_False
;
1161 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1162 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1164 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1165 bRet
= pBreakIt
->GetBreakIter()->isEndWord(
1166 pTxtNd
->GetTxt(), nPtPos
,
1167 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
) ),
1174 sal_Bool
SwCursor::IsInWordWT( sal_Int16 nWordType
) const
1176 sal_Bool bRet
= sal_False
;
1177 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1178 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1180 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1181 Boundary aBoundary
= pBreakIt
->GetBreakIter()->getWordBoundary(
1182 pTxtNd
->GetTxt(), nPtPos
,
1183 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
) ),
1187 bRet
= aBoundary
.startPos
!= aBoundary
.endPos
&&
1188 aBoundary
.startPos
<= nPtPos
&&
1189 nPtPos
<= aBoundary
.endPos
;
1192 const CharClass
& rCC
= GetAppCharClass();
1193 bRet
= rCC
.isLetterNumeric( pTxtNd
->GetTxt(), static_cast<xub_StrLen
>(aBoundary
.startPos
) );
1199 sal_Bool
SwCursor::IsStartEndSentence( bool bEnd
) const
1201 sal_Bool bRet
= bEnd
?
1202 GetCntntNode() && GetPoint()->nContent
== GetCntntNode()->Len() :
1203 GetPoint()->nContent
.GetIndex() == 0;
1207 SwCursor
aCrsr(*GetPoint(), 0, false);
1208 SwPosition aOrigPos
= *aCrsr
.GetPoint();
1209 aCrsr
.GoSentence( bEnd
? SwCursor::END_SENT
: SwCursor::START_SENT
);
1210 bRet
= aOrigPos
== *aCrsr
.GetPoint();
1216 sal_Bool
SwCursor::GoStartWordWT( sal_Int16 nWordType
)
1218 sal_Bool bRet
= sal_False
;
1219 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1220 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1222 SwCrsrSaveState
aSave( *this );
1223 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1224 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->getWordBoundary(
1225 pTxtNd
->GetTxt(), nPtPos
,
1226 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
) ),
1228 sal_False
).startPos
;
1230 if( nPtPos
< pTxtNd
->GetTxt().Len() )
1232 GetPoint()->nContent
= nPtPos
;
1240 sal_Bool
SwCursor::GoEndWordWT( sal_Int16 nWordType
)
1242 sal_Bool bRet
= sal_False
;
1243 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1244 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1246 SwCrsrSaveState
aSave( *this );
1247 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1248 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->getWordBoundary(
1249 pTxtNd
->GetTxt(), nPtPos
,
1250 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
) ),
1254 if( nPtPos
<= pTxtNd
->GetTxt().Len() &&
1255 GetPoint()->nContent
.GetIndex() != nPtPos
)
1257 GetPoint()->nContent
= nPtPos
;
1265 sal_Bool
SwCursor::GoNextWordWT( sal_Int16 nWordType
)
1267 sal_Bool bRet
= sal_False
;
1268 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1269 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1271 SwCrsrSaveState
aSave( *this );
1272 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1274 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->nextWord(
1275 pTxtNd
->GetTxt(), nPtPos
,
1276 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
, 1 ) ),
1277 nWordType
).startPos
;
1279 if( nPtPos
< pTxtNd
->GetTxt().Len() )
1281 GetPoint()->nContent
= nPtPos
;
1289 sal_Bool
SwCursor::GoPrevWordWT( sal_Int16 nWordType
)
1291 sal_Bool bRet
= sal_False
;
1292 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1293 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1295 SwCrsrSaveState
aSave( *this );
1296 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1297 const xub_StrLen nPtStart
= nPtPos
;
1301 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->previousWord(
1302 pTxtNd
->GetTxt(), nPtStart
,
1303 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
, 1 ) ),
1304 nWordType
).startPos
;
1306 if( nPtPos
< pTxtNd
->GetTxt().Len() )
1308 GetPoint()->nContent
= nPtPos
;
1316 sal_Bool
SwCursor::SelectWordWT( ViewShell
* pViewShell
, sal_Int16 nWordType
, const Point
* pPt
)
1318 SwCrsrSaveState
aSave( *this );
1320 sal_Bool bRet
= sal_False
;
1321 sal_Bool bForward
= sal_True
;
1323 const SwRootFrm
* pLayout
= pViewShell
->GetLayout();
1324 if( pPt
&& 0 != pLayout
)
1326 // set the cursor to the layout position
1328 pLayout
->GetCrsrOfst( GetPoint(), aPt
);
1329 } //swmod 071107 //swmod 071225
1331 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1332 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1334 // Should we select the whole fieldmark?
1335 const IDocumentMarkAccess
* pMarksAccess
= GetDoc()->getIDocumentMarkAccess( );
1336 sw::mark::IFieldmark
* pMark
= GetPoint() ? pMarksAccess
->getFieldmarkFor( *GetPoint( ) ) : NULL
;
1337 if ( pMark
&& pMark
->GetFieldname() != ODF_COMMENTRANGE
)
1339 const SwPosition rStart
= pMark
->GetMarkStart();
1340 GetPoint()->nNode
= rStart
.nNode
;
1341 GetPoint()->nContent
= rStart
.nContent
;
1342 GetPoint()->nContent
++; // Don't select the start delimiter
1344 const SwPosition rEnd
= pMark
->GetMarkEnd();
1346 if ( rStart
!= rEnd
)
1349 GetMark()->nNode
= rEnd
.nNode
;
1350 GetMark()->nContent
= rEnd
.nContent
;
1351 GetMark()->nContent
--; //Don't select the end delimiter
1357 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1358 Boundary
aBndry( pBreakIt
->GetBreakIter()->getWordBoundary(
1359 pTxtNd
->GetTxt(), nPtPos
,
1360 pBreakIt
->GetLocale( pTxtNd
->GetLang( nPtPos
) ),
1364 if( aBndry
.startPos
!= aBndry
.endPos
)
1366 GetPoint()->nContent
= (xub_StrLen
)aBndry
.endPos
;
1370 GetMark()->nContent
= (xub_StrLen
)aBndry
.startPos
;
1387 static String
lcl_MaskDeletedRedlines( const SwTxtNode
* pTxtNd
)
1392 //mask deleted redlines
1393 String
sNodeText(pTxtNd
->GetTxt());
1394 const SwDoc
& rDoc
= *pTxtNd
->GetDoc();
1395 const bool nShowChg
= IDocumentRedlineAccess::IsShowChanges( rDoc
.GetRedlineMode() );
1398 sal_uInt16 nAct
= rDoc
.GetRedlinePos( *pTxtNd
, USHRT_MAX
);
1399 for ( ; nAct
< rDoc
.GetRedlineTbl().size(); nAct
++ )
1401 const SwRedline
* pRed
= rDoc
.GetRedlineTbl()[ nAct
];
1402 if ( pRed
->Start()->nNode
> pTxtNd
->GetIndex() )
1405 if( nsRedlineType_t::REDLINE_DELETE
== pRed
->GetType() )
1407 xub_StrLen nStart
, nEnd
;
1408 pRed
->CalcStartEnd( pTxtNd
->GetIndex(), nStart
, nEnd
);
1410 while ( nStart
< nEnd
&& nStart
< sNodeText
.Len() )
1411 sNodeText
.SetChar( nStart
++, CH_TXTATR_INWORD
);
1420 sal_Bool
SwCursor::GoSentence( SentenceMoveType eMoveType
)
1422 sal_Bool bRet
= sal_False
;
1423 const SwTxtNode
* pTxtNd
= GetNode()->GetTxtNode();
1424 if( pTxtNd
&& pBreakIt
->GetBreakIter().is() )
1426 String
sNodeText( lcl_MaskDeletedRedlines( pTxtNd
) );
1428 SwCrsrSaveState
aSave( *this );
1429 xub_StrLen nPtPos
= GetPoint()->nContent
.GetIndex();
1430 switch ( eMoveType
)
1432 case START_SENT
: /* when modifying: see also ExpandToSentenceBorders below! */
1433 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->beginOfSentence(
1435 nPtPos
, pBreakIt
->GetLocale(
1436 pTxtNd
->GetLang( nPtPos
) ));
1438 case END_SENT
: /* when modifying: see also ExpandToSentenceBorders below! */
1439 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->endOfSentence(
1441 nPtPos
, pBreakIt
->GetLocale(
1442 pTxtNd
->GetLang( nPtPos
) ));
1446 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->endOfSentence(
1448 nPtPos
, pBreakIt
->GetLocale(
1449 pTxtNd
->GetLang( nPtPos
) ));
1450 while (nPtPos
!= (sal_uInt16
) -1 && ++nPtPos
< sNodeText
.Len()
1451 && sNodeText
.GetChar(nPtPos
)== ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ )
1456 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->beginOfSentence(
1458 nPtPos
, pBreakIt
->GetLocale(
1459 pTxtNd
->GetLang( nPtPos
) ));
1461 return sal_False
; // the previous sentence is not in this paragraph
1463 nPtPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->beginOfSentence(
1465 nPtPos
- 1, pBreakIt
->GetLocale(
1466 pTxtNd
->GetLang( nPtPos
) ));
1470 // it is allowed to place the PaM just behind the last
1471 // character in the text thus <= ...Len
1472 if( nPtPos
<= pTxtNd
->GetTxt().Len() )
1474 GetPoint()->nContent
= nPtPos
;
1483 sal_Bool
SwCursor::ExpandToSentenceBorders()
1485 sal_Bool bRes
= sal_False
;
1486 const SwTxtNode
* pStartNd
= Start()->nNode
.GetNode().GetTxtNode();
1487 const SwTxtNode
* pEndNd
= End()->nNode
.GetNode().GetTxtNode();
1488 if (pStartNd
&& pEndNd
&& pBreakIt
->GetBreakIter().is())
1493 String
sStartText( lcl_MaskDeletedRedlines( pStartNd
) );
1494 String
sEndText( pStartNd
== pEndNd
? sStartText
: lcl_MaskDeletedRedlines( pEndNd
) );
1496 SwCrsrSaveState
aSave( *this );
1497 xub_StrLen nStartPos
= Start()->nContent
.GetIndex();
1498 xub_StrLen nEndPos
= End()->nContent
.GetIndex();
1500 nStartPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->beginOfSentence(
1501 sStartText
, nStartPos
,
1502 pBreakIt
->GetLocale( pStartNd
->GetLang( nStartPos
) ) );
1503 nEndPos
= (xub_StrLen
)pBreakIt
->GetBreakIter()->endOfSentence(
1505 pBreakIt
->GetLocale( pEndNd
->GetLang( nEndPos
) ) );
1507 // it is allowed to place the PaM just behind the last
1508 // character in the text thus <= ...Len
1509 bool bChanged
= false;
1510 if (nStartPos
<= pStartNd
->GetTxt().Len())
1512 GetMark()->nContent
= nStartPos
;
1515 if (nEndPos
<= pEndNd
->GetTxt().Len())
1517 GetPoint()->nContent
= nEndPos
;
1520 if (bChanged
&& !IsSelOvr())
1527 sal_Bool
SwTableCursor::LeftRight( sal_Bool bLeft
, sal_uInt16 nCnt
, sal_uInt16
/*nMode*/,
1528 sal_Bool
/*bVisualAllowed*/, sal_Bool
/*bSkipHidden*/, sal_Bool
/*bInsertCrsr*/ )
1530 return bLeft
? GoPrevCell( nCnt
)
1531 : GoNextCell( nCnt
);
1535 // calculate cursor bidi level: extracted from LeftRight()
1537 SwCursor::DoSetBidiLevelLeftRight(
1538 sal_Bool
& io_rbLeft
, sal_Bool bVisualAllowed
, sal_Bool bInsertCrsr
)
1540 // calculate cursor bidi level
1541 const SwCntntFrm
* pSttFrm
= NULL
;
1542 SwNode
& rNode
= GetPoint()->nNode
.GetNode();
1544 if( rNode
.IsTxtNode() )
1546 const SwTxtNode
& rTNd
= *rNode
.GetTxtNode();
1547 SwIndex
& rIdx
= GetPoint()->nContent
;
1548 xub_StrLen nPos
= rIdx
.GetIndex();
1550 const SvtCTLOptions
& rCTLOptions
= SW_MOD()->GetCTLOptions();
1551 if ( bVisualAllowed
&& rCTLOptions
.IsCTLFontEnabled() &&
1552 SvtCTLOptions::MOVEMENT_VISUAL
==
1553 rCTLOptions
.GetCTLCursorMovement() )
1555 // for visual cursor travelling (used in bidi layout)
1556 // we first have to convert the logic to a visual position
1558 pSttFrm
= rTNd
.getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1561 sal_uInt8 nCrsrLevel
= GetCrsrBidiLevel();
1562 sal_Bool bForward
= ! io_rbLeft
;
1563 ((SwTxtFrm
*)pSttFrm
)->PrepareVisualMove( nPos
, nCrsrLevel
,
1564 bForward
, bInsertCrsr
);
1566 SetCrsrBidiLevel( nCrsrLevel
);
1567 io_rbLeft
= ! bForward
;
1572 const SwScriptInfo
* pSI
= SwScriptInfo::GetScriptInfo( rTNd
);
1575 const xub_StrLen nMoveOverPos
= io_rbLeft
?
1576 ( nPos
? nPos
- 1 : 0 ) :
1578 SetCrsrBidiLevel( pSI
->DirType( nMoveOverPos
) );
1585 sal_Bool
SwCursor::LeftRight( sal_Bool bLeft
, sal_uInt16 nCnt
, sal_uInt16 nMode
,
1586 sal_Bool bVisualAllowed
,sal_Bool bSkipHidden
, sal_Bool bInsertCrsr
)
1588 // calculate cursor bidi level
1589 SwNode
& rNode
= GetPoint()->nNode
.GetNode();
1590 const SwCntntFrm
* pSttFrm
= // may side-effect bLeft!
1591 DoSetBidiLevelLeftRight(bLeft
, bVisualAllowed
, bInsertCrsr
);
1593 // can the cursor be moved n times?
1594 SwCrsrSaveState
aSave( *this );
1595 SwMoveFn fnMove
= bLeft
? fnMoveBackward
: fnMoveForward
;
1599 fnGo
= CRSR_SKIP_CELLS
== nMode
? fnGoCntntCellsSkipHidden
: fnGoCntntSkipHidden
;
1601 fnGo
= CRSR_SKIP_CELLS
== nMode
? fnGoCntntCells
: fnGoCntnt
;
1605 SwNodeIndex
aOldNodeIdx( GetPoint()->nNode
);
1607 bool bSuccess
= Move( fnMove
, fnGo
);
1611 // If we were located inside a covered cell but our position has been
1612 // corrected, we check if the last move has moved the cursor to a
1613 // different table cell. In this case we set the cursor to the stored
1614 // covered position and redo the move:
1615 if ( mnRowSpanOffset
)
1617 const SwNode
* pOldTabBoxSttNode
= aOldNodeIdx
.GetNode().FindTableBoxStartNode();
1618 const SwTableNode
* pOldTabSttNode
= pOldTabBoxSttNode
? pOldTabBoxSttNode
->FindTableNode() : 0;
1619 const SwNode
* pNewTabBoxSttNode
= GetPoint()->nNode
.GetNode().FindTableBoxStartNode();
1620 const SwTableNode
* pNewTabSttNode
= pNewTabBoxSttNode
? pNewTabBoxSttNode
->FindTableNode() : 0;
1622 const bool bCellChanged
= pOldTabSttNode
&& pNewTabSttNode
&&
1623 pOldTabSttNode
== pNewTabSttNode
&&
1624 pOldTabBoxSttNode
&& pNewTabBoxSttNode
&&
1625 pOldTabBoxSttNode
!= pNewTabBoxSttNode
;
1629 // Set cursor to start/end of covered cell:
1630 SwTableBox
* pTableBox
= pOldTabBoxSttNode
->GetTblBox();
1631 if ( pTableBox
&& pTableBox
->getRowSpan() > 1 )
1633 pTableBox
= & pTableBox
->FindEndOfRowSpan( pOldTabSttNode
->GetTable(), (sal_uInt16
)(pTableBox
->getRowSpan() + mnRowSpanOffset
) );
1634 SwNodeIndex
& rPtIdx
= GetPoint()->nNode
;
1635 SwNodeIndex
aNewIdx( *pTableBox
->GetSttNd() );
1638 GetDoc()->GetNodes().GoNextSection( &rPtIdx
, sal_False
, sal_False
);
1639 SwCntntNode
* pCntntNode
= GetCntntNode();
1642 const xub_StrLen nTmpPos
= bLeft
? pCntntNode
->Len() : 0;
1643 GetPoint()->nContent
.Assign( pCntntNode
, nTmpPos
);
1646 bSuccess
= Move( fnMove
, fnGo
);
1652 mnRowSpanOffset
= 0;
1656 // Check if I'm inside a covered cell. Correct cursor if necessary and
1657 // store covered cell:
1658 const SwNode
* pTableBoxStartNode
= GetPoint()->nNode
.GetNode().FindTableBoxStartNode();
1659 if ( pTableBoxStartNode
)
1661 const SwTableBox
* pTableBox
= pTableBoxStartNode
->GetTblBox();
1662 if ( pTableBox
&& pTableBox
->getRowSpan() < 1 )
1664 // Store the row span offset:
1665 mnRowSpanOffset
= pTableBox
->getRowSpan();
1667 // Move cursor to non-covered cell:
1668 const SwTableNode
* pTblNd
= pTableBoxStartNode
->FindTableNode();
1669 pTableBox
= & pTableBox
->FindStartOfRowSpan( pTblNd
->GetTable(), USHRT_MAX
);
1670 SwNodeIndex
& rPtIdx
= GetPoint()->nNode
;
1671 SwNodeIndex
aNewIdx( *pTableBox
->GetSttNd() );
1674 GetDoc()->GetNodes().GoNextSection( &rPtIdx
, sal_False
, sal_False
);
1675 SwCntntNode
* pCntntNode
= GetCntntNode();
1678 const xub_StrLen nTmpPos
= bLeft
? pCntntNode
->Len() : 0;
1679 GetPoint()->nContent
.Assign( pCntntNode
, nTmpPos
);
1687 // here come some special rules for visual cursor travelling
1690 SwNode
& rTmpNode
= GetPoint()->nNode
.GetNode();
1691 if ( &rTmpNode
!= &rNode
&& rTmpNode
.IsTxtNode() )
1694 const SwCntntFrm
* pEndFrm
= ((SwTxtNode
&)rTmpNode
).getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1697 if ( ! pEndFrm
->IsRightToLeft() != ! pSttFrm
->IsRightToLeft() )
1700 pEndFrm
->RightMargin( this );
1702 pEndFrm
->LeftMargin( this );
1708 return 0 == nCnt
&& !IsInProtectTable( sal_True
) &&
1709 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
1710 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
);
1713 // calculate cursor bidi level: extracted from UpDown()
1714 void SwCursor::DoSetBidiLevelUpDown()
1716 SwNode
& rNode
= GetPoint()->nNode
.GetNode();
1717 if ( rNode
.IsTxtNode() )
1719 const SwScriptInfo
* pSI
=
1720 SwScriptInfo::GetScriptInfo( (SwTxtNode
&)rNode
);
1723 SwIndex
& rIdx
= GetPoint()->nContent
;
1724 xub_StrLen nPos
= rIdx
.GetIndex();
1726 if( nPos
&& nPos
< ((SwTxtNode
&)rNode
).GetTxt().Len() )
1728 const sal_uInt8 nCurrLevel
= pSI
->DirType( nPos
);
1729 const sal_uInt8 nPrevLevel
= pSI
->DirType( nPos
- 1 );
1731 if ( nCurrLevel
% 2 != nPrevLevel
% 2 )
1733 // set cursor level to the lower of the two levels
1734 SetCrsrBidiLevel( Min( nCurrLevel
, nPrevLevel
) );
1737 SetCrsrBidiLevel( nCurrLevel
);
1743 sal_Bool
SwCursor::UpDown( sal_Bool bUp
, sal_uInt16 nCnt
,
1744 Point
* pPt
, long nUpDownX
)
1746 SwTableCursor
* pTblCrsr
= dynamic_cast<SwTableCursor
*>(this);
1747 bool bAdjustTableCrsr
= false;
1749 // If the point/mark of the table cursor in the same box then set cursor to
1750 // beginning of the box
1751 if( pTblCrsr
&& GetNode( sal_True
)->StartOfSectionNode() ==
1752 GetNode( sal_False
)->StartOfSectionNode() )
1754 if ( End() != GetPoint() )
1756 bAdjustTableCrsr
= true;
1759 sal_Bool bRet
= sal_False
;
1763 SwCntntFrm
* pFrm
= GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1767 SwCrsrSaveState
aSave( *this );
1772 pFrm
->GetCharRect( aTmpRect
, *GetPoint() );
1773 aPt
= aTmpRect
.Pos();
1775 nUpDownX
= pFrm
->IsVertical() ?
1776 aPt
.Y() - pFrm
->Frm().Top() :
1777 aPt
.X() - pFrm
->Frm().Left();
1780 // It is allowed to move footnotes in other footnotes but not sections
1781 const sal_Bool bChkRange
= pFrm
->IsInFtn() && !HasMark()
1782 ? sal_False
: sal_True
;
1783 const SwPosition
aOldPos( *GetPoint() );
1784 sal_Bool bInReadOnly
= IsReadOnlyAvailable();
1786 if ( bAdjustTableCrsr
&& !bUp
)
1788 // Special case: We have a table cursor but the start box has more
1789 // than one paragraph. If we want to go down, we have to set the
1790 // point to the last frame in the table box. This is only necessary
1791 // if we do not already have a table selection
1792 const SwStartNode
* pTblNd
= GetNode( sal_True
)->FindTableBoxStartNode();
1793 OSL_ENSURE( pTblNd
, "pTblCrsr without SwTableNode?" );
1795 if ( pTblNd
) // safety first
1797 const SwNode
* pEndNd
= pTblNd
->EndOfSectionNode();
1798 GetPoint()->nNode
= *pEndNd
;
1799 pTblCrsr
->Move( fnMoveBackward
, fnGoNode
);
1800 pFrm
= GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1805 (bUp
? pFrm
->UnitUp( this, nUpDownX
, bInReadOnly
)
1806 : pFrm
->UnitDown( this, nUpDownX
, bInReadOnly
) ) &&
1807 CheckNodesRange( aOldPos
.nNode
, GetPoint()->nNode
, bChkRange
))
1809 pFrm
= GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1813 // iterate over whole number of items?
1814 if( !nCnt
&& !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
1815 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
) )
1819 // try to position the cursor at half of the char-rect's height
1820 pFrm
= GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1821 SwCrsrMoveState
eTmpState( MV_UPDOWN
);
1822 eTmpState
.bSetInReadOnly
= bInReadOnly
;
1824 pFrm
->GetCharRect( aTmpRect
, *GetPoint(), &eTmpState
);
1825 if ( pFrm
->IsVertical() )
1827 aPt
.X() = aTmpRect
.Center().X();
1829 aPt
.Y() = pFrm
->Frm().Top() + nUpDownX
;
1833 aPt
.Y() = aTmpRect
.Center().Y();
1835 aPt
.X() = pFrm
->Frm().Left() + nUpDownX
;
1837 pFrm
->GetCrsrOfst( GetPoint(), aPt
, &eTmpState
);
1842 *GetPoint() = aOldPos
;
1844 DoSetBidiLevelUpDown(); // calculate cursor bidi level
1850 sal_Bool
SwCursor::LeftRightMargin( sal_Bool bLeft
, sal_Bool bAPI
)
1853 SwCntntFrm
* pFrm
= GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1855 // calculate cursor bidi level
1857 SetCrsrBidiLevel( pFrm
->IsRightToLeft() ? 1 : 0 );
1859 return pFrm
&& (bLeft
? pFrm
->LeftMargin( this ) :
1860 pFrm
->RightMargin( this, bAPI
) );
1863 sal_Bool
SwCursor::IsAtLeftRightMargin( sal_Bool bLeft
, sal_Bool bAPI
) const
1865 sal_Bool bRet
= sal_False
;
1867 SwCntntFrm
* pFrm
= GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt
, GetPoint() );
1870 SwPaM
aPam( *GetPoint() );
1871 if( !bLeft
&& aPam
.GetPoint()->nContent
.GetIndex() )
1872 aPam
.GetPoint()->nContent
--;
1873 bRet
= (bLeft
? pFrm
->LeftMargin( &aPam
)
1874 : pFrm
->RightMargin( &aPam
, bAPI
))
1875 && *aPam
.GetPoint() == *GetPoint();
1880 sal_Bool
SwCursor::SttEndDoc( sal_Bool bStt
)
1882 SwCrsrSaveState
aSave( *this );
1883 // Never jump over section boundaries during selection!
1884 // Can the cursor still moved on?
1885 SwMoveFn fnMove
= bStt
? fnMoveBackward
: fnMoveForward
;
1886 sal_Bool bRet
= (!HasMark() || !IsNoCntnt() ) &&
1887 Move( fnMove
, fnGoDoc
) &&
1888 !IsInProtectTable( sal_True
) &&
1889 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
1890 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
|
1891 nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION
);
1896 sal_Bool
SwCursor::GoPrevNextCell( sal_Bool bNext
, sal_uInt16 nCnt
)
1898 const SwTableNode
* pTblNd
= GetPoint()->nNode
.GetNode().FindTableNode();
1902 // If there is another EndNode in front of the cell's StartNode then there
1903 // exists a previous cell
1904 SwCrsrSaveState
aSave( *this );
1905 SwNodeIndex
& rPtIdx
= GetPoint()->nNode
;
1909 const SwNode
* pTableBoxStartNode
= rPtIdx
.GetNode().FindTableBoxStartNode();
1910 const SwTableBox
* pTableBox
= pTableBoxStartNode
->GetTblBox();
1912 // Check if we have to move the cursor to a covered cell before
1914 if ( mnRowSpanOffset
)
1916 if ( pTableBox
&& pTableBox
->getRowSpan() > 1 )
1918 pTableBox
= & pTableBox
->FindEndOfRowSpan( pTblNd
->GetTable(), (sal_uInt16
)(pTableBox
->getRowSpan() + mnRowSpanOffset
) );
1919 SwNodeIndex
aNewIdx( *pTableBox
->GetSttNd() );
1921 pTableBoxStartNode
= rPtIdx
.GetNode().FindTableBoxStartNode();
1923 mnRowSpanOffset
= 0;
1926 const SwNode
* pTmpNode
= bNext
?
1927 pTableBoxStartNode
->EndOfSectionNode() :
1930 SwNodeIndex
aCellIdx( *pTmpNode
, bNext
? 1 : -1 );
1931 if( (bNext
&& !aCellIdx
.GetNode().IsStartNode()) ||
1932 (!bNext
&& !aCellIdx
.GetNode().IsEndNode()) )
1935 rPtIdx
= bNext
? aCellIdx
: SwNodeIndex(*aCellIdx
.GetNode().StartOfSectionNode());
1937 pTableBoxStartNode
= rPtIdx
.GetNode().FindTableBoxStartNode();
1938 pTableBox
= pTableBoxStartNode
->GetTblBox();
1939 if ( pTableBox
&& pTableBox
->getRowSpan() < 1 )
1941 mnRowSpanOffset
= pTableBox
->getRowSpan();
1942 // move cursor to non-covered cell:
1943 pTableBox
= & pTableBox
->FindStartOfRowSpan( pTblNd
->GetTable(), USHRT_MAX
);
1944 SwNodeIndex
aNewIdx( *pTableBox
->GetSttNd() );
1950 if( !rPtIdx
.GetNode().IsCntntNode() )
1951 GetDoc()->GetNodes().GoNextSection( &rPtIdx
, sal_True
, sal_False
);
1952 GetPoint()->nContent
.Assign( GetCntntNode(), 0 );
1954 return !IsInProtectTable( sal_True
);
1957 bool SwTableCursor::GotoTable( const String
& )
1959 return false; // invalid action
1962 bool SwCursor::GotoTable( const String
& rName
)
1967 SwTable
* pTmpTbl
= SwTable::FindTable( GetDoc()->FindTblFmtByName( rName
) );
1970 // a table in a normal nodes array
1971 SwCrsrSaveState
aSave( *this );
1972 GetPoint()->nNode
= *pTmpTbl
->GetTabSortBoxes()[ 0 ]->
1973 GetSttNd()->FindTableNode();
1974 Move( fnMoveForward
, fnGoCntnt
);
1981 sal_Bool
SwCursor::GotoTblBox( const String
& rName
)
1983 sal_Bool bRet
= sal_False
;
1984 const SwTableNode
* pTblNd
= GetPoint()->nNode
.GetNode().FindTableNode();
1987 // retrieve box by name
1988 const SwTableBox
* pTblBox
= pTblNd
->GetTable().GetTblBox( rName
);
1989 if( pTblBox
&& pTblBox
->GetSttNd() &&
1990 ( !pTblBox
->GetFrmFmt()->GetProtect().IsCntntProtected() ||
1991 IsReadOnlyAvailable() ) )
1993 SwCrsrSaveState
aSave( *this );
1994 GetPoint()->nNode
= *pTblBox
->GetSttNd();
1995 Move( fnMoveForward
, fnGoCntnt
);
2002 sal_Bool
SwCursor::MovePara(SwWhichPara fnWhichPara
, SwPosPara fnPosPara
)
2004 // for optimization test something before
2005 const SwNode
* pNd
= &GetPoint()->nNode
.GetNode();
2006 bool bShortCut
= false;
2007 if ( fnWhichPara
== fnParaCurr
)
2010 // If fnWhichPara == fnParaCurr then (*fnWhichPara)( *this, fnPosPara )
2011 // can already move the cursor to a different text node. In this case
2012 // we better check if IsSelOvr().
2013 const SwCntntNode
* pCntntNd
= pNd
->GetCntntNode();
2016 const xub_StrLen nSttEnd
= fnPosPara
== fnMoveForward
? 0 : pCntntNd
->Len();
2017 if ( GetPoint()->nContent
.GetIndex() != nSttEnd
)
2023 if ( pNd
->IsTxtNode() &&
2024 pNd
->GetNodes()[ pNd
->GetIndex() +
2025 (fnWhichPara
== fnParaNext
? 1 : -1 ) ]->IsTxtNode() )
2030 return (*fnWhichPara
)( *this, fnPosPara
);
2032 // else we must use the SaveStructure, because the next/prev is not
2033 // a same node type.
2034 SwCrsrSaveState
aSave( *this );
2035 return (*fnWhichPara
)( *this, fnPosPara
) &&
2036 !IsInProtectTable( sal_True
) &&
2037 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
2038 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
);
2042 sal_Bool
SwCursor::MoveSection( SwWhichSection fnWhichSect
,
2043 SwPosSection fnPosSect
)
2045 SwCrsrSaveState
aSave( *this );
2046 return (*fnWhichSect
)( *this, fnPosSect
) &&
2047 !IsInProtectTable( sal_True
) &&
2048 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE
|
2049 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS
);
2052 void SwCursor::RestoreSavePos()
2054 // This method is not supposed to be used in cases when nodes may be
2055 // deleted; detect such cases, but do not crash (example: fdo#40831).
2056 sal_uLong uNodeCount
= GetPoint()->nNode
.GetNodes().Count();
2057 OSL_ENSURE(!pSavePos
|| pSavePos
->nNode
< uNodeCount
,
2058 "SwCursor::RestoreSavePos: invalid node: "
2059 "probably something was deleted; consider using SwUnoCrsr instead");
2060 if( pSavePos
&& pSavePos
->nNode
< uNodeCount
)
2062 GetPoint()->nNode
= pSavePos
->nNode
;
2064 xub_StrLen nIdx
= 0;
2065 if ( GetCntntNode() )
2067 if ( pSavePos
->nCntnt
<= GetCntntNode()->Len() )
2068 nIdx
= pSavePos
->nCntnt
;
2071 nIdx
= GetCntntNode()->Len();
2072 OSL_FAIL("SwCursor::RestoreSavePos: invalid content index");
2075 GetPoint()->nContent
.Assign( GetCntntNode(), nIdx
);
2081 SwTableCursor::SwTableCursor( const SwPosition
&rPos
, SwPaM
* pRing
)
2082 : SwCursor( rPos
, pRing
, false )
2084 bParked
= sal_False
;
2086 nTblPtNd
= 0, nTblMkNd
= 0;
2087 nTblPtCnt
= 0, nTblMkCnt
= 0;
2090 SwTableCursor::~SwTableCursor() {}
2094 lcl_SeekEntry(const SwSelBoxes
& rTmp
, SwStartNode
const*const pSrch
,
2097 sal_uLong nIdx
= pSrch
->GetIndex();
2099 size_t nO
= rTmp
.size();
2106 size_t nM
= nU
+ ( nO
- nU
) / 2;
2107 if( rTmp
[ nM
]->GetSttNd() == pSrch
)
2112 else if( rTmp
[ nM
]->GetSttIdx() < nIdx
)
2124 SwCursor
* SwTableCursor::MakeBoxSels( SwCursor
* pAktCrsr
)
2130 // move back into content
2132 Move( fnMoveForward
);
2134 Move( fnMoveForward
);
2135 bParked
= sal_False
;
2140 // create temporary copies so that all boxes that
2141 // have already cursors can be removed
2142 SwSelBoxes
aTmp(m_SelectedBoxes
);
2144 // compare old and new ones
2145 SwNodes
& rNds
= pAktCrsr
->GetDoc()->GetNodes();
2146 const SwStartNode
* pSttNd
;
2147 SwPaM
* pCur
= pAktCrsr
;
2151 pSttNd
= pCur
->GetPoint()->nNode
.GetNode().FindTableBoxStartNode();
2152 if( !pCur
->HasMark() || !pSttNd
||
2153 pSttNd
!= pCur
->GetMark()->nNode
.GetNode().FindTableBoxStartNode() )
2156 else if( lcl_SeekEntry( aTmp
, pSttNd
, nPos
))
2158 SwNodeIndex
aIdx( *pSttNd
, 1 );
2159 const SwNode
* pNd
= &aIdx
.GetNode();
2160 if( !pNd
->IsCntntNode() )
2161 pNd
= rNds
.GoNextSection( &aIdx
, sal_True
, sal_False
);
2163 SwPosition
* pPos
= pCur
->GetMark();
2164 if( pNd
!= &pPos
->nNode
.GetNode() )
2166 pPos
->nContent
.Assign( (SwCntntNode
*)pNd
, 0 );
2168 aIdx
.Assign( *pSttNd
->EndOfSectionNode(), - 1 );
2169 if( !( pNd
= &aIdx
.GetNode())->IsCntntNode() )
2170 pNd
= rNds
.GoPrevSection( &aIdx
, sal_True
, sal_False
);
2172 pPos
= pCur
->GetPoint();
2173 if( pNd
!= &pPos
->nNode
.GetNode() )
2175 pPos
->nContent
.Assign( (SwCntntNode
*)pNd
, ((SwCntntNode
*)pNd
)->Len() );
2177 aTmp
.erase( aTmp
.begin() + nPos
);
2182 pCur
= (SwPaM
*)pCur
->GetNext();
2185 SwPaM
* pDel
= (SwPaM
*)pCur
->GetPrev();
2187 if( pDel
== pAktCrsr
)
2188 pAktCrsr
->DeleteMark();
2192 } while ( pAktCrsr
!= pCur
);
2194 for (size_t nPos
= 0; nPos
< aTmp
.size(); ++nPos
)
2196 pSttNd
= aTmp
[ nPos
]->GetSttNd();
2198 SwNodeIndex
aIdx( *pSttNd
, 1 );
2199 if( &aIdx
.GetNodes() != &rNds
)
2201 const SwNode
* pNd
= &aIdx
.GetNode();
2202 if( !pNd
->IsCntntNode() )
2203 pNd
= rNds
.GoNextSection( &aIdx
, sal_True
, sal_False
);
2206 if( pAktCrsr
->GetNext() == pAktCrsr
&& !pAktCrsr
->HasMark() )
2209 pNew
->GetPoint()->nNode
= *pNd
;
2210 pNew
->GetPoint()->nContent
.Assign( (SwCntntNode
*)pNd
, 0 );
2214 pNew
= pAktCrsr
->Create( pAktCrsr
);
2215 pNew
->GetPoint()->nNode
= *pNd
;
2216 pNew
->GetPoint()->nContent
.Assign( (SwCntntNode
*)pNd
, 0 );
2220 SwPosition
* pPos
= pNew
->GetPoint();
2221 pPos
->nNode
.Assign( *pSttNd
->EndOfSectionNode(), - 1 );
2222 if( !( pNd
= &pPos
->nNode
.GetNode())->IsCntntNode() )
2223 pNd
= rNds
.GoPrevSection( &pPos
->nNode
, sal_True
, sal_False
);
2225 pPos
->nContent
.Assign( (SwCntntNode
*)pNd
, ((SwCntntNode
*)pNd
)->Len() );
2232 void SwTableCursor::InsertBox( const SwTableBox
& rTblBox
)
2234 SwTableBox
* pBox
= (SwTableBox
*)&rTblBox
;
2235 m_SelectedBoxes
.insert(pBox
);
2240 void SwTableCursor::DeleteBox(size_t const nPos
)
2242 m_SelectedBoxes
.erase(m_SelectedBoxes
.begin() + nPos
);
2246 bool SwTableCursor::NewTableSelection()
2249 const SwNode
*pStart
= GetCntntNode()->FindTableBoxStartNode();
2250 const SwNode
*pEnd
= GetCntntNode(sal_False
)->FindTableBoxStartNode();
2251 if( pStart
&& pEnd
)
2253 const SwTableNode
*pTableNode
= pStart
->FindTableNode();
2254 if( pTableNode
== pEnd
->FindTableNode() &&
2255 pTableNode
->GetTable().IsNewModel() )
2258 SwSelBoxes
aNew(m_SelectedBoxes
);
2259 pTableNode
->GetTable().CreateSelection( pStart
, pEnd
, aNew
,
2260 SwTable::SEARCH_NONE
, false );
2261 ActualizeSelection( aNew
);
2267 void SwTableCursor::ActualizeSelection( const SwSelBoxes
&rNew
)
2269 size_t nOld
= 0, nNew
= 0;
2270 while (nOld
< m_SelectedBoxes
.size() && nNew
< rNew
.size())
2272 SwTableBox
const*const pPOld
= m_SelectedBoxes
[ nOld
];
2273 const SwTableBox
* pPNew
= rNew
[ nNew
];
2274 if( pPOld
== pPNew
)
2275 { // this box will stay
2279 else if( pPOld
->GetSttIdx() < pPNew
->GetSttIdx() )
2281 DeleteBox( nOld
); // this box has to go
2285 InsertBox( *pPNew
); // this is a new one
2291 while (nOld
< m_SelectedBoxes
.size())
2293 DeleteBox( nOld
); // some more to delete
2296 for ( ; nNew
< rNew
.size(); ++nNew
) // some more to insert
2298 InsertBox( *rNew
[ nNew
] );
2302 sal_Bool
SwTableCursor::IsCrsrMovedUpdt()
2304 if( !IsCrsrMoved() )
2307 nTblMkNd
= GetMark()->nNode
.GetIndex();
2308 nTblPtNd
= GetPoint()->nNode
.GetIndex();
2309 nTblMkCnt
= GetMark()->nContent
.GetIndex();
2310 nTblPtCnt
= GetPoint()->nContent
.GetIndex();
2314 /// park table cursor on the boxes' start node
2315 void SwTableCursor::ParkCrsr()
2317 // de-register index from text node
2318 SwNode
* pNd
= &GetPoint()->nNode
.GetNode();
2319 if( !pNd
->IsStartNode() )
2320 pNd
= pNd
->StartOfSectionNode();
2321 GetPoint()->nNode
= *pNd
;
2322 GetPoint()->nContent
.Assign( 0, 0 );
2324 pNd
= &GetMark()->nNode
.GetNode();
2325 if( !pNd
->IsStartNode() )
2326 pNd
= pNd
->StartOfSectionNode();
2327 GetMark()->nNode
= *pNd
;
2328 GetMark()->nContent
.Assign( 0, 0 );
2335 sal_Bool
SwTableCursor::HasReadOnlyBoxSel() const
2337 sal_Bool bRet
= sal_False
;
2338 for (size_t n
= m_SelectedBoxes
.size(); n
; )
2340 if (m_SelectedBoxes
[--n
]->GetFrmFmt()->GetProtect().IsCntntProtected())
2349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */