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