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