LCOV - code coverage report
Current view: top level - libreoffice/vcl/source/edit - textview.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1252 0.0 %
Date: 2012-12-27 Functions: 0 111 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10