xref: /trunk/main/sw/source/core/crsr/swcrsr.cxx (revision 150c6d32)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <hintids.hxx>
29 #include <editeng/protitem.hxx>
30 #include <com/sun/star/i18n/WordType.hdl>
31 #include <com/sun/star/i18n/CharType.hdl>
32 #include <unotools/charclass.hxx>
33 #include <svl/ctloptions.hxx>
34 #include <swmodule.hxx>
35 #include <fmtcntnt.hxx>
36 #include <swtblfmt.hxx>
37 #include <swcrsr.hxx>
38 #include <unocrsr.hxx>
39 #include <doc.hxx>
40 #include <IDocumentUndoRedo.hxx>
41 #include <docary.hxx>
42 #include <ndtxt.hxx>
43 #include <section.hxx>
44 #include <swtable.hxx>
45 #include <cntfrm.hxx>
46 #include <rootfrm.hxx>
47 #include <txtfrm.hxx>
48 #include <scriptinfo.hxx>
49 #include <crstate.hxx>
50 #include <docsh.hxx>
51 #include <viewsh.hxx>
52 #include <frmatr.hxx>
53 #include <breakit.hxx>
54 #include <crsskip.hxx>
55 #include <vcl/msgbox.hxx>
56 #include <mdiexp.hxx>			// ...Percent()
57 #include <statstr.hrc>			// ResId fuer Statusleiste
58 #include <redline.hxx>      // SwRedline
59 #include <txatbase.hxx>
60 
61 
62 using namespace ::com::sun::star::i18n;
63 
64 
65 static const sal_uInt16 coSrchRplcThreshold = 60000;
66 
67 struct _PercentHdl
68 {
69 	SwDocShell* pDSh;
70 	sal_uLong nActPos;
71 	sal_Bool bBack, bNodeIdx;
72 
_PercentHdl_PercentHdl73 	_PercentHdl( sal_uLong nStt, sal_uLong nEnd, SwDocShell* pSh )
74 		: pDSh( pSh )
75 	{
76 		nActPos = nStt;
77 		if( 0 != ( bBack = (nStt > nEnd )) )
78 		{
79 			sal_uLong n = nStt; nStt = nEnd; nEnd = n;
80 		}
81 		::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, 0 );
82 	}
83 
_PercentHdl_PercentHdl84 	_PercentHdl( const SwPaM& rPam )
85 		: pDSh( (SwDocShell*)rPam.GetDoc()->GetDocShell() )
86 	{
87 		sal_uLong nStt, nEnd;
88 		if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
89 		{
90 			bNodeIdx = sal_False;
91 			nStt = rPam.GetMark()->nContent.GetIndex();
92 			nEnd = rPam.GetPoint()->nContent.GetIndex();
93 		}
94 		else
95 		{
96             bNodeIdx = sal_True;
97             nStt = rPam.GetMark()->nNode.GetIndex();
98 			nEnd = rPam.GetPoint()->nNode.GetIndex();
99 		}
100 		nActPos = nStt;
101 		if( 0 != ( bBack = (nStt > nEnd )) )
102 		{
103 			sal_uLong n = nStt; nStt = nEnd; nEnd = n;
104 		}
105 		::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh );
106 	}
107 
~_PercentHdl_PercentHdl108 	~_PercentHdl()  					{ ::EndProgress( pDSh ); }
109 
NextPos_PercentHdl110 	void NextPos( sal_uLong nPos ) const
111 		{ ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); }
112 
NextPos_PercentHdl113 	void NextPos( SwPosition& rPos ) const
114 		{
115 			sal_uLong nPos;
116 			if( bNodeIdx )
117 				nPos = rPos.nNode.GetIndex();
118 			else
119 				nPos = rPos.nContent.GetIndex();
120 			::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh );
121 		}
122 };
123 
SwCursor(const SwPosition & rPos,SwPaM * pRing,bool bColumnSel)124 SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing, bool bColumnSel )
125     : SwPaM( rPos, pRing ), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ),
126     mbColumnSelection( bColumnSel )
127 {
128 }
129 
130 // @@@ semantic: no copy ctor.
SwCursor(SwCursor & rCpy)131 SwCursor::SwCursor( SwCursor& rCpy )
132     : SwPaM( rCpy ), pSavePos( 0 ), mnRowSpanOffset( rCpy.mnRowSpanOffset ),
133     nCursorBidiLevel( rCpy.nCursorBidiLevel ), mbColumnSelection( rCpy.mbColumnSelection )
134 {
135 }
136 
~SwCursor()137 SwCursor::~SwCursor()
138 {
139 	while( pSavePos )
140 	{
141         _SwCursor_SavePos* pNxt = pSavePos->pNext;
142 		delete pSavePos;
143         pSavePos = pNxt;
144 	}
145 }
146 
Create(SwPaM * pRing) const147 SwCursor* SwCursor::Create( SwPaM* pRing ) const
148 {
149 	return new SwCursor( *GetPoint(), pRing, false );
150 }
151 
IsReadOnlyAvailable() const152 bool SwCursor::IsReadOnlyAvailable() const
153 {
154     return false;
155 }
156 
IsSkipOverHiddenSections() const157 sal_Bool SwCursor::IsSkipOverHiddenSections() const
158 {
159     return sal_True;
160 }
161 
IsSkipOverProtectSections() const162 sal_Bool SwCursor::IsSkipOverProtectSections() const
163 {
164     return !IsReadOnlyAvailable();
165 }
166 
167 
168 // Sicher die aktuelle Position, damit ggfs. auf diese zurueck
169 // gefallen werden kann. Die SavePos Objekte werden als Stack verwaltet,
170 // damit das auch alles bei verschachtelten Aufrufen funktioniert.
171 // Das CreateNewSavePos ist virtual, damit abgeleitete Klassen vom Cursor
172 // gegebenenfalls eigene SaveObjecte anlegen und in den virtuellen
173 // Check-Routinen verwenden koennen.
174 
SaveState()175 void SwCursor::SaveState()
176 {
177 	_SwCursor_SavePos* pNew = CreateNewSavePos();
178 	pNew->pNext = pSavePos;
179 	pSavePos = pNew;
180 }
181 
RestoreState()182 void SwCursor::RestoreState()
183 {
184     if( pSavePos ) // Robust
185     {
186         _SwCursor_SavePos* pDel = pSavePos;
187         pSavePos = pSavePos->pNext;
188         delete pDel;
189     }
190 }
191 
CreateNewSavePos() const192 _SwCursor_SavePos* SwCursor::CreateNewSavePos() const
193 {
194 	return new _SwCursor_SavePos( *this );
195 }
196 
197 // stelle fest, ob sich der Point ausserhalb des Content-Bereichs
198 // vom Nodes-Array befindet
IsNoCntnt() const199 sal_Bool SwCursor::IsNoCntnt() const
200 {
201 	return GetPoint()->nNode.GetIndex() <
202 			GetDoc()->GetNodes().GetEndOfExtras().GetIndex();
203 }
204 
IsSelOvrCheck(int)205 bool SwCursor::IsSelOvrCheck(int)
206 {
207     return false;
208 }
209 
210 // extracted from IsSelOvr()
IsSelOvrCheck(int eFlags)211 bool SwTableCursor::IsSelOvrCheck(int eFlags)
212 {
213     SwNodes& rNds = GetDoc()->GetNodes();
214     // check sections of nodes array
215     if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION & eFlags)
216         && HasMark() )
217     {
218         SwNodeIndex aOldPos( rNds, GetSavePos()->nNode );
219         if( !CheckNodesRange( aOldPos, GetPoint()->nNode, sal_True ))
220         {
221             GetPoint()->nNode = aOldPos;
222             GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
223             return true;
224         }
225     }
226     return SwCursor::IsSelOvrCheck(eFlags);
227 }
228 
IsSelOvr(int eFlags)229 sal_Bool SwCursor::IsSelOvr( int eFlags )
230 {
231 	SwDoc* pDoc = GetDoc();
232 	SwNodes& rNds = pDoc->GetNodes();
233 
234     sal_Bool bSkipOverHiddenSections = IsSkipOverHiddenSections();
235     sal_Bool bSkipOverProtectSections = IsSkipOverProtectSections();
236 
237     if ( IsSelOvrCheck( eFlags ) )
238     {
239         return sal_True;
240     }
241 
242     if( pSavePos->nNode != GetPoint()->nNode.GetIndex()
243         && ( !pDoc->GetDocShell()
244              || !pDoc->GetDocShell()->IsReadOnlyUI() ) )
245     {
246         // teste doch mal die neuen Sections:
247         SwNodeIndex& rPtIdx = GetPoint()->nNode;
248         const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode();
249         if( pSectNd &&
250             ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) ||
251             (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() )))
252         {
253             if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
254             {
255                 // dann wars das schon
256                 RestoreSavePos();
257                 return sal_True;
258             }
259 
260             // dann setze den Cursor auf die neue Position:
261             SwNodeIndex aIdx( rPtIdx );
262             xub_StrLen nCntntPos = pSavePos->nCntnt;
263             int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
264             SwCntntNode* pCNd = bGoNxt
265                 ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
266                 : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
267             if( !pCNd && ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION & eFlags ))
268             {
269                 bGoNxt = !bGoNxt;
270                 pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
271                     : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
272             }
273 
274             int bIsValidPos = 0 != pCNd;
275             sal_Bool bValidNodesRange = bIsValidPos &&
276                 ::CheckNodesRange( rPtIdx, aIdx, sal_True );
277             if( !bValidNodesRange )
278             {
279                 rPtIdx = pSavePos->nNode;
280                 if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
281                 {
282                     bIsValidPos = sal_False;
283                     nCntntPos = 0;
284                     rPtIdx = aIdx;
285                     if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
286                     {
287                         // dann auf den Anfang vom Doc
288                         rPtIdx = rNds.GetEndOfExtras();
289                         pCNd = rNds.GoNext( &rPtIdx );
290                     }
291                 }
292             }
293 
294             // ContentIndex noch anmelden:
295             xub_StrLen nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nCntntPos;
296             GetPoint()->nContent.Assign( pCNd, nTmpPos );
297             if( !bIsValidPos || !bValidNodesRange ||
298                 // sollten wir in einer Tabelle gelandet sein?
299                     IsInProtectTable( sal_True ) )
300                     return sal_True;
301         }
302 
303         // oder sollte eine geschuetzte Section innerhalb der Selektion liegen?
304         if( HasMark() && bSkipOverProtectSections)
305         {
306             sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
307                 nEndIdx = GetPoint()->nNode.GetIndex();
308             if( nEndIdx <= nSttIdx )
309             {
310                 sal_uLong nTmp = nSttIdx;
311                 nSttIdx = nEndIdx;
312                 nEndIdx = nTmp;
313             }
314 
315             const SwSectionFmts& rFmts = pDoc->GetSections();
316             for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
317             {
318                 const SwSectionFmt* pFmt = rFmts[n];
319                 const SvxProtectItem& rProtect = pFmt->GetProtect();
320                 if( rProtect.IsCntntProtected() )
321                 {
322                     const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False);
323                     ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
324                     sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex();
325                     if( nSttIdx <= nIdx && nEndIdx >= nIdx )
326                     {
327                         // ist es keine gelinkte Section, dann kann sie auch
328                         // nicht mitselektiert werden
329                         const SwSection& rSect = *pFmt->GetSection();
330                         if( CONTENT_SECTION == rSect.GetType() )
331                         {
332                             RestoreSavePos();
333                             return sal_True;
334                         }
335                     }
336                 }
337             }
338         }
339 
340     }
341 
342     const SwNode* pNd = &GetPoint()->nNode.GetNode();
343     if( pNd->IsCntntNode() && !dynamic_cast<SwUnoCrsr*>(this) )
344     {
345         const SwCntntFrm* pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() );
346         if( pFrm != NULL
347             && pFrm->IsValid()
348             && 0 == pFrm->Frm().Height()
349             && 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
350         {
351             // skip to the next / prev valid paragraph with a layout
352             SwNodeIndex& rPtIdx = GetPoint()->nNode;
353             int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
354             while( 0 != ( pFrm = ( bGoNxt ? pFrm->GetNextCntntFrm() : pFrm->GetPrevCntntFrm() ))
355                    && 0 == pFrm->Frm().Height() )
356                 ;
357 
358             // --> LIJIAN/FME 2007-11-27 #i72394# skip to prev /next valid paragraph
359             // with a layout in case the first search did not succeed:
360             if ( pFrm == NULL )
361             {
362                 bGoNxt = !bGoNxt;
363                 pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() );
364                 while ( pFrm != NULL
365                         && 0 == pFrm->Frm().Height() )
366                 {
367                     pFrm = bGoNxt ? pFrm->GetNextCntntFrm() : pFrm->GetPrevCntntFrm();
368                 }
369             }
370             // <--
371 
372             SwCntntNode* pCNd = (pFrm != NULL) ? (SwCntntNode*)pFrm->GetNode() : NULL;
373             if ( pCNd != NULL )
374             {
375                 // set this cntntNode as new position
376                 rPtIdx = *pCNd;
377                 pNd = pCNd;
378 
379                 // assign corresponding ContentIndex
380                 const xub_StrLen nTmpPos = bGoNxt ? 0 : pCNd->Len();
381                 GetPoint()->nContent.Assign( pCNd, nTmpPos );
382 
383                 if ( rPtIdx.GetIndex() == pSavePos->nNode
384                      && nTmpPos == pSavePos->nCntnt )
385                 {
386                     // new position equals saved one
387                     // --> trigger restore of saved pos by setting <pFrm> to NULL - see below
388                     pFrm = NULL;
389                 }
390 
391                 if ( IsInProtectTable( sal_True ) )
392                 {
393                     // new position in protected table
394                     // --> trigger restore of saved pos by setting <pFrm> to NULL - see below
395                     pFrm = NULL;
396                 }
397             }
398         }
399 
400         if( pFrm == NULL )
401         {
402             DeleteMark();
403             RestoreSavePos();
404             return sal_True;
405         }
406     }
407 
408     // darf der Cursor in geschuetzen "Nodes" stehen?
409     if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) && !IsAtValidPos() )
410     {
411         DeleteMark();
412         RestoreSavePos();
413         return sal_True;
414     }
415 
416     if( !HasMark() )
417         return sal_False;
418 
419     //JP 19.08.98: teste mal auf ungueltige Selektion - sprich ueber
420     // 				GrundSections:
421     if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, sal_True ))
422     {
423         DeleteMark();
424         RestoreSavePos();
425         return sal_True;		// ohne Frames geht gar nichts!
426     }
427 
428     if( (pNd = &GetMark()->nNode.GetNode())->IsCntntNode()
429         && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() )
430         && !dynamic_cast<SwUnoCrsr*>(this) )
431     {
432         DeleteMark();
433         RestoreSavePos();
434         return sal_True;		// ohne Frames geht gar nichts!
435     }
436 
437     // assure that selection is only inside an InputField or contains the InputField completely
438     {
439         const SwTxtAttr* pInputFldTxtAttrAtPoint = NULL;
440         SwTxtNode* pTxtNdAtPoint = GetPoint()->nNode.GetNode().GetTxtNode();
441         if ( pTxtNdAtPoint != NULL )
442         {
443             pInputFldTxtAttrAtPoint =
444                 pTxtNdAtPoint->GetTxtAttrAt( GetPoint()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTxtNode::PARENT );
445         }
446 
447         const SwTxtAttr* pInputFldTxtAttrAtMark = NULL;
448         SwTxtNode* pTxtNdAtMark = GetMark()->nNode.GetNode().GetTxtNode();
449         if ( pTxtNdAtMark != NULL )
450         {
451             pInputFldTxtAttrAtMark =
452                 pTxtNdAtMark->GetTxtAttrAt( GetMark()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTxtNode::PARENT );
453         }
454 
455         if ( pInputFldTxtAttrAtPoint != pInputFldTxtAttrAtMark )
456         {
457             const sal_uLong nRefNodeIdx =
458                 ( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags )
459                 ? pSavePos->nNode
460                 : GetMark()->nNode.GetIndex();
461             const xub_StrLen nRefContentIdx =
462                 ( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags )
463                 ? pSavePos->nCntnt
464                 : GetMark()->nContent.GetIndex();
465             const bool bIsForwardSelection =
466                 nRefNodeIdx < GetPoint()->nNode.GetIndex()
467                 || ( nRefNodeIdx == GetPoint()->nNode.GetIndex()
468                      && nRefContentIdx < GetPoint()->nContent.GetIndex() );
469 
470             if ( pInputFldTxtAttrAtPoint != NULL )
471             {
472                 const xub_StrLen nNewPointPos =
473                     bIsForwardSelection ? *(pInputFldTxtAttrAtPoint->End()) : *(pInputFldTxtAttrAtPoint->GetStart());
474                 GetPoint()->nContent.Assign( pTxtNdAtPoint, nNewPointPos );
475             }
476 
477             if ( pInputFldTxtAttrAtMark != NULL )
478             {
479                 const xub_StrLen nNewMarkPos =
480                     bIsForwardSelection ? *(pInputFldTxtAttrAtMark->GetStart()) : *(pInputFldTxtAttrAtMark->End());
481                 GetMark()->nContent.Assign( pTxtNdAtMark, nNewMarkPos );
482             }
483         }
484     }
485 
486     const SwTableNode* pPtNd = GetPoint()->nNode.GetNode().FindTableNode();
487     const SwTableNode* pMrkNd = GetMark()->nNode.GetNode().FindTableNode();
488     // beide in keinem oder beide im gleichen TableNode
489     if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd )
490         return sal_False;
491 
492     // in unterschiedlichen Tabellen oder nur Mark in der Tabelle
493     if( ( pPtNd && pMrkNd ) || pMrkNd )
494     {
495         // dann lasse das nicht zu, alte Pos zurueck
496         RestoreSavePos();
497         // Crsr bleibt an der alten Position
498         return sal_True;
499     }
500 
501     // ACHTUNG: dieses kann nicht im TableMode geschehen !!
502     if( pPtNd )		// nur Point in Tabelle, dann gehe hinter/vor diese
503     {
504         if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags )
505         {
506             sal_Bool bSelTop = GetPoint()->nNode.GetIndex() <
507                 (( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags ) ? pSavePos->nNode
508                 : GetMark()->nNode.GetIndex());
509 
510             do {
511                 // in Schleife fuer Tabelle hinter Tabelle
512                 sal_uLong nSEIdx = pPtNd->EndOfSectionIndex();
513                 sal_uLong nSttEndTbl = nSEIdx + 1; // dflt. Sel. nach unten
514 
515                 if( bSelTop )								// Sel. nach oben
516                     nSttEndTbl = rNds[ nSEIdx ]->StartOfSectionIndex() - 1;
517 
518                 GetPoint()->nNode = nSttEndTbl;
519                 const SwNode* pMyNd = GetNode();
520 
521                 if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() &&
522                     pMyNd->StartOfSectionNode()->IsSectionNode() ) )
523                 {
524                     // die lassen wir zu:
525                     pMyNd = bSelTop
526                         ? rNds.GoPrevSection( &GetPoint()->nNode,sal_True,sal_False )
527                         : rNds.GoNextSection( &GetPoint()->nNode,sal_True,sal_False );
528 
529                     /* #i12312# Handle failure of Go{Prev|Next}Section */
530                     if ( 0 == pMyNd)
531                         break;
532 
533                     if( 0 != ( pPtNd = pMyNd->FindTableNode() ))
534                         continue;
535                 }
536 
537                 if( pMyNd->IsCntntNode() &&      // ist es ein ContentNode ??
538                     ::CheckNodesRange( GetMark()->nNode,
539                     GetPoint()->nNode, sal_True ))
540                 {
541                     // TABLE IN TABLE
542                     const SwTableNode* pOuterTableNd = pMyNd->FindTableNode();
543                     if ( pOuterTableNd )
544                         pMyNd = pOuterTableNd;
545                     else
546                     {
547                         SwCntntNode* pCNd = (SwCntntNode*)pMyNd;
548                         xub_StrLen nTmpPos = bSelTop ? pCNd->Len() : 0;
549                         GetPoint()->nContent.Assign( pCNd, nTmpPos );
550                         return sal_False;
551                     }
552                 }
553                 if( bSelTop
554                     ? ( !pMyNd->IsEndNode() || 0 == ( pPtNd = pMyNd->FindTableNode() ))
555                     : 0 == ( pPtNd = pMyNd->GetTableNode() ))
556                     break;
557             } while( sal_True );
558         }
559 
560         // dann verbleibe auf der alten Position
561         RestoreSavePos();
562         return sal_True;		// Crsr bleibt an der alten Position
563     }
564 
565     return sal_False;
566 }
567 
568 #if defined( UNX )
569 #define IDX     (*pCellStt)
570 #else
571 #define IDX     aCellStt
572 #endif
573 
574 
IsInProtectTable(sal_Bool bMove,sal_Bool bChgCrsr)575 sal_Bool SwCursor::IsInProtectTable( sal_Bool bMove, sal_Bool bChgCrsr )
576 {
577 	SwCntntNode* pCNd = GetCntntNode();
578 	if( !pCNd )
579         return sal_False;
580 
581 	// No table, no protected cell:
582     const SwTableNode* pTableNode = pCNd->FindTableNode();
583     if ( !pTableNode )
584         return sal_False;
585 
586     // Current position == last save position?
587     if ( pSavePos->nNode == GetPoint()->nNode.GetIndex() )
588         return sal_False;
589 
590     // Check for convered cell:
591     bool bInCoveredCell = false;
592     const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
593     ASSERT( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" )
594     const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTblBox( pTmpSttNode->GetIndex() ) : 0; //Robust #151355
595     if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
596         bInCoveredCell = true;
597 
598     // Positions of covered cells are not acceptable:
599     if ( !bInCoveredCell )
600     {
601         // Position not protected?
602         if ( !pCNd->IsProtect() )
603 		    return sal_False;
604 
605         // Cursor in protected cells allowed?
606         if ( IsReadOnlyAvailable() )
607             return sal_False;
608     }
609 
610     // If we reach this point, we are in a protected or covered table cell!
611 
612 	if( !bMove )
613 	{
614 		if( bChgCrsr )
615 			// restore the last save position
616 			RestoreSavePos();
617 		return sal_True;		// Crsr bleibt an der alten Position
618 	}
619 
620 	// wir stehen in einer geschuetzten TabellenZelle
621 	// von Oben nach Unten Traveln ?
622 	if( pSavePos->nNode < GetPoint()->nNode.GetIndex() )
623 	{
624 		// suche die naechste "gueltige" Box
625 
626 		// folgt nach dem EndNode der Zelle ein weiterer StartNode, dann
627 		// gibt es auch eine naechste Zelle
628 #if defined( UNX )
629 		SwNodeIndex* pCellStt = new SwNodeIndex( *GetNode()->
630 						FindTableBoxStartNode()->EndOfSectionNode(), 1 );
631 #else
632 		SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
633 #endif
634 		sal_Bool bProt = sal_True;
635 GoNextCell:
636 		do {
637 			if( !IDX.GetNode().IsStartNode() )
638 				break;
639 			IDX++;
640 			if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
641 				pCNd = IDX.GetNodes().GoNext( &IDX );
642 			if( 0 == ( bProt = pCNd->IsProtect() ))
643 				break;
644 			IDX.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
645 		} while( bProt );
646 
647 SetNextCrsr:
648 		if( !bProt )		// eine freie Zelle gefunden
649 		{
650 			GetPoint()->nNode = IDX;
651 #if defined( UNX )
652 			delete pCellStt;
653 #endif
654             SwCntntNode* pTmpCNd = GetCntntNode();
655             if( pTmpCNd )
656 			{
657                 GetPoint()->nContent.Assign( pTmpCNd, 0 );
658 				return sal_False;
659 			}
660             return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
661                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
662 		}
663 		// am Ende der Tabelle, also setze hinter diese
664 		IDX++;     // auf den naechsten Node
665 		SwNode* pNd;
666 		if( ( pNd = &IDX.GetNode())->IsEndNode() || HasMark())
667 		{
668 			// Tabelle allein in einem FlyFrame oder SSelection,
669 			// dann verbleibe auf der alten Position
670 			if( bChgCrsr )
671 				RestoreSavePos();
672 #if defined( UNX )
673 			delete pCellStt;
674 #endif
675 			return sal_True;        // Crsr bleibt an der alten Position
676 		}
677 		else if( pNd->IsTableNode() && IDX++ )
678 			goto GoNextCell;
679 
680 		bProt = sal_False;		// Index steht jetzt auf einem ContentNode
681 		goto SetNextCrsr;
682 	}
683 
684 	// suche die vorherige "gueltige" Box
685 	{
686 		// liegt vor dem StartNode der Zelle ein weiterer EndNode, dann
687 		// gibt es auch eine vorherige Zelle
688 #if defined( UNX )
689 		SwNodeIndex* pCellStt = new SwNodeIndex(
690 					*GetNode()->FindTableBoxStartNode(), -1 );
691 #else
692 		SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode(), -1 );
693 #endif
694 		SwNode* pNd;
695 		sal_Bool bProt = sal_True;
696 GoPrevCell:
697 		do {
698 			if( !( pNd = &IDX.GetNode())->IsEndNode() )
699 				break;
700 			IDX.Assign( *pNd->StartOfSectionNode(), +1 );
701 			if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
702 				pCNd = pNd->GetNodes().GoNext( &IDX );
703 			if( 0 == ( bProt = pCNd->IsProtect() ))
704 				break;
705 			IDX.Assign( *pNd->FindTableBoxStartNode(), -1 );
706 		} while( bProt );
707 
708 SetPrevCrsr:
709 		if( !bProt )		// eine freie Zelle gefunden
710 		{
711 			GetPoint()->nNode = IDX;
712 #if defined( UNX )
713 			delete pCellStt;
714 #endif
715             SwCntntNode* pTmpCNd = GetCntntNode();
716             if( pTmpCNd )
717 			{
718                 GetPoint()->nContent.Assign( pTmpCNd, 0 );
719 				return sal_False;
720 			}
721             return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
722                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
723 		}
724 		// am Start der Tabelle, also setze vor diese
725 		IDX--;     // auf den naechsten Node
726 		if( ( pNd = &IDX.GetNode())->IsStartNode() || HasMark() )
727 		{
728 			// Tabelle allein in einem FlyFrame oder Selektion,
729 			// dann verbleibe auf der alten Position
730 			if( bChgCrsr )
731 				RestoreSavePos();
732 #if defined( UNX )
733 			delete pCellStt;
734 #endif
735 			return sal_True;        // Crsr bleibt an der alten Position
736 		}
737 		else if( pNd->StartOfSectionNode()->IsTableNode() && IDX-- )
738 			goto GoPrevCell;
739 
740 		bProt = sal_False;		// Index steht jetzt auf einem ContentNode
741 		goto SetPrevCrsr;
742 	}
743 }
744 
745 // sal_True: an die Position kann der Cursor gesetzt werden
IsAtValidPos(sal_Bool bPoint) const746 sal_Bool SwCursor::IsAtValidPos( sal_Bool bPoint ) const
747 {
748 	const SwDoc* pDoc = GetDoc();
749 	const SwPosition* pPos = bPoint ? GetPoint() : GetMark();
750 	const SwNode* pNd = &pPos->nNode.GetNode();
751 
752 	if( pNd->IsCntntNode() && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
753         !dynamic_cast<const SwUnoCrsr*>(this) )
754     {
755 		return sal_False;
756     }
757 
758 		//JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
759 	if( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() )
760 		return sal_True;
761 
762 	sal_Bool bCrsrInReadOnly = IsReadOnlyAvailable();
763 	if( !bCrsrInReadOnly && pNd->IsProtect() )
764 		return sal_False;
765 
766 	const SwSectionNode* pSectNd = pNd->FindSectionNode();
767 	if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
768 					( !bCrsrInReadOnly && pSectNd->GetSection().IsProtectFlag() )))
769 		return sal_False;
770 
771 	return sal_True;
772 }
773 
SaveTblBoxCntnt(const SwPosition *)774 void SwCursor::SaveTblBoxCntnt( const SwPosition* )	{}
775 
776 // setze den SRange fuer das Suchen im Dokument
MakeFindRange(SwDocPositions nStart,SwDocPositions nEnd,SwPaM * pRange) const777 SwMoveFnCollection* SwCursor::MakeFindRange( SwDocPositions nStart,
778 								SwDocPositions nEnd, SwPaM* pRange ) const
779 {
780 	pRange->SetMark();
781 	FillFindPos( nStart, *pRange->GetMark() );
782 	FillFindPos( nEnd, *pRange->GetPoint() );
783 
784 	// bestimme die Richtung, in der zu suchen ist
785 	// ( GetPoint > GetMark -> vorwaerts, sonst rueckwaerts )
786 	return ( DOCPOS_START == nStart || DOCPOS_OTHERSTART == nStart ||
787 			  (DOCPOS_CURR == nStart &&
788 				(DOCPOS_END == nEnd || DOCPOS_OTHEREND == nEnd ) ))
789 				? fnMoveForward : fnMoveBackward;
790 }
791 
792 
lcl_FindSelection(SwFindParas & rParas,SwCursor * pCurCrsr,SwMoveFn fnMove,SwCursor * & pFndRing,SwPaM & aRegion,FindRanges eFndRngs,sal_Bool bInReadOnly,sal_Bool & bCancel)793 sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurCrsr,
794 						SwMoveFn fnMove, SwCursor*& pFndRing,
795 						SwPaM& aRegion, FindRanges eFndRngs,
796                         sal_Bool bInReadOnly, sal_Bool& bCancel )
797 {
798 	SwDoc* pDoc = pCurCrsr->GetDoc();
799     bool const bDoesUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
800 	int nFndRet = 0;
801 	sal_uLong nFound = 0;
802 	int bSrchBkwrd = fnMove == fnMoveBackward, bEnde = sal_False;
803 	SwPaM *pTmpCrsr = pCurCrsr, *pSaveCrsr = pCurCrsr;
804 
805     // only create progress-bar for ShellCrsr
806     bool bIsUnoCrsr = 0 != dynamic_cast<SwUnoCrsr*>(pCurCrsr);
807 	_PercentHdl* pPHdl = 0;
808 	sal_uInt16 nCrsrCnt = 0;
809 	if( FND_IN_SEL & eFndRngs )
810 	{
811 		while( pCurCrsr != ( pTmpCrsr = (SwPaM*)pTmpCrsr->GetNext() ))
812 			++nCrsrCnt;
813 		if( nCrsrCnt && !bIsUnoCrsr )
814 			pPHdl = new _PercentHdl( 0, nCrsrCnt, pDoc->GetDocShell() );
815 	}
816     else
817         pSaveCrsr = (SwPaM*)pSaveCrsr->GetPrev();
818 
819 	do {
820 		aRegion.SetMark();
821 		// egal in welche Richtung, SPoint ist immer groesser als Mark,
822 		// wenn der Suchbereich gueltig ist !!
823 		SwPosition *pSttPos = aRegion.GetMark(),
824 						*pEndPos = aRegion.GetPoint();
825 		*pSttPos = *pTmpCrsr->Start();
826 		*pEndPos = *pTmpCrsr->End();
827 		if( bSrchBkwrd )
828 			aRegion.Exchange();
829 
830 		if( !nCrsrCnt && !pPHdl && !bIsUnoCrsr )
831 			pPHdl = new _PercentHdl( aRegion );
832 
833 		// solange gefunden und nicht auf gleicher Position haengen bleibt
834 		while(  *pSttPos <= *pEndPos &&
835 				0 != ( nFndRet = rParas.Find( pCurCrsr, fnMove,
836 											&aRegion, bInReadOnly )) &&
837 				( !pFndRing ||
838 					*pFndRing->GetPoint() != *pCurCrsr->GetPoint() ||
839 					*pFndRing->GetMark() != *pCurCrsr->GetMark() ))
840 		{
841 			if( !( FIND_NO_RING & nFndRet ))
842 			{
843 				// Bug 24084: Ring richtig herum aufbauen -> gleiche Mimik
844 				//			  wie beim CreateCrsr !!!!
845 
846 				SwCursor* pNew = pCurCrsr->Create( pFndRing );
847 				if( !pFndRing )
848 					pFndRing = pNew;
849 
850 				pNew->SetMark();
851 				*pNew->GetMark() = *pCurCrsr->GetMark();
852 			}
853 
854 			++nFound;
855 
856 			if( !( eFndRngs & FND_IN_SELALL) )
857 			{
858 				bEnde = sal_True;
859 				break;
860 			}
861 
862             if ((coSrchRplcThreshold == nFound)
863                 && pDoc->GetIDocumentUndoRedo().DoesUndo()
864                 && rParas.IsReplaceMode())
865             {
866                 short nRet = pCurCrsr->MaxReplaceArived();
867                 if( RET_YES == nRet )
868                 {
869                     pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
870                     pDoc->GetIDocumentUndoRedo().DoUndo(false);
871                 }
872                 else
873                 {
874                     bEnde = sal_True;
875                     if(RET_CANCEL == nRet)
876                     {
877                         bCancel = sal_True;
878                         //unwind() ??
879                     }
880                     break;
881                 }
882             }
883 
884 			if( bSrchBkwrd )
885 				// bewege pEndPos vor den gefundenen Bereich
886 				*pEndPos = *pCurCrsr->Start();
887 			else
888 				// bewege pSttPos hinter den gefundenen Bereich
889 				*pSttPos = *pCurCrsr->End();
890 
891 			if( *pSttPos == *pEndPos )		// im Bereich, aber am Ende
892 				break;						// fertig
893 
894             if( !nCrsrCnt && pPHdl )
895             {
896 				pPHdl->NextPos( *aRegion.GetMark() );
897             }
898 		}
899 
900 		if( bEnde || !( eFndRngs & ( FND_IN_SELALL | FND_IN_SEL )) )
901 			break;
902 
903 		pTmpCrsr = ((SwPaM*)pTmpCrsr->GetNext());
904         if( nCrsrCnt && pPHdl )
905         {
906 			pPHdl->NextPos( ++pPHdl->nActPos );
907         }
908 
909 	} while( pTmpCrsr != pSaveCrsr );
910 
911 	if( nFound && !pFndRing )		// falls kein Ring aufgebaut werden soll
912 		pFndRing = pCurCrsr->Create();
913 
914 	delete pPHdl;
915     pDoc->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
916 	return nFound;
917 }
918 
919 
lcl_MakeSelFwrd(const SwNode & rSttNd,const SwNode & rEndNd,SwPaM & rPam,int bFirst)920 int lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
921 						SwPaM& rPam, int bFirst )
922 {
923 	if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() )
924 		return sal_False;
925 
926 	SwNodes& rNds = rPam.GetDoc()->GetNodes();
927 	rPam.DeleteMark();
928 	SwCntntNode* pCNd;
929 	if( !bFirst )
930 	{
931 		rPam.GetPoint()->nNode = rSttNd;
932 		pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
933 		if( !pCNd )
934 			return sal_False;
935 		pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
936 	}
937 	else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
938 			 rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() )
939 		return sal_False;		// steht nicht in dieser Section
940 
941 	rPam.SetMark();
942 	rPam.GetPoint()->nNode = rEndNd;
943 	pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
944 	if( !pCNd )
945 		return sal_False;
946 	pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
947 
948 	return *rPam.GetMark() < *rPam.GetPoint();
949 }
950 
951 
lcl_MakeSelBkwrd(const SwNode & rSttNd,const SwNode & rEndNd,SwPaM & rPam,int bFirst)952 int lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
953 						SwPaM& rPam, int bFirst )
954 {
955 	if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() )
956 		return sal_False;
957 
958 	SwNodes& rNds = rPam.GetDoc()->GetNodes();
959 	rPam.DeleteMark();
960 	SwCntntNode* pCNd;
961 	if( !bFirst )
962 	{
963 		rPam.GetPoint()->nNode = rSttNd;
964 		pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
965 		if( !pCNd )
966 			return sal_False;
967 		pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
968 	}
969 	else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
970 			 rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() )
971 		return sal_False;		// steht nicht in dieser Section
972 
973 	rPam.SetMark();
974 	rPam.GetPoint()->nNode = rEndNd;
975 	pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
976 	if( !pCNd )
977 		return sal_False;
978 	pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
979 
980 	return *rPam.GetPoint() < *rPam.GetMark();
981 }
982 
983 
984 // diese Methode "sucht" fuer alle Anwendungsfaelle, denn in SwFindParas
985 // steht immer die richtigen Parameter und die entsprechende Find-Methode
986 
FindAll(SwFindParas & rParas,SwDocPositions nStart,SwDocPositions nEnde,FindRanges eFndRngs,sal_Bool & bCancel)987 sal_uLong SwCursor::FindAll( SwFindParas& rParas,
988 							SwDocPositions nStart, SwDocPositions nEnde,
989                             FindRanges eFndRngs, sal_Bool& bCancel )
990 {
991     bCancel = sal_False;
992     SwCrsrSaveState aSaveState( *this );
993 
994 	// Region erzeugen, ohne das diese in den Ring aufgenommen wird !
995 	SwPaM aRegion( *GetPoint() );
996 	SwMoveFn fnMove = MakeFindRange( nStart, nEnde, &aRegion );
997 
998 	sal_uLong nFound = 0;
999 	int bMvBkwrd = fnMove == fnMoveBackward;
1000 	sal_Bool bInReadOnly = IsReadOnlyAvailable();
1001 
1002 	SwCursor* pFndRing = 0;
1003 	SwNodes& rNds = GetDoc()->GetNodes();
1004 
1005 	// suche in Bereichen ?
1006 	if( FND_IN_SEL & eFndRngs )
1007 	{
1008 		// String nicht im Bereich gefunden, dann erhalte alle Bereiche,
1009 		// der Cursor beleibt unveraendert
1010 		if( 0 == ( nFound = lcl_FindSelection( rParas, this, fnMove,
1011 												pFndRing, aRegion, eFndRngs,
1012                                                 bInReadOnly, bCancel ) ))
1013 			return nFound;
1014 
1015 		// der String wurde ein- bis mehrmals gefunden. Das steht alles
1016 		// im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
1017 		while( GetNext() != this )
1018 			delete GetNext();
1019 
1020 		*GetPoint() = *pFndRing->GetPoint();
1021 		SetMark();
1022 		*GetMark() = *pFndRing->GetMark();
1023 		pFndRing->MoveRingTo( this );
1024 		delete pFndRing;
1025 	}
1026 	else if( FND_IN_OTHER & eFndRngs )
1027 	{
1028 		// Cursor als Kopie vom akt. und in den Ring aufnehmen
1029 		// Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
1030 		std::auto_ptr< SwCursor > pSav( Create( this ) ); 	// save the current cursor
1031 
1032 		// wenn schon ausserhalb vom Bodytext, suche von der Position,
1033 		// ansonsten beginne mit der 1. GrundSection
1034 		if( bMvBkwrd
1035 			? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
1036 					*rNds.GetEndOfPostIts().StartOfSectionNode(),
1037 					 *this, rNds.GetEndOfExtras().GetIndex() >=
1038 					GetPoint()->nNode.GetIndex() )
1039 			: lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(),
1040 					rNds.GetEndOfExtras(), *this,
1041 					rNds.GetEndOfExtras().GetIndex() >=
1042 					GetPoint()->nNode.GetIndex() ))
1043 		{
1044 			nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
1045                                         aRegion, eFndRngs, bInReadOnly, bCancel );
1046 		}
1047 
1048 		if( !nFound )
1049 		{
1050 			// den alten wieder zurueck
1051 			*GetPoint() = *pSav->GetPoint();
1052 			if( pSav->HasMark() )
1053 			{
1054 				SetMark();
1055 				*GetMark() = *pSav->GetMark();
1056 			}
1057 			else
1058 				DeleteMark();
1059 			return 0;
1060 		}
1061         pSav.release();
1062 
1063 		if( !( FND_IN_SELALL & eFndRngs ))
1064 		{
1065 			// es sollte nur einer gesucht werden, also fuege in dazu
1066 			// egal in welche Richtung, SPoint ist immer groesser als Mark,
1067 			// wenn der Suchbereich gueltig ist !!
1068 			*GetPoint() = *pFndRing->GetPoint();
1069 			SetMark();
1070 			*GetMark() = *pFndRing->GetMark();
1071 		}
1072 		else
1073 		{
1074 			// es  wurde ein- bis mehrmals gefunden. Das steht alles
1075 			// im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
1076 			while( GetNext() != this )
1077 				delete GetNext();
1078 
1079 			*GetPoint() = *pFndRing->GetPoint();
1080 			SetMark();
1081 			*GetMark() = *pFndRing->GetMark();
1082 			pFndRing->MoveRingTo( this );
1083 		}
1084 		delete pFndRing;
1085 	}
1086 	else if( FND_IN_SELALL & eFndRngs )
1087 	{
1088 		::std::auto_ptr< SwCursor> pSav( Create( this ) ); 	// save the current cursor
1089 
1090 		const SwNode* pSttNd = ( FND_IN_BODYONLY & eFndRngs )
1091 							? rNds.GetEndOfContent().StartOfSectionNode()
1092 							: rNds.GetEndOfPostIts().StartOfSectionNode();
1093 
1094 		if( bMvBkwrd
1095 			? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd,*this, sal_False )
1096 			: lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, sal_False ))
1097 		{
1098 			nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
1099                                         aRegion, eFndRngs, bInReadOnly, bCancel );
1100 		}
1101 
1102 		if( !nFound )
1103 		{
1104 			// den alten wieder zurueck
1105 			*GetPoint() = *pSav->GetPoint();
1106 			if( pSav->HasMark() )
1107 			{
1108 				SetMark();
1109 				*GetMark() = *pSav->GetMark();
1110 			}
1111 			else
1112 				DeleteMark();
1113 			return 0;
1114 		}
1115         pSav.release();
1116 		while( GetNext() != this )
1117 			delete GetNext();
1118 
1119 		*GetPoint() = *pFndRing->GetPoint();
1120 		SetMark();
1121 		*GetMark() = *pFndRing->GetMark();
1122 		pFndRing->MoveRingTo( this );
1123 		delete pFndRing;
1124 	}
1125 	else
1126 	{
1127 		// ist ein GetMark gesetzt, dann wird bei gefundenem Object
1128 		// der GetMark beibehalten !! Dadurch kann ein Bereich mit der Suche
1129 		// aufgespannt werden.
1130 		SwPosition aMarkPos( *GetMark() );
1131 		int bMarkPos = HasMark() && !eFndRngs;
1132 
1133 		if( 0 != (nFound = rParas.Find( this, fnMove,
1134 										&aRegion, bInReadOnly ) ? 1 : 0)
1135 			&& bMarkPos )
1136 			*GetMark() = aMarkPos;
1137 	}
1138 
1139     if( nFound && SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
1140         nFound = 0;
1141 	return nFound;
1142 }
1143 
1144 
FillFindPos(SwDocPositions ePos,SwPosition & rPos) const1145 void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const
1146 {
1147 	sal_Bool bIsStart = sal_True;
1148 	SwCntntNode* pCNd = 0;
1149 	SwNodes& rNds = GetDoc()->GetNodes();
1150 
1151 	switch( ePos )
1152 	{
1153 	case DOCPOS_START:
1154 		rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
1155 		pCNd = rNds.GoNext( &rPos.nNode );
1156 		break;
1157 
1158 	case DOCPOS_END:
1159 		rPos.nNode = rNds.GetEndOfContent();
1160 		pCNd = rNds.GoPrevious( &rPos.nNode );
1161 		bIsStart = sal_False;
1162 		break;
1163 
1164 	case DOCPOS_OTHERSTART:
1165 		rPos.nNode = *rNds[ sal_uLong(0) ];
1166 		pCNd = rNds.GoNext( &rPos.nNode );
1167 		break;
1168 
1169 	case DOCPOS_OTHEREND:
1170 		rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
1171 		pCNd = rNds.GoPrevious( &rPos.nNode );
1172 		bIsStart = sal_False;
1173 		break;
1174 
1175 //	case DOCPOS_CURR:
1176 	default:
1177 		rPos = *GetPoint();
1178 	}
1179 
1180 	if( pCNd )
1181 	{
1182 		xub_StrLen nCPos = 0;
1183 		if( !bIsStart )
1184 			nCPos = pCNd->Len();
1185 		rPos.nContent.Assign( pCNd, nCPos );
1186 	}
1187 }
1188 
MaxReplaceArived()1189 short SwCursor::MaxReplaceArived()
1190 {
1191     return RET_YES;
1192 }
1193 
1194 
IsStartWord(sal_Int16 nWordType) const1195 sal_Bool SwCursor::IsStartWord( sal_Int16 nWordType ) const
1196 {
1197     return IsStartWordWT( nWordType );
1198 }
1199 
IsEndWord(sal_Int16 nWordType) const1200 sal_Bool SwCursor::IsEndWord( sal_Int16 nWordType ) const
1201 {
1202     return IsEndWordWT( nWordType );
1203 }
1204 
IsInWord(sal_Int16 nWordType) const1205 sal_Bool SwCursor::IsInWord( sal_Int16 nWordType ) const
1206 {
1207     return IsInWordWT( nWordType );
1208 }
1209 
GoStartWord()1210 sal_Bool SwCursor::GoStartWord()
1211 {
1212     return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1213 }
1214 
GoEndWord()1215 sal_Bool SwCursor::GoEndWord()
1216 {
1217     return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1218 }
1219 
GoNextWord()1220 sal_Bool SwCursor::GoNextWord()
1221 {
1222     return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1223 }
1224 
GoPrevWord()1225 sal_Bool SwCursor::GoPrevWord()
1226 {
1227     return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1228 }
1229 
SelectWord(ViewShell * pViewShell,const Point * pPt)1230 sal_Bool SwCursor::SelectWord( ViewShell* pViewShell, const Point* pPt )
1231 {
1232     return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt );
1233 }
1234 
IsStartWordWT(sal_Int16 nWordType) const1235 sal_Bool SwCursor::IsStartWordWT( sal_Int16 nWordType ) const
1236 {
1237 	sal_Bool bRet = sal_False;
1238 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1239 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1240 	{
1241 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1242 		bRet = pBreakIt->GetBreakIter()->isBeginWord(
1243 							pTxtNd->GetTxt(), nPtPos,
1244 							pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos )),
1245                             nWordType );
1246 	}
1247 	return bRet;
1248 }
1249 
IsEndWordWT(sal_Int16 nWordType) const1250 sal_Bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
1251 {
1252 	sal_Bool bRet = sal_False;
1253 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1254 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1255 	{
1256 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1257 		bRet = pBreakIt->GetBreakIter()->isEndWord(
1258 							pTxtNd->GetTxt(), nPtPos,
1259 							pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1260                             nWordType );
1261 
1262 	}
1263 	return bRet;
1264 }
1265 
IsInWordWT(sal_Int16 nWordType) const1266 sal_Bool SwCursor::IsInWordWT( sal_Int16 nWordType ) const
1267 {
1268     sal_Bool bRet = sal_False;
1269 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1270 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1271 	{
1272 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1273         Boundary aBoundary = pBreakIt->GetBreakIter()->getWordBoundary(
1274 							pTxtNd->GetTxt(), nPtPos,
1275 							pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1276                             nWordType,
1277                             sal_True );
1278 
1279         bRet = aBoundary.startPos != aBoundary.endPos &&
1280                 aBoundary.startPos <= nPtPos &&
1281                     nPtPos <= aBoundary.endPos;
1282         if(bRet)
1283         {
1284             const CharClass& rCC = GetAppCharClass();
1285             bRet = rCC.isLetterNumeric( pTxtNd->GetTxt(), static_cast<xub_StrLen>(aBoundary.startPos) );
1286         }
1287 	}
1288 	return bRet;
1289 }
1290 
IsStartEndSentence(bool bEnd) const1291 sal_Bool SwCursor::IsStartEndSentence( bool bEnd ) const
1292 {
1293     sal_Bool bRet = bEnd ?
1294                     GetCntntNode() && GetPoint()->nContent == GetCntntNode()->Len() :
1295                     GetPoint()->nContent.GetIndex() == 0;
1296 
1297     if( !bRet )
1298     {
1299         SwCursor aCrsr(*GetPoint(), 0, false);
1300         SwPosition aOrigPos = *aCrsr.GetPoint();
1301         aCrsr.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT );
1302         bRet = aOrigPos == *aCrsr.GetPoint();
1303     }
1304 
1305     return bRet;
1306 }
1307 
GoStartWordWT(sal_Int16 nWordType)1308 sal_Bool SwCursor::GoStartWordWT( sal_Int16 nWordType )
1309 {
1310 	sal_Bool bRet = sal_False;
1311 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1312 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1313 	{
1314 		SwCrsrSaveState aSave( *this );
1315 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1316 		nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
1317 							pTxtNd->GetTxt(), nPtPos,
1318 							pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1319                             nWordType,
1320 							sal_False ).startPos;
1321 
1322         if( nPtPos < pTxtNd->GetTxt().Len() )
1323 		{
1324 			GetPoint()->nContent = nPtPos;
1325 			if( !IsSelOvr() )
1326 				bRet = sal_True;
1327 		}
1328 	}
1329 	return bRet;
1330 }
1331 
GoEndWordWT(sal_Int16 nWordType)1332 sal_Bool SwCursor::GoEndWordWT( sal_Int16 nWordType )
1333 {
1334 	sal_Bool bRet = sal_False;
1335 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1336 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1337 	{
1338 		SwCrsrSaveState aSave( *this );
1339 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1340 		nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
1341 							pTxtNd->GetTxt(), nPtPos,
1342 							pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1343                             nWordType,
1344 							sal_True ).endPos;
1345 
1346         if( nPtPos <= pTxtNd->GetTxt().Len() &&
1347 			GetPoint()->nContent.GetIndex() != nPtPos )
1348 		{
1349 			GetPoint()->nContent = nPtPos;
1350 			if( !IsSelOvr() )
1351 				bRet = sal_True;
1352 		}
1353 	}
1354 	return bRet;
1355 }
1356 
GoNextWordWT(sal_Int16 nWordType)1357 sal_Bool SwCursor::GoNextWordWT( sal_Int16 nWordType )
1358 {
1359 	sal_Bool bRet = sal_False;
1360 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1361 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1362 	{
1363 		SwCrsrSaveState aSave( *this );
1364 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1365 
1366 		nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextWord(
1367 								pTxtNd->GetTxt(), nPtPos,
1368             pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
1369                     nWordType ).startPos;
1370 
1371         if( nPtPos < pTxtNd->GetTxt().Len() )
1372 		{
1373 			GetPoint()->nContent = nPtPos;
1374 			if( !IsSelOvr() )
1375 				bRet = sal_True;
1376 		}
1377 	}
1378 	return bRet;
1379 }
1380 
GoPrevWordWT(sal_Int16 nWordType)1381 sal_Bool SwCursor::GoPrevWordWT( sal_Int16 nWordType )
1382 {
1383 	sal_Bool bRet = sal_False;
1384 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1385 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1386 	{
1387 		SwCrsrSaveState aSave( *this );
1388 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1389         const xub_StrLen nPtStart = nPtPos;
1390 
1391         if( nPtPos )
1392             --nPtPos;
1393 		nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousWord(
1394                                 pTxtNd->GetTxt(), nPtStart,
1395             pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
1396                     nWordType ).startPos;
1397 
1398         if( nPtPos < pTxtNd->GetTxt().Len() )
1399 		{
1400 			GetPoint()->nContent = nPtPos;
1401 			if( !IsSelOvr() )
1402 				bRet = sal_True;
1403 		}
1404 	}
1405 	return bRet;
1406 }
1407 
SelectWordWT(ViewShell * pViewShell,sal_Int16 nWordType,const Point * pPt)1408 sal_Bool SwCursor::SelectWordWT( ViewShell* pViewShell, sal_Int16 nWordType, const Point* pPt )
1409 {
1410 	SwCrsrSaveState aSave( *this );
1411 
1412 	sal_Bool bRet = sal_False;
1413 	sal_Bool bForward = sal_True;
1414 	DeleteMark();
1415 	const SwRootFrm* pLayout = pViewShell->GetLayout();
1416 	if( pPt && 0 != pLayout )
1417 	{
1418 		// set the cursor to the layout position
1419 		Point aPt( *pPt );
1420 		pLayout->GetCrsrOfst( GetPoint(), aPt );
1421 	}	//swmod 071107//swmod 071225
1422 
1423 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1424 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1425 	{
1426 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1427 		Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary(
1428 							pTxtNd->GetTxt(), nPtPos,
1429 							pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1430                             nWordType,
1431 							bForward ));
1432 
1433 		if( aBndry.startPos != aBndry.endPos )
1434 		{
1435 			GetPoint()->nContent = (xub_StrLen)aBndry.endPos;
1436 			if( !IsSelOvr() )
1437 			{
1438 				SetMark();
1439 				GetMark()->nContent = (xub_StrLen)aBndry.startPos;
1440 				if( !IsSelOvr() )
1441 					bRet = sal_True;
1442 			}
1443 		}
1444 	}
1445 
1446 	if( !bRet )
1447 	{
1448 		DeleteMark();
1449 		RestoreSavePos();
1450 	}
1451 	return bRet;
1452 }
1453 
1454 //-----------------------------------------------------------------------------
1455 
lcl_MaskDeletedRedlines(const SwTxtNode * pTxtNd)1456 static String lcl_MaskDeletedRedlines( const SwTxtNode* pTxtNd )
1457 {
1458     String aRes;
1459 	if (pTxtNd)
1460 	{
1461         //mask deleted redlines
1462         String sNodeText(pTxtNd->GetTxt());
1463         const SwDoc& rDoc = *pTxtNd->GetDoc();
1464         const bool nShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() );
1465         if ( nShowChg )
1466         {
1467             sal_uInt16 nAct = rDoc.GetRedlinePos( *pTxtNd, USHRT_MAX );
1468             for ( ; nAct < rDoc.GetRedlineTbl().Count(); nAct++ )
1469             {
1470                 const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ];
1471                 if ( pRed->Start()->nNode > pTxtNd->GetIndex() )
1472                     break;
1473 
1474                 if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
1475                 {
1476                     xub_StrLen nStart, nEnd;
1477                     pRed->CalcStartEnd( pTxtNd->GetIndex(), nStart, nEnd );
1478 
1479                     while ( nStart < nEnd && nStart < sNodeText.Len() )
1480                         sNodeText.SetChar( nStart++, CH_TXTATR_INWORD );
1481                 }
1482             }
1483         }
1484         aRes = sNodeText;
1485     }
1486     return aRes;
1487 }
1488 
GoSentence(SentenceMoveType eMoveType)1489 sal_Bool SwCursor::GoSentence( SentenceMoveType eMoveType )
1490 {
1491 	sal_Bool bRet = sal_False;
1492 	const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1493 	if( pTxtNd && pBreakIt->GetBreakIter().is() )
1494 	{
1495         String sNodeText( lcl_MaskDeletedRedlines( pTxtNd ) );
1496 
1497         SwCrsrSaveState aSave( *this );
1498 		xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1499 		switch ( eMoveType )
1500 		{
1501 		case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
1502 			nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1503                                     sNodeText,
1504 									nPtPos, pBreakIt->GetLocale(
1505 											pTxtNd->GetLang( nPtPos ) ));
1506 			break;
1507 		case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
1508             nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
1509                                     sNodeText,
1510                                     nPtPos, pBreakIt->GetLocale(
1511                                                 pTxtNd->GetLang( nPtPos ) ));
1512 			break;
1513 		case NEXT_SENT:
1514 			{
1515 				nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
1516                                         sNodeText,
1517 										nPtPos, pBreakIt->GetLocale(
1518 													pTxtNd->GetLang( nPtPos ) ));
1519                 while (nPtPos != (sal_uInt16) -1 && ++nPtPos < sNodeText.Len()
1520                        && sNodeText.GetChar(nPtPos)== ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ )
1521 					;
1522 				break;
1523 			}
1524 		case PREV_SENT:
1525 			nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1526                                     sNodeText,
1527                                     nPtPos, pBreakIt->GetLocale(
1528                                                 pTxtNd->GetLang( nPtPos ) ));
1529 			if (nPtPos == 0)
1530 				return sal_False;	// the previous sentence is not in this paragraph
1531 			if (nPtPos > 0)
1532 				nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1533                                     sNodeText,
1534                                     nPtPos - 1, pBreakIt->GetLocale(
1535                                                 pTxtNd->GetLang( nPtPos ) ));
1536 			break;
1537 		}
1538 
1539 		// it is allowed to place the PaM just behind the last
1540 		// character in the text thus <= ...Len
1541         if( nPtPos <= pTxtNd->GetTxt().Len() )
1542 		{
1543 			GetPoint()->nContent = nPtPos;
1544 			if( !IsSelOvr() )
1545 				bRet = sal_True;
1546 		}
1547 	}
1548 	return bRet;
1549 }
1550 
1551 
ExpandToSentenceBorders()1552 sal_Bool SwCursor::ExpandToSentenceBorders()
1553 {
1554     sal_Bool bRes = sal_False;
1555 	const SwTxtNode* pStartNd = Start()->nNode.GetNode().GetTxtNode();
1556 	const SwTxtNode* pEndNd   = End()->nNode.GetNode().GetTxtNode();
1557 	if (pStartNd && pEndNd && pBreakIt->GetBreakIter().is())
1558 	{
1559         if (!HasMark())
1560             SetMark();
1561 
1562         String sStartText( lcl_MaskDeletedRedlines( pStartNd ) );
1563         String sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) );
1564 
1565         SwCrsrSaveState aSave( *this );
1566 		xub_StrLen nStartPos = Start()->nContent.GetIndex();
1567 		xub_StrLen nEndPos   = End()->nContent.GetIndex();
1568 
1569         nStartPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1570                                 sStartText, nStartPos,
1571                                 pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
1572 		nEndPos   = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
1573                                 sEndText, nEndPos,
1574                                 pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
1575 
1576 		// it is allowed to place the PaM just behind the last
1577 		// character in the text thus <= ...Len
1578         bool bChanged = false;
1579         if (nStartPos <= pStartNd->GetTxt().Len())
1580 		{
1581 			GetMark()->nContent = nStartPos;
1582             bChanged = true;
1583 		}
1584         if (nEndPos <= pEndNd->GetTxt().Len())
1585 		{
1586 			GetPoint()->nContent = nEndPos;
1587             bChanged = true;
1588 		}
1589 		if (bChanged && !IsSelOvr())
1590             bRes = sal_True;
1591     }
1592     return bRes;
1593 }
1594 
1595 
LeftRight(sal_Bool bLeft,sal_uInt16 nCnt,sal_uInt16,sal_Bool,sal_Bool,sal_Bool)1596 sal_Bool SwTableCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/,
1597     sal_Bool /*bVisualAllowed*/, sal_Bool /*bSkipHidden*/, sal_Bool /*bInsertCrsr*/ )
1598 {
1599     return bLeft ? GoPrevCell( nCnt )
1600                  : GoNextCell( nCnt );
1601 }
1602 
1603 
1604 // calculate cursor bidi level: extracted from LeftRight()
1605 const SwCntntFrm*
DoSetBidiLevelLeftRight(sal_Bool & io_rbLeft,sal_Bool bVisualAllowed,sal_Bool bInsertCrsr)1606 SwCursor::DoSetBidiLevelLeftRight(
1607     sal_Bool & io_rbLeft, sal_Bool bVisualAllowed, sal_Bool bInsertCrsr)
1608 {
1609     // calculate cursor bidi level
1610     const SwCntntFrm* pSttFrm = NULL;
1611     SwNode& rNode = GetPoint()->nNode.GetNode();
1612 
1613     if( rNode.IsTxtNode() )
1614     {
1615         const SwTxtNode& rTNd = *rNode.GetTxtNode();
1616         SwIndex& rIdx = GetPoint()->nContent;
1617         xub_StrLen nPos = rIdx.GetIndex();
1618 
1619         const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
1620         if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() &&
1621              SvtCTLOptions::MOVEMENT_VISUAL ==
1622              rCTLOptions.GetCTLCursorMovement() )
1623         {
1624             // for visual cursor travelling (used in bidi layout)
1625             // we first have to convert the logic to a visual position
1626             Point aPt;
1627             pSttFrm = rTNd.getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1628             if( pSttFrm )
1629             {
1630                 sal_uInt8 nCrsrLevel = GetCrsrBidiLevel();
1631                 sal_Bool bForward = ! io_rbLeft;
1632                 ((SwTxtFrm*)pSttFrm)->PrepareVisualMove( nPos, nCrsrLevel,
1633                                                          bForward, bInsertCrsr );
1634                 rIdx = nPos;
1635                 SetCrsrBidiLevel( nCrsrLevel );
1636                 io_rbLeft = ! bForward;
1637             }
1638         }
1639         else
1640         {
1641             const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd );
1642             if ( pSI )
1643             {
1644                 const xub_StrLen nMoveOverPos = io_rbLeft ?
1645                                                ( nPos ? nPos - 1 : 0 ) :
1646                                                 nPos;
1647                 SetCrsrBidiLevel( pSI->DirType( nMoveOverPos ) );
1648             }
1649         }
1650     }
1651     return pSttFrm;
1652 }
1653 
LeftRight(sal_Bool bLeft,sal_uInt16 nCnt,sal_uInt16 nMode,sal_Bool bVisualAllowed,sal_Bool bSkipHidden,sal_Bool bInsertCrsr)1654 sal_Bool SwCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
1655                           sal_Bool bVisualAllowed,sal_Bool bSkipHidden, sal_Bool bInsertCrsr )
1656 {
1657     // calculate cursor bidi level
1658     SwNode& rNode = GetPoint()->nNode.GetNode();
1659     const SwCntntFrm* pSttFrm = // may side-effect bLeft!
1660         DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCrsr);
1661 
1662 	// kann der Cursor n-mal weiterverschoben werden ?
1663     SwCrsrSaveState aSave( *this );
1664     SwMoveFn fnMove = bLeft ? fnMoveBackward : fnMoveForward;
1665 
1666     SwGoInDoc fnGo;
1667     if ( bSkipHidden )
1668         fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCellsSkipHidden : fnGoCntntSkipHidden;
1669     else
1670         fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCells : fnGoCntnt;
1671 
1672     // ASSERT( not in covered cell )
1673 
1674     while( nCnt )
1675     {
1676         SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
1677 
1678         bool bSuccess = Move( fnMove, fnGo );
1679         if ( !bSuccess )
1680             break;
1681 
1682         // If we were located inside a covered cell but our position has been
1683         // corrected, we check if the last move has moved the cursor to a different
1684         // table cell. In this case we set the cursor to the stored covered position
1685         // and redo the move:
1686         if ( mnRowSpanOffset )
1687         {
1688             const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode();
1689             const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : 0;
1690             const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1691             const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : 0;
1692 
1693             const bool bCellChanged = pOldTabSttNode && pNewTabSttNode &&
1694                                       pOldTabSttNode == pNewTabSttNode &&
1695                                       pOldTabBoxSttNode && pNewTabBoxSttNode &&
1696                                       pOldTabBoxSttNode != pNewTabBoxSttNode;
1697 
1698             if ( bCellChanged )
1699             {
1700                 // Set cursor to start/end of covered cell:
1701                 SwTableBox* pTableBox = pOldTabBoxSttNode->GetTblBox();
1702                 const long nRowSpan = pTableBox->getRowSpan();
1703                 if ( nRowSpan > 1 )
1704                 {
1705                     pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset ) );
1706             	    SwNodeIndex& rPtIdx = GetPoint()->nNode;
1707                     SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1708                     rPtIdx = aNewIdx;
1709 
1710                     GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False );
1711                     SwCntntNode* pCntntNode = GetCntntNode();
1712                     if ( pCntntNode )
1713                     {
1714                         const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
1715 		        		GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
1716 
1717                         // Redo the move:
1718                         bSuccess = Move( fnMove, fnGo );
1719                         if ( !bSuccess )
1720                             break;
1721                     }
1722                 }
1723 
1724                 mnRowSpanOffset = 0;
1725             }
1726         }
1727 
1728         // Check if I'm inside a covered cell. Correct cursor if necessary and
1729         // store covered cell:
1730         const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1731         if ( pTableBoxStartNode )
1732         {
1733             const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
1734             if ( pTableBox->getRowSpan() < 1 )
1735             {
1736                 // Store the row span offset:
1737                 mnRowSpanOffset = pTableBox->getRowSpan();
1738 
1739                 // Move cursor to non-covered cell:
1740                 const SwTableNode* pTblNd = pTableBoxStartNode->FindTableNode();
1741                 pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
1742          	    SwNodeIndex& rPtIdx = GetPoint()->nNode;
1743                 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1744                 rPtIdx = aNewIdx;
1745 
1746                 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False );
1747                 SwCntntNode* pCntntNode = GetCntntNode();
1748                 if ( pCntntNode )
1749                 {
1750                     const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
1751                		GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
1752                 }
1753             }
1754         }
1755 
1756         --nCnt;
1757     }
1758 
1759     // here come some special rules for visual cursor travelling
1760     if ( pSttFrm )
1761     {
1762         SwNode& rTmpNode = GetPoint()->nNode.GetNode();
1763         if ( &rTmpNode != &rNode && rTmpNode.IsTxtNode() )
1764         {
1765             Point aPt;
1766             const SwCntntFrm* pEndFrm = ((SwTxtNode&)rTmpNode).getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1767             if ( pEndFrm )
1768             {
1769                 if ( ! pEndFrm->IsRightToLeft() != ! pSttFrm->IsRightToLeft() )
1770                 {
1771                     if ( ! bLeft )
1772                         pEndFrm->RightMargin( this );
1773                     else
1774                         pEndFrm->LeftMargin( this );
1775                 }
1776             }
1777         }
1778     }
1779 
1780 	return 0 == nCnt && !IsInProtectTable( sal_True ) &&
1781             !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1782                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1783 }
1784 
1785 // calculate cursor bidi level: extracted from UpDown()
DoSetBidiLevelUpDown()1786 void SwCursor::DoSetBidiLevelUpDown()
1787 {
1788     SwNode& rNode = GetPoint()->nNode.GetNode();
1789     if ( rNode.IsTxtNode() )
1790     {
1791         const SwScriptInfo* pSI =
1792             SwScriptInfo::GetScriptInfo( (SwTxtNode&)rNode );
1793         if ( pSI )
1794         {
1795             SwIndex& rIdx = GetPoint()->nContent;
1796             xub_StrLen nPos = rIdx.GetIndex();
1797 
1798             if( nPos && nPos < ((SwTxtNode&)rNode).GetTxt().Len() )
1799             {
1800                 const sal_uInt8 nCurrLevel = pSI->DirType( nPos );
1801                 const sal_uInt8 nPrevLevel = pSI->DirType( nPos - 1 );
1802 
1803                 if ( nCurrLevel % 2 != nPrevLevel % 2 )
1804                 {
1805                     // set cursor level to the lower of the two levels
1806                     SetCrsrBidiLevel( Min( nCurrLevel, nPrevLevel ) );
1807                 }
1808                 else
1809                     SetCrsrBidiLevel( nCurrLevel );
1810             }
1811         }
1812     }
1813 }
1814 
UpDown(sal_Bool bUp,sal_uInt16 nCnt,Point * pPt,long nUpDownX)1815 sal_Bool SwCursor::UpDown( sal_Bool bUp, sal_uInt16 nCnt,
1816 							Point* pPt, long nUpDownX )
1817 {
1818     SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
1819     sal_Bool bAdjustTableCrsr = sal_False;
1820 
1821 	// vom Tabellen Crsr Point/Mark in der gleichen Box ??
1822 	// dann stelle den Point an den Anfang der Box
1823     if( pTblCrsr && GetNode( sal_True )->StartOfSectionNode() ==
1824                     GetNode( sal_False )->StartOfSectionNode() )
1825     {
1826         if ( End() != GetPoint() )
1827             Exchange();
1828         bAdjustTableCrsr = sal_True;
1829     }
1830 
1831 	sal_Bool bRet = sal_False;
1832 	Point aPt;
1833 	if( pPt )
1834 		aPt = *pPt;
1835 	SwCntntFrm* pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1836 
1837 	if( pFrm )
1838 	{
1839 		SwCrsrSaveState aSave( *this );
1840 
1841 		if( !pPt )
1842 		{
1843 			SwRect aTmpRect;
1844 			pFrm->GetCharRect( aTmpRect, *GetPoint() );
1845 			aPt = aTmpRect.Pos();
1846 
1847             nUpDownX = pFrm->IsVertical() ?
1848                 aPt.Y() - pFrm->Frm().Top() :
1849                 aPt.X() - pFrm->Frm().Left();
1850 		}
1851 
1852 		// Bei Fussnoten ist auch die Bewegung in eine andere Fussnote erlaubt.
1853 		// aber keine Selection!!
1854 		const sal_Bool bChkRange = pFrm->IsInFtn() && !HasMark()
1855 									? sal_False : sal_True;
1856 		const SwPosition aOldPos( *GetPoint() );
1857 		sal_Bool bInReadOnly = IsReadOnlyAvailable();
1858 
1859         if ( bAdjustTableCrsr && !bUp )
1860         {
1861             // Special case: We have a table cursor but the start box
1862             // has more than one paragraph. If we want to go down, we have to
1863             // set the point to the last frame in the table box. This is
1864             // only necessary if we do not already have a table selection
1865             const SwStartNode* pTblNd = GetNode( sal_True )->FindTableBoxStartNode();
1866             ASSERT( pTblNd, "pTblCrsr without SwTableNode?" )
1867 
1868             if ( pTblNd ) // safety first
1869             {
1870                 const SwNode* pEndNd = pTblNd->EndOfSectionNode();
1871                 GetPoint()->nNode = *pEndNd;
1872                 pTblCrsr->Move( fnMoveBackward, fnGoNode );
1873    			    pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1874             }
1875         }
1876 
1877         while( nCnt &&
1878                (bUp ? pFrm->UnitUp( this, nUpDownX, bInReadOnly )
1879 		            : pFrm->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
1880     		    CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
1881 	    {
1882    			pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1883 		    --nCnt;
1884 	    }
1885 
1886         if( !nCnt && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1887                                 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )  // die gesamte Anzahl durchlaufen ?
1888 		{
1889 			if( !pTblCrsr )
1890 			{
1891 				// dann versuche den Cursor auf die Position zu setzen,
1892 				// auf halber Heohe vom Char-Rectangle
1893 				pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1894 				SwCrsrMoveState eTmpState( MV_UPDOWN );
1895 				eTmpState.bSetInReadOnly = bInReadOnly;
1896 				SwRect aTmpRect;
1897 				pFrm->GetCharRect( aTmpRect, *GetPoint(), &eTmpState );
1898                 if ( pFrm->IsVertical() )
1899                 {
1900                     aPt.X() = aTmpRect.Center().X();
1901                     pFrm->Calc();
1902                     aPt.Y() = pFrm->Frm().Top() + nUpDownX;
1903                 }
1904                 else
1905                 {
1906                     aPt.Y() = aTmpRect.Center().Y();
1907                     pFrm->Calc();
1908                     aPt.X() = pFrm->Frm().Left() + nUpDownX;
1909                 }
1910                 pFrm->GetCrsrOfst( GetPoint(), aPt, &eTmpState );
1911             }
1912             bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1913         }
1914         else
1915             *GetPoint() = aOldPos;
1916 
1917         DoSetBidiLevelUpDown(); // calculate cursor bidi level
1918     }
1919 
1920 	return bRet;
1921 }
1922 
LeftRightMargin(sal_Bool bLeft,sal_Bool bAPI)1923 sal_Bool SwCursor::LeftRightMargin( sal_Bool bLeft, sal_Bool bAPI )
1924 {
1925     Point aPt;
1926     SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1927 
1928     // calculate cursor bidi level
1929     if ( pFrm )
1930         SetCrsrBidiLevel( pFrm->IsRightToLeft() ? 1 : 0 );
1931 
1932     SwCrsrSaveState aSave( *this );
1933     return pFrm
1934            && (bLeft ? pFrm->LeftMargin( this ) : pFrm->RightMargin( this, bAPI ) )
1935            && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1936 }
1937 
IsAtLeftRightMargin(sal_Bool bLeft,sal_Bool bAPI) const1938 sal_Bool SwCursor::IsAtLeftRightMargin( sal_Bool bLeft, sal_Bool bAPI ) const
1939 {
1940 	sal_Bool bRet = sal_False;
1941 	Point aPt;
1942 	SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1943 	if( pFrm )
1944 	{
1945 		SwPaM aPam( *GetPoint() );
1946 		if( !bLeft && aPam.GetPoint()->nContent.GetIndex() )
1947 			aPam.GetPoint()->nContent--;
1948 		bRet = (bLeft ? pFrm->LeftMargin( &aPam )
1949 					  : pFrm->RightMargin( &aPam, bAPI ))
1950 				&& *aPam.GetPoint() == *GetPoint();
1951 	}
1952 	return bRet;
1953 }
1954 
SttEndDoc(sal_Bool bStt)1955 sal_Bool SwCursor::SttEndDoc( sal_Bool bStt )
1956 {
1957 	SwCrsrSaveState aSave( *this );
1958 
1959 	// Springe beim Selektieren nie ueber Section-Grenzen !!
1960 	// kann der Cursor weiterverschoben werden ?
1961 	SwMoveFn fnMove = bStt ? fnMoveBackward : fnMoveForward;
1962 	sal_Bool bRet = (!HasMark() || !IsNoCntnt() ) &&
1963 					Move( fnMove, fnGoDoc ) &&
1964 					!IsInProtectTable( sal_True ) &&
1965                     !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1966                                nsSwCursorSelOverFlags::SELOVER_CHANGEPOS |
1967                                nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION );
1968 
1969 	return bRet;
1970 }
1971 
GoPrevNextCell(sal_Bool bNext,sal_uInt16 nCnt)1972 sal_Bool SwCursor::GoPrevNextCell( sal_Bool bNext, sal_uInt16 nCnt )
1973 {
1974 	const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
1975 	if( !pTblNd )
1976 		return sal_False;
1977 
1978 	// liegt vor dem StartNode der Cell ein weiterer EndNode, dann
1979 	// gibt es auch eine vorherige Celle
1980 	SwCrsrSaveState aSave( *this );
1981 	SwNodeIndex& rPtIdx = GetPoint()->nNode;
1982 
1983     while( nCnt-- )
1984 	{
1985         const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
1986         const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
1987 
1988         // Check if we have to move the cursor to a covered cell before
1989         // proceeding:
1990         if ( mnRowSpanOffset )
1991         {
1992             if ( pTableBox->getRowSpan() > 1 )
1993             {
1994                 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset) );
1995                 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1996                 rPtIdx = aNewIdx;
1997                 pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
1998             }
1999             mnRowSpanOffset = 0;
2000         }
2001 
2002         const SwNode* pTmpNode = bNext ?
2003                                  pTableBoxStartNode->EndOfSectionNode() :
2004                                  pTableBoxStartNode;
2005 
2006         SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 );
2007 		if(  (bNext && !aCellIdx.GetNode().IsStartNode()) ||
2008             (!bNext && !aCellIdx.GetNode().IsEndNode()) )
2009 			return sal_False;
2010 
2011         rPtIdx = bNext ? aCellIdx : SwNodeIndex(*aCellIdx.GetNode().StartOfSectionNode());
2012 
2013         pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
2014         pTableBox = pTableBoxStartNode->GetTblBox();
2015         if ( pTableBox->getRowSpan() < 1 )
2016         {
2017             mnRowSpanOffset = pTableBox->getRowSpan();
2018             // move cursor to non-covered cell:
2019             pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
2020             SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
2021             rPtIdx = aNewIdx;
2022         }
2023     }
2024 
2025 	rPtIdx++;
2026 	if( !rPtIdx.GetNode().IsCntntNode() )
2027 		GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_True, sal_False );
2028 	GetPoint()->nContent.Assign( GetCntntNode(), 0 );
2029 
2030 	return !IsInProtectTable( sal_True );
2031 }
2032 
GotoTable(const String &)2033 sal_Bool SwTableCursor::GotoTable( const String& /*rName*/ )
2034 {
2035     return sal_False; // invalid action
2036 }
2037 
GotoTable(const String & rName)2038 sal_Bool SwCursor::GotoTable( const String& rName )
2039 {
2040 	sal_Bool bRet = sal_False;
2041     if ( !HasMark() )
2042 	{
2043 		SwTable* pTmpTbl = SwTable::FindTable( GetDoc()->FindTblFmtByName( rName ) );
2044 		if( pTmpTbl )
2045 		{
2046 			// eine Tabelle im normalen NodesArr
2047 			SwCrsrSaveState aSave( *this );
2048 			GetPoint()->nNode = *pTmpTbl->GetTabSortBoxes()[ 0 ]->
2049 								GetSttNd()->FindTableNode();
2050 			Move( fnMoveForward, fnGoCntnt );
2051 			bRet = !IsSelOvr();
2052 		}
2053 	}
2054 	return bRet;
2055 }
2056 
GotoTblBox(const String & rName)2057 sal_Bool SwCursor::GotoTblBox( const String& rName )
2058 {
2059 	sal_Bool bRet = sal_False;
2060 	const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
2061 	if( pTblNd )
2062 	{
2063 		// erfrage die Box, mit dem Nanen
2064 		const SwTableBox* pTblBox = pTblNd->GetTable().GetTblBox( rName );
2065 		if( pTblBox && pTblBox->GetSttNd() &&
2066 			( !pTblBox->GetFrmFmt()->GetProtect().IsCntntProtected() ||
2067 			  IsReadOnlyAvailable() ) )
2068 		{
2069 			SwCrsrSaveState aSave( *this );
2070 			GetPoint()->nNode = *pTblBox->GetSttNd();
2071 			Move( fnMoveForward, fnGoCntnt );
2072 			bRet = !IsSelOvr();
2073 		}
2074 	}
2075 	return bRet;
2076 }
2077 
MovePara(SwWhichPara fnWhichPara,SwPosPara fnPosPara)2078 sal_Bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
2079 {
2080 	//JP 28.8.2001: for optimization test something before
2081     const SwNode* pNd = &GetPoint()->nNode.GetNode();
2082     bool bShortCut = false;
2083     if ( fnWhichPara == fnParaCurr )
2084     {
2085         // --> FME 2005-02-21 #i41048#
2086         // If fnWhichPara == fnParaCurr, (*fnWhichPara)( *this, fnPosPara )
2087         // can already move the cursor to a different text node. In this case
2088         // we better check if IsSelOvr().
2089         const SwCntntNode* pCntntNd = pNd->GetCntntNode();
2090         if ( pCntntNd )
2091         {
2092             const xub_StrLen nSttEnd = fnPosPara == fnMoveForward ? 0 : pCntntNd->Len();
2093             if ( GetPoint()->nContent.GetIndex() != nSttEnd )
2094                 bShortCut = true;
2095         }
2096         // <--
2097     }
2098     else
2099     {
2100         if ( pNd->IsTxtNode() &&
2101              pNd->GetNodes()[ pNd->GetIndex() +
2102                     (fnWhichPara == fnParaNext ? 1 : -1 ) ]->IsTxtNode() )
2103             bShortCut = true;
2104     }
2105 
2106     if ( bShortCut )
2107         return (*fnWhichPara)( *this, fnPosPara );
2108 
2109     // else we must use the SaveStructure, because the next/prev is not
2110 	// a same node type.
2111 	SwCrsrSaveState aSave( *this );
2112 	return (*fnWhichPara)( *this, fnPosPara ) &&
2113 			!IsInProtectTable( sal_True ) &&
2114             !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2115                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
2116 }
2117 
2118 
MoveSection(SwWhichSection fnWhichSect,SwPosSection fnPosSect)2119 sal_Bool SwCursor::MoveSection( SwWhichSection fnWhichSect,
2120 								SwPosSection fnPosSect)
2121 {
2122 	SwCrsrSaveState aSave( *this );
2123 	return (*fnWhichSect)( *this, fnPosSect ) &&
2124 			!IsInProtectTable( sal_True ) &&
2125             !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2126                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
2127 }
2128 
2129 /*
2130 	sal_Bool MoveTable( SwWhichTable, SwPosTable );
2131 	sal_Bool MoveColumn( SwWhichColumn, SwPosColumn );
2132 	sal_Bool MoveRegion( SwWhichRegion, SwPosRegion );
2133 */
2134 
RestoreSavePos()2135 void SwCursor::RestoreSavePos()		// Point auf die SavePos setzen
2136 {
2137 	if( pSavePos )
2138 	{
2139 		GetPoint()->nNode = pSavePos->nNode;
2140 		GetPoint()->nContent.Assign( GetCntntNode(), pSavePos->nCntnt );
2141 	}
2142 }
2143 
2144 
2145 /*  */
2146 
SwTableCursor(const SwPosition & rPos,SwPaM * pRing)2147 SwTableCursor::SwTableCursor( const SwPosition &rPos, SwPaM* pRing )
2148 	: SwCursor( rPos, pRing, false )
2149 {
2150 	bParked = sal_False;
2151 	bChg = sal_False;
2152 	nTblPtNd = 0, nTblMkNd = 0;
2153 	nTblPtCnt = 0, nTblMkCnt = 0;
2154 }
2155 
~SwTableCursor()2156 SwTableCursor::~SwTableCursor() {}
2157 
2158 
lcl_SeekEntry(const SwSelBoxes & rTmp,const SwStartNode * pSrch,sal_uInt16 & rFndPos)2159 sal_Bool lcl_SeekEntry( const SwSelBoxes& rTmp, const SwStartNode* pSrch, sal_uInt16& rFndPos )
2160 {
2161 	sal_uLong nIdx = pSrch->GetIndex();
2162 
2163 	sal_uInt16 nO = rTmp.Count(), nM, nU = 0;
2164 	if( nO > 0 )
2165 	{
2166 		nO--;
2167 		while( nU <= nO )
2168 		{
2169 			nM = nU + ( nO - nU ) / 2;
2170 			if( rTmp[ nM ]->GetSttNd() == pSrch )
2171 			{
2172 				rFndPos = nM;
2173 				return sal_True;
2174 			}
2175 			else if( rTmp[ nM ]->GetSttIdx() < nIdx )
2176 				nU = nM + 1;
2177 			else if( nM == 0 )
2178 				return sal_False;
2179 			else
2180 				nO = nM - 1;
2181 		}
2182 	}
2183 	return sal_False;
2184 }
2185 
2186 
MakeBoxSels(SwCursor * pAktCrsr)2187 SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pAktCrsr )
2188 {
2189 	if( bChg )		// ???
2190 	{
2191 		if( bParked )
2192 		{
2193 			// wieder in den Inhalt schieben
2194 			Exchange();
2195 			Move( fnMoveForward );
2196 			Exchange();
2197 			Move( fnMoveForward );
2198 			bParked = sal_False;
2199 		}
2200 
2201 		bChg = sal_False;
2202 
2203 		// temp Kopie anlegen, damit alle Boxen, fuer die schon Cursor
2204 		// existieren, entfernt werden koennen.
2205 		SwSelBoxes aTmp;
2206 		aTmp.Insert( &aSelBoxes );
2207 
2208 		//Jetzt die Alten und die neuen abgleichen.
2209 		SwNodes& rNds = pAktCrsr->GetDoc()->GetNodes();
2210 		sal_uInt16 nPos;
2211 		const SwStartNode* pSttNd;
2212 		SwPaM* pCur = pAktCrsr;
2213 		do {
2214 			sal_Bool bDel = sal_False;
2215 			pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
2216 			if( !pCur->HasMark() || !pSttNd ||
2217 				pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() )
2218 				bDel = sal_True;
2219 
2220 			else if( lcl_SeekEntry( aTmp, pSttNd, nPos ))
2221 			{
2222 				SwNodeIndex aIdx( *pSttNd, 1 );
2223 				const SwNode* pNd = &aIdx.GetNode();
2224 				if( !pNd->IsCntntNode() )
2225 					pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
2226 
2227 				SwPosition* pPos = pCur->GetMark();
2228 				if( pNd != &pPos->nNode.GetNode() )
2229 					pPos->nNode = *pNd;
2230 				pPos->nContent.Assign( (SwCntntNode*)pNd, 0 );
2231 
2232 				aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 );
2233 				if( !( pNd = &aIdx.GetNode())->IsCntntNode() )
2234 					pNd = rNds.GoPrevSection( &aIdx, sal_True, sal_False );
2235 
2236 				pPos = pCur->GetPoint();
2237 				if( pNd != &pPos->nNode.GetNode() )
2238 					pPos->nNode = *pNd;
2239 				pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
2240 
2241 				aTmp.Remove( nPos );
2242 			}
2243 			else
2244 				bDel = sal_True;
2245 
2246 			pCur = (SwPaM*)pCur->GetNext();
2247 			if( bDel )
2248 			{
2249 				SwPaM* pDel = (SwPaM*)pCur->GetPrev();
2250 /*
2251 JP 20.07.98: der alte Code geht mit dem UNO-TableCrsr nicht
2252 				if( pDel == pAktCrsr )
2253 				{
2254 					if( pAktCrsr->GetNext() == pAktCrsr )
2255 					{
2256 						pAktCrsr->DeleteMark();
2257 						break;		// es gibt nichts mehr zu loeschen!
2258 					}
2259 					pAktCrsr = (SwCursor*)pDel->GetPrev();
2260 				}
2261 				delete pDel;
2262 */
2263 
2264 				if( pDel == pAktCrsr )
2265 					pAktCrsr->DeleteMark();
2266 				else
2267 					delete pDel;
2268 			}
2269 		} while ( pAktCrsr != pCur );
2270 
2271 		for( nPos = 0; nPos < aTmp.Count(); ++nPos )
2272 		{
2273 			pSttNd = aTmp[ nPos ]->GetSttNd();
2274 
2275 			SwNodeIndex aIdx( *pSttNd, 1 );
2276             if( &aIdx.GetNodes() != &rNds )
2277                 break;
2278 			const SwNode* pNd = &aIdx.GetNode();
2279 			if( !pNd->IsCntntNode() )
2280 				pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
2281 
2282 			SwPaM* pNew;
2283 			if( pAktCrsr->GetNext() == pAktCrsr && !pAktCrsr->HasMark() )
2284 			{
2285 				pNew = pAktCrsr;
2286 				pNew->GetPoint()->nNode = *pNd;
2287 				pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
2288 			}
2289 			else
2290 			{
2291 				pNew = pAktCrsr->Create( pAktCrsr );
2292 				pNew->GetPoint()->nNode = *pNd;
2293 				pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
2294 			}
2295 			pNew->SetMark();
2296 
2297 			SwPosition* pPos = pNew->GetPoint();
2298 			pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 );
2299 			if( !( pNd = &pPos->nNode.GetNode())->IsCntntNode() )
2300 				pNd = rNds.GoPrevSection( &pPos->nNode, sal_True, sal_False );
2301 
2302 			pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
2303 		}
2304 	}
2305 	return pAktCrsr;
2306 }
2307 
2308 
InsertBox(const SwTableBox & rTblBox)2309 void SwTableCursor::InsertBox( const SwTableBox& rTblBox )
2310 {
2311 	SwTableBox* pBox = (SwTableBox*)&rTblBox;
2312 	aSelBoxes.Insert( pBox );
2313 	bChg = sal_True;
2314 }
2315 
NewTableSelection()2316 bool SwTableCursor::NewTableSelection()
2317 {
2318     bool bRet = false;
2319 	const SwNode *pStart = GetCntntNode()->FindTableBoxStartNode();
2320 	const SwNode *pEnd = GetCntntNode(sal_False)->FindTableBoxStartNode();
2321     if( pStart && pEnd )
2322     {
2323         const SwTableNode *pTableNode = pStart->FindTableNode();
2324         if( pTableNode == pEnd->FindTableNode() &&
2325             pTableNode->GetTable().IsNewModel() )
2326         {
2327             bRet = true;
2328             SwSelBoxes aNew;
2329             aNew.Insert( &aSelBoxes );
2330             pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew,
2331                 SwTable::SEARCH_NONE, false );
2332             ActualizeSelection( aNew );
2333         }
2334     }
2335     return bRet;
2336 }
2337 
ActualizeSelection(const SwSelBoxes & rNew)2338 void SwTableCursor::ActualizeSelection( const SwSelBoxes &rNew )
2339 {
2340     sal_uInt16 nOld = 0, nNew = 0;
2341     while ( nOld < aSelBoxes.Count() && nNew < rNew.Count() )
2342     {
2343         const SwTableBox* pPOld = *( aSelBoxes.GetData() + nOld );
2344         const SwTableBox* pPNew = *( rNew.GetData() + nNew );
2345         if( pPOld == pPNew )
2346         {   // this box will stay
2347             ++nOld;
2348             ++nNew;
2349         }
2350         else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
2351             DeleteBox( nOld ); // this box has to go
2352         else
2353         {
2354             InsertBox( *pPNew ); // this is a new one
2355             ++nOld;
2356             ++nNew;
2357         }
2358     }
2359 
2360     while( nOld < aSelBoxes.Count() )
2361         DeleteBox( nOld ); // some more to delete
2362 
2363     for( ; nNew < rNew.Count(); ++nNew ) // some more to insert
2364         InsertBox( **( rNew.GetData() + nNew ) );
2365 }
2366 
IsCrsrMovedUpdt()2367 sal_Bool SwTableCursor::IsCrsrMovedUpdt()
2368 {
2369 	if( !IsCrsrMoved() )
2370 		return sal_False;
2371 
2372 	nTblMkNd = GetMark()->nNode.GetIndex();
2373 	nTblPtNd = GetPoint()->nNode.GetIndex();
2374 	nTblMkCnt = GetMark()->nContent.GetIndex();
2375 	nTblPtCnt = GetPoint()->nContent.GetIndex();
2376 	return sal_True;
2377 }
2378 
2379 
2380 // Parke den Tabellen-Cursor auf dem StartNode der Boxen.
ParkCrsr()2381 void SwTableCursor::ParkCrsr()
2382 {
2383 	// Index aus dem TextNode abmelden
2384 	SwNode* pNd = &GetPoint()->nNode.GetNode();
2385 	if( !pNd->IsStartNode() )
2386 		pNd = pNd->StartOfSectionNode();
2387 	GetPoint()->nNode = *pNd;
2388 	GetPoint()->nContent.Assign( 0, 0 );
2389 
2390 	pNd = &GetMark()->nNode.GetNode();
2391 	if( !pNd->IsStartNode() )
2392 		pNd = pNd->StartOfSectionNode();
2393 	GetMark()->nNode = *pNd;
2394 	GetMark()->nContent.Assign( 0, 0 );
2395 
2396 	bChg = sal_True;
2397 	bParked = sal_True;
2398 }
2399 
2400 
HasReadOnlyBoxSel() const2401 sal_Bool SwTableCursor::HasReadOnlyBoxSel() const
2402 {
2403 	sal_Bool bRet = sal_False;
2404 	for( sal_uInt16 n = aSelBoxes.Count(); n;  )
2405 		if( aSelBoxes[ --n ]->GetFrmFmt()->GetProtect().IsCntntProtected() )
2406 		{
2407 			bRet = sal_True;
2408 			break;
2409 		}
2410 	return bRet;
2411 }
2412 
2413 
2414