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 .
22 #include <vcl/decoview.hxx>
23 #include <vcl/event.hxx>
24 #include <vcl/cursor.hxx>
25 #include <vcl/virdev.hxx>
26 #include <vcl/menu.hxx>
27 #include <vcl/edit.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/msgbox.hxx>
34 #include <controldata.hxx>
36 #include <osl/mutex.hxx>
39 #include <com/sun/star/i18n/BreakIterator.hpp>
40 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
41 #include <com/sun/star/i18n/WordType.hpp>
42 #include <cppuhelper/weak.hxx>
43 #include <com/sun/star/datatransfer/XTransferable.hpp>
44 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
48 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
49 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
51 #include <com/sun/star/i18n/InputSequenceChecker.hpp>
52 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
53 #include <com/sun/star/i18n/ScriptType.hpp>
54 #include <com/sun/star/container/XNameAccess.hpp>
56 #include <com/sun/star/uno/Any.hxx>
58 #include <comphelper/processfactory.hxx>
59 #include <comphelper/string.hxx>
61 #include <sot/exchange.hxx>
62 #include <sot/formats.hxx>
63 #include <sal/macros.h>
65 #include <vcl/unohelp.hxx>
66 #include <vcl/unohelp2.hxx>
68 #include <officecfg/Office/Common.hxx>
73 using namespace ::com::sun::star
;
74 using namespace ::com::sun::star::uno
;
75 using namespace ::com::sun::star::lang
;
76 using namespace ::rtl
;
79 // - Bei Tracking-Cancel DefaultSelection wieder herstellen
81 // =======================================================================
83 static FncGetSpecialChars pImplFncGetSpecialChars
= NULL
;
85 // =======================================================================
87 #define EDIT_ALIGN_LEFT 1
88 #define EDIT_ALIGN_CENTER 2
89 #define EDIT_ALIGN_RIGHT 3
91 #define EDIT_DEL_LEFT 1
92 #define EDIT_DEL_RIGHT 2
94 #define EDIT_DELMODE_SIMPLE 11
95 #define EDIT_DELMODE_RESTOFWORD 12
96 #define EDIT_DELMODE_RESTOFCONTENT 13
98 // =======================================================================
103 Selection aDndStartSel
;
108 bool bIsStringSupported
;
112 aCursor
.SetStyle( CURSOR_SHADOW
);
114 bStarterOfDD
= false;
115 bDroppedInMe
= false;
117 bIsStringSupported
= false;
121 // =======================================================================
125 OUString aOldTextAfterStartPos
;
126 sal_uInt16
* pAttribs
;
130 bool bWasCursorOverwrite
;
132 Impl_IMEInfos( xub_StrLen nPos
, const OUString
& rOldTextAfterStartPos
);
135 void CopyAttribs( const xub_StrLen
* pA
, xub_StrLen nL
);
136 void DestroyAttribs();
139 // -----------------------------------------------------------------------
141 Impl_IMEInfos::Impl_IMEInfos( xub_StrLen nP
, const OUString
& rOldTextAfterStartPos
)
142 : aOldTextAfterStartPos( rOldTextAfterStartPos
)
148 bWasCursorOverwrite
= false;
151 // -----------------------------------------------------------------------
153 Impl_IMEInfos::~Impl_IMEInfos()
158 // -----------------------------------------------------------------------
160 void Impl_IMEInfos::CopyAttribs( const xub_StrLen
* pA
, xub_StrLen nL
)
164 pAttribs
= new sal_uInt16
[ nL
];
165 memcpy( pAttribs
, pA
, nL
*sizeof(sal_uInt16
) );
168 // -----------------------------------------------------------------------
170 void Impl_IMEInfos::DestroyAttribs()
177 // =======================================================================
179 Edit::Edit( WindowType nType
) :
185 // -----------------------------------------------------------------------
187 Edit::Edit( Window
* pParent
, WinBits nStyle
) :
188 Control( WINDOW_EDIT
)
191 ImplInit( pParent
, nStyle
);
194 Edit::Edit( Window
* pParent
, const ResId
& rResId
) :
195 Control( WINDOW_EDIT
)
197 rResId
.SetRT( RSC_EDIT
);
198 WinBits nStyle
= ImplInitRes( rResId
);
200 ImplInit( pParent
, nStyle
);
201 ImplLoadRes( rResId
);
203 // Derived MultiLineEdit takes care to call Show only after MultiLineEdit
204 // ctor has already started:
205 if ( !(nStyle
& WB_HIDE
) && rResId
.GetRT() != RSC_MULTILINEEDIT
)
209 void Edit::SetWidthInChars(sal_Int32 nWidthInChars
)
211 if (mnWidthInChars
!= nWidthInChars
)
213 mnWidthInChars
= nWidthInChars
;
218 void Edit::setMaxWidthChars(sal_Int32 nWidth
)
220 if (nWidth
!= mnMaxWidthChars
)
222 mnMaxWidthChars
= nWidth
;
227 bool Edit::set_property(const OString
&rKey
, const OString
&rValue
)
229 if (rKey
== "width-chars")
230 SetWidthInChars(rValue
.toInt32());
231 else if (rKey
== "max-width-chars")
232 setMaxWidthChars(rValue
.toInt32());
233 else if (rKey
== "max-length")
235 sal_Int32 nTextLen
= rValue
.toInt32();
236 SetMaxTextLen(nTextLen
== 0 ? EDIT_NOLIMIT
: nTextLen
);
238 else if (rKey
== "editable")
240 bool bReadOnly
= !toBool(rValue
);
241 SetReadOnly(bReadOnly
);
242 //disable tab to traverse into readonly editables
243 WinBits nBits
= GetStyle();
244 nBits
&= ~(WB_TABSTOP
|WB_NOTABSTOP
);
248 nBits
|= WB_NOTABSTOP
;
251 else if (rKey
== "visibility")
253 WinBits nBits
= GetStyle();
254 nBits
&= ~(WB_PASSWORD
);
256 nBits
|= WB_PASSWORD
;
259 else if (rKey
== "placeholder-text")
260 SetPlaceholderText(OStringToOUString(rValue
, RTL_TEXTENCODING_UTF8
));
262 return Control::set_property(rKey
, rValue
);
266 // -----------------------------------------------------------------------
271 Cursor
* pCursor
= GetCursor();
280 delete mpUpdateDataTimer
;
282 if ( mxDnDListener
.is() )
284 if ( GetDragGestureRecognizer().is() )
286 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mxDnDListener
, uno::UNO_QUERY
);
287 GetDragGestureRecognizer()->removeDragGestureListener( xDGL
);
289 if ( GetDropTarget().is() )
291 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( mxDnDListener
, uno::UNO_QUERY
);
292 GetDropTarget()->removeDropTargetListener( xDTL
);
295 uno::Reference
< lang::XEventListener
> xEL( mxDnDListener
, uno::UNO_QUERY
);
296 xEL
->disposing( lang::EventObject() ); // #95154# #96585# Empty Source means it's the Client
300 // -----------------------------------------------------------------------
302 void Edit::ImplInitEditData()
305 mpUpdateDataTimer
= NULL
;
307 mnAlign
= EDIT_ALIGN_LEFT
;
308 mnMaxTextLen
= EDIT_NOLIMIT
;
310 mnMaxWidthChars
= -1;
311 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
312 mbModified
= sal_False
;
313 mbInternModified
= sal_False
;
314 mbReadOnly
= sal_False
;
315 mbInsertMode
= sal_True
;
316 mbClickedInSelection
= sal_False
;
317 mbActivePopup
= sal_False
;
318 mbIsSubEdit
= sal_False
;
319 mbInMBDown
= sal_False
;
324 // --- RTL --- no default mirroring for Edit controls
325 // note: controls that use a subedit will revert this (SpinField, ComboBox)
326 EnableRTL( sal_False
);
328 vcl::unohelper::DragAndDropWrapper
* pDnDWrapper
= new vcl::unohelper::DragAndDropWrapper( this );
329 mxDnDListener
= pDnDWrapper
;
332 // -----------------------------------------------------------------------
334 bool Edit::ImplUseNativeBorder( WinBits nStyle
)
337 IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE
)
338 && ((nStyle
&WB_BORDER
) && !(nStyle
&WB_NOBORDER
));
339 if( ! bRet
&& mbIsSubEdit
)
341 Window
* pWindow
= GetParent();
342 nStyle
= pWindow
->GetStyle();
343 bRet
= pWindow
->IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE
)
344 && ((nStyle
&WB_BORDER
) && !(nStyle
&WB_NOBORDER
));
349 void Edit::ImplInit( Window
* pParent
, WinBits nStyle
)
351 nStyle
= ImplInitStyle( nStyle
);
352 if ( !(nStyle
& (WB_CENTER
| WB_RIGHT
)) )
355 Control::ImplInit( pParent
, nStyle
, NULL
);
357 mbReadOnly
= (nStyle
& WB_READONLY
) != 0;
359 mnAlign
= EDIT_ALIGN_LEFT
;
361 // --- RTL --- hack: right align until keyinput and cursor travelling works
363 mnAlign
= EDIT_ALIGN_RIGHT
;
365 if ( nStyle
& WB_RIGHT
)
366 mnAlign
= EDIT_ALIGN_RIGHT
;
367 else if ( nStyle
& WB_CENTER
)
368 mnAlign
= EDIT_ALIGN_CENTER
;
370 SetCursor( new Cursor
);
372 SetPointer( Pointer( POINTER_TEXT
) );
373 ImplInitSettings( sal_True
, sal_True
, sal_True
);
375 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mxDnDListener
, uno::UNO_QUERY
);
376 uno::Reference
< datatransfer::dnd::XDragGestureRecognizer
> xDGR
= GetDragGestureRecognizer();
379 xDGR
->addDragGestureListener( xDGL
);
380 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( mxDnDListener
, uno::UNO_QUERY
);
381 GetDropTarget()->addDropTargetListener( xDTL
);
382 GetDropTarget()->setActive( sal_True
);
383 GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE
);
387 // -----------------------------------------------------------------------
389 WinBits
Edit::ImplInitStyle( WinBits nStyle
)
391 if ( !(nStyle
& WB_NOTABSTOP
) )
392 nStyle
|= WB_TABSTOP
;
393 if ( !(nStyle
& WB_NOGROUP
) )
399 // -----------------------------------------------------------------------
401 sal_Bool
Edit::IsCharInput( const KeyEvent
& rKeyEvent
)
403 // In the future we must use new Unicode functions for this
404 sal_Unicode cCharCode
= rKeyEvent
.GetCharCode();
405 return ((cCharCode
>= 32) && (cCharCode
!= 127) &&
406 !rKeyEvent
.GetKeyCode().IsMod3() &&
407 !rKeyEvent
.GetKeyCode().IsMod2() &&
408 !rKeyEvent
.GetKeyCode().IsMod1() );
411 // -----------------------------------------------------------------------
413 void Edit::ImplModified()
415 mbModified
= sal_True
;
419 // -----------------------------------------------------------------------
421 void Edit::ImplInitSettings( sal_Bool bFont
, sal_Bool bForeground
, sal_Bool bBackground
)
423 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
427 Font aFont
= rStyleSettings
.GetFieldFont();
428 if ( IsControlFont() )
429 aFont
.Merge( GetControlFont() );
430 SetZoomedPointFont( aFont
);
431 ImplClearLayoutData();
434 if ( bFont
|| bForeground
)
436 Color aTextColor
= rStyleSettings
.GetFieldTextColor();
437 if ( IsControlForeground() )
438 aTextColor
= GetControlForeground();
439 SetTextColor( aTextColor
);
444 if ( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() )
446 // Transparent background
450 else if ( IsControlBackground() )
452 SetBackground( GetControlBackground() );
453 SetFillColor( GetControlBackground() );
457 SetBackground( rStyleSettings
.GetFieldColor() );
458 SetFillColor( rStyleSettings
.GetFieldColor() );
463 // -----------------------------------------------------------------------
465 long Edit::ImplGetExtraOffset() const
467 // MT 09/2002: nExtraOffsetX should become a member, instead of checking every time,
468 // but I need an incompatible update for this...
469 // #94095# Use extra offset only when edit has a border
470 long nExtraOffset
= 0;
471 if( ( GetStyle() & WB_BORDER
) || ( mbIsSubEdit
&& ( GetParent()->GetStyle() & WB_BORDER
) ) )
478 // -----------------------------------------------------------------------
480 OUString
Edit::ImplGetText() const
482 if ( mcEchoChar
|| (GetStyle() & WB_PASSWORD
) )
484 sal_Unicode cEchoChar
;
486 cEchoChar
= mcEchoChar
;
489 OUStringBuffer aText
;
490 comphelper::string::padToLength(aText
, maText
.getLength(), cEchoChar
);
491 return aText
.makeStringAndClear();
494 return maText
.toString();
497 // -----------------------------------------------------------------------
499 void Edit::ImplInvalidateOrRepaint( sal_Int32 nStart
, sal_Int32 nEnd
)
501 if( IsPaintTransparent() )
504 // FIXME: this is currently only on aqua
505 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
)
509 ImplRepaint( nStart
, nEnd
);
512 // -----------------------------------------------------------------------
514 long Edit::ImplGetTextYPosition() const
516 if ( GetStyle() & WB_TOP
)
517 return ImplGetExtraOffset();
518 else if ( GetStyle() & WB_BOTTOM
)
519 return GetOutputSizePixel().Height() - GetTextHeight() - ImplGetExtraOffset();
520 return ( GetOutputSizePixel().Height() - GetTextHeight() ) / 2;
523 // -----------------------------------------------------------------------
525 void Edit::ImplRepaint( sal_Int32 nStart
, sal_Int32 nEnd
, bool bLayout
)
527 if ( !IsReallyVisible() )
530 OUString aText
= ImplGetText();
532 nEnd
= aText
.getLength();
534 sal_Int32 nDXBuffer
[256];
535 sal_Int32
* pDXBuffer
= NULL
;
536 sal_Int32
* pDX
= nDXBuffer
;
538 if( !aText
.isEmpty() )
540 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
542 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
546 GetCaretPositions( aText
, pDX
, nStart
, nEnd
);
549 long nTH
= GetTextHeight();
550 Point
aPos( mnXOffset
, ImplGetTextYPosition() );
554 long nPos
= nStart
? pDX
[2*nStart
] : 0;
555 aPos
.X() = nPos
+ mnXOffset
+ ImplGetExtraOffset();
557 MetricVector
* pVector
= &mpControlData
->mpLayoutData
->m_aUnicodeBoundRects
;
558 OUString
* pDisplayText
= &mpControlData
->mpLayoutData
->m_aDisplayText
;
560 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
, pVector
, pDisplayText
);
567 Cursor
* pCursor
= GetCursor();
568 bool bVisCursor
= pCursor
? pCursor
->IsVisible() : false;
572 ImplClearBackground( 0, GetOutputSizePixel().Width() );
574 bool bPaintPlaceholderText
= aText
.isEmpty() && !maPlaceholderText
.isEmpty();
576 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
578 ImplInitSettings( sal_False
, sal_True
, sal_False
);
579 if ( !IsEnabled() || bPaintPlaceholderText
)
580 SetTextColor( rStyleSettings
.GetDisableColor() );
582 // Set background color of the normal text
583 if( (GetStyle() & WB_FORCECTRLBACKGROUND
) != 0 && IsControlBackground() )
585 // check if we need to set ControlBackground even in NWF case
586 Push( PUSH_FILLCOLOR
| PUSH_LINECOLOR
);
588 SetFillColor( GetControlBackground() );
589 DrawRect( Rectangle( aPos
, Size( GetOutputSizePixel().Width() - 2*mnXOffset
, GetOutputSizePixel().Height() ) ) );
592 SetTextFillColor( GetControlBackground() );
594 else if( IsPaintTransparent() || ImplUseNativeBorder( GetStyle() ) )
597 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor() );
599 ImplPaintBorder( 0, GetOutputSizePixel().Width() );
601 bool bDrawSelection
= maSelection
.Len() && ( HasFocus() || ( GetStyle() & WB_NOHIDESELECTION
) || mbActivePopup
);
603 long nPos
= nStart
? pDX
[2*nStart
] : 0;
604 aPos
.X() = nPos
+ mnXOffset
+ ImplGetExtraOffset();
605 if ( bPaintPlaceholderText
)
607 DrawText( aPos
, maPlaceholderText
);
609 else if ( !bDrawSelection
&& !mpIMEInfos
)
611 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
615 // save graphics state
617 // first calculate higlighted and non highlighted clip regions
618 Region aHiglightClipRegion
;
619 Region aNormalClipRegion
;
620 Selection
aTmpSel( maSelection
);
622 // selection is highlighted
624 for( i
= 0; i
< aText
.getLength(); i
++ )
626 Rectangle
aRect( aPos
, Size( 10, nTH
) );
627 aRect
.Left() = pDX
[2*i
] + mnXOffset
+ ImplGetExtraOffset();
628 aRect
.Right() = pDX
[2*i
+1] + mnXOffset
+ ImplGetExtraOffset();
630 bool bHighlight
= false;
631 if( i
>= aTmpSel
.Min() && i
< aTmpSel
.Max() )
634 if( mpIMEInfos
&& mpIMEInfos
->pAttribs
&&
635 i
>= mpIMEInfos
->nPos
&& i
< (mpIMEInfos
->nPos
+mpIMEInfos
->nLen
) &&
636 ( mpIMEInfos
->pAttribs
[i
-mpIMEInfos
->nPos
] & EXTTEXTINPUT_ATTR_HIGHLIGHT
) )
640 aHiglightClipRegion
.Union( aRect
);
642 aNormalClipRegion
.Union( aRect
);
645 Color aNormalTextColor
= GetTextColor();
646 SetClipRegion( aNormalClipRegion
);
648 if( IsPaintTransparent() )
652 // Set background color when part of the text is selected
653 if ( ImplUseNativeBorder( GetStyle() ) )
655 if( (GetStyle() & WB_FORCECTRLBACKGROUND
) != 0 && IsControlBackground() )
656 SetTextFillColor( GetControlBackground() );
661 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor() );
663 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
665 // draw highlighted text
666 SetClipRegion( aHiglightClipRegion
);
667 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
668 SetTextFillColor( rStyleSettings
.GetHighlightColor() );
669 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
671 // if IME info exists loop over portions and output different font attributes
672 if( mpIMEInfos
&& mpIMEInfos
->pAttribs
)
674 for( int n
= 0; n
< 2; n
++ )
679 SetTextColor( aNormalTextColor
);
680 if( IsPaintTransparent() )
683 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor() );
684 aRegion
= aNormalClipRegion
;
688 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
689 SetTextFillColor( rStyleSettings
.GetHighlightColor() );
690 aRegion
= aHiglightClipRegion
;
693 for( i
= 0; i
< mpIMEInfos
->nLen
; )
695 sal_uInt16 nAttr
= mpIMEInfos
->pAttribs
[i
];
698 while( nIndex
< mpIMEInfos
->nLen
&& mpIMEInfos
->pAttribs
[nIndex
] == nAttr
) // #112631# check nIndex before using it
700 Rectangle
aRect( aPos
, Size( 10, nTH
) );
701 aRect
.Left() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)] + mnXOffset
+ ImplGetExtraOffset();
702 aRect
.Right() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)+1] + mnXOffset
+ ImplGetExtraOffset();
704 aClip
.Union( aRect
);
708 aClip
.Intersect(aRegion
);
709 if( !aClip
.IsEmpty() && nAttr
)
711 Font aFont
= GetFont();
712 if ( nAttr
& EXTTEXTINPUT_ATTR_UNDERLINE
)
713 aFont
.SetUnderline( UNDERLINE_SINGLE
);
714 else if ( nAttr
& EXTTEXTINPUT_ATTR_BOLDUNDERLINE
)
715 aFont
.SetUnderline( UNDERLINE_BOLD
);
716 else if ( nAttr
& EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE
)
717 aFont
.SetUnderline( UNDERLINE_DOTTED
);
718 else if ( nAttr
& EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE
)
719 aFont
.SetUnderline( UNDERLINE_DASHDOT
);
720 else if ( nAttr
& EXTTEXTINPUT_ATTR_GRAYWAVELINE
)
722 aFont
.SetUnderline( UNDERLINE_WAVE
);
723 SetTextLineColor( Color( COL_LIGHTGRAY
) );
727 if ( nAttr
& EXTTEXTINPUT_ATTR_REDTEXT
)
728 SetTextColor( Color( COL_RED
) );
729 else if ( nAttr
& EXTTEXTINPUT_ATTR_HALFTONETEXT
)
730 SetTextColor( Color( COL_LIGHTGRAY
) );
732 SetClipRegion( aClip
);
733 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
739 // restore graphics state
743 if ( bVisCursor
&& ( !mpIMEInfos
|| mpIMEInfos
->bCursor
) )
750 // -----------------------------------------------------------------------
752 void Edit::ImplDelete( const Selection
& rSelection
, sal_uInt8 nDirection
, sal_uInt8 nMode
)
754 OUString aText
= ImplGetText();
756 // loeschen moeglich?
757 if ( !rSelection
.Len() &&
758 (((rSelection
.Min() == 0) && (nDirection
== EDIT_DEL_LEFT
)) ||
759 ((rSelection
.Max() == aText
.getLength()) && (nDirection
== EDIT_DEL_RIGHT
))) )
762 ImplClearLayoutData();
764 Selection
aSelection( rSelection
);
765 aSelection
.Justify();
767 if ( !aSelection
.Len() )
769 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
770 if ( nDirection
== EDIT_DEL_LEFT
)
772 if ( nMode
== EDIT_DELMODE_RESTOFWORD
)
774 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSelection
.Min(),
775 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
776 if ( aBoundary
.startPos
== aSelection
.Min() )
777 aBoundary
= xBI
->previousWord( maText
.toString(), aSelection
.Min(),
778 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
779 aSelection
.Min() = aBoundary
.startPos
;
781 else if ( nMode
== EDIT_DELMODE_RESTOFCONTENT
)
783 aSelection
.Min() = 0;
787 sal_Int32 nCount
= 1;
788 aSelection
.Min() = xBI
->previousCharacters( maText
.toString(), aSelection
.Min(),
789 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
794 if ( nMode
== EDIT_DELMODE_RESTOFWORD
)
796 i18n::Boundary aBoundary
= xBI
->nextWord( maText
.toString(), aSelection
.Max(),
797 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
798 aSelection
.Max() = aBoundary
.startPos
;
800 else if ( nMode
== EDIT_DELMODE_RESTOFCONTENT
)
802 aSelection
.Max() = aText
.getLength();
806 sal_Int32 nCount
= 1;
807 aSelection
.Max() = xBI
->nextCharacters( maText
.toString(), aSelection
.Max(),
808 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
813 maText
.remove( static_cast<sal_Int32
>(aSelection
.Min()), static_cast<sal_Int32
>(aSelection
.Len()) );
814 maSelection
.Min() = aSelection
.Min();
815 maSelection
.Max() = aSelection
.Min();
817 mbInternModified
= sal_True
;
820 // -----------------------------------------------------------------------
822 OUString
Edit::ImplGetValidString( const OUString
& rString
) const
824 OUString
aValidString( rString
);
825 aValidString
= comphelper::string::remove(aValidString
, '\n');
826 aValidString
= comphelper::string::remove(aValidString
, '\r');
827 aValidString
= aValidString
.replace('\t', ' ');
831 // -----------------------------------------------------------------------
832 uno::Reference
< i18n::XBreakIterator
> Edit::ImplGetBreakIterator() const
834 //!! since we don't want to become incompatible in the next minor update
835 //!! where this code will get integrated into, xISC will be a local
836 //!! variable instead of a class member!
837 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
838 return i18n::BreakIterator::create(xContext
);
840 // -----------------------------------------------------------------------
842 uno::Reference
< i18n::XExtendedInputSequenceChecker
> Edit::ImplGetInputSequenceChecker() const
844 //!! since we don't want to become incompatible in the next minor update
845 //!! where this code will get integrated into, xISC will be a local
846 //!! variable instead of a class member!
847 uno::Reference
< i18n::XExtendedInputSequenceChecker
> xISC
;
850 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
851 xISC
= i18n::InputSequenceChecker::create(xContext
);
856 // -----------------------------------------------------------------------
858 void Edit::ShowTruncationWarning( Window
* pParent
)
860 ResMgr
* pResMgr
= ImplGetResMgr();
863 WarningBox
aBox( pParent
, ResId( SV_EDIT_WARNING_BOX
, *pResMgr
) );
868 // -----------------------------------------------------------------------
870 bool Edit::ImplTruncateToMaxLen( OUString
& rStr
, sal_uInt32 nSelectionLen
) const
872 bool bWasTruncated
= false;
873 const sal_uInt32 nMaxLen
= mnMaxTextLen
< 65534 ? mnMaxTextLen
: 65534;
874 sal_uInt32 nLenAfter
= static_cast<sal_uInt32
>(maText
.getLength()) + rStr
.getLength() - nSelectionLen
;
875 if ( nLenAfter
> nMaxLen
)
877 sal_uInt32 nErasePos
= nMaxLen
- static_cast<sal_uInt32
>(maText
.getLength()) + nSelectionLen
;
878 rStr
= rStr
.copy( 0, nErasePos
);
879 bWasTruncated
= true;
881 return bWasTruncated
;
884 // -----------------------------------------------------------------------
886 void Edit::ImplInsertText( const OUString
& rStr
, const Selection
* pNewSel
, sal_Bool bIsUserInput
)
888 Selection
aSelection( maSelection
);
889 aSelection
.Justify();
891 OUString
aNewText( ImplGetValidString( rStr
) );
892 ImplTruncateToMaxLen( aNewText
, aSelection
.Len() );
894 ImplClearLayoutData();
896 if ( aSelection
.Len() )
897 maText
.remove( static_cast<sal_Int32
>(aSelection
.Min()), static_cast<sal_Int32
>(aSelection
.Len()) );
898 else if ( !mbInsertMode
&& (aSelection
.Max() < maText
.getLength()) )
899 maText
.remove( static_cast<sal_Int32
>(aSelection
.Max()), 1 );
901 // take care of input-sequence-checking now
902 if (bIsUserInput
&& !rStr
.isEmpty())
904 DBG_ASSERT( rStr
.getLength() == 1, "unexpected string length. User input is expected to providse 1 char only!" );
906 // determine if input-sequence-checking should be applied or not
908 uno::Reference
< i18n::XBreakIterator
> xBI( ImplGetBreakIterator(), UNO_QUERY
);
909 bool bIsInputSequenceChecking
= rStr
.getLength() == 1 &&
910 officecfg::Office::Common::I18N::CTL::CTLFont::get() &&
911 officecfg::Office::Common::I18N::CTL::CTLSequenceChecking::get() &&
912 aSelection
.Min() > 0 && /* first char needs not to be checked */
913 xBI
.is() && i18n::ScriptType::COMPLEX
== xBI
->getScriptType( rStr
, 0 );
916 uno::Reference
< i18n::XExtendedInputSequenceChecker
> xISC
;
917 if (bIsInputSequenceChecking
&& (xISC
= ImplGetInputSequenceChecker()).is())
919 sal_Unicode cChar
= rStr
[0];
920 sal_Int32 nTmpPos
= static_cast< sal_Int32
>( aSelection
.Min() );
921 sal_Int16 nCheckMode
= officecfg::Office::Common::I18N::CTL::CTLSequenceCheckingRestricted::get()?
922 i18n::InputSequenceCheckMode::STRICT
: i18n::InputSequenceCheckMode::BASIC
;
924 // the text that needs to be checked is only the one
925 // before the current cursor position
926 OUString
aOldText( maText
.getStr(), nTmpPos
);
927 OUString
aTmpText( aOldText
);
928 if (officecfg::Office::Common::I18N::CTL::CTLSequenceCheckingTypeAndReplace::get())
930 xISC
->correctInputSequence( aTmpText
, nTmpPos
- 1, cChar
, nCheckMode
);
932 // find position of first character that has changed
933 sal_Int32 nOldLen
= aOldText
.getLength();
934 sal_Int32 nTmpLen
= aTmpText
.getLength();
935 const sal_Unicode
*pOldTxt
= aOldText
.getStr();
936 const sal_Unicode
*pTmpTxt
= aTmpText
.getStr();
937 sal_Int32 nChgPos
= 0;
938 while ( nChgPos
< nOldLen
&& nChgPos
< nTmpLen
&&
939 pOldTxt
[nChgPos
] == pTmpTxt
[nChgPos
] )
942 OUString
aChgText( aTmpText
.copy( nChgPos
) );
944 // remove text from first pos to be changed to current pos
945 maText
.remove( nChgPos
, nTmpPos
- nChgPos
);
947 if (!aChgText
.isEmpty())
950 aSelection
.Min() = nChgPos
; // position for new text to be inserted
957 // should the character be ignored (i.e. not get inserted) ?
958 if (!xISC
->checkInputSequence( aOldText
, nTmpPos
- 1, cChar
, nCheckMode
))
963 // at this point now we will insert the non-empty text 'normally' some lines below...
966 if ( !aNewText
.isEmpty() )
967 maText
.insert( static_cast<sal_Int32
>(aSelection
.Min()), aNewText
);
971 maSelection
.Min() = aSelection
.Min() + aNewText
.getLength();
972 maSelection
.Max() = maSelection
.Min();
976 maSelection
= *pNewSel
;
977 if ( maSelection
.Min() > maText
.getLength() )
978 maSelection
.Min() = maText
.getLength();
979 if ( maSelection
.Max() > maText
.getLength() )
980 maSelection
.Max() = maText
.getLength();
984 mbInternModified
= sal_True
;
987 // -----------------------------------------------------------------------
989 void Edit::ImplSetText( const OUString
& rText
, const Selection
* pNewSelection
)
991 // we delete text by "selecting" the old text completely then calling InsertText; this is flicker free
992 if ( ( rText
.getLength() <= mnMaxTextLen
) &&
993 ( (rText
!= maText
.getStr()) || (pNewSelection
&& (*pNewSelection
!= maSelection
)) ) )
995 ImplClearLayoutData();
996 maSelection
.Min() = 0;
997 maSelection
.Max() = maText
.getLength();
998 if ( mnXOffset
|| HasPaintEvent() )
1001 maText
= ImplGetValidString( rText
);
1003 // #i54929# recalculate mnXOffset before ImplSetSelection,
1004 // else cursor ends up in wrong position
1007 if ( pNewSelection
)
1008 ImplSetSelection( *pNewSelection
, sal_False
);
1010 if ( mnXOffset
&& !pNewSelection
)
1011 maSelection
.Max() = 0;
1016 ImplInsertText( rText
, pNewSelection
);
1018 ImplCallEventListeners( VCLEVENT_EDIT_MODIFY
);
1022 // -----------------------------------------------------------------------
1024 int Edit::ImplGetNativeControlType() const
1027 const Window
*pControl
= mbIsSubEdit
? GetParent() : this;
1029 switch( pControl
->GetType() )
1031 case WINDOW_COMBOBOX
:
1032 case WINDOW_PATTERNBOX
:
1033 case WINDOW_NUMERICBOX
:
1034 case WINDOW_METRICBOX
:
1035 case WINDOW_CURRENCYBOX
:
1036 case WINDOW_DATEBOX
:
1037 case WINDOW_TIMEBOX
:
1038 case WINDOW_LONGCURRENCYBOX
:
1039 nCtrl
= CTRL_COMBOBOX
;
1042 case WINDOW_MULTILINEEDIT
:
1043 if ( GetWindow( WINDOW_BORDER
) != this )
1044 nCtrl
= CTRL_MULTILINE_EDITBOX
;
1046 nCtrl
= CTRL_EDITBOX_NOBORDER
;
1050 case WINDOW_PATTERNFIELD
:
1051 case WINDOW_METRICFIELD
:
1052 case WINDOW_CURRENCYFIELD
:
1053 case WINDOW_DATEFIELD
:
1054 case WINDOW_TIMEFIELD
:
1055 case WINDOW_LONGCURRENCYFIELD
:
1056 case WINDOW_NUMERICFIELD
:
1057 case WINDOW_SPINFIELD
:
1058 if( pControl
->GetStyle() & WB_SPIN
)
1059 nCtrl
= CTRL_SPINBOX
;
1062 if ( GetWindow( WINDOW_BORDER
) != this )
1063 nCtrl
= CTRL_EDITBOX
;
1065 nCtrl
= CTRL_EDITBOX_NOBORDER
;
1070 nCtrl
= CTRL_EDITBOX
;
1075 void Edit::ImplClearBackground( long nXStart
, long nXEnd
)
1078 * note: at this point the cursor must be switched off already
1081 Rectangle
aRect( aTmpPoint
, GetOutputSizePixel() );
1082 aRect
.Left() = nXStart
;
1083 aRect
.Right() = nXEnd
;
1085 if( !(ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent()) )
1089 void Edit::ImplPaintBorder( long nXStart
, long nXEnd
)
1092 Rectangle
aRect( aTmpPoint
, GetOutputSizePixel() );
1093 aRect
.Left() = nXStart
;
1094 aRect
.Right() = nXEnd
;
1096 if( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() )
1098 // draw the inner part by painting the whole control using its border window
1099 Window
*pControl
= this;
1100 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
1101 if( pBorder
== this )
1103 // we have no border, use parent
1104 pControl
= mbIsSubEdit
? GetParent() : this;
1105 pBorder
= pControl
->GetWindow( WINDOW_BORDER
);
1106 if( pBorder
== this )
1107 pBorder
= GetParent();
1112 // set proper clipping region to not overdraw the whole control
1113 Region aClipRgn
= GetPaintRegion();
1114 if( !aClipRgn
.IsNull() )
1116 // transform clipping region to border window's coordinate system
1117 if( IsRTLEnabled() != pBorder
->IsRTLEnabled() && Application::GetSettings().GetLayoutRTL() )
1119 // need to mirror in case border is not RTL but edit is (or vice versa)
1122 Rectangle
aBounds( aClipRgn
.GetBoundRect() );
1123 int xNew
= GetOutputSizePixel().Width() - aBounds
.GetWidth() - aBounds
.Left();
1124 aClipRgn
.Move( xNew
- aBounds
.Left(), 0 );
1126 // move offset of border window
1128 aBorderOffs
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs
) );
1129 aClipRgn
.Move( aBorderOffs
.X(), aBorderOffs
.Y() );
1135 aBorderOffs
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs
) );
1136 aClipRgn
.Move( aBorderOffs
.X(), aBorderOffs
.Y() );
1139 Region
oldRgn( pBorder
->GetClipRegion() );
1140 pBorder
->SetClipRegion( aClipRgn
);
1142 pBorder
->Paint( Rectangle() );
1144 pBorder
->SetClipRegion( oldRgn
);
1147 pBorder
->Paint( Rectangle() );
1153 // -----------------------------------------------------------------------
1155 void Edit::ImplShowCursor( sal_Bool bOnlyIfVisible
)
1157 if ( !IsUpdateMode() || ( bOnlyIfVisible
&& !IsReallyVisible() ) )
1160 Cursor
* pCursor
= GetCursor();
1161 OUString aText
= ImplGetText();
1165 sal_Int32 nDXBuffer
[256];
1166 sal_Int32
* pDXBuffer
= NULL
;
1167 sal_Int32
* pDX
= nDXBuffer
;
1169 if( !aText
.isEmpty() )
1171 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
1173 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
1177 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
1179 if( maSelection
.Max() < aText
.getLength() )
1180 nTextPos
= pDX
[ 2*maSelection
.Max() ];
1182 nTextPos
= pDX
[ 2*aText
.getLength()-1 ];
1185 long nCursorWidth
= 0;
1186 if ( !mbInsertMode
&& !maSelection
.Len() && (maSelection
.Max() < aText
.getLength()) )
1187 nCursorWidth
= GetTextWidth( aText
, (xub_StrLen
)maSelection
.Max(), 1 );
1188 long nCursorPosX
= nTextPos
+ mnXOffset
+ ImplGetExtraOffset();
1190 // cursor should land in visible area
1191 const Size aOutSize
= GetOutputSizePixel();
1192 if ( (nCursorPosX
< 0) || (nCursorPosX
>= aOutSize
.Width()) )
1194 long nOldXOffset
= mnXOffset
;
1196 if ( nCursorPosX
< 0 )
1198 mnXOffset
= - nTextPos
;
1200 mnXOffset
+= aOutSize
.Width() / 5;
1201 if ( mnXOffset
> nMaxX
)
1206 mnXOffset
= (aOutSize
.Width()-ImplGetExtraOffset()) - nTextPos
;
1208 if ( (aOutSize
.Width()-ImplGetExtraOffset()) < nTextPos
)
1210 long nMaxNegX
= (aOutSize
.Width()-ImplGetExtraOffset()) - GetTextWidth( aText
);
1211 mnXOffset
-= aOutSize
.Width() / 5;
1212 if ( mnXOffset
< nMaxNegX
) // beides negativ...
1213 mnXOffset
= nMaxNegX
;
1217 nCursorPosX
= nTextPos
+ mnXOffset
+ ImplGetExtraOffset();
1218 if ( nCursorPosX
== aOutSize
.Width() ) // dann nicht sichtbar...
1221 if ( mnXOffset
!= nOldXOffset
)
1222 ImplInvalidateOrRepaint();
1225 const long nTextHeight
= GetTextHeight();
1226 const long nCursorPosY
= ImplGetTextYPosition();
1227 pCursor
->SetPos( Point( nCursorPosX
, nCursorPosY
) );
1228 pCursor
->SetSize( Size( nCursorWidth
, nTextHeight
) );
1232 delete [] pDXBuffer
;
1235 // -----------------------------------------------------------------------
1237 void Edit::ImplAlign()
1239 long nTextWidth
= GetTextWidth( ImplGetText() );
1240 long nOutWidth
= GetOutputSizePixel().Width();
1242 if ( mnAlign
== EDIT_ALIGN_LEFT
)
1244 if( mnXOffset
&& ( nTextWidth
< nOutWidth
) )
1248 else if ( mnAlign
== EDIT_ALIGN_RIGHT
)
1250 long nMinXOffset
= nOutWidth
- nTextWidth
- 1 - ImplGetExtraOffset();
1251 bool bRTL
= IsRTLEnabled();
1252 if( mbIsSubEdit
&& GetParent() )
1253 bRTL
= GetParent()->IsRTLEnabled();
1256 if( nTextWidth
< nOutWidth
)
1257 mnXOffset
= nMinXOffset
;
1261 if( nTextWidth
< nOutWidth
)
1262 mnXOffset
= nMinXOffset
;
1263 else if ( mnXOffset
< nMinXOffset
)
1264 mnXOffset
= nMinXOffset
;
1267 else if( mnAlign
== EDIT_ALIGN_CENTER
)
1269 // would be nicer with check while scrolling but then it's not centred in scrolled state
1270 mnXOffset
= (nOutWidth
- nTextWidth
) / 2;
1275 // -----------------------------------------------------------------------
1277 void Edit::ImplAlignAndPaint()
1280 ImplInvalidateOrRepaint( 0, STRING_LEN
);
1284 // -----------------------------------------------------------------------
1286 sal_Int32
Edit::ImplGetCharPos( const Point
& rWindowPos
) const
1288 sal_Int32 nIndex
= STRING_LEN
;
1289 OUString aText
= ImplGetText();
1291 sal_Int32 nDXBuffer
[256];
1292 sal_Int32
* pDXBuffer
= NULL
;
1293 sal_Int32
* pDX
= nDXBuffer
;
1294 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
1296 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
1300 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
1301 long nX
= rWindowPos
.X() - mnXOffset
- ImplGetExtraOffset();
1302 for( int i
= 0; i
< aText
.getLength(); i
++ )
1304 if( (pDX
[2*i
] >= nX
&& pDX
[2*i
+1] <= nX
) ||
1305 (pDX
[2*i
+1] >= nX
&& pDX
[2*i
] <= nX
))
1307 nIndex
= sal::static_int_cast
<xub_StrLen
>(i
);
1308 if( pDX
[2*i
] < pDX
[2*i
+1] )
1310 if( nX
> (pDX
[2*i
]+pDX
[2*i
+1])/2 )
1315 if( nX
< (pDX
[2*i
]+pDX
[2*i
+1])/2 )
1321 if( nIndex
== STRING_LEN
)
1324 long nDiff
= std::abs( pDX
[0]-nX
);
1325 for( int i
= 1; i
< aText
.getLength(); i
++ )
1327 long nNewDiff
= std::abs( pDX
[2*i
]-nX
);
1329 if( nNewDiff
< nDiff
)
1331 nIndex
= sal::static_int_cast
<xub_StrLen
>(i
);
1335 if( nIndex
== aText
.getLength()-1 && std::abs( pDX
[2*nIndex
+1] - nX
) < nDiff
)
1336 nIndex
= STRING_LEN
;
1340 delete [] pDXBuffer
;
1345 // -----------------------------------------------------------------------
1347 void Edit::ImplSetCursorPos( sal_Int32 nChar
, sal_Bool bSelect
)
1349 Selection
aSelection( maSelection
);
1350 aSelection
.Max() = nChar
;
1352 aSelection
.Min() = aSelection
.Max();
1353 ImplSetSelection( aSelection
);
1356 // -----------------------------------------------------------------------
1358 void Edit::ImplLoadRes( const ResId
& rResId
)
1360 Control::ImplLoadRes( rResId
);
1362 xub_StrLen nTextLength
= ReadShortRes();
1364 SetMaxTextLen( nTextLength
);
1367 // -----------------------------------------------------------------------
1369 void Edit::ImplCopyToSelectionClipboard()
1371 if ( GetSelection().Len() )
1373 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aSelection(GetPrimarySelection());
1374 ImplCopy( aSelection
);
1378 void Edit::ImplCopy( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1380 ::vcl::unohelper::TextDataObject::CopyStringTo( GetSelected(), rxClipboard
);
1383 // -----------------------------------------------------------------------
1385 void Edit::ImplPaste( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1387 if ( rxClipboard
.is() )
1389 uno::Reference
< datatransfer::XTransferable
> xDataObj
;
1391 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
1395 xDataObj
= rxClipboard
->getContents();
1397 catch( const ::com::sun::star::uno::Exception
& )
1401 Application::AcquireSolarMutex( nRef
);
1403 if ( xDataObj
.is() )
1405 datatransfer::DataFlavor aFlavor
;
1406 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
1409 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
1412 if( ImplTruncateToMaxLen( aText
, maSelection
.Len() ) )
1413 ShowTruncationWarning( const_cast<Edit
*>(this) );
1414 ReplaceSelected( aText
);
1416 catch( const ::com::sun::star::uno::Exception
& )
1423 // -----------------------------------------------------------------------
1425 void Edit::MouseButtonDown( const MouseEvent
& rMEvt
)
1429 Control::MouseButtonDown( rMEvt
);
1433 xub_StrLen nChar
= ImplGetCharPos( rMEvt
.GetPosPixel() );
1434 Selection
aSelection( maSelection
);
1435 aSelection
.Justify();
1437 if ( rMEvt
.GetClicks() < 4 )
1439 mbClickedInSelection
= sal_False
;
1440 if ( rMEvt
.GetClicks() == 3 )
1442 ImplSetSelection( Selection( 0, 0xFFFF ) );
1443 ImplCopyToSelectionClipboard();
1446 else if ( rMEvt
.GetClicks() == 2 )
1448 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
1449 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSelection
.Max(),
1450 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
1451 ImplSetSelection( Selection( aBoundary
.startPos
, aBoundary
.endPos
) );
1452 ImplCopyToSelectionClipboard();
1454 else if ( !rMEvt
.IsShift() && HasFocus() && aSelection
.IsInside( nChar
) )
1455 mbClickedInSelection
= sal_True
;
1456 else if ( rMEvt
.IsLeft() )
1457 ImplSetCursorPos( nChar
, rMEvt
.IsShift() );
1459 if ( !mbClickedInSelection
&& rMEvt
.IsLeft() && ( rMEvt
.GetClicks() == 1 ) )
1460 StartTracking( STARTTRACK_SCROLLREPEAT
);
1463 mbInMBDown
= sal_True
; // then do not select all in GetFocus
1465 mbInMBDown
= sal_False
;
1468 // -----------------------------------------------------------------------
1470 void Edit::MouseButtonUp( const MouseEvent
& rMEvt
)
1472 if ( mbClickedInSelection
&& rMEvt
.IsLeft() )
1474 xub_StrLen nChar
= ImplGetCharPos( rMEvt
.GetPosPixel() );
1475 ImplSetCursorPos( nChar
, sal_False
);
1476 mbClickedInSelection
= sal_False
;
1478 else if ( rMEvt
.IsMiddle() && !mbReadOnly
&&
1479 ( GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION
) )
1481 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aSelection(Window::GetPrimarySelection());
1482 ImplPaste( aSelection
);
1487 // -----------------------------------------------------------------------
1489 void Edit::Tracking( const TrackingEvent
& rTEvt
)
1491 if ( rTEvt
.IsTrackingEnded() )
1493 if ( mbClickedInSelection
)
1495 xub_StrLen nChar
= ImplGetCharPos( rTEvt
.GetMouseEvent().GetPosPixel() );
1496 ImplSetCursorPos( nChar
, sal_False
);
1497 mbClickedInSelection
= sal_False
;
1499 else if ( rTEvt
.GetMouseEvent().IsLeft() )
1501 ImplCopyToSelectionClipboard();
1506 if( !mbClickedInSelection
)
1508 xub_StrLen nChar
= ImplGetCharPos( rTEvt
.GetMouseEvent().GetPosPixel() );
1509 ImplSetCursorPos( nChar
, sal_True
);
1513 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1514 mpUpdateDataTimer
->Start();//do not update while the user is still travelling in the control
1517 // -----------------------------------------------------------------------
1519 sal_Bool
Edit::ImplHandleKeyEvent( const KeyEvent
& rKEvt
)
1521 sal_Bool bDone
= sal_False
;
1522 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1523 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
1525 mbInternModified
= sal_False
;
1527 if ( eFunc
!= KEYFUNC_DONTKNOW
)
1533 if ( !mbReadOnly
&& maSelection
.Len() && !(GetStyle() & WB_PASSWORD
) )
1544 if ( !(GetStyle() & WB_PASSWORD
) )
1573 eFunc
= KEYFUNC_DONTKNOW
;
1577 if ( !bDone
&& rKEvt
.GetKeyCode().IsMod1() && !rKEvt
.GetKeyCode().IsMod2() )
1579 if ( nCode
== KEY_A
)
1581 ImplSetSelection( Selection( 0, maText
.getLength() ) );
1584 else if ( rKEvt
.GetKeyCode().IsShift() && (nCode
== KEY_S
) )
1586 if ( pImplFncGetSpecialChars
)
1588 Selection aSaveSel
= GetSelection(); // if someone changes the selection in Get/LoseFocus, e.g. URL bar
1589 OUString aChars
= pImplFncGetSpecialChars( this, GetFont() );
1590 SetSelection( aSaveSel
);
1591 if ( !aChars
.isEmpty() )
1593 ImplInsertText( aChars
);
1601 if ( eFunc
== KEYFUNC_DONTKNOW
&& ! bDone
)
1605 case com::sun::star::awt::Key::SELECT_ALL
:
1607 ImplSetSelection( Selection( 0, maText
.getLength() ) );
1616 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
1617 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
1618 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
1619 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
1620 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1621 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
1622 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1623 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
1624 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1625 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1626 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1627 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1628 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1629 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1630 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1631 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1633 if ( !rKEvt
.GetKeyCode().IsMod2() )
1635 ImplClearLayoutData();
1636 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
1638 Selection
aSel( maSelection
);
1639 bool bWord
= rKEvt
.GetKeyCode().IsMod1();
1640 bool bSelect
= rKEvt
.GetKeyCode().IsShift();
1641 bool bGoLeft
= (nCode
== KEY_LEFT
);
1642 bool bGoRight
= (nCode
== KEY_RIGHT
);
1643 bool bGoHome
= (nCode
== KEY_HOME
);
1644 bool bGoEnd
= (nCode
== KEY_END
);
1648 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
1649 bGoRight
= bWord
= true;break;
1650 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
1651 bGoRight
= bSelect
= bWord
= true;break;
1652 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
1653 bGoLeft
= bWord
= true;break;
1654 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
1655 bGoLeft
= bSelect
= bWord
= true;break;
1656 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1657 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1658 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1660 // fallthrough intended
1661 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1662 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1663 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1664 bGoHome
= true;break;
1665 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
1666 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1667 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1669 // fallthrough intended
1670 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
1671 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1672 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1673 bGoEnd
= true;break;
1678 // Range wird in ImplSetSelection geprueft...
1679 if ( bGoLeft
&& aSel
.Max() )
1683 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSel
.Max(),
1684 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
1685 if ( aBoundary
.startPos
== aSel
.Max() )
1686 aBoundary
= xBI
->previousWord( maText
.toString(), aSel
.Max(),
1687 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1688 aSel
.Max() = aBoundary
.startPos
;
1692 sal_Int32 nCount
= 1;
1693 aSel
.Max() = xBI
->previousCharacters( maText
.toString(), aSel
.Max(),
1694 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
1697 else if ( bGoRight
&& ( aSel
.Max() < maText
.getLength() ) )
1701 i18n::Boundary aBoundary
= xBI
->nextWord( maText
.toString(), aSel
.Max(),
1702 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1703 aSel
.Max() = aBoundary
.startPos
;
1707 sal_Int32 nCount
= 1;
1708 aSel
.Max() = xBI
->nextCharacters( maText
.toString(), aSel
.Max(),
1709 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
1718 aSel
.Max() = 0xFFFF;
1722 aSel
.Min() = aSel
.Max();
1724 if ( aSel
!= GetSelection() )
1726 ImplSetSelection( aSel
);
1727 ImplCopyToSelectionClipboard();
1730 if ( bGoEnd
&& maAutocompleteHdl
.IsSet() && !rKEvt
.GetKeyCode().GetModifier() )
1732 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
1734 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
1735 maAutocompleteHdl
.Call( this );
1744 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
1745 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
1746 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
1747 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
1751 if ( !mbReadOnly
&& !rKEvt
.GetKeyCode().IsMod2() )
1753 sal_uInt8 nDel
= (nCode
== KEY_DELETE
) ? EDIT_DEL_RIGHT
: EDIT_DEL_LEFT
;
1754 sal_uInt8 nMode
= rKEvt
.GetKeyCode().IsMod1() ? EDIT_DELMODE_RESTOFWORD
: EDIT_DELMODE_SIMPLE
;
1755 if ( (nMode
== EDIT_DELMODE_RESTOFWORD
) && rKEvt
.GetKeyCode().IsShift() )
1756 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1759 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
1760 nDel
= EDIT_DEL_LEFT
;
1761 nMode
= EDIT_DELMODE_RESTOFWORD
;
1763 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
1764 nDel
= EDIT_DEL_RIGHT
;
1765 nMode
= EDIT_DELMODE_RESTOFWORD
;
1767 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
1768 nDel
= EDIT_DEL_LEFT
;
1769 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1771 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
1772 nDel
= EDIT_DEL_RIGHT
;
1773 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1777 sal_Int32 nOldLen
= maText
.getLength();
1778 ImplDelete( maSelection
, nDel
, nMode
);
1779 if ( maText
.getLength() != nOldLen
)
1788 if ( !mpIMEInfos
&& !mbReadOnly
&& !rKEvt
.GetKeyCode().IsMod2() )
1790 SetInsertMode( !mbInsertMode
);
1796 /* #i101255# disable autocomplete tab forward/backward
1797 users expect tab/shif-tab to move the focus to other controls
1798 not suddenly to cycle the autocompletion
1801 if ( !mbReadOnly && maAutocompleteHdl.IsSet() &&
1802 maSelection.Min() && (maSelection.Min() == maText.Len()) &&
1803 !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() )
1805 // Kein Autocomplete wenn alles Selektiert oder Edit leer, weil dann
1806 // keine vernuenftige Tab-Steuerung!
1807 if ( rKEvt.GetKeyCode().IsShift() )
1808 meAutocompleteAction = AUTOCOMPLETE_TABBACKWARD;
1810 meAutocompleteAction = AUTOCOMPLETE_TABFORWARD;
1812 maAutocompleteHdl.Call( this );
1814 // Wurde nichts veraendert, dann TAB fuer DialogControl
1815 if ( GetSelection().Len() )
1824 if ( IsCharInput( rKEvt
) )
1826 bDone
= sal_True
; // read characters also when in ReadOnly
1829 ImplInsertText(OUString(rKEvt
.GetCharCode()), 0, sal_True
);
1830 if ( maAutocompleteHdl
.IsSet() )
1832 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
1834 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
1835 maAutocompleteHdl
.Call( this );
1844 if ( mbInternModified
)
1850 // -----------------------------------------------------------------------
1852 void Edit::KeyInput( const KeyEvent
& rKEvt
)
1854 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1855 mpUpdateDataTimer
->Start();//do not update while the user is still travelling in the control
1857 if ( mpSubEdit
|| !ImplHandleKeyEvent( rKEvt
) )
1858 Control::KeyInput( rKEvt
);
1861 // -----------------------------------------------------------------------
1863 void Edit::FillLayoutData() const
1865 mpControlData
->mpLayoutData
= new vcl::ControlLayoutData();
1866 const_cast<Edit
*>(this)->ImplRepaint( 0, STRING_LEN
, true );
1869 // -----------------------------------------------------------------------
1871 void Edit::Paint( const Rectangle
& )
1877 // -----------------------------------------------------------------------
1881 if ( !mpSubEdit
&& IsReallyVisible() )
1884 // Wegen vertikaler Zentrierung...
1892 // -----------------------------------------------------------------------
1894 void Edit::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, sal_uLong nFlags
)
1896 ImplInitSettings( sal_True
, sal_True
, sal_True
);
1898 Point aPos
= pDev
->LogicToPixel( rPos
);
1899 Size aSize
= pDev
->LogicToPixel( rSize
);
1900 Font aFont
= GetDrawPixelFont( pDev
);
1901 OutDevType eOutDevType
= pDev
->GetOutDevType();
1905 pDev
->SetFont( aFont
);
1906 pDev
->SetTextFillColor();
1908 // Border/Background
1909 pDev
->SetLineColor();
1910 pDev
->SetFillColor();
1911 bool bBorder
= !(nFlags
& WINDOW_DRAW_NOBORDER
) && (GetStyle() & WB_BORDER
);
1912 bool bBackground
= !(nFlags
& WINDOW_DRAW_NOBACKGROUND
) && IsControlBackground();
1913 if ( bBorder
|| bBackground
)
1915 Rectangle
aRect( aPos
, aSize
);
1918 ImplDrawFrame( pDev
, aRect
);
1922 pDev
->SetFillColor( GetControlBackground() );
1923 pDev
->DrawRect( aRect
);
1928 if ( ( nFlags
& WINDOW_DRAW_MONO
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1929 pDev
->SetTextColor( Color( COL_BLACK
) );
1932 if ( !(nFlags
& WINDOW_DRAW_NODISABLE
) && !IsEnabled() )
1934 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1935 pDev
->SetTextColor( rStyleSettings
.GetDisableColor() );
1939 pDev
->SetTextColor( GetTextColor() );
1943 OUString aText
= ImplGetText();
1944 long nTextHeight
= pDev
->GetTextHeight();
1945 long nTextWidth
= pDev
->GetTextWidth( aText
);
1946 long nOnePixel
= GetDrawPixel( pDev
, 1 );
1947 long nOffX
= 3*nOnePixel
;
1948 long nOffY
= (aSize
.Height() - nTextHeight
) / 2;
1952 ((nOffY
+nTextHeight
) > aSize
.Height()) ||
1953 ((nOffX
+nTextWidth
) > aSize
.Width()) )
1955 Rectangle
aClip( aPos
, aSize
);
1956 if ( nTextHeight
> aSize
.Height() )
1957 aClip
.Bottom() += nTextHeight
-aSize
.Height()+1; // prevent HP printers from 'optimizing'
1958 pDev
->IntersectClipRegion( aClip
);
1961 if ( GetStyle() & WB_CENTER
)
1963 aPos
.X() += (aSize
.Width() - nTextWidth
) / 2;
1966 else if ( GetStyle() & WB_RIGHT
)
1968 aPos
.X() += aSize
.Width() - nTextWidth
;
1972 pDev
->DrawText( Point( aPos
.X() + nOffX
, aPos
.Y() + nOffY
), aText
);
1977 GetSubEdit()->Draw( pDev
, rPos
, rSize
, nFlags
);
1981 // -----------------------------------------------------------------------
1983 void Edit::ImplInvalidateOutermostBorder( Window
* pWin
)
1985 // allow control to show focused state
1986 Window
*pInvalWin
= pWin
, *pBorder
= pWin
;
1987 while( ( pBorder
= pInvalWin
->GetWindow( WINDOW_BORDER
) ) != pInvalWin
&& pBorder
&&
1988 pInvalWin
->ImplGetFrame() == pBorder
->ImplGetFrame() )
1990 pInvalWin
= pBorder
;
1993 pInvalWin
->Invalidate( INVALIDATE_CHILDREN
| INVALIDATE_UPDATE
);
1996 void Edit::GetFocus()
1999 mpSubEdit
->ImplGrabFocus( GetGetFocusFlags() );
2000 else if ( !mbActivePopup
)
2002 maUndoText
= maText
.toString();
2004 sal_uLong nSelOptions
= GetSettings().GetStyleSettings().GetSelectionOptions();
2005 if ( !( GetStyle() & (WB_NOHIDESELECTION
|WB_READONLY
) )
2006 && ( GetGetFocusFlags() & (GETFOCUS_INIT
|GETFOCUS_TAB
|GETFOCUS_CURSOR
|GETFOCUS_MNEMONIC
) ) )
2008 if ( nSelOptions
& SELECTION_OPTION_SHOWFIRST
)
2010 maSelection
.Min() = maText
.getLength();
2011 maSelection
.Max() = 0;
2015 maSelection
.Min() = 0;
2016 maSelection
.Max() = maText
.getLength();
2019 ((Edit
*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2021 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2026 // FIXME: this is currently only on aqua
2027 // check for other platforms that need similar handling
2028 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2029 IsNativeWidgetEnabled() &&
2030 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
2032 ImplInvalidateOutermostBorder( mbIsSubEdit
? GetParent() : this );
2034 else if ( maSelection
.Len() )
2037 if ( !HasPaintEvent() )
2038 ImplInvalidateOrRepaint();
2043 SetInputContext( InputContext( GetFont(), !IsReadOnly() ? INPUTCONTEXT_TEXT
|INPUTCONTEXT_EXTTEXTINPUT
: 0 ) );
2046 Control::GetFocus();
2049 // -----------------------------------------------------------------------
2051 Window
* Edit::GetPreferredKeyInputWindow()
2054 return mpSubEdit
->GetPreferredKeyInputWindow();
2059 // -----------------------------------------------------------------------
2061 void Edit::LoseFocus()
2063 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
2065 //notify an update latest when the focus is lost
2066 mpUpdateDataTimer
->Stop();
2067 mpUpdateDataTimer
->Timeout();
2072 // FIXME: this is currently only on aqua
2073 // check for other platforms that need similar handling
2074 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2075 IsNativeWidgetEnabled() &&
2076 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
2078 ImplInvalidateOutermostBorder( mbIsSubEdit
? GetParent() : this );
2081 if ( !mbActivePopup
&& !( GetStyle() & WB_NOHIDESELECTION
) && maSelection
.Len() )
2082 ImplInvalidateOrRepaint(); // Selektion malen
2085 Control::LoseFocus();
2088 // -----------------------------------------------------------------------
2090 void Edit::Command( const CommandEvent
& rCEvt
)
2092 if ( rCEvt
.GetCommand() == COMMAND_CONTEXTMENU
)
2094 PopupMenu
* pPopup
= Edit::CreatePopupMenu();
2096 if ( !maSelection
.Len() )
2098 pPopup
->EnableItem( SV_MENU_EDIT_CUT
, sal_False
);
2099 pPopup
->EnableItem( SV_MENU_EDIT_COPY
, sal_False
);
2100 pPopup
->EnableItem( SV_MENU_EDIT_DELETE
, sal_False
);
2105 pPopup
->EnableItem( SV_MENU_EDIT_CUT
, sal_False
);
2106 pPopup
->EnableItem( SV_MENU_EDIT_PASTE
, sal_False
);
2107 pPopup
->EnableItem( SV_MENU_EDIT_DELETE
, sal_False
);
2108 pPopup
->EnableItem( SV_MENU_EDIT_INSERTSYMBOL
, sal_False
);
2112 // Paste nur, wenn Text im Clipboard
2113 sal_Bool bData
= sal_False
;
2114 uno::Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetClipboard();
2115 if ( xClipboard
.is() )
2117 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
2118 uno::Reference
< datatransfer::XTransferable
> xDataObj
= xClipboard
->getContents();
2119 Application::AcquireSolarMutex( nRef
);
2120 if ( xDataObj
.is() )
2122 datatransfer::DataFlavor aFlavor
;
2123 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
2124 bData
= xDataObj
->isDataFlavorSupported( aFlavor
);
2127 pPopup
->EnableItem( SV_MENU_EDIT_PASTE
, bData
);
2130 if ( maUndoText
== maText
.getStr() )
2131 pPopup
->EnableItem( SV_MENU_EDIT_UNDO
, sal_False
);
2132 if ( ( maSelection
.Min() == 0 ) && ( maSelection
.Max() == maText
.getLength() ) )
2133 pPopup
->EnableItem( SV_MENU_EDIT_SELECTALL
, sal_False
);
2134 if ( !pImplFncGetSpecialChars
)
2136 sal_uInt16 nPos
= pPopup
->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL
);
2137 pPopup
->RemoveItem( nPos
);
2138 pPopup
->RemoveItem( nPos
-1 );
2141 mbActivePopup
= sal_True
;
2142 Selection aSaveSel
= GetSelection(); // if someone changes selection in Get/LoseFocus, e.g. URL bar
2143 Point aPos
= rCEvt
.GetMousePosPixel();
2144 if ( !rCEvt
.IsMouseEvent() )
2146 // Show menu enventually centered in selection
2147 Size aSize
= GetOutputSizePixel();
2148 aPos
= Point( aSize
.Width()/2, aSize
.Height()/2 );
2150 sal_uInt16 n
= pPopup
->Execute( this, aPos
);
2151 Edit::DeletePopupMenu( pPopup
);
2152 SetSelection( aSaveSel
);
2155 case SV_MENU_EDIT_UNDO
:
2159 case SV_MENU_EDIT_CUT
:
2163 case SV_MENU_EDIT_COPY
:
2166 case SV_MENU_EDIT_PASTE
:
2170 case SV_MENU_EDIT_DELETE
:
2174 case SV_MENU_EDIT_SELECTALL
:
2175 ImplSetSelection( Selection( 0, maText
.getLength() ) );
2177 case SV_MENU_EDIT_INSERTSYMBOL
:
2179 OUString aChars
= pImplFncGetSpecialChars( this, GetFont() );
2180 SetSelection( aSaveSel
);
2181 if ( !aChars
.isEmpty() )
2183 ImplInsertText( aChars
);
2189 mbActivePopup
= sal_False
;
2191 else if ( rCEvt
.GetCommand() == COMMAND_STARTEXTTEXTINPUT
)
2195 sal_Int32 nPos
= static_cast<sal_Int32
>(maSelection
.Max());
2196 mpIMEInfos
= new Impl_IMEInfos( nPos
, OUString(maText
.getStr() + nPos
) );
2197 mpIMEInfos
->bWasCursorOverwrite
= !IsInsertMode();
2199 else if ( rCEvt
.GetCommand() == COMMAND_ENDEXTTEXTINPUT
)
2201 sal_Bool bInsertMode
= !mpIMEInfos
->bWasCursorOverwrite
;
2205 // set font without attributes, because it will not be re-initialised in Repaint anymore
2206 ImplInitSettings( sal_True
, sal_False
, sal_False
);
2208 SetInsertMode( bInsertMode
);
2212 // #i25161# call auto complete handler for ext text commit also
2213 if ( maAutocompleteHdl
.IsSet() )
2215 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
2217 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
2218 maAutocompleteHdl
.Call( this );
2222 else if ( rCEvt
.GetCommand() == COMMAND_EXTTEXTINPUT
)
2224 const CommandExtTextInputData
* pData
= rCEvt
.GetExtTextInputData();
2226 maText
.remove( mpIMEInfos
->nPos
, mpIMEInfos
->nLen
);
2227 maText
.insert( mpIMEInfos
->nPos
, pData
->GetText() );
2228 if ( mpIMEInfos
->bWasCursorOverwrite
)
2230 sal_Int32 nOldIMETextLen
= mpIMEInfos
->nLen
;
2231 sal_Int32 nNewIMETextLen
= pData
->GetText().getLength();
2232 if ( ( nOldIMETextLen
> nNewIMETextLen
) &&
2233 ( nNewIMETextLen
< mpIMEInfos
->aOldTextAfterStartPos
.getLength() ) )
2235 // restore old characters
2236 sal_Int32 nRestore
= nOldIMETextLen
- nNewIMETextLen
;
2237 maText
.insert( mpIMEInfos
->nPos
+ nNewIMETextLen
, mpIMEInfos
->aOldTextAfterStartPos
.copy( nNewIMETextLen
, nRestore
) );
2239 else if ( ( nOldIMETextLen
< nNewIMETextLen
) &&
2240 ( nOldIMETextLen
< mpIMEInfos
->aOldTextAfterStartPos
.getLength() ) )
2243 sal_uInt16 nOverwrite
= nNewIMETextLen
- nOldIMETextLen
;
2244 if ( ( nOldIMETextLen
+ nOverwrite
) > mpIMEInfos
->aOldTextAfterStartPos
.getLength() )
2245 nOverwrite
= mpIMEInfos
->aOldTextAfterStartPos
.getLength() - nOldIMETextLen
;
2246 maText
.remove( mpIMEInfos
->nPos
+ nNewIMETextLen
, nOverwrite
);
2251 if ( pData
->GetTextAttr() )
2253 mpIMEInfos
->CopyAttribs( pData
->GetTextAttr(), pData
->GetText().getLength() );
2254 mpIMEInfos
->bCursor
= pData
->IsCursorVisible();
2258 mpIMEInfos
->DestroyAttribs();
2261 ImplAlignAndPaint();
2262 xub_StrLen nCursorPos
= mpIMEInfos
->nPos
+ pData
->GetCursorPos();
2263 SetSelection( Selection( nCursorPos
, nCursorPos
) );
2264 SetInsertMode( !pData
->IsCursorOverwrite() );
2266 if ( pData
->IsCursorVisible() )
2267 GetCursor()->Show();
2269 GetCursor()->Hide();
2271 else if ( rCEvt
.GetCommand() == COMMAND_CURSORPOS
)
2275 xub_StrLen nCursorPos
= (sal_uInt16
)GetSelection().Max();
2276 SetCursorRect( NULL
, GetTextWidth( maText
.toString(), nCursorPos
, mpIMEInfos
->nPos
+mpIMEInfos
->nLen
-nCursorPos
) );
2283 else if ( rCEvt
.GetCommand() == COMMAND_SELECTIONCHANGE
)
2285 const CommandSelectionChangeData
*pData
= rCEvt
.GetSelectionChangeData();
2286 Selection
aSelection( pData
->GetStart(), pData
->GetEnd() );
2287 SetSelection(aSelection
);
2289 else if ( rCEvt
.GetCommand() == COMMAND_QUERYCHARPOSITION
)
2291 if (mpIMEInfos
&& mpIMEInfos
->nLen
> 0)
2293 OUString aText
= ImplGetText();
2294 sal_Int32 nDXBuffer
[256];
2295 sal_Int32
* pDXBuffer
= NULL
;
2296 sal_Int32
* pDX
= nDXBuffer
;
2298 if( !aText
.isEmpty() )
2300 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
2302 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
2306 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
2308 long nTH
= GetTextHeight();
2309 Point
aPos( mnXOffset
, ImplGetTextYPosition() );
2311 Rectangle
* aRects
= new Rectangle
[ mpIMEInfos
->nLen
];
2312 for ( int nIndex
= 0; nIndex
< mpIMEInfos
->nLen
; ++nIndex
)
2314 Rectangle
aRect( aPos
, Size( 10, nTH
) );
2315 aRect
.Left() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)] + mnXOffset
+ ImplGetExtraOffset();
2316 aRects
[ nIndex
] = aRect
;
2318 SetCompositionCharRect( aRects
, mpIMEInfos
->nLen
);
2324 Control::Command( rCEvt
);
2327 // -----------------------------------------------------------------------
2329 void Edit::StateChanged( StateChangedType nType
)
2331 if ( nType
== STATE_CHANGE_INITSHOW
)
2335 mnXOffset
= 0; // if GrabFocus before while size was still wrong
2338 ImplShowCursor( sal_False
);
2340 // update background (eventual SetPaintTransparent)
2341 ImplInitSettings( sal_False
, sal_False
, sal_True
);
2343 else if ( nType
== STATE_CHANGE_ENABLE
)
2347 // change text color only
2348 ImplInvalidateOrRepaint( 0, 0xFFFF );
2351 else if ( nType
== STATE_CHANGE_STYLE
|| nType
== STATE_CHANGE_MIRRORING
)
2353 WinBits nStyle
= GetStyle();
2354 if( nType
== STATE_CHANGE_STYLE
)
2356 nStyle
= ImplInitStyle( GetStyle() );
2360 sal_uInt16 nOldAlign
= mnAlign
;
2361 mnAlign
= EDIT_ALIGN_LEFT
;
2363 // --- RTL --- hack: right align until keyinput and cursor travelling works
2364 // edits are always RTL disabled
2365 // however the parent edits contain the correct setting
2366 if( mbIsSubEdit
&& GetParent()->IsRTLEnabled() )
2368 if( GetParent()->GetStyle() & WB_LEFT
)
2369 mnAlign
= EDIT_ALIGN_RIGHT
;
2370 if ( nType
== STATE_CHANGE_MIRRORING
)
2371 SetLayoutMode( TEXT_LAYOUT_BIDI_RTL
| TEXT_LAYOUT_TEXTORIGIN_LEFT
);
2373 else if( mbIsSubEdit
&& !GetParent()->IsRTLEnabled() )
2375 if ( nType
== STATE_CHANGE_MIRRORING
)
2376 SetLayoutMode( TEXT_LAYOUT_BIDI_LTR
| TEXT_LAYOUT_TEXTORIGIN_LEFT
);
2379 if ( nStyle
& WB_RIGHT
)
2380 mnAlign
= EDIT_ALIGN_RIGHT
;
2381 else if ( nStyle
& WB_CENTER
)
2382 mnAlign
= EDIT_ALIGN_CENTER
;
2383 if ( !maText
.isEmpty() && ( mnAlign
!= nOldAlign
) )
2390 else if ( nType
== STATE_CHANGE_ZOOM
)
2394 ImplInitSettings( sal_True
, sal_False
, sal_False
);
2395 ImplShowCursor( sal_True
);
2399 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
2403 ImplInitSettings( sal_True
, sal_False
, sal_False
);
2408 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
2412 ImplInitSettings( sal_False
, sal_True
, sal_False
);
2416 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
2420 ImplInitSettings( sal_False
, sal_False
, sal_True
);
2425 Control::StateChanged( nType
);
2428 // -----------------------------------------------------------------------
2430 void Edit::DataChanged( const DataChangedEvent
& rDCEvt
)
2432 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
2433 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
2434 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
2435 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
2439 ImplInitSettings( sal_True
, sal_True
, sal_True
);
2440 ImplShowCursor( sal_True
);
2445 Control::DataChanged( rDCEvt
);
2448 // -----------------------------------------------------------------------
2450 void Edit::ImplShowDDCursor()
2452 if ( !mpDDInfo
->bVisCursor
)
2454 long nTextWidth
= GetTextWidth( maText
.toString(), 0, mpDDInfo
->nDropPos
);
2455 long nTextHeight
= GetTextHeight();
2456 Rectangle
aCursorRect( Point( nTextWidth
+ mnXOffset
, (GetOutputSize().Height()-nTextHeight
)/2 ), Size( 2, nTextHeight
) );
2457 mpDDInfo
->aCursor
.SetWindow( this );
2458 mpDDInfo
->aCursor
.SetPos( aCursorRect
.TopLeft() );
2459 mpDDInfo
->aCursor
.SetSize( aCursorRect
.GetSize() );
2460 mpDDInfo
->aCursor
.Show();
2461 mpDDInfo
->bVisCursor
= true;
2465 // -----------------------------------------------------------------------
2467 void Edit::ImplHideDDCursor()
2469 if ( mpDDInfo
&& mpDDInfo
->bVisCursor
)
2471 mpDDInfo
->aCursor
.Hide();
2472 mpDDInfo
->bVisCursor
= false;
2476 // -----------------------------------------------------------------------
2482 ((Edit
*)GetParent())->Modify();
2486 if ( mpUpdateDataTimer
)
2487 mpUpdateDataTimer
->Start();
2489 if ( ImplCallEventListenersAndHandler( VCLEVENT_EDIT_MODIFY
, maModifyHdl
, this ) )
2490 // have been destroyed while calling into the handlers
2493 // #i13677# notify edit listeners about caret position change
2494 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2496 // FIXME: this is currently only on aqua
2497 // check for other platforms that need similar handling
2498 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2499 IsNativeWidgetEnabled() &&
2500 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
2502 ImplInvalidateOutermostBorder( this );
2507 // -----------------------------------------------------------------------
2509 void Edit::UpdateData()
2511 maUpdateDataHdl
.Call( this );
2514 // -----------------------------------------------------------------------
2516 IMPL_LINK_NOARG(Edit
, ImplUpdateDataHdl
)
2522 // -----------------------------------------------------------------------
2524 void Edit::EnableUpdateData( sal_uLong nTimeout
)
2527 DisableUpdateData();
2530 if ( !mpUpdateDataTimer
)
2532 mpUpdateDataTimer
= new Timer
;
2533 mpUpdateDataTimer
->SetTimeoutHdl( LINK( this, Edit
, ImplUpdateDataHdl
) );
2536 mpUpdateDataTimer
->SetTimeout( nTimeout
);
2540 // -----------------------------------------------------------------------
2542 void Edit::SetEchoChar( sal_Unicode c
)
2546 mpSubEdit
->SetEchoChar( c
);
2549 // -----------------------------------------------------------------------
2551 void Edit::SetReadOnly( sal_Bool bReadOnly
)
2553 if ( mbReadOnly
!= bReadOnly
)
2555 mbReadOnly
= bReadOnly
;
2557 mpSubEdit
->SetReadOnly( bReadOnly
);
2559 StateChanged( STATE_CHANGE_READONLY
);
2563 // -----------------------------------------------------------------------
2565 void Edit::SetAutocompleteHdl( const Link
& rHdl
)
2567 maAutocompleteHdl
= rHdl
;
2569 mpSubEdit
->SetAutocompleteHdl( rHdl
);
2572 // -----------------------------------------------------------------------
2574 void Edit::SetInsertMode( sal_Bool bInsert
)
2576 if ( bInsert
!= mbInsertMode
)
2578 mbInsertMode
= bInsert
;
2580 mpSubEdit
->SetInsertMode( bInsert
);
2586 // -----------------------------------------------------------------------
2588 sal_Bool
Edit::IsInsertMode() const
2591 return mpSubEdit
->IsInsertMode();
2593 return mbInsertMode
;
2596 // -----------------------------------------------------------------------
2598 void Edit::SetMaxTextLen( xub_StrLen nMaxLen
)
2600 mnMaxTextLen
= nMaxLen
? nMaxLen
: EDIT_NOLIMIT
;
2603 mpSubEdit
->SetMaxTextLen( mnMaxTextLen
);
2606 if ( maText
.getLength() > mnMaxTextLen
)
2607 ImplDelete( Selection( mnMaxTextLen
, maText
.getLength() ), EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2611 // -----------------------------------------------------------------------
2613 void Edit::SetSelection( const Selection
& rSelection
)
2615 // If the selection was changed from outside, e.g. by MouseButtonDown, don't call Tracking()
2616 // directly afterwards which would change the selection again
2619 else if ( mpSubEdit
&& mpSubEdit
->IsTracking() )
2620 mpSubEdit
->EndTracking();
2622 ImplSetSelection( rSelection
);
2625 // -----------------------------------------------------------------------
2627 void Edit::ImplSetSelection( const Selection
& rSelection
, sal_Bool bPaint
)
2630 mpSubEdit
->ImplSetSelection( rSelection
);
2633 if ( rSelection
!= maSelection
)
2635 Selection
aOld( maSelection
);
2636 Selection
aNew( rSelection
);
2638 if ( aNew
.Min() > maText
.getLength() )
2639 aNew
.Min() = maText
.getLength();
2640 if ( aNew
.Max() > maText
.getLength() )
2641 aNew
.Max() = maText
.getLength();
2642 if ( aNew
.Min() < 0 )
2644 if ( aNew
.Max() < 0 )
2647 if ( aNew
!= maSelection
)
2649 ImplClearLayoutData();
2652 if ( bPaint
&& ( aOld
.Len() || aNew
.Len() || IsPaintTransparent() ) )
2653 ImplInvalidateOrRepaint( 0, maText
.getLength() );
2656 ((Edit
*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2658 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2659 // #103511# notify combobox listeners of deselection
2660 if( !maSelection
&& GetParent() && GetParent()->GetType() == WINDOW_COMBOBOX
)
2661 ((Edit
*)GetParent())->ImplCallEventListeners( VCLEVENT_COMBOBOX_DESELECT
);
2667 // -----------------------------------------------------------------------
2669 const Selection
& Edit::GetSelection() const
2672 return mpSubEdit
->GetSelection();
2677 // -----------------------------------------------------------------------
2679 void Edit::ReplaceSelected( const OUString
& rStr
)
2682 mpSubEdit
->ReplaceSelected( rStr
);
2684 ImplInsertText( rStr
);
2687 // -----------------------------------------------------------------------
2689 void Edit::DeleteSelected()
2692 mpSubEdit
->DeleteSelected();
2695 if ( maSelection
.Len() )
2696 ImplDelete( maSelection
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2700 // -----------------------------------------------------------------------
2702 OUString
Edit::GetSelected() const
2705 return mpSubEdit
->GetSelected();
2708 Selection
aSelection( maSelection
);
2709 aSelection
.Justify();
2710 return OUString( maText
.getStr() + aSelection
.Min(), aSelection
.Len() );
2714 // -----------------------------------------------------------------------
2718 if ( !(GetStyle() & WB_PASSWORD
) )
2721 ReplaceSelected( OUString() );
2725 // -----------------------------------------------------------------------
2729 if ( !(GetStyle() & WB_PASSWORD
) )
2731 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aClipboard(GetClipboard());
2732 ImplCopy( aClipboard
);
2736 // -----------------------------------------------------------------------
2740 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aClipboard(GetClipboard());
2741 ImplPaste( aClipboard
);
2744 // -----------------------------------------------------------------------
2752 OUString
aText( maText
.toString() );
2753 ImplDelete( Selection( 0, aText
.getLength() ), EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2754 ImplInsertText( maUndoText
);
2755 ImplSetSelection( Selection( 0, maUndoText
.getLength() ) );
2760 // -----------------------------------------------------------------------
2762 void Edit::SetText( const OUString
& rStr
)
2765 mpSubEdit
->SetText( rStr
); // not directly ImplSetText if SetText overloaded
2768 Selection
aNewSel( 0, 0 ); // prevent scrolling
2769 ImplSetText( rStr
, &aNewSel
);
2773 // -----------------------------------------------------------------------
2775 void Edit::SetText( const OUString
& rStr
, const Selection
& rSelection
)
2778 mpSubEdit
->SetText( rStr
, rSelection
);
2780 ImplSetText( rStr
, &rSelection
);
2783 // -----------------------------------------------------------------------
2785 OUString
Edit::GetText() const
2788 return mpSubEdit
->GetText();
2790 return maText
.toString();
2793 // -----------------------------------------------------------------------
2795 void Edit::SetPlaceholderText( const OUString
& rStr
)
2798 mpSubEdit
->SetPlaceholderText( rStr
);
2799 else if ( maPlaceholderText
!= rStr
)
2801 maPlaceholderText
= rStr
;
2802 if ( GetText().isEmpty() )
2807 // -----------------------------------------------------------------------
2809 OUString
Edit::GetPlaceholderText() const
2812 return mpSubEdit
->GetPlaceholderText();
2814 return maPlaceholderText
;
2817 // -----------------------------------------------------------------------
2819 void Edit::SetModifyFlag()
2822 mpSubEdit
->mbModified
= sal_True
;
2824 mbModified
= sal_True
;
2827 // -----------------------------------------------------------------------
2829 void Edit::ClearModifyFlag()
2832 mpSubEdit
->mbModified
= sal_False
;
2834 mbModified
= sal_False
;
2837 // -----------------------------------------------------------------------
2839 void Edit::SetSubEdit( Edit
* pEdit
)
2844 SetPointer( POINTER_ARROW
); // Nur das SubEdit hat den BEAM...
2845 mpSubEdit
->mbIsSubEdit
= sal_True
;
2847 mpSubEdit
->SetReadOnly( mbReadOnly
);
2851 Size
Edit::CalcMinimumSizeForText(const OUString
&rString
) const
2853 int eCtrlType
= ImplGetNativeControlType();
2856 if (mnWidthInChars
!= -1)
2858 //CalcSize calls CalcWindowSize, but we will call that also in this
2859 //function, so undo the first one with CalcOutputSize
2860 aSize
= CalcOutputSize(CalcSize(mnWidthInChars
));
2865 if (mnMaxWidthChars
!= -1 && mnMaxWidthChars
< rString
.getLength())
2866 aString
= rString
.copy(0, mnMaxWidthChars
);
2870 aSize
.Height() = GetTextHeight();
2871 aSize
.Width() = GetTextWidth(aString
);
2872 aSize
.Width() += ImplGetExtraOffset() * 2;
2874 // do not create edit fields in which one cannot enter anything
2875 // a default minimum width should exist for at least 3 characters
2877 //CalcSize calls CalcWindowSize, but we will call that also in this
2878 //function, so undo the first one with CalcOutputSize
2879 Size
aMinSize(CalcOutputSize(CalcSize(3)));
2880 if (aSize
.Width() < aMinSize
.Width())
2881 aSize
.Width() = aMinSize
.Width();
2884 if (eCtrlType
!= CTRL_EDITBOX_NOBORDER
)
2886 // add some space between text entry and border
2887 aSize
.Height() += 4;
2890 aSize
= CalcWindowSize( aSize
);
2892 // ask NWF what if it has an opinion, too
2893 ImplControlValue aControlValue
;
2894 Rectangle
aRect( Point( 0, 0 ), aSize
);
2895 Rectangle aContent
, aBound
;
2896 if( GetNativeControlRegion(
2897 eCtrlType
, PART_ENTIRE_CONTROL
,
2898 aRect
, 0, aControlValue
, OUString(), aBound
, aContent
) )
2900 if( aBound
.GetHeight() > aSize
.Height() )
2901 aSize
.Height() = aBound
.GetHeight();
2906 Size
Edit::CalcMinimumSize() const
2908 return CalcMinimumSizeForText(GetText());
2911 Size
Edit::GetMinimumEditSize()
2913 Window
* pDefWin
= ImplGetDefaultWindow();
2914 Edit
aEdit( pDefWin
, WB_BORDER
);
2915 Size
aSize( aEdit
.CalcMinimumSize() );
2919 // -----------------------------------------------------------------------
2921 Size
Edit::GetOptimalSize() const
2923 return CalcMinimumSize();
2926 // -----------------------------------------------------------------------
2928 Size
Edit::CalcSize( xub_StrLen nChars
) const
2930 // width for N characters, independent from content.
2931 // works only correct for fixed fonts, average otherwise
2932 Size
aSz( GetTextWidth( OUString('x') ), GetTextHeight() );
2933 aSz
.Width() *= nChars
;
2934 aSz
.Width() += ImplGetExtraOffset() * 2;
2935 aSz
= CalcWindowSize( aSz
);
2939 // -----------------------------------------------------------------------
2941 xub_StrLen
Edit::GetMaxVisChars() const
2943 const Window
* pW
= mpSubEdit
? mpSubEdit
: this;
2944 long nOutWidth
= pW
->GetOutputSizePixel().Width();
2945 long nCharWidth
= GetTextWidth( OUString('x') );
2946 return nCharWidth
? (xub_StrLen
)(nOutWidth
/nCharWidth
) : 0;
2949 // -----------------------------------------------------------------------
2951 xub_StrLen
Edit::GetCharPos( const Point
& rWindowPos
) const
2953 return ImplGetCharPos( rWindowPos
);
2956 // -----------------------------------------------------------------------
2958 void Edit::SetGetSpecialCharsFunction( FncGetSpecialChars fn
)
2960 pImplFncGetSpecialChars
= fn
;
2963 // -----------------------------------------------------------------------
2965 FncGetSpecialChars
Edit::GetGetSpecialCharsFunction()
2967 return pImplFncGetSpecialChars
;
2970 // -----------------------------------------------------------------------
2972 PopupMenu
* Edit::CreatePopupMenu()
2974 ResMgr
* pResMgr
= ImplGetResMgr();
2976 return new PopupMenu();
2978 PopupMenu
* pPopup
= new PopupMenu( ResId( SV_RESID_MENU_EDIT
, *pResMgr
) );
2979 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
2980 if ( rStyleSettings
.GetHideDisabledMenuItems() )
2981 pPopup
->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES
);
2983 pPopup
->SetMenuFlags ( MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES
);
2984 if ( rStyleSettings
.GetAcceleratorsInContextMenus() )
2986 pPopup
->SetAccelKey( SV_MENU_EDIT_UNDO
, KeyCode( KEYFUNC_UNDO
) );
2987 pPopup
->SetAccelKey( SV_MENU_EDIT_CUT
, KeyCode( KEYFUNC_CUT
) );
2988 pPopup
->SetAccelKey( SV_MENU_EDIT_COPY
, KeyCode( KEYFUNC_COPY
) );
2989 pPopup
->SetAccelKey( SV_MENU_EDIT_PASTE
, KeyCode( KEYFUNC_PASTE
) );
2990 pPopup
->SetAccelKey( SV_MENU_EDIT_DELETE
, KeyCode( KEYFUNC_DELETE
) );
2991 pPopup
->SetAccelKey( SV_MENU_EDIT_SELECTALL
, KeyCode( KEY_A
, sal_False
, sal_True
, sal_False
, sal_False
) );
2992 pPopup
->SetAccelKey( SV_MENU_EDIT_INSERTSYMBOL
, KeyCode( KEY_S
, sal_True
, sal_True
, sal_False
, sal_False
) );
2997 // -----------------------------------------------------------------------
2999 void Edit::DeletePopupMenu( PopupMenu
* pMenu
)
3004 // ::com::sun::star::datatransfer::dnd::XDragGestureListener
3005 void Edit::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent
& rDGE
) throw (::com::sun::star::uno::RuntimeException
)
3007 SolarMutexGuard aVclGuard
;
3009 if ( !IsTracking() && maSelection
.Len() &&
3010 !(GetStyle() & WB_PASSWORD
) && (!mpDDInfo
|| mpDDInfo
->bStarterOfDD
== false) ) // Kein Mehrfach D&D
3012 Selection
aSel( maSelection
);
3015 // Nur wenn Maus in der Selektion...
3016 Point
aMousePos( rDGE
.DragOriginX
, rDGE
.DragOriginY
);
3017 xub_StrLen nChar
= ImplGetCharPos( aMousePos
);
3018 if ( (nChar
>= aSel
.Min()) && (nChar
< aSel
.Max()) )
3021 mpDDInfo
= new DDInfo
;
3023 mpDDInfo
->bStarterOfDD
= true;
3024 mpDDInfo
->aDndStartSel
= aSel
;
3028 EndTracking(); // Vor D&D Tracking ausschalten
3030 ::vcl::unohelper::TextDataObject
* pDataObj
= new ::vcl::unohelper::TextDataObject( GetSelected() );
3031 sal_Int8 nActions
= datatransfer::dnd::DNDConstants::ACTION_COPY
;
3032 if ( !IsReadOnly() )
3033 nActions
|= datatransfer::dnd::DNDConstants::ACTION_MOVE
;
3034 rDGE
.DragSource
->startDrag( rDGE
, nActions
, 0 /*cursor*/, 0 /*image*/, pDataObj
, mxDnDListener
);
3036 GetCursor()->Hide();
3042 // ::com::sun::star::datatransfer::dnd::XDragSourceListener
3043 void Edit::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent
& rDSDE
) throw (::com::sun::star::uno::RuntimeException
)
3045 SolarMutexGuard aVclGuard
;
3047 if ( rDSDE
.DropSuccess
&& ( rDSDE
.DropAction
& datatransfer::dnd::DNDConstants::ACTION_MOVE
) )
3049 Selection
aSel( mpDDInfo
->aDndStartSel
);
3050 if ( mpDDInfo
->bDroppedInMe
)
3052 if ( aSel
.Max() > mpDDInfo
->nDropPos
)
3054 long nLen
= aSel
.Len();
3059 ImplDelete( aSel
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
3068 // ::com::sun::star::datatransfer::dnd::XDropTargetListener
3069 void Edit::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
3071 SolarMutexGuard aVclGuard
;
3073 sal_Bool bChanges
= sal_False
;
3074 if ( !mbReadOnly
&& mpDDInfo
)
3078 Selection
aSel( maSelection
);
3081 if ( aSel
.Len() && !mpDDInfo
->bStarterOfDD
)
3082 ImplDelete( aSel
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
3084 mpDDInfo
->bDroppedInMe
= true;
3086 aSel
.Min() = mpDDInfo
->nDropPos
;
3087 aSel
.Max() = mpDDInfo
->nDropPos
;
3088 ImplSetSelection( aSel
);
3090 uno::Reference
< datatransfer::XTransferable
> xDataObj
= rDTDE
.Transferable
;
3091 if ( xDataObj
.is() )
3093 datatransfer::DataFlavor aFlavor
;
3094 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
3095 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
3097 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
3100 ImplInsertText( aText
);
3101 bChanges
= sal_True
;
3106 if ( !mpDDInfo
->bStarterOfDD
)
3113 rDTDE
.Context
->dropComplete( bChanges
);
3116 void Edit::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
3120 mpDDInfo
= new DDInfo
;
3122 // search for string data type
3123 const Sequence
< com::sun::star::datatransfer::DataFlavor
>& rFlavors( rDTDE
.SupportedDataFlavors
);
3124 sal_Int32 nEle
= rFlavors
.getLength();
3125 mpDDInfo
->bIsStringSupported
= false;
3126 for( sal_Int32 i
= 0; i
< nEle
; i
++ )
3128 sal_Int32 nIndex
= 0;
3129 OUString aMimetype
= rFlavors
[i
].MimeType
.getToken( 0, ';', nIndex
);
3130 if ( aMimetype
== "text/plain" )
3132 mpDDInfo
->bIsStringSupported
= true;
3138 void Edit::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent
& ) throw (::com::sun::star::uno::RuntimeException
)
3140 SolarMutexGuard aVclGuard
;
3145 void Edit::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
3147 SolarMutexGuard aVclGuard
;
3149 Point
aMousePos( rDTDE
.LocationX
, rDTDE
.LocationY
);
3151 xub_StrLen nPrevDropPos
= mpDDInfo
->nDropPos
;
3152 mpDDInfo
->nDropPos
= ImplGetCharPos( aMousePos
);
3155 Size aOutSize = GetOutputSizePixel();
3156 if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) )
3159 // No, I will not receive events in this case....
3163 Selection
aSel( maSelection
);
3166 // Don't accept drop in selection or read-only field...
3167 if ( IsReadOnly() || aSel
.IsInside( mpDDInfo
->nDropPos
) || ! mpDDInfo
->bIsStringSupported
)
3170 rDTDE
.Context
->rejectDrag();
3174 // Alten Cursor wegzeichnen...
3175 if ( !mpDDInfo
->bVisCursor
|| ( nPrevDropPos
!= mpDDInfo
->nDropPos
) )
3180 rDTDE
.Context
->acceptDrag( rDTDE
.DropAction
);
3184 OUString
Edit::GetSurroundingText() const
3187 return mpSubEdit
->GetSurroundingText();
3188 return maText
.toString();
3191 Selection
Edit::GetSurroundingTextSelection() const
3193 return GetSelection();
3196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */