xref: /AOO41X/main/vcl/source/control/edit.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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