LibreOffice Module vcl (master)  1
edit.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 <vcl/builder.hxx>
21 #include <vcl/event.hxx>
22 #include <vcl/cursor.hxx>
23 #include <vcl/menu.hxx>
24 #include <vcl/edit.hxx>
25 #include <vcl/weld.hxx>
26 #include <vcl/specialchars.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/uitest/uiobject.hxx>
30 #include <vcl/ptrstyle.hxx>
31 
32 #include <window.h>
33 #include <svdata.hxx>
34 #include <strings.hrc>
35 #include <controldata.hxx>
36 
37 #include <com/sun/star/i18n/BreakIterator.hpp>
38 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
39 #include <com/sun/star/i18n/WordType.hpp>
40 #include <com/sun/star/datatransfer/XTransferable.hpp>
41 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
42 
43 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
44 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
45 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
46 
47 #include <com/sun/star/i18n/InputSequenceChecker.hpp>
48 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
49 #include <com/sun/star/i18n/ScriptType.hpp>
50 
51 #include <com/sun/star/uno/Any.hxx>
52 
54 #include <comphelper/string.hxx>
55 
56 #include <sot/exchange.hxx>
57 #include <sot/formats.hxx>
58 #include <sal/macros.h>
59 #include <sal/log.hxx>
60 
62 #include <vcl/unohelp2.hxx>
63 #include <o3tl/safeint.hxx>
64 #include <officecfg/Office/Common.hxx>
65 
66 #include <algorithm>
67 #include <memory>
68 
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::lang;
72 
73 // - Redo
74 // - if Tracking-Cancel recreate DefaultSelection
75 
77 
78 #define EDIT_ALIGN_LEFT 1
79 #define EDIT_ALIGN_CENTER 2
80 #define EDIT_ALIGN_RIGHT 3
81 
82 #define EDIT_DEL_LEFT 1
83 #define EDIT_DEL_RIGHT 2
84 
85 #define EDIT_DELMODE_SIMPLE 11
86 #define EDIT_DELMODE_RESTOFWORD 12
87 #define EDIT_DELMODE_RESTOFCONTENT 13
88 
89 struct DDInfo
90 {
93  sal_Int32 nDropPos;
96  bool bVisCursor;
98 
100  {
101  aCursor.SetStyle( CURSOR_SHADOW );
102  nDropPos = 0;
103  bStarterOfDD = false;
104  bDroppedInMe = false;
105  bVisCursor = false;
106  bIsStringSupported = false;
107  }
108 };
109 
111 {
113  std::unique_ptr<ExtTextInputAttr[]>
115  sal_Int32 nPos;
116  sal_Int32 nLen;
117  bool bCursor;
119 
120  Impl_IMEInfos(sal_Int32 nPos, const OUString& rOldTextAfterStartPos);
121 
122  void CopyAttribs(const ExtTextInputAttr* pA, sal_Int32 nL);
123  void DestroyAttribs();
124 };
125 
126 Impl_IMEInfos::Impl_IMEInfos(sal_Int32 nP, const OUString& rOldTextAfterStartPos)
127  : aOldTextAfterStartPos(rOldTextAfterStartPos),
128  nPos(nP),
129  nLen(0),
130  bCursor(true),
131  bWasCursorOverwrite(false)
132 {
133 }
134 
135 void Impl_IMEInfos::CopyAttribs(const ExtTextInputAttr* pA, sal_Int32 nL)
136 {
137  nLen = nL;
138  pAttribs.reset(new ExtTextInputAttr[ nL ]);
139  memcpy( pAttribs.get(), pA, nL*sizeof(ExtTextInputAttr) );
140 }
141 
143 {
144  pAttribs.reset();
145  nLen = 0;
146 }
147 
149  : Control( nType )
150 {
152 }
153 
154 Edit::Edit( vcl::Window* pParent, WinBits nStyle )
155  : Control( WindowType::EDIT )
156 {
158  ImplInit( pParent, nStyle );
159 }
160 
161 void Edit::SetWidthInChars(sal_Int32 nWidthInChars)
162 {
163  if (mnWidthInChars != nWidthInChars)
164  {
165  mnWidthInChars = nWidthInChars;
166  queue_resize();
167  }
168 }
169 
170 void Edit::setMaxWidthChars(sal_Int32 nWidth)
171 {
172  if (nWidth != mnMaxWidthChars)
173  {
174  mnMaxWidthChars = nWidth;
175  queue_resize();
176  }
177 }
178 
179 bool Edit::set_property(const OString &rKey, const OUString &rValue)
180 {
181  if (rKey == "width-chars")
182  SetWidthInChars(rValue.toInt32());
183  else if (rKey == "max-width-chars")
184  setMaxWidthChars(rValue.toInt32());
185  else if (rKey == "max-length")
186  {
187  sal_Int32 nTextLen = rValue.toInt32();
188  SetMaxTextLen(nTextLen == 0 ? EDIT_NOLIMIT : nTextLen);
189  }
190  else if (rKey == "editable")
191  {
192  SetReadOnly(!toBool(rValue));
193  }
194  else if (rKey == "overwrite-mode")
195  {
196  SetInsertMode(!toBool(rValue));
197  }
198  else if (rKey == "visibility")
199  {
200  mbPassword = false;
201  if (!toBool(rValue))
202  mbPassword = true;
203  }
204  else if (rKey == "placeholder-text")
205  SetPlaceholderText(rValue);
206  else
207  return Control::set_property(rKey, rValue);
208  return true;
209 }
210 
212 {
213  disposeOnce();
214 }
215 
217 {
218  mpUIBuilder.reset();
219  mpDDInfo.reset();
220 
221  vcl::Cursor* pCursor = GetCursor();
222  if ( pCursor )
223  {
224  SetCursor( nullptr );
225  delete pCursor;
226  }
227 
228  mpIMEInfos.reset();
229 
230  if ( mxDnDListener.is() )
231  {
232  if ( GetDragGestureRecognizer().is() )
233  {
234  uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
235  GetDragGestureRecognizer()->removeDragGestureListener( xDGL );
236  }
237  if ( GetDropTarget().is() )
238  {
239  uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( mxDnDListener, uno::UNO_QUERY );
240  GetDropTarget()->removeDropTargetListener( xDTL );
241  }
242 
243  mxDnDListener->disposing( lang::EventObject() ); // #95154# #96585# Empty Source means it's the Client
244  mxDnDListener.clear();
245  }
246 
247  SetType(WindowType::WINDOW);
248 
251 }
252 
254 {
256  mpFilterText = nullptr;
257  mnXOffset = 0;
260  mnWidthInChars = -1;
261  mnMaxWidthChars = -1;
262  mbModified = false;
263  mbInternModified = false;
264  mbReadOnly = false;
265  mbInsertMode = true;
266  mbClickedInSelection = false;
267  mbActivePopup = false;
268  mbIsSubEdit = false;
269  mbForceControlBackground = false;
270  mbPassword = false;
271  mpDDInfo = nullptr;
272  mpIMEInfos = nullptr;
273  mcEchoChar = 0;
274 
275  // no default mirroring for Edit controls
276  // note: controls that use a subedit will revert this (SpinField, ComboBox)
277  EnableRTL( false );
278 
280  mxDnDListener = pDnDWrapper;
281 }
282 
283 bool Edit::ImplUseNativeBorder(vcl::RenderContext const & rRenderContext, WinBits nStyle)
284 {
285  bool bRet = rRenderContext.IsNativeControlSupported(ImplGetNativeControlType(),
287  && ((nStyle & WB_BORDER) && !(nStyle & WB_NOBORDER));
288  if (!bRet && mbIsSubEdit)
289  {
290  vcl::Window* pWindow = GetParent();
291  nStyle = pWindow->GetStyle();
294  && ((nStyle & WB_BORDER) && !(nStyle & WB_NOBORDER));
295  }
296  return bRet;
297 }
298 
299 void Edit::ImplInit(vcl::Window* pParent, WinBits nStyle)
300 {
301  nStyle = ImplInitStyle(nStyle);
302 
303  if (!(nStyle & (WB_CENTER | WB_RIGHT)))
304  nStyle |= WB_LEFT;
305 
306  Control::ImplInit(pParent, nStyle, nullptr);
307 
308  mbReadOnly = (nStyle & WB_READONLY) != 0;
309 
311 
312  // hack: right align until keyinput and cursor travelling works
313  if( IsRTLEnabled() )
315 
316  if ( nStyle & WB_RIGHT )
318  else if ( nStyle & WB_CENTER )
320 
321  SetCursor( new vcl::Cursor );
322 
324  ApplySettings(*this);
325 
326  uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
327  uno::Reference< datatransfer::dnd::XDragGestureRecognizer > xDGR = GetDragGestureRecognizer();
328  if ( xDGR.is() )
329  {
330  xDGR->addDragGestureListener( xDGL );
331  uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( mxDnDListener, uno::UNO_QUERY );
332  GetDropTarget()->addDropTargetListener( xDTL );
333  GetDropTarget()->setActive( true );
334  GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
335  }
336 }
337 
339 {
340  if ( !(nStyle & WB_NOTABSTOP) )
341  nStyle |= WB_TABSTOP;
342  if ( !(nStyle & WB_NOGROUP) )
343  nStyle |= WB_GROUP;
344 
345  return nStyle;
346 }
347 
348 bool Edit::IsCharInput( const KeyEvent& rKeyEvent )
349 {
350  // In the future we must use new Unicode functions for this
351  sal_Unicode cCharCode = rKeyEvent.GetCharCode();
352  return ((cCharCode >= 32) && (cCharCode != 127) &&
353  !rKeyEvent.GetKeyCode().IsMod3() &&
354  !rKeyEvent.GetKeyCode().IsMod2() &&
355  !rKeyEvent.GetKeyCode().IsMod1() );
356 }
357 
359 {
360  mbModified = true;
361  Modify();
362 }
363 
365 {
366  Control::ApplySettings(rRenderContext);
367 
368  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
369 
370  const vcl::Font& aFont = rStyleSettings.GetFieldFont();
371  ApplyControlFont(rRenderContext, aFont);
372 
374 
375  Color aTextColor = rStyleSettings.GetFieldTextColor();
376  ApplyControlForeground(rRenderContext, aTextColor);
377 
378  if (ImplUseNativeBorder(rRenderContext, GetStyle()))
379  {
380  // Transparent background
381  rRenderContext.SetBackground();
382  rRenderContext.SetFillColor();
383  }
384  else if (IsControlBackground())
385  {
386  rRenderContext.SetBackground(GetControlBackground());
387  rRenderContext.SetFillColor(GetControlBackground());
388  }
389  else
390  {
391  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
392  rRenderContext.SetFillColor(rStyleSettings.GetFieldColor());
393  }
394 }
395 
397 {
398  // MT 09/2002: nExtraOffsetX should become a member, instead of checking every time,
399  // but I need an incompatible update for this...
400  // #94095# Use extra offset only when edit has a border
401  long nExtraOffset = 0;
402  if( ( GetStyle() & WB_BORDER ) || ( mbIsSubEdit && ( GetParent()->GetStyle() & WB_BORDER ) ) )
403  nExtraOffset = 2;
404 
405  return nExtraOffset;
406 }
407 
409 {
410  long nExtraOffset = 0;
412  if (eCtrlType != ControlType::EditboxNoBorder)
413  {
414  // add some space between text entry and border
415  nExtraOffset = 2;
416  }
417  return nExtraOffset;
418 }
419 
420 OUString Edit::ImplGetText() const
421 {
422  if ( mcEchoChar || mbPassword )
423  {
424  sal_Unicode cEchoChar;
425  if ( mcEchoChar )
426  cEchoChar = mcEchoChar;
427  else
428  cEchoChar = u'\x2022';
429  OUStringBuffer aText;
430  comphelper::string::padToLength(aText, maText.getLength(), cEchoChar);
431  return aText.makeStringAndClear();
432  }
433  else
434  return maText.toString();
435 }
436 
438 {
439  if( IsPaintTransparent() )
440  {
441  Invalidate();
442  // FIXME: this is currently only on macOS
443  if( ImplGetSVData()->maNWFData.mbNoFocusRects )
445  }
446  else
447  Invalidate();
448 }
449 
451 {
452  if ( GetStyle() & WB_TOP )
453  return ImplGetExtraXOffset();
454  else if ( GetStyle() & WB_BOTTOM )
456  return ( GetOutputSizePixel().Height() - GetTextHeight() ) / 2;
457 }
458 
459 void Edit::ImplRepaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRectangle)
460 {
461  if (!IsReallyVisible())
462  return;
463 
464  ApplySettings(rRenderContext);
465 
466  const OUString aText = ImplGetText();
467  const sal_Int32 nLen = aText.getLength();
468 
469  long nDXBuffer[256];
470  std::unique_ptr<long[]> pDXBuffer;
471  long* pDX = nDXBuffer;
472 
473  if (nLen)
474  {
475  if (o3tl::make_unsigned(2 * nLen) > SAL_N_ELEMENTS(nDXBuffer))
476  {
477  pDXBuffer.reset(new long[2 * (nLen + 1)]);
478  pDX = pDXBuffer.get();
479  }
480 
481  GetCaretPositions(aText, pDX, 0, nLen);
482  }
483 
484  long nTH = GetTextHeight();
486 
487  vcl::Cursor* pCursor = GetCursor();
488  bool bVisCursor = pCursor && pCursor->IsVisible();
489  if (pCursor)
490  pCursor->Hide();
491 
492  ImplClearBackground(rRenderContext, rRectangle, 0, GetOutputSizePixel().Width()-1);
493 
494  bool bPaintPlaceholderText = aText.isEmpty() && !maPlaceholderText.isEmpty();
495 
496  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
497 
498  if (!IsEnabled() || bPaintPlaceholderText)
499  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
500 
501  // Set background color of the normal text
503  {
504  // check if we need to set ControlBackground even in NWF case
506  rRenderContext.SetLineColor();
507  rRenderContext.SetFillColor(GetControlBackground());
509  rRenderContext.Pop();
510 
511  rRenderContext.SetTextFillColor(GetControlBackground());
512  }
513  else if (IsPaintTransparent() || ImplUseNativeBorder(rRenderContext, GetStyle()))
514  rRenderContext.SetTextFillColor();
515  else
516  rRenderContext.SetTextFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
517 
518  ImplPaintBorder(rRenderContext);
519 
520  bool bDrawSelection = maSelection.Len() && (HasFocus() || (GetStyle() & WB_NOHIDESELECTION) || mbActivePopup);
521 
522  aPos.setX( mnXOffset + ImplGetExtraXOffset() );
523  if (bPaintPlaceholderText)
524  {
525  rRenderContext.DrawText(aPos, maPlaceholderText);
526  }
527  else if (!bDrawSelection && !mpIMEInfos)
528  {
529  rRenderContext.DrawText(aPos, aText, 0, nLen);
530  }
531  else
532  {
533  // save graphics state
534  rRenderContext.Push();
535  // first calculate highlighted and non highlighted clip regions
536  vcl::Region aHighlightClipRegion;
537  vcl::Region aNormalClipRegion;
538  Selection aTmpSel(maSelection);
539  aTmpSel.Justify();
540  // selection is highlighted
541  for(sal_Int32 i = 0; i < nLen; ++i)
542  {
543  tools::Rectangle aRect(aPos, Size(10, nTH));
544  aRect.SetLeft( pDX[2 * i] + mnXOffset + ImplGetExtraXOffset() );
545  aRect.SetRight( pDX[2 * i + 1] + mnXOffset + ImplGetExtraXOffset() );
546  aRect.Justify();
547  bool bHighlight = false;
548  if (i >= aTmpSel.Min() && i < aTmpSel.Max())
549  bHighlight = true;
550 
551  if (mpIMEInfos && mpIMEInfos->pAttribs &&
552  i >= mpIMEInfos->nPos && i < (mpIMEInfos->nPos+mpIMEInfos->nLen) &&
553  (mpIMEInfos->pAttribs[i - mpIMEInfos->nPos] & ExtTextInputAttr::Highlight))
554  {
555  bHighlight = true;
556  }
557 
558  if (bHighlight)
559  aHighlightClipRegion.Union(aRect);
560  else
561  aNormalClipRegion.Union(aRect);
562  }
563  // draw normal text
564  Color aNormalTextColor = rRenderContext.GetTextColor();
565  rRenderContext.SetClipRegion(aNormalClipRegion);
566 
567  if (IsPaintTransparent())
568  rRenderContext.SetTextFillColor();
569  else
570  {
571  // Set background color when part of the text is selected
572  if (ImplUseNativeBorder(rRenderContext, GetStyle()))
573  {
575  rRenderContext.SetTextFillColor(GetControlBackground());
576  else
577  rRenderContext.SetTextFillColor();
578  }
579  else
580  {
581  rRenderContext.SetTextFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
582  }
583  }
584  rRenderContext.DrawText(aPos, aText, 0, nLen);
585 
586  // draw highlighted text
587  rRenderContext.SetClipRegion(aHighlightClipRegion);
588  rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
589  rRenderContext.SetTextFillColor(rStyleSettings.GetHighlightColor());
590  rRenderContext.DrawText(aPos, aText, 0, nLen);
591 
592  // if IME info exists loop over portions and output different font attributes
593  if (mpIMEInfos && mpIMEInfos->pAttribs)
594  {
595  for(int n = 0; n < 2; n++)
596  {
597  vcl::Region aRegion;
598  if (n == 0)
599  {
600  rRenderContext.SetTextColor(aNormalTextColor);
601  if (IsPaintTransparent())
602  rRenderContext.SetTextFillColor();
603  else
604  rRenderContext.SetTextFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
605  aRegion = aNormalClipRegion;
606  }
607  else
608  {
609  rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
610  rRenderContext.SetTextFillColor(rStyleSettings.GetHighlightColor());
611  aRegion = aHighlightClipRegion;
612  }
613 
614  for(int i = 0; i < mpIMEInfos->nLen; )
615  {
616  ExtTextInputAttr nAttr = mpIMEInfos->pAttribs[i];
617  vcl::Region aClip;
618  int nIndex = i;
619  while (nIndex < mpIMEInfos->nLen && mpIMEInfos->pAttribs[nIndex] == nAttr) // #112631# check nIndex before using it
620  {
621  tools::Rectangle aRect( aPos, Size( 10, nTH ) );
622  aRect.SetLeft( pDX[2 * (nIndex + mpIMEInfos->nPos)] + mnXOffset + ImplGetExtraXOffset() );
623  aRect.SetRight( pDX[2 * (nIndex + mpIMEInfos->nPos) + 1] + mnXOffset + ImplGetExtraXOffset() );
624  aRect.Justify();
625  aClip.Union(aRect);
626  nIndex++;
627  }
628  i = nIndex;
629  aClip.Intersect(aRegion);
630  if (!aClip.IsEmpty() && nAttr != ExtTextInputAttr::NONE)
631  {
632  vcl::Font aFont = rRenderContext.GetFont();
633  if (nAttr & ExtTextInputAttr::Underline)
635  else if (nAttr & ExtTextInputAttr::BoldUnderline)
637  else if (nAttr & ExtTextInputAttr::DottedUnderline)
639  else if (nAttr & ExtTextInputAttr::DashDotUnderline)
641  else if (nAttr & ExtTextInputAttr::GrayWaveline)
642  {
644  rRenderContext.SetTextLineColor(COL_LIGHTGRAY);
645  }
646  rRenderContext.SetFont(aFont);
647 
648  if (nAttr & ExtTextInputAttr::RedText)
649  rRenderContext.SetTextColor(COL_RED);
650  else if (nAttr & ExtTextInputAttr::HalfToneText)
651  rRenderContext.SetTextColor(COL_LIGHTGRAY);
652 
653  rRenderContext.SetClipRegion(aClip);
654  rRenderContext.DrawText(aPos, aText, 0, nLen);
655  }
656  }
657  }
658  }
659 
660  // restore graphics state
661  rRenderContext.Pop();
662  }
663 
664  if (bVisCursor && (!mpIMEInfos || mpIMEInfos->bCursor))
665  pCursor->Show();
666 }
667 
668 void Edit::ImplDelete( const Selection& rSelection, sal_uInt8 nDirection, sal_uInt8 nMode )
669 {
670  const sal_Int32 nTextLen = ImplGetText().getLength();
671 
672  // deleting possible?
673  if ( !rSelection.Len() &&
674  (((rSelection.Min() == 0) && (nDirection == EDIT_DEL_LEFT)) ||
675  ((rSelection.Max() == nTextLen) && (nDirection == EDIT_DEL_RIGHT))) )
676  return;
677 
679 
680  Selection aSelection( rSelection );
681  aSelection.Justify();
682 
683  if ( !aSelection.Len() )
684  {
685  uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
686  if ( nDirection == EDIT_DEL_LEFT )
687  {
688  if ( nMode == EDIT_DELMODE_RESTOFWORD )
689  {
690  i18n::Boundary aBoundary = xBI->getWordBoundary( maText.toString(), aSelection.Min(),
691  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, true );
692  auto startPos = aBoundary.startPos;
693  if ( startPos == aSelection.Min() )
694  {
695  aBoundary = xBI->previousWord( maText.toString(), aSelection.Min(),
696  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
697  startPos = std::max(aBoundary.startPos, sal_Int32(0));
698  }
699  aSelection.Min() = startPos;
700  }
701  else if ( nMode == EDIT_DELMODE_RESTOFCONTENT )
702  {
703  aSelection.Min() = 0;
704  }
705  else
706  {
707  sal_Int32 nCount = 1;
708  aSelection.Min() = xBI->previousCharacters( maText.toString(), aSelection.Min(),
709  GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
710  }
711  }
712  else
713  {
714  if ( nMode == EDIT_DELMODE_RESTOFWORD )
715  {
716  i18n::Boundary aBoundary = xBI->nextWord( maText.toString(), aSelection.Max(),
717  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
718  aSelection.Max() = aBoundary.startPos;
719  }
720  else if ( nMode == EDIT_DELMODE_RESTOFCONTENT )
721  {
722  aSelection.Max() = nTextLen;
723  }
724  else
725  {
726  sal_Int32 nCount = 1;
727  aSelection.Max() = xBI->nextCharacters( maText.toString(), aSelection.Max(),
728  GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
729  }
730  }
731  }
732 
733  const auto nSelectionMin = aSelection.Min();
734  maText.remove( nSelectionMin, aSelection.Len() );
735  maSelection.Min() = nSelectionMin;
736  maSelection.Max() = nSelectionMin;
738  mbInternModified = true;
739 }
740 
741 OUString Edit::ImplGetValidString( const OUString& rString )
742 {
743  OUString aValidString = rString.replaceAll("\n", "").replaceAll("\r", "");
744  aValidString = aValidString.replace('\t', ' ');
745  return aValidString;
746 }
747 
748 uno::Reference <i18n::XBreakIterator> const& Edit::ImplGetBreakIterator()
749 {
750  if (!mxBreakIterator)
751  mxBreakIterator = i18n::BreakIterator::create(::comphelper::getProcessComponentContext());
752  return mxBreakIterator;
753 }
754 
755 uno::Reference <i18n::XExtendedInputSequenceChecker> const& Edit::ImplGetInputSequenceChecker()
756 {
757  if (!mxISC.is())
758  mxISC = i18n::InputSequenceChecker::create(::comphelper::getProcessComponentContext());
759  return mxISC;
760 }
761 
763 {
764  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, VclMessageType::Warning,
765  VclButtonsType::Ok, VclResId(SV_EDIT_WARNING_STR)));
766  xBox->run();
767 }
768 
769 bool Edit::ImplTruncateToMaxLen( OUString& rStr, sal_Int32 nSelectionLen ) const
770 {
771  bool bWasTruncated = false;
772  if (maText.getLength() - nSelectionLen > mnMaxTextLen - rStr.getLength())
773  {
774  sal_Int32 nErasePos = mnMaxTextLen - maText.getLength() + nSelectionLen;
775  rStr = rStr.copy( 0, nErasePos );
776  bWasTruncated = true;
777  }
778  return bWasTruncated;
779 }
780 
781 void Edit::ImplInsertText( const OUString& rStr, const Selection* pNewSel, bool bIsUserInput )
782 {
783  Selection aSelection( maSelection );
784  aSelection.Justify();
785 
786  OUString aNewText( ImplGetValidString( rStr ) );
787 
788  // as below, if there's no selection, but we're in overwrite mode and not beyond
789  // the end of the existing text then that's like a selection of 1
790  auto nSelectionLen = aSelection.Len();
791  if (!nSelectionLen && !mbInsertMode && aSelection.Max() < maText.getLength())
792  nSelectionLen = 1;
793  ImplTruncateToMaxLen( aNewText, nSelectionLen );
794 
796 
797  if ( aSelection.Len() )
798  maText.remove( aSelection.Min(), aSelection.Len() );
799  else if (!mbInsertMode && aSelection.Max() < maText.getLength())
800  maText.remove( aSelection.Max(), 1 );
801 
802  // take care of input-sequence-checking now
803  if (bIsUserInput && !rStr.isEmpty())
804  {
805  SAL_WARN_IF( rStr.getLength() != 1, "vcl", "unexpected string length. User input is expected to provide 1 char only!" );
806 
807  // determine if input-sequence-checking should be applied or not
808 
809  uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
810  bool bIsInputSequenceChecking = rStr.getLength() == 1 &&
811  officecfg::Office::Common::I18N::CTL::CTLFont::get() &&
812  officecfg::Office::Common::I18N::CTL::CTLSequenceChecking::get() &&
813  aSelection.Min() > 0 && /* first char needs not to be checked */
814  xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( rStr, 0 );
815 
816  if (bIsInputSequenceChecking)
817  {
818  uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = ImplGetInputSequenceChecker();
819  if (xISC.is())
820  {
821  sal_Unicode cChar = rStr[0];
822  sal_Int32 nTmpPos = aSelection.Min();
823  sal_Int16 nCheckMode = officecfg::Office::Common::I18N::CTL::CTLSequenceCheckingRestricted::get()?
824  i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
825 
826  // the text that needs to be checked is only the one
827  // before the current cursor position
828  const OUString aOldText( maText.getStr(), nTmpPos);
829  OUString aTmpText( aOldText );
830  if (officecfg::Office::Common::I18N::CTL::CTLSequenceCheckingTypeAndReplace::get())
831  {
832  xISC->correctInputSequence( aTmpText, nTmpPos - 1, cChar, nCheckMode );
833 
834  // find position of first character that has changed
835  sal_Int32 nOldLen = aOldText.getLength();
836  sal_Int32 nTmpLen = aTmpText.getLength();
837  const sal_Unicode *pOldTxt = aOldText.getStr();
838  const sal_Unicode *pTmpTxt = aTmpText.getStr();
839  sal_Int32 nChgPos = 0;
840  while ( nChgPos < nOldLen && nChgPos < nTmpLen &&
841  pOldTxt[nChgPos] == pTmpTxt[nChgPos] )
842  ++nChgPos;
843 
844  const OUString aChgText( aTmpText.copy( nChgPos ) );
845 
846  // remove text from first pos to be changed to current pos
847  maText.remove( nChgPos, nTmpPos - nChgPos );
848 
849  if (!aChgText.isEmpty())
850  {
851  aNewText = aChgText;
852  aSelection.Min() = nChgPos; // position for new text to be inserted
853  }
854  else
855  aNewText.clear();
856  }
857  else
858  {
859  // should the character be ignored (i.e. not get inserted) ?
860  if (!xISC->checkInputSequence( aOldText, nTmpPos - 1, cChar, nCheckMode ))
861  aNewText.clear();
862  }
863  }
864  }
865 
866  // at this point now we will insert the non-empty text 'normally' some lines below...
867  }
868 
869  if ( !aNewText.isEmpty() )
870  maText.insert( aSelection.Min(), aNewText );
871 
872  if ( !pNewSel )
873  {
874  maSelection.Min() = aSelection.Min() + aNewText.getLength();
876  }
877  else
878  {
879  maSelection = *pNewSel;
880  if ( maSelection.Min() > maText.getLength() )
881  maSelection.Min() = maText.getLength();
882  if ( maSelection.Max() > maText.getLength() )
883  maSelection.Max() = maText.getLength();
884  }
885 
887  mbInternModified = true;
888 }
889 
890 void Edit::ImplSetText( const OUString& rText, const Selection* pNewSelection )
891 {
892  // we delete text by "selecting" the old text completely then calling InsertText; this is flicker free
893  if ( ( rText.getLength() <= mnMaxTextLen ) &&
894  ( (rText != maText.getStr()) || (pNewSelection && (*pNewSelection != maSelection)) ) )
895  {
897  maSelection.Min() = 0;
898  maSelection.Max() = maText.getLength();
899  if ( mnXOffset || HasPaintEvent() )
900  {
901  mnXOffset = 0;
902  maText = ImplGetValidString( rText );
903 
904  // #i54929# recalculate mnXOffset before ImplSetSelection,
905  // else cursor ends up in wrong position
906  ImplAlign();
907 
908  if ( pNewSelection )
909  ImplSetSelection( *pNewSelection, false );
910 
911  if ( mnXOffset && !pNewSelection )
912  maSelection.Max() = 0;
913 
914  Invalidate();
915  }
916  else
917  ImplInsertText( rText, pNewSelection );
918 
920  }
921 }
922 
924 {
926  const vcl::Window* pControl = mbIsSubEdit ? GetParent() : this;
927 
928  switch (pControl->GetType())
929  {
930  case WindowType::COMBOBOX:
931  case WindowType::PATTERNBOX:
932  case WindowType::NUMERICBOX:
933  case WindowType::METRICBOX:
934  case WindowType::CURRENCYBOX:
935  case WindowType::DATEBOX:
936  case WindowType::TIMEBOX:
937  case WindowType::LONGCURRENCYBOX:
938  nCtrl = ControlType::Combobox;
939  break;
940 
941  case WindowType::MULTILINEEDIT:
942  if ( GetWindow( GetWindowType::Border ) != this )
944  else
946  break;
947 
948  case WindowType::EDIT:
949  case WindowType::PATTERNFIELD:
950  case WindowType::METRICFIELD:
951  case WindowType::CURRENCYFIELD:
952  case WindowType::DATEFIELD:
953  case WindowType::TIMEFIELD:
954  case WindowType::SPINFIELD:
955  case WindowType::FORMATTEDFIELD:
956  if (pControl->GetStyle() & WB_SPIN)
957  nCtrl = ControlType::Spinbox;
958  else
959  {
960  if (GetWindow(GetWindowType::Border) != this)
961  nCtrl = ControlType::Editbox;
962  else
964  }
965  break;
966 
967  default:
968  nCtrl = ControlType::Editbox;
969  }
970  return nCtrl;
971 }
972 
973 void Edit::ImplClearBackground(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRectangle, long nXStart, long nXEnd )
974 {
975  /*
976  * note: at this point the cursor must be switched off already
977  */
979  aRect.SetLeft( nXStart );
980  aRect.SetRight( nXEnd );
981 
982  if( !(ImplUseNativeBorder(rRenderContext, GetStyle()) || IsPaintTransparent()))
983  rRenderContext.Erase(aRect);
984  else if (SupportsDoubleBuffering() && mbIsSubEdit)
985  {
986  // ImplPaintBorder() is a NOP, we have a native border, and this is a sub-edit of a control.
987  // That means we have to draw the parent native widget to paint the edit area to clear our background.
989  GetParent()->Paint(rRenderContext, rRectangle);
990  }
991 }
992 
993 void Edit::ImplPaintBorder(vcl::RenderContext const & rRenderContext)
994 {
995  // this is not needed when double-buffering
997  return;
998 
999  if (ImplUseNativeBorder(rRenderContext, GetStyle()) || IsPaintTransparent())
1000  {
1001  // draw the inner part by painting the whole control using its border window
1003  if (pBorder == this)
1004  {
1005  // we have no border, use parent
1006  vcl::Window* pControl = mbIsSubEdit ? GetParent() : this;
1007  pBorder = pControl->GetWindow(GetWindowType::Border);
1008  if (pBorder == this)
1009  pBorder = GetParent();
1010  }
1011 
1012  if (pBorder)
1013  {
1014  // set proper clipping region to not overdraw the whole control
1015  vcl::Region aClipRgn = GetPaintRegion();
1016  if (!aClipRgn.IsNull())
1017  {
1018  // transform clipping region to border window's coordinate system
1019  if (IsRTLEnabled() != pBorder->IsRTLEnabled() && AllSettings::GetLayoutRTL())
1020  {
1021  // need to mirror in case border is not RTL but edit is (or vice versa)
1022 
1023  // mirror
1024  tools::Rectangle aBounds(aClipRgn.GetBoundRect());
1025  int xNew = GetOutputSizePixel().Width() - aBounds.GetWidth() - aBounds.Left();
1026  aClipRgn.Move(xNew - aBounds.Left(), 0);
1027 
1028  // move offset of border window
1029  Point aBorderOffs = pBorder->ScreenToOutputPixel(OutputToScreenPixel(Point()));
1030  aClipRgn.Move(aBorderOffs.X(), aBorderOffs.Y());
1031  }
1032  else
1033  {
1034  // normal case
1035  Point aBorderOffs = pBorder->ScreenToOutputPixel(OutputToScreenPixel(Point()));
1036  aClipRgn.Move(aBorderOffs.X(), aBorderOffs.Y());
1037  }
1038 
1039  vcl::Region oldRgn(pBorder->GetClipRegion());
1040  pBorder->SetClipRegion(aClipRgn);
1041 
1042  pBorder->Paint(*pBorder, tools::Rectangle());
1043 
1044  pBorder->SetClipRegion(oldRgn);
1045  }
1046  else
1047  {
1048  pBorder->Paint(*pBorder, tools::Rectangle());
1049  }
1050  }
1051  }
1052 }
1053 
1054 void Edit::ImplShowCursor( bool bOnlyIfVisible )
1055 {
1056  if ( !IsUpdateMode() || ( bOnlyIfVisible && !IsReallyVisible() ) )
1057  return;
1058 
1059  vcl::Cursor* pCursor = GetCursor();
1060  OUString aText = ImplGetText();
1061 
1062  long nTextPos = 0;
1063 
1064  long nDXBuffer[256];
1065  std::unique_ptr<long[]> pDXBuffer;
1066  long* pDX = nDXBuffer;
1067 
1068  if( !aText.isEmpty() )
1069  {
1070  if( o3tl::make_unsigned(2*aText.getLength()) > SAL_N_ELEMENTS(nDXBuffer) )
1071  {
1072  pDXBuffer.reset(new long[2*(aText.getLength()+1)]);
1073  pDX = pDXBuffer.get();
1074  }
1075 
1076  GetCaretPositions( aText, pDX, 0, aText.getLength() );
1077 
1078  if( maSelection.Max() < aText.getLength() )
1079  nTextPos = pDX[ 2*maSelection.Max() ];
1080  else
1081  nTextPos = pDX[ 2*aText.getLength()-1 ];
1082  }
1083 
1084  long nCursorWidth = 0;
1085  if ( !mbInsertMode && !maSelection.Len() && (maSelection.Max() < aText.getLength()) )
1086  nCursorWidth = GetTextWidth(aText, maSelection.Max(), 1);
1087  long nCursorPosX = nTextPos + mnXOffset + ImplGetExtraXOffset();
1088 
1089  // cursor should land in visible area
1090  const Size aOutSize = GetOutputSizePixel();
1091  if ( (nCursorPosX < 0) || (nCursorPosX >= aOutSize.Width()) )
1092  {
1093  long nOldXOffset = mnXOffset;
1094 
1095  if ( nCursorPosX < 0 )
1096  {
1097  mnXOffset = - nTextPos;
1098  long nMaxX = 0;
1099  mnXOffset += aOutSize.Width() / 5;
1100  if ( mnXOffset > nMaxX )
1101  mnXOffset = nMaxX;
1102  }
1103  else
1104  {
1105  mnXOffset = (aOutSize.Width()-ImplGetExtraXOffset()) - nTextPos;
1106  // Something more?
1107  if ( (aOutSize.Width()-ImplGetExtraXOffset()) < nTextPos )
1108  {
1109  long nMaxNegX = (aOutSize.Width()-ImplGetExtraXOffset()) - GetTextWidth( aText );
1110  mnXOffset -= aOutSize.Width() / 5;
1111  if ( mnXOffset < nMaxNegX ) // both negative...
1112  mnXOffset = nMaxNegX;
1113  }
1114  }
1115 
1116  nCursorPosX = nTextPos + mnXOffset + ImplGetExtraXOffset();
1117  if ( nCursorPosX == aOutSize.Width() ) // then invisible...
1118  nCursorPosX--;
1119 
1120  if ( mnXOffset != nOldXOffset )
1122  }
1123 
1124  const long nTextHeight = GetTextHeight();
1125  const long nCursorPosY = ImplGetTextYPosition();
1126  if (pCursor)
1127  {
1128  pCursor->SetPos( Point( nCursorPosX, nCursorPosY ) );
1129  pCursor->SetSize( Size( nCursorWidth, nTextHeight ) );
1130  pCursor->Show();
1131  }
1132 }
1133 
1135 {
1136  if (mnAlign == EDIT_ALIGN_LEFT && !mnXOffset)
1137  {
1138  // short circuit common case and avoid slow GetTextWidth() calc
1139  return;
1140  }
1141 
1142  long nTextWidth = GetTextWidth( ImplGetText() );
1143  long nOutWidth = GetOutputSizePixel().Width();
1144 
1145  if ( mnAlign == EDIT_ALIGN_LEFT )
1146  {
1147  if (nTextWidth < nOutWidth)
1148  mnXOffset = 0;
1149  }
1150  else if ( mnAlign == EDIT_ALIGN_RIGHT )
1151  {
1152  long nMinXOffset = nOutWidth - nTextWidth - 1 - ImplGetExtraXOffset();
1153  bool bRTL = IsRTLEnabled();
1154  if( mbIsSubEdit && GetParent() )
1155  bRTL = GetParent()->IsRTLEnabled();
1156  if( bRTL )
1157  {
1158  if( nTextWidth < nOutWidth )
1159  mnXOffset = nMinXOffset;
1160  }
1161  else
1162  {
1163  if( nTextWidth < nOutWidth )
1164  mnXOffset = nMinXOffset;
1165  else if ( mnXOffset < nMinXOffset )
1166  mnXOffset = nMinXOffset;
1167  }
1168  }
1169  else if( mnAlign == EDIT_ALIGN_CENTER )
1170  {
1171  // would be nicer with check while scrolling but then it's not centred in scrolled state
1172  mnXOffset = (nOutWidth - nTextWidth) / 2;
1173  }
1174 }
1175 
1177 {
1178  ImplAlign();
1180  ImplShowCursor();
1181 }
1182 
1183 sal_Int32 Edit::ImplGetCharPos( const Point& rWindowPos ) const
1184 {
1185  sal_Int32 nIndex = EDIT_NOLIMIT;
1186  OUString aText = ImplGetText();
1187 
1188  long nDXBuffer[256];
1189  std::unique_ptr<long[]> pDXBuffer;
1190  long* pDX = nDXBuffer;
1191  if( o3tl::make_unsigned(2*aText.getLength()) > SAL_N_ELEMENTS(nDXBuffer) )
1192  {
1193  pDXBuffer.reset(new long[2*(aText.getLength()+1)]);
1194  pDX = pDXBuffer.get();
1195  }
1196 
1197  GetCaretPositions( aText, pDX, 0, aText.getLength() );
1198  long nX = rWindowPos.X() - mnXOffset - ImplGetExtraXOffset();
1199  for (sal_Int32 i = 0; i < aText.getLength(); aText.iterateCodePoints(&i))
1200  {
1201  if( (pDX[2*i] >= nX && pDX[2*i+1] <= nX) ||
1202  (pDX[2*i+1] >= nX && pDX[2*i] <= nX))
1203  {
1204  nIndex = i;
1205  if( pDX[2*i] < pDX[2*i+1] )
1206  {
1207  if( nX > (pDX[2*i]+pDX[2*i+1])/2 )
1208  aText.iterateCodePoints(&nIndex);
1209  }
1210  else
1211  {
1212  if( nX < (pDX[2*i]+pDX[2*i+1])/2 )
1213  aText.iterateCodePoints(&nIndex);
1214  }
1215  break;
1216  }
1217  }
1218  if( nIndex == EDIT_NOLIMIT )
1219  {
1220  nIndex = 0;
1221  sal_Int32 nFinalIndex = 0;
1222  long nDiff = std::abs( pDX[0]-nX );
1223  sal_Int32 i = 0;
1224  if (!aText.isEmpty())
1225  {
1226  aText.iterateCodePoints(&i); //skip the first character
1227  }
1228  while (i < aText.getLength())
1229  {
1230  long nNewDiff = std::abs( pDX[2*i]-nX );
1231 
1232  if( nNewDiff < nDiff )
1233  {
1234  nIndex = i;
1235  nDiff = nNewDiff;
1236  }
1237 
1238  nFinalIndex = i;
1239 
1240  aText.iterateCodePoints(&i);
1241  }
1242  if (nIndex == nFinalIndex && std::abs( pDX[2*nIndex+1] - nX ) < nDiff)
1243  nIndex = EDIT_NOLIMIT;
1244  }
1245 
1246  return nIndex;
1247 }
1248 
1249 void Edit::ImplSetCursorPos( sal_Int32 nChar, bool bSelect )
1250 {
1251  Selection aSelection( maSelection );
1252  aSelection.Max() = nChar;
1253  if ( !bSelect )
1254  aSelection.Min() = aSelection.Max();
1255  ImplSetSelection( aSelection );
1256 }
1257 
1259 {
1260  if ( GetSelection().Len() )
1261  {
1262  css::uno::Reference<css::datatransfer::clipboard::XClipboard> aSelection(GetPrimarySelection());
1263  ImplCopy( aSelection );
1264  }
1265 }
1266 
1267 void Edit::ImplCopy( uno::Reference< datatransfer::clipboard::XClipboard > const & rxClipboard )
1268 {
1270 }
1271 
1272 void Edit::ImplPaste( uno::Reference< datatransfer::clipboard::XClipboard > const & rxClipboard )
1273 {
1274  if ( rxClipboard.is() )
1275  {
1276  uno::Reference< datatransfer::XTransferable > xDataObj;
1277 
1278  try
1279  {
1280  SolarMutexReleaser aReleaser;
1281  xDataObj = rxClipboard->getContents();
1282  }
1283  catch( const css::uno::Exception& )
1284  {
1285  }
1286 
1287  if ( xDataObj.is() )
1288  {
1289  datatransfer::DataFlavor aFlavor;
1290  SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
1291  try
1292  {
1293  uno::Any aData = xDataObj->getTransferData( aFlavor );
1294  OUString aText;
1295  aData >>= aText;
1296 
1297  Selection aSelection(maSelection);
1298  aSelection.Justify();
1299  if (ImplTruncateToMaxLen(aText, aSelection.Len()))
1301 
1302  ReplaceSelected( aText );
1303  }
1304  catch( const css::uno::Exception& )
1305  {
1306  }
1307  }
1308  }
1309 }
1310 
1311 void Edit::MouseButtonDown( const MouseEvent& rMEvt )
1312 {
1313  if ( mpSubEdit )
1314  {
1315  Control::MouseButtonDown( rMEvt );
1316  return;
1317  }
1318 
1319  sal_Int32 nCharPos = ImplGetCharPos( rMEvt.GetPosPixel() );
1320  Selection aSelection( maSelection );
1321  aSelection.Justify();
1322 
1323  if ( rMEvt.GetClicks() < 4 )
1324  {
1325  mbClickedInSelection = false;
1326  if ( rMEvt.GetClicks() == 3 )
1327  {
1330 
1331  }
1332  else if ( rMEvt.GetClicks() == 2 )
1333  {
1334  uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
1335  i18n::Boundary aBoundary = xBI->getWordBoundary( maText.toString(), aSelection.Max(),
1336  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, true );
1337  ImplSetSelection( Selection( aBoundary.startPos, aBoundary.endPos ) );
1339  }
1340  else if ( !rMEvt.IsShift() && HasFocus() && aSelection.IsInside( nCharPos ) )
1341  mbClickedInSelection = true;
1342  else if ( rMEvt.IsLeft() )
1343  ImplSetCursorPos( nCharPos, rMEvt.IsShift() );
1344 
1345  if ( !mbClickedInSelection && rMEvt.IsLeft() && ( rMEvt.GetClicks() == 1 ) )
1347  }
1348 
1349  GrabFocus();
1350 }
1351 
1352 void Edit::MouseButtonUp( const MouseEvent& rMEvt )
1353 {
1354  if ( mbClickedInSelection && rMEvt.IsLeft() )
1355  {
1356  sal_Int32 nCharPos = ImplGetCharPos( rMEvt.GetPosPixel() );
1357  ImplSetCursorPos( nCharPos, false );
1358  mbClickedInSelection = false;
1359  }
1360  else if ( rMEvt.IsMiddle() && !mbReadOnly &&
1362  {
1363  css::uno::Reference<css::datatransfer::clipboard::XClipboard> aSelection(Window::GetPrimarySelection());
1364  ImplPaste( aSelection );
1365  ImplModified();
1366  }
1367 }
1368 
1369 void Edit::Tracking( const TrackingEvent& rTEvt )
1370 {
1371  if ( rTEvt.IsTrackingEnded() )
1372  {
1373  if ( mbClickedInSelection )
1374  {
1375  sal_Int32 nCharPos = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() );
1376  ImplSetCursorPos( nCharPos, false );
1377  mbClickedInSelection = false;
1378  }
1379  else if ( rTEvt.GetMouseEvent().IsLeft() )
1380  {
1382  }
1383  }
1384  else
1385  {
1386  if( !mbClickedInSelection )
1387  {
1388  sal_Int32 nCharPos = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() );
1389  ImplSetCursorPos( nCharPos, true );
1390  }
1391  }
1392 }
1393 
1395 {
1396  bool bDone = false;
1397  sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1398  KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
1399 
1400  mbInternModified = false;
1401 
1402  if ( eFunc != KeyFuncType::DONTKNOW )
1403  {
1404  switch ( eFunc )
1405  {
1406  case KeyFuncType::CUT:
1407  {
1408  if ( !mbReadOnly && maSelection.Len() && !mbPassword )
1409  {
1410  Cut();
1411  ImplModified();
1412  bDone = true;
1413  }
1414  }
1415  break;
1416 
1417  case KeyFuncType::COPY:
1418  {
1419  if ( !mbPassword )
1420  {
1421  Copy();
1422  bDone = true;
1423  }
1424  }
1425  break;
1426 
1427  case KeyFuncType::PASTE:
1428  {
1429  if ( !mbReadOnly )
1430  {
1431  Paste();
1432  bDone = true;
1433  }
1434  }
1435  break;
1436 
1437  case KeyFuncType::UNDO:
1438  {
1439  if ( !mbReadOnly )
1440  {
1441  Undo();
1442  bDone = true;
1443  }
1444  }
1445  break;
1446 
1447  default:
1448  eFunc = KeyFuncType::DONTKNOW;
1449  }
1450  }
1451 
1452  if ( !bDone && rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() )
1453  {
1454  if ( nCode == KEY_A )
1455  {
1456  ImplSetSelection( Selection( 0, maText.getLength() ) );
1457  bDone = true;
1458  }
1459  else if ( rKEvt.GetKeyCode().IsShift() && (nCode == KEY_S) )
1460  {
1462  {
1463  Selection aSaveSel = GetSelection(); // if someone changes the selection in Get/LoseFocus, e.g. URL bar
1464  OUString aChars = pImplFncGetSpecialChars( GetFrameWeld(), GetFont() );
1465  SetSelection( aSaveSel );
1466  if ( !aChars.isEmpty() )
1467  {
1468  ImplInsertText( aChars );
1469  ImplModified();
1470  }
1471  bDone = true;
1472  }
1473  }
1474  }
1475 
1476  if ( eFunc == KeyFuncType::DONTKNOW && ! bDone )
1477  {
1478  switch ( nCode )
1479  {
1480  case css::awt::Key::SELECT_ALL:
1481  {
1482  ImplSetSelection( Selection( 0, maText.getLength() ) );
1483  bDone = true;
1484  }
1485  break;
1486 
1487  case KEY_LEFT:
1488  case KEY_RIGHT:
1489  case KEY_HOME:
1490  case KEY_END:
1491  case css::awt::Key::MOVE_WORD_FORWARD:
1492  case css::awt::Key::SELECT_WORD_FORWARD:
1493  case css::awt::Key::MOVE_WORD_BACKWARD:
1494  case css::awt::Key::SELECT_WORD_BACKWARD:
1495  case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1496  case css::awt::Key::MOVE_TO_END_OF_LINE:
1497  case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1498  case css::awt::Key::SELECT_TO_END_OF_LINE:
1499  case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1500  case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1501  case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1502  case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1503  case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1504  case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1505  case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1506  case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1507  {
1508  if ( !rKEvt.GetKeyCode().IsMod2() )
1509  {
1511  uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
1512 
1513  Selection aSel( maSelection );
1514  bool bWord = rKEvt.GetKeyCode().IsMod1();
1515  bool bSelect = rKEvt.GetKeyCode().IsShift();
1516  bool bGoLeft = (nCode == KEY_LEFT);
1517  bool bGoRight = (nCode == KEY_RIGHT);
1518  bool bGoHome = (nCode == KEY_HOME);
1519  bool bGoEnd = (nCode == KEY_END);
1520 
1521  switch( nCode )
1522  {
1523  case css::awt::Key::MOVE_WORD_FORWARD:
1524  bGoRight = bWord = true;break;
1525  case css::awt::Key::SELECT_WORD_FORWARD:
1526  bGoRight = bSelect = bWord = true;break;
1527  case css::awt::Key::MOVE_WORD_BACKWARD:
1528  bGoLeft = bWord = true;break;
1529  case css::awt::Key::SELECT_WORD_BACKWARD:
1530  bGoLeft = bSelect = bWord = true;break;
1531  case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1532  case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1533  case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1534  bSelect = true;
1535  [[fallthrough]];
1536  case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1537  case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1538  case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1539  bGoHome = true;break;
1540  case css::awt::Key::SELECT_TO_END_OF_LINE:
1541  case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1542  case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1543  bSelect = true;
1544  [[fallthrough]];
1545  case css::awt::Key::MOVE_TO_END_OF_LINE:
1546  case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1547  case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1548  bGoEnd = true;break;
1549  default:
1550  break;
1551  }
1552 
1553  // range is checked in ImplSetSelection ...
1554  if ( bGoLeft && aSel.Max() )
1555  {
1556  if ( bWord )
1557  {
1558  i18n::Boundary aBoundary = xBI->getWordBoundary( maText.toString(), aSel.Max(),
1559  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, true );
1560  if ( aBoundary.startPos == aSel.Max() )
1561  aBoundary = xBI->previousWord( maText.toString(), aSel.Max(),
1562  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1563  aSel.Max() = aBoundary.startPos;
1564  }
1565  else
1566  {
1567  sal_Int32 nCount = 1;
1568  aSel.Max() = xBI->previousCharacters( maText.toString(), aSel.Max(),
1569  GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
1570  }
1571  }
1572  else if ( bGoRight && ( aSel.Max() < maText.getLength() ) )
1573  {
1574  if ( bWord )
1575  {
1576  i18n::Boundary aBoundary = xBI->nextWord( maText.toString(), aSel.Max(),
1577  GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1578  aSel.Max() = aBoundary.startPos;
1579  }
1580  else
1581  {
1582  sal_Int32 nCount = 1;
1583  aSel.Max() = xBI->nextCharacters( maText.toString(), aSel.Max(),
1584  GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
1585  }
1586  }
1587  else if ( bGoHome )
1588  {
1589  aSel.Max() = 0;
1590  }
1591  else if ( bGoEnd )
1592  {
1593  aSel.Max() = EDIT_NOLIMIT;
1594  }
1595 
1596  if ( !bSelect )
1597  aSel.Min() = aSel.Max();
1598 
1599  if ( aSel != GetSelection() )
1600  {
1601  ImplSetSelection( aSel );
1603  }
1604 
1605  if (bGoEnd && maAutocompleteHdl.IsSet() && !rKEvt.GetKeyCode().GetModifier())
1606  {
1607  if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.getLength()) )
1608  {
1609  maAutocompleteHdl.Call(*this);
1610  }
1611  }
1612 
1613  bDone = true;
1614  }
1615  }
1616  break;
1617 
1618  case css::awt::Key::DELETE_WORD_BACKWARD:
1619  case css::awt::Key::DELETE_WORD_FORWARD:
1620  case css::awt::Key::DELETE_TO_BEGIN_OF_LINE:
1621  case css::awt::Key::DELETE_TO_END_OF_LINE:
1622  case KEY_BACKSPACE:
1623  case KEY_DELETE:
1624  {
1625  if ( !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() )
1626  {
1627  sal_uInt8 nDel = (nCode == KEY_DELETE) ? EDIT_DEL_RIGHT : EDIT_DEL_LEFT;
1629  if ( (nMode == EDIT_DELMODE_RESTOFWORD) && rKEvt.GetKeyCode().IsShift() )
1631  switch( nCode )
1632  {
1633  case css::awt::Key::DELETE_WORD_BACKWARD:
1634  nDel = EDIT_DEL_LEFT;
1635  nMode = EDIT_DELMODE_RESTOFWORD;
1636  break;
1637  case css::awt::Key::DELETE_WORD_FORWARD:
1638  nDel = EDIT_DEL_RIGHT;
1639  nMode = EDIT_DELMODE_RESTOFWORD;
1640  break;
1641  case css::awt::Key::DELETE_TO_BEGIN_OF_LINE:
1642  nDel = EDIT_DEL_LEFT;
1644  break;
1645  case css::awt::Key::DELETE_TO_END_OF_LINE:
1646  nDel = EDIT_DEL_RIGHT;
1648  break;
1649  default: break;
1650  }
1651  sal_Int32 nOldLen = maText.getLength();
1652  ImplDelete( maSelection, nDel, nMode );
1653  if ( maText.getLength() != nOldLen )
1654  ImplModified();
1655  bDone = true;
1656  }
1657  }
1658  break;
1659 
1660  case KEY_INSERT:
1661  {
1662  if ( !mpIMEInfos && !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() )
1663  {
1665  bDone = true;
1666  }
1667  }
1668  break;
1669 
1670  case KEY_RETURN:
1671  if (maActivateHdl.IsSet())
1672  {
1673  bDone = maActivateHdl.Call(*this);
1674  }
1675  break;
1676 
1677  default:
1678  {
1679  if ( IsCharInput( rKEvt ) )
1680  {
1681  bDone = true; // read characters also when in ReadOnly
1682  if ( !mbReadOnly )
1683  {
1684  ImplInsertText(OUString(rKEvt.GetCharCode()), nullptr, true);
1685  if (maAutocompleteHdl.IsSet())
1686  {
1687  if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.getLength()) )
1688  {
1689  maAutocompleteHdl.Call(*this);
1690  }
1691  }
1692  }
1693  }
1694  }
1695  }
1696  }
1697 
1698  if ( mbInternModified )
1699  ImplModified();
1700 
1701  return bDone;
1702 }
1703 
1704 void Edit::KeyInput( const KeyEvent& rKEvt )
1705 {
1706  if ( mpSubEdit || !ImplHandleKeyEvent( rKEvt ) )
1707  Control::KeyInput( rKEvt );
1708 }
1709 
1711 {
1712  mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
1713  const_cast<Edit*>(this)->Invalidate();
1714 }
1715 
1716 void Edit::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRectangle)
1717 {
1718  if (!mpSubEdit)
1719  ImplRepaint(rRenderContext, rRectangle);
1720 }
1721 
1723 {
1724  if ( !mpSubEdit && IsReallyVisible() )
1725  {
1726  Control::Resize();
1727  // because of vertical centering...
1728  mnXOffset = 0;
1729  ImplAlign();
1730  Invalidate();
1731  ImplShowCursor();
1732  }
1733 }
1734 
1735 void Edit::Draw( OutputDevice* pDev, const Point& rPos, DrawFlags nFlags )
1736 {
1737  ApplySettings(*pDev);
1738 
1739  Point aPos = pDev->LogicToPixel( rPos );
1740  Size aSize = GetSizePixel();
1741  vcl::Font aFont = GetDrawPixelFont( pDev );
1742 
1743  pDev->Push();
1744  pDev->SetMapMode();
1745  pDev->SetFont( aFont );
1746  pDev->SetTextFillColor();
1747 
1748  // Border/Background
1749  pDev->SetLineColor();
1750  pDev->SetFillColor();
1751  bool bBorder = (GetStyle() & WB_BORDER);
1752  bool bBackground = IsControlBackground();
1753  if ( bBorder || bBackground )
1754  {
1755  tools::Rectangle aRect( aPos, aSize );
1756  if ( bBorder )
1757  {
1758  ImplDrawFrame( pDev, aRect );
1759  }
1760  if ( bBackground )
1761  {
1763  pDev->DrawRect( aRect );
1764  }
1765  }
1766 
1767  // Content
1768  if ( nFlags & DrawFlags::Mono )
1769  pDev->SetTextColor( COL_BLACK );
1770  else
1771  {
1772  if ( !IsEnabled() )
1773  {
1774  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1775  pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1776  }
1777  else
1778  {
1779  pDev->SetTextColor( GetTextColor() );
1780  }
1781  }
1782 
1783  const long nOnePixel = GetDrawPixel( pDev, 1 );
1784  const long nOffX = 3*nOnePixel;
1786  tools::Rectangle aTextRect( aPos, aSize );
1787 
1788  if ( GetStyle() & WB_CENTER )
1789  nTextStyle |= DrawTextFlags::Center;
1790  else if ( GetStyle() & WB_RIGHT )
1791  nTextStyle |= DrawTextFlags::Right;
1792  else
1793  nTextStyle |= DrawTextFlags::Left;
1794 
1795  aTextRect.AdjustLeft(nOffX );
1796  aTextRect.AdjustRight( -nOffX );
1797 
1798  OUString aText = ImplGetText();
1799  long nTextHeight = pDev->GetTextHeight();
1800  long nTextWidth = pDev->GetTextWidth( aText );
1801  long nOffY = (aSize.Height() - nTextHeight) / 2;
1802 
1803  // Clipping?
1804  if ( (nOffY < 0) ||
1805  ((nOffY+nTextHeight) > aSize.Height()) ||
1806  ((nOffX+nTextWidth) > aSize.Width()) )
1807  {
1808  tools::Rectangle aClip( aPos, aSize );
1809  if ( nTextHeight > aSize.Height() )
1810  aClip.AdjustBottom(nTextHeight-aSize.Height()+1 ); // prevent HP printers from 'optimizing'
1811  pDev->IntersectClipRegion( aClip );
1812  }
1813 
1814  pDev->DrawText( aTextRect, aText, nTextStyle );
1815  pDev->Pop();
1816 
1817  if ( GetSubEdit() )
1818  {
1819  Size aOrigSize(GetSubEdit()->GetSizePixel());
1821  GetSubEdit()->Draw(pDev, rPos, nFlags);
1822  GetSubEdit()->SetSizePixel(aOrigSize);
1823  }
1824 }
1825 
1827 {
1828  // allow control to show focused state
1829  vcl::Window *pInvalWin = pWin;
1830  for (;;)
1831  {
1832  vcl::Window* pBorder = pInvalWin->GetWindow( GetWindowType::Border );
1833  if (pBorder == pInvalWin || !pBorder ||
1834  pInvalWin->ImplGetFrame() != pBorder->ImplGetFrame() )
1835  break;
1836  pInvalWin = pBorder;
1837  }
1838 
1840 }
1841 
1843 {
1844  if ( mpSubEdit )
1846  else if ( !mbActivePopup )
1847  {
1848  maUndoText = maText.toString();
1850  if ( !( GetStyle() & (WB_NOHIDESELECTION|WB_READONLY) )
1852  {
1853  if ( nSelOptions & SelectionOptions::ShowFirst )
1854  {
1855  maSelection.Min() = maText.getLength();
1856  maSelection.Max() = 0;
1857  }
1858  else
1859  {
1860  maSelection.Min() = 0;
1861  maSelection.Max() = maText.getLength();
1862  }
1863  if ( mbIsSubEdit )
1865  else
1867  }
1868 
1869  ImplShowCursor();
1870 
1871  // FIXME: this is currently only on macOS
1872  // check for other platforms that need similar handling
1873  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
1876  {
1878  }
1879  else if ( maSelection.Len() )
1880  {
1881  // paint the selection
1882  if ( !HasPaintEvent() )
1884  else
1885  Invalidate();
1886  }
1887 
1889  }
1890 
1892 }
1893 
1895 {
1896  if ( !mpSubEdit )
1897  {
1898  // FIXME: this is currently only on macOS
1899  // check for other platforms that need similar handling
1900  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
1903  {
1905  }
1906 
1907  if ( !mbActivePopup && !( GetStyle() & WB_NOHIDESELECTION ) && maSelection.Len() )
1908  ImplInvalidateOrRepaint(); // paint the selection
1909  }
1910 
1912 }
1913 
1914 void Edit::Command( const CommandEvent& rCEvt )
1915 {
1916  if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
1917  {
1919 
1920  bool bEnableCut = true;
1921  bool bEnableCopy = true;
1922  bool bEnableDelete = true;
1923  bool bEnablePaste = true;
1924  bool bEnableSpecialChar = true;
1925 
1926  if ( !maSelection.Len() )
1927  {
1928  bEnableCut = false;
1929  bEnableCopy = false;
1930  bEnableDelete = false;
1931  }
1932 
1933  if ( IsReadOnly() )
1934  {
1935  bEnableCut = false;
1936  bEnablePaste = false;
1937  bEnableDelete = false;
1938  bEnableSpecialChar = false;
1939  }
1940  else
1941  {
1942  // only paste if text available in clipboard
1943  bool bData = false;
1944  uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard();
1945 
1946  if ( xClipboard.is() )
1947  {
1948  uno::Reference< datatransfer::XTransferable > xDataObj;
1949  {
1950  SolarMutexReleaser aReleaser;
1951  xDataObj = xClipboard->getContents();
1952  }
1953  if ( xDataObj.is() )
1954  {
1955  datatransfer::DataFlavor aFlavor;
1956  SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
1957  bData = xDataObj->isDataFlavorSupported( aFlavor );
1958  }
1959  }
1960  bEnablePaste = bData;
1961  }
1962 
1963  pPopup->EnableItem(pPopup->GetItemId("cut"), bEnableCut);
1964  pPopup->EnableItem(pPopup->GetItemId("copy"), bEnableCopy);
1965  pPopup->EnableItem(pPopup->GetItemId("delete"), bEnableDelete);
1966  pPopup->EnableItem(pPopup->GetItemId("paste"), bEnablePaste);
1967  pPopup->EnableItem(pPopup->GetItemId("specialchar"), bEnableSpecialChar);
1968  pPopup->EnableItem(pPopup->GetItemId("undo"), maUndoText != maText.getStr());
1969  bool bAllSelected = maSelection.Min() == 0 && maSelection.Max() == maText.getLength();
1970  pPopup->EnableItem(pPopup->GetItemId("selectall"), !bAllSelected);
1971  pPopup->ShowItem(pPopup->GetItemId("specialchar"), pImplFncGetSpecialChars != nullptr);
1972 
1973  mbActivePopup = true;
1974  Selection aSaveSel = GetSelection(); // if someone changes selection in Get/LoseFocus, e.g. URL bar
1975  Point aPos = rCEvt.GetMousePosPixel();
1976  if ( !rCEvt.IsMouseEvent() )
1977  {
1978  // Show menu eventually centered in selection
1979  Size aSize = GetOutputSizePixel();
1980  aPos = Point( aSize.Width()/2, aSize.Height()/2 );
1981  }
1982  sal_uInt16 n = pPopup->Execute( this, aPos );
1983  SetSelection( aSaveSel );
1984  OString sCommand = pPopup->GetItemIdent(n);
1985  if (sCommand == "undo")
1986  {
1987  Undo();
1988  ImplModified();
1989  }
1990  else if (sCommand == "cut")
1991  {
1992  Cut();
1993  ImplModified();
1994  }
1995  else if (sCommand == "copy")
1996  {
1997  Copy();
1998  }
1999  else if (sCommand == "paste")
2000  {
2001  Paste();
2002  ImplModified();
2003  }
2004  else if (sCommand == "delete")
2005  {
2006  DeleteSelected();
2007  ImplModified();
2008  }
2009  else if (sCommand == "selectall")
2010  {
2011  ImplSetSelection( Selection( 0, maText.getLength() ) );
2012  }
2013  else if (sCommand == "specialchar" && pImplFncGetSpecialChars)
2014  {
2015  OUString aChars = pImplFncGetSpecialChars(GetFrameWeld(), GetFont());
2016  SetSelection( aSaveSel );
2017  if (!aChars.isEmpty())
2018  {
2019  ImplInsertText( aChars );
2020  ImplModified();
2021  }
2022  }
2023  pPopup.clear();
2024  mbActivePopup = false;
2025  }
2026  else if ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput )
2027  {
2028  DeleteSelected();
2029  sal_Int32 nPos = maSelection.Max();
2030  mpIMEInfos.reset(new Impl_IMEInfos( nPos, OUString(maText.getStr() + nPos ) ));
2031  mpIMEInfos->bWasCursorOverwrite = !IsInsertMode();
2032  }
2033  else if ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput )
2034  {
2035  bool bInsertMode = !mpIMEInfos->bWasCursorOverwrite;
2036  mpIMEInfos.reset();
2037 
2038  SetInsertMode(bInsertMode);
2039  ImplModified();
2040 
2041  Invalidate();
2042 
2043  // #i25161# call auto complete handler for ext text commit also
2044  if (maAutocompleteHdl.IsSet())
2045  {
2046  if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.getLength()) )
2047  {
2048  maAutocompleteHdl.Call(*this);
2049  }
2050  }
2051  }
2052  else if ( rCEvt.GetCommand() == CommandEventId::ExtTextInput )
2053  {
2055 
2056  maText.remove( mpIMEInfos->nPos, mpIMEInfos->nLen );
2057  maText.insert( mpIMEInfos->nPos, pData->GetText() );
2058  if ( mpIMEInfos->bWasCursorOverwrite )
2059  {
2060  const sal_Int32 nOldIMETextLen = mpIMEInfos->nLen;
2061  const sal_Int32 nNewIMETextLen = pData->GetText().getLength();
2062  if ( ( nOldIMETextLen > nNewIMETextLen ) &&
2063  ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.getLength() ) )
2064  {
2065  // restore old characters
2066  const sal_Int32 nRestore = nOldIMETextLen - nNewIMETextLen;
2067  maText.insert( mpIMEInfos->nPos + nNewIMETextLen, mpIMEInfos->aOldTextAfterStartPos.copy( nNewIMETextLen, nRestore ) );
2068  }
2069  else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
2070  ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.getLength() ) )
2071  {
2072  const sal_Int32 nOverwrite = ( nNewIMETextLen > mpIMEInfos->aOldTextAfterStartPos.getLength()
2073  ? mpIMEInfos->aOldTextAfterStartPos.getLength() : nNewIMETextLen ) - nOldIMETextLen;
2074  maText.remove( mpIMEInfos->nPos + nNewIMETextLen, nOverwrite );
2075  }
2076  }
2077 
2078  if ( pData->GetTextAttr() )
2079  {
2080  mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().getLength() );
2081  mpIMEInfos->bCursor = pData->IsCursorVisible();
2082  }
2083  else
2084  {
2085  mpIMEInfos->DestroyAttribs();
2086  }
2087 
2089  sal_Int32 nCursorPos = mpIMEInfos->nPos + pData->GetCursorPos();
2090  SetSelection( Selection( nCursorPos, nCursorPos ) );
2091  SetInsertMode( !pData->IsCursorOverwrite() );
2092 
2093  if ( pData->IsCursorVisible() )
2094  GetCursor()->Show();
2095  else
2096  GetCursor()->Hide();
2097  }
2098  else if ( rCEvt.GetCommand() == CommandEventId::CursorPos )
2099  {
2100  if ( mpIMEInfos )
2101  {
2102  sal_Int32 nCursorPos = GetSelection().Max();
2103  SetCursorRect( nullptr, GetTextWidth( maText.toString(), nCursorPos, mpIMEInfos->nPos+mpIMEInfos->nLen-nCursorPos ) );
2104  }
2105  else
2106  {
2107  SetCursorRect();
2108  }
2109  }
2110  else if ( rCEvt.GetCommand() == CommandEventId::SelectionChange )
2111  {
2113  Selection aSelection( pData->GetStart(), pData->GetEnd() );
2114  SetSelection(aSelection);
2115  }
2116  else if ( rCEvt.GetCommand() == CommandEventId::QueryCharPosition )
2117  {
2118  if (mpIMEInfos && mpIMEInfos->nLen > 0)
2119  {
2120  OUString aText = ImplGetText();
2121  long nDXBuffer[256];
2122  std::unique_ptr<long[]> pDXBuffer;
2123  long* pDX = nDXBuffer;
2124 
2125  if( !aText.isEmpty() )
2126  {
2127  if( o3tl::make_unsigned(2*aText.getLength()) > SAL_N_ELEMENTS(nDXBuffer) )
2128  {
2129  pDXBuffer.reset(new long[2*(aText.getLength()+1)]);
2130  pDX = pDXBuffer.get();
2131  }
2132 
2133  GetCaretPositions( aText, pDX, 0, aText.getLength() );
2134  }
2135  long nTH = GetTextHeight();
2137 
2138  std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ mpIMEInfos->nLen ]);
2139  for ( int nIndex = 0; nIndex < mpIMEInfos->nLen; ++nIndex )
2140  {
2141  tools::Rectangle aRect( aPos, Size( 10, nTH ) );
2142  aRect.SetLeft( pDX[2*(nIndex+mpIMEInfos->nPos)] + mnXOffset + ImplGetExtraXOffset() );
2143  aRects[ nIndex ] = aRect;
2144  }
2145  SetCompositionCharRect( aRects.get(), mpIMEInfos->nLen );
2146  }
2147  }
2148  else
2149  Control::Command( rCEvt );
2150 }
2151 
2153 {
2154  if (nType == StateChangedType::InitShow)
2155  {
2156  if (!mpSubEdit)
2157  {
2158  mnXOffset = 0; // if GrabFocus before while size was still wrong
2159  ImplAlign();
2160  if (!mpSubEdit)
2161  ImplShowCursor(false);
2162  Invalidate();
2163  }
2164  }
2165  else if (nType == StateChangedType::Enable)
2166  {
2167  if (!mpSubEdit)
2168  {
2169  // change text color only
2171  }
2172  }
2173  else if (nType == StateChangedType::Style || nType == StateChangedType::Mirroring)
2174  {
2175  WinBits nStyle = GetStyle();
2176  if (nType == StateChangedType::Style)
2177  {
2178  nStyle = ImplInitStyle(GetStyle());
2179  SetStyle(nStyle);
2180  }
2181 
2182  sal_uInt16 nOldAlign = mnAlign;
2184 
2185  // hack: right align until keyinput and cursor travelling works
2186  // edits are always RTL disabled
2187  // however the parent edits contain the correct setting
2188  if (mbIsSubEdit && GetParent()->IsRTLEnabled())
2189  {
2190  if (GetParent()->GetStyle() & WB_LEFT)
2192  if (nType == StateChangedType::Mirroring)
2194  }
2195  else if (mbIsSubEdit && !GetParent()->IsRTLEnabled())
2196  {
2197  if (nType == StateChangedType::Mirroring)
2199  }
2200 
2201  if (nStyle & WB_RIGHT)
2203  else if (nStyle & WB_CENTER)
2205  if (!maText.isEmpty() && (mnAlign != nOldAlign))
2206  {
2207  ImplAlign();
2208  Invalidate();
2209  }
2210 
2211  }
2212  else if ((nType == StateChangedType::Zoom) || (nType == StateChangedType::ControlFont))
2213  {
2214  if (!mpSubEdit)
2215  {
2216  ApplySettings(*this);
2217  ImplShowCursor();
2218  Invalidate();
2219  }
2220  }
2222  {
2223  if (!mpSubEdit)
2224  {
2225  ApplySettings(*this);
2226  Invalidate();
2227  }
2228  }
2229 
2230  Control::StateChanged(nType);
2231 }
2232 
2234 {
2235  if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
2237  ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2238  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
2239  {
2240  if ( !mpSubEdit )
2241  {
2242  ApplySettings(*this);
2243  ImplShowCursor();
2244  Invalidate();
2245  }
2246  }
2247 
2248  Control::DataChanged( rDCEvt );
2249 }
2250 
2252 {
2253  if (!mpDDInfo->bVisCursor)
2254  {
2255  long nTextWidth = GetTextWidth( maText.toString(), 0, mpDDInfo->nDropPos );
2256  long nTextHeight = GetTextHeight();
2257  tools::Rectangle aCursorRect( Point( nTextWidth + mnXOffset, (GetOutputSize().Height()-nTextHeight)/2 ), Size( 2, nTextHeight ) );
2258  mpDDInfo->aCursor.SetWindow( this );
2259  mpDDInfo->aCursor.SetPos( aCursorRect.TopLeft() );
2260  mpDDInfo->aCursor.SetSize( aCursorRect.GetSize() );
2261  mpDDInfo->aCursor.Show();
2262  mpDDInfo->bVisCursor = true;
2263  }
2264 }
2265 
2267 {
2268  if ( mpDDInfo && mpDDInfo->bVisCursor )
2269  {
2270  mpDDInfo->aCursor.Hide();
2271  mpDDInfo->bVisCursor = false;
2272  }
2273 }
2274 
2275 TextFilter::TextFilter(const OUString &rForbiddenChars)
2276  : sForbiddenChars(rForbiddenChars)
2277 {
2278 }
2279 
2281 {
2282 }
2283 
2284 OUString TextFilter::filter(const OUString &rText)
2285 {
2286  OUString sTemp(rText);
2287  for (sal_Int32 i = 0; i < sForbiddenChars.getLength(); ++i)
2288  {
2289  sTemp = sTemp.replaceAll(OUStringChar(sForbiddenChars[i]), "");
2290  }
2291  return sTemp;
2292 }
2293 
2295 {
2296  Selection aSel = GetSelection();
2297  const OUString sOrig = GetText();
2298  const OUString sNew = mpFilterText->filter(GetText());
2299  if (sOrig != sNew)
2300  {
2301  sal_Int32 nDiff = sOrig.getLength() - sNew.getLength();
2302  if (nDiff)
2303  {
2304  aSel.setMin(aSel.getMin() - nDiff);
2305  aSel.setMax(aSel.getMin());
2306  }
2307  SetText(sNew);
2308  SetSelection(aSel);
2309  }
2310 }
2311 
2313 {
2314  if (mpFilterText)
2315  filterText();
2316 
2317  if ( mbIsSubEdit )
2318  {
2319  static_cast<Edit*>(GetParent())->Modify();
2320  }
2321  else
2322  {
2324  // have been destroyed while calling into the handlers
2325  return;
2326 
2327  // #i13677# notify edit listeners about caret position change
2329  // FIXME: this is currently only on macOS
2330  // check for other platforms that need similar handling
2331  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2334  {
2336  }
2337  }
2338 }
2339 
2341 {
2342  mcEchoChar = c;
2343  if ( mpSubEdit )
2344  mpSubEdit->SetEchoChar( c );
2345 }
2346 
2347 void Edit::SetReadOnly( bool bReadOnly )
2348 {
2349  if ( mbReadOnly != bReadOnly )
2350  {
2351  mbReadOnly = bReadOnly;
2352  if ( mpSubEdit )
2353  mpSubEdit->SetReadOnly( bReadOnly );
2354 
2356  }
2357 }
2358 
2359 void Edit::SetInsertMode( bool bInsert )
2360 {
2361  if ( bInsert != mbInsertMode )
2362  {
2363  mbInsertMode = bInsert;
2364  if ( mpSubEdit )
2365  mpSubEdit->SetInsertMode( bInsert );
2366  else
2367  ImplShowCursor();
2368  }
2369 }
2370 
2372 {
2373  if ( mpSubEdit )
2374  return mpSubEdit->IsInsertMode();
2375  else
2376  return mbInsertMode;
2377 }
2378 
2379 void Edit::SetMaxTextLen(sal_Int32 nMaxLen)
2380 {
2381  mnMaxTextLen = nMaxLen > 0 ? nMaxLen : EDIT_NOLIMIT;
2382 
2383  if ( mpSubEdit )
2385  else
2386  {
2387  if ( maText.getLength() > mnMaxTextLen )
2389  }
2390 }
2391 
2392 void Edit::SetSelection( const Selection& rSelection )
2393 {
2394  // If the selection was changed from outside, e.g. by MouseButtonDown, don't call Tracking()
2395  // directly afterwards which would change the selection again
2396  if ( IsTracking() )
2397  EndTracking();
2398  else if ( mpSubEdit && mpSubEdit->IsTracking() )
2400 
2401  ImplSetSelection( rSelection );
2402 }
2403 
2404 void Edit::ImplSetSelection( const Selection& rSelection, bool bPaint )
2405 {
2406  if ( mpSubEdit )
2407  mpSubEdit->ImplSetSelection( rSelection );
2408  else
2409  {
2410  if ( rSelection != maSelection )
2411  {
2412  Selection aOld( maSelection );
2413  Selection aNew( rSelection );
2414 
2415  if ( aNew.Min() > maText.getLength() )
2416  aNew.Min() = maText.getLength();
2417  if ( aNew.Max() > maText.getLength() )
2418  aNew.Max() = maText.getLength();
2419  if ( aNew.Min() < 0 )
2420  aNew.Min() = 0;
2421  if ( aNew.Max() < 0 )
2422  aNew.Max() = 0;
2423 
2424  if ( aNew != maSelection )
2425  {
2427  Selection aTemp = maSelection;
2428  maSelection = aNew;
2429 
2430  if ( bPaint && ( aOld.Len() || aNew.Len() || IsPaintTransparent() ) )
2432  ImplShowCursor();
2433 
2434  bool bCaret = false, bSelection = false;
2435  long nB=aNew.Max(), nA=aNew.Min(),oB=aTemp.Max(), oA=aTemp.Min();
2436  long nGap = nB-nA, oGap = oB-oA;
2437  if (nB != oB)
2438  bCaret = true;
2439  if (nGap != 0 || oGap != 0)
2440  bSelection = true;
2441 
2442  if (bSelection)
2443  {
2444  if ( mbIsSubEdit )
2446  else
2448  }
2449 
2450  if (bCaret)
2451  {
2452  if ( mbIsSubEdit )
2454  else
2456  }
2457 
2458  // #103511# notify combobox listeners of deselection
2459  if( !maSelection && GetParent() && GetParent()->GetType() == WindowType::COMBOBOX )
2461  }
2462  }
2463  }
2464 }
2465 
2467 {
2468  if ( mpSubEdit )
2469  return mpSubEdit->GetSelection();
2470  else
2471  return maSelection;
2472 }
2473 
2474 void Edit::ReplaceSelected( const OUString& rStr )
2475 {
2476  if ( mpSubEdit )
2477  mpSubEdit->ReplaceSelected( rStr );
2478  else
2479  ImplInsertText( rStr );
2480 }
2481 
2483 {
2484  if ( mpSubEdit )
2486  else
2487  {
2488  if ( maSelection.Len() )
2490  }
2491 }
2492 
2493 OUString Edit::GetSelected() const
2494 {
2495  if ( mpSubEdit )
2496  return mpSubEdit->GetSelected();
2497  else
2498  {
2499  Selection aSelection( maSelection );
2500  aSelection.Justify();
2501  return OUString( maText.getStr() + aSelection.Min(), aSelection.Len() );
2502  }
2503 }
2504 
2506 {
2507  if ( !mbPassword )
2508  {
2509  Copy();
2510  ReplaceSelected( OUString() );
2511  }
2512 }
2513 
2515 {
2516  if ( !mbPassword )
2517  {
2518  css::uno::Reference<css::datatransfer::clipboard::XClipboard> aClipboard(GetClipboard());
2519  ImplCopy( aClipboard );
2520  }
2521 }
2522 
2524 {
2525  css::uno::Reference<css::datatransfer::clipboard::XClipboard> aClipboard(GetClipboard());
2526  ImplPaste( aClipboard );
2527 }
2528 
2530 {
2531  if ( mpSubEdit )
2532  mpSubEdit->Undo();
2533  else
2534  {
2535  const OUString aText( maText.toString() );
2536  ImplDelete( Selection( 0, aText.getLength() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
2538  ImplSetSelection( Selection( 0, maUndoText.getLength() ) );
2539  maUndoText = aText;
2540  }
2541 }
2542 
2543 void Edit::SetText( const OUString& rStr )
2544 {
2545  if ( mpSubEdit )
2546  mpSubEdit->SetText( rStr ); // not directly ImplSetText if SetText overridden
2547  else
2548  {
2549  Selection aNewSel( 0, 0 ); // prevent scrolling
2550  ImplSetText( rStr, &aNewSel );
2551  }
2552 }
2553 
2554 void Edit::SetText( const OUString& rStr, const Selection& rSelection )
2555 {
2556  if ( mpSubEdit )
2557  mpSubEdit->SetText( rStr, rSelection );
2558  else
2559  ImplSetText( rStr, &rSelection );
2560 }
2561 
2562 OUString Edit::GetText() const
2563 {
2564  if ( mpSubEdit )
2565  return mpSubEdit->GetText();
2566  else
2567  return maText.toString();
2568 }
2569 
2571  ImplSetCursorPos( GetText().getLength(), false );
2572 }
2573 
2574 void Edit::SetPlaceholderText( const OUString& rStr )
2575 {
2576  if ( mpSubEdit )
2577  mpSubEdit->SetPlaceholderText( rStr );
2578  else if ( maPlaceholderText != rStr )
2579  {
2580  maPlaceholderText = rStr;
2581  if ( GetText().isEmpty() )
2582  Invalidate();
2583  }
2584 }
2585 
2587 {
2588  if ( mpSubEdit )
2589  mpSubEdit->mbModified = true;
2590  else
2591  mbModified = true;
2592 }
2593 
2595 {
2596  if ( mpSubEdit )
2597  mpSubEdit->mbModified = false;
2598  else
2599  mbModified = false;
2600 }
2601 
2603 {
2605  mpSubEdit.set(pEdit);
2606 
2607  if (mpSubEdit)
2608  {
2609  SetPointer(PointerStyle::Arrow); // Only SubEdit has the BEAM...
2610  mpSubEdit->mbIsSubEdit = true;
2611 
2614  }
2615 }
2616 
2617 Size Edit::CalcMinimumSizeForText(const OUString &rString) const
2618 {
2619  ControlType eCtrlType = ImplGetNativeControlType();
2620 
2621  Size aSize;
2622  if (mnWidthInChars != -1)
2623  {
2624  //CalcSize calls CalcWindowSize, but we will call that also in this
2625  //function, so undo the first one with CalcOutputSize
2627  }
2628  else
2629  {
2630  OUString aString;
2631  if (mnMaxWidthChars != -1 && mnMaxWidthChars < rString.getLength())
2632  aString = rString.copy(0, mnMaxWidthChars);
2633  else
2634  aString = rString;
2635 
2636  aSize.setHeight( GetTextHeight() );
2637  aSize.setWidth( GetTextWidth(aString) );
2638  aSize.AdjustWidth(ImplGetExtraXOffset() * 2 );
2639 
2640  // do not create edit fields in which one cannot enter anything
2641  // a default minimum width should exist for at least 3 characters
2642 
2643  //CalcSize calls CalcWindowSize, but we will call that also in this
2644  //function, so undo the first one with CalcOutputSize
2645  Size aMinSize(CalcOutputSize(CalcSize(3)));
2646  if (aSize.Width() < aMinSize.Width())
2647  aSize.setWidth( aMinSize.Width() );
2648  }
2649 
2650  aSize.AdjustHeight(ImplGetExtraYOffset() * 2 );
2651 
2652  aSize = CalcWindowSize( aSize );
2653 
2654  // ask NWF what if it has an opinion, too
2655  ImplControlValue aControlValue;
2656  tools::Rectangle aRect( Point( 0, 0 ), aSize );
2657  tools::Rectangle aContent, aBound;
2659  aControlValue, aBound, aContent))
2660  {
2661  if (aBound.GetHeight() > aSize.Height())
2662  aSize.setHeight( aBound.GetHeight() );
2663  }
2664  return aSize;
2665 }
2666 
2668 {
2669  return CalcMinimumSizeForText(GetText());
2670 }
2671 
2673 {
2674  vcl::Window* pDefWin = ImplGetDefaultWindow();
2675  ScopedVclPtrInstance< Edit > aEdit( pDefWin, WB_BORDER );
2676  Size aSize( aEdit->CalcMinimumSize() );
2677  return aSize;
2678 }
2679 
2681 {
2682  return CalcMinimumSize();
2683 }
2684 
2685 Size Edit::CalcSize(sal_Int32 nChars) const
2686 {
2687  // width for N characters, independent from content.
2688  // works only correct for fixed fonts, average otherwise
2689  Size aSz( GetTextWidth( "x" ), GetTextHeight() );
2690  aSz.setWidth( aSz.Width() * nChars );
2691  aSz.AdjustWidth(ImplGetExtraXOffset() * 2 );
2692  aSz = CalcWindowSize( aSz );
2693  return aSz;
2694 }
2695 
2696 sal_Int32 Edit::GetMaxVisChars() const
2697 {
2698  const vcl::Window* pW = mpSubEdit ? mpSubEdit : this;
2699  sal_Int32 nOutWidth = pW->GetOutputSizePixel().Width();
2700  sal_Int32 nCharWidth = GetTextWidth( "x" );
2701  return nCharWidth ? nOutWidth/nCharWidth : 0;
2702 }
2703 
2704 namespace vcl
2705 {
2707  {
2709  }
2710 
2712  {
2713  return pImplFncGetSpecialChars;
2714  }
2715 }
2716 
2718 {
2719  if (!mpUIBuilder)
2720  mpUIBuilder.reset(new VclBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "vcl/ui/editmenu.ui", ""));
2721  VclPtr<PopupMenu> pPopup = mpUIBuilder->get_menu("menu");
2722  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2723  if (rStyleSettings.GetHideDisabledMenuItems())
2725  else
2727  if (rStyleSettings.GetContextMenuShortcuts())
2728  {
2729  pPopup->SetAccelKey(pPopup->GetItemId("undo"), vcl::KeyCode( KeyFuncType::UNDO));
2730  pPopup->SetAccelKey(pPopup->GetItemId("cut"), vcl::KeyCode( KeyFuncType::CUT));
2731  pPopup->SetAccelKey(pPopup->GetItemId("copy"), vcl::KeyCode( KeyFuncType::COPY));
2732  pPopup->SetAccelKey(pPopup->GetItemId("paste"), vcl::KeyCode( KeyFuncType::PASTE));
2733  pPopup->SetAccelKey(pPopup->GetItemId("delete"), vcl::KeyCode( KeyFuncType::DELETE));
2734  pPopup->SetAccelKey(pPopup->GetItemId("selectall"), vcl::KeyCode( KEY_A, false, true, false, false));
2735  pPopup->SetAccelKey(pPopup->GetItemId("specialchar"), vcl::KeyCode( KEY_S, true, true, false, false));
2736  }
2737  return pPopup;
2738 }
2739 
2740 // css::datatransfer::dnd::XDragGestureListener
2741 void Edit::dragGestureRecognized( const css::datatransfer::dnd::DragGestureEvent& rDGE )
2742 {
2743  SolarMutexGuard aVclGuard;
2744 
2745  if ( !IsTracking() && maSelection.Len() &&
2746  !mbPassword && (!mpDDInfo || !mpDDInfo->bStarterOfDD) ) // no repeated D&D
2747  {
2748  Selection aSel( maSelection );
2749  aSel.Justify();
2750 
2751  // only if mouse in the selection...
2752  Point aMousePos( rDGE.DragOriginX, rDGE.DragOriginY );
2753  sal_Int32 nCharPos = ImplGetCharPos( aMousePos );
2754  if ( (nCharPos >= aSel.Min()) && (nCharPos < aSel.Max()) )
2755  {
2756  if ( !mpDDInfo )
2757  mpDDInfo.reset(new DDInfo);
2758 
2759  mpDDInfo->bStarterOfDD = true;
2760  mpDDInfo->aDndStartSel = aSel;
2761 
2762  if ( IsTracking() )
2763  EndTracking(); // before D&D disable tracking
2764 
2766  sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
2767  if ( !IsReadOnly() )
2768  nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
2769  rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mxDnDListener );
2770  if ( GetCursor() )
2771  GetCursor()->Hide();
2772 
2773  }
2774  }
2775 }
2776 
2777 // css::datatransfer::dnd::XDragSourceListener
2778 void Edit::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent& rDSDE )
2779 {
2780  SolarMutexGuard aVclGuard;
2781 
2782  if (rDSDE.DropSuccess && (rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE) && mpDDInfo)
2783  {
2784  Selection aSel( mpDDInfo->aDndStartSel );
2785  if ( mpDDInfo->bDroppedInMe )
2786  {
2787  if ( aSel.Max() > mpDDInfo->nDropPos )
2788  {
2789  long nLen = aSel.Len();
2790  aSel.Min() += nLen;
2791  aSel.Max() += nLen;
2792  }
2793  }
2795  ImplModified();
2796  }
2797 
2798  ImplHideDDCursor();
2799  mpDDInfo.reset();
2800 }
2801 
2802 // css::datatransfer::dnd::XDropTargetListener
2803 void Edit::drop( const css::datatransfer::dnd::DropTargetDropEvent& rDTDE )
2804 {
2805  SolarMutexGuard aVclGuard;
2806 
2807  bool bChanges = false;
2808  if ( !mbReadOnly && mpDDInfo )
2809  {
2810  ImplHideDDCursor();
2811 
2812  Selection aSel( maSelection );
2813  aSel.Justify();
2814 
2815  if ( aSel.Len() && !mpDDInfo->bStarterOfDD )
2817 
2818  mpDDInfo->bDroppedInMe = true;
2819 
2820  aSel.Min() = mpDDInfo->nDropPos;
2821  aSel.Max() = mpDDInfo->nDropPos;
2822  ImplSetSelection( aSel );
2823 
2824  uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
2825  if ( xDataObj.is() )
2826  {
2827  datatransfer::DataFlavor aFlavor;
2828  SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
2829  if ( xDataObj->isDataFlavorSupported( aFlavor ) )
2830  {
2831  uno::Any aData = xDataObj->getTransferData( aFlavor );
2832  OUString aText;
2833  aData >>= aText;
2834  ImplInsertText( aText );
2835  bChanges = true;
2836  ImplModified();
2837  }
2838  }
2839 
2840  if ( !mpDDInfo->bStarterOfDD )
2841  {
2842  mpDDInfo.reset();
2843  }
2844  }
2845 
2846  rDTDE.Context->dropComplete( bChanges );
2847 }
2848 
2849 void Edit::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEvent& rDTDE )
2850 {
2851  if ( !mpDDInfo )
2852  {
2853  mpDDInfo.reset(new DDInfo);
2854  }
2855  // search for string data type
2856  const Sequence< css::datatransfer::DataFlavor >& rFlavors( rDTDE.SupportedDataFlavors );
2857  mpDDInfo->bIsStringSupported = std::any_of(rFlavors.begin(), rFlavors.end(),
2858  [](const css::datatransfer::DataFlavor& rFlavor) {
2859  sal_Int32 nIndex = 0;
2860  const OUString aMimetype = rFlavor.MimeType.getToken( 0, ';', nIndex );
2861  return aMimetype == "text/plain";
2862  });
2863 }
2864 
2865 void Edit::dragExit( const css::datatransfer::dnd::DropTargetEvent& )
2866 {
2867  SolarMutexGuard aVclGuard;
2868 
2869  ImplHideDDCursor();
2870 }
2871 
2872 void Edit::dragOver( const css::datatransfer::dnd::DropTargetDragEvent& rDTDE )
2873 {
2874  SolarMutexGuard aVclGuard;
2875 
2876  Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
2877 
2878  sal_Int32 nPrevDropPos = mpDDInfo->nDropPos;
2879  mpDDInfo->nDropPos = ImplGetCharPos( aMousePos );
2880 
2881  /*
2882  Size aOutSize = GetOutputSizePixel();
2883  if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) )
2884  {
2885  // Scroll?
2886  // No, I will not receive events in this case...
2887  }
2888  */
2889 
2890  Selection aSel( maSelection );
2891  aSel.Justify();
2892 
2893  // Don't accept drop in selection or read-only field...
2894  if ( IsReadOnly() || aSel.IsInside( mpDDInfo->nDropPos ) || ! mpDDInfo->bIsStringSupported )
2895  {
2896  ImplHideDDCursor();
2897  rDTDE.Context->rejectDrag();
2898  }
2899  else
2900  {
2901  // draw the old cursor away...
2902  if ( !mpDDInfo->bVisCursor || ( nPrevDropPos != mpDDInfo->nDropPos ) )
2903  {
2904  ImplHideDDCursor();
2905  ImplShowDDCursor();
2906  }
2907  rDTDE.Context->acceptDrag( rDTDE.DropAction );
2908  }
2909 }
2910 
2912 {
2913  if (mpSubEdit)
2914  return mpSubEdit->GetSurroundingText();
2915  return maText.toString();
2916 }
2917 
2919 {
2920  return GetSelection();
2921 }
2922 
2924 {
2925  return EditUIObject::create;
2926 }
2927 
2928 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPRIVATE void ImplPaintBorder(vcl::RenderContext const &rRenderContext)
Definition: edit.cxx:993
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: edit.cxx:1716
Point TopLeft() const
virtual Size CalcMinimumSize() const
Definition: edit.cxx:2667
long Width() const
vcl::Region GetClipRegion() const
const Color & GetTextColor() const
Definition: outdev.hxx:1127
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
Definition: text.cxx:787
bool IsControlBackground() const
Definition: window2.cxx:1087
virtual void EnableRTL(bool bEnable=true) override
Definition: ctrl.cxx:65
GetFocusFlags GetGetFocusFlags() const
Definition: window2.cxx:1188
bool ImplCallEventListenersAndHandler(VclEventId nEvent, std::function< void()> const &callHandler)
this calls both our event listeners, and a specified handler
Definition: ctrl.cxx:305
void SetCompositionCharRect(const tools::Rectangle *pRect, long nCompositionLength, bool bVertical=false)
Definition: window.cxx:2142
sal_Int32 mnMaxWidthChars
Definition: edit.hxx:72
sal_uLong GetEnd() const
SAL_DLLPRIVATE void ImplInsertText(const OUString &rStr, const Selection *pNewSelection=nullptr, bool bIsUserInput=false)
Definition: edit.cxx:781
bool GetContextMenuShortcuts() const
sal_Int32 nIndex
virtual void Cut()
Definition: edit.cxx:2505
Edit(WindowType nType)
Definition: edit.cxx:148
long GetHeight() const
SAL_DLLPRIVATE long ImplGetTextYPosition() const
Definition: edit.cxx:450
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
bool IsNull() const
Definition: region.hxx:102
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
Definition: edit.cxx:364
Link< Edit &, void > maModifyHdl
Definition: edit.hxx:83
virtual void dragExit(const css::datatransfer::dnd::DropTargetEvent &dte) override
Definition: edit.cxx:2865
virtual OUString GetSelected() const
Definition: edit.cxx:2493
void SetPos(const Point &rNewPos)
Definition: cursor.cxx:394
long AdjustWidth(long n)
FncGetSpecialChars GetGetSpecialCharsFunction()
Definition: edit.cxx:2711
const char aData[]
bool GetNativeControlRegion(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion) const
Query the native control's actual drawing region (including adornment)
virtual void MouseButtonDown(const MouseEvent &rMEvt)
Definition: mouse.cxx:414
const Color & GetHighlightTextColor() const
std::unique_ptr< ContentProperties > pData
Edit * GetSubEdit() const
Definition: edit.hxx:223
#define EDIT_DELMODE_RESTOFWORD
Definition: edit.cxx:86
long Height() const
long mnXOffset
Definition: edit.hxx:67
SAL_DLLPRIVATE void ImplDrawFrame(OutputDevice *pDev, tools::Rectangle &rRect)
draws a frame around the give rectangle, onto the given device
Definition: ctrl.cxx:336
signed char sal_Int8
css::uno::Reference< css::datatransfer::clipboard::XClipboard > GetClipboard()
Definition: window.cxx:3453
bool mbForceControlBackground
Definition: edit.hxx:74
WinBits const WB_NOGROUP
virtual OUString filter(const OUString &rText)
Definition: edit.cxx:2284
virtual FactoryFunction GetUITestFactory() const override
Definition: edit.cxx:2923
constexpr::Color COL_RED(0x80, 0x00, 0x00)
void Union(const tools::Rectangle &rRegion)
Definition: region.cxx:508
SelectionOptions GetSelectionOptions() const
virtual Size CalcMinimumSizeForText(const OUString &rString) const
Definition: edit.cxx:2617
SAL_DLLPRIVATE void ImplClearLayoutData() const
Definition: ctrl.cxx:330
SelectionOptions
Definition: settings.hxx:181
long AdjustLeft(long nHorzMoveDelta)
LINESTYLE_BOLD
static FncGetSpecialChars pImplFncGetSpecialChars
Definition: edit.cxx:76
virtual ~TextFilter()
Definition: edit.cxx:2280
void disposeAndClear()
Definition: vclptr.hxx:200
sal_Int32 nPos
Definition: edit.cxx:115
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:715
constexpr sal_uInt16 KEY_A
Definition: keycodes.hxx:56
virtual void StateChanged(StateChangedType nStateChange) override
Definition: ctrl.cxx:260
SAL_DLLPRIVATE void ImplGrabFocus(GetFocusFlags nFlags)
Definition: mouse.cxx:195
sal_Int64 n
OUString maPlaceholderText
Definition: edit.hxx:64
virtual void Paste()
Definition: edit.cxx:2523
std::function< std::unique_ptr< UIObject >vcl::Window *)> FactoryFunction
virtual Size GetSizePixel() const
Definition: window.cxx:2396
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1262
WinBits const WB_RIGHT
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:554
sal_uInt16 mnAlign
Definition: edit.hxx:69
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: edit.cxx:216
void CompatStateChanged(StateChangedType nStateChange)
Definition: window.cxx:3874
bool IsShift() const
Definition: event.hxx:155
void SetEchoChar(sal_Unicode c)
Definition: edit.cxx:2340
bool mbReadOnly
Definition: edit.hxx:74
SAL_DLLPRIVATE OUString ImplGetText() const
Definition: edit.cxx:420
void SetTextFillColor()
Definition: text.cxx:700
long Len() const
sal_uInt16 GetCode() const
Definition: keycod.hxx:53
void DestroyAttribs()
Definition: edit.cxx:142
css::uno::Reference< css::datatransfer::dnd::XDragSourceListener > mxDnDListener
Definition: edit.hxx:130
vcl::Region GetPaintRegion() const
Definition: paint.cxx:1146
void SetLayoutMode(ComplexTextLayoutFlags nTextLayoutMode)
DataChangedEventType GetType() const
Definition: event.hxx:357
OUString sForbiddenChars
Definition: textfilter.hxx:18
void IntersectClipRegion(const tools::Rectangle &rRect)
sal_uInt16 Execute(vcl::Window *pWindow, const Point &rPopupPos)
Definition: menu.cxx:2764
bool bVisCursor
Definition: edit.cxx:96
SAL_DLLPRIVATE void ImplCopy(css::uno::Reference< css::datatransfer::clipboard::XClipboard > const &rxClipboard)
Definition: edit.cxx:1267
void SetPlaceholderText(const OUString &rStr)
Definition: edit.cxx:2574
KeyFuncType
Definition: keycod.hxx:29
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: edit.cxx:179
constexpr::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
const Color & GetControlBackground() const
Definition: window2.cxx:1082
virtual void drop(const css::datatransfer::dnd::DropTargetDropEvent &dtde) override
Definition: edit.cxx:2803
SAL_DLLPRIVATE void ImplShowCursor(bool bOnlyIfVisible=true)
Definition: edit.cxx:1054
static void ShowTruncationWarning(weld::Widget *pParent)
Definition: edit.cxx:762
virtual ~Edit() override
Definition: edit.cxx:211
tools::Rectangle GetBoundRect() const
Definition: region.cxx:1214
void SetType(WindowType nType)
Definition: window2.cxx:968
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
Definition: ctrl.cxx:418
bool IsMiddle() const
Definition: event.hxx:148
void PaintImmediately()
Definition: paint.cxx:1286
sal_Int32 nLen
Definition: edit.cxx:116
long AdjustHeight(long n)
void StartTracking(StartTrackingFlags nFlags=StartTrackingFlags::NONE)
Definition: window2.cxx:244
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
void SetMapMode()
Definition: map.cxx:655
const vcl::Font & GetFieldFont() const
#define EDIT_DELMODE_SIMPLE
Definition: edit.cxx:85
const Color & GetFieldTextColor() const
bool IsTracking() const
Definition: window2.cxx:312
bool bStarterOfDD
Definition: edit.cxx:94
bool mbInternModified
Definition: edit.hxx:74
virtual void ClearModifyFlag()
Definition: edit.cxx:2594
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
#define EDIT_DEL_RIGHT
Definition: edit.cxx:83
const Color & GetHighlightColor() const
bool mbPassword
Definition: edit.hxx:74
long AdjustBottom(long nVertMoveDelta)
bool bWasCursorOverwrite
Definition: edit.cxx:118
constexpr sal_uInt16 KEY_END
Definition: keycodes.hxx:115
StateChangedType
Definition: window.hxx:310
bool IsInsertMode() const
Definition: edit.cxx:2371
weld::Window * GetFrameWeld() const
Definition: window2.cxx:853
LINESTYLE_DASHDOT
A construction helper for ScopedVclPtr.
Definition: vclptr.hxx:407
sal_uInt16 GetClicks() const
Definition: event.hxx:123
sal_Int64 WinBits
sal_uInt16 sal_Unicode
virtual OUString GetSurroundingText() const override
Definition: edit.cxx:2911
void SetBackground()
Size CalcOutputSize(const Size &rWinSz) const
Definition: window2.cxx:545
virtual void FillLayoutData() const override
Definition: edit.cxx:1710
WinBits const WB_BOTTOM
WinBits const WB_TOP
SAL_DLLPRIVATE long ImplGetExtraYOffset() const
Definition: edit.cxx:408
std::unique_ptr< ExtTextInputAttr[]> pAttribs
Definition: edit.cxx:114
Creates a hierarchy of vcl::Windows (widgets) from a .ui file for dialogs, sidebar, etc.
Definition: builder.hxx:64
const vcl::Font & GetFont() const
Definition: outdev.hxx:649
A helper class that calls Application::ReleaseSolarMutex() in its constructor and restores the mutex ...
Definition: svapp.hxx:1421
sal_Int32 nDropPos
Definition: edit.cxx:93
css::uno::Reference< css::datatransfer::clipboard::XClipboard > GetPrimarySelection()
Definition: window.cxx:3462
void EndTracking(TrackingEventFlags nFlags=TrackingEventFlags::NONE)
Definition: window2.cxx:272
bool IsMouseEvent() const
SAL_DLLPRIVATE void ImplSetSelection(const Selection &rSelection, bool bPaint=true)
Definition: edit.cxx:2404
css::uno::Reference< css::i18n::XBreakIterator > mxBreakIterator
Definition: edit.hxx:88
int nCount
AllSettingsFlags GetFlags() const
Definition: event.hxx:358
void SetMenuFlags(MenuFlags nFlags)
Definition: menu.hxx:252
const CommandExtTextInputData * GetExtTextInputData() const
SAL_DLLPRIVATE css::uno::Reference< css::i18n::XBreakIterator > const & ImplGetBreakIterator()
Definition: edit.cxx:748
virtual void SetModifyFlag()
Definition: edit.cxx:2586
virtual void queue_resize(StateChangedType eReason=StateChangedType::Layout)
Definition: window2.cxx:1314
void Undo()
Definition: edit.cxx:2529
#define CURSOR_SHADOW
Definition: cursor.hxx:36
virtual void Draw(OutputDevice *pDev, const Point &rPos, DrawFlags nFlags) override
Definition: edit.cxx:1735
SAL_DLLPRIVATE bool ImplHandleKeyEvent(const KeyEvent &rKEvt)
Definition: edit.cxx:1394
sal_uLong GetStart() const
virtual void dragDropEnd(const css::datatransfer::dnd::DragSourceDropEvent &dsde) override
Definition: edit.cxx:2778
virtual const Selection & GetSelection() const
Definition: edit.cxx:2466
sal_uInt16 GetModifier() const
Definition: keycod.hxx:56
void SetUnderline(FontLineStyle)
Definition: font/font.cxx:245
virtual void MouseButtonUp(const MouseEvent &rMEvt) override
Definition: edit.cxx:1352
void SetStyle(sal_uInt16 nStyle)
Definition: cursor.cxx:358
virtual void dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent &dtdee) override
Definition: edit.cxx:2849
sal_Int32 mnMaxTextLen
Definition: edit.hxx:70
Definition: edit.cxx:89
void Move(long nHorzMove, long nVertMove)
Definition: region.cxx:414
Definition: edit.hxx:56
WinBits const WB_NOHIDESELECTION
bool IsCursorOverwrite() const
SAL_DLLPRIVATE void ImplSetCursorPos(sal_Int32 nChar, bool bSelect)
Definition: edit.cxx:1249
css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > GetDragGestureRecognizer()
Definition: mouse.cxx:784
void setMax(long nMax)
void Hide()
Definition: cursor.cxx:376
virtual void DeleteSelected()
Definition: edit.cxx:2482
sal_uInt16 nCode
virtual void SetSelection(const Selection &rSelection)
Definition: edit.cxx:2392
SAL_DLLPRIVATE void ImplHideDDCursor()
Definition: edit.cxx:2266
OUString maUndoText
Definition: edit.hxx:66
void SetTextLineColor()
Definition: textline.cxx:800
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:51
std::unique_ptr< Impl_IMEInfos > mpIMEInfos
Definition: edit.hxx:62
OUStringBuffer maText
Definition: edit.hxx:63
const LanguageTag & GetLanguageTag() const
long GetDrawPixel(::OutputDevice const *pDev, long nPixels) const
Definition: window2.cxx:563
#define SAL_N_ELEMENTS(arr)
virtual void Tracking(const TrackingEvent &rTEvt) override
Definition: edit.cxx:1369
#define EDIT_ALIGN_RIGHT
Definition: edit.cxx:80
SAL_DLLPRIVATE bool ImplUseNativeBorder(vcl::RenderContext const &rRenderContext, WinBits nStyle)
Definition: edit.cxx:283
bool mbInsertMode
Definition: edit.hxx:74
SAL_DLLPRIVATE void ImplDelete(const Selection &rSelection, sal_uInt8 nDirection, sal_uInt8 nMode)
Definition: edit.cxx:668
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
bool IsEmpty() const
Definition: region.cxx:228
Size CalcWindowSize(const Size &rOutSz) const
Definition: window2.cxx:537
long Min() const
void SetLineColor()
const OUString & GetText() const
void clear()
Definition: vclptr.hxx:190
VclPtr< PopupMenu > CreatePopupMenu()
Definition: edit.cxx:2717
Selection maSelection
Definition: edit.hxx:68
const Color & GetDisableColor() const
void Justify()
#define EDIT_ALIGN_CENTER
Definition: edit.cxx:79
bool IsRTLEnabled() const
Definition: outdev.hxx:1358
SAL_DLLPRIVATE sal_Int32 ImplGetCharPos(const Point &rWindowPos) const
Definition: edit.cxx:1183
void SetInputContext(const InputContext &rInputContext)
Definition: window.cxx:2071
virtual Size GetOptimalSize() const override
Definition: edit.cxx:2680
SAL_DLLPRIVATE void ImplShowDDCursor()
Definition: edit.cxx:2251
int i
static bool IsCharInput(const KeyEvent &rKEvt)
Definition: edit.cxx:348
DrawFlags
Definition: window.hxx:353
MouseMiddleButtonAction GetMiddleButtonAction() const
virtual void GetFocus() override
Definition: edit.cxx:1842
bool IsNativeWidgetEnabled() const
Definition: window.cxx:3725
void SetCursorRect(const tools::Rectangle *pRect=nullptr, long nExtTextInputWidth=0)
Definition: window.cxx:2107
void GetCaretPositions(const OUString &, long *pCaretXArray, sal_Int32 nIndex, sal_Int32 nLen, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1063
virtual void StateChanged(StateChangedType nType) override
Definition: edit.cxx:2152
SAL_DLLPRIVATE void ImplInvalidateOrRepaint()
Definition: edit.cxx:437
constexpr sal_uInt16 KEY_HOME
Definition: keycodes.hxx:114
SAL_DLLPRIVATE void ImplModified()
Definition: edit.cxx:358
SAL_DLLPRIVATE void ImplRepaint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRectangle)
Definition: edit.cxx:459
virtual void SetReadOnly(bool bReadOnly=true)
Definition: edit.cxx:2347
LINESTYLE_WAVE
bool mbIsSubEdit
Definition: edit.hxx:74
SAL_DLLPRIVATE void ImplCopyToSelectionClipboard()
Definition: edit.cxx:1258
SAL_DLLPRIVATE long ImplGetExtraXOffset() const
Definition: edit.cxx:396
bool mbModified
Definition: edit.hxx:74
sal_uInt16 GetItemId(sal_uInt16 nPos) const
Definition: menu.cxx:634
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1162
void SetCursorAtLast()
Definition: edit.cxx:2570
css::uno::Reference< css::datatransfer::dnd::XDropTarget > GetDropTarget()
Definition: mouse.cxx:658
Size GetOutputSize() const
Definition: outdev.hxx:450
std::unique_ptr< VclBuilder > mpUIBuilder
Definition: edit.hxx:86
virtual Selection GetSurroundingTextSelection() const override
Definition: edit.cxx:2918
vcl::Cursor aCursor
Definition: edit.cxx:91
void SetRight(long v)
static SAL_DLLPRIVATE WinBits ImplInitStyle(WinBits nStyle)
Definition: edit.cxx:338
virtual OUString GetText() const override
Definition: edit.cxx:2562
void CallEventListeners(VclEventId nEvent, void *pData=nullptr)
Definition: ctrl.cxx:297
SAL_DLLPRIVATE void ImplPaste(css::uno::Reference< css::datatransfer::clipboard::XClipboard > const &rxClipboard)
Definition: edit.cxx:1272
bool IsUpdateMode() const
Definition: window2.cxx:1173
void SetFillColor()
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:302
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
const Color & GetFieldColor() const
CommandEventId GetCommand() const
bool GetHideDisabledMenuItems() const
virtual void Modify()
Definition: edit.cxx:2312
LINESTYLE_SINGLE
float u
void SetTextColor(const Color &rColor)
Definition: text.cxx:665
bool HasPaintEvent() const
Definition: paint.cxx:1259
virtual void Resize() override
Definition: edit.cxx:1722
static bool GetLayoutRTL()
sal_Unicode mcEchoChar
Definition: edit.hxx:73
void CopyAttribs(const ExtTextInputAttr *pA, sal_Int32 nL)
Definition: edit.cxx:135
bool IsInside(long nIs) const
void Intersect(const tools::Rectangle &rRegion)
Definition: region.cxx:584
vcl::Cursor * GetCursor() const
Definition: window2.cxx:1203
bool bDroppedInMe
Definition: edit.cxx:95
void Show()
Definition: cursor.cxx:367
SAL_DLLPRIVATE void filterText()
Definition: edit.cxx:2294
void SetSubEdit(Edit *pEdit)
Definition: edit.cxx:2602
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: ctrl.cxx:59
void SetSize(const Size &rNewSize)
Definition: cursor.cxx:403
static bool toBool(const OString &rValue)
Definition: builder.cxx:77
const AllSettings & GetSettings() const
Definition: outdev.hxx:418
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
DrawTextFlags
Definition: outdev.hxx:142
static OUString getUIRootDir()
Definition: dialog.cxx:546
Sets up the buffer to have settings matching the window, and restores the original state in the dtor...
Definition: window.h:404
void ApplyControlForeground(vcl::RenderContext &rRenderContext, const Color &rDefaultColor)
Definition: window2.cxx:489
virtual bool set_property(const OString &rKey, const OUString &rValue)
Definition: window2.cxx:1431
virtual void LoseFocus()
Definition: window.cxx:1850
KeyFuncType GetFunction() const
Definition: keycod.cxx:85
Point ScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2856
void GrabFocus()
Definition: window.cxx:3006
long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
Definition: text.cxx:895
virtual void KeyInput(const KeyEvent &rKEvt) override
Definition: edit.cxx:1704
vcl::Window * GetParent() const
Definition: window2.cxx:1097
WinBits const WB_LEFT
bool IsTrackingEnded() const
Definition: event.hxx:263
void SetStyle(WinBits nStyle)
Definition: window.cxx:1957
static void CopyStringTo(const OUString &rContent, const css::uno::Reference< css::datatransfer::clipboard::XClipboard > &rxClipboard)
copies a given string to a given clipboard
Definition: unohelp2.cxx:42
Size GetSize() const
void EnableItem(sal_uInt16 nItemId, bool bEnable=true)
Definition: menu.cxx:905
constexpr sal_uInt16 KEY_RETURN
Definition: keycodes.hxx:119
WinBits const WB_NOBORDER
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1046
constexpr sal_uInt16 KEY_RIGHT
Definition: keycodes.hxx:113
const Point & GetMousePosPixel() const
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:942
OUString aOldTextAfterStartPos
Definition: edit.cxx:112
constexpr sal_uInt16 KEY_S
Definition: keycodes.hxx:74
ControlType
These types are all based on the supported variants vcl/salnativewidgets.hxx and must be kept in-sync...
virtual void KeyInput(const KeyEvent &rKEvt)
Definition: window.cxx:1800
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle, SystemParentData *pSystemParentData)
Definition: window.cxx:936
virtual Size CalcSize(sal_Int32 nChars) const
Definition: edit.cxx:2685
void SetPointer(PointerStyle)
Definition: mouse.cxx:474
SalFrame * ImplGetFrame() const
Definition: window2.cxx:848
std::unique_ptr< DDInfo, o3tl::default_delete< DDInfo > > mpDDInfo
Definition: edit.hxx:61
const CommandSelectionChangeData * GetSelectionChangeData() const
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:54
static SAL_DLLPRIVATE void ImplInvalidateOutermostBorder(vcl::Window *pWin)
Definition: edit.cxx:1826
void Erase()
Definition: wallpaper.cxx:103
bool IsShift() const
Definition: keycod.hxx:58
css::uno::Reference< css::i18n::XExtendedInputSequenceChecker > mxISC
Definition: edit.hxx:89
Link< Edit &, void > maAutocompleteHdl
Definition: edit.hxx:84
void SetWidthInChars(sal_Int32 nWidthInChars)
Definition: edit.cxx:161
bool IsCursorVisible() const
virtual void Resize() override
Definition: ctrl.cxx:74
OUString(* FncGetSpecialChars)(weld::Widget *pWin, const vcl::Font &rFont)
static Size GetMinimumEditSize()
Definition: edit.cxx:2672
long AdjustRight(long nHorzMoveDelta)
WindowType
Definition: ctrl.hxx:33
virtual void GetFocus()
Definition: window.cxx:1836
#define SAL_WARN_IF(condition, area, stream)
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: edit.cxx:2233
WinBits const WB_BORDER
unsigned char sal_uInt8
virtual void dragOver(const css::datatransfer::dnd::DropTargetDragEvent &dtde) override
Definition: edit.cxx:2872
void SetCursor(vcl::Cursor *pCursor)
Definition: window.cxx:3043
LINESTYLE_DOTTED
void SetFont(const vcl::Font &rNewFont)
std::unique_ptr< vcl::ImplControlData > mpControlData
Definition: ctrl.hxx:36
Link< Edit &, bool > maActivateHdl
Definition: edit.hxx:85
void SetInsertMode(bool bInsert)
Definition: edit.cxx:2359
WinBits const WB_READONLY
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: edit.cxx:1311
void ShowItem(sal_uInt16 nItemId, bool bVisible=true)
Definition: menu.cxx:950
Impl_IMEInfos(sal_Int32 nPos, const OUString &rOldTextAfterStartPos)
Definition: edit.cxx:126
SAL_DLLPRIVATE void ImplAlign()
Definition: edit.cxx:1134
Selection aDndStartSel
Definition: edit.cxx:92
vcl::Font GetDrawPixelFont(::OutputDevice const *pDev) const
Definition: window2.cxx:553
bool IsLeft() const
Definition: event.hxx:146
sal_Unicode GetCharCode() const
Definition: event.hxx:53
void setMaxWidthChars(sal_Int32 nWidth)
Definition: edit.cxx:170
sal_Int32 GetCursorPos() const
bool IsMod1() const
Definition: keycod.hxx:60
static std::unique_ptr< UIObject > create(vcl::Window *pWindow)
virtual void Copy()
Definition: edit.cxx:2514
Reference< XComponentContext > getProcessComponentContext()
const MouseSettings & GetMouseSettings() const
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
Definition: paint.cxx:1019
void SetAccelKey(sal_uInt16 nItemId, const vcl::KeyCode &rKeyCode)
Definition: menu.cxx:771
SAL_DLLPRIVATE void ImplClearBackground(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRectangle, long nXStart, long nXEnd)
Definition: edit.cxx:973
VclPtr< Edit > mpSubEdit
Definition: edit.hxx:59
const Point & GetPosPixel() const
Definition: event.hxx:120
bool bCursor
Definition: edit.cxx:117
double getLength(const B2DPolygon &rCandidate)
void set(reference_type *pBody)
Definition: vclptr.hxx:148
constexpr sal_uInt16 KEY_BACKSPACE
Definition: keycodes.hxx:122
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Width of the text.
Definition: text.cxx:884
WinBits const WB_TABSTOP
bool IsVisible() const
Definition: cursor.hxx:77
long getMin() const
TextFilter(const OUString &rForbiddenChars=OUString(" "))
Definition: edit.cxx:2275
void SetGetSpecialCharsFunction(FncGetSpecialChars fn)
Definition: edit.cxx:2706
SAL_DLLPRIVATE void ImplInitEditData()
Definition: edit.cxx:253
WindowType GetType() const
Definition: window2.cxx:974
#define EDIT_DELMODE_RESTOFCONTENT
Definition: edit.cxx:87
bool IsPaintTransparent() const
Definition: window2.cxx:1037
SAL_DLLPRIVATE bool ImplTruncateToMaxLen(OUString &, sal_Int32 nSelectionLen) const
Definition: edit.cxx:769
void setMin(long nMin)
WinBits const WB_CENTER
#define EDIT_ALIGN_LEFT
Definition: edit.cxx:78
bool IsEnabled() const
Definition: window2.cxx:1122
void SetLeft(long v)
DDInfo()
Definition: edit.cxx:99
virtual void SetMaxTextLen(sal_Int32 nMaxLen)
Definition: edit.cxx:2379
SAL_DLLPRIVATE void ImplAlignAndPaint()
Definition: edit.cxx:1176
OUString VclResId(const char *pId)
Definition: svdata.cxx:267
ExtTextInputAttr
WinBits GetStyle() const
Definition: window2.cxx:953
void ApplyControlFont(vcl::RenderContext &rRenderContext, const vcl::Font &rDefaultFont)
Definition: window2.cxx:449
constexpr sal_uInt16 KEY_DELETE
Definition: keycodes.hxx:125
virtual void LoseFocus() override
Definition: edit.cxx:1894
constexpr sal_uInt16 KEY_LEFT
Definition: keycodes.hxx:112
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2850
long Max() const
WinBits const WB_GROUP
virtual bool IsReadOnly() const
Definition: edit.hxx:180
virtual void SetText(const OUString &rStr) override
Definition: edit.cxx:2543
#define EDIT_DEL_LEFT
Definition: edit.cxx:82
SAL_DLLPRIVATE css::uno::Reference< css::i18n::XExtendedInputSequenceChecker > const & ImplGetInputSequenceChecker()
Definition: edit.cxx:755
constexpr sal_uInt16 KEY_INSERT
Definition: keycodes.hxx:124
virtual void Command(const CommandEvent &rCEvt)
Definition: window.cxx:1918
const MouseEvent & GetMouseEvent() const
Definition: event.hxx:259
bool IsReallyVisible() const
Definition: window2.cxx:1107
SAL_DLLPRIVATE ControlType ImplGetNativeControlType() const
Definition: edit.cxx:923
vcl::Window * ImplGetDefaultWindow()
Returns either the application window, or the default GL context window.
Definition: svdata.cxx:211
bool HasFocus() const
Definition: window.cxx:3011
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
bool mbActivePopup
Definition: edit.hxx:74
WinBits const WB_SPIN
OString GetItemIdent(sal_uInt16 nItemId) const
Definition: menu.cxx:676
bool SupportsDoubleBuffering() const
Can the widget derived from this Window do the double-buffering via RenderContext properly...
Definition: window.cxx:3836
sal_Int32 mnWidthInChars
Definition: edit.hxx:71
void setWidth(long nWidth)
WinBits const WB_NOTABSTOP
SAL_DLLPRIVATE void ImplSetText(const OUString &rStr, const Selection *pNewSelection)
Definition: edit.cxx:890
bool bIsStringSupported
Definition: edit.cxx:97
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
Definition: builder.cxx:187
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: edit.cxx:299
bool IsMod3() const
Definition: keycod.hxx:64
sal_Int32 GetMaxVisChars() const
Definition: edit.cxx:2696
sal_uInt16 nPos
static SAL_DLLPRIVATE OUString ImplGetValidString(const OUString &rString)
Definition: edit.cxx:741
bool mbClickedInSelection
Definition: edit.hxx:74
virtual void dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent &dge) override
Definition: edit.cxx:2741
#define EDIT_NOLIMIT
Definition: edit.hxx:52
TextFilter * mpFilterText
Definition: edit.hxx:60
virtual void DataChanged(const DataChangedEvent &rDCEvt)
Definition: event.cxx:35
virtual void Command(const CommandEvent &rCEvt) override
Definition: edit.cxx:1914
virtual void ReplaceSelected(const OUString &rStr)
Definition: edit.cxx:2474
bool IsMod2() const
Definition: keycod.hxx:62
static bool GetFormatDataFlavor(SotClipboardFormatId nFormat, css::datatransfer::DataFlavor &rFlavor)
void setHeight(long nHeight)
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill= '\0')
const ExtTextInputAttr * GetTextAttr() const