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