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