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