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