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