1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <comphelper/lok.hxx>
23 #include <vcl/IDialogRenderable.hxx>
24 #include <vcl/decoview.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/cursor.hxx>
27 #include <vcl/virdev.hxx>
28 #include <vcl/menu.hxx>
29 #include <vcl/edit.hxx>
30 #include <vcl/layout.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/settings.hxx>
33 #include <vcl/uitest/uiobject.hxx>
38 #include <controldata.hxx>
40 #include <osl/mutex.hxx>
42 #include <com/sun/star/i18n/BreakIterator.hpp>
43 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
44 #include <com/sun/star/i18n/WordType.hpp>
45 #include <cppuhelper/weak.hxx>
46 #include <com/sun/star/datatransfer/XTransferable.hpp>
47 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
48 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
51 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
52 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
54 #include <com/sun/star/i18n/InputSequenceChecker.hpp>
55 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
56 #include <com/sun/star/i18n/ScriptType.hpp>
57 #include <com/sun/star/container/XNameAccess.hpp>
59 #include <com/sun/star/uno/Any.hxx>
61 #include <comphelper/processfactory.hxx>
62 #include <comphelper/string.hxx>
64 #include <sot/exchange.hxx>
65 #include <sot/formats.hxx>
66 #include <sal/macros.h>
68 #include <vcl/unohelp.hxx>
69 #include <vcl/unohelp2.hxx>
71 #include <officecfg/Office/Common.hxx>
75 using namespace ::com::sun::star
;
76 using namespace ::com::sun::star::uno
;
77 using namespace ::com::sun::star::lang
;
80 // - Bei Tracking-Cancel DefaultSelection wieder herstellen
82 static FncGetSpecialChars pImplFncGetSpecialChars
= nullptr;
84 #define EDIT_ALIGN_LEFT 1
85 #define EDIT_ALIGN_CENTER 2
86 #define EDIT_ALIGN_RIGHT 3
88 #define EDIT_DEL_LEFT 1
89 #define EDIT_DEL_RIGHT 2
91 #define EDIT_DELMODE_SIMPLE 11
92 #define EDIT_DELMODE_RESTOFWORD 12
93 #define EDIT_DELMODE_RESTOFCONTENT 13
98 Selection aDndStartSel
;
103 bool bIsStringSupported
;
107 aCursor
.SetStyle( CURSOR_SHADOW
);
109 bStarterOfDD
= false;
110 bDroppedInMe
= false;
112 bIsStringSupported
= false;
118 OUString aOldTextAfterStartPos
;
119 std::unique_ptr
<ExtTextInputAttr
[]>
124 bool bWasCursorOverwrite
;
126 Impl_IMEInfos(sal_Int32 nPos
, const OUString
& rOldTextAfterStartPos
);
128 void CopyAttribs(const ExtTextInputAttr
* pA
, sal_Int32 nL
);
129 void DestroyAttribs();
132 Impl_IMEInfos::Impl_IMEInfos(sal_Int32 nP
, const OUString
& rOldTextAfterStartPos
)
133 : aOldTextAfterStartPos(rOldTextAfterStartPos
)
139 bWasCursorOverwrite
= false;
142 void Impl_IMEInfos::CopyAttribs(const ExtTextInputAttr
* pA
, sal_Int32 nL
)
145 pAttribs
.reset(new ExtTextInputAttr
[ nL
]);
146 memcpy( pAttribs
.get(), pA
, nL
*sizeof(ExtTextInputAttr
) );
149 void Impl_IMEInfos::DestroyAttribs()
155 Edit::Edit( WindowType nType
)
161 Edit::Edit( vcl::Window
* pParent
, WinBits nStyle
)
162 : Control( WINDOW_EDIT
)
165 ImplInit( pParent
, nStyle
);
168 void Edit::SetWidthInChars(sal_Int32 nWidthInChars
)
170 if (mnWidthInChars
!= nWidthInChars
)
172 mnWidthInChars
= nWidthInChars
;
177 void Edit::setMaxWidthChars(sal_Int32 nWidth
)
179 if (nWidth
!= mnMaxWidthChars
)
181 mnMaxWidthChars
= nWidth
;
186 bool Edit::set_property(const OString
&rKey
, const OString
&rValue
)
188 if (rKey
== "width-chars")
189 SetWidthInChars(rValue
.toInt32());
190 else if (rKey
== "max-width-chars")
191 setMaxWidthChars(rValue
.toInt32());
192 else if (rKey
== "max-length")
194 sal_Int32 nTextLen
= rValue
.toInt32();
195 SetMaxTextLen(nTextLen
== 0 ? EDIT_NOLIMIT
: nTextLen
);
197 else if (rKey
== "editable")
199 bool bReadOnly
= !toBool(rValue
);
200 SetReadOnly(bReadOnly
);
201 //disable tab to traverse into readonly editables
202 WinBits nBits
= GetStyle();
203 nBits
&= ~(WB_TABSTOP
|WB_NOTABSTOP
);
207 nBits
|= WB_NOTABSTOP
;
210 else if (rKey
== "visibility")
212 WinBits nBits
= GetStyle();
213 nBits
&= ~(WB_PASSWORD
);
215 nBits
|= WB_PASSWORD
;
218 else if (rKey
== "placeholder-text")
219 SetPlaceholderText(OStringToOUString(rValue
, RTL_TEXTENCODING_UTF8
));
221 return Control::set_property(rKey
, rValue
);
235 vcl::Cursor
* pCursor
= GetCursor();
238 SetCursor( nullptr );
243 mpIMEInfos
= nullptr;
245 delete mpUpdateDataTimer
;
246 mpUpdateDataTimer
= nullptr;
248 if ( mxDnDListener
.is() )
250 if ( GetDragGestureRecognizer().is() )
252 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mxDnDListener
, uno::UNO_QUERY
);
253 GetDragGestureRecognizer()->removeDragGestureListener( xDGL
);
255 if ( GetDropTarget().is() )
257 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( mxDnDListener
, uno::UNO_QUERY
);
258 GetDropTarget()->removeDropTargetListener( xDTL
);
261 uno::Reference
< lang::XEventListener
> xEL( mxDnDListener
, uno::UNO_QUERY
);
262 xEL
->disposing( lang::EventObject() ); // #95154# #96585# Empty Source means it's the Client
263 mxDnDListener
.clear();
266 SetType(WINDOW_WINDOW
);
268 mpSubEdit
.disposeAndClear();
272 void Edit::ImplInitEditData()
274 mpSubEdit
= VclPtr
<Edit
>();
275 mpUpdateDataTimer
= nullptr;
276 mpFilterText
= nullptr;
278 mnAlign
= EDIT_ALIGN_LEFT
;
279 mnMaxTextLen
= EDIT_NOLIMIT
;
281 mnMaxWidthChars
= -1;
283 mbInternModified
= false;
286 mbClickedInSelection
= false;
287 mbActivePopup
= false;
291 mpIMEInfos
= nullptr;
294 // --- RTL --- no default mirroring for Edit controls
295 // note: controls that use a subedit will revert this (SpinField, ComboBox)
298 vcl::unohelper::DragAndDropWrapper
* pDnDWrapper
= new vcl::unohelper::DragAndDropWrapper( this );
299 mxDnDListener
= pDnDWrapper
;
302 bool Edit::ImplUseNativeBorder(vcl::RenderContext
& rRenderContext
, WinBits nStyle
)
304 bool bRet
= rRenderContext
.IsNativeControlSupported(ImplGetNativeControlType(),
305 ControlPart::HasBackgroundTexture
)
306 && ((nStyle
& WB_BORDER
) && !(nStyle
& WB_NOBORDER
));
307 if (!bRet
&& mbIsSubEdit
)
309 vcl::Window
* pWindow
= GetParent();
310 nStyle
= pWindow
->GetStyle();
311 bRet
= pWindow
->IsNativeControlSupported(ImplGetNativeControlType(),
312 ControlPart::HasBackgroundTexture
)
313 && ((nStyle
& WB_BORDER
) && !(nStyle
& WB_NOBORDER
));
318 void Edit::ImplInit(vcl::Window
* pParent
, WinBits nStyle
)
320 nStyle
= ImplInitStyle(nStyle
);
322 if (!(nStyle
& (WB_CENTER
| WB_RIGHT
)))
325 Control::ImplInit(pParent
, nStyle
, nullptr);
327 mbReadOnly
= (nStyle
& WB_READONLY
) != 0;
329 mnAlign
= EDIT_ALIGN_LEFT
;
331 // --- RTL --- hack: right align until keyinput and cursor travelling works
333 mnAlign
= EDIT_ALIGN_RIGHT
;
335 if ( nStyle
& WB_RIGHT
)
336 mnAlign
= EDIT_ALIGN_RIGHT
;
337 else if ( nStyle
& WB_CENTER
)
338 mnAlign
= EDIT_ALIGN_CENTER
;
340 SetCursor( new vcl::Cursor
);
342 SetPointer( Pointer( PointerStyle::Text
) );
344 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mxDnDListener
, uno::UNO_QUERY
);
345 uno::Reference
< datatransfer::dnd::XDragGestureRecognizer
> xDGR
= GetDragGestureRecognizer();
348 xDGR
->addDragGestureListener( xDGL
);
349 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( mxDnDListener
, uno::UNO_QUERY
);
350 GetDropTarget()->addDropTargetListener( xDTL
);
351 GetDropTarget()->setActive( true );
352 GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE
);
356 WinBits
Edit::ImplInitStyle( WinBits nStyle
)
358 if ( !(nStyle
& WB_NOTABSTOP
) )
359 nStyle
|= WB_TABSTOP
;
360 if ( !(nStyle
& WB_NOGROUP
) )
366 bool Edit::IsCharInput( const KeyEvent
& rKeyEvent
)
368 // In the future we must use new Unicode functions for this
369 sal_Unicode cCharCode
= rKeyEvent
.GetCharCode();
370 return ((cCharCode
>= 32) && (cCharCode
!= 127) &&
371 !rKeyEvent
.GetKeyCode().IsMod3() &&
372 !rKeyEvent
.GetKeyCode().IsMod2() &&
373 !rKeyEvent
.GetKeyCode().IsMod1() );
376 void Edit::ImplModified()
382 void Edit::ApplySettings(vcl::RenderContext
& rRenderContext
)
384 Control::ApplySettings(rRenderContext
);
386 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
388 const vcl::Font
& aFont
= rStyleSettings
.GetFieldFont();
389 ApplyControlFont(rRenderContext
, aFont
);
391 ImplClearLayoutData();
393 Color aTextColor
= rStyleSettings
.GetFieldTextColor();
394 ApplyControlForeground(rRenderContext
, aTextColor
);
396 if (ImplUseNativeBorder(rRenderContext
, GetStyle()) || IsPaintTransparent())
398 // Transparent background
399 rRenderContext
.SetBackground();
400 rRenderContext
.SetFillColor();
402 else if (IsControlBackground())
404 rRenderContext
.SetBackground(GetControlBackground());
405 rRenderContext
.SetFillColor(GetControlBackground());
409 rRenderContext
.SetBackground(rStyleSettings
.GetFieldColor());
410 rRenderContext
.SetFillColor(rStyleSettings
.GetFieldColor());
414 long Edit::ImplGetExtraXOffset() const
416 // MT 09/2002: nExtraOffsetX should become a member, instead of checking every time,
417 // but I need an incompatible update for this...
418 // #94095# Use extra offset only when edit has a border
419 long nExtraOffset
= 0;
420 if( ( GetStyle() & WB_BORDER
) || ( mbIsSubEdit
&& ( GetParent()->GetStyle() & WB_BORDER
) ) )
426 long Edit::ImplGetExtraYOffset() const
428 long nExtraOffset
= 0;
429 ControlType eCtrlType
= ImplGetNativeControlType();
430 if (eCtrlType
!= ControlType::EditboxNoBorder
)
432 // add some space between text entry and border
438 OUString
Edit::ImplGetText() const
440 if ( mcEchoChar
|| (GetStyle() & WB_PASSWORD
) )
442 sal_Unicode cEchoChar
;
444 cEchoChar
= mcEchoChar
;
446 cEchoChar
= sal_Unicode(0x2022);
447 OUStringBuffer aText
;
448 comphelper::string::padToLength(aText
, maText
.getLength(), cEchoChar
);
449 return aText
.makeStringAndClear();
452 return maText
.toString();
455 void Edit::ImplInvalidateOrRepaint()
457 if( IsPaintTransparent() )
460 // FIXME: this is currently only on OS X
461 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
)
468 long Edit::ImplGetTextYPosition() const
470 if ( GetStyle() & WB_TOP
)
471 return ImplGetExtraXOffset();
472 else if ( GetStyle() & WB_BOTTOM
)
473 return GetOutputSizePixel().Height() - GetTextHeight() - ImplGetExtraXOffset();
474 return ( GetOutputSizePixel().Height() - GetTextHeight() ) / 2;
477 void Edit::ImplRepaint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRectangle
)
479 if (!IsReallyVisible())
482 ApplySettings(rRenderContext
);
484 const OUString aText
= ImplGetText();
485 const sal_Int32 nLen
= aText
.getLength();
488 std::unique_ptr
<long[]> pDXBuffer
;
489 long* pDX
= nDXBuffer
;
493 if ((size_t) (2 * nLen
) > SAL_N_ELEMENTS(nDXBuffer
))
495 pDXBuffer
.reset(new long[2 * (nLen
+ 1)]);
496 pDX
= pDXBuffer
.get();
499 GetCaretPositions(aText
, pDX
, 0, nLen
);
502 long nTH
= GetTextHeight();
503 Point
aPos(mnXOffset
, ImplGetTextYPosition());
505 vcl::Cursor
* pCursor
= GetCursor();
506 bool bVisCursor
= pCursor
&& pCursor
->IsVisible();
510 ImplClearBackground(rRenderContext
, rRectangle
, 0, GetOutputSizePixel().Width()-1);
512 bool bPaintPlaceholderText
= aText
.isEmpty() && !maPlaceholderText
.isEmpty();
514 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
516 if (!IsEnabled() || bPaintPlaceholderText
)
517 rRenderContext
.SetTextColor(rStyleSettings
.GetDisableColor());
519 // Set background color of the normal text
520 if ((GetStyle() & WB_FORCECTRLBACKGROUND
) != 0 && IsControlBackground())
522 // check if we need to set ControlBackground even in NWF case
523 rRenderContext
.Push(PushFlags::FILLCOLOR
| PushFlags::LINECOLOR
);
524 rRenderContext
.SetLineColor();
525 rRenderContext
.SetFillColor(GetControlBackground());
526 rRenderContext
.DrawRect(Rectangle(aPos
, Size(GetOutputSizePixel().Width() - 2 * mnXOffset
, GetOutputSizePixel().Height())));
527 rRenderContext
.Pop();
529 rRenderContext
.SetTextFillColor(GetControlBackground());
531 else if (IsPaintTransparent() || ImplUseNativeBorder(rRenderContext
, GetStyle()))
532 rRenderContext
.SetTextFillColor();
534 rRenderContext
.SetTextFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor());
536 ImplPaintBorder(rRenderContext
, 0, GetOutputSizePixel().Width());
538 bool bDrawSelection
= maSelection
.Len() && (HasFocus() || (GetStyle() & WB_NOHIDESELECTION
) || mbActivePopup
);
540 aPos
.X() = mnXOffset
+ ImplGetExtraXOffset();
541 if (bPaintPlaceholderText
)
543 rRenderContext
.DrawText(aPos
, maPlaceholderText
);
545 else if (!bDrawSelection
&& !mpIMEInfos
)
547 rRenderContext
.DrawText(aPos
, aText
, 0, nLen
);
551 // save graphics state
552 rRenderContext
.Push();
553 // first calculate higlighted and non highlighted clip regions
554 vcl::Region aHiglightClipRegion
;
555 vcl::Region aNormalClipRegion
;
556 Selection
aTmpSel(maSelection
);
558 // selection is highlighted
559 for(sal_Int32 i
= 0; i
< nLen
; ++i
)
561 Rectangle
aRect(aPos
, Size(10, nTH
));
562 aRect
.Left() = pDX
[2 * i
] + mnXOffset
+ ImplGetExtraXOffset();
563 aRect
.Right() = pDX
[2 * i
+ 1] + mnXOffset
+ ImplGetExtraXOffset();
565 bool bHighlight
= false;
566 if (i
>= aTmpSel
.Min() && i
< aTmpSel
.Max())
569 if (mpIMEInfos
&& mpIMEInfos
->pAttribs
&&
570 i
>= mpIMEInfos
->nPos
&& i
< (mpIMEInfos
->nPos
+mpIMEInfos
->nLen
) &&
571 (mpIMEInfos
->pAttribs
[i
- mpIMEInfos
->nPos
] & ExtTextInputAttr::Highlight
))
577 aHiglightClipRegion
.Union(aRect
);
579 aNormalClipRegion
.Union(aRect
);
582 Color aNormalTextColor
= rRenderContext
.GetTextColor();
583 rRenderContext
.SetClipRegion(aNormalClipRegion
);
585 if (IsPaintTransparent())
586 rRenderContext
.SetTextFillColor();
589 // Set background color when part of the text is selected
590 if (ImplUseNativeBorder(rRenderContext
, GetStyle()))
592 if( (GetStyle() & WB_FORCECTRLBACKGROUND
) != 0 && IsControlBackground() )
593 rRenderContext
.SetTextFillColor(GetControlBackground());
595 rRenderContext
.SetTextFillColor();
599 rRenderContext
.SetTextFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor());
602 rRenderContext
.DrawText(aPos
, aText
, 0, nLen
);
604 // draw highlighted text
605 rRenderContext
.SetClipRegion(aHiglightClipRegion
);
606 rRenderContext
.SetTextColor(rStyleSettings
.GetHighlightTextColor());
607 rRenderContext
.SetTextFillColor(rStyleSettings
.GetHighlightColor());
608 rRenderContext
.DrawText(aPos
, aText
, 0, nLen
);
610 // if IME info exists loop over portions and output different font attributes
611 if (mpIMEInfos
&& mpIMEInfos
->pAttribs
)
613 for(int n
= 0; n
< 2; n
++)
618 rRenderContext
.SetTextColor(aNormalTextColor
);
619 if (IsPaintTransparent())
620 rRenderContext
.SetTextFillColor();
622 rRenderContext
.SetTextFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor());
623 aRegion
= aNormalClipRegion
;
627 rRenderContext
.SetTextColor(rStyleSettings
.GetHighlightTextColor());
628 rRenderContext
.SetTextFillColor(rStyleSettings
.GetHighlightColor());
629 aRegion
= aHiglightClipRegion
;
632 for(int i
= 0; i
< mpIMEInfos
->nLen
; )
634 ExtTextInputAttr nAttr
= mpIMEInfos
->pAttribs
[i
];
637 while (nIndex
< mpIMEInfos
->nLen
&& mpIMEInfos
->pAttribs
[nIndex
] == nAttr
) // #112631# check nIndex before using it
639 Rectangle
aRect( aPos
, Size( 10, nTH
) );
640 aRect
.Left() = pDX
[2 * (nIndex
+ mpIMEInfos
->nPos
)] + mnXOffset
+ ImplGetExtraXOffset();
641 aRect
.Right() = pDX
[2 * (nIndex
+ mpIMEInfos
->nPos
) + 1] + mnXOffset
+ ImplGetExtraXOffset();
647 aClip
.Intersect(aRegion
);
648 if (!aClip
.IsEmpty() && nAttr
!= ExtTextInputAttr::NONE
)
650 vcl::Font aFont
= rRenderContext
.GetFont();
651 if (nAttr
& ExtTextInputAttr::Underline
)
652 aFont
.SetUnderline(LINESTYLE_SINGLE
);
653 else if (nAttr
& ExtTextInputAttr::BoldUnderline
)
654 aFont
.SetUnderline( LINESTYLE_BOLD
);
655 else if (nAttr
& ExtTextInputAttr::DottedUnderline
)
656 aFont
.SetUnderline( LINESTYLE_DOTTED
);
657 else if (nAttr
& ExtTextInputAttr::DashDotUnderline
)
658 aFont
.SetUnderline( LINESTYLE_DASHDOT
);
659 else if (nAttr
& ExtTextInputAttr::GrayWaveline
)
661 aFont
.SetUnderline(LINESTYLE_WAVE
);
662 rRenderContext
.SetTextLineColor(Color(COL_LIGHTGRAY
));
664 rRenderContext
.SetFont(aFont
);
666 if (nAttr
& ExtTextInputAttr::RedText
)
667 rRenderContext
.SetTextColor(Color(COL_RED
));
668 else if (nAttr
& ExtTextInputAttr::HalfToneText
)
669 rRenderContext
.SetTextColor(Color(COL_LIGHTGRAY
));
671 rRenderContext
.SetClipRegion(aClip
);
672 rRenderContext
.DrawText(aPos
, aText
, 0, nLen
);
678 // restore graphics state
679 rRenderContext
.Pop();
682 if (bVisCursor
&& (!mpIMEInfos
|| mpIMEInfos
->bCursor
))
686 void Edit::ImplDelete( const Selection
& rSelection
, sal_uInt8 nDirection
, sal_uInt8 nMode
)
688 const sal_Int32 nTextLen
= ImplGetText().getLength();
690 // loeschen moeglich?
691 if ( !rSelection
.Len() &&
692 (((rSelection
.Min() == 0) && (nDirection
== EDIT_DEL_LEFT
)) ||
693 ((rSelection
.Max() == nTextLen
) && (nDirection
== EDIT_DEL_RIGHT
))) )
696 ImplClearLayoutData();
698 Selection
aSelection( rSelection
);
699 aSelection
.Justify();
701 if ( !aSelection
.Len() )
703 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
704 if ( nDirection
== EDIT_DEL_LEFT
)
706 if ( nMode
== EDIT_DELMODE_RESTOFWORD
)
708 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSelection
.Min(),
709 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, true );
710 if ( aBoundary
.startPos
== aSelection
.Min() )
711 aBoundary
= xBI
->previousWord( maText
.toString(), aSelection
.Min(),
712 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
713 aSelection
.Min() = aBoundary
.startPos
;
715 else if ( nMode
== EDIT_DELMODE_RESTOFCONTENT
)
717 aSelection
.Min() = 0;
721 sal_Int32 nCount
= 1;
722 aSelection
.Min() = xBI
->previousCharacters( maText
.toString(), aSelection
.Min(),
723 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
728 if ( nMode
== EDIT_DELMODE_RESTOFWORD
)
730 i18n::Boundary aBoundary
= xBI
->nextWord( maText
.toString(), aSelection
.Max(),
731 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
732 aSelection
.Max() = aBoundary
.startPos
;
734 else if ( nMode
== EDIT_DELMODE_RESTOFCONTENT
)
736 aSelection
.Max() = nTextLen
;
740 sal_Int32 nCount
= 1;
741 aSelection
.Max() = xBI
->nextCharacters( maText
.toString(), aSelection
.Max(),
742 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
747 maText
.remove( static_cast<sal_Int32
>(aSelection
.Min()), static_cast<sal_Int32
>(aSelection
.Len()) );
748 maSelection
.Min() = aSelection
.Min();
749 maSelection
.Max() = aSelection
.Min();
751 mbInternModified
= true;
754 OUString
Edit::ImplGetValidString( const OUString
& rString
)
756 OUString
aValidString( rString
);
757 aValidString
= aValidString
.replaceAll("\n", "").replaceAll("\r", "");
758 aValidString
= aValidString
.replace('\t', ' ');
762 uno::Reference
< i18n::XBreakIterator
> Edit::ImplGetBreakIterator()
764 //!! since we don't want to become incompatible in the next minor update
765 //!! where this code will get integrated into, xISC will be a local
766 //!! variable instead of a class member!
767 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
768 return i18n::BreakIterator::create(xContext
);
771 uno::Reference
< i18n::XExtendedInputSequenceChecker
> const & Edit::ImplGetInputSequenceChecker()
775 mxISC
= i18n::InputSequenceChecker::create(
776 ::comphelper::getProcessComponentContext() );
781 void Edit::ShowTruncationWarning( vcl::Window
* pParent
)
783 ResMgr
* pResMgr
= ImplGetResMgr();
786 ScopedVclPtrInstance
< MessageDialog
> aBox( pParent
, ResId(SV_EDIT_WARNING_STR
, *pResMgr
), VclMessageType::Warning
);
791 bool Edit::ImplTruncateToMaxLen( OUString
& rStr
, sal_Int32 nSelectionLen
) const
793 bool bWasTruncated
= false;
794 if (maText
.getLength() - nSelectionLen
> mnMaxTextLen
- rStr
.getLength())
796 sal_Int32 nErasePos
= mnMaxTextLen
- maText
.getLength() + nSelectionLen
;
797 rStr
= rStr
.copy( 0, nErasePos
);
798 bWasTruncated
= true;
800 return bWasTruncated
;
803 void Edit::ImplInsertText( const OUString
& rStr
, const Selection
* pNewSel
, bool bIsUserInput
)
805 Selection
aSelection( maSelection
);
806 aSelection
.Justify();
808 OUString
aNewText( ImplGetValidString( rStr
) );
809 ImplTruncateToMaxLen( aNewText
, aSelection
.Len() );
811 ImplClearLayoutData();
813 if ( aSelection
.Len() )
814 maText
.remove( static_cast<sal_Int32
>(aSelection
.Min()), static_cast<sal_Int32
>(aSelection
.Len()) );
815 else if ( !mbInsertMode
&& (aSelection
.Max() < maText
.getLength()) )
816 maText
.remove( static_cast<sal_Int32
>(aSelection
.Max()), 1 );
818 // take care of input-sequence-checking now
819 if (bIsUserInput
&& !rStr
.isEmpty())
821 SAL_WARN_IF( rStr
.getLength() != 1, "vcl", "unexpected string length. User input is expected to provide 1 char only!" );
823 // determine if input-sequence-checking should be applied or not
825 uno::Reference
< i18n::XBreakIterator
> xBI( ImplGetBreakIterator(), UNO_QUERY
);
826 bool bIsInputSequenceChecking
= rStr
.getLength() == 1 &&
827 officecfg::Office::Common::I18N::CTL::CTLFont::get() &&
828 officecfg::Office::Common::I18N::CTL::CTLSequenceChecking::get() &&
829 aSelection
.Min() > 0 && /* first char needs not to be checked */
830 xBI
.is() && i18n::ScriptType::COMPLEX
== xBI
->getScriptType( rStr
, 0 );
832 uno::Reference
< i18n::XExtendedInputSequenceChecker
> xISC
;
833 if (bIsInputSequenceChecking
&& (xISC
= ImplGetInputSequenceChecker()).is())
835 sal_Unicode cChar
= rStr
[0];
836 sal_Int32 nTmpPos
= static_cast< sal_Int32
>( aSelection
.Min() );
837 sal_Int16 nCheckMode
= officecfg::Office::Common::I18N::CTL::CTLSequenceCheckingRestricted::get()?
838 i18n::InputSequenceCheckMode::STRICT
: i18n::InputSequenceCheckMode::BASIC
;
840 // the text that needs to be checked is only the one
841 // before the current cursor position
842 const OUString
aOldText( maText
.getStr(), nTmpPos
);
843 OUString
aTmpText( aOldText
);
844 if (officecfg::Office::Common::I18N::CTL::CTLSequenceCheckingTypeAndReplace::get())
846 xISC
->correctInputSequence( aTmpText
, nTmpPos
- 1, cChar
, nCheckMode
);
848 // find position of first character that has changed
849 sal_Int32 nOldLen
= aOldText
.getLength();
850 sal_Int32 nTmpLen
= aTmpText
.getLength();
851 const sal_Unicode
*pOldTxt
= aOldText
.getStr();
852 const sal_Unicode
*pTmpTxt
= aTmpText
.getStr();
853 sal_Int32 nChgPos
= 0;
854 while ( nChgPos
< nOldLen
&& nChgPos
< nTmpLen
&&
855 pOldTxt
[nChgPos
] == pTmpTxt
[nChgPos
] )
858 const OUString
aChgText( aTmpText
.copy( nChgPos
) );
860 // remove text from first pos to be changed to current pos
861 maText
.remove( nChgPos
, nTmpPos
- nChgPos
);
863 if (!aChgText
.isEmpty())
866 aSelection
.Min() = nChgPos
; // position for new text to be inserted
873 // should the character be ignored (i.e. not get inserted) ?
874 if (!xISC
->checkInputSequence( aOldText
, nTmpPos
- 1, cChar
, nCheckMode
))
879 // at this point now we will insert the non-empty text 'normally' some lines below...
882 if ( !aNewText
.isEmpty() )
883 maText
.insert( static_cast<sal_Int32
>(aSelection
.Min()), aNewText
);
887 maSelection
.Min() = aSelection
.Min() + aNewText
.getLength();
888 maSelection
.Max() = maSelection
.Min();
892 maSelection
= *pNewSel
;
893 if ( maSelection
.Min() > maText
.getLength() )
894 maSelection
.Min() = maText
.getLength();
895 if ( maSelection
.Max() > maText
.getLength() )
896 maSelection
.Max() = maText
.getLength();
900 mbInternModified
= true;
903 void Edit::ImplSetText( const OUString
& rText
, const Selection
* pNewSelection
)
905 // we delete text by "selecting" the old text completely then calling InsertText; this is flicker free
906 if ( ( rText
.getLength() <= mnMaxTextLen
) &&
907 ( (rText
!= maText
.getStr()) || (pNewSelection
&& (*pNewSelection
!= maSelection
)) ) )
909 ImplClearLayoutData();
910 maSelection
.Min() = 0;
911 maSelection
.Max() = maText
.getLength();
912 if ( mnXOffset
|| HasPaintEvent() )
915 maText
= ImplGetValidString( rText
);
917 // #i54929# recalculate mnXOffset before ImplSetSelection,
918 // else cursor ends up in wrong position
922 ImplSetSelection( *pNewSelection
, false );
924 if ( mnXOffset
&& !pNewSelection
)
925 maSelection
.Max() = 0;
930 ImplInsertText( rText
, pNewSelection
);
932 CallEventListeners( VCLEVENT_EDIT_MODIFY
);
936 ControlType
Edit::ImplGetNativeControlType() const
938 ControlType nCtrl
= ControlType::Generic
;
939 const vcl::Window
* pControl
= mbIsSubEdit
? GetParent() : this;
941 switch (pControl
->GetType())
943 case WINDOW_COMBOBOX
:
944 case WINDOW_PATTERNBOX
:
945 case WINDOW_NUMERICBOX
:
946 case WINDOW_METRICBOX
:
947 case WINDOW_CURRENCYBOX
:
950 case WINDOW_LONGCURRENCYBOX
:
951 nCtrl
= ControlType::Combobox
;
954 case WINDOW_MULTILINEEDIT
:
955 if ( GetWindow( GetWindowType::Border
) != this )
956 nCtrl
= ControlType::MultilineEditbox
;
958 nCtrl
= ControlType::EditboxNoBorder
;
962 case WINDOW_PATTERNFIELD
:
963 case WINDOW_METRICFIELD
:
964 case WINDOW_CURRENCYFIELD
:
965 case WINDOW_DATEFIELD
:
966 case WINDOW_TIMEFIELD
:
967 case WINDOW_LONGCURRENCYFIELD
:
968 case WINDOW_NUMERICFIELD
:
969 case WINDOW_SPINFIELD
:
970 if (pControl
->GetStyle() & WB_SPIN
)
971 nCtrl
= ControlType::Spinbox
;
974 if (GetWindow(GetWindowType::Border
) != this)
975 nCtrl
= ControlType::Editbox
;
977 nCtrl
= ControlType::EditboxNoBorder
;
982 nCtrl
= ControlType::Editbox
;
987 void Edit::ImplClearBackground(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRectangle
, long nXStart
, long nXEnd
)
990 * note: at this point the cursor must be switched off already
993 Rectangle
aRect(aTmpPoint
, GetOutputSizePixel());
994 aRect
.Left() = nXStart
;
995 aRect
.Right() = nXEnd
;
997 if( !(ImplUseNativeBorder(rRenderContext
, GetStyle()) || IsPaintTransparent()))
998 rRenderContext
.Erase(aRect
);
999 else if (SupportsDoubleBuffering() && mbIsSubEdit
)
1001 // ImplPaintBorder() is a NOP, we have a native border, and this is a sub-edit of a control.
1002 // That means we have to draw the parent native widget to paint the edit area to clear our background.
1003 PaintBufferGuard
g(ImplGetWindowImpl()->mpFrameData
, GetParent());
1004 GetParent()->Paint(rRenderContext
, rRectangle
);
1008 void Edit::ImplPaintBorder(vcl::RenderContext
& rRenderContext
, long nXStart
, long nXEnd
)
1010 // this is not needed when double-buffering
1011 if (SupportsDoubleBuffering())
1015 Rectangle
aRect(aTmpPoint
, GetOutputSizePixel());
1016 aRect
.Left() = nXStart
;
1017 aRect
.Right() = nXEnd
;
1019 if (ImplUseNativeBorder(rRenderContext
, GetStyle()) || IsPaintTransparent())
1021 // draw the inner part by painting the whole control using its border window
1022 vcl::Window
* pBorder
= GetWindow(GetWindowType::Border
);
1023 if (pBorder
== this)
1025 // we have no border, use parent
1026 vcl::Window
* pControl
= mbIsSubEdit
? GetParent() : this;
1027 pBorder
= pControl
->GetWindow(GetWindowType::Border
);
1028 if (pBorder
== this)
1029 pBorder
= GetParent();
1034 // set proper clipping region to not overdraw the whole control
1035 vcl::Region aClipRgn
= GetPaintRegion();
1036 if (!aClipRgn
.IsNull())
1038 // transform clipping region to border window's coordinate system
1039 if (IsRTLEnabled() != pBorder
->IsRTLEnabled() && AllSettings::GetLayoutRTL())
1041 // need to mirror in case border is not RTL but edit is (or vice versa)
1044 Rectangle
aBounds(aClipRgn
.GetBoundRect());
1045 int xNew
= GetOutputSizePixel().Width() - aBounds
.GetWidth() - aBounds
.Left();
1046 aClipRgn
.Move(xNew
- aBounds
.Left(), 0);
1048 // move offset of border window
1050 aBorderOffs
= pBorder
->ScreenToOutputPixel(OutputToScreenPixel(aBorderOffs
));
1051 aClipRgn
.Move(aBorderOffs
.X(), aBorderOffs
.Y());
1057 aBorderOffs
= pBorder
->ScreenToOutputPixel(OutputToScreenPixel(aBorderOffs
));
1058 aClipRgn
.Move(aBorderOffs
.X(), aBorderOffs
.Y());
1061 vcl::Region
oldRgn(pBorder
->GetClipRegion());
1062 pBorder
->SetClipRegion(aClipRgn
);
1064 pBorder
->Paint(*pBorder
, Rectangle());
1066 pBorder
->SetClipRegion(oldRgn
);
1070 pBorder
->Paint(*pBorder
, Rectangle());
1076 void Edit::ImplShowCursor( bool bOnlyIfVisible
)
1078 if ( !IsUpdateMode() || ( bOnlyIfVisible
&& !IsReallyVisible() ) )
1081 vcl::Cursor
* pCursor
= GetCursor();
1082 OUString aText
= ImplGetText();
1086 long nDXBuffer
[256];
1087 std::unique_ptr
<long[]> pDXBuffer
;
1088 long* pDX
= nDXBuffer
;
1090 if( !aText
.isEmpty() )
1092 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
1094 pDXBuffer
.reset(new long[2*(aText
.getLength()+1)]);
1095 pDX
= pDXBuffer
.get();
1098 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
1100 if( maSelection
.Max() < aText
.getLength() )
1101 nTextPos
= pDX
[ 2*maSelection
.Max() ];
1103 nTextPos
= pDX
[ 2*aText
.getLength()-1 ];
1106 long nCursorWidth
= 0;
1107 if ( !mbInsertMode
&& !maSelection
.Len() && (maSelection
.Max() < aText
.getLength()) )
1108 nCursorWidth
= GetTextWidth(aText
, maSelection
.Max(), 1);
1109 long nCursorPosX
= nTextPos
+ mnXOffset
+ ImplGetExtraXOffset();
1111 // cursor should land in visible area
1112 const Size aOutSize
= GetOutputSizePixel();
1113 if ( (nCursorPosX
< 0) || (nCursorPosX
>= aOutSize
.Width()) )
1115 long nOldXOffset
= mnXOffset
;
1117 if ( nCursorPosX
< 0 )
1119 mnXOffset
= - nTextPos
;
1121 mnXOffset
+= aOutSize
.Width() / 5;
1122 if ( mnXOffset
> nMaxX
)
1127 mnXOffset
= (aOutSize
.Width()-ImplGetExtraXOffset()) - nTextPos
;
1129 if ( (aOutSize
.Width()-ImplGetExtraXOffset()) < nTextPos
)
1131 long nMaxNegX
= (aOutSize
.Width()-ImplGetExtraXOffset()) - GetTextWidth( aText
);
1132 mnXOffset
-= aOutSize
.Width() / 5;
1133 if ( mnXOffset
< nMaxNegX
) // beides negativ...
1134 mnXOffset
= nMaxNegX
;
1138 nCursorPosX
= nTextPos
+ mnXOffset
+ ImplGetExtraXOffset();
1139 if ( nCursorPosX
== aOutSize
.Width() ) // dann nicht sichtbar...
1142 if ( mnXOffset
!= nOldXOffset
)
1143 ImplInvalidateOrRepaint();
1146 const long nTextHeight
= GetTextHeight();
1147 const long nCursorPosY
= ImplGetTextYPosition();
1150 pCursor
->SetPos( Point( nCursorPosX
, nCursorPosY
) );
1151 pCursor
->SetSize( Size( nCursorWidth
, nTextHeight
) );
1156 void Edit::ImplAlign()
1158 long nTextWidth
= GetTextWidth( ImplGetText() );
1159 long nOutWidth
= GetOutputSizePixel().Width();
1161 if ( mnAlign
== EDIT_ALIGN_LEFT
)
1163 if( mnXOffset
&& ( nTextWidth
< nOutWidth
) )
1167 else if ( mnAlign
== EDIT_ALIGN_RIGHT
)
1169 long nMinXOffset
= nOutWidth
- nTextWidth
- 1 - ImplGetExtraXOffset();
1170 bool bRTL
= IsRTLEnabled();
1171 if( mbIsSubEdit
&& GetParent() )
1172 bRTL
= GetParent()->IsRTLEnabled();
1175 if( nTextWidth
< nOutWidth
)
1176 mnXOffset
= nMinXOffset
;
1180 if( nTextWidth
< nOutWidth
)
1181 mnXOffset
= nMinXOffset
;
1182 else if ( mnXOffset
< nMinXOffset
)
1183 mnXOffset
= nMinXOffset
;
1186 else if( mnAlign
== EDIT_ALIGN_CENTER
)
1188 // would be nicer with check while scrolling but then it's not centred in scrolled state
1189 mnXOffset
= (nOutWidth
- nTextWidth
) / 2;
1193 void Edit::ImplAlignAndPaint()
1196 ImplInvalidateOrRepaint();
1200 sal_Int32
Edit::ImplGetCharPos( const Point
& rWindowPos
) const
1202 sal_Int32 nIndex
= EDIT_NOLIMIT
;
1203 OUString aText
= ImplGetText();
1205 long nDXBuffer
[256];
1206 std::unique_ptr
<long[]> pDXBuffer
;
1207 long* pDX
= nDXBuffer
;
1208 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
1210 pDXBuffer
.reset(new long[2*(aText
.getLength()+1)]);
1211 pDX
= pDXBuffer
.get();
1214 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
1215 long nX
= rWindowPos
.X() - mnXOffset
- ImplGetExtraXOffset();
1216 for( sal_Int32 i
= 0; i
< aText
.getLength(); i
++ )
1218 if( (pDX
[2*i
] >= nX
&& pDX
[2*i
+1] <= nX
) ||
1219 (pDX
[2*i
+1] >= nX
&& pDX
[2*i
] <= nX
))
1222 if( pDX
[2*i
] < pDX
[2*i
+1] )
1224 if( nX
> (pDX
[2*i
]+pDX
[2*i
+1])/2 )
1229 if( nX
< (pDX
[2*i
]+pDX
[2*i
+1])/2 )
1235 if( nIndex
== EDIT_NOLIMIT
)
1238 long nDiff
= std::abs( pDX
[0]-nX
);
1239 for( sal_Int32 i
= 1; i
< aText
.getLength(); i
++ )
1241 long nNewDiff
= std::abs( pDX
[2*i
]-nX
);
1243 if( nNewDiff
< nDiff
)
1249 if( nIndex
== aText
.getLength()-1 && std::abs( pDX
[2*nIndex
+1] - nX
) < nDiff
)
1250 nIndex
= EDIT_NOLIMIT
;
1256 void Edit::ImplSetCursorPos( sal_Int32 nChar
, bool bSelect
)
1258 Selection
aSelection( maSelection
);
1259 aSelection
.Max() = nChar
;
1261 aSelection
.Min() = aSelection
.Max();
1262 ImplSetSelection( aSelection
);
1265 void Edit::ImplCopyToSelectionClipboard()
1267 if ( GetSelection().Len() )
1269 css::uno::Reference
<css::datatransfer::clipboard::XClipboard
> aSelection(GetPrimarySelection());
1270 ImplCopy( aSelection
);
1274 void Edit::ImplCopy( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1276 vcl::unohelper::TextDataObject::CopyStringTo( GetSelected(), rxClipboard
);
1279 void Edit::ImplPaste( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1281 if ( rxClipboard
.is() )
1283 uno::Reference
< datatransfer::XTransferable
> xDataObj
;
1287 SolarMutexReleaser aReleaser
;
1288 xDataObj
= rxClipboard
->getContents();
1290 catch( const css::uno::Exception
& )
1294 if ( xDataObj
.is() )
1296 datatransfer::DataFlavor aFlavor
;
1297 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING
, aFlavor
);
1300 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
1303 if( ImplTruncateToMaxLen( aText
, maSelection
.Len() ) )
1304 ShowTruncationWarning( this );
1305 ReplaceSelected( aText
);
1307 catch( const css::uno::Exception
& )
1314 void Edit::MouseButtonDown( const MouseEvent
& rMEvt
)
1318 Control::MouseButtonDown( rMEvt
);
1322 sal_Int32 nCharPos
= ImplGetCharPos( rMEvt
.GetPosPixel() );
1323 Selection
aSelection( maSelection
);
1324 aSelection
.Justify();
1326 if ( rMEvt
.GetClicks() < 4 )
1328 mbClickedInSelection
= false;
1329 if ( rMEvt
.GetClicks() == 3 )
1331 ImplSetSelection( Selection( 0, EDIT_NOLIMIT
) );
1332 ImplCopyToSelectionClipboard();
1335 else if ( rMEvt
.GetClicks() == 2 )
1337 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
1338 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSelection
.Max(),
1339 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, true );
1340 ImplSetSelection( Selection( aBoundary
.startPos
, aBoundary
.endPos
) );
1341 ImplCopyToSelectionClipboard();
1343 else if ( !rMEvt
.IsShift() && HasFocus() && aSelection
.IsInside( nCharPos
) )
1344 mbClickedInSelection
= true;
1345 else if ( rMEvt
.IsLeft() )
1346 ImplSetCursorPos( nCharPos
, rMEvt
.IsShift() );
1348 if ( !mbClickedInSelection
&& rMEvt
.IsLeft() && ( rMEvt
.GetClicks() == 1 ) )
1349 StartTracking( StartTrackingFlags::ScrollRepeat
);
1352 mbInMBDown
= true; // then do not select all in GetFocus
1357 void Edit::MouseButtonUp( const MouseEvent
& rMEvt
)
1359 if ( mbClickedInSelection
&& rMEvt
.IsLeft() )
1361 sal_Int32 nCharPos
= ImplGetCharPos( rMEvt
.GetPosPixel() );
1362 ImplSetCursorPos( nCharPos
, false );
1363 mbClickedInSelection
= false;
1365 else if ( rMEvt
.IsMiddle() && !mbReadOnly
&&
1366 ( GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection
) )
1368 css::uno::Reference
<css::datatransfer::clipboard::XClipboard
> aSelection(Window::GetPrimarySelection());
1369 ImplPaste( aSelection
);
1374 void Edit::Tracking( const TrackingEvent
& rTEvt
)
1376 if ( rTEvt
.IsTrackingEnded() )
1378 if ( mbClickedInSelection
)
1380 sal_Int32 nCharPos
= ImplGetCharPos( rTEvt
.GetMouseEvent().GetPosPixel() );
1381 ImplSetCursorPos( nCharPos
, false );
1382 mbClickedInSelection
= false;
1384 else if ( rTEvt
.GetMouseEvent().IsLeft() )
1386 ImplCopyToSelectionClipboard();
1391 if( !mbClickedInSelection
)
1393 sal_Int32 nCharPos
= ImplGetCharPos( rTEvt
.GetMouseEvent().GetPosPixel() );
1394 ImplSetCursorPos( nCharPos
, true );
1398 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1399 mpUpdateDataTimer
->Start();//do not update while the user is still travelling in the control
1402 bool Edit::ImplHandleKeyEvent( const KeyEvent
& rKEvt
)
1405 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1406 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
1408 mbInternModified
= false;
1410 if ( eFunc
!= KeyFuncType::DONTKNOW
)
1414 case KeyFuncType::CUT
:
1416 if ( !mbReadOnly
&& maSelection
.Len() && !(GetStyle() & WB_PASSWORD
) )
1425 case KeyFuncType::COPY
:
1427 if ( !(GetStyle() & WB_PASSWORD
) )
1435 case KeyFuncType::PASTE
:
1445 case KeyFuncType::UNDO
:
1456 eFunc
= KeyFuncType::DONTKNOW
;
1460 if ( !bDone
&& rKEvt
.GetKeyCode().IsMod1() && !rKEvt
.GetKeyCode().IsMod2() )
1462 if ( nCode
== KEY_A
)
1464 ImplSetSelection( Selection( 0, maText
.getLength() ) );
1467 else if ( rKEvt
.GetKeyCode().IsShift() && (nCode
== KEY_S
) )
1469 if ( pImplFncGetSpecialChars
)
1471 Selection aSaveSel
= GetSelection(); // if someone changes the selection in Get/LoseFocus, e.g. URL bar
1472 OUString aChars
= pImplFncGetSpecialChars( this, GetFont() );
1473 SetSelection( aSaveSel
);
1474 if ( !aChars
.isEmpty() )
1476 ImplInsertText( aChars
);
1484 if ( eFunc
== KeyFuncType::DONTKNOW
&& ! bDone
)
1488 case css::awt::Key::SELECT_ALL
:
1490 ImplSetSelection( Selection( 0, maText
.getLength() ) );
1499 case css::awt::Key::MOVE_WORD_FORWARD
:
1500 case css::awt::Key::SELECT_WORD_FORWARD
:
1501 case css::awt::Key::MOVE_WORD_BACKWARD
:
1502 case css::awt::Key::SELECT_WORD_BACKWARD
:
1503 case css::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1504 case css::awt::Key::MOVE_TO_END_OF_LINE
:
1505 case css::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1506 case css::awt::Key::SELECT_TO_END_OF_LINE
:
1507 case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1508 case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1509 case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1510 case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1511 case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1512 case css::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1513 case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1514 case css::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1516 if ( !rKEvt
.GetKeyCode().IsMod2() )
1518 ImplClearLayoutData();
1519 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
1521 Selection
aSel( maSelection
);
1522 bool bWord
= rKEvt
.GetKeyCode().IsMod1();
1523 bool bSelect
= rKEvt
.GetKeyCode().IsShift();
1524 bool bGoLeft
= (nCode
== KEY_LEFT
);
1525 bool bGoRight
= (nCode
== KEY_RIGHT
);
1526 bool bGoHome
= (nCode
== KEY_HOME
);
1527 bool bGoEnd
= (nCode
== KEY_END
);
1531 case css::awt::Key::MOVE_WORD_FORWARD
:
1532 bGoRight
= bWord
= true;break;
1533 case css::awt::Key::SELECT_WORD_FORWARD
:
1534 bGoRight
= bSelect
= bWord
= true;break;
1535 case css::awt::Key::MOVE_WORD_BACKWARD
:
1536 bGoLeft
= bWord
= true;break;
1537 case css::awt::Key::SELECT_WORD_BACKWARD
:
1538 bGoLeft
= bSelect
= bWord
= true;break;
1539 case css::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1540 case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1541 case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1544 case css::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1545 case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1546 case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1547 bGoHome
= true;break;
1548 case css::awt::Key::SELECT_TO_END_OF_LINE
:
1549 case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1550 case css::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1553 case css::awt::Key::MOVE_TO_END_OF_LINE
:
1554 case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1555 case css::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1556 bGoEnd
= true;break;
1561 // Range wird in ImplSetSelection geprueft...
1562 if ( bGoLeft
&& aSel
.Max() )
1566 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSel
.Max(),
1567 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, true );
1568 if ( aBoundary
.startPos
== aSel
.Max() )
1569 aBoundary
= xBI
->previousWord( maText
.toString(), aSel
.Max(),
1570 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1571 aSel
.Max() = aBoundary
.startPos
;
1575 sal_Int32 nCount
= 1;
1576 aSel
.Max() = xBI
->previousCharacters( maText
.toString(), aSel
.Max(),
1577 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
1580 else if ( bGoRight
&& ( aSel
.Max() < maText
.getLength() ) )
1584 i18n::Boundary aBoundary
= xBI
->nextWord( maText
.toString(), aSel
.Max(),
1585 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1586 aSel
.Max() = aBoundary
.startPos
;
1590 sal_Int32 nCount
= 1;
1591 aSel
.Max() = xBI
->nextCharacters( maText
.toString(), aSel
.Max(),
1592 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
1601 aSel
.Max() = EDIT_NOLIMIT
;
1605 aSel
.Min() = aSel
.Max();
1607 if ( aSel
!= GetSelection() )
1609 ImplSetSelection( aSel
);
1610 ImplCopyToSelectionClipboard();
1613 if (bGoEnd
&& maAutocompleteHdl
.IsSet() && !rKEvt
.GetKeyCode().GetModifier())
1615 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
1617 maAutocompleteHdl
.Call(*this);
1626 case css::awt::Key::DELETE_WORD_BACKWARD
:
1627 case css::awt::Key::DELETE_WORD_FORWARD
:
1628 case css::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
1629 case css::awt::Key::DELETE_TO_END_OF_LINE
:
1633 if ( !mbReadOnly
&& !rKEvt
.GetKeyCode().IsMod2() )
1635 sal_uInt8 nDel
= (nCode
== KEY_DELETE
) ? EDIT_DEL_RIGHT
: EDIT_DEL_LEFT
;
1636 sal_uInt8 nMode
= rKEvt
.GetKeyCode().IsMod1() ? EDIT_DELMODE_RESTOFWORD
: EDIT_DELMODE_SIMPLE
;
1637 if ( (nMode
== EDIT_DELMODE_RESTOFWORD
) && rKEvt
.GetKeyCode().IsShift() )
1638 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1641 case css::awt::Key::DELETE_WORD_BACKWARD
:
1642 nDel
= EDIT_DEL_LEFT
;
1643 nMode
= EDIT_DELMODE_RESTOFWORD
;
1645 case css::awt::Key::DELETE_WORD_FORWARD
:
1646 nDel
= EDIT_DEL_RIGHT
;
1647 nMode
= EDIT_DELMODE_RESTOFWORD
;
1649 case css::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
1650 nDel
= EDIT_DEL_LEFT
;
1651 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1653 case css::awt::Key::DELETE_TO_END_OF_LINE
:
1654 nDel
= EDIT_DEL_RIGHT
;
1655 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1659 sal_Int32 nOldLen
= maText
.getLength();
1660 ImplDelete( maSelection
, nDel
, nMode
);
1661 if ( maText
.getLength() != nOldLen
)
1670 if ( !mpIMEInfos
&& !mbReadOnly
&& !rKEvt
.GetKeyCode().IsMod2() )
1672 SetInsertMode( !mbInsertMode
);
1680 if ( IsCharInput( rKEvt
) )
1682 bDone
= true; // read characters also when in ReadOnly
1685 ImplInsertText(OUString(rKEvt
.GetCharCode()), nullptr, true);
1686 if (maAutocompleteHdl
.IsSet())
1688 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
1690 maAutocompleteHdl
.Call(*this);
1699 if ( mbInternModified
)
1705 void Edit::KeyInput( const KeyEvent
& rKEvt
)
1707 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1708 mpUpdateDataTimer
->Start();//do not update while the user is still travelling in the control
1710 if ( mpSubEdit
|| !ImplHandleKeyEvent( rKEvt
) )
1711 Control::KeyInput( rKEvt
);
1714 void Edit::FillLayoutData() const
1716 mpControlData
->mpLayoutData
.reset( new vcl::ControlLayoutData
);
1717 const_cast<Edit
*>(this)->Invalidate();
1720 void Edit::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRectangle
)
1723 ImplRepaint(rRenderContext
, rRectangle
);
1728 if ( !mpSubEdit
&& IsReallyVisible() )
1731 // Wegen vertikaler Zentrierung...
1739 void Edit::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, DrawFlags nFlags
)
1741 ApplySettings(*pDev
);
1743 Point aPos
= pDev
->LogicToPixel( rPos
);
1744 Size aSize
= pDev
->LogicToPixel( rSize
);
1745 vcl::Font aFont
= GetDrawPixelFont( pDev
);
1746 OutDevType eOutDevType
= pDev
->GetOutDevType();
1750 pDev
->SetFont( aFont
);
1751 pDev
->SetTextFillColor();
1753 // Border/Background
1754 pDev
->SetLineColor();
1755 pDev
->SetFillColor();
1756 bool bBorder
= !(nFlags
& DrawFlags::NoBorder
) && (GetStyle() & WB_BORDER
);
1757 bool bBackground
= !(nFlags
& DrawFlags::NoBackground
) && IsControlBackground();
1758 if ( bBorder
|| bBackground
)
1760 Rectangle
aRect( aPos
, aSize
);
1763 ImplDrawFrame( pDev
, aRect
);
1767 pDev
->SetFillColor( GetControlBackground() );
1768 pDev
->DrawRect( aRect
);
1773 if ( ( nFlags
& DrawFlags::Mono
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1774 pDev
->SetTextColor( Color( COL_BLACK
) );
1777 if ( !(nFlags
& DrawFlags::NoDisable
) && !IsEnabled() )
1779 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1780 pDev
->SetTextColor( rStyleSettings
.GetDisableColor() );
1784 pDev
->SetTextColor( GetTextColor() );
1788 const long nOnePixel
= GetDrawPixel( pDev
, 1 );
1789 const long nOffX
= 3*nOnePixel
;
1790 DrawTextFlags nTextStyle
= DrawTextFlags::VCenter
;
1791 Rectangle
aTextRect( aPos
, aSize
);
1793 if ( GetStyle() & WB_CENTER
)
1794 nTextStyle
|= DrawTextFlags::Center
;
1795 else if ( GetStyle() & WB_RIGHT
)
1796 nTextStyle
|= DrawTextFlags::Right
;
1798 nTextStyle
|= DrawTextFlags::Left
;
1800 aTextRect
.Left() += nOffX
;
1801 aTextRect
.Right() -= nOffX
;
1803 OUString aText
= ImplGetText();
1804 long nTextHeight
= pDev
->GetTextHeight();
1805 long nTextWidth
= pDev
->GetTextWidth( aText
);
1806 long nOffY
= (aSize
.Height() - nTextHeight
) / 2;
1810 ((nOffY
+nTextHeight
) > aSize
.Height()) ||
1811 ((nOffX
+nTextWidth
) > aSize
.Width()) )
1813 Rectangle
aClip( aPos
, aSize
);
1814 if ( nTextHeight
> aSize
.Height() )
1815 aClip
.Bottom() += nTextHeight
-aSize
.Height()+1; // prevent HP printers from 'optimizing'
1816 pDev
->IntersectClipRegion( aClip
);
1819 pDev
->DrawText( aTextRect
, aText
, nTextStyle
);
1824 GetSubEdit()->Draw( pDev
, rPos
, rSize
, nFlags
);
1828 void Edit::ImplInvalidateOutermostBorder( vcl::Window
* pWin
)
1830 // allow control to show focused state
1831 vcl::Window
*pInvalWin
= pWin
, *pBorder
= pWin
;
1832 while( ( pBorder
= pInvalWin
->GetWindow( GetWindowType::Border
) ) != pInvalWin
&& pBorder
&&
1833 pInvalWin
->ImplGetFrame() == pBorder
->ImplGetFrame() )
1835 pInvalWin
= pBorder
;
1838 pInvalWin
->Invalidate( InvalidateFlags::Children
| InvalidateFlags::Update
);
1841 void Edit::GetFocus()
1844 mpSubEdit
->ImplGrabFocus( GetGetFocusFlags() );
1845 else if ( !mbActivePopup
)
1847 maUndoText
= maText
.toString();
1849 SelectionOptions nSelOptions
= GetSettings().GetStyleSettings().GetSelectionOptions();
1850 if ( !( GetStyle() & (WB_NOHIDESELECTION
|WB_READONLY
) )
1851 && ( GetGetFocusFlags() & (GetFocusFlags::Init
|GetFocusFlags::Tab
|GetFocusFlags::CURSOR
|GetFocusFlags::Mnemonic
) ) )
1853 if ( nSelOptions
& SelectionOptions::ShowFirst
)
1855 maSelection
.Min() = maText
.getLength();
1856 maSelection
.Max() = 0;
1860 maSelection
.Min() = 0;
1861 maSelection
.Max() = maText
.getLength();
1864 static_cast<Edit
*>(GetParent())->CallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
1866 CallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
1871 // FIXME: this is currently only on OS X
1872 // check for other platforms that need similar handling
1873 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
1874 IsNativeWidgetEnabled() &&
1875 IsNativeControlSupported( ControlType::Editbox
, ControlPart::Entire
) )
1877 ImplInvalidateOutermostBorder( mbIsSubEdit
? GetParent() : this );
1879 else if ( maSelection
.Len() )
1882 if ( !HasPaintEvent() )
1883 ImplInvalidateOrRepaint();
1888 SetInputContext( InputContext( GetFont(), !IsReadOnly() ? InputContextFlags::Text
|InputContextFlags::ExtText
: InputContextFlags::NONE
) );
1891 Control::GetFocus();
1894 void Edit::LoseFocus()
1896 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1898 //notify an update latest when the focus is lost
1899 mpUpdateDataTimer
->Stop();
1900 mpUpdateDataTimer
->Timeout();
1905 // FIXME: this is currently only on OS X
1906 // check for other platforms that need similar handling
1907 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
1908 IsNativeWidgetEnabled() &&
1909 IsNativeControlSupported( ControlType::Editbox
, ControlPart::Entire
) )
1911 ImplInvalidateOutermostBorder( mbIsSubEdit
? GetParent() : this );
1914 if ( !mbActivePopup
&& !( GetStyle() & WB_NOHIDESELECTION
) && maSelection
.Len() )
1915 ImplInvalidateOrRepaint(); // Selektion malen
1918 Control::LoseFocus();
1921 void Edit::Command( const CommandEvent
& rCEvt
)
1923 if ( rCEvt
.GetCommand() == CommandEventId::ContextMenu
)
1925 VclPtr
<PopupMenu
> pPopup
= Edit::CreatePopupMenu();
1927 if ( !maSelection
.Len() )
1929 pPopup
->EnableItem( SV_MENU_EDIT_CUT
, false );
1930 pPopup
->EnableItem( SV_MENU_EDIT_COPY
, false );
1931 pPopup
->EnableItem( SV_MENU_EDIT_DELETE
, false );
1936 pPopup
->EnableItem( SV_MENU_EDIT_CUT
, false );
1937 pPopup
->EnableItem( SV_MENU_EDIT_PASTE
, false );
1938 pPopup
->EnableItem( SV_MENU_EDIT_DELETE
, false );
1939 pPopup
->EnableItem( SV_MENU_EDIT_INSERTSYMBOL
, false );
1943 // only paste if text available in clipboard
1945 uno::Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetClipboard();
1947 if ( xClipboard
.is() )
1949 uno::Reference
< datatransfer::XTransferable
> xDataObj
;
1951 SolarMutexReleaser aReleaser
;
1952 xDataObj
= xClipboard
->getContents();
1954 if ( xDataObj
.is() )
1956 datatransfer::DataFlavor aFlavor
;
1957 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING
, aFlavor
);
1958 bData
= xDataObj
->isDataFlavorSupported( aFlavor
);
1961 pPopup
->EnableItem( SV_MENU_EDIT_PASTE
, bData
);
1964 if ( maUndoText
== maText
.getStr() )
1965 pPopup
->EnableItem( SV_MENU_EDIT_UNDO
, false );
1966 if ( ( maSelection
.Min() == 0 ) && ( maSelection
.Max() == maText
.getLength() ) )
1967 pPopup
->EnableItem( SV_MENU_EDIT_SELECTALL
, false );
1968 if ( !pImplFncGetSpecialChars
)
1970 sal_uInt16 nPos
= pPopup
->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL
);
1971 pPopup
->RemoveItem( nPos
);
1972 pPopup
->RemoveItem( nPos
-1 );
1975 mbActivePopup
= true;
1976 Selection aSaveSel
= GetSelection(); // if someone changes selection in Get/LoseFocus, e.g. URL bar
1977 Point aPos
= rCEvt
.GetMousePosPixel();
1978 if ( !rCEvt
.IsMouseEvent() )
1980 // Show menu eventually centered in selection
1981 Size aSize
= GetOutputSizePixel();
1982 aPos
= Point( aSize
.Width()/2, aSize
.Height()/2 );
1984 sal_uInt16 n
= pPopup
->Execute( this, aPos
);
1985 pPopup
.disposeAndClear();
1986 SetSelection( aSaveSel
);
1989 case SV_MENU_EDIT_UNDO
:
1993 case SV_MENU_EDIT_CUT
:
1997 case SV_MENU_EDIT_COPY
:
2000 case SV_MENU_EDIT_PASTE
:
2004 case SV_MENU_EDIT_DELETE
:
2008 case SV_MENU_EDIT_SELECTALL
:
2009 ImplSetSelection( Selection( 0, maText
.getLength() ) );
2011 case SV_MENU_EDIT_INSERTSYMBOL
:
2013 OUString aChars
= pImplFncGetSpecialChars( this, GetFont() );
2014 SetSelection( aSaveSel
);
2015 if ( !aChars
.isEmpty() )
2017 ImplInsertText( aChars
);
2023 mbActivePopup
= false;
2025 else if ( rCEvt
.GetCommand() == CommandEventId::StartExtTextInput
)
2029 sal_Int32 nPos
= static_cast<sal_Int32
>(maSelection
.Max());
2030 mpIMEInfos
= new Impl_IMEInfos( nPos
, OUString(maText
.getStr() + nPos
) );
2031 mpIMEInfos
->bWasCursorOverwrite
= !IsInsertMode();
2033 else if ( rCEvt
.GetCommand() == CommandEventId::EndExtTextInput
)
2035 bool bInsertMode
= !mpIMEInfos
->bWasCursorOverwrite
;
2037 mpIMEInfos
= nullptr;
2039 SetInsertMode(bInsertMode
);
2044 // #i25161# call auto complete handler for ext text commit also
2045 if (maAutocompleteHdl
.IsSet())
2047 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
2049 maAutocompleteHdl
.Call(*this);
2053 else if ( rCEvt
.GetCommand() == CommandEventId::ExtTextInput
)
2055 const CommandExtTextInputData
* pData
= rCEvt
.GetExtTextInputData();
2057 maText
.remove( mpIMEInfos
->nPos
, mpIMEInfos
->nLen
);
2058 maText
.insert( mpIMEInfos
->nPos
, pData
->GetText() );
2059 if ( mpIMEInfos
->bWasCursorOverwrite
)
2061 const sal_Int32 nOldIMETextLen
= mpIMEInfos
->nLen
;
2062 const sal_Int32 nNewIMETextLen
= pData
->GetText().getLength();
2063 if ( ( nOldIMETextLen
> nNewIMETextLen
) &&
2064 ( nNewIMETextLen
< mpIMEInfos
->aOldTextAfterStartPos
.getLength() ) )
2066 // restore old characters
2067 const sal_Int32 nRestore
= nOldIMETextLen
- nNewIMETextLen
;
2068 maText
.insert( mpIMEInfos
->nPos
+ nNewIMETextLen
, mpIMEInfos
->aOldTextAfterStartPos
.copy( nNewIMETextLen
, nRestore
) );
2070 else if ( ( nOldIMETextLen
< nNewIMETextLen
) &&
2071 ( nOldIMETextLen
< mpIMEInfos
->aOldTextAfterStartPos
.getLength() ) )
2073 const sal_Int32 nOverwrite
= ( nNewIMETextLen
> mpIMEInfos
->aOldTextAfterStartPos
.getLength()
2074 ? mpIMEInfos
->aOldTextAfterStartPos
.getLength() : nNewIMETextLen
) - nOldIMETextLen
;
2075 maText
.remove( mpIMEInfos
->nPos
+ nNewIMETextLen
, nOverwrite
);
2079 if ( pData
->GetTextAttr() )
2081 mpIMEInfos
->CopyAttribs( pData
->GetTextAttr(), pData
->GetText().getLength() );
2082 mpIMEInfos
->bCursor
= pData
->IsCursorVisible();
2086 mpIMEInfos
->DestroyAttribs();
2089 ImplAlignAndPaint();
2090 sal_Int32 nCursorPos
= mpIMEInfos
->nPos
+ pData
->GetCursorPos();
2091 SetSelection( Selection( nCursorPos
, nCursorPos
) );
2092 SetInsertMode( !pData
->IsCursorOverwrite() );
2094 if ( pData
->IsCursorVisible() )
2095 GetCursor()->Show();
2097 GetCursor()->Hide();
2099 else if ( rCEvt
.GetCommand() == CommandEventId::CursorPos
)
2103 sal_Int32 nCursorPos
= GetSelection().Max();
2104 SetCursorRect( nullptr, GetTextWidth( maText
.toString(), nCursorPos
, mpIMEInfos
->nPos
+mpIMEInfos
->nLen
-nCursorPos
) );
2111 else if ( rCEvt
.GetCommand() == CommandEventId::SelectionChange
)
2113 const CommandSelectionChangeData
*pData
= rCEvt
.GetSelectionChangeData();
2114 Selection
aSelection( pData
->GetStart(), pData
->GetEnd() );
2115 SetSelection(aSelection
);
2117 else if ( rCEvt
.GetCommand() == CommandEventId::QueryCharPosition
)
2119 if (mpIMEInfos
&& mpIMEInfos
->nLen
> 0)
2121 OUString aText
= ImplGetText();
2122 long nDXBuffer
[256];
2123 std::unique_ptr
<long[]> pDXBuffer
;
2124 long* pDX
= nDXBuffer
;
2126 if( !aText
.isEmpty() )
2128 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
2130 pDXBuffer
.reset(new long[2*(aText
.getLength()+1)]);
2131 pDX
= pDXBuffer
.get();
2134 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
2136 long nTH
= GetTextHeight();
2137 Point
aPos( mnXOffset
, ImplGetTextYPosition() );
2139 std::unique_ptr
<Rectangle
[]> aRects(new Rectangle
[ mpIMEInfos
->nLen
]);
2140 for ( int nIndex
= 0; nIndex
< mpIMEInfos
->nLen
; ++nIndex
)
2142 Rectangle
aRect( aPos
, Size( 10, nTH
) );
2143 aRect
.Left() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)] + mnXOffset
+ ImplGetExtraXOffset();
2144 aRects
[ nIndex
] = aRect
;
2146 SetCompositionCharRect( aRects
.get(), mpIMEInfos
->nLen
);
2150 Control::Command( rCEvt
);
2153 void Edit::StateChanged( StateChangedType nType
)
2155 if (nType
== StateChangedType::InitShow
)
2159 mnXOffset
= 0; // if GrabFocus before while size was still wrong
2162 ImplShowCursor(false);
2166 else if (nType
== StateChangedType::Enable
)
2170 // change text color only
2171 ImplInvalidateOrRepaint();
2174 else if (nType
== StateChangedType::Style
|| nType
== StateChangedType::Mirroring
)
2176 WinBits nStyle
= GetStyle();
2177 if (nType
== StateChangedType::Style
)
2179 nStyle
= ImplInitStyle(GetStyle());
2183 sal_uInt16 nOldAlign
= mnAlign
;
2184 mnAlign
= EDIT_ALIGN_LEFT
;
2186 // --- RTL --- hack: right align until keyinput and cursor travelling works
2187 // edits are always RTL disabled
2188 // however the parent edits contain the correct setting
2189 if (mbIsSubEdit
&& GetParent()->IsRTLEnabled())
2191 if (GetParent()->GetStyle() & WB_LEFT
)
2192 mnAlign
= EDIT_ALIGN_RIGHT
;
2193 if (nType
== StateChangedType::Mirroring
)
2194 SetLayoutMode(ComplexTextLayoutFlags::BiDiRtl
| ComplexTextLayoutFlags::TextOriginLeft
);
2196 else if (mbIsSubEdit
&& !GetParent()->IsRTLEnabled())
2198 if (nType
== StateChangedType::Mirroring
)
2199 SetLayoutMode(ComplexTextLayoutFlags::TextOriginLeft
);
2202 if (nStyle
& WB_RIGHT
)
2203 mnAlign
= EDIT_ALIGN_RIGHT
;
2204 else if (nStyle
& WB_CENTER
)
2205 mnAlign
= EDIT_ALIGN_CENTER
;
2206 if (!maText
.isEmpty() && (mnAlign
!= nOldAlign
))
2213 else if (nType
== StateChangedType::Zoom
)
2217 ApplySettings(*this);
2222 else if (nType
== StateChangedType::ControlFont
)
2226 ApplySettings(*this);
2231 else if (nType
== StateChangedType::ControlForeground
)
2235 ApplySettings(*this);
2239 else if (nType
== StateChangedType::ControlBackground
)
2243 ApplySettings(*this);
2248 Control::StateChanged(nType
);
2251 void Edit::DataChanged( const DataChangedEvent
& rDCEvt
)
2253 if ( (rDCEvt
.GetType() == DataChangedEventType::FONTS
) ||
2254 (rDCEvt
.GetType() == DataChangedEventType::FONTSUBSTITUTION
) ||
2255 ((rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
2256 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
)) )
2260 ApplySettings(*this);
2266 Control::DataChanged( rDCEvt
);
2269 void Edit::ImplShowDDCursor()
2271 if (!mpDDInfo
->bVisCursor
)
2273 long nTextWidth
= GetTextWidth( maText
.toString(), 0, mpDDInfo
->nDropPos
);
2274 long nTextHeight
= GetTextHeight();
2275 Rectangle
aCursorRect( Point( nTextWidth
+ mnXOffset
, (GetOutputSize().Height()-nTextHeight
)/2 ), Size( 2, nTextHeight
) );
2276 mpDDInfo
->aCursor
.SetWindow( this );
2277 mpDDInfo
->aCursor
.SetPos( aCursorRect
.TopLeft() );
2278 mpDDInfo
->aCursor
.SetSize( aCursorRect
.GetSize() );
2279 mpDDInfo
->aCursor
.Show();
2280 mpDDInfo
->bVisCursor
= true;
2284 void Edit::ImplHideDDCursor()
2286 if ( mpDDInfo
&& mpDDInfo
->bVisCursor
)
2288 mpDDInfo
->aCursor
.Hide();
2289 mpDDInfo
->bVisCursor
= false;
2293 TextFilter::TextFilter(const OUString
&rForbiddenChars
)
2294 : sForbiddenChars(rForbiddenChars
)
2298 TextFilter::~TextFilter()
2302 OUString
TextFilter::filter(const OUString
&rText
)
2304 OUString
sTemp(rText
);
2305 for (sal_Int32 i
= 0; i
< sForbiddenChars
.getLength(); ++i
)
2307 sTemp
= sTemp
.replaceAll(OUStringLiteral1(sForbiddenChars
[i
]), "");
2312 void Edit::filterText()
2314 Selection aSel
= GetSelection();
2315 const OUString sOrig
= GetText();
2316 const OUString sNew
= mpFilterText
->filter(GetText());
2319 sal_Int32 nDiff
= sOrig
.getLength() - sNew
.getLength();
2322 aSel
.setMin(aSel
.getMin() - nDiff
);
2323 aSel
.setMax(aSel
.getMin());
2337 static_cast<Edit
*>(GetParent())->Modify();
2341 if ( mpUpdateDataTimer
)
2342 mpUpdateDataTimer
->Start();
2344 if ( ImplCallEventListenersAndHandler( VCLEVENT_EDIT_MODIFY
, [this] () { maModifyHdl
.Call(*this); } ) )
2345 // have been destroyed while calling into the handlers
2348 // #i13677# notify edit listeners about caret position change
2349 CallEventListeners( VCLEVENT_EDIT_CARETCHANGED
);
2350 // FIXME: this is currently only on OS X
2351 // check for other platforms that need similar handling
2352 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2353 IsNativeWidgetEnabled() &&
2354 IsNativeControlSupported( ControlType::Editbox
, ControlPart::Entire
) )
2356 ImplInvalidateOutermostBorder( this );
2361 void Edit::UpdateData()
2363 maUpdateDataHdl
.Call( *this );
2366 IMPL_LINK_NOARG(Edit
, ImplUpdateDataHdl
, Timer
*, void)
2371 void Edit::EnableUpdateData( sal_uLong nTimeout
)
2374 DisableUpdateData();
2377 if ( !mpUpdateDataTimer
)
2379 mpUpdateDataTimer
= new Timer("UpdateDataTimer");
2380 mpUpdateDataTimer
->SetTimeoutHdl( LINK( this, Edit
, ImplUpdateDataHdl
) );
2381 mpUpdateDataTimer
->SetDebugName( "vcl::Edit mpUpdateDataTimer" );
2384 mpUpdateDataTimer
->SetTimeout( nTimeout
);
2388 void Edit::DisableUpdateData()
2390 delete mpUpdateDataTimer
;
2391 mpUpdateDataTimer
= nullptr;
2394 void Edit::SetEchoChar( sal_Unicode c
)
2398 mpSubEdit
->SetEchoChar( c
);
2401 void Edit::SetReadOnly( bool bReadOnly
)
2403 if ( mbReadOnly
!= bool(bReadOnly
) )
2405 mbReadOnly
= bReadOnly
;
2407 mpSubEdit
->SetReadOnly( bReadOnly
);
2409 CompatStateChanged( StateChangedType::ReadOnly
);
2413 void Edit::SetInsertMode( bool bInsert
)
2415 if ( bInsert
!= mbInsertMode
)
2417 mbInsertMode
= bInsert
;
2419 mpSubEdit
->SetInsertMode( bInsert
);
2425 bool Edit::IsInsertMode() const
2428 return mpSubEdit
->IsInsertMode();
2430 return mbInsertMode
;
2433 void Edit::SetMaxTextLen(sal_Int32 nMaxLen
)
2435 mnMaxTextLen
= nMaxLen
> 0 ? nMaxLen
: EDIT_NOLIMIT
;
2438 mpSubEdit
->SetMaxTextLen( mnMaxTextLen
);
2441 if ( maText
.getLength() > mnMaxTextLen
)
2442 ImplDelete( Selection( mnMaxTextLen
, maText
.getLength() ), EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2446 void Edit::SetSelection( const Selection
& rSelection
)
2448 // If the selection was changed from outside, e.g. by MouseButtonDown, don't call Tracking()
2449 // directly afterwards which would change the selection again
2452 else if ( mpSubEdit
&& mpSubEdit
->IsTracking() )
2453 mpSubEdit
->EndTracking();
2455 ImplSetSelection( rSelection
);
2458 void Edit::ImplSetSelection( const Selection
& rSelection
, bool bPaint
)
2461 mpSubEdit
->ImplSetSelection( rSelection
);
2464 if ( rSelection
!= maSelection
)
2466 Selection
aOld( maSelection
);
2467 Selection
aNew( rSelection
);
2469 if ( aNew
.Min() > maText
.getLength() )
2470 aNew
.Min() = maText
.getLength();
2471 if ( aNew
.Max() > maText
.getLength() )
2472 aNew
.Max() = maText
.getLength();
2473 if ( aNew
.Min() < 0 )
2475 if ( aNew
.Max() < 0 )
2478 if ( aNew
!= maSelection
)
2480 ImplClearLayoutData();
2481 Selection aTemp
= maSelection
;
2484 if ( bPaint
&& ( aOld
.Len() || aNew
.Len() || IsPaintTransparent() ) )
2485 ImplInvalidateOrRepaint();
2488 bool bCaret
= false, bSelection
= false;
2489 long nB
=aNew
.Max(), nA
=aNew
.Min(),oB
=aTemp
.Max(), oA
=aTemp
.Min();
2490 long nGap
= nB
-nA
, oGap
= oB
-oA
;
2493 if (nGap
!= 0 || oGap
!= 0)
2499 static_cast<Edit
*>(GetParent())->CallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2501 CallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2507 static_cast<Edit
*>(GetParent())->CallEventListeners( VCLEVENT_EDIT_CARETCHANGED
);
2509 CallEventListeners( VCLEVENT_EDIT_CARETCHANGED
);
2512 // #103511# notify combobox listeners of deselection
2513 if( !maSelection
&& GetParent() && GetParent()->GetType() == WINDOW_COMBOBOX
)
2514 static_cast<Edit
*>(GetParent())->CallEventListeners( VCLEVENT_COMBOBOX_DESELECT
);
2520 const Selection
& Edit::GetSelection() const
2523 return mpSubEdit
->GetSelection();
2528 void Edit::ReplaceSelected( const OUString
& rStr
)
2531 mpSubEdit
->ReplaceSelected( rStr
);
2533 ImplInsertText( rStr
);
2536 void Edit::DeleteSelected()
2539 mpSubEdit
->DeleteSelected();
2542 if ( maSelection
.Len() )
2543 ImplDelete( maSelection
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2547 OUString
Edit::GetSelected() const
2550 return mpSubEdit
->GetSelected();
2553 Selection
aSelection( maSelection
);
2554 aSelection
.Justify();
2555 return OUString( maText
.getStr() + aSelection
.Min(), aSelection
.Len() );
2561 if ( !(GetStyle() & WB_PASSWORD
) )
2564 ReplaceSelected( OUString() );
2570 if ( !(GetStyle() & WB_PASSWORD
) )
2572 css::uno::Reference
<css::datatransfer::clipboard::XClipboard
> aClipboard(GetClipboard());
2573 ImplCopy( aClipboard
);
2579 css::uno::Reference
<css::datatransfer::clipboard::XClipboard
> aClipboard(GetClipboard());
2580 ImplPaste( aClipboard
);
2589 const OUString
aText( maText
.toString() );
2590 ImplDelete( Selection( 0, aText
.getLength() ), EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2591 ImplInsertText( maUndoText
);
2592 ImplSetSelection( Selection( 0, maUndoText
.getLength() ) );
2597 void Edit::SetText( const OUString
& rStr
)
2600 mpSubEdit
->SetText( rStr
); // not directly ImplSetText if SetText overridden
2603 Selection
aNewSel( 0, 0 ); // prevent scrolling
2604 ImplSetText( rStr
, &aNewSel
);
2608 void Edit::SetText( const OUString
& rStr
, const Selection
& rSelection
)
2611 mpSubEdit
->SetText( rStr
, rSelection
);
2613 ImplSetText( rStr
, &rSelection
);
2616 OUString
Edit::GetText() const
2619 return mpSubEdit
->GetText();
2621 return maText
.toString();
2624 void Edit::SetCursorAtLast(){
2625 ImplSetCursorPos( GetText().getLength(), false );
2628 void Edit::SetPlaceholderText( const OUString
& rStr
)
2631 mpSubEdit
->SetPlaceholderText( rStr
);
2632 else if ( maPlaceholderText
!= rStr
)
2634 maPlaceholderText
= rStr
;
2635 if ( GetText().isEmpty() )
2640 OUString
Edit::GetPlaceholderText() const
2643 return mpSubEdit
->GetPlaceholderText();
2645 return maPlaceholderText
;
2648 void Edit::SetModifyFlag()
2651 mpSubEdit
->mbModified
= true;
2656 void Edit::ClearModifyFlag()
2659 mpSubEdit
->mbModified
= false;
2664 void Edit::SetSubEdit(Edit
* pEdit
)
2666 mpSubEdit
.disposeAndClear();
2667 mpSubEdit
.set(pEdit
);
2671 SetPointer(PointerStyle::Arrow
); // Nur das SubEdit hat den BEAM...
2672 mpSubEdit
->mbIsSubEdit
= true;
2674 mpSubEdit
->SetReadOnly(mbReadOnly
);
2675 mpSubEdit
->maAutocompleteHdl
= maAutocompleteHdl
;
2679 Size
Edit::CalcMinimumSizeForText(const OUString
&rString
) const
2681 ControlType eCtrlType
= ImplGetNativeControlType();
2684 if (mnWidthInChars
!= -1)
2686 //CalcSize calls CalcWindowSize, but we will call that also in this
2687 //function, so undo the first one with CalcOutputSize
2688 aSize
= CalcOutputSize(CalcSize(mnWidthInChars
));
2693 if (mnMaxWidthChars
!= -1 && mnMaxWidthChars
< rString
.getLength())
2694 aString
= rString
.copy(0, mnMaxWidthChars
);
2698 aSize
.Height() = GetTextHeight();
2699 aSize
.Width() = GetTextWidth(aString
);
2700 aSize
.Width() += ImplGetExtraXOffset() * 2;
2702 // do not create edit fields in which one cannot enter anything
2703 // a default minimum width should exist for at least 3 characters
2705 //CalcSize calls CalcWindowSize, but we will call that also in this
2706 //function, so undo the first one with CalcOutputSize
2707 Size
aMinSize(CalcOutputSize(CalcSize(3)));
2708 if (aSize
.Width() < aMinSize
.Width())
2709 aSize
.Width() = aMinSize
.Width();
2712 aSize
.Height() += ImplGetExtraYOffset() * 2;
2714 aSize
= CalcWindowSize( aSize
);
2716 // ask NWF what if it has an opinion, too
2717 ImplControlValue aControlValue
;
2718 Rectangle
aRect( Point( 0, 0 ), aSize
);
2719 Rectangle aContent
, aBound
;
2720 if (GetNativeControlRegion(eCtrlType
, ControlPart::Entire
, aRect
, ControlState::NONE
,
2721 aControlValue
, OUString(), aBound
, aContent
))
2723 if (aBound
.GetHeight() > aSize
.Height())
2724 aSize
.Height() = aBound
.GetHeight();
2729 Size
Edit::CalcMinimumSize() const
2731 return CalcMinimumSizeForText(GetText());
2734 Size
Edit::GetMinimumEditSize()
2736 vcl::Window
* pDefWin
= ImplGetDefaultWindow();
2737 ScopedVclPtrInstance
< Edit
> aEdit( pDefWin
, WB_BORDER
);
2738 Size
aSize( aEdit
->CalcMinimumSize() );
2742 Size
Edit::GetOptimalSize() const
2744 return CalcMinimumSize();
2747 Size
Edit::CalcSize(sal_Int32 nChars
) const
2749 // width for N characters, independent from content.
2750 // works only correct for fixed fonts, average otherwise
2751 Size
aSz( GetTextWidth( "x" ), GetTextHeight() );
2752 aSz
.Width() *= nChars
;
2753 aSz
.Width() += ImplGetExtraXOffset() * 2;
2754 aSz
= CalcWindowSize( aSz
);
2758 sal_Int32
Edit::GetMaxVisChars() const
2760 const vcl::Window
* pW
= mpSubEdit
? mpSubEdit
: this;
2761 sal_Int32 nOutWidth
= pW
->GetOutputSizePixel().Width();
2762 sal_Int32 nCharWidth
= GetTextWidth( "x" );
2763 return nCharWidth
? nOutWidth
/nCharWidth
: 0;
2766 sal_Int32
Edit::GetCharPos( const Point
& rWindowPos
) const
2768 return ImplGetCharPos( rWindowPos
);
2771 void Edit::SetGetSpecialCharsFunction( FncGetSpecialChars fn
)
2773 pImplFncGetSpecialChars
= fn
;
2776 FncGetSpecialChars
Edit::GetGetSpecialCharsFunction()
2778 return pImplFncGetSpecialChars
;
2781 VclPtr
<PopupMenu
> Edit::CreatePopupMenu()
2783 ResMgr
* pResMgr
= ImplGetResMgr();
2785 return VclPtr
<PopupMenu
>::Create();
2787 VclPtrInstance
<PopupMenu
> pPopup( ResId( SV_RESID_MENU_EDIT
, *pResMgr
) );
2788 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2789 if ( rStyleSettings
.GetHideDisabledMenuItems() )
2790 pPopup
->SetMenuFlags( MenuFlags::HideDisabledEntries
);
2792 pPopup
->SetMenuFlags ( MenuFlags::AlwaysShowDisabledEntries
);
2793 if ( rStyleSettings
.GetContextMenuShortcuts() )
2795 pPopup
->SetAccelKey( SV_MENU_EDIT_UNDO
, vcl::KeyCode( KeyFuncType::UNDO
) );
2796 pPopup
->SetAccelKey( SV_MENU_EDIT_CUT
, vcl::KeyCode( KeyFuncType::CUT
) );
2797 pPopup
->SetAccelKey( SV_MENU_EDIT_COPY
, vcl::KeyCode( KeyFuncType::COPY
) );
2798 pPopup
->SetAccelKey( SV_MENU_EDIT_PASTE
, vcl::KeyCode( KeyFuncType::PASTE
) );
2799 pPopup
->SetAccelKey( SV_MENU_EDIT_DELETE
, vcl::KeyCode( KeyFuncType::DELETE
) );
2800 pPopup
->SetAccelKey( SV_MENU_EDIT_SELECTALL
, vcl::KeyCode( KEY_A
, false, true, false, false ) );
2801 pPopup
->SetAccelKey( SV_MENU_EDIT_INSERTSYMBOL
, vcl::KeyCode( KEY_S
, true, true, false, false ) );
2806 // css::datatransfer::dnd::XDragGestureListener
2807 void Edit::dragGestureRecognized( const css::datatransfer::dnd::DragGestureEvent
& rDGE
) throw (css::uno::RuntimeException
, std::exception
)
2809 SolarMutexGuard aVclGuard
;
2811 if ( !IsTracking() && maSelection
.Len() &&
2812 !(GetStyle() & WB_PASSWORD
) && (!mpDDInfo
|| !mpDDInfo
->bStarterOfDD
) ) // Kein Mehrfach D&D
2814 Selection
aSel( maSelection
);
2817 // Nur wenn Maus in der Selektion...
2818 Point
aMousePos( rDGE
.DragOriginX
, rDGE
.DragOriginY
);
2819 sal_Int32 nCharPos
= ImplGetCharPos( aMousePos
);
2820 if ( (nCharPos
>= aSel
.Min()) && (nCharPos
< aSel
.Max()) )
2823 mpDDInfo
= new DDInfo
;
2825 mpDDInfo
->bStarterOfDD
= true;
2826 mpDDInfo
->aDndStartSel
= aSel
;
2829 EndTracking(); // Vor D&D Tracking ausschalten
2831 vcl::unohelper::TextDataObject
* pDataObj
= new vcl::unohelper::TextDataObject( GetSelected() );
2832 sal_Int8 nActions
= datatransfer::dnd::DNDConstants::ACTION_COPY
;
2833 if ( !IsReadOnly() )
2834 nActions
|= datatransfer::dnd::DNDConstants::ACTION_MOVE
;
2835 rDGE
.DragSource
->startDrag( rDGE
, nActions
, 0 /*cursor*/, 0 /*image*/, pDataObj
, mxDnDListener
);
2837 GetCursor()->Hide();
2843 // css::datatransfer::dnd::XDragSourceListener
2844 void Edit::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent
& rDSDE
) throw (css::uno::RuntimeException
, std::exception
)
2846 SolarMutexGuard aVclGuard
;
2848 if (rDSDE
.DropSuccess
&& (rDSDE
.DropAction
& datatransfer::dnd::DNDConstants::ACTION_MOVE
) && mpDDInfo
)
2850 Selection
aSel( mpDDInfo
->aDndStartSel
);
2851 if ( mpDDInfo
->bDroppedInMe
)
2853 if ( aSel
.Max() > mpDDInfo
->nDropPos
)
2855 long nLen
= aSel
.Len();
2860 ImplDelete( aSel
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2869 // css::datatransfer::dnd::XDropTargetListener
2870 void Edit::drop( const css::datatransfer::dnd::DropTargetDropEvent
& rDTDE
) throw (css::uno::RuntimeException
, std::exception
)
2872 SolarMutexGuard aVclGuard
;
2874 bool bChanges
= false;
2875 if ( !mbReadOnly
&& mpDDInfo
)
2879 Selection
aSel( maSelection
);
2882 if ( aSel
.Len() && !mpDDInfo
->bStarterOfDD
)
2883 ImplDelete( aSel
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2885 mpDDInfo
->bDroppedInMe
= true;
2887 aSel
.Min() = mpDDInfo
->nDropPos
;
2888 aSel
.Max() = mpDDInfo
->nDropPos
;
2889 ImplSetSelection( aSel
);
2891 uno::Reference
< datatransfer::XTransferable
> xDataObj
= rDTDE
.Transferable
;
2892 if ( xDataObj
.is() )
2894 datatransfer::DataFlavor aFlavor
;
2895 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING
, aFlavor
);
2896 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
2898 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
2901 ImplInsertText( aText
);
2907 if ( !mpDDInfo
->bStarterOfDD
)
2914 rDTDE
.Context
->dropComplete( bChanges
);
2917 void Edit::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEvent
& rDTDE
) throw (css::uno::RuntimeException
, std::exception
)
2921 mpDDInfo
= new DDInfo
;
2923 // search for string data type
2924 const Sequence
< css::datatransfer::DataFlavor
>& rFlavors( rDTDE
.SupportedDataFlavors
);
2925 sal_Int32 nEle
= rFlavors
.getLength();
2926 mpDDInfo
->bIsStringSupported
= false;
2927 for( sal_Int32 i
= 0; i
< nEle
; i
++ )
2929 sal_Int32 nIndex
= 0;
2930 const OUString aMimetype
= rFlavors
[i
].MimeType
.getToken( 0, ';', nIndex
);
2931 if ( aMimetype
== "text/plain" )
2933 mpDDInfo
->bIsStringSupported
= true;
2939 void Edit::dragExit( const css::datatransfer::dnd::DropTargetEvent
& ) throw (css::uno::RuntimeException
, std::exception
)
2941 SolarMutexGuard aVclGuard
;
2946 void Edit::dragOver( const css::datatransfer::dnd::DropTargetDragEvent
& rDTDE
) throw (css::uno::RuntimeException
, std::exception
)
2948 SolarMutexGuard aVclGuard
;
2950 Point
aMousePos( rDTDE
.LocationX
, rDTDE
.LocationY
);
2952 sal_Int32 nPrevDropPos
= mpDDInfo
->nDropPos
;
2953 mpDDInfo
->nDropPos
= ImplGetCharPos( aMousePos
);
2956 Size aOutSize = GetOutputSizePixel();
2957 if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) )
2960 // No, I will not receive events in this case....
2964 Selection
aSel( maSelection
);
2967 // Don't accept drop in selection or read-only field...
2968 if ( IsReadOnly() || aSel
.IsInside( mpDDInfo
->nDropPos
) || ! mpDDInfo
->bIsStringSupported
)
2971 rDTDE
.Context
->rejectDrag();
2975 // Alten Cursor wegzeichnen...
2976 if ( !mpDDInfo
->bVisCursor
|| ( nPrevDropPos
!= mpDDInfo
->nDropPos
) )
2981 rDTDE
.Context
->acceptDrag( rDTDE
.DropAction
);
2985 OUString
Edit::GetSurroundingText() const
2988 return mpSubEdit
->GetSurroundingText();
2989 return maText
.toString();
2992 Selection
Edit::GetSurroundingTextSelection() const
2994 return GetSelection();
2997 FactoryFunction
Edit::GetUITestFactory() const
2999 return EditUIObject::create
;
3002 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */