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