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