1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 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/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 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 . 18 */ 19 20 #include <swtypes.hxx> 21 #include <hintids.hxx> 22 #include <com/sun/star/accessibility/XAccessible.hpp> 23 #include <comphelper/string.hxx> 24 #include <com/sun/star/i18n/XBreakIterator.hpp> 25 #include <com/sun/star/i18n/ScriptType.hpp> 26 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp> 27 #include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp> 28 29 #include <com/sun/star/i18n/UnicodeScript.hpp> 30 #include <com/sun/star/ui/ContextMenuExecuteEvent.hpp> 31 32 #include <vcl/inputctx.hxx> 33 #include <vcl/help.hxx> 34 #include <vcl/weld.hxx> 35 #include <vcl/ptrstyle.hxx> 36 #include <svl/macitem.hxx> 37 #include <unotools/securityoptions.hxx> 38 #include <basic/sbxvar.hxx> 39 #include <svl/ctloptions.hxx> 40 #include <basic/sbx.hxx> 41 #include <svl/eitem.hxx> 42 #include <svl/stritem.hxx> 43 #include <sfx2/ipclient.hxx> 44 #include <sfx2/viewfrm.hxx> 45 #include <sfx2/request.hxx> 46 #include <sfx2/bindings.hxx> 47 #include <sfx2/dispatch.hxx> 48 #include <svl/ptitem.hxx> 49 #include <editeng/sizeitem.hxx> 50 #include <editeng/langitem.hxx> 51 #include <svx/svdview.hxx> 52 #include <svx/svdhdl.hxx> 53 #include <svx/svdoutl.hxx> 54 #include <editeng/editeng.hxx> 55 #include <editeng/editview.hxx> 56 #include <editeng/svxacorr.hxx> 57 #include <editeng/flditem.hxx> 58 #include <editeng/colritem.hxx> 59 #include <unotools/charclass.hxx> 60 #include <unotools/datetime.hxx> 61 62 #include <comphelper/lok.hxx> 63 #include <sfx2/lokhelper.hxx> 64 65 #include <editeng/acorrcfg.hxx> 66 #include <SwSmartTagMgr.hxx> 67 #include <edtdd.hxx> 68 #include <edtwin.hxx> 69 #include <view.hxx> 70 #include <wrtsh.hxx> 71 #include <IDocumentDrawModelAccess.hxx> 72 #include <IDocumentUndoRedo.hxx> 73 #include <textboxhelper.hxx> 74 #include <dcontact.hxx> 75 #include <fldbas.hxx> 76 #include <swmodule.hxx> 77 #include <docsh.hxx> 78 #include <viewopt.hxx> 79 #include <drawbase.hxx> 80 #include <dselect.hxx> 81 #include <textsh.hxx> 82 #include <shdwcrsr.hxx> 83 #include <txatbase.hxx> 84 #include <fmtanchr.hxx> 85 #include <fmtornt.hxx> 86 #include <fmthdft.hxx> 87 #include <frmfmt.hxx> 88 #include <modcfg.hxx> 89 #include <fmtcol.hxx> 90 #include <wview.hxx> 91 #include <gloslst.hxx> 92 #include <inputwin.hxx> 93 #include <gloshdl.hxx> 94 #include <swundo.hxx> 95 #include <drwtxtsh.hxx> 96 #include <fchrfmt.hxx> 97 #include "romenu.hxx" 98 #include <initui.hxx> 99 #include <frmatr.hxx> 100 #include <extinput.hxx> 101 #include <acmplwrd.hxx> 102 #include <swcalwrp.hxx> 103 #include <swdtflvr.hxx> 104 #include <breakit.hxx> 105 #include <checkit.hxx> 106 #include <pagefrm.hxx> 107 108 #include <helpids.h> 109 #include <cmdid.h> 110 #include <uitool.hxx> 111 #include <fmtfollowtextflow.hxx> 112 #include <toolkit/helper/vclunohelper.hxx> 113 #include <charfmt.hxx> 114 #include <numrule.hxx> 115 #include <pagedesc.hxx> 116 #include <svtools/ruler.hxx> 117 #include <formatclipboard.hxx> 118 #include <vcl/svapp.hxx> 119 #include <wordcountdialog.hxx> 120 #include <fmtfld.hxx> 121 122 #include <IMark.hxx> 123 #include <doc.hxx> 124 #include <xmloff/odffields.hxx> 125 126 #include <PostItMgr.hxx> 127 #include <FrameControlsManager.hxx> 128 #include <AnnotationWin.hxx> 129 130 #include <algorithm> 131 #include <vector> 132 133 #include <rootfrm.hxx> 134 135 #include <unotools/syslocaleoptions.hxx> 136 #include <i18nlangtag/mslangid.hxx> 137 #include <salhelper/singletonref.hxx> 138 #include <sfx2/event.hxx> 139 #include <memory> 140 141 #include <IDocumentOutlineNodes.hxx> 142 #include <ndtxt.hxx> 143 #include <cntfrm.hxx> 144 #include <txtfrm.hxx> 145 #include <strings.hrc> 146 147 using namespace sw::mark; 148 using namespace ::com::sun::star; 149 150 /** 151 * Globals 152 */ 153 static bool g_bInputLanguageSwitched = false; 154 155 // Usually in MouseButtonUp a selection is revoked when the selection is 156 // not currently being pulled open. Unfortunately in MouseButtonDown there 157 // is being selected at double/triple click. That selection is completely 158 // finished in the Handler and thus can't be distinguished in the Up. 159 // To resolve this g_bHoldSelection is set in Down and evaluated in Up. 160 static bool g_bHoldSelection = false; 161 162 bool g_bFrameDrag = false; 163 static bool g_bValidCursorPos = false; 164 static bool g_bModePushed = false; 165 bool g_bDDTimerStarted = false; 166 bool g_bFlushCharBuffer = false; 167 bool g_bDDINetAttr = false; 168 static SdrHdlKind g_eSdrMoveHdl = SdrHdlKind::User; 169 170 QuickHelpData* SwEditWin::m_pQuickHlpData = nullptr; 171 172 tools::Long SwEditWin::m_nDDStartPosY = 0; 173 tools::Long SwEditWin::m_nDDStartPosX = 0; 174 175 static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView ); 176 177 /// Check if the selected shape has a TextBox: if so, go into that instead. 178 static bool lcl_goIntoTextBox(SwEditWin& rEditWin, SwWrtShell& rSh) 179 { 180 SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0); 181 if (!pMark) 182 return false; 183 184 SdrObject* pSdrObject = pMark->GetMarkedSdrObj(); 185 SwFrameFormat* pObjectFormat = ::FindFrameFormat(pSdrObject); 186 if (SwFrameFormat* pTextBoxFormat = SwTextBoxHelper::getOtherTextBoxFormat(pObjectFormat, RES_DRAWFRMFMT)) 187 { 188 SdrObject* pTextBox = pTextBoxFormat->FindRealSdrObject(); 189 SdrView* pSdrView = rSh.GetDrawView(); 190 // Unmark the shape. 191 pSdrView->UnmarkAllObj(); 192 // Mark the textbox. 193 rSh.SelectObj(Point(), SW_ALLOW_TEXTBOX, pTextBox); 194 // Clear the DrawFuncPtr. 195 rEditWin.StopInsFrame(); 196 return true; 197 } 198 return false; 199 } 200 201 class SwAnchorMarker 202 { 203 SdrHdl* pHdl; 204 Point aHdlPos; 205 Point aLastPos; 206 bool bTopRightHandle; 207 public: 208 explicit SwAnchorMarker( SdrHdl* pH ) 209 : pHdl( pH ) 210 , aHdlPos( pH->GetPos() ) 211 , aLastPos( pH->GetPos() ) 212 , bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR ) 213 {} 214 const Point& GetLastPos() const { return aLastPos; } 215 void SetLastPos( const Point& rNew ) { aLastPos = rNew; } 216 void SetPos( const Point& rNew ) { pHdl->SetPos( rNew ); } 217 const Point& GetHdlPos() const { return aHdlPos; } 218 SdrHdl* GetHdl() const { return pHdl; } 219 void ChgHdl( SdrHdl* pNew ) 220 { 221 pHdl = pNew; 222 if ( pHdl ) 223 { 224 bTopRightHandle = (pHdl->GetKind() == SdrHdlKind::Anchor_TR); 225 } 226 } 227 Point GetPosForHitTest( const OutputDevice& rOut ) 228 { 229 Point aHitTestPos( pHdl->GetPos() ); 230 aHitTestPos = rOut.LogicToPixel( aHitTestPos ); 231 if ( bTopRightHandle ) 232 { 233 aHitTestPos += Point( -1, 1 ); 234 } 235 else 236 { 237 aHitTestPos += Point( 1, 1 ); 238 } 239 aHitTestPos = rOut.PixelToLogic( aHitTestPos ); 240 241 return aHitTestPos; 242 } 243 }; 244 245 /// Assists with auto-completion of AutoComplete words and AutoText names. 246 struct QuickHelpData 247 { 248 /// Strings that at least partially match an input word, and match length. 249 std::vector<std::pair<OUString, sal_uInt16>> m_aHelpStrings; 250 /// Index of the current help string. 251 sal_uInt16 nCurArrPos; 252 static constexpr sal_uInt16 nNoPos = std::numeric_limits<sal_uInt16>::max(); 253 254 /// Help data stores AutoText names rather than AutoComplete words. 255 bool m_bIsAutoText; 256 /// Display help string as a tip rather than inline. 257 bool m_bIsTip; 258 /// Tip ID when a help string is displayed as a tip. 259 void* nTipId; 260 /// Append a space character to the displayed help string (if appropriate). 261 bool m_bAppendSpace; 262 263 /// Help string is currently displayed. 264 bool m_bIsDisplayed; 265 266 QuickHelpData() { ClearContent(); } 267 268 void Move( QuickHelpData& rCpy ); 269 void ClearContent(); 270 void Start(SwWrtShell& rSh, bool bRestart); 271 void Stop( SwWrtShell& rSh ); 272 273 bool HasContent() const { return !m_aHelpStrings.empty() && nCurArrPos != nNoPos; } 274 const OUString& CurStr() const { return m_aHelpStrings[nCurArrPos].first; } 275 sal_uInt16 CurLen() const { return m_aHelpStrings[nCurArrPos].second; } 276 277 /// Next help string. 278 void Next( bool bEndLess ) 279 { 280 if( ++nCurArrPos >= m_aHelpStrings.size() ) 281 nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1; 282 } 283 /// Previous help string. 284 void Previous( bool bEndLess ) 285 { 286 if( 0 == nCurArrPos-- ) 287 nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0; 288 } 289 290 // Fills internal structures with hopefully helpful information. 291 void FillStrArr( SwWrtShell const & rSh, const OUString& rWord ); 292 void SortAndFilter(const OUString &rOrigWord); 293 }; 294 295 /** 296 * Avoid minimal movement shiver 297 */ 298 #define HIT_PIX 2 /* hit tolerance in pixel */ 299 #define MIN_MOVE 4 300 301 static bool IsMinMove(const Point &rStartPos, const Point &rLPt) 302 { 303 return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE || 304 std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE; 305 } 306 307 /** 308 * For MouseButtonDown - determine whether a DrawObject 309 * a NO SwgFrame was hit! Shift/Ctrl should only result 310 * in selecting, with DrawObjects; at SwgFlys to trigger 311 * hyperlinks if applicable (Download/NewWindow!) 312 */ 313 static bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt ) 314 { 315 bool bRet = true; 316 SdrObject* pObj; 317 switch( rSh.GetObjCntType( rPt, pObj )) 318 { 319 case OBJCNT_NONE: 320 case OBJCNT_FLY: 321 case OBJCNT_GRF: 322 case OBJCNT_OLE: 323 bRet = false; 324 break; 325 default:; //prevent warning 326 } 327 return bRet; 328 } 329 330 /* 331 * Switch pointer 332 */ 333 void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier ) 334 { 335 SetQuickHelpText(OUString()); 336 SwWrtShell &rSh = m_rView.GetWrtShell(); 337 if( m_pApplyTempl ) 338 { 339 PointerStyle eStyle = PointerStyle::Fill; 340 if ( rSh.IsOverReadOnlyPos( rLPt ) ) 341 { 342 m_pUserMarker.reset(); 343 344 eStyle = PointerStyle::NotAllowed; 345 } 346 else 347 { 348 SwRect aRect; 349 SwRect* pRect = &aRect; 350 const SwFrameFormat* pFormat = nullptr; 351 352 bool bFrameIsValidTarget = false; 353 if( m_pApplyTempl->m_pFormatClipboard ) 354 bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( SelectionType::Frame ); 355 else if( !m_pApplyTempl->nColor ) 356 bFrameIsValidTarget = ( m_pApplyTempl->eType == SfxStyleFamily::Frame ); 357 358 if( bFrameIsValidTarget && 359 nullptr !=(pFormat = rSh.GetFormatFromObj( rLPt, &pRect )) && 360 dynamic_cast<const SwFlyFrameFormat*>( pFormat) ) 361 { 362 //turn on highlight for frame 363 tools::Rectangle aTmp( pRect->SVRect() ); 364 365 if ( !m_pUserMarker ) 366 { 367 m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp )); 368 } 369 } 370 else 371 { 372 m_pUserMarker.reset(); 373 } 374 375 rSh.SwCursorShell::SetVisibleCursor( rLPt ); 376 } 377 SetPointer( eStyle ); 378 return; 379 } 380 381 if( !rSh.VisArea().Width() ) 382 return; 383 384 CurrShell aCurr(&rSh); 385 386 if ( IsChainMode() ) 387 { 388 SwRect aRect; 389 SwChainRet nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrameFormat(), rLPt ); 390 PointerStyle eStyle = nChainable != SwChainRet::OK 391 ? PointerStyle::ChainNotAllowed : PointerStyle::Chain; 392 if ( nChainable == SwChainRet::OK ) 393 { 394 tools::Rectangle aTmp( aRect.SVRect() ); 395 396 if ( !m_pUserMarker ) 397 { 398 m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp )); 399 } 400 } 401 else 402 { 403 m_pUserMarker.reset(); 404 } 405 406 SetPointer( eStyle ); 407 return; 408 } 409 410 bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); 411 if ( !bExecHyperlinks ) 412 { 413 SvtSecurityOptions aSecOpts; 414 const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink ); 415 if ( ( bSecureOption && nModifier == KEY_MOD1 ) || 416 ( !bSecureOption && nModifier != KEY_MOD1 ) ) 417 bExecHyperlinks = true; 418 } 419 420 const bool bExecSmarttags = nModifier == KEY_MOD1; 421 422 SdrView *pSdrView = rSh.GetDrawView(); 423 bool bPrefSdrPointer = false; 424 bool bHitHandle = false; 425 bool bCntAtPos = false; 426 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && 427 rSh.IsCursorReadonly(); 428 m_aActHitType = SdrHitKind::NONE; 429 PointerStyle eStyle = PointerStyle::Text; 430 if ( !pSdrView ) 431 bCntAtPos = true; 432 else if ( (bHitHandle = (pSdrView->PickHandle(rLPt) != nullptr)) ) 433 { 434 m_aActHitType = SdrHitKind::Object; 435 bPrefSdrPointer = true; 436 } 437 else 438 { 439 const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt ); 440 if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj ) 441 { 442 m_aActHitType = SdrHitKind::Object; 443 if (IsObjectSelect()) 444 eStyle = PointerStyle::Arrow; 445 else 446 bPrefSdrPointer = true; 447 } 448 else 449 { 450 SdrPageView* pPV = nullptr; 451 pSdrView->SetHitTolerancePixel( HIT_PIX ); 452 SdrObject* pObj = (bNotInSelObj && bExecHyperlinks) ? 453 pSdrView->PickObj(rLPt, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) : 454 nullptr; 455 if (pObj) 456 { 457 SdrObjMacroHitRec aTmp; 458 aTmp.aPos = rLPt; 459 aTmp.pPageView = pPV; 460 SetPointer( pObj->GetMacroPointer( aTmp ) ); 461 return; 462 } 463 else 464 { 465 // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so 466 // apparently this is used to determine whether this is a 467 // drawling layer object or not. 468 if ( rSh.IsObjSelectable( rLPt ) ) 469 { 470 if (pSdrView->IsTextEdit()) 471 { 472 m_aActHitType = SdrHitKind::NONE; 473 bPrefSdrPointer = true; 474 } 475 else 476 { 477 SdrViewEvent aVEvt; 478 SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt); 479 480 if (eHit == SdrHitKind::UrlField && bExecHyperlinks) 481 { 482 m_aActHitType = SdrHitKind::Object; 483 bPrefSdrPointer = true; 484 } 485 else 486 { 487 // if we're over a selected object, we show an 488 // ARROW by default. We only show a MOVE if 1) the 489 // object is selected, and 2) it may be moved 490 // (i.e., position is not protected). 491 bool bMovable = 492 (!bNotInSelObj) && 493 (rSh.IsObjSelected() || rSh.IsFrameSelected()) && 494 (rSh.IsSelObjProtected(FlyProtectFlags::Pos) == FlyProtectFlags::NONE); 495 496 SdrObject* pSelectableObj = rSh.GetObjAt(rLPt); 497 // Don't update pointer if this is a background image only. 498 if (pSelectableObj->GetLayer() != rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId()) 499 eStyle = bMovable ? PointerStyle::Move : PointerStyle::Arrow; 500 m_aActHitType = SdrHitKind::Object; 501 } 502 } 503 } 504 else 505 { 506 if ( rSh.IsFrameSelected() && !bNotInSelObj ) 507 { 508 // dvo: this branch appears to be dead and should be 509 // removed in a future version. Reason: The condition 510 // !bNotInSelObj means that this branch will only be 511 // executed in the cursor points inside a selected 512 // object. However, if this is the case, the previous 513 // if( rSh.IsObjSelectable(rLPt) ) must always be true: 514 // rLPt is inside a selected object, then obviously 515 // rLPt is over a selectable object. 516 if (rSh.IsSelObjProtected(FlyProtectFlags::Size) != FlyProtectFlags::NONE) 517 eStyle = PointerStyle::NotAllowed; 518 else 519 eStyle = PointerStyle::Move; 520 m_aActHitType = SdrHitKind::Object; 521 } 522 else 523 { 524 if ( m_rView.GetDrawFuncPtr() ) 525 bPrefSdrPointer = true; 526 else 527 bCntAtPos = true; 528 } 529 } 530 } 531 } 532 } 533 if ( bPrefSdrPointer ) 534 { 535 if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE)) 536 SetPointer( PointerStyle::NotAllowed ); 537 else 538 { 539 if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle) 540 SetPointer( PointerStyle::DrawRect ); 541 else 542 SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) ); 543 } 544 } 545 else 546 { 547 if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker ) 548 eStyle = PointerStyle::Arrow; 549 else 550 { 551 // Even if we already have something, prefer URLs if possible. 552 SwContentAtPos aUrlPos(IsAttrAtPos::InetAttr); 553 if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos)) 554 { 555 SwContentAtPos aSwContentAtPos( 556 IsAttrAtPos::Field | 557 IsAttrAtPos::ClickField | 558 IsAttrAtPos::InetAttr | 559 IsAttrAtPos::Ftn | 560 IsAttrAtPos::SmartTag); 561 if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) ) 562 { 563 // Is edit inline input field 564 if (IsAttrAtPos::Field == aSwContentAtPos.eContentAtPos 565 && aSwContentAtPos.pFndTextAttr != nullptr 566 && aSwContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD) 567 { 568 const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr; 569 if (!(pCursorField && pCursorField == aSwContentAtPos.pFndTextAttr->GetFormatField().GetField())) 570 eStyle = PointerStyle::RefHand; 571 } 572 else 573 { 574 const bool bClickToFollow = IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos || 575 IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos; 576 if( !bClickToFollow || 577 (IsAttrAtPos::InetAttr == aSwContentAtPos.eContentAtPos && bExecHyperlinks) || 578 (IsAttrAtPos::SmartTag == aSwContentAtPos.eContentAtPos && bExecSmarttags) ) 579 eStyle = PointerStyle::RefHand; 580 } 581 } 582 else if (GetView().GetWrtShell().GetViewOptions()->IsShowOutlineContentVisibilityButton()) 583 { 584 aSwContentAtPos.eContentAtPos = IsAttrAtPos::Outline; 585 if (rSh.GetContentAtPos(rLPt, aSwContentAtPos)) 586 { 587 if (IsAttrAtPos::Outline == aSwContentAtPos.eContentAtPos) 588 { 589 if (nModifier == KEY_MOD1) 590 { 591 eStyle = PointerStyle::RefHand; 592 // set quick help 593 if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode()) 594 { 595 const SwNodes& rNds = GetView().GetWrtShell().GetDoc()->GetNodes(); 596 SwOutlineNodes::size_type nPos; 597 rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos); 598 SwOutlineNodes::size_type nOutlineNodesCount 599 = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); 600 int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos); 601 OUString sQuickHelp(SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY)); 602 if (!rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent() 603 && nPos + 1 < nOutlineNodesCount 604 && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos + 1) > nLevel) 605 sQuickHelp += " (" + SwResId(STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")"; 606 SetQuickHelpText(sQuickHelp); 607 } 608 } 609 } 610 } 611 } 612 } 613 } 614 615 // which kind of text pointer have we to show - horz / vert - ? 616 if( PointerStyle::Text == eStyle && rSh.IsInVerticalText( &rLPt )) 617 eStyle = PointerStyle::TextVertical; 618 else if (rSh.GetViewOptions()->CanHideWhitespace() && 619 rSh.GetLayout()->IsBetweenPages(rLPt)) 620 { 621 if (rSh.GetViewOptions()->IsHideWhitespaceMode()) 622 eStyle = PointerStyle::ShowWhitespace; 623 else 624 eStyle = PointerStyle::HideWhitespace; 625 } 626 627 SetPointer( eStyle ); 628 } 629 } 630 631 /** 632 * Increase timer for selection 633 */ 634 IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void) 635 { 636 SwWrtShell &rSh = m_rView.GetWrtShell(); 637 Point aModPt( m_aMovePos ); 638 const SwRect aOldVis( rSh.VisArea() ); 639 bool bDone = false; 640 641 if ( !rSh.VisArea().IsInside( aModPt ) ) 642 { 643 if ( m_bInsDraw ) 644 { 645 const int nMaxScroll = 40; 646 m_rView.Scroll( tools::Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll); 647 bDone = true; 648 } 649 else if ( g_bFrameDrag ) 650 { 651 rSh.Drag(&aModPt, false); 652 bDone = true; 653 } 654 if ( !bDone ) 655 aModPt = rSh.GetContentPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() ); 656 } 657 if ( !bDone && !(g_bFrameDrag || m_bInsDraw) ) 658 { 659 if ( m_xRowColumnSelectionStart ) 660 { 661 Point aPos( aModPt ); 662 rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag ); 663 } 664 else 665 rSh.CallSetCursor( &aModPt, false ); 666 667 // It can be that a "jump" over a table cannot be accomplished like 668 // that. So we jump over the table by Up/Down here. 669 const SwRect& rVisArea = rSh.VisArea(); 670 if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() ) 671 { 672 // take the center point of VisArea to 673 // decide in which direction the user want. 674 if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) ) 675 rSh.Up( true ); 676 else 677 rSh.Down( true ); 678 } 679 } 680 681 m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos(); 682 JustifyAreaTimer(); 683 } 684 685 void SwEditWin::JustifyAreaTimer() 686 { 687 const tools::Rectangle &rVisArea = GetView().GetVisArea(); 688 #ifdef UNX 689 const tools::Long coMinLen = 100; 690 #else 691 const tools::Long coMinLen = 50; 692 #endif 693 tools::Long const nTimeout = 800, 694 nDiff = std::max( 695 std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ), 696 std::max( m_aMovePos.X() - rVisArea.Right(), rVisArea.Left() - m_aMovePos.X())); 697 m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) ); 698 } 699 700 void SwEditWin::LeaveArea(const Point &rPos) 701 { 702 m_aMovePos = rPos; 703 JustifyAreaTimer(); 704 if( !m_aTimer.IsActive() ) 705 m_aTimer.Start(); 706 m_pShadCursor.reset(); 707 } 708 709 inline void SwEditWin::EnterArea() 710 { 711 m_aTimer.Stop(); 712 } 713 714 /** 715 * Insert mode for frames 716 */ 717 void SwEditWin::InsFrame(sal_uInt16 nCols) 718 { 719 StdDrawMode( OBJ_NONE, false ); 720 m_bInsFrame = true; 721 m_nInsFrameColCount = nCols; 722 } 723 724 void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect ) 725 { 726 SetSdrDrawMode( eSdrObjectKind ); 727 728 if (bObjSelect) 729 m_rView.SetDrawFuncPtr(std::make_unique<DrawSelection>( &m_rView.GetWrtShell(), this, &m_rView )); 730 else 731 m_rView.SetDrawFuncPtr(std::make_unique<SwDrawBase>( &m_rView.GetWrtShell(), this, &m_rView )); 732 733 m_rView.SetSelDrawSlot(); 734 SetSdrDrawMode( eSdrObjectKind ); 735 if (bObjSelect) 736 m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT ); 737 else 738 m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) ); 739 m_bInsFrame = false; 740 m_nInsFrameColCount = 1; 741 } 742 743 void SwEditWin::StopInsFrame() 744 { 745 if (m_rView.GetDrawFuncPtr()) 746 { 747 m_rView.GetDrawFuncPtr()->Deactivate(); 748 m_rView.SetDrawFuncPtr(nullptr); 749 } 750 m_rView.LeaveDrawCreate(); // leave construction mode 751 m_bInsFrame = false; 752 m_nInsFrameColCount = 1; 753 } 754 755 bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCursor ) 756 { 757 const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); 758 if ( !rCTLOptions.IsCTLFontEnabled() || 759 !rCTLOptions.IsCTLSequenceChecking() ) 760 return false; 761 762 if ( 0 == rCursor.Start()->nContent.GetIndex() ) /* first char needs not to be checked */ 763 return false; 764 765 SwBreakIt *pBreakIter = SwBreakIt::Get(); 766 uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter(); 767 assert(xBI.is()); 768 tools::Long nCTLScriptPos = -1; 769 770 if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX) 771 nCTLScriptPos = 0; 772 else 773 nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX ); 774 775 return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength()); 776 } 777 778 //return INVALID_HINT if language should not be explicitly overridden, the correct 779 //HintId to use for the eBufferLanguage otherwise 780 static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView const & rView, 781 const OUString &rInBuffer) 782 { 783 sal_uInt16 nWhich = INVALID_HINT; 784 785 //If the option to IgnoreLanguageChange is set, short-circuit this method 786 //which results in the document/paragraph language remaining the same 787 //despite a change to the keyboard/input language 788 SvtSysLocaleOptions aSysLocaleOptions; 789 if(aSysLocaleOptions.IsIgnoreLanguageChange()) 790 { 791 return INVALID_HINT; 792 } 793 794 bool bLang = true; 795 if(eBufferLanguage != LANGUAGE_DONTKNOW) 796 { 797 switch( SvtLanguageOptions::GetI18NScriptTypeOfLanguage( eBufferLanguage )) 798 { 799 case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break; 800 case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break; 801 case i18n::ScriptType::LATIN: nWhich = RES_CHRATR_LANGUAGE; break; 802 default: bLang = false; 803 } 804 if(bLang) 805 { 806 SfxItemSet aLangSet(rView.GetPool(), {{nWhich, nWhich}}); 807 SwWrtShell& rSh = rView.GetWrtShell(); 808 rSh.GetCurAttr(aLangSet); 809 if(SfxItemState::DEFAULT <= aLangSet.GetItemState(nWhich)) 810 { 811 LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage(); 812 if ( eLang == eBufferLanguage ) 813 { 814 // current language attribute equal to language reported from system 815 bLang = false; 816 } 817 else if ( !g_bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich ) 818 { 819 // special case: switching between two "LATIN" languages 820 // In case the current keyboard setting might be suitable 821 // for both languages we can't safely assume that the user 822 // wants to use the language reported from the system, 823 // except if we knew that it was explicitly switched (thus 824 // the check for "bInputLangeSwitched"). 825 826 // The language reported by the system could be just the 827 // system default language that the user is not even aware 828 // of, because no language selection tool is installed at 829 // all. In this case the OOo language should get preference 830 // as it might have been selected by the user explicitly. 831 832 // Usually this case happens if the OOo language is 833 // different to the system language but the system keyboard 834 // is still suitable for the OOo language (e.g. writing 835 // English texts with a German keyboard). 836 837 // For non-latin keyboards overwriting the attribute is 838 // still valid. We do this for cyrillic and greek ATM. In 839 // future versions of OOo this should be replaced by a 840 // configuration switch that allows to give the preference 841 // to the OOo setting or the system setting explicitly 842 // and/or a better handling of the script type. 843 i18n::UnicodeScript eType = !rInBuffer.isEmpty() ? 844 GetAppCharClass().getScript( rInBuffer, 0 ) : 845 i18n::UnicodeScript_kScriptCount; 846 847 bool bSystemIsNonLatin = false; 848 switch ( eType ) 849 { 850 case i18n::UnicodeScript_kGreek: 851 case i18n::UnicodeScript_kCyrillic: 852 // in case other UnicodeScripts require special 853 // keyboards they can be added here 854 bSystemIsNonLatin = true; 855 break; 856 default: 857 break; 858 } 859 860 bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang); 861 862 bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin); 863 } 864 } 865 } 866 } 867 return bLang ? nWhich : INVALID_HINT; 868 } 869 870 /** 871 * Character buffer is inserted into the document 872 */ 873 void SwEditWin::FlushInBuffer() 874 { 875 if ( m_aInBuffer.isEmpty() ) 876 return; 877 878 SwWrtShell& rSh = m_rView.GetWrtShell(); 879 880 // generate new sequence input checker if not already done 881 if ( !pCheckIt ) 882 pCheckIt = new SwCheckIt; 883 884 uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck; 885 if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCursor() ) ) 886 { 887 888 // apply (Thai) input sequence checking/correction 889 890 rSh.Push(); // push current cursor to stack 891 892 // get text from the beginning (i.e left side) of current selection 893 // to the start of the paragraph 894 rSh.NormalizePam(); // make point be the first (left) one 895 if (!rSh.GetCursor()->HasMark()) 896 rSh.GetCursor()->SetMark(); 897 rSh.GetCursor()->GetMark()->nContent = 0; 898 899 const OUString aOldText( rSh.GetCursor()->GetText() ); 900 const sal_Int32 nOldLen = aOldText.getLength(); 901 902 SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); 903 904 sal_Int32 nExpandSelection = 0; 905 if (nOldLen > 0) 906 { 907 sal_Int32 nTmpPos = nOldLen; 908 sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ? 909 i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC; 910 911 OUString aNewText( aOldText ); 912 if (rCTLOptions.IsCTLSequenceCheckingTypeAndReplace()) 913 { 914 for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k) 915 { 916 const sal_Unicode cChar = m_aInBuffer[k]; 917 const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ); 918 919 // valid sequence or sequence could be corrected: 920 if (nPrevPos != aNewText.getLength()) 921 nTmpPos = nPrevPos + 1; 922 } 923 924 // find position of first character that has changed 925 sal_Int32 nNewLen = aNewText.getLength(); 926 const sal_Unicode *pOldText = aOldText.getStr(); 927 const sal_Unicode *pNewText = aNewText.getStr(); 928 sal_Int32 nChgPos = 0; 929 while ( nChgPos < nOldLen && nChgPos < nNewLen && 930 pOldText[nChgPos] == pNewText[nChgPos] ) 931 ++nChgPos; 932 933 const sal_Int32 nChgLen = nNewLen - nChgPos; 934 if (nChgLen) 935 { 936 m_aInBuffer = aNewText.copy( nChgPos, nChgLen ); 937 nExpandSelection = nOldLen - nChgPos; 938 } 939 else 940 m_aInBuffer.clear(); 941 } 942 else 943 { 944 for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k ) 945 { 946 const sal_Unicode cChar = m_aInBuffer[k]; 947 if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode )) 948 { 949 // character can be inserted: 950 aNewText += OUStringChar( cChar ); 951 ++nTmpPos; 952 } 953 } 954 m_aInBuffer = aNewText.copy( aOldText.getLength() ); // copy new text to be inserted to buffer 955 } 956 } 957 958 // at this point now we will insert the buffer text 'normally' some lines below... 959 960 rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); 961 962 if (m_aInBuffer.isEmpty()) 963 return; 964 965 // if text prior to the original selection needs to be changed 966 // as well, we now expand the selection accordingly. 967 SwPaM &rCursor = *rSh.GetCursor(); 968 const sal_Int32 nCursorStartPos = rCursor.Start()->nContent.GetIndex(); 969 OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" ); 970 if (nExpandSelection && nCursorStartPos >= nExpandSelection) 971 { 972 if (!rCursor.HasMark()) 973 rCursor.SetMark(); 974 rCursor.Start()->nContent -= nExpandSelection; 975 } 976 } 977 978 uno::Reference< frame::XDispatchRecorder > xRecorder = 979 m_rView.GetViewFrame()->GetBindings().GetRecorder(); 980 if ( xRecorder.is() ) 981 { 982 // determine shell 983 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView ); 984 // generate request and record 985 if (pSfxShell) 986 { 987 SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING ); 988 aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) ); 989 aReq.Done(); 990 } 991 } 992 993 sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer); 994 if (nWhich != INVALID_HINT ) 995 { 996 SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich ); 997 rSh.SetAttrItem( aLangItem ); 998 } 999 1000 rSh.Insert( m_aInBuffer ); 1001 m_eBufferLanguage = LANGUAGE_DONTKNOW; 1002 m_aInBuffer.clear(); 1003 g_bFlushCharBuffer = false; 1004 1005 } 1006 1007 #define MOVE_LEFT_SMALL 0 1008 #define MOVE_UP_SMALL 1 1009 #define MOVE_RIGHT_BIG 2 1010 #define MOVE_DOWN_BIG 3 1011 #define MOVE_LEFT_BIG 4 1012 #define MOVE_UP_BIG 5 1013 #define MOVE_RIGHT_SMALL 6 1014 #define MOVE_DOWN_SMALL 7 1015 1016 // #i121236# Support for shift key in writer 1017 #define MOVE_LEFT_HUGE 8 1018 #define MOVE_UP_HUGE 9 1019 #define MOVE_RIGHT_HUGE 10 1020 #define MOVE_DOWN_HUGE 11 1021 1022 void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb ) 1023 { 1024 SwWrtShell &rSh = m_rView.GetWrtShell(); 1025 SwRect aTmp = rSh.GetFlyRect(); 1026 if( !aTmp.HasArea() || 1027 rSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE ) 1028 return; 1029 1030 SfxItemSet aSet( 1031 rSh.GetAttrPool(), 1032 svl::Items< 1033 RES_FRM_SIZE, RES_FRM_SIZE, 1034 RES_PROTECT, RES_PROTECT, 1035 RES_VERT_ORIENT, RES_ANCHOR, 1036 RES_COL, RES_COL, 1037 RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW>{}); 1038 rSh.GetFlyFrameAttr( aSet ); 1039 RndStdIds eAnchorId = aSet.Get(RES_ANCHOR).GetAnchorId(); 1040 Size aSnap; 1041 bool bHuge(MOVE_LEFT_HUGE == nDir || 1042 MOVE_UP_HUGE == nDir || 1043 MOVE_RIGHT_HUGE == nDir || 1044 MOVE_DOWN_HUGE == nDir); 1045 1046 if(MOVE_LEFT_SMALL == nDir || 1047 MOVE_UP_SMALL == nDir || 1048 MOVE_RIGHT_SMALL == nDir || 1049 MOVE_DOWN_SMALL == nDir ) 1050 { 1051 aSnap = PixelToLogic(Size(1,1)); 1052 } 1053 else 1054 { 1055 aSnap = rSh.GetViewOptions()->GetSnapSize(); 1056 short nDiv = rSh.GetViewOptions()->GetDivisionX(); 1057 if ( nDiv > 0 ) 1058 aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) ); 1059 nDiv = rSh.GetViewOptions()->GetDivisionY(); 1060 if ( nDiv > 0 ) 1061 aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) ); 1062 } 1063 1064 if(bHuge) 1065 { 1066 // #i121236# 567twips == 1cm, but just take three times the normal snap 1067 aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3); 1068 } 1069 1070 SwRect aBoundRect; 1071 Point aRefPoint; 1072 // adjustment for allowing vertical position 1073 // aligned to page for fly frame anchored to paragraph or to character. 1074 { 1075 const SwFormatVertOrient& aVert( aSet.Get(RES_VERT_ORIENT) ); 1076 const bool bFollowTextFlow = 1077 aSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue(); 1078 const SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor(); 1079 rSh.CalcBoundRect( aBoundRect, eAnchorId, 1080 text::RelOrientation::FRAME, aVert.GetRelationOrient(), 1081 pToCharContentPos, bFollowTextFlow, 1082 false, &aRefPoint ); 1083 } 1084 tools::Long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() ); 1085 tools::Long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() ); 1086 tools::Long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() ); 1087 tools::Long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() ); 1088 1089 switch ( nDir ) 1090 { 1091 case MOVE_LEFT_BIG: 1092 case MOVE_LEFT_HUGE: 1093 case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft ); 1094 break; 1095 1096 case MOVE_UP_BIG: 1097 case MOVE_UP_HUGE: 1098 case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp ); 1099 break; 1100 1101 case MOVE_RIGHT_SMALL: 1102 if( aTmp.Width() < aSnap.Width() + MINFLY ) 1103 break; 1104 nRight = aSnap.Width(); 1105 [[fallthrough]]; 1106 case MOVE_RIGHT_HUGE: 1107 case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight ); 1108 break; 1109 1110 case MOVE_DOWN_SMALL: 1111 if( aTmp.Height() < aSnap.Height() + MINFLY ) 1112 break; 1113 nDown = aSnap.Height(); 1114 [[fallthrough]]; 1115 case MOVE_DOWN_HUGE: 1116 case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown ); 1117 break; 1118 1119 default: OSL_ENSURE(true, "ChangeFly: Unknown direction." ); 1120 } 1121 bool bSet = false; 1122 if ((RndStdIds::FLY_AS_CHAR == eAnchorId) && ( nDir % 2 )) 1123 { 1124 tools::Long aDiff = aTmp.Top() - aRefPoint.Y(); 1125 if( aDiff > 0 ) 1126 aDiff = 0; 1127 else if ( aDiff < -aTmp.Height() ) 1128 aDiff = -aTmp.Height(); 1129 SwFormatVertOrient aVert( aSet.Get(RES_VERT_ORIENT) ); 1130 sal_Int16 eNew; 1131 if( bWeb ) 1132 { 1133 eNew = aVert.GetVertOrient(); 1134 bool bDown = 0 != ( nDir & 0x02 ); 1135 switch( eNew ) 1136 { 1137 case text::VertOrientation::CHAR_TOP: 1138 if( bDown ) eNew = text::VertOrientation::CENTER; 1139 break; 1140 case text::VertOrientation::CENTER: 1141 eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP; 1142 break; 1143 case text::VertOrientation::TOP: 1144 if( !bDown ) eNew = text::VertOrientation::CENTER; 1145 break; 1146 case text::VertOrientation::LINE_TOP: 1147 if( bDown ) eNew = text::VertOrientation::LINE_CENTER; 1148 break; 1149 case text::VertOrientation::LINE_CENTER: 1150 eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP; 1151 break; 1152 case text::VertOrientation::LINE_BOTTOM: 1153 if( !bDown ) eNew = text::VertOrientation::LINE_CENTER; 1154 break; 1155 default:; //prevent warning 1156 } 1157 } 1158 else 1159 { 1160 aVert.SetPos( aDiff ); 1161 eNew = text::VertOrientation::NONE; 1162 } 1163 aVert.SetVertOrient( eNew ); 1164 aSet.Put( aVert ); 1165 bSet = true; 1166 } 1167 if (bWeb && (RndStdIds::FLY_AT_PARA == eAnchorId) 1168 && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG )) 1169 { 1170 SwFormatHoriOrient aHori( aSet.Get(RES_HORI_ORIENT) ); 1171 sal_Int16 eNew; 1172 eNew = aHori.GetHoriOrient(); 1173 switch( eNew ) 1174 { 1175 case text::HoriOrientation::RIGHT: 1176 if( nDir==MOVE_LEFT_SMALL ) 1177 eNew = text::HoriOrientation::LEFT; 1178 break; 1179 case text::HoriOrientation::LEFT: 1180 if( nDir==MOVE_RIGHT_BIG ) 1181 eNew = text::HoriOrientation::RIGHT; 1182 break; 1183 default:; //prevent warning 1184 } 1185 if( eNew != aHori.GetHoriOrient() ) 1186 { 1187 aHori.SetHoriOrient( eNew ); 1188 aSet.Put( aHori ); 1189 bSet = true; 1190 } 1191 } 1192 rSh.StartAllAction(); 1193 if( bSet ) 1194 rSh.SetFlyFrameAttr( aSet ); 1195 bool bSetPos = (RndStdIds::FLY_AS_CHAR != eAnchorId); 1196 if(bSetPos && bWeb) 1197 { 1198 bSetPos = RndStdIds::FLY_AT_PAGE == eAnchorId; 1199 } 1200 if( bSetPos ) 1201 rSh.SetFlyPos( aTmp.Pos() ); 1202 rSh.EndAllAction(); 1203 1204 } 1205 1206 void SwEditWin::ChangeDrawing( sal_uInt8 nDir ) 1207 { 1208 // start undo action in order to get only one 1209 // undo action for this change. 1210 SwWrtShell &rSh = m_rView.GetWrtShell(); 1211 rSh.StartUndo(); 1212 1213 tools::Long nX = 0; 1214 tools::Long nY = 0; 1215 const bool bOnePixel( 1216 MOVE_LEFT_SMALL == nDir || 1217 MOVE_UP_SMALL == nDir || 1218 MOVE_RIGHT_SMALL == nDir || 1219 MOVE_DOWN_SMALL == nDir); 1220 const bool bHuge( 1221 MOVE_LEFT_HUGE == nDir || 1222 MOVE_UP_HUGE == nDir || 1223 MOVE_RIGHT_HUGE == nDir || 1224 MOVE_DOWN_HUGE == nDir); 1225 SwMove nAnchorDir = SwMove::UP; 1226 switch(nDir) 1227 { 1228 case MOVE_LEFT_SMALL: 1229 case MOVE_LEFT_HUGE: 1230 case MOVE_LEFT_BIG: 1231 nX = -1; 1232 nAnchorDir = SwMove::LEFT; 1233 break; 1234 case MOVE_UP_SMALL: 1235 case MOVE_UP_HUGE: 1236 case MOVE_UP_BIG: 1237 nY = -1; 1238 break; 1239 case MOVE_RIGHT_SMALL: 1240 case MOVE_RIGHT_HUGE: 1241 case MOVE_RIGHT_BIG: 1242 nX = +1; 1243 nAnchorDir = SwMove::RIGHT; 1244 break; 1245 case MOVE_DOWN_SMALL: 1246 case MOVE_DOWN_HUGE: 1247 case MOVE_DOWN_BIG: 1248 nY = +1; 1249 nAnchorDir = SwMove::DOWN; 1250 break; 1251 } 1252 1253 if(0 != nX || 0 != nY) 1254 { 1255 FlyProtectFlags nProtect = rSh.IsSelObjProtected( FlyProtectFlags::Pos|FlyProtectFlags::Size ); 1256 Size aSnap( rSh.GetViewOptions()->GetSnapSize() ); 1257 short nDiv = rSh.GetViewOptions()->GetDivisionX(); 1258 if ( nDiv > 0 ) 1259 aSnap.setWidth( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Width()) / nDiv ) ); 1260 nDiv = rSh.GetViewOptions()->GetDivisionY(); 1261 if ( nDiv > 0 ) 1262 aSnap.setHeight( std::max( sal_uLong(1), static_cast<sal_uLong>(aSnap.Height()) / nDiv ) ); 1263 1264 if(bOnePixel) 1265 { 1266 aSnap = PixelToLogic(Size(1,1)); 1267 } 1268 else if(bHuge) 1269 { 1270 // #i121236# 567twips == 1cm, but just take three times the normal snap 1271 aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3); 1272 } 1273 1274 nX *= aSnap.Width(); 1275 nY *= aSnap.Height(); 1276 1277 SdrView *pSdrView = rSh.GetDrawView(); 1278 const SdrHdlList& rHdlList = pSdrView->GetHdlList(); 1279 SdrHdl* pHdl = rHdlList.GetFocusHdl(); 1280 rSh.StartAllAction(); 1281 if(nullptr == pHdl) 1282 { 1283 // now move the selected draw objects 1284 // if the object's position is not protected 1285 if(!(nProtect&FlyProtectFlags::Pos)) 1286 { 1287 // Check if object is anchored as character and move direction 1288 bool bDummy1, bDummy2; 1289 const bool bVertAnchor = rSh.IsFrameVertical( true, bDummy1, bDummy2 ); 1290 bool bHoriMove = !bVertAnchor == !( nDir % 2 ); 1291 bool bMoveAllowed = 1292 !bHoriMove || (rSh.GetAnchorId() != RndStdIds::FLY_AS_CHAR); 1293 if ( bMoveAllowed ) 1294 { 1295 pSdrView->MoveAllMarked(Size(nX, nY)); 1296 rSh.SetModified(); 1297 } 1298 } 1299 } 1300 else 1301 { 1302 // move handle with index nHandleIndex 1303 if (nX || nY) 1304 { 1305 if( SdrHdlKind::Anchor == pHdl->GetKind() || 1306 SdrHdlKind::Anchor_TR == pHdl->GetKind() ) 1307 { 1308 // anchor move cannot be allowed when position is protected 1309 if(!(nProtect&FlyProtectFlags::Pos)) 1310 rSh.MoveAnchor( nAnchorDir ); 1311 } 1312 //now resize if size is protected 1313 else if(!(nProtect&FlyProtectFlags::Size)) 1314 { 1315 // now move the Handle (nX, nY) 1316 Point aStartPoint(pHdl->GetPos()); 1317 Point aEndPoint(pHdl->GetPos() + Point(nX, nY)); 1318 const SdrDragStat& rDragStat = pSdrView->GetDragStat(); 1319 1320 // start dragging 1321 pSdrView->BegDragObj(aStartPoint, nullptr, pHdl, 0); 1322 1323 if(pSdrView->IsDragObj()) 1324 { 1325 bool bWasNoSnap = rDragStat.IsNoSnap(); 1326 bool bWasSnapEnabled = pSdrView->IsSnapEnabled(); 1327 1328 // switch snapping off 1329 if(!bWasNoSnap) 1330 const_cast<SdrDragStat&>(rDragStat).SetNoSnap(); 1331 if(bWasSnapEnabled) 1332 pSdrView->SetSnapEnabled(false); 1333 1334 pSdrView->MovAction(aEndPoint); 1335 pSdrView->EndDragObj(); 1336 rSh.SetModified(); 1337 1338 // restore snap 1339 if(!bWasNoSnap) 1340 const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap); 1341 if(bWasSnapEnabled) 1342 pSdrView->SetSnapEnabled(bWasSnapEnabled); 1343 } 1344 } 1345 } 1346 } 1347 rSh.EndAllAction(); 1348 } 1349 1350 rSh.EndUndo(); 1351 } 1352 1353 /** 1354 * KeyEvents 1355 */ 1356 void SwEditWin::KeyInput(const KeyEvent &rKEvt) 1357 { 1358 SwWrtShell &rSh = m_rView.GetWrtShell(); 1359 1360 if (comphelper::LibreOfficeKit::isActive() && m_rView.GetPostItMgr()) 1361 { 1362 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->GetActiveSidebarWin()) 1363 { 1364 pWindow->KeyInput(rKEvt); 1365 return; 1366 } 1367 } 1368 1369 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) 1370 { 1371 // not allowed if outline content visibility is false 1372 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); 1373 if ((rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT)) 1374 || (rSh.IsEndOfPara() && (nKey == KEY_DELETE || nKey == KEY_RETURN || nKey == KEY_RIGHT))) 1375 { 1376 SwContentNode* pContentNode = rSh.GetCurrentShellCursor().GetContentNode(); 1377 SwOutlineNodes::size_type nPos; 1378 if (rSh.GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(pContentNode, &nPos)) 1379 { 1380 bool bOutlineContentVisibleAttr = true; 1381 pContentNode->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); 1382 if (!bOutlineContentVisibleAttr) 1383 return; // outline content visibility is false 1384 if (rSh.IsSttPara() && (nKey == KEY_BACKSPACE || nKey == KEY_LEFT) && (nPos-1 != SwOutlineNodes::npos)) 1385 { 1386 bOutlineContentVisibleAttr = true; 1387 rSh.GetDoc()->GetNodes().GetOutLineNds()[nPos-1]->GetTextNode()->GetAttrOutlineContentVisible(bOutlineContentVisibleAttr); 1388 if (!bOutlineContentVisibleAttr) 1389 return; // previous outline node has content visibility false 1390 } 1391 } 1392 } 1393 } 1394 1395 if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && 1396 m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard ) 1397 { 1398 m_pApplyTempl->m_pFormatClipboard->Erase(); 1399 SetApplyTemplate(SwApplyTemplate()); 1400 m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH); 1401 } 1402 else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && 1403 rSh.IsHeaderFooterEdit( ) ) 1404 { 1405 bool bHeader = bool(FrameTypeFlags::HEADER & rSh.GetFrameType(nullptr,false)); 1406 if ( bHeader ) 1407 rSh.SttPg(); 1408 else 1409 rSh.EndPg(); 1410 rSh.ToggleHeaderFooterEdit(); 1411 } 1412 1413 SfxObjectShell *pObjSh = m_rView.GetViewFrame()->GetObjectShell(); 1414 if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) ) 1415 // When the progress bar is active or a progress is 1416 // running on a document, no order is being taken 1417 return; 1418 1419 m_pShadCursor.reset(); 1420 m_aKeyInputFlushTimer.Stop(); 1421 1422 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && 1423 rSh.IsCursorReadonly(); 1424 1425 //if the language changes the buffer must be flushed 1426 LanguageType eNewLanguage = GetInputLanguage(); 1427 if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty()) 1428 { 1429 FlushInBuffer(); 1430 } 1431 m_eBufferLanguage = eNewLanguage; 1432 1433 QuickHelpData aTmpQHD; 1434 if( m_pQuickHlpData->m_bIsDisplayed ) 1435 { 1436 aTmpQHD.Move( *m_pQuickHlpData ); 1437 m_pQuickHlpData->Stop( rSh ); 1438 } 1439 1440 // OS:the DrawView also needs a readonly-Flag as well 1441 if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) ) 1442 { 1443 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false ); 1444 rSh.SetModified(); 1445 return; // Event evaluated by SdrView 1446 } 1447 1448 if ( m_rView.GetDrawFuncPtr() && m_bInsFrame ) 1449 { 1450 StopInsFrame(); 1451 rSh.Edit(); 1452 } 1453 1454 bool bFlushBuffer = false; 1455 bool bNormalChar = false; 1456 bool bAppendSpace = m_pQuickHlpData->m_bAppendSpace; 1457 m_pQuickHlpData->m_bAppendSpace = false; 1458 1459 if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 ) 1460 { 1461 if( rKEvt.GetKeyCode().IsShift()) 1462 { 1463 GetView().GetDocShell()->GetDoc()->dumpAsXml(); 1464 return; 1465 } 1466 else 1467 { 1468 SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout(); 1469 pLayout->dumpAsXml( ); 1470 return; 1471 } 1472 } 1473 1474 KeyEvent aKeyEvent( rKEvt ); 1475 // look for vertical mappings 1476 if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() ) 1477 { 1478 // must changed from switch to if, because the Linux 1479 // compiler has problem with the code. Has to remove if the new general 1480 // handler exist. 1481 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); 1482 1483 if( KEY_UP == nKey || KEY_DOWN == nKey || 1484 KEY_LEFT == nKey || KEY_RIGHT == nKey ) 1485 { 1486 // In general, we want to map the direction keys if we are inside 1487 // some vertical formatted text. 1488 // 1. Exception: For a table cursor in a horizontal table, the 1489 // directions should never be mapped. 1490 // 2. Exception: For a table cursor in a vertical table, the 1491 // directions should always be mapped. 1492 const bool bVertText = rSh.IsInVerticalText(); 1493 const bool bTableCursor = rSh.GetTableCursor(); 1494 const bool bVertTable = rSh.IsTableVertical(); 1495 if( ( bVertText && ( !bTableCursor || bVertTable ) ) || 1496 ( bTableCursor && bVertTable ) ) 1497 { 1498 SvxFrameDirection eDirection = rSh.GetTextDirection(); 1499 if (eDirection == SvxFrameDirection::Vertical_LR_BT) 1500 { 1501 // Map from physical to logical, so rotate clockwise. 1502 if (KEY_UP == nKey) 1503 nKey = KEY_RIGHT; 1504 else if (KEY_DOWN == nKey) 1505 nKey = KEY_LEFT; 1506 else if (KEY_LEFT == nKey) 1507 nKey = KEY_UP; 1508 else /* KEY_RIGHT == nKey */ 1509 nKey = KEY_DOWN; 1510 } 1511 else 1512 { 1513 // Attempt to integrate cursor travelling for mongolian layout does not work. 1514 // Thus, back to previous mapping of cursor keys to direction keys. 1515 if( KEY_UP == nKey ) nKey = KEY_LEFT; 1516 else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT; 1517 else if( KEY_LEFT == nKey ) nKey = KEY_DOWN; 1518 else /* KEY_RIGHT == nKey */ nKey = KEY_UP; 1519 } 1520 } 1521 1522 if ( rSh.IsInRightToLeftText() ) 1523 { 1524 if( KEY_LEFT == nKey ) nKey = KEY_RIGHT; 1525 else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT; 1526 } 1527 1528 aKeyEvent = KeyEvent( rKEvt.GetCharCode(), 1529 vcl::KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ), 1530 rKEvt.GetRepeat() ); 1531 } 1532 } 1533 1534 const vcl::KeyCode& rKeyCode = aKeyEvent.GetKeyCode(); 1535 sal_Unicode aCh = aKeyEvent.GetCharCode(); 1536 1537 // enable switching to notes anchor with Ctrl - Alt - Page Up/Down 1538 // pressing this inside a note will switch to next/previous note 1539 if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN))) 1540 { 1541 const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN; 1542 const SwFieldType* pFieldType = rSh.GetFieldType( 0, SwFieldIds::Postit ); 1543 rSh.MoveFieldType( pFieldType, bNext ); 1544 return; 1545 } 1546 1547 const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat(); 1548 if( pFlyFormat ) 1549 { 1550 SvMacroItemId nEvent; 1551 1552 if( 32 <= aCh && 1553 0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() )) 1554 nEvent = SvMacroItemId::SwFrmKeyInputAlpha; 1555 else 1556 nEvent = SvMacroItemId::SwFrmKeyInputNoAlpha; 1557 1558 const SvxMacro* pMacro = pFlyFormat->GetMacro().GetMacroTable().Get( nEvent ); 1559 if( pMacro ) 1560 { 1561 SbxArrayRef xArgs = new SbxArray; 1562 SbxVariableRef xVar = new SbxVariable; 1563 xVar->PutString( pFlyFormat->GetName() ); 1564 xArgs->Put32( xVar.get(), 1 ); 1565 1566 xVar = new SbxVariable; 1567 if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent ) 1568 xVar->PutChar( aCh ); 1569 else 1570 xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() ); 1571 xArgs->Put32( xVar.get(), 2 ); 1572 1573 OUString sRet; 1574 rSh.ExecMacro( *pMacro, &sRet, xArgs.get() ); 1575 if( !sRet.isEmpty() && sRet.toInt32()!=0 ) 1576 return ; 1577 } 1578 } 1579 SelectionType nLclSelectionType; 1580 //A is converted to 1 1581 if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT) 1582 && rSh.HasDrawView() && 1583 (bool(nLclSelectionType = rSh.GetSelectionType()) && 1584 ((nLclSelectionType & (SelectionType::Frame|SelectionType::Graphic)) || 1585 ((nLclSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) && 1586 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1)))) 1587 { 1588 SdrHdlList& rHdlList = const_cast<SdrHdlList&>(rSh.GetDrawView()->GetHdlList()); 1589 SdrHdl* pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor); 1590 if ( ! pAnchor ) 1591 pAnchor = rHdlList.GetHdl(SdrHdlKind::Anchor_TR); 1592 if(pAnchor) 1593 rHdlList.SetFocusHdl(pAnchor); 1594 return; 1595 } 1596 1597 SvxAutoCorrCfg* pACfg = nullptr; 1598 SvxAutoCorrect* pACorr = nullptr; 1599 1600 uno::Reference< frame::XDispatchRecorder > xRecorder = 1601 m_rView.GetViewFrame()->GetBindings().GetRecorder(); 1602 if ( !xRecorder.is() ) 1603 { 1604 pACfg = &SvxAutoCorrCfg::Get(); 1605 pACorr = pACfg->GetAutoCorrect(); 1606 } 1607 1608 SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); 1609 1610 OUString sFormulaEntry; 1611 1612 enum class SwKeyState { CheckKey, InsChar, InsTab, 1613 NoNum, NumOff, NumOrNoNum, NumDown, NumUp, 1614 NumIndentInc, NumIndentDec, 1615 1616 OutlineLvOff, 1617 NextCell, PrevCell, OutlineUp, OutlineDown, 1618 GlossaryExpand, NextPrevGlossary, 1619 AutoFormatByInput, 1620 NextObject, PrevObject, 1621 KeyToView, 1622 LaunchOLEObject, GoIntoFly, GoIntoDrawing, 1623 EnterDrawHandleMode, 1624 CheckDocReadOnlyKeys, 1625 CheckAutoCorrect, EditFormula, 1626 ColLeftBig, ColRightBig, 1627 ColLeftSmall, ColRightSmall, 1628 ColBottomBig, 1629 ColBottomSmall, 1630 CellLeftBig, CellRightBig, 1631 CellLeftSmall, CellRightSmall, 1632 CellTopBig, CellBottomBig, 1633 CellTopSmall, CellBottomSmall, 1634 1635 Fly_Change, Draw_Change, 1636 SpecialInsert, 1637 EnterCharCell, 1638 GotoNextFieldMark, 1639 GotoPrevFieldMark, 1640 End }; 1641 1642 SwKeyState eKeyState = bIsDocReadOnly ? SwKeyState::CheckDocReadOnlyKeys : SwKeyState::CheckKey; 1643 SwKeyState eNextKeyState = SwKeyState::End; 1644 sal_uInt8 nDir = 0; 1645 1646 if (m_nKS_NUMDOWN_Count > 0) 1647 m_nKS_NUMDOWN_Count--; 1648 1649 if (m_nKS_NUMINDENTINC_Count > 0) 1650 m_nKS_NUMINDENTINC_Count--; 1651 1652 while( SwKeyState::End != eKeyState ) 1653 { 1654 SwKeyState eFlyState = SwKeyState::KeyToView; 1655 1656 switch( eKeyState ) 1657 { 1658 case SwKeyState::CheckKey: 1659 eKeyState = SwKeyState::KeyToView; // default forward to View 1660 1661 #if OSL_DEBUG_LEVEL > 1 1662 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1663 // for switching cursor behaviour in ReadOnly regions 1664 if( 0x7210 == rKeyCode.GetFullCode() ) 1665 rSh.SetReadOnlyAvailable( !rSh.IsReadOnlyAvailable() ); 1666 else 1667 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1668 #endif 1669 1670 if (!comphelper::LibreOfficeKit::isActive() && 1671 !rKeyCode.IsMod2() && '=' == aCh && 1672 !rSh.IsTableMode() && rSh.GetTableFormat() && 1673 rSh.IsSttPara() && 1674 !rSh.HasReadonlySel()) 1675 { 1676 // at the beginning of the table's cell a '=' -> 1677 // call EditRow (F2-functionality) 1678 // [Avoid this for LibreOfficeKit, as the separate input window 1679 // steals the focus & things go wrong - the user never gets 1680 // the focus back.] 1681 rSh.Push(); 1682 if( !rSh.MoveSection( GoCurrSection, fnSectionStart) && 1683 !rSh.IsTableBoxTextFormat() ) 1684 { 1685 // is at the beginning of the box 1686 eKeyState = SwKeyState::EditFormula; 1687 if( rSh.HasMark() ) 1688 rSh.SwapPam(); 1689 else 1690 rSh.SttSelect(); 1691 rSh.MoveSection( GoCurrSection, fnSectionEnd ); 1692 rSh.Pop(); 1693 rSh.EndSelect(); 1694 sFormulaEntry = "="; 1695 } 1696 else 1697 rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); 1698 } 1699 else 1700 { 1701 if( pACorr && aTmpQHD.HasContent() && !rSh.HasSelection() && 1702 !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText && 1703 pACorr->GetSwFlags().nAutoCmpltExpandKey == 1704 (rKeyCode.GetModifier() | rKeyCode.GetCode()) ) 1705 { 1706 eKeyState = SwKeyState::GlossaryExpand; 1707 break; 1708 } 1709 1710 switch( rKeyCode.GetModifier() | rKeyCode.GetCode() ) 1711 { 1712 case KEY_RIGHT | KEY_MOD2: 1713 eKeyState = SwKeyState::ColRightBig; 1714 eFlyState = SwKeyState::Fly_Change; 1715 nDir = MOVE_RIGHT_SMALL; 1716 goto KEYINPUT_CHECKTABLE; 1717 1718 case KEY_LEFT | KEY_MOD2: 1719 eKeyState = SwKeyState::ColRightSmall; 1720 eFlyState = SwKeyState::Fly_Change; 1721 nDir = MOVE_LEFT_SMALL; 1722 goto KEYINPUT_CHECKTABLE; 1723 1724 case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT: 1725 eKeyState = SwKeyState::ColLeftSmall; 1726 goto KEYINPUT_CHECKTABLE; 1727 1728 case KEY_LEFT | KEY_MOD2 | KEY_SHIFT: 1729 eKeyState = SwKeyState::ColLeftBig; 1730 goto KEYINPUT_CHECKTABLE; 1731 1732 case KEY_RIGHT | KEY_MOD2 | KEY_MOD1: 1733 eKeyState = SwKeyState::CellRightBig; 1734 goto KEYINPUT_CHECKTABLE; 1735 1736 case KEY_LEFT | KEY_MOD2 | KEY_MOD1: 1737 eKeyState = SwKeyState::CellRightSmall; 1738 goto KEYINPUT_CHECKTABLE; 1739 1740 case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: 1741 eKeyState = SwKeyState::CellLeftSmall; 1742 goto KEYINPUT_CHECKTABLE; 1743 1744 case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: 1745 eKeyState = SwKeyState::CellLeftBig; 1746 goto KEYINPUT_CHECKTABLE; 1747 1748 case KEY_UP | KEY_MOD2: 1749 eKeyState = SwKeyState::ColBottomSmall; 1750 eFlyState = SwKeyState::Fly_Change; 1751 nDir = MOVE_UP_SMALL; 1752 goto KEYINPUT_CHECKTABLE; 1753 1754 case KEY_DOWN | KEY_MOD2: 1755 eKeyState = SwKeyState::ColBottomBig; 1756 eFlyState = SwKeyState::Fly_Change; 1757 nDir = MOVE_DOWN_SMALL; 1758 goto KEYINPUT_CHECKTABLE; 1759 1760 case KEY_UP | KEY_MOD2 | KEY_MOD1: 1761 eKeyState = SwKeyState::CellBottomSmall; 1762 goto KEYINPUT_CHECKTABLE; 1763 1764 case KEY_DOWN | KEY_MOD2 | KEY_MOD1: 1765 eKeyState = SwKeyState::CellBottomBig; 1766 goto KEYINPUT_CHECKTABLE; 1767 1768 case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: 1769 eKeyState = SwKeyState::CellTopBig; 1770 goto KEYINPUT_CHECKTABLE; 1771 1772 case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: 1773 eKeyState = SwKeyState::CellTopSmall; 1774 goto KEYINPUT_CHECKTABLE; 1775 1776 KEYINPUT_CHECKTABLE: 1777 if( rSh.IsTableMode() || !rSh.GetTableFormat() ) 1778 { 1779 if(!pFlyFormat && SwKeyState::KeyToView != eFlyState && 1780 (rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm)) && 1781 rSh.GetDrawView()->AreObjectsMarked()) 1782 eKeyState = SwKeyState::Draw_Change; 1783 1784 if( pFlyFormat ) 1785 eKeyState = eFlyState; 1786 else if( SwKeyState::Draw_Change != eKeyState) 1787 eKeyState = SwKeyState::EnterCharCell; 1788 } 1789 break; 1790 1791 // huge object move 1792 case KEY_RIGHT | KEY_SHIFT: 1793 case KEY_LEFT | KEY_SHIFT: 1794 case KEY_UP | KEY_SHIFT: 1795 case KEY_DOWN | KEY_SHIFT: 1796 { 1797 const SelectionType nSelectionType = rSh.GetSelectionType(); 1798 if ( ( pFlyFormat 1799 && ( nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic) ) ) 1800 || ( ( nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm) ) 1801 && rSh.GetDrawView()->AreObjectsMarked() ) ) 1802 { 1803 eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change; 1804 if (nSelectionType & SelectionType::DrawObject) 1805 { 1806 // tdf#137964: always move the DrawObject if one is selected 1807 eKeyState = SwKeyState::Draw_Change; 1808 } 1809 switch ( rKeyCode.GetCode() ) 1810 { 1811 case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break; 1812 case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break; 1813 case KEY_UP: nDir = MOVE_UP_HUGE; break; 1814 case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break; 1815 } 1816 } 1817 break; 1818 } 1819 1820 case KEY_LEFT: 1821 case KEY_LEFT | KEY_MOD1: 1822 { 1823 bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1); 1824 if(!bMod1) 1825 { 1826 eFlyState = SwKeyState::Fly_Change; 1827 nDir = MOVE_LEFT_BIG; 1828 } 1829 goto KEYINPUT_CHECKTABLE_INSDEL; 1830 } 1831 case KEY_RIGHT | KEY_MOD1: 1832 { 1833 goto KEYINPUT_CHECKTABLE_INSDEL; 1834 } 1835 case KEY_UP: 1836 case KEY_UP | KEY_MOD1: 1837 { 1838 bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1); 1839 if(!bMod1) 1840 { 1841 eFlyState = SwKeyState::Fly_Change; 1842 nDir = MOVE_UP_BIG; 1843 } 1844 goto KEYINPUT_CHECKTABLE_INSDEL; 1845 } 1846 case KEY_DOWN: 1847 case KEY_DOWN | KEY_MOD1: 1848 { 1849 bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1); 1850 if(!bMod1) 1851 { 1852 eFlyState = SwKeyState::Fly_Change; 1853 nDir = MOVE_DOWN_BIG; 1854 } 1855 goto KEYINPUT_CHECKTABLE_INSDEL; 1856 } 1857 1858 KEYINPUT_CHECKTABLE_INSDEL: 1859 if( rSh.IsTableMode() || !rSh.GetTableFormat() ) 1860 { 1861 const SelectionType nSelectionType = rSh.GetSelectionType(); 1862 1863 eKeyState = SwKeyState::KeyToView; 1864 if(SwKeyState::KeyToView != eFlyState) 1865 { 1866 if((nSelectionType & (SelectionType::DrawObject|SelectionType::DbForm)) && 1867 rSh.GetDrawView()->AreObjectsMarked()) 1868 eKeyState = SwKeyState::Draw_Change; 1869 else if(nSelectionType & (SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) 1870 eKeyState = SwKeyState::Fly_Change; 1871 } 1872 } 1873 break; 1874 1875 1876 case KEY_DELETE: 1877 if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField()) 1878 { 1879 if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum()) 1880 eKeyState = SwKeyState::NumOrNoNum; 1881 } 1882 else if (!rSh.IsCursorInParagraphMetadataField()) 1883 { 1884 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); 1885 std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); 1886 xInfo->run(); 1887 eKeyState = SwKeyState::End; 1888 } 1889 break; 1890 1891 case KEY_RETURN: 1892 { 1893 if ( !rSh.HasReadonlySel() 1894 && !rSh.CursorInsideInputField() ) 1895 { 1896 const SelectionType nSelectionType = rSh.GetSelectionType(); 1897 if(nSelectionType & SelectionType::Ole) 1898 eKeyState = SwKeyState::LaunchOLEObject; 1899 else if(nSelectionType & SelectionType::Frame) 1900 eKeyState = SwKeyState::GoIntoFly; 1901 else if((nSelectionType & SelectionType::DrawObject) && 1902 !(nSelectionType & SelectionType::DrawObjectEditMode) && 1903 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1) 1904 { 1905 eKeyState = SwKeyState::GoIntoDrawing; 1906 if (lcl_goIntoTextBox(*this, rSh)) 1907 eKeyState = SwKeyState::GoIntoFly; 1908 } 1909 else if( aTmpQHD.HasContent() && !rSh.HasSelection() && 1910 aTmpQHD.m_bIsAutoText ) 1911 eKeyState = SwKeyState::GlossaryExpand; 1912 1913 //RETURN and empty paragraph in numbering -> end numbering 1914 else if( m_aInBuffer.isEmpty() && 1915 rSh.GetNumRuleAtCurrCursorPos() && 1916 !rSh.GetNumRuleAtCurrCursorPos()->IsOutlineRule() && 1917 !rSh.HasSelection() && 1918 rSh.IsSttPara() && rSh.IsEndPara() ) 1919 { 1920 eKeyState = SwKeyState::NumOff; 1921 eNextKeyState = SwKeyState::OutlineLvOff; 1922 } 1923 //RETURN for new paragraph with AutoFormatting 1924 else if( pACfg && pACfg->IsAutoFormatByInput() && 1925 !(nSelectionType & (SelectionType::Graphic | 1926 SelectionType::Ole | SelectionType::Frame | 1927 SelectionType::TableCell | SelectionType::DrawObject | 1928 SelectionType::DrawObjectEditMode)) ) 1929 { 1930 eKeyState = SwKeyState::AutoFormatByInput; 1931 } 1932 else 1933 { 1934 eNextKeyState = eKeyState; 1935 eKeyState = SwKeyState::CheckAutoCorrect; 1936 } 1937 } 1938 } 1939 break; 1940 case KEY_RETURN | KEY_MOD2: 1941 { 1942 if ( !rSh.HasReadonlySel() 1943 && !rSh.IsSttPara() 1944 && rSh.GetNumRuleAtCurrCursorPos() 1945 && !rSh.CursorInsideInputField() ) 1946 { 1947 eKeyState = SwKeyState::NoNum; 1948 } 1949 else if( rSh.CanSpecialInsert() ) 1950 eKeyState = SwKeyState::SpecialInsert; 1951 } 1952 break; 1953 case KEY_BACKSPACE: 1954 case KEY_BACKSPACE | KEY_SHIFT: 1955 if ( !rSh.HasReadonlySel() || rSh.CursorInsideInputField()) 1956 { 1957 bool bDone = false; 1958 // try to add comment for code snip: 1959 // Remove the paragraph indent, if the cursor is at the 1960 // beginning of a paragraph, there is no selection 1961 // and no numbering rule found at the current paragraph 1962 // Also try to remove indent, if current paragraph 1963 // has numbering rule, but isn't counted and only 1964 // key <backspace> is hit. 1965 const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() ); 1966 if ( rSh.IsSttPara() 1967 && !rSh.HasSelection() 1968 && ( rSh.GetNumRuleAtCurrCursorPos() == nullptr 1969 || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) ) 1970 { 1971 bDone = rSh.TryRemoveIndent(); 1972 } 1973 1974 if (bDone) 1975 eKeyState = SwKeyState::End; 1976 else 1977 { 1978 if ( rSh.IsSttPara() && !rSh.IsNoNum() ) 1979 { 1980 if (m_nKS_NUMDOWN_Count > 0 && 1981 0 < rSh.GetNumLevel()) 1982 { 1983 eKeyState = SwKeyState::NumUp; 1984 m_nKS_NUMDOWN_Count = 2; 1985 bDone = true; 1986 } 1987 else if (m_nKS_NUMINDENTINC_Count > 0) 1988 { 1989 eKeyState = SwKeyState::NumIndentDec; 1990 m_nKS_NUMINDENTINC_Count = 2; 1991 bDone = true; 1992 } 1993 } 1994 1995 // If the cursor is in an empty paragraph, which has 1996 // a numbering, but not the outline numbering, and 1997 // there is no selection, the numbering has to be 1998 // deleted on key <Backspace>. 1999 // Otherwise method <SwEditShell::NumOrNoNum(..)> 2000 // should only change the <IsCounted()> state of 2001 // the current paragraph depending of the key. 2002 // On <backspace> it is set to <false>, 2003 // on <shift-backspace> it is set to <true>. 2004 // Thus, assure that method <SwEditShell::NumOrNum(..)> 2005 // is only called for the intended purpose. 2006 if ( !bDone && rSh.IsSttPara() ) 2007 { 2008 bool bCallNumOrNoNum( false ); 2009 if ( bOnlyBackspaceKey && !rSh.IsNoNum() ) 2010 { 2011 bCallNumOrNoNum = true; 2012 } 2013 else if ( !bOnlyBackspaceKey && rSh.IsNoNum() ) 2014 { 2015 bCallNumOrNoNum = true; 2016 } 2017 else if ( bOnlyBackspaceKey 2018 && rSh.IsSttPara() 2019 && rSh.IsEndPara() 2020 && !rSh.HasSelection() ) 2021 { 2022 const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCursorPos() ); 2023 if ( pCurrNumRule != nullptr 2024 && pCurrNumRule != rSh.GetOutlineNumRule() ) 2025 { 2026 bCallNumOrNoNum = true; 2027 } 2028 } 2029 if ( bCallNumOrNoNum 2030 && rSh.NumOrNoNum( !bOnlyBackspaceKey ) ) 2031 { 2032 eKeyState = SwKeyState::NumOrNoNum; 2033 } 2034 } 2035 } 2036 } 2037 else if (!rSh.IsCursorInParagraphMetadataField()) 2038 { 2039 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); 2040 std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); 2041 xInfo->run(); 2042 eKeyState = SwKeyState::End; 2043 } 2044 break; 2045 2046 case KEY_RIGHT: 2047 { 2048 eFlyState = SwKeyState::Fly_Change; 2049 nDir = MOVE_RIGHT_BIG; 2050 goto KEYINPUT_CHECKTABLE_INSDEL; 2051 } 2052 case KEY_TAB: 2053 { 2054 2055 if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) 2056 { 2057 eKeyState = SwKeyState::GotoNextFieldMark; 2058 } 2059 else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() ) 2060 { 2061 GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD ); 2062 eKeyState = SwKeyState::End; 2063 } 2064 else if( rSh.GetNumRuleAtCurrCursorPos() 2065 && rSh.IsSttOfPara() 2066 && !rSh.HasReadonlySel() ) 2067 { 2068 if ( !rSh.IsMultiSelection() 2069 && rSh.IsFirstOfNumRuleAtCursorPos() 2070 && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() ) 2071 eKeyState = SwKeyState::NumIndentInc; 2072 else 2073 { 2074 if (numfunc::NumDownChangesIndent(rSh)) 2075 { 2076 eKeyState = SwKeyState::NumDown; 2077 } 2078 else 2079 { 2080 eKeyState = SwKeyState::InsTab; 2081 } 2082 } 2083 } 2084 else if ( rSh.GetTableFormat() ) 2085 { 2086 if( rSh.HasSelection() || rSh.HasReadonlySel() ) 2087 eKeyState = SwKeyState::NextCell; 2088 else 2089 { 2090 eKeyState = SwKeyState::CheckAutoCorrect; 2091 eNextKeyState = SwKeyState::NextCell; 2092 } 2093 } 2094 else if ( rSh.GetSelectionType() & 2095 (SelectionType::Graphic | 2096 SelectionType::Frame | 2097 SelectionType::Ole | 2098 SelectionType::DrawObject | 2099 SelectionType::DbForm)) 2100 2101 eKeyState = SwKeyState::NextObject; 2102 else 2103 { 2104 eKeyState = SwKeyState::InsTab; 2105 if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() ) 2106 { 2107 SwTextFormatColl* pColl = rSh.GetCurTextFormatColl(); 2108 if( pColl && 2109 2110 pColl->IsAssignedToListLevelOfOutlineStyle() 2111 && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() ) 2112 eKeyState = SwKeyState::OutlineDown; 2113 } 2114 } 2115 } 2116 break; 2117 case KEY_TAB | KEY_SHIFT: 2118 { 2119 if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) 2120 { 2121 eKeyState = SwKeyState::GotoPrevFieldMark; 2122 } 2123 else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() ) 2124 { 2125 GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD ); 2126 eKeyState = SwKeyState::End; 2127 } 2128 else if( rSh.GetNumRuleAtCurrCursorPos() 2129 && rSh.IsSttOfPara() 2130 && !rSh.HasReadonlySel() ) 2131 { 2132 if ( !rSh.IsMultiSelection() 2133 && rSh.IsFirstOfNumRuleAtCursorPos() 2134 && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() ) 2135 eKeyState = SwKeyState::NumIndentDec; 2136 else 2137 eKeyState = SwKeyState::NumUp; 2138 } 2139 else if ( rSh.GetTableFormat() ) 2140 { 2141 if( rSh.HasSelection() || rSh.HasReadonlySel() ) 2142 eKeyState = SwKeyState::PrevCell; 2143 else 2144 { 2145 eKeyState = SwKeyState::CheckAutoCorrect; 2146 eNextKeyState = SwKeyState::PrevCell; 2147 } 2148 } 2149 else if ( rSh.GetSelectionType() & 2150 (SelectionType::Graphic | 2151 SelectionType::Frame | 2152 SelectionType::Ole | 2153 SelectionType::DrawObject | 2154 SelectionType::DbForm)) 2155 2156 eKeyState = SwKeyState::PrevObject; 2157 else 2158 { 2159 eKeyState = SwKeyState::End; 2160 if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() ) 2161 { 2162 SwTextFormatColl* pColl = rSh.GetCurTextFormatColl(); 2163 if( pColl && 2164 pColl->IsAssignedToListLevelOfOutlineStyle() && 2165 0 < pColl->GetAssignedOutlineStyleLevel()) 2166 eKeyState = SwKeyState::OutlineUp; 2167 } 2168 } 2169 } 2170 break; 2171 case KEY_TAB | KEY_MOD1: 2172 case KEY_TAB | KEY_MOD2: 2173 if( !rSh.HasReadonlySel() ) 2174 { 2175 if( aTmpQHD.HasContent() && !rSh.HasSelection() ) 2176 { 2177 // Next auto-complete suggestion 2178 aTmpQHD.Next( pACorr && 2179 pACorr->GetSwFlags().bAutoCmpltEndless ); 2180 eKeyState = SwKeyState::NextPrevGlossary; 2181 } 2182 else if( rSh.GetTableFormat() ) 2183 eKeyState = SwKeyState::InsTab; 2184 else if((rSh.GetSelectionType() & 2185 (SelectionType::DrawObject|SelectionType::DbForm| 2186 SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) && 2187 rSh.GetDrawView()->AreObjectsMarked()) 2188 eKeyState = SwKeyState::EnterDrawHandleMode; 2189 else 2190 { 2191 eKeyState = SwKeyState::InsTab; 2192 } 2193 } 2194 break; 2195 2196 case KEY_TAB | KEY_MOD1 | KEY_SHIFT: 2197 { 2198 if( aTmpQHD.HasContent() && !rSh.HasSelection() && 2199 !rSh.HasReadonlySel() ) 2200 { 2201 // Previous auto-complete suggestion. 2202 aTmpQHD.Previous( pACorr && 2203 pACorr->GetSwFlags().bAutoCmpltEndless ); 2204 eKeyState = SwKeyState::NextPrevGlossary; 2205 } 2206 else if((rSh.GetSelectionType() & (SelectionType::DrawObject|SelectionType::DbForm| 2207 SelectionType::Frame|SelectionType::Ole|SelectionType::Graphic)) && 2208 rSh.GetDrawView()->AreObjectsMarked()) 2209 { 2210 eKeyState = SwKeyState::EnterDrawHandleMode; 2211 } 2212 } 2213 break; 2214 case KEY_F2 : 2215 if( !rSh.HasReadonlySel() ) 2216 { 2217 const SelectionType nSelectionType = rSh.GetSelectionType(); 2218 if(nSelectionType & SelectionType::Frame) 2219 eKeyState = SwKeyState::GoIntoFly; 2220 else if(nSelectionType & SelectionType::DrawObject) 2221 { 2222 eKeyState = SwKeyState::GoIntoDrawing; 2223 if (lcl_goIntoTextBox(*this, rSh)) 2224 eKeyState = SwKeyState::GoIntoFly; 2225 } 2226 } 2227 break; 2228 } 2229 } 2230 break; 2231 case SwKeyState::CheckDocReadOnlyKeys: 2232 { 2233 eKeyState = SwKeyState::KeyToView; 2234 switch( rKeyCode.GetModifier() | rKeyCode.GetCode() ) 2235 { 2236 case KEY_TAB: 2237 case KEY_TAB | KEY_SHIFT: 2238 bNormalChar = false; 2239 eKeyState = SwKeyState::End; 2240 if ( rSh.GetSelectionType() & 2241 (SelectionType::Graphic | 2242 SelectionType::Frame | 2243 SelectionType::Ole | 2244 SelectionType::DrawObject | 2245 SelectionType::DbForm)) 2246 2247 { 2248 eKeyState = (rKeyCode.GetModifier() & KEY_SHIFT) ? 2249 SwKeyState::PrevObject : SwKeyState::NextObject; 2250 } 2251 else if ( !rSh.IsMultiSelection() && rSh.CursorInsideInputField() ) 2252 { 2253 GetView().GetViewFrame()->GetDispatcher()->Execute( 2254 KEY_SHIFT != rKeyCode.GetModifier() ? FN_GOTO_NEXT_INPUTFLD : FN_GOTO_PREV_INPUTFLD ); 2255 } 2256 else 2257 { 2258 rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() ); 2259 } 2260 break; 2261 case KEY_RETURN: 2262 { 2263 const SelectionType nSelectionType = rSh.GetSelectionType(); 2264 if(nSelectionType & SelectionType::Frame) 2265 eKeyState = SwKeyState::GoIntoFly; 2266 else 2267 { 2268 SfxItemSet aSet(rSh.GetAttrPool(), svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{}); 2269 rSh.GetCurAttr(aSet); 2270 if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false)) 2271 { 2272 const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT); 2273 bNormalChar = false; 2274 eKeyState = SwKeyState::End; 2275 rSh.ClickToINetAttr(static_cast<const SwFormatINetFormat&>(rItem)); 2276 } 2277 } 2278 } 2279 break; 2280 } 2281 } 2282 break; 2283 2284 case SwKeyState::EnterCharCell: 2285 { 2286 eKeyState = SwKeyState::KeyToView; 2287 switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() ) 2288 { 2289 case KEY_RIGHT | KEY_MOD2: 2290 rSh.Right( CRSR_SKIP_CHARS, false, 1, false ); 2291 eKeyState = SwKeyState::End; 2292 FlushInBuffer(); 2293 break; 2294 case KEY_LEFT | KEY_MOD2: 2295 rSh.Left( CRSR_SKIP_CHARS, false, 1, false ); 2296 eKeyState = SwKeyState::End; 2297 FlushInBuffer(); 2298 break; 2299 } 2300 } 2301 break; 2302 2303 case SwKeyState::KeyToView: 2304 { 2305 eKeyState = SwKeyState::End; 2306 bNormalChar = 2307 !rKeyCode.IsMod2() && 2308 rKeyCode.GetModifier() != KEY_MOD1 && 2309 rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) && 2310 SW_ISPRINTABLE( aCh ); 2311 2312 if( bNormalChar && rSh.IsInFrontOfLabel() ) 2313 { 2314 rSh.NumOrNoNum(); 2315 } 2316 2317 if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly )) 2318 FlushInBuffer(); 2319 2320 if (rSh.HasReadonlySel() 2321 && ( rKeyCode.GetFunction() == KeyFuncType::PASTE 2322 || rKeyCode.GetFunction() == KeyFuncType::CUT)) 2323 { 2324 auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog")); 2325 weld::DialogController::runAsync(xInfo, [](int) {}); 2326 eKeyState = SwKeyState::End; 2327 } 2328 else if( m_rView.KeyInput( aKeyEvent ) ) 2329 { 2330 bFlushBuffer = true; 2331 bNormalChar = false; 2332 } 2333 else 2334 { 2335 // Because Sfx accelerators are only called when they were 2336 // enabled at the last status update, copy has to called 2337 // 'forcefully' by us if necessary. 2338 if( rKeyCode.GetFunction() == KeyFuncType::COPY ) 2339 GetView().GetViewFrame()->GetBindings().Execute(SID_COPY); 2340 2341 if( !bIsDocReadOnly && bNormalChar ) 2342 { 2343 const SelectionType nSelectionType = rSh.GetSelectionType(); 2344 const bool bDrawObject = (nSelectionType & SelectionType::DrawObject) && 2345 !(nSelectionType & SelectionType::DrawObjectEditMode) && 2346 rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1; 2347 2348 bool bTextBox = false; 2349 if (bDrawObject && lcl_goIntoTextBox(*this, rSh)) 2350 // A draw shape was selected, but it has a TextBox, 2351 // start editing that instead when the normal 2352 // character is pressed. 2353 bTextBox = true; 2354 2355 if (bDrawObject && !bTextBox) 2356 { 2357 SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); 2358 if(pObj) 2359 { 2360 EnterDrawTextMode(pObj->GetLogicRect().Center()); 2361 if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) ) 2362 pSwDrawTextShell->Init(); 2363 rSh.GetDrawView()->KeyInput( rKEvt, this ); 2364 } 2365 } 2366 else if (nSelectionType & SelectionType::Frame || bTextBox) 2367 { 2368 rSh.UnSelectFrame(); 2369 rSh.LeaveSelFrameMode(); 2370 m_rView.AttrChangedNotify(nullptr); 2371 rSh.MoveSection( GoCurrSection, fnSectionEnd ); 2372 } 2373 eKeyState = SwKeyState::InsChar; 2374 } 2375 else 2376 { 2377 bNormalChar = false; 2378 Window::KeyInput( aKeyEvent ); 2379 } 2380 } 2381 } 2382 break; 2383 case SwKeyState::LaunchOLEObject: 2384 { 2385 rSh.LaunchOLEObj(); 2386 eKeyState = SwKeyState::End; 2387 } 2388 break; 2389 case SwKeyState::GoIntoFly: 2390 { 2391 rSh.UnSelectFrame(); 2392 rSh.LeaveSelFrameMode(); 2393 m_rView.AttrChangedNotify(nullptr); 2394 rSh.MoveSection( GoCurrSection, fnSectionEnd ); 2395 eKeyState = SwKeyState::End; 2396 } 2397 break; 2398 case SwKeyState::GoIntoDrawing: 2399 { 2400 if (SdrMark* pMark = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)) 2401 { 2402 SdrObject* pObj = pMark->GetMarkedSdrObj(); 2403 if(pObj) 2404 { 2405 EnterDrawTextMode(pObj->GetLogicRect().Center()); 2406 if (auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) ) 2407 pSwDrawTextShell->Init(); 2408 } 2409 } 2410 eKeyState = SwKeyState::End; 2411 } 2412 break; 2413 case SwKeyState::EnterDrawHandleMode: 2414 { 2415 const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList(); 2416 bool bForward(!aKeyEvent.GetKeyCode().IsShift()); 2417 2418 const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward); 2419 eKeyState = SwKeyState::End; 2420 } 2421 break; 2422 case SwKeyState::InsTab: 2423 if( dynamic_cast<const SwWebView*>( &m_rView) != nullptr) // no Tab for WebView 2424 { 2425 // then it should be passed along 2426 Window::KeyInput( aKeyEvent ); 2427 eKeyState = SwKeyState::End; 2428 break; 2429 } 2430 aCh = '\t'; 2431 [[fallthrough]]; 2432 case SwKeyState::InsChar: 2433 if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) 2434 { 2435 ::sw::mark::ICheckboxFieldmark* pFieldmark = 2436 dynamic_cast< ::sw::mark::ICheckboxFieldmark* > 2437 (rSh.GetCurrentFieldmark()); 2438 OSL_ENSURE(pFieldmark, 2439 "Where is my FieldMark??"); 2440 if(pFieldmark) 2441 { 2442 pFieldmark->SetChecked(!pFieldmark->IsChecked()); 2443 OSL_ENSURE(pFieldmark->IsExpanded(), 2444 "where is the otherpos?"); 2445 if (pFieldmark->IsExpanded()) 2446 { 2447 rSh.CalcLayout(); 2448 } 2449 } 2450 eKeyState = SwKeyState::End; 2451 } 2452 else if ( !rSh.HasReadonlySel() 2453 || rSh.CursorInsideInputField() ) 2454 { 2455 const bool bIsNormalChar = 2456 GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 ); 2457 if( bAppendSpace && bIsNormalChar && 2458 (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() )) 2459 { 2460 // insert a blank ahead of the character. this ends up 2461 // between the expanded text and the new "non-word-separator". 2462 m_aInBuffer += " "; 2463 } 2464 2465 const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh ); 2466 if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) && 2467 pACfg->IsAutoFormatByInput() && 2468 (( pACorr->IsAutoCorrFlag( ACFlags::ChgWeightUnderl ) && 2469 ( '*' == aCh || '_' == aCh ) ) || 2470 ( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))|| 2471 ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh)))) 2472 { 2473 FlushInBuffer(); 2474 rSh.AutoCorrect( *pACorr, aCh ); 2475 if( '\"' != aCh && '\'' != aCh ) // only call when "*_"! 2476 rSh.UpdateAttr(); 2477 } 2478 else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || rSh.IsNbspRunNext() ) && 2479 pACfg->IsAutoFormatByInput() && 2480 pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord | 2481 ACFlags::ChgOrdinalNumber | ACFlags::AddNonBrkSpace | 2482 ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | 2483 ACFlags::Autocorrect | ACFlags::TransliterateRTL ) && 2484 '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh 2485 ) 2486 { 2487 FlushInBuffer(); 2488 rSh.AutoCorrect( *pACorr, aCh ); 2489 } 2490 else 2491 { 2492 OUStringBuffer aBuf(m_aInBuffer); 2493 comphelper::string::padToLength(aBuf, 2494 m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh); 2495 m_aInBuffer = aBuf.makeStringAndClear(); 2496 g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD ); 2497 bFlushBuffer = !g_bFlushCharBuffer; 2498 if( g_bFlushCharBuffer ) 2499 m_aKeyInputFlushTimer.Start(); 2500 } 2501 eKeyState = SwKeyState::End; 2502 } 2503 else 2504 { 2505 auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog")); 2506 weld::DialogController::runAsync(xInfo, [](int) {}); 2507 eKeyState = SwKeyState::End; 2508 } 2509 break; 2510 2511 case SwKeyState::CheckAutoCorrect: 2512 { 2513 if( pACorr && pACfg->IsAutoFormatByInput() && 2514 pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord | 2515 ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL | 2516 ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | 2517 ACFlags::Autocorrect ) && 2518 !rSh.HasReadonlySel() ) 2519 { 2520 FlushInBuffer(); 2521 rSh.AutoCorrect( *pACorr, u'\0' ); 2522 } 2523 eKeyState = eNextKeyState; 2524 } 2525 break; 2526 2527 default: 2528 { 2529 sal_uInt16 nSlotId = 0; 2530 FlushInBuffer(); 2531 switch( eKeyState ) 2532 { 2533 case SwKeyState::SpecialInsert: 2534 rSh.DoSpecialInsert(); 2535 break; 2536 2537 case SwKeyState::NoNum: 2538 rSh.NoNum(); 2539 break; 2540 2541 case SwKeyState::NumOff: 2542 // shell change - so record in advance 2543 rSh.DelNumRules(); 2544 break; 2545 case SwKeyState::OutlineLvOff: // delete autofmt outlinelevel later 2546 break; 2547 2548 case SwKeyState::NumDown: 2549 rSh.NumUpDown(); 2550 m_nKS_NUMDOWN_Count = 2; 2551 break; 2552 case SwKeyState::NumUp: 2553 rSh.NumUpDown( false ); 2554 break; 2555 2556 case SwKeyState::NumIndentInc: 2557 rSh.ChangeIndentOfAllListLevels(360); 2558 m_nKS_NUMINDENTINC_Count = 2; 2559 break; 2560 2561 case SwKeyState::GotoNextFieldMark: 2562 { 2563 ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter(); 2564 if(pFieldmark) rSh.GotoFieldmark(pFieldmark); 2565 } 2566 break; 2567 2568 case SwKeyState::GotoPrevFieldMark: 2569 { 2570 ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore(); 2571 if( pFieldmark ) 2572 rSh.GotoFieldmark(pFieldmark); 2573 } 2574 break; 2575 2576 case SwKeyState::NumIndentDec: 2577 rSh.ChangeIndentOfAllListLevels(-360); 2578 break; 2579 2580 case SwKeyState::OutlineDown: 2581 rSh.OutlineUpDown(); 2582 break; 2583 case SwKeyState::OutlineUp: 2584 rSh.OutlineUpDown( -1 ); 2585 break; 2586 2587 case SwKeyState::NextCell: 2588 // always 'flush' in tables 2589 rSh.GoNextCell(!rSh.HasReadonlySel()); 2590 nSlotId = FN_GOTO_NEXT_CELL; 2591 break; 2592 case SwKeyState::PrevCell: 2593 rSh.GoPrevCell(); 2594 nSlotId = FN_GOTO_PREV_CELL; 2595 break; 2596 case SwKeyState::AutoFormatByInput: 2597 rSh.SplitNode( true ); 2598 break; 2599 2600 case SwKeyState::NextObject: 2601 case SwKeyState::PrevObject: 2602 if(rSh.GotoObj( SwKeyState::NextObject == eKeyState, GotoObjFlags::Any)) 2603 { 2604 if( rSh.IsFrameSelected() && 2605 m_rView.GetDrawFuncPtr() ) 2606 { 2607 m_rView.GetDrawFuncPtr()->Deactivate(); 2608 m_rView.SetDrawFuncPtr(nullptr); 2609 m_rView.LeaveDrawCreate(); 2610 m_rView.AttrChangedNotify(nullptr); 2611 } 2612 rSh.HideCursor(); 2613 rSh.EnterSelFrameMode(); 2614 } 2615 break; 2616 case SwKeyState::GlossaryExpand: 2617 { 2618 // replace the word or abbreviation with the auto text 2619 rSh.StartUndo( SwUndoId::START ); 2620 2621 OUString sFnd(aTmpQHD.CurStr()); 2622 if( aTmpQHD.m_bIsAutoText ) 2623 { 2624 SwGlossaryList* pList = ::GetGlossaryList(); 2625 OUString sShrtNm; 2626 OUString sGroup; 2627 if(pList->GetShortName( sFnd, sShrtNm, sGroup)) 2628 { 2629 rSh.SttSelect(); 2630 rSh.ExtendSelection(false, aTmpQHD.CurLen()); 2631 SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl(); 2632 pGlosHdl->SetCurGroup(sGroup, true); 2633 pGlosHdl->InsertGlossary( sShrtNm); 2634 m_pQuickHlpData->m_bAppendSpace = true; 2635 } 2636 } 2637 else 2638 { 2639 sFnd = sFnd.copy(aTmpQHD.CurLen()); 2640 rSh.Insert( sFnd ); 2641 m_pQuickHlpData->m_bAppendSpace = !pACorr || 2642 pACorr->GetSwFlags().bAutoCmpltAppendBlank; 2643 } 2644 rSh.EndUndo( SwUndoId::END ); 2645 } 2646 break; 2647 2648 case SwKeyState::NextPrevGlossary: 2649 m_pQuickHlpData->Move( aTmpQHD ); 2650 m_pQuickHlpData->Start(rSh, false); 2651 break; 2652 2653 case SwKeyState::EditFormula: 2654 { 2655 const sal_uInt16 nId = SwInputChild::GetChildWindowId(); 2656 2657 SfxViewFrame* pVFrame = GetView().GetViewFrame(); 2658 pVFrame->ToggleChildWindow( nId ); 2659 SwInputChild* pChildWin = static_cast<SwInputChild*>(pVFrame-> 2660 GetChildWindow( nId )); 2661 if( pChildWin ) 2662 pChildWin->SetFormula( sFormulaEntry ); 2663 } 2664 break; 2665 2666 case SwKeyState::ColLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break; 2667 case SwKeyState::ColRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break; 2668 case SwKeyState::ColLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColLeft, pModOpt->GetTableHMove() ); break; 2669 case SwKeyState::ColRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::ColRight, pModOpt->GetTableHMove() ); break; 2670 case SwKeyState::ColBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break; 2671 case SwKeyState::ColBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::RowBottom, pModOpt->GetTableVMove() ); break; 2672 case SwKeyState::CellLeftBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break; 2673 case SwKeyState::CellRightBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableHMove() ); break; 2674 case SwKeyState::CellLeftSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellLeft, pModOpt->GetTableHMove() ); break; 2675 case SwKeyState::CellRightSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellRight, pModOpt->GetTableHMove() ); break; 2676 case SwKeyState::CellTopBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break; 2677 case SwKeyState::CellBottomBig: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom|TableChgWidthHeightType::BiggerMode, pModOpt->GetTableVMove() ); break; 2678 case SwKeyState::CellTopSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellTop, pModOpt->GetTableVMove() ); break; 2679 case SwKeyState::CellBottomSmall: rSh.SetColRowWidthHeight( TableChgWidthHeightType::CellBottom, pModOpt->GetTableVMove() ); break; 2680 2681 case SwKeyState::Fly_Change: 2682 { 2683 SdrView *pSdrView = rSh.GetDrawView(); 2684 const SdrHdlList& rHdlList = pSdrView->GetHdlList(); 2685 if(rHdlList.GetFocusHdl()) 2686 ChangeDrawing( nDir ); 2687 else 2688 ChangeFly( nDir, dynamic_cast<const SwWebView*>( &m_rView) != nullptr ); 2689 } 2690 break; 2691 case SwKeyState::Draw_Change : 2692 ChangeDrawing( nDir ); 2693 break; 2694 default: 2695 break; 2696 } 2697 if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() ) 2698 { 2699 SfxRequest aReq(m_rView.GetViewFrame(), nSlotId ); 2700 aReq.Done(); 2701 } 2702 eKeyState = SwKeyState::End; 2703 } 2704 } 2705 } 2706 2707 // x11 backend doesn't like not having this 2708 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) 2709 GetFrameControlsManager().SetOutlineContentVisibilityButtons(); 2710 2711 // update the page number in the statusbar 2712 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); 2713 if( KEY_UP == nKey || KEY_DOWN == nKey || KEY_PAGEUP == nKey || KEY_PAGEDOWN == nKey ) 2714 GetView().GetViewFrame()->GetBindings().Update( FN_STAT_PAGE ); 2715 2716 // in case the buffered characters are inserted 2717 if( bFlushBuffer && !m_aInBuffer.isEmpty() ) 2718 { 2719 // bFlushCharBuffer was not reset here 2720 // why not? 2721 bool bSave = g_bFlushCharBuffer; 2722 FlushInBuffer(); 2723 g_bFlushCharBuffer = bSave; 2724 2725 // maybe show Tip-Help 2726 if (bNormalChar) 2727 { 2728 const bool bAutoTextShown 2729 = pACfg && pACfg->IsAutoTextTip() && ShowAutoText(rSh.GetChunkForAutoText()); 2730 if (!bAutoTextShown && pACorr && pACorr->GetSwFlags().bAutoCompleteWords) 2731 ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr); 2732 } 2733 } 2734 2735 // get the word count dialog to update itself 2736 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); 2737 if( pWrdCnt ) 2738 pWrdCnt->UpdateCounts(); 2739 2740 } 2741 2742 /** 2743 * MouseEvents 2744 */ 2745 void SwEditWin::RstMBDownFlags() 2746 { 2747 // Not on all systems a MouseButtonUp is used ahead 2748 // of the modal dialog (like on WINDOWS). 2749 // So reset the statuses here and release the mouse 2750 // for the dialog. 2751 m_bMBPressed = false; 2752 g_bNoInterrupt = false; 2753 EnterArea(); 2754 ReleaseMouse(); 2755 } 2756 2757 /** 2758 * Determines if the current position has a clickable url over a background 2759 * frame. In that case, ctrl-click should select the url, not the frame. 2760 */ 2761 static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos) 2762 { 2763 SwContentAtPos aSwContentAtPos(IsAttrAtPos::InetAttr); 2764 SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos); 2765 2766 return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->getIDocumentDrawModelAccess().GetHellId(); 2767 } 2768 2769 void SwEditWin::MoveCursor( SwWrtShell &rSh, const Point& rDocPos, 2770 const bool bOnlyText, bool bLockView ) 2771 { 2772 const bool bTmpNoInterrupt = g_bNoInterrupt; 2773 g_bNoInterrupt = false; 2774 2775 int nTmpSetCursor = 0; 2776 2777 if( !rSh.IsViewLocked() && bLockView ) 2778 rSh.LockView( true ); 2779 else 2780 bLockView = false; 2781 2782 { 2783 // only temporary generate move context because otherwise 2784 // the query to the content form doesn't work!!! 2785 SwMvContext aMvContext( &rSh ); 2786 nTmpSetCursor = rSh.CallSetCursor(&rDocPos, bOnlyText); 2787 g_bValidCursorPos = !(CRSR_POSCHG & nTmpSetCursor); 2788 } 2789 2790 // notify the edit window that from now on we do not use the input language 2791 if ( !(CRSR_POSOLD & nTmpSetCursor) ) 2792 SetUseInputLanguage( false ); 2793 2794 if( bLockView ) 2795 rSh.LockView( false ); 2796 2797 g_bNoInterrupt = bTmpNoInterrupt; 2798 } 2799 2800 void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt) 2801 { 2802 SwWrtShell &rSh = m_rView.GetWrtShell(); 2803 const SwField *pCursorField = rSh.CursorInsideInputField() ? rSh.GetCurField( true ) : nullptr; 2804 2805 // We have to check if a context menu is shown and we have an UI 2806 // active inplace client. In that case we have to ignore the mouse 2807 // button down event. Otherwise we would crash (context menu has been 2808 // opened by inplace client and we would deactivate the inplace client, 2809 // the context menu is closed by VCL asynchronously which in the end 2810 // would work on deleted objects or the context menu has no parent anymore) 2811 SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient(); 2812 bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() ); 2813 2814 if ( bIsOleActive && PopupMenu::IsInExecute() ) 2815 return; 2816 2817 MouseEvent rMEvt(_rMEvt); 2818 2819 if (m_rView.GetPostItMgr()->IsHit(rMEvt.GetPosPixel())) 2820 return; 2821 2822 if (comphelper::LibreOfficeKit::isActive()) 2823 { 2824 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel())) 2825 { 2826 pWindow->MouseButtonDown(rMEvt); 2827 return; 2828 } 2829 } 2830 2831 m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr); 2832 2833 GrabFocus(); 2834 rSh.addCurrentPosition(); 2835 2836 //ignore key modifiers for format paintbrush 2837 { 2838 bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard 2839 && m_pApplyTempl->m_pFormatClipboard->HasContent(); 2840 if( bExecFormatPaintbrush ) 2841 rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(), 2842 _rMEvt.GetMode(), _rMEvt.GetButtons() ); 2843 } 2844 2845 m_bWasShdwCursor = nullptr != m_pShadCursor; 2846 m_pShadCursor.reset(); 2847 2848 const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) ); 2849 2850 FrameControlType eControl; 2851 bool bOverFly = false; 2852 bool bPageAnchored = false; 2853 bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored ); 2854 2855 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly(); 2856 if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurField())) 2857 // We have a field here, that should have priority over header/footer fly. 2858 bOverHeaderFooterFly = false; 2859 2860 // Are we clicking on a blank header/footer area? 2861 if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly ) 2862 { 2863 const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( aDocPos ); 2864 2865 // Is it active? 2866 bool bActive = true; 2867 const SwPageDesc* pDesc = pPageFrame->GetPageDesc(); 2868 2869 const SwFrameFormat* pFormat = pDesc->GetLeftFormat(); 2870 if ( pPageFrame->OnRightPage() ) 2871 pFormat = pDesc->GetRightFormat(); 2872 2873 if ( pFormat ) 2874 { 2875 if ( eControl == FrameControlType::Header ) 2876 bActive = pFormat->GetHeader().IsActive(); 2877 else 2878 bActive = pFormat->GetFooter().IsActive(); 2879 } 2880 2881 if ( !bActive ) 2882 { 2883 // When in Hide-Whitespace mode, we don't want header 2884 // and footer controls. 2885 if (!rSh.GetViewOptions()->IsHideWhitespaceMode()) 2886 { 2887 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint()); 2888 const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr; 2889 const bool bWasInFooter = aPam.GetPoint()->nNode.GetNode().FindFooterStartNode() != nullptr; 2890 2891 // Is the cursor in a part like similar to the one we clicked on? For example, 2892 // if the cursor is in a header and we click on an empty header... don't change anything to 2893 // keep consistent behaviour due to header edit mode (and the same for the footer as well). 2894 2895 // Otherwise, we hide the header/footer control if a separator is shown, and vice versa. 2896 if (!(bWasInHeader && eControl == FrameControlType::Header) && 2897 !(bWasInFooter && eControl == FrameControlType::Footer)) 2898 { 2899 const bool bSeparatorWasVisible = rSh.IsShowHeaderFooterSeparator(eControl); 2900 rSh.SetShowHeaderFooterSeparator(eControl, !bSeparatorWasVisible); 2901 2902 // Repaint everything 2903 Invalidate(); 2904 2905 // tdf#84929. If the footer control had not been showing, do not change the cursor position, 2906 // because the user may have scrolled to turn on the separator control and 2907 // if the cursor cannot be positioned on-screen, then the user would need to scroll back again to use the control. 2908 // This should only be done for the footer. The cursor can always be re-positioned near the header. tdf#134023. 2909 if ( eControl == FrameControlType::Footer && !bSeparatorWasVisible 2910 && rSh.GetViewOptions()->IsUseHeaderFooterMenu() && !Application::IsHeadlessModeEnabled() ) 2911 return; 2912 } 2913 } 2914 } 2915 else 2916 { 2917 // Make sure we have the proper Header/Footer separators shown 2918 // as these may be changed if clicking on an empty Header/Footer 2919 rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, eControl == FrameControlType::Header ); 2920 rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, eControl == FrameControlType::Footer ); 2921 2922 if ( !rSh.IsHeaderFooterEdit() ) 2923 { 2924 rSh.ToggleHeaderFooterEdit(); 2925 2926 // Repaint everything 2927 rSh.GetWin()->Invalidate(); 2928 } 2929 } 2930 } 2931 else 2932 { 2933 if ( rSh.IsHeaderFooterEdit( ) ) 2934 rSh.ToggleHeaderFooterEdit( ); 2935 else 2936 { 2937 // Make sure that the separators are hidden 2938 rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, false ); 2939 rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, false ); 2940 2941 // Repaint everything 2942 // FIXME fdo#67358 for unknown reasons this causes painting 2943 // problems when resizing table columns, so disable it 2944 // rSh.GetWin()->Invalidate(); 2945 } 2946 2947 // Toggle Hide-Whitespace if between pages. 2948 if (rSh.GetViewOptions()->CanHideWhitespace() && 2949 rSh.GetLayout()->IsBetweenPages(aDocPos)) 2950 { 2951 if (_rMEvt.GetClicks() >= 2) 2952 { 2953 SwViewOption aOpt(*rSh.GetViewOptions()); 2954 aOpt.SetHideWhitespaceMode(!aOpt.IsHideWhitespaceMode()); 2955 rSh.ApplyViewOptions(aOpt); 2956 } 2957 2958 return; 2959 } 2960 } 2961 2962 if ( IsChainMode() ) 2963 { 2964 SetChainMode( false ); 2965 SwRect aDummy; 2966 SwFlyFrameFormat *pFormat = static_cast<SwFlyFrameFormat*>(rSh.GetFlyFrameFormat()); 2967 if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK ) 2968 rSh.Chain( *pFormat, aDocPos ); 2969 UpdatePointer( aDocPos, rMEvt.GetModifier() ); 2970 return; 2971 } 2972 2973 // After GrabFocus a shell should be pushed. That should actually 2974 // work but in practice ... 2975 m_rView.SelectShellForDrop(); 2976 2977 bool bCallBase = true; 2978 2979 if( m_pQuickHlpData->m_bIsDisplayed ) 2980 m_pQuickHlpData->Stop( rSh ); 2981 m_pQuickHlpData->m_bAppendSpace = false; 2982 2983 if( rSh.FinishOLEObj() ) 2984 return; // end InPlace and the click doesn't count anymore 2985 2986 CurrShell aCurr( &rSh ); 2987 2988 SdrView *pSdrView = rSh.GetDrawView(); 2989 if ( pSdrView ) 2990 { 2991 if (pSdrView->MouseButtonDown( rMEvt, this ) ) 2992 { 2993 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); 2994 return; // SdrView's event evaluated 2995 } 2996 } 2997 2998 m_bIsInMove = false; 2999 m_aStartPos = rMEvt.GetPosPixel(); 3000 m_aRszMvHdlPt.setX( 0 ); 3001 m_aRszMvHdlPt.setY( 0 ); 3002 3003 SwTab nMouseTabCol = SwTab::COL_NONE; 3004 const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect() && 3005 rMEvt.GetClicks() == 1 && MOUSE_LEFT == rMEvt.GetButtons(); 3006 if ( bTmp && 3007 SwTab::COL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) && 3008 !rSh.IsObjSelectable( aDocPos ) ) 3009 { 3010 // Enhanced table selection 3011 if ( SwTab::SEL_HORI <= nMouseTabCol && SwTab::COLSEL_VERT >= nMouseTabCol ) 3012 { 3013 rSh.EnterStdMode(); 3014 rSh.SelectTableRowCol( aDocPos ); 3015 if( SwTab::SEL_HORI != nMouseTabCol && SwTab::SEL_HORI_RTL != nMouseTabCol) 3016 { 3017 m_xRowColumnSelectionStart = aDocPos; 3018 m_bIsRowDrag = SwTab::ROWSEL_HORI == nMouseTabCol|| 3019 SwTab::ROWSEL_HORI_RTL == nMouseTabCol || 3020 SwTab::COLSEL_VERT == nMouseTabCol; 3021 m_bMBPressed = true; 3022 CaptureMouse(); 3023 } 3024 return; 3025 } 3026 3027 if ( !rSh.IsTableMode() ) 3028 { 3029 // comes from table columns out of the document. 3030 if(SwTab::COL_VERT == nMouseTabCol || SwTab::COL_HORI == nMouseTabCol) 3031 m_rView.SetTabColFromDoc( true ); 3032 else 3033 m_rView.SetTabRowFromDoc( true ); 3034 3035 m_rView.SetTabColFromDocPos( aDocPos ); 3036 m_rView.InvalidateRulerPos(); 3037 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); 3038 rBind.Update(); 3039 if ( RulerColumnDrag( rMEvt, 3040 (SwTab::COL_VERT == nMouseTabCol || SwTab::ROW_HORI == nMouseTabCol)) ) 3041 { 3042 m_rView.SetTabColFromDoc( false ); 3043 m_rView.SetTabRowFromDoc( false ); 3044 m_rView.InvalidateRulerPos(); 3045 rBind.Update(); 3046 bCallBase = false; 3047 } 3048 else 3049 { 3050 return; 3051 } 3052 } 3053 } 3054 else if (bTmp && 3055 rSh.IsNumLabel(aDocPos)) 3056 { 3057 SwTextNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos ); 3058 m_rView.SetNumRuleNodeFromDoc( pNodeAtPos ); 3059 m_rView.InvalidateRulerPos(); 3060 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); 3061 rBind.Update(); 3062 3063 if ( RulerMarginDrag( rMEvt, 3064 SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPos ) ) ) 3065 { 3066 m_rView.SetNumRuleNodeFromDoc( nullptr ); 3067 m_rView.InvalidateRulerPos(); 3068 rBind.Update(); 3069 bCallBase = false; 3070 } 3071 else 3072 { 3073 // Make sure the pointer is set to 0, otherwise it may point to 3074 // nowhere after deleting the corresponding text node. 3075 m_rView.SetNumRuleNodeFromDoc( nullptr ); 3076 return; 3077 } 3078 } 3079 3080 if ( rSh.IsInSelect() ) 3081 rSh.EndSelect(); 3082 3083 // query against LEFT because otherwise for example also a right 3084 // click releases the selection. 3085 if ( MOUSE_LEFT == rMEvt.GetButtons() ) 3086 { 3087 bool bOnlyText = false; 3088 m_bMBPressed = true; 3089 g_bNoInterrupt = true; 3090 m_nKS_NUMDOWN_Count = 0; 3091 3092 CaptureMouse(); 3093 3094 // reset cursor position if applicable 3095 rSh.ResetCursorStack(); 3096 3097 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) 3098 { 3099 case MOUSE_LEFT: 3100 case MOUSE_LEFT + KEY_SHIFT: 3101 case MOUSE_LEFT + KEY_MOD2: 3102 if( rSh.IsObjSelected() ) 3103 { 3104 SdrHdl* pHdl; 3105 if( !bIsDocReadOnly && 3106 !m_pAnchorMarker && 3107 pSdrView && 3108 nullptr != ( pHdl = pSdrView->PickHandle(aDocPos) ) && 3109 ( pHdl->GetKind() == SdrHdlKind::Anchor || 3110 pHdl->GetKind() == SdrHdlKind::Anchor_TR ) ) 3111 { 3112 // #i121463# Set selected during drag 3113 pHdl->SetSelected(); 3114 m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) ); 3115 UpdatePointer( aDocPos, rMEvt.GetModifier() ); 3116 return; 3117 } 3118 } 3119 if ( EnterDrawMode( rMEvt, aDocPos ) ) 3120 { 3121 g_bNoInterrupt = false; 3122 return; 3123 } 3124 else if ( m_rView.GetDrawFuncPtr() && m_bInsFrame ) 3125 { 3126 StopInsFrame(); 3127 rSh.Edit(); 3128 } 3129 3130 // Without SHIFT because otherwise Toggle doesn't work at selection 3131 if (rMEvt.GetClicks() == 1) 3132 { 3133 if ( rSh.IsSelFrameMode()) 3134 { 3135 SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos); 3136 bool bHitHandle = pHdl && pHdl->GetKind() != SdrHdlKind::Anchor && 3137 pHdl->GetKind() != SdrHdlKind::Anchor_TR; 3138 3139 if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle) && 3140 (rMEvt.GetModifier() != KEY_SHIFT || bHitHandle)) 3141 { 3142 rSh.EnterSelFrameMode( &aDocPos ); 3143 if ( !m_pApplyTempl ) 3144 { 3145 // only if no position to size was hit. 3146 if (!bHitHandle) 3147 { 3148 StartDDTimer(); 3149 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 3150 SwEditWin::m_nDDStartPosX = aDocPos.X(); 3151 } 3152 g_bFrameDrag = true; 3153 } 3154 g_bNoInterrupt = false; 3155 return; 3156 } 3157 } 3158 } 3159 } 3160 3161 bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); 3162 if ( !bExecHyperlinks ) 3163 { 3164 SvtSecurityOptions aSecOpts; 3165 const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink ); 3166 if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) || 3167 ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) ) 3168 bExecHyperlinks = true; 3169 } 3170 3171 // Enhanced selection 3172 sal_uInt8 nNumberOfClicks = static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4); 3173 if ( 0 == nNumberOfClicks && 0 < rMEvt.GetClicks() ) 3174 nNumberOfClicks = 4; 3175 3176 bool bExecDrawTextLink = false; 3177 3178 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) 3179 { 3180 case MOUSE_LEFT: 3181 case MOUSE_LEFT + KEY_MOD1: 3182 case MOUSE_LEFT + KEY_MOD2: 3183 { 3184 3185 // fdo#79604: first, check if a link has been clicked - do not 3186 // select fly in this case! 3187 if (1 == nNumberOfClicks) 3188 { 3189 UpdatePointer( aDocPos, rMEvt.GetModifier() ); 3190 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 3191 SwEditWin::m_nDDStartPosX = aDocPos.X(); 3192 3193 // hit a URL in DrawText object? 3194 if (bExecHyperlinks && pSdrView) 3195 { 3196 SdrViewEvent aVEvt; 3197 pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 3198 3199 if (aVEvt.eEvent == SdrEventKind::ExecuteUrl) 3200 bExecDrawTextLink = true; 3201 } 3202 } 3203 3204 if (1 == nNumberOfClicks && !bExecDrawTextLink) 3205 { 3206 // only try to select frame, if pointer already was 3207 // switched accordingly 3208 if ( m_aActHitType != SdrHitKind::NONE && !rSh.IsSelFrameMode() && 3209 !GetView().GetViewFrame()->GetDispatcher()->IsLocked()) 3210 { 3211 // Test if there is a draw object at that position and if it should be selected. 3212 bool bShould = rSh.ShouldObjectBeSelected(aDocPos); 3213 3214 if(bShould) 3215 { 3216 m_rView.NoRotate(); 3217 rSh.HideCursor(); 3218 3219 bool bUnLockView = !rSh.IsViewLocked(); 3220 rSh.LockView( true ); 3221 bool bSelObj = rSh.SelectObj( aDocPos, 3222 rMEvt.IsMod1() ? SW_ENTER_GROUP : 0); 3223 if( bUnLockView ) 3224 rSh.LockView( false ); 3225 3226 if( bSelObj ) 3227 { 3228 // if the frame was deselected in the macro 3229 // the cursor just has to be displayed again 3230 if( FrameTypeFlags::NONE == rSh.GetSelFrameType() ) 3231 rSh.ShowCursor(); 3232 else 3233 { 3234 if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr()) 3235 { 3236 m_rView.GetDrawFuncPtr()->Deactivate(); 3237 m_rView.SetDrawFuncPtr(nullptr); 3238 m_rView.LeaveDrawCreate(); 3239 m_rView.AttrChangedNotify(nullptr); 3240 } 3241 3242 rSh.EnterSelFrameMode( &aDocPos ); 3243 g_bFrameDrag = true; 3244 UpdatePointer( aDocPos, rMEvt.GetModifier() ); 3245 } 3246 return; 3247 } 3248 else 3249 bOnlyText = rSh.IsObjSelectable( aDocPos ); 3250 3251 if (!m_rView.GetDrawFuncPtr()) 3252 rSh.ShowCursor(); 3253 } 3254 else 3255 bOnlyText = KEY_MOD1 != rMEvt.GetModifier(); 3256 } 3257 else if ( rSh.IsSelFrameMode() && 3258 (m_aActHitType == SdrHitKind::NONE || 3259 !rSh.IsInsideSelectedObj( aDocPos ))) 3260 { 3261 m_rView.NoRotate(); 3262 SdrHdl *pHdl; 3263 if( !bIsDocReadOnly && !m_pAnchorMarker && nullptr != 3264 ( pHdl = pSdrView->PickHandle(aDocPos) ) && 3265 ( pHdl->GetKind() == SdrHdlKind::Anchor || 3266 pHdl->GetKind() == SdrHdlKind::Anchor_TR ) ) 3267 { 3268 m_pAnchorMarker.reset( new SwAnchorMarker( pHdl ) ); 3269 UpdatePointer( aDocPos, rMEvt.GetModifier() ); 3270 return; 3271 } 3272 else 3273 { 3274 bool bUnLockView = !rSh.IsViewLocked(); 3275 rSh.LockView( true ); 3276 sal_uInt8 nFlag = rMEvt.IsShift() ? SW_ADD_SELECT :0; 3277 if( rMEvt.IsMod1() ) 3278 nFlag = nFlag | SW_ENTER_GROUP; 3279 3280 if ( rSh.IsSelFrameMode() ) 3281 { 3282 rSh.UnSelectFrame(); 3283 rSh.LeaveSelFrameMode(); 3284 m_rView.AttrChangedNotify(nullptr); 3285 } 3286 3287 bool bSelObj = rSh.SelectObj( aDocPos, nFlag ); 3288 if( bUnLockView ) 3289 rSh.LockView( false ); 3290 3291 if( !bSelObj ) 3292 { 3293 // move cursor here so that it is not drawn in the 3294 // frame first; ShowCursor() happens in LeaveSelFrameMode() 3295 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false)); 3296 rSh.LeaveSelFrameMode(); 3297 m_rView.AttrChangedNotify(nullptr); 3298 bCallBase = false; 3299 } 3300 else 3301 { 3302 rSh.HideCursor(); 3303 rSh.EnterSelFrameMode( &aDocPos ); 3304 rSh.SelFlyGrabCursor(); 3305 rSh.MakeSelVisible(); 3306 g_bFrameDrag = true; 3307 if( rSh.IsFrameSelected() && 3308 m_rView.GetDrawFuncPtr() ) 3309 { 3310 m_rView.GetDrawFuncPtr()->Deactivate(); 3311 m_rView.SetDrawFuncPtr(nullptr); 3312 m_rView.LeaveDrawCreate(); 3313 m_rView.AttrChangedNotify(nullptr); 3314 } 3315 UpdatePointer( aDocPos, rMEvt.GetModifier() ); 3316 return; 3317 } 3318 } 3319 } 3320 } 3321 3322 switch ( nNumberOfClicks ) 3323 { 3324 case 1: 3325 break; 3326 case 2: 3327 { 3328 g_bFrameDrag = false; 3329 if ( !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) && 3330 FlyProtectFlags::NONE == rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) ) 3331 { 3332 /* This is no good: on the one hand GetSelectionType is used as flag field 3333 * (take a look into the GetSelectionType method) and on the other hand the 3334 * return value is used in a switch without proper masking (very nice), this must lead to trouble 3335 */ 3336 switch ( rSh.GetSelectionType() & ~SelectionType( SelectionType::FontWork | SelectionType::ExtrudedCustomShape ) ) 3337 { 3338 case SelectionType::Graphic: 3339 RstMBDownFlags(); 3340 if (!comphelper::LibreOfficeKit::isActive()) 3341 { 3342 GetView().GetViewFrame()->GetBindings().Execute( 3343 FN_FORMAT_GRAFIC_DLG, nullptr, 3344 SfxCallMode::RECORD|SfxCallMode::SLOT); 3345 } 3346 return; 3347 3348 // double click on OLE object --> OLE-InPlace 3349 case SelectionType::Ole: 3350 if (rSh.IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) 3351 { 3352 RstMBDownFlags(); 3353 rSh.LaunchOLEObj(); 3354 } 3355 return; 3356 3357 case SelectionType::Frame: 3358 RstMBDownFlags(); 3359 if (!comphelper::LibreOfficeKit::isActive()) 3360 { 3361 GetView().GetViewFrame()->GetBindings().Execute( 3362 FN_FORMAT_FRAME_DLG, nullptr, 3363 SfxCallMode::RECORD|SfxCallMode::SLOT); 3364 } 3365 return; 3366 3367 case SelectionType::DrawObject: 3368 RstMBDownFlags(); 3369 EnterDrawTextMode(aDocPos); 3370 if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) ) 3371 pSwDrawTextShell->Init(); 3372 return; 3373 3374 default: break; 3375 } 3376 } 3377 3378 // if the cursor position was corrected or if a Fly 3379 // was selected in ReadOnlyMode, no word selection, except when tiled rendering. 3380 if ((!g_bValidCursorPos || rSh.IsFrameSelected()) && !comphelper::LibreOfficeKit::isActive()) 3381 return; 3382 3383 SwField *pField; 3384 bool bFootnote = false; 3385 3386 if( !bIsDocReadOnly && 3387 (nullptr != (pField = rSh.GetCurField(true)) || 3388 ( bFootnote = rSh.GetCurFootnote() ) ) ) 3389 { 3390 RstMBDownFlags(); 3391 if( bFootnote ) 3392 GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE ); 3393 else 3394 { 3395 SwFieldTypesEnum nTypeId = pField->GetTypeId(); 3396 SfxViewFrame* pVFrame = GetView().GetViewFrame(); 3397 switch( nTypeId ) 3398 { 3399 case SwFieldTypesEnum::Postit: 3400 case SwFieldTypesEnum::Script: 3401 { 3402 // if it's a Readonly region, status has to be enabled 3403 sal_uInt16 nSlot = SwFieldTypesEnum::Postit == nTypeId ? FN_POSTIT : FN_JAVAEDIT; 3404 SfxBoolItem aItem(nSlot, true); 3405 pVFrame->GetBindings().SetState(aItem); 3406 pVFrame->GetBindings().Execute(nSlot); 3407 break; 3408 } 3409 case SwFieldTypesEnum::Authority : 3410 pVFrame->GetBindings().Execute(FN_EDIT_AUTH_ENTRY_DLG); 3411 break; 3412 case SwFieldTypesEnum::Input: 3413 case SwFieldTypesEnum::Dropdown: 3414 case SwFieldTypesEnum::SetInput: 3415 pVFrame->GetBindings().Execute(FN_UPDATE_INPUTFIELDS); 3416 break; 3417 default: 3418 pVFrame->GetBindings().Execute(FN_EDIT_FIELD); 3419 } 3420 } 3421 return; 3422 } 3423 // in extended mode double and triple 3424 // click has no effect. 3425 if ( rSh.IsExtMode() || rSh.IsBlockMode() ) 3426 return; 3427 3428 // select word, AdditionalMode if applicable 3429 if ( KEY_MOD1 == rMEvt.GetModifier() && !rSh.IsAddMode() ) 3430 { 3431 rSh.EnterAddMode(); 3432 rSh.SelWrd( &aDocPos ); 3433 rSh.LeaveAddMode(); 3434 } 3435 else 3436 { 3437 if (!rSh.SelWrd(&aDocPos) && comphelper::LibreOfficeKit::isActive()) 3438 // Double click did not select any word: try to 3439 // select the current cell in case we are in a 3440 // table. 3441 rSh.SelTableBox(); 3442 } 3443 3444 SwContentAtPos aContentAtPos(IsAttrAtPos::FormControl); 3445 if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) && 3446 aContentAtPos.aFnd.pFieldmark != nullptr) 3447 { 3448 IFieldmark *pFieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark ); 3449 if ( pFieldBM->GetFieldname( ) == ODF_FORMDROPDOWN || pFieldBM->GetFieldname( ) == ODF_FORMDATE ) 3450 { 3451 RstMBDownFlags(); 3452 rSh.getIDocumentMarkAccess()->ClearFieldActivation(); 3453 GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES); 3454 return; 3455 } 3456 } 3457 3458 g_bHoldSelection = true; 3459 return; 3460 } 3461 case 3: 3462 case 4: 3463 { 3464 g_bFrameDrag = false; 3465 // in extended mode double and triple 3466 // click has no effect. 3467 if ( rSh.IsExtMode() ) 3468 return; 3469 3470 // if the cursor position was corrected or if a Fly 3471 // was selected in ReadOnlyMode, no word selection. 3472 if ( !g_bValidCursorPos || rSh.IsFrameSelected() ) 3473 return; 3474 3475 // select line, AdditionalMode if applicable 3476 const bool bMod = KEY_MOD1 == rMEvt.GetModifier() && 3477 !rSh.IsAddMode(); 3478 3479 if ( bMod ) 3480 rSh.EnterAddMode(); 3481 3482 // Enhanced selection 3483 if ( 3 == nNumberOfClicks ) 3484 rSh.SelSentence( &aDocPos ); 3485 else 3486 rSh.SelPara( &aDocPos ); 3487 3488 if ( bMod ) 3489 rSh.LeaveAddMode(); 3490 3491 g_bHoldSelection = true; 3492 return; 3493 } 3494 3495 default: 3496 return; 3497 } 3498 3499 [[fallthrough]]; 3500 } 3501 case MOUSE_LEFT + KEY_SHIFT: 3502 case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1: 3503 { 3504 bool bLockView = m_bWasShdwCursor; 3505 3506 switch ( rMEvt.GetModifier() ) 3507 { 3508 case KEY_MOD1 + KEY_SHIFT: 3509 { 3510 if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) ) 3511 { 3512 m_rView.NoRotate(); 3513 rSh.HideCursor(); 3514 if ( rSh.IsSelFrameMode() ) 3515 rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP); 3516 else 3517 { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) ) 3518 { 3519 rSh.EnterSelFrameMode( &aDocPos ); 3520 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 3521 SwEditWin::m_nDDStartPosX = aDocPos.X(); 3522 g_bFrameDrag = true; 3523 return; 3524 } 3525 } 3526 } 3527 else if( rSh.IsSelFrameMode() && 3528 rSh.GetDrawView()->PickHandle( aDocPos )) 3529 { 3530 g_bFrameDrag = true; 3531 g_bNoInterrupt = false; 3532 return; 3533 } 3534 } 3535 break; 3536 case KEY_MOD1: 3537 if ( !bExecDrawTextLink ) 3538 { 3539 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) 3540 { 3541 SwContentAtPos aContentAtPos(IsAttrAtPos::Outline); 3542 if(rSh.GetContentAtPos(aDocPos, aContentAtPos)) 3543 { 3544 // move cursor to outline para start and toggle outline content visibility 3545 MoveCursor(rSh, aDocPos, bOnlyText, bLockView); 3546 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint()); 3547 SwOutlineNodes::size_type nPos; 3548 if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos)) 3549 rSh.ToggleOutlineContentVisibility(nPos); 3550 return; 3551 } 3552 } 3553 if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) ) 3554 { 3555 m_rView.NoRotate(); 3556 rSh.HideCursor(); 3557 if ( rSh.IsSelFrameMode() ) 3558 rSh.SelectObj(aDocPos, SW_ENTER_GROUP); 3559 else 3560 { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) ) 3561 { 3562 rSh.EnterSelFrameMode( &aDocPos ); 3563 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 3564 SwEditWin::m_nDDStartPosX = aDocPos.X(); 3565 g_bFrameDrag = true; 3566 return; 3567 } 3568 } 3569 } 3570 else if( rSh.IsSelFrameMode() && 3571 rSh.GetDrawView()->PickHandle( aDocPos )) 3572 { 3573 g_bFrameDrag = true; 3574 g_bNoInterrupt = false; 3575 return; 3576 } 3577 else 3578 { 3579 if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() ) 3580 { 3581 rSh.PushMode(); 3582 g_bModePushed = true; 3583 3584 bool bUnLockView = !rSh.IsViewLocked(); 3585 rSh.LockView( true ); 3586 rSh.EnterAddMode(); 3587 if( bUnLockView ) 3588 rSh.LockView( false ); 3589 } 3590 bCallBase = false; 3591 } 3592 } 3593 break; 3594 case KEY_MOD2: 3595 { 3596 if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() ) 3597 { 3598 rSh.PushMode(); 3599 g_bModePushed = true; 3600 bool bUnLockView = !rSh.IsViewLocked(); 3601 rSh.LockView( true ); 3602 rSh.EnterBlockMode(); 3603 if( bUnLockView ) 3604 rSh.LockView( false ); 3605 } 3606 bCallBase = false; 3607 } 3608 break; 3609 case KEY_SHIFT: 3610 { 3611 if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) ) 3612 { 3613 m_rView.NoRotate(); 3614 rSh.HideCursor(); 3615 if ( rSh.IsSelFrameMode() ) 3616 { 3617 rSh.SelectObj(aDocPos, SW_ADD_SELECT); 3618 3619 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); 3620 if (rMarkList.GetMark(0) == nullptr) 3621 { 3622 rSh.LeaveSelFrameMode(); 3623 m_rView.AttrChangedNotify(nullptr); 3624 g_bFrameDrag = false; 3625 } 3626 } 3627 else 3628 { if ( rSh.SelectObj( aDocPos ) ) 3629 { 3630 rSh.EnterSelFrameMode( &aDocPos ); 3631 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 3632 SwEditWin::m_nDDStartPosX = aDocPos.X(); 3633 g_bFrameDrag = true; 3634 return; 3635 } 3636 } 3637 } 3638 else 3639 { 3640 if ( rSh.IsSelFrameMode() && 3641 rSh.IsInsideSelectedObj( aDocPos ) ) 3642 { 3643 rSh.EnterSelFrameMode( &aDocPos ); 3644 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 3645 SwEditWin::m_nDDStartPosX = aDocPos.X(); 3646 g_bFrameDrag = true; 3647 return; 3648 } 3649 if ( rSh.IsSelFrameMode() ) 3650 { 3651 rSh.UnSelectFrame(); 3652 rSh.LeaveSelFrameMode(); 3653 m_rView.AttrChangedNotify(nullptr); 3654 g_bFrameDrag = false; 3655 } 3656 if ( !rSh.IsExtMode() ) 3657 { 3658 // don't start a selection when an 3659 // URL field or a graphic is clicked 3660 bool bSttSelect = rSh.HasSelection() || 3661 PointerStyle::RefHand != GetPointer(); 3662 3663 if( !bSttSelect ) 3664 { 3665 bSttSelect = true; 3666 if( bExecHyperlinks ) 3667 { 3668 SwContentAtPos aContentAtPos( 3669 IsAttrAtPos::Ftn | 3670 IsAttrAtPos::InetAttr ); 3671 3672 if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) ) 3673 { 3674 if( !rSh.IsViewLocked() && 3675 !rSh.IsReadOnlyAvailable() && 3676 aContentAtPos.IsInProtectSect() ) 3677 bLockView = true; 3678 3679 bSttSelect = false; 3680 } 3681 else if( rSh.IsURLGrfAtPos( aDocPos )) 3682 bSttSelect = false; 3683 } 3684 } 3685 3686 if( bSttSelect ) 3687 rSh.SttSelect(); 3688 } 3689 } 3690 bCallBase = false; 3691 break; 3692 } 3693 default: 3694 if( !rSh.IsViewLocked() ) 3695 { 3696 SwContentAtPos aContentAtPos( IsAttrAtPos::ClickField | 3697 IsAttrAtPos::InetAttr ); 3698 if( rSh.GetContentAtPos( aDocPos, aContentAtPos ) && 3699 !rSh.IsReadOnlyAvailable() && 3700 aContentAtPos.IsInProtectSect() ) 3701 bLockView = true; 3702 } 3703 } 3704 3705 if ( rSh.IsGCAttr() ) 3706 { 3707 rSh.GCAttr(); 3708 rSh.ClearGCAttr(); 3709 } 3710 3711 SwContentAtPos aFieldAtPos(IsAttrAtPos::Field); 3712 bool bEditableFieldClicked = false; 3713 3714 // Are we clicking on a field? 3715 if (rSh.GetContentAtPos(aDocPos, aFieldAtPos)) 3716 { 3717 bool bEditableField = (aFieldAtPos.pFndTextAttr != nullptr 3718 && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD); 3719 3720 if (!bEditableField) 3721 { 3722 rSh.CallSetCursor(&aDocPos, bOnlyText); 3723 // Unfortunately the cursor may be on field 3724 // position or on position after field depending on which 3725 // half of the field was clicked on. 3726 SwTextAttr const*const pTextField(aFieldAtPos.pFndTextAttr); 3727 if (pTextField && rSh.GetCurrentShellCursor().GetPoint()->nContent 3728 .GetIndex() != pTextField->GetStart()) 3729 { 3730 assert(rSh.GetCurrentShellCursor().GetPoint()->nContent 3731 .GetIndex() == (pTextField->GetStart() + 1)); 3732 rSh.Left( CRSR_SKIP_CHARS, false, 1, false ); 3733 } 3734 // don't go into the !bOverSelect block below - it moves 3735 // the cursor 3736 break; 3737 } 3738 else 3739 { 3740 bEditableFieldClicked = true; 3741 } 3742 } 3743 3744 bool bOverSelect = rSh.TestCurrPam( aDocPos ); 3745 bool bOverURLGrf = false; 3746 if( !bOverSelect ) 3747 bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos ); 3748 3749 if ( !bOverSelect || rSh.IsInSelect() ) 3750 { 3751 MoveCursor( rSh, aDocPos, bOnlyText, bLockView ); 3752 bCallBase = false; 3753 } 3754 if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText) 3755 { 3756 const SelectionType nSelType = rSh.GetSelectionType(); 3757 // Check in general, if an object is selectable at given position. 3758 // Thus, also text fly frames in background become selectable via Ctrl-Click. 3759 if ( ( nSelType & SelectionType::Ole || 3760 nSelType & SelectionType::Graphic || 3761 rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) ) 3762 { 3763 SwMvContext aMvContext( &rSh ); 3764 rSh.EnterSelFrameMode(); 3765 bCallBase = false; 3766 } 3767 } 3768 if ( !bOverSelect && bEditableFieldClicked && (!pCursorField || 3769 pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField())) 3770 { 3771 // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART 3772 // and CH_TXT_ATR_INPUTFIELDEND 3773 rSh.SttSelect(); 3774 rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1, 3775 *(aFieldAtPos.pFndTextAttr->End()) - 1 ); 3776 } 3777 // don't reset here any longer so that, in case through MouseMove 3778 // with pressed Ctrl key a multiple-selection should happen, 3779 // the previous selection is not released in Drag. 3780 break; 3781 } 3782 } 3783 } 3784 else if (MOUSE_RIGHT == rMEvt.GetButtons()) 3785 { 3786 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton() && rMEvt.GetModifier() == KEY_MOD1) 3787 { 3788 SwContentAtPos aContentAtPos(IsAttrAtPos::Outline); 3789 if(rSh.GetContentAtPos(aDocPos, aContentAtPos)) 3790 { 3791 // move cursor to para start toggle outline content visibility and set the same visibility for subs 3792 MoveCursor(rSh, aDocPos, false, true); 3793 SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint()); 3794 SwOutlineNodes::size_type nPos; 3795 if (rSh.GetNodes().GetOutLineNds().Seek_Entry(&aPam.GetPoint()->nNode.GetNode(), &nPos)) 3796 { 3797 if (rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()) 3798 rSh.ToggleOutlineContentVisibility(nPos); 3799 else 3800 { 3801 SwOutlineNodes::size_type nOutlineNodesCount = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); 3802 int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos); 3803 bool bVisible = rSh.IsOutlineContentVisible(nPos); 3804 do 3805 { 3806 if (rSh.IsOutlineContentVisible(nPos) == bVisible) 3807 rSh.ToggleOutlineContentVisibility(nPos); 3808 } while (++nPos < nOutlineNodesCount 3809 && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel); 3810 } 3811 return; 3812 } 3813 } 3814 } 3815 else if ( !rMEvt.GetModifier() 3816 && static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4) == 1 3817 && !rSh.TestCurrPam( aDocPos ) ) 3818 { 3819 SwContentAtPos aFieldAtPos(IsAttrAtPos::Field); 3820 3821 // Are we clicking on a field? 3822 if (g_bValidCursorPos 3823 && rSh.GetContentAtPos(aDocPos, aFieldAtPos) 3824 && aFieldAtPos.pFndTextAttr != nullptr 3825 && aFieldAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD 3826 && (!pCursorField || pCursorField != aFieldAtPos.pFndTextAttr->GetFormatField().GetField())) 3827 { 3828 // Move the cursor 3829 MoveCursor( rSh, aDocPos, rSh.IsObjSelectable( aDocPos ), m_bWasShdwCursor ); 3830 bCallBase = false; 3831 3832 // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART 3833 // and CH_TXT_ATR_INPUTFIELDEND 3834 rSh.SttSelect(); 3835 rSh.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1, 3836 *(aFieldAtPos.pFndTextAttr->End()) - 1 ); 3837 } 3838 } 3839 } 3840 3841 if (bCallBase) 3842 Window::MouseButtonDown(rMEvt); 3843 } 3844 3845 bool SwEditWin::changeMousePointer(Point const & rDocPoint) 3846 { 3847 SwWrtShell & rShell = m_rView.GetWrtShell(); 3848 3849 SwTab nMouseTabCol; 3850 if ( SwTab::COL_NONE != (nMouseTabCol = rShell.WhichMouseTabCol( rDocPoint ) ) && 3851 !rShell.IsObjSelectable( rDocPoint ) ) 3852 { 3853 PointerStyle nPointer = PointerStyle::Null; 3854 bool bChkTableSel = false; 3855 3856 switch ( nMouseTabCol ) 3857 { 3858 case SwTab::COL_VERT : 3859 case SwTab::ROW_HORI : 3860 nPointer = PointerStyle::VSizeBar; 3861 bChkTableSel = true; 3862 break; 3863 case SwTab::ROW_VERT : 3864 case SwTab::COL_HORI : 3865 nPointer = PointerStyle::HSizeBar; 3866 bChkTableSel = true; 3867 break; 3868 // Enhanced table selection 3869 case SwTab::SEL_HORI : 3870 nPointer = PointerStyle::TabSelectSE; 3871 break; 3872 case SwTab::SEL_HORI_RTL : 3873 case SwTab::SEL_VERT : 3874 nPointer = PointerStyle::TabSelectSW; 3875 break; 3876 case SwTab::COLSEL_HORI : 3877 case SwTab::ROWSEL_VERT : 3878 nPointer = PointerStyle::TabSelectS; 3879 break; 3880 case SwTab::ROWSEL_HORI : 3881 nPointer = PointerStyle::TabSelectE; 3882 break; 3883 case SwTab::ROWSEL_HORI_RTL : 3884 case SwTab::COLSEL_VERT : 3885 nPointer = PointerStyle::TabSelectW; 3886 break; 3887 default: break; // prevent compiler warning 3888 } 3889 3890 if ( PointerStyle::Null != nPointer && 3891 // i#35543 - Enhanced table selection is explicitly allowed in table mode 3892 ( !bChkTableSel || !rShell.IsTableMode() ) && 3893 !comphelper::LibreOfficeKit::isActive() ) 3894 { 3895 SetPointer( nPointer ); 3896 } 3897 3898 return true; 3899 } 3900 else if (rShell.IsNumLabel(rDocPoint, RULER_MOUSE_MARGINWIDTH)) 3901 { 3902 // i#42921 - consider vertical mode 3903 SwTextNode* pNodeAtPos = rShell.GetNumRuleNodeAtPos( rDocPoint ); 3904 const PointerStyle nPointer = 3905 SwFEShell::IsVerticalModeAtNdAndPos( *pNodeAtPos, rDocPoint ) 3906 ? PointerStyle::VSizeBar 3907 : PointerStyle::HSizeBar; 3908 SetPointer( nPointer ); 3909 3910 return true; 3911 } 3912 return false; 3913 } 3914 3915 void SwEditWin::MouseMove(const MouseEvent& _rMEvt) 3916 { 3917 MouseEvent rMEvt(_rMEvt); 3918 3919 if (comphelper::LibreOfficeKit::isActive()) 3920 { 3921 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel())) 3922 { 3923 pWindow->MouseMove(rMEvt); 3924 return; 3925 } 3926 } 3927 3928 //ignore key modifiers for format paintbrush 3929 { 3930 bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard 3931 && m_pApplyTempl->m_pFormatClipboard->HasContent(); 3932 if( bExecFormatPaintbrush ) 3933 rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(), 3934 _rMEvt.GetMode(), _rMEvt.GetButtons() ); 3935 } 3936 3937 // as long as an action is running the MouseMove should be disconnected 3938 // otherwise bug 40102 occurs 3939 SwWrtShell &rSh = m_rView.GetWrtShell(); 3940 if( rSh.ActionPend() ) 3941 return ; 3942 3943 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) 3944 { 3945 // add/remove outline collapse button 3946 SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline); 3947 if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos)) 3948 { 3949 if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode()) 3950 { 3951 const SwNodes& rNds = rSh.GetDoc()->GetNodes(); 3952 SwOutlineNodes::size_type nPos; 3953 SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr); 3954 if (pContentFrame != m_pSavedOutlineFrame) 3955 { 3956 // remove collapse button when saved frame is not frame at mouse position 3957 if (m_pSavedOutlineFrame && /* is it possible that m_pSavedOutlineFrame is removed? */ !m_pSavedOutlineFrame->IsInDtor() && 3958 rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) && 3959 rSh.IsOutlineContentVisible(nPos)) 3960 { 3961 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); 3962 } 3963 m_pSavedOutlineFrame = pContentFrame; 3964 } 3965 // show collapse button 3966 if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), 3967 &nPos) && rSh.IsOutlineContentVisible(nPos)) 3968 { 3969 GetFrameControlsManager().SetOutlineContentVisibilityButton(aSwContentAtPos.aFnd.pNode->GetTextNode()); 3970 } 3971 } 3972 } 3973 else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor()) 3974 { 3975 // current pointer pos is not over an outline frame 3976 // previous frame was an outline frame 3977 // remove collapse button if showing 3978 const SwNodes& rNds = rSh.GetDoc()->GetNodes(); 3979 SwOutlineNodes::size_type nPos; 3980 if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)-> 3981 GetTextNodeFirst(), &nPos) && 3982 rSh.IsOutlineContentVisible(nPos)) 3983 { 3984 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, 3985 m_pSavedOutlineFrame); 3986 } 3987 m_pSavedOutlineFrame = nullptr; 3988 } 3989 } 3990 3991 if( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) ) 3992 { 3993 m_pShadCursor.reset(); 3994 } 3995 3996 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly(); 3997 3998 CurrShell aCurr( &rSh ); 3999 4000 //aPixPt == Point in Pixel, relative to ChildWin 4001 //aDocPt == Point in Twips, document coordinates 4002 const Point aPixPt( rMEvt.GetPosPixel() ); 4003 const Point aDocPt( PixelToLogic( aPixPt ) ); 4004 4005 if ( IsChainMode() ) 4006 { 4007 UpdatePointer( aDocPt, rMEvt.GetModifier() ); 4008 return; 4009 } 4010 4011 SdrView *pSdrView = rSh.GetDrawView(); 4012 4013 const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent ); 4014 m_aSaveCallEvent.Clear(); 4015 4016 if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) ) 4017 { 4018 SetPointer( PointerStyle::Text ); 4019 return; // evaluate SdrView's event 4020 } 4021 4022 const Point aOldPt( rSh.VisArea().Pos() ); 4023 const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive(); 4024 4025 if (rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) 4026 { 4027 if (m_pSavedOutlineFrame && !bInsWin) 4028 { 4029 // the mouse pointer has left the building 4030 // 86 the collapse button if showing 4031 const SwNodes& rNds = rSh.GetDoc()->GetNodes(); 4032 SwOutlineNodes::size_type nPos; 4033 rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos); 4034 if (rSh.IsOutlineContentVisible(nPos)) 4035 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); 4036 m_pSavedOutlineFrame = nullptr; 4037 } 4038 } 4039 4040 if( m_pShadCursor && !bInsWin ) 4041 { 4042 m_pShadCursor.reset(); 4043 } 4044 4045 if( bInsWin && m_xRowColumnSelectionStart ) 4046 { 4047 EnterArea(); 4048 Point aPos( aDocPt ); 4049 if( rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, m_bIsRowDrag )) 4050 return; 4051 } 4052 4053 // position is necessary for OS/2 because obviously after a MB-Down 4054 // a MB-Move is called immediately. 4055 if( g_bDDTimerStarted ) 4056 { 4057 Point aDD( SwEditWin::m_nDDStartPosX, SwEditWin::m_nDDStartPosY ); 4058 aDD = LogicToPixel( aDD ); 4059 tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 ); 4060 if ( !aRect.IsInside( aPixPt ) ) 4061 StopDDTimer( &rSh, aDocPt ); 4062 } 4063 4064 if(m_rView.GetDrawFuncPtr()) 4065 { 4066 if( m_bInsDraw ) 4067 { 4068 m_rView.GetDrawFuncPtr()->MouseMove( rMEvt ); 4069 if ( !bInsWin ) 4070 { 4071 Point aTmp( aDocPt ); 4072 aTmp += rSh.VisArea().Pos() - aOldPt; 4073 LeaveArea( aTmp ); 4074 } 4075 else 4076 EnterArea(); 4077 return; 4078 } 4079 else if(!rSh.IsFrameSelected() && !rSh.IsObjSelected()) 4080 { 4081 SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings(); 4082 Point aRelPos = rSh.GetRelativePagePosition(aDocPt); 4083 if(aRelPos.X() >= 0) 4084 { 4085 FieldUnit eMetric = ::GetDfltMetric(dynamic_cast<SwWebView*>( &GetView()) != nullptr ); 4086 SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); 4087 const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos ); 4088 rBnd.SetState( aTmp1 ); 4089 } 4090 else 4091 { 4092 rBnd.Invalidate(SID_ATTR_POSITION); 4093 } 4094 rBnd.Invalidate(SID_ATTR_SIZE); 4095 const SfxStringItem aCell( SID_TABLE_CELL, OUString() ); 4096 rBnd.SetState( aCell ); 4097 } 4098 } 4099 4100 // determine if we only change the mouse pointer and return 4101 if (!bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() && changeMousePointer(aDocPt)) 4102 { 4103 return; 4104 } 4105 4106 bool bDelShadCursor = true; 4107 4108 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) 4109 { 4110 case MOUSE_LEFT: 4111 if( m_pAnchorMarker ) 4112 { 4113 // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker. 4114 // This looks a little bit tricky, but it solves the following 4115 // problem: the m_pAnchorMarker contains a pointer to an SdrHdl, 4116 // if the FindAnchorPos-call cause a scrolling of the visible 4117 // area, it's possible that the SdrHdl will be destroyed and a 4118 // new one will initialized at the original position(GetHdlPos). 4119 // So the m_pAnchorMarker has to find the right SdrHdl, if it's 4120 // the old one, it will find it with position aOld, if this one 4121 // is destroyed, it will find a new one at position GetHdlPos(). 4122 4123 const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) ); 4124 Point aNew = rSh.FindAnchorPos( aDocPt ); 4125 SdrHdl* pHdl; 4126 if( pSdrView && (nullptr!=( pHdl = pSdrView->PickHandle( aOld ) )|| 4127 nullptr !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) && 4128 ( pHdl->GetKind() == SdrHdlKind::Anchor || 4129 pHdl->GetKind() == SdrHdlKind::Anchor_TR ) ) 4130 { 4131 m_pAnchorMarker->ChgHdl( pHdl ); 4132 if( aNew.X() || aNew.Y() ) 4133 { 4134 m_pAnchorMarker->SetPos( aNew ); 4135 m_pAnchorMarker->SetLastPos( aDocPt ); 4136 } 4137 } 4138 else 4139 { 4140 m_pAnchorMarker.reset(); 4141 } 4142 } 4143 if ( m_bInsDraw ) 4144 { 4145 if ( !m_bMBPressed ) 4146 break; 4147 if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) ) 4148 { 4149 if ( !bInsWin ) 4150 LeaveArea( aDocPt ); 4151 else 4152 EnterArea(); 4153 if ( m_rView.GetDrawFuncPtr() ) 4154 { 4155 pSdrView->SetOrtho(false); 4156 m_rView.GetDrawFuncPtr()->MouseMove( rMEvt ); 4157 } 4158 m_bIsInMove = true; 4159 } 4160 return; 4161 } 4162 4163 { 4164 SwWordCountWrapper *pWrdCnt = static_cast<SwWordCountWrapper*>(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); 4165 if (pWrdCnt) 4166 pWrdCnt->UpdateCounts(); 4167 } 4168 [[fallthrough]]; 4169 4170 case MOUSE_LEFT + KEY_SHIFT: 4171 case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1: 4172 if ( !m_bMBPressed ) 4173 break; 4174 [[fallthrough]]; 4175 case MOUSE_LEFT + KEY_MOD1: 4176 if ( g_bFrameDrag && rSh.IsSelFrameMode() ) 4177 { 4178 if( !m_bMBPressed ) 4179 break; 4180 4181 if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) ) 4182 { 4183 // event processing for resizing 4184 if (pSdrView && pSdrView->AreObjectsMarked()) 4185 { 4186 const Point aSttPt( PixelToLogic( m_aStartPos ) ); 4187 4188 // can we start? 4189 if( SdrHdlKind::User == g_eSdrMoveHdl ) 4190 { 4191 SdrHdl* pHdl = pSdrView->PickHandle( aSttPt ); 4192 g_eSdrMoveHdl = pHdl ? pHdl->GetKind() : SdrHdlKind::Move; 4193 } 4194 4195 const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat()); 4196 const SvxMacro* pMacro = nullptr; 4197 4198 SvMacroItemId nEvent = SdrHdlKind::Move == g_eSdrMoveHdl 4199 ? SvMacroItemId::SwFrmMove 4200 : SvMacroItemId::SwFrmResize; 4201 4202 if (nullptr != pFlyFormat) 4203 pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent); 4204 if (nullptr != pMacro && 4205 // or notify only e.g. every 20 Twip? 4206 m_aRszMvHdlPt != aDocPt ) 4207 { 4208 m_aRszMvHdlPt = aDocPt; 4209 sal_uInt32 nPos = 0; 4210 SbxArrayRef xArgs = new SbxArray; 4211 SbxVariableRef xVar = new SbxVariable; 4212 xVar->PutString( pFlyFormat->GetName() ); 4213 xArgs->Put32( xVar.get(), ++nPos ); 4214 4215 if( SvMacroItemId::SwFrmResize == nEvent ) 4216 { 4217 xVar = new SbxVariable; 4218 xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) ); 4219 xArgs->Put32( xVar.get(), ++nPos ); 4220 } 4221 4222 xVar = new SbxVariable; 4223 xVar->PutLong( aDocPt.X() - aSttPt.X() ); 4224 xArgs->Put32( xVar.get(), ++nPos ); 4225 xVar = new SbxVariable; 4226 xVar->PutLong( aDocPt.Y() - aSttPt.Y() ); 4227 xArgs->Put32( xVar.get(), ++nPos ); 4228 4229 OUString sRet; 4230 4231 ReleaseMouse(); 4232 4233 rSh.ExecMacro( *pMacro, &sRet, xArgs.get() ); 4234 4235 CaptureMouse(); 4236 4237 if( !sRet.isEmpty() && sRet.toInt32()!=0 ) 4238 return ; 4239 } 4240 } 4241 // event processing for resizing 4242 4243 if( bIsDocReadOnly ) 4244 break; 4245 4246 bool bResizeKeepRatio = rSh.GetSelectionType() & SelectionType::Graphic || 4247 rSh.GetSelectionType() & SelectionType::Media || 4248 rSh.GetSelectionType() & SelectionType::Ole; 4249 bool bisResize = g_eSdrMoveHdl != SdrHdlKind::Move; 4250 4251 if (pSdrView) 4252 { 4253 // Resize proportionally when media is selected and the user drags on a corner 4254 const Point aSttPt(PixelToLogic(m_aStartPos)); 4255 SdrHdl* pHdl = pSdrView->PickHandle(aSttPt); 4256 if (pHdl) 4257 bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl(); 4258 4259 if (pSdrView->GetDragMode() == SdrDragMode::Crop) 4260 bisResize = false; 4261 if (rMEvt.IsShift()) 4262 { 4263 pSdrView->SetAngleSnapEnabled(!bResizeKeepRatio); 4264 if (bisResize) 4265 pSdrView->SetOrtho(!bResizeKeepRatio); 4266 else 4267 pSdrView->SetOrtho(true); 4268 } 4269 else 4270 { 4271 pSdrView->SetAngleSnapEnabled(bResizeKeepRatio); 4272 if (bisResize) 4273 pSdrView->SetOrtho(bResizeKeepRatio); 4274 else 4275 pSdrView->SetOrtho(false); 4276 } 4277 } 4278 4279 rSh.Drag( &aDocPt, rMEvt.IsShift() ); 4280 m_bIsInMove = true; 4281 } 4282 else if( bIsDocReadOnly ) 4283 break; 4284 4285 if ( !bInsWin ) 4286 { 4287 Point aTmp( aDocPt ); 4288 aTmp += rSh.VisArea().Pos() - aOldPt; 4289 LeaveArea( aTmp ); 4290 } 4291 else if(m_bIsInMove) 4292 EnterArea(); 4293 return; 4294 } 4295 if ( !rSh.IsSelFrameMode() && !g_bDDINetAttr && 4296 (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) && 4297 (rSh.IsInSelect() || !rSh.TestCurrPam( aDocPt )) ) 4298 { 4299 if ( pSdrView ) 4300 { 4301 if ( rMEvt.IsShift() ) 4302 pSdrView->SetOrtho(true); 4303 else 4304 pSdrView->SetOrtho(false); 4305 } 4306 if ( !bInsWin ) 4307 { 4308 Point aTmp( aDocPt ); 4309 aTmp += rSh.VisArea().Pos() - aOldPt; 4310 LeaveArea( aTmp ); 4311 } 4312 else 4313 { 4314 if( !rMEvt.IsSynthetic() && 4315 ( MOUSE_LEFT != rMEvt.GetButtons() || 4316 KEY_MOD1 != rMEvt.GetModifier() || 4317 !rSh.Is_FnDragEQBeginDrag() || 4318 rSh.IsAddMode() ) ) 4319 { 4320 rSh.Drag( &aDocPt, false ); 4321 4322 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false)); 4323 EnterArea(); 4324 } 4325 } 4326 } 4327 g_bDDINetAttr = false; 4328 break; 4329 case 0: 4330 { 4331 if ( m_pApplyTempl ) 4332 { 4333 UpdatePointer(aDocPt); // maybe a frame has to be marked here 4334 break; 4335 } 4336 // change ui if mouse is over SwPostItField 4337 // TODO: do the same thing for redlines IsAttrAtPos::Redline 4338 SwContentAtPos aContentAtPos( IsAttrAtPos::Field); 4339 if (rSh.GetContentAtPos(aDocPt, aContentAtPos, false)) 4340 { 4341 const SwField* pField = aContentAtPos.aFnd.pField; 4342 if (pField->Which()== SwFieldIds::Postit) 4343 { 4344 m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pField),false); 4345 } 4346 else 4347 m_rView.GetPostItMgr()->SetShadowState(nullptr,false); 4348 } 4349 else 4350 m_rView.GetPostItMgr()->SetShadowState(nullptr,false); 4351 [[fallthrough]]; 4352 } 4353 case KEY_SHIFT: 4354 case KEY_MOD2: 4355 case KEY_MOD1: 4356 if ( !m_bInsDraw ) 4357 { 4358 bool bTstShdwCursor = true; 4359 4360 UpdatePointer( aDocPt, rMEvt.GetModifier() ); 4361 4362 const SwFrameFormat* pFormat = nullptr; 4363 const SwFormatINetFormat* pINet = nullptr; 4364 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr ); 4365 if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) ) 4366 pINet = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr); 4367 4368 const void* pTmp = pINet; 4369 4370 if( pINet || 4371 nullptr != ( pTmp = pFormat = rSh.GetFormatFromAnyObj( aDocPt ))) 4372 { 4373 bTstShdwCursor = false; 4374 if( pTmp == pINet ) 4375 m_aSaveCallEvent.Set( pINet ); 4376 else 4377 { 4378 IMapObject* pIMapObj = pFormat->GetIMapObject( aDocPt ); 4379 if( pIMapObj ) 4380 m_aSaveCallEvent.Set( pFormat, pIMapObj ); 4381 else 4382 m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFormat ); 4383 } 4384 4385 // should be over an InternetField with an 4386 // embedded macro? 4387 if( m_aSaveCallEvent != aLastCallEvent ) 4388 { 4389 if( aLastCallEvent.HasEvent() ) 4390 rSh.CallEvent( SvMacroItemId::OnMouseOut, 4391 aLastCallEvent, true ); 4392 // 0 says that the object doesn't have any table 4393 if( !rSh.CallEvent( SvMacroItemId::OnMouseOver, 4394 m_aSaveCallEvent )) 4395 m_aSaveCallEvent.Clear(); 4396 } 4397 } 4398 else if( aLastCallEvent.HasEvent() ) 4399 { 4400 // cursor was on an object 4401 rSh.CallEvent( SvMacroItemId::OnMouseOut, 4402 aLastCallEvent, true ); 4403 } 4404 4405 if( bTstShdwCursor && bInsWin && !bIsDocReadOnly && 4406 !m_bInsFrame && 4407 !rSh.GetViewOptions()->getBrowseMode() && 4408 rSh.GetViewOptions()->IsShadowCursor() && 4409 !(rMEvt.GetModifier() + rMEvt.GetButtons()) && 4410 !rSh.HasSelection() && !GetConnectMetaFile() ) 4411 { 4412 SwRect aRect; 4413 sal_Int16 eOrient; 4414 SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode(); 4415 if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient )) 4416 { 4417 if( !m_pShadCursor ) 4418 m_pShadCursor.reset( new SwShadowCursor( *this, 4419 SwViewOption::GetDirectCursorColor() ) ); 4420 if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient ) 4421 eOrient = text::HoriOrientation::LEFT; 4422 m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) ); 4423 bDelShadCursor = false; 4424 } 4425 } 4426 } 4427 break; 4428 case MOUSE_LEFT + KEY_MOD2: 4429 if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() ) 4430 { 4431 rSh.Drag( &aDocPt, false ); 4432 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPt, false)); 4433 EnterArea(); 4434 } 4435 break; 4436 } 4437 4438 if( bDelShadCursor && m_pShadCursor ) 4439 { 4440 m_pShadCursor.reset(); 4441 } 4442 m_bWasShdwCursor = false; 4443 } 4444 4445 /** 4446 * Button Up 4447 */ 4448 void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt) 4449 { 4450 if (comphelper::LibreOfficeKit::isActive()) 4451 { 4452 if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel())) 4453 { 4454 pWindow->MouseButtonUp(rMEvt); 4455 return; 4456 } 4457 } 4458 4459 bool bCallBase = true; 4460 4461 bool bCallShadowCursor = m_bWasShdwCursor; 4462 m_bWasShdwCursor = false; 4463 if( m_pShadCursor ) 4464 { 4465 m_pShadCursor.reset(); 4466 } 4467 4468 m_xRowColumnSelectionStart.reset(); 4469 4470 SdrHdlKind eOldSdrMoveHdl = g_eSdrMoveHdl; 4471 g_eSdrMoveHdl = SdrHdlKind::User; // for MoveEvents - reset again 4472 4473 // preventively reset 4474 m_rView.SetTabColFromDoc( false ); 4475 m_rView.SetNumRuleNodeFromDoc(nullptr); 4476 4477 SwWrtShell &rSh = m_rView.GetWrtShell(); 4478 CurrShell aCurr( &rSh ); 4479 SdrView *pSdrView = rSh.GetDrawView(); 4480 if ( pSdrView ) 4481 { 4482 // tdf34555: ortho was always reset before being used in EndSdrDrag 4483 // Now, it is reset only if not in Crop mode. 4484 if (pSdrView->GetDragMode() != SdrDragMode::Crop && !rMEvt.IsShift()) 4485 pSdrView->SetOrtho(false); 4486 4487 if ( pSdrView->MouseButtonUp( rMEvt,this ) ) 4488 { 4489 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); 4490 return; // SdrView's event evaluated 4491 } 4492 } 4493 // only process MouseButtonUp when the Down went to that windows as well. 4494 if ( !m_bMBPressed ) 4495 { 4496 // Undo for the watering can is already in CommandHdl 4497 // that's the way it should be! 4498 4499 return; 4500 } 4501 4502 Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) ); 4503 4504 if ( g_bDDTimerStarted ) 4505 { 4506 StopDDTimer( &rSh, aDocPt ); 4507 m_bMBPressed = false; 4508 if ( rSh.IsSelFrameMode() ) 4509 { 4510 rSh.EndDrag( &aDocPt, false ); 4511 g_bFrameDrag = false; 4512 } 4513 g_bNoInterrupt = false; 4514 const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) ); 4515 if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved 4516 { 4517 SdrPageView* pPV = nullptr; 4518 SdrObject* pObj = pSdrView ? pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr; 4519 if (pObj) 4520 { 4521 SwFrameFormat* pFormat = GetUserCall(pObj)->GetFormat(); 4522 SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_FLYFRMFMT); 4523 if (!pShapeFormat) 4524 { 4525 pSdrView->UnmarkAllObj(); 4526 pSdrView->MarkObj(pObj,pPV); 4527 } 4528 else 4529 { 4530 // If the fly frame is a textbox of a shape, then select the shape instead. 4531 SdrObject* pShape = pShapeFormat->FindSdrObject(); 4532 pSdrView->UnmarkAllObj(); 4533 pSdrView->MarkObj(pShape, pPV); 4534 } 4535 } 4536 } 4537 ReleaseMouse(); 4538 return; 4539 } 4540 4541 if( m_pAnchorMarker ) 4542 { 4543 if(m_pAnchorMarker->GetHdl()) 4544 { 4545 // #i121463# delete selected after drag 4546 m_pAnchorMarker->GetHdl()->SetSelected(false); 4547 } 4548 4549 Point aPnt( m_pAnchorMarker->GetLastPos() ); 4550 m_pAnchorMarker.reset(); 4551 if( aPnt.X() || aPnt.Y() ) 4552 rSh.FindAnchorPos( aPnt, true ); 4553 } 4554 if ( m_bInsDraw && m_rView.GetDrawFuncPtr() ) 4555 { 4556 if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) ) 4557 { 4558 if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp 4559 { 4560 m_rView.GetDrawFuncPtr()->Deactivate(); 4561 4562 if (!m_rView.IsDrawMode()) 4563 { 4564 m_rView.SetDrawFuncPtr(nullptr); 4565 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); 4566 rBind.Invalidate( SID_ATTR_SIZE ); 4567 rBind.Invalidate( SID_TABLE_CELL ); 4568 } 4569 } 4570 4571 if ( rSh.IsObjSelected() ) 4572 { 4573 rSh.EnterSelFrameMode(); 4574 if (!m_rView.GetDrawFuncPtr()) 4575 StdDrawMode( OBJ_NONE, true ); 4576 } 4577 else if ( rSh.IsFrameSelected() ) 4578 { 4579 rSh.EnterSelFrameMode(); 4580 StopInsFrame(); 4581 } 4582 else 4583 { 4584 const Point aDocPos( PixelToLogic( m_aStartPos ) ); 4585 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false)); 4586 rSh.Edit(); 4587 } 4588 4589 m_rView.AttrChangedNotify(nullptr); 4590 } 4591 else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate()) 4592 m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing 4593 4594 g_bNoInterrupt = false; 4595 if (IsMouseCaptured()) 4596 ReleaseMouse(); 4597 return; 4598 } 4599 bool bPopMode = false; 4600 switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) 4601 { 4602 case MOUSE_LEFT: 4603 if ( m_bInsDraw && rSh.IsDrawCreate() ) 4604 { 4605 if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) ) 4606 { 4607 m_rView.GetDrawFuncPtr()->Deactivate(); 4608 m_rView.AttrChangedNotify(nullptr); 4609 if ( rSh.IsObjSelected() ) 4610 rSh.EnterSelFrameMode(); 4611 if ( m_rView.GetDrawFuncPtr() && m_bInsFrame ) 4612 StopInsFrame(); 4613 } 4614 bCallBase = false; 4615 break; 4616 } 4617 [[fallthrough]]; 4618 case MOUSE_LEFT + KEY_MOD1: 4619 case MOUSE_LEFT + KEY_MOD2: 4620 case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1: 4621 if ( g_bFrameDrag && rSh.IsSelFrameMode() ) 4622 { 4623 if ( rMEvt.IsMod1() ) // copy and don't move. 4624 { 4625 // abort drag, use internal Copy instead 4626 tools::Rectangle aRect; 4627 rSh.GetDrawView()->TakeActionRect( aRect ); 4628 if (!aRect.IsEmpty()) 4629 { 4630 rSh.BreakDrag(); 4631 Point aEndPt, aSttPt; 4632 if ( rSh.GetSelFrameType() & FrameTypeFlags::FLY_ATCNT ) 4633 { 4634 aEndPt = aRect.TopLeft(); 4635 aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft(); 4636 } 4637 else 4638 { 4639 aEndPt = aRect.Center(); 4640 aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center(); 4641 } 4642 if ( aSttPt != aEndPt ) 4643 { 4644 rSh.StartUndo( SwUndoId::UI_DRAG_AND_COPY ); 4645 rSh.Copy(rSh, aSttPt, aEndPt); 4646 rSh.EndUndo( SwUndoId::UI_DRAG_AND_COPY ); 4647 } 4648 } 4649 else { 4650 rSh.EndDrag( &aDocPt, false ); 4651 } 4652 } 4653 else 4654 { 4655 { 4656 const SwFrameFormat *const pFlyFormat(rSh.GetFlyFrameFormat()); 4657 const SvxMacro* pMacro = nullptr; 4658 4659 SvMacroItemId nEvent = SdrHdlKind::Move == eOldSdrMoveHdl 4660 ? SvMacroItemId::SwFrmMove 4661 : SvMacroItemId::SwFrmResize; 4662 4663 if (nullptr != pFlyFormat) 4664 pMacro = pFlyFormat->GetMacro().GetMacroTable().Get(nEvent); 4665 if (nullptr != pMacro) 4666 { 4667 const Point aSttPt( PixelToLogic( m_aStartPos ) ); 4668 m_aRszMvHdlPt = aDocPt; 4669 sal_uInt32 nPos = 0; 4670 SbxArrayRef xArgs = new SbxArray; 4671 SbxVariableRef xVar = new SbxVariable; 4672 xVar->PutString( pFlyFormat->GetName() ); 4673 xArgs->Put32( xVar.get(), ++nPos ); 4674 4675 if( SvMacroItemId::SwFrmResize == nEvent ) 4676 { 4677 xVar = new SbxVariable; 4678 xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) ); 4679 xArgs->Put32( xVar.get(), ++nPos ); 4680 } 4681 4682 xVar = new SbxVariable; 4683 xVar->PutLong( aDocPt.X() - aSttPt.X() ); 4684 xArgs->Put32( xVar.get(), ++nPos ); 4685 xVar = new SbxVariable; 4686 xVar->PutLong( aDocPt.Y() - aSttPt.Y() ); 4687 xArgs->Put32( xVar.get(), ++nPos ); 4688 4689 xVar = new SbxVariable; 4690 xVar->PutUShort( 1 ); 4691 xArgs->Put32( xVar.get(), ++nPos ); 4692 4693 ReleaseMouse(); 4694 4695 rSh.ExecMacro( *pMacro, nullptr, xArgs.get() ); 4696 4697 CaptureMouse(); 4698 } 4699 } 4700 rSh.EndDrag( &aDocPt, false ); 4701 } 4702 g_bFrameDrag = false; 4703 bCallBase = false; 4704 break; 4705 } 4706 bPopMode = true; 4707 [[fallthrough]]; 4708 case MOUSE_LEFT + KEY_SHIFT: 4709 if (rSh.IsSelFrameMode()) 4710 { 4711 4712 rSh.EndDrag( &aDocPt, false ); 4713 g_bFrameDrag = false; 4714 bCallBase = false; 4715 break; 4716 } 4717 4718 if( g_bHoldSelection ) 4719 { 4720 // the EndDrag should be called in any case 4721 g_bHoldSelection = false; 4722 rSh.EndDrag( &aDocPt, false ); 4723 } 4724 else 4725 { 4726 SwContentAtPos aFieldAtPos ( IsAttrAtPos::Field ); 4727 if ( !rSh.IsInSelect() && rSh.TestCurrPam( aDocPt ) && 4728 !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) ) 4729 { 4730 const bool bTmpNoInterrupt = g_bNoInterrupt; 4731 g_bNoInterrupt = false; 4732 { // create only temporary move context because otherwise 4733 // the query to the content form doesn't work!!! 4734 SwMvContext aMvContext( &rSh ); 4735 const Point aDocPos( PixelToLogic( m_aStartPos ) ); 4736 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false)); 4737 } 4738 g_bNoInterrupt = bTmpNoInterrupt; 4739 4740 } 4741 else 4742 { 4743 bool bInSel = rSh.IsInSelect(); 4744 rSh.EndDrag( &aDocPt, false ); 4745 4746 // Internetfield? --> call link (load doc!!) 4747 if( !bInSel ) 4748 { 4749 LoadUrlFlags nFilter = LoadUrlFlags::NONE; 4750 if( KEY_MOD1 == rMEvt.GetModifier() ) 4751 nFilter |= LoadUrlFlags::NewView; 4752 4753 bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); 4754 if ( !bExecHyperlinks ) 4755 { 4756 SvtSecurityOptions aSecOpts; 4757 const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink ); 4758 if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) || 4759 ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) ) 4760 bExecHyperlinks = true; 4761 } 4762 4763 const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1; 4764 4765 if(m_pApplyTempl) 4766 bExecHyperlinks = false; 4767 4768 SwContentAtPos aContentAtPos( IsAttrAtPos::Field | 4769 IsAttrAtPos::InetAttr | 4770 IsAttrAtPos::SmartTag | IsAttrAtPos::FormControl); 4771 4772 if( rSh.GetContentAtPos( aDocPt, aContentAtPos ) ) 4773 { 4774 // Do it again if we're not on a field/hyperlink to update the cursor accordingly 4775 if ( IsAttrAtPos::Field != aContentAtPos.eContentAtPos 4776 && IsAttrAtPos::InetAttr != aContentAtPos.eContentAtPos ) 4777 rSh.GetContentAtPos( aDocPt, aContentAtPos, true ); 4778 4779 bool bViewLocked = rSh.IsViewLocked(); 4780 if( !bViewLocked && !rSh.IsReadOnlyAvailable() && 4781 aContentAtPos.IsInProtectSect() ) 4782 rSh.LockView( true ); 4783 4784 ReleaseMouse(); 4785 4786 if( IsAttrAtPos::Field == aContentAtPos.eContentAtPos ) 4787 { 4788 bool bAddMode(false); 4789 // AdditionalMode if applicable 4790 if (KEY_MOD1 == rMEvt.GetModifier() 4791 && !rSh.IsAddMode()) 4792 { 4793 bAddMode = true; 4794 rSh.EnterAddMode(); 4795 } 4796 if ( aContentAtPos.pFndTextAttr != nullptr 4797 && aContentAtPos.pFndTextAttr->Which() == RES_TXTATR_INPUTFIELD ) 4798 { 4799 if (!rSh.IsInSelect()) 4800 { 4801 // create only temporary move context because otherwise 4802 // the query to the content form doesn't work!!! 4803 SwMvContext aMvContext( &rSh ); 4804 const Point aDocPos( PixelToLogic( m_aStartPos ) ); 4805 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false)); 4806 } 4807 else 4808 { 4809 g_bValidCursorPos = true; 4810 } 4811 } 4812 else 4813 { 4814 rSh.ClickToField( *aContentAtPos.aFnd.pField ); 4815 // a bit of a mystery what this is good for? 4816 // in this case we assume it's valid since we 4817 // just selected a field 4818 g_bValidCursorPos = true; 4819 } 4820 if (bAddMode) 4821 { 4822 rSh.LeaveAddMode(); 4823 } 4824 } 4825 else if ( IsAttrAtPos::SmartTag == aContentAtPos.eContentAtPos ) 4826 { 4827 // execute smarttag menu 4828 if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() ) 4829 m_rView.ExecSmartTagPopup( aDocPt ); 4830 } 4831 else if ( IsAttrAtPos::FormControl == aContentAtPos.eContentAtPos ) 4832 { 4833 OSL_ENSURE( aContentAtPos.aFnd.pFieldmark != nullptr, "where is my field ptr???"); 4834 if ( aContentAtPos.aFnd.pFieldmark != nullptr) 4835 { 4836 IFieldmark *fieldBM = const_cast< IFieldmark* > ( aContentAtPos.aFnd.pFieldmark ); 4837 if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX ) 4838 { 4839 ICheckboxFieldmark& rCheckboxFm = dynamic_cast<ICheckboxFieldmark&>(*fieldBM); 4840 rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked()); 4841 rCheckboxFm.Invalidate(); 4842 rSh.InvalidateWindows( m_rView.GetVisArea() ); 4843 } 4844 } 4845 } 4846 else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos ) 4847 { 4848 if (comphelper::LibreOfficeKit::isActive()) 4849 { 4850 OUString val((*static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)).GetValue()); 4851 if (val.startsWith("#")) 4852 bExecHyperlinks = true; 4853 } 4854 if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr ) 4855 rSh.ClickToINetAttr( *static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr), nFilter ); 4856 } 4857 4858 rSh.LockView( bViewLocked ); 4859 bCallShadowCursor = false; 4860 } 4861 else 4862 { 4863 aContentAtPos = SwContentAtPos( IsAttrAtPos::Ftn ); 4864 if( !rSh.GetContentAtPos( aDocPt, aContentAtPos, true ) && bExecHyperlinks ) 4865 { 4866 SdrViewEvent aVEvt; 4867 4868 if (pSdrView) 4869 pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 4870 4871 if (pSdrView && aVEvt.eEvent == SdrEventKind::ExecuteUrl) 4872 { 4873 // hit URL field 4874 const SvxURLField *pField = aVEvt.pURLField; 4875 if (pField) 4876 { 4877 const OUString& sURL(pField->GetURL()); 4878 const OUString& sTarget(pField->GetTargetFrame()); 4879 ::LoadURL(rSh, sURL, nFilter, sTarget); 4880 } 4881 bCallShadowCursor = false; 4882 } 4883 else 4884 { 4885 // hit graphic 4886 ReleaseMouse(); 4887 if( rSh.ClickToINetGrf( aDocPt, nFilter )) 4888 bCallShadowCursor = false; 4889 } 4890 } 4891 } 4892 4893 if( bCallShadowCursor && 4894 rSh.GetViewOptions()->IsShadowCursor() && 4895 MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) && 4896 !rSh.HasSelection() && 4897 !GetConnectMetaFile() && 4898 rSh.VisArea().IsInside( aDocPt )) 4899 { 4900 SwUndoId nLastUndoId(SwUndoId::EMPTY); 4901 if (rSh.GetLastUndoInfo(nullptr, & nLastUndoId)) 4902 { 4903 if (SwUndoId::INS_FROM_SHADOWCRSR == nLastUndoId) 4904 { 4905 rSh.Undo(); 4906 } 4907 } 4908 SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode(); 4909 rSh.SetShadowCursorPos( aDocPt, eMode ); 4910 } 4911 } 4912 } 4913 bCallBase = false; 4914 4915 } 4916 4917 // reset pushed mode in Down again if applicable 4918 if ( bPopMode && g_bModePushed ) 4919 { 4920 rSh.PopMode(); 4921 g_bModePushed = false; 4922 bCallBase = false; 4923 } 4924 break; 4925 4926 default: 4927 ReleaseMouse(); 4928 return; 4929 } 4930 4931 if( m_pApplyTempl ) 4932 { 4933 SelectionType eSelection = rSh.GetSelectionType(); 4934 SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard; 4935 if( pFormatClipboard )//apply format paintbrush 4936 { 4937 //get some parameters 4938 SwWrtShell& rWrtShell = m_rView.GetWrtShell(); 4939 SfxStyleSheetBasePool* pPool=nullptr; 4940 bool bNoCharacterFormats = false; 4941 bool bNoParagraphFormats = true; 4942 { 4943 SwDocShell* pDocSh = m_rView.GetDocShell(); 4944 if(pDocSh) 4945 pPool = pDocSh->GetStyleSheetPool(); 4946 if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) ) 4947 { 4948 bNoCharacterFormats = true; 4949 bNoParagraphFormats = false; 4950 } 4951 else if( rMEvt.GetModifier() & KEY_MOD1 ) 4952 bNoParagraphFormats = false; 4953 } 4954 //execute paste 4955 pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats ); 4956 4957 //if the clipboard is empty after paste remove the ApplyTemplate 4958 if(!pFormatClipboard->HasContent()) 4959 SetApplyTemplate(SwApplyTemplate()); 4960 4961 //tdf#38101 remove temporary highlighting 4962 m_pUserMarker.reset(); 4963 } 4964 else if( m_pApplyTempl->nColor ) 4965 { 4966 sal_uInt16 nId = 0; 4967 switch( m_pApplyTempl->nColor ) 4968 { 4969 case SID_ATTR_CHAR_COLOR_EXT: 4970 nId = RES_CHRATR_COLOR; 4971 break; 4972 case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT: 4973 nId = RES_CHRATR_BACKGROUND; 4974 break; 4975 } 4976 if( nId && (SelectionType::Text|SelectionType::Table) & eSelection) 4977 { 4978 if( rSh.IsSelection() && !rSh.HasReadonlySel() ) 4979 { 4980 m_pApplyTempl->nUndo = 4981 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()); 4982 if (nId == RES_CHRATR_BACKGROUND) 4983 ApplyCharBackground(m_aWaterCanTextBackColor, rSh); 4984 else 4985 rSh.SetAttrItem( SvxColorItem( m_aWaterCanTextColor, nId ) ); 4986 rSh.UnSetVisibleCursor(); 4987 rSh.EnterStdMode(); 4988 rSh.SetVisibleCursor(aDocPt); 4989 bCallBase = false; 4990 m_aTemplateTimer.Stop(); 4991 } 4992 else if(rMEvt.GetClicks() == 1) 4993 { 4994 // no selection -> so turn off watering can 4995 m_aTemplateTimer.Start(); 4996 } 4997 } 4998 } 4999 else 5000 { 5001 OUString aStyleName; 5002 switch ( m_pApplyTempl->eType ) 5003 { 5004 case SfxStyleFamily::Para: 5005 if( (( SelectionType::Text | SelectionType::Table ) 5006 & eSelection ) && !rSh.HasReadonlySel() ) 5007 { 5008 rSh.SetTextFormatColl( m_pApplyTempl->aColl.pTextColl ); 5009 m_pApplyTempl->nUndo = 5010 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()); 5011 bCallBase = false; 5012 if ( m_pApplyTempl->aColl.pTextColl ) 5013 aStyleName = m_pApplyTempl->aColl.pTextColl->GetName(); 5014 } 5015 break; 5016 case SfxStyleFamily::Char: 5017 if( (( SelectionType::Text | SelectionType::Table ) 5018 & eSelection ) && !rSh.HasReadonlySel() ) 5019 { 5020 rSh.SetAttrItem( SwFormatCharFormat(m_pApplyTempl->aColl.pCharFormat) ); 5021 rSh.UnSetVisibleCursor(); 5022 rSh.EnterStdMode(); 5023 rSh.SetVisibleCursor(aDocPt); 5024 m_pApplyTempl->nUndo = 5025 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()); 5026 bCallBase = false; 5027 if ( m_pApplyTempl->aColl.pCharFormat ) 5028 aStyleName = m_pApplyTempl->aColl.pCharFormat->GetName(); 5029 } 5030 break; 5031 case SfxStyleFamily::Frame : 5032 { 5033 const SwFrameFormat* pFormat = rSh.GetFormatFromObj( aDocPt ); 5034 if(dynamic_cast<const SwFlyFrameFormat*>( pFormat) ) 5035 { 5036 rSh.SetFrameFormat( m_pApplyTempl->aColl.pFrameFormat, false, &aDocPt ); 5037 m_pApplyTempl->nUndo = 5038 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()); 5039 bCallBase = false; 5040 if( m_pApplyTempl->aColl.pFrameFormat ) 5041 aStyleName = m_pApplyTempl->aColl.pFrameFormat->GetName(); 5042 } 5043 break; 5044 } 5045 case SfxStyleFamily::Page: 5046 // no Undo with page templates 5047 rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc ); 5048 if ( m_pApplyTempl->aColl.pPageDesc ) 5049 aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName(); 5050 m_pApplyTempl->nUndo = 5051 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()); 5052 bCallBase = false; 5053 break; 5054 case SfxStyleFamily::Pseudo: 5055 if( !rSh.HasReadonlySel() ) 5056 { 5057 rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule, 5058 false, 5059 m_pApplyTempl->aColl.pNumRule->GetDefaultListId() ); 5060 bCallBase = false; 5061 m_pApplyTempl->nUndo = 5062 std::min(m_pApplyTempl->nUndo, rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()); 5063 if( m_pApplyTempl->aColl.pNumRule ) 5064 aStyleName = m_pApplyTempl->aColl.pNumRule->GetName(); 5065 } 5066 break; 5067 default: break; 5068 } 5069 5070 uno::Reference< frame::XDispatchRecorder > xRecorder = 5071 m_rView.GetViewFrame()->GetBindings().GetRecorder(); 5072 if ( !aStyleName.isEmpty() && xRecorder.is() ) 5073 { 5074 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView ); 5075 if ( pSfxShell ) 5076 { 5077 SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY ); 5078 aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) ); 5079 aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, static_cast<sal_uInt16>(m_pApplyTempl->eType) ) ); 5080 aReq.Done(); 5081 } 5082 } 5083 } 5084 5085 } 5086 ReleaseMouse(); 5087 // Only processed MouseEvents arrive here; only at these this mode can 5088 // be reset. 5089 m_bMBPressed = false; 5090 5091 // Make this call just to be sure. Selecting has finished surely by now. 5092 // Otherwise the timeout's timer could give problems. 5093 EnterArea(); 5094 g_bNoInterrupt = false; 5095 5096 if (bCallBase) 5097 Window::MouseButtonUp(rMEvt); 5098 5099 if (!(pSdrView && rMEvt.GetClicks() == 1 && comphelper::LibreOfficeKit::isActive())) 5100 return; 5101 5102 // When tiled rendering, single click on a shape text starts editing already. 5103 SdrViewEvent aViewEvent; 5104 SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aViewEvent); 5105 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); 5106 if (eHit == SdrHitKind::TextEditObj && rMarkList.GetMarkCount() == 1) 5107 { 5108 if (SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj()) 5109 { 5110 EnterDrawTextMode(pObj->GetLogicRect().Center()); 5111 if ( auto pSwDrawTextShell = dynamic_cast< SwDrawTextShell *>( m_rView.GetCurShell() ) ) 5112 pSwDrawTextShell->Init(); 5113 } 5114 } 5115 } 5116 5117 /** 5118 * Apply template 5119 */ 5120 void SwEditWin::SetApplyTemplate(const SwApplyTemplate &rTempl) 5121 { 5122 static bool bIdle = false; 5123 m_pApplyTempl.reset(); 5124 SwWrtShell &rSh = m_rView.GetWrtShell(); 5125 5126 if(rTempl.m_pFormatClipboard) 5127 { 5128 m_pApplyTempl.reset(new SwApplyTemplate( rTempl )); 5129 m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount(); 5130 SetPointer( PointerStyle::Fill );//@todo #i20119# maybe better a new brush pointer here in future 5131 rSh.NoEdit( false ); 5132 bIdle = rSh.GetViewOptions()->IsIdle(); 5133 rSh.GetViewOptions()->SetIdle( false ); 5134 } 5135 else if(rTempl.nColor) 5136 { 5137 m_pApplyTempl.reset(new SwApplyTemplate( rTempl )); 5138 m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount(); 5139 SetPointer( PointerStyle::Fill ); 5140 rSh.NoEdit( false ); 5141 bIdle = rSh.GetViewOptions()->IsIdle(); 5142 rSh.GetViewOptions()->SetIdle( false ); 5143 } 5144 else if( rTempl.eType != SfxStyleFamily::None ) 5145 { 5146 m_pApplyTempl.reset(new SwApplyTemplate( rTempl )); 5147 m_pApplyTempl->nUndo = rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount(); 5148 SetPointer( PointerStyle::Fill ); 5149 rSh.NoEdit( false ); 5150 bIdle = rSh.GetViewOptions()->IsIdle(); 5151 rSh.GetViewOptions()->SetIdle( false ); 5152 } 5153 else 5154 { 5155 SetPointer( PointerStyle::Text ); 5156 rSh.UnSetVisibleCursor(); 5157 5158 rSh.GetViewOptions()->SetIdle( bIdle ); 5159 if ( !rSh.IsSelFrameMode() ) 5160 rSh.Edit(); 5161 } 5162 5163 static sal_uInt16 aInva[] = 5164 { 5165 SID_STYLE_WATERCAN, 5166 SID_ATTR_CHAR_COLOR_EXT, 5167 SID_ATTR_CHAR_COLOR_BACKGROUND_EXT, 5168 0 5169 }; 5170 m_rView.GetViewFrame()->GetBindings().Invalidate(aInva); 5171 } 5172 5173 /** 5174 * Ctor 5175 */ 5176 SwEditWin::SwEditWin(vcl::Window *pParent, SwView &rMyView): 5177 Window(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)), 5178 DropTargetHelper( this ), 5179 DragSourceHelper( this ), 5180 5181 m_eBufferLanguage(LANGUAGE_DONTKNOW), 5182 m_pUserMarkerObj( nullptr ), 5183 5184 m_rView( rMyView ), 5185 5186 m_aActHitType(SdrHitKind::NONE), 5187 m_nDropFormat( SotClipboardFormatId::NONE ), 5188 m_nDropAction( 0 ), 5189 m_nDropDestination( SotExchangeDest::NONE ), 5190 5191 m_eBezierMode(SID_BEZIER_INSERT), 5192 m_nInsFrameColCount( 1 ), 5193 m_eDrawMode(OBJ_NONE), 5194 5195 m_bMBPressed(false), 5196 m_bInsDraw(false), 5197 m_bInsFrame(false), 5198 m_bIsInMove(false), 5199 m_bIsInDrag(false), 5200 m_bOldIdle(false), 5201 m_bOldIdleSet(false), 5202 m_bChainMode(false), 5203 m_bWasShdwCursor(false), 5204 m_bLockInput(false), 5205 m_bIsRowDrag(false), 5206 m_bUseInputLanguage(false), 5207 m_bObjectSelect(false), 5208 m_nKS_NUMDOWN_Count(0), 5209 m_nKS_NUMINDENTINC_Count(0), 5210 m_pFrameControlsManager(new SwFrameControlsManager(this)) 5211 { 5212 set_id("writer_edit"); 5213 SetHelpId(HID_EDIT_WIN); 5214 EnableChildTransparentMode(); 5215 SetDialogControlFlags( DialogControlFlags::Return | DialogControlFlags::WantFocus ); 5216 5217 m_bMBPressed = m_bInsDraw = m_bInsFrame = 5218 m_bIsInDrag = m_bOldIdle = m_bOldIdleSet = m_bChainMode = m_bWasShdwCursor = false; 5219 // initially use the input language 5220 m_bUseInputLanguage = true; 5221 5222 SetMapMode(MapMode(MapUnit::MapTwip)); 5223 5224 SetPointer( PointerStyle::Text ); 5225 m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, TimerHandler)); 5226 5227 m_aKeyInputFlushTimer.SetTimeout( 200 ); 5228 m_aKeyInputFlushTimer.SetInvokeHandler(LINK(this, SwEditWin, KeyInputFlushHandler)); 5229 5230 // TemplatePointer for colors should be reset without 5231 // selection after single click, but not after double-click (tdf#122442) 5232 m_aTemplateTimer.SetTimeout(GetSettings().GetMouseSettings().GetDoubleClickTime()); 5233 m_aTemplateTimer.SetInvokeHandler(LINK(this, SwEditWin, TemplateTimerHdl)); 5234 5235 // temporary solution!!! Should set the font of the current 5236 // insert position at every cursor movement! 5237 if( !rMyView.GetDocShell()->IsReadOnly() ) 5238 { 5239 vcl::Font aFont; 5240 SetInputContext( InputContext( aFont, InputContextFlags::Text | 5241 InputContextFlags::ExtText ) ); 5242 } 5243 } 5244 5245 SwEditWin::~SwEditWin() 5246 { 5247 disposeOnce(); 5248 } 5249 5250 void SwEditWin::dispose() 5251 { 5252 m_pShadCursor.reset(); 5253 5254 if( m_pQuickHlpData->m_bIsDisplayed && m_rView.GetWrtShellPtr() ) 5255 m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); 5256 g_bExecuteDrag = false; 5257 m_pApplyTempl.reset(); 5258 5259 m_rView.SetDrawFuncPtr(nullptr); 5260 5261 m_pUserMarker.reset(); 5262 5263 m_pAnchorMarker.reset(); 5264 5265 m_pFrameControlsManager->dispose(); 5266 m_pFrameControlsManager.reset(); 5267 5268 DragSourceHelper::dispose(); 5269 DropTargetHelper::dispose(); 5270 vcl::Window::dispose(); 5271 } 5272 5273 /** 5274 * Turn on DrawTextEditMode 5275 */ 5276 void SwEditWin::EnterDrawTextMode( const Point& aDocPos ) 5277 { 5278 if ( m_rView.EnterDrawTextMode(aDocPos) ) 5279 { 5280 if (m_rView.GetDrawFuncPtr()) 5281 { 5282 m_rView.GetDrawFuncPtr()->Deactivate(); 5283 m_rView.SetDrawFuncPtr(nullptr); 5284 m_rView.LeaveDrawCreate(); 5285 } 5286 m_rView.NoRotate(); 5287 m_rView.AttrChangedNotify(nullptr); 5288 } 5289 } 5290 5291 /** 5292 * Turn on DrawMode 5293 */ 5294 bool SwEditWin::EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos) 5295 { 5296 SwWrtShell &rSh = m_rView.GetWrtShell(); 5297 SdrView *pSdrView = rSh.GetDrawView(); 5298 5299 if ( m_rView.GetDrawFuncPtr() ) 5300 { 5301 if (rSh.IsDrawCreate()) 5302 return true; 5303 5304 bool bRet = m_rView.GetDrawFuncPtr()->MouseButtonDown( rMEvt ); 5305 m_rView.AttrChangedNotify(nullptr); 5306 return bRet; 5307 } 5308 5309 if ( pSdrView && pSdrView->IsTextEdit() ) 5310 { 5311 bool bUnLockView = !rSh.IsViewLocked(); 5312 rSh.LockView( true ); 5313 5314 rSh.EndTextEdit(); // clicked aside, end Edit 5315 rSh.SelectObj( aDocPos ); 5316 if ( !rSh.IsObjSelected() && !rSh.IsFrameSelected() ) 5317 rSh.LeaveSelFrameMode(); 5318 else 5319 { 5320 SwEditWin::m_nDDStartPosY = aDocPos.Y(); 5321 SwEditWin::m_nDDStartPosX = aDocPos.X(); 5322 g_bFrameDrag = true; 5323 } 5324 if( bUnLockView ) 5325 rSh.LockView( false ); 5326 m_rView.AttrChangedNotify(nullptr); 5327 return true; 5328 } 5329 return false; 5330 } 5331 5332 bool SwEditWin::IsDrawSelMode() const 5333 { 5334 return IsObjectSelect(); 5335 } 5336 5337 void SwEditWin::GetFocus() 5338 { 5339 if ( m_rView.GetPostItMgr()->HasActiveSidebarWin() ) 5340 { 5341 m_rView.GetPostItMgr()->GrabFocusOnActiveSidebarWin(); 5342 } 5343 else 5344 { 5345 m_rView.GotFocus(); 5346 Window::GetFocus(); 5347 m_rView.GetWrtShell().InvalidateAccessibleFocus(); 5348 } 5349 } 5350 5351 void SwEditWin::LoseFocus() 5352 { 5353 if (m_rView.GetWrtShellPtr()) 5354 m_rView.GetWrtShell().InvalidateAccessibleFocus(); 5355 Window::LoseFocus(); 5356 if( m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed ) 5357 m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); 5358 } 5359 5360 void SwEditWin::Command( const CommandEvent& rCEvt ) 5361 { 5362 SwWrtShell &rSh = m_rView.GetWrtShell(); 5363 5364 if ( !m_rView.GetViewFrame() ) 5365 { 5366 // If ViewFrame dies shortly, no popup anymore! 5367 Window::Command(rCEvt); 5368 return; 5369 } 5370 5371 // The command event is send to the window after a possible context 5372 // menu from an inplace client has been closed. Now we have the chance 5373 // to deactivate the inplace client without any problem regarding parent 5374 // windows and code on the stack. 5375 SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient(); 5376 bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() ); 5377 if ( bIsOleActive && ( rCEvt.GetCommand() == CommandEventId::ContextMenu )) 5378 { 5379 rSh.FinishOLEObj(); 5380 return; 5381 } 5382 5383 bool bCallBase = true; 5384 5385 switch ( rCEvt.GetCommand() ) 5386 { 5387 case CommandEventId::ContextMenu: 5388 { 5389 const sal_uInt16 nId = SwInputChild::GetChildWindowId(); 5390 SwInputChild* pChildWin = static_cast<SwInputChild*>(GetView().GetViewFrame()-> 5391 GetChildWindow( nId )); 5392 5393 if (m_rView.GetPostItMgr()->IsHit(rCEvt.GetMousePosPixel())) 5394 return; 5395 5396 Point aDocPos( PixelToLogic( rCEvt.GetMousePosPixel() ) ); 5397 if ( !rCEvt.IsMouseEvent() ) 5398 aDocPos = rSh.GetCharRect().Center(); 5399 5400 // Don't trigger the command on a frame anchored to header/footer is not editing it 5401 FrameControlType eControl; 5402 bool bOverFly = false; 5403 bool bPageAnchored = false; 5404 bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored ); 5405 // !bOverHeaderFooterFly doesn't mean we have a frame to select 5406 if ( !bPageAnchored && rCEvt.IsMouseEvent( ) && 5407 ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) || 5408 ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) ) 5409 { 5410 return; 5411 } 5412 5413 if((!pChildWin || pChildWin->GetView() != &m_rView) && 5414 !rSh.IsDrawCreate() && !IsDrawAction()) 5415 { 5416 CurrShell aCurr( &rSh ); 5417 if (!m_pApplyTempl) 5418 { 5419 if (g_bNoInterrupt) 5420 { 5421 ReleaseMouse(); 5422 g_bNoInterrupt = false; 5423 m_bMBPressed = false; 5424 } 5425 if ( rCEvt.IsMouseEvent() ) 5426 { 5427 SelectMenuPosition(rSh, rCEvt.GetMousePosPixel()); 5428 m_rView.StopShellTimer(); 5429 } 5430 const Point aPixPos = LogicToPixel( aDocPos ); 5431 5432 if ( m_rView.GetDocShell()->IsReadOnly() ) 5433 { 5434 SwReadOnlyPopup aROPopup(aDocPos, m_rView); 5435 5436 ui::ContextMenuExecuteEvent aEvent; 5437 aEvent.SourceWindow = VCLUnoHelper::GetInterface( this ); 5438 aEvent.ExecutePosition.X = aPixPos.X(); 5439 aEvent.ExecutePosition.Y = aPixPos.Y(); 5440 ScopedVclPtr<Menu> pMenu; 5441 if (GetView().TryContextMenuInterception(aROPopup.GetMenu(), "private:resource/ReadonlyContextMenu", pMenu, aEvent)) 5442 { 5443 if ( pMenu ) 5444 { 5445 sal_uInt16 nExecId = static_cast<PopupMenu*>(pMenu.get())->Execute(this, aPixPos); 5446 if( !::ExecuteMenuCommand( *static_cast<PopupMenu*>(pMenu.get()), *m_rView.GetViewFrame(), nExecId )) 5447 aROPopup.Execute(this, nExecId); 5448 } 5449 else 5450 aROPopup.Execute(this, aPixPos); 5451 } 5452 } 5453 else if ( !m_rView.ExecSpellPopup( aDocPos ) ) 5454 SfxDispatcher::ExecutePopup(this, &aPixPos); 5455 } 5456 else if (m_pApplyTempl->nUndo < rSh.GetDoc()->GetIDocumentUndoRedo().GetUndoActionCount()) 5457 { 5458 // Undo until we reach the point when we entered this context. 5459 rSh.Do(SwWrtShell::UNDO); 5460 } 5461 bCallBase = false; 5462 } 5463 } 5464 break; 5465 5466 case CommandEventId::Wheel: 5467 case CommandEventId::StartAutoScroll: 5468 case CommandEventId::AutoScroll: 5469 if (m_pSavedOutlineFrame && rSh.GetViewOptions()->IsShowOutlineContentVisibilityButton()) 5470 { 5471 GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame); 5472 m_pSavedOutlineFrame = nullptr; 5473 } 5474 m_pShadCursor.reset(); 5475 bCallBase = !m_rView.HandleWheelCommands( rCEvt ); 5476 break; 5477 5478 case CommandEventId::LongPress: 5479 case CommandEventId::Swipe: //nothing yet 5480 break; 5481 5482 case CommandEventId::StartExtTextInput: 5483 { 5484 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && 5485 rSh.IsCursorReadonly(); 5486 if(!bIsDocReadOnly) 5487 { 5488 if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() ) 5489 { 5490 bCallBase = false; 5491 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt ); 5492 } 5493 else 5494 { 5495 if( rSh.HasSelection() ) 5496 rSh.DelRight(); 5497 5498 bCallBase = false; 5499 LanguageType eInputLanguage = GetInputLanguage(); 5500 rSh.CreateExtTextInput(eInputLanguage); 5501 } 5502 } 5503 break; 5504 } 5505 case CommandEventId::EndExtTextInput: 5506 { 5507 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && 5508 rSh.IsCursorReadonly(); 5509 if(!bIsDocReadOnly) 5510 { 5511 if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() ) 5512 { 5513 bCallBase = false; 5514 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt ); 5515 } 5516 else 5517 { 5518 bCallBase = false; 5519 OUString sRecord = rSh.DeleteExtTextInput(); 5520 uno::Reference< frame::XDispatchRecorder > xRecorder = 5521 m_rView.GetViewFrame()->GetBindings().GetRecorder(); 5522 5523 if ( !sRecord.isEmpty() ) 5524 { 5525 // convert quotes in IME text 5526 // works on the last input character, this is especially in Korean text often done 5527 // quotes that are inside of the string are not replaced! 5528 const sal_Unicode aCh = sRecord[sRecord.getLength() - 1]; 5529 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get(); 5530 SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect(); 5531 if(pACorr && 5532 (( pACorr->IsAutoCorrFlag( ACFlags::ChgQuotes ) && ('\"' == aCh ))|| 5533 ( pACorr->IsAutoCorrFlag( ACFlags::ChgSglQuotes ) && ( '\'' == aCh)))) 5534 { 5535 rSh.DelLeft(); 5536 rSh.AutoCorrect( *pACorr, aCh ); 5537 } 5538 5539 if ( xRecorder.is() ) 5540 { 5541 // determine Shell 5542 SfxShell *pSfxShell = lcl_GetTextShellFromDispatcher( m_rView ); 5543 // generate request and record 5544 if (pSfxShell) 5545 { 5546 SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING ); 5547 aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sRecord ) ); 5548 aReq.Done(); 5549 } 5550 } 5551 } 5552 } 5553 } 5554 } 5555 break; 5556 case CommandEventId::ExtTextInput: 5557 { 5558 bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && 5559 rSh.IsCursorReadonly(); 5560 if (!bIsDocReadOnly && !rSh.HasReadonlySel()) 5561 { 5562 if( m_pQuickHlpData->m_bIsDisplayed ) 5563 m_pQuickHlpData->Stop( rSh ); 5564 5565 if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() ) 5566 { 5567 bCallBase = false; 5568 rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt ); 5569 } 5570 else 5571 { 5572 const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); 5573 if( pData ) 5574 { 5575 bCallBase = false; 5576 rSh.SetExtTextInputData( *pData ); 5577 } 5578 } 5579 uno::Reference< frame::XDispatchRecorder > xRecorder = 5580 m_rView.GetViewFrame()->GetBindings().GetRecorder(); 5581 if(!xRecorder.is()) 5582 { 5583 SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get(); 5584 if (!rACfg.IsAutoTextTip() || !ShowAutoText(rSh.GetChunkForAutoText())) 5585 { 5586 SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect(); 5587 if (pACorr && pACorr->GetSwFlags().bAutoCompleteWords) 5588 ShowAutoCorrectQuickHelp(rSh.GetPrevAutoCorrWord(*pACorr), *pACorr); 5589 } 5590 } 5591 } 5592 5593 if (rSh.HasReadonlySel()) 5594 { 5595 // Inform the user that the request has been ignored. 5596 auto xInfo = std::make_shared<weld::GenericDialogController>( 5597 GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog"); 5598 weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {}); 5599 } 5600 } 5601 break; 5602 case CommandEventId::CursorPos: 5603 // will be handled by the base class 5604 break; 5605 5606 case CommandEventId::PasteSelection: 5607 if( !m_rView.GetDocShell()->IsReadOnly() ) 5608 { 5609 TransferableDataHelper aDataHelper( 5610 TransferableDataHelper::CreateFromSelection( this )); 5611 if( !aDataHelper.GetXTransferable().is() ) 5612 break; 5613 5614 SotExchangeDest nDropDestination = GetDropDestination( rCEvt.GetMousePosPixel() ); 5615 if( !bool(nDropDestination) ) 5616 break; 5617 SotClipboardFormatId nDropFormat; 5618 sal_uInt8 nEventAction, nDropAction; 5619 SotExchangeActionFlags nActionFlags; 5620 nDropAction = SotExchange::GetExchangeAction( 5621 aDataHelper.GetDataFlavorExVector(), 5622 nDropDestination, EXCHG_IN_ACTION_COPY, 5623 EXCHG_IN_ACTION_COPY, nDropFormat, 5624 nEventAction, 5625 SotClipboardFormatId::NONE, nullptr, 5626 &nActionFlags ); 5627 if( EXCHG_INOUT_ACTION_NONE != nDropAction ) 5628 { 5629 const Point aDocPt( PixelToLogic( rCEvt.GetMousePosPixel() ) ); 5630 SwTransferable::PasteData( aDataHelper, rSh, nDropAction, nActionFlags, 5631 nDropFormat, nDropDestination, false, 5632 false, &aDocPt, EXCHG_IN_ACTION_COPY, 5633 true ); 5634 } 5635 } 5636 break; 5637 case CommandEventId::ModKeyChange : 5638 { 5639 const CommandModKeyData* pCommandData = rCEvt.GetModKeyData(); 5640 if (!pCommandData->IsDown() && pCommandData->IsMod1() && !pCommandData->IsMod2()) 5641 { 5642 sal_uInt16 nSlot = 0; 5643 if(pCommandData->IsLeftShift() && !pCommandData->IsRightShift()) 5644 nSlot = SID_ATTR_PARA_LEFT_TO_RIGHT; 5645 else if(!pCommandData->IsLeftShift() && pCommandData->IsRightShift()) 5646 nSlot = SID_ATTR_PARA_RIGHT_TO_LEFT; 5647 if(nSlot && SW_MOD()->GetCTLOptions().IsCTLFontEnabled()) 5648 GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot); 5649 } 5650 } 5651 break; 5652 case CommandEventId::InputLanguageChange : 5653 // i#42732 - update state of fontname if input language changes 5654 g_bInputLanguageSwitched = true; 5655 SetUseInputLanguage( true ); 5656 break; 5657 case CommandEventId::SelectionChange: 5658 { 5659 const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData(); 5660 rSh.SttCursorMove(); 5661 rSh.GoStartSentence(); 5662 rSh.GetCursor()->GetPoint()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetStart()); 5663 rSh.SetMark(); 5664 rSh.GetCursor()->GetMark()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetEnd() - pData->GetStart()); 5665 rSh.EndCursorMove( true ); 5666 } 5667 break; 5668 case CommandEventId::PrepareReconversion: 5669 if( rSh.HasSelection() ) 5670 { 5671 SwPaM *pCursor = rSh.GetCursor(); 5672 5673 if( rSh.IsMultiSelection() ) 5674 { 5675 if (pCursor && !pCursor->HasMark() && 5676 pCursor->GetPoint() == pCursor->GetMark()) 5677 { 5678 rSh.GoPrevCursor(); 5679 pCursor = rSh.GetCursor(); 5680 } 5681 5682 // Cancel all selections other than the last selected one. 5683 while( rSh.GetCursor()->GetNext() != rSh.GetCursor() ) 5684 delete rSh.GetCursor()->GetNext(); 5685 } 5686 5687 if( pCursor ) 5688 { 5689 sal_uLong nPosNodeIdx = pCursor->GetPoint()->nNode.GetIndex(); 5690 const sal_Int32 nPosIdx = pCursor->GetPoint()->nContent.GetIndex(); 5691 sal_uLong nMarkNodeIdx = pCursor->GetMark()->nNode.GetIndex(); 5692 const sal_Int32 nMarkIdx = pCursor->GetMark()->nContent.GetIndex(); 5693 5694 if( !rSh.GetCursor()->HasMark() ) 5695 rSh.GetCursor()->SetMark(); 5696 5697 rSh.SttCursorMove(); 5698 5699 if( nPosNodeIdx < nMarkNodeIdx ) 5700 { 5701 rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx; 5702 rSh.GetCursor()->GetPoint()->nContent = nPosIdx; 5703 rSh.GetCursor()->GetMark()->nNode = nPosNodeIdx; 5704 rSh.GetCursor()->GetMark()->nContent = 5705 rSh.GetCursor()->GetContentNode()->Len(); 5706 } 5707 else if( nPosNodeIdx == nMarkNodeIdx ) 5708 { 5709 rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx; 5710 rSh.GetCursor()->GetPoint()->nContent = nPosIdx; 5711 rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx; 5712 rSh.GetCursor()->GetMark()->nContent = nMarkIdx; 5713 } 5714 else 5715 { 5716 rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx; 5717 rSh.GetCursor()->GetMark()->nContent = nMarkIdx; 5718 rSh.GetCursor()->GetPoint()->nNode = nMarkNodeIdx; 5719 rSh.GetCursor()->GetPoint()->nContent = 5720 rSh.GetCursor()->GetContentNode( false )->Len(); 5721 } 5722 5723 rSh.EndCursorMove( true ); 5724 } 5725 } 5726 break; 5727 case CommandEventId::QueryCharPosition: 5728 { 5729 bool bVertical = rSh.IsInVerticalText(); 5730 const SwPosition& rPos = *rSh.GetCursor()->GetPoint(); 5731 SwDocShell* pDocSh = m_rView.GetDocShell(); 5732 SwDoc *pDoc = pDocSh->GetDoc(); 5733 SwExtTextInput* pInput = pDoc->GetExtTextInput( rPos.nNode.GetNode(), rPos.nContent.GetIndex() ); 5734 if ( pInput ) 5735 { 5736 const SwPosition& rStart = *pInput->Start(); 5737 const SwPosition& rEnd = *pInput->End(); 5738 int nSize = 0; 5739 for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex ) 5740 { 5741 ++nSize; 5742 } 5743 vcl::Window& rWin = rSh.GetView().GetEditWin(); 5744 if ( nSize == 0 ) 5745 { 5746 // When the composition does not exist, use Caret rect instead. 5747 const SwRect& aCaretRect ( rSh.GetCharRect() ); 5748 tools::Rectangle aRect( aCaretRect.Left(), aCaretRect.Top(), aCaretRect.Right(), aCaretRect.Bottom() ); 5749 rWin.SetCompositionCharRect( &aRect, 1, bVertical ); 5750 } 5751 else 5752 { 5753 std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ nSize ]); 5754 int nRectIndex = 0; 5755 for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex ) 5756 { 5757 const SwPosition aPos( rStart.nNode, nIndex ); 5758 SwRect aRect ( rSh.GetCharRect() ); 5759 rSh.GetCharRectAt( aRect, &aPos ); 5760 aRects[ nRectIndex ] = tools::Rectangle( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom() ); 5761 ++nRectIndex; 5762 } 5763 rWin.SetCompositionCharRect( aRects.get(), nSize, bVertical ); 5764 } 5765 } 5766 bCallBase = false; 5767 } 5768 break; 5769 default: 5770 SAL_WARN("sw.ui", "unknown command."); 5771 break; 5772 } 5773 if (bCallBase) 5774 Window::Command(rCEvt); 5775 } 5776 5777 /* i#18686 select the object/cursor at the mouse 5778 position of the context menu request */ 5779 void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos ) 5780 { 5781 const Point aDocPos( PixelToLogic( rMousePos ) ); 5782 const bool bIsInsideSelectedObj( rSh.IsInsideSelectedObj( aDocPos ) ); 5783 //create a synthetic mouse event out of the coordinates 5784 MouseEvent aMEvt(rMousePos); 5785 SdrView *pSdrView = rSh.GetDrawView(); 5786 if ( pSdrView ) 5787 { 5788 // no close of insert_draw and reset of 5789 // draw mode, if context menu position is inside a selected object. 5790 if ( !bIsInsideSelectedObj && m_rView.GetDrawFuncPtr() ) 5791 { 5792 5793 m_rView.GetDrawFuncPtr()->Deactivate(); 5794 m_rView.SetDrawFuncPtr(nullptr); 5795 m_rView.LeaveDrawCreate(); 5796 SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); 5797 rBind.Invalidate( SID_ATTR_SIZE ); 5798 rBind.Invalidate( SID_TABLE_CELL ); 5799 } 5800 5801 // if draw text is active and there's a text selection 5802 // at the mouse position then do nothing 5803 if(rSh.GetSelectionType() & SelectionType::DrawObjectEditMode) 5804 { 5805 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView(); 5806 ESelection aSelection = pOLV->GetSelection(); 5807 if(!aSelection.IsZero()) 5808 { 5809 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner(); 5810 bool bVertical = pOutliner->IsVertical(); 5811 const EditEngine& rEditEng = pOutliner->GetEditEngine(); 5812 Point aEEPos(aDocPos); 5813 const tools::Rectangle& rOutputArea = pOLV->GetOutputArea(); 5814 // regard vertical mode 5815 if(bVertical) 5816 { 5817 aEEPos -= rOutputArea.TopRight(); 5818 //invert the horizontal direction and exchange X and Y 5819 tools::Long nTemp = -aEEPos.X(); 5820 aEEPos.setX( aEEPos.Y() ); 5821 aEEPos.setY( nTemp ); 5822 } 5823 else 5824 aEEPos -= rOutputArea.TopLeft(); 5825 5826 EPosition aDocPosition = rEditEng.FindDocPosition(aEEPos); 5827 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); 5828 // make it a forward selection - otherwise the IsLess/IsGreater do not work :-( 5829 aSelection.Adjust(); 5830 if(!(aCompare < aSelection) && !(aCompare > aSelection)) 5831 { 5832 return; 5833 } 5834 } 5835 5836 } 5837 5838 if (pSdrView->MouseButtonDown( aMEvt, this ) ) 5839 { 5840 pSdrView->MouseButtonUp( aMEvt, this ); 5841 rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); 5842 return; 5843 } 5844 } 5845 rSh.ResetCursorStack(); 5846 5847 if ( EnterDrawMode( aMEvt, aDocPos ) ) 5848 { 5849 return; 5850 } 5851 if ( m_rView.GetDrawFuncPtr() && m_bInsFrame ) 5852 { 5853 StopInsFrame(); 5854 rSh.Edit(); 5855 } 5856 5857 UpdatePointer( aDocPos ); 5858 5859 if( !rSh.IsSelFrameMode() && 5860 !GetView().GetViewFrame()->GetDispatcher()->IsLocked() ) 5861 { 5862 // Test if there is a draw object at that position and if it should be selected. 5863 bool bShould = rSh.ShouldObjectBeSelected(aDocPos); 5864 5865 if(bShould) 5866 { 5867 m_rView.NoRotate(); 5868 rSh.HideCursor(); 5869 5870 bool bUnLockView = !rSh.IsViewLocked(); 5871 rSh.LockView( true ); 5872 bool bSelObj = rSh.SelectObj( aDocPos ); 5873 if( bUnLockView ) 5874 rSh.LockView( false ); 5875 5876 if( bSelObj ) 5877 { 5878 // in case the frame was deselected in the macro 5879 // just the cursor has to be displayed again. 5880 if( FrameTypeFlags::NONE == rSh.GetSelFrameType() ) 5881 rSh.ShowCursor(); 5882 else 5883 { 5884 if (rSh.IsFrameSelected() && m_rView.GetDrawFuncPtr()) 5885 { 5886 m_rView.GetDrawFuncPtr()->Deactivate(); 5887 m_rView.SetDrawFuncPtr(nullptr); 5888 m_rView.LeaveDrawCreate(); 5889 m_rView.AttrChangedNotify(nullptr); 5890 } 5891 5892 rSh.EnterSelFrameMode( &aDocPos ); 5893 g_bFrameDrag = true; 5894 UpdatePointer( aDocPos ); 5895 return; 5896 } 5897 } 5898 5899 if (!m_rView.GetDrawFuncPtr()) 5900 rSh.ShowCursor(); 5901 } 5902 } 5903 else if ( rSh.IsSelFrameMode() && 5904 (m_aActHitType == SdrHitKind::NONE || 5905 !bIsInsideSelectedObj)) 5906 { 5907 m_rView.NoRotate(); 5908 bool bUnLockView = !rSh.IsViewLocked(); 5909 rSh.LockView( true ); 5910 5911 if ( rSh.IsSelFrameMode() ) 5912 { 5913 rSh.UnSelectFrame(); 5914 rSh.LeaveSelFrameMode(); 5915 m_rView.AttrChangedNotify(nullptr); 5916 } 5917 5918 bool bSelObj = rSh.SelectObj( aDocPos, 0/*nFlag*/ ); 5919 if( bUnLockView ) 5920 rSh.LockView( false ); 5921 5922 if( !bSelObj ) 5923 { 5924 // move cursor here so that it is not drawn in the 5925 // frame at first; ShowCursor() happens in LeaveSelFrameMode() 5926 g_bValidCursorPos = !(CRSR_POSCHG & rSh.CallSetCursor(&aDocPos, false)); 5927 rSh.LeaveSelFrameMode(); 5928 m_rView.LeaveDrawCreate(); 5929 m_rView.AttrChangedNotify(nullptr); 5930 } 5931 else 5932 { 5933 rSh.HideCursor(); 5934 rSh.EnterSelFrameMode( &aDocPos ); 5935 rSh.SelFlyGrabCursor(); 5936 rSh.MakeSelVisible(); 5937 g_bFrameDrag = true; 5938 if( rSh.IsFrameSelected() && 5939 m_rView.GetDrawFuncPtr() ) 5940 { 5941 m_rView.GetDrawFuncPtr()->Deactivate(); 5942 m_rView.SetDrawFuncPtr(nullptr); 5943 m_rView.LeaveDrawCreate(); 5944 m_rView.AttrChangedNotify(nullptr); 5945 } 5946 UpdatePointer( aDocPos ); 5947 } 5948 } 5949 else if ( rSh.IsSelFrameMode() && bIsInsideSelectedObj ) 5950 { 5951 // Object at the mouse cursor is already selected - do nothing 5952 return; 5953 } 5954 5955 if ( rSh.IsGCAttr() ) 5956 { 5957 rSh.GCAttr(); 5958 rSh.ClearGCAttr(); 5959 } 5960 5961 bool bOverSelect = rSh.TestCurrPam( aDocPos ); 5962 bool bOverURLGrf = false; 5963 if( !bOverSelect ) 5964 bOverURLGrf = bOverSelect = nullptr != rSh.IsURLGrfAtPos( aDocPos ); 5965 5966 if ( !bOverSelect ) 5967 { 5968 // create only temporary move context because otherwise 5969 // the query against the content form doesn't work!!! 5970 SwMvContext aMvContext( &rSh ); 5971 rSh.CallSetCursor(&aDocPos, false); 5972 } 5973 if( !bOverURLGrf ) 5974 { 5975 const SelectionType nSelType = rSh.GetSelectionType(); 5976 if( nSelType == SelectionType::Ole || 5977 nSelType == SelectionType::Graphic ) 5978 { 5979 SwMvContext aMvContext( &rSh ); 5980 if( !rSh.IsFrameSelected() ) 5981 rSh.GotoNextFly(); 5982 rSh.EnterSelFrameMode(); 5983 } 5984 } 5985 } 5986 5987 static SfxShell* lcl_GetTextShellFromDispatcher( SwView const & rView ) 5988 { 5989 // determine Shell 5990 SfxShell* pShell; 5991 SfxDispatcher* pDispatcher = rView.GetViewFrame()->GetDispatcher(); 5992 for(sal_uInt16 i = 0; true; ++i ) 5993 { 5994 pShell = pDispatcher->GetShell( i ); 5995 if( !pShell || dynamic_cast< const SwTextShell *>( pShell ) != nullptr ) 5996 break; 5997 } 5998 return pShell; 5999 } 6000 6001 IMPL_LINK_NOARG(SwEditWin, KeyInputFlushHandler, Timer *, void) 6002 { 6003 FlushInBuffer(); 6004 } 6005 6006 void SwEditWin::InitStaticData() 6007 { 6008 m_pQuickHlpData = new QuickHelpData(); 6009 } 6010 6011 void SwEditWin::FinitStaticData() 6012 { 6013 delete m_pQuickHlpData; 6014 } 6015 /* i#3370 - remove quick help to prevent saving 6016 * of autocorrection suggestions */ 6017 void SwEditWin::StopQuickHelp() 6018 { 6019 if( HasFocus() && m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed ) 6020 m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); 6021 } 6022 6023 IMPL_LINK_NOARG(SwEditWin, TemplateTimerHdl, Timer *, void) 6024 { 6025 SetApplyTemplate(SwApplyTemplate()); 6026 } 6027 6028 void SwEditWin::SetChainMode( bool bOn ) 6029 { 6030 if ( !m_bChainMode ) 6031 StopInsFrame(); 6032 6033 m_pUserMarker.reset(); 6034 6035 m_bChainMode = bOn; 6036 6037 static sal_uInt16 aInva[] = 6038 { 6039 FN_FRAME_CHAIN, FN_FRAME_UNCHAIN, 0 6040 }; 6041 m_rView.GetViewFrame()->GetBindings().Invalidate(aInva); 6042 } 6043 6044 uno::Reference< css::accessibility::XAccessible > SwEditWin::CreateAccessible() 6045 { 6046 SolarMutexGuard aGuard; // this should have happened already!!! 6047 SwWrtShell *pSh = m_rView.GetWrtShellPtr(); 6048 OSL_ENSURE( pSh, "no writer shell, no accessible object" ); 6049 uno::Reference< 6050 css::accessibility::XAccessible > xAcc; 6051 if( pSh ) 6052 xAcc = pSh->CreateAccessible(); 6053 6054 return xAcc; 6055 } 6056 6057 void QuickHelpData::Move( QuickHelpData& rCpy ) 6058 { 6059 m_aHelpStrings.clear(); 6060 m_aHelpStrings.swap( rCpy.m_aHelpStrings ); 6061 6062 m_bIsDisplayed = rCpy.m_bIsDisplayed; 6063 nCurArrPos = rCpy.nCurArrPos; 6064 m_bAppendSpace = rCpy.m_bAppendSpace; 6065 m_bIsTip = rCpy.m_bIsTip; 6066 m_bIsAutoText = rCpy.m_bIsAutoText; 6067 } 6068 6069 void QuickHelpData::ClearContent() 6070 { 6071 nCurArrPos = nNoPos; 6072 m_bIsDisplayed = m_bAppendSpace = false; 6073 nTipId = nullptr; 6074 m_aHelpStrings.clear(); 6075 m_bIsTip = true; 6076 m_bIsAutoText = true; 6077 } 6078 6079 void QuickHelpData::Start(SwWrtShell& rSh, const bool bRestart) 6080 { 6081 if (bRestart) 6082 { 6083 nCurArrPos = 0; 6084 } 6085 m_bIsDisplayed = true; 6086 6087 vcl::Window& rWin = rSh.GetView().GetEditWin(); 6088 if( m_bIsTip ) 6089 { 6090 Point aPt( rWin.OutputToScreenPixel( rWin.LogicToPixel( 6091 rSh.GetCharRect().Pos() ))); 6092 aPt.AdjustY( -3 ); 6093 nTipId = Help::ShowPopover(&rWin, tools::Rectangle( aPt, Size( 1, 1 )), 6094 CurStr(), 6095 QuickHelpFlags::Left | QuickHelpFlags::Bottom); 6096 } 6097 else 6098 { 6099 OUString sStr(CurStr()); 6100 sStr = sStr.copy(CurLen()); 6101 sal_uInt16 nL = sStr.getLength(); 6102 const ExtTextInputAttr nVal = ExtTextInputAttr::DottedUnderline | 6103 ExtTextInputAttr::Highlight; 6104 const std::vector<ExtTextInputAttr> aAttrs( nL, nVal ); 6105 CommandExtTextInputData aCETID( sStr, aAttrs.data(), nL, 6106 0, false ); 6107 6108 //fdo#33092. If the current input language is the default 6109 //language that text would appear in if typed, then don't 6110 //force a language on for the ExtTextInput. 6111 LanguageType eInputLanguage = rWin.GetInputLanguage(); 6112 if (lcl_isNonDefaultLanguage(eInputLanguage, 6113 rSh.GetView(), sStr) == INVALID_HINT) 6114 { 6115 eInputLanguage = LANGUAGE_DONTKNOW; 6116 } 6117 6118 rSh.CreateExtTextInput(eInputLanguage); 6119 rSh.SetExtTextInputData( aCETID ); 6120 } 6121 } 6122 6123 void QuickHelpData::Stop( SwWrtShell& rSh ) 6124 { 6125 if( !m_bIsTip ) 6126 rSh.DeleteExtTextInput( false ); 6127 else if( nTipId ) 6128 { 6129 vcl::Window& rWin = rSh.GetView().GetEditWin(); 6130 Help::HidePopover(&rWin, nTipId); 6131 } 6132 ClearContent(); 6133 } 6134 6135 void QuickHelpData::FillStrArr( SwWrtShell const & rSh, const OUString& rWord ) 6136 { 6137 enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER }; 6138 6139 // Determine word capitalization 6140 const CharClass& rCC = GetAppCharClass(); 6141 const OUString sWordLower = rCC.lowercase( rWord ); 6142 Capitalization aWordCase = CASE_OTHER; 6143 if ( !rWord.isEmpty() ) 6144 { 6145 if ( rWord[0] == sWordLower[0] ) 6146 { 6147 if ( rWord == sWordLower ) 6148 aWordCase = CASE_LOWER; 6149 } 6150 else 6151 { 6152 // First character is not lower case i.e. assume upper or title case 6153 OUString sWordSentence = sWordLower.replaceAt( 0, 1, OUString(rWord[0]) ); 6154 if ( rWord == sWordSentence ) 6155 aWordCase = CASE_SENTENCE; 6156 else 6157 { 6158 if ( rWord == rCC.uppercase( rWord ) ) 6159 aWordCase = CASE_UPPER; 6160 } 6161 } 6162 } 6163 6164 salhelper::SingletonRef<SwCalendarWrapper>* pCalendar = s_getCalendarWrapper(); 6165 (*pCalendar)->LoadDefaultCalendar( rSh.GetCurLang() ); 6166 6167 // Add matching calendar month and day names 6168 for ( const auto& aNames : { (*pCalendar)->getMonths(), (*pCalendar)->getDays() } ) 6169 { 6170 for ( const auto& rName : aNames ) 6171 { 6172 const OUString& rStr( rName.FullName ); 6173 // Check string longer than word and case insensitive match 6174 if( rStr.getLength() > rWord.getLength() && 6175 rCC.lowercase( rStr, 0, rWord.getLength() ) == sWordLower ) 6176 { 6177 OUString sStr; 6178 6179 //fdo#61251 if it's an exact match, ensure unchanged replacement 6180 //exists as a candidate 6181 if (rStr.startsWith(rWord)) 6182 m_aHelpStrings.emplace_back(rStr, rWord.getLength()); 6183 else 6184 sStr = rStr; // to be added if no case conversion is performed below 6185 6186 if ( aWordCase == CASE_LOWER ) 6187 sStr = rCC.lowercase(rStr); 6188 else if ( aWordCase == CASE_SENTENCE ) 6189 sStr = rCC.lowercase(rStr).replaceAt(0, 1, OUString(rStr[0])); 6190 else if ( aWordCase == CASE_UPPER ) 6191 sStr = rCC.uppercase(rStr); 6192 6193 if (!sStr.isEmpty()) 6194 m_aHelpStrings.emplace_back(sStr, rWord.getLength()); 6195 } 6196 } 6197 } 6198 6199 // Add matching current date in ISO 8601 format, for example 2016-01-30 6200 OUString rStrToday; 6201 6202 // do not suggest for single years, for example for "2016", 6203 // only for "201" or "2016-..." (to avoid unintentional text 6204 // insertion at line ending, for example typing "30 January 2016") 6205 if (!rWord.isEmpty() && rWord.getLength() != 4 && rWord[0] == '2') 6206 { 6207 rStrToday = utl::toISO8601(DateTime(Date(Date::SYSTEM)).GetUNODateTime()); 6208 if (rStrToday.startsWith(rWord)) 6209 m_aHelpStrings.emplace_back(rStrToday, rWord.getLength()); 6210 } 6211 6212 // Add matching words from AutoCompleteWord list 6213 const SwAutoCompleteWord& rACList = SwEditShell::GetAutoCompleteWords(); 6214 std::vector<OUString> strings; 6215 6216 if ( !rACList.GetWordsMatching( rWord, strings ) ) 6217 return; 6218 6219 for (const OUString & aCompletedString : strings) 6220 { 6221 // when we have a matching current date, avoid to suggest 6222 // other words with the same matching starting characters, 6223 // for example 2016-01-3 instead of 2016-01-30 6224 if (!rStrToday.isEmpty() && aCompletedString.startsWith(rWord)) 6225 continue; 6226 6227 OUString sStr; 6228 6229 //fdo#61251 if it's an exact match, ensure unchanged replacement 6230 //exists as a candidate 6231 if (aCompletedString.startsWith(rWord)) 6232 m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength()); 6233 else 6234 sStr = aCompletedString; // to be added if no case conversion is performed below 6235 6236 if (aWordCase == CASE_LOWER) 6237 sStr = rCC.lowercase(aCompletedString); 6238 else if (aWordCase == CASE_SENTENCE) 6239 sStr = rCC.lowercase(aCompletedString) 6240 .replaceAt(0, 1, OUString(aCompletedString[0])); 6241 else if (aWordCase == CASE_UPPER) 6242 sStr = rCC.uppercase(aCompletedString); 6243 6244 if (!sStr.isEmpty()) 6245 m_aHelpStrings.emplace_back(aCompletedString, rWord.getLength()); 6246 } 6247 } 6248 6249 namespace { 6250 6251 class CompareIgnoreCaseAsciiFavorExact 6252 { 6253 const OUString &m_rOrigWord; 6254 public: 6255 explicit CompareIgnoreCaseAsciiFavorExact(const OUString& rOrigWord) 6256 : m_rOrigWord(rOrigWord) 6257 { 6258 } 6259 6260 bool operator()(const std::pair<OUString, sal_uInt16>& s1, 6261 const std::pair<OUString, sal_uInt16>& s2) const 6262 { 6263 int nRet = s1.first.compareToIgnoreAsciiCase(s2.first); 6264 if (nRet == 0) 6265 { 6266 //fdo#61251 sort stuff that starts with the exact rOrigWord before 6267 //another ignore-case candidate 6268 int n1StartsWithOrig = s1.first.startsWith(m_rOrigWord) ? 0 : 1; 6269 int n2StartsWithOrig = s2.first.startsWith(m_rOrigWord) ? 0 : 1; 6270 return n1StartsWithOrig < n2StartsWithOrig; 6271 } 6272 return nRet < 0; 6273 } 6274 }; 6275 6276 struct EqualIgnoreCaseAscii 6277 { 6278 bool operator()(const std::pair<OUString, sal_uInt16>& s1, 6279 const std::pair<OUString, sal_uInt16>& s2) const 6280 { 6281 return s1.first.equalsIgnoreAsciiCase(s2.first); 6282 } 6283 }; 6284 6285 } // anonymous namespace 6286 6287 // TODO Implement an i18n aware sort 6288 void QuickHelpData::SortAndFilter(const OUString &rOrigWord) 6289 { 6290 std::sort( m_aHelpStrings.begin(), 6291 m_aHelpStrings.end(), 6292 CompareIgnoreCaseAsciiFavorExact(rOrigWord) ); 6293 6294 const auto& it 6295 = std::unique(m_aHelpStrings.begin(), m_aHelpStrings.end(), EqualIgnoreCaseAscii()); 6296 m_aHelpStrings.erase( it, m_aHelpStrings.end() ); 6297 6298 nCurArrPos = 0; 6299 } 6300 6301 // For a given chunk of typed text between 3 and 9 characters long that may start at a word boundary 6302 // or in a whitespace and may include whitespaces, SwEditShell::GetChunkForAutoTextcreates a list of 6303 // possible candidates for long AutoText names. Let's say, we have typed text "lorem ipsum dr f"; 6304 // and the cursor is right after the "f". SwEditShell::GetChunkForAutoText would take " dr f", 6305 // since it's the longest chunk to the left of the cursor no longer than 9 characters, not starting 6306 // in the middle of a word. Then it would create this list from it (in this order, longest first): 6307 // " dr f" 6308 // " dr f" 6309 // "dr f" 6310 // It cannot add "r f", because it starts in the middle of the word "dr"; also it cannot give " f", 6311 // because it's only 2 characters long. 6312 // Now the result of SwEditShell::GetChunkForAutoText is passed here to SwEditWin::ShowAutoText, and 6313 // then to SwGlossaryList::HasLongName, where all existing autotext entries' long names are tested 6314 // if they start with one of the list elements. The matches are sorted according the position of the 6315 // candidate that matched first, then alphabetically inside the group of suggestions for a given 6316 // candidate. Say, if we have these AutoText entry long names: 6317 // "Dr Frodo" 6318 // "Dr Credo" 6319 // "Or Bilbo" 6320 // "dr foo" 6321 // " Dr Fuzz" 6322 // " dr Faust" 6323 // the resulting list would be: 6324 // " Dr Fuzz" -> matches the first (longest) item in the candidates list 6325 // " dr Faust" -> matches the second candidate item 6326 // "Dr Foo" -> first item of the two matching the third candidate; alphabetically sorted 6327 // "Dr Frodo" -> second item of the two matching the third candidate; alphabetically sorted 6328 // Each of the resulting suggestions knows the length of the candidate it replaces, so accepting the 6329 // first suggestion would replace 6 characters before cursor, while tabbing to and accepting the 6330 // last suggestion would replace only 4 characters to the left of cursor. 6331 bool SwEditWin::ShowAutoText(const std::vector<OUString>& rChunkCandidates) 6332 { 6333 m_pQuickHlpData->ClearContent(); 6334 if (!rChunkCandidates.empty()) 6335 { 6336 SwGlossaryList* pList = ::GetGlossaryList(); 6337 pList->HasLongName(rChunkCandidates, m_pQuickHlpData->m_aHelpStrings); 6338 } 6339 6340 if (!m_pQuickHlpData->m_aHelpStrings.empty()) 6341 { 6342 m_pQuickHlpData->Start(m_rView.GetWrtShell(), true); 6343 } 6344 return !m_pQuickHlpData->m_aHelpStrings.empty(); 6345 } 6346 6347 void SwEditWin::ShowAutoCorrectQuickHelp( 6348 const OUString& rWord, SvxAutoCorrect& rACorr ) 6349 { 6350 if (rWord.isEmpty()) 6351 return; 6352 SwWrtShell& rSh = m_rView.GetWrtShell(); 6353 m_pQuickHlpData->ClearContent(); 6354 6355 if( m_pQuickHlpData->m_aHelpStrings.empty() && 6356 rACorr.GetSwFlags().bAutoCompleteWords ) 6357 { 6358 m_pQuickHlpData->m_bIsAutoText = false; 6359 m_pQuickHlpData->m_bIsTip = rACorr.GetSwFlags().bAutoCmpltShowAsTip; 6360 6361 // Get the necessary data to show help text. 6362 m_pQuickHlpData->FillStrArr( rSh, rWord ); 6363 } 6364 6365 if( !m_pQuickHlpData->m_aHelpStrings.empty() ) 6366 { 6367 m_pQuickHlpData->SortAndFilter(rWord); 6368 m_pQuickHlpData->Start(rSh, true); 6369 } 6370 } 6371 6372 bool SwEditWin::IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const 6373 { 6374 SwWrtShell &rSh = m_rView.GetWrtShell(); 6375 const SwPageFrame* pPageFrame = rSh.GetLayout()->GetPageAtPos( rDocPt ); 6376 6377 if ( pPageFrame && pPageFrame->IsOverHeaderFooterArea( rDocPt, rControl ) ) 6378 return true; 6379 6380 if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) || rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) ) 6381 { 6382 SwFrameControlsManager &rMgr = rSh.GetView().GetEditWin().GetFrameControlsManager(); 6383 Point aPoint( LogicToPixel( rDocPt ) ); 6384 6385 if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Header ) ) 6386 { 6387 SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Header, pPageFrame ); 6388 if ( pControl && pControl->Contains( aPoint ) ) 6389 { 6390 rControl = FrameControlType::Header; 6391 return true; 6392 } 6393 } 6394 6395 if ( rSh.IsShowHeaderFooterSeparator( FrameControlType::Footer ) ) 6396 { 6397 SwFrameControlPtr pControl = rMgr.GetControl( FrameControlType::Footer, pPageFrame ); 6398 if ( pControl && pControl->Contains( aPoint ) ) 6399 { 6400 rControl = FrameControlType::Footer; 6401 return true; 6402 } 6403 } 6404 } 6405 6406 return false; 6407 } 6408 6409 bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const 6410 { 6411 bool bRet = false; 6412 Point aPt( rDocPos ); 6413 SwWrtShell &rSh = m_rView.GetWrtShell(); 6414 SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() ); 6415 rSh.GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aPt, nullptr, true ); 6416 6417 const SwStartNode* pStartFly = aPam.GetPoint()->nNode.GetNode().FindFlyStartNode(); 6418 if ( pStartFly ) 6419 { 6420 bOverFly = true; 6421 SwFrameFormat* pFlyFormat = pStartFly->GetFlyFormat( ); 6422 if ( pFlyFormat ) 6423 { 6424 const SwPosition* pAnchor = pFlyFormat->GetAnchor( ).GetContentAnchor( ); 6425 if ( pAnchor ) 6426 { 6427 bool bInHeader = pAnchor->nNode.GetNode( ).FindHeaderStartNode( ) != nullptr; 6428 bool bInFooter = pAnchor->nNode.GetNode( ).FindFooterStartNode( ) != nullptr; 6429 6430 bRet = bInHeader || bInFooter; 6431 if ( bInHeader ) 6432 rControl = FrameControlType::Header; 6433 else if ( bInFooter ) 6434 rControl = FrameControlType::Footer; 6435 } 6436 else 6437 bPageAnchored = pFlyFormat->GetAnchor( ).GetAnchorId( ) == RndStdIds::FLY_AT_PAGE; 6438 } 6439 } 6440 else 6441 bOverFly = false; 6442 return bRet; 6443 } 6444 6445 void SwEditWin::SetUseInputLanguage( bool bNew ) 6446 { 6447 if ( bNew || m_bUseInputLanguage ) 6448 { 6449 SfxBindings& rBind = GetView().GetViewFrame()->GetBindings(); 6450 rBind.Invalidate( SID_ATTR_CHAR_FONT ); 6451 rBind.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); 6452 } 6453 m_bUseInputLanguage = bNew; 6454 } 6455 6456 OUString SwEditWin::GetSurroundingText() const 6457 { 6458 OUString sReturn; 6459 SwWrtShell& rSh = m_rView.GetWrtShell(); 6460 if( rSh.HasSelection() && !rSh.IsMultiSelection() && rSh.IsSelOnePara() ) 6461 rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR ); 6462 else if( !rSh.HasSelection() ) 6463 { 6464 bool bUnLockView = !rSh.IsViewLocked(); 6465 rSh.LockView(true); 6466 6467 SwPosition *pPos = rSh.GetCursor()->GetPoint(); 6468 const sal_Int32 nPos = pPos->nContent.GetIndex(); 6469 6470 // get the sentence around the cursor 6471 rSh.HideCursor(); 6472 rSh.GoStartSentence(); 6473 rSh.SetMark(); 6474 rSh.GoEndSentence(); 6475 rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR ); 6476 6477 pPos->nContent = nPos; 6478 rSh.ClearMark(); 6479 rSh.HideCursor(); 6480 6481 if (bUnLockView) 6482 rSh.LockView(false); 6483 } 6484 6485 return sReturn; 6486 } 6487 6488 Selection SwEditWin::GetSurroundingTextSelection() const 6489 { 6490 SwWrtShell& rSh = m_rView.GetWrtShell(); 6491 if( rSh.HasSelection() ) 6492 { 6493 OUString sReturn; 6494 rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR ); 6495 return Selection( 0, sReturn.getLength() ); 6496 } 6497 else 6498 { 6499 bool bUnLockView = !rSh.IsViewLocked(); 6500 rSh.LockView(true); 6501 6502 // Return the position of the visible cursor in the sentence 6503 // around the visible cursor. 6504 SwPosition *pPos = rSh.GetCursor()->GetPoint(); 6505 const sal_Int32 nPos = pPos->nContent.GetIndex(); 6506 6507 rSh.HideCursor(); 6508 rSh.GoStartSentence(); 6509 const sal_Int32 nStartPos = rSh.GetCursor()->GetPoint()->nContent.GetIndex(); 6510 6511 pPos->nContent = nPos; 6512 rSh.ClearMark(); 6513 rSh.ShowCursor(); 6514 6515 if (bUnLockView) 6516 rSh.LockView(false); 6517 6518 return Selection( nPos - nStartPos, nPos - nStartPos ); 6519 } 6520 } 6521 6522 bool SwEditWin::DeleteSurroundingText(const Selection& rSelection) 6523 { 6524 SwWrtShell& rSh = m_rView.GetWrtShell(); 6525 6526 if (rSh.HasSelection()) 6527 return false; 6528 6529 // rSelection is relative to the start of the sentence, so find that and 6530 // adjust the range by it 6531 SwPosition *pPos = rSh.GetCursor()->GetPoint(); 6532 const sal_Int32 nPos = pPos->nContent.GetIndex(); 6533 6534 rSh.HideCursor(); 6535 rSh.GoStartSentence(); 6536 const sal_Int32 nStartPos = rSh.GetCursor()->GetPoint()->nContent.GetIndex(); 6537 pPos->nContent = nPos; 6538 rSh.ClearMark(); 6539 rSh.ShowCursor(); 6540 6541 if (rSh.SelectText(nStartPos + rSelection.Min(), nStartPos + rSelection.Max())) 6542 { 6543 rSh.Delete(); 6544 return true; 6545 } 6546 6547 return false; 6548 } 6549 6550 void SwEditWin::LogicInvalidate(const tools::Rectangle* pRectangle) 6551 { 6552 OString sRectangle; 6553 if (!pRectangle) 6554 sRectangle = "EMPTY"; 6555 else 6556 sRectangle = pRectangle->toString(); 6557 6558 SfxLokHelper::notifyInvalidation(&m_rView, sRectangle); 6559 } 6560 6561 void SwEditWin::LogicMouseButtonDown(const MouseEvent& rMouseEvent) 6562 { 6563 // When we're not doing tiled rendering, then positions must be passed as pixels. 6564 assert(comphelper::LibreOfficeKit::isActive()); 6565 6566 Point aPoint = GetPointerPosPixel(); 6567 SetLastMousePos(rMouseEvent.GetPosPixel()); 6568 6569 MouseButtonDown(rMouseEvent); 6570 6571 SetPointerPosPixel(aPoint); 6572 } 6573 6574 void SwEditWin::LogicMouseButtonUp(const MouseEvent& rMouseEvent) 6575 { 6576 // When we're not doing tiled rendering, then positions must be passed as pixels. 6577 assert(comphelper::LibreOfficeKit::isActive()); 6578 6579 Point aPoint = GetPointerPosPixel(); 6580 SetLastMousePos(rMouseEvent.GetPosPixel()); 6581 6582 MouseButtonUp(rMouseEvent); 6583 6584 SetPointerPosPixel(aPoint); 6585 } 6586 6587 void SwEditWin::LogicMouseMove(const MouseEvent& rMouseEvent) 6588 { 6589 // When we're not doing tiled rendering, then positions must be passed as pixels. 6590 assert(comphelper::LibreOfficeKit::isActive()); 6591 6592 Point aPoint = GetPointerPosPixel(); 6593 SetLastMousePos(rMouseEvent.GetPosPixel()); 6594 6595 MouseMove(rMouseEvent); 6596 6597 SetPointerPosPixel(aPoint); 6598 } 6599 6600 void SwEditWin::SetCursorTwipPosition(const Point& rPosition, bool bPoint, bool bClearMark) 6601 { 6602 if (SdrView* pSdrView = m_rView.GetWrtShell().GetDrawView()) 6603 { 6604 // Editing shape text, then route the call to editeng. 6605 if (pSdrView->GetTextEditObject()) 6606 { 6607 EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); 6608 rEditView.SetCursorLogicPosition(rPosition, bPoint, bClearMark); 6609 return; 6610 } 6611 } 6612 6613 if (m_rView.GetPostItMgr()) 6614 { 6615 if (sw::annotation::SwAnnotationWin* pWin = m_rView.GetPostItMgr()->GetActiveSidebarWin()) 6616 { 6617 // Editing postit text. 6618 pWin->SetCursorLogicPosition(rPosition, bPoint, bClearMark); 6619 return; 6620 } 6621 } 6622 6623 // Not an SwWrtShell, as that would make SwCursorShell::GetCursor() inaccessible. 6624 SwEditShell& rShell = m_rView.GetWrtShell(); 6625 6626 bool bCreateSelection = false; 6627 { 6628 SwMvContext aMvContext(&rShell); 6629 if (bClearMark) 6630 rShell.ClearMark(); 6631 else 6632 bCreateSelection = !rShell.HasMark(); 6633 6634 if (bCreateSelection) 6635 m_rView.GetWrtShell().SttSelect(); 6636 6637 // If the mark is to be updated, then exchange the point and mark before 6638 // and after, as we can't easily set the mark. 6639 if (!bPoint) 6640 rShell.getShellCursor(/*bBlock=*/false)->Exchange(); 6641 rShell.SetCursor(rPosition); 6642 if (!bPoint) 6643 rShell.getShellCursor(/*bBlock=*/false)->Exchange(); 6644 } 6645 6646 if (bCreateSelection) 6647 m_rView.GetWrtShell().EndSelect(); 6648 } 6649 6650 void SwEditWin::SetGraphicTwipPosition(bool bStart, const Point& rPosition) 6651 { 6652 if (bStart) 6653 { 6654 MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT); 6655 MouseButtonDown(aClickEvent); 6656 MouseEvent aMoveEvent(Point(rPosition.getX() + MIN_MOVE + 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT); 6657 MouseMove(aMoveEvent); 6658 } 6659 else 6660 { 6661 MouseEvent aMoveEvent(Point(rPosition.getX() - MIN_MOVE - 1, rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT); 6662 MouseMove(aMoveEvent); 6663 MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT); 6664 MouseButtonUp(aClickEvent); 6665 } 6666 } 6667 6668 SwFrameControlsManager& SwEditWin::GetFrameControlsManager() 6669 { 6670 return *m_pFrameControlsManager; 6671 } 6672 6673 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 6674
