1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: select.cxx,v $
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"
36 #include <hintids.hxx>
37 #include <sfx2/bindings.hxx>
38 #include <svtools/eitem.hxx>
39 #include <svtools/macitem.hxx>
40 #include <unotools/charclass.hxx>
41 #include <svx/scripttypeitem.hxx>
57 #include <swundo.hxx> // fuer Undo-Ids
58 #include <swevent.hxx>
59 #include <swdtflvr.hxx>
60 #include <crsskip.hxx>
62 #if OSL_DEBUG_LEVEL > 1
66 namespace com
{ namespace sun
{ namespace star
{ namespace util
{
70 using namespace ::com::sun::star::util
;
73 static long nStartDragX
= 0, nStartDragY
= 0;
74 static BOOL bStartDrag
= FALSE
;
76 void SwWrtShell::Invalidate()
78 // to avoid making the slot volatile, invalidate it everytime if something could have been changed
79 // this is still much cheaper than asking for the state every 200 ms (and avoid background processing)
80 GetView().GetViewFrame()->GetBindings().Invalidate( FN_STAT_SELMODE
);
83 BOOL
SwWrtShell::SelNearestWrd()
86 if( !IsInWrd() && !IsEndWrd() && !IsSttWrd() )
89 Left(CRSR_SKIP_CELLS
, FALSE
, 1, FALSE
);
95 BOOL
SwWrtShell::SelWrd(const Point
*pPt
, BOOL
)
101 bRet
= SwCrsrShell::SelectWord( pPt
);
113 void SwWrtShell::SelSentence(const Point
*pPt
, BOOL
)
118 SwCrsrShell::GoStartSentence();
120 SwCrsrShell::GoEndSentence();
126 bSelWrd
= FALSE
; // SelWord abschalten, sonst geht kein SelLine weiter
129 void SwWrtShell::SelPara(const Point
*pPt
, BOOL
)
134 SwCrsrShell::MovePara( fnParaCurr
, fnParaStart
);
136 SwCrsrShell::MovePara( fnParaCurr
, fnParaEnd
);
142 bSelWrd
= FALSE
; // SelWord abschalten, sonst geht kein SelLine weiter
146 long SwWrtShell::SelAll()
148 const BOOL bLockedView
= IsViewLocked();
154 BOOL bMoveTable
= FALSE
;
155 SwPosition
*pStartPos
= 0;
156 SwPosition
*pEndPos
= 0;
157 SwShellCrsr
* pTmpCrsr
= 0;
158 if( !HasWholeTabSelection() )
160 if ( IsSelection() && IsCrsrPtAtEnd() )
162 pTmpCrsr
= getShellCrsr( false );
165 pStartPos
= new SwPosition( *pTmpCrsr
->GetPoint() );
166 pEndPos
= new SwPosition( *pTmpCrsr
->GetMark() );
169 BOOL bIsFullSel
= !MoveSection( fnSectionCurr
, fnSectionStart
);
171 bIsFullSel
&= !MoveSection( fnSectionCurr
, fnSectionEnd
);
173 GoStart(TRUE
, &bMoveTable
, FALSE
, !bIsFullSel
);
181 GoEnd(TRUE
, &bMoveTable
);
184 pTmpCrsr
= getShellCrsr( false );
187 // Some special handling for sections (e.g. TOC) at the beginning of the document body
188 // to avoid the selection of the first section
189 // if the last selection was behind the first section or
190 // if the last selection was already the first section
191 // In this both cases we select to the end of document
192 if( *pTmpCrsr
->GetPoint() < *pEndPos
||
193 ( *pStartPos
== *pTmpCrsr
->GetMark() &&
194 *pEndPos
== *pTmpCrsr
->GetPoint() ) )
195 SwCrsrShell::SttEndDoc(FALSE
);
202 LockView( bLockedView
);
206 /*------------------------------------------------------------------------
207 Beschreibung: Textsuche
208 ------------------------------------------------------------------------*/
211 ULONG
SwWrtShell::SearchPattern( const SearchOptions
& rSearchOpt
, BOOL bSearchInNotes
,
212 SwDocPositions eStt
, SwDocPositions eEnd
,
213 FindRanges eFlags
, int bReplace
)
215 // keine Erweiterung bestehender Selektionen
216 if(!(eFlags
& FND_IN_SEL
))
218 BOOL bCancel
= FALSE
;
219 ULONG nRet
= Find( rSearchOpt
, bSearchInNotes
, eStt
, eEnd
, bCancel
, eFlags
, bReplace
);
227 /*------------------------------------------------------------------------
228 Beschreibung: Suche nach Vorlagen
229 ------------------------------------------------------------------------*/
233 ULONG
SwWrtShell::SearchTempl( const String
&rTempl
,
234 SwDocPositions eStt
, SwDocPositions eEnd
,
235 FindRanges eFlags
, const String
* pReplTempl
)
237 // keine Erweiterung bestehender Selektionen
238 if(!(eFlags
& FND_IN_SEL
))
240 SwTxtFmtColl
*pColl
= GetParaStyle(rTempl
, SwWrtShell::GETSTYLE_CREATESOME
);
241 SwTxtFmtColl
*pReplaceColl
= 0;
243 pReplaceColl
= GetParaStyle(*pReplTempl
, SwWrtShell::GETSTYLE_CREATESOME
);
245 BOOL bCancel
= FALSE
;
246 ULONG nRet
= Find(pColl
? *pColl
: GetDfltTxtFmtColl(),
247 eStt
,eEnd
, bCancel
, eFlags
, pReplaceColl
);
256 // Suche nach Attributen ----------------------------------------------------
260 ULONG
SwWrtShell::SearchAttr( const SfxItemSet
& rFindSet
, BOOL bNoColls
,
261 SwDocPositions eStart
, SwDocPositions eEnde
,
262 FindRanges eFlags
, const SearchOptions
* pSearchOpt
,
263 const SfxItemSet
* pReplaceSet
)
265 // Keine Erweiterung bestehender Selektionen
266 if (!(eFlags
& FND_IN_SEL
))
270 BOOL bCancel
= FALSE
;
271 ULONG nRet
= Find( rFindSet
, bNoColls
, eStart
, eEnde
, bCancel
, eFlags
, pSearchOpt
, pReplaceSet
);
281 // ---------- Selektionsmodi ----------
285 void SwWrtShell::PushMode()
287 pModeStack
= new ModeStack( pModeStack
, bIns
, bExtMode
, bAddMode
, bBlockMode
);
292 void SwWrtShell::PopMode()
294 if ( 0 == pModeStack
)
297 if ( bExtMode
&& !pModeStack
->bExt
)
299 if ( bAddMode
&& !pModeStack
->bAdd
)
301 if ( bBlockMode
&& !pModeStack
->bBlock
)
303 bIns
= pModeStack
->bIns
;
305 ModeStack
*pTmp
= pModeStack
->pNext
;
311 * Zwei Methoden fuer das Cursorsetzen; die erste mappt auf die
312 * gleichnamige Methoden an der CursorShell, die zweite hebt
313 * zuerst alle Selektionen auf.
318 long SwWrtShell::SetCrsr(const Point
*pPt
, BOOL bTextOnly
)
321 * eine gfs. bestehende Selektion an der Position des
322 * Mausklicks aufheben
324 if(!IsInSelect() && ChgCurrPam(*pPt
)) {
328 return SwCrsrShell::SetCrsr(*pPt
, bTextOnly
);
332 long SwWrtShell::SetCrsrKillSel(const Point
*pPt
, BOOL bTextOnly
)
335 ResetSelect(pPt
,FALSE
);
336 return SwCrsrShell::SetCrsr(*pPt
, bTextOnly
);
341 void SwWrtShell::UnSelectFrm()
343 // Rahmenselektion aufheben mit garantiert ungueltiger Position
344 Point
aPt(LONG_MIN
, LONG_MIN
);
346 GetView().LeaveDrawCreate();
347 SwTransferable::ClearSelection( *this );
351 * Aufheben aller Selektionen
356 long SwWrtShell::ResetSelect(const Point
*,BOOL
)
365 /* ACT_KONTEXT() macht eine Action auf -
366 um im Basicablauf keine Probleme mit der
367 Shellumschaltung zu bekommen, darf
368 GetChgLnk().Call() erst nach
369 EndAction() gerufen werden.
373 bSelWrd
= bSelLn
= FALSE
;
376 fnKillSel
= &SwWrtShell::Ignore
;
377 fnSetCrsr
= &SwWrtShell::SetCrsr
;
380 * nach dem Aufheben aller Selektionen koennte ein Update der
381 * Attr-Controls notwendig sein.
383 GetChgLnk().Call(this);
386 SwTransferable::ClearSelection( *this );
395 long SwWrtShell::Ignore(const Point
*, BOOL
) {
400 * Start eines Selektionsvorganges.
405 void SwWrtShell::SttSelect()
413 SwShellCrsr
* pTmp
= getShellCrsr( true );
414 if( !pTmp
->HasMark() )
417 fnKillSel
= &SwWrtShell::Ignore
;
418 fnSetCrsr
= &SwWrtShell::SetCrsr
;
421 SwTransferable::CreateSelection( *this );
424 * Ende eines Selektionsvorganges.
429 void SwWrtShell::EndSelect()
431 if(!bInSelect
|| bExtMode
)
434 (this->*fnLeaveSelect
)(0,FALSE
);
436 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
437 fnKillSel
= &SwWrtShell::ResetSelect
;
440 /* Methode, um eine bestehende wortweise oder zeilenweise Selektion
444 inline BOOL
operator<(const Point
&rP1
,const Point
&rP2
)
446 return rP1
.Y() < rP2
.Y() || (rP1
.Y() == rP2
.Y() && rP1
.X() < rP2
.X());
451 long SwWrtShell::ExtSelWrd(const Point
*pPt
, BOOL
)
457 // Bug 66823: actual crsr has in additional mode no selection?
458 // Then destroy the actual an go to prev, this will be expand
459 if( !HasMark() && GoPrevCrsr() )
461 BOOL bHasMark
= HasMark(); // thats wrong!
470 // check the direction of the selection with the new point
471 BOOL bRet
= FALSE
, bMoveCrsr
= TRUE
, bToTop
= FALSE
;
472 SwCrsrShell::SelectWord( &aStart
); // select the startword
473 SwCrsrShell::Push(); // save the cursor
474 SwCrsrShell::SetCrsr( *pPt
); // and check the direction
476 switch( SwCrsrShell::CompareCursor( StackMkCurrPt
))
478 case -1: bToTop
= FALSE
; break;
479 case 1: bToTop
= TRUE
; break;
480 default: bMoveCrsr
= FALSE
; break;
483 SwCrsrShell::Pop( FALSE
); // retore the saved cursor
487 // select to Top but cursor select to Bottom? or
488 // select to Bottom but cursor select to Top? --> swap the cursor
492 SwCrsrShell::Push(); // save cur cursor
493 if( SwCrsrShell::SelectWord( pPt
)) // select the current word
502 SwCrsrShell::Pop( FALSE
);
513 long SwWrtShell::ExtSelLn(const Point
*pPt
, BOOL
)
516 SwCrsrShell::SetCrsr(*pPt
);
520 // Bug 66823: actual crsr has in additional mode no selection?
521 // Then destroy the actual an go to prev, this will be expand
522 if( !HasMark() && GoPrevCrsr() )
524 BOOL bHasMark
= HasMark(); // thats wrong!
533 // ggfs. den Mark der Selektion anpassen
534 BOOL bToTop
= !IsCrsrPtAtEnd();
537 // der "Mark" muss am Zeilenende/-anfang stehen
538 if( bToTop
? !IsEndSentence() : !IsStartSentence() )
543 SwCrsrShell::Right(1,CRSR_SKIP_CHARS
);
544 SwCrsrShell::GoEndSentence();
547 SwCrsrShell::GoStartSentence();
551 return bToTop
? SwCrsrShell::GoStartSentence() : SwCrsrShell::GoEndSentence();
556 * zurueck in den Standard Mode: kein Mode, keine Selektionen.
559 void SwWrtShell::EnterStdMode()
575 /* ACT_KONTEXT() opens and action which has to be
576 closed prior to the call of
581 bSelWrd
= bSelLn
= FALSE
;
582 if( !IsRetainSelection() )
585 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
586 fnKillSel
= &SwWrtShell::ResetSelect
;
590 SwTransferable::ClearSelection( *this );
599 void SwWrtShell::EnterExtMode()
615 void SwWrtShell::LeaveExtMode()
621 * Ende einer Selektion; falls die Selektion leer ist,
627 long SwWrtShell::SttLeaveSelect(const Point
*, BOOL
)
629 if(SwCrsrShell::HasSelection() && !IsSelTblCells() && bClearMark
) {
632 // if( IsSelTblCells() ) aSelTblLink.Call(this);
637 * Verlassen des Selektionsmodus in Additional Mode
642 long SwWrtShell::AddLeaveSelect(const Point
*, BOOL
)
644 if(IsTableMode()) LeaveAddMode();
645 else if(SwCrsrShell::HasSelection())
655 void SwWrtShell::EnterAddMode()
657 if(IsTableMode()) return;
660 fnLeaveSelect
= &SwWrtShell::AddLeaveSelect
;
661 fnKillSel
= &SwWrtShell::Ignore
;
662 fnSetCrsr
= &SwWrtShell::SetCrsr
;
666 if(SwCrsrShell::HasSelection())
673 void SwWrtShell::LeaveAddMode()
675 fnLeaveSelect
= &SwWrtShell::SttLeaveSelect
;
676 fnKillSel
= &SwWrtShell::ResetSelect
;
677 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
686 void SwWrtShell::EnterBlockMode()
697 void SwWrtShell::LeaveBlockMode()
709 void SwWrtShell::SetInsMode( BOOL bOn
)
712 SwCrsrShell::SetOverwriteCrsr( !bIns
);
713 const SfxBoolItem
aTmp( SID_ATTR_INSERT
, bIns
);
714 GetView().GetViewFrame()->GetBindings().SetState( aTmp
);
719 //Overwrite mode is incompatible with red-lining
720 void SwWrtShell::SetRedlineModeAndCheckInsMode( USHORT eMode
)
722 SetRedlineMode( eMode
);
732 long SwWrtShell::BeginFrmDrag(const Point
*pPt
, BOOL
)
734 fnDrag
= &SwFEShell::Drag
;
737 Point
aTmp( nStartDragX
, nStartDragY
);
738 SwFEShell::BeginDrag( &aTmp
, FALSE
);
741 SwFEShell::BeginDrag( pPt
, FALSE
);
747 void SwWrtShell::EnterSelFrmMode(const Point
*pPos
)
751 nStartDragX
= pPos
->X();
752 nStartDragY
= pPos
->Y();
755 bNoEdit
= bLayoutMode
= TRUE
;
758 // gleicher Aufruf von BeginDrag an der SwFEShell
759 fnDrag
= &SwWrtShell::BeginFrmDrag
;
760 fnEndDrag
= &SwWrtShell::UpdateLayoutFrm
;
761 SwBaseShell::SetFrmMode( FLY_DRAG_START
, this );
767 void SwWrtShell::LeaveSelFrmMode()
769 fnDrag
= &SwWrtShell::BeginDrag
;
770 fnEndDrag
= &SwWrtShell::EndDrag
;
774 SwBaseShell::SetFrmMode( FLY_DRAG_END
, this );
777 /*------------------------------------------------------------------------
778 Beschreibung: Rahmengebundenes Macro ausfuehren
779 ------------------------------------------------------------------------*/
783 IMPL_LINK( SwWrtShell
, ExecFlyMac
, void *, pFlyFmt
)
785 const SwFrmFmt
*pFmt
= pFlyFmt
? (SwFrmFmt
*)pFlyFmt
: GetFlyFrmFmt();
786 ASSERT(pFmt
, kein FrameFormat
.);
787 const SvxMacroItem
&rFmtMac
= pFmt
->GetMacro();
789 if(rFmtMac
.HasMacro(SW_EVENT_OBJECT_SELECT
))
791 const SvxMacro
&rMac
= rFmtMac
.GetMacro(SW_EVENT_OBJECT_SELECT
);
792 if( IsFrmSelected() )
802 long SwWrtShell::UpdateLayoutFrm(const Point
*pPt
, BOOL
)
805 SwFEShell::EndDrag( pPt
, FALSE
);
806 fnDrag
= &SwWrtShell::BeginFrmDrag
;
811 * Handler fuer das Togglen der Modi. Liefern alten Mode zurueck.
816 long SwWrtShell::ToggleAddMode()
818 bAddMode
? LeaveAddMode(): EnterAddMode();
824 long SwWrtShell::ToggleBlockMode()
826 bBlockMode
? LeaveBlockMode(): EnterBlockMode();
832 long SwWrtShell::ToggleExtMode()
834 bExtMode
? LeaveExtMode() : EnterExtMode();
839 * Draggen im Standard Modus (Selektieren von Inhalt)
844 long SwWrtShell::BeginDrag(const Point
* /*pPt*/, BOOL
)
849 if( !IsCrsrPtAtEnd() )
852 fnDrag
= &SwWrtShell::ExtSelWrd
;
853 fnSetCrsr
= &SwWrtShell::Ignore
;
858 fnDrag
= &SwWrtShell::ExtSelLn
;
859 fnSetCrsr
= &SwWrtShell::Ignore
;
863 fnDrag
= &SwWrtShell::Drag
;
872 long SwWrtShell::Drag(const Point
*, BOOL
)
874 if( IsSelTblCells() )
875 aSelTblLink
.Call(this);
882 long SwWrtShell::EndDrag(const Point
* /*pPt*/, BOOL
)
884 fnDrag
= &SwWrtShell::BeginDrag
;
888 if( IsSelTblCells() )
889 aSelTblLink
.Call(this);
894 // --> FME 2004-07-30 #i32329# Enhanced table selection
895 BOOL
SwWrtShell::SelectTableRowCol( const Point
& rPt
, const Point
* pEnd
, bool bRowDrag
)
899 if(SelTblRowCol( rPt
, pEnd
, bRowDrag
))
901 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
902 fnKillSel
= &SwWrtShell::ResetSelect
;
909 /*------------------------------------------------------------------------
910 Beschreibung: Selektion einer Tabellenzeile / Spalte
911 ------------------------------------------------------------------------*/
913 BOOL
SwWrtShell::SelectTableRow()
917 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
918 fnKillSel
= &SwWrtShell::ResetSelect
;
926 BOOL
SwWrtShell::SelectTableCol()
930 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
931 fnKillSel
= &SwWrtShell::ResetSelect
;
937 BOOL
SwWrtShell::SelectTableCell()
941 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
942 fnKillSel
= &SwWrtShell::ResetSelect
;
947 /*------------------------------------------------------------------------
948 Beschreibung: Prueft, ob eine Wortselektion vorliegt.
949 Gemaess den Regeln fuer intelligentes Cut / Paste
950 werden umgebende Spaces rausgeschnitten.
951 Return: Liefert Art der Wortselektion zurueck.
952 ------------------------------------------------------------------------*/
956 int SwWrtShell::IntelligentCut(int nSelection
, BOOL bCut
)
958 // kein intelligentes Drag and Drop bei Mehrfachselektion
959 // es existieren mehrere Cursor, da ein zweiter bereits
960 // an die Zielposition gesetzt wurde
961 if( IsAddMode() || !(nSelection
& nsSelectionType::SEL_TXT
) )
965 CharClass
& rCC
= GetAppCharClass();
967 // wenn das erste und das letzte Zeichen kein Wortzeichen ist,
968 // ist kein Wort selektiert.
969 sal_Unicode cPrev
= GetChar(FALSE
);
970 sal_Unicode cNext
= GetChar(TRUE
, -1);
971 if( !cPrev
|| !cNext
||
972 !rCC
.isLetterNumeric( ( sTxt
= cPrev
), 0 ) ||
973 !rCC
.isLetterNumeric( ( sTxt
= cNext
), 0 ) )
976 cPrev
= GetChar(FALSE
, -1);
977 cNext
= GetChar(TRUE
);
980 // ist ein Wort selektiert?
981 if(!cWord
&& cPrev
&& cNext
&&
982 CH_TXTATR_BREAKWORD
!= cPrev
&& CH_TXTATR_INWORD
!= cPrev
&&
983 CH_TXTATR_BREAKWORD
!= cNext
&& CH_TXTATR_INWORD
!= cNext
&&
984 !rCC
.isLetterNumeric( ( sTxt
= cPrev
), 0 ) &&
985 !rCC
.isLetterNumeric( ( sTxt
= cNext
), 0 ) )
986 cWord
= WORD_NO_SPACE
;
988 if(cWord
== WORD_NO_SPACE
&& ' ' == cPrev
)
990 cWord
= WORD_SPACE_BEFORE
;
991 // Space davor loeschen
999 SwCrsrShell::Left(1,CRSR_SKIP_CHARS
);
1000 SwFEShell::Delete();
1004 else if(cWord
== WORD_NO_SPACE
&& cNext
== ' ')
1006 cWord
= WORD_SPACE_AFTER
;
1007 // Space dahinter loeschen
1010 if(!IsCrsrPtAtEnd()) SwapPam();
1013 SwCrsrShell::Right(1,CRSR_SKIP_CHARS
);
1014 SwFEShell::Delete();
1023 // jump to the next / previous hyperlink - inside text and also
1025 BOOL
SwWrtShell::SelectNextPrevHyperlink( BOOL bNext
)
1028 BOOL bRet
= SwCrsrShell::SelectNxtPrvHyperlink( bNext
);
1031 // will we have this feature?
1037 bRet
= SwCrsrShell::SelectNxtPrvHyperlink( bNext
);
1041 BOOL bCreateXSelection
= FALSE
;
1042 const BOOL bFrmSelected
= IsFrmSelected() || IsObjSelected();
1048 // Funktionspointer fuer das Aufheben der Selektion setzen
1049 // bei Cursor setzen
1050 fnKillSel
= &SwWrtShell::ResetSelect
;
1051 fnSetCrsr
= &SwWrtShell::SetCrsrKillSel
;
1052 bCreateXSelection
= TRUE
;
1054 else if( bFrmSelected
)
1057 bCreateXSelection
= TRUE
;
1059 else if( (CNT_GRF
| CNT_OLE
) & GetCntType() )
1061 SelectObj( GetCharRect().Pos() );
1063 bCreateXSelection
= TRUE
;
1066 if( bCreateXSelection
)
1067 SwTransferable::CreateSelection( *this );
1073 /* fuer den Erhalt der Selektion wird nach SetMark() der Cursor
1074 * nach links bewegt, damit er durch das Einfuegen von Text nicht
1075 * verschoben wird. Da auf der CORE-Seite am aktuellen Cursor
1076 * eine bestehende Selektion aufgehoben wird, wird der Cursor auf
1077 * den Stack gepushed. Nach dem Verschieben werden sie wieder
1078 * zusammengefasst. */