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