android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / uibase / wrtsh / select.cxx
bloba23c1ec6a830727c68103dc89e76f3a072674e7b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <limits.h>
21 #include <hintids.hxx>
22 #include <sfx2/bindings.hxx>
23 #include <sfx2/viewfrm.hxx>
24 #include <svl/eitem.hxx>
25 #include <svl/macitem.hxx>
26 #include <unotools/charclass.hxx>
27 #include <sfx2/event.hxx>
28 #include <osl/diagnose.h>
29 #include <cmdid.h>
30 #include <view.hxx>
31 #include <basesh.hxx>
32 #include <wrtsh.hxx>
33 #include <frmatr.hxx>
34 #include <mdiexp.hxx>
35 #include <fmtcol.hxx>
36 #include <frmfmt.hxx>
37 #include <swdtflvr.hxx>
38 #include <doc.hxx>
39 #include <wordcountdialog.hxx>
40 #include <memory>
41 #include <vcl/uitest/logger.hxx>
42 #include <vcl/uitest/eventdescription.hxx>
44 namespace com::sun::star::util {
45 struct SearchOptions2;
48 using namespace ::com::sun::star::util;
50 static tools::Long nStartDragX = 0, nStartDragY = 0;
51 static bool bStartDrag = false;
53 void SwWrtShell::Invalidate()
55 // to avoid making the slot volatile, invalidate it every time if something could have been changed
56 // this is still much cheaper than asking for the state every 200 ms (and avoid background processing)
57 GetView().GetViewFrame().GetBindings().Invalidate( FN_STAT_SELMODE );
58 GetView().GetViewFrame().GetBindings().Update(FN_STAT_SELMODE); // make selection mode control icon update immediately
59 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
60 if (pWrdCnt)
61 pWrdCnt->UpdateCounts();
64 bool SwWrtShell::SelNearestWrd()
66 SwMvContext aMvContext(this);
67 if( !IsInWord() && !IsEndWrd() && !IsStartWord() )
68 PrvWrd();
69 if( IsEndWrd() )
70 Left(SwCursorSkipMode::Cells, false, 1, false );
71 return SelWrd();
74 bool SwWrtShell::SelWrd(const Point *pPt )
76 bool bRet;
78 SwMvContext aMvContext(this);
79 SttSelect();
80 bRet = SwCursorShell::SelectWord( pPt );
82 EndSelect();
83 if( bRet )
85 m_bSelWrd = true;
86 if(pPt)
87 m_aStart = *pPt;
89 return bRet;
92 void SwWrtShell::SelSentence(const Point *pPt )
95 SwMvContext aMvContext(this);
96 ClearMark();
97 SwCursorShell::GoStartSentence();
98 SttSelect();
99 SwCursorShell::GoEndSentence();
101 EndSelect();
102 if(pPt)
103 m_aStart = *pPt;
104 m_bSelLn = true;
105 m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on
108 void SwWrtShell::SelPara(const Point *pPt )
111 SwMvContext aMvContext(this);
112 ClearMark();
113 SwCursorShell::MovePara( GoCurrPara, fnParaStart );
114 SttSelect();
115 SwCursorShell::MovePara( GoCurrPara, fnParaEnd );
117 EndSelect();
118 if(pPt)
119 m_aStart = *pPt;
120 m_bSelLn = false;
121 m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on
124 void SwWrtShell::SelAll()
126 const bool bLockedView = IsViewLocked();
127 LockView( true );
129 if(m_bBlockMode)
130 LeaveBlockMode();
131 SwMvContext aMvContext(this);
132 bool bMoveTable = false;
133 std::optional<SwPosition> oStartPos;
134 std::optional<SwPosition> oEndPos;
135 SwShellCursor* pTmpCursor = nullptr;
137 // Query these early, before we move the cursor.
138 bool bHasWholeTabSelection = HasWholeTabSelection();
139 bool bIsCursorInTable = IsCursorInTable();
141 if (!bHasWholeTabSelection
142 && ( !bIsCursorInTable
143 || getShellCursor(false)->GetMarkNode().FindTableNode() == nullptr
144 || !ExtendedSelectedAll())) // ESA inside table -> else branch
146 if ( IsSelection() && IsCursorPtAtEnd() )
147 SwapPam();
148 pTmpCursor = getShellCursor( false );
149 if( pTmpCursor )
151 oStartPos.emplace( *pTmpCursor->GetPoint() );
152 oEndPos.emplace( *pTmpCursor->GetMark() );
154 Push();
155 bool bIsFullSel = !MoveSection( GoCurrSection, fnSectionStart);
156 SwapPam();
157 bIsFullSel &= !MoveSection( GoCurrSection, fnSectionEnd);
158 Pop(SwCursorShell::PopMode::DeleteCurrent);
159 GoStart(true, &bMoveTable, false, !bIsFullSel);
160 SttSelect();
161 GoEnd(true, &bMoveTable);
163 else
165 if (MoveOutOfTable())
166 { // select outer text
167 EnterStdMode(); // delete m_pTableCursor
168 // GoStart(true, &bMoveTable, false, true);
169 MoveSection(GoCurrSection, fnSectionStart); // don't move into prev table
170 SttSelect();
171 MoveSection(GoCurrSection, fnSectionEnd); // don't move to different cell
173 else
175 TrySelectOuterTable();
179 bool bNeedsExtendedSelectAll = StartsWith_() != StartsWith::None;
181 // the GoEnd() could have created a table selection, if so avoid ESA.
182 if (bNeedsExtendedSelectAll && bIsCursorInTable)
184 bNeedsExtendedSelectAll = !HasWholeTabSelection();
187 if (bNeedsExtendedSelectAll)
189 ExtendedSelectAll(/*bFootnotes =*/ false);
192 SwDoc *pDoc = GetDoc();
193 if ( pDoc )
195 pDoc->SetPrepareSelAll();
198 if( oStartPos )
200 pTmpCursor = getShellCursor( false );
201 if( pTmpCursor )
203 // Some special handling for sections (e.g. TOC) at the beginning of the document body
204 // to avoid the selection of the first section
205 // if the last selection was behind the first section or
206 // if the last selection was already the first section
207 // In this both cases we select to the end of document
208 if( ( *pTmpCursor->GetPoint() < *oEndPos ||
209 ( *oStartPos == *pTmpCursor->GetMark() &&
210 *oEndPos == *pTmpCursor->GetPoint() ) ) && !bNeedsExtendedSelectAll)
211 SwCursorShell::SttEndDoc(false);
215 EndSelect();
216 LockView( bLockedView );
219 // Description: Text search
221 sal_Int32 SwWrtShell::SearchPattern( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
222 SwDocPositions eStt, SwDocPositions eEnd,
223 FindRanges eFlags, bool bReplace )
225 // no enhancement of existing selections
226 if(!(eFlags & FindRanges::InSel))
227 ClearMark();
228 bool bCancel = false;
229 sal_Int32 nRet = Find_Text(rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace);
230 if(bCancel)
232 Undo();
233 nRet = SAL_MAX_INT32;
235 return nRet;
238 // Description: search for templates
240 sal_Int32 SwWrtShell::SearchTempl( const OUString &rTempl,
241 SwDocPositions eStt, SwDocPositions eEnd,
242 FindRanges eFlags, const OUString* pReplTempl )
244 // no enhancement of existing selections
245 if(!(eFlags & FindRanges::InSel))
246 ClearMark();
247 SwTextFormatColl *pColl = GetParaStyle(rTempl, SwWrtShell::GETSTYLE_CREATESOME);
248 SwTextFormatColl *pReplaceColl = nullptr;
249 if( pReplTempl )
250 pReplaceColl = GetParaStyle(*pReplTempl, SwWrtShell::GETSTYLE_CREATESOME );
252 bool bCancel = false;
253 sal_Int32 nRet = FindFormat(pColl ? *pColl : GetDfltTextFormatColl(),
254 eStt,eEnd, bCancel, eFlags, pReplaceColl);
255 if(bCancel)
257 Undo();
258 nRet = SAL_MAX_INT32;
260 return nRet;
263 // search for attributes
265 sal_Int32 SwWrtShell::SearchAttr( const SfxItemSet& rFindSet, bool bNoColls,
266 SwDocPositions eStart, SwDocPositions eEnd,
267 FindRanges eFlags, const i18nutil::SearchOptions2* pSearchOpt,
268 const SfxItemSet* pReplaceSet )
270 // no enhancement of existing selections
271 if (!(eFlags & FindRanges::InSel))
272 ClearMark();
274 // Searching
275 bool bCancel = false;
276 sal_Int32 nRet = FindAttrs(rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet);
278 if(bCancel)
280 Undo();
281 nRet = SAL_MAX_INT32;
283 return nRet;
286 // Selection modes
288 void SwWrtShell::PushMode()
290 m_pModeStack = new ModeStack( m_pModeStack, m_bIns, m_bExtMode, m_bAddMode, m_bBlockMode );
293 void SwWrtShell::PopMode()
295 if ( nullptr == m_pModeStack )
296 return;
298 if ( m_bExtMode && !m_pModeStack->bExt )
299 LeaveExtMode();
300 if ( m_bAddMode && !m_pModeStack->bAdd )
301 LeaveAddMode();
302 if ( m_bBlockMode && !m_pModeStack->bBlock )
303 LeaveBlockMode();
304 m_bIns = m_pModeStack->bIns;
306 m_pModeStack = std::move(m_pModeStack->pNext);
309 // Two methods for setting cursors: the first maps at the
310 // eponymous methods in the CursorShell, the second removes
311 // all selections at first.
313 tools::Long SwWrtShell::SetCursor(const Point *pPt, bool bTextOnly)
315 // Remove a possibly present selection at the position
316 // of the mouseclick
318 if(!IsInSelect() && TestCurrPam(*pPt)) {
319 ClearMark();
322 return SwCursorShell::SetCursor(*pPt, bTextOnly);
325 tools::Long SwWrtShell::SetCursorKillSel(const Point *pPt, bool bTextOnly )
327 SwActContext aActContext(this);
328 ResetSelect(pPt,false);
329 return SwCursorShell::SetCursor(*pPt, bTextOnly);
332 void SwWrtShell::UnSelectFrame()
334 // Remove Frame selection with guaranteed invalid position
335 Point aPt(LONG_MIN, LONG_MIN);
336 SelectObj(aPt);
337 SwTransferable::ClearSelection( *this );
340 // Remove of all selections
342 tools::Long SwWrtShell::ResetSelect(const Point *,bool)
344 if(IsSelFrameMode())
346 UnSelectFrame();
347 LeaveSelFrameMode();
349 else
351 // SwActContext opens an Action -
352 // to avoid problems in the basic process with the
353 // shell switching, GetChgLnk().Call() may be called
354 // after EndAction().
356 SwActContext aActContext(this);
357 m_bSelWrd = m_bSelLn = false;
358 KillPams();
359 ClearMark();
360 m_fnKillSel = &SwWrtShell::Ignore;
361 m_fnSetCursor = &SwWrtShell::SetCursor;
364 // After canceling of all selections an update of Attr-Controls
365 // could be necessary.
366 GetChgLnk().Call(nullptr);
368 if ( GetEnhancedTableSelection() != SwTable::SEARCH_NONE )
369 UnsetEnhancedTableSelection();
371 Invalidate();
372 SwTransferable::ClearSelection( *this );
373 return 1;
376 bool SwWrtShell::IsSplitVerticalByDefault() const
378 return GetDoc()->IsSplitVerticalByDefault();
381 void SwWrtShell::SetSplitVerticalByDefault(bool value)
383 GetDoc()->SetSplitVerticalByDefault(value);
386 // Do nothing
388 tools::Long SwWrtShell::Ignore(const Point *, bool ) {
389 return 1;
392 // Begin of a selection process.
394 void SwWrtShell::SttSelect()
396 if(m_bInSelect)
397 return;
398 if(!HasMark())
399 SetMark();
400 if( m_bBlockMode )
402 SwShellCursor* pTmp = getShellCursor( true );
403 if( !pTmp->HasMark() )
404 pTmp->SetMark();
406 m_fnKillSel = &SwWrtShell::Ignore;
407 m_fnSetCursor = &SwWrtShell::SetCursor;
408 m_bInSelect = true;
409 Invalidate();
410 SwTransferable::CreateSelection( *this );
413 namespace {
415 void collectUIInformation(SwShellCursor* pCursor)
417 EventDescription aDescription;
418 OUString aSelStart = OUString::number(pCursor->Start()->GetContentIndex());
419 OUString aSelEnd = OUString::number(pCursor->End()->GetContentIndex());
421 aDescription.aParameters = {{"START_POS", aSelStart}, {"END_POS", aSelEnd}};
422 aDescription.aAction = "SELECT";
423 aDescription.aID = "writer_edit";
424 aDescription.aKeyWord = "SwEditWinUIObject";
425 aDescription.aParent = "MainWindow";
427 UITestLogger::getInstance().logEvent(aDescription);
432 // End of a selection process.
434 void SwWrtShell::EndSelect()
436 if(m_bInSelect && !m_bExtMode)
438 m_bInSelect = false;
439 if (m_bAddMode)
441 AddLeaveSelect();
443 else
445 SttLeaveSelect();
446 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
447 m_fnKillSel = &SwWrtShell::ResetSelect;
450 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
451 if (pWrdCnt)
452 pWrdCnt->UpdateCounts();
454 collectUIInformation(GetCursor_());
457 void SwWrtShell::ExtSelWrd(const Point *pPt, bool )
459 SwMvContext aMvContext(this);
460 if( IsTableMode() )
461 return;
463 // Bug 66823: actual crsr has in additional mode no selection?
464 // Then destroy the actual and go to prev, this will be expand
465 if( !HasMark() && GoPrevCursor() )
467 bool bHasMark = HasMark(); // that's wrong!
468 GoNextCursor();
469 if( bHasMark )
471 DestroyCursor();
472 GoPrevCursor();
476 // check the direction of the selection with the new point
477 bool bMoveCursor = true, bToTop = false;
478 SwCursorShell::SelectWord( &m_aStart ); // select the startword
479 SwCursorShell::Push(); // save the cursor
480 SwCursorShell::SetCursor( *pPt ); // and check the direction
482 switch( SwCursorShell::CompareCursorStackMkCurrPt())
484 case -1: bToTop = false; break;
485 case 1: bToTop = true; break;
486 default: bMoveCursor = false; break;
489 SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); // restore the saved cursor
491 if( !bMoveCursor )
492 return;
494 // select to Top but cursor select to Bottom? or
495 // select to Bottom but cursor select to Top? --> swap the cursor
496 if( bToTop )
497 SwapPam();
499 SwCursorShell::Push(); // save cur cursor
500 if( SwCursorShell::SelectWord( pPt )) // select the current word
502 if( bToTop )
503 SwapPam();
504 Combine();
506 else
508 SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
509 if( bToTop )
510 SwapPam();
514 void SwWrtShell::ExtSelLn(const Point *pPt, bool )
516 SwMvContext aMvContext(this);
517 SwCursorShell::SetCursor(*pPt);
518 if( IsTableMode() )
519 return;
521 // Bug 66823: actual crsr has in additional mode no selection?
522 // Then destroy the actual and go to prev, this will be expand
523 if( !HasMark() && GoPrevCursor() )
525 bool bHasMark = HasMark(); // that's wrong!
526 GoNextCursor();
527 if( bHasMark )
529 DestroyCursor();
530 GoPrevCursor();
534 // if applicable fit the selection to the "Mark"
535 bool bToTop = !IsCursorPtAtEnd();
536 SwapPam();
538 // The "Mark" has to be at the end or the beginning of the line.
539 if( bToTop ? !IsEndSentence() : !IsStartSentence() )
541 if( bToTop )
543 if( !IsEndPara() )
544 SwCursorShell::Right(1,SwCursorSkipMode::Chars);
545 SwCursorShell::GoEndSentence();
547 else
548 SwCursorShell::GoStartSentence();
550 SwapPam();
552 if (bToTop)
553 SwCursorShell::GoStartSentence();
554 else
555 SwCursorShell::GoEndSentence();
558 // Back into the standard mode: no mode, no selections.
560 void SwWrtShell::EnterStdMode()
562 if(m_bAddMode)
563 LeaveAddMode();
564 if(m_bBlockMode)
565 LeaveBlockMode();
566 m_bBlockMode = false;
567 m_bExtMode = false;
568 m_bInSelect = false;
569 if(IsSelFrameMode())
571 UnSelectFrame();
572 LeaveSelFrameMode();
574 else
576 // SwActContext opens and action which has to be
577 // closed prior to the call of
578 // GetChgLnk().Call()
579 SwActContext aActContext(this);
580 m_bSelWrd = m_bSelLn = false;
581 if( !IsRetainSelection() )
582 KillPams();
583 ClearMark();
584 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
585 m_fnKillSel = &SwWrtShell::ResetSelect;
587 Invalidate();
588 SwTransferable::ClearSelection( *this );
591 // Extended Mode
593 void SwWrtShell::EnterExtMode()
595 if(m_bBlockMode)
597 LeaveBlockMode();
598 KillPams();
599 ClearMark();
601 m_bExtMode = true;
602 m_bAddMode = false;
603 m_bBlockMode = false;
604 SttSelect();
607 void SwWrtShell::LeaveExtMode()
609 m_bExtMode = false;
610 EndSelect();
613 // End of a selection; if the selection is empty,
614 // ClearMark().
616 void SwWrtShell::SttLeaveSelect()
618 if(SwCursorShell::HasSelection() && !IsSelTableCells() && m_bClearMark) {
619 return;
621 ClearMark();
624 // Leaving of the selection mode in additional mode
626 void SwWrtShell::AddLeaveSelect()
628 if(IsTableMode()) LeaveAddMode();
629 else if(SwCursorShell::HasSelection())
630 CreateCursor();
633 // Additional Mode
635 void SwWrtShell::EnterAddMode()
637 if(IsTableMode()) return;
638 if(m_bBlockMode)
639 LeaveBlockMode();
640 m_fnKillSel = &SwWrtShell::Ignore;
641 m_fnSetCursor = &SwWrtShell::SetCursor;
642 m_bAddMode = true;
643 m_bBlockMode = false;
644 m_bExtMode = false;
645 if(SwCursorShell::HasSelection())
646 CreateCursor();
647 Invalidate();
650 void SwWrtShell::LeaveAddMode()
652 m_fnKillSel = &SwWrtShell::ResetSelect;
653 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
654 m_bAddMode = false;
655 Invalidate();
658 // Block Mode
660 void SwWrtShell::EnterBlockMode()
662 m_bBlockMode = false;
663 EnterStdMode();
664 m_bBlockMode = true;
665 CursorToBlockCursor();
666 Invalidate();
669 void SwWrtShell::LeaveBlockMode()
671 m_bBlockMode = false;
672 BlockCursorToCursor();
673 EndSelect();
674 Invalidate();
677 // Insert mode
679 void SwWrtShell::SetInsMode( bool bOn )
681 m_bIns = bOn;
682 SwCursorShell::SetOverwriteCursor( !m_bIns );
683 const SfxBoolItem aTmp( SID_ATTR_INSERT, m_bIns );
684 GetView().GetViewFrame().GetBindings().SetState( aTmp );
685 StartAction();
686 EndAction();
687 Invalidate();
689 //Overwrite mode is incompatible with red-lining
690 void SwWrtShell::SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode )
692 SetRedlineFlags( eMode );
693 if (IsRedlineOn())
694 SetInsMode();
697 // Edit frame
699 void SwWrtShell::BeginFrameDrag(const Point *pPt, bool bIsShift)
701 m_fnDrag = &SwFEShell::Drag;
702 if(bStartDrag)
704 Point aTmp( nStartDragX, nStartDragY );
705 SwFEShell::BeginDrag( &aTmp, bIsShift );
707 else
708 SwFEShell::BeginDrag( pPt, bIsShift );
711 void SwWrtShell::EnterSelFrameMode(const Point *pPos)
713 if(pPos)
715 nStartDragX = pPos->X();
716 nStartDragY = pPos->Y();
717 bStartDrag = true;
719 m_bLayoutMode = true;
720 HideCursor();
722 // equal call of BeginDrag in the SwFEShell
723 m_fnDrag = &SwWrtShell::BeginFrameDrag;
724 m_fnEndDrag = &SwWrtShell::UpdateLayoutFrame;
725 SwBaseShell::SetFrameMode( FLY_DRAG_START, this );
726 Invalidate();
729 void SwWrtShell::LeaveSelFrameMode()
731 m_fnDrag = &SwWrtShell::BeginDrag;
732 m_fnEndDrag = &SwWrtShell::DefaultEndDrag;
733 m_bLayoutMode = false;
734 bStartDrag = false;
735 Edit();
736 SwBaseShell::SetFrameMode( FLY_DRAG_END, this );
737 Invalidate();
740 // Description: execute framebound macro
742 IMPL_LINK( SwWrtShell, ExecFlyMac, const SwFlyFrameFormat*, pFlyFormat, void )
744 const SwFrameFormat *pFormat = pFlyFormat ? static_cast<const SwFrameFormat*>(pFlyFormat) : GetFlyFrameFormat();
745 OSL_ENSURE(pFormat, "no frame format");
746 const SvxMacroItem &rFormatMac = pFormat->GetMacro();
748 if(rFormatMac.HasMacro(SvMacroItemId::SwObjectSelect))
750 const SvxMacro &rMac = rFormatMac.GetMacro(SvMacroItemId::SwObjectSelect);
751 if( IsFrameSelected() )
752 m_bLayoutMode = true;
753 CallChgLnk();
754 ExecMacro( rMac );
758 void SwWrtShell::UpdateLayoutFrame(const Point *, bool )
760 // still a dummy
761 SwFEShell::EndDrag();
762 m_fnDrag = &SwWrtShell::BeginFrameDrag;
765 // Handler for toggling the modes. Returns back the old mode.
767 void SwWrtShell::ToggleAddMode()
769 m_bAddMode ? LeaveAddMode(): EnterAddMode();
770 Invalidate();
773 void SwWrtShell::ToggleBlockMode()
775 m_bBlockMode ? LeaveBlockMode(): EnterBlockMode();
776 Invalidate();
779 void SwWrtShell::ToggleExtMode()
781 m_bExtMode ? LeaveExtMode() : EnterExtMode();
782 Invalidate();
785 // Dragging in standard mode (Selecting of content)
787 void SwWrtShell::BeginDrag(const Point * /*pPt*/, bool )
789 if(m_bSelWrd)
791 m_bInSelect = true;
792 if( !IsCursorPtAtEnd() )
793 SwapPam();
795 m_fnDrag = &SwWrtShell::ExtSelWrd;
796 m_fnSetCursor = &SwWrtShell::Ignore;
798 else if(m_bSelLn)
800 m_bInSelect = true;
801 m_fnDrag = &SwWrtShell::ExtSelLn;
802 m_fnSetCursor = &SwWrtShell::Ignore;
804 else
806 m_fnDrag = &SwWrtShell::DefaultDrag;
807 SttSelect();
811 void SwWrtShell::DefaultDrag(const Point *, bool )
813 if( IsSelTableCells() )
814 m_aSelTableLink.Call(*this);
817 void SwWrtShell::DefaultEndDrag(const Point * /*pPt*/, bool )
819 m_fnDrag = &SwWrtShell::BeginDrag;
820 if( IsExtSel() )
821 LeaveExtSel();
823 if( IsSelTableCells() )
824 m_aSelTableLink.Call(*this);
825 EndSelect();
828 // #i32329# Enhanced table selection
829 bool SwWrtShell::SelectTableRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
831 SwMvContext aMvContext(this);
832 SttSelect();
833 if(SelTableRowCol( rPt, pEnd, bRowDrag ))
835 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
836 m_fnKillSel = &SwWrtShell::ResetSelect;
837 return true;
839 return false;
842 // Description: Selection of a table line or column
844 void SwWrtShell::SelectTableRow()
846 if ( SelTableRow() )
848 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
849 m_fnKillSel = &SwWrtShell::ResetSelect;
853 void SwWrtShell::SelectTableCol()
855 if ( SelTableCol() )
857 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
858 m_fnKillSel = &SwWrtShell::ResetSelect;
862 void SwWrtShell::SelectTableCell()
864 if ( SelTableBox() )
866 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
867 m_fnKillSel = &SwWrtShell::ResetSelect;
871 // Description: Check if a word selection is present.
872 // According to the rules for intelligent cut / paste
873 // surrounding spaces are cut out.
874 // Return: Delivers the type of the word selection.
876 int SwWrtShell::IntelligentCut(SelectionType nSelection, bool bCut)
878 // On multiple selection no intelligent drag and drop
879 // there are multiple cursors, since a second was placed
880 // already at the target position.
881 if( IsAddMode() || !(nSelection & SelectionType::Text) )
882 return NO_WORD;
884 OUString sText;
885 CharClass& rCC = GetAppCharClass();
887 // If the first character is no word character,
888 // no word selected.
889 sal_Unicode cPrev = GetChar(false);
890 sal_Unicode cNext = GetChar(true, -1);
891 if( !cPrev || !cNext ||
892 !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) ||
893 !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) )
894 return NO_WORD;
896 cPrev = GetChar(false, -1);
897 cNext = GetChar();
899 int cWord = NO_WORD;
900 // is a word selected?
901 if (cPrev && cNext &&
902 CH_TXTATR_BREAKWORD != cPrev && CH_TXTATR_INWORD != cPrev &&
903 CH_TXTATR_BREAKWORD != cNext && CH_TXTATR_INWORD != cNext &&
904 !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) &&
905 !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) )
906 cWord = WORD_NO_SPACE;
908 if(cWord == WORD_NO_SPACE && ' ' == cPrev )
910 cWord = WORD_SPACE_BEFORE;
911 // delete the space before
912 if(bCut)
914 Push();
915 if(IsCursorPtAtEnd())
916 SwapPam();
917 ClearMark();
918 SetMark();
919 SwCursorShell::Left(1,SwCursorSkipMode::Chars);
920 SwFEShell::Delete(true);
921 Pop(SwCursorShell::PopMode::DeleteCurrent);
924 else if(cWord == WORD_NO_SPACE && cNext == ' ')
926 cWord = WORD_SPACE_AFTER;
927 // delete the space behind
928 if(bCut) {
929 Push();
930 if(!IsCursorPtAtEnd()) SwapPam();
931 ClearMark();
932 SetMark();
933 SwCursorShell::Right(1,SwCursorSkipMode::Chars);
934 SwFEShell::Delete(true);
935 Pop(SwCursorShell::PopMode::DeleteCurrent);
938 return cWord;
941 // jump to the next / previous hyperlink - inside text and also
942 // on graphics
943 void SwWrtShell::SelectNextPrevHyperlink( bool bNext )
945 StartAction();
946 bool bRet = SwCursorShell::SelectNxtPrvHyperlink( bNext );
947 if( !bRet ) // didn't find? wrap and check again
949 SwShellCursor* pCursor = GetCursor_();
950 SwCursorSaveState aSaveState(*pCursor);
951 EnterStdMode();
952 if( bNext )
953 SttEndDoc(true);
954 else
955 SttEndDoc(false);
956 bRet = SwCursorShell::SelectNxtPrvHyperlink(bNext);
957 if (!bRet) // didn't find again? restore cursor position and bail
959 pCursor->RestoreSavePos();
960 EndAction(true); // don't scroll to restored cursor position
961 return;
964 EndAction();
966 bool bCreateXSelection = false;
967 const bool bFrameSelected = IsFrameSelected() || IsObjSelected();
968 if( IsSelection() )
970 if ( bFrameSelected )
971 UnSelectFrame();
973 // Set the function pointer for the canceling of the selection
974 // set at cursor
975 m_fnKillSel = &SwWrtShell::ResetSelect;
976 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
977 bCreateXSelection = true;
979 else if( bFrameSelected )
981 EnterSelFrameMode();
982 bCreateXSelection = true;
984 else if( (CNT_GRF | CNT_OLE ) & GetCntType() )
986 SelectObj( GetCharRect().Pos() );
987 EnterSelFrameMode();
988 bCreateXSelection = true;
991 if( bCreateXSelection )
992 SwTransferable::CreateSelection( *this );
995 // For the preservation of the selection the cursor will be moved left
996 // after SetMark(), so that the cursor is not moved by inserting text.
997 // Because a present selection at the CORE page is cleared at the
998 // current cursor position, the cursor will be pushed on the stack.
999 // After moving, they will again resummarized.
1001 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */