xref: /trunk/main/vcl/source/control/edit.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <tools/rc.h>
32 #include <vcl/decoview.hxx>
33 #include <vcl/event.hxx>
34 #include <vcl/cursor.hxx>
35 #include <vcl/virdev.hxx>
36 #include <vcl/menu.hxx>
37 #include <vcl/cmdevt.h>
38 #include <vcl/edit.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/msgbox.hxx>
41 
42 #include <window.h>
43 #include <svdata.hxx>
44 #include <svids.hrc>
45 #include <subedit.hxx>
46 #include <controldata.hxx>
47 
48 #include <vos/mutex.hxx>
49 
50 
51 #include <com/sun/star/i18n/XBreakIterator.hpp>
52 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
53 #include <com/sun/star/i18n/WordType.hpp>
54 #include <cppuhelper/weak.hxx>
55 #include <com/sun/star/datatransfer/XTransferable.hpp>
56 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
57 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
58 
59 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANS_HPP_
60 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
61 #endif
62 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
63 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
64 
65 #ifndef _COM_SUN_STAR_I18N_XEXTENDEDINPUTSEQUENCECHECKER_HDL_
66 #include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
67 #endif
68 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
69 #include <com/sun/star/i18n/ScriptType.hpp>
70 #include <com/sun/star/container/XNameAccess.hpp>
71 
72 #include <com/sun/star/uno/Any.hxx>
73 
74 #include <comphelper/processfactory.hxx>
75 #include <comphelper/configurationhelper.hxx>
76 
77 #include <sot/exchange.hxx>
78 #include <sot/formats.hxx>
79 #include <rtl/memory.h>
80 
81 #include <vcl/unohelp.hxx>
82 #include <vcl/unohelp2.hxx>
83 
84 
85 
86 
87 using namespace ::com::sun::star;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::lang;
90 using namespace ::rtl;
91 
92 // - Redo
93 // - Bei Tracking-Cancel DefaultSelection wieder herstellen
94 
95 // =======================================================================
96 
97 static FncGetSpecialChars pImplFncGetSpecialChars = NULL;
98 
99 // =======================================================================
100 
101 #define EDIT_ALIGN_LEFT             1
102 #define EDIT_ALIGN_CENTER           2
103 #define EDIT_ALIGN_RIGHT            3
104 
105 #define EDIT_DEL_LEFT               1
106 #define EDIT_DEL_RIGHT              2
107 
108 #define EDIT_DELMODE_SIMPLE         11
109 #define EDIT_DELMODE_RESTOFWORD     12
110 #define EDIT_DELMODE_RESTOFCONTENT  13
111 
112 // =======================================================================
113 
114 struct DDInfo
115 {
116     Cursor          aCursor;
117     Selection       aDndStartSel;
118     xub_StrLen      nDropPos;
119     sal_Bool            bStarterOfDD;
120     sal_Bool            bDroppedInMe;
121     sal_Bool            bVisCursor;
122     sal_Bool            bIsStringSupported;
123 
124     DDInfo()
125     {
126         aCursor.SetStyle( CURSOR_SHADOW );
127         nDropPos = 0;
128         bStarterOfDD = sal_False;
129         bDroppedInMe = sal_False;
130         bVisCursor = sal_False;
131         bIsStringSupported = sal_False;
132     }
133 };
134 
135 // =======================================================================
136 
137 struct Impl_IMEInfos
138 {
139     String      aOldTextAfterStartPos;
140     sal_uInt16*     pAttribs;
141     xub_StrLen  nPos;
142     xub_StrLen  nLen;
143     sal_Bool        bCursor;
144     sal_Bool        bWasCursorOverwrite;
145 
146                 Impl_IMEInfos( xub_StrLen nPos, const String& rOldTextAfterStartPos );
147                 ~Impl_IMEInfos();
148 
149     void        CopyAttribs( const xub_StrLen* pA, xub_StrLen nL );
150     void        DestroyAttribs();
151 };
152 
153 // -----------------------------------------------------------------------
154 
155 Impl_IMEInfos::Impl_IMEInfos( xub_StrLen nP, const String& rOldTextAfterStartPos )
156  : aOldTextAfterStartPos( rOldTextAfterStartPos )
157 {
158     nPos = nP;
159     nLen = 0;
160     bCursor = sal_True;
161     pAttribs = NULL;
162     bWasCursorOverwrite = sal_False;
163 }
164 
165 // -----------------------------------------------------------------------
166 
167 Impl_IMEInfos::~Impl_IMEInfos()
168 {
169     delete[] pAttribs;
170 }
171 
172 // -----------------------------------------------------------------------
173 
174 void Impl_IMEInfos::CopyAttribs( const xub_StrLen* pA, xub_StrLen nL )
175 {
176     nLen = nL;
177     delete[] pAttribs;
178     pAttribs = new sal_uInt16[ nL ];
179     rtl_copyMemory( pAttribs, pA, nL*sizeof(sal_uInt16) );
180 }
181 
182 // -----------------------------------------------------------------------
183 
184 void Impl_IMEInfos::DestroyAttribs()
185 {
186     delete[] pAttribs;
187     pAttribs = NULL;
188     nLen = 0;
189 }
190 
191 // =======================================================================
192 
193 Edit::Edit( WindowType nType ) :
194     Control( nType )
195 {
196     ImplInitEditData();
197 }
198 
199 // -----------------------------------------------------------------------
200 
201 Edit::Edit( Window* pParent, WinBits nStyle ) :
202     Control( WINDOW_EDIT )
203 {
204     ImplInitEditData();
205     ImplInit( pParent, nStyle );
206 }
207 
208 // -----------------------------------------------------------------------
209 
210 Edit::Edit( Window* pParent, const ResId& rResId ) :
211     Control( WINDOW_EDIT )
212 {
213     ImplInitEditData();
214     rResId.SetRT( RSC_EDIT );
215     WinBits nStyle = ImplInitRes( rResId );
216     ImplInit( pParent, nStyle );
217     ImplLoadRes( rResId );
218 
219     // Derived MultiLineEdit takes care to call Show only after MultiLineEdit
220     // ctor has already started:
221     if ( !(nStyle & WB_HIDE) && rResId.GetRT() != RSC_MULTILINEEDIT )
222         Show();
223 }
224 
225 // -----------------------------------------------------------------------
226 
227 Edit::Edit( Window* pParent, const ResId& rResId, bool bDisableAccessibleLabeledByRelation ) :
228     Control( WINDOW_EDIT )
229 {
230     ImplInitEditData();
231     rResId.SetRT( RSC_EDIT );
232     WinBits nStyle = ImplInitRes( rResId );
233     ImplInit( pParent, nStyle );
234     ImplLoadRes( rResId );
235     if ( bDisableAccessibleLabeledByRelation )
236         ImplGetWindowImpl()->mbDisableAccessibleLabeledByRelation = sal_True;
237 
238     // Derived MultiLineEdit takes care to call Show only after MultiLineEdit
239     // ctor has already started:
240     if ( !(nStyle & WB_HIDE) && rResId.GetRT() != RSC_MULTILINEEDIT )
241         Show();
242 }
243 
244 // -----------------------------------------------------------------------
245 
246 Edit::~Edit()
247 {
248     delete mpDDInfo;
249     Cursor* pCursor = GetCursor();
250     if ( pCursor )
251     {
252         SetCursor( NULL );
253         delete pCursor;
254     }
255 
256     delete mpIMEInfos;
257 
258     if ( mpUpdateDataTimer )
259         delete mpUpdateDataTimer;
260 
261     if ( mxDnDListener.is() )
262     {
263         if ( GetDragGestureRecognizer().is() )
264         {
265             uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
266             GetDragGestureRecognizer()->removeDragGestureListener( xDGL );
267         }
268         if ( GetDropTarget().is() )
269         {
270             uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( mxDnDListener, uno::UNO_QUERY );
271             GetDropTarget()->removeDropTargetListener( xDTL );
272         }
273 
274         uno::Reference< lang::XEventListener> xEL( mxDnDListener, uno::UNO_QUERY );
275         xEL->disposing( lang::EventObject() );  // #95154# #96585# Empty Source means it's the Client
276     }
277 }
278 
279 // -----------------------------------------------------------------------
280 
281 void Edit::ImplInitEditData()
282 {
283     mpSubEdit               = NULL;
284     mpUpdateDataTimer       = NULL;
285     mnXOffset               = 0;
286     mnAlign                 = EDIT_ALIGN_LEFT;
287     mnMaxTextLen            = EDIT_NOLIMIT;
288     meAutocompleteAction    = AUTOCOMPLETE_KEYINPUT;
289     mbModified              = sal_False;
290     mbInternModified        = sal_False;
291     mbReadOnly              = sal_False;
292     mbInsertMode            = sal_True;
293     mbClickedInSelection    = sal_False;
294     mbActivePopup           = sal_False;
295     mbIsSubEdit             = sal_False;
296     mbInMBDown              = sal_False;
297     mpDDInfo                = NULL;
298     mpIMEInfos              = NULL;
299     mcEchoChar              = 0;
300 
301     // --- RTL --- no default mirroring for Edit controls
302     // note: controls that use a subedit will revert this (SpinField, ComboBox)
303     EnableRTL( sal_False );
304 
305     vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this );
306     mxDnDListener = pDnDWrapper;
307 }
308 
309 // -----------------------------------------------------------------------
310 
311 bool Edit::ImplUseNativeBorder( WinBits nStyle )
312 {
313     bool bRet =
314         IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE)
315                                  && ((nStyle&WB_BORDER) && !(nStyle&WB_NOBORDER));
316     if( ! bRet && mbIsSubEdit )
317     {
318         Window* pWindow = GetParent();
319         nStyle = pWindow->GetStyle();
320         bRet = pWindow->IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE)
321                && ((nStyle&WB_BORDER) && !(nStyle&WB_NOBORDER));
322     }
323     return bRet;
324 }
325 
326 void Edit::ImplInit( Window* pParent, WinBits nStyle )
327 {
328     nStyle = ImplInitStyle( nStyle );
329     if ( !(nStyle & (WB_CENTER | WB_RIGHT)) )
330         nStyle |= WB_LEFT;
331 
332     Control::ImplInit( pParent, nStyle, NULL );
333 
334     mbReadOnly = (nStyle & WB_READONLY) != 0;
335 
336     mnAlign = EDIT_ALIGN_LEFT;
337 
338     // --- RTL --- hack: right align until keyinput and cursor travelling works
339     if( IsRTLEnabled() )
340         mnAlign = EDIT_ALIGN_RIGHT;
341 
342     if ( nStyle & WB_RIGHT )
343         mnAlign = EDIT_ALIGN_RIGHT;
344     else if ( nStyle & WB_CENTER )
345         mnAlign = EDIT_ALIGN_CENTER;
346 
347     SetCursor( new Cursor );
348 
349     SetPointer( Pointer( POINTER_TEXT ) );
350     ImplInitSettings( sal_True, sal_True, sal_True );
351 
352     uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
353     uno::Reference< datatransfer::dnd::XDragGestureRecognizer > xDGR = GetDragGestureRecognizer();
354     if ( xDGR.is() )
355     {
356         xDGR->addDragGestureListener( xDGL );
357         uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( mxDnDListener, uno::UNO_QUERY );
358         GetDropTarget()->addDropTargetListener( xDTL );
359         GetDropTarget()->setActive( sal_True );
360         GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
361     }
362 }
363 
364 // -----------------------------------------------------------------------
365 
366 WinBits Edit::ImplInitStyle( WinBits nStyle )
367 {
368     if ( !(nStyle & WB_NOTABSTOP) )
369         nStyle |= WB_TABSTOP;
370     if ( !(nStyle & WB_NOGROUP) )
371         nStyle |= WB_GROUP;
372 
373     return nStyle;
374 }
375 
376 // -----------------------------------------------------------------------
377 
378 sal_Bool Edit::IsCharInput( const KeyEvent& rKeyEvent )
379 {
380     // In the future we must use new Unicode functions for this
381     xub_Unicode cCharCode = rKeyEvent.GetCharCode();
382     return ((cCharCode >= 32) && (cCharCode != 127) &&
383             !rKeyEvent.GetKeyCode().IsMod3() &&
384             !rKeyEvent.GetKeyCode().IsMod2() &&
385             !rKeyEvent.GetKeyCode().IsMod1() );
386 }
387 
388 // -----------------------------------------------------------------------
389 
390 void Edit::ImplModified()
391 {
392     mbModified = sal_True;
393     Modify();
394 }
395 
396 // -----------------------------------------------------------------------
397 
398 void Edit::ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground )
399 {
400     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
401 
402     if ( bFont )
403     {
404         Font aFont = rStyleSettings.GetFieldFont();
405         if ( IsControlFont() )
406             aFont.Merge( GetControlFont() );
407         SetZoomedPointFont( aFont );
408         ImplClearLayoutData();
409     }
410 
411     if ( bFont || bForeground )
412     {
413         Color aTextColor = rStyleSettings.GetFieldTextColor();
414         if ( IsControlForeground() )
415             aTextColor = GetControlForeground();
416         SetTextColor( aTextColor );
417     }
418 
419     if ( bBackground )
420     {
421         if ( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() )
422         {
423             // Transparent background
424             SetBackground();
425             SetFillColor();
426         }
427         else if ( IsControlBackground() )
428         {
429             SetBackground( GetControlBackground() );
430             SetFillColor( GetControlBackground() );
431         }
432         else
433         {
434             SetBackground( rStyleSettings.GetFieldColor() );
435             SetFillColor( rStyleSettings.GetFieldColor() );
436         }
437     }
438 }
439 
440 // -----------------------------------------------------------------------
441 
442 long Edit::ImplGetExtraOffset() const
443 {
444     // MT 09/2002: nExtraOffsetX should become a member, instead of checking every time,
445     // but I need an incompatible update for this...
446     // #94095# Use extra offset only when edit has a border
447     long nExtraOffset = 0;
448     if( ( GetStyle() & WB_BORDER ) || ( mbIsSubEdit && ( GetParent()->GetStyle() & WB_BORDER ) ) )
449         nExtraOffset = 2;
450 
451     return nExtraOffset;
452 }
453 
454 
455 // -----------------------------------------------------------------------
456 
457 XubString Edit::ImplGetText() const
458 {
459     if ( mcEchoChar || (GetStyle() & WB_PASSWORD) )
460     {
461         XubString   aText;
462         xub_Unicode cEchoChar;
463         if ( mcEchoChar )
464             cEchoChar = mcEchoChar;
465         else
466             cEchoChar = '*';
467         aText.Fill( maText.Len(), cEchoChar );
468         return aText;
469     }
470     else
471         return maText;
472 }
473 
474 // -----------------------------------------------------------------------
475 
476 void Edit::ImplInvalidateOrRepaint( xub_StrLen nStart, xub_StrLen nEnd )
477 {
478     if( IsPaintTransparent() )
479     {
480         Invalidate();
481         // FIXME: this is currently only on aqua
482         if( ImplGetSVData()->maNWFData.mbNoFocusRects )
483             Update();
484     }
485     else
486         ImplRepaint( nStart, nEnd );
487 }
488 
489 // -----------------------------------------------------------------------
490 
491 long Edit::ImplGetTextYPosition() const
492 {
493     if ( GetStyle() & WB_TOP )
494         return ImplGetExtraOffset();
495     else if ( GetStyle() & WB_BOTTOM )
496         return GetOutputSizePixel().Height() - GetTextHeight() - ImplGetExtraOffset();
497     return ( GetOutputSizePixel().Height() - GetTextHeight() ) / 2;
498 }
499 
500 // -----------------------------------------------------------------------
501 
502 void Edit::ImplRepaint( xub_StrLen nStart, xub_StrLen nEnd, bool bLayout )
503 {
504     if ( !IsReallyVisible() )
505         return;
506 
507     XubString aText = ImplGetText();
508     nStart = 0;
509     nEnd = aText.Len();
510 
511     sal_Int32   nDXBuffer[256];
512     sal_Int32*  pDXBuffer = NULL;
513     sal_Int32*  pDX = nDXBuffer;
514 
515     if( aText.Len() )
516     {
517         if( 2*aText.Len() > xub_StrLen(sizeof(nDXBuffer)/sizeof(nDXBuffer[0])) )
518         {
519             pDXBuffer = new sal_Int32[2*(aText.Len()+1)];
520             pDX = pDXBuffer;
521         }
522 
523         GetCaretPositions( aText, pDX, nStart, nEnd );
524     }
525 
526     long    nTH = GetTextHeight();
527     Point   aPos( mnXOffset, ImplGetTextYPosition() );
528 
529     if( bLayout )
530     {
531         long nPos = nStart ? pDX[2*nStart] : 0;
532         aPos.X() = nPos + mnXOffset + ImplGetExtraOffset();
533 
534         MetricVector* pVector = &mpControlData->mpLayoutData->m_aUnicodeBoundRects;
535         String* pDisplayText = &mpControlData->mpLayoutData->m_aDisplayText;
536 
537         DrawText( aPos, aText, nStart, nEnd - nStart, pVector, pDisplayText );
538 
539         if( pDXBuffer )
540             delete [] pDXBuffer;
541         return;
542     }
543 
544     Cursor* pCursor = GetCursor();
545     sal_Bool bVisCursor = pCursor ? pCursor->IsVisible() : sal_False;
546     if ( pCursor )
547         pCursor->Hide();
548 
549     ImplClearBackground( 0, GetOutputSizePixel().Width() );
550 
551     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
552     if ( IsEnabled() )
553         ImplInitSettings( sal_False, sal_True, sal_False );
554     else
555         SetTextColor( rStyleSettings.GetDisableColor() );
556 
557     // Set background color of the normal text
558     if( (GetStyle() & WB_FORCECTRLBACKGROUND) != 0 && IsControlBackground() )
559     {
560         // check if we need to set ControlBackground even in NWF case
561         Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
562         SetLineColor();
563         SetFillColor( GetControlBackground() );
564         DrawRect( Rectangle( aPos, Size( GetOutputSizePixel().Width() - 2*mnXOffset, nTH ) ) );
565         Pop();
566 
567         SetTextFillColor( GetControlBackground() );
568     }
569     else if( IsPaintTransparent() || ImplUseNativeBorder( GetStyle() ) )
570         SetTextFillColor();
571     else
572         SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
573 
574     sal_Bool bDrawSelection = maSelection.Len() && ( HasFocus() || ( GetStyle() & WB_NOHIDESELECTION ) || mbActivePopup );
575 
576     long nPos = nStart ? pDX[2*nStart] : 0;
577     aPos.X() = nPos + mnXOffset + ImplGetExtraOffset();
578     if ( !bDrawSelection && !mpIMEInfos )
579     {
580         DrawText( aPos, aText, nStart, nEnd - nStart );
581     }
582     else
583     {
584         // save graphics state
585         Push();
586         // first calculate higlighted and non highlighted clip regions
587         Region aHiglightClipRegion;
588         Region aNormalClipRegion;
589         Selection aTmpSel( maSelection );
590         aTmpSel.Justify();
591         // selection is highlighted
592         int i;
593         for( i = 0; i < aText.Len(); i++ )
594         {
595             Rectangle aRect( aPos, Size( 10, nTH ) );
596             aRect.Left() = pDX[2*i] + mnXOffset + ImplGetExtraOffset();
597             aRect.Right() = pDX[2*i+1] + mnXOffset + ImplGetExtraOffset();
598             aRect.Justify();
599             bool bHighlight = false;
600             if( i >= aTmpSel.Min() && i < aTmpSel.Max() )
601                 bHighlight = true;
602 
603             if( mpIMEInfos && mpIMEInfos->pAttribs &&
604                 i >= mpIMEInfos->nPos && i < (mpIMEInfos->nPos+mpIMEInfos->nLen ) &&
605                 ( mpIMEInfos->pAttribs[i-mpIMEInfos->nPos] & EXTTEXTINPUT_ATTR_HIGHLIGHT) )
606                 bHighlight = true;
607 
608             if( bHighlight )
609                 aHiglightClipRegion.Union( aRect );
610             else
611                 aNormalClipRegion.Union( aRect );
612         }
613         // draw normal text
614         Color aNormalTextColor = GetTextColor();
615         SetClipRegion( aNormalClipRegion );
616 
617         if( IsPaintTransparent() )
618             SetTextFillColor();
619         else
620         {
621             // Set background color when part of the text is selected
622             if ( ImplUseNativeBorder( GetStyle() ) )
623             {
624                 if( (GetStyle() & WB_FORCECTRLBACKGROUND) != 0 && IsControlBackground() )
625                     SetTextFillColor( GetControlBackground() );
626                 else
627                     SetTextFillColor();
628             }
629             else
630                 SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
631         }
632         DrawText( aPos, aText, nStart, nEnd - nStart );
633 
634         // draw highlighted text
635         SetClipRegion( aHiglightClipRegion );
636         SetTextColor( rStyleSettings.GetHighlightTextColor() );
637         SetTextFillColor( rStyleSettings.GetHighlightColor() );
638         DrawText( aPos, aText, nStart, nEnd - nStart );
639 
640         // if IME info exists loop over portions and output different font attributes
641         if( mpIMEInfos && mpIMEInfos->pAttribs )
642         {
643             for( int n = 0; n < 2; n++ )
644             {
645                 Region aRegion;
646                 if( n == 0 )
647                 {
648                     SetTextColor( aNormalTextColor );
649                     if( IsPaintTransparent() )
650                         SetTextFillColor();
651                     else
652                         SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
653                     aRegion = aNormalClipRegion;
654                 }
655                 else
656                 {
657                     SetTextColor( rStyleSettings.GetHighlightTextColor() );
658                     SetTextFillColor( rStyleSettings.GetHighlightColor() );
659                     aRegion = aHiglightClipRegion;
660                 }
661 
662                 for( i = 0; i < mpIMEInfos->nLen; )
663                 {
664                     sal_uInt16 nAttr = mpIMEInfos->pAttribs[i];
665                     Region aClip;
666                     int nIndex = i;
667                     while( nIndex < mpIMEInfos->nLen && mpIMEInfos->pAttribs[nIndex] == nAttr)  // #112631# check nIndex before using it
668                     {
669                         Rectangle aRect( aPos, Size( 10, nTH ) );
670                         aRect.Left() = pDX[2*(nIndex+mpIMEInfos->nPos)] + mnXOffset + ImplGetExtraOffset();
671                         aRect.Right() = pDX[2*(nIndex+mpIMEInfos->nPos)+1] + mnXOffset + ImplGetExtraOffset();
672                         aRect.Justify();
673                         aClip.Union( aRect );
674                         nIndex++;
675                     }
676                     i = nIndex;
677                     if( aClip.Intersect( aRegion ) && nAttr )
678                     {
679                         Font aFont = GetFont();
680                         if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE )
681                             aFont.SetUnderline( UNDERLINE_SINGLE );
682                         else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE )
683                             aFont.SetUnderline( UNDERLINE_BOLD );
684                         else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE )
685                             aFont.SetUnderline( UNDERLINE_DOTTED );
686                         else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE )
687                             aFont.SetUnderline( UNDERLINE_DOTTED );
688                         else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE )
689                         {
690                             aFont.SetUnderline( UNDERLINE_WAVE );
691                             SetTextLineColor( Color( COL_LIGHTGRAY ) );
692                         }
693                         SetFont( aFont );
694 
695                         if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT )
696                             SetTextColor( Color( COL_RED ) );
697                         else if ( nAttr & EXTTEXTINPUT_ATTR_HALFTONETEXT )
698                             SetTextColor( Color( COL_LIGHTGRAY ) );
699 
700                         SetClipRegion( aClip );
701                         DrawText( aPos, aText, nStart, nEnd - nStart );
702                     }
703                 }
704             }
705         }
706 
707         // restore graphics state
708         Pop();
709     }
710 
711     if ( bVisCursor && ( !mpIMEInfos || mpIMEInfos->bCursor ) )
712         pCursor->Show();
713 
714     if( pDXBuffer )
715         delete [] pDXBuffer;
716 }
717 
718 // -----------------------------------------------------------------------
719 
720 void Edit::ImplDelete( const Selection& rSelection, sal_uInt8 nDirection, sal_uInt8 nMode )
721 {
722     XubString aText = ImplGetText();
723 
724     // loeschen moeglich?
725     if ( !rSelection.Len() &&
726          (((rSelection.Min() == 0) && (nDirection == EDIT_DEL_LEFT)) ||
727           ((rSelection.Max() == aText.Len()) && (nDirection == EDIT_DEL_RIGHT))) )
728         return;
729 
730     ImplClearLayoutData();
731 
732     Selection aSelection( rSelection );
733     aSelection.Justify();
734 
735     if ( !aSelection.Len() )
736     {
737         uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
738         if ( nDirection == EDIT_DEL_LEFT )
739         {
740             if ( nMode == EDIT_DELMODE_RESTOFWORD )
741             {
742                 i18n::Boundary aBoundary = xBI->getWordBoundary( maText, aSelection.Min(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
743                 if ( aBoundary.startPos == aSelection.Min() )
744                     aBoundary = xBI->previousWord( maText, aSelection.Min(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
745                 aSelection.Min() = aBoundary.startPos;
746             }
747             else if ( nMode == EDIT_DELMODE_RESTOFCONTENT )
748             {
749                 aSelection.Min() = 0;
750             }
751             else
752             {
753                 sal_Int32 nCount = 1;
754                 aSelection.Min() = xBI->previousCharacters( maText, aSelection.Min(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
755             }
756         }
757         else
758         {
759             if ( nMode == EDIT_DELMODE_RESTOFWORD )
760             {
761                 i18n::Boundary aBoundary = xBI->nextWord( maText, aSelection.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
762                 aSelection.Max() = aBoundary.startPos;
763             }
764             else if ( nMode == EDIT_DELMODE_RESTOFCONTENT )
765             {
766                 aSelection.Max() = aText.Len();
767             }
768             else
769             {
770                 sal_Int32 nCount = 1;
771                 aSelection.Max() = xBI->nextCharacters( maText, aSelection.Max(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );;
772             }
773         }
774     }
775 
776     maText.Erase( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() );
777     maSelection.Min() = aSelection.Min();
778     maSelection.Max() = aSelection.Min();
779     ImplAlignAndPaint();
780     mbInternModified = sal_True;
781 }
782 
783 // -----------------------------------------------------------------------
784 
785 String Edit::ImplGetValidString( const String& rString ) const
786 {
787     String aValidString( rString );
788     aValidString.EraseAllChars( _LF );
789     aValidString.EraseAllChars( _CR );
790     aValidString.SearchAndReplaceAll( '\t', ' ' );
791     return aValidString;
792 }
793 
794 // -----------------------------------------------------------------------
795 uno::Reference < i18n::XBreakIterator > Edit::ImplGetBreakIterator() const
796 {
797     //!! since we don't want to become incompatible in the next minor update
798     //!! where this code will get integrated into, xISC will be a local
799     //!! variable instead of a class member!
800     uno::Reference < i18n::XBreakIterator > xBI;
801 //    if ( !xBI.is() )
802     {
803         uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
804         uno::Reference < XInterface > xI = xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.BreakIterator" ) );
805         if ( xI.is() )
806         {
807             Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XBreakIterator >*)0) );
808             x >>= xBI;
809         }
810     }
811     return xBI;
812 }
813 // -----------------------------------------------------------------------
814 
815 uno::Reference < i18n::XExtendedInputSequenceChecker > Edit::ImplGetInputSequenceChecker() const
816 {
817     //!! since we don't want to become incompatible in the next minor update
818     //!! where this code will get integrated into, xISC will be a local
819     //!! variable instead of a class member!
820     uno::Reference < i18n::XExtendedInputSequenceChecker > xISC;
821 //    if ( !xISC.is() )
822     {
823         uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
824         uno::Reference < XInterface > xI = xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.InputSequenceChecker" ) );
825         if ( xI.is() )
826         {
827             Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XExtendedInputSequenceChecker >*)0) );
828             x >>= xISC;
829         }
830     }
831     return xISC;
832 }
833 
834 // -----------------------------------------------------------------------
835 
836 void Edit::ShowTruncationWarning( Window* pParent )
837 {
838     ResMgr* pResMgr = ImplGetResMgr();
839     if( pResMgr )
840     {
841         WarningBox aBox( pParent, ResId( SV_EDIT_WARNING_BOX, *pResMgr ) );
842         aBox.Execute();
843     }
844 }
845 
846 // -----------------------------------------------------------------------
847 
848 bool Edit::ImplTruncateToMaxLen( rtl::OUString& rStr, sal_uInt32 nSelectionLen ) const
849 {
850     bool bWasTruncated = false;
851     const sal_uInt32 nMaxLen = mnMaxTextLen < 65534 ? mnMaxTextLen : 65534;
852     sal_uInt32 nLenAfter = static_cast<sal_uInt32>(maText.Len()) + rStr.getLength() - nSelectionLen;
853     if ( nLenAfter > nMaxLen )
854     {
855         sal_uInt32 nErasePos = nMaxLen - static_cast<sal_uInt32>(maText.Len()) + nSelectionLen;
856         rStr = rStr.copy( 0, nErasePos );
857         bWasTruncated = true;
858     }
859     return bWasTruncated;
860 }
861 
862 // -----------------------------------------------------------------------
863 
864 void Edit::ImplInsertText( const XubString& rStr, const Selection* pNewSel, sal_Bool bIsUserInput )
865 {
866     Selection aSelection( maSelection );
867     aSelection.Justify();
868 
869     rtl::OUString aNewText( ImplGetValidString( rStr ) );
870     ImplTruncateToMaxLen( aNewText, aSelection.Len() );
871 
872     ImplClearLayoutData();
873 
874     if ( aSelection.Len() )
875         maText.Erase( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() );
876     else if ( !mbInsertMode && (aSelection.Max() < maText.Len()) )
877         maText.Erase( (xub_StrLen)aSelection.Max(), 1 );
878 
879     // take care of input-sequence-checking now
880     if (bIsUserInput && rStr.Len())
881     {
882         DBG_ASSERT( rStr.Len() == 1, "unexpected string length. User input is expected to providse 1 char only!" );
883 
884         // determine if input-sequence-checking should be applied or not
885         //
886         static OUString sModule( OUString::createFromAscii( "/org.openoffice.Office.Common/I18N" ) );
887         static OUString sRelNode( OUString::createFromAscii( "CTL" ) );
888         static OUString sCTLSequenceChecking( OUString::createFromAscii( "CTLSequenceChecking" ) );
889         static OUString sCTLSequenceCheckingRestricted( OUString::createFromAscii( "CTLSequenceCheckingRestricted" ) );
890         static OUString sCTLSequenceCheckingTypeAndReplace( OUString::createFromAscii( "CTLSequenceCheckingTypeAndReplace" ) );
891         static OUString sCTLFont( OUString::createFromAscii( "CTLFont" ) );
892         //
893         sal_Bool bCTLSequenceChecking               = sal_False;
894         sal_Bool bCTLSequenceCheckingRestricted     = sal_False;
895         sal_Bool bCTLSequenceCheckingTypeAndReplace = sal_False;
896         sal_Bool bCTLFontEnabled                    = sal_False;
897         sal_Bool bIsInputSequenceChecking           = sal_False;
898         //
899         // get access to the configuration of this office module
900         try
901         {
902             uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
903             uno::Reference< container::XNameAccess > xModuleCfg( ::comphelper::ConfigurationHelper::openConfig(
904                                     xMSF,
905                                     sModule,
906                                     ::comphelper::ConfigurationHelper::E_READONLY ),
907                                 uno::UNO_QUERY );
908 
909             //!! get values from configuration.
910             //!! we can't use SvtCTLOptions here since vcl must not be linked
911             //!! against svtools. (It is already the other way around.)
912             Any aCTLSequenceChecking                = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLSequenceChecking );
913             Any aCTLSequenceCheckingRestricted      = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLSequenceCheckingRestricted );
914             Any aCTLSequenceCheckingTypeAndReplace  = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLSequenceCheckingTypeAndReplace );
915             Any aCTLFontEnabled                     = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLFont );
916             aCTLSequenceChecking                >>= bCTLSequenceChecking;
917             aCTLSequenceCheckingRestricted      >>= bCTLSequenceCheckingRestricted;
918             aCTLSequenceCheckingTypeAndReplace  >>= bCTLSequenceCheckingTypeAndReplace;
919             aCTLFontEnabled                     >>= bCTLFontEnabled;
920         }
921         catch(...)
922         {
923             bIsInputSequenceChecking = sal_False;   // continue with inserting the new text
924         }
925         //
926         uno::Reference < i18n::XBreakIterator > xBI( ImplGetBreakIterator(), UNO_QUERY );
927         bIsInputSequenceChecking = rStr.Len() == 1 &&
928                 bCTLFontEnabled &&
929                 bCTLSequenceChecking &&
930                 aSelection.Min() > 0 && /* first char needs not to be checked */
931                 xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( rStr, 0 );
932 
933 
934         uno::Reference < i18n::XExtendedInputSequenceChecker > xISC;
935         if (bIsInputSequenceChecking && (xISC = ImplGetInputSequenceChecker()).is())
936         {
937             sal_Unicode cChar = rStr.GetChar(0);
938             xub_StrLen nTmpPos = static_cast< xub_StrLen >( aSelection.Min() );
939             sal_Int16 nCheckMode = bCTLSequenceCheckingRestricted ?
940                     i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
941 
942             // the text that needs to be checked is only the one
943             // before the current cursor position
944             rtl::OUString aOldText( maText.Copy(0, nTmpPos) );
945             rtl::OUString aTmpText( aOldText );
946             if (bCTLSequenceCheckingTypeAndReplace)
947             {
948                 xISC->correctInputSequence( aTmpText, nTmpPos - 1, cChar, nCheckMode );
949 
950                 // find position of first character that has changed
951                 sal_Int32 nOldLen = aOldText.getLength();
952                 sal_Int32 nTmpLen = aTmpText.getLength();
953                 const sal_Unicode *pOldTxt = aOldText.getStr();
954                 const sal_Unicode *pTmpTxt = aTmpText.getStr();
955                 sal_Int32 nChgPos = 0;
956                 while ( nChgPos < nOldLen && nChgPos < nTmpLen &&
957                         pOldTxt[nChgPos] == pTmpTxt[nChgPos] )
958                     ++nChgPos;
959 
960                 xub_StrLen nChgLen = static_cast< xub_StrLen >( nTmpLen - nChgPos );
961                 String aChgText( aTmpText.copy( nChgPos ), nChgLen );
962 
963                 // remove text from first pos to be changed to current pos
964                 maText.Erase( static_cast< xub_StrLen >( nChgPos ), static_cast< xub_StrLen >( nTmpPos - nChgPos ) );
965 
966                 if (aChgText.Len())
967                 {
968                     aNewText = aChgText;
969                     aSelection.Min() = nChgPos; // position for new text to be inserted
970                 }
971                 else
972                     aNewText = String::EmptyString();
973             }
974             else
975             {
976                 // should the character be ignored (i.e. not get inserted) ?
977                 if (!xISC->checkInputSequence( aOldText, nTmpPos - 1, cChar, nCheckMode ))
978                     aNewText = String::EmptyString();
979             }
980         }
981 
982         // at this point now we will insert the non-empty text 'normally' some lines below...
983     }
984 
985     if ( aNewText.getLength() )
986         maText.Insert( String( aNewText ), (xub_StrLen)aSelection.Min() );
987 
988     if ( !pNewSel )
989     {
990         maSelection.Min() = aSelection.Min() + aNewText.getLength();
991         maSelection.Max() = maSelection.Min();
992     }
993     else
994     {
995         maSelection = *pNewSel;
996         if ( maSelection.Min() > maText.Len() )
997             maSelection.Min() = maText.Len();
998         if ( maSelection.Max() > maText.Len() )
999             maSelection.Max() = maText.Len();
1000     }
1001 
1002     ImplAlignAndPaint();
1003     mbInternModified = sal_True;
1004 }
1005 
1006 // -----------------------------------------------------------------------
1007 
1008 void Edit::ImplSetText( const XubString& rText, const Selection* pNewSelection )
1009 {
1010     // Der Text wird dadurch geloescht das der alte Text komplett 'selektiert'
1011     // wird, dann InsertText, damit flackerfrei.
1012     if ( ( rText.Len() <= mnMaxTextLen ) && ( (rText != maText) || (pNewSelection && (*pNewSelection != maSelection)) ) )
1013     {
1014         ImplClearLayoutData();
1015         maSelection.Min() = 0;
1016         maSelection.Max() = maText.Len();
1017         if ( mnXOffset || HasPaintEvent() )
1018         {
1019             mnXOffset = 0;
1020             maText = ImplGetValidString( rText );
1021 
1022             // #i54929# recalculate mnXOffset before ImplSetSelection,
1023             // else cursor ends up in wrong position
1024             ImplAlign();
1025 
1026             if ( pNewSelection )
1027                 ImplSetSelection( *pNewSelection, sal_False );
1028 
1029             if ( mnXOffset && !pNewSelection )
1030                 maSelection.Max() = 0;
1031 
1032             Invalidate();
1033         }
1034         else
1035             ImplInsertText( rText, pNewSelection );
1036 
1037         ImplCallEventListeners( VCLEVENT_EDIT_MODIFY );
1038     }
1039 }
1040 
1041 // -----------------------------------------------------------------------
1042 
1043 int Edit::ImplGetNativeControlType()
1044 {
1045     int nCtrl = 0;
1046     Window *pControl = mbIsSubEdit ? GetParent() : this;
1047 
1048     switch( pControl->GetType() )
1049     {
1050         case WINDOW_COMBOBOX:
1051         case WINDOW_PATTERNBOX:
1052         case WINDOW_NUMERICBOX:
1053         case WINDOW_METRICBOX:
1054         case WINDOW_CURRENCYBOX:
1055         case WINDOW_DATEBOX:
1056         case WINDOW_TIMEBOX:
1057         case WINDOW_LONGCURRENCYBOX:
1058             nCtrl = CTRL_COMBOBOX;
1059             break;
1060 
1061         case WINDOW_MULTILINEEDIT:
1062             if ( GetWindow( WINDOW_BORDER ) != this )
1063                 nCtrl = CTRL_MULTILINE_EDITBOX;
1064             else
1065                 nCtrl = CTRL_EDITBOX_NOBORDER;
1066             break;
1067 
1068         case WINDOW_EDIT:
1069         case WINDOW_PATTERNFIELD:
1070         case WINDOW_METRICFIELD:
1071         case WINDOW_CURRENCYFIELD:
1072         case WINDOW_DATEFIELD:
1073         case WINDOW_TIMEFIELD:
1074         case WINDOW_LONGCURRENCYFIELD:
1075         case WINDOW_NUMERICFIELD:
1076         case WINDOW_SPINFIELD:
1077             if( pControl->GetStyle() & WB_SPIN )
1078                 nCtrl = CTRL_SPINBOX;
1079             else
1080             {
1081                 if ( GetWindow( WINDOW_BORDER ) != this )
1082                     nCtrl = CTRL_EDITBOX;
1083                 else
1084                     nCtrl = CTRL_EDITBOX_NOBORDER;
1085             }
1086             break;
1087 
1088         default:
1089             nCtrl = CTRL_EDITBOX;
1090     }
1091     return nCtrl;
1092 }
1093 
1094 void Edit::ImplClearBackground( long nXStart, long nXEnd )
1095 {
1096     /*
1097     * note: at this point the cursor must be switched off already
1098     */
1099     Point aTmpPoint;
1100     Rectangle aRect( aTmpPoint, GetOutputSizePixel() );
1101     aRect.Left() = nXStart;
1102     aRect.Right() = nXEnd;
1103 
1104     if( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() )
1105     {
1106         // draw the inner part by painting the whole control using its border window
1107         Window *pControl = this;
1108         Window *pBorder = GetWindow( WINDOW_BORDER );
1109         if( pBorder == this )
1110         {
1111             // we have no border, use parent
1112             pControl = mbIsSubEdit ? GetParent() : this;
1113             pBorder = pControl->GetWindow( WINDOW_BORDER );
1114             if( pBorder == this )
1115                 pBorder = GetParent();
1116         }
1117 
1118         if( pBorder )
1119         {
1120             // set proper clipping region to not overdraw the whole control
1121             Region aClipRgn = GetPaintRegion();
1122             if( !aClipRgn.IsNull() )
1123             {
1124                 // transform clipping region to border window's coordinate system
1125                 if( IsRTLEnabled() != pBorder->IsRTLEnabled() && Application::GetSettings().GetLayoutRTL() )
1126                 {
1127                     // need to mirror in case border is not RTL but edit is (or vice versa)
1128 
1129                     // mirror
1130                     Rectangle aBounds( aClipRgn.GetBoundRect() );
1131                     int xNew = GetOutputSizePixel().Width() - aBounds.GetWidth() - aBounds.Left();
1132                     aClipRgn.Move( xNew - aBounds.Left(), 0 );
1133 
1134                     // move offset of border window
1135                     Point aBorderOffs;
1136                     aBorderOffs = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs ) );
1137                     aClipRgn.Move( aBorderOffs.X(), aBorderOffs.Y() );
1138                 }
1139                 else
1140                 {
1141                     // normal case
1142                     Point aBorderOffs;
1143                     aBorderOffs = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs ) );
1144                     aClipRgn.Move( aBorderOffs.X(), aBorderOffs.Y() );
1145                 }
1146 
1147                 Region oldRgn( pBorder->GetClipRegion() );
1148                 pBorder->SetClipRegion( aClipRgn );
1149 
1150                 pBorder->Paint( Rectangle() );
1151 
1152                 pBorder->SetClipRegion( oldRgn );
1153             }
1154             else
1155                 pBorder->Paint( Rectangle() );
1156 
1157         }
1158     }
1159     else
1160         Erase( aRect );
1161 }
1162 
1163 // -----------------------------------------------------------------------
1164 
1165 void Edit::ImplShowCursor( sal_Bool bOnlyIfVisible )
1166 {
1167     if ( !IsUpdateMode() || ( bOnlyIfVisible && !IsReallyVisible() ) )
1168         return;
1169 
1170     Cursor*     pCursor = GetCursor();
1171     XubString   aText = ImplGetText();
1172 
1173     long nTextPos = 0;
1174 
1175     sal_Int32   nDXBuffer[256];
1176     sal_Int32*  pDXBuffer = NULL;
1177     sal_Int32*  pDX = nDXBuffer;
1178 
1179     if( aText.Len() )
1180     {
1181         if( 2*aText.Len() > xub_StrLen(sizeof(nDXBuffer)/sizeof(nDXBuffer[0])) )
1182         {
1183             pDXBuffer = new sal_Int32[2*(aText.Len()+1)];
1184             pDX = pDXBuffer;
1185         }
1186 
1187         GetCaretPositions( aText, pDX, 0, aText.Len() );
1188 
1189         if( maSelection.Max() < aText.Len() )
1190             nTextPos = pDX[ 2*maSelection.Max() ];
1191         else
1192             nTextPos = pDX[ 2*aText.Len()-1 ];
1193     }
1194 
1195     long nCursorWidth = 0;
1196     if ( !mbInsertMode && !maSelection.Len() && (maSelection.Max() < aText.Len()) )
1197         nCursorWidth = GetTextWidth( aText, (xub_StrLen)maSelection.Max(), 1 );
1198     long nCursorPosX = nTextPos + mnXOffset + ImplGetExtraOffset();
1199 
1200     // Cursor muss im sichtbaren Bereich landen:
1201     const Size aOutSize = GetOutputSizePixel();
1202     if ( (nCursorPosX < 0) || (nCursorPosX >= aOutSize.Width()) )
1203     {
1204         long nOldXOffset = mnXOffset;
1205 
1206         if ( nCursorPosX < 0 )
1207         {
1208             mnXOffset = - nTextPos;
1209             long nMaxX = 0;
1210             mnXOffset += aOutSize.Width() / 5;
1211             if ( mnXOffset > nMaxX )
1212                 mnXOffset = nMaxX;
1213         }
1214         else
1215         {
1216             mnXOffset = (aOutSize.Width()-ImplGetExtraOffset()) - nTextPos;
1217             // Etwas mehr?
1218             if ( (aOutSize.Width()-ImplGetExtraOffset()) < nTextPos )
1219             {
1220                 long nMaxNegX = (aOutSize.Width()-ImplGetExtraOffset()) - GetTextWidth( aText );
1221                 mnXOffset -= aOutSize.Width() / 5;
1222                 if ( mnXOffset < nMaxNegX )  // beides negativ...
1223                     mnXOffset = nMaxNegX;
1224             }
1225         }
1226 
1227         nCursorPosX = nTextPos + mnXOffset + ImplGetExtraOffset();
1228         if ( nCursorPosX == aOutSize.Width() )  // dann nicht sichtbar...
1229             nCursorPosX--;
1230 
1231         if ( mnXOffset != nOldXOffset )
1232             ImplInvalidateOrRepaint();
1233     }
1234 
1235     const long nTextHeight = GetTextHeight();
1236     const long nCursorPosY = ImplGetTextYPosition();
1237     pCursor->SetPos( Point( nCursorPosX, nCursorPosY ) );
1238     pCursor->SetSize( Size( nCursorWidth, nTextHeight ) );
1239     pCursor->Show();
1240 
1241     if( pDXBuffer )
1242         delete [] pDXBuffer;
1243 }
1244 
1245 // -----------------------------------------------------------------------
1246 
1247 void Edit::ImplAlign()
1248 {
1249     long nTextWidth = GetTextWidth( ImplGetText() );
1250     long nOutWidth = GetOutputSizePixel().Width();
1251 
1252     if ( mnAlign == EDIT_ALIGN_LEFT )
1253     {
1254         if( mnXOffset && ( nTextWidth < nOutWidth ) )
1255             mnXOffset = 0;
1256 
1257     }
1258     else if ( mnAlign == EDIT_ALIGN_RIGHT )
1259     {
1260         long nMinXOffset = nOutWidth - nTextWidth - 1 - ImplGetExtraOffset();
1261         bool bRTL = IsRTLEnabled();
1262         if( mbIsSubEdit && GetParent() )
1263             bRTL = GetParent()->IsRTLEnabled();
1264         if( bRTL )
1265         {
1266             if( nTextWidth < nOutWidth )
1267                 mnXOffset = nMinXOffset;
1268         }
1269         else
1270         {
1271             if( nTextWidth < nOutWidth )
1272                 mnXOffset = nMinXOffset;
1273             else if ( mnXOffset < nMinXOffset )
1274                 mnXOffset = nMinXOffset;
1275         }
1276     }
1277     else if( mnAlign == EDIT_ALIGN_CENTER )
1278     {
1279         // Mit Abfrage schoener, wenn gescrollt, dann aber nicht zentriert im gescrollten Zustand...
1280 //      if ( nTextWidth < nOutWidth )
1281             mnXOffset = (nOutWidth - nTextWidth) / 2;
1282     }
1283 }
1284 
1285 
1286 // -----------------------------------------------------------------------
1287 
1288 void Edit::ImplAlignAndPaint()
1289 {
1290     ImplAlign();
1291     ImplInvalidateOrRepaint( 0, STRING_LEN );
1292     ImplShowCursor();
1293 }
1294 
1295 // -----------------------------------------------------------------------
1296 
1297 xub_StrLen Edit::ImplGetCharPos( const Point& rWindowPos ) const
1298 {
1299     xub_StrLen nIndex = STRING_LEN;
1300     String aText = ImplGetText();
1301 
1302     sal_Int32   nDXBuffer[256];
1303     sal_Int32*  pDXBuffer = NULL;
1304     sal_Int32*  pDX = nDXBuffer;
1305     if( 2*aText.Len() > xub_StrLen(sizeof(nDXBuffer)/sizeof(nDXBuffer[0])) )
1306     {
1307         pDXBuffer = new sal_Int32[2*(aText.Len()+1)];
1308         pDX = pDXBuffer;
1309     }
1310 
1311     GetCaretPositions( aText, pDX, 0, aText.Len() );
1312     long nX = rWindowPos.X() - mnXOffset - ImplGetExtraOffset();
1313     for( int i = 0; i < aText.Len(); i++ )
1314     {
1315         if( (pDX[2*i] >= nX && pDX[2*i+1] <= nX) ||
1316             (pDX[2*i+1] >= nX && pDX[2*i] <= nX))
1317         {
1318             nIndex = sal::static_int_cast<xub_StrLen>(i);
1319             if( pDX[2*i] < pDX[2*i+1] )
1320             {
1321                 if( nX > (pDX[2*i]+pDX[2*i+1])/2 )
1322                     nIndex++;
1323             }
1324             else
1325             {
1326                 if( nX < (pDX[2*i]+pDX[2*i+1])/2 )
1327                     nIndex++;
1328             }
1329             break;
1330         }
1331     }
1332     if( nIndex == STRING_LEN )
1333     {
1334         nIndex = 0;
1335         long nDiff = Abs( pDX[0]-nX );
1336         for( int i = 1; i < aText.Len(); i++ )
1337         {
1338             long nNewDiff = Abs( pDX[2*i]-nX );
1339 
1340             if( nNewDiff < nDiff )
1341             {
1342                 nIndex = sal::static_int_cast<xub_StrLen>(i);
1343                 nDiff = nNewDiff;
1344             }
1345         }
1346         if( nIndex == aText.Len()-1 && Abs( pDX[2*nIndex+1] - nX ) < nDiff )
1347             nIndex = STRING_LEN;
1348     }
1349 
1350     if( pDXBuffer )
1351         delete [] pDXBuffer;
1352 
1353     return nIndex;
1354 }
1355 
1356 // -----------------------------------------------------------------------
1357 
1358 void Edit::ImplSetCursorPos( xub_StrLen nChar, sal_Bool bSelect )
1359 {
1360     Selection aSelection( maSelection );
1361     aSelection.Max() = nChar;
1362     if ( !bSelect )
1363         aSelection.Min() = aSelection.Max();
1364     ImplSetSelection( aSelection );
1365 }
1366 
1367 // -----------------------------------------------------------------------
1368 
1369 void Edit::ImplLoadRes( const ResId& rResId )
1370 {
1371     Control::ImplLoadRes( rResId );
1372 
1373     xub_StrLen nTextLength = ReadShortRes();
1374     if ( nTextLength )
1375         SetMaxTextLen( nTextLength );
1376 }
1377 
1378 // -----------------------------------------------------------------------
1379 
1380 void Edit::ImplCopyToSelectionClipboard()
1381 {
1382     if ( GetSelection().Len() )
1383     {
1384         ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aSelection(GetPrimarySelection());
1385         ImplCopy( aSelection );
1386     }
1387 }
1388 
1389 void Edit::ImplCopy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1390 {
1391     ::vcl::unohelper::TextDataObject::CopyStringTo( GetSelected(), rxClipboard );
1392 }
1393 
1394 // -----------------------------------------------------------------------
1395 
1396 void Edit::ImplPaste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1397 {
1398     if ( rxClipboard.is() )
1399     {
1400         uno::Reference< datatransfer::XTransferable > xDataObj;
1401 
1402         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1403 
1404         try
1405         {
1406             xDataObj = rxClipboard->getContents();
1407         }
1408         catch( const ::com::sun::star::uno::Exception& )
1409         {
1410         }
1411 
1412         Application::AcquireSolarMutex( nRef );
1413 
1414         if ( xDataObj.is() )
1415         {
1416             datatransfer::DataFlavor aFlavor;
1417             SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
1418             try
1419             {
1420                 uno::Any aData = xDataObj->getTransferData( aFlavor );
1421                 ::rtl::OUString aText;
1422                 aData >>= aText;
1423                 if( ImplTruncateToMaxLen( aText, maSelection.Len() ) )
1424                     ShowTruncationWarning( const_cast<Edit*>(this) );
1425                 ReplaceSelected( aText );
1426             }
1427             catch( const ::com::sun::star::uno::Exception& )
1428             {
1429             }
1430         }
1431     }
1432 }
1433 
1434 // -----------------------------------------------------------------------
1435 
1436 void Edit::MouseButtonDown( const MouseEvent& rMEvt )
1437 {
1438     if ( mpSubEdit )
1439     {
1440         Control::MouseButtonDown( rMEvt );
1441         return;
1442     }
1443 
1444     xub_StrLen nChar = ImplGetCharPos( rMEvt.GetPosPixel() );
1445     Selection aSelection( maSelection );
1446     aSelection.Justify();
1447 
1448     if ( rMEvt.GetClicks() < 4 )
1449     {
1450         mbClickedInSelection = sal_False;
1451         if ( rMEvt.GetClicks() == 3 )
1452         {
1453             ImplSetSelection( Selection( 0, 0xFFFF ) );
1454             ImplCopyToSelectionClipboard();
1455 
1456         }
1457         else if ( rMEvt.GetClicks() == 2 )
1458         {
1459             uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
1460             i18n::Boundary aBoundary = xBI->getWordBoundary( maText, aSelection.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1461             ImplSetSelection( Selection( aBoundary.startPos, aBoundary.endPos ) );
1462             ImplCopyToSelectionClipboard();
1463         }
1464         else if ( !rMEvt.IsShift() && HasFocus() && aSelection.IsInside( nChar ) )
1465             mbClickedInSelection = sal_True;
1466         else if ( rMEvt.IsLeft() )
1467             ImplSetCursorPos( nChar, rMEvt.IsShift() );
1468 
1469         if ( !mbClickedInSelection && rMEvt.IsLeft() && ( rMEvt.GetClicks() == 1 ) )
1470             StartTracking( STARTTRACK_SCROLLREPEAT );
1471     }
1472 
1473     mbInMBDown = sal_True;  // Dann im GetFocus nicht alles selektieren
1474     GrabFocus();
1475     mbInMBDown = sal_False;
1476 }
1477 
1478 // -----------------------------------------------------------------------
1479 
1480 void Edit::MouseButtonUp( const MouseEvent& rMEvt )
1481 {
1482     if ( mbClickedInSelection && rMEvt.IsLeft() )
1483     {
1484         xub_StrLen nChar = ImplGetCharPos( rMEvt.GetPosPixel() );
1485         ImplSetCursorPos( nChar, sal_False );
1486         mbClickedInSelection = sal_False;
1487     }
1488     else if ( rMEvt.IsMiddle() && !mbReadOnly &&
1489               ( GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) )
1490     {
1491         ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aSelection(Window::GetPrimarySelection());
1492         ImplPaste( aSelection );
1493         ImplModified();
1494     }
1495 }
1496 
1497 // -----------------------------------------------------------------------
1498 
1499 void Edit::Tracking( const TrackingEvent& rTEvt )
1500 {
1501     if ( rTEvt.IsTrackingEnded() )
1502     {
1503         if ( mbClickedInSelection )
1504         {
1505             xub_StrLen nChar = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() );
1506             ImplSetCursorPos( nChar, sal_False );
1507             mbClickedInSelection = sal_False;
1508         }
1509         else if ( rTEvt.GetMouseEvent().IsLeft() )
1510         {
1511             ImplCopyToSelectionClipboard();
1512         }
1513     }
1514     else
1515     {
1516         if( !mbClickedInSelection )
1517         {
1518             xub_StrLen nChar = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() );
1519             ImplSetCursorPos( nChar, sal_True );
1520         }
1521     }
1522 
1523     if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() )
1524         mpUpdateDataTimer->Start();//do not update while the user is still travelling in the control
1525 }
1526 
1527 // -----------------------------------------------------------------------
1528 
1529 sal_Bool Edit::ImplHandleKeyEvent( const KeyEvent& rKEvt )
1530 {
1531     sal_Bool        bDone = sal_False;
1532     sal_uInt16      nCode = rKEvt.GetKeyCode().GetCode();
1533     KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
1534 
1535     mbInternModified = sal_False;
1536 
1537     if ( eFunc != KEYFUNC_DONTKNOW )
1538     {
1539         switch ( eFunc )
1540         {
1541             case KEYFUNC_CUT:
1542             {
1543                 if ( !mbReadOnly && maSelection.Len() && !(GetStyle() & WB_PASSWORD) )
1544                 {
1545                     Cut();
1546                     ImplModified();
1547                     bDone = sal_True;
1548                 }
1549             }
1550             break;
1551 
1552             case KEYFUNC_COPY:
1553             {
1554                 if ( !(GetStyle() & WB_PASSWORD) )
1555                 {
1556                     Copy();
1557                     bDone = sal_True;
1558                 }
1559             }
1560             break;
1561 
1562             case KEYFUNC_PASTE:
1563             {
1564                 if ( !mbReadOnly )
1565                 {
1566                     Paste();
1567                     bDone = sal_True;
1568                 }
1569             }
1570             break;
1571 
1572             case KEYFUNC_UNDO:
1573             {
1574                 if ( !mbReadOnly )
1575                 {
1576                     Undo();
1577                     bDone = sal_True;
1578                 }
1579             }
1580             break;
1581 
1582             default: // wird dann evtl. unten bearbeitet.
1583                 eFunc = KEYFUNC_DONTKNOW;
1584         }
1585     }
1586 
1587     if ( !bDone && rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() )
1588     {
1589         if ( nCode == KEY_A )
1590         {
1591             ImplSetSelection( Selection( 0, maText.Len() ) );
1592             bDone = sal_True;
1593         }
1594         else if ( rKEvt.GetKeyCode().IsShift() && (nCode == KEY_S) )
1595         {
1596             if ( pImplFncGetSpecialChars )
1597             {
1598                 Selection aSaveSel = GetSelection();    // Falls jemand in Get/LoseFocus die Selektion verbiegt, z.B. URL-Zeile...
1599                 XubString aChars = pImplFncGetSpecialChars( this, GetFont() );
1600                 SetSelection( aSaveSel );
1601                 if ( aChars.Len() )
1602                 {
1603                     ImplInsertText( aChars );
1604                     ImplModified();
1605                 }
1606                 bDone = sal_True;
1607             }
1608         }
1609     }
1610 
1611     if ( eFunc == KEYFUNC_DONTKNOW && ! bDone )
1612     {
1613         switch ( nCode )
1614         {
1615             case com::sun::star::awt::Key::SELECT_ALL:
1616             {
1617                 ImplSetSelection( Selection( 0, maText.Len() ) );
1618                 bDone = sal_True;
1619             }
1620             break;
1621 
1622             case KEY_LEFT:
1623             case KEY_RIGHT:
1624             case KEY_HOME:
1625             case KEY_END:
1626             case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
1627             case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
1628             case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
1629             case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
1630             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1631             case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
1632             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1633             case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
1634             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1635             case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1636             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1637             case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1638             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1639             case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1640             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1641             case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1642             {
1643                 if ( !rKEvt.GetKeyCode().IsMod2() )
1644                 {
1645                     ImplClearLayoutData();
1646                     uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
1647 
1648                     Selection aSel( maSelection );
1649                     bool bWord = rKEvt.GetKeyCode().IsMod1();
1650                     bool bSelect = rKEvt.GetKeyCode().IsShift();
1651                     bool bGoLeft = (nCode == KEY_LEFT);
1652                     bool bGoRight = (nCode == KEY_RIGHT);
1653                     bool bGoHome = (nCode == KEY_HOME);
1654                     bool bGoEnd = (nCode == KEY_END);
1655 
1656                     switch( nCode )
1657                     {
1658                     case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
1659                         bGoRight = bWord = true;break;
1660                     case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
1661                         bGoRight = bSelect = bWord = true;break;
1662                     case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
1663                         bGoLeft = bWord = true;break;
1664                     case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
1665                         bGoLeft = bSelect = bWord = true;break;
1666                     case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1667                     case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1668                     case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1669                         bSelect = true;
1670                         // fallthrough intended
1671                     case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1672                     case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1673                     case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1674                         bGoHome = true;break;
1675                     case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
1676                     case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1677                     case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1678                         bSelect = true;
1679                         // fallthrough intended
1680                     case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
1681                     case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1682                     case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1683                         bGoEnd = true;break;
1684                     default:
1685                         break;
1686                     };
1687 
1688                     // Range wird in ImplSetSelection geprueft...
1689                     if ( bGoLeft && aSel.Max() )
1690                     {
1691                         if ( bWord )
1692                         {
1693                             i18n::Boundary aBoundary = xBI->getWordBoundary( maText, aSel.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1694                             if ( aBoundary.startPos == aSel.Max() )
1695                                 aBoundary = xBI->previousWord( maText, aSel.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1696                             aSel.Max() = aBoundary.startPos;
1697                         }
1698                         else
1699                         {
1700                             sal_Int32 nCount = 1;
1701                             aSel.Max() = xBI->previousCharacters( maText, aSel.Max(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
1702                         }
1703                     }
1704                     else if ( bGoRight && ( aSel.Max() < maText.Len() ) )
1705                     {
1706                         if ( bWord )
1707                         {
1708                             i18n::Boundary aBoundary = xBI->nextWord( maText, aSel.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1709                             aSel.Max() = aBoundary.startPos;
1710                         }
1711                         else
1712                         {
1713                             sal_Int32 nCount = 1;
1714                             aSel.Max() = xBI->nextCharacters( maText, aSel.Max(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );
1715                         }
1716                     }
1717                     else if ( bGoHome )
1718                     {
1719                         aSel.Max() = 0;
1720                     }
1721                     else if ( bGoEnd )
1722                     {
1723                         aSel.Max() = 0xFFFF;
1724                     }
1725 
1726                     if ( !bSelect )
1727                         aSel.Min() = aSel.Max();
1728 
1729                     if ( aSel != GetSelection() )
1730                     {
1731                         ImplSetSelection( aSel );
1732                         ImplCopyToSelectionClipboard();
1733                     }
1734 
1735                     if ( bGoEnd && maAutocompleteHdl.IsSet() && !rKEvt.GetKeyCode().GetModifier() )
1736                     {
1737                         if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) )
1738                         {
1739                             meAutocompleteAction = AUTOCOMPLETE_KEYINPUT;
1740                             maAutocompleteHdl.Call( this );
1741                         }
1742                     }
1743 
1744                     bDone = sal_True;
1745                 }
1746             }
1747             break;
1748 
1749             case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
1750             case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
1751             case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
1752             case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
1753             case KEY_BACKSPACE:
1754             case KEY_DELETE:
1755             {
1756                 if ( !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() )
1757                 {
1758                     sal_uInt8 nDel = (nCode == KEY_DELETE) ? EDIT_DEL_RIGHT : EDIT_DEL_LEFT;
1759                     sal_uInt8 nMode = rKEvt.GetKeyCode().IsMod1() ? EDIT_DELMODE_RESTOFWORD : EDIT_DELMODE_SIMPLE;
1760                     if ( (nMode == EDIT_DELMODE_RESTOFWORD) && rKEvt.GetKeyCode().IsShift() )
1761                         nMode = EDIT_DELMODE_RESTOFCONTENT;
1762                     switch( nCode )
1763                     {
1764                     case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
1765                         nDel = EDIT_DEL_LEFT;
1766                         nMode = EDIT_DELMODE_RESTOFWORD;
1767                         break;
1768                     case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
1769                         nDel = EDIT_DEL_RIGHT;
1770                         nMode = EDIT_DELMODE_RESTOFWORD;
1771                         break;
1772                     case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
1773                         nDel = EDIT_DEL_LEFT;
1774                         nMode = EDIT_DELMODE_RESTOFCONTENT;
1775                         break;
1776                     case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
1777                         nDel = EDIT_DEL_RIGHT;
1778                         nMode = EDIT_DELMODE_RESTOFCONTENT;
1779                         break;
1780                     default: break;
1781                     }
1782                     xub_StrLen nOldLen = maText.Len();
1783                     ImplDelete( maSelection, nDel, nMode );
1784                     if ( maText.Len() != nOldLen )
1785                         ImplModified();
1786                     bDone = sal_True;
1787                 }
1788             }
1789             break;
1790 
1791             case KEY_INSERT:
1792             {
1793                 if ( !mpIMEInfos && !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() )
1794                 {
1795                     SetInsertMode( !mbInsertMode );
1796                     bDone = sal_True;
1797                 }
1798             }
1799             break;
1800 
1801             /* #i101255# disable autocomplete tab forward/backward
1802                users expect tab/shif-tab to move the focus to other controls
1803                not suddenly to cycle the autocompletion
1804             case KEY_TAB:
1805             {
1806                 if ( !mbReadOnly && maAutocompleteHdl.IsSet() &&
1807                      maSelection.Min() && (maSelection.Min() == maText.Len()) &&
1808                      !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() )
1809                 {
1810                     // Kein Autocomplete wenn alles Selektiert oder Edit leer, weil dann
1811                     // keine vernuenftige Tab-Steuerung!
1812                     if ( rKEvt.GetKeyCode().IsShift() )
1813                         meAutocompleteAction = AUTOCOMPLETE_TABBACKWARD;
1814                     else
1815                         meAutocompleteAction = AUTOCOMPLETE_TABFORWARD;
1816 
1817                     maAutocompleteHdl.Call( this );
1818 
1819                     // Wurde nichts veraendert, dann TAB fuer DialogControl
1820                     if ( GetSelection().Len() )
1821                         bDone = sal_True;
1822                 }
1823             }
1824             break;
1825             */
1826 
1827             default:
1828             {
1829                 if ( IsCharInput( rKEvt ) )
1830                 {
1831                     bDone = sal_True;   // Auch bei ReadOnly die Zeichen schlucken.
1832                     if ( !mbReadOnly )
1833                     {
1834                         ImplInsertText( rKEvt.GetCharCode(), 0, sal_True );
1835                         if ( maAutocompleteHdl.IsSet() )
1836                         {
1837                             if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) )
1838                             {
1839                                 meAutocompleteAction = AUTOCOMPLETE_KEYINPUT;
1840                                 maAutocompleteHdl.Call( this );
1841                             }
1842                         }
1843                     }
1844                 }
1845             }
1846         }
1847     }
1848 
1849     if ( mbInternModified )
1850         ImplModified();
1851 
1852     return bDone;
1853 }
1854 
1855 // -----------------------------------------------------------------------
1856 
1857 void Edit::KeyInput( const KeyEvent& rKEvt )
1858 {
1859     if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() )
1860         mpUpdateDataTimer->Start();//do not update while the user is still travelling in the control
1861 
1862     if ( mpSubEdit || !ImplHandleKeyEvent( rKEvt ) )
1863         Control::KeyInput( rKEvt );
1864 }
1865 
1866 // -----------------------------------------------------------------------
1867 
1868 void Edit::FillLayoutData() const
1869 {
1870     mpControlData->mpLayoutData = new vcl::ControlLayoutData();
1871     const_cast<Edit*>(this)->ImplRepaint( 0, STRING_LEN, true );
1872 }
1873 
1874 // -----------------------------------------------------------------------
1875 
1876 void Edit::Paint( const Rectangle& )
1877 {
1878     if ( !mpSubEdit )
1879         ImplRepaint();
1880 }
1881 
1882 // -----------------------------------------------------------------------
1883 
1884 void Edit::Resize()
1885 {
1886     if ( !mpSubEdit && IsReallyVisible() )
1887     {
1888         Control::Resize();
1889         // Wegen vertikaler Zentrierung...
1890         mnXOffset = 0;
1891         ImplAlign();
1892         Invalidate();
1893         ImplShowCursor();
1894     }
1895 }
1896 
1897 // -----------------------------------------------------------------------
1898 
1899 void Edit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
1900 {
1901     ImplInitSettings( sal_True, sal_True, sal_True );
1902 
1903     Point aPos = pDev->LogicToPixel( rPos );
1904     Size aSize = pDev->LogicToPixel( rSize );
1905     Font aFont = GetDrawPixelFont( pDev );
1906     OutDevType eOutDevType = pDev->GetOutDevType();
1907 
1908     pDev->Push();
1909     pDev->SetMapMode();
1910     pDev->SetFont( aFont );
1911     pDev->SetTextFillColor();
1912 
1913     // Border/Background
1914     pDev->SetLineColor();
1915     pDev->SetFillColor();
1916     sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
1917     sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
1918     if ( bBorder || bBackground )
1919     {
1920         Rectangle aRect( aPos, aSize );
1921         if ( bBorder )
1922         {
1923             ImplDrawFrame( pDev, aRect );
1924         }
1925         if ( bBackground )
1926         {
1927             pDev->SetFillColor( GetControlBackground() );
1928             pDev->DrawRect( aRect );
1929         }
1930     }
1931 
1932     // Inhalt
1933     if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
1934         pDev->SetTextColor( Color( COL_BLACK ) );
1935     else
1936     {
1937         if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
1938         {
1939             const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1940             pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1941         }
1942         else
1943         {
1944             pDev->SetTextColor( GetTextColor() );
1945         }
1946     }
1947 
1948     XubString   aText = ImplGetText();
1949     long        nTextHeight = pDev->GetTextHeight();
1950     long        nTextWidth = pDev->GetTextWidth( aText );
1951     long        nOnePixel = GetDrawPixel( pDev, 1 );
1952     long        nOffX = 3*nOnePixel;
1953     long        nOffY = (aSize.Height() - nTextHeight) / 2;
1954 
1955     // Clipping?
1956     if ( (nOffY < 0) ||
1957          ((nOffY+nTextHeight) > aSize.Height()) ||
1958          ((nOffX+nTextWidth) > aSize.Width()) )
1959     {
1960         Rectangle aClip( aPos, aSize );
1961         if ( nTextHeight > aSize.Height() )
1962             aClip.Bottom() += nTextHeight-aSize.Height()+1;  // Damit HP-Drucker nicht 'weg-optimieren'
1963         pDev->IntersectClipRegion( aClip );
1964     }
1965 
1966     if ( GetStyle() & WB_CENTER )
1967     {
1968         aPos.X() += (aSize.Width() - nTextWidth) / 2;
1969         nOffX = 0;
1970     }
1971     else if ( GetStyle() & WB_RIGHT )
1972     {
1973         aPos.X() += aSize.Width() - nTextWidth;
1974         nOffX = -nOffX;
1975     }
1976 
1977     pDev->DrawText( Point( aPos.X() + nOffX, aPos.Y() + nOffY ), aText );
1978     pDev->Pop();
1979 
1980     if ( GetSubEdit() )
1981     {
1982         GetSubEdit()->Draw( pDev, rPos, rSize, nFlags );
1983     }
1984 }
1985 
1986 // -----------------------------------------------------------------------
1987 
1988 void Edit::ImplInvalidateOutermostBorder( Window* pWin )
1989 {
1990     // allow control to show focused state
1991     Window *pInvalWin = pWin, *pBorder = pWin;
1992     while( ( pBorder = pInvalWin->GetWindow( WINDOW_BORDER ) ) != pInvalWin && pBorder &&
1993            pInvalWin->ImplGetFrame() == pBorder->ImplGetFrame() )
1994     {
1995         pInvalWin = pBorder;
1996     }
1997 
1998     pInvalWin->Invalidate( INVALIDATE_CHILDREN | INVALIDATE_UPDATE );
1999 }
2000 
2001 void Edit::GetFocus()
2002 {
2003     if ( mpSubEdit )
2004         mpSubEdit->ImplGrabFocus( GetGetFocusFlags() );
2005     else if ( !mbActivePopup )
2006     {
2007         maUndoText = maText;
2008 
2009         sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
2010         if ( !( GetStyle() & (WB_NOHIDESELECTION|WB_READONLY) )
2011                 && ( GetGetFocusFlags() & (GETFOCUS_INIT|GETFOCUS_TAB|GETFOCUS_CURSOR|GETFOCUS_MNEMONIC) ) )
2012         {
2013             if ( nSelOptions & SELECTION_OPTION_SHOWFIRST )
2014             {
2015                 maSelection.Min() = maText.Len();
2016                 maSelection.Max() = 0;
2017             }
2018             else
2019             {
2020                 maSelection.Min() = 0;
2021                 maSelection.Max() = maText.Len();
2022             }
2023             if ( mbIsSubEdit )
2024                 ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED );
2025             else
2026                 ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED );
2027         }
2028 
2029         ImplShowCursor();
2030 
2031         // FIXME: this is currently only on aqua
2032         // check for other platforms that need similar handling
2033         if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2034             IsNativeWidgetEnabled() &&
2035             IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) )
2036         {
2037             ImplInvalidateOutermostBorder( mbIsSubEdit ? GetParent() : this );
2038         }
2039         else if ( maSelection.Len() )
2040         {
2041             // Selektion malen
2042             if ( !HasPaintEvent() )
2043                 ImplInvalidateOrRepaint();
2044             else
2045                 Invalidate();
2046         }
2047 
2048         SetInputContext( InputContext( GetFont(), !IsReadOnly() ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
2049     }
2050 
2051     Control::GetFocus();
2052 }
2053 
2054 // -----------------------------------------------------------------------
2055 
2056 Window* Edit::GetPreferredKeyInputWindow()
2057 {
2058     if ( mpSubEdit )
2059         return mpSubEdit->GetPreferredKeyInputWindow();
2060     else
2061         return this;
2062 }
2063 
2064 // -----------------------------------------------------------------------
2065 
2066 void Edit::LoseFocus()
2067 {
2068     if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() )
2069     {
2070         //notify an update latest when the focus is lost
2071         mpUpdateDataTimer->Stop();
2072         mpUpdateDataTimer->Timeout();
2073     }
2074 
2075     if ( !mpSubEdit )
2076     {
2077         // FIXME: this is currently only on aqua
2078         // check for other platforms that need similar handling
2079         if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2080             IsNativeWidgetEnabled() &&
2081             IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) )
2082         {
2083             ImplInvalidateOutermostBorder( mbIsSubEdit ? GetParent() : this );
2084         }
2085 
2086         if ( !mbActivePopup && !( GetStyle() & WB_NOHIDESELECTION ) && maSelection.Len() )
2087             ImplInvalidateOrRepaint();    // Selektion malen
2088     }
2089 
2090     Control::LoseFocus();
2091 }
2092 
2093 // -----------------------------------------------------------------------
2094 
2095 void Edit::Command( const CommandEvent& rCEvt )
2096 {
2097     if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
2098     {
2099         PopupMenu* pPopup = Edit::CreatePopupMenu();
2100         const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2101         if ( rStyleSettings.GetOptions() & STYLE_OPTION_HIDEDISABLED )
2102             pPopup->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES );
2103 
2104         if ( !maSelection.Len() )
2105         {
2106             pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False );
2107             pPopup->EnableItem( SV_MENU_EDIT_COPY, sal_False );
2108             pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False );
2109         }
2110 
2111         if ( IsReadOnly() )
2112         {
2113             pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False );
2114             pPopup->EnableItem( SV_MENU_EDIT_PASTE, sal_False );
2115             pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False );
2116             pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, sal_False );
2117         }
2118         else
2119         {
2120             // Paste nur, wenn Text im Clipboard
2121             sal_Bool bData = sal_False;
2122             uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard();
2123             if ( xClipboard.is() )
2124             {
2125                 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
2126                 uno::Reference< datatransfer::XTransferable > xDataObj = xClipboard->getContents();
2127                 Application::AcquireSolarMutex( nRef );
2128                 if ( xDataObj.is() )
2129                 {
2130                     datatransfer::DataFlavor aFlavor;
2131                     SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
2132                     bData = xDataObj->isDataFlavorSupported( aFlavor );
2133                 }
2134             }
2135             pPopup->EnableItem( SV_MENU_EDIT_PASTE, bData );
2136         }
2137 
2138         if ( maUndoText == maText )
2139             pPopup->EnableItem( SV_MENU_EDIT_UNDO, sal_False );
2140         if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) )
2141             pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, sal_False );
2142         if ( !pImplFncGetSpecialChars )
2143         {
2144             sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL );
2145             pPopup->RemoveItem( nPos );
2146             pPopup->RemoveItem( nPos-1 );
2147         }
2148 
2149         mbActivePopup = sal_True;
2150         Selection aSaveSel = GetSelection();    // Falls jemand in Get/LoseFocus die Selektion verbiegt, z.B. URL-Zeile...
2151         Point aPos = rCEvt.GetMousePosPixel();
2152         if ( !rCEvt.IsMouseEvent() )
2153         {
2154             // !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!!
2155             Size aSize = GetOutputSizePixel();
2156             aPos = Point( aSize.Width()/2, aSize.Height()/2 );
2157         }
2158         sal_uInt16 n = pPopup->Execute( this, aPos );
2159         Edit::DeletePopupMenu( pPopup );
2160         SetSelection( aSaveSel );
2161         switch ( n )
2162         {
2163             case SV_MENU_EDIT_UNDO:
2164                 Undo();
2165                 ImplModified();
2166                 break;
2167             case SV_MENU_EDIT_CUT:
2168                 Cut();
2169                 ImplModified();
2170                 break;
2171             case SV_MENU_EDIT_COPY:
2172                 Copy();
2173                 break;
2174             case SV_MENU_EDIT_PASTE:
2175                 Paste();
2176                 ImplModified();
2177                 break;
2178             case SV_MENU_EDIT_DELETE:
2179                 DeleteSelected();
2180                 ImplModified();
2181                 break;
2182             case SV_MENU_EDIT_SELECTALL:
2183                 ImplSetSelection( Selection( 0, maText.Len() ) );
2184                 break;
2185             case SV_MENU_EDIT_INSERTSYMBOL:
2186                 {
2187                     XubString aChars = pImplFncGetSpecialChars( this, GetFont() );
2188                     SetSelection( aSaveSel );
2189                     if ( aChars.Len() )
2190                     {
2191                         ImplInsertText( aChars );
2192                         ImplModified();
2193                     }
2194                 }
2195                 break;
2196         }
2197         mbActivePopup = sal_False;
2198     }
2199     else if ( rCEvt.GetCommand() == COMMAND_VOICE )
2200     {
2201         const CommandVoiceData* pData = rCEvt.GetVoiceData();
2202         if ( pData->GetType() == VOICECOMMANDTYPE_DICTATION )
2203         {
2204             switch ( pData->GetCommand() )
2205             {
2206                 case DICTATIONCOMMAND_UNKNOWN:
2207                 {
2208                     ReplaceSelected( pData->GetText() );
2209                 }
2210                 break;
2211                 case DICTATIONCOMMAND_LEFT:
2212                 {
2213                     ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1  ) ) );
2214                 }
2215                 break;
2216                 case DICTATIONCOMMAND_RIGHT:
2217                 {
2218                     ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_RIGHT, KEY_MOD1  ) ) );
2219                 }
2220                 break;
2221                 case DICTATIONCOMMAND_UNDO:
2222                 {
2223                     Undo();
2224                 }
2225                 break;
2226                 case DICTATIONCOMMAND_DEL:
2227                 {
2228                     ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1|KEY_SHIFT  ) ) );
2229                     DeleteSelected();
2230                 }
2231                 break;
2232             }
2233         }
2234     }
2235     else if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
2236     {
2237         DeleteSelected();
2238         delete mpIMEInfos;
2239         xub_StrLen nPos = (xub_StrLen)maSelection.Max();
2240         mpIMEInfos = new Impl_IMEInfos( nPos, maText.Copy( nPos ) );
2241         mpIMEInfos->bWasCursorOverwrite = !IsInsertMode();
2242     }
2243     else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
2244     {
2245         sal_Bool bInsertMode = !mpIMEInfos->bWasCursorOverwrite;
2246         delete mpIMEInfos;
2247         mpIMEInfos = NULL;
2248         // Font wieder ohne Attribute einstellen, wird jetzt im Repaint nicht
2249         // mehr neu initialisiert
2250         ImplInitSettings( sal_True, sal_False, sal_False );
2251 
2252         SetInsertMode( bInsertMode );
2253 
2254         ImplModified();
2255 
2256         // #i25161# call auto complete handler for ext text commit also
2257         if ( maAutocompleteHdl.IsSet() )
2258         {
2259             if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) )
2260             {
2261                 meAutocompleteAction = AUTOCOMPLETE_KEYINPUT;
2262                 maAutocompleteHdl.Call( this );
2263             }
2264         }
2265     }
2266     else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
2267     {
2268         const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
2269 
2270         maText.Erase( mpIMEInfos->nPos, mpIMEInfos->nLen );
2271         maText.Insert( pData->GetText(), mpIMEInfos->nPos );
2272         if ( mpIMEInfos->bWasCursorOverwrite )
2273         {
2274             sal_uInt16 nOldIMETextLen = mpIMEInfos->nLen;
2275             sal_uInt16 nNewIMETextLen = pData->GetText().Len();
2276             if ( ( nOldIMETextLen > nNewIMETextLen ) &&
2277                  ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
2278             {
2279                 // restore old characters
2280                 sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen;
2281                 maText.Insert( mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ), mpIMEInfos->nPos + nNewIMETextLen );
2282             }
2283             else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
2284                       ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
2285             {
2286                 // overwrite
2287                 sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen;
2288                 if ( ( nOldIMETextLen + nOverwrite ) > mpIMEInfos->aOldTextAfterStartPos.Len() )
2289                     nOverwrite = mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen;
2290                 maText.Erase( mpIMEInfos->nPos + nNewIMETextLen, nOverwrite );
2291             }
2292         }
2293 
2294 
2295         if ( pData->GetTextAttr() )
2296         {
2297             mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
2298             mpIMEInfos->bCursor = pData->IsCursorVisible();
2299         }
2300         else
2301         {
2302             mpIMEInfos->DestroyAttribs();
2303         }
2304 
2305         ImplAlignAndPaint();
2306         xub_StrLen nCursorPos = mpIMEInfos->nPos + pData->GetCursorPos();
2307         SetSelection( Selection( nCursorPos, nCursorPos ) );
2308         SetInsertMode( !pData->IsCursorOverwrite() );
2309 
2310         if ( pData->IsCursorVisible() )
2311             GetCursor()->Show();
2312         else
2313             GetCursor()->Hide();
2314     }
2315     else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
2316     {
2317         if ( mpIMEInfos )
2318         {
2319             xub_StrLen nCursorPos = (sal_uInt16)GetSelection().Max();
2320             SetCursorRect( NULL, GetTextWidth(
2321                 maText, nCursorPos, mpIMEInfos->nPos+mpIMEInfos->nLen-nCursorPos ) );
2322         }
2323         else
2324         {
2325             SetCursorRect();
2326         }
2327     }
2328     else if ( rCEvt.GetCommand() == COMMAND_SELECTIONCHANGE )
2329     {
2330         const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
2331         Selection aSelection( pData->GetStart(), pData->GetEnd() );
2332         SetSelection(aSelection);
2333     }
2334     else
2335         Control::Command( rCEvt );
2336 }
2337 
2338 // -----------------------------------------------------------------------
2339 
2340 void Edit::StateChanged( StateChangedType nType )
2341 {
2342     if ( nType == STATE_CHANGE_INITSHOW )
2343     {
2344         if ( !mpSubEdit )
2345         {
2346             mnXOffset = 0;  // Falls vorher GrabFocus, als Groesse noch falsch.
2347             ImplAlign();
2348             if ( !mpSubEdit )
2349                 ImplShowCursor( sal_False );
2350         }
2351         // update background (eventual SetPaintTransparent)
2352         ImplInitSettings( sal_False, sal_False, sal_True );
2353     }
2354     else if ( nType == STATE_CHANGE_ENABLE )
2355     {
2356         if ( !mpSubEdit )
2357         {
2358             // Es aendert sich nur die Textfarbe...
2359             ImplInvalidateOrRepaint( 0, 0xFFFF );
2360         }
2361     }
2362     else if ( nType == STATE_CHANGE_STYLE || nType == STATE_CHANGE_MIRRORING )
2363     {
2364         WinBits nStyle = GetStyle();
2365         if( nType == STATE_CHANGE_STYLE )
2366         {
2367             nStyle = ImplInitStyle( GetStyle() );
2368             SetStyle( nStyle );
2369         }
2370 
2371         sal_uInt16 nOldAlign = mnAlign;
2372         mnAlign = EDIT_ALIGN_LEFT;
2373 
2374         // --- RTL --- hack: right align until keyinput and cursor travelling works
2375         // edits are always RTL disabled
2376         // however the parent edits contain the correct setting
2377         if( mbIsSubEdit && GetParent()->IsRTLEnabled() )
2378         {
2379             if( GetParent()->GetStyle() & WB_LEFT )
2380                 mnAlign = EDIT_ALIGN_RIGHT;
2381             if ( nType == STATE_CHANGE_MIRRORING )
2382                 SetLayoutMode( TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT );
2383         }
2384         else if( mbIsSubEdit && !GetParent()->IsRTLEnabled() )
2385         {
2386             if ( nType == STATE_CHANGE_MIRRORING )
2387                 SetLayoutMode( TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_TEXTORIGIN_LEFT );
2388         }
2389 
2390         if ( nStyle & WB_RIGHT )
2391             mnAlign = EDIT_ALIGN_RIGHT;
2392         else if ( nStyle & WB_CENTER )
2393             mnAlign = EDIT_ALIGN_CENTER;
2394         if ( maText.Len() && ( mnAlign != nOldAlign ) )
2395         {
2396             ImplAlign();
2397             Invalidate();
2398         }
2399 
2400     }
2401     else if ( nType == STATE_CHANGE_ZOOM )
2402     {
2403         if ( !mpSubEdit )
2404         {
2405             ImplInitSettings( sal_True, sal_False, sal_False );
2406             ImplShowCursor( sal_True );
2407             Invalidate();
2408         }
2409     }
2410     else if ( nType == STATE_CHANGE_CONTROLFONT )
2411     {
2412         if ( !mpSubEdit )
2413         {
2414             ImplInitSettings( sal_True, sal_False, sal_False );
2415             ImplShowCursor();
2416             Invalidate();
2417         }
2418     }
2419     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
2420     {
2421         if ( !mpSubEdit )
2422         {
2423             ImplInitSettings( sal_False, sal_True, sal_False );
2424             Invalidate();
2425         }
2426     }
2427     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
2428     {
2429         if ( !mpSubEdit )
2430         {
2431             ImplInitSettings( sal_False, sal_False, sal_True );
2432             Invalidate();
2433         }
2434     }
2435 
2436     Control::StateChanged( nType );
2437 }
2438 
2439 // -----------------------------------------------------------------------
2440 
2441 void Edit::DataChanged( const DataChangedEvent& rDCEvt )
2442 {
2443     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
2444          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
2445          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2446           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
2447     {
2448         if ( !mpSubEdit )
2449         {
2450             ImplInitSettings( sal_True, sal_True, sal_True );
2451             ImplShowCursor( sal_True );
2452             Invalidate();
2453         }
2454     }
2455 
2456     Control::DataChanged( rDCEvt );
2457 }
2458 
2459 // -----------------------------------------------------------------------
2460 
2461 void Edit::ImplShowDDCursor()
2462 {
2463     if ( !mpDDInfo->bVisCursor )
2464     {
2465         long nTextWidth = GetTextWidth( maText, 0, mpDDInfo->nDropPos );
2466         long nTextHeight = GetTextHeight();
2467         Rectangle aCursorRect( Point( nTextWidth + mnXOffset, (GetOutputSize().Height()-nTextHeight)/2 ), Size( 2, nTextHeight ) );
2468         mpDDInfo->aCursor.SetWindow( this );
2469         mpDDInfo->aCursor.SetPos( aCursorRect.TopLeft() );
2470         mpDDInfo->aCursor.SetSize( aCursorRect.GetSize() );
2471         mpDDInfo->aCursor.Show();
2472         mpDDInfo->bVisCursor = sal_True;
2473     }
2474 }
2475 
2476 // -----------------------------------------------------------------------
2477 
2478 void Edit::ImplHideDDCursor()
2479 {
2480     if ( mpDDInfo && mpDDInfo->bVisCursor )
2481     {
2482         mpDDInfo->aCursor.Hide();
2483         mpDDInfo->bVisCursor = sal_False;
2484     }
2485 }
2486 
2487 // -----------------------------------------------------------------------
2488 
2489 void Edit::Modify()
2490 {
2491     if ( mbIsSubEdit )
2492     {
2493         ((Edit*)GetParent())->Modify();
2494     }
2495     else
2496     {
2497         if ( mpUpdateDataTimer )
2498             mpUpdateDataTimer->Start();
2499 
2500         if ( ImplCallEventListenersAndHandler( VCLEVENT_EDIT_MODIFY, maModifyHdl, this ) )
2501             // have been destroyed while calling into the handlers
2502             return;
2503 
2504         // #i13677# notify edit listeners about caret position change
2505         ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED );
2506 
2507         // FIXME: this is currently only on aqua
2508         // check for other platforms that need similar handling
2509         if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2510             IsNativeWidgetEnabled() &&
2511             IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) )
2512         {
2513             ImplInvalidateOutermostBorder( this );
2514         }
2515     }
2516 }
2517 
2518 // -----------------------------------------------------------------------
2519 
2520 void Edit::UpdateData()
2521 {
2522     maUpdateDataHdl.Call( this );
2523 }
2524 
2525 // -----------------------------------------------------------------------
2526 
2527 IMPL_LINK( Edit, ImplUpdateDataHdl, Timer*, EMPTYARG )
2528 {
2529     UpdateData();
2530     return 0;
2531 }
2532 
2533 // -----------------------------------------------------------------------
2534 
2535 void Edit::EnableUpdateData( sal_uLong nTimeout )
2536 {
2537     if ( !nTimeout )
2538         DisableUpdateData();
2539     else
2540     {
2541         if ( !mpUpdateDataTimer )
2542         {
2543             mpUpdateDataTimer = new Timer;
2544             mpUpdateDataTimer->SetTimeoutHdl( LINK( this, Edit, ImplUpdateDataHdl ) );
2545         }
2546 
2547         mpUpdateDataTimer->SetTimeout( nTimeout );
2548     }
2549 }
2550 
2551 // -----------------------------------------------------------------------
2552 
2553 void Edit::SetEchoChar( xub_Unicode c )
2554 {
2555     mcEchoChar = c;
2556     if ( mpSubEdit )
2557         mpSubEdit->SetEchoChar( c );
2558 }
2559 
2560 // -----------------------------------------------------------------------
2561 
2562 void Edit::SetReadOnly( sal_Bool bReadOnly )
2563 {
2564     if ( mbReadOnly != bReadOnly )
2565     {
2566         mbReadOnly = bReadOnly;
2567         if ( mpSubEdit )
2568             mpSubEdit->SetReadOnly( bReadOnly );
2569 
2570         StateChanged( STATE_CHANGE_READONLY );
2571     }
2572 }
2573 
2574 // -----------------------------------------------------------------------
2575 
2576 void Edit::SetAutocompleteHdl( const Link& rHdl )
2577 {
2578     maAutocompleteHdl = rHdl;
2579     if ( mpSubEdit )
2580         mpSubEdit->SetAutocompleteHdl( rHdl );
2581 }
2582 
2583 // -----------------------------------------------------------------------
2584 
2585 void Edit::SetInsertMode( sal_Bool bInsert )
2586 {
2587     if ( bInsert != mbInsertMode )
2588     {
2589         mbInsertMode = bInsert;
2590         if ( mpSubEdit )
2591             mpSubEdit->SetInsertMode( bInsert );
2592         else
2593             ImplShowCursor();
2594     }
2595 }
2596 
2597 // -----------------------------------------------------------------------
2598 
2599 sal_Bool Edit::IsInsertMode() const
2600 {
2601     if ( mpSubEdit )
2602         return mpSubEdit->IsInsertMode();
2603     else
2604         return mbInsertMode;
2605 }
2606 
2607 // -----------------------------------------------------------------------
2608 
2609 void Edit::SetMaxTextLen( xub_StrLen nMaxLen )
2610 {
2611     mnMaxTextLen = nMaxLen ? nMaxLen : EDIT_NOLIMIT;
2612 
2613     if ( mpSubEdit )
2614         mpSubEdit->SetMaxTextLen( mnMaxTextLen );
2615     else
2616     {
2617         if ( maText.Len() > mnMaxTextLen )
2618             ImplDelete( Selection( mnMaxTextLen, maText.Len() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
2619     }
2620 }
2621 
2622 // -----------------------------------------------------------------------
2623 
2624 void Edit::SetSelection( const Selection& rSelection )
2625 {
2626     // Wenn von aussen z.B. im MouseButtonDown die Selektion geaendert wird,
2627     // soll nicht gleich ein Tracking() zuschlagen und die Selektion aendern.
2628     if ( IsTracking() )
2629         EndTracking();
2630     else if ( mpSubEdit && mpSubEdit->IsTracking() )
2631         mpSubEdit->EndTracking();
2632 
2633     ImplSetSelection( rSelection );
2634 }
2635 
2636 // -----------------------------------------------------------------------
2637 
2638 void Edit::ImplSetSelection( const Selection& rSelection, sal_Bool bPaint )
2639 {
2640     if ( mpSubEdit )
2641         mpSubEdit->ImplSetSelection( rSelection );
2642     else
2643     {
2644         if ( rSelection != maSelection )
2645         {
2646             Selection aOld( maSelection );
2647             Selection aNew( rSelection );
2648 
2649             if ( aNew.Min() > maText.Len() )
2650                 aNew.Min() = maText.Len();
2651             if ( aNew.Max() > maText.Len() )
2652                 aNew.Max() = maText.Len();
2653             if ( aNew.Min() < 0 )
2654                 aNew.Min() = 0;
2655             if ( aNew.Max() < 0 )
2656                 aNew.Max() = 0;
2657 
2658             if ( aNew != maSelection )
2659             {
2660                 ImplClearLayoutData();
2661                 maSelection = aNew;
2662 
2663                 if ( bPaint && ( aOld.Len() || aNew.Len() || IsPaintTransparent() ) )
2664                     ImplInvalidateOrRepaint( 0, maText.Len() );
2665                 ImplShowCursor();
2666                 if ( mbIsSubEdit )
2667                     ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED );
2668                 else
2669                     ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED );
2670                 // #103511# notify combobox listeners of deselection
2671                 if( !maSelection && GetParent() && GetParent()->GetType() == WINDOW_COMBOBOX )
2672                     ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_COMBOBOX_DESELECT );
2673             }
2674         }
2675     }
2676 }
2677 
2678 // -----------------------------------------------------------------------
2679 
2680 const Selection& Edit::GetSelection() const
2681 {
2682     if ( mpSubEdit )
2683         return mpSubEdit->GetSelection();
2684     else
2685         return maSelection;
2686 }
2687 
2688 // -----------------------------------------------------------------------
2689 
2690 void Edit::ReplaceSelected( const XubString& rStr )
2691 {
2692     if ( mpSubEdit )
2693         mpSubEdit->ReplaceSelected( rStr );
2694     else
2695         ImplInsertText( rStr );
2696 }
2697 
2698 // -----------------------------------------------------------------------
2699 
2700 void Edit::DeleteSelected()
2701 {
2702     if ( mpSubEdit )
2703         mpSubEdit->DeleteSelected();
2704     else
2705     {
2706         if ( maSelection.Len() )
2707             ImplDelete( maSelection, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
2708     }
2709 }
2710 
2711 // -----------------------------------------------------------------------
2712 
2713 XubString Edit::GetSelected() const
2714 {
2715     if ( mpSubEdit )
2716         return mpSubEdit->GetSelected();
2717     else
2718     {
2719         Selection aSelection( maSelection );
2720         aSelection.Justify();
2721         return maText.Copy( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() );
2722     }
2723 }
2724 
2725 // -----------------------------------------------------------------------
2726 
2727 void Edit::Cut()
2728 {
2729     if ( !(GetStyle() & WB_PASSWORD ) )
2730     {
2731         Copy();
2732         ReplaceSelected( ImplGetSVEmptyStr() );
2733     }
2734 }
2735 
2736 // -----------------------------------------------------------------------
2737 
2738 void Edit::Copy()
2739 {
2740     if ( !(GetStyle() & WB_PASSWORD ) )
2741     {
2742         ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipboard(GetClipboard());
2743         ImplCopy( aClipboard );
2744     }
2745 }
2746 
2747 // -----------------------------------------------------------------------
2748 
2749 void Edit::Paste()
2750 {
2751         ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipboard(GetClipboard());
2752     ImplPaste( aClipboard );
2753 }
2754 
2755 // -----------------------------------------------------------------------
2756 
2757 void Edit::Undo()
2758 {
2759     if ( mpSubEdit )
2760         mpSubEdit->Undo();
2761     else
2762     {
2763         XubString aText( maText );
2764         ImplDelete( Selection( 0, aText.Len() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
2765         ImplInsertText( maUndoText );
2766         ImplSetSelection( Selection( 0, maUndoText.Len() ) );
2767         maUndoText = aText;
2768     }
2769 }
2770 
2771 // -----------------------------------------------------------------------
2772 
2773 void Edit::SetText( const XubString& rStr )
2774 {
2775     if ( mpSubEdit )
2776         mpSubEdit->SetText( rStr );     // Nicht direkt ImplSetText, falls SetText ueberladen
2777     else
2778     {
2779         Selection aNewSel( 0, 0 );  // Damit nicht gescrollt wird
2780         ImplSetText( rStr, &aNewSel );
2781     }
2782 }
2783 
2784 // -----------------------------------------------------------------------
2785 
2786 void Edit::SetText( const XubString& rStr, const Selection& rSelection )
2787 {
2788     if ( mpSubEdit )
2789         mpSubEdit->SetText( rStr, rSelection );
2790     else
2791         ImplSetText( rStr, &rSelection );
2792 }
2793 
2794 // -----------------------------------------------------------------------
2795 
2796 XubString Edit::GetText() const
2797 {
2798     if ( mpSubEdit )
2799         return mpSubEdit->GetText();
2800     else
2801         return maText;
2802 }
2803 
2804 // -----------------------------------------------------------------------
2805 
2806 void Edit::SetModifyFlag()
2807 {
2808     if ( mpSubEdit )
2809         mpSubEdit->mbModified = sal_True;
2810     else
2811         mbModified = sal_True;
2812 }
2813 
2814 // -----------------------------------------------------------------------
2815 
2816 void Edit::ClearModifyFlag()
2817 {
2818     if ( mpSubEdit )
2819         mpSubEdit->mbModified = sal_False;
2820     else
2821         mbModified = sal_False;
2822 }
2823 
2824 // -----------------------------------------------------------------------
2825 
2826 void Edit::SetSubEdit( Edit* pEdit )
2827 {
2828     mpSubEdit = pEdit;
2829     if ( mpSubEdit )
2830     {
2831         SetPointer( POINTER_ARROW );    // Nur das SubEdit hat den BEAM...
2832         mpSubEdit->mbIsSubEdit = sal_True;
2833 
2834         mpSubEdit->SetReadOnly( mbReadOnly );
2835     }
2836 }
2837 
2838 // -----------------------------------------------------------------------
2839 
2840 Size Edit::CalcMinimumSize() const
2841 {
2842     Size aSize ( GetTextWidth( GetText() ), GetTextHeight() );
2843     // do not create edit fields in which one cannot enter anything
2844     // a default minimum width should exist for at least 3 characters
2845     Size aMinSize ( CalcSize( 3 ) );
2846     if( aSize.Width() < aMinSize.Width() )
2847         aSize.Width() = aMinSize.Width();
2848     // add some space between text entry and border
2849     aSize.Height() += 4;
2850 
2851     aSize = CalcWindowSize( aSize );
2852 
2853     // ask NWF what if it has an opinion, too
2854     ImplControlValue aControlValue;
2855     Rectangle aRect( Point( 0, 0 ), aSize );
2856     Rectangle aContent, aBound;
2857     if( const_cast<Edit*>(this)->GetNativeControlRegion(
2858                    CTRL_EDITBOX, PART_ENTIRE_CONTROL,
2859                    aRect, 0, aControlValue, rtl::OUString(), aBound, aContent) )
2860     {
2861         if( aBound.GetHeight() > aSize.Height() )
2862             aSize.Height() = aBound.GetHeight();
2863     }
2864     return aSize;
2865 }
2866 
2867 Size Edit::GetMinimumEditSize()
2868 {
2869     Window* pDefWin = ImplGetDefaultWindow();
2870     Edit aEdit( pDefWin, WB_BORDER );
2871     Size aSize( aEdit.CalcMinimumSize() );
2872     return aSize;
2873 }
2874 
2875 // -----------------------------------------------------------------------
2876 
2877 Size Edit::GetOptimalSize(WindowSizeType eType) const
2878 {
2879     switch (eType) {
2880     case WINDOWSIZE_MINIMUM:
2881         return CalcMinimumSize();
2882     default:
2883         return Control::GetOptimalSize( eType );
2884     }
2885 }
2886 
2887 // -----------------------------------------------------------------------
2888 
2889 Size Edit::CalcSize( xub_StrLen nChars ) const
2890 {
2891     // Breite fuer n Zeichen, unabhaengig vom Inhalt.
2892     // Funktioniert nur bei FixedFont richtig, sonst Mittelwert.
2893     Size aSz( GetTextWidth( XubString( 'x' ) ), GetTextHeight() );
2894     aSz.Width() *= nChars;
2895     aSz = CalcWindowSize( aSz );
2896     return aSz;
2897 }
2898 
2899 // -----------------------------------------------------------------------
2900 
2901 xub_StrLen Edit::GetMaxVisChars() const
2902 {
2903     const Window* pW = mpSubEdit ? mpSubEdit : this;
2904     long nOutWidth = pW->GetOutputSizePixel().Width();
2905     long nCharWidth = GetTextWidth( XubString( 'x' ) );
2906     return nCharWidth ? (xub_StrLen)(nOutWidth/nCharWidth) : 0;
2907 }
2908 
2909 // -----------------------------------------------------------------------
2910 
2911 xub_StrLen Edit::GetCharPos( const Point& rWindowPos ) const
2912 {
2913     return ImplGetCharPos( rWindowPos );
2914 }
2915 
2916 // -----------------------------------------------------------------------
2917 
2918 void Edit::SetGetSpecialCharsFunction( FncGetSpecialChars fn )
2919 {
2920     pImplFncGetSpecialChars = fn;
2921 }
2922 
2923 // -----------------------------------------------------------------------
2924 
2925 FncGetSpecialChars Edit::GetGetSpecialCharsFunction()
2926 {
2927     return pImplFncGetSpecialChars;
2928 }
2929 
2930 // -----------------------------------------------------------------------
2931 
2932 PopupMenu* Edit::CreatePopupMenu()
2933 {
2934     ResMgr* pResMgr = ImplGetResMgr();
2935     if( ! pResMgr )
2936         return new PopupMenu();
2937 
2938     PopupMenu* pPopup = new PopupMenu( ResId( SV_RESID_MENU_EDIT, *pResMgr ) );
2939     pPopup->SetAccelKey( SV_MENU_EDIT_UNDO, KeyCode( KEYFUNC_UNDO ) );
2940     pPopup->SetAccelKey( SV_MENU_EDIT_CUT, KeyCode( KEYFUNC_CUT ) );
2941     pPopup->SetAccelKey( SV_MENU_EDIT_COPY, KeyCode( KEYFUNC_COPY ) );
2942     pPopup->SetAccelKey( SV_MENU_EDIT_PASTE, KeyCode( KEYFUNC_PASTE ) );
2943     pPopup->SetAccelKey( SV_MENU_EDIT_DELETE, KeyCode( KEYFUNC_DELETE ) );
2944     pPopup->SetAccelKey( SV_MENU_EDIT_SELECTALL, KeyCode( KEY_A, sal_False, sal_True, sal_False, sal_False ) );
2945     pPopup->SetAccelKey( SV_MENU_EDIT_INSERTSYMBOL, KeyCode( KEY_S, sal_True, sal_True, sal_False, sal_False ) );
2946     return pPopup;
2947 }
2948 
2949 // -----------------------------------------------------------------------
2950 
2951 void Edit::DeletePopupMenu( PopupMenu* pMenu )
2952 {
2953     delete pMenu;
2954 }
2955 
2956 // ::com::sun::star::datatransfer::dnd::XDragGestureListener
2957 void Edit::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
2958 {
2959     vos::OGuard aVclGuard( Application::GetSolarMutex() );
2960 
2961     if ( !IsTracking() && maSelection.Len() &&
2962          !(GetStyle() & WB_PASSWORD) && (!mpDDInfo || mpDDInfo->bStarterOfDD == sal_False) ) // Kein Mehrfach D&D
2963     {
2964         Selection aSel( maSelection );
2965         aSel.Justify();
2966 
2967         // Nur wenn Maus in der Selektion...
2968         Point aMousePos( rDGE.DragOriginX, rDGE.DragOriginY );
2969         xub_StrLen nChar = ImplGetCharPos( aMousePos );
2970         if ( (nChar >= aSel.Min()) && (nChar < aSel.Max()) )
2971         {
2972             if ( !mpDDInfo )
2973                 mpDDInfo = new DDInfo;
2974 
2975             mpDDInfo->bStarterOfDD = sal_True;
2976             mpDDInfo->aDndStartSel = aSel;
2977 
2978 
2979             if ( IsTracking() )
2980                 EndTracking();  // Vor D&D Tracking ausschalten
2981 
2982             ::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( GetSelected() );
2983             sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
2984             if ( !IsReadOnly() )
2985                 nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
2986             rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mxDnDListener );
2987             if ( GetCursor() )
2988                 GetCursor()->Hide();
2989 
2990         }
2991     }
2992 }
2993 
2994 // ::com::sun::star::datatransfer::dnd::XDragSourceListener
2995 void Edit::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& rDSDE ) throw (::com::sun::star::uno::RuntimeException)
2996 {
2997     vos::OGuard aVclGuard( Application::GetSolarMutex() );
2998 
2999     if ( rDSDE.DropSuccess && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) )
3000     {
3001         Selection aSel( mpDDInfo->aDndStartSel );
3002         if ( mpDDInfo->bDroppedInMe )
3003         {
3004             if ( aSel.Max() > mpDDInfo->nDropPos )
3005             {
3006                 long nLen = aSel.Len();
3007                 aSel.Min() += nLen;
3008                 aSel.Max() += nLen;
3009             }
3010         }
3011         ImplDelete( aSel, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
3012         ImplModified();
3013     }
3014 
3015     ImplHideDDCursor();
3016     delete mpDDInfo;
3017     mpDDInfo = NULL;
3018 }
3019 
3020 // ::com::sun::star::datatransfer::dnd::XDropTargetListener
3021 void Edit::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
3022 {
3023     vos::OGuard aVclGuard( Application::GetSolarMutex() );
3024 
3025     sal_Bool bChanges = sal_False;
3026     if ( !mbReadOnly && mpDDInfo )
3027     {
3028         ImplHideDDCursor();
3029 
3030         Selection aSel( maSelection );
3031         aSel.Justify();
3032 
3033         if ( aSel.Len() && !mpDDInfo->bStarterOfDD )
3034             ImplDelete( aSel, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE );
3035 
3036         mpDDInfo->bDroppedInMe = sal_True;
3037 
3038         aSel.Min() = mpDDInfo->nDropPos;
3039         aSel.Max() = mpDDInfo->nDropPos;
3040         ImplSetSelection( aSel );
3041 
3042         uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
3043         if ( xDataObj.is() )
3044         {
3045             datatransfer::DataFlavor aFlavor;
3046             SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
3047             if ( xDataObj->isDataFlavorSupported( aFlavor ) )
3048             {
3049                 uno::Any aData = xDataObj->getTransferData( aFlavor );
3050                 ::rtl::OUString aText;
3051                 aData >>= aText;
3052                 ImplInsertText( aText );
3053                 bChanges = sal_True;
3054                 ImplModified();
3055             }
3056         }
3057 
3058         if ( !mpDDInfo->bStarterOfDD )
3059         {
3060             delete mpDDInfo;
3061             mpDDInfo = NULL;
3062         }
3063     }
3064 
3065     rDTDE.Context->dropComplete( bChanges );
3066 }
3067 
3068 void Edit::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
3069 {
3070     if ( !mpDDInfo )
3071     {
3072         mpDDInfo = new DDInfo;
3073     }
3074     // search for string data type
3075     const Sequence< com::sun::star::datatransfer::DataFlavor >& rFlavors( rDTDE.SupportedDataFlavors );
3076     sal_Int32 nEle = rFlavors.getLength();
3077     mpDDInfo->bIsStringSupported = sal_False;
3078     for( sal_Int32 i = 0; i < nEle; i++ )
3079     {
3080         sal_Int32 nIndex = 0;
3081         rtl::OUString aMimetype = rFlavors[i].MimeType.getToken( 0, ';', nIndex );
3082         if( aMimetype.equalsAscii( "text/plain" ) )
3083         {
3084             mpDDInfo->bIsStringSupported = sal_True;
3085             break;
3086         }
3087     }
3088 }
3089 
3090 void Edit::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
3091 {
3092     vos::OGuard aVclGuard( Application::GetSolarMutex() );
3093 
3094     ImplHideDDCursor();
3095 }
3096 
3097 void Edit::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
3098 {
3099     vos::OGuard aVclGuard( Application::GetSolarMutex() );
3100 
3101     Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
3102 
3103     xub_StrLen nPrevDropPos = mpDDInfo->nDropPos;
3104     mpDDInfo->nDropPos = ImplGetCharPos( aMousePos );
3105 
3106     /*
3107     Size aOutSize = GetOutputSizePixel();
3108     if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) )
3109     {
3110         // Scroll?
3111         // No, I will not receive events in this case....
3112     }
3113     */
3114 
3115     Selection aSel( maSelection );
3116     aSel.Justify();
3117 
3118     // Don't accept drop in selection or read-only field...
3119     if ( IsReadOnly() || aSel.IsInside( mpDDInfo->nDropPos ) || ! mpDDInfo->bIsStringSupported )
3120     {
3121         ImplHideDDCursor();
3122         rDTDE.Context->rejectDrag();
3123     }
3124     else
3125     {
3126         // Alten Cursor wegzeichnen...
3127         if ( !mpDDInfo->bVisCursor || ( nPrevDropPos != mpDDInfo->nDropPos ) )
3128         {
3129             ImplHideDDCursor();
3130             ImplShowDDCursor();
3131         }
3132         rDTDE.Context->acceptDrag( rDTDE.DropAction );
3133     }
3134 }
3135 
3136 ImplSubEdit::ImplSubEdit( Edit* pParent, WinBits nStyle ) :
3137     Edit( pParent, nStyle )
3138 {
3139     pParent->SetSubEdit( this );
3140 }
3141 
3142 // -----------------------------------------------------------------------
3143 
3144 void ImplSubEdit::Modify()
3145 {
3146     GetParent()->Modify();
3147 }
3148 
3149 XubString Edit::GetSurroundingText() const
3150 {
3151   if ( mpSubEdit )
3152     return mpSubEdit->GetSurroundingText();
3153   else
3154     return maText;
3155 }
3156 
3157 Selection Edit::GetSurroundingTextSelection() const
3158 {
3159   return GetSelection();
3160 }
3161