svx: prefix members of SvxClipboardFormatItem
[LibreOffice.git] / sw / source / uibase / wrtsh / select.cxx
blob701cb23d487a9bc9cfd3f52881050ad30d8b3054
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 #include <officecfg/Office/Common.hxx>
45 #include <strings.hrc>
47 #include <svx/svdview.hxx>
49 namespace com::sun::star::util {
50 struct SearchOptions2;
53 using namespace ::com::sun::star::util;
55 static tools::Long nStartDragX = 0, nStartDragY = 0;
56 static bool bStartDrag = false;
58 void SwWrtShell::Invalidate()
60 // to avoid making the slot volatile, invalidate it every time if something could have been changed
61 // this is still much cheaper than asking for the state every 200 ms (and avoid background processing)
62 GetView().GetViewFrame().GetBindings().Invalidate( FN_STAT_SELMODE );
63 GetView().GetViewFrame().GetBindings().Update(FN_STAT_SELMODE); // make selection mode control icon update immediately
64 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
65 if (pWrdCnt)
66 pWrdCnt->UpdateCounts();
69 bool SwWrtShell::SelNearestWrd()
71 SwMvContext aMvContext(this);
72 if( !IsInWord() && !IsEndWrd() && !IsStartWord() )
73 PrvWrd();
74 if( IsEndWrd() )
75 Left(SwCursorSkipMode::Cells, false, 1, false );
76 return SelWrd();
79 bool SwWrtShell::SelWrd(const Point *pPt, sal_Int16 nWordType )
81 bool bRet;
83 SwMvContext aMvContext(this);
84 SttSelect();
85 bRet = SwCursorShell::SelectWordWT( pPt, nWordType );
87 EndSelect();
88 if( bRet )
90 m_bSelWrd = true;
91 if(pPt)
92 m_aStart = *pPt;
94 return bRet;
97 void SwWrtShell::SelSentence(const Point *pPt )
100 SwMvContext aMvContext(this);
101 ClearMark();
102 SwCursorShell::GoStartSentence();
103 SttSelect();
104 SwCursorShell::GoEndSentence();
106 EndSelect();
107 if(pPt)
108 m_aStart = *pPt;
109 m_bSelLn = true;
110 m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on
113 void SwWrtShell::SelPara(const Point *pPt )
116 SwMvContext aMvContext(this);
117 ClearMark();
118 SwCursorShell::MovePara( GoCurrPara, fnParaStart );
119 SttSelect();
120 SwCursorShell::MovePara( GoCurrPara, fnParaEnd );
122 EndSelect();
123 if(pPt)
124 m_aStart = *pPt;
125 m_bSelLn = false;
126 m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on
129 void SwWrtShell::SelAll()
131 const bool bLockedView = IsViewLocked();
132 LockView( true );
134 if(m_bBlockMode)
135 LeaveBlockMode();
136 SwMvContext aMvContext(this);
137 bool bMoveTable = false;
138 std::optional<SwPosition> oStartPos;
139 std::optional<SwPosition> oEndPos;
140 SwShellCursor* pTmpCursor = nullptr;
142 // Query these early, before we move the cursor.
143 bool bHasWholeTabSelection = HasWholeTabSelection();
144 bool bIsCursorInTable = IsCursorInTable();
146 if (!bHasWholeTabSelection
147 && ( !bIsCursorInTable
148 || getShellCursor(false)->GetMarkNode().FindTableNode() == nullptr
149 || !ExtendedSelectedAll())) // ESA inside table -> else branch
151 if ( IsSelection() && IsCursorPtAtEnd() )
152 SwapPam();
153 pTmpCursor = getShellCursor( false );
154 if( pTmpCursor )
156 oStartPos.emplace( *pTmpCursor->GetPoint() );
157 oEndPos.emplace( *pTmpCursor->GetMark() );
159 Push();
160 bool bIsFullSel = !MoveSection( GoCurrSection, fnSectionStart);
161 SwapPam();
162 bIsFullSel &= !MoveSection( GoCurrSection, fnSectionEnd);
163 Pop(SwCursorShell::PopMode::DeleteCurrent);
164 GoStart(true, &bMoveTable, false, !bIsFullSel);
165 SttSelect();
166 GoEnd(true, &bMoveTable);
168 else
170 if (MoveOutOfTable())
171 { // select outer text
172 EnterStdMode(); // delete m_pTableCursor
173 // GoStart(true, &bMoveTable, false, true);
174 MoveSection(GoCurrSection, fnSectionStart); // don't move into prev table
175 SttSelect();
176 MoveSection(GoCurrSection, fnSectionEnd); // don't move to different cell
178 else
180 TrySelectOuterTable();
184 bool bNeedsExtendedSelectAll = StartsWith_() != StartsWith::None;
186 // the GoEnd() could have created a table selection, if so avoid ESA.
187 if (bNeedsExtendedSelectAll && bIsCursorInTable)
189 bNeedsExtendedSelectAll = !HasWholeTabSelection();
192 if (bNeedsExtendedSelectAll)
194 ExtendedSelectAll(/*bFootnotes =*/ false);
197 SwDoc *pDoc = GetDoc();
198 if ( pDoc )
200 pDoc->SetPrepareSelAll();
203 if( oStartPos )
205 pTmpCursor = getShellCursor( false );
206 if( pTmpCursor )
208 // Some special handling for sections (e.g. TOC) at the beginning of the document body
209 // to avoid the selection of the first section
210 // if the last selection was behind the first section or
211 // if the last selection was already the first section
212 // In this both cases we select to the end of document
213 if( ( *pTmpCursor->GetPoint() < *oEndPos ||
214 ( *oStartPos == *pTmpCursor->GetMark() &&
215 *oEndPos == *pTmpCursor->GetPoint() ) ) && !bNeedsExtendedSelectAll)
216 SwCursorShell::SttEndDoc(false);
220 EndSelect();
221 LockView( bLockedView );
224 // Description: Text search
226 sal_Int32 SwWrtShell::SearchPattern( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
227 SwDocPositions eStt, SwDocPositions eEnd,
228 FindRanges eFlags, bool bReplace )
230 // no enhancement of existing selections
231 if(!(eFlags & FindRanges::InSel))
232 ClearMark();
233 bool bCancel = false;
234 sal_Int32 nRet = Find_Text(rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace);
235 if(bCancel)
237 Undo();
238 nRet = SAL_MAX_INT32;
240 return nRet;
243 // Description: search for templates
245 sal_Int32 SwWrtShell::SearchTempl( const OUString &rTempl,
246 SwDocPositions eStt, SwDocPositions eEnd,
247 FindRanges eFlags, const OUString* pReplTempl )
249 // no enhancement of existing selections
250 if(!(eFlags & FindRanges::InSel))
251 ClearMark();
252 SwTextFormatColl *pColl = GetParaStyle(rTempl, SwWrtShell::GETSTYLE_CREATESOME);
253 SwTextFormatColl *pReplaceColl = nullptr;
254 if( pReplTempl )
255 pReplaceColl = GetParaStyle(*pReplTempl, SwWrtShell::GETSTYLE_CREATESOME );
257 bool bCancel = false;
258 sal_Int32 nRet = FindFormat(pColl ? *pColl : GetDfltTextFormatColl(),
259 eStt,eEnd, bCancel, eFlags, pReplaceColl);
260 if(bCancel)
262 Undo();
263 nRet = SAL_MAX_INT32;
265 return nRet;
268 // search for attributes
270 sal_Int32 SwWrtShell::SearchAttr( const SfxItemSet& rFindSet, bool bNoColls,
271 SwDocPositions eStart, SwDocPositions eEnd,
272 FindRanges eFlags, const i18nutil::SearchOptions2* pSearchOpt,
273 const SfxItemSet* pReplaceSet )
275 // no enhancement of existing selections
276 if (!(eFlags & FindRanges::InSel))
277 ClearMark();
279 // Searching
280 bool bCancel = false;
281 sal_Int32 nRet = FindAttrs(rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet);
283 if(bCancel)
285 Undo();
286 nRet = SAL_MAX_INT32;
288 return nRet;
291 // Selection modes
293 void SwWrtShell::PushMode()
295 m_pModeStack = new ModeStack( m_pModeStack, m_bIns, m_bExtMode, m_bAddMode, m_bBlockMode );
298 void SwWrtShell::PopMode()
300 if ( nullptr == m_pModeStack )
301 return;
303 if ( m_bExtMode && !m_pModeStack->bExt )
304 LeaveExtMode();
305 if ( m_bAddMode && !m_pModeStack->bAdd )
306 LeaveAddMode();
307 if ( m_bBlockMode && !m_pModeStack->bBlock )
308 LeaveBlockMode();
309 m_bIns = m_pModeStack->bIns;
311 m_pModeStack = std::move(m_pModeStack->pNext);
314 // Two methods for setting cursors: the first maps at the
315 // eponymous methods in the CursorShell, the second removes
316 // all selections at first.
318 tools::Long SwWrtShell::SetCursor(const Point *pPt, bool bTextOnly, ScrollSizeMode eScrollSizeMode)
320 // Remove a possibly present selection at the position
321 // of the mouseclick
323 if(!IsInSelect() && TestCurrPam(*pPt)) {
324 ClearMark();
327 return SwCursorShell::SetCursor(*pPt, bTextOnly, true, false, eScrollSizeMode );
330 tools::Long SwWrtShell::SetCursorKillSel(const Point *pPt, bool bTextOnly, ScrollSizeMode eScrollSizeMode )
332 SwActContext aActContext(this);
333 ResetSelect(pPt, false, ScrollSizeMode::ScrollSizeDefault);
334 return SwCursorShell::SetCursor(*pPt, bTextOnly, true, false, eScrollSizeMode);
337 void SwWrtShell::UnSelectFrame()
339 // Remove Frame selection with guaranteed invalid position
340 Point aPt(LONG_MIN, LONG_MIN);
341 SelectObj(aPt);
342 SwTransferable::ClearSelection( *this );
345 // Remove of all selections
347 tools::Long SwWrtShell::ResetSelect(const Point *, bool, ScrollSizeMode)
349 if(IsSelFrameMode())
351 UnSelectFrame();
352 LeaveSelFrameMode();
354 else
356 // SwActContext opens an Action -
357 // to avoid problems in the basic process with the
358 // shell switching, GetChgLnk().Call() may be called
359 // after EndAction().
361 SwActContext aActContext(this);
362 m_bSelWrd = m_bSelLn = false;
363 KillPams();
364 ClearMark();
365 m_fnKillSel = &SwWrtShell::Ignore;
366 m_fnSetCursor = &SwWrtShell::SetCursor;
369 // After canceling of all selections an update of Attr-Controls
370 // could be necessary.
371 GetChgLnk().Call(nullptr);
373 if ( GetEnhancedTableSelection() != SwTable::SEARCH_NONE )
374 UnsetEnhancedTableSelection();
376 Invalidate();
377 SwTransferable::ClearSelection( *this );
378 return 1;
381 bool SwWrtShell::IsSplitVerticalByDefault() const
383 return GetDoc()->IsSplitVerticalByDefault();
386 void SwWrtShell::SetSplitVerticalByDefault(bool value)
388 GetDoc()->SetSplitVerticalByDefault(value);
391 // Do nothing
393 tools::Long SwWrtShell::Ignore(const Point *, bool, ScrollSizeMode )
395 return 1;
398 // Begin of a selection process.
400 void SwWrtShell::SttSelect()
402 if(m_bInSelect)
403 return;
404 if(!HasMark())
405 SetMark();
406 if( m_bBlockMode )
408 SwShellCursor* pTmp = getShellCursor( true );
409 if( !pTmp->HasMark() )
410 pTmp->SetMark();
412 m_fnKillSel = &SwWrtShell::Ignore;
413 m_fnSetCursor = &SwWrtShell::SetCursor;
414 m_bInSelect = true;
415 Invalidate();
416 SwTransferable::CreateSelection( *this );
419 namespace {
421 void collectUIInformation(SwShellCursor* pCursor)
423 EventDescription aDescription;
424 OUString aSelStart = OUString::number(pCursor->Start()->GetContentIndex());
425 OUString aSelEnd = OUString::number(pCursor->End()->GetContentIndex());
427 aDescription.aParameters = {{"START_POS", aSelStart}, {"END_POS", aSelEnd}};
428 aDescription.aAction = "SELECT";
429 aDescription.aID = "writer_edit";
430 aDescription.aKeyWord = "SwEditWinUIObject";
431 aDescription.aParent = "MainWindow";
433 UITestLogger::getInstance().logEvent(aDescription);
438 // End of a selection process.
440 void SwWrtShell::EndSelect()
442 if(m_bInSelect && !m_bExtMode)
444 m_bInSelect = false;
445 if (m_bAddMode)
447 AddLeaveSelect();
449 else
451 SttLeaveSelect();
452 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
453 m_fnKillSel = &SwWrtShell::ResetSelect;
456 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame().GetChildWindow(SwWordCountWrapper::GetChildWindowId()));
457 if (pWrdCnt)
458 pWrdCnt->UpdateCounts();
460 collectUIInformation(GetCursor_());
463 void SwWrtShell::ExtSelWrd(const Point *pPt, bool )
465 SwMvContext aMvContext(this);
466 if( IsTableMode() )
467 return;
469 // Bug 66823: actual crsr has in additional mode no selection?
470 // Then destroy the actual and go to prev, this will be expand
471 if( !HasMark() && GoPrevCursor() )
473 bool bHasMark = HasMark(); // that's wrong!
474 GoNextCursor();
475 if( bHasMark )
477 DestroyCursor();
478 GoPrevCursor();
482 // check the direction of the selection with the new point
483 bool bMoveCursor = true, bToTop = false;
484 SwCursorShell::SelectWord( &m_aStart ); // select the startword
485 SwCursorShell::Push(); // save the cursor
486 SwCursorShell::SetCursor( *pPt ); // and check the direction
488 switch( SwCursorShell::CompareCursorStackMkCurrPt())
490 case -1: bToTop = false; break;
491 case 1: bToTop = true; break;
492 default: bMoveCursor = false; break;
495 SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); // restore the saved cursor
497 if( !bMoveCursor )
498 return;
500 // select to Top but cursor select to Bottom? or
501 // select to Bottom but cursor select to Top? --> swap the cursor
502 if( bToTop )
503 SwapPam();
505 SwCursorShell::Push(); // save cur cursor
506 if( SwCursorShell::SelectWord( pPt )) // select the current word
508 if( bToTop )
509 SwapPam();
510 Combine();
512 else
514 SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
515 if( bToTop )
516 SwapPam();
520 void SwWrtShell::ExtSelLn(const Point *pPt, bool )
522 SwMvContext aMvContext(this);
523 SwCursorShell::SetCursor(*pPt);
524 if( IsTableMode() )
525 return;
527 // Bug 66823: actual crsr has in additional mode no selection?
528 // Then destroy the actual and go to prev, this will be expand
529 if( !HasMark() && GoPrevCursor() )
531 bool bHasMark = HasMark(); // that's wrong!
532 GoNextCursor();
533 if( bHasMark )
535 DestroyCursor();
536 GoPrevCursor();
540 // if applicable fit the selection to the "Mark"
541 bool bToTop = !IsCursorPtAtEnd();
542 SwapPam();
544 // The "Mark" has to be at the end or the beginning of the line.
545 if( bToTop ? !IsEndSentence() : !IsStartSentence() )
547 if( bToTop )
549 if( !IsEndPara() )
550 SwCursorShell::Right(1,SwCursorSkipMode::Chars);
551 SwCursorShell::GoEndSentence();
553 else
554 SwCursorShell::GoStartSentence();
556 SwapPam();
558 if (bToTop)
559 SwCursorShell::GoStartSentence();
560 else
561 SwCursorShell::GoEndSentence();
564 // Back into the standard mode: no mode, no selections.
566 void SwWrtShell::EnterStdMode()
568 if(m_bAddMode)
569 LeaveAddMode();
570 if(m_bBlockMode)
571 LeaveBlockMode();
572 m_bBlockMode = false;
573 m_bExtMode = false;
574 m_bInSelect = false;
575 if(IsSelFrameMode())
577 UnSelectFrame();
578 LeaveSelFrameMode();
580 else
582 // SwActContext opens and action which has to be
583 // closed prior to the call of
584 // GetChgLnk().Call()
585 SwActContext aActContext(this);
586 m_bSelWrd = m_bSelLn = false;
587 if( !IsRetainSelection() )
588 KillPams();
589 ClearMark();
590 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
591 m_fnKillSel = &SwWrtShell::ResetSelect;
593 Invalidate();
594 SwTransferable::ClearSelection( *this );
597 void SwWrtShell::AssureStdMode()
599 // deselect any drawing or frame and leave editing mode
600 if (SdrView* pSdrView = GetDrawView())
602 if (pSdrView->IsTextEdit())
604 bool bLockView = IsViewLocked();
605 LockView(true);
606 EndTextEdit();
607 LockView(bLockView);
609 // go out of the frame
610 Point aPt(LONG_MIN, LONG_MIN);
611 SelectObj(aPt, SW_LEAVE_FRAME);
613 if (IsSelFrameMode() || GetSelectedObjCount())
615 UnSelectFrame();
616 LeaveSelFrameMode();
617 GetView().LeaveDrawCreate();
618 EnterStdMode();
619 DrawSelChanged();
620 GetView().StopShellTimer();
622 else
623 EnterStdMode();
626 // Extended Mode
628 void SwWrtShell::EnterExtMode()
630 if(m_bBlockMode)
632 LeaveBlockMode();
633 KillPams();
634 ClearMark();
636 m_bExtMode = true;
637 m_bAddMode = false;
638 m_bBlockMode = false;
639 SttSelect();
642 void SwWrtShell::LeaveExtMode()
644 m_bExtMode = false;
645 EndSelect();
648 // End of a selection; if the selection is empty,
649 // ClearMark().
651 void SwWrtShell::SttLeaveSelect()
653 if(SwCursorShell::HasSelection() && !IsSelTableCells() && m_bClearMark) {
654 return;
656 ClearMark();
659 // Leaving of the selection mode in additional mode
661 void SwWrtShell::AddLeaveSelect()
663 if(IsTableMode()) LeaveAddMode();
664 else if(SwCursorShell::HasSelection())
665 CreateCursor();
668 // Additional Mode
670 void SwWrtShell::EnterAddMode()
672 if(IsTableMode()) return;
673 if(m_bBlockMode)
674 LeaveBlockMode();
675 m_fnSetCursor = &SwWrtShell::SetCursor;
676 m_bAddMode = true;
677 m_bBlockMode = false;
678 m_bExtMode = false;
679 if(SwCursorShell::HasSelection())
680 CreateCursor();
681 Invalidate();
684 void SwWrtShell::LeaveAddMode()
686 m_fnKillSel = &SwWrtShell::ResetSelect;
687 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
688 m_bAddMode = false;
689 Invalidate();
692 // Block Mode
694 void SwWrtShell::EnterBlockMode()
696 m_bBlockMode = false;
697 EnterStdMode();
698 m_bBlockMode = true;
699 CursorToBlockCursor();
700 Invalidate();
703 void SwWrtShell::LeaveBlockMode()
705 m_bBlockMode = false;
706 BlockCursorToCursor();
707 EndSelect();
708 Invalidate();
711 // Insert mode
713 void SwWrtShell::ImplSetInsMode(bool bOn)
715 m_bIns = bOn;
716 SwCursorShell::SetOverwriteCursor( !m_bIns );
717 const SfxBoolItem aTmp( SID_ATTR_INSERT, m_bIns );
718 GetView().GetViewFrame().GetBindings().SetState( aTmp );
719 StartAction();
720 EndAction();
721 Invalidate();
724 void SwWrtShell::SetInsMode( bool bOn )
726 const bool bDoAsk = officecfg::Office::Common::Misc::QuerySetInsMode::get();
727 if (!bOn && bDoAsk)
729 VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create();
730 auto pDlg = pFact->CreateQueryDialog(
731 GetView().GetFrameWeld(), SwResId(STR_QUERY_INSMODE_TITLE),
732 SwResId(STR_QUERY_INSMODE_TEXT), SwResId(STR_QUERY_INSMODE_QUESTION), true);
733 pDlg->StartExecuteAsync( [this, pDlg] (sal_Int32 nResult)->void
735 if (pDlg->ShowAgain() == false)
737 std::shared_ptr<comphelper::ConfigurationChanges> xChanges(
738 comphelper::ConfigurationChanges::create());
739 officecfg::Office::Common::Misc::QuerySetInsMode::set(false, xChanges);
740 xChanges->commit();
742 if (nResult == RET_YES)
743 ImplSetInsMode(false);
744 pDlg->disposeOnce();
746 return;
748 ImplSetInsMode(bOn);
751 //Overwrite mode is incompatible with red-lining
752 void SwWrtShell::SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode )
754 SetRedlineFlags( eMode );
755 if (IsRedlineOn())
756 SetInsMode();
759 // Edit frame
761 void SwWrtShell::BeginFrameDrag(const Point *pPt, bool bIsShift)
763 m_fnDrag = &SwFEShell::Drag;
764 if(bStartDrag)
766 Point aTmp( nStartDragX, nStartDragY );
767 SwFEShell::BeginDrag( &aTmp, bIsShift );
769 else
770 SwFEShell::BeginDrag( pPt, bIsShift );
773 void SwWrtShell::EnterSelFrameMode(const Point *pPos)
775 if(pPos)
777 nStartDragX = pPos->X();
778 nStartDragY = pPos->Y();
779 bStartDrag = true;
781 m_bLayoutMode = true;
782 HideCursor();
784 // equal call of BeginDrag in the SwFEShell
785 m_fnDrag = &SwWrtShell::BeginFrameDrag;
786 m_fnEndDrag = &SwWrtShell::UpdateLayoutFrame;
787 SwBaseShell::SetFrameMode( FLY_DRAG_START, this );
788 Invalidate();
791 void SwWrtShell::LeaveSelFrameMode()
793 m_fnDrag = &SwWrtShell::BeginDrag;
794 m_fnEndDrag = &SwWrtShell::DefaultEndDrag;
795 m_bLayoutMode = false;
796 bStartDrag = false;
797 Edit();
798 SwBaseShell::SetFrameMode( FLY_DRAG_END, this );
799 Invalidate();
802 // Description: execute framebound macro
804 IMPL_LINK( SwWrtShell, ExecFlyMac, const SwFlyFrameFormat*, pFlyFormat, void )
806 const SwFrameFormat *pFormat = pFlyFormat ? static_cast<const SwFrameFormat*>(pFlyFormat) : GetFlyFrameFormat();
807 assert(pFormat && "no frame format");
808 const SvxMacroItem &rFormatMac = pFormat->GetMacro();
810 if(rFormatMac.HasMacro(SvMacroItemId::SwObjectSelect))
812 const SvxMacro &rMac = rFormatMac.GetMacro(SvMacroItemId::SwObjectSelect);
813 if( IsFrameSelected() )
814 m_bLayoutMode = true;
815 CallChgLnk();
816 ExecMacro( rMac );
820 void SwWrtShell::UpdateLayoutFrame(const Point *, bool )
822 // still a dummy
823 SwFEShell::EndDrag();
824 m_fnDrag = &SwWrtShell::BeginFrameDrag;
827 // Handler for toggling the modes. Returns back the old mode.
829 void SwWrtShell::ToggleAddMode()
831 m_bAddMode ? LeaveAddMode(): EnterAddMode();
832 Invalidate();
835 void SwWrtShell::ToggleBlockMode()
837 m_bBlockMode ? LeaveBlockMode(): EnterBlockMode();
838 Invalidate();
841 void SwWrtShell::ToggleExtMode()
843 m_bExtMode ? LeaveExtMode() : EnterExtMode();
844 Invalidate();
847 // Dragging in standard mode (Selecting of content)
849 void SwWrtShell::BeginDrag(const Point * /*pPt*/, bool )
851 if(m_bSelWrd)
853 m_bInSelect = true;
854 if( !IsCursorPtAtEnd() )
855 SwapPam();
857 m_fnDrag = &SwWrtShell::ExtSelWrd;
858 m_fnSetCursor = &SwWrtShell::Ignore;
860 else if(m_bSelLn)
862 m_bInSelect = true;
863 m_fnDrag = &SwWrtShell::ExtSelLn;
864 m_fnSetCursor = &SwWrtShell::Ignore;
866 else
868 m_fnDrag = &SwWrtShell::DefaultDrag;
869 SttSelect();
873 void SwWrtShell::DefaultDrag(const Point *, bool )
875 if( IsSelTableCells() )
876 m_aSelTableLink.Call(*this);
879 void SwWrtShell::DefaultEndDrag(const Point * /*pPt*/, bool )
881 m_fnDrag = &SwWrtShell::BeginDrag;
882 if( IsExtSel() )
883 LeaveExtSel();
885 if( IsSelTableCells() )
886 m_aSelTableLink.Call(*this);
887 EndSelect();
890 // #i32329# Enhanced table selection
891 bool SwWrtShell::SelectTableRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
893 SwMvContext aMvContext(this);
894 SttSelect();
895 if(SelTableRowCol( rPt, pEnd, bRowDrag ))
897 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
898 m_fnKillSel = &SwWrtShell::ResetSelect;
899 return true;
901 return false;
904 // Description: Selection of a table line or column
906 void SwWrtShell::SelectTableRow()
908 if ( SelTableRow() )
910 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
911 m_fnKillSel = &SwWrtShell::ResetSelect;
915 void SwWrtShell::SelectTableCol()
917 if ( SelTableCol() )
919 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
920 m_fnKillSel = &SwWrtShell::ResetSelect;
924 void SwWrtShell::SelectTableCell()
926 if ( SelTableBox() )
928 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
929 m_fnKillSel = &SwWrtShell::ResetSelect;
933 // Description: Check if a word selection is present.
934 // According to the rules for intelligent cut / paste
935 // surrounding spaces are cut out.
936 // Return: Delivers the type of the word selection.
938 int SwWrtShell::IntelligentCut(SelectionType nSelection, bool bCut)
940 // On multiple selection no intelligent drag and drop
941 // there are multiple cursors, since a second was placed
942 // already at the target position.
943 if( IsAddMode() || !(nSelection & SelectionType::Text) )
944 return NO_WORD;
946 OUString sText;
947 CharClass& rCC = GetAppCharClass();
949 // If the first character is no word character,
950 // no word selected.
951 sal_Unicode cPrev = GetChar(false);
952 sal_Unicode cNext = GetChar(true, -1);
953 if( !cPrev || !cNext ||
954 !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) ||
955 !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) )
956 return NO_WORD;
958 cPrev = GetChar(false, -1);
959 cNext = GetChar();
961 int cWord = NO_WORD;
962 // is a word selected?
963 if (cPrev && cNext &&
964 CH_TXTATR_BREAKWORD != cPrev && CH_TXTATR_INWORD != cPrev &&
965 CH_TXTATR_BREAKWORD != cNext && CH_TXTATR_INWORD != cNext &&
966 !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) &&
967 !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) )
968 cWord = WORD_NO_SPACE;
970 if(cWord == WORD_NO_SPACE && ' ' == cPrev )
972 cWord = WORD_SPACE_BEFORE;
973 // delete the space before
974 if(bCut)
976 Push();
977 if(IsCursorPtAtEnd())
978 SwapPam();
979 ClearMark();
980 SetMark();
981 SwCursorShell::Left(1,SwCursorSkipMode::Chars);
982 SwFEShell::Delete(true);
983 Pop(SwCursorShell::PopMode::DeleteCurrent);
986 else if(cWord == WORD_NO_SPACE && cNext == ' ')
988 cWord = WORD_SPACE_AFTER;
989 // delete the space behind
990 if(bCut) {
991 Push();
992 if(!IsCursorPtAtEnd()) SwapPam();
993 ClearMark();
994 SetMark();
995 SwCursorShell::Right(1,SwCursorSkipMode::Chars);
996 SwFEShell::Delete(true);
997 Pop(SwCursorShell::PopMode::DeleteCurrent);
1000 return cWord;
1003 // jump to the next / previous hyperlink - inside text and also
1004 // on graphics
1005 void SwWrtShell::SelectNextPrevHyperlink( bool bNext )
1007 StartAction();
1008 bool bRet = SwCursorShell::SelectNxtPrvHyperlink( bNext );
1009 if( !bRet ) // didn't find? wrap and check again
1011 SwShellCursor* pCursor = GetCursor_();
1012 SwCursorSaveState aSaveState(*pCursor);
1013 EnterStdMode();
1014 if( bNext )
1015 SttEndDoc(true);
1016 else
1017 SttEndDoc(false);
1018 bRet = SwCursorShell::SelectNxtPrvHyperlink(bNext);
1019 if (!bRet) // didn't find again? restore cursor position and bail
1021 pCursor->RestoreSavePos();
1022 EndAction(true); // don't scroll to restored cursor position
1023 return;
1026 EndAction();
1028 bool bCreateXSelection = false;
1029 const bool bFrameSelected = IsFrameSelected() || GetSelectedObjCount();
1030 if( IsSelection() )
1032 if ( bFrameSelected )
1033 UnSelectFrame();
1035 // Set the function pointer for the canceling of the selection
1036 // set at cursor
1037 m_fnKillSel = &SwWrtShell::ResetSelect;
1038 m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
1039 bCreateXSelection = true;
1041 else if( bFrameSelected )
1043 EnterSelFrameMode();
1044 bCreateXSelection = true;
1046 else if( (CNT_GRF | CNT_OLE ) & GetCntType() )
1048 SelectObj( GetCharRect().Pos() );
1049 EnterSelFrameMode();
1050 bCreateXSelection = true;
1053 if( bCreateXSelection )
1054 SwTransferable::CreateSelection( *this );
1057 // For the preservation of the selection the cursor will be moved left
1058 // after SetMark(), so that the cursor is not moved by inserting text.
1059 // Because a present selection at the CORE page is cleared at the
1060 // current cursor position, the cursor will be pushed on the stack.
1061 // After moving, they will again resummarized.
1063 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */