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