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/configurationhelper.hxx>
59 #include <comphelper/processfactory.hxx>
60 #include <comphelper/string.hxx>
62 #include <sot/exchange.hxx>
63 #include <sot/formats.hxx>
64 #include <sal/macros.h>
66 #include <vcl/unohelp.hxx>
67 #include <vcl/unohelp2.hxx>
72 using namespace ::com::sun::star
;
73 using namespace ::com::sun::star::uno
;
74 using namespace ::com::sun::star::lang
;
75 using namespace ::rtl
;
78 // - Bei Tracking-Cancel DefaultSelection wieder herstellen
80 // =======================================================================
82 static FncGetSpecialChars pImplFncGetSpecialChars
= NULL
;
84 // =======================================================================
86 #define EDIT_ALIGN_LEFT 1
87 #define EDIT_ALIGN_CENTER 2
88 #define EDIT_ALIGN_RIGHT 3
90 #define EDIT_DEL_LEFT 1
91 #define EDIT_DEL_RIGHT 2
93 #define EDIT_DELMODE_SIMPLE 11
94 #define EDIT_DELMODE_RESTOFWORD 12
95 #define EDIT_DELMODE_RESTOFCONTENT 13
97 // =======================================================================
102 Selection aDndStartSel
;
107 bool bIsStringSupported
;
111 aCursor
.SetStyle( CURSOR_SHADOW
);
113 bStarterOfDD
= false;
114 bDroppedInMe
= false;
116 bIsStringSupported
= false;
120 // =======================================================================
124 OUString aOldTextAfterStartPos
;
125 sal_uInt16
* pAttribs
;
129 bool bWasCursorOverwrite
;
131 Impl_IMEInfos( xub_StrLen nPos
, const OUString
& rOldTextAfterStartPos
);
134 void CopyAttribs( const xub_StrLen
* pA
, xub_StrLen nL
);
135 void DestroyAttribs();
138 // -----------------------------------------------------------------------
140 Impl_IMEInfos::Impl_IMEInfos( xub_StrLen nP
, const OUString
& rOldTextAfterStartPos
)
141 : aOldTextAfterStartPos( rOldTextAfterStartPos
)
147 bWasCursorOverwrite
= false;
150 // -----------------------------------------------------------------------
152 Impl_IMEInfos::~Impl_IMEInfos()
157 // -----------------------------------------------------------------------
159 void Impl_IMEInfos::CopyAttribs( const xub_StrLen
* pA
, xub_StrLen nL
)
163 pAttribs
= new sal_uInt16
[ nL
];
164 memcpy( pAttribs
, pA
, nL
*sizeof(sal_uInt16
) );
167 // -----------------------------------------------------------------------
169 void Impl_IMEInfos::DestroyAttribs()
176 // =======================================================================
178 Edit::Edit( WindowType nType
) :
184 // -----------------------------------------------------------------------
186 Edit::Edit( Window
* pParent
, WinBits nStyle
) :
187 Control( WINDOW_EDIT
)
190 ImplInit( pParent
, nStyle
);
193 Edit::Edit( Window
* pParent
, const ResId
& rResId
) :
194 Control( WINDOW_EDIT
)
196 rResId
.SetRT( RSC_EDIT
);
197 WinBits nStyle
= ImplInitRes( rResId
);
199 ImplInit( pParent
, nStyle
);
200 ImplLoadRes( rResId
);
202 // Derived MultiLineEdit takes care to call Show only after MultiLineEdit
203 // ctor has already started:
204 if ( !(nStyle
& WB_HIDE
) && rResId
.GetRT() != RSC_MULTILINEEDIT
)
208 void Edit::SetWidthInChars(sal_Int32 nWidthInChars
)
210 if (mnWidthInChars
!= nWidthInChars
)
212 mnWidthInChars
= nWidthInChars
;
217 void Edit::setMaxWidthChars(sal_Int32 nWidth
)
219 if (nWidth
!= mnMaxWidthChars
)
221 mnMaxWidthChars
= nWidth
;
226 bool Edit::set_property(const OString
&rKey
, const OString
&rValue
)
228 if (rKey
== "width-chars")
229 SetWidthInChars(rValue
.toInt32());
230 else if (rKey
== "max-width-chars")
231 setMaxWidthChars(rValue
.toInt32());
232 else if (rKey
== "max-length")
234 sal_Int32 nTextLen
= rValue
.toInt32();
235 SetMaxTextLen(nTextLen
== 0 ? EDIT_NOLIMIT
: nTextLen
);
237 else if (rKey
== "editable")
239 bool bReadOnly
= !toBool(rValue
);
240 SetReadOnly(bReadOnly
);
241 //disable tab to traverse into readonly editables
242 WinBits nBits
= GetStyle();
243 nBits
&= ~(WB_TABSTOP
|WB_NOTABSTOP
);
247 nBits
|= WB_NOTABSTOP
;
250 else if (rKey
== "visibility")
252 WinBits nBits
= GetStyle();
253 nBits
&= ~(WB_PASSWORD
);
255 nBits
|= WB_PASSWORD
;
258 else if (rKey
== "placeholder-text")
259 SetPlaceholderText(OStringToOUString(rValue
, RTL_TEXTENCODING_UTF8
));
261 return Control::set_property(rKey
, rValue
);
265 // -----------------------------------------------------------------------
270 Cursor
* pCursor
= GetCursor();
279 delete mpUpdateDataTimer
;
281 if ( mxDnDListener
.is() )
283 if ( GetDragGestureRecognizer().is() )
285 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mxDnDListener
, uno::UNO_QUERY
);
286 GetDragGestureRecognizer()->removeDragGestureListener( xDGL
);
288 if ( GetDropTarget().is() )
290 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( mxDnDListener
, uno::UNO_QUERY
);
291 GetDropTarget()->removeDropTargetListener( xDTL
);
294 uno::Reference
< lang::XEventListener
> xEL( mxDnDListener
, uno::UNO_QUERY
);
295 xEL
->disposing( lang::EventObject() ); // #95154# #96585# Empty Source means it's the Client
299 // -----------------------------------------------------------------------
301 void Edit::ImplInitEditData()
304 mpUpdateDataTimer
= NULL
;
306 mnAlign
= EDIT_ALIGN_LEFT
;
307 mnMaxTextLen
= EDIT_NOLIMIT
;
309 mnMaxWidthChars
= -1;
310 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
311 mbModified
= sal_False
;
312 mbInternModified
= sal_False
;
313 mbReadOnly
= sal_False
;
314 mbInsertMode
= sal_True
;
315 mbClickedInSelection
= sal_False
;
316 mbActivePopup
= sal_False
;
317 mbIsSubEdit
= sal_False
;
318 mbInMBDown
= sal_False
;
323 // --- RTL --- no default mirroring for Edit controls
324 // note: controls that use a subedit will revert this (SpinField, ComboBox)
325 EnableRTL( sal_False
);
327 vcl::unohelper::DragAndDropWrapper
* pDnDWrapper
= new vcl::unohelper::DragAndDropWrapper( this );
328 mxDnDListener
= pDnDWrapper
;
331 // -----------------------------------------------------------------------
333 bool Edit::ImplUseNativeBorder( WinBits nStyle
)
336 IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE
)
337 && ((nStyle
&WB_BORDER
) && !(nStyle
&WB_NOBORDER
));
338 if( ! bRet
&& mbIsSubEdit
)
340 Window
* pWindow
= GetParent();
341 nStyle
= pWindow
->GetStyle();
342 bRet
= pWindow
->IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE
)
343 && ((nStyle
&WB_BORDER
) && !(nStyle
&WB_NOBORDER
));
348 void Edit::ImplInit( Window
* pParent
, WinBits nStyle
)
350 nStyle
= ImplInitStyle( nStyle
);
351 if ( !(nStyle
& (WB_CENTER
| WB_RIGHT
)) )
354 Control::ImplInit( pParent
, nStyle
, NULL
);
356 mbReadOnly
= (nStyle
& WB_READONLY
) != 0;
358 mnAlign
= EDIT_ALIGN_LEFT
;
360 // --- RTL --- hack: right align until keyinput and cursor travelling works
362 mnAlign
= EDIT_ALIGN_RIGHT
;
364 if ( nStyle
& WB_RIGHT
)
365 mnAlign
= EDIT_ALIGN_RIGHT
;
366 else if ( nStyle
& WB_CENTER
)
367 mnAlign
= EDIT_ALIGN_CENTER
;
369 SetCursor( new Cursor
);
371 SetPointer( Pointer( POINTER_TEXT
) );
372 ImplInitSettings( sal_True
, sal_True
, sal_True
);
374 uno::Reference
< datatransfer::dnd::XDragGestureListener
> xDGL( mxDnDListener
, uno::UNO_QUERY
);
375 uno::Reference
< datatransfer::dnd::XDragGestureRecognizer
> xDGR
= GetDragGestureRecognizer();
378 xDGR
->addDragGestureListener( xDGL
);
379 uno::Reference
< datatransfer::dnd::XDropTargetListener
> xDTL( mxDnDListener
, uno::UNO_QUERY
);
380 GetDropTarget()->addDropTargetListener( xDTL
);
381 GetDropTarget()->setActive( sal_True
);
382 GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE
);
386 // -----------------------------------------------------------------------
388 WinBits
Edit::ImplInitStyle( WinBits nStyle
)
390 if ( !(nStyle
& WB_NOTABSTOP
) )
391 nStyle
|= WB_TABSTOP
;
392 if ( !(nStyle
& WB_NOGROUP
) )
398 // -----------------------------------------------------------------------
400 sal_Bool
Edit::IsCharInput( const KeyEvent
& rKeyEvent
)
402 // In the future we must use new Unicode functions for this
403 sal_Unicode cCharCode
= rKeyEvent
.GetCharCode();
404 return ((cCharCode
>= 32) && (cCharCode
!= 127) &&
405 !rKeyEvent
.GetKeyCode().IsMod3() &&
406 !rKeyEvent
.GetKeyCode().IsMod2() &&
407 !rKeyEvent
.GetKeyCode().IsMod1() );
410 // -----------------------------------------------------------------------
412 void Edit::ImplModified()
414 mbModified
= sal_True
;
418 // -----------------------------------------------------------------------
420 void Edit::ImplInitSettings( sal_Bool bFont
, sal_Bool bForeground
, sal_Bool bBackground
)
422 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
426 Font aFont
= rStyleSettings
.GetFieldFont();
427 if ( IsControlFont() )
428 aFont
.Merge( GetControlFont() );
429 SetZoomedPointFont( aFont
);
430 ImplClearLayoutData();
433 if ( bFont
|| bForeground
)
435 Color aTextColor
= rStyleSettings
.GetFieldTextColor();
436 if ( IsControlForeground() )
437 aTextColor
= GetControlForeground();
438 SetTextColor( aTextColor
);
443 if ( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() )
445 // Transparent background
449 else if ( IsControlBackground() )
451 SetBackground( GetControlBackground() );
452 SetFillColor( GetControlBackground() );
456 SetBackground( rStyleSettings
.GetFieldColor() );
457 SetFillColor( rStyleSettings
.GetFieldColor() );
462 // -----------------------------------------------------------------------
464 long Edit::ImplGetExtraOffset() const
466 // MT 09/2002: nExtraOffsetX should become a member, instead of checking every time,
467 // but I need an incompatible update for this...
468 // #94095# Use extra offset only when edit has a border
469 long nExtraOffset
= 0;
470 if( ( GetStyle() & WB_BORDER
) || ( mbIsSubEdit
&& ( GetParent()->GetStyle() & WB_BORDER
) ) )
477 // -----------------------------------------------------------------------
479 OUString
Edit::ImplGetText() const
481 if ( mcEchoChar
|| (GetStyle() & WB_PASSWORD
) )
483 sal_Unicode cEchoChar
;
485 cEchoChar
= mcEchoChar
;
488 OUStringBuffer aText
;
489 comphelper::string::padToLength(aText
, maText
.getLength(), cEchoChar
);
490 return aText
.makeStringAndClear();
493 return maText
.toString();
496 // -----------------------------------------------------------------------
498 void Edit::ImplInvalidateOrRepaint( xub_StrLen nStart
, xub_StrLen nEnd
)
500 if( IsPaintTransparent() )
503 // FIXME: this is currently only on aqua
504 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
)
508 ImplRepaint( nStart
, nEnd
);
511 // -----------------------------------------------------------------------
513 long Edit::ImplGetTextYPosition() const
515 if ( GetStyle() & WB_TOP
)
516 return ImplGetExtraOffset();
517 else if ( GetStyle() & WB_BOTTOM
)
518 return GetOutputSizePixel().Height() - GetTextHeight() - ImplGetExtraOffset();
519 return ( GetOutputSizePixel().Height() - GetTextHeight() ) / 2;
522 // -----------------------------------------------------------------------
524 void Edit::ImplRepaint( xub_StrLen nStart
, xub_StrLen nEnd
, bool bLayout
)
526 if ( !IsReallyVisible() )
529 OUString aText
= ImplGetText();
531 nEnd
= aText
.getLength();
533 sal_Int32 nDXBuffer
[256];
534 sal_Int32
* pDXBuffer
= NULL
;
535 sal_Int32
* pDX
= nDXBuffer
;
537 if( !aText
.isEmpty() )
539 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
541 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
545 GetCaretPositions( aText
, pDX
, nStart
, nEnd
);
548 long nTH
= GetTextHeight();
549 Point
aPos( mnXOffset
, ImplGetTextYPosition() );
553 long nPos
= nStart
? pDX
[2*nStart
] : 0;
554 aPos
.X() = nPos
+ mnXOffset
+ ImplGetExtraOffset();
556 MetricVector
* pVector
= &mpControlData
->mpLayoutData
->m_aUnicodeBoundRects
;
557 OUString
* pDisplayText
= &mpControlData
->mpLayoutData
->m_aDisplayText
;
559 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
, pVector
, pDisplayText
);
566 Cursor
* pCursor
= GetCursor();
567 bool bVisCursor
= pCursor
? pCursor
->IsVisible() : false;
571 ImplClearBackground( 0, GetOutputSizePixel().Width() );
573 bool bPaintPlaceholderText
= aText
.isEmpty() && !maPlaceholderText
.isEmpty();
575 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
577 ImplInitSettings( sal_False
, sal_True
, sal_False
);
578 if ( !IsEnabled() || bPaintPlaceholderText
)
579 SetTextColor( rStyleSettings
.GetDisableColor() );
581 // Set background color of the normal text
582 if( (GetStyle() & WB_FORCECTRLBACKGROUND
) != 0 && IsControlBackground() )
584 // check if we need to set ControlBackground even in NWF case
585 Push( PUSH_FILLCOLOR
| PUSH_LINECOLOR
);
587 SetFillColor( GetControlBackground() );
588 DrawRect( Rectangle( aPos
, Size( GetOutputSizePixel().Width() - 2*mnXOffset
, GetOutputSizePixel().Height() ) ) );
591 SetTextFillColor( GetControlBackground() );
593 else if( IsPaintTransparent() || ImplUseNativeBorder( GetStyle() ) )
596 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor() );
598 ImplPaintBorder( 0, GetOutputSizePixel().Width() );
600 bool bDrawSelection
= maSelection
.Len() && ( HasFocus() || ( GetStyle() & WB_NOHIDESELECTION
) || mbActivePopup
);
602 long nPos
= nStart
? pDX
[2*nStart
] : 0;
603 aPos
.X() = nPos
+ mnXOffset
+ ImplGetExtraOffset();
604 if ( bPaintPlaceholderText
)
606 DrawText( aPos
, maPlaceholderText
);
608 else if ( !bDrawSelection
&& !mpIMEInfos
)
610 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
614 // save graphics state
616 // first calculate higlighted and non highlighted clip regions
617 Region aHiglightClipRegion
;
618 Region aNormalClipRegion
;
619 Selection
aTmpSel( maSelection
);
621 // selection is highlighted
623 for( i
= 0; i
< aText
.getLength(); i
++ )
625 Rectangle
aRect( aPos
, Size( 10, nTH
) );
626 aRect
.Left() = pDX
[2*i
] + mnXOffset
+ ImplGetExtraOffset();
627 aRect
.Right() = pDX
[2*i
+1] + mnXOffset
+ ImplGetExtraOffset();
629 bool bHighlight
= false;
630 if( i
>= aTmpSel
.Min() && i
< aTmpSel
.Max() )
633 if( mpIMEInfos
&& mpIMEInfos
->pAttribs
&&
634 i
>= mpIMEInfos
->nPos
&& i
< (mpIMEInfos
->nPos
+mpIMEInfos
->nLen
) &&
635 ( mpIMEInfos
->pAttribs
[i
-mpIMEInfos
->nPos
] & EXTTEXTINPUT_ATTR_HIGHLIGHT
) )
639 aHiglightClipRegion
.Union( aRect
);
641 aNormalClipRegion
.Union( aRect
);
644 Color aNormalTextColor
= GetTextColor();
645 SetClipRegion( aNormalClipRegion
);
647 if( IsPaintTransparent() )
651 // Set background color when part of the text is selected
652 if ( ImplUseNativeBorder( GetStyle() ) )
654 if( (GetStyle() & WB_FORCECTRLBACKGROUND
) != 0 && IsControlBackground() )
655 SetTextFillColor( GetControlBackground() );
660 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor() );
662 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
664 // draw highlighted text
665 SetClipRegion( aHiglightClipRegion
);
666 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
667 SetTextFillColor( rStyleSettings
.GetHighlightColor() );
668 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
670 // if IME info exists loop over portions and output different font attributes
671 if( mpIMEInfos
&& mpIMEInfos
->pAttribs
)
673 for( int n
= 0; n
< 2; n
++ )
678 SetTextColor( aNormalTextColor
);
679 if( IsPaintTransparent() )
682 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings
.GetFieldColor() );
683 aRegion
= aNormalClipRegion
;
687 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
688 SetTextFillColor( rStyleSettings
.GetHighlightColor() );
689 aRegion
= aHiglightClipRegion
;
692 for( i
= 0; i
< mpIMEInfos
->nLen
; )
694 sal_uInt16 nAttr
= mpIMEInfos
->pAttribs
[i
];
697 while( nIndex
< mpIMEInfos
->nLen
&& mpIMEInfos
->pAttribs
[nIndex
] == nAttr
) // #112631# check nIndex before using it
699 Rectangle
aRect( aPos
, Size( 10, nTH
) );
700 aRect
.Left() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)] + mnXOffset
+ ImplGetExtraOffset();
701 aRect
.Right() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)+1] + mnXOffset
+ ImplGetExtraOffset();
703 aClip
.Union( aRect
);
707 aClip
.Intersect(aRegion
);
708 if( !aClip
.IsEmpty() && nAttr
)
710 Font aFont
= GetFont();
711 if ( nAttr
& EXTTEXTINPUT_ATTR_UNDERLINE
)
712 aFont
.SetUnderline( UNDERLINE_SINGLE
);
713 else if ( nAttr
& EXTTEXTINPUT_ATTR_BOLDUNDERLINE
)
714 aFont
.SetUnderline( UNDERLINE_BOLD
);
715 else if ( nAttr
& EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE
)
716 aFont
.SetUnderline( UNDERLINE_DOTTED
);
717 else if ( nAttr
& EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE
)
718 aFont
.SetUnderline( UNDERLINE_DASHDOT
);
719 else if ( nAttr
& EXTTEXTINPUT_ATTR_GRAYWAVELINE
)
721 aFont
.SetUnderline( UNDERLINE_WAVE
);
722 SetTextLineColor( Color( COL_LIGHTGRAY
) );
726 if ( nAttr
& EXTTEXTINPUT_ATTR_REDTEXT
)
727 SetTextColor( Color( COL_RED
) );
728 else if ( nAttr
& EXTTEXTINPUT_ATTR_HALFTONETEXT
)
729 SetTextColor( Color( COL_LIGHTGRAY
) );
731 SetClipRegion( aClip
);
732 DrawText( aPos
, aText
, nStart
, nEnd
- nStart
);
738 // restore graphics state
742 if ( bVisCursor
&& ( !mpIMEInfos
|| mpIMEInfos
->bCursor
) )
749 // -----------------------------------------------------------------------
751 void Edit::ImplDelete( const Selection
& rSelection
, sal_uInt8 nDirection
, sal_uInt8 nMode
)
753 OUString aText
= ImplGetText();
755 // loeschen moeglich?
756 if ( !rSelection
.Len() &&
757 (((rSelection
.Min() == 0) && (nDirection
== EDIT_DEL_LEFT
)) ||
758 ((rSelection
.Max() == aText
.getLength()) && (nDirection
== EDIT_DEL_RIGHT
))) )
761 ImplClearLayoutData();
763 Selection
aSelection( rSelection
);
764 aSelection
.Justify();
766 if ( !aSelection
.Len() )
768 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
769 if ( nDirection
== EDIT_DEL_LEFT
)
771 if ( nMode
== EDIT_DELMODE_RESTOFWORD
)
773 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSelection
.Min(),
774 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
775 if ( aBoundary
.startPos
== aSelection
.Min() )
776 aBoundary
= xBI
->previousWord( maText
.toString(), aSelection
.Min(),
777 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
778 aSelection
.Min() = aBoundary
.startPos
;
780 else if ( nMode
== EDIT_DELMODE_RESTOFCONTENT
)
782 aSelection
.Min() = 0;
786 sal_Int32 nCount
= 1;
787 aSelection
.Min() = xBI
->previousCharacters( maText
.toString(), aSelection
.Min(),
788 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
793 if ( nMode
== EDIT_DELMODE_RESTOFWORD
)
795 i18n::Boundary aBoundary
= xBI
->nextWord( maText
.toString(), aSelection
.Max(),
796 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
797 aSelection
.Max() = aBoundary
.startPos
;
799 else if ( nMode
== EDIT_DELMODE_RESTOFCONTENT
)
801 aSelection
.Max() = aText
.getLength();
805 sal_Int32 nCount
= 1;
806 aSelection
.Max() = xBI
->nextCharacters( maText
.toString(), aSelection
.Max(),
807 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
812 maText
.remove( static_cast<sal_Int32
>(aSelection
.Min()), static_cast<sal_Int32
>(aSelection
.Len()) );
813 maSelection
.Min() = aSelection
.Min();
814 maSelection
.Max() = aSelection
.Min();
816 mbInternModified
= sal_True
;
819 // -----------------------------------------------------------------------
821 OUString
Edit::ImplGetValidString( const OUString
& rString
) const
823 OUString
aValidString( rString
);
824 aValidString
= comphelper::string::remove(aValidString
, '\n');
825 aValidString
= comphelper::string::remove(aValidString
, '\r');
826 aValidString
= aValidString
.replace('\t', ' ');
830 // -----------------------------------------------------------------------
831 uno::Reference
< i18n::XBreakIterator
> Edit::ImplGetBreakIterator() const
833 //!! since we don't want to become incompatible in the next minor update
834 //!! where this code will get integrated into, xISC will be a local
835 //!! variable instead of a class member!
836 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
837 return i18n::BreakIterator::create(xContext
);
839 // -----------------------------------------------------------------------
841 uno::Reference
< i18n::XExtendedInputSequenceChecker
> Edit::ImplGetInputSequenceChecker() const
843 //!! since we don't want to become incompatible in the next minor update
844 //!! where this code will get integrated into, xISC will be a local
845 //!! variable instead of a class member!
846 uno::Reference
< i18n::XExtendedInputSequenceChecker
> xISC
;
849 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
850 xISC
= i18n::InputSequenceChecker::create(xContext
);
855 // -----------------------------------------------------------------------
857 void Edit::ShowTruncationWarning( Window
* pParent
)
859 ResMgr
* pResMgr
= ImplGetResMgr();
862 WarningBox
aBox( pParent
, ResId( SV_EDIT_WARNING_BOX
, *pResMgr
) );
867 // -----------------------------------------------------------------------
869 bool Edit::ImplTruncateToMaxLen( OUString
& rStr
, sal_uInt32 nSelectionLen
) const
871 bool bWasTruncated
= false;
872 const sal_uInt32 nMaxLen
= mnMaxTextLen
< 65534 ? mnMaxTextLen
: 65534;
873 sal_uInt32 nLenAfter
= static_cast<sal_uInt32
>(maText
.getLength()) + rStr
.getLength() - nSelectionLen
;
874 if ( nLenAfter
> nMaxLen
)
876 sal_uInt32 nErasePos
= nMaxLen
- static_cast<sal_uInt32
>(maText
.getLength()) + nSelectionLen
;
877 rStr
= rStr
.copy( 0, nErasePos
);
878 bWasTruncated
= true;
880 return bWasTruncated
;
883 // -----------------------------------------------------------------------
885 void Edit::ImplInsertText( const OUString
& rStr
, const Selection
* pNewSel
, sal_Bool bIsUserInput
)
887 Selection
aSelection( maSelection
);
888 aSelection
.Justify();
890 OUString
aNewText( ImplGetValidString( rStr
) );
891 ImplTruncateToMaxLen( aNewText
, aSelection
.Len() );
893 ImplClearLayoutData();
895 if ( aSelection
.Len() )
896 maText
.remove( static_cast<sal_Int32
>(aSelection
.Min()), static_cast<sal_Int32
>(aSelection
.Len()) );
897 else if ( !mbInsertMode
&& (aSelection
.Max() < maText
.getLength()) )
898 maText
.remove( static_cast<sal_Int32
>(aSelection
.Max()), 1 );
900 // take care of input-sequence-checking now
901 if (bIsUserInput
&& !rStr
.isEmpty())
903 DBG_ASSERT( rStr
.getLength() == 1, "unexpected string length. User input is expected to providse 1 char only!" );
905 // determine if input-sequence-checking should be applied or not
907 static OUString
sModule( "/org.openoffice.Office.Common/I18N" );
908 static OUString
sRelNode( "CTL" );
909 static OUString
sCTLSequenceChecking( "CTLSequenceChecking" );
910 static OUString
sCTLSequenceCheckingRestricted( "CTLSequenceCheckingRestricted" );
911 static OUString
sCTLSequenceCheckingTypeAndReplace( "CTLSequenceCheckingTypeAndReplace" );
912 static OUString
sCTLFont( "CTLFont" );
914 sal_Bool bCTLSequenceChecking
= sal_False
;
915 sal_Bool bCTLSequenceCheckingRestricted
= sal_False
;
916 sal_Bool bCTLSequenceCheckingTypeAndReplace
= sal_False
;
917 sal_Bool bCTLFontEnabled
= sal_False
;
918 bool bIsInputSequenceChecking
= false;
920 // get access to the configuration of this office module
923 uno::Reference
< uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
924 uno::Reference
< container::XNameAccess
> xModuleCfg( ::comphelper::ConfigurationHelper::openConfig(
927 ::comphelper::ConfigurationHelper::E_READONLY
),
930 //!! get values from configuration.
931 //!! we can't use SvtCTLOptions here since vcl must not be linked
932 //!! against svtools. (It is already the other way around.)
933 Any aCTLSequenceChecking
= ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg
, sRelNode
, sCTLSequenceChecking
);
934 Any aCTLSequenceCheckingRestricted
= ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg
, sRelNode
, sCTLSequenceCheckingRestricted
);
935 Any aCTLSequenceCheckingTypeAndReplace
= ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg
, sRelNode
, sCTLSequenceCheckingTypeAndReplace
);
936 Any aCTLFontEnabled
= ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg
, sRelNode
, sCTLFont
);
937 aCTLSequenceChecking
>>= bCTLSequenceChecking
;
938 aCTLSequenceCheckingRestricted
>>= bCTLSequenceCheckingRestricted
;
939 aCTLSequenceCheckingTypeAndReplace
>>= bCTLSequenceCheckingTypeAndReplace
;
940 aCTLFontEnabled
>>= bCTLFontEnabled
;
944 bIsInputSequenceChecking
= false; // continue with inserting the new text
947 uno::Reference
< i18n::XBreakIterator
> xBI( ImplGetBreakIterator(), UNO_QUERY
);
948 bIsInputSequenceChecking
= rStr
.getLength() == 1 &&
950 bCTLSequenceChecking
&&
951 aSelection
.Min() > 0 && /* first char needs not to be checked */
952 xBI
.is() && i18n::ScriptType::COMPLEX
== xBI
->getScriptType( rStr
, 0 );
955 uno::Reference
< i18n::XExtendedInputSequenceChecker
> xISC
;
956 if (bIsInputSequenceChecking
&& (xISC
= ImplGetInputSequenceChecker()).is())
958 sal_Unicode cChar
= rStr
[0];
959 sal_Int32 nTmpPos
= static_cast< sal_Int32
>( aSelection
.Min() );
960 sal_Int16 nCheckMode
= bCTLSequenceCheckingRestricted
?
961 i18n::InputSequenceCheckMode::STRICT
: i18n::InputSequenceCheckMode::BASIC
;
963 // the text that needs to be checked is only the one
964 // before the current cursor position
965 OUString
aOldText( maText
.getStr(), nTmpPos
);
966 OUString
aTmpText( aOldText
);
967 if (bCTLSequenceCheckingTypeAndReplace
)
969 xISC
->correctInputSequence( aTmpText
, nTmpPos
- 1, cChar
, nCheckMode
);
971 // find position of first character that has changed
972 sal_Int32 nOldLen
= aOldText
.getLength();
973 sal_Int32 nTmpLen
= aTmpText
.getLength();
974 const sal_Unicode
*pOldTxt
= aOldText
.getStr();
975 const sal_Unicode
*pTmpTxt
= aTmpText
.getStr();
976 sal_Int32 nChgPos
= 0;
977 while ( nChgPos
< nOldLen
&& nChgPos
< nTmpLen
&&
978 pOldTxt
[nChgPos
] == pTmpTxt
[nChgPos
] )
981 OUString
aChgText( aTmpText
.copy( nChgPos
) );
983 // remove text from first pos to be changed to current pos
984 maText
.remove( nChgPos
, nTmpPos
- nChgPos
);
986 if (!aChgText
.isEmpty())
989 aSelection
.Min() = nChgPos
; // position for new text to be inserted
996 // should the character be ignored (i.e. not get inserted) ?
997 if (!xISC
->checkInputSequence( aOldText
, nTmpPos
- 1, cChar
, nCheckMode
))
1002 // at this point now we will insert the non-empty text 'normally' some lines below...
1005 if ( !aNewText
.isEmpty() )
1006 maText
.insert( static_cast<sal_Int32
>(aSelection
.Min()), aNewText
);
1010 maSelection
.Min() = aSelection
.Min() + aNewText
.getLength();
1011 maSelection
.Max() = maSelection
.Min();
1015 maSelection
= *pNewSel
;
1016 if ( maSelection
.Min() > maText
.getLength() )
1017 maSelection
.Min() = maText
.getLength();
1018 if ( maSelection
.Max() > maText
.getLength() )
1019 maSelection
.Max() = maText
.getLength();
1022 ImplAlignAndPaint();
1023 mbInternModified
= sal_True
;
1026 // -----------------------------------------------------------------------
1028 void Edit::ImplSetText( const OUString
& rText
, const Selection
* pNewSelection
)
1030 // we delete text by "selecting" the old text completely then calling InsertText; this is flicker free
1031 if ( ( rText
.getLength() <= mnMaxTextLen
) &&
1032 ( (rText
!= maText
.getStr()) || (pNewSelection
&& (*pNewSelection
!= maSelection
)) ) )
1034 ImplClearLayoutData();
1035 maSelection
.Min() = 0;
1036 maSelection
.Max() = maText
.getLength();
1037 if ( mnXOffset
|| HasPaintEvent() )
1040 maText
= ImplGetValidString( rText
);
1042 // #i54929# recalculate mnXOffset before ImplSetSelection,
1043 // else cursor ends up in wrong position
1046 if ( pNewSelection
)
1047 ImplSetSelection( *pNewSelection
, sal_False
);
1049 if ( mnXOffset
&& !pNewSelection
)
1050 maSelection
.Max() = 0;
1055 ImplInsertText( rText
, pNewSelection
);
1057 ImplCallEventListeners( VCLEVENT_EDIT_MODIFY
);
1061 // -----------------------------------------------------------------------
1063 int Edit::ImplGetNativeControlType() const
1066 const Window
*pControl
= mbIsSubEdit
? GetParent() : this;
1068 switch( pControl
->GetType() )
1070 case WINDOW_COMBOBOX
:
1071 case WINDOW_PATTERNBOX
:
1072 case WINDOW_NUMERICBOX
:
1073 case WINDOW_METRICBOX
:
1074 case WINDOW_CURRENCYBOX
:
1075 case WINDOW_DATEBOX
:
1076 case WINDOW_TIMEBOX
:
1077 case WINDOW_LONGCURRENCYBOX
:
1078 nCtrl
= CTRL_COMBOBOX
;
1081 case WINDOW_MULTILINEEDIT
:
1082 if ( GetWindow( WINDOW_BORDER
) != this )
1083 nCtrl
= CTRL_MULTILINE_EDITBOX
;
1085 nCtrl
= CTRL_EDITBOX_NOBORDER
;
1089 case WINDOW_PATTERNFIELD
:
1090 case WINDOW_METRICFIELD
:
1091 case WINDOW_CURRENCYFIELD
:
1092 case WINDOW_DATEFIELD
:
1093 case WINDOW_TIMEFIELD
:
1094 case WINDOW_LONGCURRENCYFIELD
:
1095 case WINDOW_NUMERICFIELD
:
1096 case WINDOW_SPINFIELD
:
1097 if( pControl
->GetStyle() & WB_SPIN
)
1098 nCtrl
= CTRL_SPINBOX
;
1101 if ( GetWindow( WINDOW_BORDER
) != this )
1102 nCtrl
= CTRL_EDITBOX
;
1104 nCtrl
= CTRL_EDITBOX_NOBORDER
;
1109 nCtrl
= CTRL_EDITBOX
;
1114 void Edit::ImplClearBackground( long nXStart
, long nXEnd
)
1117 * note: at this point the cursor must be switched off already
1120 Rectangle
aRect( aTmpPoint
, GetOutputSizePixel() );
1121 aRect
.Left() = nXStart
;
1122 aRect
.Right() = nXEnd
;
1124 if( !(ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent()) )
1128 void Edit::ImplPaintBorder( long nXStart
, long nXEnd
)
1131 Rectangle
aRect( aTmpPoint
, GetOutputSizePixel() );
1132 aRect
.Left() = nXStart
;
1133 aRect
.Right() = nXEnd
;
1135 if( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() )
1137 // draw the inner part by painting the whole control using its border window
1138 Window
*pControl
= this;
1139 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
1140 if( pBorder
== this )
1142 // we have no border, use parent
1143 pControl
= mbIsSubEdit
? GetParent() : this;
1144 pBorder
= pControl
->GetWindow( WINDOW_BORDER
);
1145 if( pBorder
== this )
1146 pBorder
= GetParent();
1151 // set proper clipping region to not overdraw the whole control
1152 Region aClipRgn
= GetPaintRegion();
1153 if( !aClipRgn
.IsNull() )
1155 // transform clipping region to border window's coordinate system
1156 if( IsRTLEnabled() != pBorder
->IsRTLEnabled() && Application::GetSettings().GetLayoutRTL() )
1158 // need to mirror in case border is not RTL but edit is (or vice versa)
1161 Rectangle
aBounds( aClipRgn
.GetBoundRect() );
1162 int xNew
= GetOutputSizePixel().Width() - aBounds
.GetWidth() - aBounds
.Left();
1163 aClipRgn
.Move( xNew
- aBounds
.Left(), 0 );
1165 // move offset of border window
1167 aBorderOffs
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs
) );
1168 aClipRgn
.Move( aBorderOffs
.X(), aBorderOffs
.Y() );
1174 aBorderOffs
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs
) );
1175 aClipRgn
.Move( aBorderOffs
.X(), aBorderOffs
.Y() );
1178 Region
oldRgn( pBorder
->GetClipRegion() );
1179 pBorder
->SetClipRegion( aClipRgn
);
1181 pBorder
->Paint( Rectangle() );
1183 pBorder
->SetClipRegion( oldRgn
);
1186 pBorder
->Paint( Rectangle() );
1192 // -----------------------------------------------------------------------
1194 void Edit::ImplShowCursor( sal_Bool bOnlyIfVisible
)
1196 if ( !IsUpdateMode() || ( bOnlyIfVisible
&& !IsReallyVisible() ) )
1199 Cursor
* pCursor
= GetCursor();
1200 OUString aText
= ImplGetText();
1204 sal_Int32 nDXBuffer
[256];
1205 sal_Int32
* pDXBuffer
= NULL
;
1206 sal_Int32
* pDX
= nDXBuffer
;
1208 if( !aText
.isEmpty() )
1210 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
1212 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
1216 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
1218 if( maSelection
.Max() < aText
.getLength() )
1219 nTextPos
= pDX
[ 2*maSelection
.Max() ];
1221 nTextPos
= pDX
[ 2*aText
.getLength()-1 ];
1224 long nCursorWidth
= 0;
1225 if ( !mbInsertMode
&& !maSelection
.Len() && (maSelection
.Max() < aText
.getLength()) )
1226 nCursorWidth
= GetTextWidth( aText
, (xub_StrLen
)maSelection
.Max(), 1 );
1227 long nCursorPosX
= nTextPos
+ mnXOffset
+ ImplGetExtraOffset();
1229 // cursor should land in visible area
1230 const Size aOutSize
= GetOutputSizePixel();
1231 if ( (nCursorPosX
< 0) || (nCursorPosX
>= aOutSize
.Width()) )
1233 long nOldXOffset
= mnXOffset
;
1235 if ( nCursorPosX
< 0 )
1237 mnXOffset
= - nTextPos
;
1239 mnXOffset
+= aOutSize
.Width() / 5;
1240 if ( mnXOffset
> nMaxX
)
1245 mnXOffset
= (aOutSize
.Width()-ImplGetExtraOffset()) - nTextPos
;
1247 if ( (aOutSize
.Width()-ImplGetExtraOffset()) < nTextPos
)
1249 long nMaxNegX
= (aOutSize
.Width()-ImplGetExtraOffset()) - GetTextWidth( aText
);
1250 mnXOffset
-= aOutSize
.Width() / 5;
1251 if ( mnXOffset
< nMaxNegX
) // beides negativ...
1252 mnXOffset
= nMaxNegX
;
1256 nCursorPosX
= nTextPos
+ mnXOffset
+ ImplGetExtraOffset();
1257 if ( nCursorPosX
== aOutSize
.Width() ) // dann nicht sichtbar...
1260 if ( mnXOffset
!= nOldXOffset
)
1261 ImplInvalidateOrRepaint();
1264 const long nTextHeight
= GetTextHeight();
1265 const long nCursorPosY
= ImplGetTextYPosition();
1266 pCursor
->SetPos( Point( nCursorPosX
, nCursorPosY
) );
1267 pCursor
->SetSize( Size( nCursorWidth
, nTextHeight
) );
1271 delete [] pDXBuffer
;
1274 // -----------------------------------------------------------------------
1276 void Edit::ImplAlign()
1278 long nTextWidth
= GetTextWidth( ImplGetText() );
1279 long nOutWidth
= GetOutputSizePixel().Width();
1281 if ( mnAlign
== EDIT_ALIGN_LEFT
)
1283 if( mnXOffset
&& ( nTextWidth
< nOutWidth
) )
1287 else if ( mnAlign
== EDIT_ALIGN_RIGHT
)
1289 long nMinXOffset
= nOutWidth
- nTextWidth
- 1 - ImplGetExtraOffset();
1290 bool bRTL
= IsRTLEnabled();
1291 if( mbIsSubEdit
&& GetParent() )
1292 bRTL
= GetParent()->IsRTLEnabled();
1295 if( nTextWidth
< nOutWidth
)
1296 mnXOffset
= nMinXOffset
;
1300 if( nTextWidth
< nOutWidth
)
1301 mnXOffset
= nMinXOffset
;
1302 else if ( mnXOffset
< nMinXOffset
)
1303 mnXOffset
= nMinXOffset
;
1306 else if( mnAlign
== EDIT_ALIGN_CENTER
)
1308 // would be nicer with check while scrolling but then it's not centred in scrolled state
1309 mnXOffset
= (nOutWidth
- nTextWidth
) / 2;
1314 // -----------------------------------------------------------------------
1316 void Edit::ImplAlignAndPaint()
1319 ImplInvalidateOrRepaint( 0, STRING_LEN
);
1323 // -----------------------------------------------------------------------
1325 xub_StrLen
Edit::ImplGetCharPos( const Point
& rWindowPos
) const
1327 xub_StrLen nIndex
= STRING_LEN
;
1328 OUString aText
= ImplGetText();
1330 sal_Int32 nDXBuffer
[256];
1331 sal_Int32
* pDXBuffer
= NULL
;
1332 sal_Int32
* pDX
= nDXBuffer
;
1333 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
1335 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
1339 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
1340 long nX
= rWindowPos
.X() - mnXOffset
- ImplGetExtraOffset();
1341 for( int i
= 0; i
< aText
.getLength(); i
++ )
1343 if( (pDX
[2*i
] >= nX
&& pDX
[2*i
+1] <= nX
) ||
1344 (pDX
[2*i
+1] >= nX
&& pDX
[2*i
] <= nX
))
1346 nIndex
= sal::static_int_cast
<xub_StrLen
>(i
);
1347 if( pDX
[2*i
] < pDX
[2*i
+1] )
1349 if( nX
> (pDX
[2*i
]+pDX
[2*i
+1])/2 )
1354 if( nX
< (pDX
[2*i
]+pDX
[2*i
+1])/2 )
1360 if( nIndex
== STRING_LEN
)
1363 long nDiff
= std::abs( pDX
[0]-nX
);
1364 for( int i
= 1; i
< aText
.getLength(); i
++ )
1366 long nNewDiff
= std::abs( pDX
[2*i
]-nX
);
1368 if( nNewDiff
< nDiff
)
1370 nIndex
= sal::static_int_cast
<xub_StrLen
>(i
);
1374 if( nIndex
== aText
.getLength()-1 && std::abs( pDX
[2*nIndex
+1] - nX
) < nDiff
)
1375 nIndex
= STRING_LEN
;
1379 delete [] pDXBuffer
;
1384 // -----------------------------------------------------------------------
1386 void Edit::ImplSetCursorPos( xub_StrLen nChar
, sal_Bool bSelect
)
1388 Selection
aSelection( maSelection
);
1389 aSelection
.Max() = nChar
;
1391 aSelection
.Min() = aSelection
.Max();
1392 ImplSetSelection( aSelection
);
1395 // -----------------------------------------------------------------------
1397 void Edit::ImplLoadRes( const ResId
& rResId
)
1399 Control::ImplLoadRes( rResId
);
1401 xub_StrLen nTextLength
= ReadShortRes();
1403 SetMaxTextLen( nTextLength
);
1406 // -----------------------------------------------------------------------
1408 void Edit::ImplCopyToSelectionClipboard()
1410 if ( GetSelection().Len() )
1412 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aSelection(GetPrimarySelection());
1413 ImplCopy( aSelection
);
1417 void Edit::ImplCopy( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1419 ::vcl::unohelper::TextDataObject::CopyStringTo( GetSelected(), rxClipboard
);
1422 // -----------------------------------------------------------------------
1424 void Edit::ImplPaste( uno::Reference
< datatransfer::clipboard::XClipboard
>& rxClipboard
)
1426 if ( rxClipboard
.is() )
1428 uno::Reference
< datatransfer::XTransferable
> xDataObj
;
1430 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
1434 xDataObj
= rxClipboard
->getContents();
1436 catch( const ::com::sun::star::uno::Exception
& )
1440 Application::AcquireSolarMutex( nRef
);
1442 if ( xDataObj
.is() )
1444 datatransfer::DataFlavor aFlavor
;
1445 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
1448 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
1451 if( ImplTruncateToMaxLen( aText
, maSelection
.Len() ) )
1452 ShowTruncationWarning( const_cast<Edit
*>(this) );
1453 ReplaceSelected( aText
);
1455 catch( const ::com::sun::star::uno::Exception
& )
1462 // -----------------------------------------------------------------------
1464 void Edit::MouseButtonDown( const MouseEvent
& rMEvt
)
1468 Control::MouseButtonDown( rMEvt
);
1472 xub_StrLen nChar
= ImplGetCharPos( rMEvt
.GetPosPixel() );
1473 Selection
aSelection( maSelection
);
1474 aSelection
.Justify();
1476 if ( rMEvt
.GetClicks() < 4 )
1478 mbClickedInSelection
= sal_False
;
1479 if ( rMEvt
.GetClicks() == 3 )
1481 ImplSetSelection( Selection( 0, 0xFFFF ) );
1482 ImplCopyToSelectionClipboard();
1485 else if ( rMEvt
.GetClicks() == 2 )
1487 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
1488 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSelection
.Max(),
1489 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
1490 ImplSetSelection( Selection( aBoundary
.startPos
, aBoundary
.endPos
) );
1491 ImplCopyToSelectionClipboard();
1493 else if ( !rMEvt
.IsShift() && HasFocus() && aSelection
.IsInside( nChar
) )
1494 mbClickedInSelection
= sal_True
;
1495 else if ( rMEvt
.IsLeft() )
1496 ImplSetCursorPos( nChar
, rMEvt
.IsShift() );
1498 if ( !mbClickedInSelection
&& rMEvt
.IsLeft() && ( rMEvt
.GetClicks() == 1 ) )
1499 StartTracking( STARTTRACK_SCROLLREPEAT
);
1502 mbInMBDown
= sal_True
; // then do not select all in GetFocus
1504 mbInMBDown
= sal_False
;
1507 // -----------------------------------------------------------------------
1509 void Edit::MouseButtonUp( const MouseEvent
& rMEvt
)
1511 if ( mbClickedInSelection
&& rMEvt
.IsLeft() )
1513 xub_StrLen nChar
= ImplGetCharPos( rMEvt
.GetPosPixel() );
1514 ImplSetCursorPos( nChar
, sal_False
);
1515 mbClickedInSelection
= sal_False
;
1517 else if ( rMEvt
.IsMiddle() && !mbReadOnly
&&
1518 ( GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION
) )
1520 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aSelection(Window::GetPrimarySelection());
1521 ImplPaste( aSelection
);
1526 // -----------------------------------------------------------------------
1528 void Edit::Tracking( const TrackingEvent
& rTEvt
)
1530 if ( rTEvt
.IsTrackingEnded() )
1532 if ( mbClickedInSelection
)
1534 xub_StrLen nChar
= ImplGetCharPos( rTEvt
.GetMouseEvent().GetPosPixel() );
1535 ImplSetCursorPos( nChar
, sal_False
);
1536 mbClickedInSelection
= sal_False
;
1538 else if ( rTEvt
.GetMouseEvent().IsLeft() )
1540 ImplCopyToSelectionClipboard();
1545 if( !mbClickedInSelection
)
1547 xub_StrLen nChar
= ImplGetCharPos( rTEvt
.GetMouseEvent().GetPosPixel() );
1548 ImplSetCursorPos( nChar
, sal_True
);
1552 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1553 mpUpdateDataTimer
->Start();//do not update while the user is still travelling in the control
1556 // -----------------------------------------------------------------------
1558 sal_Bool
Edit::ImplHandleKeyEvent( const KeyEvent
& rKEvt
)
1560 sal_Bool bDone
= sal_False
;
1561 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1562 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
1564 mbInternModified
= sal_False
;
1566 if ( eFunc
!= KEYFUNC_DONTKNOW
)
1572 if ( !mbReadOnly
&& maSelection
.Len() && !(GetStyle() & WB_PASSWORD
) )
1583 if ( !(GetStyle() & WB_PASSWORD
) )
1612 eFunc
= KEYFUNC_DONTKNOW
;
1616 if ( !bDone
&& rKEvt
.GetKeyCode().IsMod1() && !rKEvt
.GetKeyCode().IsMod2() )
1618 if ( nCode
== KEY_A
)
1620 ImplSetSelection( Selection( 0, maText
.getLength() ) );
1623 else if ( rKEvt
.GetKeyCode().IsShift() && (nCode
== KEY_S
) )
1625 if ( pImplFncGetSpecialChars
)
1627 Selection aSaveSel
= GetSelection(); // if someone changes the selection in Get/LoseFocus, e.g. URL bar
1628 XubString aChars
= pImplFncGetSpecialChars( this, GetFont() );
1629 SetSelection( aSaveSel
);
1632 ImplInsertText( aChars
);
1640 if ( eFunc
== KEYFUNC_DONTKNOW
&& ! bDone
)
1644 case com::sun::star::awt::Key::SELECT_ALL
:
1646 ImplSetSelection( Selection( 0, maText
.getLength() ) );
1655 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
1656 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
1657 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
1658 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
1659 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1660 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
1661 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1662 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
1663 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1664 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1665 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1666 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1667 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1668 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1669 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1670 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1672 if ( !rKEvt
.GetKeyCode().IsMod2() )
1674 ImplClearLayoutData();
1675 uno::Reference
< i18n::XBreakIterator
> xBI
= ImplGetBreakIterator();
1677 Selection
aSel( maSelection
);
1678 bool bWord
= rKEvt
.GetKeyCode().IsMod1();
1679 bool bSelect
= rKEvt
.GetKeyCode().IsShift();
1680 bool bGoLeft
= (nCode
== KEY_LEFT
);
1681 bool bGoRight
= (nCode
== KEY_RIGHT
);
1682 bool bGoHome
= (nCode
== KEY_HOME
);
1683 bool bGoEnd
= (nCode
== KEY_END
);
1687 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
1688 bGoRight
= bWord
= true;break;
1689 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
1690 bGoRight
= bSelect
= bWord
= true;break;
1691 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
1692 bGoLeft
= bWord
= true;break;
1693 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
1694 bGoLeft
= bSelect
= bWord
= true;break;
1695 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
1696 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
1697 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
1699 // fallthrough intended
1700 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
1701 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
1702 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
1703 bGoHome
= true;break;
1704 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
1705 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
1706 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
1708 // fallthrough intended
1709 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
1710 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
1711 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
1712 bGoEnd
= true;break;
1717 // Range wird in ImplSetSelection geprueft...
1718 if ( bGoLeft
&& aSel
.Max() )
1722 i18n::Boundary aBoundary
= xBI
->getWordBoundary( maText
.toString(), aSel
.Max(),
1723 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
, sal_True
);
1724 if ( aBoundary
.startPos
== aSel
.Max() )
1725 aBoundary
= xBI
->previousWord( maText
.toString(), aSel
.Max(),
1726 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1727 aSel
.Max() = aBoundary
.startPos
;
1731 sal_Int32 nCount
= 1;
1732 aSel
.Max() = xBI
->previousCharacters( maText
.toString(), aSel
.Max(),
1733 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
1736 else if ( bGoRight
&& ( aSel
.Max() < maText
.getLength() ) )
1740 i18n::Boundary aBoundary
= xBI
->nextWord( maText
.toString(), aSel
.Max(),
1741 GetSettings().GetLanguageTag().getLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES
);
1742 aSel
.Max() = aBoundary
.startPos
;
1746 sal_Int32 nCount
= 1;
1747 aSel
.Max() = xBI
->nextCharacters( maText
.toString(), aSel
.Max(),
1748 GetSettings().GetLanguageTag().getLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER
, nCount
, nCount
);
1757 aSel
.Max() = 0xFFFF;
1761 aSel
.Min() = aSel
.Max();
1763 if ( aSel
!= GetSelection() )
1765 ImplSetSelection( aSel
);
1766 ImplCopyToSelectionClipboard();
1769 if ( bGoEnd
&& maAutocompleteHdl
.IsSet() && !rKEvt
.GetKeyCode().GetModifier() )
1771 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
1773 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
1774 maAutocompleteHdl
.Call( this );
1783 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
1784 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
1785 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
1786 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
1790 if ( !mbReadOnly
&& !rKEvt
.GetKeyCode().IsMod2() )
1792 sal_uInt8 nDel
= (nCode
== KEY_DELETE
) ? EDIT_DEL_RIGHT
: EDIT_DEL_LEFT
;
1793 sal_uInt8 nMode
= rKEvt
.GetKeyCode().IsMod1() ? EDIT_DELMODE_RESTOFWORD
: EDIT_DELMODE_SIMPLE
;
1794 if ( (nMode
== EDIT_DELMODE_RESTOFWORD
) && rKEvt
.GetKeyCode().IsShift() )
1795 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1798 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
1799 nDel
= EDIT_DEL_LEFT
;
1800 nMode
= EDIT_DELMODE_RESTOFWORD
;
1802 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
1803 nDel
= EDIT_DEL_RIGHT
;
1804 nMode
= EDIT_DELMODE_RESTOFWORD
;
1806 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
1807 nDel
= EDIT_DEL_LEFT
;
1808 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1810 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
1811 nDel
= EDIT_DEL_RIGHT
;
1812 nMode
= EDIT_DELMODE_RESTOFCONTENT
;
1816 sal_Int32 nOldLen
= maText
.getLength();
1817 ImplDelete( maSelection
, nDel
, nMode
);
1818 if ( maText
.getLength() != nOldLen
)
1827 if ( !mpIMEInfos
&& !mbReadOnly
&& !rKEvt
.GetKeyCode().IsMod2() )
1829 SetInsertMode( !mbInsertMode
);
1835 /* #i101255# disable autocomplete tab forward/backward
1836 users expect tab/shif-tab to move the focus to other controls
1837 not suddenly to cycle the autocompletion
1840 if ( !mbReadOnly && maAutocompleteHdl.IsSet() &&
1841 maSelection.Min() && (maSelection.Min() == maText.Len()) &&
1842 !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() )
1844 // Kein Autocomplete wenn alles Selektiert oder Edit leer, weil dann
1845 // keine vernuenftige Tab-Steuerung!
1846 if ( rKEvt.GetKeyCode().IsShift() )
1847 meAutocompleteAction = AUTOCOMPLETE_TABBACKWARD;
1849 meAutocompleteAction = AUTOCOMPLETE_TABFORWARD;
1851 maAutocompleteHdl.Call( this );
1853 // Wurde nichts veraendert, dann TAB fuer DialogControl
1854 if ( GetSelection().Len() )
1863 if ( IsCharInput( rKEvt
) )
1865 bDone
= sal_True
; // read characters also when in ReadOnly
1868 ImplInsertText(OUString(rKEvt
.GetCharCode()), 0, sal_True
);
1869 if ( maAutocompleteHdl
.IsSet() )
1871 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
1873 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
1874 maAutocompleteHdl
.Call( this );
1883 if ( mbInternModified
)
1889 // -----------------------------------------------------------------------
1891 void Edit::KeyInput( const KeyEvent
& rKEvt
)
1893 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
1894 mpUpdateDataTimer
->Start();//do not update while the user is still travelling in the control
1896 if ( mpSubEdit
|| !ImplHandleKeyEvent( rKEvt
) )
1897 Control::KeyInput( rKEvt
);
1900 // -----------------------------------------------------------------------
1902 void Edit::FillLayoutData() const
1904 mpControlData
->mpLayoutData
= new vcl::ControlLayoutData();
1905 const_cast<Edit
*>(this)->ImplRepaint( 0, STRING_LEN
, true );
1908 // -----------------------------------------------------------------------
1910 void Edit::Paint( const Rectangle
& )
1916 // -----------------------------------------------------------------------
1920 if ( !mpSubEdit
&& IsReallyVisible() )
1923 // Wegen vertikaler Zentrierung...
1931 // -----------------------------------------------------------------------
1933 void Edit::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, sal_uLong nFlags
)
1935 ImplInitSettings( sal_True
, sal_True
, sal_True
);
1937 Point aPos
= pDev
->LogicToPixel( rPos
);
1938 Size aSize
= pDev
->LogicToPixel( rSize
);
1939 Font aFont
= GetDrawPixelFont( pDev
);
1940 OutDevType eOutDevType
= pDev
->GetOutDevType();
1944 pDev
->SetFont( aFont
);
1945 pDev
->SetTextFillColor();
1947 // Border/Background
1948 pDev
->SetLineColor();
1949 pDev
->SetFillColor();
1950 bool bBorder
= !(nFlags
& WINDOW_DRAW_NOBORDER
) && (GetStyle() & WB_BORDER
);
1951 bool bBackground
= !(nFlags
& WINDOW_DRAW_NOBACKGROUND
) && IsControlBackground();
1952 if ( bBorder
|| bBackground
)
1954 Rectangle
aRect( aPos
, aSize
);
1957 ImplDrawFrame( pDev
, aRect
);
1961 pDev
->SetFillColor( GetControlBackground() );
1962 pDev
->DrawRect( aRect
);
1967 if ( ( nFlags
& WINDOW_DRAW_MONO
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1968 pDev
->SetTextColor( Color( COL_BLACK
) );
1971 if ( !(nFlags
& WINDOW_DRAW_NODISABLE
) && !IsEnabled() )
1973 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1974 pDev
->SetTextColor( rStyleSettings
.GetDisableColor() );
1978 pDev
->SetTextColor( GetTextColor() );
1982 OUString aText
= ImplGetText();
1983 long nTextHeight
= pDev
->GetTextHeight();
1984 long nTextWidth
= pDev
->GetTextWidth( aText
);
1985 long nOnePixel
= GetDrawPixel( pDev
, 1 );
1986 long nOffX
= 3*nOnePixel
;
1987 long nOffY
= (aSize
.Height() - nTextHeight
) / 2;
1991 ((nOffY
+nTextHeight
) > aSize
.Height()) ||
1992 ((nOffX
+nTextWidth
) > aSize
.Width()) )
1994 Rectangle
aClip( aPos
, aSize
);
1995 if ( nTextHeight
> aSize
.Height() )
1996 aClip
.Bottom() += nTextHeight
-aSize
.Height()+1; // prevent HP printers from 'optimizing'
1997 pDev
->IntersectClipRegion( aClip
);
2000 if ( GetStyle() & WB_CENTER
)
2002 aPos
.X() += (aSize
.Width() - nTextWidth
) / 2;
2005 else if ( GetStyle() & WB_RIGHT
)
2007 aPos
.X() += aSize
.Width() - nTextWidth
;
2011 pDev
->DrawText( Point( aPos
.X() + nOffX
, aPos
.Y() + nOffY
), aText
);
2016 GetSubEdit()->Draw( pDev
, rPos
, rSize
, nFlags
);
2020 // -----------------------------------------------------------------------
2022 void Edit::ImplInvalidateOutermostBorder( Window
* pWin
)
2024 // allow control to show focused state
2025 Window
*pInvalWin
= pWin
, *pBorder
= pWin
;
2026 while( ( pBorder
= pInvalWin
->GetWindow( WINDOW_BORDER
) ) != pInvalWin
&& pBorder
&&
2027 pInvalWin
->ImplGetFrame() == pBorder
->ImplGetFrame() )
2029 pInvalWin
= pBorder
;
2032 pInvalWin
->Invalidate( INVALIDATE_CHILDREN
| INVALIDATE_UPDATE
);
2035 void Edit::GetFocus()
2038 mpSubEdit
->ImplGrabFocus( GetGetFocusFlags() );
2039 else if ( !mbActivePopup
)
2041 maUndoText
= maText
.toString();
2043 sal_uLong nSelOptions
= GetSettings().GetStyleSettings().GetSelectionOptions();
2044 if ( !( GetStyle() & (WB_NOHIDESELECTION
|WB_READONLY
) )
2045 && ( GetGetFocusFlags() & (GETFOCUS_INIT
|GETFOCUS_TAB
|GETFOCUS_CURSOR
|GETFOCUS_MNEMONIC
) ) )
2047 if ( nSelOptions
& SELECTION_OPTION_SHOWFIRST
)
2049 maSelection
.Min() = maText
.getLength();
2050 maSelection
.Max() = 0;
2054 maSelection
.Min() = 0;
2055 maSelection
.Max() = maText
.getLength();
2058 ((Edit
*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2060 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2065 // FIXME: this is currently only on aqua
2066 // check for other platforms that need similar handling
2067 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2068 IsNativeWidgetEnabled() &&
2069 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
2071 ImplInvalidateOutermostBorder( mbIsSubEdit
? GetParent() : this );
2073 else if ( maSelection
.Len() )
2076 if ( !HasPaintEvent() )
2077 ImplInvalidateOrRepaint();
2082 SetInputContext( InputContext( GetFont(), !IsReadOnly() ? INPUTCONTEXT_TEXT
|INPUTCONTEXT_EXTTEXTINPUT
: 0 ) );
2085 Control::GetFocus();
2088 // -----------------------------------------------------------------------
2090 Window
* Edit::GetPreferredKeyInputWindow()
2093 return mpSubEdit
->GetPreferredKeyInputWindow();
2098 // -----------------------------------------------------------------------
2100 void Edit::LoseFocus()
2102 if ( mpUpdateDataTimer
&& !mbIsSubEdit
&& mpUpdateDataTimer
->IsActive() )
2104 //notify an update latest when the focus is lost
2105 mpUpdateDataTimer
->Stop();
2106 mpUpdateDataTimer
->Timeout();
2111 // FIXME: this is currently only on aqua
2112 // check for other platforms that need similar handling
2113 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2114 IsNativeWidgetEnabled() &&
2115 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
2117 ImplInvalidateOutermostBorder( mbIsSubEdit
? GetParent() : this );
2120 if ( !mbActivePopup
&& !( GetStyle() & WB_NOHIDESELECTION
) && maSelection
.Len() )
2121 ImplInvalidateOrRepaint(); // Selektion malen
2124 Control::LoseFocus();
2127 // -----------------------------------------------------------------------
2129 void Edit::Command( const CommandEvent
& rCEvt
)
2131 if ( rCEvt
.GetCommand() == COMMAND_CONTEXTMENU
)
2133 PopupMenu
* pPopup
= Edit::CreatePopupMenu();
2135 if ( !maSelection
.Len() )
2137 pPopup
->EnableItem( SV_MENU_EDIT_CUT
, sal_False
);
2138 pPopup
->EnableItem( SV_MENU_EDIT_COPY
, sal_False
);
2139 pPopup
->EnableItem( SV_MENU_EDIT_DELETE
, sal_False
);
2144 pPopup
->EnableItem( SV_MENU_EDIT_CUT
, sal_False
);
2145 pPopup
->EnableItem( SV_MENU_EDIT_PASTE
, sal_False
);
2146 pPopup
->EnableItem( SV_MENU_EDIT_DELETE
, sal_False
);
2147 pPopup
->EnableItem( SV_MENU_EDIT_INSERTSYMBOL
, sal_False
);
2151 // Paste nur, wenn Text im Clipboard
2152 sal_Bool bData
= sal_False
;
2153 uno::Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetClipboard();
2154 if ( xClipboard
.is() )
2156 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
2157 uno::Reference
< datatransfer::XTransferable
> xDataObj
= xClipboard
->getContents();
2158 Application::AcquireSolarMutex( nRef
);
2159 if ( xDataObj
.is() )
2161 datatransfer::DataFlavor aFlavor
;
2162 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
2163 bData
= xDataObj
->isDataFlavorSupported( aFlavor
);
2166 pPopup
->EnableItem( SV_MENU_EDIT_PASTE
, bData
);
2169 if ( maUndoText
== maText
.getStr() )
2170 pPopup
->EnableItem( SV_MENU_EDIT_UNDO
, sal_False
);
2171 if ( ( maSelection
.Min() == 0 ) && ( maSelection
.Max() == maText
.getLength() ) )
2172 pPopup
->EnableItem( SV_MENU_EDIT_SELECTALL
, sal_False
);
2173 if ( !pImplFncGetSpecialChars
)
2175 sal_uInt16 nPos
= pPopup
->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL
);
2176 pPopup
->RemoveItem( nPos
);
2177 pPopup
->RemoveItem( nPos
-1 );
2180 mbActivePopup
= sal_True
;
2181 Selection aSaveSel
= GetSelection(); // if someone changes selection in Get/LoseFocus, e.g. URL bar
2182 Point aPos
= rCEvt
.GetMousePosPixel();
2183 if ( !rCEvt
.IsMouseEvent() )
2185 // Show menu enventually centered in selection
2186 Size aSize
= GetOutputSizePixel();
2187 aPos
= Point( aSize
.Width()/2, aSize
.Height()/2 );
2189 sal_uInt16 n
= pPopup
->Execute( this, aPos
);
2190 Edit::DeletePopupMenu( pPopup
);
2191 SetSelection( aSaveSel
);
2194 case SV_MENU_EDIT_UNDO
:
2198 case SV_MENU_EDIT_CUT
:
2202 case SV_MENU_EDIT_COPY
:
2205 case SV_MENU_EDIT_PASTE
:
2209 case SV_MENU_EDIT_DELETE
:
2213 case SV_MENU_EDIT_SELECTALL
:
2214 ImplSetSelection( Selection( 0, maText
.getLength() ) );
2216 case SV_MENU_EDIT_INSERTSYMBOL
:
2218 XubString aChars
= pImplFncGetSpecialChars( this, GetFont() );
2219 SetSelection( aSaveSel
);
2222 ImplInsertText( aChars
);
2228 mbActivePopup
= sal_False
;
2230 else if ( rCEvt
.GetCommand() == COMMAND_STARTEXTTEXTINPUT
)
2234 sal_Int32 nPos
= static_cast<sal_Int32
>(maSelection
.Max());
2235 mpIMEInfos
= new Impl_IMEInfos( nPos
, OUString(maText
.getStr() + nPos
) );
2236 mpIMEInfos
->bWasCursorOverwrite
= !IsInsertMode();
2238 else if ( rCEvt
.GetCommand() == COMMAND_ENDEXTTEXTINPUT
)
2240 sal_Bool bInsertMode
= !mpIMEInfos
->bWasCursorOverwrite
;
2244 // set font without attributes, because it will not be re-initialised in Repaint anymore
2245 ImplInitSettings( sal_True
, sal_False
, sal_False
);
2247 SetInsertMode( bInsertMode
);
2251 // #i25161# call auto complete handler for ext text commit also
2252 if ( maAutocompleteHdl
.IsSet() )
2254 if ( (maSelection
.Min() == maSelection
.Max()) && (maSelection
.Min() == maText
.getLength()) )
2256 meAutocompleteAction
= AUTOCOMPLETE_KEYINPUT
;
2257 maAutocompleteHdl
.Call( this );
2261 else if ( rCEvt
.GetCommand() == COMMAND_EXTTEXTINPUT
)
2263 const CommandExtTextInputData
* pData
= rCEvt
.GetExtTextInputData();
2265 maText
.remove( mpIMEInfos
->nPos
, mpIMEInfos
->nLen
);
2266 maText
.insert( mpIMEInfos
->nPos
, pData
->GetText() );
2267 if ( mpIMEInfos
->bWasCursorOverwrite
)
2269 sal_uInt16 nOldIMETextLen
= mpIMEInfos
->nLen
;
2270 sal_uInt16 nNewIMETextLen
= pData
->GetText().Len();
2271 if ( ( nOldIMETextLen
> nNewIMETextLen
) &&
2272 ( nNewIMETextLen
< mpIMEInfos
->aOldTextAfterStartPos
.getLength() ) )
2274 // restore old characters
2275 sal_uInt16 nRestore
= nOldIMETextLen
- nNewIMETextLen
;
2276 maText
.insert( mpIMEInfos
->nPos
+ nNewIMETextLen
, mpIMEInfos
->aOldTextAfterStartPos
.copy( nNewIMETextLen
, nRestore
) );
2278 else if ( ( nOldIMETextLen
< nNewIMETextLen
) &&
2279 ( nOldIMETextLen
< mpIMEInfos
->aOldTextAfterStartPos
.getLength() ) )
2282 sal_uInt16 nOverwrite
= nNewIMETextLen
- nOldIMETextLen
;
2283 if ( ( nOldIMETextLen
+ nOverwrite
) > mpIMEInfos
->aOldTextAfterStartPos
.getLength() )
2284 nOverwrite
= mpIMEInfos
->aOldTextAfterStartPos
.getLength() - nOldIMETextLen
;
2285 maText
.remove( mpIMEInfos
->nPos
+ nNewIMETextLen
, nOverwrite
);
2290 if ( pData
->GetTextAttr() )
2292 mpIMEInfos
->CopyAttribs( pData
->GetTextAttr(), pData
->GetText().Len() );
2293 mpIMEInfos
->bCursor
= pData
->IsCursorVisible();
2297 mpIMEInfos
->DestroyAttribs();
2300 ImplAlignAndPaint();
2301 xub_StrLen nCursorPos
= mpIMEInfos
->nPos
+ pData
->GetCursorPos();
2302 SetSelection( Selection( nCursorPos
, nCursorPos
) );
2303 SetInsertMode( !pData
->IsCursorOverwrite() );
2305 if ( pData
->IsCursorVisible() )
2306 GetCursor()->Show();
2308 GetCursor()->Hide();
2310 else if ( rCEvt
.GetCommand() == COMMAND_CURSORPOS
)
2314 xub_StrLen nCursorPos
= (sal_uInt16
)GetSelection().Max();
2315 SetCursorRect( NULL
, GetTextWidth( maText
.toString(), nCursorPos
, mpIMEInfos
->nPos
+mpIMEInfos
->nLen
-nCursorPos
) );
2322 else if ( rCEvt
.GetCommand() == COMMAND_SELECTIONCHANGE
)
2324 const CommandSelectionChangeData
*pData
= rCEvt
.GetSelectionChangeData();
2325 Selection
aSelection( pData
->GetStart(), pData
->GetEnd() );
2326 SetSelection(aSelection
);
2328 else if ( rCEvt
.GetCommand() == COMMAND_QUERYCHARPOSITION
)
2330 if (mpIMEInfos
&& mpIMEInfos
->nLen
> 0)
2332 OUString aText
= ImplGetText();
2333 sal_Int32 nDXBuffer
[256];
2334 sal_Int32
* pDXBuffer
= NULL
;
2335 sal_Int32
* pDX
= nDXBuffer
;
2337 if( !aText
.isEmpty() )
2339 if( (size_t) (2*aText
.getLength()) > SAL_N_ELEMENTS(nDXBuffer
) )
2341 pDXBuffer
= new sal_Int32
[2*(aText
.getLength()+1)];
2345 GetCaretPositions( aText
, pDX
, 0, aText
.getLength() );
2347 long nTH
= GetTextHeight();
2348 Point
aPos( mnXOffset
, ImplGetTextYPosition() );
2350 Rectangle
* aRects
= new Rectangle
[ mpIMEInfos
->nLen
];
2351 for ( int nIndex
= 0; nIndex
< mpIMEInfos
->nLen
; ++nIndex
)
2353 Rectangle
aRect( aPos
, Size( 10, nTH
) );
2354 aRect
.Left() = pDX
[2*(nIndex
+mpIMEInfos
->nPos
)] + mnXOffset
+ ImplGetExtraOffset();
2355 aRects
[ nIndex
] = aRect
;
2357 SetCompositionCharRect( aRects
, mpIMEInfos
->nLen
);
2363 Control::Command( rCEvt
);
2366 // -----------------------------------------------------------------------
2368 void Edit::StateChanged( StateChangedType nType
)
2370 if ( nType
== STATE_CHANGE_INITSHOW
)
2374 mnXOffset
= 0; // if GrabFocus before while size was still wrong
2377 ImplShowCursor( sal_False
);
2379 // update background (eventual SetPaintTransparent)
2380 ImplInitSettings( sal_False
, sal_False
, sal_True
);
2382 else if ( nType
== STATE_CHANGE_ENABLE
)
2386 // change text color only
2387 ImplInvalidateOrRepaint( 0, 0xFFFF );
2390 else if ( nType
== STATE_CHANGE_STYLE
|| nType
== STATE_CHANGE_MIRRORING
)
2392 WinBits nStyle
= GetStyle();
2393 if( nType
== STATE_CHANGE_STYLE
)
2395 nStyle
= ImplInitStyle( GetStyle() );
2399 sal_uInt16 nOldAlign
= mnAlign
;
2400 mnAlign
= EDIT_ALIGN_LEFT
;
2402 // --- RTL --- hack: right align until keyinput and cursor travelling works
2403 // edits are always RTL disabled
2404 // however the parent edits contain the correct setting
2405 if( mbIsSubEdit
&& GetParent()->IsRTLEnabled() )
2407 if( GetParent()->GetStyle() & WB_LEFT
)
2408 mnAlign
= EDIT_ALIGN_RIGHT
;
2409 if ( nType
== STATE_CHANGE_MIRRORING
)
2410 SetLayoutMode( TEXT_LAYOUT_BIDI_RTL
| TEXT_LAYOUT_TEXTORIGIN_LEFT
);
2412 else if( mbIsSubEdit
&& !GetParent()->IsRTLEnabled() )
2414 if ( nType
== STATE_CHANGE_MIRRORING
)
2415 SetLayoutMode( TEXT_LAYOUT_BIDI_LTR
| TEXT_LAYOUT_TEXTORIGIN_LEFT
);
2418 if ( nStyle
& WB_RIGHT
)
2419 mnAlign
= EDIT_ALIGN_RIGHT
;
2420 else if ( nStyle
& WB_CENTER
)
2421 mnAlign
= EDIT_ALIGN_CENTER
;
2422 if ( maText
.getLength() && ( mnAlign
!= nOldAlign
) )
2429 else if ( nType
== STATE_CHANGE_ZOOM
)
2433 ImplInitSettings( sal_True
, sal_False
, sal_False
);
2434 ImplShowCursor( sal_True
);
2438 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
2442 ImplInitSettings( sal_True
, sal_False
, sal_False
);
2447 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
2451 ImplInitSettings( sal_False
, sal_True
, sal_False
);
2455 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
2459 ImplInitSettings( sal_False
, sal_False
, sal_True
);
2464 Control::StateChanged( nType
);
2467 // -----------------------------------------------------------------------
2469 void Edit::DataChanged( const DataChangedEvent
& rDCEvt
)
2471 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
2472 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
2473 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
2474 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
2478 ImplInitSettings( sal_True
, sal_True
, sal_True
);
2479 ImplShowCursor( sal_True
);
2484 Control::DataChanged( rDCEvt
);
2487 // -----------------------------------------------------------------------
2489 void Edit::ImplShowDDCursor()
2491 if ( !mpDDInfo
->bVisCursor
)
2493 long nTextWidth
= GetTextWidth( maText
.toString(), 0, mpDDInfo
->nDropPos
);
2494 long nTextHeight
= GetTextHeight();
2495 Rectangle
aCursorRect( Point( nTextWidth
+ mnXOffset
, (GetOutputSize().Height()-nTextHeight
)/2 ), Size( 2, nTextHeight
) );
2496 mpDDInfo
->aCursor
.SetWindow( this );
2497 mpDDInfo
->aCursor
.SetPos( aCursorRect
.TopLeft() );
2498 mpDDInfo
->aCursor
.SetSize( aCursorRect
.GetSize() );
2499 mpDDInfo
->aCursor
.Show();
2500 mpDDInfo
->bVisCursor
= true;
2504 // -----------------------------------------------------------------------
2506 void Edit::ImplHideDDCursor()
2508 if ( mpDDInfo
&& mpDDInfo
->bVisCursor
)
2510 mpDDInfo
->aCursor
.Hide();
2511 mpDDInfo
->bVisCursor
= false;
2515 // -----------------------------------------------------------------------
2521 ((Edit
*)GetParent())->Modify();
2525 if ( mpUpdateDataTimer
)
2526 mpUpdateDataTimer
->Start();
2528 if ( ImplCallEventListenersAndHandler( VCLEVENT_EDIT_MODIFY
, maModifyHdl
, this ) )
2529 // have been destroyed while calling into the handlers
2532 // #i13677# notify edit listeners about caret position change
2533 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2535 // FIXME: this is currently only on aqua
2536 // check for other platforms that need similar handling
2537 if( ImplGetSVData()->maNWFData
.mbNoFocusRects
&&
2538 IsNativeWidgetEnabled() &&
2539 IsNativeControlSupported( CTRL_EDITBOX
, PART_ENTIRE_CONTROL
) )
2541 ImplInvalidateOutermostBorder( this );
2546 // -----------------------------------------------------------------------
2548 void Edit::UpdateData()
2550 maUpdateDataHdl
.Call( this );
2553 // -----------------------------------------------------------------------
2555 IMPL_LINK_NOARG(Edit
, ImplUpdateDataHdl
)
2561 // -----------------------------------------------------------------------
2563 void Edit::EnableUpdateData( sal_uLong nTimeout
)
2566 DisableUpdateData();
2569 if ( !mpUpdateDataTimer
)
2571 mpUpdateDataTimer
= new Timer
;
2572 mpUpdateDataTimer
->SetTimeoutHdl( LINK( this, Edit
, ImplUpdateDataHdl
) );
2575 mpUpdateDataTimer
->SetTimeout( nTimeout
);
2579 // -----------------------------------------------------------------------
2581 void Edit::SetEchoChar( sal_Unicode c
)
2585 mpSubEdit
->SetEchoChar( c
);
2588 // -----------------------------------------------------------------------
2590 void Edit::SetReadOnly( sal_Bool bReadOnly
)
2592 if ( mbReadOnly
!= bReadOnly
)
2594 mbReadOnly
= bReadOnly
;
2596 mpSubEdit
->SetReadOnly( bReadOnly
);
2598 StateChanged( STATE_CHANGE_READONLY
);
2602 // -----------------------------------------------------------------------
2604 void Edit::SetAutocompleteHdl( const Link
& rHdl
)
2606 maAutocompleteHdl
= rHdl
;
2608 mpSubEdit
->SetAutocompleteHdl( rHdl
);
2611 // -----------------------------------------------------------------------
2613 void Edit::SetInsertMode( sal_Bool bInsert
)
2615 if ( bInsert
!= mbInsertMode
)
2617 mbInsertMode
= bInsert
;
2619 mpSubEdit
->SetInsertMode( bInsert
);
2625 // -----------------------------------------------------------------------
2627 sal_Bool
Edit::IsInsertMode() const
2630 return mpSubEdit
->IsInsertMode();
2632 return mbInsertMode
;
2635 // -----------------------------------------------------------------------
2637 void Edit::SetMaxTextLen( xub_StrLen nMaxLen
)
2639 mnMaxTextLen
= nMaxLen
? nMaxLen
: EDIT_NOLIMIT
;
2642 mpSubEdit
->SetMaxTextLen( mnMaxTextLen
);
2645 if ( maText
.getLength() > mnMaxTextLen
)
2646 ImplDelete( Selection( mnMaxTextLen
, maText
.getLength() ), EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2650 // -----------------------------------------------------------------------
2652 void Edit::SetSelection( const Selection
& rSelection
)
2654 // If the selection was changed from outside, e.g. by MouseButtonDown, don't call Tracking()
2655 // directly afterwards which would change the selection again
2658 else if ( mpSubEdit
&& mpSubEdit
->IsTracking() )
2659 mpSubEdit
->EndTracking();
2661 ImplSetSelection( rSelection
);
2664 // -----------------------------------------------------------------------
2666 void Edit::ImplSetSelection( const Selection
& rSelection
, sal_Bool bPaint
)
2669 mpSubEdit
->ImplSetSelection( rSelection
);
2672 if ( rSelection
!= maSelection
)
2674 Selection
aOld( maSelection
);
2675 Selection
aNew( rSelection
);
2677 if ( aNew
.Min() > maText
.getLength() )
2678 aNew
.Min() = maText
.getLength();
2679 if ( aNew
.Max() > maText
.getLength() )
2680 aNew
.Max() = maText
.getLength();
2681 if ( aNew
.Min() < 0 )
2683 if ( aNew
.Max() < 0 )
2686 if ( aNew
!= maSelection
)
2688 ImplClearLayoutData();
2691 if ( bPaint
&& ( aOld
.Len() || aNew
.Len() || IsPaintTransparent() ) )
2692 ImplInvalidateOrRepaint( 0, maText
.getLength() );
2695 ((Edit
*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2697 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED
);
2698 // #103511# notify combobox listeners of deselection
2699 if( !maSelection
&& GetParent() && GetParent()->GetType() == WINDOW_COMBOBOX
)
2700 ((Edit
*)GetParent())->ImplCallEventListeners( VCLEVENT_COMBOBOX_DESELECT
);
2706 // -----------------------------------------------------------------------
2708 const Selection
& Edit::GetSelection() const
2711 return mpSubEdit
->GetSelection();
2716 // -----------------------------------------------------------------------
2718 void Edit::ReplaceSelected( const OUString
& rStr
)
2721 mpSubEdit
->ReplaceSelected( rStr
);
2723 ImplInsertText( rStr
);
2726 // -----------------------------------------------------------------------
2728 void Edit::DeleteSelected()
2731 mpSubEdit
->DeleteSelected();
2734 if ( maSelection
.Len() )
2735 ImplDelete( maSelection
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2739 // -----------------------------------------------------------------------
2741 OUString
Edit::GetSelected() const
2744 return mpSubEdit
->GetSelected();
2747 Selection
aSelection( maSelection
);
2748 aSelection
.Justify();
2749 return OUString( maText
.getStr() + aSelection
.Min(), aSelection
.Len() );
2753 // -----------------------------------------------------------------------
2757 if ( !(GetStyle() & WB_PASSWORD
) )
2760 ReplaceSelected( ImplGetSVEmptyStr() );
2764 // -----------------------------------------------------------------------
2768 if ( !(GetStyle() & WB_PASSWORD
) )
2770 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aClipboard(GetClipboard());
2771 ImplCopy( aClipboard
);
2775 // -----------------------------------------------------------------------
2779 ::com::sun::star::uno::Reference
<com::sun::star::datatransfer::clipboard::XClipboard
> aClipboard(GetClipboard());
2780 ImplPaste( aClipboard
);
2783 // -----------------------------------------------------------------------
2791 OUString
aText( maText
.toString() );
2792 ImplDelete( Selection( 0, aText
.getLength() ), EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
2793 ImplInsertText( maUndoText
);
2794 ImplSetSelection( Selection( 0, maUndoText
.getLength() ) );
2799 // -----------------------------------------------------------------------
2801 void Edit::SetText( const OUString
& rStr
)
2804 mpSubEdit
->SetText( rStr
); // not directly ImplSetText if SetText overloaded
2807 Selection
aNewSel( 0, 0 ); // prevent scrolling
2808 ImplSetText( rStr
, &aNewSel
);
2812 // -----------------------------------------------------------------------
2814 void Edit::SetText( const OUString
& rStr
, const Selection
& rSelection
)
2817 mpSubEdit
->SetText( rStr
, rSelection
);
2819 ImplSetText( rStr
, &rSelection
);
2822 // -----------------------------------------------------------------------
2824 OUString
Edit::GetText() const
2827 return mpSubEdit
->GetText();
2829 return maText
.toString();
2832 // -----------------------------------------------------------------------
2834 void Edit::SetPlaceholderText( const OUString
& rStr
)
2837 mpSubEdit
->SetPlaceholderText( rStr
);
2838 else if ( maPlaceholderText
!= rStr
)
2840 maPlaceholderText
= rStr
;
2841 if ( GetText().isEmpty() )
2846 // -----------------------------------------------------------------------
2848 OUString
Edit::GetPlaceholderText() const
2851 return mpSubEdit
->GetPlaceholderText();
2853 return maPlaceholderText
;
2856 // -----------------------------------------------------------------------
2858 void Edit::SetModifyFlag()
2861 mpSubEdit
->mbModified
= sal_True
;
2863 mbModified
= sal_True
;
2866 // -----------------------------------------------------------------------
2868 void Edit::ClearModifyFlag()
2871 mpSubEdit
->mbModified
= sal_False
;
2873 mbModified
= sal_False
;
2876 // -----------------------------------------------------------------------
2878 void Edit::SetSubEdit( Edit
* pEdit
)
2883 SetPointer( POINTER_ARROW
); // Nur das SubEdit hat den BEAM...
2884 mpSubEdit
->mbIsSubEdit
= sal_True
;
2886 mpSubEdit
->SetReadOnly( mbReadOnly
);
2890 Size
Edit::CalcMinimumSizeForText(const OUString
&rString
) const
2892 int eCtrlType
= ImplGetNativeControlType();
2895 if (mnWidthInChars
!= -1)
2897 //CalcSize calls CalcWindowSize, but we will call that also in this
2898 //function, so undo the first one with CalcOutputSize
2899 aSize
= CalcOutputSize(CalcSize(mnWidthInChars
));
2904 if (mnMaxWidthChars
!= -1 && mnMaxWidthChars
< rString
.getLength())
2905 aString
= rString
.copy(0, mnMaxWidthChars
);
2909 aSize
.Height() = GetTextHeight();
2910 aSize
.Width() = GetTextWidth(aString
);
2911 aSize
.Width() += ImplGetExtraOffset() * 2;
2913 // do not create edit fields in which one cannot enter anything
2914 // a default minimum width should exist for at least 3 characters
2916 //CalcSize calls CalcWindowSize, but we will call that also in this
2917 //function, so undo the first one with CalcOutputSize
2918 Size
aMinSize(CalcOutputSize(CalcSize(3)));
2919 if (aSize
.Width() < aMinSize
.Width())
2920 aSize
.Width() = aMinSize
.Width();
2923 if (eCtrlType
!= CTRL_EDITBOX_NOBORDER
)
2925 // add some space between text entry and border
2926 aSize
.Height() += 4;
2929 aSize
= CalcWindowSize( aSize
);
2931 // ask NWF what if it has an opinion, too
2932 ImplControlValue aControlValue
;
2933 Rectangle
aRect( Point( 0, 0 ), aSize
);
2934 Rectangle aContent
, aBound
;
2935 if( const_cast<Edit
*>(this)->GetNativeControlRegion(
2936 eCtrlType
, PART_ENTIRE_CONTROL
,
2937 aRect
, 0, aControlValue
, OUString(), aBound
, aContent
) )
2939 if( aBound
.GetHeight() > aSize
.Height() )
2940 aSize
.Height() = aBound
.GetHeight();
2945 Size
Edit::CalcMinimumSize() const
2947 return CalcMinimumSizeForText(GetText());
2950 Size
Edit::GetMinimumEditSize()
2952 Window
* pDefWin
= ImplGetDefaultWindow();
2953 Edit
aEdit( pDefWin
, WB_BORDER
);
2954 Size
aSize( aEdit
.CalcMinimumSize() );
2958 // -----------------------------------------------------------------------
2960 Size
Edit::GetOptimalSize() const
2962 return CalcMinimumSize();
2965 // -----------------------------------------------------------------------
2967 Size
Edit::CalcSize( xub_StrLen nChars
) const
2969 // width for N characters, independent from content.
2970 // works only correct for fixed fonts, average otherwise
2971 Size
aSz( GetTextWidth( OUString('x') ), GetTextHeight() );
2972 aSz
.Width() *= nChars
;
2973 aSz
.Width() += ImplGetExtraOffset() * 2;
2974 aSz
= CalcWindowSize( aSz
);
2978 // -----------------------------------------------------------------------
2980 xub_StrLen
Edit::GetMaxVisChars() const
2982 const Window
* pW
= mpSubEdit
? mpSubEdit
: this;
2983 long nOutWidth
= pW
->GetOutputSizePixel().Width();
2984 long nCharWidth
= GetTextWidth( OUString('x') );
2985 return nCharWidth
? (xub_StrLen
)(nOutWidth
/nCharWidth
) : 0;
2988 // -----------------------------------------------------------------------
2990 xub_StrLen
Edit::GetCharPos( const Point
& rWindowPos
) const
2992 return ImplGetCharPos( rWindowPos
);
2995 // -----------------------------------------------------------------------
2997 void Edit::SetGetSpecialCharsFunction( FncGetSpecialChars fn
)
2999 pImplFncGetSpecialChars
= fn
;
3002 // -----------------------------------------------------------------------
3004 FncGetSpecialChars
Edit::GetGetSpecialCharsFunction()
3006 return pImplFncGetSpecialChars
;
3009 // -----------------------------------------------------------------------
3011 PopupMenu
* Edit::CreatePopupMenu()
3013 ResMgr
* pResMgr
= ImplGetResMgr();
3015 return new PopupMenu();
3017 PopupMenu
* pPopup
= new PopupMenu( ResId( SV_RESID_MENU_EDIT
, *pResMgr
) );
3018 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
3019 if ( rStyleSettings
.GetHideDisabledMenuItems() )
3020 pPopup
->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES
);
3022 pPopup
->SetMenuFlags ( MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES
);
3023 if ( rStyleSettings
.GetAcceleratorsInContextMenus() )
3025 pPopup
->SetAccelKey( SV_MENU_EDIT_UNDO
, KeyCode( KEYFUNC_UNDO
) );
3026 pPopup
->SetAccelKey( SV_MENU_EDIT_CUT
, KeyCode( KEYFUNC_CUT
) );
3027 pPopup
->SetAccelKey( SV_MENU_EDIT_COPY
, KeyCode( KEYFUNC_COPY
) );
3028 pPopup
->SetAccelKey( SV_MENU_EDIT_PASTE
, KeyCode( KEYFUNC_PASTE
) );
3029 pPopup
->SetAccelKey( SV_MENU_EDIT_DELETE
, KeyCode( KEYFUNC_DELETE
) );
3030 pPopup
->SetAccelKey( SV_MENU_EDIT_SELECTALL
, KeyCode( KEY_A
, sal_False
, sal_True
, sal_False
, sal_False
) );
3031 pPopup
->SetAccelKey( SV_MENU_EDIT_INSERTSYMBOL
, KeyCode( KEY_S
, sal_True
, sal_True
, sal_False
, sal_False
) );
3036 // -----------------------------------------------------------------------
3038 void Edit::DeletePopupMenu( PopupMenu
* pMenu
)
3043 // ::com::sun::star::datatransfer::dnd::XDragGestureListener
3044 void Edit::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent
& rDGE
) throw (::com::sun::star::uno::RuntimeException
)
3046 SolarMutexGuard aVclGuard
;
3048 if ( !IsTracking() && maSelection
.Len() &&
3049 !(GetStyle() & WB_PASSWORD
) && (!mpDDInfo
|| mpDDInfo
->bStarterOfDD
== false) ) // Kein Mehrfach D&D
3051 Selection
aSel( maSelection
);
3054 // Nur wenn Maus in der Selektion...
3055 Point
aMousePos( rDGE
.DragOriginX
, rDGE
.DragOriginY
);
3056 xub_StrLen nChar
= ImplGetCharPos( aMousePos
);
3057 if ( (nChar
>= aSel
.Min()) && (nChar
< aSel
.Max()) )
3060 mpDDInfo
= new DDInfo
;
3062 mpDDInfo
->bStarterOfDD
= true;
3063 mpDDInfo
->aDndStartSel
= aSel
;
3067 EndTracking(); // Vor D&D Tracking ausschalten
3069 ::vcl::unohelper::TextDataObject
* pDataObj
= new ::vcl::unohelper::TextDataObject( GetSelected() );
3070 sal_Int8 nActions
= datatransfer::dnd::DNDConstants::ACTION_COPY
;
3071 if ( !IsReadOnly() )
3072 nActions
|= datatransfer::dnd::DNDConstants::ACTION_MOVE
;
3073 rDGE
.DragSource
->startDrag( rDGE
, nActions
, 0 /*cursor*/, 0 /*image*/, pDataObj
, mxDnDListener
);
3075 GetCursor()->Hide();
3081 // ::com::sun::star::datatransfer::dnd::XDragSourceListener
3082 void Edit::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent
& rDSDE
) throw (::com::sun::star::uno::RuntimeException
)
3084 SolarMutexGuard aVclGuard
;
3086 if ( rDSDE
.DropSuccess
&& ( rDSDE
.DropAction
& datatransfer::dnd::DNDConstants::ACTION_MOVE
) )
3088 Selection
aSel( mpDDInfo
->aDndStartSel
);
3089 if ( mpDDInfo
->bDroppedInMe
)
3091 if ( aSel
.Max() > mpDDInfo
->nDropPos
)
3093 long nLen
= aSel
.Len();
3098 ImplDelete( aSel
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
3107 // ::com::sun::star::datatransfer::dnd::XDropTargetListener
3108 void Edit::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
3110 SolarMutexGuard aVclGuard
;
3112 sal_Bool bChanges
= sal_False
;
3113 if ( !mbReadOnly
&& mpDDInfo
)
3117 Selection
aSel( maSelection
);
3120 if ( aSel
.Len() && !mpDDInfo
->bStarterOfDD
)
3121 ImplDelete( aSel
, EDIT_DEL_RIGHT
, EDIT_DELMODE_SIMPLE
);
3123 mpDDInfo
->bDroppedInMe
= true;
3125 aSel
.Min() = mpDDInfo
->nDropPos
;
3126 aSel
.Max() = mpDDInfo
->nDropPos
;
3127 ImplSetSelection( aSel
);
3129 uno::Reference
< datatransfer::XTransferable
> xDataObj
= rDTDE
.Transferable
;
3130 if ( xDataObj
.is() )
3132 datatransfer::DataFlavor aFlavor
;
3133 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
3134 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
3136 uno::Any aData
= xDataObj
->getTransferData( aFlavor
);
3139 ImplInsertText( aText
);
3140 bChanges
= sal_True
;
3145 if ( !mpDDInfo
->bStarterOfDD
)
3152 rDTDE
.Context
->dropComplete( bChanges
);
3155 void Edit::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
3159 mpDDInfo
= new DDInfo
;
3161 // search for string data type
3162 const Sequence
< com::sun::star::datatransfer::DataFlavor
>& rFlavors( rDTDE
.SupportedDataFlavors
);
3163 sal_Int32 nEle
= rFlavors
.getLength();
3164 mpDDInfo
->bIsStringSupported
= false;
3165 for( sal_Int32 i
= 0; i
< nEle
; i
++ )
3167 sal_Int32 nIndex
= 0;
3168 OUString aMimetype
= rFlavors
[i
].MimeType
.getToken( 0, ';', nIndex
);
3169 if ( aMimetype
== "text/plain" )
3171 mpDDInfo
->bIsStringSupported
= true;
3177 void Edit::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent
& ) throw (::com::sun::star::uno::RuntimeException
)
3179 SolarMutexGuard aVclGuard
;
3184 void Edit::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent
& rDTDE
) throw (::com::sun::star::uno::RuntimeException
)
3186 SolarMutexGuard aVclGuard
;
3188 Point
aMousePos( rDTDE
.LocationX
, rDTDE
.LocationY
);
3190 xub_StrLen nPrevDropPos
= mpDDInfo
->nDropPos
;
3191 mpDDInfo
->nDropPos
= ImplGetCharPos( aMousePos
);
3194 Size aOutSize = GetOutputSizePixel();
3195 if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) )
3198 // No, I will not receive events in this case....
3202 Selection
aSel( maSelection
);
3205 // Don't accept drop in selection or read-only field...
3206 if ( IsReadOnly() || aSel
.IsInside( mpDDInfo
->nDropPos
) || ! mpDDInfo
->bIsStringSupported
)
3209 rDTDE
.Context
->rejectDrag();
3213 // Alten Cursor wegzeichnen...
3214 if ( !mpDDInfo
->bVisCursor
|| ( nPrevDropPos
!= mpDDInfo
->nDropPos
) )
3219 rDTDE
.Context
->acceptDrag( rDTDE
.DropAction
);
3223 OUString
Edit::GetSurroundingText() const
3226 return mpSubEdit
->GetSurroundingText();
3227 return maText
.toString();
3230 Selection
Edit::GetSurroundingTextSelection() const
3232 return GetSelection();
3235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */