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