LibreOffice Module editeng (master) 1
impedit.cxx
Go to the documentation of this file.
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 "impedit.hxx"
21#include <sal/log.hxx>
22#include <editeng/editeng.hxx>
23#include <editeng/editview.hxx>
24#include <editeng/outliner.hxx>
26#include <tools/poly.hxx>
27#include <editeng/unolingu.hxx>
28#include <com/sun/star/linguistic2/XDictionary.hpp>
29#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
30#include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
31#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
32#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
33#include <comphelper/lok.hxx>
34#include <editeng/flditem.hxx>
35#include <svl/intitem.hxx>
36#include <vcl/inputctx.hxx>
37#include <vcl/transfer.hxx>
38#include <vcl/svapp.hxx>
39#include <vcl/weldutils.hxx>
40#include <vcl/window.hxx>
41#include <sot/exchange.hxx>
42#include <sot/formats.hxx>
43#include <LibreOfficeKit/LibreOfficeKitEnums.h>
44#include <comphelper/string.hxx>
45#include <sfx2/viewsh.hxx>
46#include <sfx2/lokhelper.hxx>
47#include <boost/property_tree/ptree.hpp>
48
49using namespace ::com::sun::star;
50using namespace ::com::sun::star::uno;
51using namespace ::com::sun::star::linguistic2;
52
53#define SCRLRANGE 20 // Scroll 1/20 of the width/height, when in QueryDrop
54
55static void lcl_AlignToPixel(Point& rPoint, const OutputDevice& rOutDev, short nDiffX, short nDiffY)
56{
57 rPoint = rOutDev.LogicToPixel( rPoint );
58
59 if ( nDiffX )
60 rPoint.AdjustX(nDiffX );
61 if ( nDiffY )
62 rPoint.AdjustY(nDiffY );
63
64 rPoint = rOutDev.PixelToLogic( rPoint );
65}
66
68 const tools::Rectangle& rOutputArea,
69 const Point& rVisDocStartPos) :
70 mrImpEditView(rImpEditView),
71 maOutArea(rOutputArea),
72 maVisDocStartPos(rVisDocStartPos),
73 meUnit(eUnit),
74 meFlags(LOKSpecialFlags::NONE)
75{
76}
77
78void LOKSpecialPositioning::ReInit(MapUnit eUnit, const tools::Rectangle& rOutputArea, const Point& rVisDocStartPos)
79{
80 meUnit = eUnit;
81 maOutArea = rOutputArea;
82 maVisDocStartPos = rVisDocStartPos;
83}
84
86{
87 maOutArea = rOutputArea;
88}
89
91{
92 return maOutArea;
93}
94
96{
97 maVisDocStartPos = rVisDocStartPos;
98}
99
101{
103}
104
106{
107 return mrImpEditView.IsVertical();
108}
109
111{
113}
114
115Point LOKSpecialPositioning::GetWindowPos(const Point& rDocPos, MapUnit eDocPosUnit) const
116{
117 const Point aDocPos = convertUnit(rDocPos, eDocPosUnit);
118 Point aPoint;
119 if ( !IsVertical() )
120 {
121 aPoint.setX(aDocPos.X() + maOutArea.Left() - GetVisDocLeft());
122 aPoint.setY(aDocPos.Y() + maOutArea.Top() - GetVisDocTop());
123 }
124 else
125 {
126 if (IsTopToBottom())
127 {
128 aPoint.setX(maOutArea.Right() - aDocPos.Y() + GetVisDocTop());
129 aPoint.setY(aDocPos.X() + maOutArea.Top() - GetVisDocLeft());
130 }
131 else
132 {
133 aPoint.setX(maOutArea.Left() + aDocPos.Y() - GetVisDocTop());
134 aPoint.setY(maOutArea.Bottom() - aDocPos.X() + GetVisDocLeft());
135 }
136 }
137
138 return aPoint;
139}
140
142{
143 const tools::Rectangle aDocRect = convertUnit(rDocRect, eDocRectUnit);
144 Point aPos(GetWindowPos(aDocRect.TopLeft(), meUnit));
145 Size aSz = aDocRect.GetSize();
146 tools::Rectangle aRect;
147 if (!IsVertical())
148 {
149 aRect = tools::Rectangle(aPos, aSz);
150 }
151 else
152 {
153 Point aNewPos(aPos.X() - aSz.Height(), aPos.Y());
154 // coverity[swapped_arguments : FALSE] - this is in the correct order
155 aRect = tools::Rectangle(aNewPos, Size(aSz.Height(), aSz.Width()));
156 }
157 return aRect;
158}
159
161{
162 if (ePosUnit == meUnit)
163 return rPos;
164
165 return OutputDevice::LogicToLogic(rPos, MapMode(ePosUnit), MapMode(meUnit));
166}
167
169{
170 if (eRectUnit == meUnit)
171 return rRect;
172
173 return OutputDevice::LogicToLogic(rRect, MapMode(eRectUnit), MapMode(meUnit));
174}
175
177{
178 return maOutArea.TopLeft();
179}
180
181// class ImpEditView
182
184 pEditView(pView),
185 mpViewShell(nullptr),
186 mpOtherShell(nullptr),
187 pEditEngine(pEng),
188 pOutWin(pWindow),
189 nInvMore(1),
191 nTravelXPos(TRAVEL_X_DONTKNOW),
192 nExtraCursorFlags(GetCursorFlags::NONE),
193 nCursorBidiLevel(CURSOR_BIDILEVEL_DONTKNOW),
194 nScrollDiffX(0),
195 bReadOnly(false),
196 bClickedInSelection(false),
197 bActiveDragAndDropListener(false),
198 aOutArea( Point(), pEng->GetPaperSize() ),
199 eSelectionMode(EESelectionMode::Std),
200 eAnchorMode(EEAnchorMode::TopLeft),
201 mpEditViewCallbacks(nullptr),
202 mbBroadcastLOKViewCursor(comphelper::LibreOfficeKit::isActive()),
203 mbSuppressLOKMessages(false),
204 mbNegativeX(false)
205{
208
210}
211
213{
215
216 if ( pOutWin && ( pOutWin->GetCursor() == pCursor.get() ) )
217 pOutWin->SetCursor( nullptr );
218}
219
221{
222 mxBackgroundColor = rColor;
223}
224
226{
228}
229
231{
232 mpViewShell = pViewShell;
233}
234
236{
237 mpOtherShell = pOtherShell;
238}
239
241{
242 return mpViewShell;
243}
244
245void ImpEditView::SetEditSelection( const EditSelection& rEditSelection )
246{
247 // set state before notification
248 aEditSelection = rEditSelection;
249
251
253 // Tiled rendering: selections are only painted when we are in selection mode.
255
256 if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() )
257 {
258 const EditDoc& rDoc = pEditEngine->GetEditDoc();
259 const EditPaM pmEnd = rDoc.GetEndPaM();
260 EENotifyType eNotifyType;
261 if (rDoc.Count() > 1 &&
262 pmEnd == rEditSelection.Min() &&
263 pmEnd == rEditSelection.Max())//if move cursor to the last para.
264 {
266 }
267 else
268 {
270 }
271 EENotify aNotify( eNotifyType );
272 pEditEngine->pImpEditEngine->GetNotifyHdl().Call( aNotify );
273 }
274 if(pEditEngine->pImpEditEngine->IsFormatted())
275 {
277 pEditEngine->pImpEditEngine->GetNotifyHdl().Call(aNotify);
278 }
279}
280
282static void lcl_translateTwips(const OutputDevice& rParent, OutputDevice& rChild)
283{
284 // Don't translate if we already have a non-zero origin.
285 // This prevents multiple translate calls that negate
286 // one another.
287 const Point aOrigin = rChild.GetMapMode().GetOrigin();
288 if (aOrigin.getX() != 0 || aOrigin.getY() != 0)
289 return;
290
291 // Set map mode, so that callback payloads will contain absolute coordinates instead of relative ones.
292 Point aOffset(rChild.GetOutOffXPixel() - rParent.GetOutOffXPixel(), rChild.GetOutOffYPixel() - rParent.GetOutOffYPixel());
293 if (!rChild.IsMapModeEnabled())
294 {
295 MapMode aMapMode(rChild.GetMapMode());
296 aMapMode.SetMapUnit(MapUnit::MapTwip);
297 aMapMode.SetScaleX(rParent.GetMapMode().GetScaleX());
298 aMapMode.SetScaleY(rParent.GetMapMode().GetScaleY());
299 rChild.SetMapMode(aMapMode);
300 rChild.EnableMapMode();
301 }
302 aOffset = rChild.PixelToLogic(aOffset);
303 MapMode aMapMode(rChild.GetMapMode());
304 aMapMode.SetOrigin(aOffset);
305 aMapMode.SetMapUnit(rParent.GetMapMode().GetMapUnit());
306 rChild.SetMapMode(aMapMode);
307 rChild.EnableMapMode(false);
308}
309
310// EditView never had a central/secure place to react on SelectionChange since
311// Selection was changed in many places, often by not using SetEditSelection()
312// but (mis)using GetEditSelection() and manipulating this non-const return
313// value. Sorted this out now to have such a place, this is needed for safely
314// change/update the Selection visualization for enhanced mechanisms
316{
317 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
318 {
319 // use callback to tell about change in selection visualisation
320 pCallbacks->EditViewSelectionChange();
321 }
322}
323
324// This function is also called when a text's font || size is changed. Because its highlight rectangle must be updated.
325void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible) {
326 VclPtr<vcl::Window> pParent = pOutWin->GetParentWithLOKNotifier();
327 vcl::Region aRegion( *pPolyPoly );
328
329 if (pParent && pParent->GetLOKWindowId() != 0)
330 {
331 const tools::Long nX = pOutWin->GetOutOffXPixel() - pParent->GetOutOffXPixel();
332 const tools::Long nY = pOutWin->GetOutOffYPixel() - pParent->GetOutOffYPixel();
333
334 std::vector<tools::Rectangle> aRectangles;
335 aRegion.GetRegionRectangles(aRectangles);
336
337 std::vector<OString> v;
338 for (tools::Rectangle & rRectangle : aRectangles)
339 {
340 rRectangle = pOutWin->LogicToPixel(rRectangle);
341 rRectangle.Move(nX, nY);
342 v.emplace_back(rRectangle.toString().getStr());
343 }
344 OString sRectangle = comphelper::string::join("; ", v);
345
346 const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier();
347 std::vector<vcl::LOKPayloadItem> aItems;
348 aItems.emplace_back("rectangles", sRectangle);
349 aItems.emplace_back("startHandleVisible", OString::boolean(bStartHandleVisible));
350 aItems.emplace_back("endHandleVisible", OString::boolean(bEndHandleVisible));
351 pNotifier->notifyWindow(pParent->GetLOKWindowId(), "text_selection", aItems);
352 }
353 else
354 {
355 pOutWin->GetOutDev()->Push(vcl::PushFlags::MAPMODE);
356 if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::MapTwip)
357 {
358 // Find the parent that is not right
359 // on top of us to use its offset.
360 vcl::Window* parent = pOutWin->GetParent();
361 while (parent &&
362 parent->GetOutOffXPixel() == pOutWin->GetOutOffXPixel() &&
363 parent->GetOutOffYPixel() == pOutWin->GetOutOffYPixel())
364 {
365 parent = parent->GetParent();
366 }
367
368 if (parent)
369 {
370 lcl_translateTwips(*parent->GetOutDev(), *pOutWin->GetOutDev());
371 }
372 }
373
374 bool bMm100ToTwip = !mpLOKSpecialPositioning &&
375 (pOutWin->GetMapMode().GetMapUnit() == MapUnit::Map100thMM);
376
377 Point aOrigin;
378 if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::MapTwip)
379 // Writer comments: they use editeng, but are separate widgets.
380 aOrigin = pOutWin->GetMapMode().GetOrigin();
381
382 OString sRectangle;
383 OString sRefPoint;
385 sRefPoint = mpLOKSpecialPositioning->GetRefPoint().toString();
386
387 std::vector<tools::Rectangle> aRectangles;
388 aRegion.GetRegionRectangles(aRectangles);
389
390 if (!aRectangles.empty())
391 {
392 if (pOutWin->IsChart())
393 {
394 const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj();
395 if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin))
396 {
397 Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow);
398 Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx);
399 for (tools::Rectangle& rRect : aRectangles)
400 rRect.Move(aLogicOffset.getX(), aLogicOffset.getY());
401 }
402 }
403
404 std::vector<OString> v;
405 for (tools::Rectangle & rRectangle : aRectangles)
406 {
407 if (bMm100ToTwip)
408 {
409 rRectangle = o3tl::convert(rRectangle, o3tl::Length::mm100, o3tl::Length::twip);
410 }
411 rRectangle.Move(aOrigin.getX(), aOrigin.getY());
412 v.emplace_back(rRectangle.toString().getStr());
413 }
414 sRectangle = comphelper::string::join("; ", v);
415
416 if (mpLOKSpecialPositioning && !sRectangle.isEmpty())
417 sRectangle += ":: " + sRefPoint;
418
419 tools::Rectangle& rStart = aRectangles.front();
420 tools::Rectangle aStart(rStart.Left(), rStart.Top(), rStart.Left() + 1, rStart.Bottom());
421
422 OString aPayload = aStart.toString();
424 aPayload += ":: " + sRefPoint;
425
426 mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, aPayload);
427
428 tools::Rectangle& rEnd = aRectangles.back();
429 tools::Rectangle aEnd(rEnd.Right() - 1, rEnd.Top(), rEnd.Right(), rEnd.Bottom());
430
431 aPayload = aEnd.toString();
433 aPayload += ":: " + sRefPoint;
434
435 mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, aPayload);
436 }
437
438 if (mpOtherShell)
439 {
440 // Another shell wants to know about our existing selection.
442 mpViewShell->NotifyOtherView(mpOtherShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle);
443 }
444 else
445 {
446 mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle);
447 mpViewShell->NotifyOtherViews(LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle);
448 }
449
450 pOutWin->GetOutDev()->Pop();
451 }
452}
453
454// renamed from DrawSelection to DrawSelectionXOR to better reflect what this
455// method was used for: Paint Selection in XOR, change it and again paint it in XOR.
456// This can be safely assumed due to the EditView only being capable of painting the
457// selection in XOR until today.
458// This also means that all places calling DrawSelectionXOR are thoroughly weighted
459// and chosen to make this fragile XOR-paint water-proof and thus contain some
460// information in this sense.
461// Someone thankfully expanded it to collect the SelectionRectangles when called with
462// the Region*, see GetSelectionRectangles below.
464{
466 {
467 // we are done, do *not* visualize self
468 // CAUTION: do not use when comphelper::LibreOfficeKit::isActive()
469 // due to event stuff triggered below. That *should* probably be moved
470 // to SelectionChanged() which exists now, but I do not know enough about
471 // that stuff to do it
472 return;
473 }
474
476 return;
477
478 // It must be ensured before rendering the selection, that the contents of
479 // the window is completely valid! Must be here so that in any case if
480 // empty, then later on two-Paint Events! Must be done even before the
481 // query from bUpdate, if after Invalidate paints still in the queue,
482 // but someone switches the update mode!
483
484 // pRegion: When not NULL, then only calculate Region.
485
486 OutputDevice& rTarget = pTargetDevice ? *pTargetDevice : GetOutputDevice();
487 bool bClipRegion = rTarget.IsClipRegion();
488 vcl::Region aOldRegion = rTarget.GetClipRegion();
489
490 std::optional<tools::PolyPolygon> pPolyPoly;
491
492 if ( !pRegion && !comphelper::LibreOfficeKit::isActive())
493 {
494 if ( !pEditEngine->pImpEditEngine->IsUpdateLayout() )
495 return;
496 if ( pEditEngine->pImpEditEngine->IsInUndo() )
497 return;
498
499 if ( !aTmpSel.HasRange() )
500 return;
501
502 // aTmpOutArea: if OutputArea > Paper width and
503 // Text > Paper width ( over large fields )
504 tools::Rectangle aTmpOutArea( aOutArea );
505 if ( aTmpOutArea.GetWidth() > pEditEngine->pImpEditEngine->GetPaperSize().Width() )
506 aTmpOutArea.SetRight( aTmpOutArea.Left() + pEditEngine->pImpEditEngine->GetPaperSize().Width() );
507 rTarget.IntersectClipRegion( aTmpOutArea );
508
509 if (pOutWin && pOutWin->GetCursor())
510 pOutWin->GetCursor()->Hide();
511 }
512
514 pPolyPoly = tools::PolyPolygon();
515
516 DBG_ASSERT( !pEditEngine->IsIdleFormatterActive(), "DrawSelectionXOR: Not formatted!" );
517 aTmpSel.Adjust( pEditEngine->GetEditDoc() );
518
519 ContentNode* pStartNode = aTmpSel.Min().GetNode();
520 ContentNode* pEndNode = aTmpSel.Max().GetNode();
521 const sal_Int32 nStartPara = pEditEngine->GetEditDoc().GetPos(pStartNode);
522 const sal_Int32 nEndPara = pEditEngine->GetEditDoc().GetPos(pEndNode);
523 if (nStartPara == EE_PARA_NOT_FOUND || nEndPara == EE_PARA_NOT_FOUND)
524 return;
525
526 bool bStartHandleVisible = false;
527 bool bEndHandleVisible = false;
528 bool bLOKCalcRTL = mpLOKSpecialPositioning &&
529 (mpLOKSpecialPositioning->IsLayoutRTL() || pEditEngine->IsRightToLeft(nStartPara));
530
531 auto DrawHighlight = [&, nStartLine = sal_Int32(0), nEndLine = sal_Int32(0)](
532 const ImpEditEngine::LineAreaInfo& rInfo) mutable {
533 if (!rInfo.pLine) // Begin of ParaPortion
534 {
535 if (rInfo.nPortion < nStartPara)
537 if (rInfo.nPortion > nEndPara)
539 DBG_ASSERT(!rInfo.rPortion.IsInvalid(), "Portion in Selection not formatted!");
540 if (rInfo.rPortion.IsInvalid())
542
543 if (rInfo.nPortion == nStartPara)
544 nStartLine = rInfo.rPortion.GetLines().FindLine(aTmpSel.Min().GetIndex(), false);
545 else
546 nStartLine = 0;
547
548 if (rInfo.nPortion == nEndPara)
549 nEndLine = rInfo.rPortion.GetLines().FindLine(aTmpSel.Max().GetIndex(), true);
550 else
551 nEndLine = rInfo.rPortion.GetLines().Count() - 1;
552 }
553 else // This is a correct ParaPortion
554 {
555 if (rInfo.nLine < nStartLine)
557 if (rInfo.nLine > nEndLine)
559
560 bool bPartOfLine = false;
561 sal_Int32 nStartIndex = rInfo.pLine->GetStart();
562 sal_Int32 nEndIndex = rInfo.pLine->GetEnd();
563 if ((rInfo.nPortion == nStartPara) && (rInfo.nLine == nStartLine)
564 && (nStartIndex != aTmpSel.Min().GetIndex()))
565 {
566 nStartIndex = aTmpSel.Min().GetIndex();
567 bPartOfLine = true;
568 }
569 if ((rInfo.nPortion == nEndPara) && (rInfo.nLine == nEndLine)
570 && (nEndIndex != aTmpSel.Max().GetIndex()))
571 {
572 nEndIndex = aTmpSel.Max().GetIndex();
573 bPartOfLine = true;
574 }
575
576 // Can happen if at the beginning of a wrapped line.
577 if (nEndIndex < nStartIndex)
578 nEndIndex = nStartIndex;
579
580 tools::Rectangle aTmpRect(pEditEngine->pImpEditEngine->GetEditCursor(
581 &rInfo.rPortion, rInfo.pLine, nStartIndex, GetCursorFlags::NONE));
582 const Size aLineOffset = pEditEngine->pImpEditEngine->getTopLeftDocOffset(rInfo.aArea);
583 aTmpRect.Move(0, aLineOffset.Height());
584
585 // Only paint if in the visible range ...
586 if (aTmpRect.Top() > GetVisDocBottom())
588
589 if (aTmpRect.Bottom() < GetVisDocTop())
591
592 if ((rInfo.nPortion == nStartPara) && (rInfo.nLine == nStartLine))
593 bStartHandleVisible = true;
594 if ((rInfo.nPortion == nEndPara) && (rInfo.nLine == nEndLine))
595 bEndHandleVisible = true;
596
597 // Now that we have Bidi, the first/last index doesn't have to be the 'most outside' position
598 if (!bPartOfLine)
599 {
600 Range aLineXPosStartEnd
601 = pEditEngine->GetLineXPosStartEnd(&rInfo.rPortion, rInfo.pLine);
602 aTmpRect.SetLeft(aLineXPosStartEnd.Min());
603 aTmpRect.SetRight(aLineXPosStartEnd.Max());
604 aTmpRect.Move(aLineOffset.Width(), 0);
605 ImplDrawHighlightRect(rTarget, aTmpRect.TopLeft(), aTmpRect.BottomRight(),
606 pPolyPoly ? &*pPolyPoly : nullptr, bLOKCalcRTL);
607 }
608 else
609 {
610 sal_Int32 nTmpStartIndex = nStartIndex;
611 sal_Int32 nWritingDirStart, nTmpEndIndex;
612
613 while (nTmpStartIndex < nEndIndex)
614 {
615 pEditEngine->pImpEditEngine->GetRightToLeft(rInfo.nPortion, nTmpStartIndex + 1,
616 &nWritingDirStart, &nTmpEndIndex);
617 if (nTmpEndIndex > nEndIndex)
618 nTmpEndIndex = nEndIndex;
619
620 DBG_ASSERT(nTmpEndIndex > nTmpStartIndex, "DrawSelectionXOR, Start >= End?");
621
622 tools::Long nX1
623 = pEditEngine->GetXPos(&rInfo.rPortion, rInfo.pLine, nTmpStartIndex, true);
624 tools::Long nX2
625 = pEditEngine->GetXPos(&rInfo.rPortion, rInfo.pLine, nTmpEndIndex);
626
627 aTmpRect.SetLeft(std::min(nX1, nX2));
628 aTmpRect.SetRight(std::max(nX1, nX2));
629 aTmpRect.Move(aLineOffset.Width(), 0);
630
631 ImplDrawHighlightRect(rTarget, aTmpRect.TopLeft(), aTmpRect.BottomRight(),
632 pPolyPoly ? &*pPolyPoly : nullptr, bLOKCalcRTL);
633 nTmpStartIndex = nTmpEndIndex;
634 }
635 }
636 }
638 };
639 pEditEngine->pImpEditEngine->IterateLineAreas(DrawHighlight, ImpEditEngine::IterFlag::none);
640
642 lokSelectionCallback(pPolyPoly, bStartHandleVisible, bEndHandleVisible);
643
645 {
646 if (pRegion)
647 *pRegion = vcl::Region( *pPolyPoly );
648 pPolyPoly.reset();
649 }
650 else
651 {
652 if (pOutWin && pOutWin->GetCursor())
653 pOutWin->GetCursor()->Show();
654
655 if (bClipRegion)
656 rTarget.SetClipRegion(aOldRegion);
657 else
658 rTarget.SetClipRegion();
659 }
660}
661
662void ImpEditView::GetSelectionRectangles(EditSelection aTmpSel, std::vector<tools::Rectangle>& rLogicRects)
663{
664 vcl::Region aRegion;
665 DrawSelectionXOR(aTmpSel, &aRegion);
666 aRegion.GetRegionRectangles(rLogicRects);
667}
668
669void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly, bool bLOKCalcRTL )
670{
671 if ( rDocPosTopLeft.X() == rDocPosBottomRight.X() )
672 return;
673
674 if (mpLOKSpecialPositioning && pPolyPoly)
675 {
676 MapUnit eDevUnit = rTarget.GetMapMode().GetMapUnit();
677 tools::Rectangle aSelRect(rDocPosTopLeft, rDocPosBottomRight);
678 aSelRect = GetWindowPos(aSelRect);
679 Point aRefPointLogical = GetOutputArea().TopLeft();
680 // Get the relative coordinates w.r.t refpoint in display units.
681 aSelRect.Move(-aRefPointLogical.X(), -aRefPointLogical.Y());
682 if (bLOKCalcRTL)
683 {
684 tools::Long nMirrorW = GetOutputArea().GetWidth();
685 tools::Long nLeft = aSelRect.Left(), nRight = aSelRect.Right();
686 aSelRect.SetLeft(nMirrorW - nRight);
687 aSelRect.SetRight(nMirrorW - nLeft);
688 }
689 // Convert from display unit to twips.
690 aSelRect = OutputDevice::LogicToLogic(aSelRect, MapMode(eDevUnit), MapMode(MapUnit::MapTwip));
691
692 tools::Polygon aTmpPoly(4);
693 aTmpPoly[0] = aSelRect.TopLeft();
694 aTmpPoly[1] = aSelRect.TopRight();
695 aTmpPoly[2] = aSelRect.BottomRight();
696 aTmpPoly[3] = aSelRect.BottomLeft();
697 pPolyPoly->Insert(aTmpPoly);
698 return;
699 }
700
701 bool bPixelMode = rTarget.GetMapMode().GetMapUnit() == MapUnit::MapPixel;
702
703 Point aPnt1( GetWindowPos( rDocPosTopLeft ) );
704 Point aPnt2( GetWindowPos( rDocPosBottomRight ) );
705
706 if ( !IsVertical() )
707 {
708 lcl_AlignToPixel(aPnt1, rTarget, +1, 0);
709 lcl_AlignToPixel(aPnt2, rTarget, 0, (bPixelMode ? 0 : -1));
710 }
711 else
712 {
713 lcl_AlignToPixel(aPnt1, rTarget, 0, +1 );
714 lcl_AlignToPixel(aPnt2, rTarget, (bPixelMode ? 0 : +1), 0);
715 }
716
717 tools::Rectangle aRect( aPnt1, aPnt2 );
718 if ( pPolyPoly )
719 {
720 tools::Polygon aTmpPoly( 4 );
721 aTmpPoly[0] = aRect.TopLeft();
722 aTmpPoly[1] = aRect.TopRight();
723 aTmpPoly[2] = aRect.BottomRight();
724 aTmpPoly[3] = aRect.BottomLeft();
725 pPolyPoly->Insert( aTmpPoly );
726 }
727 else
728 {
729 vcl::Window* pWindow = rTarget.GetOwnerWindow();
730
731 if (pWindow)
732 {
733 pWindow->GetOutDev()->Invert( aRect );
734 }
735 else
736 {
738 rTarget.SetLineColor();
739 rTarget.SetFillColor(COL_BLACK);
740 rTarget.SetRasterOp(RasterOp::Invert);
741 rTarget.DrawRect(aRect);
742 rTarget.Pop();
743 }
744 }
745}
746
747
749{
750 return pEditEngine->pImpEditEngine->IsEffectivelyVertical();
751}
752
754{
755 return pEditEngine->pImpEditEngine->IsTopToBottom();
756}
757
759{
761}
762
763Point ImpEditView::GetDocPos( const Point& rWindowPos ) const
764{
765 // Window Position => Position Document
766 Point aPoint;
767
768 if ( !pEditEngine->pImpEditEngine->IsEffectivelyVertical() )
769 {
770 aPoint.setX( rWindowPos.X() - aOutArea.Left() + GetVisDocLeft() );
771 aPoint.setY( rWindowPos.Y() - aOutArea.Top() + GetVisDocTop() );
772 }
773 else
774 {
775 if (pEditEngine->pImpEditEngine->IsTopToBottom())
776 {
777 aPoint.setX( rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft() );
778 aPoint.setY( aOutArea.Right() - rWindowPos.X() + GetVisDocTop() );
779 }
780 else
781 {
782 aPoint.setX( aOutArea.Bottom() - rWindowPos.Y() + GetVisDocLeft() );
783 aPoint.setY( rWindowPos.X() - aOutArea.Left() + GetVisDocTop() );
784 }
785 }
786
787 return aPoint;
788}
789
790Point ImpEditView::GetWindowPos( const Point& rDocPos ) const
791{
792 // Document position => window position
793 Point aPoint;
794
795 if ( !pEditEngine->pImpEditEngine->IsEffectivelyVertical() )
796 {
797 aPoint.setX( rDocPos.X() + aOutArea.Left() - GetVisDocLeft() );
798 aPoint.setY( rDocPos.Y() + aOutArea.Top() - GetVisDocTop() );
799 }
800 else
801 {
802 if (pEditEngine->pImpEditEngine->IsTopToBottom())
803 {
804 aPoint.setX( aOutArea.Right() - rDocPos.Y() + GetVisDocTop() );
805 aPoint.setY( rDocPos.X() + aOutArea.Top() - GetVisDocLeft() );
806 }
807 else
808 {
809 aPoint.setX( aOutArea.Left() + rDocPos.Y() - GetVisDocTop() );
810 aPoint.setY( aOutArea.Bottom() - rDocPos.X() + GetVisDocLeft() );
811 }
812 }
813
814 return aPoint;
815}
816
818{
819 // Document position => window position
820 Point aPos( GetWindowPos( rDocRect.TopLeft() ) );
821 Size aSz = rDocRect.GetSize();
822 tools::Rectangle aRect;
823 if ( !pEditEngine->pImpEditEngine->IsEffectivelyVertical() )
824 {
825 aRect = tools::Rectangle( aPos, aSz );
826 }
827 else
828 {
829 Point aNewPos( aPos.X()-aSz.Height(), aPos.Y() );
830 // coverity[swapped_arguments : FALSE] - this is in the correct order
831 aRect = tools::Rectangle( aNewPos, Size( aSz.Height(), aSz.Width() ) );
832 }
833 return aRect;
834}
835
837{
838 if ( eSelectionMode != eNewMode )
839 {
841 eSelectionMode = eNewMode;
842 DrawSelectionXOR(); // redraw
843 }
844}
845
847{
848 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
849 return pCallbacks->EditViewOutputDevice();
850 return *pOutWin->GetOutDev();
851}
852
854{
855 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
856 {
857 weld::Widget* pParent = pCallbacks->EditViewPopupParent();
858 if (pParent)
859 return pParent;
860 }
861 return weld::GetPopupParent(*pOutWin, rRect);
862}
863
865{
866 const OutputDevice& rOutDev = GetOutputDevice();
867 // should be better be aligned on pixels!
868 tools::Rectangle aNewRect(rOutDev.LogicToPixel(rRect));
869 aNewRect = rOutDev.PixelToLogic(aNewRect);
870 aOutArea = aNewRect;
875
876 SetScrollDiffX( static_cast<sal_uInt16>(aOutArea.GetWidth()) * 2 / 10 );
877}
878
879namespace {
880
881tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect)
882{
883 return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom());
884}
885
886}
887
889{
890 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
891 {
892 // do not invalidate and trigger a global repaint, but forward
893 // the need for change to the applied EditViewCallback, can e.g.
894 // be used to visualize the active edit text in an OverlayObject
895 pCallbacks->EditViewInvalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect);
896 }
897 else
898 {
899 // classic mode: invalidate and trigger full repaint
900 // of the changed area
901 GetWindow()->Invalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect);
902 }
903}
904
906{
907 // remember old out area
908 const tools::Rectangle aOldArea(aOutArea);
909
910 // apply new one
911 SetOutputArea(rRect);
912
913 // invalidate surrounding areas if update is true
914 if(aOldArea.IsEmpty() || !pEditEngine->pImpEditEngine->IsUpdateLayout())
915 return;
916
917 // #i119885# use grown area if needed; do when getting bigger OR smaller
918 const sal_Int32 nMore(DoInvalidateMore() ? GetOutputDevice().PixelToLogic(Size(nInvMore, 0)).Width() : 0);
919
920 if(aOldArea.Left() > aOutArea.Left())
921 {
922 const tools::Rectangle aRect(aOutArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Left(), aOldArea.Bottom() + nMore);
923 InvalidateAtWindow(aRect);
924 }
925 else if(aOldArea.Left() < aOutArea.Left())
926 {
927 const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOutArea.Left(), aOldArea.Bottom() + nMore);
928 InvalidateAtWindow(aRect);
929 }
930
931 if(aOldArea.Right() > aOutArea.Right())
932 {
933 const tools::Rectangle aRect(aOutArea.Right(), aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Bottom() + nMore);
934 InvalidateAtWindow(aRect);
935 }
936 else if(aOldArea.Right() < aOutArea.Right())
937 {
938 const tools::Rectangle aRect(aOldArea.Right(), aOldArea.Top() - nMore, aOutArea.Right() + nMore, aOldArea.Bottom() + nMore);
939 InvalidateAtWindow(aRect);
940 }
941
942 if(aOldArea.Top() > aOutArea.Top())
943 {
944 const tools::Rectangle aRect(aOldArea.Left() - nMore, aOutArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Top());
945 InvalidateAtWindow(aRect);
946 }
947 else if(aOldArea.Top() < aOutArea.Top())
948 {
949 const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOutArea.Top());
950 InvalidateAtWindow(aRect);
951 }
952
953 if(aOldArea.Bottom() > aOutArea.Bottom())
954 {
955 const tools::Rectangle aRect(aOldArea.Left() - nMore, aOutArea.Bottom(), aOldArea.Right() + nMore, aOldArea.Bottom() + nMore);
956 InvalidateAtWindow(aRect);
957 }
958 else if(aOldArea.Bottom() < aOutArea.Bottom())
959 {
960 const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Bottom(), aOldArea.Right() + nMore, aOutArea.Bottom() + nMore);
961 InvalidateAtWindow(aRect);
962 }
963}
964
966{
967 Point aNewTopLeft( aOutArea.TopLeft() );
968 Size aNewSz( aOutArea.GetSize() );
969
970 // X:
971 if ( DoAutoWidth() )
972 {
973 if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageWidth() )
974 aNewSz.setWidth( pEditEngine->pImpEditEngine->GetPaperSize().Width() );
975 switch ( eAnchorMode )
976 {
980 {
981 aNewTopLeft.setX( aAnchorPoint.X() );
982 }
983 break;
987 {
988 aNewTopLeft.setX( aAnchorPoint.X() - aNewSz.Width() / 2 );
989 }
990 break;
994 {
995 aNewTopLeft.setX( aAnchorPoint.X() - aNewSz.Width() - 1 );
996 }
997 break;
998 }
999 }
1000
1001 // Y:
1002 if ( DoAutoHeight() )
1003 {
1004 if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageHeight() )
1005 aNewSz.setHeight( pEditEngine->pImpEditEngine->GetPaperSize().Height() );
1006 switch ( eAnchorMode )
1007 {
1011 {
1012 aNewTopLeft.setY( aAnchorPoint.Y() );
1013 }
1014 break;
1018 {
1019 aNewTopLeft.setY( aAnchorPoint.Y() - aNewSz.Height() / 2 );
1020 }
1021 break;
1025 {
1026 aNewTopLeft.setY( aAnchorPoint.Y() - aNewSz.Height() - 1 );
1027 }
1028 break;
1029 }
1030 }
1031 ResetOutputArea( tools::Rectangle( aNewTopLeft, aNewSz ) );
1032}
1033
1035{
1038}
1039
1041{
1042 // GetHeight() and GetWidth() -1, because rectangle calculation not preferred.
1043
1044 // X:
1045 switch ( eAnchorMode )
1046 {
1050 {
1052 }
1053 break;
1057 {
1059 }
1060 break;
1064 {
1066 }
1067 break;
1068 }
1069
1070 // Y:
1071 switch ( eAnchorMode )
1072 {
1076 {
1078 }
1079 break;
1083 {
1085 }
1086 break;
1090 {
1092 }
1093 break;
1094 }
1095}
1096
1097namespace
1098{
1099
1100// For building JSON message to be sent to Online
1101boost::property_tree::ptree getHyperlinkPropTree(const OUString& sText, const OUString& sLink)
1102{
1103 boost::property_tree::ptree aTree;
1104 aTree.put("text", sText);
1105 aTree.put("link", sLink);
1106 return aTree;
1107}
1108
1109} // End of anon namespace
1110
1111tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags, sal_Int32& nTextPortionStart,
1112 const ParaPortion* pParaPortion) const
1113{
1114 tools::Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags );
1115 if ( !IsInsertMode() && !aEditSelection.HasRange() )
1116 {
1117 if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
1118 {
1119 // If we are behind a portion, and the next portion has other direction, we must change position...
1120 aEditCursor.SetLeft( pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly|GetCursorFlags::PreferPortionStart ).Left() );
1121 aEditCursor.SetRight( aEditCursor.Left() );
1122
1123 sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true );
1124 const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
1125 if ( rTextPortion.GetKind() == PortionKind::TAB )
1126 {
1127 aEditCursor.AdjustRight(rTextPortion.GetSize().Width() );
1128 }
1129 else
1130 {
1131 EditPaM aNext = pEditEngine->CursorRight( aPaM );
1132 tools::Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly );
1133 if ( aTmpRect.Top() != aEditCursor.Top() )
1135 aEditCursor.SetRight( aTmpRect.Left() );
1136 }
1137 }
1138 }
1139
1140 tools::Long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth();
1141 if ( aEditCursor.GetHeight() > nMaxHeight )
1142 {
1143 aEditCursor.SetBottom( aEditCursor.Top() + nMaxHeight - 1 );
1144 }
1145
1146 return aEditCursor;
1147}
1148
1150{
1151 EditPaM aPaM( aEditSelection.Max() );
1152
1153 sal_Int32 nTextPortionStart = 0;
1154 sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
1155 if (nPara == EE_PARA_NOT_FOUND) // #i94322
1156 return tools::Rectangle();
1157
1158 const ParaPortion* pParaPortion = pEditEngine->GetParaPortions()[nPara];
1159
1161
1162 // Use CursorBidiLevel 0/1 in meaning of
1163 // 0: prefer portion end, normal mode
1164 // 1: prefer portion start
1165
1167 {
1168 nShowCursorFlags |= GetCursorFlags::PreferPortionStart;
1169 }
1170
1171 return ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, pParaPortion);
1172}
1173
1174void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
1175{
1176 // No ShowCursor in an empty View ...
1177 if (aOutArea.IsEmpty())
1178 return;
1179 if ( ( aOutArea.Left() >= aOutArea.Right() ) && ( aOutArea.Top() >= aOutArea.Bottom() ) )
1180 return;
1181
1183 if (!pEditEngine->IsFormatted())
1184 pEditEngine->pImpEditEngine->FormatDoc();
1185
1186 // For some reasons I end up here during the formatting, if the Outliner
1187 // is initialized in Paint, because no SetPool();
1188 if ( pEditEngine->pImpEditEngine->IsFormatting() )
1189 return;
1190 if ( !pEditEngine->pImpEditEngine->IsUpdateLayout() )
1191 return;
1192 if ( pEditEngine->pImpEditEngine->IsInUndo() )
1193 return;
1194
1195 if (pOutWin && pOutWin->GetCursor() != GetCursor())
1196 pOutWin->SetCursor(GetCursor());
1197
1198 EditPaM aPaM( aEditSelection.Max() );
1199
1200 sal_Int32 nTextPortionStart = 0;
1201 sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
1202 if (nPara == EE_PARA_NOT_FOUND) // #i94322
1203 return;
1204
1205 const ParaPortion* pParaPortion = pEditEngine->GetParaPortions()[nPara];
1206
1208
1209 // Use CursorBidiLevel 0/1 in meaning of
1210 // 0: prefer portion end, normal mode
1211 // 1: prefer portion start
1212
1214 {
1215 nShowCursorFlags |= GetCursorFlags::PreferPortionStart;
1216 }
1217
1218 tools::Rectangle aEditCursor = ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, pParaPortion);
1219
1220 if ( bGotoCursor ) // && (!pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) )
1221 {
1222 // check if scrolling is necessary...
1223 // if scrolling, then update () and Scroll ()!
1224 tools::Long nDocDiffX = 0;
1225 tools::Long nDocDiffY = 0;
1226
1227 tools::Rectangle aTmpVisArea( GetVisDocArea() );
1228 // aTmpOutArea: if OutputArea > Paper width and
1229 // Text > Paper width ( over large fields )
1230 tools::Long nMaxTextWidth = !IsVertical() ? pEditEngine->pImpEditEngine->GetPaperSize().Width() : pEditEngine->pImpEditEngine->GetPaperSize().Height();
1231 if ( aTmpVisArea.GetWidth() > nMaxTextWidth )
1232 aTmpVisArea.SetRight( aTmpVisArea.Left() + nMaxTextWidth );
1233
1234 if ( aEditCursor.Bottom() > aTmpVisArea.Bottom() )
1235 { // Scroll up, here positive
1236 nDocDiffY = aEditCursor.Bottom() - aTmpVisArea.Bottom();
1237 }
1238 else if ( aEditCursor.Top() < aTmpVisArea.Top() )
1239 { // Scroll down, here negative
1240 nDocDiffY = aEditCursor.Top() - aTmpVisArea.Top();
1241 }
1242
1243 if ( aEditCursor.Right() > aTmpVisArea.Right() )
1244 {
1245 // Scroll left, positive
1246 nDocDiffX = aEditCursor.Right() - aTmpVisArea.Right();
1247 // Can it be a little more?
1248 if ( aEditCursor.Right() < ( nMaxTextWidth - GetScrollDiffX() ) )
1249 nDocDiffX += GetScrollDiffX();
1250 else
1251 {
1252 tools::Long n = nMaxTextWidth - aEditCursor.Right();
1253 // If MapMode != RefMapMode then the EditCursor can go beyond
1254 // the paper width!
1255 nDocDiffX += ( n > 0 ? n : -n );
1256 }
1257 }
1258 else if ( aEditCursor.Left() < aTmpVisArea.Left() )
1259 {
1260 // Scroll right, negative:
1261 nDocDiffX = aEditCursor.Left() - aTmpVisArea.Left();
1262 // Can it be a little more?
1263 if ( aEditCursor.Left() > ( - static_cast<tools::Long>(GetScrollDiffX()) ) )
1264 nDocDiffX -= GetScrollDiffX();
1265 else
1266 nDocDiffX -= aEditCursor.Left();
1267 }
1268 if ( aPaM.GetIndex() == 0 ) // Olli needed for the Outliner
1269 {
1270 // But make sure that the cursor is not leaving visible area
1271 // because of this!
1272 if ( aEditCursor.Left() < aTmpVisArea.GetWidth() )
1273 {
1274 nDocDiffX = -aTmpVisArea.Left();
1275 }
1276 }
1277
1278 if ( nDocDiffX | nDocDiffY )
1279 {
1280 tools::Long nDiffX = !IsVertical() ? nDocDiffX : (IsTopToBottom() ? -nDocDiffY : nDocDiffY);
1281 tools::Long nDiffY = !IsVertical() ? nDocDiffY : (IsTopToBottom() ? nDocDiffX : -nDocDiffX);
1282
1283 if ( nDiffX )
1285 if ( nDiffY )
1287 Scroll( -nDiffX, -nDiffY );
1288 pEditEngine->pImpEditEngine->DelayedCallStatusHdl();
1289 }
1290 }
1291
1292 // Cursor may trim a little ...
1293 if ( ( aEditCursor.Bottom() > GetVisDocTop() ) &&
1294 ( aEditCursor.Top() < GetVisDocBottom() ) )
1295 {
1296 if ( aEditCursor.Bottom() > GetVisDocBottom() )
1297 aEditCursor.SetBottom( GetVisDocBottom() );
1298 if ( aEditCursor.Top() < GetVisDocTop() )
1299 aEditCursor.SetTop( GetVisDocTop() );
1300 }
1301
1302 const OutputDevice& rOutDev = GetOutputDevice();
1303
1304 tools::Long nOnePixel = rOutDev.PixelToLogic( Size( 1, 0 ) ).Width();
1305
1306 if ( ( aEditCursor.Top() + nOnePixel >= GetVisDocTop() ) &&
1307 ( aEditCursor.Bottom() - nOnePixel <= GetVisDocBottom() ) &&
1308 ( aEditCursor.Left() + nOnePixel >= GetVisDocLeft() ) &&
1309 ( aEditCursor.Right() - nOnePixel <= GetVisDocRight() ) )
1310 {
1311 tools::Rectangle aCursorRect = GetWindowPos( aEditCursor );
1312 GetCursor()->SetPos( aCursorRect.TopLeft() );
1313 Size aCursorSz( aCursorRect.GetSize() );
1314 // Rectangle is inclusive
1315 aCursorSz.AdjustWidth( -1 );
1316 aCursorSz.AdjustHeight( -1 );
1317 if ( !aCursorSz.Width() || !aCursorSz.Height() )
1318 {
1319 tools::Long nCursorSz = rOutDev.GetSettings().GetStyleSettings().GetCursorSize();
1320 nCursorSz = rOutDev.PixelToLogic( Size( nCursorSz, 0 ) ).Width();
1321 if ( !aCursorSz.Width() )
1322 aCursorSz.setWidth( nCursorSz );
1323 if ( !aCursorSz.Height() )
1324 aCursorSz.setHeight( nCursorSz );
1325 }
1326 // #111036# Let VCL do orientation for cursor, otherwise problem when cursor has direction flag
1327 if ( IsVertical() )
1328 {
1329 Size aOldSz( aCursorSz );
1330 aCursorSz.setWidth( aOldSz.Height() );
1331 aCursorSz.setHeight( aOldSz.Width() );
1332 GetCursor()->SetPos( aCursorRect.TopRight() );
1333 GetCursor()->SetOrientation( Degree10(IsTopToBottom() ? 2700 : 900) );
1334 }
1335 else
1336 // #i32593# Reset correct orientation in horizontal layout
1338
1339 GetCursor()->SetSize( aCursorSz );
1340
1342 {
1343 Point aPos = GetCursor()->GetPos();
1344 boost::property_tree::ptree aMessageParams;
1346 {
1347 // Sending the absolute (pure) logical coordinates of the cursor to the client is not
1348 // enough for it to accurately reconstruct the corresponding tile-twips coordinates of the cursor.
1349 // This is because the editeng(doc) positioning is not pixel aligned for each cell involved in the output-area
1350 // (it better not be!). A simple solution is to send the coordinates of a point ('refpoint') in the output-area
1351 // along with the relative position of the cursor w.r.t this chosen 'refpoint'.
1352
1353 MapUnit eDevUnit = rOutDev.GetMapMode().GetMapUnit();
1354 tools::Rectangle aCursorRectPureLogical(aEditCursor.TopLeft(), GetCursor()->GetSize());
1355 // Get rectangle in window-coordinates from editeng(doc) coordinates in hmm.
1356 aCursorRectPureLogical = GetWindowPos(aCursorRectPureLogical);
1357 Point aRefPointLogical = GetOutputArea().TopLeft();
1358 // Get the relative coordinates w.r.t refpoint in display hmm.
1359 aCursorRectPureLogical.Move(-aRefPointLogical.X(), -aRefPointLogical.Y());
1360 if (pEditEngine->IsRightToLeft(nPara) || mpLOKSpecialPositioning->IsLayoutRTL())
1361 {
1362 tools::Long nMirrorW = GetOutputArea().GetWidth();
1363 tools::Long nLeft = aCursorRectPureLogical.Left(), nRight = aCursorRectPureLogical.Right();
1364 aCursorRectPureLogical.SetLeft(nMirrorW - nRight);
1365 aCursorRectPureLogical.SetRight(nMirrorW - nLeft);
1366 }
1367 // Convert to twips.
1368 aCursorRectPureLogical = OutputDevice::LogicToLogic(aCursorRectPureLogical, MapMode(eDevUnit), MapMode(MapUnit::MapTwip));
1369 // "refpoint" in print twips.
1370 const Point aRefPoint = mpLOKSpecialPositioning->GetRefPoint();
1371 aMessageParams.put("relrect", aCursorRectPureLogical.toString());
1372 aMessageParams.put("refpoint", aRefPoint.toString());
1373 }
1374
1375 if (pOutWin && pOutWin->IsChart())
1376 {
1377 const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj();
1378 if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin))
1379 {
1380 Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow);
1381 Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx);
1382 aPos.Move(aLogicOffset.getX(), aLogicOffset.getY());
1383 }
1384 }
1385
1386 tools::Rectangle aRect(aPos.getX(), aPos.getY(), aPos.getX() + GetCursor()->GetWidth(), aPos.getY() + GetCursor()->GetHeight());
1387
1388 // LOK output is always in twips, convert from mm100 if necessary.
1389 if (rOutDev.GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
1390 {
1392 }
1393 else if (rOutDev.GetMapMode().GetMapUnit() == MapUnit::MapTwip)
1394 {
1395 // Writer comments: they use editeng, but are separate widgets.
1396 Point aOrigin = rOutDev.GetMapMode().GetOrigin();
1397 // Move the rectangle, so that we output absolute twips.
1398 aRect.Move(aOrigin.getX(), aOrigin.getY());
1399 }
1400 // Let the LOK client decide the cursor width.
1401 aRect.setWidth(0);
1402
1403 OString sRect = aRect.toString();
1404 aMessageParams.put("rectangle", sRect);
1405
1406 SfxViewShell* pThisShell = dynamic_cast<SfxViewShell*>(mpViewShell);
1407 SfxViewShell* pOtherShell = dynamic_cast<SfxViewShell*>(mpOtherShell);
1408 assert(pThisShell);
1409
1410 if (pOtherShell && pThisShell != pOtherShell)
1411 {
1412 // Another shell wants to know about our existing cursor.
1413 SfxLokHelper::notifyOtherView(pThisShell, pOtherShell,
1414 LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, aMessageParams);
1415 }
1416 else
1417 {
1418 // is cursor at a misspelled word ?
1419 Reference< linguistic2::XSpellChecker1 > xSpeller( pEditEngine->pImpEditEngine->GetSpeller() );
1420 bool bIsWrong = xSpeller.is() && IsWrongSpelledWord(aPaM, /*bMarkIfWrong*/ false);
1421 EditView* pActiveView = GetEditViewPtr();
1422
1423 boost::property_tree::ptree aHyperlinkTree;
1424 if (pActiveView && URLFieldHelper::IsCursorAtURLField(*pActiveView))
1425 {
1426 if (const SvxFieldItem* pFld = GetField(aPos, nullptr, nullptr))
1427 if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField()))
1428 aHyperlinkTree = getHyperlinkPropTree(pUrlField->GetRepresentation(), pUrlField->GetURL());
1429 }
1430 else if (GetEditSelection().HasRange())
1431 {
1432 if (pActiveView)
1433 {
1434 const SvxFieldItem* pFieldItem = pActiveView->GetFieldAtSelection();
1435 if (pFieldItem)
1436 {
1437 const SvxFieldData* pField = pFieldItem->GetField();
1438 if ( auto pUrlField = dynamic_cast<const SvxURLField*>( pField) )
1439 {
1440 aHyperlinkTree = getHyperlinkPropTree(pUrlField->GetRepresentation(), pUrlField->GetURL());
1441 }
1442 }
1443 }
1444 }
1445
1448 LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, aMessageParams);
1449
1450 aMessageParams.put("mispelledWord", bIsWrong ? 1 : 0);
1451 aMessageParams.add_child("hyperlink", aHyperlinkTree);
1452
1454 SfxLokHelper::notifyOtherView(pThisShell, pThisShell,
1455 LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, aMessageParams);
1456 else
1457 pThisShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR,
1458 OString(aMessageParams.get<std::string>("rectangle")));
1459 }
1460 }
1461
1462 CursorDirection nCursorDir = CursorDirection::NONE;
1463 if ( IsInsertMode() && !aEditSelection.HasRange() && ( pEditEngine->pImpEditEngine->HasDifferentRTLLevels( aPaM.GetNode() ) ) )
1464 {
1465 sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, bool(nShowCursorFlags & GetCursorFlags::PreferPortionStart) );
1466 const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
1467 if (rTextPortion.IsRightToLeft())
1468 nCursorDir = CursorDirection::RTL;
1469 else
1470 nCursorDir = CursorDirection::LTR;
1471
1472 }
1473 GetCursor()->SetDirection( nCursorDir );
1474
1475 if ( bForceVisCursor )
1476 GetCursor()->Show();
1477 {
1478 SvxFont aFont;
1479 pEditEngine->SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont );
1480
1481 InputContext aInputContext(std::move(aFont), InputContextFlags::Text | InputContextFlags::ExtText);
1482 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
1483 pCallbacks->EditViewInputContext(aInputContext);
1484 else if (auto xWindow = GetWindow())
1485 xWindow->SetInputContext(aInputContext);
1486 }
1487 }
1488 else
1489 {
1490 pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() = pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() | EditStatusFlags::CURSOROUT;
1491 GetCursor()->Hide();
1492 GetCursor()->SetPos( Point( -1, -1 ) );
1493 GetCursor()->SetSize( Size( 0, 0 ) );
1494 }
1495}
1496
1497// call this so users of EditViewCallbacks can update their scrollbar state
1498// so called when we have either scrolled to a new location
1499// or the size of document has changed
1501{
1502 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
1503 pCallbacks->EditViewScrollStateChange();
1504}
1505
1507{
1508 DBG_ASSERT( pEditEngine->pImpEditEngine->IsFormatted(), "Scroll: Not formatted!" );
1509 if ( !ndX && !ndY )
1510 return Pair( 0, 0 );
1511
1512 const OutputDevice& rOutDev = GetOutputDevice();
1513
1514#ifdef DBG_UTIL
1516 aR = rOutDev.LogicToPixel( aR );
1517 aR = rOutDev.PixelToLogic( aR );
1518 SAL_WARN_IF( aR != aOutArea, "editeng", "OutArea before Scroll not aligned" );
1519#endif
1520
1521 tools::Rectangle aNewVisArea( GetVisDocArea() );
1522
1523 // Vertical:
1524 if ( !IsVertical() )
1525 {
1526 aNewVisArea.AdjustTop( -ndY );
1527 aNewVisArea.AdjustBottom( -ndY );
1528 }
1529 else
1530 {
1531 if( IsTopToBottom() )
1532 {
1533 aNewVisArea.AdjustTop(ndX );
1534 aNewVisArea.AdjustBottom(ndX );
1535 }
1536 else
1537 {
1538 aNewVisArea.AdjustTop( -ndX );
1539 aNewVisArea.AdjustBottom( -ndX );
1540 }
1541 }
1542 if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Bottom() > static_cast<tools::Long>(pEditEngine->pImpEditEngine->GetTextHeight()) ) )
1543 {
1544 // GetTextHeight still optimizing!
1545 tools::Long nDiff = pEditEngine->pImpEditEngine->GetTextHeight() - aNewVisArea.Bottom(); // negative
1546 aNewVisArea.Move( 0, nDiff ); // could end up in the negative area...
1547 }
1548 if ( aNewVisArea.Top() < 0 )
1549 aNewVisArea.Move( 0, -aNewVisArea.Top() );
1550
1551 // Horizontal:
1552 if ( !IsVertical() )
1553 {
1554 aNewVisArea.AdjustLeft( -ndX );
1555 aNewVisArea.AdjustRight( -ndX );
1556 }
1557 else
1558 {
1559 if (IsTopToBottom())
1560 {
1561 aNewVisArea.AdjustLeft( -ndY );
1562 aNewVisArea.AdjustRight( -ndY );
1563 }
1564 else
1565 {
1566 aNewVisArea.AdjustLeft(ndY );
1567 aNewVisArea.AdjustRight(ndY );
1568 }
1569 }
1570 if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Right() > static_cast<tools::Long>(pEditEngine->pImpEditEngine->CalcTextWidth( false )) ) )
1571 {
1572 tools::Long nDiff = pEditEngine->pImpEditEngine->CalcTextWidth( false ) - aNewVisArea.Right(); // negative
1573 aNewVisArea.Move( nDiff, 0 ); // could end up in the negative area...
1574 }
1575 if ( aNewVisArea.Left() < 0 )
1576 aNewVisArea.Move( -aNewVisArea.Left(), 0 );
1577
1578 // The difference must be alignt on pixel (due to scroll!)
1579 tools::Long nDiffX = !IsVertical() ? ( GetVisDocLeft() - aNewVisArea.Left() ) : (IsTopToBottom() ? -( GetVisDocTop() - aNewVisArea.Top() ) : (GetVisDocTop() - aNewVisArea.Top()));
1580 tools::Long nDiffY = !IsVertical() ? ( GetVisDocTop() - aNewVisArea.Top() ) : (IsTopToBottom() ? (GetVisDocLeft() - aNewVisArea.Left()) : -(GetVisDocTop() - aNewVisArea.Top()));
1581
1582 Size aDiffs( nDiffX, nDiffY );
1583 aDiffs = rOutDev.LogicToPixel( aDiffs );
1584 aDiffs = rOutDev.PixelToLogic( aDiffs );
1585
1586 tools::Long nRealDiffX = aDiffs.Width();
1587 tools::Long nRealDiffY = aDiffs.Height();
1588
1589
1590 if ( nRealDiffX || nRealDiffY )
1591 {
1592 vcl::Cursor* pCrsr = GetCursor();
1593 bool bVisCursor = pCrsr->IsVisible();
1594 pCrsr->Hide();
1595 if (pOutWin)
1596 pOutWin->PaintImmediately();
1597 if ( !IsVertical() )
1598 aVisDocStartPos.Move( -nRealDiffX, -nRealDiffY );
1599 else
1600 {
1601 if (IsTopToBottom())
1602 aVisDocStartPos.Move(-nRealDiffY, nRealDiffX);
1603 else
1604 aVisDocStartPos.Move(nRealDiffY, -nRealDiffX);
1605 }
1606 // Move by aligned value does not necessarily result in aligned
1607 // rectangle ...
1610 tools::Rectangle aRect( aOutArea );
1611
1612 if (pOutWin)
1613 {
1614 pOutWin->Scroll( nRealDiffX, nRealDiffY, aRect, ScrollFlags::Clip );
1615 }
1616
1618 {
1619 // Need to invalidate the window, otherwise no tile will be re-painted.
1621 }
1622
1623 if (pOutWin)
1624 pOutWin->PaintImmediately();
1625 pCrsr->SetPos( pCrsr->GetPos() + Point( nRealDiffX, nRealDiffY ) );
1626 if ( bVisCursor )
1627 {
1628 tools::Rectangle aCursorRect( pCrsr->GetPos(), pCrsr->GetSize() );
1629 if ( aOutArea.Contains( aCursorRect ) )
1630 pCrsr->Show();
1631 }
1632
1633 if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() )
1634 {
1636 pEditEngine->pImpEditEngine->GetNotifyHdl().Call( aNotify );
1637 }
1638
1639 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
1640 pCallbacks->EditViewScrollStateChange();
1641
1643 {
1645 }
1646 }
1647
1648 return Pair( nRealDiffX, nRealDiffY );
1649}
1650
1651Reference<css::datatransfer::clipboard::XClipboard> ImpEditView::GetClipboard() const
1652{
1653 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
1654 return pCallbacks->GetClipboard();
1655 if (vcl::Window* pWindow = GetWindow())
1656 return pWindow->GetClipboard();
1657 SAL_WARN("editeng", "falling back to using GetSystemClipboard");
1658 return GetSystemClipboard();
1659}
1660
1661bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * pFrameWin )
1662{
1663 bool bDone = false;
1664
1665 KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
1666 if ( eFunc != KeyFuncType::DONTKNOW )
1667 {
1668 switch ( eFunc )
1669 {
1670 case KeyFuncType::CUT:
1671 {
1672 if ( !bReadOnly )
1673 {
1674 Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard());
1675 CutCopy( aClipBoard, true );
1676 bDone = true;
1677 }
1678 }
1679 break;
1680 case KeyFuncType::COPY:
1681 {
1682 Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard());
1683 CutCopy( aClipBoard, false );
1684 bDone = true;
1685 }
1686 break;
1687 case KeyFuncType::PASTE:
1688 {
1689 if ( !bReadOnly && IsPasteEnabled() )
1690 {
1691 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE );
1692 Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard());
1693 Paste( aClipBoard, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
1694 pEditEngine->pImpEditEngine->UndoActionEnd();
1695 bDone = true;
1696 }
1697 }
1698 break;
1699 default:
1700 break;
1701 }
1702 }
1703
1704 if( !bDone )
1705 bDone = pEditEngine->PostKeyEvent( rKeyEvent, GetEditViewPtr(), pFrameWin );
1706
1707 return bDone;
1708}
1709
1710bool ImpEditView::MouseButtonUp( const MouseEvent& rMouseEvent )
1711{
1715 bClickedInSelection = false;
1716
1717 if ( rMouseEvent.IsMiddle() && !bReadOnly &&
1718 Application::GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection )
1719 {
1720 Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection());
1721 Paste( aClipBoard );
1722 }
1723 else if ( rMouseEvent.IsLeft() && GetEditSelection().HasRange() )
1724 {
1725 Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection());
1726 CutCopy( aClipBoard, false );
1727 }
1728
1729 return pEditEngine->pImpEditEngine->MouseButtonUp( rMouseEvent, GetEditViewPtr() );
1730}
1731
1733{
1734 pEditEngine->pImpEditEngine->ReleaseMouse();
1735}
1736
1738{
1739 pEditEngine->CheckIdleFormatter(); // If fast typing and mouse button downs
1743 bool bPrevUpdateLayout = pEditEngine->pImpEditEngine->SetUpdateLayout(true);
1745 bool bRet = pEditEngine->pImpEditEngine->MouseButtonDown( rMouseEvent, GetEditViewPtr() );
1746 pEditEngine->pImpEditEngine->SetUpdateLayout(bPrevUpdateLayout);
1747 return bRet;
1748}
1749
1750bool ImpEditView::MouseMove( const MouseEvent& rMouseEvent )
1751{
1752 return pEditEngine->pImpEditEngine->MouseMove( rMouseEvent, GetEditViewPtr() );
1753}
1754
1756{
1757 pEditEngine->CheckIdleFormatter(); // If fast typing and mouse button down
1758 return pEditEngine->pImpEditEngine->Command(rCEvt, GetEditViewPtr());
1759}
1760
1761
1762void ImpEditView::SetInsertMode( bool bInsert )
1763{
1764 if ( bInsert != IsInsertMode() )
1765 {
1767 ShowCursor( DoAutoScroll(), false );
1768 }
1769}
1770
1771bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, bool bMarkIfWrong )
1772{
1773 bool bIsWrong = false;
1774 if ( rPaM.GetNode()->GetWrongList() )
1775 {
1776 EditSelection aSel = pEditEngine->SelectWord( rPaM, css::i18n::WordType::DICTIONARY_WORD );
1777 bIsWrong = rPaM.GetNode()->GetWrongList()->HasWrong( aSel.Min().GetIndex(), aSel.Max().GetIndex() );
1778 if ( bIsWrong && bMarkIfWrong )
1779 {
1781 SetEditSelection( aSel );
1783 }
1784 }
1785 return bIsWrong;
1786}
1787
1789{
1790 OUString aWord;
1791 if ( pEditEngine->pImpEditEngine->GetSpeller().is() )
1792 {
1793 EditPaM aPaM = GetEditSelection().Max();
1794 if ( !HasSelection() )
1795 {
1796 EditSelection aSel = pEditEngine->SelectWord(aPaM);
1797 aWord = pEditEngine->pImpEditEngine->GetSelected( aSel );
1798 }
1799 else
1800 {
1801 aWord = pEditEngine->pImpEditEngine->GetSelected( GetEditSelection() );
1802 // And deselect
1804 SetEditSelection( EditSelection( aPaM, aPaM ) );
1806 }
1807
1808 if ( !aWord.isEmpty() )
1809 {
1810 Reference< XDictionary > xDic = LinguMgr::GetIgnoreAllList();
1811 if (xDic.is())
1812 xDic->add( aWord, false, OUString() );
1813 EditDoc& rDoc = pEditEngine->GetEditDoc();
1814 sal_Int32 nNodes = rDoc.Count();
1815 for ( sal_Int32 n = 0; n < nNodes; n++ )
1816 {
1817 ContentNode* pNode = rDoc.GetObject( n );
1818 pNode->GetWrongList()->MarkWrongsInvalid();
1819 }
1820 pEditEngine->pImpEditEngine->DoOnlineSpelling( aPaM.GetNode() );
1821 pEditEngine->pImpEditEngine->StartOnlineSpellTimer();
1822 }
1823 }
1824 return aWord;
1825}
1826
1828{
1830
1831 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DELETE );
1832
1833 EditPaM aPaM = pEditEngine->pImpEditEngine->DeleteSelected( GetEditSelection() );
1834
1835 pEditEngine->pImpEditEngine->UndoActionEnd();
1836
1837 SetEditSelection( EditSelection( aPaM, aPaM ) );
1838
1840
1841 pEditEngine->pImpEditEngine->FormatAndLayout( GetEditViewPtr() );
1842 ShowCursor( DoAutoScroll(), true );
1843}
1844
1845const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_Int32* pPara, sal_Int32* pPos ) const
1846{
1847 if( !GetOutputArea().Contains( rPos ) )
1848 return nullptr;
1849
1850 Point aDocPos( GetDocPos( rPos ) );
1851 EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false);
1852 if (!aPaM)
1853 return nullptr;
1854
1855 if ( aPaM.GetIndex() == aPaM.GetNode()->Len() )
1856 {
1857 // Otherwise, whenever the Field at the very end and mouse under the text
1858 return nullptr;
1859 }
1860
1862 const sal_Int32 nXPos = aPaM.GetIndex();
1863 for (size_t nAttr = rAttrs.size(); nAttr; )
1864 {
1865 const EditCharAttrib& rAttr = *rAttrs[--nAttr];
1866 if (rAttr.GetStart() == nXPos || rAttr.GetEnd() == nXPos)
1867 {
1868 if (rAttr.Which() == EE_FEATURE_FIELD)
1869 {
1870 DBG_ASSERT(dynamic_cast<const SvxFieldItem*>(rAttr.GetItem()), "No FieldItem...");
1871 if ( pPara )
1872 *pPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
1873 if ( pPos )
1874 *pPos = rAttr.GetStart();
1875 return static_cast<const SvxFieldItem*>(rAttr.GetItem());
1876 }
1877 }
1878 }
1879 return nullptr;
1880}
1881
1882bool ImpEditView::IsBulletArea( const Point& rPos, sal_Int32* pPara )
1883{
1884 if ( pPara )
1885 *pPara = EE_PARA_NOT_FOUND;
1886
1887 if( !GetOutputArea().Contains( rPos ) )
1888 return false;
1889
1890 Point aDocPos( GetDocPos( rPos ) );
1891 EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false);
1892 if (!aPaM)
1893 return false;
1894
1895 if ( aPaM.GetIndex() == 0 )
1896 {
1897 sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
1898 tools::Rectangle aBulletArea = pEditEngine->GetBulletArea( nPara );
1899 tools::Long nY = pEditEngine->GetDocPosTopLeft( nPara ).Y();
1900 const ParaPortion* pParaPortion = pEditEngine->GetParaPortions()[nPara];
1901 nY += pParaPortion->GetFirstLineOffset();
1902 if ( ( aDocPos.Y() > ( nY + aBulletArea.Top() ) ) &&
1903 ( aDocPos.Y() < ( nY + aBulletArea.Bottom() ) ) &&
1904 ( aDocPos.X() > ( aBulletArea.Left() ) ) &&
1905 ( aDocPos.X() < ( aBulletArea.Right() ) ) )
1906 {
1907 if ( pPara )
1908 *pPara = nPara;
1909 return true;
1910 }
1911 }
1912
1913 return false;
1914}
1915
1916void ImpEditView::CutCopy( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bCut )
1917{
1918 if ( !(rxClipboard.is() && HasSelection()) )
1919 return;
1920
1921 uno::Reference<datatransfer::XTransferable> xData = pEditEngine->CreateTransferable( GetEditSelection() );
1922
1923 {
1924 SolarMutexReleaser aReleaser;
1925
1926 try
1927 {
1928 rxClipboard->setContents( xData, nullptr );
1929
1930 // #87756# FlushClipboard, but it would be better to become a TerminateListener to the Desktop and flush on demand...
1931 uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
1932 if( xFlushableClipboard.is() )
1933 xFlushableClipboard->flushClipboard();
1934 }
1935 catch( const css::uno::Exception& )
1936 {
1937 }
1938
1939 }
1940
1941 if (bCut)
1942 {
1943 pEditEngine->pImpEditEngine->UndoActionStart(EDITUNDO_CUT);
1945 pEditEngine->pImpEditEngine->UndoActionEnd();
1946 }
1947}
1948
1949void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial )
1950{
1951 if ( !rxClipboard.is() )
1952 return;
1953
1954 uno::Reference< datatransfer::XTransferable > xDataObj;
1955
1956 try
1957 {
1958 SolarMutexReleaser aReleaser;
1959 xDataObj = rxClipboard->getContents();
1960 }
1961 catch( const css::uno::Exception& )
1962 {
1963 }
1964
1965 if ( !xDataObj.is() || !EditEngine::HasValidData( xDataObj ) )
1966 return;
1967
1968 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE );
1969
1971 if ( aSel.HasRange() )
1972 {
1974 aSel = pEditEngine->DeleteSelection(aSel);
1975 }
1976
1977 PasteOrDropInfos aPasteOrDropInfos;
1978 aPasteOrDropInfos.nStartPara = pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() );
1979 pEditEngine->HandleBeginPasteOrDrop(aPasteOrDropInfos);
1980
1981 if ( DoSingleLinePaste() )
1982 {
1983 datatransfer::DataFlavor aFlavor;
1984 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
1985 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
1986 {
1987 try
1988 {
1989 uno::Any aData = xDataObj->getTransferData( aFlavor );
1990 OUString aTmpText;
1991 aData >>= aTmpText;
1992 OUString aText(convertLineEnd(aTmpText, LINEEND_LF));
1993 aText = aText.replaceAll( OUStringChar(LINE_SEP), " " );
1994 aSel = pEditEngine->InsertText(aSel, aText);
1995 }
1996 catch( ... )
1997 {
1998 ; // #i9286# can happen, even if isDataFlavorSupported returns true...
1999 }
2000 }
2001 }
2002 else
2003 {
2004 // Prevent notifications of paragraph inserts et al that would trigger
2005 // a11y to format content in a half-ready state when obtaining
2006 // paragraphs. Collect and broadcast when done instead.
2007 aSel = pEditEngine->InsertText(
2008 xDataObj, OUString(), aSel.Min(),
2010 }
2011
2012 aPasteOrDropInfos.nEndPara = pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() );
2013 pEditEngine->HandleEndPasteOrDrop(aPasteOrDropInfos);
2014
2015 pEditEngine->pImpEditEngine->UndoActionEnd();
2016 SetEditSelection( aSel );
2017 pEditEngine->pImpEditEngine->UpdateSelections();
2018 pEditEngine->pImpEditEngine->FormatAndLayout( GetEditViewPtr() );
2019 ShowCursor( DoAutoScroll(), true );
2020}
2021
2022
2024{
2026 if ( !aSel.HasRange() )
2027 return false;
2028
2029 aSel.Adjust( pEditEngine->GetEditDoc() );
2030
2031 sal_Int32 nStartNode = pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() );
2032 sal_Int32 nEndNode = pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() );
2033 sal_Int32 nCurNode = pEditEngine->GetEditDoc().GetPos( rPaM.GetNode() );
2034
2035 if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
2036 return true;
2037
2038 if ( nStartNode == nEndNode )
2039 {
2040 if ( nCurNode == nStartNode )
2041 if ( ( rPaM.GetIndex() >= aSel.Min().GetIndex() ) && ( rPaM.GetIndex() < aSel.Max().GetIndex() ) )
2042 return true;
2043 }
2044 else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.Min().GetIndex() ) )
2045 return true;
2046 else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.Max().GetIndex() ) )
2047 return true;
2048
2049 return false;
2050}
2051
2053{
2056 aNewSelection.Min() = aNewSelection.Max();
2058 // const_cast<EditPaM&>(GetEditSelection().Min()) = GetEditSelection().Max();
2059}
2060
2062{
2066 aNewSelection.Min() = aNewSelection.Max();
2068 // const_cast<EditPaM&>(GetEditSelection().Min()) = GetEditSelection().Max();
2069
2071 {
2072 VclPtr<vcl::Window> pParent = pOutWin->GetParentWithLOKNotifier();
2073 if (pParent && pParent->GetLOKWindowId())
2074 {
2075 const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier();
2076 std::vector<vcl::LOKPayloadItem> aItems;
2077 aItems.emplace_back("rectangles", "");
2078 pNotifier->notifyWindow(pParent->GetLOKWindowId(), "text_selection", aItems);
2079 }
2080 }
2081}
2082
2084{
2085 if ( pDragAndDropInfo && pDragAndDropInfo->pField )
2086 return true;
2087
2088 // Logical units ...
2089 const OutputDevice& rOutDev = GetOutputDevice();
2090 Point aMousePos = rOutDev.PixelToLogic(rPosPixel);
2091
2092 if ( ( !GetOutputArea().Contains( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() )
2093 {
2094 return false;
2095 }
2096
2097 Point aDocPos( GetDocPos( aMousePos ) );
2098 EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false);
2099 return IsInSelection( aPaM );
2100}
2101
2102bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel )
2103{
2105
2106 Point aMousePos( rPointPixel );
2107
2108 // Logical units ...
2109 const OutputDevice& rOutDev = GetOutputDevice();
2110 aMousePos = rOutDev.PixelToLogic( aMousePos );
2111
2112 if ( ( !GetOutputArea().Contains( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() )
2113 {
2114 return false;
2115 }
2116
2117 Point aDocPos( GetDocPos( aMousePos ) );
2118
2119 // Can be optimized: first go through the lines within a paragraph for PAM,
2120 // then again with the PaM for the Rect, even though the line is already
2121 // known... This must not be, though!
2122 EditPaM aPaM = pEditEngine->GetPaM(aDocPos);
2123 bool bGotoCursor = DoAutoScroll();
2124
2125 // aTmpNewSel: Diff between old and new, not the new selection, unless for tiled rendering
2127
2128 // #i27299#
2129 // work on copy of current selection and set new selection, if it has changed.
2130 EditSelection aNewEditSelection( GetEditSelection() );
2131
2132 aNewEditSelection.Max() = aPaM;
2134 {
2135 if ( aNewEditSelection.Min() != aPaM )
2136 pEditEngine->CursorMoved(aNewEditSelection.Min().GetNode());
2137 aNewEditSelection.Min() = aPaM;
2138 }
2139 else
2140 {
2141 DrawSelectionXOR( aTmpNewSel );
2142 }
2143
2144 // set changed text selection
2145 if ( GetEditSelection() != aNewEditSelection )
2146 {
2147 SetEditSelection( aNewEditSelection );
2148 }
2149
2150 bool bForceCursor = pDragAndDropInfo == nullptr && !pEditEngine->pImpEditEngine->IsInSelectionMode();
2151 ShowCursor( bGotoCursor, bForceCursor );
2152 return true;
2153}
2154
2156{
2157 if ( pDragAndDropInfo && pDragAndDropInfo->bVisCursor )
2158 {
2159 OutputDevice& rOutDev = GetOutputDevice();
2160 rOutDev.DrawOutDev( pDragAndDropInfo->aCurSavedCursor.TopLeft(), pDragAndDropInfo->aCurSavedCursor.GetSize(),
2161 Point(0,0), pDragAndDropInfo->aCurSavedCursor.GetSize(),*pDragAndDropInfo->pBackground );
2162 pDragAndDropInfo->bVisCursor = false;
2163 }
2164}
2165
2167{
2168 if ( !pDragAndDropInfo || pDragAndDropInfo->bVisCursor )
2169 return;
2170
2171 if (pOutWin && pOutWin->GetCursor())
2172 pOutWin->GetCursor()->Hide();
2173
2174 OutputDevice& rOutDev = GetOutputDevice();
2175 Color aOldFillColor = rOutDev.GetFillColor();
2176 rOutDev.SetFillColor( Color(4210752) ); // GRAY BRUSH_50, OLDSV, change to DDCursor!
2177
2178 // Save background ...
2179 tools::Rectangle aSaveRect( rOutDev.LogicToPixel( rRect ) );
2180 // prefer to save some more ...
2181 aSaveRect.AdjustRight(1 );
2182 aSaveRect.AdjustBottom(1 );
2183
2184 if ( !pDragAndDropInfo->pBackground )
2185 {
2186 pDragAndDropInfo->pBackground = VclPtr<VirtualDevice>::Create(rOutDev);
2187 MapMode aMapMode( rOutDev.GetMapMode() );
2188 aMapMode.SetOrigin( Point( 0, 0 ) );
2189 pDragAndDropInfo->pBackground->SetMapMode( aMapMode );
2190
2191 }
2192
2193 Size aNewSzPx( aSaveRect.GetSize() );
2194 Size aCurSzPx( pDragAndDropInfo->pBackground->GetOutputSizePixel() );
2195 if ( ( aCurSzPx.Width() < aNewSzPx.Width() ) ||( aCurSzPx.Height() < aNewSzPx.Height() ) )
2196 {
2197 bool bDone = pDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx );
2198 DBG_ASSERT( bDone, "Virtual Device broken?" );
2199 }
2200
2201 aSaveRect = rOutDev.PixelToLogic( aSaveRect );
2202
2203 pDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRect.GetSize(),
2204 aSaveRect.TopLeft(), aSaveRect.GetSize(), rOutDev );
2205 pDragAndDropInfo->aCurSavedCursor = aSaveRect;
2206
2207 // Draw Cursor...
2208 rOutDev.DrawRect( rRect );
2209
2210 pDragAndDropInfo->bVisCursor = true;
2211 pDragAndDropInfo->aCurCursor = rRect;
2212
2213 rOutDev.SetFillColor( aOldFillColor );
2214}
2215
2216void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent& rDGE)
2217{
2218 DBG_ASSERT( !pDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!" );
2219
2220 SolarMutexGuard aVclGuard;
2221
2222 pDragAndDropInfo.reset();
2223
2224 Point aMousePosPixel( rDGE.DragOriginX, rDGE.DragOriginY );
2225
2226 EditSelection aCopySel( GetEditSelection() );
2227 aCopySel.Adjust( pEditEngine->GetEditDoc() );
2228
2230 {
2231 pDragAndDropInfo.reset(new DragAndDropInfo());
2232 }
2233 else
2234 {
2235 // Field?!
2236 sal_Int32 nPara;
2237 sal_Int32 nPos;
2238 Point aMousePos = GetOutputDevice().PixelToLogic( aMousePosPixel );
2239 const SvxFieldItem* pField = GetField( aMousePos, &nPara, &nPos );
2240 if ( pField )
2241 {
2242 pDragAndDropInfo.reset(new DragAndDropInfo());
2243 pDragAndDropInfo->pField = pField;
2244 ContentNode* pNode = pEditEngine->GetEditDoc().GetObject( nPara );
2245 aCopySel = EditSelection( EditPaM( pNode, nPos ), EditPaM( pNode, nPos+1 ) );
2246 SetEditSelection(aCopySel);
2248 bool bGotoCursor = DoAutoScroll();
2249 ShowCursor( bGotoCursor, /*bForceCursor=*/false );
2250 }
2251 else if ( IsBulletArea( aMousePos, &nPara ) )
2252 {
2253 pDragAndDropInfo.reset(new DragAndDropInfo());
2254 pDragAndDropInfo->bOutlinerMode = true;
2255 EditPaM aStartPaM( pEditEngine->GetEditDoc().GetObject( nPara ), 0 );
2256 EditPaM aEndPaM( aStartPaM );
2257 const SfxInt16Item& rLevel = pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL );
2258 for ( sal_Int32 n = nPara +1; n < pEditEngine->GetEditDoc().Count(); n++ )
2259 {
2261 if ( rL.GetValue() > rLevel.GetValue() )
2262 {
2263 aEndPaM.SetNode( pEditEngine->GetEditDoc().GetObject( n ) );
2264 }
2265 else
2266 {
2267 break;
2268 }
2269 }
2270 aEndPaM.SetIndex( aEndPaM.GetNode()->Len() );
2271 SetEditSelection( EditSelection( aStartPaM, aEndPaM ) );
2272 }
2273 }
2274
2275 if ( !pDragAndDropInfo )
2276 return;
2277
2278
2279 pDragAndDropInfo->bStarterOfDD = true;
2280
2281 // Sensitive area to be scrolled.
2282 Size aSz( 5, 0 );
2283 aSz = GetOutputDevice().PixelToLogic( aSz );
2284 pDragAndDropInfo->nSensibleRange = static_cast<sal_uInt16>(aSz.Width());
2285 pDragAndDropInfo->nCursorWidth = static_cast<sal_uInt16>(aSz.Width()) / 2;
2286 pDragAndDropInfo->aBeginDragSel = pEditEngine->pImpEditEngine->CreateESel( aCopySel );
2287
2288 uno::Reference<datatransfer::XTransferable> xData = pEditEngine->CreateTransferable(aCopySel);
2289
2290 sal_Int8 nActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE;
2291
2292 rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, xData, mxDnDListener );
2293 // If Drag&Move in an Engine, then Copy&Del has to be optional!
2294 GetCursor()->Hide();
2295}
2296
2297void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent& rDSDE )
2298{
2299 SolarMutexGuard aVclGuard;
2300
2301 DBG_ASSERT( pDragAndDropInfo, "ImpEditView::dragDropEnd: pDragAndDropInfo is NULL!" );
2302
2303 // #123688# Shouldn't happen, but seems to happen...
2304 if ( !pDragAndDropInfo )
2305 return;
2306
2307 if ( !bReadOnly && rDSDE.DropSuccess && !pDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) )
2308 {
2309 if ( pDragAndDropInfo->bStarterOfDD && pDragAndDropInfo->bDroppedInMe )
2310 {
2311 // DropPos: Where was it dropped, irrespective of length.
2312 ESelection aDropPos( pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos, pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos );
2313 ESelection aToBeDelSel = pDragAndDropInfo->aBeginDragSel;
2314 ESelection aNewSel( pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos,
2315 pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos );
2316 bool bBeforeSelection = aDropPos < pDragAndDropInfo->aBeginDragSel;
2317 sal_Int32 nParaDiff = pDragAndDropInfo->aBeginDragSel.nEndPara - pDragAndDropInfo->aBeginDragSel.nStartPara;
2318 if ( bBeforeSelection )
2319 {
2320 // Adjust aToBeDelSel.
2321 DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara >= pDragAndDropInfo->aDropSel.nStartPara, "But not before? ");
2322 aToBeDelSel.nStartPara = aToBeDelSel.nStartPara + nParaDiff;
2323 aToBeDelSel.nEndPara = aToBeDelSel.nEndPara + nParaDiff;
2324 // To correct the character?
2325 if ( aToBeDelSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara )
2326 {
2327 sal_uInt16 nMoreChars;
2328 if ( pDragAndDropInfo->aDropSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara )
2329 nMoreChars = pDragAndDropInfo->aDropSel.nEndPos - pDragAndDropInfo->aDropSel.nStartPos;
2330 else
2331 nMoreChars = pDragAndDropInfo->aDropSel.nEndPos;
2332 aToBeDelSel.nStartPos =
2333 aToBeDelSel.nStartPos + nMoreChars;
2334 if ( aToBeDelSel.nStartPara == aToBeDelSel.nEndPara )
2335 aToBeDelSel.nEndPos =
2336 aToBeDelSel.nEndPos + nMoreChars;
2337 }
2338 }
2339 else
2340 {
2341 // aToBeDelSel is ok, but the selection of the View
2342 // has to be adapted, if it was deleted before!
2343 DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara <= pDragAndDropInfo->aDropSel.nStartPara, "But not before? ");
2344 aNewSel.nStartPara = aNewSel.nStartPara - nParaDiff;
2345 aNewSel.nEndPara = aNewSel.nEndPara - nParaDiff;
2346 // To correct the character?
2347 if ( pDragAndDropInfo->aBeginDragSel.nEndPara == pDragAndDropInfo->aDropSel.nStartPara )
2348 {
2349 sal_uInt16 nLessChars;
2350 if ( pDragAndDropInfo->aBeginDragSel.nStartPara == pDragAndDropInfo->aBeginDragSel.nEndPara )
2351 nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos - pDragAndDropInfo->aBeginDragSel.nStartPos;
2352 else
2353 nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos;
2354 aNewSel.nStartPos = aNewSel.nStartPos - nLessChars;
2355 if ( aNewSel.nStartPara == aNewSel.nEndPara )
2356 aNewSel.nEndPos = aNewSel.nEndPos - nLessChars;
2357 }
2358 }
2359
2361 EditSelection aDelSel( pEditEngine->pImpEditEngine->CreateSel( aToBeDelSel ) );
2362 DBG_ASSERT( !aDelSel.DbgIsBuggy( pEditEngine->GetEditDoc() ), "ToBeDel is buggy!" );
2363 pEditEngine->DeleteSelection(aDelSel);
2364 if ( !bBeforeSelection )
2365 {
2366 DBG_ASSERT( !pEditEngine->pImpEditEngine->CreateSel( aNewSel ).DbgIsBuggy(pEditEngine->GetEditDoc()), "Bad" );
2367 SetEditSelection( pEditEngine->pImpEditEngine->CreateSel( aNewSel ) );
2368 }
2369 pEditEngine->pImpEditEngine->FormatAndLayout( pEditEngine->pImpEditEngine->GetActiveView() );
2371 }
2372 else
2373 {
2374 // other EditEngine ...
2375 if (pEditEngine->HasText()) // #88630# SC is removing the content when switching the task
2377 }
2378 }
2379
2380 if ( pDragAndDropInfo->bUndoAction )
2381 pEditEngine->pImpEditEngine->UndoActionEnd();
2382
2383 HideDDCursor();
2384 ShowCursor( DoAutoScroll(), true );
2385 pDragAndDropInfo.reset();
2387}
2388
2389void ImpEditView::drop( const css::datatransfer::dnd::DropTargetDropEvent& rDTDE )
2390{
2391 SolarMutexGuard aVclGuard;
2392
2393 DBG_ASSERT( pDragAndDropInfo, "Drop - No Drag&Drop info?!" );
2394
2395 if ( !(pDragAndDropInfo && pDragAndDropInfo->bDragAccepted) )
2396 return;
2397
2399 bool bChanges = false;
2400
2401 HideDDCursor();
2402
2403 if ( pDragAndDropInfo->bStarterOfDD )
2404 {
2405 pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DRAGANDDROP );
2406 pDragAndDropInfo->bUndoAction = true;
2407 }
2408
2409 if ( pDragAndDropInfo->bOutlinerMode )
2410 {
2411 bChanges = true;
2412 GetEditViewPtr()->MoveParagraphs( Range( pDragAndDropInfo->aBeginDragSel.nStartPara, pDragAndDropInfo->aBeginDragSel.nEndPara ), pDragAndDropInfo->nOutlinerDropDest );
2413 }
2414 else
2415 {
2416 uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
2417 if ( xDataObj.is() )
2418 {
2419 bChanges = true;
2420 // remove Selection ...
2422 EditPaM aPaM( pDragAndDropInfo->aDropDest );
2423
2424 PasteOrDropInfos aPasteOrDropInfos;
2425 aPasteOrDropInfos.nStartPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
2426 pEditEngine->HandleBeginPasteOrDrop(aPasteOrDropInfos);
2427
2429 xDataObj, OUString(), aPaM, pEditEngine->GetInternalEditStatus().AllowPasteSpecial());
2430
2431 aPasteOrDropInfos.nEndPara = pEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() );
2432 pEditEngine->HandleEndPasteOrDrop(aPasteOrDropInfos);
2433
2434 SetEditSelection( aNewSel );
2435 pEditEngine->pImpEditEngine->FormatAndLayout( pEditEngine->pImpEditEngine->GetActiveView() );
2436 if ( pDragAndDropInfo->bStarterOfDD )
2437 {
2438 // Only set if the same engine!
2439 pDragAndDropInfo->aDropSel.nStartPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
2440 pDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex();
2441 pDragAndDropInfo->aDropSel.nEndPara = pEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() );
2442 pDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex();
2443 pDragAndDropInfo->bDroppedInMe = true;
2444 }
2445 }
2446 }
2447
2448 if ( bChanges )
2449 {
2450 rDTDE.Context->acceptDrop( rDTDE.DropAction );
2451 }
2452
2453 if ( !pDragAndDropInfo->bStarterOfDD )
2454 {
2455 pDragAndDropInfo.reset();
2456 }
2457
2458 rDTDE.Context->dropComplete( bChanges );
2459}
2460
2461void ImpEditView::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEvent& rDTDEE )
2462{
2463 SolarMutexGuard aVclGuard;
2464
2465 if ( !pDragAndDropInfo )
2466 pDragAndDropInfo.reset(new DragAndDropInfo());
2467
2468 pDragAndDropInfo->bHasValidData = false;
2469
2470 // Check for supported format...
2471 // Only check for text, will also be there if bin or rtf
2472 datatransfer::DataFlavor aTextFlavor;
2473 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aTextFlavor );
2474 const css::datatransfer::DataFlavor* pFlavors = rDTDEE.SupportedDataFlavors.getConstArray();
2475 int nFlavors = rDTDEE.SupportedDataFlavors.getLength();
2476 for ( int n = 0; n < nFlavors; n++ )
2477 {
2478 if( TransferableDataHelper::IsEqual( pFlavors[n], aTextFlavor ) )
2479 {
2480 pDragAndDropInfo->bHasValidData = true;
2481 break;
2482 }
2483 }
2484
2485 dragOver( rDTDEE );
2486}
2487
2488void ImpEditView::dragExit( const css::datatransfer::dnd::DropTargetEvent& )
2489{
2490 SolarMutexGuard aVclGuard;
2491
2492 HideDDCursor();
2493
2494 if ( pDragAndDropInfo && !pDragAndDropInfo->bStarterOfDD )
2495 {
2496 pDragAndDropInfo.reset();
2497 }
2498}
2499
2500void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rDTDE)
2501{
2502 SolarMutexGuard aVclGuard;
2503
2504 const OutputDevice& rOutDev = GetOutputDevice();
2505
2506 Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
2507 aMousePos = rOutDev.PixelToLogic( aMousePos );
2508
2509 bool bAccept = false;
2510
2511 if ( GetOutputArea().Contains( aMousePos ) && !bReadOnly )
2512 {
2513 if ( pDragAndDropInfo && pDragAndDropInfo->bHasValidData )
2514 {
2515 bAccept = true;
2516
2517 bool bAllowScroll = DoAutoScroll();
2518 if ( bAllowScroll )
2519 {
2522 // Check if in the sensitive area
2523 if ( ( (aMousePos.X()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) )
2525 else if ( ( (aMousePos.X()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) )
2527
2528 if ( ( (aMousePos.Y()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) )
2530 else if ( ( (aMousePos.Y()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) )
2532
2533 if ( nScrollX || nScrollY )
2534 {
2535 HideDDCursor();
2537 }
2538 }
2539
2540 Point aDocPos( GetDocPos( aMousePos ) );
2541 EditPaM aPaM = pEditEngine->GetPaM( aDocPos );
2542 pDragAndDropInfo->aDropDest = aPaM;
2543 if ( pDragAndDropInfo->bOutlinerMode )
2544 {
2545 sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
2546 ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( nPara );
2547 if (pPPortion)
2548 {
2549 tools::Long nDestParaStartY = pEditEngine->GetParaPortions().GetYOffset( pPPortion );
2550 tools::Long nRel = aDocPos.Y() - nDestParaStartY;
2551 if ( nRel < ( pPPortion->GetHeight() / 2 ) )
2552 {
2553 pDragAndDropInfo->nOutlinerDropDest = nPara;
2554 }
2555 else
2556 {
2557 pDragAndDropInfo->nOutlinerDropDest = nPara+1;
2558 }
2559
2560 if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) &&
2561 ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) )
2562 {
2563 bAccept = false;
2564 }
2565 }
2566 }
2567 else if ( HasSelection() )
2568 {
2569 // it must not be dropped into a selection
2570 EPaM aP = pEditEngine->pImpEditEngine->CreateEPaM( aPaM );
2571 ESelection aDestSel( aP.nPara, aP.nIndex, aP.nPara, aP.nIndex);
2572 ESelection aCurSel = pEditEngine->pImpEditEngine->CreateESel( GetEditSelection() );
2573 aCurSel.Adjust();
2574 if ( !(aDestSel < aCurSel) && !(aDestSel > aCurSel) )
2575 {
2576 bAccept = false;
2577 }
2578 }
2579 if ( bAccept )
2580 {
2581 tools::Rectangle aEditCursor;
2582 if ( pDragAndDropInfo->bOutlinerMode )
2583 {
2584 tools::Long nDDYPos(0);
2585 if ( pDragAndDropInfo->nOutlinerDropDest < pEditEngine->GetEditDoc().Count() )
2586 {
2587 ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( pDragAndDropInfo->nOutlinerDropDest );
2588 if (pPPortion)
2589 nDDYPos = pEditEngine->GetParaPortions().GetYOffset( pPPortion );
2590 }
2591 else
2592 {
2593 nDDYPos = pEditEngine->pImpEditEngine->GetTextHeight();
2594 }
2595 Point aStartPos( 0, nDDYPos );
2596 aStartPos = GetWindowPos( aStartPos );
2597 Point aEndPos( GetOutputArea().GetWidth(), nDDYPos );
2598 aEndPos = GetWindowPos( aEndPos );
2599 aEditCursor = rOutDev.LogicToPixel( tools::Rectangle( aStartPos, aEndPos ) );
2601 {
2602 aEditCursor.AdjustTop( -1 );
2603 aEditCursor.AdjustBottom( 1 );
2604 }
2605 else
2606 {
2607 if( IsTopToBottom() )
2608 {
2609 aEditCursor.AdjustLeft( -1 );
2610 aEditCursor.AdjustRight( 1 );
2611 }
2612 else
2613 {
2614 aEditCursor.AdjustLeft( 1 );
2615 aEditCursor.AdjustRight( -1 );
2616 }
2617 }
2618 aEditCursor = rOutDev.PixelToLogic( aEditCursor );
2619 }
2620 else
2621 {
2622 aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM );
2623 Point aTopLeft( GetWindowPos( aEditCursor.TopLeft() ) );
2624 aEditCursor.SetPos( aTopLeft );
2625 aEditCursor.SetRight( aEditCursor.Left() + pDragAndDropInfo->nCursorWidth );
2626 aEditCursor = rOutDev.LogicToPixel( aEditCursor );
2627 aEditCursor = rOutDev.PixelToLogic( aEditCursor );
2628 }
2629
2630 bool bCursorChanged = !pDragAndDropInfo->bVisCursor || ( pDragAndDropInfo->aCurCursor != aEditCursor );
2631 if ( bCursorChanged )
2632 {
2633 HideDDCursor();
2634 ShowDDCursor(aEditCursor );
2635 }
2636 pDragAndDropInfo->bDragAccepted = true;
2637 rDTDE.Context->acceptDrag( rDTDE.DropAction );
2638 }
2639 }
2640 }
2641
2642 if ( !bAccept )
2643 {
2644 HideDDCursor();
2645 if (pDragAndDropInfo)
2646 pDragAndDropInfo->bDragAccepted = false;
2647 rDTDE.Context->rejectDrag();
2648 }
2649}
2650
2652{
2654 return;
2655
2656 css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget;
2657 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
2658 xDropTarget = pCallbacks->GetDropTarget();
2659 else if (auto xWindow = GetWindow())
2660 xDropTarget = xWindow->GetDropTarget();
2661
2662 if (!xDropTarget.is())
2663 return;
2664
2666
2667 css::uno::Reference<css::datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY);
2668 if (xDragGestureRecognizer.is())
2669 {
2670 uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY);
2671 xDragGestureRecognizer->addDragGestureListener(xDGL);
2672 }
2673
2674 uno::Reference<datatransfer::dnd::XDropTargetListener> xDTL(mxDnDListener, uno::UNO_QUERY);
2675 xDropTarget->addDropTargetListener(xDTL);
2676 xDropTarget->setActive(true);
2677 xDropTarget->setDefaultActions(datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE);
2678
2680}
2681
2683{
2685 return;
2686
2687 css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget;
2688 if (EditViewCallbacks* pCallbacks = getEditViewCallbacks())
2689 xDropTarget = pCallbacks->GetDropTarget();
2690 else if (auto xWindow = GetWindow())
2691 xDropTarget = xWindow->GetDropTarget();
2692
2693 if (xDropTarget.is())
2694 {
2695 css::uno::Reference<css::datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY);
2696 if (xDragGestureRecognizer.is())
2697 {
2698 uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY);
2699 xDragGestureRecognizer->removeDragGestureListener(xDGL);
2700 }
2701
2702 uno::Reference<datatransfer::dnd::XDropTargetListener> xDTL(mxDnDListener, uno::UNO_QUERY);
2703 xDropTarget->removeDropTargetListener(xDTL);
2704 }
2705
2706 if ( mxDnDListener.is() )
2707 {
2708 mxDnDListener->disposing( lang::EventObject() ); // #95154# Empty Source means it's the Client
2709 mxDnDListener.clear();
2710 }
2711
2713}
2714
2716 const tools::Rectangle& rOutputArea,
2717 const Point& rVisDocStartPos)
2718{
2720 mpLOKSpecialPositioning.reset(new LOKSpecialPositioning(*this, eUnit, rOutputArea, rVisDocStartPos));
2721 else
2722 mpLOKSpecialPositioning->ReInit(eUnit, rOutputArea, rVisDocStartPos);
2723}
2724
2726{
2728 mpLOKSpecialPositioning->SetOutputArea(rOutputArea);
2729}
2730
2732{
2734 return mpLOKSpecialPositioning->GetOutputArea();
2735}
2736
2738{
2740 mpLOKSpecialPositioning->SetVisDocStartPos(rVisArea.TopLeft());
2741}
2742
2744{
2746 return mpLOKSpecialPositioning->GetVisDocArea();
2747}
2748
2750{
2751 return bool(mpLOKSpecialPositioning);
2752}
2753
2755{
2757 mpLOKSpecialPositioning->SetFlags(eFlags);
2758}
2759
2760/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const MouseSettings & GetMouseSettings() const
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
AttribsType & GetAttribs()
Definition: editdoc.hxx:222
std::vector< std::unique_ptr< EditCharAttrib > > AttribsType
Definition: editdoc.hxx:186
CharAttribList & GetCharAttribs()
Definition: editdoc.hxx:256
WrongList * GetWrongList()
Definition: editdoc.cxx:1777
sal_Int32 Len() const
Definition: editdoc.cxx:1615
sal_Int32 & GetStart()
Definition: editattr.hxx:87
const SfxPoolItem * GetItem() const
Definition: editattr.hxx:85
sal_uInt16 Which() const
Definition: editattr.hxx:84
sal_Int32 & GetEnd()
Definition: editattr.hxx:88
EditPaM GetEndPaM() const
Definition: editdoc.cxx:2204
sal_Int32 GetPos(const ContentNode *pNode) const
Definition: editdoc.cxx:2086
const ContentNode * GetObject(sal_Int32 nPos) const
Definition: editdoc.cxx:2091
sal_Int32 Count() const
Definition: editdoc.cxx:2143
EditPaM GetStartPaM() const
Definition: editdoc.cxx:2198
EDITENG_DLLPRIVATE tools::Long GetXPos(const ParaPortion *pParaPortion, const EditLine *pLine, sal_Int32 nIndex, bool bPreferPortionStart=false) const
Definition: editeng.cxx:873
EDITENG_DLLPRIVATE InternalEditStatus & GetInternalEditStatus()
Definition: editeng.cxx:900
EditPaM CursorRight(const EditPaM &rPaM, sal_uInt16 nCharacterIteratorMode=css::i18n::CharacterIteratorMode::SKIPCELL)
Definition: editeng.cxx:895
EditPaM DeleteSelection(const EditSelection &rSel)
Definition: editeng.cxx:935
EDITENG_DLLPRIVATE const EditSelectionEngine & GetSelectionEngine() const
Definition: editeng.cxx:990
EDITENG_DLLPRIVATE void HandleEndPasteOrDrop(PasteOrDropInfos &rInfos)
Definition: editeng.cxx:980
EDITENG_DLLPRIVATE css::uno::Reference< css::datatransfer::XTransferable > CreateTransferable(const EditSelection &rSelection)
Definition: editeng.cxx:814
EDITENG_DLLPRIVATE void SetInSelectionMode(bool b)
Definition: editeng.cxx:995
void SeekCursor(ContentNode *pNode, sal_Int32 nPos, SvxFont &rFont)
Definition: editeng.cxx:930
bool IsEffectivelyVertical() const
Definition: editeng.cxx:441
virtual tools::Rectangle GetBulletArea(sal_Int32 nPara)
Definition: editeng.cxx:2613
EditSelection InsertText(css::uno::Reference< css::datatransfer::XTransferable > const &rxDataObj, const OUString &rBaseURL, const EditPaM &rPaM, bool bUseSpecial)
EDITENG_DLLPRIVATE bool IsIdleFormatterActive() const
Definition: editeng.cxx:691
Link< EditView *, void > const & GetEndDropHdl() const
Definition: editeng.cxx:2825
bool IsRightToLeft(sal_Int32 nPara) const
Definition: editeng.cxx:2034
const SfxPoolItem & GetParaAttrib(sal_Int32 nPara, sal_uInt16 nWhich) const
Definition: editeng.cxx:1764
EDITENG_DLLPRIVATE void HandleBeginPasteOrDrop(PasteOrDropInfos &rInfos)
Definition: editeng.cxx:975
Link< EditView *, void > const & GetBeginDropHdl() const
Definition: editeng.cxx:2814
EDITENG_DLLPRIVATE void CheckIdleFormatter()
Definition: editeng.cxx:686
EDITENG_DLLPRIVATE void CursorMoved(const ContentNode *pPrevNode)
Definition: editeng.cxx:681
ParaPortionList & GetParaPortions()
Definition: editeng.cxx:920
bool IsFormatted() const
Definition: editeng.cxx:885
EDITENG_DLLPRIVATE bool PostKeyEvent(const KeyEvent &rKeyEvent, EditView *pView, vcl::Window const *pFrameWin)
Definition: editeng.cxx:1000
EDITENG_DLLPRIVATE EditPaM GetPaM(const Point &aDocPos, bool bSmart=true)
Definition: editeng.cxx:862
std::unique_ptr< ImpEditEngine > pImpEditEngine
EDITENG_DLLPRIVATE bool HasText() const
Definition: editeng.cxx:985
EDITENG_DLLPRIVATE EditSelection SelectWord(const EditSelection &rCurSelection, sal_Int16 nWordType=css::i18n::WordType::ANYWORD_IGNOREWHITESPACES)
Definition: editeng.cxx:867
static bool HasValidData(const css::uno::Reference< css::datatransfer::XTransferable > &rTransferable)
Definition: editeng.cxx:2790
Point GetDocPosTopLeft(sal_Int32 nParagraph)
Definition: editeng.cxx:1993
EditDoc & GetEditDoc()
Definition: editeng.cxx:905
EDITENG_DLLPRIVATE Range GetLineXPosStartEnd(const ParaPortion *pParaPortion, const EditLine *pLine) const
Definition: editeng.cxx:879
void SetIndex(sal_Int32 n)
Definition: editdoc.hxx:317
void SetNode(ContentNode *p)
Definition: editdoc.cxx:1122
const ContentNode * GetNode() const
Definition: editdoc.hxx:312
sal_Int32 GetIndex() const
Definition: editdoc.hxx:316
EditPaM & Min()
Definition: editdoc.hxx:705
bool DbgIsBuggy(EditDoc const &rDoc) const
Definition: editdoc.cxx:1134
bool HasRange() const
Definition: editdoc.hxx:711
EditPaM & Max()
Definition: editdoc.hxx:706
void Adjust(const EditDoc &rNodes)
Definition: editdoc.cxx:1162
EditStatusFlags GetStatusWord() const
Definition: editstat.hxx:110
void MoveParagraphs(Range aParagraphs, sal_Int32 nNewPos)
Definition: editview.cxx:700
const SvxFieldItem * GetFieldAtSelection() const
Definition: editview.cxx:1337
void Invalidate()
Definition: editview.cxx:239
void SetBackgroundColor(const Color &rColor)
Definition: impedit.cxx:220
tools::Long nInvMore
Definition: impedit.hxx:280
void ScrollStateChange()
Definition: impedit.cxx:1500
bool IsVertical() const
Definition: impedit.cxx:748
bool bReadOnly
Definition: impedit.hxx:286
bool DoInvalidateMore() const
Definition: impedit.hxx:444
void CutCopy(css::uno::Reference< css::datatransfer::clipboard::XClipboard > const &rxClipboard, bool bCut)
Definition: impedit.cxx:1916
void AddDragAndDropListeners()
Definition: impedit.cxx:2651
void DrawSelectionXOR()
Definition: impedit.hxx:395
bool IsTopToBottom() const
Definition: impedit.cxx:753
vcl::Cursor * GetCursor()
Definition: impedit.hxx:1353
void SelectionChanged()
Definition: impedit.cxx:315
sal_uInt16 nCursorBidiLevel
Definition: impedit.hxx:284
void RegisterOtherShell(OutlinerViewShell *pViewShell)
Informs this edit view about which other shell listens to it.
Definition: impedit.cxx:235
EditView * pEditView
Definition: impedit.hxx:264
void ShowDDCursor(const tools::Rectangle &rRect)
Definition: impedit.cxx:2166
void RecalcOutputArea()
Definition: impedit.cxx:965
ImpEditView(EditView *pView, EditEngine *pEng, vcl::Window *pWindow)
Definition: impedit.cxx:183
bool IsBulletArea(const Point &rPos, sal_Int32 *pPara)
Definition: impedit.cxx:1882
std::optional< Color > mxBackgroundColor
Definition: impedit.hxx:266
EditViewCallbacks * getEditViewCallbacks() const
Definition: impedit.hxx:310
const tools::Rectangle & GetLOKSpecialOutputArea() const
Definition: impedit.cxx:2731
void CalcAnchorPoint()
Definition: impedit.cxx:1040
tools::Rectangle ImplGetEditCursor(EditPaM &aPaM, GetCursorFlags nShowCursorFlags, sal_Int32 &nTextPortionStart, const ParaPortion *pParaPortion) const
Definition: impedit.cxx:1111
bool mbBroadcastLOKViewCursor
Definition: impedit.hxx:306
vcl::Window * GetWindow() const
Definition: impedit.hxx:403
void SetLOKSpecialFlags(LOKSpecialFlags eFlags)
Definition: impedit.cxx:2754
void Paste(css::uno::Reference< css::datatransfer::clipboard::XClipboard > const &rxClipboard, bool bUseSpecial=false)
Definition: impedit.cxx:1949
EVControlBits nControl
Definition: impedit.hxx:281
OUString SpellIgnoreWord()
Definition: impedit.cxx:1788
const tools::Rectangle & GetOutputArea() const
Definition: impedit.hxx:366
void SetOutputArea(const tools::Rectangle &rRect)
Definition: impedit.cxx:864
bool DoAutoScroll() const
Definition: impedit.hxx:440
void InvalidateAtWindow(const tools::Rectangle &rRect)
Definition: impedit.cxx:888
bool MouseMove(const MouseEvent &rMouseEvent)
Definition: impedit.cxx:1750
void dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent &dtdee) override
Definition: impedit.cxx:2461
bool mbSuppressLOKMessages
Definition: impedit.hxx:307
void drop(const css::datatransfer::dnd::DropTargetDropEvent &dtde) override
Definition: impedit.cxx:2389
void GetSelectionRectangles(EditSelection aTmpSel, std::vector< tools::Rectangle > &rLogicRects)
Definition: impedit.cxx:662
EESelectionMode eSelectionMode
Definition: impedit.hxx:293
void dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent &dge) override
Definition: impedit.cxx:2216
bool bClickedInSelection
Definition: impedit.hxx:287
void dragExit(const css::datatransfer::dnd::DropTargetEvent &dte) override
Definition: impedit.cxx:2488
EditSelection aEditSelection
Definition: impedit.hxx:294
tools::Rectangle GetVisDocArea() const
Definition: impedit.cxx:758
const SvxFieldItem * GetField(const Point &rPos, sal_Int32 *pPara, sal_Int32 *pPos) const
Definition: impedit.cxx:1845
bool MouseButtonUp(const MouseEvent &rMouseEvent)
Definition: impedit.cxx:1710
Point aAnchorPoint
Definition: impedit.hxx:290
void HideDDCursor()
Definition: impedit.cxx:2155
tools::Rectangle GetEditCursor() const
Definition: impedit.cxx:1149
bool DoAutoHeight() const
Definition: impedit.hxx:443
bool MouseButtonDown(const MouseEvent &rMouseEvent)
Definition: impedit.cxx:1737
bool HasLOKSpecialPositioning() const
Definition: impedit.cxx:2749
sal_uInt16 GetCursorBidiLevel() const
Definition: impedit.hxx:357
tools::Long GetVisDocTop() const
Definition: impedit.hxx:385
void dragOver(const css::datatransfer::dnd::DropTargetDragEvent &dtde) override
Definition: impedit.cxx:2500
sal_uInt32 nTravelXPos
Definition: impedit.hxx:282
void SetSelectionMode(EESelectionMode eMode)
Definition: impedit.cxx:836
bool HasSelection() const
Definition: impedit.hxx:392
void lokSelectionCallback(const std::optional< tools::PolyPolygon > &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible)
Definition: impedit.cxx:325
bool DoAutoWidth() const
Definition: impedit.hxx:442
void SetInsertMode(bool bInsert)
Definition: impedit.cxx:1762
css::uno::Reference< css::datatransfer::dnd::XDragSourceListener > mxDnDListener
Definition: impedit.hxx:277
std::unique_ptr< DragAndDropInfo > pDragAndDropInfo
Definition: impedit.hxx:275
EditView * GetEditViewPtr()
Definition: impedit.hxx:352
virtual ~ImpEditView() override
Definition: impedit.cxx:212
const OutlinerViewShell * GetViewShell() const
Definition: impedit.cxx:240
void SetAnchorMode(EEAnchorMode eMode)
Definition: impedit.cxx:1034
bool IsInsertMode() const
Definition: impedit.hxx:435
tools::Long GetVisDocRight() const
Definition: impedit.hxx:386
void dragDropEnd(const css::datatransfer::dnd::DragSourceDropEvent &dsde) override
Definition: impedit.cxx:2297
const EditSelection & GetEditSelection() const
Definition: impedit.hxx:390
tools::Rectangle aOutArea
Definition: impedit.hxx:291
tools::Long GetVisDocBottom() const
Definition: impedit.hxx:387
EEAnchorMode eAnchorMode
Definition: impedit.hxx:295
std::unique_ptr< LOKSpecialPositioning > mpLOKSpecialPositioning
Definition: impedit.hxx:305
void SetLOKSpecialVisArea(const tools::Rectangle &rVisArea)
Definition: impedit.cxx:2737
Point aVisDocStartPos
Definition: impedit.hxx:292
sal_uInt16 GetScrollDiffX() const
Definition: impedit.hxx:354
VclPtr< vcl::Window > pOutWin
Definition: impedit.hxx:272
void RegisterViewShell(OutlinerViewShell *pViewShell)
Informs this edit view about which view shell contains it.
Definition: impedit.cxx:230
void SetScrollDiffX(sal_uInt16 n)
Definition: impedit.hxx:355
void CreateAnchor()
Definition: impedit.cxx:2052
tools::Long GetVisDocLeft() const
Definition: impedit.hxx:384
std::unique_ptr< vcl::Cursor, o3tl::default_delete< vcl::Cursor > > pCursor
Definition: impedit.hxx:265
OutlinerViewShell * mpViewShell
Containing view shell, if any.
Definition: impedit.hxx:268
css::uno::Reference< css::datatransfer::clipboard::XClipboard > GetClipboard() const
Definition: impedit.cxx:1651
bool IsInSelection(const EditPaM &rPaM)
Definition: impedit.cxx:2023
bool IsWrongSpelledWord(const EditPaM &rPaM, bool bMarkIfWrong)
Definition: impedit.cxx:1771
bool PostKeyEvent(const KeyEvent &rKeyEvent, vcl::Window const *pFrameWin)
Definition: impedit.cxx:1661
void DeleteSelected()
Definition: impedit.cxx:1827
void ShowCursor(bool bGotoCursor, bool bForceVisCursor)
Definition: impedit.cxx:1174
Point GetWindowPos(const Point &rDocPos) const
Definition: impedit.cxx:790
bool SetCursorAtPoint(const Point &rPointPixel)
Definition: impedit.cxx:2102
Point GetDocPos(const Point &rWindowPos) const
Definition: impedit.cxx:763
OutlinerViewShell * mpOtherShell
Another shell, just listening to our state, if any.
Definition: impedit.hxx:270
void ImplDrawHighlightRect(OutputDevice &rTarget, const Point &rDocPosTopLeft, const Point &rDocPosBottomRight, tools::PolyPolygon *pPolyPoly, bool bLOKCalcRTL)
Definition: impedit.cxx:669
bool IsSelectionAtPoint(const Point &rPosPixel)
Definition: impedit.cxx:2083
bool IsPasteEnabled() const
Definition: impedit.hxx:437
bool Command(const CommandEvent &rCEvt)
Definition: impedit.cxx:1755
OutputDevice & GetOutputDevice() const
Definition: impedit.cxx:846
void DeselectAll()
Definition: impedit.cxx:2061
void SetLOKSpecialOutputArea(const tools::Rectangle &rOutputArea)
Definition: impedit.cxx:2725
const Color & GetBackgroundColor() const
Definition: impedit.cxx:225
void InitLOKSpecialPositioning(MapUnit eUnit, const tools::Rectangle &rOutputArea, const Point &rVisDocStartPos)
Definition: impedit.cxx:2715
void SetEditSelection(const EditSelection &rEditSelection)
Definition: impedit.cxx:245
GetCursorFlags nExtraCursorFlags
Definition: impedit.hxx:283
bool bActiveDragAndDropListener
Definition: impedit.hxx:288
bool mbNegativeX
Definition: impedit.hxx:308
weld::Widget * GetPopupParent(tools::Rectangle &rRect) const
Definition: impedit.cxx:853
void ReleaseMouse()
Definition: impedit.cxx:1732
bool DoSingleLinePaste() const
Definition: impedit.hxx:439
EditEngine * pEditEngine
Definition: impedit.hxx:271
void RemoveDragAndDropListeners()
Definition: impedit.cxx:2682
void ResetOutputArea(const tools::Rectangle &rRect)
Definition: impedit.cxx:905
Pair Scroll(tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck=ScrollRangeCheck::NoNegative)
Definition: impedit.cxx:1506
tools::Rectangle GetLOKSpecialVisArea() const
Definition: impedit.cxx:2743
bool AllowPasteSpecial() const
Definition: editstt2.hxx:40
const vcl::KeyCode & GetKeyCode() const
This is meant just for Calc, where all positions in logical units (twips for LOK) are computed by doi...
Definition: impedit.hxx:213
tools::Rectangle maOutArea
Definition: impedit.hxx:246
void SetOutputArea(const tools::Rectangle &rOutputArea)
Definition: impedit.cxx:85
LOKSpecialPositioning(const ImpEditView &rImpEditView, MapUnit eUnit, const tools::Rectangle &rOutputArea, const Point &rVisDocStartPos)
Definition: impedit.cxx:67
bool IsTopToBottom() const
Definition: impedit.cxx:110
const ImpEditView & mrImpEditView
Definition: impedit.hxx:245
tools::Long GetVisDocBottom() const
Definition: impedit.hxx:230
tools::Long GetVisDocRight() const
Definition: impedit.hxx:229
Point GetRefPoint() const
Definition: impedit.cxx:176
tools::Rectangle GetVisDocArea() const
Definition: impedit.cxx:100
Point GetWindowPos(const Point &rDocPos, MapUnit eDocPosUnit) const
Definition: impedit.cxx:115
tools::Long GetVisDocTop() const
Definition: impedit.hxx:228
const tools::Rectangle & GetOutputArea() const
Definition: impedit.cxx:90
void ReInit(MapUnit eUnit, const tools::Rectangle &rOutputArea, const Point &rVisDocStartPos)
Definition: impedit.cxx:78
tools::Long GetVisDocLeft() const
Definition: impedit.hxx:227
Point convertUnit(const Point &rPos, MapUnit ePosUnit) const
Definition: impedit.cxx:160
void SetVisDocStartPos(const Point &rVisDocStartPos)
Definition: impedit.cxx:95
bool IsVertical() const
Definition: impedit.cxx:105
static css::uno::Reference< css::linguistic2::XDictionary > GetIgnoreAllList()
Definition: unolingu.cxx:511
void SetOrigin(const Point &rOrigin)
void SetScaleY(const Fraction &rScaleY)
const Fraction & GetScaleX() const
MapUnit GetMapUnit() const
void SetMapUnit(MapUnit eUnit)
const Point & GetOrigin() const
const Fraction & GetScaleY() const
void SetScaleX(const Fraction &rScaleX)
const Point & GetPosPixel() const
bool IsMiddle() const
bool IsLeft() const
MouseMiddleButtonAction GetMiddleButtonAction() const
Interface class to not depend on SfxViewShell in editeng.
Definition: outliner.hxx:372
virtual vcl::Window * GetEditWindowForActiveOLEObj() const =0
virtual void libreOfficeKitViewCallback(int nType, const OString &pPayload) const =0
virtual void NotifyOtherViews(int nType, const OString &rKey, const OString &rPayload)=0
Wrapper around SfxLokHelper::notifyOtherViews().
virtual void NotifyOtherView(OutlinerViewShell *pOtherShell, int nType, const OString &rKey, const OString &rPayload)=0
Wrapper around SfxLokHelper::notifyOtherView().
void EnableMapMode(bool bEnable=true)
tools::Long GetOutOffYPixel() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
void DrawRect(const tools::Rectangle &rRect)
const Wallpaper & GetBackground() const
void Invert(const tools::Rectangle &rRect, InvertFlags nFlags=InvertFlags::NONE)
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void SetMapMode()
void SetFillColor()
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
SAL_DLLPRIVATE void DrawOutDev(const Point &, const Size &, const Point &, const Size &, const Printer &)=delete
const MapMode & GetMapMode() const
tools::Long GetOutOffXPixel() const
const AllSettings & GetSettings() const
bool IsMapModeEnabled() const
const Color & GetFillColor() const
tools::Long GetYOffset(const ParaPortion *pPPortion) const
Definition: editdoc.cxx:757
const ParaPortion * SafeGetObject(sal_Int32 nPos) const
Definition: editdoc.cxx:783
TextPortionList & GetTextPortions()
Definition: editdoc.hxx:646
tools::Long GetHeight() const
Definition: editdoc.hxx:641
sal_Int32 GetFirstLineOffset() const
Definition: editdoc.hxx:642
constexpr tools::Long Y() const
void setX(tools::Long nX)
void Move(tools::Long nHorzMove, tools::Long nVertMove)
TOOLS_DLLPUBLIC rtl::OString toString() const
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
constexpr tools::Long getX() const
constexpr tools::Long getY() const
tools::Long Max() const
tools::Long Min() const
bool HasAnchor() const
sal_Int16 GetValue() const
static void notifyOtherView(const SfxViewShell *pThisView, SfxViewShell const *pOtherView, int nType, std::string_view rKey, const OString &rPayload)
static void notifyOtherViews(const SfxViewShell *pThisView, int nType, std::string_view rKey, const OString &rPayload)
virtual void libreOfficeKitViewCallback(int nType, const OString &pPayload) const override
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
void setWidth(tools::Long nWidth)
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
static bool GetFormatDataFlavor(SotClipboardFormatId nFormat, css::datatransfer::DataFlavor &rFlavor)
sal_Int32 GetCursorSize() const
This item stores a field (SvxFieldData).
Definition: flditem.hxx:70
const SvxFieldData * GetField() const
Definition: flditem.hxx:81
sal_Int32 FindPortion(sal_Int32 nCharPos, sal_Int32 &rPortionStart, bool bPreferStartingPortion=false) const
Definition: editdoc.cxx:448
PortionKind GetKind() const
Definition: editdoc.hxx:438
bool IsRightToLeft() const
Definition: editdoc.hxx:442
const Size & GetSize() const
Definition: editdoc.hxx:435
static bool IsEqual(const css::datatransfer::DataFlavor &rInternalFlavor, const css::datatransfer::DataFlavor &rRequestFlavor)
static bool IsCursorAtURLField(const EditView &pEditView)
static VclPtr< reference_type > Create(Arg &&... arg)
const Color & GetColor() const
void MarkWrongsInvalid()
Definition: edtspell.cxx:420
bool HasWrong(size_t nStart, size_t nEnd) const
Definition: edtspell.cxx:338
void Insert(const tools::Polygon &rPoly, sal_uInt16 nPos=POLYPOLY_APPEND)
constexpr tools::Long GetWidth() const
bool Contains(const Point &rPOINT) const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr tools::Long Top() const
constexpr Point TopLeft() const
void SetPos(const Point &rPoint)
void setWidth(tools::Long n)
constexpr void SetRight(tools::Long v)
constexpr Size GetSize() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Right() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
constexpr bool IsWidthEmpty() const
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr void SetBottom(tools::Long v)
constexpr Point BottomRight() const
constexpr Point TopRight() const
constexpr tools::Long GetHeight() const
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
constexpr bool IsHeightEmpty() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
rtl::OString toString() const
constexpr Point BottomLeft() const
const Point & GetPos() const
bool IsVisible() const
void SetPos(const Point &rNewPos)
void SetOrientation(Degree10 nOrientation=0_deg10)
void SetSize(const Size &rNewSize)
void SetDirection(CursorDirection nDirection=CursorDirection::NONE)
const Size & GetSize() const
virtual void notifyWindow(vcl::LOKWindowId nLOKWindowId, const OUString &rAction, const std::vector< LOKPayloadItem > &rPayload=std::vector< LOKPayloadItem >()) const=0
KeyFuncType GetFunction() const
void GetRegionRectangles(RectangleVector &rTarget) const
vcl::Window * GetParent() const
tools::Long GetOutOffXPixel() const
tools::Long GetOutOffYPixel() const
::OutputDevice const * GetOutDev() const
void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
bool IsAncestorOf(const vcl::Window &rWindow) const
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
CursorDirection
#define DBG_ASSERT(sCon, aError)
float v
ESelection aNewSelection(GetSelection())
#define EE_PARA_NOT_FOUND
Definition: editdata.hxx:48
EENotifyType
Definition: editdata.hxx:304
@ EE_NOTIFY_TEXTVIEWSCROLLED
The view area of the EditEngine scrolled.
Definition: editdata.hxx:321
@ EE_NOTIFY_TEXTVIEWSELECTIONCHANGED
The selection and/or the cursor position has changed.
Definition: editdata.hxx:324
@ EE_NOTIFY_PROCESSNOTIFICATIONS
The EditEngine is in a valid state again. Process pending notifications.
Definition: editdata.hxx:327
@ EE_NOTIFY_TEXTVIEWSELECTIONCHANGED_ENDD_PARA
Definition: editdata.hxx:329
#define EDITUNDO_DRAGANDDROP
Definition: editdata.hxx:76
#define EDITUNDO_CUT
Definition: editdata.hxx:70
EEAnchorMode
Definition: editdata.hxx:41
#define EDITUNDO_PASTE
Definition: editdata.hxx:71
#define EDITUNDO_DELETE
Definition: editdata.hxx:69
EESelectionMode
Definition: editdata.hxx:37
void SetFlags(EVControlBits &rBits, EVControlBits nMask, bool bOn)
Definition: editstat.hxx:91
EVControlBits
Definition: editstat.hxx:61
LOKSpecialFlags
Definition: editview.hxx:89
ScrollRangeCheck
Definition: editview.hxx:84
constexpr TypedWhichId< SvxFieldItem > EE_FEATURE_FIELD(EE_FEATURE_NOTCONV+1)
constexpr TypedWhichId< SfxInt16Item > EE_PARA_OUTLLEVEL(EE_PARA_START+11)
FilterGroup & rTarget
bool bReadOnly
static void lcl_translateTwips(const OutputDevice &rParent, OutputDevice &rChild)
Translate absolute <-> relative twips: LOK wants absolute coordinates as output and gives absolute co...
Definition: impedit.cxx:282
#define SCRLRANGE
Definition: impedit.cxx:53
static void lcl_AlignToPixel(Point &rPoint, const OutputDevice &rOutDev, short nDiffX, short nDiffY)
Definition: impedit.cxx:55
#define TRAVEL_X_DONTKNOW
Definition: impedit.hxx:85
#define LINE_SEP
Definition: impedit.hxx:88
GetCursorFlags
Definition: impedit.hxx:93
#define CURSOR_BIDILEVEL_DONTKNOW
Definition: impedit.hxx:86
Mode eMode
sal_Int64 n
KeyFuncType
LINEEND_LF
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
MapUnit
constexpr OUStringLiteral aData
NONE
bool isActive()
OString join(std::string_view rSeparator, const std::vector< OString > &rSequence)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
long Long
weld::Window * GetPopupParent(vcl::Window &rOutWin, tools::Rectangle &rRect)
Definition: editdoc.hxx:56
sal_Int32 nIndex
Definition: editdoc.hxx:58
sal_Int32 nPara
Definition: editdoc.hxx:57
sal_Int32 nStartPara
Definition: editdata.hxx:113
sal_Int32 nEndPos
Definition: editdata.hxx:116
sal_Int32 nStartPos
Definition: editdata.hxx:114
void Adjust()
Definition: editdata.hxx:184
sal_Int32 nEndPara
Definition: editdata.hxx:115
sal_Int32 nStartPara
Definition: editdata.hxx:297
sal_Int32 nEndPara
Definition: editdata.hxx:298
Left
Right
css::uno::Reference< css::datatransfer::clipboard::XClipboard > VCL_DLLPUBLIC GetSystemClipboard()
css::uno::Reference< css::datatransfer::clipboard::XClipboard > VCL_DLLPUBLIC GetSystemPrimarySelection()
signed char sal_Int8
Count
const tools::Long nScrollX
const tools::Long nScrollY