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