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

Generated by: LCOV version 1.10