diff options
Diffstat (limited to 'sw/source/uibase/wrtsh/select.cxx')
-rw-r--r-- | sw/source/uibase/wrtsh/select.cxx | 992 |
1 files changed, 992 insertions, 0 deletions
diff --git a/sw/source/uibase/wrtsh/select.cxx b/sw/source/uibase/wrtsh/select.cxx new file mode 100644 index 000000000..c122162b0 --- /dev/null +++ b/sw/source/uibase/wrtsh/select.cxx @@ -0,0 +1,992 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <limits.h> +#include <hintids.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/eitem.hxx> +#include <svl/macitem.hxx> +#include <unotools/charclass.hxx> +#include <sfx2/event.hxx> +#include <osl/diagnose.h> +#include <cmdid.h> +#include <view.hxx> +#include <basesh.hxx> +#include <wrtsh.hxx> +#include <frmatr.hxx> +#include <mdiexp.hxx> +#include <fmtcol.hxx> +#include <frmfmt.hxx> +#include <swdtflvr.hxx> +#include <doc.hxx> +#include <wordcountdialog.hxx> +#include <memory> +#include <vcl/uitest/logger.hxx> +#include <vcl/uitest/eventdescription.hxx> + +namespace com::sun::star::util { + struct SearchOptions2; +} + +using namespace ::com::sun::star::util; + +static tools::Long nStartDragX = 0, nStartDragY = 0; +static bool bStartDrag = false; + +void SwWrtShell::Invalidate() +{ + // to avoid making the slot volatile, invalidate it every time if something could have been changed + // this is still much cheaper than asking for the state every 200 ms (and avoid background processing) + GetView().GetViewFrame()->GetBindings().Invalidate( FN_STAT_SELMODE ); + SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); + if (pWrdCnt) + pWrdCnt->UpdateCounts(); +} + +bool SwWrtShell::SelNearestWrd() +{ + SwMvContext aMvContext(this); + if( !IsInWord() && !IsEndWrd() && !IsStartWord() ) + PrvWrd(); + if( IsEndWrd() ) + Left(CRSR_SKIP_CELLS, false, 1, false ); + return SelWrd(); +} + +bool SwWrtShell::SelWrd(const Point *pPt ) +{ + bool bRet; + { + SwMvContext aMvContext(this); + SttSelect(); + bRet = SwCursorShell::SelectWord( pPt ); + } + EndSelect(); + if( bRet ) + { + m_bSelWrd = true; + if(pPt) + m_aStart = *pPt; + } + return bRet; +} + +void SwWrtShell::SelSentence(const Point *pPt ) +{ + { + SwMvContext aMvContext(this); + ClearMark(); + SwCursorShell::GoStartSentence(); + SttSelect(); + SwCursorShell::GoEndSentence(); + } + EndSelect(); + if(pPt) + m_aStart = *pPt; + m_bSelLn = true; + m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on +} + +void SwWrtShell::SelPara(const Point *pPt ) +{ + { + SwMvContext aMvContext(this); + ClearMark(); + SwCursorShell::MovePara( GoCurrPara, fnParaStart ); + SttSelect(); + SwCursorShell::MovePara( GoCurrPara, fnParaEnd ); + } + EndSelect(); + if(pPt) + m_aStart = *pPt; + m_bSelLn = false; + m_bSelWrd = false; // disable SelWord, otherwise no SelLine goes on +} + +void SwWrtShell::SelAll() +{ + const bool bLockedView = IsViewLocked(); + LockView( true ); + { + if(m_bBlockMode) + LeaveBlockMode(); + SwMvContext aMvContext(this); + bool bMoveTable = false; + std::unique_ptr<SwPosition> pStartPos; + std::unique_ptr<SwPosition> pEndPos; + SwShellCursor* pTmpCursor = nullptr; + + // Query these early, before we move the cursor. + bool bHasWholeTabSelection = HasWholeTabSelection(); + bool bIsCursorInTable = IsCursorInTable(); + + if (!bHasWholeTabSelection) + { + if ( IsSelection() && IsCursorPtAtEnd() ) + SwapPam(); + pTmpCursor = getShellCursor( false ); + if( pTmpCursor ) + { + pStartPos.reset(new SwPosition( *pTmpCursor->GetPoint() )); + pEndPos.reset(new SwPosition( *pTmpCursor->GetMark() )); + } + Push(); + bool bIsFullSel = !MoveSection( GoCurrSection, fnSectionStart); + SwapPam(); + bIsFullSel &= !MoveSection( GoCurrSection, fnSectionEnd); + Pop(SwCursorShell::PopMode::DeleteCurrent); + GoStart(true, &bMoveTable, false, !bIsFullSel); + } + else + { + EnterStdMode(); + SttEndDoc(true); + } + SttSelect(); + GoEnd(true, &bMoveTable); + + bool bNeedsExtendedSelectAll = StartsWithTable(); + + // If the cursor was in a table, then we only need the extended select + // all if the whole table is already selected, to still allow selecting + // only a single cell or a single table before selecting the whole + // document. + if (bNeedsExtendedSelectAll && bIsCursorInTable) + bNeedsExtendedSelectAll = bHasWholeTabSelection; + + if (bNeedsExtendedSelectAll) + { + // Disable table cursor to make sure getShellCursor() returns m_pCurrentCursor, not m_pTableCursor. + if (IsTableMode()) + TableCursorToCursor(); + // Do the extended select all on m_pCurrentCursor. + ExtendedSelectAll(/*bFootnotes =*/ false); + } + + SwDoc *pDoc = GetDoc(); + if ( pDoc ) + { + pDoc->SetPrepareSelAll(); + } + + if( pStartPos ) + { + pTmpCursor = getShellCursor( false ); + if( pTmpCursor ) + { + // Some special handling for sections (e.g. TOC) at the beginning of the document body + // to avoid the selection of the first section + // if the last selection was behind the first section or + // if the last selection was already the first section + // In this both cases we select to the end of document + if( ( *pTmpCursor->GetPoint() < *pEndPos || + ( *pStartPos == *pTmpCursor->GetMark() && + *pEndPos == *pTmpCursor->GetPoint() ) ) && !bNeedsExtendedSelectAll) + SwCursorShell::SttEndDoc(false); + } + } + } + EndSelect(); + LockView( bLockedView ); +} + +// Description: Text search + +sal_uLong SwWrtShell::SearchPattern( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, + SwDocPositions eStt, SwDocPositions eEnd, + FindRanges eFlags, bool bReplace ) +{ + // no enhancement of existing selections + if(!(eFlags & FindRanges::InSel)) + ClearMark(); + bool bCancel = false; + sal_uLong nRet = Find_Text(rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace); + if(bCancel) + { + Undo(); + nRet = ULONG_MAX; + } + return nRet; +} + +// Description: search for templates + +sal_uLong SwWrtShell::SearchTempl( const OUString &rTempl, + SwDocPositions eStt, SwDocPositions eEnd, + FindRanges eFlags, const OUString* pReplTempl ) +{ + // no enhancement of existing selections + if(!(eFlags & FindRanges::InSel)) + ClearMark(); + SwTextFormatColl *pColl = GetParaStyle(rTempl, SwWrtShell::GETSTYLE_CREATESOME); + SwTextFormatColl *pReplaceColl = nullptr; + if( pReplTempl ) + pReplaceColl = GetParaStyle(*pReplTempl, SwWrtShell::GETSTYLE_CREATESOME ); + + bool bCancel = false; + sal_uLong nRet = FindFormat(pColl ? *pColl : GetDfltTextFormatColl(), + eStt,eEnd, bCancel, eFlags, pReplaceColl); + if(bCancel) + { + Undo(); + nRet = ULONG_MAX; + } + return nRet; +} + +// search for attributes + +sal_uLong SwWrtShell::SearchAttr( const SfxItemSet& rFindSet, bool bNoColls, + SwDocPositions eStart, SwDocPositions eEnd, + FindRanges eFlags, const i18nutil::SearchOptions2* pSearchOpt, + const SfxItemSet* pReplaceSet ) +{ + // no enhancement of existing selections + if (!(eFlags & FindRanges::InSel)) + ClearMark(); + + // Searching + bool bCancel = false; + sal_uLong nRet = FindAttrs(rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet); + + if(bCancel) + { + Undo(); + nRet = ULONG_MAX; + } + return nRet; +} + +// Selection modes + +void SwWrtShell::PushMode() +{ + m_pModeStack = new ModeStack( m_pModeStack, m_bIns, m_bExtMode, m_bAddMode, m_bBlockMode ); +} + +void SwWrtShell::PopMode() +{ + if ( nullptr == m_pModeStack ) + return; + + if ( m_bExtMode && !m_pModeStack->bExt ) + LeaveExtMode(); + if ( m_bAddMode && !m_pModeStack->bAdd ) + LeaveAddMode(); + if ( m_bBlockMode && !m_pModeStack->bBlock ) + LeaveBlockMode(); + m_bIns = m_pModeStack->bIns; + + m_pModeStack = std::move(m_pModeStack->pNext); +} + +// Two methods for setting cursors: the first maps at the +// eponymous methods in the CursorShell, the second removes +// all selections at first. + +tools::Long SwWrtShell::SetCursor(const Point *pPt, bool bTextOnly) +{ + // Remove a possibly present selection at the position + // of the mouseclick + + if(!IsInSelect() && TestCurrPam(*pPt)) { + ClearMark(); + } + + return SwCursorShell::SetCursor(*pPt, bTextOnly); +} + +tools::Long SwWrtShell::SetCursorKillSel(const Point *pPt, bool bTextOnly ) +{ + SwActContext aActContext(this); + ResetSelect(pPt,false); + return SwCursorShell::SetCursor(*pPt, bTextOnly); +} + +void SwWrtShell::UnSelectFrame() +{ + // Remove Frame selection with guaranteed invalid position + Point aPt(LONG_MIN, LONG_MIN); + SelectObj(aPt); + SwTransferable::ClearSelection( *this ); +} + +// Remove of all selections + +tools::Long SwWrtShell::ResetSelect(const Point *,bool) +{ + if(IsSelFrameMode()) + { + UnSelectFrame(); + LeaveSelFrameMode(); + } + else + { + // SwActContext opens an Action - + // to avoid problems in the basic process with the + // shell switching, GetChgLnk().Call() may be called + // after EndAction(). + { + SwActContext aActContext(this); + m_bSelWrd = m_bSelLn = false; + KillPams(); + ClearMark(); + m_fnKillSel = &SwWrtShell::Ignore; + m_fnSetCursor = &SwWrtShell::SetCursor; + } + + // After canceling of all selections an update of Attr-Controls + // could be necessary. + GetChgLnk().Call(nullptr); + + if ( GetEnhancedTableSelection() != SwTable::SEARCH_NONE ) + UnsetEnhancedTableSelection(); + } + Invalidate(); + SwTransferable::ClearSelection( *this ); + return 1; +} + +bool SwWrtShell::IsSplitVerticalByDefault() const +{ + return GetDoc()->IsSplitVerticalByDefault(); +} + +void SwWrtShell::SetSplitVerticalByDefault(bool value) +{ + GetDoc()->SetSplitVerticalByDefault(value); +} + +// Do nothing + +tools::Long SwWrtShell::Ignore(const Point *, bool ) { + return 1; +} + +// Begin of a selection process. + +void SwWrtShell::SttSelect() +{ + if(m_bInSelect) + return; + if(!HasMark()) + SetMark(); + if( m_bBlockMode ) + { + SwShellCursor* pTmp = getShellCursor( true ); + if( !pTmp->HasMark() ) + pTmp->SetMark(); + } + m_fnKillSel = &SwWrtShell::Ignore; + m_fnSetCursor = &SwWrtShell::SetCursor; + m_bInSelect = true; + Invalidate(); + SwTransferable::CreateSelection( *this ); +} + +namespace { + +void collectUIInformation(SwShellCursor* pCursor) +{ + EventDescription aDescription; + OUString aSelStart = OUString::number(pCursor->Start()->nContent.GetIndex()); + OUString aSelEnd = OUString::number(pCursor->End()->nContent.GetIndex()); + + aDescription.aParameters = {{"START_POS", aSelStart}, {"END_POS", aSelEnd}}; + aDescription.aAction = "SELECT"; + aDescription.aID = "writer_edit"; + aDescription.aKeyWord = "SwEditWinUIObject"; + aDescription.aParent = "MainWindow"; + + UITestLogger::getInstance().logEvent(aDescription); +} + +} + +// End of a selection process. + +void SwWrtShell::EndSelect() +{ + if(m_bInSelect && !m_bExtMode) + { + m_bInSelect = false; + if (m_bAddMode) + { + AddLeaveSelect(); + } + else + { + SttLeaveSelect(); + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_fnKillSel = &SwWrtShell::ResetSelect; + } + } + SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); + if (pWrdCnt) + pWrdCnt->UpdateCounts(); + + collectUIInformation(GetCursor_()); +} + +void SwWrtShell::ExtSelWrd(const Point *pPt, bool ) +{ + SwMvContext aMvContext(this); + if( IsTableMode() ) + return; + + // Bug 66823: actual crsr has in additional mode no selection? + // Then destroy the actual and go to prev, this will be expand + if( !HasMark() && GoPrevCursor() ) + { + bool bHasMark = HasMark(); // that's wrong! + GoNextCursor(); + if( bHasMark ) + { + DestroyCursor(); + GoPrevCursor(); + } + } + + // check the direction of the selection with the new point + bool bMoveCursor = true, bToTop = false; + SwCursorShell::SelectWord( &m_aStart ); // select the startword + SwCursorShell::Push(); // save the cursor + SwCursorShell::SetCursor( *pPt ); // and check the direction + + switch( SwCursorShell::CompareCursorStackMkCurrPt()) + { + case -1: bToTop = false; break; + case 1: bToTop = true; break; + default: bMoveCursor = false; break; + } + + SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); // restore the saved cursor + + if( !bMoveCursor ) + return; + + // select to Top but cursor select to Bottom? or + // select to Bottom but cursor select to Top? --> swap the cursor + if( bToTop ) + SwapPam(); + + SwCursorShell::Push(); // save cur cursor + if( SwCursorShell::SelectWord( pPt )) // select the current word + { + if( bToTop ) + SwapPam(); + Combine(); + } + else + { + SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); + if( bToTop ) + SwapPam(); + } +} + +void SwWrtShell::ExtSelLn(const Point *pPt, bool ) +{ + SwMvContext aMvContext(this); + SwCursorShell::SetCursor(*pPt); + if( IsTableMode() ) + return; + + // Bug 66823: actual crsr has in additional mode no selection? + // Then destroy the actual and go to prev, this will be expand + if( !HasMark() && GoPrevCursor() ) + { + bool bHasMark = HasMark(); // that's wrong! + GoNextCursor(); + if( bHasMark ) + { + DestroyCursor(); + GoPrevCursor(); + } + } + + // if applicable fit the selection to the "Mark" + bool bToTop = !IsCursorPtAtEnd(); + SwapPam(); + + // The "Mark" has to be at the end or the beginning of the line. + if( bToTop ? !IsEndSentence() : !IsStartSentence() ) + { + if( bToTop ) + { + if( !IsEndPara() ) + SwCursorShell::Right(1,CRSR_SKIP_CHARS); + SwCursorShell::GoEndSentence(); + } + else + SwCursorShell::GoStartSentence(); + } + SwapPam(); + + if (bToTop) + SwCursorShell::GoStartSentence(); + else + SwCursorShell::GoEndSentence(); +} + +// Back into the standard mode: no mode, no selections. + +void SwWrtShell::EnterStdMode() +{ + if(m_bAddMode) + LeaveAddMode(); + if(m_bBlockMode) + LeaveBlockMode(); + m_bBlockMode = false; + m_bExtMode = false; + m_bInSelect = false; + if(IsSelFrameMode()) + { + UnSelectFrame(); + LeaveSelFrameMode(); + } + else + { + // SwActContext opens and action which has to be + // closed prior to the call of + // GetChgLnk().Call() + SwActContext aActContext(this); + m_bSelWrd = m_bSelLn = false; + if( !IsRetainSelection() ) + KillPams(); + ClearMark(); + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_fnKillSel = &SwWrtShell::ResetSelect; + } + Invalidate(); + SwTransferable::ClearSelection( *this ); +} + +// Extended Mode + +void SwWrtShell::EnterExtMode() +{ + if(m_bBlockMode) + { + LeaveBlockMode(); + KillPams(); + ClearMark(); + } + m_bExtMode = true; + m_bAddMode = false; + m_bBlockMode = false; + SttSelect(); +} + +void SwWrtShell::LeaveExtMode() +{ + m_bExtMode = false; + EndSelect(); +} + +// End of a selection; if the selection is empty, +// ClearMark(). + +void SwWrtShell::SttLeaveSelect() +{ + if(SwCursorShell::HasSelection() && !IsSelTableCells() && m_bClearMark) { + return; + } + ClearMark(); +} + +// Leaving of the selection mode in additional mode + +void SwWrtShell::AddLeaveSelect() +{ + if(IsTableMode()) LeaveAddMode(); + else if(SwCursorShell::HasSelection()) + CreateCursor(); +} + +// Additional Mode + +void SwWrtShell::EnterAddMode() +{ + if(IsTableMode()) return; + if(m_bBlockMode) + LeaveBlockMode(); + m_fnKillSel = &SwWrtShell::Ignore; + m_fnSetCursor = &SwWrtShell::SetCursor; + m_bAddMode = true; + m_bBlockMode = false; + m_bExtMode = false; + if(SwCursorShell::HasSelection()) + CreateCursor(); + Invalidate(); +} + +void SwWrtShell::LeaveAddMode() +{ + m_fnKillSel = &SwWrtShell::ResetSelect; + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_bAddMode = false; + Invalidate(); +} + +// Block Mode + +void SwWrtShell::EnterBlockMode() +{ + m_bBlockMode = false; + EnterStdMode(); + m_bBlockMode = true; + CursorToBlockCursor(); + Invalidate(); +} + +void SwWrtShell::LeaveBlockMode() +{ + m_bBlockMode = false; + BlockCursorToCursor(); + EndSelect(); + Invalidate(); +} + +// Insert mode + +void SwWrtShell::SetInsMode( bool bOn ) +{ + m_bIns = bOn; + SwCursorShell::SetOverwriteCursor( !m_bIns ); + const SfxBoolItem aTmp( SID_ATTR_INSERT, m_bIns ); + GetView().GetViewFrame()->GetBindings().SetState( aTmp ); + StartAction(); + EndAction(); + Invalidate(); +} +//Overwrite mode is incompatible with red-lining +void SwWrtShell::SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode ) +{ + SetRedlineFlags( eMode ); + if (IsRedlineOn()) + SetInsMode(); +} + +// Edit frame + +void SwWrtShell::BeginFrameDrag(const Point *pPt, bool bIsShift) +{ + m_fnDrag = &SwFEShell::Drag; + if(bStartDrag) + { + Point aTmp( nStartDragX, nStartDragY ); + SwFEShell::BeginDrag( &aTmp, bIsShift ); + } + else + SwFEShell::BeginDrag( pPt, bIsShift ); +} + +void SwWrtShell::EnterSelFrameMode(const Point *pPos) +{ + if(pPos) + { + nStartDragX = pPos->X(); + nStartDragY = pPos->Y(); + bStartDrag = true; + } + m_bLayoutMode = true; + HideCursor(); + + // equal call of BeginDrag in the SwFEShell + m_fnDrag = &SwWrtShell::BeginFrameDrag; + m_fnEndDrag = &SwWrtShell::UpdateLayoutFrame; + SwBaseShell::SetFrameMode( FLY_DRAG_START, this ); + Invalidate(); +} + +void SwWrtShell::LeaveSelFrameMode() +{ + m_fnDrag = &SwWrtShell::BeginDrag; + m_fnEndDrag = &SwWrtShell::DefaultEndDrag; + m_bLayoutMode = false; + bStartDrag = false; + Edit(); + SwBaseShell::SetFrameMode( FLY_DRAG_END, this ); + Invalidate(); +} + +// Description: execute framebound macro + +IMPL_LINK( SwWrtShell, ExecFlyMac, const SwFlyFrameFormat*, pFlyFormat, void ) +{ + const SwFrameFormat *pFormat = pFlyFormat ? static_cast<const SwFrameFormat*>(pFlyFormat) : GetFlyFrameFormat(); + OSL_ENSURE(pFormat, "no frame format"); + const SvxMacroItem &rFormatMac = pFormat->GetMacro(); + + if(rFormatMac.HasMacro(SvMacroItemId::SwObjectSelect)) + { + const SvxMacro &rMac = rFormatMac.GetMacro(SvMacroItemId::SwObjectSelect); + if( IsFrameSelected() ) + m_bLayoutMode = true; + CallChgLnk(); + ExecMacro( rMac ); + } +} + +void SwWrtShell::UpdateLayoutFrame(const Point *, bool ) +{ + // still a dummy + SwFEShell::EndDrag(); + m_fnDrag = &SwWrtShell::BeginFrameDrag; +} + +// Handler for toggling the modes. Returns back the old mode. + +void SwWrtShell::ToggleAddMode() +{ + m_bAddMode ? LeaveAddMode(): EnterAddMode(); + Invalidate(); +} + +void SwWrtShell::ToggleBlockMode() +{ + m_bBlockMode ? LeaveBlockMode(): EnterBlockMode(); + Invalidate(); +} + +void SwWrtShell::ToggleExtMode() +{ + m_bExtMode ? LeaveExtMode() : EnterExtMode(); + Invalidate(); +} + +// Dragging in standard mode (Selecting of content) + +void SwWrtShell::BeginDrag(const Point * /*pPt*/, bool ) +{ + if(m_bSelWrd) + { + m_bInSelect = true; + if( !IsCursorPtAtEnd() ) + SwapPam(); + + m_fnDrag = &SwWrtShell::ExtSelWrd; + m_fnSetCursor = &SwWrtShell::Ignore; + } + else if(m_bSelLn) + { + m_bInSelect = true; + m_fnDrag = &SwWrtShell::ExtSelLn; + m_fnSetCursor = &SwWrtShell::Ignore; + } + else + { + m_fnDrag = &SwWrtShell::DefaultDrag; + SttSelect(); + } +} + +void SwWrtShell::DefaultDrag(const Point *, bool ) +{ + if( IsSelTableCells() ) + m_aSelTableLink.Call(*this); +} + +void SwWrtShell::DefaultEndDrag(const Point * /*pPt*/, bool ) +{ + m_fnDrag = &SwWrtShell::BeginDrag; + if( IsExtSel() ) + LeaveExtSel(); + + if( IsSelTableCells() ) + m_aSelTableLink.Call(*this); + EndSelect(); +} + +// #i32329# Enhanced table selection +bool SwWrtShell::SelectTableRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag ) +{ + SwMvContext aMvContext(this); + SttSelect(); + if(SelTableRowCol( rPt, pEnd, bRowDrag )) + { + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_fnKillSel = &SwWrtShell::ResetSelect; + return true; + } + return false; +} + +// Description: Selection of a table line or column + +void SwWrtShell::SelectTableRow() +{ + if ( SelTableRow() ) + { + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_fnKillSel = &SwWrtShell::ResetSelect; + } +} + +void SwWrtShell::SelectTableCol() +{ + if ( SelTableCol() ) + { + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_fnKillSel = &SwWrtShell::ResetSelect; + } +} + +void SwWrtShell::SelectTableCell() +{ + if ( SelTableBox() ) + { + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + m_fnKillSel = &SwWrtShell::ResetSelect; + } +} + +// Description: Check if a word selection is present. +// According to the rules for intelligent cut / paste +// surrounding spaces are cut out. +// Return: Delivers the type of the word selection. + +int SwWrtShell::IntelligentCut(SelectionType nSelection, bool bCut) +{ + // On multiple selection no intelligent drag and drop + // there are multiple cursors, since a second was placed + // already at the target position. + if( IsAddMode() || !(nSelection & SelectionType::Text) ) + return NO_WORD; + + OUString sText; + CharClass& rCC = GetAppCharClass(); + + // If the first character is no word character, + // no word selected. + sal_Unicode cPrev = GetChar(false); + sal_Unicode cNext = GetChar(true, -1); + if( !cPrev || !cNext || + !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) || + !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) ) + return NO_WORD; + + cPrev = GetChar(false, -1); + cNext = GetChar(); + + int cWord = NO_WORD; + // is a word selected? + if (cPrev && cNext && + CH_TXTATR_BREAKWORD != cPrev && CH_TXTATR_INWORD != cPrev && + CH_TXTATR_BREAKWORD != cNext && CH_TXTATR_INWORD != cNext && + !rCC.isLetterNumeric( ( sText = OUString(cPrev) ), 0 ) && + !rCC.isLetterNumeric( ( sText = OUString(cNext) ), 0 ) ) + cWord = WORD_NO_SPACE; + + if(cWord == WORD_NO_SPACE && ' ' == cPrev ) + { + cWord = WORD_SPACE_BEFORE; + // delete the space before + if(bCut) + { + Push(); + if(IsCursorPtAtEnd()) + SwapPam(); + ClearMark(); + SetMark(); + SwCursorShell::Left(1,CRSR_SKIP_CHARS); + SwFEShell::Delete(true); + Pop(SwCursorShell::PopMode::DeleteCurrent); + } + } + else if(cWord == WORD_NO_SPACE && cNext == ' ') + { + cWord = WORD_SPACE_AFTER; + // delete the space behind + if(bCut) { + Push(); + if(!IsCursorPtAtEnd()) SwapPam(); + ClearMark(); + SetMark(); + SwCursorShell::Right(1,CRSR_SKIP_CHARS); + SwFEShell::Delete(true); + Pop(SwCursorShell::PopMode::DeleteCurrent); + } + } + return cWord; +} + + // jump to the next / previous hyperlink - inside text and also + // on graphics +void SwWrtShell::SelectNextPrevHyperlink( bool bNext ) +{ + StartAction(); + bool bRet = SwCursorShell::SelectNxtPrvHyperlink( bNext ); + if( !bRet ) // didn't find? wrap and check again + { + SwShellCursor* pCursor = GetCursor_(); + SwCursorSaveState aSaveState(*pCursor); + EnterStdMode(); + if( bNext ) + SttEndDoc(true); + else + SttEndDoc(false); + bRet = SwCursorShell::SelectNxtPrvHyperlink(bNext); + if (!bRet) // didn't find again? restore cursor position and bail + { + pCursor->RestoreSavePos(); + EndAction(true); // don't scroll to restored cursor position + return; + } + } + EndAction(); + + bool bCreateXSelection = false; + const bool bFrameSelected = IsFrameSelected() || IsObjSelected(); + if( IsSelection() ) + { + if ( bFrameSelected ) + UnSelectFrame(); + + // Set the function pointer for the canceling of the selection + // set at cursor + m_fnKillSel = &SwWrtShell::ResetSelect; + m_fnSetCursor = &SwWrtShell::SetCursorKillSel; + bCreateXSelection = true; + } + else if( bFrameSelected ) + { + EnterSelFrameMode(); + bCreateXSelection = true; + } + else if( (CNT_GRF | CNT_OLE ) & GetCntType() ) + { + SelectObj( GetCharRect().Pos() ); + EnterSelFrameMode(); + bCreateXSelection = true; + } + + if( bCreateXSelection ) + SwTransferable::CreateSelection( *this ); +} + +// For the preservation of the selection the cursor will be moved left +// after SetMark(), so that the cursor is not moved by inserting text. +// Because a present selection at the CORE page is cleared at the +// current cursor position, the cursor will be pushed on the stack. +// After moving, they will again resummarized. + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |