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