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