xref: /aoo42x/main/sw/source/core/crsr/crsrsh.cxx (revision af7a586e)
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 sal_Bool SwCrsrShell::GetCharRectAt( SwRect& rOrig, const SwPosition& rPos,
1237                                      SwCrsrMoveState* pCMS ) const
1238 {
1239     SwCntntFrm * pFrm = GetCurrFrm();
1240     return pFrm ? pFrm->GetCharRect( rOrig, rPos, pCMS ) : sal_False;
1241 }
1242 
1243 
1244 void SwCrsrShell::Paint( const Rectangle &rRect)
1245 {
1246 	SET_CURR_SHELL( this );
1247 
1248 	// beim Painten immer alle Cursor ausschalten
1249 	SwRect aRect( rRect );
1250 
1251 	sal_Bool bVis = sal_False;
1252 	// ist Cursor sichtbar, dann verstecke den SV-Cursor
1253 	if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) )	//JP 18.06.97: ???
1254 	{
1255 		bVis = sal_True;
1256 		pVisCrsr->Hide();
1257 	}
1258 
1259 	// Bereich neu painten
1260 	ViewShell::Paint( rRect );
1261 
1262 	if( bHasFocus && !bBasicHideCrsr )
1263 	{
1264 		SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
1265 //		pAktCrsr->Invalidate( aRect );
1266 		if( !ActionPend() )
1267 		{
1268 			// damit nicht rechts/unten die Raender abgeschnitten werden
1269 			pAktCrsr->Invalidate( VisArea() );
1270 			pAktCrsr->Show();
1271 		}
1272 		else
1273 			pAktCrsr->Invalidate( aRect );
1274 
1275 	}
1276 	if( bSVCrsrVis && bVis )        // auch SV-Cursor wieder anzeigen
1277 		pVisCrsr->Show();
1278 }
1279 
1280 
1281 
1282 void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1283 {
1284 	SET_CURR_SHELL( this );
1285 	sal_Bool bVis;      // beim Scrollen immer alle Cursor ausschalten
1286 
1287 	// ist Cursor sichtbar, dann verstecke den SV-Cursor
1288 	if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
1289 		pVisCrsr->Hide();
1290 
1291 	bVisPortChgd = sal_True;
1292 	aOldRBPos.X() = VisArea().Right();
1293 	aOldRBPos.Y() = VisArea().Bottom();
1294 
1295 	//Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
1296 	//ViewShell::VisPo.. ein Update() auf das Window gerufen.
1297 	//Waehrend des Paintens duerfen aber nun wieder keine Selectionen
1298 	//angezeigt werden, deshalb wird der Aufruf hier geklammert.
1299 	ViewShell::VisPortChgd( rRect );        // Bereich verschieben
1300 
1301 /*
1302 	SwRect aRect( rRect );
1303 	if( VisArea().IsOver( aRect ) )
1304 		pCurCrsr->Invalidate( aRect );
1305 */
1306 
1307 	if( bSVCrsrVis && bVis )    // auch SV-Cursor wieder anzeigen
1308 		pVisCrsr->Show();
1309 
1310 	if( nCrsrMove )
1311 		bInCMvVisportChgd = sal_True;
1312 
1313 	bVisPortChgd = sal_False;
1314 }
1315 
1316 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
1317 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
1318 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
1319 // ergibt sich aus seiner aktuellen Position im Layout !!
1320 
1321 
1322 void SwCrsrShell::UpdateCrsrPos()
1323 {
1324 	SET_CURR_SHELL( this );
1325 	++nStartAction;
1326     SwShellCrsr* pShellCrsr = getShellCrsr( true );
1327 	Size aOldSz( GetDocSize() );
1328 	SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
1329 	SwCntntFrm  *pFrm = pCNode ?
1330 		pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
1331 	if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
1332 	{
1333 		SwCrsrMoveState aTmpState( MV_NONE );
1334 		aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1335 		GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1336 									 &aTmpState );
1337 		if( pShellCrsr->HasMark())
1338 			pShellCrsr->DeleteMark();
1339 	}
1340     IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1341     if( pGrammarContact )
1342         pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
1343 	--nStartAction;
1344 	if( aOldSz != GetDocSize() )
1345         SizeChgNotify();
1346 }
1347 
1348 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1349 //				stehen, so mussen diese daraus verschoben werden
1350 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1351 {
1352 	const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1353 	if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1354 	{
1355 		SwNodeIndex aTmp( *pSectNd );
1356 #if OSL_DEBUG_LEVEL > 1
1357         const SwNode* pFrmNd =
1358 #endif
1359         rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1360 
1361 #if OSL_DEBUG_LEVEL > 1
1362         (void) pFrmNd;
1363         ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
1364 #endif
1365 		rIdx = aTmp;
1366 	}
1367 }
1368 
1369 // Try to set the cursor to the next visible content node.
1370 static void lcl_CheckHiddenPara( SwPosition& rPos )
1371 {
1372     SwNodeIndex aTmp( rPos.nNode );
1373     SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1374     while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1375 	{
1376         SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1377         if ( pCntnt && pCntnt->IsTxtNode() )
1378             pTxtNd = (SwTxtNode*)pCntnt;
1379         else
1380             pTxtNd = 0;
1381 	}
1382 
1383     if ( pTxtNd )
1384         rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1385 }
1386 
1387 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
1388 // about invalid text selections in its destructor
1389 class SwNotifyAccAboutInvalidTextSelections
1390 {
1391     private:
1392         SwCrsrShell& mrCrsrSh;
1393 
1394     public:
1395         SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1396             : mrCrsrSh( _rCrsrSh )
1397         {}
1398 
1399         ~SwNotifyAccAboutInvalidTextSelections()
1400         {
1401             mrCrsrSh.InvalidateAccessibleParaTextSelection();
1402         }
1403 };
1404 // <--
1405 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
1406 {
1407 	SET_CURR_SHELL( this );
1408 
1409     ClearUpCrsrs();
1410 
1411 	// erfrage den Count fuer die Start-/End-Actions und ob die Shell
1412 	// ueberhaupt den Focus hat
1413 //	if( ActionPend() /*|| !bHasFocus*/ )
1414 	//JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
1415 	//				Cursor geupdatet werden; um z.B. den TabellenCursor zu
1416 	//				erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
1417 	if( ActionPend() && BasicActionPend() )
1418 	{
1419 		if ( eFlags & SwCrsrShell::READONLY )
1420 			bIgnoreReadonly = sal_True;
1421 		return;             // wenn nicht, dann kein Update !!
1422 	}
1423 
1424     SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1425 
1426 	if ( bIgnoreReadonly )
1427 	{
1428 		bIgnoreReadonly = sal_False;
1429 		eFlags |= SwCrsrShell::READONLY;
1430 	}
1431 
1432 	if( eFlags & SwCrsrShell::CHKRANGE )	// alle Cursor-Bewegungen auf
1433 		CheckRange( pCurCrsr );     	// ueberlappende Bereiche testen
1434 
1435 	if( !bIdleEnd )
1436 		CheckTblBoxCntnt();
1437 
1438 	// steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
1439 	// (oder ist noch TabellenMode), dann gilt der Tabellen Mode
1440 	SwPaM* pTstCrsr = getShellCrsr( true );
1441 	if( pTstCrsr->HasMark() && !pBlockCrsr &&
1442 		pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1443 		  ( pTblCrsr ||
1444             pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
1445             pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
1446 	{
1447 		SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1448 		Point aTmpPt( pITmpCrsr->GetPtPos() );
1449 		Point aTmpMk( pITmpCrsr->GetMkPos() );
1450 		SwPosition* pPos = pITmpCrsr->GetPoint();
1451 
1452 		// JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1453 		//				stehen, so mussen diese daraus verschoben werden
1454 		lcl_CheckHiddenSection( pPos->nNode );
1455 		lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1456 
1457 		// Move cursor out of hidden paragraphs
1458         if ( !GetViewOptions()->IsShowHiddenChar() )
1459         {
1460             lcl_CheckHiddenPara( *pPos );
1461             lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1462         }
1463 
1464 		SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1465                               getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
1466 
1467         ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1468 
1469         // --> FME 2005-12-02 #126107# Make code robust. The table
1470         // cursor may point to a table in a currently inactive header.
1471         SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1472         // <--
1473 
1474         if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1475         {
1476             // First check if point is in repeated headline:
1477             bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1478 
1479             // Second check if mark is in repeated headline:
1480             if ( !bInRepeatedHeadline )
1481             {
1482                 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
1483                     getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
1484                 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1485 
1486                 if ( pMarkTblFrm )
1487                 {
1488                     SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1489                     ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1490 
1491                     // --> FME 2005-11-28 #120360# Make code robust:
1492                     if ( pMarkTab )
1493                     {
1494                         bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1495                     }
1496                     // <--
1497                 }
1498             }
1499 
1500             // No table cursor in repeaded headlines:
1501             if ( bInRepeatedHeadline )
1502             {
1503                 pTblFrm = 0;
1504 
1505                 SwPosSection fnPosSect = *pPos <  *pITmpCrsr->GetMark()
1506                                             ? fnSectionStart
1507                                             : fnSectionEnd;
1508 
1509                 // dann nur innerhalb der Box selektieren
1510                 if( pTblCrsr )
1511                 {
1512                     pCurCrsr->SetMark();
1513                     *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
1514                     pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
1515                     pTblCrsr->DeleteMark();
1516                     pTblCrsr->SwSelPaintRects::Hide();
1517                 }
1518 
1519                 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
1520                 (*fnSectionCurr)( *pCurCrsr, fnPosSect );
1521             }
1522 		}
1523 
1524 		// wir wollen wirklich eine Tabellen-Selektion
1525 		if( pTab && pTblFrm )
1526 		{
1527 			if( !pTblCrsr )
1528 			{
1529 				pTblCrsr = new SwShellTableCrsr( *this,
1530 								*pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
1531 								*pPos, aTmpPt );
1532 				pCurCrsr->DeleteMark();
1533 				pCurCrsr->SwSelPaintRects::Hide();
1534 
1535 				CheckTblBoxCntnt();
1536 			}
1537 
1538             SwCrsrMoveState aTmpState( MV_NONE );
1539             aTmpState.bRealHeight = sal_True;
1540             if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
1541             {
1542                 Point aCentrPt( aCharRect.Center() );
1543                 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1544                 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1545 #ifndef DBG_UTIL
1546                 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
1547 #else
1548                 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
1549                     ASSERT( !this, "GetCharRect failed." );
1550 #endif
1551             }
1552 //          ALIGNRECT( aCharRect );
1553 
1554 			pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
1555 			// Curosr in den sichtbaren Bereich scrollen
1556 			if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1557                 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1558 				 !IsCrsrReadonly()) )
1559 			{
1560 				SwFrm* pBoxFrm = pTblFrm;
1561 				while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1562 					pBoxFrm = pBoxFrm->GetUpper();
1563 				if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1564 					MakeVisible( pBoxFrm->Frm() );
1565 				else
1566 					MakeVisible( aCharRect );
1567 			}
1568 
1569 			// lasse vom Layout die Crsr in den Boxen erzeugen
1570 			if( pTblCrsr->IsCrsrMovedUpdt() )
1571 				GetLayout()->MakeTblCrsrs( *pTblCrsr );
1572 			if( bHasFocus && !bBasicHideCrsr )
1573 				pTblCrsr->Show();
1574 
1575 			// Cursor-Points auf die neuen Positionen setzen
1576 			pTblCrsr->GetPtPos().X() = aCharRect.Left();
1577 			pTblCrsr->GetPtPos().Y() = aCharRect.Top();
1578 
1579 			if( bSVCrsrVis )
1580 			{
1581 				aCrsrHeight.X() = 0;
1582                 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1583                                   -aCharRect.Width() : aCharRect.Height();
1584                 pVisCrsr->Show();           // wieder anzeigen
1585 			}
1586 			eMvState = MV_NONE;		// Status fuers Crsr-Travelling - GetCrsrOfst
1587 			if( pTblFrm && Imp()->IsAccessible() )
1588 				Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1589 			return;
1590 		}
1591 	}
1592 
1593 	if( pTblCrsr )
1594 	{
1595 		// Cursor Ring loeschen
1596 		while( pCurCrsr->GetNext() != pCurCrsr )
1597 			delete pCurCrsr->GetNext();
1598 		pCurCrsr->DeleteMark();
1599 		*pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1600 		pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1601 		delete pTblCrsr, pTblCrsr = 0;
1602 	}
1603 
1604 	pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
1605 
1606 	// sind wir vielleicht in einer geschuetzten/versteckten Section ?
1607 	{
1608         SwShellCrsr* pShellCrsr = getShellCrsr( true );
1609 		sal_Bool bChgState = sal_True;
1610 		const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
1611 		if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1612 			( !IsReadOnlyAvailable() &&
1613               pSectNd->GetSection().IsProtectFlag() &&
1614 			 ( !pDoc->GetDocShell() ||
1615 			   !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
1616 		{
1617 			if( !FindValidCntntNode( !HasDrawView() ||
1618 					0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1619 			{
1620 				// alles ist geschuetzt / versteckt -> besonderer Mode
1621 				if( bAllProtect && !IsReadOnlyAvailable() &&
1622                     pSectNd->GetSection().IsProtectFlag() )
1623 					bChgState = sal_False;
1624 				else
1625 				{
1626 					eMvState = MV_NONE;		// Status fuers Crsr-Travelling
1627 					bAllProtect = sal_True;
1628 					if( GetDoc()->GetDocShell() )
1629 					{
1630 						GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1631 						CallChgLnk();		// UI bescheid sagen!
1632 					}
1633 					return;
1634 				}
1635 			}
1636 		}
1637 		if( bChgState )
1638 		{
1639 			sal_Bool bWasAllProtect = bAllProtect;
1640 			bAllProtect = sal_False;
1641 			if( bWasAllProtect && GetDoc()->GetDocShell() &&
1642 				GetDoc()->GetDocShell()->IsReadOnlyUI() )
1643 			{
1644 				GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1645 				CallChgLnk();		// UI bescheid sagen!
1646 			}
1647 		}
1648 	}
1649 
1650 	UpdateCrsrPos();
1651 
1652     // #100722# The cursor must always point into content; there's some code
1653     // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1654     // loops _behind_ the last node in the selection, which always works if you
1655     // are in content.) To achieve this, we'll force cursor(s) to point into
1656     // content, if UpdateCrsrPos() hasn't already done so.
1657     SwPaM* pCmp = pCurCrsr;
1658     do
1659     {
1660         // start will move forwards, end will move backwards
1661         bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1662 
1663         // move point; forward if it's the start, backwards if it's the end
1664         if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1665             pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1666                         fnGoCntnt );
1667 
1668         // move mark (if exists); forward if it's the start, else backwards
1669         if( pCmp->HasMark() )
1670         {
1671             if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1672             {
1673                 pCmp->Exchange();
1674                 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1675                             fnGoCntnt );
1676                 pCmp->Exchange();
1677             }
1678         }
1679 
1680         // iterate to next PaM in ring
1681         pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1682     }
1683     while( pCmp != pCurCrsr );
1684 
1685 
1686 	SwRect aOld( aCharRect );
1687 	sal_Bool bFirst = sal_True;
1688 	SwCntntFrm *pFrm;
1689 	int nLoopCnt = 100;
1690     SwShellCrsr* pShellCrsr = getShellCrsr( true );
1691 
1692 	do {
1693 		sal_Bool bAgainst;
1694 		do {
1695 			bAgainst = sal_False;
1696 			pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1697 						&pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1698 			// ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
1699 			// erzeugt werden, weil ja mal hier einer vorhanden war !!
1700 			if ( !pFrm )
1701 			{
1702 				do
1703 				{
1704 					CalcLayout();
1705 					pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1706 								&pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1707 				}  while( !pFrm );
1708 			}
1709 			else if ( Imp()->IsIdleAction() )
1710 				//Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
1711 				pFrm->PrepareCrsr();
1712 
1713 			// im geschuetzten Fly? aber bei Rahmenselektion ignorieren
1714 			if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1715 				( !Imp()->GetDrawView() ||
1716 				  !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1717 				(!pDoc->GetDocShell() ||
1718 				 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
1719 			{
1720 				// dann suche eine gueltige Position
1721 				sal_Bool bChgState = sal_True;
1722 				if( !FindValidCntntNode(!HasDrawView() ||
1723 					0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1724 				{
1725 					// alles ist geschuetzt / versteckt -> besonderer Mode
1726 					if( bAllProtect )
1727 						bChgState = sal_False;
1728 					else
1729 					{
1730 						eMvState = MV_NONE;     // Status fuers Crsr-Travelling
1731 						bAllProtect = sal_True;
1732 						if( GetDoc()->GetDocShell() )
1733 						{
1734 							GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1735 							CallChgLnk();		// UI bescheid sagen!
1736 						}
1737 						return;
1738 					}
1739 				}
1740 
1741 				if( bChgState )
1742 				{
1743 					sal_Bool bWasAllProtect = bAllProtect;
1744 					bAllProtect = sal_False;
1745 					if( bWasAllProtect && GetDoc()->GetDocShell() &&
1746 						GetDoc()->GetDocShell()->IsReadOnlyUI() )
1747 					{
1748 						GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1749 						CallChgLnk();		// UI bescheid sagen!
1750 					}
1751 					bAllProtect = sal_False;
1752 					bAgainst = sal_True;        // nochmal den richigen Frm suchen
1753 				}
1754 			}
1755 		} while( bAgainst );
1756 
1757 		if( !( eFlags & SwCrsrShell::NOCALRECT ))
1758 		{
1759 			SwCrsrMoveState aTmpState( eMvState );
1760 			aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1761             aTmpState.bRealHeight = sal_True;
1762 			aTmpState.bRealWidth = IsOverwriteCrsr();
1763             aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1764 
1765             // #i27615#,#i30453#
1766             SwSpecialPos aSpecialPos;
1767             aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1768             if (pShellCrsr->IsInFrontOfLabel())
1769             {
1770                 aTmpState.pSpecialPos = &aSpecialPos;
1771             }
1772 
1773 			if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1774 			{
1775 				Point& rPt = pShellCrsr->GetPtPos();
1776 				rPt = aCharRect.Center();
1777 				pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1778             }
1779 //			ALIGNRECT( aCharRect );
1780 
1781             if( !pShellCrsr->HasMark() )
1782 				aCrsrHeight = aTmpState.aRealHeight;
1783 			else
1784 			{
1785 				aCrsrHeight.X() = 0;
1786                 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1787                                   -aCharRect.Width() : aCharRect.Height();
1788 			}
1789 		}
1790 		else
1791 		{
1792 			aCrsrHeight.X() = 0;
1793 			aCrsrHeight.Y() = aCharRect.Height();
1794 		}
1795 
1796 		if( !bFirst && aOld == aCharRect )
1797 			break;
1798 
1799 		// falls das Layout meint, nach dem 100 durchlauf ist man immer noch
1800 		// im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
1801 		// siehe Bug: 29658
1802 		if( !--nLoopCnt )
1803 		{
1804 			ASSERT( !this, "Endlosschleife? CharRect != OldCharRect ");
1805 			break;
1806 		}
1807 		aOld = aCharRect;
1808 		bFirst = sal_False;
1809 
1810 		// Cursor-Points auf die neuen Positionen setzen
1811 		pShellCrsr->GetPtPos().X() = aCharRect.Left();
1812 		pShellCrsr->GetPtPos().Y() = aCharRect.Top();
1813 
1814 		if( !(eFlags & SwCrsrShell::UPDOWN ))	// alte Pos. von Up/Down loeschen
1815 		{
1816 			pFrm->Calc();
1817             nUpDownX = pFrm->IsVertical() ?
1818                        aCharRect.Top() - pFrm->Frm().Top() :
1819                        aCharRect.Left() - pFrm->Frm().Left();
1820         }
1821 
1822 		// Curosr in den sichtbaren Bereich scrollen
1823         if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1824 			(HasSelection() || eFlags & SwCrsrShell::READONLY ||
1825              !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1826 		{
1827 			//JP 30.04.99:  damit das EndAction, beim evtuellen Scrollen, den
1828 			//		SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
1829 			//		gesichert und zurueckgesetzt.
1830 			sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
1831 			MakeSelVisible();
1832 			bSVCrsrVis = bSav;
1833 		}
1834 
1835 	} while( eFlags & SwCrsrShell::SCROLLWIN );
1836 
1837     if( pBlockCrsr )
1838         RefreshBlockCursor();
1839 
1840     if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
1841     {
1842         if( pTblCrsr )
1843             pTblCrsr->SwSelPaintRects::Show();
1844         else
1845         {
1846             pCurCrsr->SwSelPaintRects::Show();
1847             if( pBlockCrsr )
1848             {
1849                 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1850                 while( pNxt && pNxt != pCurCrsr )
1851                 {
1852                     pNxt->SwSelPaintRects::Show();
1853                     pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1854                 }
1855             }
1856         }
1857     }
1858 
1859 	eMvState = MV_NONE;		// Status fuers Crsr-Travelling - GetCrsrOfst
1860 
1861 	if( pFrm && Imp()->IsAccessible() )
1862 		Imp()->InvalidateAccessibleCursorPosition( pFrm );
1863 
1864     // switch from blinking cursor to read-only-text-selection cursor
1865     static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1866     const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1867                             GetCursorBlinkTime();
1868 
1869     if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1870         ( nBlinkTime != nNoBlinkTime ) )
1871     {
1872         // non blinking cursor in read only - text selection mode
1873         AllSettings aSettings = GetOut()->GetSettings();
1874         StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1875         const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1876                                    Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1877                                    nNoBlinkTime;
1878         aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1879         aSettings.SetStyleSettings( aStyleSettings );
1880         GetOut()->SetSettings( aSettings );
1881     }
1882 
1883     if( bSVCrsrVis )
1884 		pVisCrsr->Show();           // wieder anzeigen
1885 }
1886 
1887 void SwCrsrShell::RefreshBlockCursor()
1888 {
1889     ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
1890     SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1891     Point aPt = rBlock.GetPtPos();
1892     SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
1893     Point aMk;
1894     if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
1895     {
1896         aPt = *pBlockCrsr->getStartPoint();
1897         aMk = *pBlockCrsr->getEndPoint();
1898     }
1899     else
1900     {
1901         aPt = rBlock.GetPtPos();
1902         if( pFrm )
1903         {
1904             if( pFrm->IsVertical() )
1905                 aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
1906             else
1907                 aPt.X() = pFrm->Frm().Left() + GetUpDownX();
1908         }
1909         aMk = rBlock.GetMkPos();
1910     }
1911     SwRect aRect( aMk, aPt );
1912     aRect.Justify();
1913     SwSelectionList aSelList( pFrm );
1914 
1915     if( GetLayout()->FillSelection( aSelList, aRect ) )
1916     {
1917         SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
1918         while( pNxt != pCurCrsr )
1919         {
1920             delete pNxt;
1921             pNxt = (SwCursor*)pCurCrsr->GetNext();
1922         }
1923 
1924         std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1925         std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1926         ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
1927         pCurCrsr->SetMark();
1928         --pPam;
1929         // If there is only one text portion inside the rectangle, a simple
1930         // selection is created
1931         if( pPam == pStart )
1932         {
1933             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1934             if( (*pPam)->HasMark() )
1935                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1936             else
1937                 pCurCrsr->DeleteMark();
1938             delete *pPam;
1939             pCurCrsr->SetColumnSelection( false );
1940         }
1941         else
1942         {
1943             // The order of the SwSelectionList has to be preserved but
1944             // the order inside the ring created by CreateCrsr() is not like
1945             // exspected => First create the selections before the last one
1946             // downto the first selection.
1947             // At least create the cursor for the last selection
1948             --pPam;
1949             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1950             if( (*pPam)->HasMark() )
1951                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1952             else
1953                 pCurCrsr->DeleteMark();
1954             delete *pPam;
1955             pCurCrsr->SetColumnSelection( true );
1956             while( pPam != pStart )
1957             {
1958                 --pPam;
1959 
1960                 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1961                 pNew->Insert( pCurCrsr, 0 );
1962                 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1963                 pCurCrsr->DeleteMark();
1964 
1965                 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1966                 if( (*pPam)->HasMark() )
1967                 {
1968                     pCurCrsr->SetMark();
1969                     *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1970                 }
1971                 else
1972                     pCurCrsr->DeleteMark();
1973                 pCurCrsr->SetColumnSelection( true );
1974                 delete *pPam;
1975             }
1976             {
1977                 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1978                 pNew->Insert( pCurCrsr, 0 );
1979                 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1980                 pCurCrsr->DeleteMark();
1981             }
1982             pPam = aSelList.getEnd();
1983             --pPam;
1984             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1985             if( (*pPam)->HasMark() )
1986             {
1987                 pCurCrsr->SetMark();
1988                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1989             }
1990             else
1991                 pCurCrsr->DeleteMark();
1992             pCurCrsr->SetColumnSelection( true );
1993             delete *pPam;
1994         }
1995 	}
1996 }
1997 
1998 // erzeuge eine Kopie vom Cursor und speicher diese im Stack
1999 
2000 
2001 void SwCrsrShell::Push()
2002 {
2003 	pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
2004 									pCurCrsr->GetPtPos(), pCrsrStk );
2005 
2006 	if( pCurCrsr->HasMark() )
2007 	{
2008 		pCrsrStk->SetMark();
2009 		*pCrsrStk->GetMark() = *pCurCrsr->GetMark();
2010 	}
2011 }
2012 
2013 /*
2014  *  Loescht einen Cursor (gesteuert durch bOldCrsr)
2015  *      - vom Stack oder    ( bOldCrsr = sal_True )
2016  *      - den aktuellen und der auf dem Stack stehende wird zum aktuellen
2017  *
2018  *  Return:  es war auf dem Stack noch einer vorhanden
2019  */
2020 
2021 
2022 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
2023 {
2024 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
2025 
2026 	// noch weitere vorhanden ?
2027 	if( 0 == pCrsrStk )
2028 		return sal_False;
2029 
2030 	SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
2031 
2032 	// der Nachfolger wird der Aktuelle
2033 	if( pCrsrStk->GetNext() != pCrsrStk )
2034     {
2035         pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2036     }
2037 
2038 	if( bOldCrsr )              // loesche vom Stack
2039 		delete pCrsrStk;        //
2040 
2041 	pCrsrStk = pTmp;            // neu zuweisen
2042 
2043 	if( !bOldCrsr )
2044 	{
2045 		SwCrsrSaveState aSaveState( *pCurCrsr );
2046 
2047 		// wurde die sichtbare SSelection nicht veraendert
2048 		if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
2049 			pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
2050 		{
2051 			// "Selektions-Rechtecke" verschieben
2052 			pCurCrsr->Insert( pOldStk, 0 );
2053 			pOldStk->Remove( 0, pOldStk->Count() );
2054 		}
2055 
2056 		if( pOldStk->HasMark() )
2057 		{
2058 			pCurCrsr->SetMark();
2059 			*pCurCrsr->GetMark() = *pOldStk->GetMark();
2060 			pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
2061 		}
2062 		else
2063 			// keine Selection also alte aufheben und auf die alte Pos setzen
2064 			pCurCrsr->DeleteMark();
2065 		*pCurCrsr->GetPoint() = *pOldStk->GetPoint();
2066 		pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
2067 		delete pOldStk;
2068 
2069 		if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2070             !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2071                                  nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2072 			UpdateCrsr();             // akt. Cursor Updaten
2073 	}
2074 	return sal_True;
2075 }
2076 
2077 /*
2078  * Verbinde zwei Cursor miteinander.
2079  * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
2080  */
2081 
2082 
2083 void SwCrsrShell::Combine()
2084 {
2085 	// noch weitere vorhanden ?
2086 	if( 0 == pCrsrStk )
2087 		return;
2088 
2089 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
2090 	SwCrsrSaveState aSaveState( *pCurCrsr );
2091 	if( pCrsrStk->HasMark() )           // nur wenn GetMark gesetzt wurde
2092 	{
2093 #ifndef DBG_UTIL
2094 		CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
2095 #else
2096 		if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
2097 			ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
2098 #endif
2099 		// kopiere das GetMark
2100 		if( !pCurCrsr->HasMark() )
2101 			pCurCrsr->SetMark();
2102 		*pCurCrsr->GetMark() = *pCrsrStk->GetMark();
2103 		pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
2104 	}
2105 
2106 	SwShellCrsr * pTmp = 0;
2107 	if( pCrsrStk->GetNext() != pCrsrStk )
2108     {
2109         pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2110     }
2111 	delete pCrsrStk;
2112 	pCrsrStk = pTmp;
2113 	if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2114         !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2115                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2116 		UpdateCrsr();             // akt. Cursor Updaten
2117 }
2118 
2119 
2120 void SwCrsrShell::HideCrsrs()
2121 {
2122 	if( !bHasFocus || bBasicHideCrsr )
2123 		return;
2124 
2125 	// ist Cursor sichtbar, dann verstecke den SV-Cursor
2126 	if( pVisCrsr->IsVisible() )
2127 	{
2128 		SET_CURR_SHELL( this );
2129 		pVisCrsr->Hide();
2130 	}
2131 	// hebe die Invertierung der SSelection auf
2132 	SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2133 	pAktCrsr->Hide();
2134 }
2135 
2136 
2137 
2138 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
2139 {
2140 	if( !bHasFocus || bAllProtect || bBasicHideCrsr )
2141 		return;
2142 
2143 	SET_CURR_SHELL( this );
2144 	SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2145 	pAktCrsr->Show();
2146 
2147 	if( bSVCrsrVis && bCrsrVis )    // auch SV-Cursor wieder anzeigen
2148 		pVisCrsr->Show();
2149 }
2150 
2151 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
2152 
2153 
2154 void SwCrsrShell::ShowCrsr()
2155 {
2156     if( !bBasicHideCrsr )
2157     {
2158         bSVCrsrVis = sal_True;
2159         pCurCrsr->SetShowTxtInputFldOverlay( true );
2160         UpdateCrsr();
2161     }
2162 }
2163 
2164 
2165 void SwCrsrShell::HideCrsr()
2166 {
2167     if( !bBasicHideCrsr )
2168     {
2169         bSVCrsrVis = sal_False;
2170         // evt. die sel. Bereiche aufheben !!
2171         SET_CURR_SHELL( this );
2172         pCurCrsr->SetShowTxtInputFldOverlay( false );
2173         pVisCrsr->Hide();
2174     }
2175 }
2176 
2177 
2178 void SwCrsrShell::ShLooseFcs()
2179 {
2180 	if( !bBasicHideCrsr )
2181 		HideCrsrs();
2182 	bHasFocus = sal_False;
2183 }
2184 
2185 
2186 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
2187 {
2188 	bHasFocus = sal_True;
2189 	if( !bBasicHideCrsr && VisArea().Width() )
2190 	{
2191 		UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
2192                     SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2193 					: SwCrsrShell::CHKRANGE ) );
2194 		ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
2195 	}
2196 }
2197 
2198 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck
2199 
2200 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
2201 {
2202 	SET_CURR_SHELL( (ViewShell*)this );
2203 	SwCntntFrm *pRet = 0;
2204 	SwCntntNode *pNd = pCurCrsr->GetCntntNode();
2205 	if ( pNd )
2206 	{
2207 		if ( bCalcFrm )
2208 		{
2209 			const sal_uInt16* pST = &nStartAction;
2210 			++(*((sal_uInt16*)pST));
2211 			const Size aOldSz( GetDocSize() );
2212 			pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
2213 			--(*((sal_uInt16*)pST));
2214 			if( aOldSz != GetDocSize() )
2215                 ((SwCrsrShell*)this)->SizeChgNotify();
2216 		}
2217 		else
2218 			pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
2219 	}
2220 	return pRet;
2221 }
2222 
2223 
2224 // alle Attribut/Format-Aenderungen am akt. Node werden an den
2225 // Link weitergeleitet.
2226 
2227 
2228 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2229 {
2230     const sal_uInt16 nWhich = pOld ?
2231                           pOld->Which() :
2232                           pNew ?
2233                           pNew->Which() :
2234                           sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
2235 
2236 	if( bCallChgLnk &&
2237 		( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2238 			nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2239 			nWhich == RES_ATTRSET_CHG ))
2240 		// die Messages werden nicht weitergemeldet
2241 		//MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
2242 		//SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
2243 		//vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
2244 		CallChgLnk();
2245 
2246 	if( aGrfArrivedLnk.IsSet() &&
2247 		( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2248 		aGrfArrivedLnk.Call( this );
2249 }
2250 
2251 
2252 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
2253 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
2254 
2255 
2256 sal_Bool SwCrsrShell::HasSelection() const
2257 {
2258 	const SwPaM* pCrsr = getShellCrsr( true );
2259 	return( IsTableMode() || ( pCrsr->HasMark() &&
2260 			*pCrsr->GetPoint() != *pCrsr->GetMark())
2261 		? sal_True : sal_False );
2262 }
2263 
2264 
2265 void SwCrsrShell::CallChgLnk()
2266 {
2267 	// innerhalb von Start-/End-Action kein Call, sondern nur merken,
2268 	// das sich etwas geaendert hat. Wird bei EndAction beachtet.
2269 	if( BasicActionPend() )
2270 		bChgCallFlag = sal_True;		// das Change merken
2271 	else if( aChgLnk.IsSet() )
2272 	{
2273 		if( bCallChgLnk )
2274 			aChgLnk.Call( this );
2275 		bChgCallFlag = sal_False;		// Flag zuruecksetzen
2276 	}
2277 }
2278 
2279 // returne den am akt.Cursor selektierten Text eines Nodes.
2280 
2281 
2282 String SwCrsrShell::GetSelTxt() const
2283 {
2284 	String aTxt;
2285 	if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2286 		pCurCrsr->GetMark()->nNode.GetIndex() )
2287 	{
2288 		SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2289 		if( pTxtNd )
2290 		{
2291 			xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
2292 			aTxt = pTxtNd->GetExpandTxt( nStt,
2293 					pCurCrsr->End()->nContent.GetIndex() - nStt );
2294 		}
2295 	}
2296 	return aTxt;
2297 }
2298 
2299 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
2300 
2301 
2302 String SwCrsrShell::GetText() const
2303 {
2304 	String aTxt;
2305 	if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2306 		pCurCrsr->GetMark()->nNode.GetIndex() )
2307 	{
2308 		SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2309 		if( pTxtNd )
2310 			aTxt = pTxtNd->GetTxt().Copy(
2311 					pCurCrsr->GetPoint()->nContent.GetIndex() );
2312 	}
2313 	return aTxt;
2314 }
2315 
2316 // hole vom Start/Ende der akt. SSelection das nte Zeichen
2317 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
2318 {
2319 	if( IsTableMode() )			// im TabelleMode nicht moeglich
2320 		return 0;
2321 
2322 	const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
2323 								: bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2324 	SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2325     if( !pTxtNd )
2326         return 0;
2327 
2328 	xub_StrLen nPos = pPos->nContent.GetIndex();
2329 	const String& rStr = pTxtNd->GetTxt();
2330 	sal_Unicode cCh = 0;
2331 
2332 	if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
2333 		cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
2334 
2335 	return cCh;
2336 }
2337 
2338 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen
2339 
2340 
2341 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
2342 {
2343 	if( !pCurCrsr->HasMark() || IsTableMode() )
2344 		return sal_False;			// keine Selektion
2345 
2346 	SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2347 	SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2348 	ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
2349 
2350 	xub_StrLen nPos = pPos->nContent.GetIndex();
2351 	if( bEnd )
2352 	{
2353 		if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
2354 			nPos = nPos + nCount;
2355 		else
2356 			return sal_False;		// nicht mehr moeglich
2357 	}
2358 	else if( nPos >= nCount )
2359 		nPos = nPos - nCount;
2360 	else
2361 		return sal_False;			// nicht mehr moeglich
2362 
2363 	SwCallLink aLk( *this );	// Crsr-Moves ueberwachen,
2364 
2365 	pPos->nContent = nPos;
2366 	UpdateCrsr();
2367 
2368 	return sal_True;
2369 }
2370 
2371 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
2372 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
2373 
2374 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
2375 {
2376 	SET_CURR_SHELL( this );
2377 	Point aPt( rPt );
2378 	SwPosition aPos( *pCurCrsr->GetPoint() );
2379 	SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2380 	aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2381 	aTmpState.bRealHeight = sal_True;
2382 
2383 	sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2384 
2385     SetInFrontOfLabel( sal_False ); // #i27615#
2386 
2387 	// nur in TextNodes anzeigen !!
2388 	SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2389 	if( !pTxtNd )
2390 		return sal_False;
2391 
2392 	const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2393 	if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2394 					( !IsReadOnlyAvailable() &&
2395 					  pSectNd->GetSection().IsProtectFlag())) )
2396 		return sal_False;
2397 
2398 	SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
2399 	if ( Imp()->IsIdleAction() )
2400 		pFrm->PrepareCrsr();
2401 	SwRect aTmp( aCharRect );
2402 
2403 	pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
2404 //	ALIGNRECT( aCharRect );
2405 
2406 	if( aTmp == aCharRect && 		// BUG 10137: bleibt der Cursor auf der
2407 		pVisCrsr->IsVisible() )     // Position nicht hidden & showen
2408 		return sal_True;
2409 
2410 	pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
2411 	if( IsScrollMDI( this, aCharRect ))
2412 	{
2413 		MakeVisible( aCharRect );
2414 		pCurCrsr->Show();
2415 	}
2416 
2417 	// Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
2418 	//			D&D-Cursor will man trotzdem haben
2419 //	if( bSVCrsrVis )
2420 	{
2421 		if( aTmpState.bRealHeight )
2422 			aCrsrHeight = aTmpState.aRealHeight;
2423 		else
2424 		{
2425 			aCrsrHeight.X() = 0;
2426 			aCrsrHeight.Y() = aCharRect.Height();
2427 		}
2428 
2429 		pVisCrsr->SetDragCrsr( sal_True );
2430 		pVisCrsr->Show();           // wieder anzeigen
2431 	}
2432 	return bRet;
2433 }
2434 
2435 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2436 {
2437 	Point aPt( rPt );
2438 	SwPaM aPam( *pCurCrsr->GetPoint() );
2439     GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2440     return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2441 }
2442 
2443 
2444 	// returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
2445 	// aufgepspannte haben will - sprich etwas selektiert ist (Basic))
2446 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
2447 {
2448 	Ring* pTmp = GetCrsr()->GetNext();
2449 	sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
2450 					*pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
2451 	while( pTmp != pCurCrsr )
2452 	{
2453 		if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2454 				*((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2455 			++n;
2456 		pTmp = pTmp->GetNext();
2457 	}
2458 	return n;
2459 }
2460 
2461 
2462 sal_Bool SwCrsrShell::IsStartOfDoc() const
2463 {
2464 	if( pCurCrsr->GetPoint()->nContent.GetIndex() )
2465 		return sal_False;
2466 
2467 	// Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
2468 	SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2469 	if( !aIdx.GetNode().IsCntntNode() )
2470 		GetDoc()->GetNodes().GoNext( &aIdx );
2471 	return aIdx == pCurCrsr->GetPoint()->nNode;
2472 }
2473 
2474 
2475 sal_Bool SwCrsrShell::IsEndOfDoc() const
2476 {
2477 	SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2478 	SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2479 	if( !pCNd )
2480 		pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2481 
2482 	return aIdx == pCurCrsr->GetPoint()->nNode &&
2483 			pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
2484 }
2485 
2486 
2487 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
2488 // Cursor auf seinen TextNode (oder StartNode?).
2489 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
2490 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
2491 sal_Bool SwCrsrShell::ParkTblCrsr()
2492 {
2493 	if( !pTblCrsr )
2494 		return sal_False;
2495 
2496 	pTblCrsr->ParkCrsr();
2497 
2498 	while( pCurCrsr->GetNext() != pCurCrsr )
2499 		delete pCurCrsr->GetNext();
2500 
2501 	// vom Cursor !immer! SPoint und Mark umsetzen
2502 	pCurCrsr->SetMark();
2503 	*pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
2504 	pCurCrsr->DeleteMark();
2505 
2506 	return sal_True;
2507 }
2508 
2509 /***********************************************************************
2510 #*	Class		:  SwCrsrShell
2511 #*	Methode 	:  ParkCrsr
2512 #*	Beschreibung:  Vernichtet Selektionen und zus. Crsr aller Shell der
2513 #*				   verbleibende Crsr der Shell wird geparkt.
2514 #*	Datum		:  MA 05. Nov. 92
2515 #*	Update		:  JP 19.09.97
2516 #***********************************************************************/
2517 
2518 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2519 {
2520 	const SwPosition *pStt = pDelRg->Start(),
2521 		*pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2522 
2523 	SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2524 
2525 	// durchsuche den gesamten Ring
2526 	sal_Bool bGoNext;
2527 	do {
2528 		const SwPosition *pTmpStt = pTmp->Start(),
2529 						*pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2530 										pTmp->GetMark() : pTmp->GetPoint();
2531 		/*
2532 		 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
2533 		 * muss der alte Bereich aufgehoben werden.
2534 		 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
2535 		 * Bereich gehoert !
2536 		 */
2537 		if( *pStt <= *pTmpStt )
2538 		{
2539 			if( *pEnd > *pTmpStt ||
2540 				( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2541 				pTmpDel = pTmp;
2542 		}
2543 		else
2544 			if( *pStt < *pTmpEnd )
2545 				pTmpDel = pTmp;
2546 
2547 		bGoNext = sal_True;
2548 		if( pTmpDel )			// ist der Pam im Bereich ?? loesche ihn
2549 		{
2550 			sal_Bool bDelete = sal_True;
2551 			if( *ppDelRing == pTmpDel )
2552 			{
2553 				if( *ppDelRing == pCurCrsr )
2554 				{
2555 					if( sal_True == ( bDelete = GoNextCrsr() ))
2556 					{
2557 						bGoNext = sal_False;
2558 						pTmp = (SwPaM*)pTmp->GetNext();
2559 					}
2560 				}
2561 				else
2562 					bDelete = sal_False;		// StackCrsr nie loeschen !!
2563 			}
2564 
2565 			if( bDelete )
2566 				delete pTmpDel; 		// hebe alten Bereich auf
2567 			else
2568 			{
2569 				pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
2570 				pTmpDel->GetPoint()->nNode = 0;
2571 				pTmpDel->SetMark();
2572 				pTmpDel->DeleteMark();
2573 			}
2574 			pTmpDel = 0;
2575 		}
2576 		else if( !pTmp->HasMark() ) 	// sorge auf jedenfall dafuer, das
2577 		{						// nicht benutzte Indizies beachtet werden!
2578 			pTmp->SetMark();			// SPoint liegt nicht im Bereich,
2579 			pTmp->DeleteMark(); 		// aber vielleicht GetMark, also setzen
2580 		}
2581 		if( bGoNext )
2582 			pTmp = (SwPaM*)pTmp->GetNext();
2583 	} while( !bGoNext || *ppDelRing != pTmp );
2584 }
2585 
2586 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2587 {
2588 	SwNode *pNode = &rIdx.GetNode();
2589 
2590 	// erzeuge einen neuen Pam
2591 	SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2592 	if( pNode->GetStartNode() )
2593 	{
2594 		if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2595 		{
2596 			// der angegebene Node steht in einer Tabelle, also Parke
2597 			// den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
2598 			pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2599 		}
2600 		else	// also auf dem StartNode selbst.
2601 				// Dann immer ueber seinen EndNode den StartNode erfragen !!!
2602 				// (StartOfSection vom StartNode ist der Parent !)
2603 			pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2604 	}
2605 	else
2606 		pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2607 	pNew->SetMark();
2608 	pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2609 
2610 	//Alle Shells wollen etwas davon haben.
2611 	ViewShell *pTmp = this;
2612 	do {
2613 		if( pTmp->IsA( TYPE( SwCrsrShell )))
2614 		{
2615 			SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2616 			if( pSh->pCrsrStk )
2617 				pSh->_ParkPams( pNew, &pSh->pCrsrStk );
2618 
2619 			pSh->_ParkPams( pNew, &pSh->pCurCrsr );
2620 			if( pSh->pTblCrsr )
2621 			{
2622 				// setze den Tabellen Cursor immer auf 0, den aktuellen
2623 				// immer auf den Anfang der Tabelle
2624 				SwPaM* pTCrsr = pSh->GetTblCrs();
2625 				SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2626 				if ( pTblNd )
2627 				{
2628 					pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
2629 					pTCrsr->GetPoint()->nNode = 0;
2630 					pTCrsr->SetMark();
2631 					pTCrsr->DeleteMark();
2632 					pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
2633 				}
2634 			}
2635 		}
2636 	} while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
2637 	delete pNew;
2638 }
2639 
2640 //=========================================================================
2641 
2642 /*
2643  * der Copy-Constructor
2644  * Cursor-Position kopieren, in den Ring eingetragen.
2645  * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
2646  */
2647 
2648 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
2649 	: ViewShell( rShell, pInitWin ),
2650 	SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2651 	pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2652     eMvState( MV_NONE ),
2653     // --> OD 2008-04-02 #refactorlists#
2654     sMarkedListId(),
2655     nMarkedListLevel( 0 )
2656     // <--
2657 {
2658 	SET_CURR_SHELL( this );
2659 	// Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
2660 	pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
2661 	pCurCrsr->GetCntntNode()->Add( this );
2662 
2663 	bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2664 	bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2665 	bOverwriteCrsr = sal_False;
2666 	bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2667 	bSetCrsrInReadOnly = sal_True;
2668 	pVisCrsr = new SwVisCrsr( this );
2669 //	UpdateCrsr( 0 );
2670     // OD 11.02.2003 #100556#
2671     mbMacroExecAllowed = rShell.IsMacroExecAllowed();
2672 	oldColFrm = NULL;
2673 }
2674 
2675 
2676 /*
2677  * der normale Constructor
2678  */
2679 
2680 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
2681 							const SwViewOption *pInitOpt )
2682 	: ViewShell( rDoc, pInitWin, pInitOpt ),
2683 	SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2684 	pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2685     eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
2686     // --> OD 2008-04-02 #refactorlists#
2687     sMarkedListId(),
2688     nMarkedListLevel( 0 )
2689     // <--
2690 {
2691 	SET_CURR_SHELL( this );
2692 	/*
2693 	 * Erzeugen des initialen Cursors, wird auf die erste
2694 	 * Inhaltsposition gesetzt
2695 	 */
2696 	SwNodes& rNds = rDoc.GetNodes();
2697 
2698 	SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2699 	SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
2700 
2701 	pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2702 
2703 	// melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
2704 	// Attribut-Aenderungen ueber den Link weiter gemeldet werden.
2705 	pCNd->Add( this );
2706 
2707 	bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2708 	bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2709 	bOverwriteCrsr = sal_False;
2710 	bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2711 	bSetCrsrInReadOnly = sal_True;
2712 
2713 	pVisCrsr = new SwVisCrsr( this );
2714 //	UpdateCrsr( 0 );
2715     // OD 11.02.2003 #100556#
2716     mbMacroExecAllowed = true;
2717 }
2718 
2719 
2720 
2721 SwCrsrShell::~SwCrsrShell()
2722 {
2723 	// wenn es nicht die letzte View so sollte zu mindest das
2724 	// Feld noch geupdatet werden.
2725 	if( GetNext() != this )
2726 		CheckTblBoxCntnt( pCurCrsr->GetPoint() );
2727 	else
2728 		ClearTblBoxCntnt();
2729 
2730 	delete pVisCrsr;
2731     delete pBlockCrsr;
2732 	delete pTblCrsr;
2733 
2734 	/*
2735 	 * Freigabe der Cursor
2736 	 */
2737 	while(pCurCrsr->GetNext() != pCurCrsr)
2738 		delete pCurCrsr->GetNext();
2739 	delete pCurCrsr;
2740 
2741 	// Stack freigeben
2742 	if( pCrsrStk )
2743 	{
2744 		while( pCrsrStk->GetNext() != pCrsrStk )
2745 			delete pCrsrStk->GetNext();
2746 		delete pCrsrStk;
2747 	}
2748 
2749 	// JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
2750 	// 				der CursorShell haengt keine Chance geben, sich an den
2751 	//				TextNode zu haengen.
2752 	if( GetRegisteredIn() )
2753 		GetRegisteredInNonConst()->Remove( this );
2754 }
2755 
2756 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2757 {
2758     if( pTblCrsr )
2759         return pTblCrsr;
2760     if( pBlockCrsr && bBlock )
2761         return &pBlockCrsr->getShellCrsr();
2762     return pCurCrsr;
2763 }
2764 
2765 //Sollte fuer das Clipboard der WaitPtr geschaltet werden?
2766 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
2767 
2768 sal_Bool SwCrsrShell::ShouldWait() const
2769 {
2770 	if ( IsTableMode() || GetCrsrCnt() > 1 )
2771 		return sal_True;
2772 
2773 	if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2774 		return sal_True;
2775 
2776 	SwPaM* pPam = GetCrsr();
2777 	return pPam->Start()->nNode.GetIndex() + 10 <
2778 			pPam->End()->nNode.GetIndex();
2779 }
2780 
2781 
2782 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
2783 {
2784 	if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
2785 		 GetLayout()->MakeTblCrsrs( *pTblCrsr );
2786 	return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
2787 }
2788 
2789 // zeige das akt. selektierte "Object" an
2790 void SwCrsrShell::MakeSelVisible()
2791 {
2792 	ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
2793 	if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
2794 	{
2795 		SwRect aTmp( aCharRect );
2796 		long nDiff = aCharRect.Height() - VisArea().Height();
2797 		if( nDiff < aCrsrHeight.X() )
2798 			aTmp.Top( nDiff + aCharRect.Top() );
2799 		else
2800 		{
2801 			aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
2802 			aTmp.Height( aCrsrHeight.Y() );
2803 		}
2804         if( !aTmp.HasArea() )
2805         {
2806             aTmp.SSize().Height() += 1;
2807             aTmp.SSize().Width() += 1;
2808         }
2809 		MakeVisible( aTmp );
2810 	}
2811 	else
2812 	{
2813 		if( aCharRect.HasArea() )
2814 			MakeVisible( aCharRect );
2815 		else
2816 		{
2817 			SwRect aTmp( aCharRect );
2818 			aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2819 			MakeVisible( aTmp );
2820 		}
2821 	}
2822 }
2823 
2824 
2825 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
2826 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
2827 {
2828 	if( pTblCrsr )		// was soll ich jetzt machen ??
2829 	{
2830 		ASSERT( !this, "TabellenSelection nicht aufgehoben!" );
2831 		return sal_False;
2832 	}
2833 
2834 	//JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
2835 	if( !bAllProtect && GetDoc()->GetDocShell() &&
2836 		GetDoc()->GetDocShell()->IsReadOnlyUI() )
2837 		return sal_True;
2838 
2839 	// dann raus da!
2840 	if( pCurCrsr->HasMark()	)
2841 		ClearMark();
2842 
2843 	// als erstes mal auf Rahmen abpruefen
2844 	SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
2845 	sal_uLong nNdIdx = rNdIdx.GetIndex();		// sichern
2846 	SwNodes& rNds = pDoc->GetNodes();
2847 	SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2848 	const SwCntntFrm * pFrm;
2849 
2850 	if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
2851 		!IsReadOnlyAvailable() && pFrm->IsProtected() &&
2852 		nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2853 	{
2854 		// geschuetzter Rahmen ueberspringen
2855 		SwPaM aPam( *pCurCrsr->GetPoint() );
2856 		aPam.SetMark();
2857 		aPam.GetMark()->nNode = rNds.GetEndOfContent();
2858 		aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2859 
2860 		sal_Bool bFirst = sal_False;
2861 		if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
2862 		{
2863 			aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2864 			pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
2865 		}
2866 
2867 		if( !pCNd )		// sollte nie passieren !!!
2868 		{
2869 			rNdIdx = nNdIdx;		// alten Node zurueck
2870 			return sal_False;
2871 		}
2872 		*pCurCrsr->GetPoint() = *aPam.GetPoint();
2873 	}
2874 	else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2875 	{
2876 		// dann auf den Anfang vom Doc stellen
2877 		rNdIdx = pDoc->GetNodes().GetEndOfExtras();
2878 		pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
2879 															&rNdIdx ), 0 );
2880 		nNdIdx = rNdIdx.GetIndex();
2881 	}
2882 
2883 	sal_Bool bOk = sal_True;
2884 
2885     // #i9059# cursor may not stand in protected cells
2886     //         (unless cursor in protected areas is OK.)
2887     const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2888     if( !IsReadOnlyAvailable()  &&
2889         pTableNode != NULL  &&  rNdIdx.GetNode().IsProtect() )
2890     {
2891         // we're in a table, and we're in a protected area, so we're
2892         // probably in a protected cell.
2893 
2894         // move forward into non-protected area.
2895         SwPaM aPam( rNdIdx.GetNode(), 0 );
2896         while( aPam.GetNode()->IsProtect() &&
2897                aPam.Move( fnMoveForward, fnGoCntnt ) )
2898             ; // nothing to do in the loop; the aPam.Move does the moving!
2899 
2900         // didn't work? then go backwards!
2901         if( aPam.GetNode()->IsProtect() )
2902         {
2903             SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2904 			aPam = aTmpPaM;
2905             while( aPam.GetNode()->IsProtect() &&
2906                    aPam.Move( fnMoveBackward, fnGoCntnt ) )
2907                 ; // nothing to do in the loop; the aPam.Move does the moving!
2908         }
2909 
2910         // if we're successful, set the new position
2911         if( ! aPam.GetNode()->IsProtect() )
2912         {
2913             *pCurCrsr->GetPoint() = *aPam.GetPoint();
2914         }
2915     }
2916 
2917 	// in einem geschuetzten Bereich
2918 	const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2919 	if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2920 		( !IsReadOnlyAvailable() &&
2921 		   pSectNd->GetSection().IsProtectFlag() )) )
2922 	{
2923 		typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
2924         FNGoSection funcGoSection = &SwNodes::GoNextSection;
2925 
2926 		bOk = sal_False;
2927 
2928 		for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2929 		{
2930 			sal_Bool bWeiter;
2931 			do {
2932 				bWeiter = sal_False;
2933                 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2934 											sal_True, !IsReadOnlyAvailable() )) )
2935 				{
2936 					// in eine Tabelle verschoben -> pruefe ob die
2937 					// vielleicht geschuetzt ist
2938 					if( pCNd->FindTableNode() )
2939 					{
2940 						SwCallLink aTmp( *this );
2941 						SwCrsrSaveState aSaveState( *pCurCrsr );
2942 						aTmp.nNdTyp = 0;		// im DTOR nichts machen!
2943 						if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
2944 						{
2945 							const SwSectionNode* pSNd = pCNd->FindSectionNode();
2946 							if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2947 								|| (!IsReadOnlyAvailable()  &&
2948 									pSNd->GetSection().IsProtectFlag() ))
2949 							{
2950 								bOk = sal_True;
2951 								break;		// eine nicht geschuetzte Zelle gef.
2952 							}
2953 							continue;		// dann weiter suchen
2954 						}
2955 					}
2956 					else
2957 					{
2958 						bOk = sal_True;
2959 						break;		// eine nicht geschuetzte Zelle gef.
2960 					}
2961 				}
2962 
2963 				if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2964 				{
2965 					// Teste mal auf Fly - kann auch noch geschuetzt sein!!
2966 					if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
2967 						( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2968 						( bOnlyText && pCNd->IsNoTxtNode() ) )
2969 					{
2970 						// dann weiter suchen!
2971 						bOk = sal_False;
2972 						bWeiter = sal_True;
2973 					}
2974 				}
2975 			} while( bWeiter );
2976 
2977 			if( !bOk )
2978 			{
2979 				if( !nLoopCnt )
2980                     funcGoSection = &SwNodes::GoPrevSection;
2981 				rNdIdx = nNdIdx;
2982 			}
2983 		}
2984 	}
2985 	if( bOk )
2986 	{
2987 		pCNd = rNdIdx.GetNode().GetCntntNode();
2988 //		sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
2989 		xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2990 		pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2991 	}
2992 	else
2993 	{
2994 		pCNd = rNdIdx.GetNode().GetCntntNode();
2995 
2996 		// falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
2997 		// verschieben!!
2998 		if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
2999 		{
3000 			SwCrsrMoveState aTmpState( MV_NONE );
3001 			aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3002 			GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
3003 										&aTmpState );
3004 		}
3005 	}
3006 	return bOk;
3007 }
3008 
3009 
3010 sal_Bool SwCrsrShell::IsCrsrReadonly() const
3011 {
3012     if ( GetViewOptions()->IsReadonly() ||
3013          GetViewOptions()->IsFormView() ) // Formular view
3014     {
3015         SwFrm *pFrm = GetCurrFrm( sal_False );
3016         const SwFlyFrm* pFly;
3017         const SwSection* pSection;
3018 
3019         if( pFrm && pFrm->IsInFly() &&
3020             (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
3021             pFly->Lower() &&
3022             !pFly->Lower()->IsNoTxtFrm() &&
3023             !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
3024         {
3025             return sal_False;
3026         }
3027         // edit in readonly sections
3028         else if ( pFrm && pFrm->IsInSct() &&
3029             0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
3030             pSection->IsEditInReadonlyFlag() )
3031         {
3032             return sal_False;
3033         }
3034         else if ( !IsMultiSelection() && CrsrInsideInputFld() )
3035         {
3036             return sal_False;
3037         }
3038 
3039         return sal_True;
3040     }
3041     return sal_False;
3042 }
3043 
3044 
3045 // darf der Cursor in ReadOnlyBereiche?
3046 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
3047 {
3048 	// im GlobalDoc darf NIE umgeschaltet werden
3049 	if( (!GetDoc()->GetDocShell() ||
3050 		 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
3051 		bFlag != bSetCrsrInReadOnly )
3052 	{
3053 		// wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
3054 		// Selektionen aufgehoben werden. Denn sonst wird sich darauf
3055 		// verlassen, das nichts geschuetztes selektiert ist!
3056 		if( !bFlag )
3057 		{
3058 			ClearMark();
3059 		}
3060 		bSetCrsrInReadOnly = bFlag;
3061 		UpdateCrsr();
3062 	}
3063 }
3064 
3065 sal_Bool SwCrsrShell::HasReadonlySel() const
3066 {
3067     sal_Bool bRet = sal_False;
3068     if ( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
3069     {
3070         if ( pTblCrsr != NULL )
3071         {
3072             bRet = pTblCrsr->HasReadOnlyBoxSel()
3073                    || pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() );
3074         }
3075         else
3076         {
3077             const SwPaM* pCrsr = pCurCrsr;
3078 
3079             do
3080             {
3081                 if ( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ) )
3082                 {
3083                     bRet = sal_True;
3084                 }
3085 
3086                 pCrsr = (SwPaM*)pCrsr->GetNext();
3087             } while ( !bRet && pCrsr != pCurCrsr );
3088         }
3089     }
3090     return bRet;
3091 }
3092 
3093 sal_Bool SwCrsrShell::IsSelFullPara() const
3094 {
3095 	sal_Bool bRet = sal_False;
3096 
3097 	if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
3098 		pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
3099 	{
3100 		xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
3101 				   nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
3102 		if( nStt > nEnd )
3103 		{
3104 			xub_StrLen nTmp = nStt;
3105 			nStt = nEnd;
3106 			nEnd = nTmp;
3107 		}
3108 		const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
3109 		bRet = pCNd && !nStt && nEnd == pCNd->Len();
3110 	}
3111 	return bRet;
3112 }
3113 
3114 short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3115 {
3116 	SwPosition aPos( *pCurCrsr->GetPoint() );
3117 	Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
3118 	if( pPt )
3119 	{
3120 		SwCrsrMoveState aTmpState( MV_NONE );
3121 		aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3122 
3123 		GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3124 	}
3125 
3126     return pDoc->GetTextDirection( aPos, &aPt );
3127 }
3128 
3129 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3130 {
3131     const short nDir = GetTextDirection( pPt );
3132     return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3133 }
3134 
3135 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3136 {
3137     const short nDir = GetTextDirection( pPt );
3138     // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3139     // vertical environment
3140     return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3141 }
3142 
3143 //
3144 // If the current cursor position is inside a hidden range, the hidden range
3145 // is selected:
3146 //
3147 bool SwCrsrShell::SelectHiddenRange()
3148 {
3149     bool bRet = false;
3150     if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
3151     {
3152         SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
3153         const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3154         if ( pNode )
3155         {
3156             const xub_StrLen nPos = rPt.nContent.GetIndex();
3157 
3158             // check if nPos is in hidden range
3159             xub_StrLen nHiddenStart;
3160             xub_StrLen nHiddenEnd;
3161             SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3162             if ( STRING_LEN != nHiddenStart )
3163             {
3164                 // make selection:
3165                 pCurCrsr->SetMark();
3166                 pCurCrsr->GetMark()->nContent = nHiddenEnd;
3167                 bRet = true;
3168             }
3169         }
3170     }
3171 
3172     return bRet;
3173 }
3174 
3175 /*  */
3176 
3177 	// die Suchfunktionen
3178 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
3179 							SwDocPositions eStart, SwDocPositions eEnde,
3180                             sal_Bool& bCancel,
3181 							FindRanges eRng, int bReplace )
3182 {
3183 	if( pTblCrsr )
3184 		GetCrsr();
3185 	delete pTblCrsr, pTblCrsr = 0;
3186     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3187     sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
3188     if( nRet || bCancel )
3189         UpdateCrsr();
3190     return nRet;
3191 }
3192 
3193 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3194 							SwDocPositions eStart, SwDocPositions eEnde,
3195 			                sal_Bool& bCancel,
3196 							FindRanges eRng, const SwTxtFmtColl* pReplFmt )
3197 {
3198 	if( pTblCrsr )
3199 		GetCrsr();
3200 	delete pTblCrsr, pTblCrsr = 0;
3201 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3202 	sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
3203 	if( nRet )
3204 		UpdateCrsr();
3205 	return nRet;
3206 }
3207 
3208 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
3209 							SwDocPositions eStart, SwDocPositions eEnde,
3210 							sal_Bool& bCancel,
3211 							FindRanges eRng, const SearchOptions* pSearchOpt,
3212 							const SfxItemSet* rReplSet )
3213 {
3214 	if( pTblCrsr )
3215 		GetCrsr();
3216 	delete pTblCrsr, pTblCrsr = 0;
3217 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3218 	sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
3219 								eRng, pSearchOpt, rReplSet );
3220 	if( nRet )
3221 		UpdateCrsr();
3222 	return nRet;
3223 }
3224 
3225 void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3226 {
3227 	StartAction();
3228 	SwPaM* pCrsr = GetCrsr();
3229 	*pCrsr->GetPoint() = *rCrsr.GetPoint();
3230 	if(rCrsr.HasMark())
3231 	{
3232 		pCrsr->SetMark();
3233 		*pCrsr->GetMark() = *rCrsr.GetMark();
3234 	}
3235 	if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3236 	{
3237 		const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3238 		do
3239 		{
3240             SwPaM* pCurrentCrsr = CreateCrsr();
3241             *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3242 			if(_pStartCrsr->HasMark())
3243 			{
3244                 pCurrentCrsr->SetMark();
3245                 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3246 			}
3247 		} while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3248 	}
3249 	EndAction();
3250 }
3251 
3252 void lcl_RemoveMark( SwPaM* pPam )
3253 {
3254     ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
3255     pPam->GetMark()->nContent.Assign( 0, 0 );
3256     pPam->GetMark()->nNode = 0;
3257     pPam->DeleteMark();
3258 }
3259 
3260 const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3261 {
3262     const SwStartNode *pRet = rNode.StartOfSectionNode();
3263     while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3264         pRet->GetStartNodeType() == SwTableBoxStartNode )
3265     {
3266         pRet = pRet->StartOfSectionNode();
3267     }
3268     return pRet;
3269 }
3270 
3271 /**
3272    Checks if a position is valid. To be valid the position's node must
3273    be a content node and the content must not be unregistered.
3274 
3275    @param aPos the position to check.
3276 */
3277 bool lcl_PosOk(const SwPosition & aPos)
3278 {
3279     return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3280            SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
3281 }
3282 
3283 /**
3284    Checks if a PaM is valid. For a PaM to be valid its point must be
3285    valid. Additionally if the PaM has a mark this has to be valid, too.
3286 
3287    @param aPam the PaM to check
3288 */
3289 static bool lcl_CrsrOk(SwPaM & aPam)
3290 {
3291     return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3292         || lcl_PosOk(*aPam.GetMark()));
3293 }
3294 
3295 void SwCrsrShell::ClearUpCrsrs()
3296 {
3297     // start of the ring
3298     SwPaM * pStartCrsr = GetCrsr();
3299     // start loop with second entry of the ring
3300     SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3301     SwPaM * pTmpCrsr;
3302     bool bChanged = false;
3303 
3304     /*
3305        For all entries in the ring except the start entry delete the
3306        entry if it is invalid.
3307     */
3308     while (pCrsr != pStartCrsr)
3309     {
3310         pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3311 
3312         if ( ! lcl_CrsrOk(*pCrsr))
3313         {
3314             delete pCrsr;
3315 
3316             bChanged = true;
3317         }
3318 
3319         pCrsr = pTmpCrsr;
3320     }
3321 
3322     if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
3323     {
3324         lcl_RemoveMark( pStartCrsr );
3325         bChanged = true;
3326     }
3327     if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
3328     {
3329         SwNodes & aNodes = GetDoc()->GetNodes();
3330         const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3331         SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3332         SwNode * pNode = aNodes.GoPrevious(&aIdx);
3333         if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3334             aNodes.GoNext( &aIdx );
3335         if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3336         {
3337             /*
3338               If the start entry of the ring is invalid replace it with a
3339               cursor pointing to the beginning of the first content node in
3340               the document.
3341             */
3342             aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3343             pNode = aNodes.GoNext( &aIdx );
3344         }
3345         bool bFound = (pNode != NULL);
3346 
3347         ASSERT(bFound, "no content node found");
3348 
3349         if (bFound)
3350         {
3351             SwPaM aTmpPam(*pNode);
3352             *pStartCrsr = aTmpPam;
3353         }
3354 
3355         bChanged = true;
3356     }
3357 
3358     /*
3359       If at least one of the cursors in the ring have been deleted or
3360       replaced, remove the table cursor.
3361     */
3362     if (pTblCrsr != NULL && bChanged)
3363         TblCrsrToCursor();
3364 }
3365 
3366 // #111827#
3367 String SwCrsrShell::GetCrsrDescr() const
3368 {
3369     String aResult;
3370 
3371     if (IsMultiSelection())
3372         aResult += String(SW_RES(STR_MULTISEL));
3373     else
3374         aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3375 
3376     return aResult;
3377 }
3378 
3379 // SMARTTAGS
3380 
3381 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3382                              uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3383                              const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
3384 {
3385     // Insert smart tag information
3386     std::vector< rtl::OUString > aSmartTagTypes;
3387     std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3388 
3389     for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
3390     {
3391         const xub_StrLen nSTPos = rSmartTagList.Pos( i );
3392         const xub_StrLen nSTLen = rSmartTagList.Len( i );
3393 
3394         if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3395         {
3396             const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3397             if ( pArea )
3398             {
3399                 aSmartTagTypes.push_back( pArea->maType );
3400                 aStringKeyMaps.push_back( pArea->mxPropertyBag );
3401             }
3402         }
3403     }
3404 
3405     if ( aSmartTagTypes.size() )
3406     {
3407         rSmartTagTypes.realloc( aSmartTagTypes.size() );
3408         rStringKeyMaps.realloc( aSmartTagTypes.size() );
3409 
3410         std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3411         sal_uInt16 i = 0;
3412         for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3413             rSmartTagTypes[i++] = *aTypesIter;
3414 
3415         std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3416         i = 0;
3417         for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3418             rStringKeyMaps[i++] = *aMapsIter;
3419     }
3420 }
3421 
3422 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3423                    SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
3424 {
3425     // create SwPosition for nStartIndex
3426     SwIndex aIndex( &rNode, nBegin );
3427     SwPosition aStartPos( rNode, aIndex );
3428 
3429     // create SwPosition for nEndIndex
3430     SwPosition aEndPos( aStartPos );
3431     aEndPos.nContent = nBegin + nLen;
3432 
3433     const uno::Reference<text::XTextRange> xRange =
3434         SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
3435 
3436     rRange = xRange;
3437 }
3438 
3439 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3440                                    uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3441                                    uno::Reference< text::XTextRange>& rRange ) const
3442 {
3443     if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3444         return;
3445 
3446     SwPaM* pCrsr = GetCrsr();
3447     SwPosition aPos( *pCrsr->GetPoint() );
3448     SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3449     if ( pNode && !pNode->IsInProtectSect() )
3450     {
3451         const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3452         if ( pSmartTagList )
3453         {
3454             xub_StrLen nCurrent = aPos.nContent.GetIndex();
3455             xub_StrLen nBegin = nCurrent;
3456             xub_StrLen nLen = 1;
3457 
3458             if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3459             {
3460                 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3461                 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3462                 if ( pSubList )
3463                 {
3464                     pSmartTagList = pSubList;
3465                     nCurrent = 0;
3466                 }
3467 
3468                 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3469                 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3470             }
3471         }
3472     }
3473 }
3474 
3475 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
3476 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3477                                    uno::Sequence< rtl::OUString >& rSmartTagTypes,
3478                                    uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3479                                    uno::Reference<text::XTextRange>& rRange )
3480 {
3481     if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3482         return;
3483 
3484     SwPaM* pCrsr = GetCrsr();
3485     SwPosition aPos( *pCrsr->GetPoint() );
3486     Point aPt( rPt );
3487     SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3488     SwSpecialPos aSpecialPos;
3489     eTmpState.pSpecialPos = &aSpecialPos;
3490     SwTxtNode *pNode;
3491     const SwWrongList *pSmartTagList;
3492 
3493     if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3494         0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3495         0 != (pSmartTagList = pNode->GetSmartTags()) &&
3496         !pNode->IsInProtectSect() )
3497     {
3498         xub_StrLen nCurrent = aPos.nContent.GetIndex();
3499         xub_StrLen nBegin = nCurrent;
3500         xub_StrLen nLen = 1;
3501 
3502         if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3503         {
3504             const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3505             const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3506             if ( pSubList )
3507             {
3508                 pSmartTagList = pSubList;
3509                 nCurrent = eTmpState.pSpecialPos->nCharOfst;
3510             }
3511 
3512             lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3513             lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3514 
3515             // get smarttag word
3516             String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
3517 
3518             //save the start and end positons of the line and the starting point
3519             Push();
3520             LeftMargin();
3521             xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3522             RightMargin();
3523             xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3524             Pop(sal_False);
3525 
3526             // make sure the selection build later from the
3527             // data below does not include footnotes and other
3528             // "in word" character to the left and right in order
3529             // to preserve those. Therefore count those "in words"
3530             // in order to modify the selection accordingly.
3531             const sal_Unicode* pChar = aText.GetBuffer();
3532             xub_StrLen nLeft = 0;
3533             while (pChar && *pChar++ == CH_TXTATR_INWORD)
3534                 ++nLeft;
3535             pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
3536             xub_StrLen nRight = 0;
3537             while (pChar && *pChar-- == CH_TXTATR_INWORD)
3538                 ++nRight;
3539 
3540             aPos.nContent = nBegin + nLeft;
3541             pCrsr = GetCrsr();
3542             *pCrsr->GetPoint() = aPos;
3543             pCrsr->SetMark();
3544             ExtendSelection( sal_True, nLen - nLeft - nRight );
3545             //no determine the rectangle in the current line
3546             xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3547             //take one less than the line end - otherwise the next line would be calculated
3548             xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
3549             Push();
3550             pCrsr->DeleteMark();
3551             SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3552             rContent = nWordStart;
3553             SwRect aStartRect;
3554             SwCrsrMoveState aState;
3555             aState.bRealWidth = sal_True;
3556             SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3557             SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
3558 
3559             pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3560             rContent = nWordEnd;
3561             SwRect aEndRect;
3562             pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3563             rSelectRect = aStartRect.Union( aEndRect );
3564             Pop(sal_False);
3565         }
3566     }
3567 }
3568 
3569