xref: /aoo41x/main/sw/source/core/crsr/crsrsh.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 #include <com/sun/star/util/SearchOptions.hpp>
31 #include <com/sun/star/text/XTextRange.hpp>
32 #include <hintids.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <editeng/frmdiritem.hxx>
35 
36 #include <SwSmartTagMgr.hxx>
37 #include <doc.hxx>
38 #include <rootfrm.hxx>
39 #include <pagefrm.hxx>
40 #include <cntfrm.hxx>
41 #include <viewimp.hxx>
42 #include <pam.hxx>
43 #include <swselectionlist.hxx>
44 #include <IBlockCursor.hxx>
45 #include "BlockCursor.hxx"
46 #include <ndtxt.hxx>
47 #include <flyfrm.hxx>
48 #include <dview.hxx>
49 #include <viewopt.hxx>
50 #include <frmtool.hxx>
51 #include <crsrsh.hxx>
52 #include <tabfrm.hxx>
53 #include <txtfrm.hxx>
54 #include <sectfrm.hxx>
55 #include <swtable.hxx>
56 #include <callnk.hxx>
57 #include <viscrs.hxx>
58 #include <section.hxx>
59 #include <docsh.hxx>
60 #include <scriptinfo.hxx>
61 #include <globdoc.hxx>
62 #include <pamtyp.hxx>
63 #include <mdiexp.hxx>			// ...Percent()
64 #include <fmteiro.hxx>
65 #include <wrong.hxx> // SMARTTAGS
66 #include <unotextrange.hxx> // SMARTTAGS
67 #include <vcl/svapp.hxx>
68 #include <numrule.hxx>
69 #include <IGrammarContact.hxx>
70 
71 #include <globals.hrc>
72 
73 #include <comcore.hrc>
74 
75 using namespace com::sun::star;
76 using namespace util;
77 
78 TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
79 
80 
81 // Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
82 void CheckRange( SwCursor* );
83 
84 //-----------------------------------------------------------------------
85 
86 /*
87  * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
88  * Wenn ja, dann hebe den alten Bereich auf.
89  */
90 
91 
92 void CheckRange( SwCursor* pCurCrsr )
93 {
94 	const SwPosition *pStt = pCurCrsr->Start(),
95 		*pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
96 
97 	SwPaM *pTmpDel = 0,
98 		  *pTmp = (SwPaM*)pCurCrsr->GetNext();
99 
100 	// durchsuche den gesamten Ring
101 	while( pTmp != pCurCrsr )
102 	{
103 		const SwPosition *pTmpStt = pTmp->Start(),
104 						*pTmpEnd = pTmp->GetPoint() == pTmpStt ?
105 										pTmp->GetMark() : pTmp->GetPoint();
106 		if( *pStt <= *pTmpStt )
107 		{
108 			if( *pEnd > *pTmpStt ||
109 				( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
110 				pTmpDel = pTmp;
111 		}
112 		else
113 			if( *pStt < *pTmpEnd )
114 				pTmpDel = pTmp;
115 		/*
116 		 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
117 		 * muss der alte Bereich aufgehoben werden.
118 		 * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
119 		 * Bereich gehoert !
120 		 */
121 		pTmp = (SwPaM*)pTmp->GetNext();
122 		if( pTmpDel )
123 		{
124 			delete pTmpDel;         // hebe alten Bereich auf
125 			pTmpDel = 0;
126 		}
127 	}
128 }
129 
130 // -------------- Methoden von der SwCrsrShell -------------
131 
132 SwPaM * SwCrsrShell::CreateCrsr()
133 {
134 	// Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
135 	ASSERT( !IsTableMode(), "in Tabellen SSelection" );
136 
137 	// neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
138 	// Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
139 	SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
140 
141 	// hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
142 	// vom kopierten Pam aufgehoben wird !!
143 
144 	// #i75172# to be able to make a complete content swap, i moved this to a method
145 	// pNew->Insert( pCurCrsr, 0 );
146 	// pCurCrsr->Remove( 0, pCurCrsr->Count() );
147 	pNew->swapContent(*pCurCrsr);
148 
149 	pCurCrsr->DeleteMark();
150 
151 	UpdateCrsr( SwCrsrShell::SCROLLWIN );
152 //	return pCurCrsr;
153 	return pNew;
154 }
155 
156 // loesche den aktuellen Cursor und der folgende wird zum Aktuellen
157 
158 
159 sal_Bool SwCrsrShell::DestroyCrsr()
160 {
161 	// Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
162 	ASSERT( !IsTableMode(), "in Tabellen SSelection" );
163 
164 	// ist ueberhaupt ein naechtser vorhanden ?
165 	if(pCurCrsr->GetNext() == pCurCrsr)
166 		return sal_False;
167 
168 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
169     SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
170 	delete pCurCrsr;
171     pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
172 	UpdateCrsr();
173 	return sal_True;
174 }
175 
176 
177 SwPaM & SwCrsrShell::CreateNewShellCursor()
178 {
179     if (HasSelection())
180     {
181         (void) CreateCrsr(); // n.b. returns old cursor
182     }
183     return *GetCrsr();
184 }
185 
186 SwPaM & SwCrsrShell::GetCurrentShellCursor()
187 {
188     return *GetCrsr();
189 }
190 
191 
192 // gebe den aktuellen zurueck
193 
194 SwPaM* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr ) const
195 {
196 	if( pTblCrsr )
197 	{
198 		if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
199 		{
200 			// geparkte Cursor werden nicht wieder erzeugt
201 			const SwCntntNode* pCNd;
202 			if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
203 				pTblCrsr->GetMark()->nNode.GetIndex() &&
204 				0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) &&
205 				0 != ( pCNd = pTblCrsr->GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( GetLayout() ) )
206 			{
207 				SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
208 				GetLayout()->MakeTblCrsrs( *pTC );
209 			}
210 		}
211 
212 		if( pTblCrsr->IsChgd() )
213 		{
214             const_cast<SwCrsrShell*>(this)->pCurCrsr =
215                 dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
216 		}
217 	}
218 	return pCurCrsr;
219 }
220 
221 
222 void SwCrsrShell::StartAction()
223 {
224 	if( !ActionPend() )
225 	{
226 		// fuer das Update des Ribbon-Bars merken
227 		const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
228 		nAktNode = rNd.GetIndex();
229 		nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
230 		nAktNdTyp = rNd.GetNodeType();
231         bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
232 		if( ND_TEXTNODE & nAktNdTyp )
233 			nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, nAktCntnt, sal_True );
234 		else
235 			nLeftFrmPos = 0;
236 	}
237 	ViewShell::StartAction();           // zur ViewShell
238 }
239 
240 
241 void SwCrsrShell::EndAction( const sal_Bool bIdleEnd )
242 {
243 /*
244 //OS: Wird z.B. eine Basic-Action im Hintergrund ausgefuehrt, geht es so nicht
245 	if( !bHasFocus )
246 	{
247 		// hat die Shell nicht den Focus, dann nur das EndAction an
248 		// die ViewShell weitergeben.
249 		ViewShell::EndAction( bIdleEnd );
250 		return;
251 	}
252 */
253 
254 	sal_Bool bVis = bSVCrsrVis;
255 
256 	// Idle-Formatierung ?
257 	if( bIdleEnd && Imp()->GetRegion() )
258 	{
259 		pCurCrsr->Hide();
260 
261 #ifdef SHOW_IDLE_REGION
262 if( GetWin() )
263 {
264 	GetWin()->Push();
265 	GetWin()->ChangePen( Pen( Color( COL_YELLOW )));
266 	for( sal_uInt16 n = 0; n < aPntReg.Count(); ++n )
267 	{
268 		SwRect aIRect( aPntReg[n] );
269 		GetWin()->DrawRect( aIRect.SVRect() );
270 	}
271 	GetWin()->Pop();
272 }
273 #endif
274 
275 	}
276 
277 	// vor der letzten Action alle invaliden Numerierungen updaten
278 	if( 1 == nStartAction )
279 		GetDoc()->UpdateNumRule();
280 
281 	// Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
282 	//				Only the UpdateCrsr shows the cursor.
283 	sal_Bool bSavSVCrsrVis = bSVCrsrVis;
284 	bSVCrsrVis = sal_False;
285 
286 	ViewShell::EndAction( bIdleEnd );	//der ViewShell den Vortritt lassen
287 
288 	bSVCrsrVis = bSavSVCrsrVis;
289 
290 	if( ActionPend() )
291 	{
292 		if( bVis )    // auch SV-Cursor wieder anzeigen
293 			pVisCrsr->Show();
294 
295 		// falls noch ein ChgCall vorhanden ist und nur noch die Basic
296 		// Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
297 		// mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
298 		if( !BasicActionPend() )
299 		{
300 			//JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction
301 			//				der Cursor geupdatet werden; um z.B. den
302 			//				TabellenCursor zu erzeugen. Im UpdateCrsr wird
303 			//				das jetzt beruecksichtigt!
304 			UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
305 
306 			{
307 				// Crsr-Moves ueberwachen, evt. Link callen
308 				// der DTOR ist das interressante!!
309 				SwCallLink aLk( *this, nAktNode, nAktCntnt, (sal_uInt8)nAktNdTyp,
310 								nLeftFrmPos, bAktSelection );
311 
312 			}
313 			if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
314 			{
315 				aChgLnk.Call( this );
316 				bChgCallFlag = sal_False;		// Flag zuruecksetzen
317 			}
318 		}
319 		return;
320 	}
321 
322 	sal_uInt16 nParm = SwCrsrShell::CHKRANGE;
323 	if ( !bIdleEnd )
324 		nParm |= SwCrsrShell::SCROLLWIN;
325 //    if( !IsViewLocked() )
326 	UpdateCrsr( nParm, bIdleEnd );		// Cursor-Aenderungen anzeigen
327 
328 	{
329 		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
330 		aLk.nNode = nAktNode;           // evt. Link callen
331 		aLk.nNdTyp = (sal_uInt8)nAktNdTyp;
332 		aLk.nCntnt = nAktCntnt;
333 		aLk.nLeftFrmPos = nLeftFrmPos;
334 
335 		if( !nCrsrMove ||
336 			( 1 == nCrsrMove && bInCMvVisportChgd ) )
337 			ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );    // Cursor & Selektionen wieder anzeigen
338 	}
339 	// falls noch ein ChgCall vorhanden ist, dann rufe ihn
340 	if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
341 	{
342 		aChgLnk.Call( this );
343 		bChgCallFlag = sal_False;		// Flag zuruecksetzen
344 	}
345 }
346 
347 
348 #if defined(DBG_UTIL)
349 
350 void SwCrsrShell::SttCrsrMove()
351 {
352 	ASSERT( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
353 	++nCrsrMove;
354 	StartAction();
355 }
356 
357 void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd )
358 {
359 	ASSERT( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
360 	EndAction( bIdleEnd );
361 	if( !--nCrsrMove )
362 		bInCMvVisportChgd = sal_False;
363 }
364 
365 #endif
366 
367 
368 sal_Bool SwCrsrShell::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
369                                  sal_Bool bVisualAllowed )
370 {
371 	if( IsTableMode() )
372 		return bLeft ? GoPrevCell() : GoNextCell();
373 
374 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
375     sal_Bool bRet = sal_False;
376 
377     // #i27615# Handle cursor in front of label.
378     const SwTxtNode* pTxtNd = 0;
379 
380     if( pBlockCrsr )
381         pBlockCrsr->clearPoints();
382 
383     //
384     // 1. CASE: Cursor is in front of label. A move to the right
385     // will simply reset the bInFrontOfLabel flag:
386     //
387     SwShellCrsr* pShellCrsr = getShellCrsr( true );
388     if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
389     {
390         SetInFrontOfLabel( sal_False );
391         bRet = sal_True;
392     }
393     //
394     // 2. CASE: Cursor is at beginning of numbered paragraph. A move
395     // to the left will simply set the bInFrontOfLabel flag:
396     //
397     else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
398              !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
399              0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
400              pTxtNd->HasVisibleNumberingOrBullet() )
401     {
402         SetInFrontOfLabel( sal_True );
403         bRet = sal_True;
404     }
405     //
406     // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
407     //
408     else
409     {
410         const sal_Bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
411         // --> OD 2009-12-30 #i107447#
412         // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
413         // reflected in the return value <bRet>.
414         const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( sal_False );
415         bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
416                                       bSkipHidden, !IsOverwriteCrsr() );
417         if ( !bRet && bLeft && bResetOfInFrontOfLabel )
418         {
419             // undo reset of <bInFrontOfLabel> flag
420             SetInFrontOfLabel( sal_True );
421         }
422         // <--
423     }
424 
425 	if( bRet )
426     {
427 		UpdateCrsr();
428     }
429 	return bRet;
430 }
431 
432 // --> OD 2008-04-02 #refactorlists#
433 void SwCrsrShell::MarkListLevel( const String& sListId,
434                                  const int nListLevel )
435 {
436     if ( sListId != sMarkedListId ||
437          nListLevel != nMarkedListLevel)
438     {
439         if ( sMarkedListId.Len() > 0 )
440             pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, sal_False );
441 
442         if ( sListId.Len() > 0 )
443         {
444             pDoc->MarkListLevel( sListId, nListLevel, sal_True );
445         }
446 
447         sMarkedListId = sListId;
448         nMarkedListLevel = nListLevel;
449     }
450 }
451 
452 void SwCrsrShell::UpdateMarkedListLevel()
453 {
454     SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
455 
456     if ( pTxtNd )
457     {
458         if ( !pTxtNd->IsNumbered() )
459         {
460             pCurCrsr->_SetInFrontOfLabel( sal_False );
461             MarkListLevel( String(), 0 );
462         }
463         else if ( pCurCrsr->IsInFrontOfLabel() )
464         {
465             if ( pTxtNd->IsInList() )
466             {
467                 ASSERT( pTxtNd->GetActualListLevel() >= 0 &&
468                         pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?")
469                 MarkListLevel( pTxtNd->GetListId(),
470                                pTxtNd->GetActualListLevel() );
471             }
472         }
473         else
474         {
475             MarkListLevel( String(), 0 );
476         }
477     }
478 }
479 // <--
480 
481 sal_Bool SwCrsrShell::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
482 {
483 	SET_CURR_SHELL( this );
484 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
485 
486 	sal_Bool bTableMode = IsTableMode();
487 	SwShellCrsr* pTmpCrsr = getShellCrsr( true );
488 
489     sal_Bool bRet = pTmpCrsr->UpDown( bUp, nCnt );
490     // --> FME 2005-01-10 #i40019# UpDown should always reset the
491     // bInFrontOfLabel flag:
492     bRet = SetInFrontOfLabel(sal_False) || bRet;
493     // <--
494 
495     if( pBlockCrsr )
496         pBlockCrsr->clearPoints();
497 
498 	if( bRet )
499 	{
500 		eMvState = MV_UPDOWN;		// Status fuers Crsr-Travelling - GetCrsrOfst
501 		if( !ActionPend() )
502 		{
503 			CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
504 			if( !bTableMode )
505 				eUpdtMode = (CrsrFlag) (eUpdtMode
506 							| SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
507 			UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) );
508 		}
509 	}
510 	return bRet;
511 }
512 
513 
514 sal_Bool SwCrsrShell::LRMargin( sal_Bool bLeft, sal_Bool bAPI)
515 {
516 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
517 	SET_CURR_SHELL( this );
518 	eMvState = MV_LEFTMARGIN;		// Status fuers Crsr-Travelling - GetCrsrOfst
519 
520     const sal_Bool bTableMode = IsTableMode();
521 	SwShellCrsr* pTmpCrsr = getShellCrsr( true );
522 
523     if( pBlockCrsr )
524         pBlockCrsr->clearPoints();
525 
526     const sal_Bool bWasAtLM =
527             ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
528 
529 	sal_Bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
530 
531     if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
532     {
533         const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
534         if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
535             SetInFrontOfLabel( sal_True );
536     }
537     else if ( !bLeft )
538     {
539         bRet = SetInFrontOfLabel( sal_False ) || bRet;
540     }
541 
542 	if( bRet )
543     {
544 		UpdateCrsr();
545     }
546 	return bRet;
547 }
548 
549 sal_Bool SwCrsrShell::IsAtLRMargin( sal_Bool bLeft, sal_Bool bAPI ) const
550 {
551 	const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
552 	return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
553 }
554 
555 
556 sal_Bool SwCrsrShell::SttEndDoc( sal_Bool bStt )
557 {
558 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
559 
560     SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
561 	sal_Bool bRet = pTmpCrsr->SttEndDoc( bStt );
562 	if( bRet )
563 	{
564 		if( bStt )
565 			pTmpCrsr->GetPtPos().Y() = 0;		// expl. 0 setzen (TabellenHeader)
566         if( pBlockCrsr )
567         {
568             pBlockCrsr->clearPoints();
569             RefreshBlockCursor();
570         }
571 
572 		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
573 	}
574 	return bRet;
575 }
576 
577 void SwCrsrShell::ExtendedSelectAll()
578 {
579     SwNodes& rNodes = GetDoc()->GetNodes();
580     SwPosition* pPos = pCurCrsr->GetPoint();
581     pPos->nNode = rNodes.GetEndOfPostIts();
582     pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
583     pPos = pCurCrsr->GetMark();
584     pPos->nNode = rNodes.GetEndOfContent();
585     SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
586     pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
587 }
588 
589 sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
590 {
591 	sal_Bool bRet = sal_False;
592 
593 	// Springe beim Selektieren nie ueber Section-Grenzen !!
594 	if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
595 	{
596 		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
597 		SET_CURR_SHELL( this );
598 
599 		SwCrsrSaveState aSaveState( *pCurCrsr );
600 		Point& rPt = pCurCrsr->GetPtPos();
601 		SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
602 							getLayoutFrm( GetLayout(), &rPt, pCurCrsr->GetPoint(), sal_False );
603 		if( pFrm && sal_True == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
604 												fnPosPage, pCurCrsr )  ) &&
605             !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
606                                  nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
607 			UpdateCrsr();
608 		else
609 			bRet = sal_False;
610 	}
611 	return bRet;
612 }
613 
614 
615 sal_Bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
616 {
617 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
618     SwCursor* pTmpCrsr = getShellCrsr( true );
619 	sal_Bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
620 	if( bRet )
621 		UpdateCrsr();
622 	return bRet;
623 }
624 
625 
626 sal_Bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
627 								SwPosSection fnPosSect)
628 {
629 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
630     SwCursor* pTmpCrsr = getShellCrsr( true );
631 	sal_Bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
632 	if( bRet )
633 		UpdateCrsr();
634 	return bRet;
635 
636 }
637 
638 
639 // Positionieren des Cursors
640 
641 
642 SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
643 {
644 	SwFrm* pFrm = 0;
645 	SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
646 	if( pCNd )
647 	{
648 		pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False )->GetUpper();
649 		while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
650             pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
651 									: pFrm->GetUpper();
652 	}
653 	return pFrm;
654 }
655 
656 sal_Bool SwCrsrShell::IsInHeaderFooter( sal_Bool* pbInHeader ) const
657 {
658 	Point aPt;
659 	SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
660 	if( pFrm && pbInHeader )
661 		*pbInHeader = pFrm->IsHeaderFrm();
662 	return 0 != pFrm;
663 }
664 
665 int SwCrsrShell::SetCrsr( const Point &rLPt, sal_Bool bOnlyText, bool bBlock )
666 {
667 	SET_CURR_SHELL( this );
668 
669 	SwShellCrsr* pCrsr = getShellCrsr( bBlock );
670 	SwPosition aPos( *pCrsr->GetPoint() );
671 	Point aPt( rLPt );
672 	Point & rAktCrsrPt = pCrsr->GetPtPos();
673 	SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
674 									bOnlyText ?  MV_SETONLYTEXT : MV_NONE );
675 	aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
676 
677     SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
678 
679     if ( pTxtNd && !IsTableMode() &&
680         // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
681         !pCrsr->HasMark() &&
682         // <--
683         pTxtNd->HasVisibleNumberingOrBullet() )
684     {
685         aTmpState.bInFrontOfLabel = sal_True; // #i27615#
686     }
687     else
688     {
689         aTmpState.bInFrontOfLabel = sal_False;
690     }
691 
692 	int bRet = CRSR_POSOLD |
693 				( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
694 					? 0 : CRSR_POSCHG );
695 
696     const bool bOldInFrontOfLabel = IsInFrontOfLabel();
697     const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
698 
699     pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
700 
701 	if( MV_RIGHTMARGIN == aTmpState.eState )
702 		eMvState = MV_RIGHTMARGIN;
703 	// steht neu Pos im Header/Footer ?
704 	SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
705     if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
706         pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
707 		// gleiche Tabellenzelle und nicht im Header/Footer
708 		// -> zurueck
709 		return bRet;
710 
711     if( pBlockCrsr && bBlock )
712     {
713         pBlockCrsr->setEndPoint( rLPt );
714         if( !pCrsr->HasMark() )
715             pBlockCrsr->setStartPoint( rLPt );
716         else if( !pBlockCrsr->getStartPoint() )
717             pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
718     }
719 	if( !pCrsr->HasMark() )
720 	{
721 		// steht an der gleichen Position und wenn im Header/Footer,
722 		// dann im gleichen
723 		if( aPos == *pCrsr->GetPoint() &&
724             bOldInFrontOfLabel == bNewInFrontOfLabel )
725 		{
726 			if( pFrm )
727 			{
728 				if( pFrm->Frm().IsInside( rAktCrsrPt ))
729 					return bRet;
730 			}
731 			else if( aPos.nNode.GetNode().IsCntntNode() )
732 			{
733 				// im gleichen Frame gelandet?
734 				SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
735                                 GetLayout(), &aCharRect.Pos(), 0, sal_False );
736 				SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
737                                 GetLayout(), &aPt, 0, sal_False );
738 				if( pNew == pOld )
739 					return bRet;
740 			}
741 		}
742 	}
743 	else
744 	{
745 		// SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
746 		// dann in verschiedene
747 		if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, sal_True )
748 			|| ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
749 			return bRet;
750 
751 		// steht an der gleichen Position und nicht im Header/Footer
752 		if( aPos == *pCrsr->GetPoint() )
753 			return bRet;
754 	}
755 
756 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
757 	SwCrsrSaveState aSaveState( *pCrsr );
758 
759 	*pCrsr->GetPoint() = aPos;
760 	rAktCrsrPt = aPt;
761 
762     // --> FME 2005-01-31 #i41424# Only update the marked number levels if necessary
763     // Force update of marked number levels if necessary.
764     if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
765         pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
766     SetInFrontOfLabel( bNewInFrontOfLabel );
767     // <--
768 
769     if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
770 	{
771         sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
772 		UpdateCrsr( nFlag );
773 		bRet &= ~CRSR_POSOLD;
774 	}
775 	else if( bOnlyText && !pCurCrsr->HasMark() )
776 	{
777 		if( FindValidCntntNode( bOnlyText ) )
778 		{
779 			// Cursor in einen gueltigen Content stellen
780 			if( aPos == *pCrsr->GetPoint() )
781 				bRet = CRSR_POSOLD;
782 			else
783 			{
784 				UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
785 				bRet &= ~CRSR_POSOLD;
786 			}
787 		}
788 		else
789 		{
790 			// es gibt keinen gueltigen Inhalt -> Cursor verstecken
791 			pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
792 			eMvState = MV_NONE;		// Status fuers Crsr-Travelling
793 			bAllProtect = sal_True;
794 			if( GetDoc()->GetDocShell() )
795 			{
796 				GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
797 				CallChgLnk();			// UI bescheid sagen!
798 			}
799 		}
800 	}
801 
802 	return bRet;
803 }
804 
805 
806 void SwCrsrShell::TblCrsrToCursor()
807 {
808 	ASSERT( pTblCrsr, "TblCrsrToCursor: Why?" );
809 	delete pTblCrsr, pTblCrsr = 0;
810 }
811 
812 void SwCrsrShell::BlockCrsrToCrsr()
813 {
814 	ASSERT( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
815     if( pBlockCrsr && !HasSelection() )
816     {
817         SwPaM& rPam = pBlockCrsr->getShellCrsr();
818         pCurCrsr->SetMark();
819         *pCurCrsr->GetPoint() = *rPam.GetPoint();
820         if( rPam.HasMark() )
821             *pCurCrsr->GetMark() = *rPam.GetMark();
822         else
823             pCurCrsr->DeleteMark();
824     }
825 	delete pBlockCrsr, pBlockCrsr = 0;
826 }
827 
828 void SwCrsrShell::CrsrToBlockCrsr()
829 {
830     if( !pBlockCrsr )
831     {
832         SwPosition aPos( *pCurCrsr->GetPoint() );
833         pBlockCrsr = createBlockCursor( *this, aPos );
834         SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
835         rBlock.GetPtPos() = pCurCrsr->GetPtPos();
836         if( pCurCrsr->HasMark() )
837         {
838             rBlock.SetMark();
839             *rBlock.GetMark() = *pCurCrsr->GetMark();
840             rBlock.GetMkPos() = pCurCrsr->GetMkPos();
841         }
842     }
843     pBlockCrsr->clearPoints();
844     RefreshBlockCursor();
845 }
846 
847 void SwCrsrShell::ClearMark()
848 {
849 	// ist ueberhaupt ein GetMark gesetzt ?
850 	if( pTblCrsr )
851 	{
852 		while( pCurCrsr->GetNext() != pCurCrsr )
853 			delete pCurCrsr->GetNext();
854 		pTblCrsr->DeleteMark();
855 
856 		if( pCurCrsr->HasMark() )
857 		{
858 			// falls doch nicht alle Indizies richtig verschoben werden
859 			//	(z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
860 			//	Mark aufs Nodes-Array setzen
861 			SwPosition& rPos = *pCurCrsr->GetMark();
862 			rPos.nNode.Assign( pDoc->GetNodes(), 0 );
863 			rPos.nContent.Assign( 0, 0 );
864 			pCurCrsr->DeleteMark();
865 		}
866 
867 		*pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
868 		pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
869 		delete pTblCrsr, pTblCrsr = 0;
870 		pCurCrsr->SwSelPaintRects::Show();
871 	}
872 	else
873 	{
874 		if( !pCurCrsr->HasMark() )
875 			return;
876 		// falls doch nicht alle Indizies richtig verschoben werden
877 		//	(z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
878 		//	Mark aufs Nodes-Array setzen
879 		SwPosition& rPos = *pCurCrsr->GetMark();
880 		rPos.nNode.Assign( pDoc->GetNodes(), 0 );
881 		rPos.nContent.Assign( 0, 0 );
882 		pCurCrsr->DeleteMark();
883 		if( !nCrsrMove )
884 			pCurCrsr->SwSelPaintRects::Show();
885 	}
886 }
887 
888 
889 void SwCrsrShell::NormalizePam(sal_Bool bPointFirst)
890 {
891 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
892     pCurCrsr->Normalize(bPointFirst);
893 }
894 
895 void SwCrsrShell::SwapPam()
896 {
897 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
898 	pCurCrsr->Exchange();
899 }
900 
901 
902 // suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
903 // den angebenen SPoint umschliesst
904 // Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
905 // SSelection besteht; des akt. Cursr wird nicht umgesetzt!
906 // Ansonsten wird er auf die gewaehlte SSelection gesetzt.
907 
908 
909 sal_Bool SwCrsrShell::ChgCurrPam( const Point & rPt,
910 							  sal_Bool bTstOnly, sal_Bool bTstHit )
911 {
912 	SET_CURR_SHELL( this );
913 
914 	// Pruefe ob der SPoint in einer Tabellen-Selektion liegt
915 	if( bTstOnly && pTblCrsr )
916 		return pTblCrsr->IsInside( rPt );
917 
918 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
919 	// Suche die Position rPt im Dokument
920 	SwPosition aPtPos( *pCurCrsr->GetPoint() );
921 	Point aPt( rPt );
922 
923 	SwCrsrMoveState aTmpState( MV_NONE );
924 	aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
925 	if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
926 		return sal_False;
927 
928 	// suche in allen Selektionen nach dieser Position
929 	SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr;        // sicher den Pointer auf Cursor
930 	do {
931 		if( pCmp->HasMark() &&
932 			*pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
933 		{
934 			if( bTstOnly || pCurCrsr == pCmp )	   // ist der aktuelle.
935 				return sal_True;         			   // return ohne Update
936 
937 			pCurCrsr = pCmp;
938 			UpdateCrsr();     // Cursor steht schon richtig
939 			return sal_True;
940 		}
941 	} while( pCurCrsr !=
942         ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
943 	return sal_False;
944 }
945 
946 
947 void SwCrsrShell::KillPams()
948 {
949 	// keiner zum loeschen vorhanden?
950 	if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
951 		return;
952 
953 	while( pCurCrsr->GetNext() != pCurCrsr )
954 		delete pCurCrsr->GetNext();
955     pCurCrsr->SetColumnSelection( false );
956 
957 	if( pTblCrsr )
958 	{
959 		// Cursor Ring loeschen
960 		pCurCrsr->DeleteMark();
961 		*pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
962 		pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
963 		delete pTblCrsr;
964         pTblCrsr = 0;
965 	}
966     else if( pBlockCrsr )
967 	{
968 		// delete the ring of cursors
969 		pCurCrsr->DeleteMark();
970         SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
971 		*pCurCrsr->GetPoint() = *rBlock.GetPoint();
972 		pCurCrsr->GetPtPos() = rBlock.GetPtPos();
973 		rBlock.DeleteMark();
974         pBlockCrsr->clearPoints();
975 	}
976 	UpdateCrsr( SwCrsrShell::SCROLLWIN );
977 }
978 
979 
980 int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
981 {
982 	int nRet = 0;
983 	const SwPosition *pFirst = 0, *pSecond = 0;
984 	const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
985 	if( CurrPtCurrMk != eType && pStk )
986 	{
987 		switch ( eType)
988 		{
989 		case StackPtStackMk:
990 			pFirst = pStk->GetPoint();
991 			pSecond = pStk->GetMark();
992 			break;
993 		case StackPtCurrPt:
994 			pFirst = pStk->GetPoint();
995 			pSecond = pCur->GetPoint();
996 			break;
997 		case StackPtCurrMk:
998 			pFirst = pStk->GetPoint();
999 			pSecond = pCur->GetMark();
1000 			break;
1001 		case StackMkCurrPt:
1002 			pFirst = pStk->GetMark();
1003 			pSecond = pCur->GetPoint();
1004 			break;
1005 		case StackMkCurrMk:
1006 			pFirst = pStk->GetMark();
1007 			pSecond = pStk->GetMark();
1008 			break;
1009 		case CurrPtCurrMk:
1010 			pFirst = pCur->GetPoint();
1011 			pSecond = pCur->GetMark();
1012 			break;
1013 		}
1014 	}
1015 	if( !pFirst || !pSecond )
1016 		nRet = INT_MAX;
1017 	else if( *pFirst < *pSecond )
1018 		nRet = -1;
1019 	else if( *pFirst == *pSecond )
1020 		nRet = 0;
1021 	else
1022 		nRet = 1;
1023 	return nRet;
1024 }
1025 
1026 
1027 sal_Bool SwCrsrShell::IsSttPara() const
1028 {   return( pCurCrsr->GetPoint()->nContent == 0 ? sal_True : sal_False ); }
1029 
1030 
1031 sal_Bool SwCrsrShell::IsEndPara() const
1032 {   return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? sal_True : sal_False ); }
1033 
1034 
1035 sal_Bool SwCrsrShell::IsInFrontOfLabel() const
1036 {
1037     return pCurCrsr->IsInFrontOfLabel();
1038 }
1039 
1040 bool SwCrsrShell::SetInFrontOfLabel( sal_Bool bNew )
1041 {
1042     if ( bNew != IsInFrontOfLabel() )
1043     {
1044         pCurCrsr->_SetInFrontOfLabel( bNew );
1045         UpdateMarkedListLevel();
1046         return true;
1047     }
1048     return false;
1049 }
1050 
1051 sal_Bool SwCrsrShell::GotoPage( sal_uInt16 nPage )
1052 {
1053 	SET_CURR_SHELL( this );
1054 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1055 	SwCrsrSaveState aSaveState( *pCurCrsr );
1056 	sal_Bool bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
1057                     !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1058                                          nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1059 	if( bRet )
1060 		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
1061 	return bRet;
1062 }
1063 
1064 
1065 void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
1066 							  sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm )
1067 {
1068 	SET_CURR_SHELL( this );
1069 	// Seitennummer: die erste sichtbare Seite oder die am Cursor
1070 	const SwCntntFrm* pCFrm;
1071 	const SwPageFrm *pPg = 0;
1072 
1073 	if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
1074 					   0 == (pPg   = pCFrm->FindPageFrm()) )
1075 	{
1076 		pPg = Imp()->GetFirstVisPage();
1077 		while( pPg && pPg->IsEmptyPage() )
1078 			pPg = (const SwPageFrm *)pPg->GetNext();
1079 	}
1080 	// Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1081 	// standard.vor sein.
1082 	rnPhyNum  = pPg? pPg->GetPhyPageNum() : 1;
1083 	rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
1084 }
1085 
1086 
1087 sal_uInt16 SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext )
1088 {
1089 	SET_CURR_SHELL( this );
1090 
1091 	// Seitennummer: die erste sichtbare Seite oder die am Cursor
1092 	const SwPageFrm *pPg = Imp()->GetFirstVisPage();
1093 	if( pPg )
1094 	{
1095         const SwTwips nPageTop = pPg->Frm().Top();
1096 
1097 		if( bNext )
1098 		{
1099             // go to next view layout row:
1100             do
1101             {
1102                 pPg = (const SwPageFrm *)pPg->GetNext();
1103             }
1104             while( pPg && pPg->Frm().Top() == nPageTop );
1105 
1106             while( pPg && pPg->IsEmptyPage() )
1107                 pPg = (const SwPageFrm *)pPg->GetNext();
1108         }
1109 		else
1110 		{
1111             // go to previous view layout row:
1112             do
1113             {
1114                 pPg = (const SwPageFrm *)pPg->GetPrev();
1115             }
1116             while( pPg && pPg->Frm().Top() == nPageTop );
1117 
1118             while( pPg && pPg->IsEmptyPage() )
1119                 pPg = (const SwPageFrm *)pPg->GetPrev();
1120         }
1121 	}
1122 	// Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1123 	// standard.vor sein.
1124 	return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
1125 }
1126 
1127 
1128 sal_uInt16 SwCrsrShell::GetPageCnt()
1129 {
1130 	SET_CURR_SHELL( this );
1131 	// gebe die Anzahl der Seiten zurueck
1132 	return GetLayout()->GetPageNum();
1133 }
1134 
1135 // Gehe zur naechsten SSelection
1136 
1137 
1138 sal_Bool SwCrsrShell::GoNextCrsr()
1139 {
1140 	// besteht ueberhaupt ein Ring ?
1141 	if( pCurCrsr->GetNext() == pCurCrsr )
1142 		return sal_False;
1143 
1144 	SET_CURR_SHELL( this );
1145 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1146     pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1147 
1148 	// Bug 24086: auch alle anderen anzeigen
1149 	if( !ActionPend() )
1150 	{
1151 		UpdateCrsr();
1152 		pCurCrsr->Show();
1153 	}
1154 	return sal_True;
1155 }
1156 
1157 // gehe zur vorherigen SSelection
1158 
1159 
1160 sal_Bool SwCrsrShell::GoPrevCrsr()
1161 {
1162 	// besteht ueberhaupt ein Ring ?
1163 	if( pCurCrsr->GetNext() == pCurCrsr )
1164 		return sal_False;
1165 
1166 	SET_CURR_SHELL( this );
1167 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1168     pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
1169 
1170 	// Bug 24086: auch alle anderen anzeigen
1171 	if( !ActionPend() )
1172 	{
1173 		UpdateCrsr();
1174 		pCurCrsr->Show();
1175 	}
1176 
1177 	return sal_True;
1178 }
1179 
1180 
1181 void SwCrsrShell::Paint( const Rectangle &rRect)
1182 {
1183 	SET_CURR_SHELL( this );
1184 
1185 	// beim Painten immer alle Cursor ausschalten
1186 	SwRect aRect( rRect );
1187 
1188 	sal_Bool bVis = sal_False;
1189 	// ist Cursor sichtbar, dann verstecke den SV-Cursor
1190 	if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) )	//JP 18.06.97: ???
1191 	{
1192 		bVis = sal_True;
1193 		pVisCrsr->Hide();
1194 	}
1195 
1196 	// Bereich neu painten
1197 	ViewShell::Paint( rRect );
1198 
1199 	if( bHasFocus && !bBasicHideCrsr )
1200 	{
1201 		SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
1202 //		pAktCrsr->Invalidate( aRect );
1203 		if( !ActionPend() )
1204 		{
1205 			// damit nicht rechts/unten die Raender abgeschnitten werden
1206 			pAktCrsr->Invalidate( VisArea() );
1207 			pAktCrsr->Show();
1208 		}
1209 		else
1210 			pAktCrsr->Invalidate( aRect );
1211 
1212 	}
1213 	if( bSVCrsrVis && bVis )        // auch SV-Cursor wieder anzeigen
1214 		pVisCrsr->Show();
1215 }
1216 
1217 
1218 
1219 void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1220 {
1221 	SET_CURR_SHELL( this );
1222 	sal_Bool bVis;      // beim Scrollen immer alle Cursor ausschalten
1223 
1224 	// ist Cursor sichtbar, dann verstecke den SV-Cursor
1225 	if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
1226 		pVisCrsr->Hide();
1227 
1228 	bVisPortChgd = sal_True;
1229 	aOldRBPos.X() = VisArea().Right();
1230 	aOldRBPos.Y() = VisArea().Bottom();
1231 
1232 	//Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
1233 	//ViewShell::VisPo.. ein Update() auf das Window gerufen.
1234 	//Waehrend des Paintens duerfen aber nun wieder keine Selectionen
1235 	//angezeigt werden, deshalb wird der Aufruf hier geklammert.
1236 	ViewShell::VisPortChgd( rRect );        // Bereich verschieben
1237 
1238 /*
1239 	SwRect aRect( rRect );
1240 	if( VisArea().IsOver( aRect ) )
1241 		pCurCrsr->Invalidate( aRect );
1242 */
1243 
1244 	if( bSVCrsrVis && bVis )    // auch SV-Cursor wieder anzeigen
1245 		pVisCrsr->Show();
1246 
1247 	if( nCrsrMove )
1248 		bInCMvVisportChgd = sal_True;
1249 
1250 	bVisPortChgd = sal_False;
1251 }
1252 
1253 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
1254 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
1255 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
1256 // ergibt sich aus seiner aktuellen Position im Layout !!
1257 
1258 
1259 void SwCrsrShell::UpdateCrsrPos()
1260 {
1261 	SET_CURR_SHELL( this );
1262 	++nStartAction;
1263     SwShellCrsr* pShellCrsr = getShellCrsr( true );
1264 	Size aOldSz( GetDocSize() );
1265 	SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
1266 	SwCntntFrm  *pFrm = pCNode ?
1267 		pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
1268 	if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
1269 	{
1270 		SwCrsrMoveState aTmpState( MV_NONE );
1271 		aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1272 		GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1273 									 &aTmpState );
1274 		if( pShellCrsr->HasMark())
1275 			pShellCrsr->DeleteMark();
1276 	}
1277     IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1278     if( pGrammarContact )
1279         pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
1280 	--nStartAction;
1281 	if( aOldSz != GetDocSize() )
1282         SizeChgNotify();
1283 }
1284 
1285 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1286 //				stehen, so mussen diese daraus verschoben werden
1287 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1288 {
1289 	const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1290 	if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1291 	{
1292 		SwNodeIndex aTmp( *pSectNd );
1293 #if OSL_DEBUG_LEVEL > 1
1294         const SwNode* pFrmNd =
1295 #endif
1296         rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1297 
1298 #if OSL_DEBUG_LEVEL > 1
1299         (void) pFrmNd;
1300         ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
1301 #endif
1302 		rIdx = aTmp;
1303 	}
1304 }
1305 
1306 // Try to set the cursor to the next visible content node.
1307 static void lcl_CheckHiddenPara( SwPosition& rPos )
1308 {
1309     SwNodeIndex aTmp( rPos.nNode );
1310     SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1311     while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1312 	{
1313         SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1314         if ( pCntnt && pCntnt->IsTxtNode() )
1315             pTxtNd = (SwTxtNode*)pCntnt;
1316         else
1317             pTxtNd = 0;
1318 	}
1319 
1320     if ( pTxtNd )
1321         rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1322 }
1323 
1324 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
1325 // about invalid text selections in its destructor
1326 class SwNotifyAccAboutInvalidTextSelections
1327 {
1328     private:
1329         SwCrsrShell& mrCrsrSh;
1330 
1331     public:
1332         SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1333             : mrCrsrSh( _rCrsrSh )
1334         {}
1335 
1336         ~SwNotifyAccAboutInvalidTextSelections()
1337         {
1338             mrCrsrSh.InvalidateAccessibleParaTextSelection();
1339         }
1340 };
1341 // <--
1342 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
1343 {
1344 	SET_CURR_SHELL( this );
1345 
1346     ClearUpCrsrs();
1347 
1348 	// erfrage den Count fuer die Start-/End-Actions und ob die Shell
1349 	// ueberhaupt den Focus hat
1350 //	if( ActionPend() /*|| !bHasFocus*/ )
1351 	//JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
1352 	//				Cursor geupdatet werden; um z.B. den TabellenCursor zu
1353 	//				erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
1354 	if( ActionPend() && BasicActionPend() )
1355 	{
1356 		if ( eFlags & SwCrsrShell::READONLY )
1357 			bIgnoreReadonly = sal_True;
1358 		return;             // wenn nicht, dann kein Update !!
1359 	}
1360 
1361     // --> OD 2005-12-14 #i27301#
1362     SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1363     // <--
1364 
1365 	if ( bIgnoreReadonly )
1366 	{
1367 		bIgnoreReadonly = sal_False;
1368 		eFlags |= SwCrsrShell::READONLY;
1369 	}
1370 
1371 	if( eFlags & SwCrsrShell::CHKRANGE )	// alle Cursor-Bewegungen auf
1372 		CheckRange( pCurCrsr );     	// ueberlappende Bereiche testen
1373 
1374 	if( !bIdleEnd )
1375 		CheckTblBoxCntnt();
1376 
1377 	// steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
1378 	// (oder ist noch TabellenMode), dann gilt der Tabellen Mode
1379 	SwPaM* pTstCrsr = getShellCrsr( true );
1380 	if( pTstCrsr->HasMark() && !pBlockCrsr &&
1381 		pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1382 		  ( pTblCrsr ||
1383             pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
1384             pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
1385 	{
1386 		SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1387 		Point aTmpPt( pITmpCrsr->GetPtPos() );
1388 		Point aTmpMk( pITmpCrsr->GetMkPos() );
1389 		SwPosition* pPos = pITmpCrsr->GetPoint();
1390 
1391 		// JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1392 		//				stehen, so mussen diese daraus verschoben werden
1393 		lcl_CheckHiddenSection( pPos->nNode );
1394 		lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1395 
1396 		// Move cursor out of hidden paragraphs
1397         if ( !GetViewOptions()->IsShowHiddenChar() )
1398         {
1399             lcl_CheckHiddenPara( *pPos );
1400             lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1401         }
1402 
1403 		SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1404                               getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
1405 
1406         ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1407 
1408         // --> FME 2005-12-02 #126107# Make code robust. The table
1409         // cursor may point to a table in a currently inactive header.
1410         SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1411         // <--
1412 
1413         if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1414         {
1415             // First check if point is in repeated headline:
1416             bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1417 
1418             // Second check if mark is in repeated headline:
1419             if ( !bInRepeatedHeadline )
1420             {
1421                 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
1422                     getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
1423                 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1424 
1425                 if ( pMarkTblFrm )
1426                 {
1427                     SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1428                     ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1429 
1430                     // --> FME 2005-11-28 #120360# Make code robust:
1431                     if ( pMarkTab )
1432                     {
1433                         bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1434                     }
1435                     // <--
1436                 }
1437             }
1438 
1439             // No table cursor in repeaded headlines:
1440             if ( bInRepeatedHeadline )
1441             {
1442                 pTblFrm = 0;
1443 
1444                 SwPosSection fnPosSect = *pPos <  *pITmpCrsr->GetMark()
1445                                             ? fnSectionStart
1446                                             : fnSectionEnd;
1447 
1448                 // dann nur innerhalb der Box selektieren
1449                 if( pTblCrsr )
1450                 {
1451                     pCurCrsr->SetMark();
1452                     *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
1453                     pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
1454                     pTblCrsr->DeleteMark();
1455                     pTblCrsr->SwSelPaintRects::Hide();
1456                 }
1457 
1458                 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
1459                 (*fnSectionCurr)( *pCurCrsr, fnPosSect );
1460             }
1461 		}
1462 
1463 		// wir wollen wirklich eine Tabellen-Selektion
1464 		if( pTab && pTblFrm )
1465 		{
1466 			if( !pTblCrsr )
1467 			{
1468 				pTblCrsr = new SwShellTableCrsr( *this,
1469 								*pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
1470 								*pPos, aTmpPt );
1471 				pCurCrsr->DeleteMark();
1472 				pCurCrsr->SwSelPaintRects::Hide();
1473 
1474 				CheckTblBoxCntnt();
1475 			}
1476 
1477             SwCrsrMoveState aTmpState( MV_NONE );
1478             aTmpState.bRealHeight = sal_True;
1479             if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
1480             {
1481                 Point aCentrPt( aCharRect.Center() );
1482                 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1483                 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1484 #ifndef DBG_UTIL
1485                 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
1486 #else
1487                 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
1488                     ASSERT( !this, "GetCharRect failed." );
1489 #endif
1490             }
1491 //          ALIGNRECT( aCharRect );
1492 
1493 			pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
1494 			// Curosr in den sichtbaren Bereich scrollen
1495 			if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1496                 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1497 				 !IsCrsrReadonly()) )
1498 			{
1499 				SwFrm* pBoxFrm = pTblFrm;
1500 				while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1501 					pBoxFrm = pBoxFrm->GetUpper();
1502 				if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1503 					MakeVisible( pBoxFrm->Frm() );
1504 				else
1505 					MakeVisible( aCharRect );
1506 			}
1507 
1508 			// lasse vom Layout die Crsr in den Boxen erzeugen
1509 			if( pTblCrsr->IsCrsrMovedUpdt() )
1510 				GetLayout()->MakeTblCrsrs( *pTblCrsr );
1511 			if( bHasFocus && !bBasicHideCrsr )
1512 				pTblCrsr->Show();
1513 
1514 			// Cursor-Points auf die neuen Positionen setzen
1515 			pTblCrsr->GetPtPos().X() = aCharRect.Left();
1516 			pTblCrsr->GetPtPos().Y() = aCharRect.Top();
1517 
1518 			if( bSVCrsrVis )
1519 			{
1520 				aCrsrHeight.X() = 0;
1521                 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1522                                   -aCharRect.Width() : aCharRect.Height();
1523                 pVisCrsr->Show();           // wieder anzeigen
1524 			}
1525 			eMvState = MV_NONE;		// Status fuers Crsr-Travelling - GetCrsrOfst
1526 			if( pTblFrm && Imp()->IsAccessible() )
1527 				Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1528 			return;
1529 		}
1530 	}
1531 
1532 	if( pTblCrsr )
1533 	{
1534 		// Cursor Ring loeschen
1535 		while( pCurCrsr->GetNext() != pCurCrsr )
1536 			delete pCurCrsr->GetNext();
1537 		pCurCrsr->DeleteMark();
1538 		*pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1539 		pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1540 		delete pTblCrsr, pTblCrsr = 0;
1541 	}
1542 
1543 	pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
1544 
1545 	// sind wir vielleicht in einer geschuetzten/versteckten Section ?
1546 	{
1547         SwShellCrsr* pShellCrsr = getShellCrsr( true );
1548 		sal_Bool bChgState = sal_True;
1549 		const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
1550 		if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1551 			( !IsReadOnlyAvailable() &&
1552               pSectNd->GetSection().IsProtectFlag() &&
1553 			 ( !pDoc->GetDocShell() ||
1554 			   !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
1555 		{
1556 			if( !FindValidCntntNode( !HasDrawView() ||
1557 					0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1558 			{
1559 				// alles ist geschuetzt / versteckt -> besonderer Mode
1560 				if( bAllProtect && !IsReadOnlyAvailable() &&
1561                     pSectNd->GetSection().IsProtectFlag() )
1562 					bChgState = sal_False;
1563 				else
1564 				{
1565 					eMvState = MV_NONE;		// Status fuers Crsr-Travelling
1566 					bAllProtect = sal_True;
1567 					if( GetDoc()->GetDocShell() )
1568 					{
1569 						GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1570 						CallChgLnk();		// UI bescheid sagen!
1571 					}
1572 					return;
1573 				}
1574 			}
1575 		}
1576 		if( bChgState )
1577 		{
1578 			sal_Bool bWasAllProtect = bAllProtect;
1579 			bAllProtect = sal_False;
1580 			if( bWasAllProtect && GetDoc()->GetDocShell() &&
1581 				GetDoc()->GetDocShell()->IsReadOnlyUI() )
1582 			{
1583 				GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1584 				CallChgLnk();		// UI bescheid sagen!
1585 			}
1586 		}
1587 	}
1588 
1589 	UpdateCrsrPos();
1590 
1591     // #100722# The cursor must always point into content; there's some code
1592     // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1593     // loops _behind_ the last node in the selection, which always works if you
1594     // are in content.) To achieve this, we'll force cursor(s) to point into
1595     // content, if UpdateCrsrPos() hasn't already done so.
1596     SwPaM* pCmp = pCurCrsr;
1597     do
1598     {
1599         // start will move forwards, end will move backwards
1600         bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1601 
1602         // move point; forward if it's the start, backwards if it's the end
1603         if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1604             pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1605                         fnGoCntnt );
1606 
1607         // move mark (if exists); forward if it's the start, else backwards
1608         if( pCmp->HasMark() )
1609         {
1610             if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1611             {
1612                 pCmp->Exchange();
1613                 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1614                             fnGoCntnt );
1615                 pCmp->Exchange();
1616             }
1617         }
1618 
1619         // iterate to next PaM in ring
1620         pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1621     }
1622     while( pCmp != pCurCrsr );
1623 
1624 
1625 	SwRect aOld( aCharRect );
1626 	sal_Bool bFirst = sal_True;
1627 	SwCntntFrm *pFrm;
1628 	int nLoopCnt = 100;
1629     SwShellCrsr* pShellCrsr = getShellCrsr( true );
1630 
1631 	do {
1632 		sal_Bool bAgainst;
1633 		do {
1634 			bAgainst = sal_False;
1635 			pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1636 						&pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1637 			// ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
1638 			// erzeugt werden, weil ja mal hier einer vorhanden war !!
1639 			if ( !pFrm )
1640 			{
1641 				do
1642 				{
1643 					CalcLayout();
1644 					pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1645 								&pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1646 				}  while( !pFrm );
1647 			}
1648 			else if ( Imp()->IsIdleAction() )
1649 				//Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
1650 				pFrm->PrepareCrsr();
1651 
1652 			// im geschuetzten Fly? aber bei Rahmenselektion ignorieren
1653 			if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1654 				( !Imp()->GetDrawView() ||
1655 				  !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1656 				(!pDoc->GetDocShell() ||
1657 				 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
1658 			{
1659 				// dann suche eine gueltige Position
1660 				sal_Bool bChgState = sal_True;
1661 				if( !FindValidCntntNode(!HasDrawView() ||
1662 					0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1663 				{
1664 					// alles ist geschuetzt / versteckt -> besonderer Mode
1665 					if( bAllProtect )
1666 						bChgState = sal_False;
1667 					else
1668 					{
1669 						eMvState = MV_NONE;     // Status fuers Crsr-Travelling
1670 						bAllProtect = sal_True;
1671 						if( GetDoc()->GetDocShell() )
1672 						{
1673 							GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1674 							CallChgLnk();		// UI bescheid sagen!
1675 						}
1676 						return;
1677 					}
1678 				}
1679 
1680 				if( bChgState )
1681 				{
1682 					sal_Bool bWasAllProtect = bAllProtect;
1683 					bAllProtect = sal_False;
1684 					if( bWasAllProtect && GetDoc()->GetDocShell() &&
1685 						GetDoc()->GetDocShell()->IsReadOnlyUI() )
1686 					{
1687 						GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1688 						CallChgLnk();		// UI bescheid sagen!
1689 					}
1690 					bAllProtect = sal_False;
1691 					bAgainst = sal_True;        // nochmal den richigen Frm suchen
1692 				}
1693 			}
1694 		} while( bAgainst );
1695 
1696 		if( !( eFlags & SwCrsrShell::NOCALRECT ))
1697 		{
1698 			SwCrsrMoveState aTmpState( eMvState );
1699 			aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1700             aTmpState.bRealHeight = sal_True;
1701 			aTmpState.bRealWidth = IsOverwriteCrsr();
1702             aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1703 
1704             // #i27615#,#i30453#
1705             SwSpecialPos aSpecialPos;
1706             aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1707             if (pShellCrsr->IsInFrontOfLabel())
1708             {
1709                 aTmpState.pSpecialPos = &aSpecialPos;
1710             }
1711 
1712 			if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1713 			{
1714 				Point& rPt = pShellCrsr->GetPtPos();
1715 				rPt = aCharRect.Center();
1716 				pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1717             }
1718 //			ALIGNRECT( aCharRect );
1719 
1720             if( !pShellCrsr->HasMark() )
1721 				aCrsrHeight = aTmpState.aRealHeight;
1722 			else
1723 			{
1724 				aCrsrHeight.X() = 0;
1725                 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1726                                   -aCharRect.Width() : aCharRect.Height();
1727 			}
1728 		}
1729 		else
1730 		{
1731 			aCrsrHeight.X() = 0;
1732 			aCrsrHeight.Y() = aCharRect.Height();
1733 		}
1734 
1735 		if( !bFirst && aOld == aCharRect )
1736 			break;
1737 
1738 		// falls das Layout meint, nach dem 100 durchlauf ist man immer noch
1739 		// im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
1740 		// siehe Bug: 29658
1741 		if( !--nLoopCnt )
1742 		{
1743 			ASSERT( !this, "Endlosschleife? CharRect != OldCharRect ");
1744 			break;
1745 		}
1746 		aOld = aCharRect;
1747 		bFirst = sal_False;
1748 
1749 		// Cursor-Points auf die neuen Positionen setzen
1750 		pShellCrsr->GetPtPos().X() = aCharRect.Left();
1751 		pShellCrsr->GetPtPos().Y() = aCharRect.Top();
1752 
1753 		if( !(eFlags & SwCrsrShell::UPDOWN ))	// alte Pos. von Up/Down loeschen
1754 		{
1755 			pFrm->Calc();
1756             nUpDownX = pFrm->IsVertical() ?
1757                        aCharRect.Top() - pFrm->Frm().Top() :
1758                        aCharRect.Left() - pFrm->Frm().Left();
1759         }
1760 
1761 		// Curosr in den sichtbaren Bereich scrollen
1762         if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1763 			(HasSelection() || eFlags & SwCrsrShell::READONLY ||
1764              !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1765 		{
1766 			//JP 30.04.99:  damit das EndAction, beim evtuellen Scrollen, den
1767 			//		SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
1768 			//		gesichert und zurueckgesetzt.
1769 			sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
1770 			MakeSelVisible();
1771 			bSVCrsrVis = bSav;
1772 		}
1773 
1774 	} while( eFlags & SwCrsrShell::SCROLLWIN );
1775 
1776     if( pBlockCrsr )
1777         RefreshBlockCursor();
1778 
1779 	if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
1780     {
1781         if( pTblCrsr )
1782             pTblCrsr->SwSelPaintRects::Show();
1783         else
1784         {
1785             pCurCrsr->SwSelPaintRects::Show();
1786             if( pBlockCrsr )
1787             {
1788                 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1789                 while( pNxt && pNxt != pCurCrsr )
1790                 {
1791                     pNxt->SwSelPaintRects::Show();
1792                     pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1793                 }
1794             }
1795         }
1796     }
1797 
1798 	eMvState = MV_NONE;		// Status fuers Crsr-Travelling - GetCrsrOfst
1799 
1800 	if( pFrm && Imp()->IsAccessible() )
1801 		Imp()->InvalidateAccessibleCursorPosition( pFrm );
1802 
1803     // switch from blinking cursor to read-only-text-selection cursor
1804     static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1805     const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1806                             GetCursorBlinkTime();
1807 
1808     if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1809         ( nBlinkTime != nNoBlinkTime ) )
1810     {
1811         // non blinking cursor in read only - text selection mode
1812         AllSettings aSettings = GetOut()->GetSettings();
1813         StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1814         const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1815                                    Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1816                                    nNoBlinkTime;
1817         aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1818         aSettings.SetStyleSettings( aStyleSettings );
1819         GetOut()->SetSettings( aSettings );
1820     }
1821 
1822     if( bSVCrsrVis )
1823 		pVisCrsr->Show();           // wieder anzeigen
1824 }
1825 
1826 void SwCrsrShell::RefreshBlockCursor()
1827 {
1828     ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
1829     SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1830     Point aPt = rBlock.GetPtPos();
1831     SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
1832     Point aMk;
1833     if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
1834     {
1835         aPt = *pBlockCrsr->getStartPoint();
1836         aMk = *pBlockCrsr->getEndPoint();
1837     }
1838     else
1839     {
1840         aPt = rBlock.GetPtPos();
1841         if( pFrm )
1842         {
1843             if( pFrm->IsVertical() )
1844                 aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
1845             else
1846                 aPt.X() = pFrm->Frm().Left() + GetUpDownX();
1847         }
1848         aMk = rBlock.GetMkPos();
1849     }
1850     SwRect aRect( aMk, aPt );
1851     aRect.Justify();
1852     SwSelectionList aSelList( pFrm );
1853 
1854     if( GetLayout()->FillSelection( aSelList, aRect ) )
1855     {
1856         SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
1857         while( pNxt != pCurCrsr )
1858         {
1859             delete pNxt;
1860             pNxt = (SwCursor*)pCurCrsr->GetNext();
1861         }
1862 
1863         std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1864         std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1865         ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
1866         pCurCrsr->SetMark();
1867         --pPam;
1868         // If there is only one text portion inside the rectangle, a simple
1869         // selection is created
1870         if( pPam == pStart )
1871         {
1872             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1873             if( (*pPam)->HasMark() )
1874                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1875             else
1876                 pCurCrsr->DeleteMark();
1877             delete *pPam;
1878             pCurCrsr->SetColumnSelection( false );
1879         }
1880         else
1881         {
1882             // The order of the SwSelectionList has to be preserved but
1883             // the order inside the ring created by CreateCrsr() is not like
1884             // exspected => First create the selections before the last one
1885             // downto the first selection.
1886             // At least create the cursor for the last selection
1887             --pPam;
1888             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1889             if( (*pPam)->HasMark() )
1890                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1891             else
1892                 pCurCrsr->DeleteMark();
1893             delete *pPam;
1894             pCurCrsr->SetColumnSelection( true );
1895             while( pPam != pStart )
1896             {
1897                 --pPam;
1898 
1899                 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1900                 pNew->Insert( pCurCrsr, 0 );
1901                 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1902                 pCurCrsr->DeleteMark();
1903 
1904                 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1905                 if( (*pPam)->HasMark() )
1906                 {
1907                     pCurCrsr->SetMark();
1908                     *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1909                 }
1910                 else
1911                     pCurCrsr->DeleteMark();
1912                 pCurCrsr->SetColumnSelection( true );
1913                 delete *pPam;
1914             }
1915             {
1916                 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1917                 pNew->Insert( pCurCrsr, 0 );
1918                 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1919                 pCurCrsr->DeleteMark();
1920             }
1921             pPam = aSelList.getEnd();
1922             --pPam;
1923             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1924             if( (*pPam)->HasMark() )
1925             {
1926                 pCurCrsr->SetMark();
1927                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1928             }
1929             else
1930                 pCurCrsr->DeleteMark();
1931             pCurCrsr->SetColumnSelection( true );
1932             delete *pPam;
1933         }
1934 	}
1935 }
1936 
1937 // erzeuge eine Kopie vom Cursor und speicher diese im Stack
1938 
1939 
1940 void SwCrsrShell::Push()
1941 {
1942 	pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
1943 									pCurCrsr->GetPtPos(), pCrsrStk );
1944 
1945 	if( pCurCrsr->HasMark() )
1946 	{
1947 		pCrsrStk->SetMark();
1948 		*pCrsrStk->GetMark() = *pCurCrsr->GetMark();
1949 	}
1950 }
1951 
1952 /*
1953  *  Loescht einen Cursor (gesteuert durch bOldCrsr)
1954  *      - vom Stack oder    ( bOldCrsr = sal_True )
1955  *      - den aktuellen und der auf dem Stack stehende wird zum aktuellen
1956  *
1957  *  Return:  es war auf dem Stack noch einer vorhanden
1958  */
1959 
1960 
1961 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
1962 {
1963 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1964 
1965 	// noch weitere vorhanden ?
1966 	if( 0 == pCrsrStk )
1967 		return sal_False;
1968 
1969 	SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
1970 
1971 	// der Nachfolger wird der Aktuelle
1972 	if( pCrsrStk->GetNext() != pCrsrStk )
1973     {
1974         pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
1975     }
1976 
1977 	if( bOldCrsr )              // loesche vom Stack
1978 		delete pCrsrStk;        //
1979 
1980 	pCrsrStk = pTmp;            // neu zuweisen
1981 
1982 	if( !bOldCrsr )
1983 	{
1984 		SwCrsrSaveState aSaveState( *pCurCrsr );
1985 
1986 		// wurde die sichtbare SSelection nicht veraendert
1987 		if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
1988 			pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
1989 		{
1990 			// "Selektions-Rechtecke" verschieben
1991 			pCurCrsr->Insert( pOldStk, 0 );
1992 			pOldStk->Remove( 0, pOldStk->Count() );
1993 		}
1994 
1995 		if( pOldStk->HasMark() )
1996 		{
1997 			pCurCrsr->SetMark();
1998 			*pCurCrsr->GetMark() = *pOldStk->GetMark();
1999 			pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
2000 		}
2001 		else
2002 			// keine Selection also alte aufheben und auf die alte Pos setzen
2003 			pCurCrsr->DeleteMark();
2004 		*pCurCrsr->GetPoint() = *pOldStk->GetPoint();
2005 		pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
2006 		delete pOldStk;
2007 
2008 		if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2009             !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2010                                  nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2011 			UpdateCrsr();             // akt. Cursor Updaten
2012 	}
2013 	return sal_True;
2014 }
2015 
2016 /*
2017  * Verbinde zwei Cursor miteinander.
2018  * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
2019  */
2020 
2021 
2022 void SwCrsrShell::Combine()
2023 {
2024 	// noch weitere vorhanden ?
2025 	if( 0 == pCrsrStk )
2026 		return;
2027 
2028 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
2029 	SwCrsrSaveState aSaveState( *pCurCrsr );
2030 	if( pCrsrStk->HasMark() )           // nur wenn GetMark gesetzt wurde
2031 	{
2032 #ifndef DBG_UTIL
2033 		CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
2034 #else
2035 		if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
2036 			ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
2037 #endif
2038 		// kopiere das GetMark
2039 		if( !pCurCrsr->HasMark() )
2040 			pCurCrsr->SetMark();
2041 		*pCurCrsr->GetMark() = *pCrsrStk->GetMark();
2042 		pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
2043 	}
2044 
2045 	SwShellCrsr * pTmp = 0;
2046 	if( pCrsrStk->GetNext() != pCrsrStk )
2047     {
2048         pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2049     }
2050 	delete pCrsrStk;
2051 	pCrsrStk = pTmp;
2052 	if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2053         !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2054                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2055 		UpdateCrsr();             // akt. Cursor Updaten
2056 }
2057 
2058 
2059 void SwCrsrShell::HideCrsrs()
2060 {
2061 	if( !bHasFocus || bBasicHideCrsr )
2062 		return;
2063 
2064 	// ist Cursor sichtbar, dann verstecke den SV-Cursor
2065 	if( pVisCrsr->IsVisible() )
2066 	{
2067 		SET_CURR_SHELL( this );
2068 		pVisCrsr->Hide();
2069 	}
2070 	// hebe die Invertierung der SSelection auf
2071 	SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2072 	pAktCrsr->Hide();
2073 }
2074 
2075 
2076 
2077 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
2078 {
2079 	if( !bHasFocus || bAllProtect || bBasicHideCrsr )
2080 		return;
2081 
2082 	SET_CURR_SHELL( this );
2083 	SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2084 	pAktCrsr->Show();
2085 
2086 	if( bSVCrsrVis && bCrsrVis )    // auch SV-Cursor wieder anzeigen
2087 		pVisCrsr->Show();
2088 }
2089 
2090 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
2091 
2092 
2093 void SwCrsrShell::ShowCrsr()
2094 {
2095 	if( !bBasicHideCrsr )
2096 	{
2097 		bSVCrsrVis = sal_True;
2098 		UpdateCrsr();
2099 	}
2100 }
2101 
2102 
2103 void SwCrsrShell::HideCrsr()
2104 {
2105 	if( !bBasicHideCrsr )
2106 	{
2107 		bSVCrsrVis = sal_False;
2108 		// evt. die sel. Bereiche aufheben !!
2109 		SET_CURR_SHELL( this );
2110 		pVisCrsr->Hide();
2111 	}
2112 }
2113 
2114 
2115 void SwCrsrShell::ShLooseFcs()
2116 {
2117 	if( !bBasicHideCrsr )
2118 		HideCrsrs();
2119 	bHasFocus = sal_False;
2120 }
2121 
2122 
2123 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
2124 {
2125 	bHasFocus = sal_True;
2126 	if( !bBasicHideCrsr && VisArea().Width() )
2127 	{
2128 		UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
2129                     SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2130 					: SwCrsrShell::CHKRANGE ) );
2131 		ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
2132 	}
2133 }
2134 
2135 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck
2136 
2137 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
2138 {
2139 	SET_CURR_SHELL( (ViewShell*)this );
2140 	SwCntntFrm *pRet = 0;
2141 	SwCntntNode *pNd = pCurCrsr->GetCntntNode();
2142 	if ( pNd )
2143 	{
2144 		if ( bCalcFrm )
2145 		{
2146 			const sal_uInt16* pST = &nStartAction;
2147 			++(*((sal_uInt16*)pST));
2148 			const Size aOldSz( GetDocSize() );
2149 			pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
2150 			--(*((sal_uInt16*)pST));
2151 			if( aOldSz != GetDocSize() )
2152                 ((SwCrsrShell*)this)->SizeChgNotify();
2153 		}
2154 		else
2155 			pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
2156 	}
2157 	return pRet;
2158 }
2159 
2160 
2161 // alle Attribut/Format-Aenderungen am akt. Node werden an den
2162 // Link weitergeleitet.
2163 
2164 
2165 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2166 {
2167     const sal_uInt16 nWhich = pOld ?
2168                           pOld->Which() :
2169                           pNew ?
2170                           pNew->Which() :
2171                           sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
2172 
2173 	if( bCallChgLnk &&
2174 		( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2175 			nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2176 			nWhich == RES_ATTRSET_CHG ))
2177 		// die Messages werden nicht weitergemeldet
2178 		//MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
2179 		//SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
2180 		//vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
2181 		CallChgLnk();
2182 
2183 	if( aGrfArrivedLnk.IsSet() &&
2184 		( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2185 		aGrfArrivedLnk.Call( this );
2186 }
2187 
2188 
2189 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
2190 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
2191 
2192 
2193 sal_Bool SwCrsrShell::HasSelection() const
2194 {
2195 	const SwPaM* pCrsr = getShellCrsr( true );
2196 	return( IsTableMode() || ( pCrsr->HasMark() &&
2197 			*pCrsr->GetPoint() != *pCrsr->GetMark())
2198 		? sal_True : sal_False );
2199 }
2200 
2201 
2202 void SwCrsrShell::CallChgLnk()
2203 {
2204 	// innerhalb von Start-/End-Action kein Call, sondern nur merken,
2205 	// das sich etwas geaendert hat. Wird bei EndAction beachtet.
2206 	if( BasicActionPend() )
2207 		bChgCallFlag = sal_True;		// das Change merken
2208 	else if( aChgLnk.IsSet() )
2209 	{
2210 		if( bCallChgLnk )
2211 			aChgLnk.Call( this );
2212 		bChgCallFlag = sal_False;		// Flag zuruecksetzen
2213 	}
2214 }
2215 
2216 // returne den am akt.Cursor selektierten Text eines Nodes.
2217 
2218 
2219 String SwCrsrShell::GetSelTxt() const
2220 {
2221 	String aTxt;
2222 	if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2223 		pCurCrsr->GetMark()->nNode.GetIndex() )
2224 	{
2225 		SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2226 		if( pTxtNd )
2227 		{
2228 			xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
2229 			aTxt = pTxtNd->GetExpandTxt( nStt,
2230 					pCurCrsr->End()->nContent.GetIndex() - nStt );
2231 		}
2232 	}
2233 	return aTxt;
2234 }
2235 
2236 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
2237 
2238 
2239 String SwCrsrShell::GetText() const
2240 {
2241 	String aTxt;
2242 	if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2243 		pCurCrsr->GetMark()->nNode.GetIndex() )
2244 	{
2245 		SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2246 		if( pTxtNd )
2247 			aTxt = pTxtNd->GetTxt().Copy(
2248 					pCurCrsr->GetPoint()->nContent.GetIndex() );
2249 	}
2250 	return aTxt;
2251 }
2252 
2253 // hole vom Start/Ende der akt. SSelection das nte Zeichen
2254 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
2255 {
2256 	if( IsTableMode() )			// im TabelleMode nicht moeglich
2257 		return 0;
2258 
2259 	const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
2260 								: bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2261 	SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2262     if( !pTxtNd )
2263         return 0;
2264 
2265 	xub_StrLen nPos = pPos->nContent.GetIndex();
2266 	const String& rStr = pTxtNd->GetTxt();
2267 	sal_Unicode cCh = 0;
2268 
2269 	if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
2270 		cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
2271 
2272 	return cCh;
2273 }
2274 
2275 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen
2276 
2277 
2278 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
2279 {
2280 	if( !pCurCrsr->HasMark() || IsTableMode() )
2281 		return sal_False;			// keine Selektion
2282 
2283 	SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2284 	SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2285 	ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
2286 
2287 	xub_StrLen nPos = pPos->nContent.GetIndex();
2288 	if( bEnd )
2289 	{
2290 		if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
2291 			nPos = nPos + nCount;
2292 		else
2293 			return sal_False;		// nicht mehr moeglich
2294 	}
2295 	else if( nPos >= nCount )
2296 		nPos = nPos - nCount;
2297 	else
2298 		return sal_False;			// nicht mehr moeglich
2299 
2300 	SwCallLink aLk( *this );	// Crsr-Moves ueberwachen,
2301 
2302 	pPos->nContent = nPos;
2303 	UpdateCrsr();
2304 
2305 	return sal_True;
2306 }
2307 
2308 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
2309 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
2310 
2311 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
2312 {
2313 	SET_CURR_SHELL( this );
2314 	Point aPt( rPt );
2315 	SwPosition aPos( *pCurCrsr->GetPoint() );
2316 	SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2317 	aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2318 	aTmpState.bRealHeight = sal_True;
2319 
2320 	sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2321 
2322     SetInFrontOfLabel( sal_False ); // #i27615#
2323 
2324 	// nur in TextNodes anzeigen !!
2325 	SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2326 	if( !pTxtNd )
2327 		return sal_False;
2328 
2329 	const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2330 	if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2331 					( !IsReadOnlyAvailable() &&
2332 					  pSectNd->GetSection().IsProtectFlag())) )
2333 		return sal_False;
2334 
2335 	SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
2336 	if ( Imp()->IsIdleAction() )
2337 		pFrm->PrepareCrsr();
2338 	SwRect aTmp( aCharRect );
2339 
2340 	pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
2341 //	ALIGNRECT( aCharRect );
2342 
2343 	if( aTmp == aCharRect && 		// BUG 10137: bleibt der Cursor auf der
2344 		pVisCrsr->IsVisible() )     // Position nicht hidden & showen
2345 		return sal_True;
2346 
2347 	pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
2348 	if( IsScrollMDI( this, aCharRect ))
2349 	{
2350 		MakeVisible( aCharRect );
2351 		pCurCrsr->Show();
2352 	}
2353 
2354 	// Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
2355 	//			D&D-Cursor will man trotzdem haben
2356 //	if( bSVCrsrVis )
2357 	{
2358 		if( aTmpState.bRealHeight )
2359 			aCrsrHeight = aTmpState.aRealHeight;
2360 		else
2361 		{
2362 			aCrsrHeight.X() = 0;
2363 			aCrsrHeight.Y() = aCharRect.Height();
2364 		}
2365 
2366 		pVisCrsr->SetDragCrsr( sal_True );
2367 		pVisCrsr->Show();           // wieder anzeigen
2368 	}
2369 	return bRet;
2370 }
2371 
2372 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2373 {
2374 	Point aPt( rPt );
2375 	SwPaM aPam( *pCurCrsr->GetPoint() );
2376     GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2377     // --> FME 2004-06-29 #114856# Formular view
2378     return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2379     // <--
2380 }
2381 
2382 
2383 	// returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
2384 	// aufgepspannte haben will - sprich etwas selektiert ist (Basic))
2385 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
2386 {
2387 	Ring* pTmp = GetCrsr()->GetNext();
2388 	sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
2389 					*pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
2390 	while( pTmp != pCurCrsr )
2391 	{
2392 		if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2393 				*((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2394 			++n;
2395 		pTmp = pTmp->GetNext();
2396 	}
2397 	return n;
2398 }
2399 
2400 
2401 sal_Bool SwCrsrShell::IsStartOfDoc() const
2402 {
2403 	if( pCurCrsr->GetPoint()->nContent.GetIndex() )
2404 		return sal_False;
2405 
2406 	// Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
2407 	SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2408 	if( !aIdx.GetNode().IsCntntNode() )
2409 		GetDoc()->GetNodes().GoNext( &aIdx );
2410 	return aIdx == pCurCrsr->GetPoint()->nNode;
2411 }
2412 
2413 
2414 sal_Bool SwCrsrShell::IsEndOfDoc() const
2415 {
2416 	SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2417 	SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2418 	if( !pCNd )
2419 		pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2420 
2421 	return aIdx == pCurCrsr->GetPoint()->nNode &&
2422 			pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
2423 }
2424 
2425 
2426 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
2427 // Cursor auf seinen TextNode (oder StartNode?).
2428 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
2429 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
2430 sal_Bool SwCrsrShell::ParkTblCrsr()
2431 {
2432 	if( !pTblCrsr )
2433 		return sal_False;
2434 
2435 	pTblCrsr->ParkCrsr();
2436 
2437 	while( pCurCrsr->GetNext() != pCurCrsr )
2438 		delete pCurCrsr->GetNext();
2439 
2440 	// vom Cursor !immer! SPoint und Mark umsetzen
2441 	pCurCrsr->SetMark();
2442 	*pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
2443 	pCurCrsr->DeleteMark();
2444 
2445 	return sal_True;
2446 }
2447 
2448 /***********************************************************************
2449 #*	Class		:  SwCrsrShell
2450 #*	Methode 	:  ParkCrsr
2451 #*	Beschreibung:  Vernichtet Selektionen und zus. Crsr aller Shell der
2452 #*				   verbleibende Crsr der Shell wird geparkt.
2453 #*	Datum		:  MA 05. Nov. 92
2454 #*	Update		:  JP 19.09.97
2455 #***********************************************************************/
2456 
2457 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2458 {
2459 	const SwPosition *pStt = pDelRg->Start(),
2460 		*pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2461 
2462 	SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2463 
2464 	// durchsuche den gesamten Ring
2465 	sal_Bool bGoNext;
2466 	do {
2467 		const SwPosition *pTmpStt = pTmp->Start(),
2468 						*pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2469 										pTmp->GetMark() : pTmp->GetPoint();
2470 		/*
2471 		 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
2472 		 * muss der alte Bereich aufgehoben werden.
2473 		 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
2474 		 * Bereich gehoert !
2475 		 */
2476 		if( *pStt <= *pTmpStt )
2477 		{
2478 			if( *pEnd > *pTmpStt ||
2479 				( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2480 				pTmpDel = pTmp;
2481 		}
2482 		else
2483 			if( *pStt < *pTmpEnd )
2484 				pTmpDel = pTmp;
2485 
2486 		bGoNext = sal_True;
2487 		if( pTmpDel )			// ist der Pam im Bereich ?? loesche ihn
2488 		{
2489 			sal_Bool bDelete = sal_True;
2490 			if( *ppDelRing == pTmpDel )
2491 			{
2492 				if( *ppDelRing == pCurCrsr )
2493 				{
2494 					if( sal_True == ( bDelete = GoNextCrsr() ))
2495 					{
2496 						bGoNext = sal_False;
2497 						pTmp = (SwPaM*)pTmp->GetNext();
2498 					}
2499 				}
2500 				else
2501 					bDelete = sal_False;		// StackCrsr nie loeschen !!
2502 			}
2503 
2504 			if( bDelete )
2505 				delete pTmpDel; 		// hebe alten Bereich auf
2506 			else
2507 			{
2508 				pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
2509 				pTmpDel->GetPoint()->nNode = 0;
2510 				pTmpDel->SetMark();
2511 				pTmpDel->DeleteMark();
2512 			}
2513 			pTmpDel = 0;
2514 		}
2515 		else if( !pTmp->HasMark() ) 	// sorge auf jedenfall dafuer, das
2516 		{						// nicht benutzte Indizies beachtet werden!
2517 			pTmp->SetMark();			// SPoint liegt nicht im Bereich,
2518 			pTmp->DeleteMark(); 		// aber vielleicht GetMark, also setzen
2519 		}
2520 		if( bGoNext )
2521 			pTmp = (SwPaM*)pTmp->GetNext();
2522 	} while( !bGoNext || *ppDelRing != pTmp );
2523 }
2524 
2525 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2526 {
2527 	SwNode *pNode = &rIdx.GetNode();
2528 
2529 	// erzeuge einen neuen Pam
2530 	SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2531 	if( pNode->GetStartNode() )
2532 	{
2533 		if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2534 		{
2535 			// der angegebene Node steht in einer Tabelle, also Parke
2536 			// den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
2537 			pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2538 		}
2539 		else	// also auf dem StartNode selbst.
2540 				// Dann immer ueber seinen EndNode den StartNode erfragen !!!
2541 				// (StartOfSection vom StartNode ist der Parent !)
2542 			pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2543 	}
2544 	else
2545 		pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2546 	pNew->SetMark();
2547 	pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2548 
2549 	//Alle Shells wollen etwas davon haben.
2550 	ViewShell *pTmp = this;
2551 	do {
2552 		if( pTmp->IsA( TYPE( SwCrsrShell )))
2553 		{
2554 			SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2555 			if( pSh->pCrsrStk )
2556 				pSh->_ParkPams( pNew, &pSh->pCrsrStk );
2557 
2558 			pSh->_ParkPams( pNew, &pSh->pCurCrsr );
2559 			if( pSh->pTblCrsr )
2560 			{
2561 				// setze den Tabellen Cursor immer auf 0, den aktuellen
2562 				// immer auf den Anfang der Tabelle
2563 				SwPaM* pTCrsr = pSh->GetTblCrs();
2564 				SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2565 				if ( pTblNd )
2566 				{
2567 					pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
2568 					pTCrsr->GetPoint()->nNode = 0;
2569 					pTCrsr->SetMark();
2570 					pTCrsr->DeleteMark();
2571 					pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
2572 				}
2573 			}
2574 		}
2575 	} while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
2576 	delete pNew;
2577 }
2578 
2579 //=========================================================================
2580 
2581 /*
2582  * der Copy-Constructor
2583  * Cursor-Position kopieren, in den Ring eingetragen.
2584  * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
2585  */
2586 
2587 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
2588 	: ViewShell( rShell, pInitWin ),
2589 	SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2590 	pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2591     eMvState( MV_NONE ),
2592     // --> OD 2008-04-02 #refactorlists#
2593     sMarkedListId(),
2594     nMarkedListLevel( 0 )
2595     // <--
2596 {
2597 	SET_CURR_SHELL( this );
2598 	// Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
2599 	pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
2600 	pCurCrsr->GetCntntNode()->Add( this );
2601 
2602 	bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2603 	bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2604 	bOverwriteCrsr = sal_False;
2605 	bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2606 	bSetCrsrInReadOnly = sal_True;
2607 	pVisCrsr = new SwVisCrsr( this );
2608 //	UpdateCrsr( 0 );
2609     // OD 11.02.2003 #100556#
2610     mbMacroExecAllowed = rShell.IsMacroExecAllowed();
2611 }
2612 
2613 
2614 /*
2615  * der normale Constructor
2616  */
2617 
2618 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
2619 							const SwViewOption *pInitOpt )
2620 	: ViewShell( rDoc, pInitWin, pInitOpt ),
2621 	SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2622 	pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2623     eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
2624     // --> OD 2008-04-02 #refactorlists#
2625     sMarkedListId(),
2626     nMarkedListLevel( 0 )
2627     // <--
2628 {
2629 	SET_CURR_SHELL( this );
2630 	/*
2631 	 * Erzeugen des initialen Cursors, wird auf die erste
2632 	 * Inhaltsposition gesetzt
2633 	 */
2634 	SwNodes& rNds = rDoc.GetNodes();
2635 
2636 	SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2637 	SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
2638 
2639 	pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2640 
2641 	// melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
2642 	// Attribut-Aenderungen ueber den Link weiter gemeldet werden.
2643 	pCNd->Add( this );
2644 
2645 	bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2646 	bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2647 	bOverwriteCrsr = sal_False;
2648 	bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2649 	bSetCrsrInReadOnly = sal_True;
2650 
2651 	pVisCrsr = new SwVisCrsr( this );
2652 //	UpdateCrsr( 0 );
2653     // OD 11.02.2003 #100556#
2654     mbMacroExecAllowed = true;
2655 }
2656 
2657 
2658 
2659 SwCrsrShell::~SwCrsrShell()
2660 {
2661 	// wenn es nicht die letzte View so sollte zu mindest das
2662 	// Feld noch geupdatet werden.
2663 	if( GetNext() != this )
2664 		CheckTblBoxCntnt( pCurCrsr->GetPoint() );
2665 	else
2666 		ClearTblBoxCntnt();
2667 
2668 	delete pVisCrsr;
2669     delete pBlockCrsr;
2670 	delete pTblCrsr;
2671 
2672 	/*
2673 	 * Freigabe der Cursor
2674 	 */
2675 	while(pCurCrsr->GetNext() != pCurCrsr)
2676 		delete pCurCrsr->GetNext();
2677 	delete pCurCrsr;
2678 
2679 	// Stack freigeben
2680 	if( pCrsrStk )
2681 	{
2682 		while( pCrsrStk->GetNext() != pCrsrStk )
2683 			delete pCrsrStk->GetNext();
2684 		delete pCrsrStk;
2685 	}
2686 
2687 	// JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
2688 	// 				der CursorShell haengt keine Chance geben, sich an den
2689 	//				TextNode zu haengen.
2690 	if( GetRegisteredIn() )
2691 		GetRegisteredInNonConst()->Remove( this );
2692 }
2693 
2694 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2695 {
2696     if( pTblCrsr )
2697         return pTblCrsr;
2698     if( pBlockCrsr && bBlock )
2699         return &pBlockCrsr->getShellCrsr();
2700     return pCurCrsr;
2701 }
2702 
2703 //Sollte fuer das Clipboard der WaitPtr geschaltet werden?
2704 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
2705 
2706 sal_Bool SwCrsrShell::ShouldWait() const
2707 {
2708 	if ( IsTableMode() || GetCrsrCnt() > 1 )
2709 		return sal_True;
2710 
2711 	if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2712 		return sal_True;
2713 
2714 	SwPaM* pPam = GetCrsr();
2715 	return pPam->Start()->nNode.GetIndex() + 10 <
2716 			pPam->End()->nNode.GetIndex();
2717 }
2718 
2719 
2720 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
2721 {
2722 	if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
2723 		 GetLayout()->MakeTblCrsrs( *pTblCrsr );
2724 	return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
2725 }
2726 
2727 // zeige das akt. selektierte "Object" an
2728 void SwCrsrShell::MakeSelVisible()
2729 {
2730 	ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
2731 	if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
2732 	{
2733 		SwRect aTmp( aCharRect );
2734 		long nDiff = aCharRect.Height() - VisArea().Height();
2735 		if( nDiff < aCrsrHeight.X() )
2736 			aTmp.Top( nDiff + aCharRect.Top() );
2737 		else
2738 		{
2739 			aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
2740 			aTmp.Height( aCrsrHeight.Y() );
2741 		}
2742         if( !aTmp.HasArea() )
2743         {
2744             aTmp.SSize().Height() += 1;
2745             aTmp.SSize().Width() += 1;
2746         }
2747 		MakeVisible( aTmp );
2748 	}
2749 	else
2750 	{
2751 		if( aCharRect.HasArea() )
2752 			MakeVisible( aCharRect );
2753 		else
2754 		{
2755 			SwRect aTmp( aCharRect );
2756 			aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2757 			MakeVisible( aTmp );
2758 		}
2759 	}
2760 }
2761 
2762 
2763 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
2764 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
2765 {
2766 	if( pTblCrsr )		// was soll ich jetzt machen ??
2767 	{
2768 		ASSERT( !this, "TabellenSelection nicht aufgehoben!" );
2769 		return sal_False;
2770 	}
2771 
2772 	//JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
2773 	if( !bAllProtect && GetDoc()->GetDocShell() &&
2774 		GetDoc()->GetDocShell()->IsReadOnlyUI() )
2775 		return sal_True;
2776 
2777 	// dann raus da!
2778 	if( pCurCrsr->HasMark()	)
2779 		ClearMark();
2780 
2781 	// als erstes mal auf Rahmen abpruefen
2782 	SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
2783 	sal_uLong nNdIdx = rNdIdx.GetIndex();		// sichern
2784 	SwNodes& rNds = pDoc->GetNodes();
2785 	SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2786 	const SwCntntFrm * pFrm;
2787 
2788 	if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
2789 		!IsReadOnlyAvailable() && pFrm->IsProtected() &&
2790 		nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2791 	{
2792 		// geschuetzter Rahmen ueberspringen
2793 		SwPaM aPam( *pCurCrsr->GetPoint() );
2794 		aPam.SetMark();
2795 		aPam.GetMark()->nNode = rNds.GetEndOfContent();
2796 		aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2797 
2798 		sal_Bool bFirst = sal_False;
2799 		if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
2800 		{
2801 			aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2802 			pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
2803 		}
2804 
2805 		if( !pCNd )		// sollte nie passieren !!!
2806 		{
2807 			rNdIdx = nNdIdx;		// alten Node zurueck
2808 			return sal_False;
2809 		}
2810 		*pCurCrsr->GetPoint() = *aPam.GetPoint();
2811 	}
2812 	else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2813 	{
2814 		// dann auf den Anfang vom Doc stellen
2815 		rNdIdx = pDoc->GetNodes().GetEndOfExtras();
2816 		pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
2817 															&rNdIdx ), 0 );
2818 		nNdIdx = rNdIdx.GetIndex();
2819 	}
2820 
2821 	sal_Bool bOk = sal_True;
2822 
2823     // #i9059# cursor may not stand in protected cells
2824     //         (unless cursor in protected areas is OK.)
2825     const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2826     if( !IsReadOnlyAvailable()  &&
2827         pTableNode != NULL  &&  rNdIdx.GetNode().IsProtect() )
2828     {
2829         // we're in a table, and we're in a protected area, so we're
2830         // probably in a protected cell.
2831 
2832         // move forward into non-protected area.
2833         SwPaM aPam( rNdIdx.GetNode(), 0 );
2834         while( aPam.GetNode()->IsProtect() &&
2835                aPam.Move( fnMoveForward, fnGoCntnt ) )
2836             ; // nothing to do in the loop; the aPam.Move does the moving!
2837 
2838         // didn't work? then go backwards!
2839         if( aPam.GetNode()->IsProtect() )
2840         {
2841             SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2842 			aPam = aTmpPaM;
2843             while( aPam.GetNode()->IsProtect() &&
2844                    aPam.Move( fnMoveBackward, fnGoCntnt ) )
2845                 ; // nothing to do in the loop; the aPam.Move does the moving!
2846         }
2847 
2848         // if we're successful, set the new position
2849         if( ! aPam.GetNode()->IsProtect() )
2850         {
2851             *pCurCrsr->GetPoint() = *aPam.GetPoint();
2852         }
2853     }
2854 
2855 	// in einem geschuetzten Bereich
2856 	const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2857 	if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2858 		( !IsReadOnlyAvailable() &&
2859 		   pSectNd->GetSection().IsProtectFlag() )) )
2860 	{
2861 		typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
2862         FNGoSection funcGoSection = &SwNodes::GoNextSection;
2863 
2864 		bOk = sal_False;
2865 
2866 		for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2867 		{
2868 			sal_Bool bWeiter;
2869 			do {
2870 				bWeiter = sal_False;
2871                 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2872 											sal_True, !IsReadOnlyAvailable() )) )
2873 				{
2874 					// in eine Tabelle verschoben -> pruefe ob die
2875 					// vielleicht geschuetzt ist
2876 					if( pCNd->FindTableNode() )
2877 					{
2878 						SwCallLink aTmp( *this );
2879 						SwCrsrSaveState aSaveState( *pCurCrsr );
2880 						aTmp.nNdTyp = 0;		// im DTOR nichts machen!
2881 						if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
2882 						{
2883 							const SwSectionNode* pSNd = pCNd->FindSectionNode();
2884 							if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2885 								|| (!IsReadOnlyAvailable()  &&
2886 									pSNd->GetSection().IsProtectFlag() ))
2887 							{
2888 								bOk = sal_True;
2889 								break;		// eine nicht geschuetzte Zelle gef.
2890 							}
2891 							continue;		// dann weiter suchen
2892 						}
2893 					}
2894 					else
2895 					{
2896 						bOk = sal_True;
2897 						break;		// eine nicht geschuetzte Zelle gef.
2898 					}
2899 				}
2900 
2901 				if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2902 				{
2903 					// Teste mal auf Fly - kann auch noch geschuetzt sein!!
2904 					if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
2905 						( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2906 						( bOnlyText && pCNd->IsNoTxtNode() ) )
2907 					{
2908 						// dann weiter suchen!
2909 						bOk = sal_False;
2910 						bWeiter = sal_True;
2911 					}
2912 				}
2913 			} while( bWeiter );
2914 
2915 			if( !bOk )
2916 			{
2917 				if( !nLoopCnt )
2918                     funcGoSection = &SwNodes::GoPrevSection;
2919 				rNdIdx = nNdIdx;
2920 			}
2921 		}
2922 	}
2923 	if( bOk )
2924 	{
2925 		pCNd = rNdIdx.GetNode().GetCntntNode();
2926 //		sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
2927 		xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2928 		pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2929 	}
2930 	else
2931 	{
2932 		pCNd = rNdIdx.GetNode().GetCntntNode();
2933 
2934 		// falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
2935 		// verschieben!!
2936 		if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
2937 		{
2938 			SwCrsrMoveState aTmpState( MV_NONE );
2939 			aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2940 			GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
2941 										&aTmpState );
2942 		}
2943 	}
2944 	return bOk;
2945 }
2946 
2947 
2948 void SwCrsrShell::NewCoreSelection()
2949 {
2950 }
2951 
2952 
2953 sal_Bool SwCrsrShell::IsCrsrReadonly() const
2954 {
2955     if ( GetViewOptions()->IsReadonly() ||
2956          // --> FME 2004-06-29 #114856# Formular view
2957          GetViewOptions()->IsFormView() )
2958          // <--
2959 	{
2960 		SwFrm *pFrm = GetCurrFrm( sal_False );
2961         const SwFlyFrm* pFly;
2962         const SwSection* pSection;
2963 
2964         if( pFrm && pFrm->IsInFly() &&
2965 			 (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
2966 			 pFly->Lower() &&
2967 			 !pFly->Lower()->IsNoTxtFrm() &&
2968 			 !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2969 		{
2970 			return sal_False;
2971 		}
2972         // --> FME 2004-06-22 #114856# edit in readonly sections
2973         else if ( pFrm && pFrm->IsInSct() &&
2974                   0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
2975                   pSection->IsEditInReadonlyFlag() )
2976         {
2977             return sal_False;
2978         }
2979         // <--
2980 
2981 		return sal_True;
2982 	}
2983 	return sal_False;
2984 }
2985 
2986 
2987 // darf der Cursor in ReadOnlyBereiche?
2988 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
2989 {
2990 	// im GlobalDoc darf NIE umgeschaltet werden
2991 	if( (!GetDoc()->GetDocShell() ||
2992 		 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
2993 		bFlag != bSetCrsrInReadOnly )
2994 	{
2995 		// wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
2996 		// Selektionen aufgehoben werden. Denn sonst wird sich darauf
2997 		// verlassen, das nichts geschuetztes selektiert ist!
2998 		if( !bFlag )
2999 		{
3000 			ClearMark();
3001 		}
3002 		bSetCrsrInReadOnly = bFlag;
3003 		UpdateCrsr();
3004 	}
3005 }
3006 
3007 sal_Bool SwCrsrShell::HasReadonlySel() const
3008 {
3009 	sal_Bool bRet = sal_False;
3010 	if( IsReadOnlyAvailable() ||
3011         // --> FME 2004-06-29 #114856# Formular view
3012         GetViewOptions()->IsFormView() )
3013         // <--
3014 	{
3015 		if( pTblCrsr )
3016 			bRet = pTblCrsr->HasReadOnlyBoxSel() ||
3017                    pTblCrsr->HasReadonlySel(
3018                             // --> FME 2004-06-29 #114856# Formular view
3019                             GetViewOptions()->IsFormView() );
3020                             // <--
3021         else
3022 		{
3023 			const SwPaM* pCrsr = pCurCrsr;
3024 
3025 			do {
3026                 if( pCrsr->HasReadonlySel(
3027                         // --> FME 2004-06-29 #114856# Formular view
3028                         GetViewOptions()->IsFormView() ) )
3029                         // <--
3030 					bRet = sal_True;
3031 			} while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
3032 		}
3033 	}
3034 	return bRet;
3035 }
3036 
3037 sal_Bool SwCrsrShell::IsSelFullPara() const
3038 {
3039 	sal_Bool bRet = sal_False;
3040 
3041 	if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
3042 		pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
3043 	{
3044 		xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
3045 				   nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
3046 		if( nStt > nEnd )
3047 		{
3048 			xub_StrLen nTmp = nStt;
3049 			nStt = nEnd;
3050 			nEnd = nTmp;
3051 		}
3052 		const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
3053 		bRet = pCNd && !nStt && nEnd == pCNd->Len();
3054 	}
3055 	return bRet;
3056 }
3057 
3058 short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3059 {
3060 	SwPosition aPos( *pCurCrsr->GetPoint() );
3061 	Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
3062 	if( pPt )
3063 	{
3064 		SwCrsrMoveState aTmpState( MV_NONE );
3065 		aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3066 
3067 		GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3068 	}
3069 
3070     return pDoc->GetTextDirection( aPos, &aPt );
3071 }
3072 
3073 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3074 {
3075     const short nDir = GetTextDirection( pPt );
3076     return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3077 }
3078 
3079 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3080 {
3081     const short nDir = GetTextDirection( pPt );
3082     // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3083     // vertical environment
3084     return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3085 }
3086 
3087 //
3088 // If the current cursor position is inside a hidden range, the hidden range
3089 // is selected:
3090 //
3091 bool SwCrsrShell::SelectHiddenRange()
3092 {
3093     bool bRet = false;
3094     if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
3095     {
3096         SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
3097         const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3098         if ( pNode )
3099         {
3100             const xub_StrLen nPos = rPt.nContent.GetIndex();
3101 
3102             // check if nPos is in hidden range
3103             xub_StrLen nHiddenStart;
3104             xub_StrLen nHiddenEnd;
3105             SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3106             if ( STRING_LEN != nHiddenStart )
3107             {
3108                 // make selection:
3109                 pCurCrsr->SetMark();
3110                 pCurCrsr->GetMark()->nContent = nHiddenEnd;
3111                 bRet = true;
3112             }
3113         }
3114     }
3115 
3116     return bRet;
3117 }
3118 
3119 /*  */
3120 
3121 	// die Suchfunktionen
3122 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
3123 							SwDocPositions eStart, SwDocPositions eEnde,
3124                             sal_Bool& bCancel,
3125 							FindRanges eRng, int bReplace )
3126 {
3127 	if( pTblCrsr )
3128 		GetCrsr();
3129 	delete pTblCrsr, pTblCrsr = 0;
3130     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3131     sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
3132     if( nRet || bCancel )
3133         UpdateCrsr();
3134     return nRet;
3135 }
3136 
3137 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3138 							SwDocPositions eStart, SwDocPositions eEnde,
3139 			                sal_Bool& bCancel,
3140 							FindRanges eRng, const SwTxtFmtColl* pReplFmt )
3141 {
3142 	if( pTblCrsr )
3143 		GetCrsr();
3144 	delete pTblCrsr, pTblCrsr = 0;
3145 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3146 	sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
3147 	if( nRet )
3148 		UpdateCrsr();
3149 	return nRet;
3150 }
3151 
3152 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
3153 							SwDocPositions eStart, SwDocPositions eEnde,
3154 							sal_Bool& bCancel,
3155 							FindRanges eRng, const SearchOptions* pSearchOpt,
3156 							const SfxItemSet* rReplSet )
3157 {
3158 	if( pTblCrsr )
3159 		GetCrsr();
3160 	delete pTblCrsr, pTblCrsr = 0;
3161 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3162 	sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
3163 								eRng, pSearchOpt, rReplSet );
3164 	if( nRet )
3165 		UpdateCrsr();
3166 	return nRet;
3167 }
3168 
3169 void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3170 {
3171 	StartAction();
3172 	SwPaM* pCrsr = GetCrsr();
3173 	*pCrsr->GetPoint() = *rCrsr.GetPoint();
3174 	if(rCrsr.HasMark())
3175 	{
3176 		pCrsr->SetMark();
3177 		*pCrsr->GetMark() = *rCrsr.GetMark();
3178 	}
3179 	if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3180 	{
3181 		const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3182 		do
3183 		{
3184             SwPaM* pCurrentCrsr = CreateCrsr();
3185             *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3186 			if(_pStartCrsr->HasMark())
3187 			{
3188                 pCurrentCrsr->SetMark();
3189                 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3190 			}
3191 		} while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3192 	}
3193 	EndAction();
3194 }
3195 
3196 void lcl_RemoveMark( SwPaM* pPam )
3197 {
3198     ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
3199     pPam->GetMark()->nContent.Assign( 0, 0 );
3200     pPam->GetMark()->nNode = 0;
3201     pPam->DeleteMark();
3202 }
3203 
3204 const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3205 {
3206     const SwStartNode *pRet = rNode.StartOfSectionNode();
3207     while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3208         pRet->GetStartNodeType() == SwTableBoxStartNode )
3209     {
3210         pRet = pRet->StartOfSectionNode();
3211     }
3212     return pRet;
3213 }
3214 
3215 /**
3216    Checks if a position is valid. To be valid the position's node must
3217    be a content node and the content must not be unregistered.
3218 
3219    @param aPos the position to check.
3220 */
3221 bool lcl_PosOk(const SwPosition & aPos)
3222 {
3223     return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3224            SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
3225 }
3226 
3227 /**
3228    Checks if a PaM is valid. For a PaM to be valid its point must be
3229    valid. Additionaly if the PaM has a mark this has to be valid, too.
3230 
3231    @param aPam the PaM to check
3232 */
3233 static bool lcl_CrsrOk(SwPaM & aPam)
3234 {
3235     return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3236         || lcl_PosOk(*aPam.GetMark()));
3237 }
3238 
3239 void SwCrsrShell::ClearUpCrsrs()
3240 {
3241     // start of the ring
3242     SwPaM * pStartCrsr = GetCrsr();
3243     // start loop with second entry of the ring
3244     SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3245     SwPaM * pTmpCrsr;
3246     bool bChanged = false;
3247 
3248     /*
3249        For all entries in the ring except the start entry delete the
3250        entry if it is invalid.
3251     */
3252     while (pCrsr != pStartCrsr)
3253     {
3254         pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3255 
3256         if ( ! lcl_CrsrOk(*pCrsr))
3257         {
3258             delete pCrsr;
3259 
3260             bChanged = true;
3261         }
3262 
3263         pCrsr = pTmpCrsr;
3264     }
3265 
3266     if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
3267     {
3268         lcl_RemoveMark( pStartCrsr );
3269         bChanged = true;
3270     }
3271     if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
3272     {
3273         SwNodes & aNodes = GetDoc()->GetNodes();
3274         const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3275         SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3276         SwNode * pNode = aNodes.GoPrevious(&aIdx);
3277         if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3278             aNodes.GoNext( &aIdx );
3279         if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3280         {
3281             /*
3282               If the start entry of the ring is invalid replace it with a
3283               cursor pointing to the beginning of the first content node in
3284               the document.
3285             */
3286             aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3287             pNode = aNodes.GoNext( &aIdx );
3288         }
3289         bool bFound = (pNode != NULL);
3290 
3291         ASSERT(bFound, "no content node found");
3292 
3293         if (bFound)
3294         {
3295             SwPaM aTmpPam(*pNode);
3296             *pStartCrsr = aTmpPam;
3297         }
3298 
3299         bChanged = true;
3300     }
3301 
3302     /*
3303       If at least one of the cursors in the ring have been deleted or
3304       replaced, remove the table cursor.
3305     */
3306     if (pTblCrsr != NULL && bChanged)
3307         TblCrsrToCursor();
3308 }
3309 
3310 // #111827#
3311 String SwCrsrShell::GetCrsrDescr() const
3312 {
3313     String aResult;
3314 
3315     if (IsMultiSelection())
3316         aResult += String(SW_RES(STR_MULTISEL));
3317     else
3318         aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3319 
3320     return aResult;
3321 }
3322 
3323 // SMARTTAGS
3324 
3325 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3326                              uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3327                              const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
3328 {
3329     // Insert smart tag information
3330     std::vector< rtl::OUString > aSmartTagTypes;
3331     std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3332 
3333     for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
3334     {
3335         const xub_StrLen nSTPos = rSmartTagList.Pos( i );
3336         const xub_StrLen nSTLen = rSmartTagList.Len( i );
3337 
3338         if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3339         {
3340             const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3341             if ( pArea )
3342             {
3343                 aSmartTagTypes.push_back( pArea->maType );
3344                 aStringKeyMaps.push_back( pArea->mxPropertyBag );
3345             }
3346         }
3347     }
3348 
3349     if ( aSmartTagTypes.size() )
3350     {
3351         rSmartTagTypes.realloc( aSmartTagTypes.size() );
3352         rStringKeyMaps.realloc( aSmartTagTypes.size() );
3353 
3354         std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3355         sal_uInt16 i = 0;
3356         for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3357             rSmartTagTypes[i++] = *aTypesIter;
3358 
3359         std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3360         i = 0;
3361         for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3362             rStringKeyMaps[i++] = *aMapsIter;
3363     }
3364 }
3365 
3366 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3367                    SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
3368 {
3369     // create SwPosition for nStartIndex
3370     SwIndex aIndex( &rNode, nBegin );
3371     SwPosition aStartPos( rNode, aIndex );
3372 
3373     // create SwPosition for nEndIndex
3374     SwPosition aEndPos( aStartPos );
3375     aEndPos.nContent = nBegin + nLen;
3376 
3377     const uno::Reference<text::XTextRange> xRange =
3378         SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
3379 
3380     rRange = xRange;
3381 }
3382 
3383 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3384                                    uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3385                                    uno::Reference< text::XTextRange>& rRange ) const
3386 {
3387     if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3388         return;
3389 
3390     SwPaM* pCrsr = GetCrsr();
3391     SwPosition aPos( *pCrsr->GetPoint() );
3392     SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3393     if ( pNode && !pNode->IsInProtectSect() )
3394     {
3395         const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3396         if ( pSmartTagList )
3397         {
3398             xub_StrLen nCurrent = aPos.nContent.GetIndex();
3399             xub_StrLen nBegin = nCurrent;
3400             xub_StrLen nLen = 1;
3401 
3402             if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3403             {
3404                 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3405                 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3406                 if ( pSubList )
3407                 {
3408                     pSmartTagList = pSubList;
3409                     nCurrent = 0;
3410                 }
3411 
3412                 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3413                 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3414             }
3415         }
3416     }
3417 }
3418 
3419 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
3420 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3421                                    uno::Sequence< rtl::OUString >& rSmartTagTypes,
3422                                    uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3423                                    uno::Reference<text::XTextRange>& rRange )
3424 {
3425     if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3426         return;
3427 
3428     SwPaM* pCrsr = GetCrsr();
3429     SwPosition aPos( *pCrsr->GetPoint() );
3430     Point aPt( rPt );
3431     SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3432     SwSpecialPos aSpecialPos;
3433     eTmpState.pSpecialPos = &aSpecialPos;
3434     SwTxtNode *pNode;
3435     const SwWrongList *pSmartTagList;
3436 
3437     if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3438         0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3439         0 != (pSmartTagList = pNode->GetSmartTags()) &&
3440         !pNode->IsInProtectSect() )
3441     {
3442         xub_StrLen nCurrent = aPos.nContent.GetIndex();
3443         xub_StrLen nBegin = nCurrent;
3444         xub_StrLen nLen = 1;
3445 
3446         if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3447         {
3448             const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3449             const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3450             if ( pSubList )
3451             {
3452                 pSmartTagList = pSubList;
3453                 nCurrent = eTmpState.pSpecialPos->nCharOfst;
3454             }
3455 
3456             lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3457             lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3458 
3459             // get smarttag word
3460             String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
3461 
3462             //save the start and end positons of the line and the starting point
3463             Push();
3464             LeftMargin();
3465             xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3466             RightMargin();
3467             xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3468             Pop(sal_False);
3469 
3470             // make sure the selection build later from the
3471             // data below does not include footnotes and other
3472             // "in word" character to the left and right in order
3473             // to preserve those. Therefore count those "in words"
3474             // in order to modify the selection accordingly.
3475             const sal_Unicode* pChar = aText.GetBuffer();
3476             xub_StrLen nLeft = 0;
3477             while (pChar && *pChar++ == CH_TXTATR_INWORD)
3478                 ++nLeft;
3479             pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
3480             xub_StrLen nRight = 0;
3481             while (pChar && *pChar-- == CH_TXTATR_INWORD)
3482                 ++nRight;
3483 
3484             aPos.nContent = nBegin + nLeft;
3485             pCrsr = GetCrsr();
3486             *pCrsr->GetPoint() = aPos;
3487             pCrsr->SetMark();
3488             ExtendSelection( sal_True, nLen - nLeft - nRight );
3489             //no determine the rectangle in the current line
3490             xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3491             //take one less than the line end - otherwise the next line would be calculated
3492             xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
3493             Push();
3494             pCrsr->DeleteMark();
3495             SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3496             rContent = nWordStart;
3497             SwRect aStartRect;
3498             SwCrsrMoveState aState;
3499             aState.bRealWidth = sal_True;
3500             SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3501             SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
3502 
3503             pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3504             rContent = nWordEnd;
3505             SwRect aEndRect;
3506             pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3507             rSelectRect = aStartRect.Union( aEndRect );
3508             Pop(sal_False);
3509         }
3510     }
3511 }
3512 
3513