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