| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <tools/rc.h> |
| #include <vcl/decoview.hxx> |
| #include <vcl/event.hxx> |
| #include <vcl/cursor.hxx> |
| #include <vcl/virdev.hxx> |
| #include <vcl/menu.hxx> |
| #include <vcl/cmdevt.h> |
| #include <vcl/edit.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/msgbox.hxx> |
| |
| #include <window.h> |
| #include <svdata.hxx> |
| #include <svids.hrc> |
| #include <subedit.hxx> |
| #include <controldata.hxx> |
| |
| #include <vos/mutex.hxx> |
| |
| |
| #include <com/sun/star/i18n/XBreakIterator.hpp> |
| #include <com/sun/star/i18n/CharacterIteratorMode.hpp> |
| #include <com/sun/star/i18n/WordType.hpp> |
| #include <cppuhelper/weak.hxx> |
| #include <com/sun/star/datatransfer/XTransferable.hpp> |
| #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| |
| #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANS_HPP_ |
| #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> |
| #endif |
| #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp> |
| #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> |
| |
| #ifndef _COM_SUN_STAR_I18N_XEXTENDEDINPUTSEQUENCECHECKER_HDL_ |
| #include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp> |
| #endif |
| #include <com/sun/star/i18n/InputSequenceCheckMode.hpp> |
| #include <com/sun/star/i18n/ScriptType.hpp> |
| #include <com/sun/star/container/XNameAccess.hpp> |
| |
| #include <com/sun/star/uno/Any.hxx> |
| |
| #include <comphelper/processfactory.hxx> |
| #include <comphelper/configurationhelper.hxx> |
| |
| #include <sot/exchange.hxx> |
| #include <sot/formats.hxx> |
| #include <rtl/memory.h> |
| |
| #include <vcl/unohelp.hxx> |
| #include <vcl/unohelp2.hxx> |
| |
| |
| |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::lang; |
| using namespace ::rtl; |
| |
| // - Redo |
| // - Bei Tracking-Cancel DefaultSelection wieder herstellen |
| |
| // ======================================================================= |
| |
| static FncGetSpecialChars pImplFncGetSpecialChars = NULL; |
| |
| // ======================================================================= |
| |
| #define EDIT_ALIGN_LEFT 1 |
| #define EDIT_ALIGN_CENTER 2 |
| #define EDIT_ALIGN_RIGHT 3 |
| |
| #define EDIT_DEL_LEFT 1 |
| #define EDIT_DEL_RIGHT 2 |
| |
| #define EDIT_DELMODE_SIMPLE 11 |
| #define EDIT_DELMODE_RESTOFWORD 12 |
| #define EDIT_DELMODE_RESTOFCONTENT 13 |
| |
| // ======================================================================= |
| |
| struct DDInfo |
| { |
| Cursor aCursor; |
| Selection aDndStartSel; |
| xub_StrLen nDropPos; |
| sal_Bool bStarterOfDD; |
| sal_Bool bDroppedInMe; |
| sal_Bool bVisCursor; |
| sal_Bool bIsStringSupported; |
| |
| DDInfo() |
| { |
| aCursor.SetStyle( CURSOR_SHADOW ); |
| nDropPos = 0; |
| bStarterOfDD = sal_False; |
| bDroppedInMe = sal_False; |
| bVisCursor = sal_False; |
| bIsStringSupported = sal_False; |
| } |
| }; |
| |
| // ======================================================================= |
| |
| struct Impl_IMEInfos |
| { |
| String aOldTextAfterStartPos; |
| sal_uInt16* pAttribs; |
| xub_StrLen nPos; |
| xub_StrLen nLen; |
| sal_Bool bCursor; |
| sal_Bool bWasCursorOverwrite; |
| |
| Impl_IMEInfos( xub_StrLen nPos, const String& rOldTextAfterStartPos ); |
| ~Impl_IMEInfos(); |
| |
| void CopyAttribs( const xub_StrLen* pA, xub_StrLen nL ); |
| void DestroyAttribs(); |
| }; |
| |
| // ----------------------------------------------------------------------- |
| |
| Impl_IMEInfos::Impl_IMEInfos( xub_StrLen nP, const String& rOldTextAfterStartPos ) |
| : aOldTextAfterStartPos( rOldTextAfterStartPos ) |
| { |
| nPos = nP; |
| nLen = 0; |
| bCursor = sal_True; |
| pAttribs = NULL; |
| bWasCursorOverwrite = sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Impl_IMEInfos::~Impl_IMEInfos() |
| { |
| delete[] pAttribs; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Impl_IMEInfos::CopyAttribs( const xub_StrLen* pA, xub_StrLen nL ) |
| { |
| nLen = nL; |
| delete[] pAttribs; |
| pAttribs = new sal_uInt16[ nL ]; |
| rtl_copyMemory( pAttribs, pA, nL*sizeof(sal_uInt16) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Impl_IMEInfos::DestroyAttribs() |
| { |
| delete[] pAttribs; |
| pAttribs = NULL; |
| nLen = 0; |
| } |
| |
| // ======================================================================= |
| |
| Edit::Edit( WindowType nType ) : |
| Control( nType ) |
| { |
| ImplInitEditData(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Edit::Edit( Window* pParent, WinBits nStyle ) : |
| Control( WINDOW_EDIT ) |
| { |
| ImplInitEditData(); |
| ImplInit( pParent, nStyle ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Edit::Edit( Window* pParent, const ResId& rResId ) : |
| Control( WINDOW_EDIT ) |
| { |
| ImplInitEditData(); |
| rResId.SetRT( RSC_EDIT ); |
| WinBits nStyle = ImplInitRes( rResId ); |
| ImplInit( pParent, nStyle ); |
| ImplLoadRes( rResId ); |
| |
| // Derived MultiLineEdit takes care to call Show only after MultiLineEdit |
| // ctor has already started: |
| if ( !(nStyle & WB_HIDE) && rResId.GetRT() != RSC_MULTILINEEDIT ) |
| Show(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Edit::Edit( Window* pParent, const ResId& rResId, bool bDisableAccessibleLabeledByRelation ) : |
| Control( WINDOW_EDIT ) |
| { |
| ImplInitEditData(); |
| rResId.SetRT( RSC_EDIT ); |
| WinBits nStyle = ImplInitRes( rResId ); |
| ImplInit( pParent, nStyle ); |
| ImplLoadRes( rResId ); |
| if ( bDisableAccessibleLabeledByRelation ) |
| ImplGetWindowImpl()->mbDisableAccessibleLabeledByRelation = sal_True; |
| |
| // Derived MultiLineEdit takes care to call Show only after MultiLineEdit |
| // ctor has already started: |
| if ( !(nStyle & WB_HIDE) && rResId.GetRT() != RSC_MULTILINEEDIT ) |
| Show(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Edit::~Edit() |
| { |
| delete mpDDInfo; |
| Cursor* pCursor = GetCursor(); |
| if ( pCursor ) |
| { |
| SetCursor( NULL ); |
| delete pCursor; |
| } |
| |
| delete mpIMEInfos; |
| |
| if ( mpUpdateDataTimer ) |
| delete mpUpdateDataTimer; |
| |
| if ( mxDnDListener.is() ) |
| { |
| if ( GetDragGestureRecognizer().is() ) |
| { |
| uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY ); |
| GetDragGestureRecognizer()->removeDragGestureListener( xDGL ); |
| } |
| if ( GetDropTarget().is() ) |
| { |
| uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( mxDnDListener, uno::UNO_QUERY ); |
| GetDropTarget()->removeDropTargetListener( xDTL ); |
| } |
| |
| uno::Reference< lang::XEventListener> xEL( mxDnDListener, uno::UNO_QUERY ); |
| xEL->disposing( lang::EventObject() ); // #95154# #96585# Empty Source means it's the Client |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplInitEditData() |
| { |
| mpSubEdit = NULL; |
| mpUpdateDataTimer = NULL; |
| mnXOffset = 0; |
| mnAlign = EDIT_ALIGN_LEFT; |
| mnMaxTextLen = EDIT_NOLIMIT; |
| meAutocompleteAction = AUTOCOMPLETE_KEYINPUT; |
| mbModified = sal_False; |
| mbInternModified = sal_False; |
| mbReadOnly = sal_False; |
| mbInsertMode = sal_True; |
| mbClickedInSelection = sal_False; |
| mbActivePopup = sal_False; |
| mbIsSubEdit = sal_False; |
| mbInMBDown = sal_False; |
| mpDDInfo = NULL; |
| mpIMEInfos = NULL; |
| mcEchoChar = 0; |
| |
| // --- RTL --- no default mirroring for Edit controls |
| // note: controls that use a subedit will revert this (SpinField, ComboBox) |
| EnableRTL( sal_False ); |
| |
| vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this ); |
| mxDnDListener = pDnDWrapper; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| bool Edit::ImplUseNativeBorder( WinBits nStyle ) |
| { |
| bool bRet = |
| IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE) |
| && ((nStyle&WB_BORDER) && !(nStyle&WB_NOBORDER)); |
| if( ! bRet && mbIsSubEdit ) |
| { |
| Window* pWindow = GetParent(); |
| nStyle = pWindow->GetStyle(); |
| bRet = pWindow->IsNativeControlSupported(ImplGetNativeControlType(), HAS_BACKGROUND_TEXTURE) |
| && ((nStyle&WB_BORDER) && !(nStyle&WB_NOBORDER)); |
| } |
| return bRet; |
| } |
| |
| void Edit::ImplInit( Window* pParent, WinBits nStyle ) |
| { |
| nStyle = ImplInitStyle( nStyle ); |
| if ( !(nStyle & (WB_CENTER | WB_RIGHT)) ) |
| nStyle |= WB_LEFT; |
| |
| Control::ImplInit( pParent, nStyle, NULL ); |
| |
| mbReadOnly = (nStyle & WB_READONLY) != 0; |
| |
| mnAlign = EDIT_ALIGN_LEFT; |
| |
| // --- RTL --- hack: right align until keyinput and cursor travelling works |
| if( IsRTLEnabled() ) |
| mnAlign = EDIT_ALIGN_RIGHT; |
| |
| if ( nStyle & WB_RIGHT ) |
| mnAlign = EDIT_ALIGN_RIGHT; |
| else if ( nStyle & WB_CENTER ) |
| mnAlign = EDIT_ALIGN_CENTER; |
| |
| SetCursor( new Cursor ); |
| |
| SetPointer( Pointer( POINTER_TEXT ) ); |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| |
| uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY ); |
| uno::Reference< datatransfer::dnd::XDragGestureRecognizer > xDGR = GetDragGestureRecognizer(); |
| if ( xDGR.is() ) |
| { |
| xDGR->addDragGestureListener( xDGL ); |
| uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( mxDnDListener, uno::UNO_QUERY ); |
| GetDropTarget()->addDropTargetListener( xDTL ); |
| GetDropTarget()->setActive( sal_True ); |
| GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| WinBits Edit::ImplInitStyle( WinBits nStyle ) |
| { |
| if ( !(nStyle & WB_NOTABSTOP) ) |
| nStyle |= WB_TABSTOP; |
| if ( !(nStyle & WB_NOGROUP) ) |
| nStyle |= WB_GROUP; |
| |
| return nStyle; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool Edit::IsCharInput( const KeyEvent& rKeyEvent ) |
| { |
| // In the future we must use new Unicode functions for this |
| xub_Unicode cCharCode = rKeyEvent.GetCharCode(); |
| return ((cCharCode >= 32) && (cCharCode != 127) && |
| !rKeyEvent.GetKeyCode().IsMod3() && |
| !rKeyEvent.GetKeyCode().IsMod2() && |
| !rKeyEvent.GetKeyCode().IsMod1() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplModified() |
| { |
| mbModified = sal_True; |
| Modify(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ) |
| { |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| |
| if ( bFont ) |
| { |
| Font aFont = rStyleSettings.GetFieldFont(); |
| if ( IsControlFont() ) |
| aFont.Merge( GetControlFont() ); |
| SetZoomedPointFont( aFont ); |
| ImplClearLayoutData(); |
| } |
| |
| if ( bFont || bForeground ) |
| { |
| Color aTextColor = rStyleSettings.GetFieldTextColor(); |
| if ( IsControlForeground() ) |
| aTextColor = GetControlForeground(); |
| SetTextColor( aTextColor ); |
| } |
| |
| if ( bBackground ) |
| { |
| if ( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() ) |
| { |
| // Transparent background |
| SetBackground(); |
| SetFillColor(); |
| } |
| else if ( IsControlBackground() ) |
| { |
| SetBackground( GetControlBackground() ); |
| SetFillColor( GetControlBackground() ); |
| } |
| else |
| { |
| SetBackground( rStyleSettings.GetFieldColor() ); |
| SetFillColor( rStyleSettings.GetFieldColor() ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long Edit::ImplGetExtraOffset() const |
| { |
| // MT 09/2002: nExtraOffsetX should become a member, instead of checking every time, |
| // but I need an incompatible update for this... |
| // #94095# Use extra offset only when edit has a border |
| long nExtraOffset = 0; |
| if( ( GetStyle() & WB_BORDER ) || ( mbIsSubEdit && ( GetParent()->GetStyle() & WB_BORDER ) ) ) |
| nExtraOffset = 2; |
| |
| return nExtraOffset; |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString Edit::ImplGetText() const |
| { |
| if ( mcEchoChar || (GetStyle() & WB_PASSWORD) ) |
| { |
| XubString aText; |
| xub_Unicode cEchoChar; |
| if ( mcEchoChar ) |
| cEchoChar = mcEchoChar; |
| else |
| cEchoChar = '*'; |
| aText.Fill( maText.Len(), cEchoChar ); |
| return aText; |
| } |
| else |
| return maText; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplInvalidateOrRepaint( xub_StrLen nStart, xub_StrLen nEnd ) |
| { |
| if( IsPaintTransparent() ) |
| { |
| Invalidate(); |
| // FIXME: this is currently only on aqua |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects ) |
| Update(); |
| } |
| else |
| ImplRepaint( nStart, nEnd ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long Edit::ImplGetTextYPosition() const |
| { |
| if ( GetStyle() & WB_TOP ) |
| return ImplGetExtraOffset(); |
| else if ( GetStyle() & WB_BOTTOM ) |
| return GetOutputSizePixel().Height() - GetTextHeight() - ImplGetExtraOffset(); |
| return ( GetOutputSizePixel().Height() - GetTextHeight() ) / 2; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplRepaint( xub_StrLen nStart, xub_StrLen nEnd, bool bLayout ) |
| { |
| if ( !IsReallyVisible() ) |
| return; |
| |
| XubString aText = ImplGetText(); |
| nStart = 0; |
| nEnd = aText.Len(); |
| |
| sal_Int32 nDXBuffer[256]; |
| sal_Int32* pDXBuffer = NULL; |
| sal_Int32* pDX = nDXBuffer; |
| |
| if( aText.Len() ) |
| { |
| if( 2*aText.Len() > xub_StrLen(sizeof(nDXBuffer)/sizeof(nDXBuffer[0])) ) |
| { |
| pDXBuffer = new sal_Int32[2*(aText.Len()+1)]; |
| pDX = pDXBuffer; |
| } |
| |
| GetCaretPositions( aText, pDX, nStart, nEnd ); |
| } |
| |
| long nTH = GetTextHeight(); |
| Point aPos( mnXOffset, ImplGetTextYPosition() ); |
| |
| if( bLayout ) |
| { |
| long nPos = nStart ? pDX[2*nStart] : 0; |
| aPos.X() = nPos + mnXOffset + ImplGetExtraOffset(); |
| |
| MetricVector* pVector = &mpControlData->mpLayoutData->m_aUnicodeBoundRects; |
| String* pDisplayText = &mpControlData->mpLayoutData->m_aDisplayText; |
| |
| DrawText( aPos, aText, nStart, nEnd - nStart, pVector, pDisplayText ); |
| |
| if( pDXBuffer ) |
| delete [] pDXBuffer; |
| return; |
| } |
| |
| Cursor* pCursor = GetCursor(); |
| sal_Bool bVisCursor = pCursor ? pCursor->IsVisible() : sal_False; |
| if ( pCursor ) |
| pCursor->Hide(); |
| |
| ImplClearBackground( 0, GetOutputSizePixel().Width() ); |
| |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| if ( IsEnabled() ) |
| ImplInitSettings( sal_False, sal_True, sal_False ); |
| else |
| SetTextColor( rStyleSettings.GetDisableColor() ); |
| |
| // Set background color of the normal text |
| if( (GetStyle() & WB_FORCECTRLBACKGROUND) != 0 && IsControlBackground() ) |
| { |
| // check if we need to set ControlBackground even in NWF case |
| Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); |
| SetLineColor(); |
| SetFillColor( GetControlBackground() ); |
| DrawRect( Rectangle( aPos, Size( GetOutputSizePixel().Width() - 2*mnXOffset, nTH ) ) ); |
| Pop(); |
| |
| SetTextFillColor( GetControlBackground() ); |
| } |
| else if( IsPaintTransparent() || ImplUseNativeBorder( GetStyle() ) ) |
| SetTextFillColor(); |
| else |
| SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() ); |
| |
| sal_Bool bDrawSelection = maSelection.Len() && ( HasFocus() || ( GetStyle() & WB_NOHIDESELECTION ) || mbActivePopup ); |
| |
| long nPos = nStart ? pDX[2*nStart] : 0; |
| aPos.X() = nPos + mnXOffset + ImplGetExtraOffset(); |
| if ( !bDrawSelection && !mpIMEInfos ) |
| { |
| DrawText( aPos, aText, nStart, nEnd - nStart ); |
| } |
| else |
| { |
| // save graphics state |
| Push(); |
| // first calculate higlighted and non highlighted clip regions |
| Region aHiglightClipRegion; |
| Region aNormalClipRegion; |
| Selection aTmpSel( maSelection ); |
| aTmpSel.Justify(); |
| // selection is highlighted |
| int i; |
| for( i = 0; i < aText.Len(); i++ ) |
| { |
| Rectangle aRect( aPos, Size( 10, nTH ) ); |
| aRect.Left() = pDX[2*i] + mnXOffset + ImplGetExtraOffset(); |
| aRect.Right() = pDX[2*i+1] + mnXOffset + ImplGetExtraOffset(); |
| aRect.Justify(); |
| bool bHighlight = false; |
| if( i >= aTmpSel.Min() && i < aTmpSel.Max() ) |
| bHighlight = true; |
| |
| if( mpIMEInfos && mpIMEInfos->pAttribs && |
| i >= mpIMEInfos->nPos && i < (mpIMEInfos->nPos+mpIMEInfos->nLen ) && |
| ( mpIMEInfos->pAttribs[i-mpIMEInfos->nPos] & EXTTEXTINPUT_ATTR_HIGHLIGHT) ) |
| bHighlight = true; |
| |
| if( bHighlight ) |
| aHiglightClipRegion.Union( aRect ); |
| else |
| aNormalClipRegion.Union( aRect ); |
| } |
| // draw normal text |
| Color aNormalTextColor = GetTextColor(); |
| SetClipRegion( aNormalClipRegion ); |
| |
| if( IsPaintTransparent() ) |
| SetTextFillColor(); |
| else |
| { |
| // Set background color when part of the text is selected |
| if ( ImplUseNativeBorder( GetStyle() ) ) |
| { |
| if( (GetStyle() & WB_FORCECTRLBACKGROUND) != 0 && IsControlBackground() ) |
| SetTextFillColor( GetControlBackground() ); |
| else |
| SetTextFillColor(); |
| } |
| else |
| SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() ); |
| } |
| DrawText( aPos, aText, nStart, nEnd - nStart ); |
| |
| // draw highlighted text |
| SetClipRegion( aHiglightClipRegion ); |
| SetTextColor( rStyleSettings.GetHighlightTextColor() ); |
| SetTextFillColor( rStyleSettings.GetHighlightColor() ); |
| DrawText( aPos, aText, nStart, nEnd - nStart ); |
| |
| // if IME info exists loop over portions and output different font attributes |
| if( mpIMEInfos && mpIMEInfos->pAttribs ) |
| { |
| for( int n = 0; n < 2; n++ ) |
| { |
| Region aRegion; |
| if( n == 0 ) |
| { |
| SetTextColor( aNormalTextColor ); |
| if( IsPaintTransparent() ) |
| SetTextFillColor(); |
| else |
| SetTextFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() ); |
| aRegion = aNormalClipRegion; |
| } |
| else |
| { |
| SetTextColor( rStyleSettings.GetHighlightTextColor() ); |
| SetTextFillColor( rStyleSettings.GetHighlightColor() ); |
| aRegion = aHiglightClipRegion; |
| } |
| |
| for( i = 0; i < mpIMEInfos->nLen; ) |
| { |
| sal_uInt16 nAttr = mpIMEInfos->pAttribs[i]; |
| Region aClip; |
| int nIndex = i; |
| while( nIndex < mpIMEInfos->nLen && mpIMEInfos->pAttribs[nIndex] == nAttr) // #112631# check nIndex before using it |
| { |
| Rectangle aRect( aPos, Size( 10, nTH ) ); |
| aRect.Left() = pDX[2*(nIndex+mpIMEInfos->nPos)] + mnXOffset + ImplGetExtraOffset(); |
| aRect.Right() = pDX[2*(nIndex+mpIMEInfos->nPos)+1] + mnXOffset + ImplGetExtraOffset(); |
| aRect.Justify(); |
| aClip.Union( aRect ); |
| nIndex++; |
| } |
| i = nIndex; |
| if( aClip.Intersect( aRegion ) && nAttr ) |
| { |
| Font aFont = GetFont(); |
| if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE ) |
| aFont.SetUnderline( UNDERLINE_SINGLE ); |
| else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE ) |
| aFont.SetUnderline( UNDERLINE_BOLD ); |
| else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE ) |
| aFont.SetUnderline( UNDERLINE_DOTTED ); |
| else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE ) |
| aFont.SetUnderline( UNDERLINE_DOTTED ); |
| else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE ) |
| { |
| aFont.SetUnderline( UNDERLINE_WAVE ); |
| SetTextLineColor( Color( COL_LIGHTGRAY ) ); |
| } |
| SetFont( aFont ); |
| |
| if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT ) |
| SetTextColor( Color( COL_RED ) ); |
| else if ( nAttr & EXTTEXTINPUT_ATTR_HALFTONETEXT ) |
| SetTextColor( Color( COL_LIGHTGRAY ) ); |
| |
| SetClipRegion( aClip ); |
| DrawText( aPos, aText, nStart, nEnd - nStart ); |
| } |
| } |
| } |
| } |
| |
| // restore graphics state |
| Pop(); |
| } |
| |
| if ( bVisCursor && ( !mpIMEInfos || mpIMEInfos->bCursor ) ) |
| pCursor->Show(); |
| |
| if( pDXBuffer ) |
| delete [] pDXBuffer; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplDelete( const Selection& rSelection, sal_uInt8 nDirection, sal_uInt8 nMode ) |
| { |
| XubString aText = ImplGetText(); |
| |
| // loeschen moeglich? |
| if ( !rSelection.Len() && |
| (((rSelection.Min() == 0) && (nDirection == EDIT_DEL_LEFT)) || |
| ((rSelection.Max() == aText.Len()) && (nDirection == EDIT_DEL_RIGHT))) ) |
| return; |
| |
| ImplClearLayoutData(); |
| |
| Selection aSelection( rSelection ); |
| aSelection.Justify(); |
| |
| if ( !aSelection.Len() ) |
| { |
| uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator(); |
| if ( nDirection == EDIT_DEL_LEFT ) |
| { |
| if ( nMode == EDIT_DELMODE_RESTOFWORD ) |
| { |
| i18n::Boundary aBoundary = xBI->getWordBoundary( maText, aSelection.Min(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); |
| if ( aBoundary.startPos == aSelection.Min() ) |
| aBoundary = xBI->previousWord( maText, aSelection.Min(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); |
| aSelection.Min() = aBoundary.startPos; |
| } |
| else if ( nMode == EDIT_DELMODE_RESTOFCONTENT ) |
| { |
| aSelection.Min() = 0; |
| } |
| else |
| { |
| sal_Int32 nCount = 1; |
| aSelection.Min() = xBI->previousCharacters( maText, aSelection.Min(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount ); |
| } |
| } |
| else |
| { |
| if ( nMode == EDIT_DELMODE_RESTOFWORD ) |
| { |
| i18n::Boundary aBoundary = xBI->nextWord( maText, aSelection.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); |
| aSelection.Max() = aBoundary.startPos; |
| } |
| else if ( nMode == EDIT_DELMODE_RESTOFCONTENT ) |
| { |
| aSelection.Max() = aText.Len(); |
| } |
| else |
| { |
| sal_Int32 nCount = 1; |
| aSelection.Max() = xBI->nextCharacters( maText, aSelection.Max(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount );; |
| } |
| } |
| } |
| |
| maText.Erase( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() ); |
| maSelection.Min() = aSelection.Min(); |
| maSelection.Max() = aSelection.Min(); |
| ImplAlignAndPaint(); |
| mbInternModified = sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| String Edit::ImplGetValidString( const String& rString ) const |
| { |
| String aValidString( rString ); |
| aValidString.EraseAllChars( _LF ); |
| aValidString.EraseAllChars( _CR ); |
| aValidString.SearchAndReplaceAll( '\t', ' ' ); |
| return aValidString; |
| } |
| |
| // ----------------------------------------------------------------------- |
| uno::Reference < i18n::XBreakIterator > Edit::ImplGetBreakIterator() const |
| { |
| //!! since we don't want to become incompatible in the next minor update |
| //!! where this code will get integrated into, xISC will be a local |
| //!! variable instead of a class member! |
| uno::Reference < i18n::XBreakIterator > xBI; |
| // if ( !xBI.is() ) |
| { |
| uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); |
| uno::Reference < XInterface > xI = xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.BreakIterator" ) ); |
| if ( xI.is() ) |
| { |
| Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XBreakIterator >*)0) ); |
| x >>= xBI; |
| } |
| } |
| return xBI; |
| } |
| // ----------------------------------------------------------------------- |
| |
| uno::Reference < i18n::XExtendedInputSequenceChecker > Edit::ImplGetInputSequenceChecker() const |
| { |
| //!! since we don't want to become incompatible in the next minor update |
| //!! where this code will get integrated into, xISC will be a local |
| //!! variable instead of a class member! |
| uno::Reference < i18n::XExtendedInputSequenceChecker > xISC; |
| // if ( !xISC.is() ) |
| { |
| uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); |
| uno::Reference < XInterface > xI = xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.InputSequenceChecker" ) ); |
| if ( xI.is() ) |
| { |
| Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XExtendedInputSequenceChecker >*)0) ); |
| x >>= xISC; |
| } |
| } |
| return xISC; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ShowTruncationWarning( Window* pParent ) |
| { |
| ResMgr* pResMgr = ImplGetResMgr(); |
| if( pResMgr ) |
| { |
| WarningBox aBox( pParent, ResId( SV_EDIT_WARNING_BOX, *pResMgr ) ); |
| aBox.Execute(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| bool Edit::ImplTruncateToMaxLen( rtl::OUString& rStr, sal_uInt32 nSelectionLen ) const |
| { |
| bool bWasTruncated = false; |
| const sal_uInt32 nMaxLen = mnMaxTextLen < 65534 ? mnMaxTextLen : 65534; |
| sal_uInt32 nLenAfter = static_cast<sal_uInt32>(maText.Len()) + rStr.getLength() - nSelectionLen; |
| if ( nLenAfter > nMaxLen ) |
| { |
| sal_uInt32 nErasePos = nMaxLen - static_cast<sal_uInt32>(maText.Len()) + nSelectionLen; |
| rStr = rStr.copy( 0, nErasePos ); |
| bWasTruncated = true; |
| } |
| return bWasTruncated; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplInsertText( const XubString& rStr, const Selection* pNewSel, sal_Bool bIsUserInput ) |
| { |
| Selection aSelection( maSelection ); |
| aSelection.Justify(); |
| |
| rtl::OUString aNewText( ImplGetValidString( rStr ) ); |
| ImplTruncateToMaxLen( aNewText, aSelection.Len() ); |
| |
| ImplClearLayoutData(); |
| |
| if ( aSelection.Len() ) |
| maText.Erase( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() ); |
| else if ( !mbInsertMode && (aSelection.Max() < maText.Len()) ) |
| maText.Erase( (xub_StrLen)aSelection.Max(), 1 ); |
| |
| // take care of input-sequence-checking now |
| if (bIsUserInput && rStr.Len()) |
| { |
| DBG_ASSERT( rStr.Len() == 1, "unexpected string length. User input is expected to providse 1 char only!" ); |
| |
| // determine if input-sequence-checking should be applied or not |
| // |
| static OUString sModule( OUString::createFromAscii( "/org.openoffice.Office.Common/I18N" ) ); |
| static OUString sRelNode( OUString::createFromAscii( "CTL" ) ); |
| static OUString sCTLSequenceChecking( OUString::createFromAscii( "CTLSequenceChecking" ) ); |
| static OUString sCTLSequenceCheckingRestricted( OUString::createFromAscii( "CTLSequenceCheckingRestricted" ) ); |
| static OUString sCTLSequenceCheckingTypeAndReplace( OUString::createFromAscii( "CTLSequenceCheckingTypeAndReplace" ) ); |
| static OUString sCTLFont( OUString::createFromAscii( "CTLFont" ) ); |
| // |
| sal_Bool bCTLSequenceChecking = sal_False; |
| sal_Bool bCTLSequenceCheckingRestricted = sal_False; |
| sal_Bool bCTLSequenceCheckingTypeAndReplace = sal_False; |
| sal_Bool bCTLFontEnabled = sal_False; |
| sal_Bool bIsInputSequenceChecking = sal_False; |
| // |
| // get access to the configuration of this office module |
| try |
| { |
| uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); |
| uno::Reference< container::XNameAccess > xModuleCfg( ::comphelper::ConfigurationHelper::openConfig( |
| xMSF, |
| sModule, |
| ::comphelper::ConfigurationHelper::E_READONLY ), |
| uno::UNO_QUERY ); |
| |
| //!! get values from configuration. |
| //!! we can't use SvtCTLOptions here since vcl must not be linked |
| //!! against svtools. (It is already the other way around.) |
| Any aCTLSequenceChecking = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLSequenceChecking ); |
| Any aCTLSequenceCheckingRestricted = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLSequenceCheckingRestricted ); |
| Any aCTLSequenceCheckingTypeAndReplace = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLSequenceCheckingTypeAndReplace ); |
| Any aCTLFontEnabled = ::comphelper::ConfigurationHelper::readRelativeKey( xModuleCfg, sRelNode, sCTLFont ); |
| aCTLSequenceChecking >>= bCTLSequenceChecking; |
| aCTLSequenceCheckingRestricted >>= bCTLSequenceCheckingRestricted; |
| aCTLSequenceCheckingTypeAndReplace >>= bCTLSequenceCheckingTypeAndReplace; |
| aCTLFontEnabled >>= bCTLFontEnabled; |
| } |
| catch(...) |
| { |
| bIsInputSequenceChecking = sal_False; // continue with inserting the new text |
| } |
| // |
| uno::Reference < i18n::XBreakIterator > xBI( ImplGetBreakIterator(), UNO_QUERY ); |
| bIsInputSequenceChecking = rStr.Len() == 1 && |
| bCTLFontEnabled && |
| bCTLSequenceChecking && |
| aSelection.Min() > 0 && /* first char needs not to be checked */ |
| xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( rStr, 0 ); |
| |
| |
| uno::Reference < i18n::XExtendedInputSequenceChecker > xISC; |
| if (bIsInputSequenceChecking && (xISC = ImplGetInputSequenceChecker()).is()) |
| { |
| sal_Unicode cChar = rStr.GetChar(0); |
| xub_StrLen nTmpPos = static_cast< xub_StrLen >( aSelection.Min() ); |
| sal_Int16 nCheckMode = bCTLSequenceCheckingRestricted ? |
| i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC; |
| |
| // the text that needs to be checked is only the one |
| // before the current cursor position |
| rtl::OUString aOldText( maText.Copy(0, nTmpPos) ); |
| rtl::OUString aTmpText( aOldText ); |
| if (bCTLSequenceCheckingTypeAndReplace) |
| { |
| xISC->correctInputSequence( aTmpText, nTmpPos - 1, cChar, nCheckMode ); |
| |
| // find position of first character that has changed |
| sal_Int32 nOldLen = aOldText.getLength(); |
| sal_Int32 nTmpLen = aTmpText.getLength(); |
| const sal_Unicode *pOldTxt = aOldText.getStr(); |
| const sal_Unicode *pTmpTxt = aTmpText.getStr(); |
| sal_Int32 nChgPos = 0; |
| while ( nChgPos < nOldLen && nChgPos < nTmpLen && |
| pOldTxt[nChgPos] == pTmpTxt[nChgPos] ) |
| ++nChgPos; |
| |
| xub_StrLen nChgLen = static_cast< xub_StrLen >( nTmpLen - nChgPos ); |
| String aChgText( aTmpText.copy( nChgPos ).getStr(), nChgLen ); |
| |
| // remove text from first pos to be changed to current pos |
| maText.Erase( static_cast< xub_StrLen >( nChgPos ), static_cast< xub_StrLen >( nTmpPos - nChgPos ) ); |
| |
| if (aChgText.Len()) |
| { |
| aNewText = aChgText; |
| aSelection.Min() = nChgPos; // position for new text to be inserted |
| } |
| else |
| aNewText = String::EmptyString(); |
| } |
| else |
| { |
| // should the character be ignored (i.e. not get inserted) ? |
| if (!xISC->checkInputSequence( aOldText, nTmpPos - 1, cChar, nCheckMode )) |
| aNewText = String::EmptyString(); |
| } |
| } |
| |
| // at this point now we will insert the non-empty text 'normally' some lines below... |
| } |
| |
| if ( aNewText.getLength() ) |
| maText.Insert( String( aNewText ), (xub_StrLen)aSelection.Min() ); |
| |
| if ( !pNewSel ) |
| { |
| maSelection.Min() = aSelection.Min() + aNewText.getLength(); |
| maSelection.Max() = maSelection.Min(); |
| } |
| else |
| { |
| maSelection = *pNewSel; |
| if ( maSelection.Min() > maText.Len() ) |
| maSelection.Min() = maText.Len(); |
| if ( maSelection.Max() > maText.Len() ) |
| maSelection.Max() = maText.Len(); |
| } |
| |
| ImplAlignAndPaint(); |
| mbInternModified = sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplSetText( const XubString& rText, const Selection* pNewSelection ) |
| { |
| // Der Text wird dadurch geloescht das der alte Text komplett 'selektiert' |
| // wird, dann InsertText, damit flackerfrei. |
| if ( ( rText.Len() <= mnMaxTextLen ) && ( (rText != maText) || (pNewSelection && (*pNewSelection != maSelection)) ) ) |
| { |
| ImplClearLayoutData(); |
| maSelection.Min() = 0; |
| maSelection.Max() = maText.Len(); |
| if ( mnXOffset || HasPaintEvent() ) |
| { |
| mnXOffset = 0; |
| maText = ImplGetValidString( rText ); |
| |
| // #i54929# recalculate mnXOffset before ImplSetSelection, |
| // else cursor ends up in wrong position |
| ImplAlign(); |
| |
| if ( pNewSelection ) |
| ImplSetSelection( *pNewSelection, sal_False ); |
| |
| if ( mnXOffset && !pNewSelection ) |
| maSelection.Max() = 0; |
| |
| Invalidate(); |
| } |
| else |
| ImplInsertText( rText, pNewSelection ); |
| |
| ImplCallEventListeners( VCLEVENT_EDIT_MODIFY ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| int Edit::ImplGetNativeControlType() |
| { |
| int nCtrl = 0; |
| Window *pControl = mbIsSubEdit ? GetParent() : this; |
| |
| switch( pControl->GetType() ) |
| { |
| case WINDOW_COMBOBOX: |
| case WINDOW_PATTERNBOX: |
| case WINDOW_NUMERICBOX: |
| case WINDOW_METRICBOX: |
| case WINDOW_CURRENCYBOX: |
| case WINDOW_DATEBOX: |
| case WINDOW_TIMEBOX: |
| case WINDOW_LONGCURRENCYBOX: |
| nCtrl = CTRL_COMBOBOX; |
| break; |
| |
| case WINDOW_MULTILINEEDIT: |
| if ( GetWindow( WINDOW_BORDER ) != this ) |
| nCtrl = CTRL_MULTILINE_EDITBOX; |
| else |
| nCtrl = CTRL_EDITBOX_NOBORDER; |
| break; |
| |
| case WINDOW_EDIT: |
| case WINDOW_PATTERNFIELD: |
| case WINDOW_METRICFIELD: |
| case WINDOW_CURRENCYFIELD: |
| case WINDOW_DATEFIELD: |
| case WINDOW_TIMEFIELD: |
| case WINDOW_LONGCURRENCYFIELD: |
| case WINDOW_NUMERICFIELD: |
| case WINDOW_SPINFIELD: |
| if( pControl->GetStyle() & WB_SPIN ) |
| nCtrl = CTRL_SPINBOX; |
| else |
| { |
| if ( GetWindow( WINDOW_BORDER ) != this ) |
| nCtrl = CTRL_EDITBOX; |
| else |
| nCtrl = CTRL_EDITBOX_NOBORDER; |
| } |
| break; |
| |
| default: |
| nCtrl = CTRL_EDITBOX; |
| } |
| return nCtrl; |
| } |
| |
| void Edit::ImplClearBackground( long nXStart, long nXEnd ) |
| { |
| /* |
| * note: at this point the cursor must be switched off already |
| */ |
| Point aTmpPoint; |
| Rectangle aRect( aTmpPoint, GetOutputSizePixel() ); |
| aRect.Left() = nXStart; |
| aRect.Right() = nXEnd; |
| |
| if( ImplUseNativeBorder( GetStyle() ) || IsPaintTransparent() ) |
| { |
| // draw the inner part by painting the whole control using its border window |
| Window *pControl = this; |
| Window *pBorder = GetWindow( WINDOW_BORDER ); |
| if( pBorder == this ) |
| { |
| // we have no border, use parent |
| pControl = mbIsSubEdit ? GetParent() : this; |
| pBorder = pControl->GetWindow( WINDOW_BORDER ); |
| if( pBorder == this ) |
| pBorder = GetParent(); |
| } |
| |
| if( pBorder ) |
| { |
| // set proper clipping region to not overdraw the whole control |
| Region aClipRgn = GetPaintRegion(); |
| if( !aClipRgn.IsNull() ) |
| { |
| // transform clipping region to border window's coordinate system |
| if( IsRTLEnabled() != pBorder->IsRTLEnabled() && Application::GetSettings().GetLayoutRTL() ) |
| { |
| // need to mirror in case border is not RTL but edit is (or vice versa) |
| |
| // mirror |
| Rectangle aBounds( aClipRgn.GetBoundRect() ); |
| int xNew = GetOutputSizePixel().Width() - aBounds.GetWidth() - aBounds.Left(); |
| aClipRgn.Move( xNew - aBounds.Left(), 0 ); |
| |
| // move offset of border window |
| Point aBorderOffs; |
| aBorderOffs = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs ) ); |
| aClipRgn.Move( aBorderOffs.X(), aBorderOffs.Y() ); |
| } |
| else |
| { |
| // normal case |
| Point aBorderOffs; |
| aBorderOffs = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aBorderOffs ) ); |
| aClipRgn.Move( aBorderOffs.X(), aBorderOffs.Y() ); |
| } |
| |
| Region oldRgn( pBorder->GetClipRegion() ); |
| pBorder->SetClipRegion( aClipRgn ); |
| |
| pBorder->Paint( Rectangle() ); |
| |
| pBorder->SetClipRegion( oldRgn ); |
| } |
| else |
| pBorder->Paint( Rectangle() ); |
| |
| } |
| } |
| else |
| Erase( aRect ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplShowCursor( sal_Bool bOnlyIfVisible ) |
| { |
| if ( !IsUpdateMode() || ( bOnlyIfVisible && !IsReallyVisible() ) ) |
| return; |
| |
| Cursor* pCursor = GetCursor(); |
| XubString aText = ImplGetText(); |
| |
| long nTextPos = 0; |
| |
| sal_Int32 nDXBuffer[256]; |
| sal_Int32* pDXBuffer = NULL; |
| sal_Int32* pDX = nDXBuffer; |
| |
| if( aText.Len() ) |
| { |
| if( 2*aText.Len() > xub_StrLen(sizeof(nDXBuffer)/sizeof(nDXBuffer[0])) ) |
| { |
| pDXBuffer = new sal_Int32[2*(aText.Len()+1)]; |
| pDX = pDXBuffer; |
| } |
| |
| GetCaretPositions( aText, pDX, 0, aText.Len() ); |
| |
| if( maSelection.Max() < aText.Len() ) |
| nTextPos = pDX[ 2*maSelection.Max() ]; |
| else |
| nTextPos = pDX[ 2*aText.Len()-1 ]; |
| } |
| |
| long nCursorWidth = 0; |
| if ( !mbInsertMode && !maSelection.Len() && (maSelection.Max() < aText.Len()) ) |
| nCursorWidth = GetTextWidth( aText, (xub_StrLen)maSelection.Max(), 1 ); |
| long nCursorPosX = nTextPos + mnXOffset + ImplGetExtraOffset(); |
| |
| // Cursor muss im sichtbaren Bereich landen: |
| const Size aOutSize = GetOutputSizePixel(); |
| if ( (nCursorPosX < 0) || (nCursorPosX >= aOutSize.Width()) ) |
| { |
| long nOldXOffset = mnXOffset; |
| |
| if ( nCursorPosX < 0 ) |
| { |
| mnXOffset = - nTextPos; |
| long nMaxX = 0; |
| mnXOffset += aOutSize.Width() / 5; |
| if ( mnXOffset > nMaxX ) |
| mnXOffset = nMaxX; |
| } |
| else |
| { |
| mnXOffset = (aOutSize.Width()-ImplGetExtraOffset()) - nTextPos; |
| // Etwas mehr? |
| if ( (aOutSize.Width()-ImplGetExtraOffset()) < nTextPos ) |
| { |
| long nMaxNegX = (aOutSize.Width()-ImplGetExtraOffset()) - GetTextWidth( aText ); |
| mnXOffset -= aOutSize.Width() / 5; |
| if ( mnXOffset < nMaxNegX ) // beides negativ... |
| mnXOffset = nMaxNegX; |
| } |
| } |
| |
| nCursorPosX = nTextPos + mnXOffset + ImplGetExtraOffset(); |
| if ( nCursorPosX == aOutSize.Width() ) // dann nicht sichtbar... |
| nCursorPosX--; |
| |
| if ( mnXOffset != nOldXOffset ) |
| ImplInvalidateOrRepaint(); |
| } |
| |
| const long nTextHeight = GetTextHeight(); |
| const long nCursorPosY = ImplGetTextYPosition(); |
| pCursor->SetPos( Point( nCursorPosX, nCursorPosY ) ); |
| pCursor->SetSize( Size( nCursorWidth, nTextHeight ) ); |
| pCursor->Show(); |
| |
| if( pDXBuffer ) |
| delete [] pDXBuffer; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplAlign() |
| { |
| long nTextWidth = GetTextWidth( ImplGetText() ); |
| long nOutWidth = GetOutputSizePixel().Width(); |
| |
| if ( mnAlign == EDIT_ALIGN_LEFT ) |
| { |
| if( mnXOffset && ( nTextWidth < nOutWidth ) ) |
| mnXOffset = 0; |
| |
| } |
| else if ( mnAlign == EDIT_ALIGN_RIGHT ) |
| { |
| long nMinXOffset = nOutWidth - nTextWidth - 1 - ImplGetExtraOffset(); |
| bool bRTL = IsRTLEnabled(); |
| if( mbIsSubEdit && GetParent() ) |
| bRTL = GetParent()->IsRTLEnabled(); |
| if( bRTL ) |
| { |
| if( nTextWidth < nOutWidth ) |
| mnXOffset = nMinXOffset; |
| } |
| else |
| { |
| if( nTextWidth < nOutWidth ) |
| mnXOffset = nMinXOffset; |
| else if ( mnXOffset < nMinXOffset ) |
| mnXOffset = nMinXOffset; |
| } |
| } |
| else if( mnAlign == EDIT_ALIGN_CENTER ) |
| { |
| // Mit Abfrage schoener, wenn gescrollt, dann aber nicht zentriert im gescrollten Zustand... |
| // if ( nTextWidth < nOutWidth ) |
| mnXOffset = (nOutWidth - nTextWidth) / 2; |
| } |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplAlignAndPaint() |
| { |
| ImplAlign(); |
| ImplInvalidateOrRepaint( 0, STRING_LEN ); |
| ImplShowCursor(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| xub_StrLen Edit::ImplGetCharPos( const Point& rWindowPos ) const |
| { |
| xub_StrLen nIndex = STRING_LEN; |
| String aText = ImplGetText(); |
| |
| sal_Int32 nDXBuffer[256]; |
| sal_Int32* pDXBuffer = NULL; |
| sal_Int32* pDX = nDXBuffer; |
| if( 2*aText.Len() > xub_StrLen(sizeof(nDXBuffer)/sizeof(nDXBuffer[0])) ) |
| { |
| pDXBuffer = new sal_Int32[2*(aText.Len()+1)]; |
| pDX = pDXBuffer; |
| } |
| |
| GetCaretPositions( aText, pDX, 0, aText.Len() ); |
| long nX = rWindowPos.X() - mnXOffset - ImplGetExtraOffset(); |
| for( int i = 0; i < aText.Len(); i++ ) |
| { |
| if( (pDX[2*i] >= nX && pDX[2*i+1] <= nX) || |
| (pDX[2*i+1] >= nX && pDX[2*i] <= nX)) |
| { |
| nIndex = sal::static_int_cast<xub_StrLen>(i); |
| if( pDX[2*i] < pDX[2*i+1] ) |
| { |
| if( nX > (pDX[2*i]+pDX[2*i+1])/2 ) |
| nIndex++; |
| } |
| else |
| { |
| if( nX < (pDX[2*i]+pDX[2*i+1])/2 ) |
| nIndex++; |
| } |
| break; |
| } |
| } |
| if( nIndex == STRING_LEN ) |
| { |
| nIndex = 0; |
| long nDiff = Abs( pDX[0]-nX ); |
| for( int i = 1; i < aText.Len(); i++ ) |
| { |
| long nNewDiff = Abs( pDX[2*i]-nX ); |
| |
| if( nNewDiff < nDiff ) |
| { |
| nIndex = sal::static_int_cast<xub_StrLen>(i); |
| nDiff = nNewDiff; |
| } |
| } |
| if( nIndex == aText.Len()-1 && Abs( pDX[2*nIndex+1] - nX ) < nDiff ) |
| nIndex = STRING_LEN; |
| } |
| |
| if( pDXBuffer ) |
| delete [] pDXBuffer; |
| |
| return nIndex; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplSetCursorPos( xub_StrLen nChar, sal_Bool bSelect ) |
| { |
| Selection aSelection( maSelection ); |
| aSelection.Max() = nChar; |
| if ( !bSelect ) |
| aSelection.Min() = aSelection.Max(); |
| ImplSetSelection( aSelection ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplLoadRes( const ResId& rResId ) |
| { |
| Control::ImplLoadRes( rResId ); |
| |
| xub_StrLen nTextLength = ReadShortRes(); |
| if ( nTextLength ) |
| SetMaxTextLen( nTextLength ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplCopyToSelectionClipboard() |
| { |
| if ( GetSelection().Len() ) |
| { |
| ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aSelection(GetPrimarySelection()); |
| ImplCopy( aSelection ); |
| } |
| } |
| |
| void Edit::ImplCopy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard ) |
| { |
| ::vcl::unohelper::TextDataObject::CopyStringTo( GetSelected(), rxClipboard ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplPaste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard ) |
| { |
| if ( rxClipboard.is() ) |
| { |
| uno::Reference< datatransfer::XTransferable > xDataObj; |
| |
| const sal_uInt32 nRef = Application::ReleaseSolarMutex(); |
| |
| try |
| { |
| xDataObj = rxClipboard->getContents(); |
| } |
| catch( const ::com::sun::star::uno::Exception& ) |
| { |
| } |
| |
| Application::AcquireSolarMutex( nRef ); |
| |
| if ( xDataObj.is() ) |
| { |
| datatransfer::DataFlavor aFlavor; |
| SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); |
| try |
| { |
| uno::Any aData = xDataObj->getTransferData( aFlavor ); |
| ::rtl::OUString aText; |
| aData >>= aText; |
| if( ImplTruncateToMaxLen( aText, maSelection.Len() ) ) |
| ShowTruncationWarning( const_cast<Edit*>(this) ); |
| ReplaceSelected( aText ); |
| } |
| catch( const ::com::sun::star::uno::Exception& ) |
| { |
| } |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::MouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| if ( mpSubEdit ) |
| { |
| Control::MouseButtonDown( rMEvt ); |
| return; |
| } |
| |
| xub_StrLen nChar = ImplGetCharPos( rMEvt.GetPosPixel() ); |
| Selection aSelection( maSelection ); |
| aSelection.Justify(); |
| |
| if ( rMEvt.GetClicks() < 4 ) |
| { |
| mbClickedInSelection = sal_False; |
| if ( rMEvt.GetClicks() == 3 ) |
| { |
| ImplSetSelection( Selection( 0, 0xFFFF ) ); |
| ImplCopyToSelectionClipboard(); |
| |
| } |
| else if ( rMEvt.GetClicks() == 2 ) |
| { |
| uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator(); |
| i18n::Boundary aBoundary = xBI->getWordBoundary( maText, aSelection.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); |
| ImplSetSelection( Selection( aBoundary.startPos, aBoundary.endPos ) ); |
| ImplCopyToSelectionClipboard(); |
| } |
| else if ( !rMEvt.IsShift() && HasFocus() && aSelection.IsInside( nChar ) ) |
| mbClickedInSelection = sal_True; |
| else if ( rMEvt.IsLeft() ) |
| ImplSetCursorPos( nChar, rMEvt.IsShift() ); |
| |
| if ( !mbClickedInSelection && rMEvt.IsLeft() && ( rMEvt.GetClicks() == 1 ) ) |
| StartTracking( STARTTRACK_SCROLLREPEAT ); |
| } |
| |
| mbInMBDown = sal_True; // Dann im GetFocus nicht alles selektieren |
| GrabFocus(); |
| mbInMBDown = sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::MouseButtonUp( const MouseEvent& rMEvt ) |
| { |
| if ( mbClickedInSelection && rMEvt.IsLeft() ) |
| { |
| xub_StrLen nChar = ImplGetCharPos( rMEvt.GetPosPixel() ); |
| ImplSetCursorPos( nChar, sal_False ); |
| mbClickedInSelection = sal_False; |
| } |
| else if ( rMEvt.IsMiddle() && !mbReadOnly && |
| ( GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) ) |
| { |
| ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aSelection(Window::GetPrimarySelection()); |
| ImplPaste( aSelection ); |
| ImplModified(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Tracking( const TrackingEvent& rTEvt ) |
| { |
| if ( rTEvt.IsTrackingEnded() ) |
| { |
| if ( mbClickedInSelection ) |
| { |
| xub_StrLen nChar = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() ); |
| ImplSetCursorPos( nChar, sal_False ); |
| mbClickedInSelection = sal_False; |
| } |
| else if ( rTEvt.GetMouseEvent().IsLeft() ) |
| { |
| ImplCopyToSelectionClipboard(); |
| } |
| } |
| else |
| { |
| if( !mbClickedInSelection ) |
| { |
| xub_StrLen nChar = ImplGetCharPos( rTEvt.GetMouseEvent().GetPosPixel() ); |
| ImplSetCursorPos( nChar, sal_True ); |
| } |
| } |
| |
| if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() ) |
| mpUpdateDataTimer->Start();//do not update while the user is still travelling in the control |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool Edit::ImplHandleKeyEvent( const KeyEvent& rKEvt ) |
| { |
| sal_Bool bDone = sal_False; |
| sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); |
| KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction(); |
| |
| mbInternModified = sal_False; |
| |
| if ( eFunc != KEYFUNC_DONTKNOW ) |
| { |
| switch ( eFunc ) |
| { |
| case KEYFUNC_CUT: |
| { |
| if ( !mbReadOnly && maSelection.Len() && !(GetStyle() & WB_PASSWORD) ) |
| { |
| Cut(); |
| ImplModified(); |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| case KEYFUNC_COPY: |
| { |
| if ( !(GetStyle() & WB_PASSWORD) ) |
| { |
| Copy(); |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| case KEYFUNC_PASTE: |
| { |
| if ( !mbReadOnly ) |
| { |
| Paste(); |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| case KEYFUNC_UNDO: |
| { |
| if ( !mbReadOnly ) |
| { |
| Undo(); |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| default: // wird dann evtl. unten bearbeitet. |
| eFunc = KEYFUNC_DONTKNOW; |
| } |
| } |
| |
| if ( !bDone && rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() ) |
| { |
| if ( nCode == KEY_A ) |
| { |
| ImplSetSelection( Selection( 0, maText.Len() ) ); |
| bDone = sal_True; |
| } |
| else if ( rKEvt.GetKeyCode().IsShift() && (nCode == KEY_S) ) |
| { |
| if ( pImplFncGetSpecialChars ) |
| { |
| Selection aSaveSel = GetSelection(); // Falls jemand in Get/LoseFocus die Selektion verbiegt, z.B. URL-Zeile... |
| XubString aChars = pImplFncGetSpecialChars( this, GetFont() ); |
| SetSelection( aSaveSel ); |
| if ( aChars.Len() ) |
| { |
| ImplInsertText( aChars ); |
| ImplModified(); |
| } |
| bDone = sal_True; |
| } |
| } |
| } |
| |
| if ( eFunc == KEYFUNC_DONTKNOW && ! bDone ) |
| { |
| switch ( nCode ) |
| { |
| case com::sun::star::awt::Key::SELECT_ALL: |
| { |
| ImplSetSelection( Selection( 0, maText.Len() ) ); |
| bDone = sal_True; |
| } |
| break; |
| |
| case KEY_LEFT: |
| case KEY_RIGHT: |
| case KEY_HOME: |
| case KEY_END: |
| case com::sun::star::awt::Key::MOVE_WORD_FORWARD: |
| case com::sun::star::awt::Key::SELECT_WORD_FORWARD: |
| case com::sun::star::awt::Key::MOVE_WORD_BACKWARD: |
| case com::sun::star::awt::Key::SELECT_WORD_BACKWARD: |
| case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE: |
| case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE: |
| case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE: |
| case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE: |
| case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT: |
| case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT: |
| case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT: |
| case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT: |
| { |
| if ( !rKEvt.GetKeyCode().IsMod2() ) |
| { |
| ImplClearLayoutData(); |
| uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator(); |
| |
| Selection aSel( maSelection ); |
| bool bWord = rKEvt.GetKeyCode().IsMod1(); |
| bool bSelect = rKEvt.GetKeyCode().IsShift(); |
| bool bGoLeft = (nCode == KEY_LEFT); |
| bool bGoRight = (nCode == KEY_RIGHT); |
| bool bGoHome = (nCode == KEY_HOME); |
| bool bGoEnd = (nCode == KEY_END); |
| |
| switch( nCode ) |
| { |
| case com::sun::star::awt::Key::MOVE_WORD_FORWARD: |
| bGoRight = bWord = true;break; |
| case com::sun::star::awt::Key::SELECT_WORD_FORWARD: |
| bGoRight = bSelect = bWord = true;break; |
| case com::sun::star::awt::Key::MOVE_WORD_BACKWARD: |
| bGoLeft = bWord = true;break; |
| case com::sun::star::awt::Key::SELECT_WORD_BACKWARD: |
| bGoLeft = bSelect = bWord = true;break; |
| case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE: |
| case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT: |
| bSelect = true; |
| // fallthrough intended |
| case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE: |
| case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT: |
| bGoHome = true;break; |
| case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE: |
| case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT: |
| bSelect = true; |
| // fallthrough intended |
| case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE: |
| case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH: |
| case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT: |
| bGoEnd = true;break; |
| default: |
| break; |
| }; |
| |
| // Range wird in ImplSetSelection geprueft... |
| if ( bGoLeft && aSel.Max() ) |
| { |
| if ( bWord ) |
| { |
| i18n::Boundary aBoundary = xBI->getWordBoundary( maText, aSel.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); |
| if ( aBoundary.startPos == aSel.Max() ) |
| aBoundary = xBI->previousWord( maText, aSel.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); |
| aSel.Max() = aBoundary.startPos; |
| } |
| else |
| { |
| sal_Int32 nCount = 1; |
| aSel.Max() = xBI->previousCharacters( maText, aSel.Max(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount ); |
| } |
| } |
| else if ( bGoRight && ( aSel.Max() < maText.Len() ) ) |
| { |
| if ( bWord ) |
| { |
| i18n::Boundary aBoundary = xBI->nextWord( maText, aSel.Max(), GetSettings().GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); |
| aSel.Max() = aBoundary.startPos; |
| } |
| else |
| { |
| sal_Int32 nCount = 1; |
| aSel.Max() = xBI->nextCharacters( maText, aSel.Max(), GetSettings().GetLocale(), i18n::CharacterIteratorMode::SKIPCHARACTER, nCount, nCount ); |
| } |
| } |
| else if ( bGoHome ) |
| { |
| aSel.Max() = 0; |
| } |
| else if ( bGoEnd ) |
| { |
| aSel.Max() = 0xFFFF; |
| } |
| |
| if ( !bSelect ) |
| aSel.Min() = aSel.Max(); |
| |
| if ( aSel != GetSelection() ) |
| { |
| ImplSetSelection( aSel ); |
| ImplCopyToSelectionClipboard(); |
| } |
| |
| if ( bGoEnd && maAutocompleteHdl.IsSet() && !rKEvt.GetKeyCode().GetModifier() ) |
| { |
| if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) ) |
| { |
| meAutocompleteAction = AUTOCOMPLETE_KEYINPUT; |
| maAutocompleteHdl.Call( this ); |
| } |
| } |
| |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| case com::sun::star::awt::Key::DELETE_WORD_BACKWARD: |
| case com::sun::star::awt::Key::DELETE_WORD_FORWARD: |
| case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE: |
| case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE: |
| case KEY_BACKSPACE: |
| case KEY_DELETE: |
| { |
| if ( !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() ) |
| { |
| sal_uInt8 nDel = (nCode == KEY_DELETE) ? EDIT_DEL_RIGHT : EDIT_DEL_LEFT; |
| sal_uInt8 nMode = rKEvt.GetKeyCode().IsMod1() ? EDIT_DELMODE_RESTOFWORD : EDIT_DELMODE_SIMPLE; |
| if ( (nMode == EDIT_DELMODE_RESTOFWORD) && rKEvt.GetKeyCode().IsShift() ) |
| nMode = EDIT_DELMODE_RESTOFCONTENT; |
| switch( nCode ) |
| { |
| case com::sun::star::awt::Key::DELETE_WORD_BACKWARD: |
| nDel = EDIT_DEL_LEFT; |
| nMode = EDIT_DELMODE_RESTOFWORD; |
| break; |
| case com::sun::star::awt::Key::DELETE_WORD_FORWARD: |
| nDel = EDIT_DEL_RIGHT; |
| nMode = EDIT_DELMODE_RESTOFWORD; |
| break; |
| case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE: |
| nDel = EDIT_DEL_LEFT; |
| nMode = EDIT_DELMODE_RESTOFCONTENT; |
| break; |
| case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE: |
| nDel = EDIT_DEL_RIGHT; |
| nMode = EDIT_DELMODE_RESTOFCONTENT; |
| break; |
| default: break; |
| } |
| xub_StrLen nOldLen = maText.Len(); |
| ImplDelete( maSelection, nDel, nMode ); |
| if ( maText.Len() != nOldLen ) |
| ImplModified(); |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| case KEY_INSERT: |
| { |
| if ( !mpIMEInfos && !mbReadOnly && !rKEvt.GetKeyCode().IsMod2() ) |
| { |
| SetInsertMode( !mbInsertMode ); |
| bDone = sal_True; |
| } |
| } |
| break; |
| |
| /* #i101255# disable autocomplete tab forward/backward |
| users expect tab/shif-tab to move the focus to other controls |
| not suddenly to cycle the autocompletion |
| case KEY_TAB: |
| { |
| if ( !mbReadOnly && maAutocompleteHdl.IsSet() && |
| maSelection.Min() && (maSelection.Min() == maText.Len()) && |
| !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() ) |
| { |
| // Kein Autocomplete wenn alles Selektiert oder Edit leer, weil dann |
| // keine vernuenftige Tab-Steuerung! |
| if ( rKEvt.GetKeyCode().IsShift() ) |
| meAutocompleteAction = AUTOCOMPLETE_TABBACKWARD; |
| else |
| meAutocompleteAction = AUTOCOMPLETE_TABFORWARD; |
| |
| maAutocompleteHdl.Call( this ); |
| |
| // Wurde nichts veraendert, dann TAB fuer DialogControl |
| if ( GetSelection().Len() ) |
| bDone = sal_True; |
| } |
| } |
| break; |
| */ |
| |
| default: |
| { |
| if ( IsCharInput( rKEvt ) ) |
| { |
| bDone = sal_True; // Auch bei ReadOnly die Zeichen schlucken. |
| if ( !mbReadOnly ) |
| { |
| ImplInsertText( rKEvt.GetCharCode(), 0, sal_True ); |
| if ( maAutocompleteHdl.IsSet() ) |
| { |
| if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) ) |
| { |
| meAutocompleteAction = AUTOCOMPLETE_KEYINPUT; |
| maAutocompleteHdl.Call( this ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if ( mbInternModified ) |
| ImplModified(); |
| |
| return bDone; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::KeyInput( const KeyEvent& rKEvt ) |
| { |
| if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() ) |
| mpUpdateDataTimer->Start();//do not update while the user is still travelling in the control |
| |
| if ( mpSubEdit || !ImplHandleKeyEvent( rKEvt ) ) |
| Control::KeyInput( rKEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::FillLayoutData() const |
| { |
| mpControlData->mpLayoutData = new vcl::ControlLayoutData(); |
| const_cast<Edit*>(this)->ImplRepaint( 0, STRING_LEN, true ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Paint( const Rectangle& ) |
| { |
| if ( !mpSubEdit ) |
| ImplRepaint(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Resize() |
| { |
| if ( !mpSubEdit && IsReallyVisible() ) |
| { |
| Control::Resize(); |
| // Wegen vertikaler Zentrierung... |
| mnXOffset = 0; |
| ImplAlign(); |
| Invalidate(); |
| ImplShowCursor(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) |
| { |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| |
| Point aPos = pDev->LogicToPixel( rPos ); |
| Size aSize = pDev->LogicToPixel( rSize ); |
| Font aFont = GetDrawPixelFont( pDev ); |
| OutDevType eOutDevType = pDev->GetOutDevType(); |
| |
| pDev->Push(); |
| pDev->SetMapMode(); |
| pDev->SetFont( aFont ); |
| pDev->SetTextFillColor(); |
| |
| // Border/Background |
| pDev->SetLineColor(); |
| pDev->SetFillColor(); |
| sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER); |
| sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground(); |
| if ( bBorder || bBackground ) |
| { |
| Rectangle aRect( aPos, aSize ); |
| if ( bBorder ) |
| { |
| ImplDrawFrame( pDev, aRect ); |
| } |
| if ( bBackground ) |
| { |
| pDev->SetFillColor( GetControlBackground() ); |
| pDev->DrawRect( aRect ); |
| } |
| } |
| |
| // Inhalt |
| if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) ) |
| pDev->SetTextColor( Color( COL_BLACK ) ); |
| else |
| { |
| if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() ) |
| { |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| pDev->SetTextColor( rStyleSettings.GetDisableColor() ); |
| } |
| else |
| { |
| pDev->SetTextColor( GetTextColor() ); |
| } |
| } |
| |
| XubString aText = ImplGetText(); |
| long nTextHeight = pDev->GetTextHeight(); |
| long nTextWidth = pDev->GetTextWidth( aText ); |
| long nOnePixel = GetDrawPixel( pDev, 1 ); |
| long nOffX = 3*nOnePixel; |
| long nOffY = (aSize.Height() - nTextHeight) / 2; |
| |
| // Clipping? |
| if ( (nOffY < 0) || |
| ((nOffY+nTextHeight) > aSize.Height()) || |
| ((nOffX+nTextWidth) > aSize.Width()) ) |
| { |
| Rectangle aClip( aPos, aSize ); |
| if ( nTextHeight > aSize.Height() ) |
| aClip.Bottom() += nTextHeight-aSize.Height()+1; // Damit HP-Drucker nicht 'weg-optimieren' |
| pDev->IntersectClipRegion( aClip ); |
| } |
| |
| if ( GetStyle() & WB_CENTER ) |
| { |
| aPos.X() += (aSize.Width() - nTextWidth) / 2; |
| nOffX = 0; |
| } |
| else if ( GetStyle() & WB_RIGHT ) |
| { |
| aPos.X() += aSize.Width() - nTextWidth; |
| nOffX = -nOffX; |
| } |
| |
| pDev->DrawText( Point( aPos.X() + nOffX, aPos.Y() + nOffY ), aText ); |
| pDev->Pop(); |
| |
| if ( GetSubEdit() ) |
| { |
| GetSubEdit()->Draw( pDev, rPos, rSize, nFlags ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplInvalidateOutermostBorder( Window* pWin ) |
| { |
| // allow control to show focused state |
| Window *pInvalWin = pWin, *pBorder = pWin; |
| while( ( pBorder = pInvalWin->GetWindow( WINDOW_BORDER ) ) != pInvalWin && pBorder && |
| pInvalWin->ImplGetFrame() == pBorder->ImplGetFrame() ) |
| { |
| pInvalWin = pBorder; |
| } |
| |
| pInvalWin->Invalidate( INVALIDATE_CHILDREN | INVALIDATE_UPDATE ); |
| } |
| |
| void Edit::GetFocus() |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->ImplGrabFocus( GetGetFocusFlags() ); |
| else if ( !mbActivePopup ) |
| { |
| maUndoText = maText; |
| |
| sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions(); |
| if ( !( GetStyle() & (WB_NOHIDESELECTION|WB_READONLY) ) |
| && ( GetGetFocusFlags() & (GETFOCUS_INIT|GETFOCUS_TAB|GETFOCUS_CURSOR|GETFOCUS_MNEMONIC) ) ) |
| { |
| if ( nSelOptions & SELECTION_OPTION_SHOWFIRST ) |
| { |
| maSelection.Min() = maText.Len(); |
| maSelection.Max() = 0; |
| } |
| else |
| { |
| maSelection.Min() = 0; |
| maSelection.Max() = maText.Len(); |
| } |
| if ( mbIsSubEdit ) |
| ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED ); |
| else |
| ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED ); |
| } |
| |
| ImplShowCursor(); |
| |
| // FIXME: this is currently only on aqua |
| // check for other platforms that need similar handling |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| IsNativeWidgetEnabled() && |
| IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) ) |
| { |
| ImplInvalidateOutermostBorder( mbIsSubEdit ? GetParent() : this ); |
| } |
| else if ( maSelection.Len() ) |
| { |
| // Selektion malen |
| if ( !HasPaintEvent() ) |
| ImplInvalidateOrRepaint(); |
| else |
| Invalidate(); |
| } |
| |
| SetInputContext( InputContext( GetFont(), !IsReadOnly() ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) ); |
| } |
| |
| Control::GetFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Window* Edit::GetPreferredKeyInputWindow() |
| { |
| if ( mpSubEdit ) |
| return mpSubEdit->GetPreferredKeyInputWindow(); |
| else |
| return this; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::LoseFocus() |
| { |
| if ( mpUpdateDataTimer && !mbIsSubEdit && mpUpdateDataTimer->IsActive() ) |
| { |
| //notify an update latest when the focus is lost |
| mpUpdateDataTimer->Stop(); |
| mpUpdateDataTimer->Timeout(); |
| } |
| |
| if ( !mpSubEdit ) |
| { |
| // FIXME: this is currently only on aqua |
| // check for other platforms that need similar handling |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| IsNativeWidgetEnabled() && |
| IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) ) |
| { |
| ImplInvalidateOutermostBorder( mbIsSubEdit ? GetParent() : this ); |
| } |
| |
| if ( !mbActivePopup && !( GetStyle() & WB_NOHIDESELECTION ) && maSelection.Len() ) |
| ImplInvalidateOrRepaint(); // Selektion malen |
| } |
| |
| Control::LoseFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Command( const CommandEvent& rCEvt ) |
| { |
| if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU ) |
| { |
| PopupMenu* pPopup = Edit::CreatePopupMenu(); |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| if ( rStyleSettings.GetOptions() & STYLE_OPTION_HIDEDISABLED ) |
| pPopup->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES ); |
| |
| if ( !maSelection.Len() ) |
| { |
| pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False ); |
| pPopup->EnableItem( SV_MENU_EDIT_COPY, sal_False ); |
| pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False ); |
| } |
| |
| if ( IsReadOnly() ) |
| { |
| pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False ); |
| pPopup->EnableItem( SV_MENU_EDIT_PASTE, sal_False ); |
| pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False ); |
| pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, sal_False ); |
| } |
| else |
| { |
| // Paste nur, wenn Text im Clipboard |
| sal_Bool bData = sal_False; |
| uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard(); |
| if ( xClipboard.is() ) |
| { |
| const sal_uInt32 nRef = Application::ReleaseSolarMutex(); |
| uno::Reference< datatransfer::XTransferable > xDataObj = xClipboard->getContents(); |
| Application::AcquireSolarMutex( nRef ); |
| if ( xDataObj.is() ) |
| { |
| datatransfer::DataFlavor aFlavor; |
| SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); |
| bData = xDataObj->isDataFlavorSupported( aFlavor ); |
| } |
| } |
| pPopup->EnableItem( SV_MENU_EDIT_PASTE, bData ); |
| } |
| |
| if ( maUndoText == maText ) |
| pPopup->EnableItem( SV_MENU_EDIT_UNDO, sal_False ); |
| if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) ) |
| pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, sal_False ); |
| if ( !pImplFncGetSpecialChars ) |
| { |
| sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL ); |
| pPopup->RemoveItem( nPos ); |
| pPopup->RemoveItem( nPos-1 ); |
| } |
| |
| mbActivePopup = sal_True; |
| Selection aSaveSel = GetSelection(); // Falls jemand in Get/LoseFocus die Selektion verbiegt, z.B. URL-Zeile... |
| Point aPos = rCEvt.GetMousePosPixel(); |
| if ( !rCEvt.IsMouseEvent() ) |
| { |
| // !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!! |
| Size aSize = GetOutputSizePixel(); |
| aPos = Point( aSize.Width()/2, aSize.Height()/2 ); |
| } |
| sal_uInt16 n = pPopup->Execute( this, aPos ); |
| Edit::DeletePopupMenu( pPopup ); |
| SetSelection( aSaveSel ); |
| switch ( n ) |
| { |
| case SV_MENU_EDIT_UNDO: |
| Undo(); |
| ImplModified(); |
| break; |
| case SV_MENU_EDIT_CUT: |
| Cut(); |
| ImplModified(); |
| break; |
| case SV_MENU_EDIT_COPY: |
| Copy(); |
| break; |
| case SV_MENU_EDIT_PASTE: |
| Paste(); |
| ImplModified(); |
| break; |
| case SV_MENU_EDIT_DELETE: |
| DeleteSelected(); |
| ImplModified(); |
| break; |
| case SV_MENU_EDIT_SELECTALL: |
| ImplSetSelection( Selection( 0, maText.Len() ) ); |
| break; |
| case SV_MENU_EDIT_INSERTSYMBOL: |
| { |
| XubString aChars = pImplFncGetSpecialChars( this, GetFont() ); |
| SetSelection( aSaveSel ); |
| if ( aChars.Len() ) |
| { |
| ImplInsertText( aChars ); |
| ImplModified(); |
| } |
| } |
| break; |
| } |
| mbActivePopup = sal_False; |
| } |
| else if ( rCEvt.GetCommand() == COMMAND_VOICE ) |
| { |
| const CommandVoiceData* pData = rCEvt.GetVoiceData(); |
| if ( pData->GetType() == VOICECOMMANDTYPE_DICTATION ) |
| { |
| switch ( pData->GetCommand() ) |
| { |
| case DICTATIONCOMMAND_UNKNOWN: |
| { |
| ReplaceSelected( pData->GetText() ); |
| } |
| break; |
| case DICTATIONCOMMAND_LEFT: |
| { |
| ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1 ) ) ); |
| } |
| break; |
| case DICTATIONCOMMAND_RIGHT: |
| { |
| ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_RIGHT, KEY_MOD1 ) ) ); |
| } |
| break; |
| case DICTATIONCOMMAND_UNDO: |
| { |
| Undo(); |
| } |
| break; |
| case DICTATIONCOMMAND_DEL: |
| { |
| ImplHandleKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1|KEY_SHIFT ) ) ); |
| DeleteSelected(); |
| } |
| break; |
| } |
| } |
| } |
| else if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT ) |
| { |
| DeleteSelected(); |
| delete mpIMEInfos; |
| xub_StrLen nPos = (xub_StrLen)maSelection.Max(); |
| mpIMEInfos = new Impl_IMEInfos( nPos, maText.Copy( nPos ) ); |
| mpIMEInfos->bWasCursorOverwrite = !IsInsertMode(); |
| } |
| else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT ) |
| { |
| sal_Bool bInsertMode = !mpIMEInfos->bWasCursorOverwrite; |
| delete mpIMEInfos; |
| mpIMEInfos = NULL; |
| // Font wieder ohne Attribute einstellen, wird jetzt im Repaint nicht |
| // mehr neu initialisiert |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| |
| SetInsertMode( bInsertMode ); |
| |
| ImplModified(); |
| |
| // #i25161# call auto complete handler for ext text commit also |
| if ( maAutocompleteHdl.IsSet() ) |
| { |
| if ( (maSelection.Min() == maSelection.Max()) && (maSelection.Min() == maText.Len()) ) |
| { |
| meAutocompleteAction = AUTOCOMPLETE_KEYINPUT; |
| maAutocompleteHdl.Call( this ); |
| } |
| } |
| } |
| else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT ) |
| { |
| const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); |
| |
| maText.Erase( mpIMEInfos->nPos, mpIMEInfos->nLen ); |
| maText.Insert( pData->GetText(), mpIMEInfos->nPos ); |
| if ( mpIMEInfos->bWasCursorOverwrite ) |
| { |
| sal_uInt16 nOldIMETextLen = mpIMEInfos->nLen; |
| sal_uInt16 nNewIMETextLen = pData->GetText().Len(); |
| if ( ( nOldIMETextLen > nNewIMETextLen ) && |
| ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) ) |
| { |
| // restore old characters |
| sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen; |
| maText.Insert( mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ), mpIMEInfos->nPos + nNewIMETextLen ); |
| } |
| else if ( ( nOldIMETextLen < nNewIMETextLen ) && |
| ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) ) |
| { |
| // overwrite |
| sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen; |
| if ( ( nOldIMETextLen + nOverwrite ) > mpIMEInfos->aOldTextAfterStartPos.Len() ) |
| nOverwrite = mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen; |
| maText.Erase( mpIMEInfos->nPos + nNewIMETextLen, nOverwrite ); |
| } |
| } |
| |
| |
| if ( pData->GetTextAttr() ) |
| { |
| mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() ); |
| mpIMEInfos->bCursor = pData->IsCursorVisible(); |
| } |
| else |
| { |
| mpIMEInfos->DestroyAttribs(); |
| } |
| |
| ImplAlignAndPaint(); |
| xub_StrLen nCursorPos = mpIMEInfos->nPos + pData->GetCursorPos(); |
| SetSelection( Selection( nCursorPos, nCursorPos ) ); |
| SetInsertMode( !pData->IsCursorOverwrite() ); |
| |
| if ( pData->IsCursorVisible() ) |
| GetCursor()->Show(); |
| else |
| GetCursor()->Hide(); |
| } |
| else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS ) |
| { |
| if ( mpIMEInfos ) |
| { |
| xub_StrLen nCursorPos = (sal_uInt16)GetSelection().Max(); |
| SetCursorRect( NULL, GetTextWidth( |
| maText, nCursorPos, mpIMEInfos->nPos+mpIMEInfos->nLen-nCursorPos ) ); |
| } |
| else |
| { |
| SetCursorRect(); |
| } |
| } |
| else if ( rCEvt.GetCommand() == COMMAND_SELECTIONCHANGE ) |
| { |
| const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData(); |
| Selection aSelection( pData->GetStart(), pData->GetEnd() ); |
| SetSelection(aSelection); |
| } |
| else |
| Control::Command( rCEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::StateChanged( StateChangedType nType ) |
| { |
| if ( nType == STATE_CHANGE_INITSHOW ) |
| { |
| if ( !mpSubEdit ) |
| { |
| mnXOffset = 0; // Falls vorher GrabFocus, als Groesse noch falsch. |
| ImplAlign(); |
| if ( !mpSubEdit ) |
| ImplShowCursor( sal_False ); |
| } |
| // update background (eventual SetPaintTransparent) |
| ImplInitSettings( sal_False, sal_False, sal_True ); |
| } |
| else if ( nType == STATE_CHANGE_ENABLE ) |
| { |
| if ( !mpSubEdit ) |
| { |
| // Es aendert sich nur die Textfarbe... |
| ImplInvalidateOrRepaint( 0, 0xFFFF ); |
| } |
| } |
| else if ( nType == STATE_CHANGE_STYLE || nType == STATE_CHANGE_MIRRORING ) |
| { |
| WinBits nStyle = GetStyle(); |
| if( nType == STATE_CHANGE_STYLE ) |
| { |
| nStyle = ImplInitStyle( GetStyle() ); |
| SetStyle( nStyle ); |
| } |
| |
| sal_uInt16 nOldAlign = mnAlign; |
| mnAlign = EDIT_ALIGN_LEFT; |
| |
| // --- RTL --- hack: right align until keyinput and cursor travelling works |
| // edits are always RTL disabled |
| // however the parent edits contain the correct setting |
| if( mbIsSubEdit && GetParent()->IsRTLEnabled() ) |
| { |
| if( GetParent()->GetStyle() & WB_LEFT ) |
| mnAlign = EDIT_ALIGN_RIGHT; |
| if ( nType == STATE_CHANGE_MIRRORING ) |
| SetLayoutMode( TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT ); |
| } |
| else if( mbIsSubEdit && !GetParent()->IsRTLEnabled() ) |
| { |
| if ( nType == STATE_CHANGE_MIRRORING ) |
| SetLayoutMode( TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_TEXTORIGIN_LEFT ); |
| } |
| |
| if ( nStyle & WB_RIGHT ) |
| mnAlign = EDIT_ALIGN_RIGHT; |
| else if ( nStyle & WB_CENTER ) |
| mnAlign = EDIT_ALIGN_CENTER; |
| if ( maText.Len() && ( mnAlign != nOldAlign ) ) |
| { |
| ImplAlign(); |
| Invalidate(); |
| } |
| |
| } |
| else if ( nType == STATE_CHANGE_ZOOM ) |
| { |
| if ( !mpSubEdit ) |
| { |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| ImplShowCursor( sal_True ); |
| Invalidate(); |
| } |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFONT ) |
| { |
| if ( !mpSubEdit ) |
| { |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| ImplShowCursor(); |
| Invalidate(); |
| } |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) |
| { |
| if ( !mpSubEdit ) |
| { |
| ImplInitSettings( sal_False, sal_True, sal_False ); |
| Invalidate(); |
| } |
| } |
| else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) |
| { |
| if ( !mpSubEdit ) |
| { |
| ImplInitSettings( sal_False, sal_False, sal_True ); |
| Invalidate(); |
| } |
| } |
| |
| Control::StateChanged( nType ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || |
| (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || |
| ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) |
| { |
| if ( !mpSubEdit ) |
| { |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| ImplShowCursor( sal_True ); |
| Invalidate(); |
| } |
| } |
| |
| Control::DataChanged( rDCEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplShowDDCursor() |
| { |
| if ( !mpDDInfo->bVisCursor ) |
| { |
| long nTextWidth = GetTextWidth( maText, 0, mpDDInfo->nDropPos ); |
| long nTextHeight = GetTextHeight(); |
| Rectangle aCursorRect( Point( nTextWidth + mnXOffset, (GetOutputSize().Height()-nTextHeight)/2 ), Size( 2, nTextHeight ) ); |
| mpDDInfo->aCursor.SetWindow( this ); |
| mpDDInfo->aCursor.SetPos( aCursorRect.TopLeft() ); |
| mpDDInfo->aCursor.SetSize( aCursorRect.GetSize() ); |
| mpDDInfo->aCursor.Show(); |
| mpDDInfo->bVisCursor = sal_True; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplHideDDCursor() |
| { |
| if ( mpDDInfo && mpDDInfo->bVisCursor ) |
| { |
| mpDDInfo->aCursor.Hide(); |
| mpDDInfo->bVisCursor = sal_False; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Modify() |
| { |
| if ( mbIsSubEdit ) |
| { |
| ((Edit*)GetParent())->Modify(); |
| } |
| else |
| { |
| if ( mpUpdateDataTimer ) |
| mpUpdateDataTimer->Start(); |
| |
| if ( ImplCallEventListenersAndHandler( VCLEVENT_EDIT_MODIFY, maModifyHdl, this ) ) |
| // have been destroyed while calling into the handlers |
| return; |
| |
| // #i13677# notify edit listeners about caret position change |
| //ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED ); |
| ImplCallEventListeners( VCLEVENT_EDIT_CARETCHANGED ); |
| // FIXME: this is currently only on aqua |
| // check for other platforms that need similar handling |
| if( ImplGetSVData()->maNWFData.mbNoFocusRects && |
| IsNativeWidgetEnabled() && |
| IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) ) |
| { |
| ImplInvalidateOutermostBorder( this ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::UpdateData() |
| { |
| maUpdateDataHdl.Call( this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( Edit, ImplUpdateDataHdl, Timer*, EMPTYARG ) |
| { |
| UpdateData(); |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::EnableUpdateData( sal_uLong nTimeout ) |
| { |
| if ( !nTimeout ) |
| DisableUpdateData(); |
| else |
| { |
| if ( !mpUpdateDataTimer ) |
| { |
| mpUpdateDataTimer = new Timer; |
| mpUpdateDataTimer->SetTimeoutHdl( LINK( this, Edit, ImplUpdateDataHdl ) ); |
| } |
| |
| mpUpdateDataTimer->SetTimeout( nTimeout ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetEchoChar( xub_Unicode c ) |
| { |
| mcEchoChar = c; |
| if ( mpSubEdit ) |
| mpSubEdit->SetEchoChar( c ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetReadOnly( sal_Bool bReadOnly ) |
| { |
| if ( mbReadOnly != bReadOnly ) |
| { |
| mbReadOnly = bReadOnly; |
| if ( mpSubEdit ) |
| mpSubEdit->SetReadOnly( bReadOnly ); |
| |
| StateChanged( STATE_CHANGE_READONLY ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetAutocompleteHdl( const Link& rHdl ) |
| { |
| maAutocompleteHdl = rHdl; |
| if ( mpSubEdit ) |
| mpSubEdit->SetAutocompleteHdl( rHdl ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetInsertMode( sal_Bool bInsert ) |
| { |
| if ( bInsert != mbInsertMode ) |
| { |
| mbInsertMode = bInsert; |
| if ( mpSubEdit ) |
| mpSubEdit->SetInsertMode( bInsert ); |
| else |
| ImplShowCursor(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool Edit::IsInsertMode() const |
| { |
| if ( mpSubEdit ) |
| return mpSubEdit->IsInsertMode(); |
| else |
| return mbInsertMode; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetMaxTextLen( xub_StrLen nMaxLen ) |
| { |
| mnMaxTextLen = nMaxLen ? nMaxLen : EDIT_NOLIMIT; |
| |
| if ( mpSubEdit ) |
| mpSubEdit->SetMaxTextLen( mnMaxTextLen ); |
| else |
| { |
| if ( maText.Len() > mnMaxTextLen ) |
| ImplDelete( Selection( mnMaxTextLen, maText.Len() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetSelection( const Selection& rSelection ) |
| { |
| // Wenn von aussen z.B. im MouseButtonDown die Selektion geaendert wird, |
| // soll nicht gleich ein Tracking() zuschlagen und die Selektion aendern. |
| if ( IsTracking() ) |
| EndTracking(); |
| else if ( mpSubEdit && mpSubEdit->IsTracking() ) |
| mpSubEdit->EndTracking(); |
| |
| ImplSetSelection( rSelection ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ImplSetSelection( const Selection& rSelection, sal_Bool bPaint ) |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->ImplSetSelection( rSelection ); |
| else |
| { |
| if ( rSelection != maSelection ) |
| { |
| Selection aOld( maSelection ); |
| Selection aNew( rSelection ); |
| |
| if ( aNew.Min() > maText.Len() ) |
| aNew.Min() = maText.Len(); |
| if ( aNew.Max() > maText.Len() ) |
| aNew.Max() = maText.Len(); |
| if ( aNew.Min() < 0 ) |
| aNew.Min() = 0; |
| if ( aNew.Max() < 0 ) |
| aNew.Max() = 0; |
| |
| if ( aNew != maSelection ) |
| { |
| ImplClearLayoutData(); |
| Selection aTemp = maSelection; |
| maSelection = aNew; |
| |
| if ( bPaint && ( aOld.Len() || aNew.Len() || IsPaintTransparent() ) ) |
| ImplInvalidateOrRepaint( 0, maText.Len() ); |
| ImplShowCursor(); |
| sal_Bool bCaret = sal_False, bSelection = sal_False; |
| long nB=aNew.Max(), nA=aNew.Min(),oB=aTemp.Max(), oA=aTemp.Min(); |
| long nGap = nB-nA, oGap = oB-oA; |
| if (nB != oB) |
| bCaret = sal_True; |
| if (nGap != 0 || oGap != 0) |
| bSelection = sal_True; |
| if (bCaret) |
| { |
| if ( mbIsSubEdit ) |
| ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_CARETCHANGED ); |
| else |
| ImplCallEventListeners( VCLEVENT_EDIT_CARETCHANGED ); |
| } |
| if (bSelection) |
| { |
| if ( mbIsSubEdit ) |
| ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED ); |
| else |
| ImplCallEventListeners( VCLEVENT_EDIT_SELECTIONCHANGED ); |
| } |
| // #103511# notify combobox listeners of deselection |
| if( !maSelection && GetParent() && GetParent()->GetType() == WINDOW_COMBOBOX ) |
| ((Edit*)GetParent())->ImplCallEventListeners( VCLEVENT_COMBOBOX_DESELECT ); |
| } |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const Selection& Edit::GetSelection() const |
| { |
| if ( mpSubEdit ) |
| return mpSubEdit->GetSelection(); |
| else |
| return maSelection; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ReplaceSelected( const XubString& rStr ) |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->ReplaceSelected( rStr ); |
| else |
| ImplInsertText( rStr ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::DeleteSelected() |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->DeleteSelected(); |
| else |
| { |
| if ( maSelection.Len() ) |
| ImplDelete( maSelection, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString Edit::GetSelected() const |
| { |
| if ( mpSubEdit ) |
| return mpSubEdit->GetSelected(); |
| else |
| { |
| Selection aSelection( maSelection ); |
| aSelection.Justify(); |
| return maText.Copy( (xub_StrLen)aSelection.Min(), (xub_StrLen)aSelection.Len() ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Cut() |
| { |
| if ( !(GetStyle() & WB_PASSWORD ) ) |
| { |
| Copy(); |
| ReplaceSelected( ImplGetSVEmptyStr() ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Copy() |
| { |
| if ( !(GetStyle() & WB_PASSWORD ) ) |
| { |
| ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipboard(GetClipboard()); |
| ImplCopy( aClipboard ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Paste() |
| { |
| ::com::sun::star::uno::Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipboard(GetClipboard()); |
| ImplPaste( aClipboard ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::Undo() |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->Undo(); |
| else |
| { |
| XubString aText( maText ); |
| ImplDelete( Selection( 0, aText.Len() ), EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE ); |
| ImplInsertText( maUndoText ); |
| ImplSetSelection( Selection( 0, maUndoText.Len() ) ); |
| maUndoText = aText; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetText( const XubString& rStr ) |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->SetText( rStr ); // Nicht direkt ImplSetText, falls SetText ueberladen |
| else |
| { |
| Selection aNewSel( 0, 0 ); // Damit nicht gescrollt wird |
| ImplSetText( rStr, &aNewSel ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetText( const XubString& rStr, const Selection& rSelection ) |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->SetText( rStr, rSelection ); |
| else |
| ImplSetText( rStr, &rSelection ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString Edit::GetText() const |
| { |
| if ( mpSubEdit ) |
| return mpSubEdit->GetText(); |
| else |
| return maText; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetModifyFlag() |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->mbModified = sal_True; |
| else |
| mbModified = sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::ClearModifyFlag() |
| { |
| if ( mpSubEdit ) |
| mpSubEdit->mbModified = sal_False; |
| else |
| mbModified = sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetSubEdit( Edit* pEdit ) |
| { |
| mpSubEdit = pEdit; |
| if ( mpSubEdit ) |
| { |
| SetPointer( POINTER_ARROW ); // Nur das SubEdit hat den BEAM... |
| mpSubEdit->mbIsSubEdit = sal_True; |
| |
| mpSubEdit->SetReadOnly( mbReadOnly ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size Edit::CalcMinimumSize() const |
| { |
| Size aSize ( GetTextWidth( GetText() ), GetTextHeight() ); |
| // do not create edit fields in which one cannot enter anything |
| // a default minimum width should exist for at least 3 characters |
| Size aMinSize ( CalcSize( 3 ) ); |
| if( aSize.Width() < aMinSize.Width() ) |
| aSize.Width() = aMinSize.Width(); |
| // add some space between text entry and border |
| aSize.Height() += 4; |
| |
| aSize = CalcWindowSize( aSize ); |
| |
| // ask NWF what if it has an opinion, too |
| ImplControlValue aControlValue; |
| Rectangle aRect( Point( 0, 0 ), aSize ); |
| Rectangle aContent, aBound; |
| if( const_cast<Edit*>(this)->GetNativeControlRegion( |
| CTRL_EDITBOX, PART_ENTIRE_CONTROL, |
| aRect, 0, aControlValue, rtl::OUString(), aBound, aContent) ) |
| { |
| if( aBound.GetHeight() > aSize.Height() ) |
| aSize.Height() = aBound.GetHeight(); |
| } |
| return aSize; |
| } |
| |
| Size Edit::GetMinimumEditSize() |
| { |
| Window* pDefWin = ImplGetDefaultWindow(); |
| Edit aEdit( pDefWin, WB_BORDER ); |
| Size aSize( aEdit.CalcMinimumSize() ); |
| return aSize; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size Edit::GetOptimalSize(WindowSizeType eType) const |
| { |
| switch (eType) { |
| case WINDOWSIZE_MINIMUM: |
| return CalcMinimumSize(); |
| default: |
| return Control::GetOptimalSize( eType ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size Edit::CalcSize( xub_StrLen nChars ) const |
| { |
| // Breite fuer n Zeichen, unabhaengig vom Inhalt. |
| // Funktioniert nur bei FixedFont richtig, sonst Mittelwert. |
| Size aSz( GetTextWidth( XubString( 'x' ) ), GetTextHeight() ); |
| aSz.Width() *= nChars; |
| aSz = CalcWindowSize( aSz ); |
| return aSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| xub_StrLen Edit::GetMaxVisChars() const |
| { |
| const Window* pW = mpSubEdit ? mpSubEdit : this; |
| long nOutWidth = pW->GetOutputSizePixel().Width(); |
| long nCharWidth = GetTextWidth( XubString( 'x' ) ); |
| return nCharWidth ? (xub_StrLen)(nOutWidth/nCharWidth) : 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| xub_StrLen Edit::GetCharPos( const Point& rWindowPos ) const |
| { |
| return ImplGetCharPos( rWindowPos ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::SetGetSpecialCharsFunction( FncGetSpecialChars fn ) |
| { |
| pImplFncGetSpecialChars = fn; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| FncGetSpecialChars Edit::GetGetSpecialCharsFunction() |
| { |
| return pImplFncGetSpecialChars; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| PopupMenu* Edit::CreatePopupMenu() |
| { |
| ResMgr* pResMgr = ImplGetResMgr(); |
| if( ! pResMgr ) |
| return new PopupMenu(); |
| |
| PopupMenu* pPopup = new PopupMenu( ResId( SV_RESID_MENU_EDIT, *pResMgr ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_UNDO, KeyCode( KEYFUNC_UNDO ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_CUT, KeyCode( KEYFUNC_CUT ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_COPY, KeyCode( KEYFUNC_COPY ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_PASTE, KeyCode( KEYFUNC_PASTE ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_DELETE, KeyCode( KEYFUNC_DELETE ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_SELECTALL, KeyCode( KEY_A, sal_False, sal_True, sal_False, sal_False ) ); |
| pPopup->SetAccelKey( SV_MENU_EDIT_INSERTSYMBOL, KeyCode( KEY_S, sal_True, sal_True, sal_False, sal_False ) ); |
| return pPopup; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void Edit::DeletePopupMenu( PopupMenu* pMenu ) |
| { |
| delete pMenu; |
| } |
| |
| // ::com::sun::star::datatransfer::dnd::XDragGestureListener |
| void Edit::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| vos::OGuard aVclGuard( Application::GetSolarMutex() ); |
| |
| if ( !IsTracking() && maSelection.Len() && |
| !(GetStyle() & WB_PASSWORD) && (!mpDDInfo || mpDDInfo->bStarterOfDD == sal_False) ) // Kein Mehrfach D&D |
| { |
| Selection aSel( maSelection ); |
| aSel.Justify(); |
| |
| // Nur wenn Maus in der Selektion... |
| Point aMousePos( rDGE.DragOriginX, rDGE.DragOriginY ); |
| xub_StrLen nChar = ImplGetCharPos( aMousePos ); |
| if ( (nChar >= aSel.Min()) && (nChar < aSel.Max()) ) |
| { |
| if ( !mpDDInfo ) |
| mpDDInfo = new DDInfo; |
| |
| mpDDInfo->bStarterOfDD = sal_True; |
| mpDDInfo->aDndStartSel = aSel; |
| |
| |
| if ( IsTracking() ) |
| EndTracking(); // Vor D&D Tracking ausschalten |
| |
| ::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( GetSelected() ); |
| sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY; |
| if ( !IsReadOnly() ) |
| nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE; |
| rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mxDnDListener ); |
| if ( GetCursor() ) |
| GetCursor()->Hide(); |
| |
| } |
| } |
| } |
| |
| // ::com::sun::star::datatransfer::dnd::XDragSourceListener |
| void Edit::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& rDSDE ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| vos::OGuard aVclGuard( Application::GetSolarMutex() ); |
| |
| if ( rDSDE.DropSuccess && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) ) |
| { |
| Selection aSel( mpDDInfo->aDndStartSel ); |
| if ( mpDDInfo->bDroppedInMe ) |
| { |
| if ( aSel.Max() > mpDDInfo->nDropPos ) |
| { |
| long nLen = aSel.Len(); |
| aSel.Min() += nLen; |
| aSel.Max() += nLen; |
| } |
| } |
| ImplDelete( aSel, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE ); |
| ImplModified(); |
| } |
| |
| ImplHideDDCursor(); |
| delete mpDDInfo; |
| mpDDInfo = NULL; |
| } |
| |
| // ::com::sun::star::datatransfer::dnd::XDropTargetListener |
| void Edit::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| vos::OGuard aVclGuard( Application::GetSolarMutex() ); |
| |
| sal_Bool bChanges = sal_False; |
| if ( !mbReadOnly && mpDDInfo ) |
| { |
| ImplHideDDCursor(); |
| |
| Selection aSel( maSelection ); |
| aSel.Justify(); |
| |
| if ( aSel.Len() && !mpDDInfo->bStarterOfDD ) |
| ImplDelete( aSel, EDIT_DEL_RIGHT, EDIT_DELMODE_SIMPLE ); |
| |
| mpDDInfo->bDroppedInMe = sal_True; |
| |
| aSel.Min() = mpDDInfo->nDropPos; |
| aSel.Max() = mpDDInfo->nDropPos; |
| ImplSetSelection( aSel ); |
| |
| uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable; |
| if ( xDataObj.is() ) |
| { |
| datatransfer::DataFlavor aFlavor; |
| SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); |
| if ( xDataObj->isDataFlavorSupported( aFlavor ) ) |
| { |
| uno::Any aData = xDataObj->getTransferData( aFlavor ); |
| ::rtl::OUString aText; |
| aData >>= aText; |
| ImplInsertText( aText ); |
| bChanges = sal_True; |
| ImplModified(); |
| } |
| } |
| |
| if ( !mpDDInfo->bStarterOfDD ) |
| { |
| delete mpDDInfo; |
| mpDDInfo = NULL; |
| } |
| } |
| |
| rDTDE.Context->dropComplete( bChanges ); |
| } |
| |
| void Edit::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| if ( !mpDDInfo ) |
| { |
| mpDDInfo = new DDInfo; |
| } |
| // search for string data type |
| const Sequence< com::sun::star::datatransfer::DataFlavor >& rFlavors( rDTDE.SupportedDataFlavors ); |
| sal_Int32 nEle = rFlavors.getLength(); |
| mpDDInfo->bIsStringSupported = sal_False; |
| for( sal_Int32 i = 0; i < nEle; i++ ) |
| { |
| sal_Int32 nIndex = 0; |
| rtl::OUString aMimetype = rFlavors[i].MimeType.getToken( 0, ';', nIndex ); |
| if( aMimetype.equalsAscii( "text/plain" ) ) |
| { |
| mpDDInfo->bIsStringSupported = sal_True; |
| break; |
| } |
| } |
| } |
| |
| void Edit::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| vos::OGuard aVclGuard( Application::GetSolarMutex() ); |
| |
| ImplHideDDCursor(); |
| } |
| |
| void Edit::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| vos::OGuard aVclGuard( Application::GetSolarMutex() ); |
| |
| Point aMousePos( rDTDE.LocationX, rDTDE.LocationY ); |
| |
| xub_StrLen nPrevDropPos = mpDDInfo->nDropPos; |
| mpDDInfo->nDropPos = ImplGetCharPos( aMousePos ); |
| |
| /* |
| Size aOutSize = GetOutputSizePixel(); |
| if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) ) |
| { |
| // Scroll? |
| // No, I will not receive events in this case.... |
| } |
| */ |
| |
| Selection aSel( maSelection ); |
| aSel.Justify(); |
| |
| // Don't accept drop in selection or read-only field... |
| if ( IsReadOnly() || aSel.IsInside( mpDDInfo->nDropPos ) || ! mpDDInfo->bIsStringSupported ) |
| { |
| ImplHideDDCursor(); |
| rDTDE.Context->rejectDrag(); |
| } |
| else |
| { |
| // Alten Cursor wegzeichnen... |
| if ( !mpDDInfo->bVisCursor || ( nPrevDropPos != mpDDInfo->nDropPos ) ) |
| { |
| ImplHideDDCursor(); |
| ImplShowDDCursor(); |
| } |
| rDTDE.Context->acceptDrag( rDTDE.DropAction ); |
| } |
| } |
| |
| ImplSubEdit::ImplSubEdit( Edit* pParent, WinBits nStyle ) : |
| Edit( pParent, nStyle ) |
| { |
| pParent->SetSubEdit( this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplSubEdit::Modify() |
| { |
| GetParent()->Modify(); |
| } |
| |
| XubString Edit::GetSurroundingText() const |
| { |
| if ( mpSubEdit ) |
| return mpSubEdit->GetSurroundingText(); |
| else |
| return maText; |
| } |
| |
| Selection Edit::GetSurroundingTextSelection() const |
| { |
| return GetSelection(); |
| } |