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