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