LCOV - code coverage report
Current view: top level - vcl/source/edit - textview.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1256 0.0 %
Date: 2014-04-14 Functions: 0 110 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <vcl/textview.hxx>
      21             : #include <vcl/texteng.hxx>
      22             : #include <vcl/settings.hxx>
      23             : #include <textdoc.hxx>
      24             : #include <vcl/textdata.hxx>
      25             : #include <textdat2.hxx>
      26             : 
      27             : #include <svl/undo.hxx>
      28             : #include <vcl/cursor.hxx>
      29             : #include <vcl/window.hxx>
      30             : #include <vcl/svapp.hxx>
      31             : #include <tools/stream.hxx>
      32             : 
      33             : #include <sot/formats.hxx>
      34             : #include <svl/urlbmk.hxx>
      35             : 
      36             : #include <com/sun/star/i18n/XBreakIterator.hpp>
      37             : 
      38             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      39             : 
      40             : #include <com/sun/star/i18n/WordType.hpp>
      41             : #include <cppuhelper/weak.hxx>
      42             : #include <vcl/unohelp.hxx>
      43             : #include <com/sun/star/datatransfer/XTransferable.hpp>
      44             : #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
      45             : #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
      46             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      47             : 
      48             : #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
      49             : #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
      50             : #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
      51             : 
      52             : #include <vcl/edit.hxx>
      53             : 
      54             : #include <sot/exchange.hxx>
      55             : 
      56             : #include <osl/mutex.hxx>
      57             : 
      58             : using namespace ::com::sun::star;
      59             : 
      60             : class TETextDataObject :    public ::com::sun::star::datatransfer::XTransferable,
      61             :                         public ::cppu::OWeakObject
      62             : 
      63             : {
      64             : private:
      65             :     OUString        maText;
      66             :     SvMemoryStream  maHTMLStream;
      67             : 
      68             : public:
      69             :                     TETextDataObject( const OUString& rText );
      70             :                     virtual ~TETextDataObject();
      71             : 
      72           0 :     OUString&        GetText() { return maText; }
      73           0 :     SvMemoryStream& GetHTMLStream() { return maHTMLStream; }
      74             : 
      75             :     // ::com::sun::star::uno::XInterface
      76             :     ::com::sun::star::uno::Any                  SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      77           0 :     void                                        SAL_CALL acquire() throw() SAL_OVERRIDE  { OWeakObject::acquire(); }
      78           0 :     void                                        SAL_CALL release() throw() SAL_OVERRIDE  { OWeakObject::release(); }
      79             : 
      80             :     // ::com::sun::star::datatransfer::XTransferable
      81             :     ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      82             :     ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors(  ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      83             :     sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      84             : };
      85             : 
      86           0 : TETextDataObject::TETextDataObject( const OUString& rText ) : maText( rText )
      87             : {
      88           0 : }
      89             : 
      90           0 : TETextDataObject::~TETextDataObject()
      91             : {
      92           0 : }
      93             : 
      94             : // uno::XInterface
      95           0 : uno::Any TETextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException, std::exception)
      96             : {
      97           0 :     uno::Any aRet = ::cppu::queryInterface( rType, (static_cast< datatransfer::XTransferable* >(this)) );
      98           0 :     return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
      99             : }
     100             : 
     101             : // datatransfer::XTransferable
     102           0 : uno::Any TETextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException, std::exception)
     103             : {
     104           0 :     uno::Any aAny;
     105             : 
     106           0 :     sal_uLong nT = SotExchange::GetFormat( rFlavor );
     107           0 :     if ( nT == SOT_FORMAT_STRING )
     108             :     {
     109           0 :         aAny <<= (OUString)GetText();
     110             :     }
     111           0 :     else if ( nT == SOT_FORMATSTR_ID_HTML )
     112             :     {
     113           0 :         GetHTMLStream().Seek( STREAM_SEEK_TO_END );
     114           0 :         sal_uLong nLen = GetHTMLStream().Tell();
     115           0 :         GetHTMLStream().Seek(0);
     116             : 
     117           0 :         uno::Sequence< sal_Int8 > aSeq( nLen );
     118           0 :         memcpy( aSeq.getArray(), GetHTMLStream().GetData(), nLen );
     119           0 :         aAny <<= aSeq;
     120             :     }
     121             :     else
     122             :     {
     123           0 :         throw datatransfer::UnsupportedFlavorException();
     124             :     }
     125           0 :     return aAny;
     126             : }
     127             : 
     128           0 : uno::Sequence< datatransfer::DataFlavor > TETextDataObject::getTransferDataFlavors(  ) throw(uno::RuntimeException, std::exception)
     129             : {
     130           0 :     GetHTMLStream().Seek( STREAM_SEEK_TO_END );
     131           0 :     bool bHTML = GetHTMLStream().Tell() > 0;
     132           0 :     uno::Sequence< datatransfer::DataFlavor > aDataFlavors( bHTML ? 2 : 1 );
     133           0 :     SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] );
     134           0 :     if ( bHTML )
     135           0 :         SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_HTML, aDataFlavors.getArray()[1] );
     136           0 :     return aDataFlavors;
     137             : }
     138             : 
     139           0 : sal_Bool TETextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException, std::exception)
     140             : {
     141           0 :     sal_uLong nT = SotExchange::GetFormat( rFlavor );
     142           0 :     return ( nT == SOT_FORMAT_STRING );
     143             : }
     144             : 
     145           0 : struct ImpTextView
     146             : {
     147             :     TextEngine*         mpTextEngine;
     148             : 
     149             :     Window*             mpWindow;
     150             :     TextSelection       maSelection;
     151             :     Point               maStartDocPos;
     152             : //    TextPaM             maMBDownPaM;
     153             : 
     154             :     Cursor*             mpCursor;
     155             : 
     156             :     TextDDInfo*         mpDDInfo;
     157             : 
     158             :     VirtualDevice*      mpVirtDev;
     159             : 
     160             :     SelectionEngine*    mpSelEngine;
     161             :     TextSelFunctionSet* mpSelFuncSet;
     162             : 
     163             :     ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener > mxDnDListener;
     164             : 
     165             :     sal_uInt16              mnTravelXPos;
     166             : 
     167             :     bool                mbAutoScroll            : 1;
     168             :     bool                mbInsertMode            : 1;
     169             :     bool                mbReadOnly              : 1;
     170             :     bool                mbPaintSelection        : 1;
     171             :     bool                mbAutoIndent            : 1;
     172             :     bool                mbHighlightSelection    : 1;
     173             :     bool                mbCursorEnabled         : 1;
     174             :     bool                mbClickedInSelection    : 1;
     175             :     bool                mbSupportProtectAttribute : 1;
     176             :     bool                mbCursorAtEndOfLine;
     177             : };
     178             : 
     179           0 : TextView::TextView( TextEngine* pEng, Window* pWindow ) :
     180           0 :     mpImpl(new ImpTextView)
     181             : {
     182           0 :     pWindow->EnableRTL( false );
     183             : 
     184           0 :     mpImpl->mpWindow = pWindow;
     185           0 :     mpImpl->mpTextEngine = pEng;
     186           0 :     mpImpl->mpVirtDev = NULL;
     187             : 
     188           0 :     mpImpl->mbPaintSelection = true;
     189           0 :     mpImpl->mbAutoScroll = true;
     190           0 :     mpImpl->mbInsertMode = true;
     191           0 :     mpImpl->mbReadOnly = false;
     192           0 :     mpImpl->mbHighlightSelection = false;
     193           0 :     mpImpl->mbAutoIndent = false;
     194           0 :     mpImpl->mbCursorEnabled = true;
     195           0 :     mpImpl->mbClickedInSelection = false;
     196           0 :     mpImpl->mbSupportProtectAttribute = false;
     197           0 :     mpImpl->mbCursorAtEndOfLine = false;
     198             : //  mbInSelection = false;
     199             : 
     200           0 :     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
     201             : 
     202           0 :     mpImpl->mpSelFuncSet = new TextSelFunctionSet( this );
     203           0 :     mpImpl->mpSelEngine = new SelectionEngine( mpImpl->mpWindow, mpImpl->mpSelFuncSet );
     204           0 :     mpImpl->mpSelEngine->SetSelectionMode( RANGE_SELECTION );
     205           0 :     mpImpl->mpSelEngine->EnableDrag( true );
     206             : 
     207           0 :     mpImpl->mpCursor = new Cursor;
     208           0 :     mpImpl->mpCursor->Show();
     209           0 :     pWindow->SetCursor( mpImpl->mpCursor );
     210           0 :     pWindow->SetInputContext( InputContext( pEng->GetFont(), INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT ) );
     211             : 
     212           0 :     if ( pWindow->GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_INVERT )
     213           0 :         mpImpl->mbHighlightSelection = true;
     214             : 
     215           0 :     pWindow->SetLineColor();
     216             : 
     217           0 :     mpImpl->mpDDInfo = NULL;
     218             : 
     219           0 :     if ( pWindow->GetDragGestureRecognizer().is() )
     220             :     {
     221           0 :         vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this );
     222           0 :         mpImpl->mxDnDListener = pDnDWrapper;
     223             : 
     224           0 :         uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mpImpl->mxDnDListener, uno::UNO_QUERY );
     225           0 :         pWindow->GetDragGestureRecognizer()->addDragGestureListener( xDGL );
     226           0 :         uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
     227           0 :         pWindow->GetDropTarget()->addDropTargetListener( xDTL );
     228           0 :         pWindow->GetDropTarget()->setActive( true );
     229           0 :         pWindow->GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
     230             :     }
     231           0 : }
     232             : 
     233           0 : TextView::~TextView()
     234             : {
     235           0 :     delete mpImpl->mpSelEngine;
     236           0 :     delete mpImpl->mpSelFuncSet;
     237           0 :     delete mpImpl->mpVirtDev;
     238             : 
     239           0 :     if ( mpImpl->mpWindow->GetCursor() == mpImpl->mpCursor )
     240           0 :         mpImpl->mpWindow->SetCursor( 0 );
     241           0 :     delete mpImpl->mpCursor;
     242           0 :     delete mpImpl->mpDDInfo;
     243           0 :     delete mpImpl;
     244           0 : }
     245             : 
     246           0 : void TextView::Invalidate()
     247             : {
     248           0 :     mpImpl->mpWindow->Invalidate();
     249           0 : }
     250             : 
     251           0 : void TextView::SetSelection( const TextSelection& rTextSel, bool bGotoCursor )
     252             : {
     253             :     // if someone left an empty attribute and then the Outliner manipulated the selection
     254           0 :     if ( !mpImpl->maSelection.HasRange() )
     255           0 :         mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
     256             : 
     257             :     // if the selection is manipulated after a KeyInput
     258           0 :     mpImpl->mpTextEngine->CheckIdleFormatter();
     259             : 
     260           0 :     HideSelection();
     261           0 :     TextSelection aNewSel( rTextSel );
     262           0 :     mpImpl->mpTextEngine->ValidateSelection( aNewSel );
     263           0 :     ImpSetSelection( aNewSel );
     264           0 :     ShowSelection();
     265           0 :     ShowCursor( bGotoCursor );
     266           0 : }
     267             : 
     268           0 : void TextView::SetSelection( const TextSelection& rTextSel )
     269             : {
     270           0 :     SetSelection( rTextSel, mpImpl->mbAutoScroll );
     271           0 : }
     272             : 
     273           0 : const TextSelection& TextView::GetSelection() const
     274             : {
     275           0 :     return mpImpl->maSelection;
     276             : }
     277           0 : TextSelection&      TextView::GetSelection()
     278             : {
     279           0 :     return mpImpl->maSelection;
     280             : }
     281             : 
     282           0 : void TextView::DeleteSelected()
     283             : {
     284             : //  HideSelection();
     285             : 
     286           0 :     mpImpl->mpTextEngine->UndoActionStart();
     287           0 :     TextPaM aPaM = mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
     288           0 :     mpImpl->mpTextEngine->UndoActionEnd();
     289             : 
     290           0 :     ImpSetSelection( aPaM );
     291           0 :     mpImpl->mpTextEngine->FormatAndUpdate( this );
     292           0 :     ShowCursor();
     293           0 : }
     294             : 
     295           0 : void TextView::ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection )
     296             : {
     297           0 :     if ( !mpImpl->mbPaintSelection )
     298           0 :         pSelection = NULL;
     299             :     else
     300             :     {
     301             :         // set correct background color;
     302             :         // unfortunately we cannot detect if it has changed
     303           0 :         Font aFont = mpImpl->mpTextEngine->GetFont();
     304           0 :         Color aColor = pOut->GetBackground().GetColor();
     305           0 :         aColor.SetTransparency( 0 );
     306           0 :         if ( aColor != aFont.GetFillColor() )
     307             :         {
     308           0 :             if( aFont.IsTransparent() )
     309           0 :                 aColor = Color( COL_TRANSPARENT );
     310           0 :             aFont.SetFillColor( aColor );
     311           0 :             mpImpl->mpTextEngine->maFont = aFont;
     312           0 :         }
     313             :     }
     314             : 
     315           0 :     mpImpl->mpTextEngine->ImpPaint( pOut, rStartPos, pPaintArea, pPaintRange, pSelection );
     316           0 : }
     317             : 
     318           0 : void TextView::Paint( const Rectangle& rRect )
     319             : {
     320           0 :     ImpPaint( rRect, false );
     321           0 : }
     322             : 
     323           0 : void TextView::ImpPaint( const Rectangle& rRect, bool bUseVirtDev )
     324             : {
     325           0 :     if ( !mpImpl->mpTextEngine->GetUpdateMode() || mpImpl->mpTextEngine->IsInUndo() )
     326           0 :         return;
     327             : 
     328           0 :     TextSelection *pDrawSelection = NULL;
     329           0 :     if ( !mpImpl->mbHighlightSelection && mpImpl->maSelection.HasRange() )
     330           0 :         pDrawSelection = &mpImpl->maSelection;
     331             : 
     332           0 :     if ( bUseVirtDev )
     333             :     {
     334           0 :         VirtualDevice* pVDev = GetVirtualDevice();
     335             : 
     336           0 :         const Color& rBackgroundColor = mpImpl->mpWindow->GetBackground().GetColor();
     337           0 :         if ( pVDev->GetFillColor() != rBackgroundColor )
     338           0 :             pVDev->SetFillColor( rBackgroundColor );
     339           0 :         if ( pVDev->GetBackground().GetColor() != rBackgroundColor )
     340           0 :             pVDev->SetBackground( rBackgroundColor );
     341             : 
     342           0 :         bool bVDevValid = true;
     343           0 :         Size aOutSz( pVDev->GetOutputSizePixel() );
     344           0 :         if ( (  aOutSz.Width() < rRect.GetWidth() ) ||
     345           0 :              (  aOutSz.Height() < rRect.GetHeight() ) )
     346             :         {
     347           0 :             bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() );
     348             :         }
     349             :         else
     350             :         {
     351             :             // the VirtDev can get very large on Resize =>
     352             :             // shrink now and then
     353           0 :             if ( ( aOutSz.Height() > ( rRect.GetHeight() + 20 ) ) ||
     354           0 :                  ( aOutSz.Width() > ( rRect.GetWidth() + 20 ) ) )
     355             :             {
     356           0 :                 bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() );
     357             :             }
     358             :             else
     359             :             {
     360           0 :                 pVDev->Erase();
     361             :             }
     362             :         }
     363           0 :         if ( !bVDevValid )
     364             :         {
     365           0 :             ImpPaint( rRect, false /* without VDev */ );
     366           0 :             return;
     367             :         }
     368             : 
     369           0 :         Rectangle aTmpRect( Point( 0, 0 ), rRect.GetSize() );
     370             : 
     371           0 :         Point aDocPos( mpImpl->maStartDocPos.X(), mpImpl->maStartDocPos.Y() + rRect.Top() );
     372           0 :         Point aStartPos = ImpGetOutputStartPos( aDocPos );
     373           0 :         ImpPaint( pVDev, aStartPos, &aTmpRect, NULL, pDrawSelection );
     374             :         mpImpl->mpWindow->DrawOutDev( rRect.TopLeft(), rRect.GetSize(),
     375           0 :                                 Point(0,0), rRect.GetSize(), *pVDev );
     376             : //      ShowSelection();
     377           0 :         if ( mpImpl->mbHighlightSelection )
     378           0 :             ImpHighlight( mpImpl->maSelection );
     379             :     }
     380             :     else
     381             :     {
     382           0 :         Point aStartPos = ImpGetOutputStartPos( mpImpl->maStartDocPos );
     383           0 :         ImpPaint( mpImpl->mpWindow, aStartPos, &rRect, NULL, pDrawSelection );
     384             : 
     385             : //      ShowSelection();
     386           0 :         if ( mpImpl->mbHighlightSelection )
     387           0 :             ImpHighlight( mpImpl->maSelection );
     388             :     }
     389             : }
     390             : 
     391           0 : void TextView::ImpHighlight( const TextSelection& rSel )
     392             : {
     393           0 :     TextSelection aSel( rSel );
     394           0 :     aSel.Justify();
     395           0 :     if ( aSel.HasRange() && !mpImpl->mpTextEngine->IsInUndo() && mpImpl->mpTextEngine->GetUpdateMode() )
     396             :     {
     397           0 :         mpImpl->mpCursor->Hide();
     398             : 
     399             :         DBG_ASSERT( !mpImpl->mpTextEngine->mpIdleFormatter->IsActive(), "ImpHighlight: Not formatted!" );
     400             : 
     401           0 :         Rectangle aVisArea( mpImpl->maStartDocPos, mpImpl->mpWindow->GetOutputSizePixel() );
     402           0 :         long nY = 0;
     403           0 :         sal_uLong nStartPara = aSel.GetStart().GetPara();
     404           0 :         sal_uLong nEndPara = aSel.GetEnd().GetPara();
     405           0 :         for ( sal_uLong nPara = 0; nPara <= nEndPara; nPara++ )
     406             :         {
     407           0 :             long nParaHeight = (long)mpImpl->mpTextEngine->CalcParaHeight( nPara );
     408           0 :             if ( ( nPara >= nStartPara ) && ( ( nY + nParaHeight ) > aVisArea.Top() ) )
     409             :             {
     410           0 :                 TEParaPortion* pTEParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( nPara );
     411           0 :                 sal_uInt16 nStartLine = 0;
     412           0 :                 sal_uInt16 nEndLine = pTEParaPortion->GetLines().size() -1;
     413           0 :                 if ( nPara == nStartPara )
     414           0 :                     nStartLine = pTEParaPortion->GetLineNumber( aSel.GetStart().GetIndex(), false );
     415           0 :                 if ( nPara == nEndPara )
     416           0 :                     nEndLine = pTEParaPortion->GetLineNumber( aSel.GetEnd().GetIndex(), true );
     417             : 
     418             :                 // iterate over all lines
     419           0 :                 for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ )
     420             :                 {
     421           0 :                     TextLine* pLine = pTEParaPortion->GetLines()[ nLine ];
     422           0 :                     sal_uInt16 nStartIndex = pLine->GetStart();
     423           0 :                     sal_uInt16 nEndIndex = pLine->GetEnd();
     424           0 :                     if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) )
     425           0 :                         nStartIndex = aSel.GetStart().GetIndex();
     426           0 :                     if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) )
     427           0 :                         nEndIndex = aSel.GetEnd().GetIndex();
     428             : 
     429             :                     // possible if at the beginning of a wrapped line
     430           0 :                     if ( nEndIndex < nStartIndex )
     431           0 :                         nEndIndex = nStartIndex;
     432             : 
     433           0 :                     Rectangle aTmpRect( mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nStartIndex ), false ) );
     434           0 :                     aTmpRect.Top() += nY;
     435           0 :                     aTmpRect.Bottom() += nY;
     436           0 :                     Point aTopLeft( aTmpRect.TopLeft() );
     437             : 
     438           0 :                     aTmpRect = mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nEndIndex ), true );
     439           0 :                     aTmpRect.Top() += nY;
     440           0 :                     aTmpRect.Bottom() += nY;
     441           0 :                     Point aBottomRight( aTmpRect.BottomRight() );
     442           0 :                     aBottomRight.X()--;
     443             : 
     444             :                     // only paint if in the visible region
     445           0 :                     if ( ( aTopLeft.X() < aBottomRight.X() ) && ( aBottomRight.Y() >= aVisArea.Top() ) )
     446             :                     {
     447           0 :                         Point aPnt1( GetWindowPos( aTopLeft ) );
     448           0 :                         Point aPnt2( GetWindowPos( aBottomRight ) );
     449             : 
     450           0 :                         Rectangle aRect( aPnt1, aPnt2 );
     451           0 :                         mpImpl->mpWindow->Invert( aRect );
     452             :                     }
     453             :                 }
     454             :             }
     455           0 :             nY += nParaHeight;
     456             : 
     457           0 :             if ( nY >= aVisArea.Bottom() )
     458           0 :                 break;
     459             :         }
     460             :     }
     461           0 : }
     462             : 
     463           0 : void TextView::ImpSetSelection( const TextSelection& rSelection )
     464             : {
     465           0 :     if (rSelection != mpImpl->maSelection)
     466             :     {
     467           0 :         bool bCaret = false, bSelection = false;
     468           0 :         const TextPaM &rEnd = rSelection.GetEnd();
     469           0 :         const TextPaM &rOldEnd = mpImpl->maSelection.GetEnd();
     470           0 :         bool bGap = rSelection.HasRange(), bOldGap = mpImpl->maSelection.HasRange();
     471           0 :         if (rEnd != rOldEnd)
     472           0 :             bCaret = true;
     473           0 :         if (bGap || bOldGap)
     474           0 :             bSelection = true;
     475             : 
     476           0 :         mpImpl->maSelection = rSelection;
     477             : 
     478           0 :         if (bSelection)
     479           0 :             mpImpl->mpTextEngine->Broadcast(TextHint(TEXT_HINT_VIEWSELECTIONCHANGED));
     480             : 
     481           0 :         if (bCaret)
     482           0 :             mpImpl->mpTextEngine->Broadcast(TextHint(TEXT_HINT_VIEWCARETCHANGED));
     483             :     }
     484           0 : }
     485             : 
     486           0 : void TextView::ShowSelection()
     487             : {
     488           0 :     ImpShowHideSelection( true );
     489           0 : }
     490             : 
     491           0 : void TextView::HideSelection()
     492             : {
     493           0 :     ImpShowHideSelection( false );
     494           0 : }
     495             : 
     496           0 : void TextView::ShowSelection( const TextSelection& rRange )
     497             : {
     498           0 :     ImpShowHideSelection( true, &rRange );
     499           0 : }
     500             : 
     501           0 : void TextView::ImpShowHideSelection( bool bShow, const TextSelection* pRange )
     502             : {
     503           0 :     const TextSelection* pRangeOrSelection = pRange ? pRange : &mpImpl->maSelection;
     504             : 
     505           0 :     if ( pRangeOrSelection->HasRange() )
     506             :     {
     507           0 :         if ( mpImpl->mbHighlightSelection )
     508             :         {
     509           0 :             ImpHighlight( *pRangeOrSelection );
     510             :         }
     511             :         else
     512             :         {
     513           0 :             if( mpImpl->mpWindow->IsPaintTransparent() )
     514           0 :                 mpImpl->mpWindow->Invalidate();
     515             :             else
     516             :             {
     517           0 :                 Rectangle aOutArea( Point( 0, 0 ), mpImpl->mpWindow->GetOutputSizePixel() );
     518           0 :                 Point aStartPos( ImpGetOutputStartPos( mpImpl->maStartDocPos ) );
     519           0 :                 TextSelection aRange( *pRangeOrSelection );
     520           0 :                 aRange.Justify();
     521           0 :                 bool bVisCursor = mpImpl->mpCursor->IsVisible();
     522           0 :                 mpImpl->mpCursor->Hide();
     523           0 :                 ImpPaint( mpImpl->mpWindow, aStartPos, &aOutArea, &aRange, bShow ? &mpImpl->maSelection : NULL );
     524           0 :                 if ( bVisCursor )
     525           0 :                     mpImpl->mpCursor->Show();
     526             :             }
     527             :         }
     528             :     }
     529           0 : }
     530             : 
     531           0 : VirtualDevice* TextView::GetVirtualDevice()
     532             : {
     533           0 :     if ( !mpImpl->mpVirtDev )
     534             :     {
     535           0 :         mpImpl->mpVirtDev = new VirtualDevice;
     536           0 :         mpImpl->mpVirtDev->SetLineColor();
     537             :     }
     538           0 :     return mpImpl->mpVirtDev;
     539             : }
     540             : 
     541           0 : void TextView::EraseVirtualDevice()
     542             : {
     543           0 :     delete mpImpl->mpVirtDev;
     544           0 :     mpImpl->mpVirtDev = 0;
     545           0 : }
     546             : 
     547           0 : bool TextView::KeyInput( const KeyEvent& rKeyEvent )
     548             : {
     549           0 :     bool bDone      = true;
     550           0 :     bool bModified  = false;
     551           0 :     bool bMoved     = false;
     552           0 :     bool bEndKey    = false;    // special CursorPosition
     553           0 :     bool bAllowIdle = true;
     554             : 
     555             :     // check mModified;
     556             :     // the local bModified is not set e.g. by Cut/Paste, as here
     557             :     // the update happens somewhere else
     558           0 :     bool bWasModified = mpImpl->mpTextEngine->IsModified();
     559           0 :     mpImpl->mpTextEngine->SetModified( false );
     560             : 
     561           0 :     TextSelection aCurSel( mpImpl->maSelection );
     562           0 :     TextSelection aOldSel( aCurSel );
     563             : 
     564           0 :     sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode();
     565           0 :     KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
     566           0 :     if ( eFunc != KEYFUNC_DONTKNOW )
     567             :     {
     568           0 :         switch ( eFunc )
     569             :         {
     570             :             case KEYFUNC_CUT:
     571             :             {
     572           0 :                 if ( !mpImpl->mbReadOnly )
     573           0 :                     Cut();
     574             :             }
     575           0 :             break;
     576             :             case KEYFUNC_COPY:
     577             :             {
     578           0 :                 Copy();
     579             :             }
     580           0 :             break;
     581             :             case KEYFUNC_PASTE:
     582             :             {
     583           0 :                 if ( !mpImpl->mbReadOnly )
     584           0 :                     Paste();
     585             :             }
     586           0 :             break;
     587             :             case KEYFUNC_UNDO:
     588             :             {
     589           0 :                 if ( !mpImpl->mbReadOnly )
     590           0 :                     Undo();
     591             :             }
     592           0 :             break;
     593             :             case KEYFUNC_REDO:
     594             :             {
     595           0 :                 if ( !mpImpl->mbReadOnly )
     596           0 :                     Redo();
     597             :             }
     598           0 :             break;
     599             : 
     600             :             default:    // might get processed below
     601           0 :                         eFunc = KEYFUNC_DONTKNOW;
     602             :         }
     603             :     }
     604           0 :     if ( eFunc == KEYFUNC_DONTKNOW )
     605             :     {
     606           0 :         switch ( nCode )
     607             :         {
     608             :             case KEY_UP:
     609             :             case KEY_DOWN:
     610             :             case KEY_LEFT:
     611             :             case KEY_RIGHT:
     612             :             case KEY_HOME:
     613             :             case KEY_END:
     614             :             case KEY_PAGEUP:
     615             :             case KEY_PAGEDOWN:
     616             :             case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
     617             :             case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
     618             :             case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
     619             :             case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
     620             :             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
     621             :             case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
     622             :             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
     623             :             case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
     624             :             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
     625             :             case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
     626             :             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
     627             :             case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
     628             :             case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
     629             :             case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
     630             :             case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
     631             :             case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
     632             :             {
     633           0 :                 if ( ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
     634           0 :                       && !( rKeyEvent.GetKeyCode().IsMod1() && ( nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN ) ) )
     635             :                 {
     636           0 :                     aCurSel = ImpMoveCursor( rKeyEvent );
     637           0 :                     if ( aCurSel.HasRange() ) {
     638           0 :                         uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
     639           0 :                         Copy( aSelection );
     640             :                     }
     641           0 :                     bMoved = true;
     642           0 :                     if ( nCode == KEY_END )
     643           0 :                         bEndKey = true;
     644             :                 }
     645             :                 else
     646           0 :                     bDone = false;
     647             :             }
     648           0 :             break;
     649             :             case KEY_BACKSPACE:
     650             :             case KEY_DELETE:
     651             :             case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
     652             :             case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
     653             :             case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
     654             :             case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
     655             :             {
     656           0 :                 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod2() )
     657             :                 {
     658           0 :                     sal_uInt8 nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT;
     659           0 :                     sal_uInt8 nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE;
     660           0 :                     if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() )
     661           0 :                         nMode = DELMODE_RESTOFCONTENT;
     662             : 
     663           0 :                     switch( nCode )
     664             :                     {
     665             :                     case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
     666           0 :                         nDel = DEL_LEFT;
     667           0 :                         nMode = DELMODE_RESTOFWORD;
     668           0 :                         break;
     669             :                     case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
     670           0 :                         nDel = DEL_RIGHT;
     671           0 :                         nMode = DELMODE_RESTOFWORD;
     672           0 :                         break;
     673             :                     case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
     674           0 :                         nDel = DEL_LEFT;
     675           0 :                         nMode = DELMODE_RESTOFCONTENT;
     676           0 :                         break;
     677             :                     case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
     678           0 :                         nDel = DEL_RIGHT;
     679           0 :                         nMode = DELMODE_RESTOFCONTENT;
     680           0 :                         break;
     681           0 :                     default: break;
     682             :                     }
     683             : 
     684           0 :                     mpImpl->mpTextEngine->UndoActionStart();
     685           0 :                     if(mpImpl->mbSupportProtectAttribute)
     686             :                     {
     687             :                         //expand selection to include all protected content - if there is any
     688             :                         const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
     689           0 :                                     TextPaM(mpImpl->maSelection.GetStart().GetPara(),
     690           0 :                                     mpImpl->maSelection.GetStart().GetIndex()),
     691           0 :                                     TEXTATTR_PROTECTED );
     692             :                         const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib(
     693           0 :                                     TextPaM(mpImpl->maSelection.GetEnd().GetPara(),
     694           0 :                                     mpImpl->maSelection.GetEnd().GetIndex()),
     695           0 :                                     TEXTATTR_PROTECTED );
     696           0 :                         if(pStartAttr && pStartAttr->GetStart() < mpImpl->maSelection.GetStart().GetIndex())
     697             :                         {
     698           0 :                             mpImpl->maSelection.GetStart().GetIndex() = pStartAttr->GetStart();
     699             :                         }
     700           0 :                         if(pEndAttr && pEndAttr->GetEnd() > mpImpl->maSelection.GetEnd().GetIndex())
     701             :                         {
     702           0 :                             mpImpl->maSelection.GetEnd().GetIndex() = pEndAttr->GetEnd();
     703             :                         }
     704             :                     }
     705           0 :                     aCurSel = ImpDelete( nDel, nMode );
     706           0 :                     mpImpl->mpTextEngine->UndoActionEnd();
     707           0 :                     bModified = true;
     708           0 :                     bAllowIdle = false;
     709             :                 }
     710             :                 else
     711           0 :                     bDone = false;
     712             :             }
     713           0 :             break;
     714             :             case KEY_TAB:
     715             :             {
     716           0 :                 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsShift() &&
     717           0 :                         !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() &&
     718           0 :                         ImplCheckTextLen( OUString('x') ) )
     719             :                 {
     720           0 :                     aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, '\t', !IsInsertMode() );
     721           0 :                     bModified = true;
     722             :                 }
     723             :                 else
     724           0 :                     bDone = false;
     725             :             }
     726           0 :             break;
     727             :             case KEY_RETURN:
     728             :             {
     729             :                 // do not swallow Shift-RETURN, as this would disable multi-line entries
     730             :                 // in dialogs & property editors
     731           0 :                 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod1() &&
     732           0 :                         !rKeyEvent.GetKeyCode().IsMod2() && ImplCheckTextLen( OUString('x') ) )
     733             :                 {
     734           0 :                     mpImpl->mpTextEngine->UndoActionStart();
     735           0 :                     aCurSel = mpImpl->mpTextEngine->ImpInsertParaBreak( aCurSel );
     736           0 :                     if ( mpImpl->mbAutoIndent )
     737             :                     {
     738           0 :                         TextNode* pPrev = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aCurSel.GetEnd().GetPara() - 1 );
     739           0 :                         sal_uInt16 n = 0;
     740           0 :                         while ( ( n < pPrev->GetText().getLength() ) && (
     741           0 :                                     ( pPrev->GetText()[ n ] == ' ' ) ||
     742           0 :                                     ( pPrev->GetText()[ n ] == '\t' ) ) )
     743             :                         {
     744           0 :                             n++;
     745             :                         }
     746           0 :                         if ( n )
     747           0 :                             aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, pPrev->GetText().copy( 0, n ) );
     748             :                     }
     749           0 :                     mpImpl->mpTextEngine->UndoActionEnd();
     750           0 :                     bModified = true;
     751             :                 }
     752             :                 else
     753           0 :                     bDone = false;
     754             :             }
     755           0 :             break;
     756             :             case KEY_INSERT:
     757             :             {
     758           0 :                 if ( !mpImpl->mbReadOnly )
     759           0 :                     SetInsertMode( !IsInsertMode() );
     760             :             }
     761           0 :             break;
     762             :             default:
     763             :             {
     764           0 :                 if ( TextEngine::IsSimpleCharInput( rKeyEvent ) )
     765             :                 {
     766           0 :                     sal_Unicode nCharCode = rKeyEvent.GetCharCode();
     767           0 :                     if ( !mpImpl->mbReadOnly && ImplCheckTextLen( OUString(nCharCode) ) )    // otherwise swallow the character anyway
     768             :                     {
     769           0 :                         aCurSel = mpImpl->mpTextEngine->ImpInsertText( nCharCode, aCurSel, !IsInsertMode(), true );
     770           0 :                         bModified = true;
     771             :                     }
     772             :                 }
     773             :                 else
     774           0 :                     bDone = false;
     775             :             }
     776             :         }
     777             :     }
     778             : 
     779           0 :     if ( aCurSel != aOldSel )   // Check if changed, maybe other method already changed mpImpl->maSelection, don't overwrite that!
     780           0 :         ImpSetSelection( aCurSel );
     781             : 
     782           0 :     mpImpl->mpTextEngine->UpdateSelections();
     783             : 
     784           0 :     if ( ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )
     785           0 :         mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
     786             : 
     787           0 :     if ( bModified )
     788             :     {
     789             :         // Idle-Formatter only if AnyInput
     790           0 :         if ( bAllowIdle && Application::AnyInput( VCL_INPUT_KEYBOARD) )
     791           0 :             mpImpl->mpTextEngine->IdleFormatAndUpdate( this );
     792             :         else
     793           0 :             mpImpl->mpTextEngine->FormatAndUpdate( this);
     794             :     }
     795           0 :     else if ( bMoved )
     796             :     {
     797             :         // selection is painted now in ImpMoveCursor
     798           0 :         ImpShowCursor( mpImpl->mbAutoScroll, true, bEndKey );
     799             :     }
     800             : 
     801           0 :     if ( mpImpl->mpTextEngine->IsModified() )
     802           0 :         mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
     803           0 :     else if ( bWasModified )
     804           0 :         mpImpl->mpTextEngine->SetModified( true );
     805             : 
     806           0 :     return bDone;
     807             : }
     808             : 
     809           0 : void TextView::MouseButtonUp( const MouseEvent& rMouseEvent )
     810             : {
     811           0 :     mpImpl->mbClickedInSelection = false;
     812           0 :     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
     813           0 :     mpImpl->mpSelEngine->SelMouseButtonUp( rMouseEvent );
     814           0 :     if ( rMouseEvent.IsMiddle() && !IsReadOnly() &&
     815           0 :          ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) )
     816             :     {
     817           0 :         uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
     818           0 :         Paste( aSelection );
     819           0 :         if ( mpImpl->mpTextEngine->IsModified() )
     820           0 :             mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
     821             :     }
     822           0 :     else if ( rMouseEvent.IsLeft() && GetSelection().HasRange() )
     823             :     {
     824           0 :         uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
     825           0 :         Copy( aSelection );
     826             :     }
     827           0 : }
     828             : 
     829           0 : void TextView::MouseButtonDown( const MouseEvent& rMouseEvent )
     830             : {
     831           0 :     mpImpl->mpTextEngine->CheckIdleFormatter();    // for fast typing and MouseButtonDown
     832           0 :     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
     833           0 :     mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
     834             : 
     835           0 :     mpImpl->mpTextEngine->SetActiveView( this );
     836             : 
     837           0 :     mpImpl->mpSelEngine->SelMouseButtonDown( rMouseEvent );
     838             : 
     839             :     // mbu 20.01.2005 - SelMouseButtonDown() possibly triggers a 'selection changed'
     840             :     // notification. The appropriate handler could change the current selection,
     841             :     // which is the case in the MailMerge address block control. To enable select'n'drag
     842             :     // we need to reevaluate the selection after the notification has been fired.
     843           0 :     mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
     844             : 
     845             :     // special cases
     846           0 :     if ( !rMouseEvent.IsShift() && ( rMouseEvent.GetClicks() >= 2 ) )
     847             :     {
     848           0 :         if ( rMouseEvent.IsMod2() )
     849             :         {
     850           0 :             HideSelection();
     851           0 :             ImpSetSelection( mpImpl->maSelection.GetEnd() );
     852           0 :             SetCursorAtPoint( rMouseEvent.GetPosPixel() );  // not set by SelectionEngine for MOD2
     853             :         }
     854             : 
     855           0 :         if ( rMouseEvent.GetClicks() == 2 )
     856             :         {
     857             :             // select word
     858           0 :             if ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) )
     859             :             {
     860           0 :                 HideSelection();
     861           0 :                 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  mpImpl->maSelection.GetEnd().GetPara() );
     862           0 :                 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
     863           0 :                 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, true );
     864           0 :                 TextSelection aNewSel( mpImpl->maSelection );
     865           0 :                 aNewSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos;
     866           0 :                 aNewSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos;
     867           0 :                 if(mpImpl->mbSupportProtectAttribute)
     868             :                 {
     869             :                     //expand selection to include all protected content - if there is any
     870             :                     const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
     871           0 :                                 TextPaM(aNewSel.GetStart().GetPara(),
     872             :                                 (sal_uInt16)aBoundary.startPos),
     873           0 :                                 TEXTATTR_PROTECTED );
     874             :                     const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib(
     875           0 :                                 TextPaM(aNewSel.GetEnd().GetPara(),
     876             :                                 (sal_uInt16)aBoundary.endPos),
     877           0 :                                 TEXTATTR_PROTECTED );
     878           0 :                     if(pStartAttr && pStartAttr->GetStart() < aNewSel.GetStart().GetIndex())
     879             :                     {
     880           0 :                         aNewSel.GetStart().GetIndex() = pStartAttr->GetStart();
     881             :                     }
     882           0 :                     if(pEndAttr && pEndAttr->GetEnd() > aNewSel.GetEnd().GetIndex())
     883             :                     {
     884           0 :                         aNewSel.GetEnd().GetIndex() = pEndAttr->GetEnd();
     885             :                     }
     886             :                 }
     887           0 :                 ImpSetSelection( aNewSel );
     888           0 :                 ShowSelection();
     889           0 :                 ShowCursor( true, true );
     890             :             }
     891             :         }
     892           0 :         else if ( rMouseEvent.GetClicks() == 3 )
     893             :         {
     894             :             // select paragraph
     895           0 :             if ( mpImpl->maSelection.GetStart().GetIndex() || ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) )
     896             :             {
     897           0 :                 HideSelection();
     898           0 :                 TextSelection aNewSel( mpImpl->maSelection );
     899           0 :                 aNewSel.GetStart().GetIndex() = 0;
     900           0 :                 aNewSel.GetEnd().GetIndex() = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() )->GetText().getLength();
     901           0 :                 ImpSetSelection( aNewSel );
     902           0 :                 ShowSelection();
     903           0 :                 ShowCursor( true, true );
     904             :             }
     905             :         }
     906             :     }
     907           0 : }
     908             : 
     909           0 : void TextView::MouseMove( const MouseEvent& rMouseEvent )
     910             : {
     911           0 :     mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
     912           0 :     mpImpl->mpSelEngine->SelMouseMove( rMouseEvent );
     913           0 : }
     914             : 
     915           0 : void TextView::Command( const CommandEvent& rCEvt )
     916             : {
     917           0 :     mpImpl->mpTextEngine->CheckIdleFormatter();    // for fast typing and MouseButtonDown
     918           0 :     mpImpl->mpTextEngine->SetActiveView( this );
     919             : 
     920           0 :     if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
     921             :     {
     922           0 :         DeleteSelected();
     923           0 :         delete mpImpl->mpTextEngine->mpIMEInfos;
     924           0 :         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( GetSelection().GetEnd().GetPara() );
     925           0 :         mpImpl->mpTextEngine->mpIMEInfos = new TEIMEInfos( GetSelection().GetEnd(), pNode->GetText().copy( GetSelection().GetEnd().GetIndex() ) );
     926           0 :         mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite = !IsInsertMode();
     927             :     }
     928           0 :     else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
     929             :     {
     930             :         DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => No Start ?" );
     931           0 :         if( mpImpl->mpTextEngine->mpIMEInfos )
     932             :         {
     933           0 :             TEParaPortion* pPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() );
     934           0 :             pPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 );
     935             : 
     936           0 :             bool bInsertMode = !mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite;
     937             : 
     938           0 :             delete mpImpl->mpTextEngine->mpIMEInfos;
     939           0 :             mpImpl->mpTextEngine->mpIMEInfos = NULL;
     940             : 
     941           0 :             mpImpl->mpTextEngine->FormatAndUpdate( this );
     942             : 
     943           0 :             SetInsertMode( bInsertMode );
     944             : 
     945           0 :             if ( mpImpl->mpTextEngine->IsModified() )
     946           0 :                 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
     947             :         }
     948             :     }
     949           0 :     else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
     950             :     {
     951             :         DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_EXTTEXTINPUT => No Start ?" );
     952           0 :         if( mpImpl->mpTextEngine->mpIMEInfos )
     953             :         {
     954           0 :             const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
     955             : 
     956           0 :             if ( !pData->IsOnlyCursorChanged() )
     957             :             {
     958           0 :                 TextSelection aSelect( mpImpl->mpTextEngine->mpIMEInfos->aPos );
     959           0 :                 aSelect.GetEnd().GetIndex() = aSelect.GetEnd().GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen;
     960           0 :                 aSelect = mpImpl->mpTextEngine->ImpDeleteText( aSelect );
     961           0 :                 aSelect = mpImpl->mpTextEngine->ImpInsertText( aSelect, pData->GetText() );
     962             : 
     963           0 :                 if ( mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite )
     964             :                 {
     965           0 :                     sal_Int32 nOldIMETextLen = mpImpl->mpTextEngine->mpIMEInfos->nLen;
     966           0 :                     sal_Int32 nNewIMETextLen = pData->GetText().getLength();
     967             : 
     968           0 :                     if ( ( nOldIMETextLen > nNewIMETextLen ) &&
     969           0 :                          ( nNewIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.getLength() ) )
     970             :                     {
     971             :                         // restore old characters
     972           0 :                         sal_Int32 nRestore = nOldIMETextLen - nNewIMETextLen;
     973           0 :                         TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos );
     974           0 :                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
     975           0 :                         mpImpl->mpTextEngine->ImpInsertText( aPaM, mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.copy( nNewIMETextLen, nRestore ) );
     976             :                     }
     977           0 :                     else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
     978           0 :                               ( nOldIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.getLength() ) )
     979             :                     {
     980             :                         // overwrite
     981           0 :                         sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen;
     982           0 :                         if ( ( nOldIMETextLen + nOverwrite ) > mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.getLength() )
     983           0 :                             nOverwrite = mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.getLength() - nOldIMETextLen;
     984             :                         DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" );
     985           0 :                         TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos );
     986           0 :                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
     987           0 :                         TextSelection aSel( aPaM );
     988           0 :                         aSel.GetEnd().GetIndex() =
     989           0 :                             aSel.GetEnd().GetIndex() + nOverwrite;
     990           0 :                         mpImpl->mpTextEngine->ImpDeleteText( aSel );
     991             :                     }
     992             :                 }
     993             : 
     994           0 :                 if ( pData->GetTextAttr() )
     995             :                 {
     996           0 :                     mpImpl->mpTextEngine->mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().getLength() );
     997           0 :                     mpImpl->mpTextEngine->mpIMEInfos->bCursor = pData->IsCursorVisible();
     998             :                 }
     999             :                 else
    1000             :                 {
    1001           0 :                     mpImpl->mpTextEngine->mpIMEInfos->DestroyAttribs();
    1002             :                 }
    1003             : 
    1004           0 :                 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() );
    1005           0 :                 pPPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 );
    1006           0 :                 mpImpl->mpTextEngine->FormatAndUpdate( this );
    1007             :             }
    1008             : 
    1009           0 :             TextSelection aNewSel = TextPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara(), mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() );
    1010           0 :             SetSelection( aNewSel );
    1011           0 :             SetInsertMode( !pData->IsCursorOverwrite() );
    1012             : 
    1013           0 :             if ( pData->IsCursorVisible() )
    1014           0 :                 ShowCursor();
    1015             :             else
    1016           0 :                 HideCursor();
    1017             :         }
    1018             :     }
    1019           0 :     else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
    1020             :     {
    1021           0 :         if ( mpImpl->mpTextEngine->mpIMEInfos && mpImpl->mpTextEngine->mpIMEInfos->nLen )
    1022             :         {
    1023           0 :             TextPaM aPaM( GetSelection().GetEnd() );
    1024           0 :             Rectangle aR1 = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM );
    1025             : 
    1026           0 :             sal_uInt16 nInputEnd = mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen;
    1027             : 
    1028           0 :             if ( !mpImpl->mpTextEngine->IsFormatted() )
    1029           0 :                 mpImpl->mpTextEngine->FormatDoc();
    1030             : 
    1031           0 :             TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
    1032           0 :             sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex(), true );
    1033           0 :             TextLine* pLine = pParaPortion->GetLines()[ nLine ];
    1034           0 :             if ( pLine && ( nInputEnd > pLine->GetEnd() ) )
    1035           0 :                 nInputEnd = pLine->GetEnd();
    1036           0 :             Rectangle aR2 = mpImpl->mpTextEngine->PaMtoEditCursor( TextPaM( aPaM.GetPara(), nInputEnd ) );
    1037             : 
    1038           0 :             long nWidth = aR2.Left()-aR1.Right();
    1039           0 :             aR1.Move( -GetStartDocPos().X(), -GetStartDocPos().Y() );
    1040           0 :             GetWindow()->SetCursorRect( &aR1, nWidth );
    1041             :         }
    1042             :         else
    1043             :         {
    1044           0 :             GetWindow()->SetCursorRect();
    1045             :         }
    1046             :     }
    1047             :     else
    1048             :     {
    1049           0 :         mpImpl->mpSelEngine->Command( rCEvt );
    1050             :     }
    1051           0 : }
    1052             : 
    1053           0 : void TextView::ShowCursor( bool bGotoCursor, bool bForceVisCursor )
    1054             : {
    1055             :     // this setting has more weight
    1056           0 :     if ( !mpImpl->mbAutoScroll )
    1057           0 :         bGotoCursor = false;
    1058           0 :     ImpShowCursor( bGotoCursor, bForceVisCursor, false );
    1059           0 : }
    1060             : 
    1061           0 : void TextView::HideCursor()
    1062             : {
    1063           0 :     mpImpl->mpCursor->Hide();
    1064           0 : }
    1065             : 
    1066           0 : void TextView::Scroll( long ndX, long ndY )
    1067             : {
    1068             :     DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Not formatted!" );
    1069             : 
    1070           0 :     if ( !ndX && !ndY )
    1071           0 :         return;
    1072             : 
    1073           0 :     Point aNewStartPos( mpImpl->maStartDocPos );
    1074             : 
    1075             :     // Vertical:
    1076           0 :     aNewStartPos.Y() -= ndY;
    1077           0 :     if ( aNewStartPos.Y() < 0 )
    1078           0 :         aNewStartPos.Y() = 0;
    1079             : 
    1080             :     // Horizontal:
    1081           0 :     aNewStartPos.X() -= ndX;
    1082           0 :     if ( aNewStartPos.X() < 0 )
    1083           0 :         aNewStartPos.X() = 0;
    1084             : 
    1085           0 :     long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X();
    1086           0 :     long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y();
    1087             : 
    1088           0 :     if ( nDiffX || nDiffY )
    1089             :     {
    1090           0 :         bool bVisCursor = mpImpl->mpCursor->IsVisible();
    1091           0 :         mpImpl->mpCursor->Hide();
    1092           0 :         mpImpl->mpWindow->Update();
    1093           0 :         mpImpl->maStartDocPos = aNewStartPos;
    1094             : 
    1095           0 :         if ( mpImpl->mpTextEngine->IsRightToLeft() )
    1096           0 :             nDiffX = -nDiffX;
    1097           0 :         mpImpl->mpWindow->Scroll( nDiffX, nDiffY );
    1098           0 :         mpImpl->mpWindow->Update();
    1099           0 :         mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) );
    1100           0 :         if ( bVisCursor && !mpImpl->mbReadOnly )
    1101           0 :             mpImpl->mpCursor->Show();
    1102             :     }
    1103             : 
    1104           0 :     mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) );
    1105             : }
    1106             : 
    1107           0 : void TextView::Undo()
    1108             : {
    1109           0 :     mpImpl->mpTextEngine->SetActiveView( this );
    1110           0 :     mpImpl->mpTextEngine->GetUndoManager().Undo();
    1111           0 : }
    1112             : 
    1113           0 : void TextView::Redo()
    1114             : {
    1115           0 :     mpImpl->mpTextEngine->SetActiveView( this );
    1116           0 :     mpImpl->mpTextEngine->GetUndoManager().Redo();
    1117           0 : }
    1118             : 
    1119           0 : void TextView::Cut()
    1120             : {
    1121           0 :     mpImpl->mpTextEngine->UndoActionStart();
    1122           0 :     Copy();
    1123           0 :     DeleteSelected();
    1124           0 :     mpImpl->mpTextEngine->UndoActionEnd();
    1125           0 : }
    1126             : 
    1127           0 : void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
    1128             : {
    1129           0 :     if ( rxClipboard.is() )
    1130             :     {
    1131           0 :         TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
    1132             : 
    1133           0 :         if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) )  // then also as HTML
    1134           0 :             mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, true );
    1135             : 
    1136           0 :         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
    1137             : 
    1138             :         try
    1139             :         {
    1140           0 :             rxClipboard->setContents( pDataObj, NULL );
    1141             : 
    1142           0 :             uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
    1143           0 :             if( xFlushableClipboard.is() )
    1144           0 :                 xFlushableClipboard->flushClipboard();
    1145             :         }
    1146           0 :         catch( const ::com::sun::star::uno::Exception& )
    1147             :         {
    1148             :         }
    1149             : 
    1150           0 :         Application::AcquireSolarMutex( nRef );
    1151             :     }
    1152           0 : }
    1153             : 
    1154           0 : void TextView::Copy()
    1155             : {
    1156           0 :     uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
    1157           0 :     Copy( aClipboard );
    1158           0 : }
    1159             : 
    1160           0 : void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
    1161             : {
    1162           0 :     if ( rxClipboard.is() )
    1163             :     {
    1164           0 :         uno::Reference< datatransfer::XTransferable > xDataObj;
    1165             : 
    1166           0 :         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
    1167             : 
    1168             :         try
    1169             :         {
    1170           0 :             xDataObj = rxClipboard->getContents();
    1171             :         }
    1172           0 :         catch( const ::com::sun::star::uno::Exception& )
    1173             :         {
    1174             :         }
    1175             : 
    1176           0 :         Application::AcquireSolarMutex( nRef );
    1177             : 
    1178           0 :         if ( xDataObj.is() )
    1179             :         {
    1180           0 :             datatransfer::DataFlavor aFlavor;
    1181           0 :             SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
    1182           0 :             if ( xDataObj->isDataFlavorSupported( aFlavor ) )
    1183             :             {
    1184             :                 try
    1185             :                 {
    1186           0 :                     uno::Any aData = xDataObj->getTransferData( aFlavor );
    1187           0 :                     OUString aText;
    1188           0 :                     aData >>= aText;
    1189           0 :                     bool bWasTruncated = false;
    1190           0 :                     if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 )
    1191           0 :                         bWasTruncated = ImplTruncateNewText( aText );
    1192           0 :                     InsertText( aText, false );
    1193           0 :                     mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
    1194             : 
    1195           0 :                     if( bWasTruncated )
    1196           0 :                         Edit::ShowTruncationWarning( mpImpl->mpWindow );
    1197             :                 }
    1198           0 :                 catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& )
    1199             :                 {
    1200             :                 }
    1201           0 :             }
    1202           0 :         }
    1203             :     }
    1204           0 : }
    1205             : 
    1206           0 : void TextView::Paste()
    1207             : {
    1208           0 :     uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
    1209           0 :     Paste( aClipboard );
    1210           0 : }
    1211             : 
    1212           0 : OUString TextView::GetSelected()
    1213             : {
    1214           0 :     return GetSelected( GetSystemLineEnd() );
    1215             : }
    1216             : 
    1217           0 : OUString TextView::GetSelected( LineEnd aSeparator )
    1218             : {
    1219           0 :     return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator );
    1220             : }
    1221             : 
    1222           0 : void TextView::SetInsertMode( bool bInsert )
    1223             : {
    1224           0 :     if ( mpImpl->mbInsertMode != bInsert )
    1225             :     {
    1226           0 :         mpImpl->mbInsertMode = bInsert;
    1227           0 :         ShowCursor( mpImpl->mbAutoScroll, false );
    1228             :     }
    1229           0 : }
    1230             : 
    1231           0 : void TextView::SetReadOnly( bool bReadOnly )
    1232             : {
    1233           0 :     if ( mpImpl->mbReadOnly != bReadOnly )
    1234             :     {
    1235           0 :         mpImpl->mbReadOnly = bReadOnly;
    1236           0 :         if ( !mpImpl->mbReadOnly )
    1237           0 :             ShowCursor( mpImpl->mbAutoScroll, false );
    1238             :         else
    1239           0 :             HideCursor();
    1240             : 
    1241           0 :         GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
    1242             :     }
    1243           0 : }
    1244             : 
    1245           0 : TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent )
    1246             : {
    1247             :     // normally only needed for Up/Down; but who cares
    1248           0 :     mpImpl->mpTextEngine->CheckIdleFormatter();
    1249             : 
    1250           0 :     TextPaM aPaM( mpImpl->maSelection.GetEnd() );
    1251           0 :     TextPaM aOldEnd( aPaM );
    1252             : 
    1253           0 :     TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
    1254           0 :     if ( mpImpl->mpTextEngine->IsRightToLeft() )
    1255           0 :         eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
    1256             : 
    1257           0 :     KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
    1258             : 
    1259           0 :     bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1();
    1260           0 :     sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
    1261             : 
    1262           0 :     bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift();
    1263           0 :     switch ( nCode )
    1264             :     {
    1265           0 :         case KEY_UP:        aPaM = CursorUp( aPaM );
    1266           0 :                             break;
    1267           0 :         case KEY_DOWN:      aPaM = CursorDown( aPaM );
    1268           0 :                             break;
    1269           0 :         case KEY_HOME:      aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
    1270           0 :                             break;
    1271           0 :         case KEY_END:       aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
    1272           0 :                             break;
    1273           0 :         case KEY_PAGEUP:    aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM );
    1274           0 :                             break;
    1275           0 :         case KEY_PAGEDOWN:  aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM );
    1276           0 :                             break;
    1277           0 :         case KEY_LEFT:      aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
    1278           0 :                             break;
    1279           0 :         case KEY_RIGHT:     aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
    1280           0 :                             break;
    1281             :         case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
    1282           0 :                             bSelect = true; // fallthrough intentional
    1283             :         case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
    1284           0 :                             aPaM = CursorWordRight( aPaM );
    1285           0 :                             break;
    1286             :         case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
    1287           0 :                             bSelect = true; // fallthrough intentional
    1288             :         case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
    1289           0 :                             aPaM = CursorWordLeft( aPaM );
    1290           0 :                             break;
    1291             :         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
    1292           0 :                             bSelect = true; // fallthrough intentional
    1293             :         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
    1294           0 :                             aPaM = CursorStartOfLine( aPaM );
    1295           0 :                             break;
    1296             :         case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
    1297           0 :                             bSelect = true; // fallthrough intentional
    1298             :         case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
    1299           0 :                             aPaM = CursorEndOfLine( aPaM );
    1300           0 :                             break;
    1301             :         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
    1302           0 :                             bSelect = true; // falltthrough intentional
    1303             :         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
    1304           0 :                             aPaM = CursorStartOfParagraph( aPaM );
    1305           0 :                             break;
    1306             :         case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
    1307           0 :                             bSelect = true; // falltthrough intentional
    1308             :         case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
    1309           0 :                             aPaM = CursorEndOfParagraph( aPaM );
    1310           0 :                             break;
    1311             :         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
    1312           0 :                             bSelect = true; // falltthrough intentional
    1313             :         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
    1314           0 :                             aPaM = CursorStartOfDoc();
    1315           0 :                             break;
    1316             :         case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
    1317           0 :                             bSelect = true; // falltthrough intentional
    1318             :         case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
    1319           0 :                             aPaM = CursorEndOfDoc();
    1320           0 :                             break;
    1321             :     }
    1322             : 
    1323             :     // might cause a CreateAnchor or Deselection all
    1324           0 :     mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
    1325             : 
    1326           0 :     if ( aOldEnd != aPaM )
    1327             :     {
    1328           0 :         mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() );
    1329             : 
    1330           0 :         TextSelection aNewSelection( mpImpl->maSelection );
    1331           0 :         aNewSelection.GetEnd() = aPaM;
    1332           0 :         if ( bSelect )
    1333             :         {
    1334             :             // extend the selection
    1335           0 :             ImpSetSelection( aNewSelection );
    1336           0 :             ShowSelection( TextSelection( aOldEnd, aPaM ) );
    1337             :         }
    1338             :         else
    1339             :         {
    1340           0 :             aNewSelection.GetStart() = aPaM;
    1341           0 :             ImpSetSelection( aNewSelection );
    1342             :         }
    1343             :     }
    1344             : 
    1345           0 :     return mpImpl->maSelection;
    1346             : }
    1347             : 
    1348           0 : void TextView::InsertText( const OUString& rStr, bool bSelect )
    1349             : {
    1350           0 :     mpImpl->mpTextEngine->UndoActionStart();
    1351             : 
    1352           0 :     TextSelection aNewSel( mpImpl->maSelection );
    1353           0 :     TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
    1354             : 
    1355           0 :     if ( bSelect )
    1356             :     {
    1357           0 :         aNewSel.Justify();
    1358           0 :         aNewSel.GetEnd() = aPaM;
    1359             :     }
    1360             :     else
    1361             :     {
    1362           0 :         aNewSel = aPaM;
    1363             :     }
    1364             : 
    1365           0 :     ImpSetSelection( aNewSel );
    1366             : 
    1367           0 :     mpImpl->mpTextEngine->UndoActionEnd();
    1368             : 
    1369           0 :     mpImpl->mpTextEngine->FormatAndUpdate( this );
    1370           0 : }
    1371             : 
    1372           0 : TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
    1373             : {
    1374           0 :     TextPaM aPaM( rPaM );
    1375             : 
    1376           0 :     if ( aPaM.GetIndex() )
    1377             :     {
    1378           0 :         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1379           0 :         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
    1380           0 :         sal_Int32 nCount = 1;
    1381           0 :         aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
    1382             :     }
    1383           0 :     else if ( aPaM.GetPara() )
    1384             :     {
    1385           0 :         aPaM.GetPara()--;
    1386           0 :         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1387           0 :         aPaM.GetIndex() = pNode->GetText().getLength();
    1388             :     }
    1389           0 :     return aPaM;
    1390             : }
    1391             : 
    1392           0 : TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
    1393             : {
    1394           0 :     TextPaM aPaM( rPaM );
    1395             : 
    1396           0 :     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1397           0 :     if ( aPaM.GetIndex() < pNode->GetText().getLength() )
    1398             :     {
    1399           0 :         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
    1400           0 :         sal_Int32 nCount = 1;
    1401           0 :         aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
    1402             :     }
    1403           0 :     else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
    1404             :     {
    1405           0 :         aPaM.GetPara()++;
    1406           0 :         aPaM.GetIndex() = 0;
    1407             :     }
    1408             : 
    1409           0 :     return aPaM;
    1410             : }
    1411             : 
    1412           0 : TextPaM TextView::CursorWordLeft( const TextPaM& rPaM )
    1413             : {
    1414           0 :     TextPaM aPaM( rPaM );
    1415             : 
    1416           0 :     if ( aPaM.GetIndex() )
    1417             :     {
    1418           0 :         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1419           0 :         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
    1420           0 :         i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, true );
    1421           0 :         if ( aBoundary.startPos >= rPaM.GetIndex() )
    1422           0 :             aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
    1423           0 :         aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0;
    1424             :     }
    1425           0 :     else if ( aPaM.GetPara() )
    1426             :     {
    1427           0 :         aPaM.GetPara()--;
    1428           0 :         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1429           0 :         aPaM.GetIndex() = pNode->GetText().getLength();
    1430             :     }
    1431           0 :     return aPaM;
    1432             : }
    1433             : 
    1434           0 : TextPaM TextView::CursorWordRight( const TextPaM& rPaM )
    1435             : {
    1436           0 :     TextPaM aPaM( rPaM );
    1437             : 
    1438           0 :     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1439           0 :     if ( aPaM.GetIndex() < pNode->GetText().getLength() )
    1440             :     {
    1441           0 :         uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
    1442           0 :         i18n::Boundary aBoundary = xBI->nextWord(  pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
    1443           0 :         aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
    1444             :     }
    1445           0 :     else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
    1446             :     {
    1447           0 :         aPaM.GetPara()++;
    1448           0 :         aPaM.GetIndex() = 0;
    1449             :     }
    1450             : 
    1451           0 :     return aPaM;
    1452             : }
    1453             : 
    1454           0 : TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode )
    1455             : {
    1456           0 :     if ( mpImpl->maSelection.HasRange() )  // only delete selection
    1457           0 :         return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
    1458             : 
    1459           0 :     TextPaM aStartPaM = mpImpl->maSelection.GetStart();
    1460           0 :     TextPaM aEndPaM = aStartPaM;
    1461           0 :     if ( nMode == DEL_LEFT )
    1462             :     {
    1463           0 :         if ( nDelMode == DELMODE_SIMPLE )
    1464             :         {
    1465           0 :             aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER );
    1466             :         }
    1467           0 :         else if ( nDelMode == DELMODE_RESTOFWORD )
    1468             :         {
    1469           0 :             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  aEndPaM.GetPara() );
    1470           0 :             uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
    1471           0 :             i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, true );
    1472           0 :             if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() )
    1473           0 :                 aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
    1474             :             // #i63506# startPos is -1 when the paragraph starts with a tab
    1475           0 :             aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0;
    1476             :         }
    1477             :         else    // DELMODE_RESTOFCONTENT
    1478             :         {
    1479           0 :             if ( aEndPaM.GetIndex() != 0 )
    1480           0 :                 aEndPaM.GetIndex() = 0;
    1481           0 :             else if ( aEndPaM.GetPara() )
    1482             :             {
    1483             :                 // previous paragraph
    1484           0 :                 aEndPaM.GetPara()--;
    1485           0 :                 aEndPaM.GetIndex() = 0;
    1486             :             }
    1487             :         }
    1488             :     }
    1489             :     else
    1490             :     {
    1491           0 :         if ( nDelMode == DELMODE_SIMPLE )
    1492             :         {
    1493           0 :             aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
    1494             :         }
    1495           0 :         else if ( nDelMode == DELMODE_RESTOFWORD )
    1496             :         {
    1497           0 :             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject(  aEndPaM.GetPara() );
    1498           0 :             uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
    1499           0 :             i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
    1500           0 :             aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
    1501             :         }
    1502             :         else    // DELMODE_RESTOFCONTENT
    1503             :         {
    1504           0 :             TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
    1505           0 :             if ( aEndPaM.GetIndex() < pNode->GetText().getLength() )
    1506           0 :                 aEndPaM.GetIndex() = pNode->GetText().getLength();
    1507           0 :             else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )
    1508             :             {
    1509             :                 // next paragraph
    1510           0 :                 aEndPaM.GetPara()++;
    1511           0 :                 TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
    1512           0 :                 aEndPaM.GetIndex() = pNextNode->GetText().getLength();
    1513             :             }
    1514             :         }
    1515             :     }
    1516             : 
    1517           0 :     return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) );
    1518             : }
    1519             : 
    1520           0 : TextPaM TextView::CursorUp( const TextPaM& rPaM )
    1521             : {
    1522           0 :     TextPaM aPaM( rPaM );
    1523             : 
    1524             :     long nX;
    1525           0 :     if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
    1526             :     {
    1527           0 :         nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, false ).Left();
    1528           0 :         mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
    1529             :     }
    1530             :     else
    1531           0 :         nX = mpImpl->mnTravelXPos;
    1532             : 
    1533           0 :     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
    1534           0 :     sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), false );
    1535           0 :     if ( nLine )    // same paragraph
    1536             :     {
    1537           0 :         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX );
    1538           0 :         aPaM.GetIndex() = nCharPos;
    1539             :         // If we need to go to the end of a line that was wrapped automatically,
    1540             :         // the cursor ends up at the beginning of the 2nd line
    1541             :         // Problem: Last character of an automatically wrapped line = Cursor
    1542           0 :         TextLine* pLine = pPPortion->GetLines()[ nLine - 1 ];
    1543           0 :         if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) )
    1544           0 :             aPaM.GetIndex()--;
    1545             :     }
    1546           0 :     else if ( rPaM.GetPara() )  // previous paragraph
    1547             :     {
    1548           0 :         aPaM.GetPara()--;
    1549           0 :         pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
    1550           0 :         sal_uInt16 nL = pPPortion->GetLines().size() - 1;
    1551           0 :         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 );
    1552           0 :         aPaM.GetIndex() = nCharPos;
    1553             :     }
    1554             : 
    1555           0 :     return aPaM;
    1556             : }
    1557             : 
    1558           0 : TextPaM TextView::CursorDown( const TextPaM& rPaM )
    1559             : {
    1560           0 :     TextPaM aPaM( rPaM );
    1561             : 
    1562             :     long nX;
    1563           0 :     if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
    1564             :     {
    1565           0 :         nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, false ).Left();
    1566           0 :         mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
    1567             :     }
    1568             :     else
    1569           0 :         nX = mpImpl->mnTravelXPos;
    1570             : 
    1571           0 :     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
    1572           0 :     sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), false );
    1573           0 :     if ( nLine < ( pPPortion->GetLines().size() - 1 ) )
    1574             :     {
    1575           0 :         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX );
    1576           0 :         aPaM.GetIndex() = nCharPos;
    1577             : 
    1578             :         // special case CursorUp
    1579           0 :         TextLine* pLine = pPPortion->GetLines()[ nLine + 1 ];
    1580           0 :         if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().getLength() )
    1581           0 :             aPaM.GetIndex()--;
    1582             :     }
    1583           0 :     else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )   // next paragraph
    1584             :     {
    1585           0 :         aPaM.GetPara()++;
    1586           0 :         pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
    1587           0 :         sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 );
    1588           0 :         aPaM.GetIndex() = nCharPos;
    1589           0 :         TextLine* pLine = pPPortion->GetLines().front();
    1590           0 :         if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().size() > 1 ) )
    1591           0 :             aPaM.GetIndex()--;
    1592             :     }
    1593             : 
    1594           0 :     return aPaM;
    1595             : }
    1596             : 
    1597           0 : TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM )
    1598             : {
    1599           0 :     TextPaM aPaM( rPaM );
    1600             : 
    1601           0 :     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
    1602           0 :     sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), false );
    1603           0 :     TextLine* pLine = pPPortion->GetLines()[ nLine ];
    1604           0 :     aPaM.GetIndex() = pLine->GetStart();
    1605             : 
    1606           0 :     return aPaM;
    1607             : }
    1608             : 
    1609           0 : TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM )
    1610             : {
    1611           0 :     TextPaM aPaM( rPaM );
    1612             : 
    1613           0 :     TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
    1614           0 :     sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), false );
    1615           0 :     TextLine* pLine = pPPortion->GetLines()[ nLine ];
    1616           0 :     aPaM.GetIndex() = pLine->GetEnd();
    1617             : 
    1618           0 :     if ( pLine->GetEnd() > pLine->GetStart() )  // empty line
    1619             :     {
    1620           0 :         sal_Unicode cLastChar = pPPortion->GetNode()->GetText()[ aPaM.GetIndex()-1 ];
    1621           0 :         if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().getLength() ) )
    1622             :         {
    1623             :             // for a blank in an automatically-wrapped line it is better to stand before it,
    1624             :             // as the user will intend to stand behind the prior word.
    1625             :             // If there is a change, special case for Pos1 after End!
    1626           0 :             aPaM.GetIndex()--;
    1627             :         }
    1628             :     }
    1629           0 :     return aPaM;
    1630             : }
    1631             : 
    1632           0 : TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM )
    1633             : {
    1634           0 :     TextPaM aPaM( rPaM );
    1635           0 :     aPaM.GetIndex() = 0;
    1636           0 :     return aPaM;
    1637             : }
    1638             : 
    1639           0 : TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM )
    1640             : {
    1641           0 :     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() );
    1642           0 :     TextPaM aPaM( rPaM );
    1643           0 :     aPaM.GetIndex() = pNode->GetText().getLength();
    1644           0 :     return aPaM;
    1645             : }
    1646             : 
    1647           0 : TextPaM TextView::CursorStartOfDoc()
    1648             : {
    1649           0 :     TextPaM aPaM( 0, 0 );
    1650           0 :     return aPaM;
    1651             : }
    1652             : 
    1653           0 : TextPaM TextView::CursorEndOfDoc()
    1654             : {
    1655           0 :     sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1;
    1656           0 :     TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode );
    1657           0 :     TextPaM aPaM( nNode, pNode->GetText().getLength() );
    1658           0 :     return aPaM;
    1659             : }
    1660             : 
    1661           0 : TextPaM TextView::PageUp( const TextPaM& rPaM )
    1662             : {
    1663           0 :     Rectangle aRect = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
    1664           0 :     Point aTopLeft = aRect.TopLeft();
    1665           0 :     aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
    1666           0 :     aTopLeft.X() += 1;
    1667           0 :     if ( aTopLeft.Y() < 0 )
    1668           0 :         aTopLeft.Y() = 0;
    1669             : 
    1670           0 :     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft );
    1671           0 :     return aPaM;
    1672             : }
    1673             : 
    1674           0 : TextPaM TextView::PageDown( const TextPaM& rPaM )
    1675             : {
    1676           0 :     Rectangle aRect = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
    1677           0 :     Point aBottomRight = aRect.BottomRight();
    1678           0 :     aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
    1679           0 :     aBottomRight.X() += 1;
    1680           0 :     long nHeight = mpImpl->mpTextEngine->GetTextHeight();
    1681           0 :     if ( aBottomRight.Y() > nHeight )
    1682           0 :         aBottomRight.Y() = nHeight-1;
    1683             : 
    1684           0 :     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight );
    1685           0 :     return aPaM;
    1686             : }
    1687             : 
    1688           0 : void TextView::ImpShowCursor( bool bGotoCursor, bool bForceVisCursor, bool bSpecial )
    1689             : {
    1690           0 :     if ( mpImpl->mpTextEngine->IsFormatting() )
    1691           0 :         return;
    1692           0 :     if ( !mpImpl->mpTextEngine->GetUpdateMode() )
    1693           0 :         return;
    1694           0 :     if ( mpImpl->mpTextEngine->IsInUndo() )
    1695           0 :         return;
    1696             : 
    1697           0 :     mpImpl->mpTextEngine->CheckIdleFormatter();
    1698           0 :     if ( !mpImpl->mpTextEngine->IsFormatted() )
    1699           0 :         mpImpl->mpTextEngine->FormatAndUpdate( this );
    1700             : 
    1701           0 :     TextPaM aPaM( mpImpl->maSelection.GetEnd() );
    1702           0 :     Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial );
    1703             : 
    1704             :     // Remember that we placed the cursor behind the last character of a line
    1705           0 :     mpImpl->mbCursorAtEndOfLine = false;
    1706           0 :     if( bSpecial )
    1707             :     {
    1708           0 :         TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
    1709             :         mpImpl->mbCursorAtEndOfLine =
    1710           0 :             pParaPortion->GetLineNumber( aPaM.GetIndex(), true ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), false );
    1711             :     }
    1712             : 
    1713           0 :     if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() )
    1714             :     {
    1715           0 :         TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
    1716           0 :         if ( !pNode->GetText().isEmpty() && ( aPaM.GetIndex() < pNode->GetText().getLength() ) )
    1717             :         {
    1718             :             // If we are behind a portion, and the next portion has other direction, we must change position...
    1719           0 :             aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, false, true ).Left();
    1720             : 
    1721           0 :             TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
    1722             : 
    1723           0 :             sal_uInt16 nTextPortionStart = 0;
    1724           0 :             sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true );
    1725           0 :             TETextPortion* pTextPortion = pParaPortion->GetTextPortions()[ nTextPortion ];
    1726           0 :             if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
    1727             :             {
    1728           0 :                 if ( mpImpl->mpTextEngine->IsRightToLeft() )
    1729             :                 {
    1730             : 
    1731             :                 }
    1732           0 :                 aEditCursor.Right() += pTextPortion->GetWidth();
    1733             :             }
    1734             :             else
    1735             :             {
    1736           0 :                 TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
    1737           0 :                 aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, true ).Left();
    1738             :             }
    1739             :         }
    1740             :     }
    1741             : 
    1742           0 :     Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel();
    1743           0 :     if ( aEditCursor.GetHeight() > aOutSz.Height() )
    1744           0 :         aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1;
    1745             : 
    1746           0 :     aEditCursor.Left() -= 1;
    1747             : 
    1748           0 :     if ( bGotoCursor
    1749             :         // #i81283# protext maStartDocPos against initialization problems
    1750           0 :         && aOutSz.Width() && aOutSz.Height()
    1751             :     )
    1752             :     {
    1753           0 :         long nVisStartY = mpImpl->maStartDocPos.Y();
    1754           0 :         long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height();
    1755           0 :         long nVisStartX = mpImpl->maStartDocPos.X();
    1756           0 :         long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width();
    1757           0 :         long nMoreX = aOutSz.Width() / 4;
    1758             : 
    1759           0 :         Point aNewStartPos( mpImpl->maStartDocPos );
    1760             : 
    1761           0 :         if ( aEditCursor.Bottom() > nVisEndY )
    1762             :         {
    1763           0 :             aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY );
    1764             :         }
    1765           0 :         else if ( aEditCursor.Top() < nVisStartY )
    1766             :         {
    1767           0 :             aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() );
    1768             :         }
    1769             : 
    1770           0 :         if ( aEditCursor.Right() >= nVisEndX )
    1771             :         {
    1772           0 :             aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX );
    1773             : 
    1774             :             // do you want some more?
    1775           0 :             aNewStartPos.X() += nMoreX;
    1776             :         }
    1777           0 :         else if ( aEditCursor.Left() <= nVisStartX )
    1778             :         {
    1779           0 :             aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() );
    1780             : 
    1781             :             // do you want some more?
    1782           0 :             aNewStartPos.X() -= nMoreX;
    1783             :         }
    1784             : 
    1785             :         // X can be wrong for the 'some more' above:
    1786             : //      sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth();
    1787             : //      if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) )
    1788             : //          nMaxTextWidth = 0x7FFFFFFF;
    1789             : //      long nMaxX = (long)nMaxTextWidth - aOutSz.Width();
    1790           0 :         long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width();
    1791           0 :         if ( nMaxX < 0 )
    1792           0 :             nMaxX = 0;
    1793             : 
    1794           0 :         if ( aNewStartPos.X() < 0 )
    1795           0 :             aNewStartPos.X() = 0;
    1796           0 :         else if ( aNewStartPos.X() > nMaxX )
    1797           0 :             aNewStartPos.X() = nMaxX;
    1798             : 
    1799             :         // Y should not be further down than needed
    1800           0 :         long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height();
    1801           0 :         if ( nYMax < 0 )
    1802           0 :             nYMax = 0;
    1803           0 :         if ( aNewStartPos.Y() > nYMax )
    1804           0 :             aNewStartPos.Y() = nYMax;
    1805             : 
    1806           0 :         if ( aNewStartPos != mpImpl->maStartDocPos )
    1807           0 :             Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) );
    1808             :     }
    1809             : 
    1810           0 :     if ( aEditCursor.Right() < aEditCursor.Left() )
    1811             :     {
    1812           0 :         long n = aEditCursor.Left();
    1813           0 :         aEditCursor.Left() = aEditCursor.Right();
    1814           0 :         aEditCursor.Right() = n;
    1815             :     }
    1816             : 
    1817           0 :     Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) );
    1818           0 :     mpImpl->mpCursor->SetPos( aPoint );
    1819           0 :     mpImpl->mpCursor->SetSize( aEditCursor.GetSize() );
    1820           0 :     if ( bForceVisCursor && mpImpl->mbCursorEnabled )
    1821           0 :         mpImpl->mpCursor->Show();
    1822             : }
    1823             : 
    1824           0 : bool TextView::SetCursorAtPoint( const Point& rPosPixel )
    1825             : {
    1826           0 :     mpImpl->mpTextEngine->CheckIdleFormatter();
    1827             : 
    1828           0 :     Point aDocPos = GetDocPos( rPosPixel );
    1829             : 
    1830           0 :     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos );
    1831             : 
    1832             :     // aTmpNewSel: Diff between old and new; not the new selection
    1833           0 :     TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM );
    1834           0 :     TextSelection aNewSel( mpImpl->maSelection );
    1835           0 :     aNewSel.GetEnd() = aPaM;
    1836             : 
    1837           0 :     if ( !mpImpl->mpSelEngine->HasAnchor() )
    1838             :     {
    1839           0 :         if ( mpImpl->maSelection.GetStart() != aPaM )
    1840           0 :             mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
    1841           0 :         aNewSel.GetStart() = aPaM;
    1842           0 :         ImpSetSelection( aNewSel );
    1843             :     }
    1844             :     else
    1845             :     {
    1846           0 :         ImpSetSelection( aNewSel );
    1847           0 :         ShowSelection( aTmpNewSel );
    1848             :     }
    1849             : 
    1850           0 :     bool bForceCursor =  mpImpl->mpDDInfo ? false : true; // && !mbInSelection
    1851           0 :     ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, false );
    1852           0 :     return true;
    1853             : }
    1854             : 
    1855           0 : bool TextView::IsSelectionAtPoint( const Point& rPosPixel )
    1856             : {
    1857             : //  if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection )
    1858             : //      return false;
    1859             : 
    1860           0 :     Point aDocPos = GetDocPos( rPosPixel );
    1861           0 :     TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, false );
    1862             :     // For Hyperlinks D&D also start w/o a selection.
    1863             :     // BeginDrag is only called, however, if IsSelectionAtPoint()
    1864             :     // Problem: IsSelectionAtPoint is not called by Command()
    1865             :     // if before MBDown returned false.
    1866           0 :     return ( IsInSelection( aPaM ) ||
    1867           0 :             ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) );
    1868             : }
    1869             : 
    1870           0 : bool TextView::IsInSelection( const TextPaM& rPaM )
    1871             : {
    1872           0 :     TextSelection aSel = mpImpl->maSelection;
    1873           0 :     aSel.Justify();
    1874             : 
    1875           0 :     sal_uLong nStartNode = aSel.GetStart().GetPara();
    1876           0 :     sal_uLong nEndNode = aSel.GetEnd().GetPara();
    1877           0 :     sal_uLong nCurNode = rPaM.GetPara();
    1878             : 
    1879           0 :     if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
    1880           0 :         return true;
    1881             : 
    1882           0 :     if ( nStartNode == nEndNode )
    1883             :     {
    1884           0 :         if ( nCurNode == nStartNode )
    1885           0 :             if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
    1886           0 :                 return true;
    1887             :     }
    1888           0 :     else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) )
    1889           0 :         return true;
    1890           0 :     else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
    1891           0 :         return true;
    1892             : 
    1893           0 :     return false;
    1894             : }
    1895             : 
    1896           0 : void TextView::ImpHideDDCursor()
    1897             : {
    1898           0 :     if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor )
    1899             :     {
    1900           0 :         mpImpl->mpDDInfo->maCursor.Hide();
    1901           0 :         mpImpl->mpDDInfo->mbVisCursor = false;
    1902             :     }
    1903           0 : }
    1904             : 
    1905           0 : void TextView::ImpShowDDCursor()
    1906             : {
    1907           0 :     if ( !mpImpl->mpDDInfo->mbVisCursor )
    1908             :     {
    1909           0 :         Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, true );
    1910           0 :         aCursor.Right()++;
    1911           0 :         aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) );
    1912             : 
    1913           0 :         mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow );
    1914           0 :         mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() );
    1915           0 :         mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() );
    1916           0 :         mpImpl->mpDDInfo->maCursor.Show();
    1917           0 :         mpImpl->mpDDInfo->mbVisCursor = true;
    1918             :     }
    1919           0 : }
    1920             : 
    1921           0 : void TextView::SetPaintSelection( bool bPaint )
    1922             : {
    1923           0 :     if ( bPaint != mpImpl->mbPaintSelection )
    1924             :     {
    1925           0 :         mpImpl->mbPaintSelection = bPaint;
    1926           0 :         ShowSelection( mpImpl->maSelection );
    1927             :     }
    1928           0 : }
    1929             : 
    1930           0 : bool TextView::Read( SvStream& rInput )
    1931             : {
    1932           0 :     bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection );
    1933           0 :     ShowCursor();
    1934           0 :     return bDone;
    1935             : }
    1936             : 
    1937           0 : bool TextView::ImplTruncateNewText( OUString& rNewText ) const
    1938             : {
    1939           0 :     bool bTruncated = false;
    1940             : 
    1941           0 :     sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen();
    1942             :     // 0 means unlimited
    1943           0 :     if( nMaxLen != 0 )
    1944             :     {
    1945           0 :         sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen();
    1946             : 
    1947           0 :         sal_uInt32 nNewLen = rNewText.getLength();
    1948           0 :         if ( nCurLen + nNewLen > nMaxLen )
    1949             :         {
    1950             :             // see how much text will be replaced
    1951           0 :             sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
    1952           0 :             if ( nCurLen + nNewLen - nSelLen > nMaxLen )
    1953             :             {
    1954           0 :                 sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen));
    1955           0 :                 rNewText = rNewText.copy( 0, nTruncatedLen );
    1956           0 :                 bTruncated = true;
    1957             :             }
    1958             :         }
    1959             :     }
    1960           0 :     return bTruncated;
    1961             : }
    1962             : 
    1963           0 : bool TextView::ImplCheckTextLen( const OUString& rNewText )
    1964             : {
    1965           0 :     bool bOK = true;
    1966           0 :     if ( mpImpl->mpTextEngine->GetMaxTextLen() )
    1967             :     {
    1968           0 :         sal_uLong n = mpImpl->mpTextEngine->GetTextLen();
    1969           0 :         n += rNewText.getLength();
    1970           0 :         if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
    1971             :         {
    1972             :             // calculate how much text is being deleted
    1973           0 :             n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
    1974           0 :             if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
    1975           0 :                 bOK = false;
    1976             :         }
    1977             :     }
    1978           0 :     return bOK;
    1979             : }
    1980             : 
    1981           0 : void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    1982             : {
    1983           0 :     if ( mpImpl->mbClickedInSelection )
    1984             :     {
    1985           0 :         SolarMutexGuard aVclGuard;
    1986             : 
    1987             :         DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" );
    1988             : 
    1989           0 :         delete mpImpl->mpDDInfo;
    1990           0 :         mpImpl->mpDDInfo = new TextDDInfo;
    1991           0 :         mpImpl->mpDDInfo->mbStarterOfDD = true;
    1992             : 
    1993           0 :         TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
    1994             : 
    1995           0 :         if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) )  // then also as HTML
    1996           0 :             mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, true );
    1997             : 
    1998             :         /*
    1999             :         // D&D of a Hyperlink
    2000             :         // TODO: Better would be to store MBDownPaM in MBDown,
    2001             :         // but this would be incompatible => change later
    2002             :         TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) );
    2003             :         const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK );
    2004             :         if ( pAttr )
    2005             :         {
    2006             :             aSel = aPaM;
    2007             :             aSel.GetStart().GetIndex() = pAttr->GetStart();
    2008             :             aSel.GetEnd().GetIndex() = pAttr->GetEnd();
    2009             : 
    2010             :             const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr();
    2011             :             String aText( rLink.GetDescription() );
    2012             :             if ( !aText.Len() )
    2013             :                 aText = mpImpl->mpTextEngine->GetText( aSel );
    2014             :             INetBookmark aBookmark( rLink.GetURL(), aText );
    2015             :             aBookmark.CopyDragServer();
    2016             :         }
    2017             :         */
    2018             : 
    2019           0 :         mpImpl->mpCursor->Hide();
    2020             : 
    2021           0 :         sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
    2022           0 :         if ( !IsReadOnly() )
    2023           0 :             nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
    2024           0 :         rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener );
    2025             :     }
    2026           0 : }
    2027             : 
    2028           0 : void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2029             : {
    2030           0 :     ImpHideDDCursor();
    2031           0 :     delete mpImpl->mpDDInfo;
    2032           0 :     mpImpl->mpDDInfo = NULL;
    2033           0 : }
    2034             : 
    2035           0 : void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2036             : {
    2037           0 :     SolarMutexGuard aVclGuard;
    2038             : 
    2039           0 :     bool bChanges = false;
    2040           0 :     if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo )
    2041             :     {
    2042           0 :         ImpHideDDCursor();
    2043             : 
    2044             :         // Data for deleting after DROP_MOVE:
    2045           0 :         TextSelection aPrevSel( mpImpl->maSelection );
    2046           0 :         aPrevSel.Justify();
    2047           0 :         sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount();
    2048           0 :         sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() );
    2049             : 
    2050           0 :         bool bStarterOfDD = false;
    2051           0 :         for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; )
    2052           0 :             bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : false;
    2053             : 
    2054           0 :         HideSelection();
    2055           0 :         ImpSetSelection( mpImpl->mpDDInfo->maDropPos );
    2056             : 
    2057           0 :         mpImpl->mpTextEngine->UndoActionStart();
    2058             : 
    2059           0 :         OUString aText;
    2060           0 :         uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
    2061           0 :         if ( xDataObj.is() )
    2062             :         {
    2063           0 :             datatransfer::DataFlavor aFlavor;
    2064           0 :             SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
    2065           0 :             if ( xDataObj->isDataFlavorSupported( aFlavor ) )
    2066             :             {
    2067           0 :                 uno::Any aData = xDataObj->getTransferData( aFlavor );
    2068           0 :                 OUString aOUString;
    2069           0 :                 aData >>= aOUString;
    2070           0 :                 aText = convertLineEnd(aOUString, LINEEND_LF);
    2071           0 :             }
    2072             :         }
    2073             : 
    2074           0 :         if ( !aText.isEmpty() && ( aText[ aText.getLength()-1 ] == LINE_SEP ) )
    2075           0 :             aText = aText.copy(0, aText.getLength()-1);
    2076             : 
    2077           0 :         TextPaM aTempStart = mpImpl->maSelection.GetStart();
    2078           0 :         if ( ImplCheckTextLen( aText ) )
    2079           0 :             ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) );
    2080           0 :         if(mpImpl->mbSupportProtectAttribute)
    2081             :         {
    2082             :             mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(),
    2083           0 :                 aTempStart.GetPara(),
    2084           0 :                 aTempStart.GetIndex(),
    2085           0 :                 mpImpl->maSelection.GetEnd().GetIndex(), false );
    2086             :         }
    2087             : 
    2088           0 :         if ( aPrevSel.HasRange() &&
    2089           0 :                 !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element
    2090           0 :                 (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) )
    2091             :         {
    2092             :             // adjust selection if necessary
    2093           0 :             if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) ||
    2094           0 :                  ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
    2095           0 :                         && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) )
    2096             :             {
    2097             :                 sal_uLong nNewParasBeforeSelection =
    2098           0 :                     mpImpl->mpTextEngine->GetParagraphCount() -    nPrevParaCount;
    2099             : 
    2100           0 :                 aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection;
    2101           0 :                 aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection;
    2102             : 
    2103           0 :                 if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
    2104             :                 {
    2105             :                     sal_uInt16 nNewChars =
    2106           0 :                         mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen;
    2107             : 
    2108           0 :                     aPrevSel.GetStart().GetIndex() =
    2109           0 :                         aPrevSel.GetStart().GetIndex() + nNewChars;
    2110           0 :                     if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() )
    2111           0 :                         aPrevSel.GetEnd().GetIndex() =
    2112           0 :                             aPrevSel.GetEnd().GetIndex() + nNewChars;
    2113             :                 }
    2114             :             }
    2115             :             else
    2116             :             {
    2117             :                 // adjust current selection
    2118           0 :                 TextPaM aPaM = mpImpl->maSelection.GetStart();
    2119           0 :                 aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() );
    2120           0 :                 if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
    2121             :                 {
    2122           0 :                     aPaM.GetIndex() =
    2123           0 :                         aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex();
    2124           0 :                     if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
    2125           0 :                         aPaM.GetIndex() =
    2126           0 :                             aPaM.GetIndex() + aPrevSel.GetStart().GetIndex();
    2127             :                 }
    2128           0 :                 ImpSetSelection( aPaM );
    2129             : 
    2130             :             }
    2131           0 :             mpImpl->mpTextEngine->ImpDeleteText( aPrevSel );
    2132             :         }
    2133             : 
    2134           0 :         mpImpl->mpTextEngine->UndoActionEnd();
    2135             : 
    2136           0 :         delete mpImpl->mpDDInfo;
    2137           0 :         mpImpl->mpDDInfo = 0;
    2138             : 
    2139           0 :         mpImpl->mpTextEngine->FormatAndUpdate( this );
    2140             : 
    2141           0 :         mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
    2142             :     }
    2143           0 :     rDTDE.Context->dropComplete( bChanges );
    2144           0 : }
    2145             : 
    2146           0 : void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2147             : {
    2148           0 : }
    2149             : 
    2150           0 : void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2151             : {
    2152           0 :     SolarMutexGuard aVclGuard;
    2153           0 :     ImpHideDDCursor();
    2154           0 : }
    2155             : 
    2156           0 : void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2157             : {
    2158           0 :     SolarMutexGuard aVclGuard;
    2159             : 
    2160           0 :     if ( !mpImpl->mpDDInfo )
    2161           0 :         mpImpl->mpDDInfo = new TextDDInfo;
    2162             : 
    2163           0 :     TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos;
    2164           0 :     Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
    2165           0 :     Point aDocPos = GetDocPos( aMousePos );
    2166           0 :     mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos );
    2167             : 
    2168           0 :     bool bProtected = false;
    2169           0 :     if(mpImpl->mbSupportProtectAttribute)
    2170             :     {
    2171             :         const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
    2172             :                     mpImpl->mpDDInfo->maDropPos,
    2173           0 :                     TEXTATTR_PROTECTED );
    2174           0 :         bProtected = pStartAttr != 0 &&
    2175           0 :                 pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() &&
    2176           0 :                 pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex();
    2177             :     }
    2178             :     // Don't drop in selection or in read only engine
    2179           0 :     if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected)
    2180             :     {
    2181           0 :         ImpHideDDCursor();
    2182           0 :         rDTDE.Context->rejectDrag();
    2183             :     }
    2184             :     else
    2185             :     {
    2186             :         // delete old Cursor
    2187           0 :         if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) )
    2188             :         {
    2189           0 :             ImpHideDDCursor();
    2190           0 :             ImpShowDDCursor();
    2191             :         }
    2192           0 :         rDTDE.Context->acceptDrag( rDTDE.DropAction );
    2193           0 :     }
    2194           0 : }
    2195             : 
    2196           0 : Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const
    2197             : {
    2198           0 :     Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() );
    2199           0 :     if ( mpImpl->mpTextEngine->IsRightToLeft() )
    2200             :     {
    2201           0 :         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
    2202           0 :         aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0
    2203             :     }
    2204           0 :     return aStartPos;
    2205             : }
    2206             : 
    2207           0 : Point TextView::GetDocPos( const Point& rWindowPos ) const
    2208             : {
    2209             :     // Window Position => Document Position
    2210             : 
    2211           0 :     Point aPoint;
    2212             : 
    2213           0 :     aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y();
    2214             : 
    2215           0 :     if ( !mpImpl->mpTextEngine->IsRightToLeft() )
    2216             :     {
    2217           0 :         aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X();
    2218             :     }
    2219             :     else
    2220             :     {
    2221           0 :         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
    2222           0 :         aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X();
    2223             :     }
    2224             : 
    2225           0 :     return aPoint;
    2226             : }
    2227             : 
    2228           0 : Point TextView::GetWindowPos( const Point& rDocPos ) const
    2229             : {
    2230             :     // Document Position => Window Position
    2231             : 
    2232           0 :     Point aPoint;
    2233             : 
    2234           0 :     aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y();
    2235             : 
    2236           0 :     if ( !mpImpl->mpTextEngine->IsRightToLeft() )
    2237             :     {
    2238           0 :         aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X();
    2239             :     }
    2240             :     else
    2241             :     {
    2242           0 :         Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
    2243           0 :         aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() );
    2244             :     }
    2245             : 
    2246           0 :     return aPoint;
    2247             : }
    2248             : 
    2249           0 : sal_Int32 TextView::GetLineNumberOfCursorInSelection() const
    2250             : {
    2251             :  // PROGRESS
    2252           0 :     sal_Int32 nLineNo = -1;
    2253           0 :     if( mpImpl->mbCursorEnabled )
    2254             :     {
    2255           0 :         TextPaM aPaM = GetSelection().GetEnd();
    2256           0 :         TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
    2257           0 :         nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), false );
    2258           0 :         if( mpImpl->mbCursorAtEndOfLine )
    2259           0 :             --nLineNo;
    2260             :     }
    2261           0 :     return nLineNo;
    2262             : }
    2263             : 
    2264             : // (+) class TextSelFunctionSet
    2265             : 
    2266           0 : TextSelFunctionSet::TextSelFunctionSet( TextView* pView )
    2267             : {
    2268           0 :     mpView = pView;
    2269           0 : }
    2270             : 
    2271           0 : void TextSelFunctionSet::BeginDrag()
    2272             : {
    2273           0 : }
    2274             : 
    2275           0 : void TextSelFunctionSet::CreateAnchor()
    2276             : {
    2277             : //  TextSelection aSel( mpView->GetSelection() );
    2278             : //  aSel.GetStart() = aSel.GetEnd();
    2279             : //  mpView->SetSelection( aSel );
    2280             : 
    2281             :     // may not be followed by ShowCursor
    2282           0 :     mpView->HideSelection();
    2283           0 :     mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() );
    2284           0 : }
    2285             : 
    2286           0 : bool TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool )
    2287             : {
    2288           0 :     return mpView->SetCursorAtPoint( rPointPixel );
    2289             : }
    2290             : 
    2291           0 : bool TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
    2292             : {
    2293           0 :     return mpView->IsSelectionAtPoint( rPointPixel );
    2294             : }
    2295             : 
    2296           0 : void TextSelFunctionSet::DeselectAll()
    2297             : {
    2298           0 :     CreateAnchor();
    2299           0 : }
    2300             : 
    2301           0 : void TextSelFunctionSet::DeselectAtPoint( const Point& )
    2302             : {
    2303             :     // only for multiple selection
    2304           0 : }
    2305             : 
    2306           0 : void TextSelFunctionSet::DestroyAnchor()
    2307             : {
    2308             :     // only for multiple selection
    2309           0 : }
    2310           0 : TextEngine*         TextView::GetTextEngine() const
    2311           0 : { return mpImpl->mpTextEngine; }
    2312           0 : Window*             TextView::GetWindow() const
    2313           0 : { return mpImpl->mpWindow; }
    2314           0 : void                TextView::EnableCursor( bool bEnable )
    2315           0 : { mpImpl->mbCursorEnabled = bEnable; }
    2316           0 : bool                TextView::IsCursorEnabled() const
    2317           0 : { return mpImpl->mbCursorEnabled; }
    2318           0 : void                TextView::SetStartDocPos( const Point& rPos )
    2319           0 : { mpImpl->maStartDocPos = rPos; }
    2320           0 : const Point&        TextView::GetStartDocPos() const
    2321           0 : { return mpImpl->maStartDocPos; }
    2322           0 : void                TextView::SetAutoIndentMode( bool bAutoIndent )
    2323           0 : { mpImpl->mbAutoIndent = bAutoIndent; }
    2324           0 : bool                TextView::IsReadOnly() const
    2325           0 : { return mpImpl->mbReadOnly; }
    2326           0 : void                TextView::SetAutoScroll( bool bAutoScroll )
    2327           0 : { mpImpl->mbAutoScroll = bAutoScroll; }
    2328           0 : bool                TextView::IsAutoScroll() const
    2329           0 : { return mpImpl->mbAutoScroll; }
    2330           0 : bool                TextView::HasSelection() const
    2331           0 : { return mpImpl->maSelection.HasRange(); }
    2332           0 : bool                TextView::IsInsertMode() const
    2333           0 : { return mpImpl->mbInsertMode; }
    2334           0 : void                TextView::SupportProtectAttribute(bool bSupport)
    2335           0 : { mpImpl->mbSupportProtectAttribute = bSupport;}
    2336             : 
    2337             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10