merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / crsr / crsrsh.cxx
blob5c6fc9a21cebb06fc2738a6889624da09ad36841
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: crsrsh.cxx,v $
10 * $Revision: 1.76 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <com/sun/star/util/SearchOptions.hpp>
34 #include <com/sun/star/text/XTextRange.hpp>
35 #include <hintids.hxx>
36 #include <svx/svdmodel.hxx>
37 #include <svx/frmdiritem.hxx>
39 #include <SwSmartTagMgr.hxx>
40 #include <doc.hxx>
41 #include <rootfrm.hxx>
42 #include <pagefrm.hxx>
43 #include <cntfrm.hxx>
44 #include <viewimp.hxx>
45 #include <pam.hxx>
46 #include <swselectionlist.hxx>
47 #include <IBlockCursor.hxx>
48 #include "BlockCursor.hxx"
49 #include <ndtxt.hxx>
50 #include <flyfrm.hxx>
51 #include <dview.hxx>
52 #include <viewopt.hxx>
53 #include <frmtool.hxx>
54 #include <crsrsh.hxx>
55 #include <tabfrm.hxx>
56 #include <txtfrm.hxx>
57 #include <sectfrm.hxx>
58 #include <swtable.hxx>
59 #include <callnk.hxx>
60 #include <viscrs.hxx>
61 #include <section.hxx>
62 #include <docsh.hxx>
63 #include <scriptinfo.hxx>
64 #include <globdoc.hxx>
65 #include <pamtyp.hxx>
66 #include <mdiexp.hxx> // ...Percent()
67 #include <fmteiro.hxx>
68 #include <wrong.hxx> // SMARTTAGS
69 #include <unoobj.hxx> // SMARTTAGS
70 #include <vcl/svapp.hxx>
71 #include <numrule.hxx>
72 #include <IGrammarContact.hxx>
74 #include <globals.hrc>
76 #include <comcore.hrc>
78 using namespace com::sun::star;
79 using namespace util;
81 TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
84 // Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
85 void CheckRange( SwCursor* );
87 //-----------------------------------------------------------------------
90 * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
91 * Wenn ja, dann hebe den alten Bereich auf.
95 void CheckRange( SwCursor* pCurCrsr )
97 const SwPosition *pStt = pCurCrsr->Start(),
98 *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
100 SwPaM *pTmpDel = 0,
101 *pTmp = (SwPaM*)pCurCrsr->GetNext();
103 // durchsuche den gesamten Ring
104 while( pTmp != pCurCrsr )
106 const SwPosition *pTmpStt = pTmp->Start(),
107 *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
108 pTmp->GetMark() : pTmp->GetPoint();
109 if( *pStt <= *pTmpStt )
111 if( *pEnd > *pTmpStt ||
112 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
113 pTmpDel = pTmp;
115 else
116 if( *pStt < *pTmpEnd )
117 pTmpDel = pTmp;
119 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
120 * muss der alte Bereich aufgehoben werden.
121 * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
122 * Bereich gehoert !
124 pTmp = (SwPaM*)pTmp->GetNext();
125 if( pTmpDel )
127 delete pTmpDel; // hebe alten Bereich auf
128 pTmpDel = 0;
133 // -------------- Methoden von der SwCrsrShell -------------
135 SwPaM * SwCrsrShell::CreateCrsr()
137 // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
138 ASSERT( !IsTableMode(), "in Tabellen SSelection" );
140 // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
141 // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
142 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
144 // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
145 // vom kopierten Pam aufgehoben wird !!
147 // #i75172# to be able to make a complete content swap, i moved this to a method
148 // pNew->Insert( pCurCrsr, 0 );
149 // pCurCrsr->Remove( 0, pCurCrsr->Count() );
150 pNew->swapContent(*pCurCrsr);
152 pCurCrsr->DeleteMark();
154 UpdateCrsr( SwCrsrShell::SCROLLWIN );
155 // return pCurCrsr;
156 return pNew;
159 // loesche den aktuellen Cursor und der folgende wird zum Aktuellen
162 BOOL SwCrsrShell::DestroyCrsr()
164 // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
165 ASSERT( !IsTableMode(), "in Tabellen SSelection" );
167 // ist ueberhaupt ein naechtser vorhanden ?
168 if(pCurCrsr->GetNext() == pCurCrsr)
169 return FALSE;
171 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
172 SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
173 delete pCurCrsr;
174 pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
175 UpdateCrsr();
176 return TRUE;
180 // gebe den aktuellen zurueck
182 SwPaM* SwCrsrShell::GetCrsr( BOOL bMakeTblCrsr ) const
184 if( pTblCrsr )
186 if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
188 // geparkte Cursor werden nicht wieder erzeugt
189 const SwCntntNode* pCNd;
190 if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
191 pTblCrsr->GetMark()->nNode.GetIndex() &&
192 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->GetFrm() &&
193 0 != ( pCNd = pTblCrsr->GetCntntNode(FALSE) ) && pCNd->GetFrm())
195 SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
196 GetLayout()->MakeTblCrsrs( *pTC );
200 if( pTblCrsr->IsChgd() )
202 const_cast<SwCrsrShell*>(this)->pCurCrsr =
203 dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
206 return pCurCrsr;
210 void SwCrsrShell::StartAction()
212 if( !ActionPend() )
214 // fuer das Update des Ribbon-Bars merken
215 const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
216 nAktNode = rNd.GetIndex();
217 nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
218 nAktNdTyp = rNd.GetNodeType();
219 bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
220 if( ND_TEXTNODE & nAktNdTyp )
221 nLeftFrmPos = SwCallLink::GetFrm( (SwTxtNode&)rNd, nAktCntnt, TRUE );
222 else
223 nLeftFrmPos = 0;
225 ViewShell::StartAction(); // zur ViewShell
229 void SwCrsrShell::EndAction( const BOOL bIdleEnd )
232 //OS: Wird z.B. eine Basic-Action im Hintergrund ausgefuehrt, geht es so nicht
233 if( !bHasFocus )
235 // hat die Shell nicht den Focus, dann nur das EndAction an
236 // die ViewShell weitergeben.
237 ViewShell::EndAction( bIdleEnd );
238 return;
242 BOOL bVis = bSVCrsrVis;
244 // Idle-Formatierung ?
245 if( bIdleEnd && Imp()->GetRegion() )
247 pCurCrsr->Hide();
249 #ifdef SHOW_IDLE_REGION
250 if( GetWin() )
252 GetWin()->Push();
253 GetWin()->ChangePen( Pen( Color( COL_YELLOW )));
254 for( USHORT n = 0; n < aPntReg.Count(); ++n )
256 SwRect aIRect( aPntReg[n] );
257 GetWin()->DrawRect( aIRect.SVRect() );
259 GetWin()->Pop();
261 #endif
265 // vor der letzten Action alle invaliden Numerierungen updaten
266 if( 1 == nStartAction )
267 GetDoc()->UpdateNumRule();
269 // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
270 // Only the UpdateCrsr shows the cursor.
271 BOOL bSavSVCrsrVis = bSVCrsrVis;
272 bSVCrsrVis = FALSE;
274 ViewShell::EndAction( bIdleEnd ); //der ViewShell den Vortritt lassen
276 bSVCrsrVis = bSavSVCrsrVis;
278 if( ActionPend() )
280 if( bVis ) // auch SV-Cursor wieder anzeigen
281 pVisCrsr->Show();
283 // falls noch ein ChgCall vorhanden ist und nur noch die Basic
284 // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
285 // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
286 if( !BasicActionPend() )
288 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction
289 // der Cursor geupdatet werden; um z.B. den
290 // TabellenCursor zu erzeugen. Im UpdateCrsr wird
291 // das jetzt beruecksichtigt!
292 UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
295 // Crsr-Moves ueberwachen, evt. Link callen
296 // der DTOR ist das interressante!!
297 SwCallLink aLk( *this, nAktNode, nAktCntnt, (BYTE)nAktNdTyp,
298 nLeftFrmPos, bAktSelection );
301 if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
303 aChgLnk.Call( this );
304 bChgCallFlag = FALSE; // Flag zuruecksetzen
307 return;
310 USHORT nParm = SwCrsrShell::CHKRANGE;
311 if ( !bIdleEnd )
312 nParm |= SwCrsrShell::SCROLLWIN;
313 UpdateCrsr( nParm, bIdleEnd ); // Cursor-Aenderungen anzeigen
316 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
317 aLk.nNode = nAktNode; // evt. Link callen
318 aLk.nNdTyp = (BYTE)nAktNdTyp;
319 aLk.nCntnt = nAktCntnt;
320 aLk.nLeftFrmPos = nLeftFrmPos;
322 if( !nCrsrMove ||
323 ( 1 == nCrsrMove && bInCMvVisportChgd ) )
324 ShowCrsrs( bSVCrsrVis ? TRUE : FALSE ); // Cursor & Selektionen wieder anzeigen
326 // falls noch ein ChgCall vorhanden ist, dann rufe ihn
327 if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
329 aChgLnk.Call( this );
330 bChgCallFlag = FALSE; // Flag zuruecksetzen
335 #if !defined( PRODUCT )
337 void SwCrsrShell::SttCrsrMove()
339 ASSERT( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
340 ++nCrsrMove;
341 StartAction();
344 void SwCrsrShell::EndCrsrMove( const BOOL bIdleEnd )
346 ASSERT( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
347 EndAction( bIdleEnd );
348 if( !--nCrsrMove )
349 bInCMvVisportChgd = FALSE;
352 #endif
355 BOOL SwCrsrShell::LeftRight( BOOL bLeft, USHORT nCnt, USHORT nMode,
356 BOOL bVisualAllowed )
358 if( IsTableMode() )
359 return bLeft ? GoPrevCell() : GoNextCell();
361 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
362 BOOL bRet = FALSE;
364 // #i27615# Handle cursor in front of label.
365 const SwTxtNode* pTxtNd = 0;
367 if( pBlockCrsr )
368 pBlockCrsr->clearPoints();
371 // 1. CASE: Cursor is in front of label. A move to the right
372 // will simply reset the bInFrontOfLabel flag:
374 SwShellCrsr* pShellCrsr = getShellCrsr( true );
375 if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
377 SetInFrontOfLabel( FALSE );
378 bRet = TRUE;
381 // 2. CASE: Cursor is at beginning of numbered paragraph. A move
382 // to the left will simply set the bInFrontOfLabel flag:
384 else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
385 !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
386 0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
387 pTxtNd->HasVisibleNumberingOrBullet() )
389 SetInFrontOfLabel( TRUE );
390 bRet = TRUE;
393 // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
395 else
397 const BOOL bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
398 bRet = SetInFrontOfLabel( FALSE );
399 bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
400 bSkipHidden,
401 !IsOverwriteCrsr() ) || bRet;
404 if( bRet )
406 UpdateCrsr();
408 return bRet;
411 // --> OD 2008-04-02 #refactorlists#
412 void SwCrsrShell::MarkListLevel( const String& sListId,
413 const int nListLevel )
415 if ( sListId != sMarkedListId ||
416 nListLevel != nMarkedListLevel)
418 if ( sMarkedListId.Len() > 0 )
419 pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, FALSE );
421 if ( sListId.Len() > 0 )
423 pDoc->MarkListLevel( sListId, nListLevel, TRUE );
426 sMarkedListId = sListId;
427 nMarkedListLevel = nListLevel;
431 void SwCrsrShell::UpdateMarkedListLevel()
433 SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
435 if ( pTxtNd )
437 if ( !pTxtNd->IsNumbered() )
439 pCurCrsr->_SetInFrontOfLabel( FALSE );
440 MarkListLevel( String(), 0 );
442 else if ( pCurCrsr->IsInFrontOfLabel() )
444 if ( pTxtNd->IsInList() )
446 ASSERT( pTxtNd->GetActualListLevel() >= 0 &&
447 pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?")
448 MarkListLevel( pTxtNd->GetListId(),
449 pTxtNd->GetActualListLevel() );
452 else
454 MarkListLevel( String(), 0 );
458 // <--
460 BOOL SwCrsrShell::UpDown( BOOL bUp, USHORT nCnt )
462 SET_CURR_SHELL( this );
463 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
465 BOOL bTableMode = IsTableMode();
466 SwShellCrsr* pTmpCrsr = getShellCrsr( true );
468 BOOL bRet = pTmpCrsr->UpDown( bUp, nCnt );
469 // --> FME 2005-01-10 #i40019# UpDown should always reset the
470 // bInFrontOfLabel flag:
471 bRet = SetInFrontOfLabel(FALSE) || bRet;
472 // <--
474 if( pBlockCrsr )
475 pBlockCrsr->clearPoints();
477 if( bRet )
479 eMvState = MV_UPDOWN; // Status fuers Crsr-Travelling - GetCrsrOfst
480 if( !ActionPend() )
482 CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
483 if( !bTableMode )
484 eUpdtMode = (CrsrFlag) (eUpdtMode
485 | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
486 UpdateCrsr( static_cast<USHORT>(eUpdtMode) );
489 return bRet;
493 BOOL SwCrsrShell::LRMargin( BOOL bLeft, BOOL bAPI)
495 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
496 SET_CURR_SHELL( this );
497 eMvState = MV_LEFTMARGIN; // Status fuers Crsr-Travelling - GetCrsrOfst
499 const BOOL bTableMode = IsTableMode();
500 SwShellCrsr* pTmpCrsr = getShellCrsr( true );
502 if( pBlockCrsr )
503 pBlockCrsr->clearPoints();
505 const BOOL bWasAtLM =
506 ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
508 BOOL bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
510 if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
512 const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
513 if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
514 SetInFrontOfLabel( TRUE );
516 else if ( !bLeft )
518 bRet = SetInFrontOfLabel( FALSE ) || bRet;
521 if( bRet )
523 UpdateCrsr();
525 return bRet;
528 BOOL SwCrsrShell::IsAtLRMargin( BOOL bLeft, BOOL bAPI ) const
530 const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
531 return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
535 BOOL SwCrsrShell::SttEndDoc( BOOL bStt )
537 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
539 SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
540 BOOL bRet = pTmpCrsr->SttEndDoc( bStt );
541 if( bRet )
543 if( bStt )
544 pTmpCrsr->GetPtPos().Y() = 0; // expl. 0 setzen (TabellenHeader)
545 if( pBlockCrsr )
547 pBlockCrsr->clearPoints();
548 RefreshBlockCursor();
551 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
553 return bRet;
556 void SwCrsrShell::ExtendedSelectAll()
558 SwNodes& rNodes = GetDoc()->GetNodes();
559 SwPosition* pPos = pCurCrsr->GetPoint();
560 pPos->nNode = rNodes.GetEndOfPostIts();
561 pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
562 pPos = pCurCrsr->GetMark();
563 pPos->nNode = rNodes.GetEndOfContent();
564 SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
565 pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
568 BOOL SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
570 BOOL bRet = FALSE;
572 // Springe beim Selektieren nie ueber Section-Grenzen !!
573 if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
575 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
576 SET_CURR_SHELL( this );
578 SwCrsrSaveState aSaveState( *pCurCrsr );
579 Point& rPt = pCurCrsr->GetPtPos();
580 SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
581 GetFrm( &rPt, pCurCrsr->GetPoint() );
582 if( pFrm && TRUE == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
583 fnPosPage, pCurCrsr ) ) &&
584 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
585 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
586 UpdateCrsr();
587 else
588 bRet = FALSE;
590 return bRet;
594 BOOL SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
596 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
597 SwCursor* pTmpCrsr = getShellCrsr( true );
598 BOOL bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
599 if( bRet )
600 UpdateCrsr();
601 return bRet;
605 BOOL SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
606 SwPosSection fnPosSect)
608 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
609 SwCursor* pTmpCrsr = getShellCrsr( true );
610 BOOL bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
611 if( bRet )
612 UpdateCrsr();
613 return bRet;
618 // Positionieren des Cursors
621 SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
623 SwFrm* pFrm = 0;
624 SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
625 if( pCNd )
627 pFrm = pCNd->GetFrm( &rPt, 0, FALSE )->GetUpper();
628 while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
629 pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
630 : pFrm->GetUpper();
632 return pFrm;
635 BOOL SwCrsrShell::IsInHeaderFooter( BOOL* pbInHeader ) const
637 Point aPt;
638 SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
639 if( pFrm && pbInHeader )
640 *pbInHeader = pFrm->IsHeaderFrm();
641 return 0 != pFrm;
644 int SwCrsrShell::SetCrsr( const Point &rLPt, BOOL bOnlyText, bool bBlock )
646 SET_CURR_SHELL( this );
648 SwShellCrsr* pCrsr = getShellCrsr( bBlock );
649 SwPosition aPos( *pCrsr->GetPoint() );
650 Point aPt( rLPt );
651 Point & rAktCrsrPt = pCrsr->GetPtPos();
652 SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
653 bOnlyText ? MV_SETONLYTEXT : MV_NONE );
654 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
656 SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
658 if ( pTxtNd && !IsTableMode() &&
659 // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
660 !pCrsr->HasMark() &&
661 // <--
662 pTxtNd->HasVisibleNumberingOrBullet() )
664 aTmpState.bInFrontOfLabel = TRUE; // #i27615#
666 else
668 aTmpState.bInFrontOfLabel = FALSE;
671 int bRet = CRSR_POSOLD |
672 ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
673 ? 0 : CRSR_POSCHG );
675 const bool bOldInFrontOfLabel = IsInFrontOfLabel();
676 const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
678 pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
680 if( MV_RIGHTMARGIN == aTmpState.eState )
681 eMvState = MV_RIGHTMARGIN;
682 // steht neu Pos im Header/Footer ?
683 SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
684 if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
685 pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
686 // gleiche Tabellenzelle und nicht im Header/Footer
687 // -> zurueck
688 return bRet;
690 if( pBlockCrsr && bBlock )
692 pBlockCrsr->setEndPoint( rLPt );
693 if( !pCrsr->HasMark() )
694 pBlockCrsr->setStartPoint( rLPt );
695 else if( !pBlockCrsr->getStartPoint() )
696 pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
698 if( !pCrsr->HasMark() )
700 // steht an der gleichen Position und wenn im Header/Footer,
701 // dann im gleichen
702 if( aPos == *pCrsr->GetPoint() &&
703 bOldInFrontOfLabel == bNewInFrontOfLabel )
705 if( pFrm )
707 if( pFrm->Frm().IsInside( rAktCrsrPt ))
708 return bRet;
710 else if( aPos.nNode.GetNode().IsCntntNode() )
712 // im gleichen Frame gelandet?
713 SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).GetFrm(
714 &aCharRect.Pos(), 0, FALSE );
715 SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).GetFrm(
716 &aPt, 0, FALSE );
717 if( pNew == pOld )
718 return bRet;
722 else
724 // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
725 // dann in verschiedene
726 if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, TRUE )
727 || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
728 return bRet;
730 // steht an der gleichen Position und nicht im Header/Footer
731 if( aPos == *pCrsr->GetPoint() )
732 return bRet;
735 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
736 SwCrsrSaveState aSaveState( *pCrsr );
738 *pCrsr->GetPoint() = aPos;
739 rAktCrsrPt = aPt;
741 // --> FME 2005-01-31 #i41424# Only update the marked number levels if necessary
742 // Force update of marked number levels if necessary.
743 if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
744 pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
745 SetInFrontOfLabel( bNewInFrontOfLabel );
746 // <--
748 if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
750 USHORT nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
751 UpdateCrsr( nFlag );
752 bRet &= ~CRSR_POSOLD;
754 else if( bOnlyText && !pCurCrsr->HasMark() )
756 if( FindValidCntntNode( bOnlyText ) )
758 // Cursor in einen gueltigen Content stellen
759 if( aPos == *pCrsr->GetPoint() )
760 bRet = CRSR_POSOLD;
761 else
763 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
764 bRet &= ~CRSR_POSOLD;
767 else
769 // es gibt keinen gueltigen Inhalt -> Cursor verstecken
770 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
771 eMvState = MV_NONE; // Status fuers Crsr-Travelling
772 bAllProtect = TRUE;
773 if( GetDoc()->GetDocShell() )
775 GetDoc()->GetDocShell()->SetReadOnlyUI( TRUE );
776 CallChgLnk(); // UI bescheid sagen!
781 return bRet;
785 void SwCrsrShell::TblCrsrToCursor()
787 ASSERT( pTblCrsr, "TblCrsrToCursor: Why?" );
788 delete pTblCrsr, pTblCrsr = 0;
791 void SwCrsrShell::BlockCrsrToCrsr()
793 ASSERT( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
794 if( pBlockCrsr && !HasSelection() )
796 SwPaM& rPam = pBlockCrsr->getShellCrsr();
797 pCurCrsr->SetMark();
798 *pCurCrsr->GetPoint() = *rPam.GetPoint();
799 if( rPam.HasMark() )
800 *pCurCrsr->GetMark() = *rPam.GetMark();
801 else
802 pCurCrsr->DeleteMark();
804 delete pBlockCrsr, pBlockCrsr = 0;
807 void SwCrsrShell::CrsrToBlockCrsr()
809 if( !pBlockCrsr )
811 SwPosition aPos( *pCurCrsr->GetPoint() );
812 pBlockCrsr = createBlockCursor( *this, aPos );
813 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
814 rBlock.GetPtPos() = pCurCrsr->GetPtPos();
815 if( pCurCrsr->HasMark() )
817 rBlock.SetMark();
818 *rBlock.GetMark() = *pCurCrsr->GetMark();
819 rBlock.GetMkPos() = pCurCrsr->GetMkPos();
822 pBlockCrsr->clearPoints();
823 RefreshBlockCursor();
826 void SwCrsrShell::ClearMark()
828 // ist ueberhaupt ein GetMark gesetzt ?
829 if( pTblCrsr )
831 while( pCurCrsr->GetNext() != pCurCrsr )
832 delete pCurCrsr->GetNext();
833 pTblCrsr->DeleteMark();
835 if( pCurCrsr->HasMark() )
837 // falls doch nicht alle Indizies richtig verschoben werden
838 // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
839 // Mark aufs Nodes-Array setzen
840 SwPosition& rPos = *pCurCrsr->GetMark();
841 rPos.nNode.Assign( pDoc->GetNodes(), 0 );
842 rPos.nContent.Assign( 0, 0 );
843 pCurCrsr->DeleteMark();
846 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
847 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
848 delete pTblCrsr, pTblCrsr = 0;
849 pCurCrsr->SwSelPaintRects::Show();
851 else
853 if( !pCurCrsr->HasMark() )
854 return;
855 // falls doch nicht alle Indizies richtig verschoben werden
856 // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
857 // Mark aufs Nodes-Array setzen
858 SwPosition& rPos = *pCurCrsr->GetMark();
859 rPos.nNode.Assign( pDoc->GetNodes(), 0 );
860 rPos.nContent.Assign( 0, 0 );
861 pCurCrsr->DeleteMark();
862 if( !nCrsrMove )
863 pCurCrsr->SwSelPaintRects::Show();
868 void SwCrsrShell::NormalizePam(BOOL bPointFirst)
870 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
871 pCurCrsr->Normalize(bPointFirst);
874 void SwCrsrShell::SwapPam()
876 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
877 pCurCrsr->Exchange();
881 // suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
882 // den angebenen SPoint umschliesst
883 // Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
884 // SSelection besteht; des akt. Cursr wird nicht umgesetzt!
885 // Ansonsten wird er auf die gewaehlte SSelection gesetzt.
888 BOOL SwCrsrShell::ChgCurrPam( const Point & rPt,
889 BOOL bTstOnly, BOOL bTstHit )
891 SET_CURR_SHELL( this );
893 // Pruefe ob der SPoint in einer Tabellen-Selektion liegt
894 if( bTstOnly && pTblCrsr )
895 return pTblCrsr->IsInside( rPt );
897 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
898 // Suche die Position rPt im Dokument
899 SwPosition aPtPos( *pCurCrsr->GetPoint() );
900 Point aPt( rPt );
902 SwCrsrMoveState aTmpState( MV_NONE );
903 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
904 if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
905 return FALSE;
907 // suche in allen Selektionen nach dieser Position
908 SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr; // sicher den Pointer auf Cursor
909 do {
910 if( pCmp->HasMark() &&
911 *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
913 if( bTstOnly || pCurCrsr == pCmp ) // ist der aktuelle.
914 return TRUE; // return ohne Update
916 pCurCrsr = pCmp;
917 UpdateCrsr(); // Cursor steht schon richtig
918 return TRUE;
920 } while( pCurCrsr !=
921 ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
922 return FALSE;
926 void SwCrsrShell::KillPams()
928 // keiner zum loeschen vorhanden?
929 if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
930 return;
932 while( pCurCrsr->GetNext() != pCurCrsr )
933 delete pCurCrsr->GetNext();
934 pCurCrsr->SetColumnSelection( false );
936 if( pTblCrsr )
938 // Cursor Ring loeschen
939 pCurCrsr->DeleteMark();
940 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
941 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
942 delete pTblCrsr;
943 pTblCrsr = 0;
945 else if( pBlockCrsr )
947 // delete the ring of cursors
948 pCurCrsr->DeleteMark();
949 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
950 *pCurCrsr->GetPoint() = *rBlock.GetPoint();
951 pCurCrsr->GetPtPos() = rBlock.GetPtPos();
952 rBlock.DeleteMark();
953 pBlockCrsr->clearPoints();
955 UpdateCrsr( SwCrsrShell::SCROLLWIN );
959 int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
961 int nRet = 0;
962 const SwPosition *pFirst = 0, *pSecond = 0;
963 const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
964 if( CurrPtCurrMk != eType && pStk )
966 switch ( eType)
968 case StackPtStackMk:
969 pFirst = pStk->GetPoint();
970 pSecond = pStk->GetMark();
971 break;
972 case StackPtCurrPt:
973 pFirst = pStk->GetPoint();
974 pSecond = pCur->GetPoint();
975 break;
976 case StackPtCurrMk:
977 pFirst = pStk->GetPoint();
978 pSecond = pCur->GetMark();
979 break;
980 case StackMkCurrPt:
981 pFirst = pStk->GetMark();
982 pSecond = pCur->GetPoint();
983 break;
984 case StackMkCurrMk:
985 pFirst = pStk->GetMark();
986 pSecond = pStk->GetMark();
987 break;
988 case CurrPtCurrMk:
989 pFirst = pCur->GetPoint();
990 pSecond = pCur->GetMark();
991 break;
994 if( !pFirst || !pSecond )
995 nRet = INT_MAX;
996 else if( *pFirst < *pSecond )
997 nRet = -1;
998 else if( *pFirst == *pSecond )
999 nRet = 0;
1000 else
1001 nRet = 1;
1002 return nRet;
1006 BOOL SwCrsrShell::IsSttPara() const
1007 { return( pCurCrsr->GetPoint()->nContent == 0 ? TRUE : FALSE ); }
1010 BOOL SwCrsrShell::IsEndPara() const
1011 { return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? TRUE : FALSE ); }
1014 BOOL SwCrsrShell::IsInFrontOfLabel() const
1016 return pCurCrsr->IsInFrontOfLabel();
1019 bool SwCrsrShell::SetInFrontOfLabel( BOOL bNew )
1021 if ( bNew != IsInFrontOfLabel() )
1023 pCurCrsr->_SetInFrontOfLabel( bNew );
1024 UpdateMarkedListLevel();
1025 return true;
1027 return false;
1030 BOOL SwCrsrShell::GotoPage( USHORT nPage )
1032 SET_CURR_SHELL( this );
1033 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1034 SwCrsrSaveState aSaveState( *pCurCrsr );
1035 BOOL bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
1036 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1037 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1038 if( bRet )
1039 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
1040 return bRet;
1044 void SwCrsrShell::GetPageNum( USHORT &rnPhyNum, USHORT &rnVirtNum,
1045 BOOL bAtCrsrPos, const BOOL bCalcFrm )
1047 SET_CURR_SHELL( this );
1048 // Seitennummer: die erste sichtbare Seite oder die am Cursor
1049 const SwCntntFrm* pCFrm;
1050 const SwPageFrm *pPg = 0;
1052 if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
1053 0 == (pPg = pCFrm->FindPageFrm()) )
1055 pPg = Imp()->GetFirstVisPage();
1056 while( pPg && pPg->IsEmptyPage() )
1057 pPg = (const SwPageFrm *)pPg->GetNext();
1059 // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1060 // standard.vor sein.
1061 rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
1062 rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
1066 USHORT SwCrsrShell::GetNextPrevPageNum( BOOL bNext )
1068 SET_CURR_SHELL( this );
1070 // Seitennummer: die erste sichtbare Seite oder die am Cursor
1071 const SwPageFrm *pPg = Imp()->GetFirstVisPage();
1072 if( pPg )
1074 const SwTwips nPageTop = pPg->Frm().Top();
1076 if( bNext )
1078 // go to next view layout row:
1081 pPg = (const SwPageFrm *)pPg->GetNext();
1083 while( pPg && pPg->Frm().Top() == nPageTop );
1085 while( pPg && pPg->IsEmptyPage() )
1086 pPg = (const SwPageFrm *)pPg->GetNext();
1088 else
1090 // go to previous view layout row:
1093 pPg = (const SwPageFrm *)pPg->GetPrev();
1095 while( pPg && pPg->Frm().Top() == nPageTop );
1097 while( pPg && pPg->IsEmptyPage() )
1098 pPg = (const SwPageFrm *)pPg->GetPrev();
1101 // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1102 // standard.vor sein.
1103 return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
1107 USHORT SwCrsrShell::GetPageCnt()
1109 SET_CURR_SHELL( this );
1110 // gebe die Anzahl der Seiten zurueck
1111 return GetLayout()->GetPageNum();
1114 // Gehe zur naechsten SSelection
1117 BOOL SwCrsrShell::GoNextCrsr()
1119 // besteht ueberhaupt ein Ring ?
1120 if( pCurCrsr->GetNext() == pCurCrsr )
1121 return FALSE;
1123 SET_CURR_SHELL( this );
1124 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1125 pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1127 // Bug 24086: auch alle anderen anzeigen
1128 if( !ActionPend() )
1130 UpdateCrsr();
1131 pCurCrsr->Show();
1133 return TRUE;
1136 // gehe zur vorherigen SSelection
1139 BOOL SwCrsrShell::GoPrevCrsr()
1141 // besteht ueberhaupt ein Ring ?
1142 if( pCurCrsr->GetNext() == pCurCrsr )
1143 return FALSE;
1145 SET_CURR_SHELL( this );
1146 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1147 pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
1149 // Bug 24086: auch alle anderen anzeigen
1150 if( !ActionPend() )
1152 UpdateCrsr();
1153 pCurCrsr->Show();
1156 return TRUE;
1160 void SwCrsrShell::Paint( const Rectangle &rRect)
1162 SET_CURR_SHELL( this );
1164 // beim Painten immer alle Cursor ausschalten
1165 SwRect aRect( rRect );
1167 BOOL bVis = FALSE;
1168 // ist Cursor sichtbar, dann verstecke den SV-Cursor
1169 if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ???
1171 bVis = TRUE;
1172 pVisCrsr->Hide();
1175 // Bereich neu painten
1176 ViewShell::Paint( rRect );
1178 if( bHasFocus && !bBasicHideCrsr )
1180 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
1181 // pAktCrsr->Invalidate( aRect );
1182 if( !ActionPend() )
1184 // damit nicht rechts/unten die Raender abgeschnitten werden
1185 pAktCrsr->Invalidate( VisArea() );
1186 pAktCrsr->Show();
1188 else
1189 pAktCrsr->Invalidate( aRect );
1192 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
1193 pVisCrsr->Show();
1198 void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1200 SET_CURR_SHELL( this );
1201 BOOL bVis; // beim Scrollen immer alle Cursor ausschalten
1203 // ist Cursor sichtbar, dann verstecke den SV-Cursor
1204 if( TRUE == ( bVis = pVisCrsr->IsVisible() ))
1205 pVisCrsr->Hide();
1207 bVisPortChgd = TRUE;
1208 aOldRBPos.X() = VisArea().Right();
1209 aOldRBPos.Y() = VisArea().Bottom();
1211 //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
1212 //ViewShell::VisPo.. ein Update() auf das Window gerufen.
1213 //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
1214 //angezeigt werden, deshalb wird der Aufruf hier geklammert.
1215 ViewShell::VisPortChgd( rRect ); // Bereich verschieben
1218 SwRect aRect( rRect );
1219 if( VisArea().IsOver( aRect ) )
1220 pCurCrsr->Invalidate( aRect );
1223 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
1224 pVisCrsr->Show();
1226 if( nCrsrMove )
1227 bInCMvVisportChgd = TRUE;
1229 bVisPortChgd = FALSE;
1232 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
1233 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
1234 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
1235 // ergibt sich aus seiner aktuellen Position im Layout !!
1238 void SwCrsrShell::UpdateCrsrPos()
1240 SET_CURR_SHELL( this );
1241 ++nStartAction;
1242 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1243 Size aOldSz( GetDocSize() );
1244 SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
1245 SwCntntFrm *pFrm = pCNode ?
1246 pCNode->GetFrm( &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint() ) :0;
1247 if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
1249 SwCrsrMoveState aTmpState( MV_NONE );
1250 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1251 GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1252 &aTmpState );
1253 if( pShellCrsr->HasMark())
1254 pShellCrsr->DeleteMark();
1256 IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1257 if( pGrammarContact )
1258 pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
1259 --nStartAction;
1260 if( aOldSz != GetDocSize() )
1261 SizeChgNotify();
1264 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1265 // stehen, so mussen diese daraus verschoben werden
1266 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1268 const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1269 if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1271 SwNodeIndex aTmp( *pSectNd );
1272 #if OSL_DEBUG_LEVEL > 1
1273 const SwNode* pFrmNd =
1274 #endif
1275 rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1277 #if OSL_DEBUG_LEVEL > 1
1278 (void) pFrmNd;
1279 ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
1280 #endif
1281 rIdx = aTmp;
1285 // Try to set the cursor to the next visible content node.
1286 static void lcl_CheckHiddenPara( SwPosition& rPos )
1288 SwNodeIndex aTmp( rPos.nNode );
1289 SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1290 while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1292 SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1293 if ( pCntnt && pCntnt->IsTxtNode() )
1294 pTxtNd = (SwTxtNode*)pCntnt;
1295 else
1296 pTxtNd = 0;
1299 if ( pTxtNd )
1300 rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1303 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
1304 // about invalid text selections in its destructor
1305 class SwNotifyAccAboutInvalidTextSelections
1307 private:
1308 SwCrsrShell& mrCrsrSh;
1310 public:
1311 SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1312 : mrCrsrSh( _rCrsrSh )
1315 ~SwNotifyAccAboutInvalidTextSelections()
1317 mrCrsrSh.InvalidateAccessibleParaTextSelection();
1320 // <--
1321 void SwCrsrShell::UpdateCrsr( USHORT eFlags, BOOL bIdleEnd )
1323 SET_CURR_SHELL( this );
1325 ClearUpCrsrs();
1327 // erfrage den Count fuer die Start-/End-Actions und ob die Shell
1328 // ueberhaupt den Focus hat
1329 // if( ActionPend() /*|| !bHasFocus*/ )
1330 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
1331 // Cursor geupdatet werden; um z.B. den TabellenCursor zu
1332 // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
1333 if( ActionPend() && BasicActionPend() )
1335 if ( eFlags & SwCrsrShell::READONLY )
1336 bIgnoreReadonly = TRUE;
1337 return; // wenn nicht, dann kein Update !!
1340 // --> OD 2005-12-14 #i27301#
1341 SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1342 // <--
1344 if ( bIgnoreReadonly )
1346 bIgnoreReadonly = FALSE;
1347 eFlags |= SwCrsrShell::READONLY;
1350 if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf
1351 CheckRange( pCurCrsr ); // ueberlappende Bereiche testen
1353 if( !bIdleEnd )
1354 CheckTblBoxCntnt();
1356 // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
1357 // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
1358 SwPaM* pTstCrsr = getShellCrsr( true );
1359 if( pTstCrsr->HasMark() && !pBlockCrsr &&
1360 pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1361 ( pTblCrsr ||
1362 pTstCrsr->GetNode( TRUE )->StartOfSectionNode() !=
1363 pTstCrsr->GetNode( FALSE )->StartOfSectionNode() ) )
1365 SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1366 Point aTmpPt( pITmpCrsr->GetPtPos() );
1367 Point aTmpMk( pITmpCrsr->GetMkPos() );
1368 SwPosition* pPos = pITmpCrsr->GetPoint();
1370 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1371 // stehen, so mussen diese daraus verschoben werden
1372 lcl_CheckHiddenSection( pPos->nNode );
1373 lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1375 // Move cursor out of hidden paragraphs
1376 if ( !GetViewOptions()->IsShowHiddenChar() )
1378 lcl_CheckHiddenPara( *pPos );
1379 lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1382 SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1383 GetFrm( &aTmpPt, pPos );
1385 ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1387 // --> FME 2005-12-02 #126107# Make code robust. The table
1388 // cursor may point to a table in a currently inactive header.
1389 SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1390 // <--
1392 if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1394 // First check if point is in repeated headline:
1395 bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1397 // Second check if mark is in repeated headline:
1398 if ( !bInRepeatedHeadline )
1400 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( FALSE )->GetFrm( &aTmpMk, pITmpCrsr->GetMark() );
1401 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1403 if ( pMarkTblFrm )
1405 SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1406 ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1408 // --> FME 2005-11-28 #120360# Make code robust:
1409 if ( pMarkTab )
1411 bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1413 // <--
1417 // No table cursor in repeaded headlines:
1418 if ( bInRepeatedHeadline )
1420 pTblFrm = 0;
1422 SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
1423 ? fnSectionStart
1424 : fnSectionEnd;
1426 // dann nur innerhalb der Box selektieren
1427 if( pTblCrsr )
1429 pCurCrsr->SetMark();
1430 *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
1431 pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
1432 pTblCrsr->DeleteMark();
1433 pTblCrsr->SwSelPaintRects::Hide();
1436 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
1437 (*fnSectionCurr)( *pCurCrsr, fnPosSect );
1441 // wir wollen wirklich eine Tabellen-Selektion
1442 if( pTab && pTblFrm )
1444 if( !pTblCrsr )
1446 pTblCrsr = new SwShellTableCrsr( *this,
1447 *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
1448 *pPos, aTmpPt );
1449 pCurCrsr->DeleteMark();
1450 pCurCrsr->SwSelPaintRects::Hide();
1452 CheckTblBoxCntnt();
1455 SwCrsrMoveState aTmpState( MV_NONE );
1456 aTmpState.bRealHeight = TRUE;
1457 if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
1459 Point aCentrPt( aCharRect.Center() );
1460 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1461 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1462 #ifdef PRODUCT
1463 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
1464 #else
1465 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
1466 ASSERT( !this, "GetCharRect failed." );
1467 #endif
1469 // ALIGNRECT( aCharRect );
1471 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
1472 // Curosr in den sichtbaren Bereich scrollen
1473 if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1474 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1475 !IsCrsrReadonly()) )
1477 SwFrm* pBoxFrm = pTblFrm;
1478 while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1479 pBoxFrm = pBoxFrm->GetUpper();
1480 if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1481 MakeVisible( pBoxFrm->Frm() );
1482 else
1483 MakeVisible( aCharRect );
1486 // lasse vom Layout die Crsr in den Boxen erzeugen
1487 if( pTblCrsr->IsCrsrMovedUpdt() )
1488 GetLayout()->MakeTblCrsrs( *pTblCrsr );
1489 if( bHasFocus && !bBasicHideCrsr )
1490 pTblCrsr->Show();
1492 // Cursor-Points auf die neuen Positionen setzen
1493 pTblCrsr->GetPtPos().X() = aCharRect.Left();
1494 pTblCrsr->GetPtPos().Y() = aCharRect.Top();
1496 if( bSVCrsrVis )
1498 aCrsrHeight.X() = 0;
1499 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1500 -aCharRect.Width() : aCharRect.Height();
1501 pVisCrsr->Show(); // wieder anzeigen
1503 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
1504 if( pTblFrm && Imp()->IsAccessible() )
1505 Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1506 return;
1510 if( pTblCrsr )
1512 // Cursor Ring loeschen
1513 while( pCurCrsr->GetNext() != pCurCrsr )
1514 delete pCurCrsr->GetNext();
1515 pCurCrsr->DeleteMark();
1516 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1517 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1518 delete pTblCrsr, pTblCrsr = 0;
1521 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
1523 // sind wir vielleicht in einer geschuetzten/versteckten Section ?
1525 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1526 BOOL bChgState = TRUE;
1527 const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
1528 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1529 ( !IsReadOnlyAvailable() &&
1530 pSectNd->GetSection().IsProtectFlag() &&
1531 ( !pDoc->GetDocShell() ||
1532 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
1534 if( !FindValidCntntNode( !HasDrawView() ||
1535 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1537 // alles ist geschuetzt / versteckt -> besonderer Mode
1538 if( bAllProtect && !IsReadOnlyAvailable() &&
1539 pSectNd->GetSection().IsProtectFlag() )
1540 bChgState = FALSE;
1541 else
1543 eMvState = MV_NONE; // Status fuers Crsr-Travelling
1544 bAllProtect = TRUE;
1545 if( GetDoc()->GetDocShell() )
1547 GetDoc()->GetDocShell()->SetReadOnlyUI( TRUE );
1548 CallChgLnk(); // UI bescheid sagen!
1550 return;
1554 if( bChgState )
1556 BOOL bWasAllProtect = bAllProtect;
1557 bAllProtect = FALSE;
1558 if( bWasAllProtect && GetDoc()->GetDocShell() &&
1559 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1561 GetDoc()->GetDocShell()->SetReadOnlyUI( FALSE );
1562 CallChgLnk(); // UI bescheid sagen!
1567 UpdateCrsrPos();
1569 // #100722# The cursor must always point into content; there's some code
1570 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1571 // loops _behind_ the last node in the selection, which always works if you
1572 // are in content.) To achieve this, we'll force cursor(s) to point into
1573 // content, if UpdateCrsrPos() hasn't already done so.
1574 SwPaM* pCmp = pCurCrsr;
1577 // start will move forwards, end will move backwards
1578 bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1580 // move point; forward if it's the start, backwards if it's the end
1581 if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1582 pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1583 fnGoCntnt );
1585 // move mark (if exists); forward if it's the start, else backwards
1586 if( pCmp->HasMark() )
1588 if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1590 pCmp->Exchange();
1591 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1592 fnGoCntnt );
1593 pCmp->Exchange();
1597 // iterate to next PaM in ring
1598 pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1600 while( pCmp != pCurCrsr );
1603 SwRect aOld( aCharRect );
1604 BOOL bFirst = TRUE;
1605 SwCntntFrm *pFrm;
1606 int nLoopCnt = 100;
1607 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1609 do {
1610 BOOL bAgainst;
1611 do {
1612 bAgainst = FALSE;
1613 pFrm = pShellCrsr->GetCntntNode()->GetFrm(
1614 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint() );
1615 // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
1616 // erzeugt werden, weil ja mal hier einer vorhanden war !!
1617 if ( !pFrm )
1621 CalcLayout();
1622 pFrm = pShellCrsr->GetCntntNode()->GetFrm(
1623 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint() );
1624 } while( !pFrm );
1626 else if ( Imp()->IsIdleAction() )
1627 //Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
1628 pFrm->PrepareCrsr();
1630 // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
1631 if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1632 ( !Imp()->GetDrawView() ||
1633 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1634 (!pDoc->GetDocShell() ||
1635 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
1637 // dann suche eine gueltige Position
1638 BOOL bChgState = TRUE;
1639 if( !FindValidCntntNode(!HasDrawView() ||
1640 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1642 // alles ist geschuetzt / versteckt -> besonderer Mode
1643 if( bAllProtect )
1644 bChgState = FALSE;
1645 else
1647 eMvState = MV_NONE; // Status fuers Crsr-Travelling
1648 bAllProtect = TRUE;
1649 if( GetDoc()->GetDocShell() )
1651 GetDoc()->GetDocShell()->SetReadOnlyUI( TRUE );
1652 CallChgLnk(); // UI bescheid sagen!
1654 return;
1658 if( bChgState )
1660 BOOL bWasAllProtect = bAllProtect;
1661 bAllProtect = FALSE;
1662 if( bWasAllProtect && GetDoc()->GetDocShell() &&
1663 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1665 GetDoc()->GetDocShell()->SetReadOnlyUI( FALSE );
1666 CallChgLnk(); // UI bescheid sagen!
1668 bAllProtect = FALSE;
1669 bAgainst = TRUE; // nochmal den richigen Frm suchen
1672 } while( bAgainst );
1674 if( !( eFlags & SwCrsrShell::NOCALRECT ))
1676 SwCrsrMoveState aTmpState( eMvState );
1677 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1678 aTmpState.bRealHeight = TRUE;
1679 aTmpState.bRealWidth = IsOverwriteCrsr();
1680 aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1682 // #i27615#,#i30453#
1683 SwSpecialPos aSpecialPos;
1684 aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1685 if (pShellCrsr->IsInFrontOfLabel())
1687 aTmpState.pSpecialPos = &aSpecialPos;
1690 if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1692 Point& rPt = pShellCrsr->GetPtPos();
1693 rPt = aCharRect.Center();
1694 pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1696 // ALIGNRECT( aCharRect );
1698 if( !pShellCrsr->HasMark() )
1699 aCrsrHeight = aTmpState.aRealHeight;
1700 else
1702 aCrsrHeight.X() = 0;
1703 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1704 -aCharRect.Width() : aCharRect.Height();
1707 else
1709 aCrsrHeight.X() = 0;
1710 aCrsrHeight.Y() = aCharRect.Height();
1713 if( !bFirst && aOld == aCharRect )
1714 break;
1716 // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
1717 // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
1718 // siehe Bug: 29658
1719 if( !--nLoopCnt )
1721 ASSERT( !this, "Endlosschleife? CharRect != OldCharRect ");
1722 break;
1724 aOld = aCharRect;
1725 bFirst = FALSE;
1727 // Cursor-Points auf die neuen Positionen setzen
1728 pShellCrsr->GetPtPos().X() = aCharRect.Left();
1729 pShellCrsr->GetPtPos().Y() = aCharRect.Top();
1731 if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen
1733 pFrm->Calc();
1734 nUpDownX = pFrm->IsVertical() ?
1735 aCharRect.Top() - pFrm->Frm().Top() :
1736 aCharRect.Left() - pFrm->Frm().Left();
1739 // Curosr in den sichtbaren Bereich scrollen
1740 if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1741 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1742 !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1744 //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den
1745 // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
1746 // gesichert und zurueckgesetzt.
1747 BOOL bSav = bSVCrsrVis; bSVCrsrVis = FALSE;
1748 MakeSelVisible();
1749 bSVCrsrVis = bSav;
1752 } while( eFlags & SwCrsrShell::SCROLLWIN );
1754 if( pBlockCrsr )
1755 RefreshBlockCursor();
1757 if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
1759 if( pTblCrsr )
1760 pTblCrsr->SwSelPaintRects::Show();
1761 else
1763 pCurCrsr->SwSelPaintRects::Show();
1764 if( pBlockCrsr )
1766 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1767 while( pNxt && pNxt != pCurCrsr )
1769 pNxt->SwSelPaintRects::Show();
1770 pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1776 //Ggf. gescrollten Bereicht korrigieren (Alignment).
1777 //Nur wenn gescrollt wurde, und wenn keine Selektion existiert.
1778 if( pFrm && Imp()->IsScrolled() &&
1779 pShellCrsr->GetNext() == pShellCrsr && !pShellCrsr->HasMark() )
1780 Imp()->RefreshScrolledArea( aCharRect );
1783 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
1785 if( pFrm && Imp()->IsAccessible() )
1786 Imp()->InvalidateAccessibleCursorPosition( pFrm );
1788 // switch from blinking cursor to read-only-text-selection cursor
1789 static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1790 const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1791 GetCursorBlinkTime();
1793 if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1794 ( nBlinkTime != nNoBlinkTime ) )
1796 // non blinking cursor in read only - text selection mode
1797 AllSettings aSettings = GetOut()->GetSettings();
1798 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1799 const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1800 Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1801 nNoBlinkTime;
1802 aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1803 aSettings.SetStyleSettings( aStyleSettings );
1804 GetOut()->SetSettings( aSettings );
1807 if( bSVCrsrVis )
1808 pVisCrsr->Show(); // wieder anzeigen
1811 void SwCrsrShell::RefreshBlockCursor()
1813 ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
1814 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1815 Point aPt = rBlock.GetPtPos();
1816 SwCntntFrm* pFrm = rBlock.GetCntntNode()->GetFrm( &aPt, rBlock.GetPoint() );
1817 Point aMk;
1818 if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
1820 aPt = *pBlockCrsr->getStartPoint();
1821 aMk = *pBlockCrsr->getEndPoint();
1823 else
1825 aPt = rBlock.GetPtPos();
1826 if( pFrm )
1828 if( pFrm->IsVertical() )
1829 aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
1830 else
1831 aPt.X() = pFrm->Frm().Left() + GetUpDownX();
1833 aMk = rBlock.GetMkPos();
1835 SwRect aRect( aMk, aPt );
1836 aRect.Justify();
1837 SwSelectionList aSelList( pFrm );
1839 if( GetLayout()->FillSelection( aSelList, aRect ) )
1841 SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
1842 while( pNxt != pCurCrsr )
1844 delete pNxt;
1845 pNxt = (SwCursor*)pCurCrsr->GetNext();
1848 std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1849 std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1850 ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
1851 pCurCrsr->SetMark();
1852 --pPam;
1853 // If there is only one text portion inside the rectangle, a simple
1854 // selection is created
1855 if( pPam == pStart )
1857 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1858 if( (*pPam)->HasMark() )
1859 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1860 else
1861 pCurCrsr->DeleteMark();
1862 delete *pPam;
1863 pCurCrsr->SetColumnSelection( false );
1865 else
1867 // The order of the SwSelectionList has to be preserved but
1868 // the order inside the ring created by CreateCrsr() is not like
1869 // exspected => First create the selections before the last one
1870 // downto the first selection.
1871 // At least create the cursor for the last selection
1872 --pPam;
1873 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1874 if( (*pPam)->HasMark() )
1875 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1876 else
1877 pCurCrsr->DeleteMark();
1878 delete *pPam;
1879 pCurCrsr->SetColumnSelection( true );
1880 while( pPam != pStart )
1882 --pPam;
1884 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1885 pNew->Insert( pCurCrsr, 0 );
1886 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1887 pCurCrsr->DeleteMark();
1889 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1890 if( (*pPam)->HasMark() )
1892 pCurCrsr->SetMark();
1893 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1895 else
1896 pCurCrsr->DeleteMark();
1897 pCurCrsr->SetColumnSelection( true );
1898 delete *pPam;
1901 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1902 pNew->Insert( pCurCrsr, 0 );
1903 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1904 pCurCrsr->DeleteMark();
1906 pPam = aSelList.getEnd();
1907 --pPam;
1908 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1909 if( (*pPam)->HasMark() )
1911 pCurCrsr->SetMark();
1912 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1914 else
1915 pCurCrsr->DeleteMark();
1916 pCurCrsr->SetColumnSelection( true );
1917 delete *pPam;
1922 // erzeuge eine Kopie vom Cursor und speicher diese im Stack
1925 void SwCrsrShell::Push()
1927 pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
1928 pCurCrsr->GetPtPos(), pCrsrStk );
1930 if( pCurCrsr->HasMark() )
1932 pCrsrStk->SetMark();
1933 *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
1938 * Loescht einen Cursor (gesteuert durch bOldCrsr)
1939 * - vom Stack oder ( bOldCrsr = TRUE )
1940 * - den aktuellen und der auf dem Stack stehende wird zum aktuellen
1942 * Return: es war auf dem Stack noch einer vorhanden
1946 BOOL SwCrsrShell::Pop( BOOL bOldCrsr )
1948 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1950 // noch weitere vorhanden ?
1951 if( 0 == pCrsrStk )
1952 return FALSE;
1954 SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
1956 // der Nachfolger wird der Aktuelle
1957 if( pCrsrStk->GetNext() != pCrsrStk )
1959 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
1962 if( bOldCrsr ) // loesche vom Stack
1963 delete pCrsrStk; //
1965 pCrsrStk = pTmp; // neu zuweisen
1967 if( !bOldCrsr )
1969 SwCrsrSaveState aSaveState( *pCurCrsr );
1971 // wurde die sichtbare SSelection nicht veraendert
1972 if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
1973 pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
1975 // "Selektions-Rechtecke" verschieben
1976 pCurCrsr->Insert( pOldStk, 0 );
1977 pOldStk->Remove( 0, pOldStk->Count() );
1980 if( pOldStk->HasMark() )
1982 pCurCrsr->SetMark();
1983 *pCurCrsr->GetMark() = *pOldStk->GetMark();
1984 pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
1986 else
1987 // keine Selection also alte aufheben und auf die alte Pos setzen
1988 pCurCrsr->DeleteMark();
1989 *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
1990 pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
1991 delete pOldStk;
1993 if( !pCurCrsr->IsInProtectTable( TRUE ) &&
1994 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1995 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
1996 UpdateCrsr(); // akt. Cursor Updaten
1998 return TRUE;
2002 * Verbinde zwei Cursor miteinander.
2003 * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
2007 void SwCrsrShell::Combine()
2009 // noch weitere vorhanden ?
2010 if( 0 == pCrsrStk )
2011 return;
2013 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
2014 SwCrsrSaveState aSaveState( *pCurCrsr );
2015 if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde
2017 #ifdef PRODUCT
2018 CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, TRUE );
2019 #else
2020 if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, TRUE ))
2021 ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
2022 #endif
2023 // kopiere das GetMark
2024 if( !pCurCrsr->HasMark() )
2025 pCurCrsr->SetMark();
2026 *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
2027 pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
2030 SwShellCrsr * pTmp = 0;
2031 if( pCrsrStk->GetNext() != pCrsrStk )
2033 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2035 delete pCrsrStk;
2036 pCrsrStk = pTmp;
2037 if( !pCurCrsr->IsInProtectTable( TRUE ) &&
2038 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2039 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2040 UpdateCrsr(); // akt. Cursor Updaten
2044 void SwCrsrShell::HideCrsrs()
2046 if( !bHasFocus || bBasicHideCrsr )
2047 return;
2049 // ist Cursor sichtbar, dann verstecke den SV-Cursor
2050 if( pVisCrsr->IsVisible() )
2052 SET_CURR_SHELL( this );
2053 pVisCrsr->Hide();
2055 // hebe die Invertierung der SSelection auf
2056 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2057 pAktCrsr->Hide();
2062 void SwCrsrShell::ShowCrsrs( BOOL bCrsrVis )
2064 if( !bHasFocus || bAllProtect || bBasicHideCrsr )
2065 return;
2067 SET_CURR_SHELL( this );
2068 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2069 pAktCrsr->Show();
2071 if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen
2072 pVisCrsr->Show();
2075 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
2078 void SwCrsrShell::ShowCrsr()
2080 if( !bBasicHideCrsr )
2082 bSVCrsrVis = TRUE;
2083 UpdateCrsr();
2088 void SwCrsrShell::HideCrsr()
2090 if( !bBasicHideCrsr )
2092 bSVCrsrVis = FALSE;
2093 // evt. die sel. Bereiche aufheben !!
2094 SET_CURR_SHELL( this );
2095 pVisCrsr->Hide();
2100 void SwCrsrShell::ShLooseFcs()
2102 if( !bBasicHideCrsr )
2103 HideCrsrs();
2104 bHasFocus = FALSE;
2108 void SwCrsrShell::ShGetFcs( BOOL bUpdate )
2110 bHasFocus = TRUE;
2111 if( !bBasicHideCrsr && VisArea().Width() )
2113 UpdateCrsr( static_cast<USHORT>( bUpdate ?
2114 SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2115 : SwCrsrShell::CHKRANGE ) );
2116 ShowCrsrs( bSVCrsrVis ? TRUE : FALSE );
2120 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck
2122 SwCntntFrm *SwCrsrShell::GetCurrFrm( const BOOL bCalcFrm ) const
2124 SET_CURR_SHELL( (ViewShell*)this );
2125 SwCntntFrm *pRet = 0;
2126 SwCntntNode *pNd = pCurCrsr->GetCntntNode();
2127 if ( pNd )
2129 if ( bCalcFrm )
2131 const USHORT* pST = &nStartAction;
2132 ++(*((USHORT*)pST));
2133 const Size aOldSz( GetDocSize() );
2134 pRet = pNd->GetFrm( &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
2135 --(*((USHORT*)pST));
2136 if( aOldSz != GetDocSize() )
2137 ((SwCrsrShell*)this)->SizeChgNotify();
2139 else
2140 pRet = pNd->GetFrm( &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), FALSE);
2142 return pRet;
2146 // alle Attribut/Format-Aenderungen am akt. Node werden an den
2147 // Link weitergeleitet.
2150 void SwCrsrShell::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
2152 const USHORT nWhich = pOld ?
2153 pOld->Which() :
2154 pNew ?
2155 pNew->Which() :
2156 sal::static_int_cast<USHORT>(RES_MSG_BEGIN);
2158 if( bCallChgLnk &&
2159 ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2160 nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2161 nWhich == RES_ATTRSET_CHG ))
2162 // die Messages werden nicht weitergemeldet
2163 //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
2164 //SwTxtNode::Insert(SwTxtHint*, USHORT) abgesetzt; hier wird reagiert und
2165 //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
2166 CallChgLnk();
2168 if( aGrfArrivedLnk.IsSet() &&
2169 ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2170 aGrfArrivedLnk.Call( this );
2174 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
2175 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
2178 BOOL SwCrsrShell::HasSelection() const
2180 const SwPaM* pCrsr = getShellCrsr( true );
2181 return( IsTableMode() || ( pCrsr->HasMark() &&
2182 *pCrsr->GetPoint() != *pCrsr->GetMark())
2183 ? TRUE : FALSE );
2187 void SwCrsrShell::CallChgLnk()
2189 // innerhalb von Start-/End-Action kein Call, sondern nur merken,
2190 // das sich etwas geaendert hat. Wird bei EndAction beachtet.
2191 if( BasicActionPend() )
2192 bChgCallFlag = TRUE; // das Change merken
2193 else if( aChgLnk.IsSet() )
2195 if( bCallChgLnk )
2196 aChgLnk.Call( this );
2197 bChgCallFlag = FALSE; // Flag zuruecksetzen
2201 // returne den am akt.Cursor selektierten Text eines Nodes.
2204 String SwCrsrShell::GetSelTxt() const
2206 String aTxt;
2207 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2208 pCurCrsr->GetMark()->nNode.GetIndex() )
2210 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2211 if( pTxtNd )
2213 xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
2214 aTxt = pTxtNd->GetExpandTxt( nStt,
2215 pCurCrsr->End()->nContent.GetIndex() - nStt );
2218 return aTxt;
2221 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
2224 String SwCrsrShell::GetText() const
2226 String aTxt;
2227 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2228 pCurCrsr->GetMark()->nNode.GetIndex() )
2230 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2231 if( pTxtNd )
2232 aTxt = pTxtNd->GetTxt().Copy(
2233 pCurCrsr->GetPoint()->nContent.GetIndex() );
2235 return aTxt;
2238 // hole vom Start/Ende der akt. SSelection das nte Zeichen
2239 sal_Unicode SwCrsrShell::GetChar( BOOL bEnd, long nOffset )
2241 if( IsTableMode() ) // im TabelleMode nicht moeglich
2242 return 0;
2244 const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
2245 : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2246 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2247 if( !pTxtNd )
2248 return 0;
2250 xub_StrLen nPos = pPos->nContent.GetIndex();
2251 const String& rStr = pTxtNd->GetTxt();
2252 sal_Unicode cCh = 0;
2254 if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
2255 cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
2257 return cCh;
2260 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen
2263 BOOL SwCrsrShell::ExtendSelection( BOOL bEnd, xub_StrLen nCount )
2265 if( !pCurCrsr->HasMark() || IsTableMode() )
2266 return FALSE; // keine Selektion
2268 SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2269 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2270 ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
2272 xub_StrLen nPos = pPos->nContent.GetIndex();
2273 if( bEnd )
2275 if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
2276 nPos = nPos + nCount;
2277 else
2278 return FALSE; // nicht mehr moeglich
2280 else if( nPos >= nCount )
2281 nPos = nPos - nCount;
2282 else
2283 return FALSE; // nicht mehr moeglich
2285 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
2287 pPos->nContent = nPos;
2288 UpdateCrsr();
2290 return TRUE;
2293 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
2294 // returnt FALSE: wenn der SPoint vom Layout korrigiert wurde.
2296 BOOL SwCrsrShell::SetVisCrsr( const Point &rPt )
2298 SET_CURR_SHELL( this );
2299 Point aPt( rPt );
2300 SwPosition aPos( *pCurCrsr->GetPoint() );
2301 SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2302 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2303 aTmpState.bRealHeight = TRUE;
2305 BOOL bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2307 SetInFrontOfLabel( FALSE ); // #i27615#
2309 // nur in TextNodes anzeigen !!
2310 SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2311 if( !pTxtNd )
2312 return FALSE;
2314 const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2315 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2316 ( !IsReadOnlyAvailable() &&
2317 pSectNd->GetSection().IsProtectFlag())) )
2318 return FALSE;
2320 SwCntntFrm *pFrm = pTxtNd->GetFrm( &aPt, &aPos );
2321 if ( Imp()->IsIdleAction() )
2322 pFrm->PrepareCrsr();
2323 SwRect aTmp( aCharRect );
2325 pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
2326 // ALIGNRECT( aCharRect );
2328 if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der
2329 pVisCrsr->IsVisible() ) // Position nicht hidden & showen
2330 return TRUE;
2332 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
2333 if( IsScrollMDI( this, aCharRect ))
2335 MakeVisible( aCharRect );
2336 pCurCrsr->Show();
2339 // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
2340 // D&D-Cursor will man trotzdem haben
2341 // if( bSVCrsrVis )
2343 if( aTmpState.bRealHeight )
2344 aCrsrHeight = aTmpState.aRealHeight;
2345 else
2347 aCrsrHeight.X() = 0;
2348 aCrsrHeight.Y() = aCharRect.Height();
2351 pVisCrsr->SetDragCrsr( TRUE );
2352 pVisCrsr->Show(); // wieder anzeigen
2354 return bRet;
2357 BOOL SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2359 Point aPt( rPt );
2360 SwPaM aPam( *pCurCrsr->GetPoint() );
2361 GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2362 // --> FME 2004-06-29 #114856# Formular view
2363 return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2364 // <--
2368 // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
2369 // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
2370 USHORT SwCrsrShell::GetCrsrCnt( BOOL bAll ) const
2372 Ring* pTmp = GetCrsr()->GetNext();
2373 USHORT n = (bAll || ( pCurCrsr->HasMark() &&
2374 *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
2375 while( pTmp != pCurCrsr )
2377 if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2378 *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2379 ++n;
2380 pTmp = pTmp->GetNext();
2382 return n;
2386 BOOL SwCrsrShell::IsStartOfDoc() const
2388 if( pCurCrsr->GetPoint()->nContent.GetIndex() )
2389 return FALSE;
2391 // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
2392 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2393 if( !aIdx.GetNode().IsCntntNode() )
2394 GetDoc()->GetNodes().GoNext( &aIdx );
2395 return aIdx == pCurCrsr->GetPoint()->nNode;
2399 BOOL SwCrsrShell::IsEndOfDoc() const
2401 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2402 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2403 if( !pCNd )
2404 pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2406 return aIdx == pCurCrsr->GetPoint()->nNode &&
2407 pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
2411 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
2412 // Cursor auf seinen TextNode (oder StartNode?).
2413 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
2414 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
2415 BOOL SwCrsrShell::ParkTblCrsr()
2417 if( !pTblCrsr )
2418 return FALSE;
2420 pTblCrsr->ParkCrsr();
2422 while( pCurCrsr->GetNext() != pCurCrsr )
2423 delete pCurCrsr->GetNext();
2425 // vom Cursor !immer! SPoint und Mark umsetzen
2426 pCurCrsr->SetMark();
2427 *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
2428 pCurCrsr->DeleteMark();
2430 return TRUE;
2433 /***********************************************************************
2434 #* Class : SwCrsrShell
2435 #* Methode : ParkCrsr
2436 #* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der
2437 #* verbleibende Crsr der Shell wird geparkt.
2438 #* Datum : MA 05. Nov. 92
2439 #* Update : JP 19.09.97
2440 #***********************************************************************/
2442 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2444 const SwPosition *pStt = pDelRg->Start(),
2445 *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2447 SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2449 // durchsuche den gesamten Ring
2450 BOOL bGoNext;
2451 do {
2452 const SwPosition *pTmpStt = pTmp->Start(),
2453 *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2454 pTmp->GetMark() : pTmp->GetPoint();
2456 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
2457 * muss der alte Bereich aufgehoben werden.
2458 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
2459 * Bereich gehoert !
2461 if( *pStt <= *pTmpStt )
2463 if( *pEnd > *pTmpStt ||
2464 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2465 pTmpDel = pTmp;
2467 else
2468 if( *pStt < *pTmpEnd )
2469 pTmpDel = pTmp;
2471 bGoNext = TRUE;
2472 if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn
2474 BOOL bDelete = TRUE;
2475 if( *ppDelRing == pTmpDel )
2477 if( *ppDelRing == pCurCrsr )
2479 if( TRUE == ( bDelete = GoNextCrsr() ))
2481 bGoNext = FALSE;
2482 pTmp = (SwPaM*)pTmp->GetNext();
2485 else
2486 bDelete = FALSE; // StackCrsr nie loeschen !!
2489 if( bDelete )
2490 delete pTmpDel; // hebe alten Bereich auf
2491 else
2493 pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
2494 pTmpDel->GetPoint()->nNode = 0;
2495 pTmpDel->SetMark();
2496 pTmpDel->DeleteMark();
2498 pTmpDel = 0;
2500 else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das
2501 { // nicht benutzte Indizies beachtet werden!
2502 pTmp->SetMark(); // SPoint liegt nicht im Bereich,
2503 pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen
2505 if( bGoNext )
2506 pTmp = (SwPaM*)pTmp->GetNext();
2507 } while( !bGoNext || *ppDelRing != pTmp );
2510 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2512 SwNode *pNode = &rIdx.GetNode();
2514 // erzeuge einen neuen Pam
2515 SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2516 if( pNode->GetStartNode() )
2518 if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2520 // der angegebene Node steht in einer Tabelle, also Parke
2521 // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
2522 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2524 else // also auf dem StartNode selbst.
2525 // Dann immer ueber seinen EndNode den StartNode erfragen !!!
2526 // (StartOfSection vom StartNode ist der Parent !)
2527 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2529 else
2530 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2531 pNew->SetMark();
2532 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2534 //Alle Shells wollen etwas davon haben.
2535 ViewShell *pTmp = this;
2536 do {
2537 if( pTmp->IsA( TYPE( SwCrsrShell )))
2539 SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2540 if( pSh->pCrsrStk )
2541 pSh->_ParkPams( pNew, &pSh->pCrsrStk );
2543 pSh->_ParkPams( pNew, &pSh->pCurCrsr );
2544 if( pSh->pTblCrsr )
2546 // setze den Tabellen Cursor immer auf 0, den aktuellen
2547 // immer auf den Anfang der Tabelle
2548 SwPaM* pTCrsr = pSh->GetTblCrs();
2549 SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2550 if ( pTblNd )
2552 pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
2553 pTCrsr->GetPoint()->nNode = 0;
2554 pTCrsr->SetMark();
2555 pTCrsr->DeleteMark();
2556 pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
2560 } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
2561 delete pNew;
2564 //=========================================================================
2567 * der Copy-Constructor
2568 * Cursor-Position kopieren, in den Ring eingetragen.
2569 * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
2572 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
2573 : ViewShell( rShell, pInitWin ),
2574 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2575 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2576 eMvState( MV_NONE ),
2577 // --> OD 2008-04-02 #refactorlists#
2578 sMarkedListId(),
2579 nMarkedListLevel( 0 )
2580 // <--
2582 SET_CURR_SHELL( this );
2583 // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
2584 pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
2585 pCurCrsr->GetCntntNode()->Add( this );
2587 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2588 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2589 bOverwriteCrsr = FALSE;
2590 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = TRUE;
2591 bSetCrsrInReadOnly = TRUE;
2592 pVisCrsr = new SwVisCrsr( this );
2593 // UpdateCrsr( 0 );
2594 // OD 11.02.2003 #100556#
2595 mbMacroExecAllowed = rShell.IsMacroExecAllowed();
2600 * der normale Constructor
2603 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
2604 const SwViewOption *pInitOpt )
2605 : ViewShell( rDoc, pInitWin, pInitOpt ),
2606 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2607 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2608 eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
2609 // --> OD 2008-04-02 #refactorlists#
2610 sMarkedListId(),
2611 nMarkedListLevel( 0 )
2612 // <--
2614 SET_CURR_SHELL( this );
2616 * Erzeugen des initialen Cursors, wird auf die erste
2617 * Inhaltsposition gesetzt
2619 SwNodes& rNds = rDoc.GetNodes();
2621 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2622 SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
2624 pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2626 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
2627 // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
2628 pCNd->Add( this );
2630 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2631 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2632 bOverwriteCrsr = FALSE;
2633 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = TRUE;
2634 bSetCrsrInReadOnly = TRUE;
2636 pVisCrsr = new SwVisCrsr( this );
2637 // UpdateCrsr( 0 );
2638 // OD 11.02.2003 #100556#
2639 mbMacroExecAllowed = true;
2644 SwCrsrShell::~SwCrsrShell()
2646 // wenn es nicht die letzte View so sollte zu mindest das
2647 // Feld noch geupdatet werden.
2648 if( GetNext() != this )
2649 CheckTblBoxCntnt( pCurCrsr->GetPoint() );
2650 else
2651 ClearTblBoxCntnt();
2653 delete pVisCrsr;
2654 delete pBlockCrsr;
2655 delete pTblCrsr;
2658 * Freigabe der Cursor
2660 while(pCurCrsr->GetNext() != pCurCrsr)
2661 delete pCurCrsr->GetNext();
2662 delete pCurCrsr;
2664 // Stack freigeben
2665 if( pCrsrStk )
2667 while( pCrsrStk->GetNext() != pCrsrStk )
2668 delete pCrsrStk->GetNext();
2669 delete pCrsrStk;
2672 // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
2673 // der CursorShell haengt keine Chance geben, sich an den
2674 // TextNode zu haengen.
2675 if( GetRegisteredIn() )
2676 pRegisteredIn->Remove( this );
2679 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2681 if( pTblCrsr )
2682 return pTblCrsr;
2683 if( pBlockCrsr && bBlock )
2684 return &pBlockCrsr->getShellCrsr();
2685 return pCurCrsr;
2688 //Sollte fuer das Clipboard der WaitPtr geschaltet werden?
2689 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
2691 BOOL SwCrsrShell::ShouldWait() const
2693 if ( IsTableMode() || GetCrsrCnt() > 1 )
2694 return TRUE;
2696 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2697 return TRUE;
2699 SwPaM* pPam = GetCrsr();
2700 return pPam->Start()->nNode.GetIndex() + 10 <
2701 pPam->End()->nNode.GetIndex();
2705 USHORT SwCrsrShell::UpdateTblSelBoxes()
2707 if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
2708 GetLayout()->MakeTblCrsrs( *pTblCrsr );
2709 return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
2712 // zeige das akt. selektierte "Object" an
2713 void SwCrsrShell::MakeSelVisible()
2715 ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
2716 if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
2718 SwRect aTmp( aCharRect );
2719 long nDiff = aCharRect.Height() - VisArea().Height();
2720 if( nDiff < aCrsrHeight.X() )
2721 aTmp.Top( nDiff + aCharRect.Top() );
2722 else
2724 aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
2725 aTmp.Height( aCrsrHeight.Y() );
2727 if( !aTmp.HasArea() )
2729 aTmp.SSize().Height() += 1;
2730 aTmp.SSize().Width() += 1;
2732 MakeVisible( aTmp );
2734 else
2736 if( aCharRect.HasArea() )
2737 MakeVisible( aCharRect );
2738 else
2740 SwRect aTmp( aCharRect );
2741 aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2742 MakeVisible( aTmp );
2748 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
2749 BOOL SwCrsrShell::FindValidCntntNode( BOOL bOnlyText )
2751 if( pTblCrsr ) // was soll ich jetzt machen ??
2753 ASSERT( !this, "TabellenSelection nicht aufgehoben!" );
2754 return FALSE;
2757 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
2758 if( !bAllProtect && GetDoc()->GetDocShell() &&
2759 GetDoc()->GetDocShell()->IsReadOnlyUI() )
2760 return TRUE;
2762 // dann raus da!
2763 if( pCurCrsr->HasMark() )
2764 ClearMark();
2766 // als erstes mal auf Rahmen abpruefen
2767 SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
2768 ULONG nNdIdx = rNdIdx.GetIndex(); // sichern
2769 SwNodes& rNds = pDoc->GetNodes();
2770 SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2771 const SwCntntFrm * pFrm;
2773 if( pCNd && 0 != (pFrm = pCNd->GetFrm(0,pCurCrsr->GetPoint(),FALSE)) &&
2774 !IsReadOnlyAvailable() && pFrm->IsProtected() &&
2775 nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2777 // geschuetzter Rahmen ueberspringen
2778 SwPaM aPam( *pCurCrsr->GetPoint() );
2779 aPam.SetMark();
2780 aPam.GetMark()->nNode = rNds.GetEndOfContent();
2781 aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2783 BOOL bFirst = FALSE;
2784 if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, FALSE )))
2786 aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2787 pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, FALSE );
2790 if( !pCNd ) // sollte nie passieren !!!
2792 rNdIdx = nNdIdx; // alten Node zurueck
2793 return FALSE;
2795 *pCurCrsr->GetPoint() = *aPam.GetPoint();
2797 else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2799 // dann auf den Anfang vom Doc stellen
2800 rNdIdx = pDoc->GetNodes().GetEndOfExtras();
2801 pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
2802 &rNdIdx ), 0 );
2803 nNdIdx = rNdIdx.GetIndex();
2806 BOOL bOk = TRUE;
2808 // #i9059# cursor may not stand in protected cells
2809 // (unless cursor in protected areas is OK.)
2810 const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2811 if( !IsReadOnlyAvailable() &&
2812 pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
2814 // we're in a table, and we're in a protected area, so we're
2815 // probably in a protected cell.
2817 // move forward into non-protected area.
2818 SwPaM aPam( rNdIdx.GetNode(), 0 );
2819 while( aPam.GetNode()->IsProtect() &&
2820 aPam.Move( fnMoveForward, fnGoCntnt ) )
2821 ; // nothing to do in the loop; the aPam.Move does the moving!
2823 // didn't work? then go backwards!
2824 if( aPam.GetNode()->IsProtect() )
2826 SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2827 aPam = aTmpPaM;
2828 while( aPam.GetNode()->IsProtect() &&
2829 aPam.Move( fnMoveBackward, fnGoCntnt ) )
2830 ; // nothing to do in the loop; the aPam.Move does the moving!
2833 // if we're successful, set the new position
2834 if( ! aPam.GetNode()->IsProtect() )
2836 *pCurCrsr->GetPoint() = *aPam.GetPoint();
2840 // in einem geschuetzten Bereich
2841 const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2842 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2843 ( !IsReadOnlyAvailable() &&
2844 pSectNd->GetSection().IsProtectFlag() )) )
2846 typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
2847 FNGoSection funcGoSection = &SwNodes::GoNextSection;
2849 bOk = FALSE;
2851 for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2853 BOOL bWeiter;
2854 do {
2855 bWeiter = FALSE;
2856 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2857 TRUE, !IsReadOnlyAvailable() )) )
2859 // in eine Tabelle verschoben -> pruefe ob die
2860 // vielleicht geschuetzt ist
2861 if( pCNd->FindTableNode() )
2863 SwCallLink aTmp( *this );
2864 SwCrsrSaveState aSaveState( *pCurCrsr );
2865 aTmp.nNdTyp = 0; // im DTOR nichts machen!
2866 if( !pCurCrsr->IsInProtectTable( TRUE, TRUE ) )
2868 const SwSectionNode* pSNd = pCNd->FindSectionNode();
2869 if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2870 || (!IsReadOnlyAvailable() &&
2871 pSNd->GetSection().IsProtectFlag() ))
2873 bOk = TRUE;
2874 break; // eine nicht geschuetzte Zelle gef.
2876 continue; // dann weiter suchen
2879 else
2881 bOk = TRUE;
2882 break; // eine nicht geschuetzte Zelle gef.
2886 if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2888 // Teste mal auf Fly - kann auch noch geschuetzt sein!!
2889 if( 0 == (pFrm = pCNd->GetFrm(0,0,FALSE)) ||
2890 ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2891 ( bOnlyText && pCNd->IsNoTxtNode() ) )
2893 // dann weiter suchen!
2894 bOk = FALSE;
2895 bWeiter = TRUE;
2898 } while( bWeiter );
2900 if( !bOk )
2902 if( !nLoopCnt )
2903 funcGoSection = &SwNodes::GoPrevSection;
2904 rNdIdx = nNdIdx;
2908 if( bOk )
2910 pCNd = rNdIdx.GetNode().GetCntntNode();
2911 // USHORT nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
2912 xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2913 pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2915 else
2917 pCNd = rNdIdx.GetNode().GetCntntNode();
2919 // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
2920 // verschieben!!
2921 if( !pCNd || !pCNd->GetFrm(0,0,FALSE) )
2923 SwCrsrMoveState aTmpState( MV_NONE );
2924 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2925 GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
2926 &aTmpState );
2929 return bOk;
2933 void SwCrsrShell::NewCoreSelection()
2938 BOOL SwCrsrShell::IsCrsrReadonly() const
2940 if ( GetViewOptions()->IsReadonly() ||
2941 // --> FME 2004-06-29 #114856# Formular view
2942 GetViewOptions()->IsFormView() )
2943 // <--
2945 SwFrm *pFrm = GetCurrFrm( FALSE );
2946 const SwFlyFrm* pFly;
2947 const SwSection* pSection;
2949 if( pFrm && pFrm->IsInFly() &&
2950 (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
2951 pFly->Lower() &&
2952 !pFly->Lower()->IsNoTxtFrm() &&
2953 !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2955 return FALSE;
2957 // --> FME 2004-06-22 #114856# edit in readonly sections
2958 else if ( pFrm && pFrm->IsInSct() &&
2959 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
2960 pSection->IsEditInReadonlyFlag() )
2962 return FALSE;
2964 // <--
2966 return TRUE;
2968 return FALSE;
2972 // darf der Cursor in ReadOnlyBereiche?
2973 void SwCrsrShell::SetReadOnlyAvailable( BOOL bFlag )
2975 // im GlobalDoc darf NIE umgeschaltet werden
2976 if( (!GetDoc()->GetDocShell() ||
2977 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
2978 bFlag != bSetCrsrInReadOnly )
2980 // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
2981 // Selektionen aufgehoben werden. Denn sonst wird sich darauf
2982 // verlassen, das nichts geschuetztes selektiert ist!
2983 if( !bFlag )
2985 ClearMark();
2987 bSetCrsrInReadOnly = bFlag;
2988 UpdateCrsr();
2992 BOOL SwCrsrShell::HasReadonlySel() const
2994 BOOL bRet = FALSE;
2995 if( IsReadOnlyAvailable() ||
2996 // --> FME 2004-06-29 #114856# Formular view
2997 GetViewOptions()->IsFormView() )
2998 // <--
3000 if( pTblCrsr )
3001 bRet = pTblCrsr->HasReadOnlyBoxSel() ||
3002 pTblCrsr->HasReadonlySel(
3003 // --> FME 2004-06-29 #114856# Formular view
3004 GetViewOptions()->IsFormView() );
3005 // <--
3006 else
3008 const SwPaM* pCrsr = pCurCrsr;
3010 do {
3011 if( pCrsr->HasReadonlySel(
3012 // --> FME 2004-06-29 #114856# Formular view
3013 GetViewOptions()->IsFormView() ) )
3014 // <--
3015 bRet = TRUE;
3016 } while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
3019 return bRet;
3022 BOOL SwCrsrShell::IsSelFullPara() const
3024 BOOL bRet = FALSE;
3026 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
3027 pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
3029 xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
3030 nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
3031 if( nStt > nEnd )
3033 xub_StrLen nTmp = nStt;
3034 nStt = nEnd;
3035 nEnd = nTmp;
3037 const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
3038 bRet = pCNd && !nStt && nEnd == pCNd->Len();
3040 return bRet;
3043 short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3045 SwPosition aPos( *pCurCrsr->GetPoint() );
3046 Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
3047 if( pPt )
3049 SwCrsrMoveState aTmpState( MV_NONE );
3050 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3052 GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3055 return pDoc->GetTextDirection( aPos, &aPt );
3058 BOOL SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3060 const short nDir = GetTextDirection( pPt );
3061 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3064 BOOL SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3066 const short nDir = GetTextDirection( pPt );
3067 // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3068 // vertical environment
3069 return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3073 // If the current cursor position is inside a hidden range, the hidden range
3074 // is selected:
3076 bool SwCrsrShell::SelectHiddenRange()
3078 bool bRet = false;
3079 if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
3081 SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
3082 const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3083 if ( pNode )
3085 const xub_StrLen nPos = rPt.nContent.GetIndex();
3087 // check if nPos is in hidden range
3088 xub_StrLen nHiddenStart;
3089 xub_StrLen nHiddenEnd;
3090 SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3091 if ( STRING_LEN != nHiddenStart )
3093 // make selection:
3094 pCurCrsr->SetMark();
3095 pCurCrsr->GetMark()->nContent = nHiddenEnd;
3096 bRet = true;
3101 return bRet;
3104 /* \f */
3106 // die Suchfunktionen
3107 ULONG SwCrsrShell::Find( const SearchOptions& rSearchOpt, BOOL bSearchInNotes,
3108 SwDocPositions eStart, SwDocPositions eEnde,
3109 BOOL& bCancel,
3110 FindRanges eRng, int bReplace )
3112 if( pTblCrsr )
3113 GetCrsr();
3114 delete pTblCrsr, pTblCrsr = 0;
3115 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3116 ULONG nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
3117 if( nRet || bCancel )
3118 UpdateCrsr();
3119 return nRet;
3122 ULONG SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3123 SwDocPositions eStart, SwDocPositions eEnde,
3124 BOOL& bCancel,
3125 FindRanges eRng, const SwTxtFmtColl* pReplFmt )
3127 if( pTblCrsr )
3128 GetCrsr();
3129 delete pTblCrsr, pTblCrsr = 0;
3130 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3131 ULONG nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
3132 if( nRet )
3133 UpdateCrsr();
3134 return nRet;
3137 ULONG SwCrsrShell::Find( const SfxItemSet& rSet, BOOL bNoCollections,
3138 SwDocPositions eStart, SwDocPositions eEnde,
3139 BOOL& bCancel,
3140 FindRanges eRng, const SearchOptions* pSearchOpt,
3141 const SfxItemSet* rReplSet )
3143 if( pTblCrsr )
3144 GetCrsr();
3145 delete pTblCrsr, pTblCrsr = 0;
3146 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3147 ULONG nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
3148 eRng, pSearchOpt, rReplSet );
3149 if( nRet )
3150 UpdateCrsr();
3151 return nRet;
3154 void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3156 StartAction();
3157 SwPaM* pCrsr = GetCrsr();
3158 *pCrsr->GetPoint() = *rCrsr.GetPoint();
3159 if(rCrsr.HasMark())
3161 pCrsr->SetMark();
3162 *pCrsr->GetMark() = *rCrsr.GetMark();
3164 if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3166 const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3169 SwPaM* pCurrentCrsr = CreateCrsr();
3170 *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3171 if(_pStartCrsr->HasMark())
3173 pCurrentCrsr->SetMark();
3174 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3176 } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3178 EndAction();
3181 void lcl_RemoveMark( SwPaM* pPam )
3183 ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
3184 pPam->GetMark()->nContent.Assign( 0, 0 );
3185 pPam->GetMark()->nNode = 0;
3186 pPam->DeleteMark();
3189 const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3191 const SwStartNode *pRet = rNode.StartOfSectionNode();
3192 while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3193 pRet->GetStartNodeType() == SwTableBoxStartNode )
3195 pRet = pRet->StartOfSectionNode();
3197 return pRet;
3201 Checks if a position is valid. To be valid the position's node must
3202 be a content node and the content must not be unregistered.
3204 @param aPos the position to check.
3206 bool lcl_PosOk(const SwPosition & aPos)
3208 return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3209 SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
3213 Checks if a PaM is valid. For a PaM to be valid its point must be
3214 valid. Additionaly if the PaM has a mark this has to be valid, too.
3216 @param aPam the PaM to check
3218 static bool lcl_CrsrOk(SwPaM & aPam)
3220 return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3221 || lcl_PosOk(*aPam.GetMark()));
3224 void SwCrsrShell::ClearUpCrsrs()
3226 // start of the ring
3227 SwPaM * pStartCrsr = GetCrsr();
3228 // start loop with second entry of the ring
3229 SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3230 SwPaM * pTmpCrsr;
3231 bool bChanged = false;
3234 For all entries in the ring except the start entry delete the
3235 entry if it is invalid.
3237 while (pCrsr != pStartCrsr)
3239 pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3241 if ( ! lcl_CrsrOk(*pCrsr))
3243 delete pCrsr;
3245 bChanged = true;
3248 pCrsr = pTmpCrsr;
3251 if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
3253 lcl_RemoveMark( pStartCrsr );
3254 bChanged = true;
3256 if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
3258 SwNodes & aNodes = GetDoc()->GetNodes();
3259 const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3260 SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3261 SwNode * pNode = aNodes.GoPrevious(&aIdx);
3262 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3263 aNodes.GoNext( &aIdx );
3264 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3267 If the start entry of the ring is invalid replace it with a
3268 cursor pointing to the beginning of the first content node in
3269 the document.
3271 aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3272 pNode = aNodes.GoNext( &aIdx );
3274 bool bFound = (pNode != NULL);
3276 ASSERT(bFound, "no content node found");
3278 if (bFound)
3280 SwPaM aTmpPam(*pNode);
3281 *pStartCrsr = aTmpPam;
3284 bChanged = true;
3288 If at least one of the cursors in the ring have been deleted or
3289 replaced, remove the table cursor.
3291 if (pTblCrsr != NULL && bChanged)
3292 TblCrsrToCursor();
3295 // #111827#
3296 String SwCrsrShell::GetCrsrDescr() const
3298 String aResult;
3300 if (IsMultiSelection())
3301 aResult += String(SW_RES(STR_MULTISEL));
3302 else
3303 aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3305 return aResult;
3308 SwRect SwCrsrShell::GetRectOfCurrentChar()
3310 SwCntntFrm* pFrm = pCurCrsr->GetCntntNode()->GetFrm( 0, pCurCrsr->GetPoint(), FALSE );
3311 SwRect aRet;
3312 SwCrsrMoveState aTmpState( MV_NONE );
3313 aTmpState.bRealHeight = TRUE;
3314 pFrm->GetCharRect( aRet, *pCurCrsr->GetPoint(), &aTmpState );
3315 //const SwTwips nRealHeight = aTmpState.aRealHeight.Y();
3316 if (aTmpState.aRealHeight.X() != 0)
3317 aRet.Top(aRet.Top() + aTmpState.aRealHeight.X());
3318 return aRet;
3321 // SMARTTAGS
3323 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3324 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3325 const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
3327 // Insert smart tag information
3328 std::vector< rtl::OUString > aSmartTagTypes;
3329 std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3331 for ( USHORT i = 0; i < rSmartTagList.Count(); ++i )
3333 const xub_StrLen nSTPos = rSmartTagList.Pos( i );
3334 const xub_StrLen nSTLen = rSmartTagList.Len( i );
3336 if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3338 const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3339 if ( pArea )
3341 aSmartTagTypes.push_back( pArea->maType );
3342 aStringKeyMaps.push_back( pArea->mxPropertyBag );
3347 if ( aSmartTagTypes.size() )
3349 rSmartTagTypes.realloc( aSmartTagTypes.size() );
3350 rStringKeyMaps.realloc( aSmartTagTypes.size() );
3352 std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3353 USHORT i = 0;
3354 for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3355 rSmartTagTypes[i++] = *aTypesIter;
3357 std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3358 i = 0;
3359 for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3360 rStringKeyMaps[i++] = *aMapsIter;
3364 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3365 SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
3367 // create SwPosition for nStartIndex
3368 SwIndex aIndex( &rNode, nBegin );
3369 SwPosition aStartPos( rNode, aIndex );
3371 // create SwPosition for nEndIndex
3372 SwPosition aEndPos( aStartPos );
3373 aEndPos.nContent = nBegin + nLen;
3375 uno::Reference<text::XTextRange> xRange =
3376 SwXTextRange::CreateTextRangeFromPosition( rNode.GetDoc(), aStartPos, &aEndPos);
3378 rRange = xRange;
3381 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3382 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3383 uno::Reference< text::XTextRange>& rRange ) const
3385 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3386 return;
3388 SwPaM* pCrsr = GetCrsr();
3389 SwPosition aPos( *pCrsr->GetPoint() );
3390 SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3391 if ( pNode && !pNode->IsInProtectSect() )
3393 const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3394 if ( pSmartTagList )
3396 xub_StrLen nCurrent = aPos.nContent.GetIndex();
3397 xub_StrLen nBegin = nCurrent;
3398 xub_StrLen nLen = 1;
3400 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3402 const USHORT nIndex = pSmartTagList->GetWrongPos( nBegin );
3403 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3404 if ( pSubList )
3406 pSmartTagList = pSubList;
3407 nCurrent = 0;
3410 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3411 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3417 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
3418 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3419 uno::Sequence< rtl::OUString >& rSmartTagTypes,
3420 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3421 uno::Reference<text::XTextRange>& rRange )
3423 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3424 return;
3426 SwPaM* pCrsr = GetCrsr();
3427 SwPosition aPos( *pCrsr->GetPoint() );
3428 Point aPt( rPt );
3429 SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3430 SwSpecialPos aSpecialPos;
3431 eTmpState.pSpecialPos = &aSpecialPos;
3432 SwTxtNode *pNode;
3433 const SwWrongList *pSmartTagList;
3435 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3436 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3437 0 != (pSmartTagList = pNode->GetSmartTags()) &&
3438 !pNode->IsInProtectSect() )
3440 xub_StrLen nCurrent = aPos.nContent.GetIndex();
3441 xub_StrLen nBegin = nCurrent;
3442 xub_StrLen nLen = 1;
3444 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3446 const USHORT nIndex = pSmartTagList->GetWrongPos( nBegin );
3447 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3448 if ( pSubList )
3450 pSmartTagList = pSubList;
3451 nCurrent = eTmpState.pSpecialPos->nCharOfst;
3454 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3455 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3457 // get smarttag word
3458 String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
3460 //save the start and end positons of the line and the starting point
3461 Push();
3462 LeftMargin();
3463 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3464 RightMargin();
3465 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3466 Pop(FALSE);
3468 // make sure the selection build later from the
3469 // data below does not include footnotes and other
3470 // "in word" character to the left and right in order
3471 // to preserve those. Therefore count those "in words"
3472 // in order to modify the selection accordingly.
3473 const sal_Unicode* pChar = aText.GetBuffer();
3474 xub_StrLen nLeft = 0;
3475 while (pChar && *pChar++ == CH_TXTATR_INWORD)
3476 ++nLeft;
3477 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
3478 xub_StrLen nRight = 0;
3479 while (pChar && *pChar-- == CH_TXTATR_INWORD)
3480 ++nRight;
3482 aPos.nContent = nBegin + nLeft;
3483 pCrsr = GetCrsr();
3484 *pCrsr->GetPoint() = aPos;
3485 pCrsr->SetMark();
3486 ExtendSelection( sal_True, nLen - nLeft - nRight );
3487 //no determine the rectangle in the current line
3488 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3489 //take one less than the line end - otherwise the next line would be calculated
3490 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
3491 Push();
3492 pCrsr->DeleteMark();
3493 SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3494 rContent = nWordStart;
3495 SwRect aStartRect;
3496 SwCrsrMoveState aState;
3497 aState.bRealWidth = TRUE;
3498 SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3499 SwCntntFrm *pCntntFrame = pCntntNode->GetFrm( &rPt, pCrsr->GetPoint(), FALSE);
3501 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3502 rContent = nWordEnd;
3503 SwRect aEndRect;
3504 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3505 rSelectRect = aStartRect.Union( aEndRect );
3506 Pop(FALSE);