LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/editeng/source/editeng - impedit2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1080 2270 47.6 %
Date: 2013-07-09 Functions: 74 115 64.3 %
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             : 
      21             : #include <vcl/wrkwin.hxx>
      22             : #include <vcl/dialog.hxx>
      23             : #include <vcl/msgbox.hxx>
      24             : #include <vcl/svapp.hxx>
      25             : 
      26             : #include <editeng/lspcitem.hxx>
      27             : #include <editeng/flditem.hxx>
      28             : #include <impedit.hxx>
      29             : #include <editeng/editeng.hxx>
      30             : #include <editeng/editview.hxx>
      31             : #include <editdbg.hxx>
      32             : #include <eerdll2.hxx>
      33             : #include <editeng/eerdll.hxx>
      34             : #include <edtspell.hxx>
      35             : #include <eeobj.hxx>
      36             : #include <editeng/txtrange.hxx>
      37             : #include <svl/urlbmk.hxx>
      38             : #include <svtools/colorcfg.hxx>
      39             : #include <svl/ctloptions.hxx>
      40             : #include <editeng/acorrcfg.hxx>
      41             : #include <editeng/fhgtitem.hxx>
      42             : #include <editeng/lrspitem.hxx>
      43             : #include <editeng/ulspitem.hxx>
      44             : #include <editeng/wghtitem.hxx>
      45             : #include <editeng/postitem.hxx>
      46             : #include <editeng/udlnitem.hxx>
      47             : #include <editeng/adjustitem.hxx>
      48             : #include <editeng/scripttypeitem.hxx>
      49             : #include <editeng/frmdiritem.hxx>
      50             : #include <editeng/fontitem.hxx>
      51             : #include <editeng/justifyitem.hxx>
      52             : 
      53             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      54             : #include <com/sun/star/i18n/WordType.hpp>
      55             : #include <com/sun/star/i18n/ScriptType.hpp>
      56             : #include <com/sun/star/lang/Locale.hpp>
      57             : #include <com/sun/star/text/CharacterCompressionType.hpp>
      58             : #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
      59             : 
      60             : #include <comphelper/processfactory.hxx>
      61             : 
      62             : #include <sot/formats.hxx>
      63             : 
      64             : #include <unicode/ubidi.h>
      65             : 
      66             : #include <boost/scoped_ptr.hpp>
      67             : 
      68             : using namespace ::com::sun::star;
      69             : 
      70        9935 : static sal_uInt16 lcl_CalcExtraSpace( ParaPortion*, const SvxLineSpacingItem& rLSItem )
      71             : {
      72        9935 :     sal_uInt16 nExtra = 0;
      73        9935 :     if ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
      74             :     {
      75         611 :         nExtra = rLSItem.GetInterLineSpace();
      76             :     }
      77             : 
      78        9935 :     return nExtra;
      79             : }
      80             : 
      81       19585 : ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) :
      82             :     aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
      83             :     aMinAutoPaperSize( 0x0, 0x0 ),
      84             :     aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
      85             :     aEditDoc( pItemPool ),
      86             :     aWordDelimiters( RTL_CONSTASCII_USTRINGPARAM( "  .,;:-'`'?!_=\"{}()[]\0xFF" ) ),
      87             :     aGroupChars( RTL_CONSTASCII_USTRINGPARAM( "{}()[]" ) ),
      88             :     bKernAsianPunctuation(false),
      89             :     bAddExtLeading(false),
      90             :     bIsFormatting(false),
      91             :     bFormatted(false),
      92             :     bInSelection(false),
      93             :     bIsInUndo(false),
      94             :     bUpdate(true),
      95             :     bUndoEnabled(true),
      96             :     bOwnerOfRefDev(false),
      97             :     bDowning(false),
      98             :     bUseAutoColor(true),
      99             :     bForceAutoColor(false),
     100             :     bCallParaInsertedOrDeleted(false),
     101             :     bImpConvertFirstCall(false),
     102             :     bFirstWordCapitalization(true),
     103       19585 :     mbLastTryMerge(false)
     104             : {
     105       19585 :     pEditEngine         = pEE;
     106       19585 :     pRefDev             = NULL;
     107       19585 :     pVirtDev            = NULL;
     108       19585 :     pEmptyItemSet       = NULL;
     109       19585 :     pActiveView         = NULL;
     110       19585 :     pSpellInfo          = NULL;
     111       19585 :     pConvInfo           = NULL;
     112       19585 :     pTextObjectPool     = NULL;
     113       19585 :     mpIMEInfos          = NULL;
     114       19585 :     pStylePool          = NULL;
     115       19585 :     pUndoManager        = NULL;
     116       19585 :     pUndoMarkSelection  = NULL;
     117       19585 :     pTextRanger         = NULL;
     118       19585 :     pColorConfig        = NULL;
     119       19585 :     pCTLOptions         = NULL;
     120             : 
     121       19585 :     nCurTextHeight      = 0;
     122       19585 :     nCurTextHeightNTP   = 0;
     123       19585 :     nBlockNotifications = 0;
     124       19585 :     nBigTextObjectStart = 20;
     125             : 
     126       19585 :     nStretchX           = 100;
     127       19585 :     nStretchY           = 100;
     128             : 
     129       19585 :     eDefLanguage        = LANGUAGE_DONTKNOW;
     130       19585 :     maBackgroundColor   = COL_AUTO;
     131             : 
     132       19585 :     nAsianCompressionMode = text::CharacterCompressionType::NONE;
     133             : 
     134       19585 :     eDefaultHorizontalTextDirection = EE_HTEXTDIR_DEFAULT;
     135             : 
     136             : 
     137       19585 :     aStatus.GetControlWord() =  EE_CNTRL_USECHARATTRIBS | EE_CNTRL_DOIDLEFORMAT |
     138             :                                 EE_CNTRL_PASTESPECIAL | EE_CNTRL_UNDOATTRIBS |
     139             :                                 EE_CNTRL_ALLOWBIGOBJS | EE_CNTRL_RTFSTYLESHEETS |
     140       19585 :                                 EE_CNTRL_FORMAT100;
     141             : 
     142       19585 :     aSelEngine.SetFunctionSet( &aSelFuncSet );
     143             : 
     144       19585 :     aStatusTimer.SetTimeout( 200 );
     145       19585 :     aStatusTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, StatusTimerHdl ) );
     146             : 
     147       19585 :     aIdleFormatter.SetTimeout( 5 );
     148       19585 :     aIdleFormatter.SetTimeoutHdl( LINK( this, ImpEditEngine, IdleFormatHdl ) );
     149             : 
     150       19585 :     aOnlineSpellTimer.SetTimeout( 100 );
     151       19585 :     aOnlineSpellTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, OnlineSpellHdl ) );
     152             : 
     153             :     // Access data already from here on!
     154       19585 :     SetRefDevice( NULL );
     155       19585 :     InitDoc( sal_False );
     156             : 
     157       19585 :     bCallParaInsertedOrDeleted = true;
     158             : 
     159       19585 :     aEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) );
     160       19585 : }
     161             : 
     162       58578 : ImpEditEngine::~ImpEditEngine()
     163             : {
     164       19526 :     aStatusTimer.Stop();
     165       19526 :     aOnlineSpellTimer.Stop();
     166       19526 :     aIdleFormatter.Stop();
     167             : 
     168             :     // Destroying templates may otherwise cause unnecessary formatting,
     169             :     // when a parent template is destroyed.
     170             :     // And this after the destruction of the data!
     171       19526 :     bDowning = true;
     172       19526 :     SetUpdateMode( sal_False );
     173             : 
     174       19526 :     delete pVirtDev;
     175       19526 :     delete pEmptyItemSet;
     176       19526 :     delete pUndoManager;
     177       19526 :     delete pTextRanger;
     178       19526 :     delete mpIMEInfos;
     179       19526 :     delete pColorConfig;
     180       19526 :     delete pCTLOptions;
     181       19526 :     if ( bOwnerOfRefDev )
     182       16344 :         delete pRefDev;
     183       19526 :     delete pSpellInfo;
     184       39052 : }
     185             : 
     186       31997 : void ImpEditEngine::SetRefDevice( OutputDevice* pRef )
     187             : {
     188       31997 :     if ( bOwnerOfRefDev )
     189       11079 :         delete pRefDev;
     190             : 
     191       31997 :     if ( !pRef )
     192             :     {
     193       27425 :         pRefDev = new VirtualDevice;
     194       27425 :         pRefDev->SetMapMode( MAP_TWIP );
     195       27425 :         bOwnerOfRefDev = true;
     196             :     } else
     197             :     {
     198        4572 :         pRefDev = pRef;
     199        4572 :         bOwnerOfRefDev = false;
     200             :     }
     201             : 
     202       31997 :     nOnePixelInRef = (sal_uInt16)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
     203             : 
     204       31997 :     if ( IsFormatted() )
     205             :     {
     206       10977 :         FormatFullDoc();
     207       10977 :         UpdateViews( (EditView*) 0);
     208             :     }
     209       31997 : }
     210             : 
     211       10657 : void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode )
     212             : {
     213       10657 :     if ( GetRefDevice()->GetMapMode() == rMapMode )
     214       16472 :         return;
     215             : 
     216        4842 :     if ( !bOwnerOfRefDev )
     217             :     {
     218          26 :         pRefDev = new VirtualDevice;
     219          26 :         pRefDev->SetMapMode( MAP_TWIP );
     220          26 :         SetRefDevice( pRefDev );
     221          26 :         bOwnerOfRefDev = true;
     222             :     }
     223        4842 :     pRefDev->SetMapMode( rMapMode );
     224        4842 :     nOnePixelInRef = (sal_uInt16)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
     225        4842 :     if ( IsFormatted() )
     226             :     {
     227        2722 :         FormatFullDoc();
     228        2722 :         UpdateViews( (EditView*) 0);
     229             :     }
     230             : }
     231             : 
     232      460309 : void ImpEditEngine::InitDoc(bool bKeepParaAttribs)
     233             : {
     234      460309 :     sal_Int32 nParas = aEditDoc.Count();
     235      683151 :     for ( sal_Int32 n = bKeepParaAttribs ? 1 : 0; n < nParas; n++ )
     236             :     {
     237      222842 :         if ( aEditDoc[n]->GetStyleSheet() )
     238      101153 :             EndListening( *aEditDoc[n]->GetStyleSheet(), sal_False );
     239             :     }
     240             : 
     241      460309 :     if ( bKeepParaAttribs )
     242      223256 :         aEditDoc.RemoveText();
     243             :     else
     244      237053 :         aEditDoc.Clear();
     245             : 
     246      460309 :     GetParaPortions().Reset();
     247             : 
     248      460309 :     ParaPortion* pIniPortion = new ParaPortion( aEditDoc[0] );
     249      460309 :     GetParaPortions().Insert(0, pIniPortion);
     250             : 
     251      460309 :     bFormatted = false;
     252             : 
     253      460309 :     if ( IsCallParaInsertedOrDeleted() )
     254             :     {
     255      440724 :         GetEditEnginePtr()->ParagraphDeleted( EE_PARA_ALL );
     256      440724 :         GetEditEnginePtr()->ParagraphInserted( 0 );
     257             :     }
     258             : 
     259      460309 :     if ( GetStatus().DoOnlineSpelling() )
     260      295829 :         aEditDoc.GetObject( 0 )->CreateWrongList();
     261      460309 : }
     262             : 
     263           3 : EditPaM ImpEditEngine::DeleteSelected( EditSelection aSel )
     264             : {
     265           3 :     EditPaM aPaM ( ImpDeleteSelection( aSel ) );
     266           3 :     return aPaM;
     267             : }
     268             : 
     269        5573 : XubString ImpEditEngine::GetSelected( const EditSelection& rSel, const LineEnd eEnd  ) const
     270             : {
     271        5573 :     XubString aText;
     272        5573 :     if ( !rSel.HasRange() )
     273         236 :         return aText;
     274             : 
     275       10674 :     String aSep = EditDoc::GetSepStr( eEnd );
     276             : 
     277        5337 :     EditSelection aSel( rSel );
     278        5337 :     aSel.Adjust( aEditDoc );
     279             : 
     280        5337 :     ContentNode* pStartNode = aSel.Min().GetNode();
     281        5337 :     ContentNode* pEndNode = aSel.Max().GetNode();
     282        5337 :     sal_Int32 nStartNode = aEditDoc.GetPos( pStartNode );
     283        5337 :     sal_Int32 nEndNode = aEditDoc.GetPos( pEndNode );
     284             : 
     285             :     OSL_ENSURE( nStartNode <= nEndNode, "Selection not sorted ?" );
     286             : 
     287             :     // iterate over the paragraphs ...
     288       10758 :     for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
     289             :     {
     290             :         OSL_ENSURE( aEditDoc.GetObject( nNode ), "Node not found: GetSelected" );
     291        5421 :         const ContentNode* pNode = aEditDoc.GetObject( nNode );
     292             : 
     293        5421 :         xub_StrLen nStartPos = 0;
     294        5421 :         xub_StrLen nEndPos = pNode->Len();
     295        5421 :         if ( nNode == nStartNode )
     296        5337 :             nStartPos = aSel.Min().GetIndex();
     297        5421 :         if ( nNode == nEndNode ) // can also be == nStart!
     298        5337 :             nEndPos = aSel.Max().GetIndex();
     299             : 
     300        5421 :         aText += aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
     301        5421 :         if ( nNode < nEndNode )
     302          84 :             aText += aSep;
     303             :     }
     304        5337 :     return aText;
     305             : }
     306             : 
     307           0 : sal_Bool ImpEditEngine::MouseButtonDown( const MouseEvent& rMEvt, EditView* pView )
     308             : {
     309           0 :     GetSelEngine().SetCurView( pView );
     310           0 :     SetActiveView( pView );
     311             : 
     312           0 :     if ( GetAutoCompleteText().Len() )
     313           0 :         SetAutoCompleteText( String(), sal_True );
     314             : 
     315           0 :     GetSelEngine().SelMouseButtonDown( rMEvt );
     316             :     // Special treatment
     317           0 :     EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
     318           0 :     if ( !rMEvt.IsShift() )
     319             :     {
     320           0 :         if ( rMEvt.GetClicks() == 2 )
     321             :         {
     322             :             // So that the SelectionEngine knows about the anchor.
     323           0 :             aSelEngine.CursorPosChanging( sal_True, sal_False );
     324             : 
     325           0 :             EditSelection aNewSelection( SelectWord( aCurSel ) );
     326           0 :             pView->pImpEditView->DrawSelection();
     327           0 :             pView->pImpEditView->SetEditSelection( aNewSelection );
     328           0 :             pView->pImpEditView->DrawSelection();
     329           0 :             pView->ShowCursor( sal_True, sal_True );
     330             :         }
     331           0 :         else if ( rMEvt.GetClicks() == 3 )
     332             :         {
     333             :             // So that the SelectionEngine knows about the anchor.
     334           0 :             aSelEngine.CursorPosChanging( sal_True, sal_False );
     335             : 
     336           0 :             EditSelection aNewSelection( aCurSel );
     337           0 :             aNewSelection.Min().SetIndex( 0 );
     338           0 :             aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() );
     339           0 :             pView->pImpEditView->DrawSelection();
     340           0 :             pView->pImpEditView->SetEditSelection( aNewSelection );
     341           0 :             pView->pImpEditView->DrawSelection();
     342           0 :             pView->ShowCursor( sal_True, sal_True );
     343             :         }
     344             :     }
     345           0 :     return sal_True;
     346             : }
     347             : 
     348           0 : void ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
     349             : {
     350           0 :     GetSelEngine().SetCurView( pView );
     351           0 :     SetActiveView( pView );
     352           0 :     if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
     353             :     {
     354           0 :         pView->DeleteSelected();
     355           0 :         delete mpIMEInfos;
     356           0 :         EditPaM aPaM = pView->GetImpEditView()->GetEditSelection().Max();
     357           0 :         String aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() );
     358           0 :         sal_uInt16 nMax = aOldTextAfterStartPos.Search( CH_FEATURE );
     359           0 :         if ( nMax != STRING_NOTFOUND )  // don't overwrite features!
     360           0 :             aOldTextAfterStartPos.Erase( nMax );
     361           0 :         mpIMEInfos = new ImplIMEInfos( aPaM, aOldTextAfterStartPos );
     362           0 :         mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode();
     363           0 :         UndoActionStart( EDITUNDO_INSERT );
     364             :     }
     365           0 :     else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
     366             :     {
     367             :         OSL_ENSURE( mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" );
     368           0 :         if( mpIMEInfos )
     369             :         {
     370             :             // #102812# convert quotes in IME text
     371             :             // works on the last input character, this is escpecially in Korean text often done
     372             :             // quotes that are inside of the string are not replaced!
     373             :             // Borrowed from sw: edtwin.cxx
     374           0 :             if ( mpIMEInfos->nLen )
     375             :             {
     376           0 :                 EditSelection aSel( mpIMEInfos->aPos );
     377           0 :                 aSel.Min().GetIndex() += mpIMEInfos->nLen-1;
     378           0 :                 aSel.Max().GetIndex() =
     379           0 :                     aSel.Max().GetIndex() + mpIMEInfos->nLen;
     380             :                 // #102812# convert quotes in IME text
     381             :                 // works on the last input character, this is escpecially in Korean text often done
     382             :                 // quotes that are inside of the string are not replaced!
     383           0 :                 const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() );
     384           0 :                 if ( ( GetStatus().DoAutoCorrect() ) && ( ( nCharCode == '\"' ) || ( nCharCode == '\'' ) ) )
     385             :                 {
     386           0 :                     aSel = DeleteSelected( aSel );
     387           0 :                     aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite );
     388           0 :                     pView->pImpEditView->SetEditSelection( aSel );
     389             :                 }
     390             :             }
     391             : 
     392           0 :             ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
     393           0 :             pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex(), 0 );
     394             : 
     395           0 :             sal_Bool bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite;
     396             : 
     397           0 :             delete mpIMEInfos;
     398           0 :             mpIMEInfos = NULL;
     399             : 
     400           0 :             FormatAndUpdate( pView );
     401             : 
     402           0 :             pView->SetInsertMode( !bWasCursorOverwrite );
     403             :         }
     404           0 :         UndoActionEnd( EDITUNDO_INSERT );
     405             :     }
     406           0 :     else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
     407             :     {
     408             :         OSL_ENSURE( mpIMEInfos, "COMMAND_EXTTEXTINPUT => No Start ?" );
     409           0 :         if( mpIMEInfos )
     410             :         {
     411           0 :             const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
     412             : 
     413           0 :             if ( !pData->IsOnlyCursorChanged() )
     414             :             {
     415           0 :                 EditSelection aSel( mpIMEInfos->aPos );
     416           0 :                 aSel.Max().GetIndex() =
     417           0 :                     aSel.Max().GetIndex() + mpIMEInfos->nLen;
     418           0 :                 aSel = DeleteSelected( aSel );
     419           0 :                 aSel = ImpInsertText( aSel, pData->GetText() );
     420             : 
     421           0 :                 if ( mpIMEInfos->bWasCursorOverwrite )
     422             :                 {
     423           0 :                     sal_uInt16 nOldIMETextLen = mpIMEInfos->nLen;
     424           0 :                     sal_uInt16 nNewIMETextLen = pData->GetText().Len();
     425             : 
     426           0 :                     if ( ( nOldIMETextLen > nNewIMETextLen ) &&
     427           0 :                          ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
     428             :                     {
     429             :                         // restore old characters
     430           0 :                         sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen;
     431           0 :                         EditPaM aPaM( mpIMEInfos->aPos );
     432           0 :                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
     433           0 :                         ImpInsertText( aPaM, mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) );
     434             :                     }
     435           0 :                     else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
     436           0 :                               ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
     437             :                     {
     438             :                         // overwrite
     439           0 :                         sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen;
     440           0 :                         if ( ( nOldIMETextLen + nOverwrite ) > mpIMEInfos->aOldTextAfterStartPos.Len() )
     441           0 :                             nOverwrite = mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen;
     442             :                         OSL_ENSURE( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" );
     443           0 :                         EditPaM aPaM( mpIMEInfos->aPos );
     444           0 :                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
     445           0 :                         EditSelection _aSel( aPaM );
     446           0 :                         _aSel.Max().GetIndex() =
     447           0 :                             _aSel.Max().GetIndex() + nOverwrite;
     448           0 :                         DeleteSelected( _aSel );
     449             :                     }
     450             :                 }
     451           0 :                 if ( pData->GetTextAttr() )
     452             :                 {
     453           0 :                     mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
     454           0 :                     mpIMEInfos->bCursor = pData->IsCursorVisible();
     455             :                 }
     456             :                 else
     457             :                 {
     458           0 :                     mpIMEInfos->DestroyAttribs();
     459           0 :                     mpIMEInfos->nLen = pData->GetText().Len();
     460             :                 }
     461             : 
     462           0 :                 ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
     463           0 :                 pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex(), 0 );
     464           0 :                 FormatAndUpdate( pView );
     465             :             }
     466             : 
     467           0 :             EditSelection aNewSel = EditPaM( mpIMEInfos->aPos.GetNode(), mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() );
     468           0 :             pView->SetSelection( CreateESel( aNewSel ) );
     469           0 :             pView->SetInsertMode( !pData->IsCursorOverwrite() );
     470             : 
     471           0 :             if ( pData->IsCursorVisible() )
     472           0 :                 pView->ShowCursor();
     473             :             else
     474           0 :                 pView->HideCursor();
     475             :         }
     476             :     }
     477           0 :     else if ( rCEvt.GetCommand() == COMMAND_INPUTCONTEXTCHANGE )
     478             :     {
     479             :     }
     480           0 :     else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
     481             :     {
     482           0 :         if ( mpIMEInfos && mpIMEInfos->nLen )
     483             :         {
     484           0 :             EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() );
     485           0 :             Rectangle aR1 = PaMtoEditCursor( aPaM, 0 );
     486             : 
     487           0 :             sal_uInt16 nInputEnd = mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen;
     488             : 
     489           0 :             if ( !IsFormatted() )
     490           0 :                 FormatDoc();
     491             : 
     492           0 :             ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( GetEditDoc().GetPos( aPaM.GetNode() ) );
     493           0 :             sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_True );
     494           0 :             const EditLine* pLine = pParaPortion->GetLines()[nLine];
     495           0 :             if ( pLine && ( nInputEnd > pLine->GetEnd() ) )
     496           0 :                 nInputEnd = pLine->GetEnd();
     497           0 :             Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GETCRSR_ENDOFLINE );
     498           0 :             Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 );
     499           0 :             pView->GetWindow()->SetCursorRect( &aRect, aR2.Left()-aR1.Right() );
     500             :         }
     501             :         else
     502             :         {
     503           0 :             pView->GetWindow()->SetCursorRect();
     504             :         }
     505             :     }
     506           0 :     else if ( rCEvt.GetCommand() == COMMAND_SELECTIONCHANGE )
     507             :     {
     508           0 :         const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
     509             : 
     510           0 :         ESelection aSelection = pView->GetSelection();
     511           0 :         aSelection.Adjust();
     512             : 
     513           0 :         if( pView->HasSelection() )
     514             :         {
     515           0 :             aSelection.nEndPos = aSelection.nStartPos;
     516           0 :             aSelection.nStartPos += pData->GetStart();
     517           0 :             aSelection.nEndPos += pData->GetEnd();
     518             :         }
     519             :         else
     520             :         {
     521           0 :             aSelection.nStartPos = pData->GetStart();
     522           0 :             aSelection.nEndPos = pData->GetEnd();
     523             :         }
     524           0 :         pView->SetSelection( aSelection );
     525             :     }
     526           0 :     else if ( rCEvt.GetCommand() == COMMAND_PREPARERECONVERSION )
     527             :     {
     528           0 :         if ( pView->HasSelection() )
     529             :         {
     530           0 :             ESelection aSelection = pView->GetSelection();
     531           0 :             aSelection.Adjust();
     532             : 
     533           0 :             if ( aSelection.nStartPara != aSelection.nEndPara )
     534             :             {
     535           0 :                 xub_StrLen aParaLen = pEditEngine->GetTextLen( aSelection.nStartPara );
     536           0 :                 aSelection.nEndPara = aSelection.nStartPara;
     537           0 :                 aSelection.nEndPos = aParaLen;
     538           0 :                 pView->SetSelection( aSelection );
     539             :             }
     540             :         }
     541             :     }
     542           0 :     else if ( rCEvt.GetCommand() == COMMAND_QUERYCHARPOSITION )
     543             :     {
     544           0 :         if ( mpIMEInfos && mpIMEInfos->nLen )
     545             :         {
     546           0 :             EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() );
     547           0 :             if ( !IsFormatted() )
     548           0 :                 FormatDoc();
     549             : 
     550           0 :             ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( GetEditDoc().GetPos( aPaM.GetNode() ) );
     551           0 :             sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_True );
     552           0 :             const EditLine* pLine = pParaPortion->GetLines()[nLine];
     553           0 :             if ( pLine )
     554             :             {
     555           0 :                 Rectangle* aRects = new Rectangle[ mpIMEInfos->nLen ];
     556           0 :                 for (sal_uInt16 i = 0; i < mpIMEInfos->nLen; ++i)
     557             :                 {
     558           0 :                     sal_uInt16 nInputPos = mpIMEInfos->aPos.GetIndex() + i;
     559           0 :                     if ( nInputPos > pLine->GetEnd() )
     560           0 :                         nInputPos = pLine->GetEnd();
     561           0 :                     Rectangle aR2 = GetEditCursor( pParaPortion, nInputPos );
     562           0 :                     aRects[ i ] = pView->GetImpEditView()->GetWindowPos( aR2 );
     563             :                 }
     564           0 :                 pView->GetWindow()->SetCompositionCharRect( aRects, mpIMEInfos->nLen );
     565           0 :                 delete[] aRects;
     566             :             }
     567             :         }
     568             :     }
     569             : 
     570           0 :     GetSelEngine().Command( rCEvt );
     571           0 : }
     572             : 
     573           0 : sal_Bool ImpEditEngine::MouseButtonUp( const MouseEvent& rMEvt, EditView* pView )
     574             : {
     575           0 :     GetSelEngine().SetCurView( pView );
     576           0 :     GetSelEngine().SelMouseButtonUp( rMEvt );
     577           0 :     bInSelection = false;
     578             :     // Special treatments
     579           0 :     EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
     580           0 :     if ( !aCurSel.HasRange() )
     581             :     {
     582           0 :         if ( ( rMEvt.GetClicks() == 1 ) && rMEvt.IsLeft() && !rMEvt.IsMod2() )
     583             :         {
     584           0 :             const SvxFieldItem* pFld = pView->GetFieldUnderMousePointer();
     585           0 :             if ( pFld )
     586             :             {
     587           0 :                 EditPaM aPaM( aCurSel.Max() );
     588           0 :                 sal_Int32 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
     589           0 :                 GetEditEnginePtr()->FieldClicked( *pFld, nPara, aPaM.GetIndex() );
     590             :             }
     591             :         }
     592             :     }
     593           0 :     return sal_True;
     594             : }
     595             : 
     596           0 : sal_Bool ImpEditEngine::MouseMove( const MouseEvent& rMEvt, EditView* pView )
     597             : {
     598             :     // MouseMove is called directly after ShowQuickHelp()!
     599           0 :     GetSelEngine().SetCurView( pView );
     600           0 :     GetSelEngine().SelMouseMove( rMEvt );
     601           0 :     return sal_True;
     602             : }
     603             : 
     604          22 : EditPaM ImpEditEngine::InsertText(const EditSelection& aSel, const String& rStr)
     605             : {
     606          22 :     EditPaM aPaM = ImpInsertText( aSel, rStr );
     607          22 :     return aPaM;
     608             : }
     609             : 
     610      217468 : EditPaM ImpEditEngine::Clear()
     611             : {
     612      217468 :     InitDoc( sal_False );
     613             : 
     614      217468 :     EditPaM aPaM = aEditDoc.GetStartPaM();
     615      217468 :     EditSelection aSel( aPaM );
     616             : 
     617      217468 :     nCurTextHeight = 0;
     618      217468 :     nCurTextHeightNTP = 0;
     619             : 
     620      217468 :     ResetUndoManager();
     621             : 
     622      434936 :     for (size_t nView = aEditViews.size(); nView; )
     623             :     {
     624           0 :         EditView* pView = aEditViews[--nView];
     625             :         DBG_CHKOBJ( pView, EditView, 0 );
     626           0 :         pView->pImpEditView->SetEditSelection( aSel );
     627             :     }
     628             : 
     629      217468 :     return aPaM;
     630             : }
     631             : 
     632      223256 : EditPaM ImpEditEngine::RemoveText()
     633             : {
     634      223256 :     InitDoc( sal_True );
     635             : 
     636      223256 :     EditPaM aStartPaM = aEditDoc.GetStartPaM();
     637      223256 :     EditSelection aEmptySel( aStartPaM, aStartPaM );
     638      223378 :     for (size_t nView = 0; nView < aEditViews.size(); ++nView)
     639             :     {
     640         122 :         EditView* pView = aEditViews[nView];
     641             :         DBG_CHKOBJ( pView, EditView, 0 );
     642         122 :         pView->pImpEditView->SetEditSelection( aEmptySel );
     643             :     }
     644      223256 :     ResetUndoManager();
     645      223256 :     return aEditDoc.GetStartPaM();
     646             : }
     647             : 
     648             : 
     649      223256 : void ImpEditEngine::SetText( const XubString& rText )
     650             : {
     651             :     // RemoveText deletes the undo list!
     652      223256 :     EditPaM aStartPaM = RemoveText();
     653      223256 :     sal_Bool bUndoCurrentlyEnabled = IsUndoEnabled();
     654             :     // The text inserted manually can not be made reversable by the user
     655      223256 :     EnableUndo( sal_False );
     656             : 
     657      223256 :     EditSelection aEmptySel( aStartPaM, aStartPaM );
     658      223256 :     EditPaM aPaM = aStartPaM;
     659      223256 :     if ( rText.Len() )
     660        8115 :         aPaM = ImpInsertText( aEmptySel, rText );
     661             : 
     662      223378 :     for (size_t nView = 0; nView < aEditViews.size(); ++nView)
     663             :     {
     664         122 :         EditView* pView = aEditViews[nView];
     665             :         DBG_CHKOBJ( pView, EditView, 0 );
     666         122 :         pView->pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) );
     667             :         //  If no text then also no Format&Update
     668             :         // => The text remains.
     669         122 :         if ( !rText.Len() && GetUpdateMode() )
     670             :         {
     671           2 :             Rectangle aTmpRect( pView->GetOutputArea().TopLeft(),
     672           4 :                                 Size( aPaperSize.Width(), nCurTextHeight ) );
     673           2 :             aTmpRect.Intersection( pView->GetOutputArea() );
     674           2 :             pView->GetWindow()->Invalidate( aTmpRect );
     675             :         }
     676             :     }
     677      223256 :     if( !rText.Len() ) {    // otherwise it must be invalidated later, !bFormatted is enough.
     678      215141 :         nCurTextHeight = 0;
     679      215141 :         nCurTextHeightNTP = 0;
     680             :     }
     681      223256 :     EnableUndo( bUndoCurrentlyEnabled );
     682             :     OSL_ENSURE( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo after SetText?" );
     683      223256 : }
     684             : 
     685             : 
     686      292300 : const SfxItemSet& ImpEditEngine::GetEmptyItemSet()
     687             : {
     688      292300 :     if ( !pEmptyItemSet )
     689             :     {
     690        4161 :         pEmptyItemSet = new SfxItemSet( aEditDoc.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END );
     691      203889 :         for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
     692             :         {
     693      199728 :             pEmptyItemSet->ClearItem( nWhich );
     694             :         }
     695             :     }
     696      292300 :     return *pEmptyItemSet;
     697             : }
     698             : 
     699             : //  ----------------------------------------------------------------------
     700             : //  MISC
     701             : //  ----------------------------------------------------------------------
     702        2815 : void ImpEditEngine::CursorMoved( ContentNode* pPrevNode )
     703             : {
     704             :     // Delete empty attributes, but only if paragraph is not empty!
     705        2815 :     if ( pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len() )
     706         168 :         pPrevNode->GetCharAttribs().DeleteEmptyAttribs( aEditDoc.GetItemPool() );
     707        2815 : }
     708             : 
     709      260325 : void ImpEditEngine::TextModified()
     710             : {
     711      260325 :     bFormatted = false;
     712             : 
     713      260325 :     if ( GetNotifyHdl().IsSet() )
     714             :     {
     715          82 :         EENotify aNotify( EE_NOTIFY_TEXTMODIFIED );
     716          82 :         aNotify.pEditEngine = GetEditEnginePtr();
     717          82 :         CallNotify( aNotify );
     718             :     }
     719      260325 : }
     720             : 
     721             : 
     722      577675 : void ImpEditEngine::ParaAttribsChanged( ContentNode* pNode )
     723             : {
     724             :     OSL_ENSURE( pNode, "ParaAttribsChanged: Which one?" );
     725             : 
     726      577675 :     aEditDoc.SetModified( sal_True );
     727      577675 :     bFormatted = false;
     728             : 
     729      577675 :     ParaPortion* pPortion = FindParaPortion( pNode );
     730             :     OSL_ENSURE( pPortion, "ParaAttribsChanged: Portion?" );
     731      577675 :     pPortion->MarkSelectionInvalid( 0, pNode->Len() );
     732             : 
     733      577675 :     sal_Int32 nPara = aEditDoc.GetPos( pNode );
     734      577675 :     pEditEngine->ParaAttribsChanged( nPara );
     735             : 
     736      577675 :     ParaPortion* pNextPortion = GetParaPortions().SafeGetObject( nPara+1 );
     737             :     // => is formatted again anyway, if Invalid.
     738      577675 :     if ( pNextPortion && !pNextPortion->IsInvalid() )
     739         219 :         CalcHeight( pNextPortion );
     740      577675 : }
     741             : 
     742             : //  ----------------------------------------------------------------------
     743             : //  Cursor movements
     744             : //  ----------------------------------------------------------------------
     745             : 
     746           0 : EditSelection ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, EditView* pEditView )
     747             : {
     748             :     // Actually, only necessary for up/down, but whatever.
     749           0 :     CheckIdleFormatter();
     750             : 
     751           0 :     EditPaM aPaM( pEditView->pImpEditView->GetEditSelection().Max() );
     752             : 
     753           0 :     EditPaM aOldPaM( aPaM );
     754             : 
     755           0 :     TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
     756           0 :     if ( IsVertical() )
     757           0 :         eTextDirection = TextDirectionality_TopToBottom_RightToLeft;
     758           0 :     else if ( IsRightToLeft( GetEditDoc().GetPos( aPaM.GetNode() ) ) )
     759           0 :         eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
     760             : 
     761           0 :     KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
     762             : 
     763           0 :     sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False;
     764           0 :     sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
     765             : 
     766           0 :     if ( DoVisualCursorTraveling( aPaM.GetNode() ) )
     767             :     {
     768             :         // Only for simple cursor movement...
     769           0 :         if ( !bCtrl && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ) )
     770             :         {
     771           0 :             aPaM = CursorVisualLeftRight( pEditView, aPaM, rKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL, rKeyEvent.GetKeyCode().GetCode() == KEY_LEFT );
     772           0 :             nCode = 0;  // skip switch statement
     773             :         }
     774             :     }
     775             : 
     776           0 :     bool bKeyModifySelection = aTranslatedKeyEvent.GetKeyCode().IsShift();
     777           0 :     switch ( nCode )
     778             :     {
     779           0 :         case KEY_UP:        aPaM = CursorUp( aPaM, pEditView );
     780           0 :                             break;
     781           0 :         case KEY_DOWN:      aPaM = CursorDown( aPaM, pEditView );
     782           0 :                             break;
     783           0 :         case KEY_LEFT:      aPaM = bCtrl ? WordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL );
     784           0 :                             break;
     785           0 :         case KEY_RIGHT:     aPaM = bCtrl ? WordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL );
     786           0 :                             break;
     787           0 :         case KEY_HOME:      aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
     788           0 :                             break;
     789           0 :         case KEY_END:       aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
     790           0 :                             break;
     791           0 :         case KEY_PAGEUP:    aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM, pEditView );
     792           0 :                             break;
     793           0 :         case KEY_PAGEDOWN:  aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM, pEditView );
     794           0 :                             break;
     795             :         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
     796           0 :                             aPaM = CursorStartOfLine( aPaM );
     797           0 :                             bKeyModifySelection = false;
     798           0 :                             break;
     799             :         case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
     800           0 :                             aPaM = CursorEndOfLine( aPaM );
     801           0 :                             bKeyModifySelection = false;
     802           0 :                             break;
     803             :         case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
     804           0 :                             aPaM = WordLeft( aPaM );
     805           0 :                             bKeyModifySelection = false;
     806           0 :                             break;
     807             :         case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
     808           0 :                             aPaM = WordRight( aPaM );
     809           0 :                             bKeyModifySelection = false;
     810           0 :                             break;
     811             :         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
     812           0 :                             aPaM = CursorStartOfParagraph( aPaM );
     813           0 :                             if( aPaM == aOldPaM )
     814             :                             {
     815           0 :                                 aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
     816           0 :                                 aPaM = CursorStartOfParagraph( aPaM );
     817             :                             }
     818           0 :                             bKeyModifySelection = false;
     819           0 :                             break;
     820             :         case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
     821           0 :                             aPaM = CursorEndOfParagraph( aPaM );
     822           0 :                             if( aPaM == aOldPaM )
     823             :                             {
     824           0 :                                 aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
     825           0 :                                 aPaM = CursorEndOfParagraph( aPaM );
     826             :                             }
     827           0 :                             bKeyModifySelection = false;
     828           0 :                             break;
     829             :         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
     830           0 :                             aPaM = CursorStartOfDoc();
     831           0 :                             bKeyModifySelection = false;
     832           0 :                             break;
     833             :         case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
     834           0 :                             aPaM = CursorEndOfDoc();
     835           0 :                             bKeyModifySelection = false;
     836           0 :                             break;
     837             :         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
     838           0 :                             aPaM = CursorStartOfLine( aPaM );
     839           0 :                             bKeyModifySelection = true;
     840           0 :                             break;
     841             :         case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
     842           0 :                             aPaM = CursorEndOfLine( aPaM );
     843           0 :                             bKeyModifySelection = true;
     844           0 :                             break;
     845             :         case com::sun::star::awt::Key::SELECT_BACKWARD:
     846           0 :                             aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
     847           0 :                             bKeyModifySelection = true;
     848           0 :                             break;
     849             :         case com::sun::star::awt::Key::SELECT_FORWARD:
     850           0 :                             aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
     851           0 :                             bKeyModifySelection = true;
     852           0 :                             break;
     853             :         case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
     854           0 :                             aPaM = WordLeft( aPaM );
     855           0 :                             bKeyModifySelection = true;
     856           0 :                             break;
     857             :         case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
     858           0 :                             aPaM = WordRight( aPaM );
     859           0 :                             bKeyModifySelection = true;
     860           0 :                             break;
     861             :         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
     862           0 :                             aPaM = CursorStartOfParagraph( aPaM );
     863           0 :                             if( aPaM == aOldPaM )
     864             :                             {
     865           0 :                                 aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
     866           0 :                                 aPaM = CursorStartOfParagraph( aPaM );
     867             :                             }
     868           0 :                             bKeyModifySelection = true;
     869           0 :                             break;
     870             :         case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
     871           0 :                             aPaM = CursorEndOfParagraph( aPaM );
     872           0 :                             if( aPaM == aOldPaM )
     873             :                             {
     874           0 :                                 aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
     875           0 :                                 aPaM = CursorEndOfParagraph( aPaM );
     876             :                             }
     877           0 :                             bKeyModifySelection = true;
     878           0 :                             break;
     879             :         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
     880           0 :                             aPaM = CursorStartOfDoc();
     881           0 :                             bKeyModifySelection = true;
     882           0 :                             break;
     883             :         case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
     884           0 :                             aPaM = CursorEndOfDoc();
     885           0 :                             bKeyModifySelection = true;
     886           0 :                             break;
     887             :     }
     888             : 
     889           0 :     if ( aOldPaM != aPaM )
     890             :     {
     891           0 :         CursorMoved( aOldPaM.GetNode() );
     892           0 :         if ( aStatus.NotifyCursorMovements() && ( aOldPaM.GetNode() != aPaM.GetNode() ) )
     893             :         {
     894           0 :             aStatus.GetStatusWord() = aStatus.GetStatusWord() | EE_STAT_CRSRLEFTPARA;
     895           0 :             aStatus.GetPrevParagraph() = aEditDoc.GetPos( aOldPaM.GetNode() );
     896             :         }
     897             :     }
     898             :     else
     899           0 :         aStatus.GetStatusWord() = aStatus.GetStatusWord() | EE_STAT_CRSRMOVEFAIL;
     900             : 
     901             :     // May cause, an CreateAnchor or deselection all
     902           0 :     aSelEngine.SetCurView( pEditView );
     903           0 :     aSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
     904           0 :     EditPaM aOldEnd( pEditView->pImpEditView->GetEditSelection().Max() );
     905           0 :     pEditView->pImpEditView->GetEditSelection().Max() = aPaM;
     906           0 :     if ( bKeyModifySelection )
     907             :     {
     908             :         // Then the selection is expanded ...
     909           0 :         EditSelection aTmpNewSel( aOldEnd, aPaM );
     910           0 :         pEditView->pImpEditView->DrawSelection( aTmpNewSel );
     911             :     }
     912             :     else
     913           0 :         pEditView->pImpEditView->GetEditSelection().Min() = aPaM;
     914             : 
     915           0 :     return pEditView->pImpEditView->GetEditSelection();
     916             : }
     917             : 
     918           0 : EditPaM ImpEditEngine::CursorVisualStartEnd( EditView* pEditView, const EditPaM& rPaM, sal_Bool bStart )
     919             : {
     920           0 :     EditPaM aPaM( rPaM );
     921             : 
     922           0 :     sal_Int32 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
     923           0 :     ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
     924             : 
     925           0 :     sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_False );
     926           0 :     const EditLine* pLine = pParaPortion->GetLines()[nLine];
     927           0 :     bool bEmptyLine = pLine->GetStart() == pLine->GetEnd();
     928             : 
     929           0 :     pEditView->pImpEditView->nExtraCursorFlags = 0;
     930             : 
     931           0 :     if ( !bEmptyLine )
     932             :     {
     933           0 :         String aLine(aPaM.GetNode()->GetString(), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart());
     934             : 
     935           0 :         const sal_Unicode* pLineString = aLine.GetBuffer();
     936             : 
     937           0 :         UErrorCode nError = U_ZERO_ERROR;
     938           0 :         UBiDi* pBidi = ubidi_openSized( aLine.Len(), 0, &nError );
     939             : 
     940           0 :         const UBiDiLevel  nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
     941           0 :         ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), aLine.Len(), nBidiLevel, NULL, &nError );   // UChar != sal_Unicode in MinGW
     942             : 
     943           0 :         sal_uInt16 nVisPos = bStart ? 0 : aLine.Len()-1;
     944           0 :         sal_uInt16 nLogPos = (sal_uInt16)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
     945             : 
     946           0 :         ubidi_close( pBidi );
     947             : 
     948           0 :         aPaM.GetIndex() = nLogPos + pLine->GetStart();
     949             : 
     950             :         sal_uInt16 nTmp;
     951           0 :         sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTmp, sal_True );
     952           0 :         const TextPortion* pTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
     953           0 :         sal_uInt16 nRTLLevel = pTextPortion->GetRightToLeft();
     954           0 :         sal_Bool bPortionRTL = (nRTLLevel%2) ? sal_True : sal_False;
     955             : 
     956           0 :         if ( bStart )
     957             :         {
     958           0 :             pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 0 : 1 );
     959             :             // Maybe we must be *behind* the character
     960           0 :             if ( bPortionRTL && pEditView->IsInsertMode() )
     961           0 :                 aPaM.GetIndex()++;
     962             :         }
     963             :         else
     964             :         {
     965           0 :             pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 1 : 0 );
     966           0 :             if ( !bPortionRTL && pEditView->IsInsertMode() )
     967           0 :                 aPaM.GetIndex()++;
     968           0 :         }
     969             :     }
     970             : 
     971           0 :     return aPaM;
     972             : }
     973             : 
     974           0 : EditPaM ImpEditEngine::CursorVisualLeftRight( EditView* pEditView, const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode, sal_Bool bVisualToLeft )
     975             : {
     976           0 :     EditPaM aPaM( rPaM );
     977             : 
     978           0 :     sal_Int32 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
     979           0 :     ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
     980             : 
     981           0 :     sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_False );
     982           0 :     const EditLine* pLine = pParaPortion->GetLines()[nLine];
     983           0 :     bool bEmptyLine = pLine->GetStart() == pLine->GetEnd();
     984             : 
     985           0 :     pEditView->pImpEditView->nExtraCursorFlags = 0;
     986             : 
     987           0 :     sal_Bool bParaRTL = IsRightToLeft( nPara );
     988             : 
     989           0 :     sal_Bool bDone = sal_False;
     990             : 
     991           0 :     if ( bEmptyLine )
     992             :     {
     993           0 :         if ( bVisualToLeft )
     994             :         {
     995           0 :             aPaM = CursorUp( aPaM, pEditView );
     996           0 :             if ( aPaM != rPaM )
     997           0 :                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_False );
     998             :         }
     999             :         else
    1000             :         {
    1001           0 :             aPaM = CursorDown( aPaM, pEditView );
    1002           0 :             if ( aPaM != rPaM )
    1003           0 :                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_True );
    1004             :         }
    1005             : 
    1006           0 :         bDone = sal_True;
    1007             :     }
    1008             : 
    1009           0 :     sal_Bool bLogicalBackward = bParaRTL ? !bVisualToLeft : bVisualToLeft;
    1010             : 
    1011           0 :     if ( !bDone && pEditView->IsInsertMode() )
    1012             :     {
    1013             :         // Check if we are within a portion and don't have overwrite mode, then it's easy...
    1014             :         sal_uInt16 nPortionStart;
    1015           0 :         sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, sal_False );
    1016           0 :         const TextPortion* pTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
    1017             : 
    1018           0 :         sal_Bool bPortionBoundary = ( aPaM.GetIndex() == nPortionStart ) || ( aPaM.GetIndex() == (nPortionStart+pTextPortion->GetLen()) );
    1019           0 :         sal_uInt16 nRTLLevel = pTextPortion->GetRightToLeft();
    1020             : 
    1021             :         // Portion boundary doesn't matter if both have same RTL level
    1022           0 :         sal_uInt16 nRTLLevelNextPortion = 0xFFFF;
    1023           0 :         if ( bPortionBoundary && aPaM.GetIndex() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
    1024             :         {
    1025             :             sal_uInt16 nTmp;
    1026           0 :             sal_uInt16 nNextTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex()+1, nTmp, bLogicalBackward ? sal_False : sal_True );
    1027           0 :             const TextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[nNextTextPortion];
    1028           0 :             nRTLLevelNextPortion = pNextTextPortion->GetRightToLeft();
    1029             :         }
    1030             : 
    1031           0 :         if ( !bPortionBoundary || ( nRTLLevel == nRTLLevelNextPortion ) )
    1032             :         {
    1033           0 :             if ( ( bVisualToLeft && !(nRTLLevel%2) ) || ( !bVisualToLeft && (nRTLLevel%2) ) )
    1034             :             {
    1035           0 :                 aPaM = CursorLeft( aPaM, nCharacterIteratorMode );
    1036           0 :                 pEditView->pImpEditView->SetCursorBidiLevel( 1 );
    1037             :             }
    1038             :             else
    1039             :             {
    1040           0 :                 aPaM = CursorRight( aPaM, nCharacterIteratorMode );
    1041           0 :                 pEditView->pImpEditView->SetCursorBidiLevel( 0 );
    1042             :             }
    1043           0 :             bDone = sal_True;
    1044             :         }
    1045             :     }
    1046             : 
    1047           0 :     if ( !bDone )
    1048             :     {
    1049           0 :         sal_Bool bGotoStartOfNextLine = sal_False;
    1050           0 :         sal_Bool bGotoEndOfPrevLine = sal_False;
    1051             : 
    1052           0 :         String aLine(aPaM.GetNode()->GetString(), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart());
    1053           0 :         sal_uInt16 nPosInLine = aPaM.GetIndex() - pLine->GetStart();
    1054             : 
    1055           0 :         const sal_Unicode* pLineString = aLine.GetBuffer();
    1056             : 
    1057           0 :         UErrorCode nError = U_ZERO_ERROR;
    1058           0 :         UBiDi* pBidi = ubidi_openSized( aLine.Len(), 0, &nError );
    1059             : 
    1060           0 :         const UBiDiLevel  nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
    1061           0 :         ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), aLine.Len(), nBidiLevel, NULL, &nError );   // UChar != sal_Unicode in MinGW
    1062             : 
    1063           0 :         if ( !pEditView->IsInsertMode() )
    1064             :         {
    1065           0 :             sal_Bool bEndOfLine = nPosInLine == aLine.Len();
    1066           0 :             sal_uInt16 nVisPos = (sal_uInt16)ubidi_getVisualIndex( pBidi, !bEndOfLine ? nPosInLine : nPosInLine-1, &nError );
    1067           0 :             if ( bVisualToLeft )
    1068             :             {
    1069           0 :                 bGotoEndOfPrevLine = nVisPos == 0;
    1070           0 :                 if ( !bEndOfLine )
    1071           0 :                     nVisPos--;
    1072             :             }
    1073             :             else
    1074             :             {
    1075           0 :                 bGotoStartOfNextLine = nVisPos == (aLine.Len() - 1);
    1076           0 :                 if ( !bEndOfLine )
    1077           0 :                     nVisPos++;
    1078             :             }
    1079             : 
    1080           0 :             if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
    1081             :             {
    1082           0 :                 sal_uInt16 nLogPos = (sal_uInt16)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
    1083           0 :                 aPaM.GetIndex() = pLine->GetStart() + nLogPos;
    1084           0 :                 pEditView->pImpEditView->SetCursorBidiLevel( 0 );
    1085             :             }
    1086             :         }
    1087             :         else
    1088             :         {
    1089           0 :             sal_Bool bWasBehind = sal_False;
    1090           0 :             sal_Bool bBeforePortion = !nPosInLine || pEditView->pImpEditView->GetCursorBidiLevel() == 1;
    1091           0 :             if ( nPosInLine && ( !bBeforePortion ) ) // before the next portion
    1092           0 :                 bWasBehind = sal_True;  // step one back, otherwise visual will be unusable when rtl portion follows.
    1093             : 
    1094             :             sal_uInt16 nPortionStart;
    1095           0 :             sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, bBeforePortion );
    1096           0 :             const TextPortion* pTextPortion = pParaPortion->GetTextPortions()[nTextPortion];
    1097           0 :             sal_Bool bRTLPortion = (pTextPortion->GetRightToLeft() % 2) != 0;
    1098             : 
    1099             :             // -1: We are 'behind' the character
    1100           0 :             long nVisPos = (long)ubidi_getVisualIndex( pBidi, bWasBehind ? nPosInLine-1 : nPosInLine, &nError );
    1101           0 :             if ( bVisualToLeft )
    1102             :             {
    1103           0 :                 if ( !bWasBehind || bRTLPortion )
    1104           0 :                     nVisPos--;
    1105             :             }
    1106             :             else
    1107             :             {
    1108           0 :                 if ( bWasBehind || bRTLPortion || bBeforePortion )
    1109           0 :                     nVisPos++;
    1110             :             }
    1111             : 
    1112           0 :             bGotoEndOfPrevLine = nVisPos < 0;
    1113           0 :             bGotoStartOfNextLine = nVisPos >= aLine.Len();
    1114             : 
    1115           0 :             if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
    1116             :             {
    1117           0 :                 sal_uInt16 nLogPos = (sal_uInt16)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
    1118             : 
    1119           0 :                 aPaM.GetIndex() = pLine->GetStart() + nLogPos;
    1120             : 
    1121             :                 // RTL portion, stay visually on the left side.
    1122             :                 sal_uInt16 _nPortionStart;
    1123             :                 // sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, !bRTLPortion );
    1124           0 :                 sal_uInt16 _nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), _nPortionStart, sal_True );
    1125           0 :                 const TextPortion* _pTextPortion = pParaPortion->GetTextPortions()[_nTextPortion];
    1126           0 :                 if ( bVisualToLeft && !bRTLPortion && ( _pTextPortion->GetRightToLeft() % 2 ) )
    1127           0 :                     aPaM.GetIndex()++;
    1128           0 :                 else if ( !bVisualToLeft && bRTLPortion && ( bWasBehind || !(_pTextPortion->GetRightToLeft() % 2 )) )
    1129           0 :                     aPaM.GetIndex()++;
    1130             : 
    1131           0 :                 pEditView->pImpEditView->SetCursorBidiLevel( _nPortionStart );
    1132             :             }
    1133             :         }
    1134             : 
    1135           0 :         ubidi_close( pBidi );
    1136             : 
    1137           0 :         if ( bGotoEndOfPrevLine )
    1138             :         {
    1139           0 :             aPaM = CursorUp( aPaM, pEditView );
    1140           0 :             if ( aPaM != rPaM )
    1141           0 :                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_False );
    1142             :         }
    1143           0 :         else if ( bGotoStartOfNextLine )
    1144             :         {
    1145           0 :             aPaM = CursorDown( aPaM, pEditView );
    1146           0 :             if ( aPaM != rPaM )
    1147           0 :                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_True );
    1148           0 :         }
    1149             :     }
    1150           0 :     return aPaM;
    1151             : }
    1152             : 
    1153             : 
    1154           0 : EditPaM ImpEditEngine::CursorLeft( const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
    1155             : {
    1156           0 :     EditPaM aCurPaM( rPaM );
    1157           0 :     EditPaM aNewPaM( aCurPaM );
    1158             : 
    1159           0 :     if ( aCurPaM.GetIndex() )
    1160             :     {
    1161           0 :         sal_Int32 nCount = 1;
    1162           0 :         uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1163             :          aNewPaM.SetIndex(
    1164           0 :              (sal_uInt16)_xBI->previousCharacters(
    1165           0 :                  aNewPaM.GetNode()->GetString(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nCharacterIteratorMode, nCount, nCount));
    1166             :     }
    1167             :     else
    1168             :     {
    1169           0 :         ContentNode* pNode = aCurPaM.GetNode();
    1170           0 :         pNode = GetPrevVisNode( pNode );
    1171           0 :         if ( pNode )
    1172             :         {
    1173           0 :             aNewPaM.SetNode( pNode );
    1174           0 :             aNewPaM.SetIndex( pNode->Len() );
    1175             :         }
    1176             :     }
    1177             : 
    1178           0 :     return aNewPaM;
    1179             : }
    1180             : 
    1181           0 : EditPaM ImpEditEngine::CursorRight( const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
    1182             : {
    1183           0 :     EditPaM aCurPaM( rPaM );
    1184           0 :     EditPaM aNewPaM( aCurPaM );
    1185             : 
    1186           0 :     if ( aCurPaM.GetIndex() < aCurPaM.GetNode()->Len() )
    1187             :     {
    1188           0 :         uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1189           0 :         sal_Int32 nCount = 1;
    1190             :         aNewPaM.SetIndex(
    1191           0 :             (sal_uInt16)_xBI->nextCharacters(
    1192           0 :                 aNewPaM.GetNode()->GetString(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nCharacterIteratorMode, nCount, nCount));
    1193             :     }
    1194             :     else
    1195             :     {
    1196           0 :         ContentNode* pNode = aCurPaM.GetNode();
    1197           0 :         pNode = GetNextVisNode( pNode );
    1198           0 :         if ( pNode )
    1199             :         {
    1200           0 :             aNewPaM.SetNode( pNode );
    1201           0 :             aNewPaM.SetIndex( 0 );
    1202             :         }
    1203             :     }
    1204             : 
    1205           0 :     return aNewPaM;
    1206             : }
    1207             : 
    1208           0 : EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView* pView )
    1209             : {
    1210             :     OSL_ENSURE( pView, "No View - No Cursor Movement!" );
    1211             : 
    1212           0 :     const ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() );
    1213             :     OSL_ENSURE( pPPortion, "No matching portion found: CursorUp ");
    1214           0 :     sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() );
    1215           0 :     const EditLine* pLine = pPPortion->GetLines()[nLine];
    1216             : 
    1217             :     long nX;
    1218           0 :     if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW )
    1219             :     {
    1220           0 :         nX = GetXPos( pPPortion, pLine, rPaM.GetIndex() );
    1221           0 :         pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef;
    1222             :     }
    1223             :     else
    1224           0 :         nX = pView->pImpEditView->nTravelXPos;
    1225             : 
    1226           0 :     EditPaM aNewPaM( rPaM );
    1227           0 :     if ( nLine )    // same paragraph
    1228             :     {
    1229           0 :         const EditLine* pPrevLine = pPPortion->GetLines()[nLine-1];
    1230           0 :         aNewPaM.SetIndex( GetChar( pPPortion, pPrevLine, nX ) );
    1231             :         // If a previous automatically wrapped line, and one has to be exactly
    1232             :         // at the end of this line, the cursor lands on the current line at the
    1233             :         // beginning. See Problem: Last character of an automatically wrapped
    1234             :         // Row = cursor
    1235           0 :         if ( aNewPaM.GetIndex() && ( aNewPaM.GetIndex() == pLine->GetStart() ) )
    1236           0 :             aNewPaM = CursorLeft( aNewPaM );
    1237             :     }
    1238             :     else    // previous paragraph
    1239             :     {
    1240           0 :         const ParaPortion* pPrevPortion = GetPrevVisPortion( pPPortion );
    1241           0 :         if ( pPrevPortion )
    1242             :         {
    1243           0 :             pLine = pPrevPortion->GetLines()[pPrevPortion->GetLines().Count()-1];
    1244             :             OSL_ENSURE( pLine, "Line in front not found: CursorUp" );
    1245           0 :             aNewPaM.SetNode( pPrevPortion->GetNode() );
    1246           0 :             aNewPaM.SetIndex( GetChar( pPrevPortion, pLine, nX+nOnePixelInRef ) );
    1247             :         }
    1248             :     }
    1249             : 
    1250           0 :     return aNewPaM;
    1251             : }
    1252             : 
    1253           0 : EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView* pView )
    1254             : {
    1255             :     OSL_ENSURE( pView, "No View - No Cursor Movement!" );
    1256             : 
    1257           0 :     const ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() );
    1258             :     OSL_ENSURE( pPPortion, "No matching portion found: CursorDown" );
    1259           0 :     sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() );
    1260             : 
    1261             :     long nX;
    1262           0 :     if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW )
    1263             :     {
    1264           0 :         const EditLine* pLine = pPPortion->GetLines()[nLine];
    1265           0 :         nX = GetXPos( pPPortion, pLine, rPaM.GetIndex() );
    1266           0 :         pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef;
    1267             :     }
    1268             :     else
    1269           0 :         nX = pView->pImpEditView->nTravelXPos;
    1270             : 
    1271           0 :     EditPaM aNewPaM( rPaM );
    1272           0 :     if ( nLine < pPPortion->GetLines().Count()-1 )
    1273             :     {
    1274           0 :         const EditLine* pNextLine = pPPortion->GetLines()[nLine+1];
    1275           0 :         aNewPaM.SetIndex( GetChar( pPPortion, pNextLine, nX ) );
    1276             :         // Special treatment, see CursorUp ...
    1277           0 :         if ( ( aNewPaM.GetIndex() == pNextLine->GetEnd() ) && ( aNewPaM.GetIndex() > pNextLine->GetStart() ) && ( aNewPaM.GetIndex() < pPPortion->GetNode()->Len() ) )
    1278           0 :             aNewPaM = CursorLeft( aNewPaM );
    1279             :     }
    1280             :     else    // next paragraph
    1281             :     {
    1282           0 :         const ParaPortion* pNextPortion = GetNextVisPortion( pPPortion );
    1283           0 :         if ( pNextPortion )
    1284             :         {
    1285           0 :             const EditLine* pLine = pNextPortion->GetLines()[0];
    1286             :             OSL_ENSURE( pLine, "Line in front not found: CursorUp" );
    1287           0 :             aNewPaM.SetNode( pNextPortion->GetNode() );
    1288             :             // Never at the very end when several lines, because then a line
    1289             :             // below the cursor appears.
    1290           0 :             aNewPaM.SetIndex( GetChar( pNextPortion, pLine, nX+nOnePixelInRef ) );
    1291           0 :             if ( ( aNewPaM.GetIndex() == pLine->GetEnd() ) && ( aNewPaM.GetIndex() > pLine->GetStart() ) && ( pNextPortion->GetLines().Count() > 1 ) )
    1292           0 :                 aNewPaM = CursorLeft( aNewPaM );
    1293             :         }
    1294             :     }
    1295             : 
    1296           0 :     return aNewPaM;
    1297             : }
    1298             : 
    1299           0 : EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM )
    1300             : {
    1301           0 :     const ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() );
    1302             :     OSL_ENSURE( pCurPortion, "No Portion for the PaM ?" );
    1303           0 :     sal_uInt16 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() );
    1304           0 :     const EditLine* pLine = pCurPortion->GetLines()[nLine];
    1305             :     OSL_ENSURE( pLine, "Current line not found ?!" );
    1306             : 
    1307           0 :     EditPaM aNewPaM( rPaM );
    1308           0 :     aNewPaM.SetIndex( pLine->GetStart() );
    1309           0 :     return aNewPaM;
    1310             : }
    1311             : 
    1312           0 : EditPaM ImpEditEngine::CursorEndOfLine( const EditPaM& rPaM )
    1313             : {
    1314           0 :     const ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() );
    1315             :     OSL_ENSURE( pCurPortion, "No Portion for the PaM ?" );
    1316           0 :     sal_uInt16 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() );
    1317           0 :     const EditLine* pLine = pCurPortion->GetLines()[nLine];
    1318             :     OSL_ENSURE( pLine, "Current line not found ?!" );
    1319             : 
    1320           0 :     EditPaM aNewPaM( rPaM );
    1321           0 :     aNewPaM.SetIndex( pLine->GetEnd() );
    1322           0 :     if ( pLine->GetEnd() > pLine->GetStart() )
    1323             :     {
    1324           0 :         if ( aNewPaM.GetNode()->IsFeature( aNewPaM.GetIndex() - 1 ) )
    1325             :         {
    1326             :             // When a soft break, be in front of it!
    1327           0 :             const EditCharAttrib* pNextFeature = aNewPaM.GetNode()->GetCharAttribs().FindFeature( aNewPaM.GetIndex()-1 );
    1328           0 :             if ( pNextFeature && ( pNextFeature->GetItem()->Which() == EE_FEATURE_LINEBR ) )
    1329           0 :                 aNewPaM = CursorLeft( aNewPaM );
    1330             :         }
    1331           0 :         else if ( ( aNewPaM.GetNode()->GetChar( aNewPaM.GetIndex() - 1 ) == ' ' ) && ( aNewPaM.GetIndex() != aNewPaM.GetNode()->Len() ) )
    1332             :         {
    1333             :             // For a Blank in an auto wrapped line, it makes sense, to stand
    1334             :             // in front of it, since the user wants to be after the word.
    1335             :             // If this is changed, special treatment for Pos1 to End!
    1336           0 :             aNewPaM = CursorLeft( aNewPaM );
    1337             :         }
    1338             :     }
    1339           0 :     return aNewPaM;
    1340             : }
    1341             : 
    1342           0 : EditPaM ImpEditEngine::CursorStartOfParagraph( const EditPaM& rPaM )
    1343             : {
    1344           0 :     EditPaM aPaM(rPaM);
    1345           0 :     aPaM.SetIndex(0);
    1346           0 :     return aPaM;
    1347             : }
    1348             : 
    1349           0 : EditPaM ImpEditEngine::CursorEndOfParagraph( const EditPaM& rPaM )
    1350             : {
    1351           0 :     EditPaM aPaM(rPaM);
    1352           0 :     aPaM.SetIndex(rPaM.GetNode()->Len());
    1353           0 :     return aPaM;
    1354             : }
    1355             : 
    1356           0 : EditPaM ImpEditEngine::CursorStartOfDoc()
    1357             : {
    1358           0 :     EditPaM aPaM( aEditDoc.GetObject( 0 ), 0 );
    1359           0 :     return aPaM;
    1360             : }
    1361             : 
    1362           0 : EditPaM ImpEditEngine::CursorEndOfDoc()
    1363             : {
    1364           0 :     ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 );
    1365           0 :     ParaPortion* pLastPortion = GetParaPortions().SafeGetObject( aEditDoc.Count()-1 );
    1366             :     OSL_ENSURE( pLastNode && pLastPortion, "CursorEndOfDoc: Node or Portion not found" );
    1367             : 
    1368           0 :     if ( !pLastPortion->IsVisible() )
    1369             :     {
    1370           0 :         pLastNode = GetPrevVisNode( pLastPortion->GetNode() );
    1371             :         OSL_ENSURE( pLastNode, "Kein sichtbarer Absatz?" );
    1372           0 :         if ( !pLastNode )
    1373           0 :             pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 );
    1374             :     }
    1375             : 
    1376           0 :     EditPaM aPaM( pLastNode, pLastNode->Len() );
    1377           0 :     return aPaM;
    1378             : }
    1379             : 
    1380           0 : EditPaM ImpEditEngine::PageUp( const EditPaM& rPaM, EditView* pView )
    1381             : {
    1382           0 :     Rectangle aRect = PaMtoEditCursor( rPaM );
    1383           0 :     Point aTopLeft = aRect.TopLeft();
    1384           0 :     aTopLeft.Y() -= pView->GetVisArea().GetHeight() *9/10;
    1385           0 :     aTopLeft.X() += nOnePixelInRef;
    1386           0 :     if ( aTopLeft.Y() < 0 )
    1387             :     {
    1388           0 :         aTopLeft.Y() = 0;
    1389             :     }
    1390           0 :     return GetPaM( aTopLeft );
    1391             : }
    1392             : 
    1393           0 : EditPaM ImpEditEngine::PageDown( const EditPaM& rPaM, EditView* pView )
    1394             : {
    1395           0 :     Rectangle aRect = PaMtoEditCursor( rPaM );
    1396           0 :     Point aBottomRight = aRect.BottomRight();
    1397           0 :     aBottomRight.Y() += pView->GetVisArea().GetHeight() *9/10;
    1398           0 :     aBottomRight.X() += nOnePixelInRef;
    1399           0 :     long nHeight = GetTextHeight();
    1400           0 :     if ( aBottomRight.Y() > nHeight )
    1401             :     {
    1402           0 :         aBottomRight.Y() = nHeight-2;
    1403             :     }
    1404           0 :     return GetPaM( aBottomRight );
    1405             : }
    1406             : 
    1407           0 : EditPaM ImpEditEngine::WordLeft( const EditPaM& rPaM, sal_Int16 nWordType )
    1408             : {
    1409           0 :     sal_uInt16 nCurrentPos = rPaM.GetIndex();
    1410           0 :     EditPaM aNewPaM( rPaM );
    1411           0 :     if ( nCurrentPos == 0 )
    1412             :     {
    1413             :         // Previous paragraph...
    1414           0 :         sal_Int32 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
    1415           0 :         ContentNode* pPrevNode = aEditDoc.GetObject( --nCurPara );
    1416           0 :         if ( pPrevNode )
    1417             :         {
    1418           0 :             aNewPaM.SetNode( pPrevNode );
    1419           0 :             aNewPaM.SetIndex( pPrevNode->Len() );
    1420             :         }
    1421             :     }
    1422             :     else
    1423             :     {
    1424             :         // we need to increase the position by 1 when retrieving the locale
    1425             :         // since the attribute for the char left to the cursor position is returned
    1426           0 :         EditPaM aTmpPaM( aNewPaM );
    1427           0 :         xub_StrLen nMax = rPaM.GetNode()->Len();
    1428           0 :         if ( aTmpPaM.GetIndex() < nMax )
    1429           0 :             aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
    1430           0 :         lang::Locale aLocale( GetLocale( aTmpPaM ) );
    1431             : 
    1432           0 :         uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1433             :         i18n::Boundary aBoundary =
    1434           0 :             _xBI->getWordBoundary(aNewPaM.GetNode()->GetString(), nCurrentPos, aLocale, nWordType, true);
    1435           0 :         if ( aBoundary.startPos >= nCurrentPos )
    1436           0 :             aBoundary = _xBI->previousWord(
    1437           0 :                 aNewPaM.GetNode()->GetString(), nCurrentPos, aLocale, nWordType);
    1438           0 :         aNewPaM.SetIndex( ( aBoundary.startPos != (-1) ) ? (sal_uInt16)aBoundary.startPos : 0 );
    1439             :     }
    1440             : 
    1441           0 :     return aNewPaM;
    1442             : }
    1443             : 
    1444        5132 : EditPaM ImpEditEngine::WordRight( const EditPaM& rPaM, sal_Int16 nWordType )
    1445             : {
    1446        5132 :     xub_StrLen nMax = rPaM.GetNode()->Len();
    1447        5132 :     EditPaM aNewPaM( rPaM );
    1448        5132 :     if ( aNewPaM.GetIndex() < nMax )
    1449             :     {
    1450             :         // we need to increase the position by 1 when retrieving the locale
    1451             :         // since the attribute for the char left to the cursor position is returned
    1452        2467 :         EditPaM aTmpPaM( aNewPaM );
    1453        2467 :         aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
    1454        2467 :         lang::Locale aLocale( GetLocale( aTmpPaM ) );
    1455             : 
    1456        4934 :         uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1457        2467 :         i18n::Boundary aBoundary = _xBI->nextWord(
    1458        2467 :             aNewPaM.GetNode()->GetString(), aNewPaM.GetIndex(), aLocale, nWordType);
    1459        4934 :         aNewPaM.SetIndex( (sal_uInt16)aBoundary.startPos );
    1460             :     }
    1461             :     // not 'else', maybe the index reached nMax now...
    1462        5132 :     if ( aNewPaM.GetIndex() >= nMax )
    1463             :     {
    1464             :         // Next paragraph ...
    1465        2738 :         sal_Int32 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
    1466        2738 :         ContentNode* pNextNode = aEditDoc.GetObject( ++nCurPara );
    1467        2738 :         if ( pNextNode )
    1468             :         {
    1469          31 :             aNewPaM.SetNode( pNextNode );
    1470          31 :             aNewPaM.SetIndex( 0 );
    1471             :         }
    1472             :     }
    1473        5132 :     return aNewPaM;
    1474             : }
    1475             : 
    1476           0 : EditPaM ImpEditEngine::StartOfWord( const EditPaM& rPaM, sal_Int16 nWordType )
    1477             : {
    1478           0 :     EditPaM aNewPaM( rPaM );
    1479             : 
    1480             :     // we need to increase the position by 1 when retrieving the locale
    1481             :     // since the attribute for the char left to the cursor position is returned
    1482           0 :     EditPaM aTmpPaM( aNewPaM );
    1483           0 :     xub_StrLen nMax = rPaM.GetNode()->Len();
    1484           0 :     if ( aTmpPaM.GetIndex() < nMax )
    1485           0 :         aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
    1486           0 :     lang::Locale aLocale( GetLocale( aTmpPaM ) );
    1487             : 
    1488           0 :     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1489           0 :     i18n::Boundary aBoundary = _xBI->getWordBoundary(
    1490           0 :         rPaM.GetNode()->GetString(), rPaM.GetIndex(), aLocale, nWordType, true);
    1491             : 
    1492           0 :     aNewPaM.SetIndex( (sal_uInt16)aBoundary.startPos );
    1493           0 :     return aNewPaM;
    1494             : }
    1495             : 
    1496           0 : EditPaM ImpEditEngine::EndOfWord( const EditPaM& rPaM, sal_Int16 nWordType )
    1497             : {
    1498           0 :     EditPaM aNewPaM( rPaM );
    1499             : 
    1500             :     // we need to increase the position by 1 when retrieving the locale
    1501             :     // since the attribute for the char left to the cursor position is returned
    1502           0 :     EditPaM aTmpPaM( aNewPaM );
    1503           0 :     xub_StrLen nMax = rPaM.GetNode()->Len();
    1504           0 :     if ( aTmpPaM.GetIndex() < nMax )
    1505           0 :         aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
    1506           0 :     lang::Locale aLocale( GetLocale( aTmpPaM ) );
    1507             : 
    1508           0 :     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1509           0 :     i18n::Boundary aBoundary = _xBI->getWordBoundary(
    1510           0 :         rPaM.GetNode()->GetString(), rPaM.GetIndex(), aLocale, nWordType, true);
    1511             : 
    1512           0 :     aNewPaM.SetIndex( (sal_uInt16)aBoundary.endPos );
    1513           0 :     return aNewPaM;
    1514             : }
    1515             : 
    1516       11842 : EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, sal_Bool bAcceptStartOfWord )
    1517             : {
    1518       11842 :     EditSelection aNewSel( rCurSel );
    1519       11842 :     EditPaM aPaM( rCurSel.Max() );
    1520             : 
    1521             :     // we need to increase the position by 1 when retrieving the locale
    1522             :     // since the attribute for the char left to the cursor position is returned
    1523       11842 :     EditPaM aTmpPaM( aPaM );
    1524       11842 :     xub_StrLen nMax = aPaM.GetNode()->Len();
    1525       11842 :     if ( aTmpPaM.GetIndex() < nMax )
    1526        6503 :         aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
    1527       11842 :     lang::Locale aLocale( GetLocale( aTmpPaM ) );
    1528             : 
    1529       23684 :     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1530       11842 :     sal_Int16 nType = _xBI->getWordType(
    1531       11842 :         aPaM.GetNode()->GetString(), aPaM.GetIndex(), aLocale);
    1532             : 
    1533       11842 :     if ( nType == i18n::WordType::ANY_WORD )
    1534             :     {
    1535       11842 :         i18n::Boundary aBoundary = _xBI->getWordBoundary(
    1536       11842 :             aPaM.GetNode()->GetString(), aPaM.GetIndex(), aLocale, nWordType, true);
    1537             : 
    1538             :         // don't select when curser at end of word
    1539       24782 :         if ( ( aBoundary.endPos > aPaM.GetIndex() ) &&
    1540       11848 :              ( ( aBoundary.startPos < aPaM.GetIndex() ) || ( bAcceptStartOfWord && ( aBoundary.startPos == aPaM.GetIndex() ) ) ) )
    1541             :         {
    1542        6466 :             aNewSel.Min().SetIndex( (sal_uInt16)aBoundary.startPos );
    1543        6466 :             aNewSel.Max().SetIndex( (sal_uInt16)aBoundary.endPos );
    1544             :         }
    1545             :     }
    1546             : 
    1547       23684 :     return aNewSel;
    1548             : }
    1549             : 
    1550           0 : EditSelection ImpEditEngine::SelectSentence( const EditSelection& rCurSel )
    1551             :     const
    1552             : {
    1553           0 :     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1554           0 :     const EditPaM& rPaM = rCurSel.Min();
    1555           0 :     const ContentNode* pNode = rPaM.GetNode();
    1556             :     // #i50710# line breaks are marked with 0x01 - the break iterator prefers 0x0a for that
    1557           0 :     String sParagraph = pNode->GetString();
    1558           0 :     sParagraph.SearchAndReplaceAll(0x01,0x0a);
    1559             :     //return Null if search starts at the beginning of the string
    1560           0 :     sal_Int32 nStart = rPaM.GetIndex() ? _xBI->beginOfSentence( sParagraph, rPaM.GetIndex(), GetLocale( rPaM ) ) : 0;
    1561             : 
    1562           0 :     sal_Int32 nEnd = _xBI->endOfSentence(
    1563           0 :         pNode->GetString(), rPaM.GetIndex(), GetLocale(rPaM));
    1564             : 
    1565           0 :     EditSelection aNewSel( rCurSel );
    1566             :     OSL_ENSURE(pNode->Len() ? (nStart < pNode->Len()) : (nStart == 0), "sentence start index out of range");
    1567             :     OSL_ENSURE(nEnd <= pNode->Len(), "sentence end index out of range");
    1568           0 :     aNewSel.Min().SetIndex( (sal_uInt16)nStart );
    1569           0 :     aNewSel.Max().SetIndex( (sal_uInt16)nEnd );
    1570           0 :     return aNewSel;
    1571             : }
    1572             : 
    1573           0 : sal_Bool ImpEditEngine::IsInputSequenceCheckingRequired( sal_Unicode nChar, const EditSelection& rCurSel ) const
    1574             : {
    1575           0 :     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1576           0 :     if (!pCTLOptions)
    1577           0 :         pCTLOptions = new SvtCTLOptions;
    1578             : 
    1579             :     // get the index that really is first
    1580           0 :     sal_uInt16 nFirstPos = rCurSel.Min().GetIndex();
    1581           0 :     sal_uInt16 nMaxPos   = rCurSel.Max().GetIndex();
    1582           0 :     if (nMaxPos < nFirstPos)
    1583           0 :         nFirstPos = nMaxPos;
    1584             : 
    1585             :     sal_Bool bIsSequenceChecking =
    1586           0 :         pCTLOptions->IsCTLFontEnabled() &&
    1587           0 :         pCTLOptions->IsCTLSequenceChecking() &&
    1588           0 :         nFirstPos != 0 && /* first char needs not to be checked */
    1589           0 :         _xBI.is() && i18n::ScriptType::COMPLEX == _xBI->getScriptType( OUString( nChar ), 0 );
    1590             : 
    1591           0 :     return bIsSequenceChecking;
    1592             : }
    1593             : 
    1594         602 : static  bool lcl_HasStrongLTR ( const String& rTxt, xub_StrLen nStart, xub_StrLen nEnd )
    1595             :  {
    1596         602 :      for ( xub_StrLen nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
    1597             :      {
    1598         602 :          const UCharDirection nCharDir = u_charDirection ( rTxt.GetChar ( nCharIdx ));
    1599         602 :          if ( nCharDir == U_LEFT_TO_RIGHT ||
    1600           0 :               nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
    1601             :               nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
    1602         602 :              return true;
    1603             :      }
    1604           0 :      return false;
    1605             :  }
    1606             : 
    1607             : 
    1608             : 
    1609      190073 : void ImpEditEngine::InitScriptTypes( sal_Int32 nPara )
    1610             : {
    1611      190073 :     ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1612      190073 :     ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
    1613      190073 :     rTypes.clear();
    1614             : 
    1615      190073 :     ContentNode* pNode = pParaPortion->GetNode();
    1616      190073 :     if ( pNode->Len() )
    1617             :     {
    1618      173832 :         uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    1619             : 
    1620      347664 :         String aText = pNode->GetString();
    1621             : 
    1622             :         // To handle fields put the character from the field in the string,
    1623             :         // because endOfScript( ... ) will skip the CH_FEATURE, because this is WEAK
    1624      173832 :         const EditCharAttrib* pField = pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, 0 );
    1625      355849 :         while ( pField )
    1626             :         {
    1627        8185 :             OUString aFldText = static_cast<const EditCharAttribField*>(pField)->GetFieldValue();
    1628        8185 :             if ( !aFldText.isEmpty() )
    1629             :             {
    1630        2339 :                 aText.SetChar( pField->GetStart(), aFldText.getStr()[0] );
    1631        2339 :                 short nFldScriptType = _xBI->getScriptType( aFldText, 0 );
    1632             : 
    1633       12703 :                 for ( sal_uInt16 nCharInField = 1; nCharInField < aFldText.getLength(); nCharInField++ )
    1634             :                 {
    1635       10364 :                     short nTmpType = _xBI->getScriptType( aFldText, nCharInField );
    1636             : 
    1637             :                     // First char from field wins...
    1638       10364 :                     if ( nFldScriptType == i18n::ScriptType::WEAK )
    1639             :                     {
    1640           0 :                         nFldScriptType = nTmpType;
    1641           0 :                         aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
    1642             :                     }
    1643             : 
    1644             :                     // ...  but if the first one is LATIN, and there are CJK or CTL chars too,
    1645             :                     // we prefer that ScripType because we need an other font.
    1646       10364 :                     if ( ( nTmpType == i18n::ScriptType::ASIAN ) || ( nTmpType == i18n::ScriptType::COMPLEX ) )
    1647             :                     {
    1648           0 :                         aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
    1649           0 :                         break;
    1650             :                     }
    1651             :                 }
    1652             :             }
    1653             :             // #112831# Last Field might go from 0xffff to 0x0000
    1654        8185 :             pField = pField->GetEnd() ? pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, pField->GetEnd() ) : NULL;
    1655        8185 :         }
    1656             : 
    1657      347664 :         OUString aOUText( aText );
    1658      173832 :         sal_uInt16 nTextLen = (sal_uInt16)aOUText.getLength();
    1659             : 
    1660      173832 :         sal_Int32 nPos = 0;
    1661      173832 :         short nScriptType = _xBI->getScriptType( aOUText, nPos );
    1662      173832 :         rTypes.push_back( ScriptTypePosInfo( nScriptType, (sal_uInt16)nPos, nTextLen ) );
    1663      173832 :         nPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
    1664      349314 :         while ( ( nPos != (-1) ) && ( nPos < nTextLen ) )
    1665             :         {
    1666        1650 :             rTypes.back().nEndPos = (sal_uInt16)nPos;
    1667             : 
    1668        1650 :             nScriptType = _xBI->getScriptType( aOUText, nPos );
    1669        1650 :             long nEndPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
    1670             : 
    1671        1650 :             if ( ( nScriptType == i18n::ScriptType::WEAK ) || ( nScriptType == rTypes.back().nScriptType ) )
    1672             :             {
    1673             :                 // Expand last ScriptTypePosInfo, don't create weak or unecessary portions
    1674           0 :                 rTypes.back().nEndPos = (sal_uInt16)nEndPos;
    1675             :             }
    1676             :             else
    1677             :             {
    1678        1650 :                 if ( _xBI->getScriptType( aOUText, nPos - 1 ) == i18n::ScriptType::WEAK )
    1679             :                 {
    1680        1650 :                     switch ( u_charType(aOUText.iterateCodePoints(&nPos, 0) ) ) {
    1681             :                     case U_NON_SPACING_MARK:
    1682             :                     case U_ENCLOSING_MARK:
    1683             :                     case U_COMBINING_SPACING_MARK:
    1684           0 :                         --nPos;
    1685           0 :                         rTypes.back().nEndPos--;
    1686           0 :                         break;
    1687             :                     }
    1688             :                 }
    1689        1650 :                 rTypes.push_back( ScriptTypePosInfo( nScriptType, (sal_uInt16)nPos, nTextLen ) );
    1690             :             }
    1691             : 
    1692        1650 :             nPos = nEndPos;
    1693             :         }
    1694             : 
    1695      173832 :         if ( rTypes[0].nScriptType == i18n::ScriptType::WEAK )
    1696        3752 :             rTypes[0].nScriptType = ( rTypes.size() > 1 ) ? rTypes[1].nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
    1697             : 
    1698             :         // create writing direction information:
    1699      173832 :         if ( pParaPortion->aWritingDirectionInfos.empty() )
    1700      173832 :             InitWritingDirections( nPara );
    1701             : 
    1702             :         // i89825: Use CTL font for numbers embedded into an RTL run:
    1703      173832 :         WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
    1704      347664 :         for ( size_t n = 0; n < rDirInfos.size(); ++n )
    1705             :         {
    1706      173832 :             const xub_StrLen nStart = rDirInfos[n].nStartPos;
    1707      173832 :             const xub_StrLen nEnd   = rDirInfos[n].nEndPos;
    1708      173832 :             const sal_uInt8 nCurrDirType = rDirInfos[n].nType;
    1709             : 
    1710      173832 :             if ( nCurrDirType % 2 == UBIDI_RTL  || // text in RTL run
    1711         602 :                 ( nCurrDirType > UBIDI_LTR && !lcl_HasStrongLTR( aText, nStart, nEnd ) ) ) // non-strong text in embedded LTR run
    1712             :             {
    1713           0 :                 size_t nIdx = 0;
    1714             : 
    1715             :                 // Skip entries in ScriptArray which are not inside the RTL run:
    1716           0 :                 while ( nIdx < rTypes.size() && rTypes[nIdx].nStartPos < nStart )
    1717           0 :                     ++nIdx;
    1718             : 
    1719             :                 // Remove any entries *inside* the current run:
    1720           0 :                 while ( nIdx < rTypes.size() && rTypes[nIdx].nEndPos <= nEnd )
    1721           0 :                     rTypes.erase( rTypes.begin()+nIdx );
    1722             : 
    1723             :                 // special case:
    1724           0 :                 if(nIdx < rTypes.size() && rTypes[nIdx].nStartPos < nStart && rTypes[nIdx].nEndPos > nEnd)
    1725             :                 {
    1726           0 :                     rTypes.insert( rTypes.begin()+nIdx, ScriptTypePosInfo( rTypes[nIdx].nScriptType, (sal_uInt16)nEnd, rTypes[nIdx].nEndPos ) );
    1727           0 :                     rTypes[nIdx].nEndPos = nStart;
    1728             :                 }
    1729             : 
    1730           0 :                 if( nIdx )
    1731           0 :                     rTypes[nIdx - 1].nEndPos = nStart;
    1732             : 
    1733           0 :                 rTypes.insert( rTypes.begin()+nIdx, ScriptTypePosInfo( i18n::ScriptType::COMPLEX, (sal_uInt16)nStart, (sal_uInt16)nEnd) );
    1734           0 :                 ++nIdx;
    1735             : 
    1736           0 :                 if( nIdx < rTypes.size() )
    1737           0 :                     rTypes[nIdx].nStartPos = nEnd;
    1738             :             }
    1739      173832 :         }
    1740             :     }
    1741      190073 : }
    1742             : 
    1743      852288 : sal_uInt16 ImpEditEngine::GetScriptType( const EditPaM& rPaM, sal_uInt16* pEndPos ) const
    1744             : {
    1745      852288 :     sal_uInt16 nScriptType = 0;
    1746             : 
    1747      852288 :     if ( pEndPos )
    1748           0 :         *pEndPos = rPaM.GetNode()->Len();
    1749             : 
    1750      852288 :     if ( rPaM.GetNode()->Len() )
    1751             :     {
    1752      531054 :         sal_Int32 nPara = GetEditDoc().GetPos( rPaM.GetNode() );
    1753      531054 :         const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1754      531054 :         if ( pParaPortion->aScriptInfos.empty() )
    1755           5 :             ((ImpEditEngine*)this)->InitScriptTypes( nPara );
    1756             : 
    1757      531054 :         const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
    1758      531054 :         sal_uInt16 nPos = rPaM.GetIndex();
    1759      533333 :         for ( size_t n = 0; n < rTypes.size(); n++ )
    1760             :         {
    1761      533333 :             if ( ( rTypes[n].nStartPos <= nPos ) && ( rTypes[n].nEndPos >= nPos ) )
    1762             :                {
    1763      531054 :                 nScriptType = rTypes[n].nScriptType;
    1764      531054 :                 if( pEndPos )
    1765           0 :                     *pEndPos = rTypes[n].nEndPos;
    1766      531054 :                 break;
    1767             :             }
    1768             :         }
    1769             :     }
    1770      852288 :     return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
    1771             : }
    1772             : 
    1773       43766 : sal_uInt16 ImpEditEngine::GetScriptType( const EditSelection& rSel ) const
    1774             : {
    1775       43766 :     EditSelection aSel( rSel );
    1776       43766 :     aSel.Adjust( aEditDoc );
    1777             : 
    1778       43766 :     short nScriptType = 0;
    1779             : 
    1780       43766 :      sal_Int32 nStartPara = GetEditDoc().GetPos( aSel.Min().GetNode() );
    1781       43766 :      sal_Int32 nEndPara = GetEditDoc().GetPos( aSel.Max().GetNode() );
    1782             : 
    1783       91411 :     for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; nPara++ )
    1784             :     {
    1785       47645 :         const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1786       47645 :         if ( pParaPortion->aScriptInfos.empty() )
    1787       44444 :             ((ImpEditEngine*)this)->InitScriptTypes( nPara );
    1788             : 
    1789       47645 :         const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
    1790             : 
    1791             :         // find the first(!) script type position that holds the
    1792             :         // complete selection. Thus it will work for selections as
    1793             :         // well as with just moving the cursor from char to char.
    1794       47645 :         sal_uInt16 nS = ( nPara == nStartPara ) ? aSel.Min().GetIndex() : 0;
    1795       47645 :         sal_uInt16 nE = ( nPara == nEndPara ) ? aSel.Max().GetIndex() : pParaPortion->GetNode()->Len();
    1796       50885 :         for ( size_t n = 0; n < rTypes.size(); n++ )
    1797             :         {
    1798       40645 :             if (rTypes[n].nStartPos <= nS  &&  nE <= rTypes[n].nEndPos)
    1799             :                {
    1800       37405 :                 if ( rTypes[n].nScriptType != i18n::ScriptType::WEAK )
    1801             :                 {
    1802       37405 :                     nScriptType |= GetItemScriptType ( rTypes[n].nScriptType );
    1803             :                 }
    1804             :                 else
    1805             :                 {
    1806           0 :                     if ( !nScriptType && n )
    1807             :                     {
    1808             :                         // #93548# When starting with WEAK, use prev ScriptType...
    1809           0 :                         nScriptType = rTypes[n-1].nScriptType;
    1810             :                     }
    1811             :                 }
    1812       37405 :                 break;
    1813             :             }
    1814             :         }
    1815             :     }
    1816       43766 :     return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
    1817             : }
    1818             : 
    1819        3977 : sal_Bool ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const
    1820             : {
    1821        3977 :     bool bScriptChange = false;
    1822             : 
    1823        3977 :     if ( rPaM.GetNode()->Len() )
    1824             :     {
    1825        3977 :         sal_Int32 nPara = GetEditDoc().GetPos( rPaM.GetNode() );
    1826        3977 :         const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1827        3977 :         if ( pParaPortion->aScriptInfos.empty() )
    1828           0 :             ((ImpEditEngine*)this)->InitScriptTypes( nPara );
    1829             : 
    1830        3977 :         const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
    1831        3977 :         sal_uInt16 nPos = rPaM.GetIndex();
    1832        7935 :         for ( size_t n = 0; n < rTypes.size(); n++ )
    1833             :         {
    1834        4090 :             if ( rTypes[n].nStartPos == nPos )
    1835             :                {
    1836         132 :                 bScriptChange = true;
    1837         132 :                 break;
    1838             :             }
    1839             :         }
    1840             :     }
    1841        3977 :     return bScriptChange;
    1842             : }
    1843             : 
    1844      327427 : sal_Bool ImpEditEngine::HasScriptType( sal_Int32 nPara, sal_uInt16 nType ) const
    1845             : {
    1846      327427 :     bool bTypeFound = false;
    1847             : 
    1848      327427 :     const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1849      327427 :     if ( pParaPortion->aScriptInfos.empty() )
    1850      145624 :         ((ImpEditEngine*)this)->InitScriptTypes( nPara );
    1851             : 
    1852      327427 :     const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
    1853      975698 :     for ( size_t n = rTypes.size(); n && !bTypeFound; )
    1854             :     {
    1855      320844 :         if ( rTypes[--n].nScriptType == nType )
    1856           0 :                 bTypeFound = true;
    1857             :     }
    1858      327427 :     return bTypeFound;
    1859             : }
    1860             : 
    1861      173832 : void ImpEditEngine::InitWritingDirections( sal_Int32 nPara )
    1862             : {
    1863      173832 :     ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1864      173832 :     WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos;
    1865      173832 :     rInfos.clear();
    1866             : 
    1867      173832 :     sal_Bool bCTL = sal_False;
    1868      173832 :     ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
    1869      349314 :     for ( size_t n = 0; n < rTypes.size(); n++ )
    1870             :     {
    1871      175482 :         if ( rTypes[n].nScriptType == i18n::ScriptType::COMPLEX )
    1872             :            {
    1873           0 :             bCTL = sal_True;
    1874           0 :             break;
    1875             :         }
    1876             :     }
    1877             : 
    1878      173832 :     const UBiDiLevel nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
    1879      173832 :     if ( ( bCTL || ( nBidiLevel == 1 /*RTL*/ ) ) && pParaPortion->GetNode()->Len() )
    1880             :     {
    1881             : 
    1882         602 :         String aText = pParaPortion->GetNode()->GetString();
    1883             : 
    1884             :         //
    1885             :         // Bidi functions from icu 2.0
    1886             :         //
    1887         602 :         UErrorCode nError = U_ZERO_ERROR;
    1888         602 :         UBiDi* pBidi = ubidi_openSized( aText.Len(), 0, &nError );
    1889         602 :         nError = U_ZERO_ERROR;
    1890             : 
    1891         602 :         ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aText.GetBuffer()), aText.Len(), nBidiLevel, NULL, &nError ); // UChar != sal_Unicode in MinGW
    1892         602 :         nError = U_ZERO_ERROR;
    1893             : 
    1894         602 :         size_t nCount = ubidi_countRuns( pBidi, &nError );
    1895             : 
    1896             :         /* ubidi_countRuns can return -1 in case of error */
    1897         602 :         if(nCount > 0)
    1898             :         {
    1899         602 :             int32_t nStart = 0;
    1900             :             int32_t nEnd;
    1901             :             UBiDiLevel nCurrDir;
    1902             : 
    1903        1204 :             for ( size_t nIdx = 0; nIdx < nCount; ++nIdx )
    1904             :             {
    1905         602 :                 ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
    1906         602 :                 rInfos.push_back( WritingDirectionInfo( nCurrDir, (sal_uInt16)nStart, (sal_uInt16)nEnd ) );
    1907         602 :                 nStart = nEnd;
    1908             :             }
    1909             :         }
    1910             : 
    1911         602 :         ubidi_close( pBidi );
    1912             :     }
    1913             : 
    1914             :     // No infos mean no CTL and default dir is L2R...
    1915      173832 :     if ( rInfos.empty() )
    1916      173230 :         rInfos.push_back( WritingDirectionInfo( 0, 0, (sal_uInt16)pParaPortion->GetNode()->Len() ) );
    1917             : 
    1918      173832 : }
    1919             : 
    1920     1029229 : sal_Bool ImpEditEngine::IsRightToLeft( sal_Int32 nPara ) const
    1921             : {
    1922     1029229 :     sal_Bool bR2L = sal_False;
    1923     1029229 :     const SvxFrameDirectionItem* pFrameDirItem = NULL;
    1924             : 
    1925     1029229 :     if ( !IsVertical() )
    1926             :     {
    1927     1029229 :         bR2L = GetDefaultHorizontalTextDirection() == EE_HTEXTDIR_R2L;
    1928     1029229 :         pFrameDirItem = &(const SvxFrameDirectionItem&)GetParaAttrib( nPara, EE_PARA_WRITINGDIR );
    1929     1029229 :         if ( pFrameDirItem->GetValue() == FRMDIR_ENVIRONMENT )
    1930             :         {
    1931             :             // #103045# if DefaultHorizontalTextDirection is set, use that value, otherwise pool default.
    1932      275486 :             if ( GetDefaultHorizontalTextDirection() != EE_HTEXTDIR_DEFAULT )
    1933             :             {
    1934        5782 :                 pFrameDirItem = NULL; // bR2L already set to default horizontal text direction
    1935             :             }
    1936             :             else
    1937             :             {
    1938             :                 // Use pool default
    1939      269704 :                 pFrameDirItem = &(const SvxFrameDirectionItem&)((ImpEditEngine*)this)->GetEmptyItemSet().Get( EE_PARA_WRITINGDIR );
    1940             :             }
    1941             :         }
    1942             :     }
    1943             : 
    1944     1029229 :     if ( pFrameDirItem )
    1945     1023447 :         bR2L = pFrameDirItem->GetValue() == FRMDIR_HORI_RIGHT_TOP;
    1946             : 
    1947     1029229 :     return bR2L;
    1948             : }
    1949             : 
    1950         894 : sal_Bool ImpEditEngine::HasDifferentRTLLevels( const ContentNode* pNode )
    1951             : {
    1952         894 :     sal_Int32 nPara = GetEditDoc().GetPos( (ContentNode*)pNode );
    1953         894 :     ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1954             : 
    1955         894 :     sal_Bool bHasDifferentRTLLevels = sal_False;
    1956             : 
    1957         894 :     sal_uInt16 nRTLLevel = IsRightToLeft( nPara ) ? 1 : 0;
    1958        1804 :     for ( sal_uInt16 n = 0; n < pParaPortion->GetTextPortions().Count(); n++ )
    1959             :     {
    1960         910 :         const TextPortion* pTextPortion = pParaPortion->GetTextPortions()[n];
    1961         910 :         if ( pTextPortion->GetRightToLeft() != nRTLLevel )
    1962             :         {
    1963           0 :             bHasDifferentRTLLevels = sal_True;
    1964           0 :             break;
    1965             :         }
    1966             :     }
    1967         894 :     return bHasDifferentRTLLevels;
    1968             : }
    1969             : 
    1970             : 
    1971      200292 : sal_uInt8 ImpEditEngine::GetRightToLeft( sal_Int32 nPara, sal_uInt16 nPos, sal_uInt16* pStart, sal_uInt16* pEnd )
    1972             : {
    1973      200292 :     sal_uInt8 nRightToLeft = 0;
    1974             : 
    1975      200292 :     ContentNode* pNode = aEditDoc.GetObject( nPara );
    1976      200292 :     if ( pNode && pNode->Len() )
    1977             :     {
    1978      199133 :         ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
    1979      199133 :         if ( pParaPortion->aWritingDirectionInfos.empty() )
    1980           0 :             InitWritingDirections( nPara );
    1981             : 
    1982      199133 :         WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
    1983      199133 :         for ( size_t n = 0; n < rDirInfos.size(); n++ )
    1984             :         {
    1985      199133 :             if ( ( rDirInfos[n].nStartPos <= nPos ) && ( rDirInfos[n].nEndPos >= nPos ) )
    1986             :                {
    1987      199133 :                 nRightToLeft = rDirInfos[n].nType;
    1988      199133 :                 if ( pStart )
    1989           8 :                     *pStart = rDirInfos[n].nStartPos;
    1990      199133 :                 if ( pEnd )
    1991           8 :                     *pEnd = rDirInfos[n].nEndPos;
    1992      199133 :                 break;
    1993             :             }
    1994             :         }
    1995             :     }
    1996      200292 :     return nRightToLeft;
    1997             : }
    1998             : 
    1999      512844 : SvxAdjust ImpEditEngine::GetJustification( sal_Int32 nPara ) const
    2000             : {
    2001      512844 :     SvxAdjust eJustification = SVX_ADJUST_LEFT;
    2002             : 
    2003      512844 :     if ( !aStatus.IsOutliner() )
    2004             :     {
    2005      512844 :         eJustification = ((const SvxAdjustItem&) GetParaAttrib( nPara, EE_PARA_JUST )).GetAdjust();
    2006             : 
    2007      512844 :         if ( IsRightToLeft( nPara ) )
    2008             :         {
    2009        1235 :             if ( eJustification == SVX_ADJUST_LEFT )
    2010           0 :                 eJustification = SVX_ADJUST_RIGHT;
    2011        1235 :             else if ( eJustification == SVX_ADJUST_RIGHT )
    2012         735 :                 eJustification = SVX_ADJUST_LEFT;
    2013             :         }
    2014             :     }
    2015      512844 :     return eJustification;
    2016             : }
    2017             : 
    2018        1816 : SvxCellJustifyMethod ImpEditEngine::GetJustifyMethod( sal_Int32 nPara ) const
    2019             : {
    2020             :     const SvxJustifyMethodItem& rItem = static_cast<const SvxJustifyMethodItem&>(
    2021        1816 :         GetParaAttrib(nPara, EE_PARA_JUST_METHOD));
    2022        1816 :     return static_cast<SvxCellJustifyMethod>(rItem.GetEnumValue());
    2023             : }
    2024             : 
    2025        8744 : SvxCellVerJustify ImpEditEngine::GetVerJustification( sal_Int32 nPara ) const
    2026             : {
    2027             :     const SvxVerJustifyItem& rItem = static_cast<const SvxVerJustifyItem&>(
    2028        8744 :         GetParaAttrib(nPara, EE_PARA_VER_JUST));
    2029        8744 :     return static_cast<SvxCellVerJustify>(rItem.GetEnumValue());
    2030             : }
    2031             : 
    2032             : //  ----------------------------------------------------------------------
    2033             : //  Text changes
    2034             : //  ----------------------------------------------------------------------
    2035             : 
    2036        1268 : void ImpEditEngine::ImpRemoveChars( const EditPaM& rPaM, sal_uInt16 nChars, EditUndoRemoveChars* pCurUndo )
    2037             : {
    2038        1268 :     if ( IsUndoEnabled() && !IsInUndo() )
    2039             :     {
    2040         126 :         XubString aStr( rPaM.GetNode()->Copy( rPaM.GetIndex(), nChars ) );
    2041             : 
    2042             :         // Check whether attributes are deleted or changed:
    2043         126 :         sal_uInt16 nStart = rPaM.GetIndex();
    2044         126 :         sal_uInt16 nEnd = nStart + nChars;
    2045         126 :         const CharAttribList::AttribsType& rAttribs = rPaM.GetNode()->GetCharAttribs().GetAttribs();
    2046         137 :         for (size_t i = 0, n = rAttribs.size(); i < n; ++i)
    2047             :         {
    2048          18 :             const EditCharAttrib& rAttr = rAttribs[i];
    2049          18 :             if (rAttr.GetEnd() >= nStart && rAttr.GetStart() < nEnd)
    2050             :             {
    2051           7 :                 EditSelection aSel( rPaM );
    2052           7 :                 aSel.Max().GetIndex() = aSel.Max().GetIndex() + nChars;
    2053           7 :                 EditUndoSetAttribs* pAttrUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
    2054           7 :                 InsertUndo( pAttrUndo );
    2055           7 :                 break;  // for
    2056             :             }
    2057             :         }
    2058         126 :         if ( pCurUndo && ( CreateEditPaM( pCurUndo->GetEPaM() ) == rPaM ) )
    2059           0 :             pCurUndo->GetStr() += aStr;
    2060             :         else
    2061         126 :             InsertUndo(new EditUndoRemoveChars(pEditEngine, CreateEPaM(rPaM), aStr));
    2062             :     }
    2063             : 
    2064        1268 :     aEditDoc.RemoveChars( rPaM, nChars );
    2065        1268 :     TextModified();
    2066        1268 : }
    2067             : 
    2068           0 : EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 nNewPos )
    2069             : {
    2070           0 :     aOldPositions.Justify();
    2071           0 :     sal_Bool bValidAction = ( (long)nNewPos < aOldPositions.Min() ) || ( (long)nNewPos > aOldPositions.Max() );
    2072             :     OSL_ENSURE( bValidAction, "Move in itself?" );
    2073             :     OSL_ENSURE( aOldPositions.Max() <= (long)GetParaPortions().Count(), "totally over it: MoveParagraphs" );
    2074             : 
    2075           0 :     EditSelection aSelection;
    2076             : 
    2077           0 :     if ( !bValidAction )
    2078             :     {
    2079           0 :         aSelection = aEditDoc.GetStartPaM();
    2080           0 :         return aSelection;
    2081             :     }
    2082             : 
    2083           0 :     sal_Int32 nParaCount = GetParaPortions().Count();
    2084             : 
    2085           0 :     if ( nNewPos >= nParaCount )
    2086           0 :         nNewPos = nParaCount;
    2087             : 
    2088             :     // Height may change when moving first or last Paragraph
    2089           0 :     ParaPortion* pRecalc1 = NULL;
    2090           0 :     ParaPortion* pRecalc2 = NULL;
    2091           0 :     ParaPortion* pRecalc3 = NULL;
    2092           0 :     ParaPortion* pRecalc4 = NULL;
    2093             : 
    2094           0 :     if ( nNewPos == 0 ) // Move to Start
    2095             :     {
    2096           0 :         pRecalc1 = GetParaPortions()[0];
    2097           0 :         pRecalc2 = GetParaPortions()[aOldPositions.Min()];
    2098             : 
    2099             :     }
    2100           0 :     else if ( nNewPos == nParaCount )
    2101             :     {
    2102           0 :         pRecalc1 = GetParaPortions()[nParaCount-1];
    2103           0 :         pRecalc2 = GetParaPortions()[aOldPositions.Max()];
    2104             :     }
    2105             : 
    2106           0 :     if ( aOldPositions.Min() == 0 ) // Move from Start
    2107             :     {
    2108           0 :         pRecalc3 = GetParaPortions()[0];
    2109           0 :         pRecalc4 = GetParaPortions()[aOldPositions.Max()+1];
    2110             :     }
    2111           0 :     else if ( (sal_uInt16)aOldPositions.Max() == (nParaCount-1) )
    2112             :     {
    2113           0 :         pRecalc3 = GetParaPortions()[aOldPositions.Max()];
    2114           0 :         pRecalc4 = GetParaPortions()[aOldPositions.Min()-1];
    2115             :     }
    2116             : 
    2117           0 :     MoveParagraphsInfo aMoveParagraphsInfo( aOldPositions.Min(), aOldPositions.Max(), nNewPos );
    2118           0 :     aBeginMovingParagraphsHdl.Call( &aMoveParagraphsInfo );
    2119             : 
    2120           0 :     if ( IsUndoEnabled() && !IsInUndo())
    2121           0 :         InsertUndo(new EditUndoMoveParagraphs(pEditEngine, aOldPositions, nNewPos));
    2122             : 
    2123             :     // do not lose sight of the Position !
    2124           0 :     ParaPortion* pDestPortion = GetParaPortions().SafeGetObject( nNewPos );
    2125             : 
    2126           0 :     ParaPortionList aTmpPortionList;
    2127           0 :     for (sal_Int32 i = aOldPositions.Min(); i <= aOldPositions.Max(); i++  )
    2128             :     {
    2129             :         // always aOldPositions.Min(), since Remove().
    2130           0 :         ParaPortion* pTmpPortion = GetParaPortions().Release(aOldPositions.Min());
    2131           0 :         aEditDoc.Release( aOldPositions.Min() );
    2132           0 :         aTmpPortionList.Append(pTmpPortion);
    2133             :     }
    2134             : 
    2135           0 :     sal_Int32 nRealNewPos = pDestPortion ? GetParaPortions().GetPos( pDestPortion ) : GetParaPortions().Count();
    2136             :     OSL_ENSURE( nRealNewPos != EE_PARA_NOT_FOUND, "ImpMoveParagraphs: Invalid Position!" );
    2137             : 
    2138           0 :     for (sal_Int32 i = 0; i < aTmpPortionList.Count(); ++i)
    2139             :     {
    2140           0 :         ParaPortion* pTmpPortion = aTmpPortionList[i];
    2141           0 :         if ( i == 0 )
    2142           0 :             aSelection.Min().SetNode( pTmpPortion->GetNode() );
    2143             : 
    2144           0 :         aSelection.Max().SetNode( pTmpPortion->GetNode() );
    2145           0 :         aSelection.Max().SetIndex( pTmpPortion->GetNode()->Len() );
    2146             : 
    2147           0 :         ContentNode* pN = pTmpPortion->GetNode();
    2148           0 :         aEditDoc.Insert(nRealNewPos+i, pN);
    2149             : 
    2150           0 :         GetParaPortions().Insert(nRealNewPos+i, pTmpPortion);
    2151             :     }
    2152             : 
    2153           0 :     aEndMovingParagraphsHdl.Call( &aMoveParagraphsInfo );
    2154             : 
    2155           0 :     if ( GetNotifyHdl().IsSet() )
    2156             :     {
    2157           0 :         EENotify aNotify( EE_NOTIFY_PARAGRAPHSMOVED );
    2158           0 :         aNotify.pEditEngine = GetEditEnginePtr();
    2159           0 :         aNotify.nParagraph = nNewPos;
    2160           0 :         aNotify.nParam1 = aOldPositions.Min();
    2161           0 :         aNotify.nParam2 = aOldPositions.Max();
    2162           0 :         CallNotify( aNotify );
    2163             :     }
    2164             : 
    2165           0 :     aEditDoc.SetModified( sal_True );
    2166             : 
    2167           0 :     if ( pRecalc1 )
    2168           0 :         CalcHeight( pRecalc1 );
    2169           0 :     if ( pRecalc2 )
    2170           0 :         CalcHeight( pRecalc2 );
    2171           0 :     if ( pRecalc3 )
    2172           0 :         CalcHeight( pRecalc3 );
    2173           0 :     if ( pRecalc4 )
    2174           0 :         CalcHeight( pRecalc4 );
    2175             : 
    2176           0 :     while( aTmpPortionList.Count() > 0 )
    2177           0 :         aTmpPortionList.Release( aTmpPortionList.Count() - 1 );
    2178             : 
    2179             : #if OSL_DEBUG_LEVEL > 2
    2180             :     GetParaPortions().DbgCheck(aEditDoc);
    2181             : #endif
    2182           0 :     return aSelection;
    2183             : }
    2184             : 
    2185             : 
    2186         543 : EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, sal_Bool bBackward )
    2187             : {
    2188             :     OSL_ENSURE( pLeft != pRight, "Join together the same paragraph ?" );
    2189             :     OSL_ENSURE( aEditDoc.GetPos( pLeft ) != EE_PARA_NOT_FOUND, "Inserted node not found (1)" );
    2190             :     OSL_ENSURE( aEditDoc.GetPos( pRight ) != EE_PARA_NOT_FOUND, "Inserted node not found (2)" );
    2191             : 
    2192             :     // #i120020# it is possible that left and right are *not* in the desired order (left/right)
    2193             :     // so correct it. This correction is needed, else an invalid SfxLinkUndoAction will be
    2194             :     // created from ConnectParagraphs below. Assert this situation, it should be corrected by the
    2195             :     // caller.
    2196         543 :     if(aEditDoc.GetPos( pLeft ) > aEditDoc.GetPos( pRight ))
    2197             :     {
    2198             :         OSL_ENSURE(false, "ImpConnectParagraphs wit wrong order of pLeft/pRight nodes (!)");
    2199           0 :         std::swap(pLeft, pRight);
    2200             :     }
    2201             : 
    2202         543 :     sal_Int32 nParagraphTobeDeleted = aEditDoc.GetPos( pRight );
    2203         543 :     DeletedNodeInfo* pInf = new DeletedNodeInfo( (sal_uIntPtr)pRight, nParagraphTobeDeleted );
    2204         543 :     aDeletedNodes.push_back(pInf);
    2205             : 
    2206         543 :     GetEditEnginePtr()->ParagraphConnected( aEditDoc.GetPos( pLeft ), aEditDoc.GetPos( pRight ) );
    2207             : 
    2208         543 :     if ( IsUndoEnabled() && !IsInUndo() )
    2209             :     {
    2210             :         InsertUndo( new EditUndoConnectParas(pEditEngine,
    2211          42 :             aEditDoc.GetPos( pLeft ), pLeft->Len(),
    2212          42 :             pLeft->GetContentAttribs().GetItems(), pRight->GetContentAttribs().GetItems(),
    2213          84 :             pLeft->GetStyleSheet(), pRight->GetStyleSheet(), bBackward ) );
    2214             :     }
    2215             : 
    2216         543 :     if ( bBackward )
    2217             :     {
    2218           0 :         pLeft->SetStyleSheet( pRight->GetStyleSheet(), sal_True );
    2219           0 :         pLeft->GetContentAttribs().GetItems().Set( pRight->GetContentAttribs().GetItems() );
    2220           0 :         pLeft->GetCharAttribs().GetDefFont() = pRight->GetCharAttribs().GetDefFont();
    2221             :     }
    2222             : 
    2223         543 :     ParaAttribsChanged( pLeft );
    2224             : 
    2225             :     // First search for Portions since pRight is gone after ConnectParagraphs.
    2226         543 :     ParaPortion* pLeftPortion = FindParaPortion( pLeft );
    2227             :     OSL_ENSURE( pLeftPortion, "Blind Portion in ImpConnectParagraphs(1)" );
    2228             : 
    2229         543 :     if ( GetStatus().DoOnlineSpelling() )
    2230             :     {
    2231           0 :         xub_StrLen nEnd = pLeft->Len();
    2232           0 :         xub_StrLen nInv = nEnd ? nEnd-1 : nEnd;
    2233           0 :         pLeft->GetWrongList()->ClearWrongs( nInv, 0xFFFF, pLeft );  // Possibly remove one
    2234           0 :         pLeft->GetWrongList()->MarkInvalid( nInv, nEnd+1 );
    2235             :         // Take over misspelled words
    2236           0 :         WrongList* pRWrongs = pRight->GetWrongList();
    2237           0 :         for (WrongList::iterator i = pRWrongs->begin(); i < pRWrongs->end(); ++i)
    2238             :         {
    2239           0 :             if (i->nStart != 0)   // Not a subsequent
    2240             :             {
    2241           0 :                 i->nStart = i->nStart + nEnd;
    2242           0 :                 i->nEnd = i->nEnd + nEnd;
    2243           0 :                 pLeft->GetWrongList()->push_back(*i);
    2244             :             }
    2245             :         }
    2246             :     }
    2247             : 
    2248         543 :     if ( IsCallParaInsertedOrDeleted() )
    2249         543 :         GetEditEnginePtr()->ParagraphDeleted( nParagraphTobeDeleted );
    2250             : 
    2251         543 :     EditPaM aPaM = aEditDoc.ConnectParagraphs( pLeft, pRight );
    2252         543 :     GetParaPortions().Remove( nParagraphTobeDeleted );
    2253             : 
    2254         543 :     pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->Len() );
    2255             : 
    2256             :     // the right node is deleted by EditDoc:ConnectParagraphs().
    2257         543 :     if ( GetTextRanger() )
    2258             :     {
    2259             :         // By joining together the two, the left is although reformatted,
    2260             :         // however if its height does not change then the formatting receives
    2261             :         // the change of the total text hight too late...
    2262           0 :         for ( sal_Int32 n = nParagraphTobeDeleted; n < GetParaPortions().Count(); n++ )
    2263             :         {
    2264           0 :             ParaPortion* pPP = GetParaPortions()[n];
    2265           0 :             pPP->MarkSelectionInvalid( 0, pPP->GetNode()->Len() );
    2266           0 :             pPP->GetLines().Reset();
    2267             :         }
    2268             :     }
    2269             : 
    2270         543 :     TextModified();
    2271             : 
    2272         543 :     return aPaM;
    2273             : }
    2274             : 
    2275           0 : EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, sal_uInt8 nMode, sal_uInt8 nDelMode )
    2276             : {
    2277             :     OSL_ENSURE( !EditSelection( rSel ).DbgIsBuggy( aEditDoc ), "Index out of range in DeleteLeftOrRight" );
    2278             : 
    2279           0 :     if ( rSel.HasRange() )  // only then Delete Selection
    2280           0 :         return ImpDeleteSelection( rSel );
    2281             : 
    2282           0 :     EditPaM aCurPos( rSel.Max() );
    2283           0 :     EditPaM aDelStart( aCurPos );
    2284           0 :     EditPaM aDelEnd( aCurPos );
    2285           0 :     if ( nMode == DEL_LEFT )
    2286             :     {
    2287           0 :         if ( nDelMode == DELMODE_SIMPLE )
    2288             :         {
    2289           0 :             aDelStart = CursorLeft( aCurPos, i18n::CharacterIteratorMode::SKIPCHARACTER );
    2290             :         }
    2291           0 :         else if ( nDelMode == DELMODE_RESTOFWORD )
    2292             :         {
    2293           0 :             aDelStart = StartOfWord( aCurPos );
    2294           0 :             if ( aDelStart.GetIndex() == aCurPos.GetIndex() )
    2295           0 :                 aDelStart = WordLeft( aCurPos );
    2296             :         }
    2297             :         else    // DELMODE_RESTOFCONTENT
    2298             :         {
    2299           0 :             aDelStart.SetIndex( 0 );
    2300           0 :             if ( aDelStart == aCurPos )
    2301             :             {
    2302             :                 // Complete paragraph previous
    2303           0 :                 ContentNode* pPrev = GetPrevVisNode( aCurPos.GetNode() );
    2304           0 :                 if ( pPrev )
    2305           0 :                     aDelStart = EditPaM( pPrev, 0 );
    2306             :             }
    2307             :         }
    2308             :     }
    2309             :     else
    2310             :     {
    2311           0 :         if ( nDelMode == DELMODE_SIMPLE )
    2312             :         {
    2313           0 :             aDelEnd = CursorRight( aCurPos );
    2314             :         }
    2315           0 :         else if ( nDelMode == DELMODE_RESTOFWORD )
    2316             :         {
    2317           0 :             aDelEnd = EndOfWord( aCurPos );
    2318             : 
    2319           0 :             if (aDelEnd.GetIndex() == aCurPos.GetIndex())
    2320             :             {
    2321           0 :                 const xub_StrLen nLen(aCurPos.GetNode()->Len());
    2322             : 
    2323             :                 // #i120020# when 0 == nLen, aDelStart needs to be adapted, not
    2324             :                 // aDelEnd. This would (and did) lead to a wrong order in the
    2325             :                 // ImpConnectParagraphs call later.
    2326           0 :                 if(nLen)
    2327             :                 {
    2328             :                     // end of para?
    2329           0 :                     if (aDelEnd.GetIndex() == nLen)
    2330             :                     {
    2331           0 :                         aDelEnd = WordLeft( aCurPos );
    2332             :                     }
    2333             :                     else // there's still sth to delete on the right
    2334             :                     {
    2335           0 :                         aDelEnd = EndOfWord( WordRight( aCurPos ) );
    2336             :                         // if there'n no next word...
    2337           0 :                         if (aDelEnd.GetIndex() == nLen )
    2338             :                         {
    2339           0 :                             aDelEnd.SetIndex( nLen );
    2340             :                         }
    2341             :                     }
    2342             :                 }
    2343             :                 else
    2344             :                 {
    2345           0 :                     aDelStart = WordLeft(aCurPos);
    2346             :                 }
    2347             :             }
    2348             :         }
    2349             :         else    // DELMODE_RESTOFCONTENT
    2350             :         {
    2351           0 :             aDelEnd.SetIndex( aCurPos.GetNode()->Len() );
    2352           0 :             if ( aDelEnd == aCurPos )
    2353             :             {
    2354             :                 // Complete paragraph next
    2355           0 :                 ContentNode* pNext = GetNextVisNode( aCurPos.GetNode() );
    2356           0 :                 if ( pNext )
    2357           0 :                     aDelEnd = EditPaM( pNext, pNext->Len() );
    2358             :             }
    2359             :         }
    2360             :     }
    2361             : 
    2362             :     // ConnectParagraphs  not enoguh for different Nodes when
    2363             :     // DELMODE_RESTOFCONTENT.
    2364           0 :     if ( ( nDelMode == DELMODE_RESTOFCONTENT ) || ( aDelStart.GetNode() == aDelEnd.GetNode() ) )
    2365           0 :         return ImpDeleteSelection( EditSelection( aDelStart, aDelEnd ) );
    2366             : 
    2367             :     // Decide now if to delete selection (RESTOFCONTENTS)
    2368           0 :     sal_Bool bSpecialBackward = ( ( nMode == DEL_LEFT ) && ( nDelMode == DELMODE_SIMPLE ) )
    2369           0 :                                 ? sal_True : sal_False;
    2370           0 :     if ( aStatus.IsAnyOutliner() )
    2371           0 :         bSpecialBackward = sal_False;
    2372             : 
    2373           0 :     return ImpConnectParagraphs( aDelStart.GetNode(), aDelEnd.GetNode(), bSpecialBackward );
    2374             : }
    2375             : 
    2376         728 : EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel)
    2377             : {
    2378         728 :     if ( !rCurSel.HasRange() )
    2379           3 :         return rCurSel.Min();
    2380             : 
    2381         725 :     EditSelection aCurSel(rCurSel);
    2382         725 :     aCurSel.Adjust( aEditDoc );
    2383         725 :     EditPaM aStartPaM(aCurSel.Min());
    2384         725 :     EditPaM aEndPaM(aCurSel.Max());
    2385             : 
    2386         725 :     CursorMoved( aStartPaM.GetNode() ); // only so that newly set Attributes dissapear...
    2387         725 :     CursorMoved( aEndPaM.GetNode() );   // only so that newly set Attributes dissapear...
    2388             : 
    2389             :     OSL_ENSURE( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" );
    2390             :     OSL_ENSURE( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" );
    2391             : 
    2392         725 :     sal_Int32 nStartNode = aEditDoc.GetPos( aStartPaM.GetNode() );
    2393         725 :     sal_Int32 nEndNode = aEditDoc.GetPos( aEndPaM.GetNode() );
    2394             : 
    2395             :     OSL_ENSURE( nEndNode != EE_PARA_NOT_FOUND, "Start > End ?!" );
    2396             :     OSL_ENSURE( nStartNode <= nEndNode, "Start > End ?!" );
    2397             : 
    2398             :     // Remove all nodes in between ....
    2399         731 :     for ( sal_Int32 z = nStartNode+1; z < nEndNode; z++ )
    2400             :     {
    2401             :         // Always nStartNode+1, due to Remove()!
    2402           6 :         ImpRemoveParagraph( nStartNode+1 );
    2403             :     }
    2404             : 
    2405         725 :     if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
    2406             :     {
    2407             :         // The Rest of the StartNodes...
    2408             :         sal_uInt16 nChars;
    2409         543 :         nChars = aStartPaM.GetNode()->Len() - aStartPaM.GetIndex();
    2410         543 :         ImpRemoveChars( aStartPaM, nChars );
    2411         543 :         ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
    2412             :         OSL_ENSURE( pPortion, "Blind Portion in ImpDeleteSelection(3)" );
    2413         543 :         pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), aStartPaM.GetNode()->Len() );
    2414             : 
    2415             :         // The beginning of the EndNodes....
    2416         543 :         nChars = aEndPaM.GetIndex();
    2417         543 :         aEndPaM.SetIndex( 0 );
    2418         543 :         ImpRemoveChars( aEndPaM, nChars );
    2419         543 :         pPortion = FindParaPortion( aEndPaM.GetNode() );
    2420             :         OSL_ENSURE( pPortion, "Blind Portion in ImpDeleteSelection(4)" );
    2421         543 :         pPortion->MarkSelectionInvalid( 0, aEndPaM.GetNode()->Len() );
    2422             :         // Join together....
    2423         543 :         aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() );
    2424             :     }
    2425             :     else
    2426             :     {
    2427             :         sal_uInt16 nChars;
    2428         182 :         nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex();
    2429         182 :         ImpRemoveChars( aStartPaM, nChars );
    2430         182 :         ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
    2431             :         OSL_ENSURE( pPortion, "Blind Portion in ImpDeleteSelection(5)" );
    2432         182 :         pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
    2433             :     }
    2434             : 
    2435         725 :     UpdateSelections();
    2436         725 :     TextModified();
    2437         725 :     return aStartPaM;
    2438             : }
    2439             : 
    2440           6 : void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara )
    2441             : {
    2442           6 :     ContentNode* pNode = aEditDoc.GetObject( nPara );
    2443           6 :     ContentNode* pNextNode = aEditDoc.GetObject( nPara+1 );
    2444             : 
    2445             :     OSL_ENSURE( pNode, "Blind Node in ImpRemoveParagraph" );
    2446             : 
    2447           6 :     DeletedNodeInfo* pInf = new DeletedNodeInfo( (sal_uIntPtr)pNode, nPara );
    2448           6 :     aDeletedNodes.push_back(pInf);
    2449             : 
    2450             :     // The node is managed by the undo and possibly destroyed!
    2451           6 :     aEditDoc.Release( nPara );
    2452           6 :     GetParaPortions().Remove( nPara );
    2453             : 
    2454           6 :     if ( IsCallParaInsertedOrDeleted() )
    2455             :     {
    2456           6 :         GetEditEnginePtr()->ParagraphDeleted( nPara );
    2457             :     }
    2458             : 
    2459             :     // Extra-Space may be determined again in the following. For
    2460             :     // ParaAttribsChanged the paragraph is unfortunately formatted again,
    2461             :     // however this method should not be time critical!
    2462           6 :     if ( pNextNode )
    2463           6 :         ParaAttribsChanged( pNextNode );
    2464             : 
    2465           6 :     if ( IsUndoEnabled() && !IsInUndo() )
    2466           6 :         InsertUndo(new EditUndoDelContent(pEditEngine, pNode, nPara));
    2467             :     else
    2468             :     {
    2469           0 :         aEditDoc.RemoveItemsFromPool(*pNode);
    2470           0 :         if ( pNode->GetStyleSheet() )
    2471           0 :             EndListening( *pNode->GetStyleSheet(), sal_False );
    2472           0 :         delete pNode;
    2473             :     }
    2474           6 : }
    2475             : 
    2476           0 : EditPaM ImpEditEngine::AutoCorrect( const EditSelection& rCurSel, sal_Unicode c,
    2477             :                                     sal_Bool bOverwrite, Window* pFrameWin )
    2478             : {
    2479           0 :     EditSelection aSel( rCurSel );
    2480           0 :     SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
    2481           0 :     if ( pAutoCorrect )
    2482             :     {
    2483           0 :         if ( aSel.HasRange() )
    2484           0 :             aSel = ImpDeleteSelection( rCurSel );
    2485             : 
    2486             :         // #i78661 allow application to turn off capitalization of
    2487             :         // start sentence explicitly.
    2488             :         // (This is done by setting IsFirstWordCapitalization to sal_False.)
    2489           0 :         sal_Bool bOldCptlSttSntnc = pAutoCorrect->IsAutoCorrFlag( CptlSttSntnc );
    2490           0 :         if (!IsFirstWordCapitalization())
    2491             :         {
    2492           0 :             ESelection aESel( CreateESel(aSel) );
    2493           0 :             EditSelection aFirstWordSel;
    2494           0 :             EditSelection aSecondWordSel;
    2495           0 :             if (aESel.nEndPara == 0)    // is this the first para?
    2496             :             {
    2497             :                 // select first word...
    2498             :                 // start by checking if para starts with word.
    2499           0 :                 aFirstWordSel = SelectWord( CreateSel(ESelection()) );
    2500           0 :                 if (aFirstWordSel.Min().GetIndex() == 0 && aFirstWordSel.Max().GetIndex() == 0)
    2501             :                 {
    2502             :                     // para does not start with word -> select next/first word
    2503           0 :                     EditPaM aRightWord( WordRight( aFirstWordSel.Max(), 1 ) );
    2504           0 :                     aFirstWordSel = SelectWord( EditSelection( aRightWord ) );
    2505             :                 }
    2506             : 
    2507             :                 // select second word
    2508             :                 // (sometimes aSel mightnot point to the end of the first word
    2509             :                 // but to some following char like '.'. ':', ...
    2510             :                 // In those cases we need aSecondWordSel to see if aSel
    2511             :                 // will actually effect the first word.)
    2512           0 :                 EditPaM aRight2Word( WordRight( aFirstWordSel.Max(), 1 ) );
    2513           0 :                 aSecondWordSel = SelectWord( EditSelection( aRight2Word ) );
    2514             :             }
    2515           0 :             sal_Bool bIsFirstWordInFirstPara = aESel.nEndPara == 0 &&
    2516           0 :                     aFirstWordSel.Max().GetIndex() <= aSel.Max().GetIndex() &&
    2517           0 :                     aSel.Max().GetIndex() <= aSecondWordSel.Min().GetIndex();
    2518             : 
    2519           0 :             if (bIsFirstWordInFirstPara)
    2520           0 :                 pAutoCorrect->SetAutoCorrFlag( CptlSttSntnc, IsFirstWordCapitalization() );
    2521             :         }
    2522             : 
    2523           0 :         ContentNode* pNode = aSel.Max().GetNode();
    2524           0 :         sal_uInt16 nIndex = aSel.Max().GetIndex();
    2525           0 :         EdtAutoCorrDoc aAuto(pEditEngine, pNode, nIndex, c);
    2526             :         // FIXME: this _must_ be called with reference to the actual node text!
    2527           0 :         String const& rNodeString(pNode->GetString());
    2528             :         pAutoCorrect->DoAutoCorrect(
    2529           0 :             aAuto, rNodeString, nIndex, c, !bOverwrite, pFrameWin );
    2530           0 :         aSel.Max().SetIndex( aAuto.GetCursor() );
    2531             : 
    2532             :         // #i78661 since the SvxAutoCorrect object used here is
    2533             :         // shared we need to reset the value to it's original state.
    2534           0 :         pAutoCorrect->SetAutoCorrFlag( CptlSttSntnc, bOldCptlSttSntnc );
    2535             :     }
    2536           0 :     return aSel.Max();
    2537             : }
    2538             : 
    2539             : 
    2540           0 : EditPaM ImpEditEngine::InsertText( const EditSelection& rCurSel,
    2541             :         sal_Unicode c, sal_Bool bOverwrite, sal_Bool bIsUserInput )
    2542             : {
    2543             :     OSL_ENSURE( c != '\t', "Tab for InsertText ?" );
    2544             :     OSL_ENSURE( c != '\n', "Word wrapping for InsertText ?");
    2545             : 
    2546           0 :     EditPaM aPaM( rCurSel.Min() );
    2547             : 
    2548           0 :     sal_Bool bDoOverwrite = ( bOverwrite &&
    2549           0 :             ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) ) ? sal_True : sal_False;
    2550             : 
    2551           0 :     sal_Bool bUndoAction = ( rCurSel.HasRange() || bDoOverwrite );
    2552             : 
    2553           0 :     if ( bUndoAction )
    2554           0 :         UndoActionStart( EDITUNDO_INSERT );
    2555             : 
    2556           0 :     if ( rCurSel.HasRange() )
    2557             :     {
    2558           0 :         aPaM = ImpDeleteSelection( rCurSel );
    2559             :     }
    2560           0 :     else if ( bDoOverwrite )
    2561             :     {
    2562             :         // If selected, then do not also overwrite a character!
    2563           0 :         EditSelection aTmpSel( aPaM );
    2564           0 :         aTmpSel.Max().GetIndex()++;
    2565             :         OSL_ENSURE( !aTmpSel.DbgIsBuggy( aEditDoc ), "Overwrite: Wrong selection! ");
    2566           0 :         ImpDeleteSelection( aTmpSel );
    2567             :     }
    2568             : 
    2569           0 :     if ( aPaM.GetNode()->Len() < MAXCHARSINPARA )
    2570             :     {
    2571           0 :         if (bIsUserInput && IsInputSequenceCheckingRequired( c, rCurSel ))
    2572             :         {
    2573           0 :             uno::Reference < i18n::XExtendedInputSequenceChecker > _xISC( ImplGetInputSequenceChecker() );
    2574           0 :             if (!pCTLOptions)
    2575           0 :                 pCTLOptions = new SvtCTLOptions;
    2576             : 
    2577           0 :             if (_xISC.is() || pCTLOptions)
    2578             :             {
    2579           0 :                 xub_StrLen nTmpPos = aPaM.GetIndex();
    2580           0 :                 sal_Int16 nCheckMode = pCTLOptions->IsCTLSequenceCheckingRestricted() ?
    2581           0 :                         i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
    2582             : 
    2583             :                 // the text that needs to be checked is only the one
    2584             :                 // before the current cursor position
    2585           0 :                 OUString aOldText( aPaM.GetNode()->Copy(0, nTmpPos) );
    2586           0 :                 OUString aNewText( aOldText );
    2587           0 :                 if (pCTLOptions->IsCTLSequenceCheckingTypeAndReplace())
    2588             :                 {
    2589           0 :                     /*const xub_StrLen nPrevPos = static_cast< xub_StrLen >*/( _xISC->correctInputSequence( aNewText, nTmpPos - 1, c, nCheckMode ) );
    2590             : 
    2591             :                     // find position of first character that has changed
    2592           0 :                     sal_Int32 nOldLen = aOldText.getLength();
    2593           0 :                     sal_Int32 nNewLen = aNewText.getLength();
    2594           0 :                     const sal_Unicode *pOldTxt = aOldText.getStr();
    2595           0 :                     const sal_Unicode *pNewTxt = aNewText.getStr();
    2596           0 :                     sal_Int32 nChgPos = 0;
    2597           0 :                     while ( nChgPos < nOldLen && nChgPos < nNewLen &&
    2598           0 :                             pOldTxt[nChgPos] == pNewTxt[nChgPos] )
    2599           0 :                         ++nChgPos;
    2600             : 
    2601           0 :                     String aChgText( aNewText.copy( nChgPos ) );
    2602             : 
    2603             :                     // select text from first pos to be changed to current pos
    2604           0 :                     EditSelection aSel( EditPaM( aPaM.GetNode(), (sal_uInt16) nChgPos ), aPaM );
    2605             : 
    2606           0 :                     if (aChgText.Len())
    2607           0 :                         return InsertText( aSel, aChgText ); // implicitly handles undo
    2608             :                     else
    2609           0 :                         return aPaM;
    2610             :                 }
    2611             :                 else
    2612             :                 {
    2613             :                     // should the character be ignored (i.e. not get inserted) ?
    2614           0 :                     if (!_xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
    2615           0 :                         return aPaM;    // nothing to be done -> no need for undo
    2616           0 :                 }
    2617           0 :             }
    2618             : 
    2619             :             // at this point now we will insert the character 'normally' some lines below...
    2620             :         }
    2621             : 
    2622           0 :         if ( IsUndoEnabled() && !IsInUndo() )
    2623             :         {
    2624           0 :             EditUndoInsertChars* pNewUndo = new EditUndoInsertChars(pEditEngine, CreateEPaM(aPaM), OUString(c));
    2625           0 :             sal_Bool bTryMerge = ( !bDoOverwrite && ( c != ' ' ) ) ? sal_True : sal_False;
    2626           0 :             InsertUndo( pNewUndo, bTryMerge );
    2627             :         }
    2628             : 
    2629           0 :         aEditDoc.InsertText( (const EditPaM&)aPaM, OUString(c) );
    2630           0 :         ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
    2631             :         OSL_ENSURE( pPortion, "Blind Portion in InsertText" );
    2632           0 :         pPortion->MarkInvalid( aPaM.GetIndex(), 1 );
    2633           0 :         aPaM.GetIndex()++;   // does not do EditDoc-Method anymore
    2634             :     }
    2635             : 
    2636           0 :     TextModified();
    2637             : 
    2638           0 :     if ( bUndoAction )
    2639           0 :         UndoActionEnd( EDITUNDO_INSERT );
    2640             : 
    2641           0 :     return aPaM;
    2642             : }
    2643             : 
    2644       36674 : EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const String& rStr)
    2645             : {
    2646       36674 :     UndoActionStart( EDITUNDO_INSERT );
    2647             : 
    2648       36674 :     EditPaM aPaM;
    2649       36674 :     if ( aCurSel.HasRange() )
    2650         444 :         aPaM = ImpDeleteSelection( aCurSel );
    2651             :     else
    2652       36230 :         aPaM = aCurSel.Max();
    2653             : 
    2654       36674 :     EditPaM aCurPaM( aPaM );    // for the Invalidate
    2655             : 
    2656             :     // get word boundaries in order to clear possible WrongList entries
    2657             :     // and invalidate all the necessary text (everything after and including the
    2658             :     // start of the word)
    2659             :     // #i107201# do the expensive SelectWord call only if online spelling is active
    2660       36674 :     EditSelection aCurWord;
    2661       36674 :     if ( GetStatus().DoOnlineSpelling() )
    2662        5312 :         aCurWord = SelectWord( aCurPaM, i18n::WordType::DICTIONARY_WORD );
    2663             : 
    2664       36674 :     XubString aText(convertLineEnd(rStr, LINEEND_LF));
    2665       73348 :     SfxVoidItem aTabItem( EE_FEATURE_TAB );
    2666             : 
    2667             :     // Converts to linesep = \n
    2668             :     // Token LINE_SEP query,
    2669             :     // since the MAC-Compiler makes something else from \n !
    2670             : 
    2671             :     // fdo#39869 The loop run variable must be capable to hold STRLEN_MAX+1,
    2672             :     // that with STRING32 would be SAL_MAX_INT32+1 but with 16-bit is 0xFFFF+1
    2673       36674 :     sal_uInt32 nStart = 0;
    2674       96426 :     while ( nStart < aText.Len() )
    2675             :     {
    2676       23078 :         sal_uInt32 nEnd = aText.Search( LINE_SEP, static_cast<xub_StrLen>(nStart) );
    2677       23078 :         if ( nEnd == STRING_NOTFOUND )
    2678       22245 :             nEnd = aText.Len(); // not dereference!
    2679             : 
    2680             :         // Start == End => empty line
    2681       23078 :         if ( nEnd > nStart )
    2682             :         {
    2683       22390 :             XubString aLine( aText, nStart, static_cast<xub_StrLen>(nEnd-nStart) );
    2684       22390 :             xub_StrLen nChars = aPaM.GetNode()->Len() + aLine.Len();
    2685       22390 :             if ( nChars > MAXCHARSINPARA )
    2686             :             {
    2687           0 :                 xub_StrLen nMaxNewChars = MAXCHARSINPARA-aPaM.GetNode()->Len();
    2688           0 :                 nEnd -= ( aLine.Len() - nMaxNewChars ); // Then the characters end up in the next paragraph.
    2689           0 :                 aLine.Erase( nMaxNewChars );            // Delete the Rest...
    2690             :             }
    2691       22390 :             if ( IsUndoEnabled() && !IsInUndo() )
    2692       12865 :                 InsertUndo(new EditUndoInsertChars(pEditEngine, CreateEPaM(aPaM), aLine));
    2693             :             // Tabs ?
    2694       22390 :             if ( aLine.Search( '\t' ) == STRING_NOTFOUND )
    2695       22380 :                 aPaM = aEditDoc.InsertText( aPaM, aLine );
    2696             :             else
    2697             :             {
    2698          10 :                 sal_uInt32 nStart2 = 0;
    2699          44 :                 while ( nStart2 < aLine.Len() )
    2700             :                 {
    2701          24 :                     sal_uInt32 nEnd2 = aLine.Search( '\t', static_cast<xub_StrLen>(nStart2) );
    2702          24 :                     if ( nEnd2 == STRING_NOTFOUND )
    2703           8 :                         nEnd2 = aLine.Len();    // not dereference!
    2704             : 
    2705          24 :                     if ( nEnd2 > nStart2 )
    2706          34 :                         aPaM = aEditDoc.InsertText( aPaM, XubString( aLine,
    2707             :                                     static_cast<xub_StrLen>(nStart2),
    2708          17 :                                     static_cast<xub_StrLen>(nEnd2-nStart2) ) );
    2709          24 :                     if ( nEnd2 < aLine.Len() )
    2710             :                     {
    2711          16 :                         aPaM = aEditDoc.InsertFeature( aPaM, aTabItem );
    2712             :                     }
    2713          24 :                     nStart2 = nEnd2+1;
    2714             :                 }
    2715             :             }
    2716       22390 :             ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
    2717             :             OSL_ENSURE( pPortion, "Blind Portion in InsertText" );
    2718             : 
    2719       22390 :             if ( GetStatus().DoOnlineSpelling() )
    2720             :             {
    2721             :                 // now remove the Wrongs (red spell check marks) from both words...
    2722        4220 :                 WrongList *pWrongs = aCurPaM.GetNode()->GetWrongList();
    2723        4220 :                 if (pWrongs && !pWrongs->empty())
    2724           0 :                     pWrongs->ClearWrongs( aCurWord.Min().GetIndex(), aPaM.GetIndex(), aPaM.GetNode() );
    2725             :                 // ... and mark both words as 'to be checked again'
    2726        4220 :                 pPortion->MarkInvalid( aCurWord.Min().GetIndex(), aLine.Len() );
    2727             :             }
    2728             :             else
    2729       18170 :                 pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.Len() );
    2730             :         }
    2731       23078 :         if ( nEnd < aText.Len() )
    2732         833 :             aPaM = ImpInsertParaBreak( aPaM );
    2733             : 
    2734       23078 :         nStart = nEnd+1;
    2735             :     }
    2736             : 
    2737       36674 :     UndoActionEnd( EDITUNDO_INSERT );
    2738             : 
    2739       36674 :     TextModified();
    2740       73348 :     return aPaM;
    2741             : }
    2742             : 
    2743      216127 : EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const XubString& rStr )
    2744             : {
    2745             :     OSL_ENSURE( rStr.Search( 0x0A ) == STRING_NOTFOUND, "FastInsertText: Newline not allowed! ");
    2746             :     OSL_ENSURE( rStr.Search( 0x0D ) == STRING_NOTFOUND, "FastInsertText: Newline not allowed! ");
    2747             :     OSL_ENSURE( rStr.Search( '\t' ) == STRING_NOTFOUND, "FastInsertText: Newline not allowed! ");
    2748             : 
    2749      216127 :     if ( ( aPaM.GetNode()->Len() + rStr.Len() ) < MAXCHARSINPARA )
    2750             :     {
    2751      216127 :         if ( IsUndoEnabled() && !IsInUndo() )
    2752           0 :             InsertUndo(new EditUndoInsertChars(pEditEngine, CreateEPaM(aPaM), rStr));
    2753             : 
    2754      216127 :         aPaM = aEditDoc.InsertText( aPaM, rStr );
    2755      216127 :         TextModified();
    2756             :     }
    2757             :     else
    2758             :     {
    2759           0 :         aPaM = ImpInsertText( aPaM, rStr );
    2760             :     }
    2761             : 
    2762      216127 :     return aPaM;
    2763             : }
    2764             : 
    2765        3673 : EditPaM ImpEditEngine::ImpInsertFeature(const EditSelection& rCurSel, const SfxPoolItem& rItem)
    2766             : {
    2767        3673 :     EditPaM aPaM;
    2768        3673 :     if ( rCurSel.HasRange() )
    2769          69 :         aPaM = ImpDeleteSelection( rCurSel );
    2770             :     else
    2771        3604 :         aPaM = rCurSel.Max();
    2772             : 
    2773        3673 :     if ( aPaM.GetIndex() >= 0xfffe )
    2774           0 :         return aPaM;
    2775             : 
    2776        3673 :     if ( IsUndoEnabled() && !IsInUndo() )
    2777        2560 :         InsertUndo(new EditUndoInsertFeature(pEditEngine, CreateEPaM(aPaM), rItem));
    2778        3673 :     aPaM = aEditDoc.InsertFeature( aPaM, rItem );
    2779             : 
    2780        3673 :     ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
    2781             :     OSL_ENSURE( pPortion, "Blind Portion in InsertFeature" );
    2782        3673 :     pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 );
    2783             : 
    2784        3673 :     TextModified();
    2785             : 
    2786        3673 :     return aPaM;
    2787             : }
    2788             : 
    2789           6 : EditPaM ImpEditEngine::ImpInsertParaBreak( const EditSelection& rCurSel, bool bKeepEndingAttribs )
    2790             : {
    2791           6 :     EditPaM aPaM;
    2792           6 :     if ( rCurSel.HasRange() )
    2793           0 :         aPaM = ImpDeleteSelection( rCurSel );
    2794             :     else
    2795           6 :         aPaM = rCurSel.Max();
    2796             : 
    2797           6 :     return ImpInsertParaBreak( aPaM, bKeepEndingAttribs );
    2798             : }
    2799             : 
    2800        1315 : EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs )
    2801             : {
    2802        1315 :     if ( aEditDoc.Count() >= EE_PARA_MAX_COUNT )
    2803             :     {
    2804             :         SAL_WARN( "editeng", "ImpEditEngine::ImpInsertParaBreak - can't process more than "
    2805             :                 << EE_PARA_MAX_COUNT << " paragraphs!");
    2806           0 :         return rPaM;
    2807             :     }
    2808             : 
    2809        1315 :     if ( IsUndoEnabled() && !IsInUndo() )
    2810         368 :         InsertUndo(new EditUndoSplitPara(pEditEngine, aEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex()));
    2811             : 
    2812        1315 :     EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) );
    2813             : 
    2814        1315 :     if ( GetStatus().DoOnlineSpelling() )
    2815             :     {
    2816         411 :         xub_StrLen nEnd = rPaM.GetNode()->Len();
    2817         411 :         aPaM.GetNode()->CreateWrongList();
    2818         411 :         WrongList* pLWrongs = rPaM.GetNode()->GetWrongList();
    2819         411 :         WrongList* pRWrongs = aPaM.GetNode()->GetWrongList();
    2820             :         // take over misspelled words:
    2821         411 :         for(WrongList::iterator i = pLWrongs->begin(); i < pLWrongs->end(); ++i)
    2822             :         {
    2823             :             // Correct only if really a word gets overlapped in the process of
    2824             :             // Spell checking
    2825           0 :             if (i->nStart > nEnd)
    2826             :             {
    2827           0 :                 pRWrongs->push_back(*i);
    2828           0 :                 WrongRange& rRWrong = pRWrongs->back();
    2829           0 :                 rRWrong.nStart = rRWrong.nStart - nEnd;
    2830           0 :                 rRWrong.nEnd = rRWrong.nEnd - nEnd;
    2831             :             }
    2832           0 :             else if (i->nStart < nEnd && i->nEnd > nEnd)
    2833           0 :                 i->nEnd = nEnd;
    2834             :         }
    2835         411 :         sal_uInt16 nInv = nEnd ? nEnd-1 : nEnd;
    2836         411 :         if ( nEnd )
    2837         403 :             pLWrongs->MarkInvalid( nInv, nEnd );
    2838             :         else
    2839           8 :             pLWrongs->SetValid();
    2840         411 :         pRWrongs->SetValid(); // otherwise 0 - 0xFFFF
    2841         411 :         pRWrongs->MarkInvalid( 0, 1 );  // Only test the first word
    2842             :     }
    2843             : 
    2844        1315 :     ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() );
    2845             :     OSL_ENSURE( pPortion, "Blind Portion in ImpInsertParaBreak" );
    2846        1315 :     pPortion->MarkInvalid( rPaM.GetIndex(), 0 );
    2847             : 
    2848             :     // Optimization: Do not place unnecessarily many getPos to Listen!
    2849             :     // Here, as in undo, but also in all other methods.
    2850        1315 :     sal_Int32 nPos = GetParaPortions().GetPos( pPortion );
    2851        1315 :     ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() );
    2852        1315 :     GetParaPortions().Insert(nPos+1, pNewPortion);
    2853        1315 :     ParaAttribsChanged( pNewPortion->GetNode() );
    2854        1315 :     if ( IsCallParaInsertedOrDeleted() )
    2855        1315 :         GetEditEnginePtr()->ParagraphInserted( nPos+1 );
    2856             : 
    2857        1315 :     CursorMoved( rPaM.GetNode() );  // if empty Attributes have emerged.
    2858        1315 :     TextModified();
    2859        1315 :     return aPaM;
    2860             : }
    2861             : 
    2862        4771 : EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_Int32 nPara )
    2863             : {
    2864        4771 :     if ( IsUndoEnabled() && !IsInUndo() )
    2865             :     {
    2866           0 :         if ( nPara )
    2867             :         {
    2868             :             OSL_ENSURE( aEditDoc.GetObject( nPara-1 ), "FastInsertParagraph: Prev does not exist" );
    2869           0 :             InsertUndo(new EditUndoSplitPara(pEditEngine, nPara-1, aEditDoc.GetObject( nPara-1 )->Len()));
    2870             :         }
    2871             :         else
    2872           0 :             InsertUndo(new EditUndoSplitPara(pEditEngine, 0, 0));
    2873             :     }
    2874             : 
    2875        4771 :     ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() );
    2876             :     // If flat mode, then later no Font is set:
    2877        4771 :     pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
    2878             : 
    2879        4771 :     if ( GetStatus().DoOnlineSpelling() )
    2880        3553 :         pNode->CreateWrongList();
    2881             : 
    2882        4771 :     aEditDoc.Insert(nPara, pNode);
    2883             : 
    2884        4771 :     ParaPortion* pNewPortion = new ParaPortion( pNode );
    2885        4771 :     GetParaPortions().Insert(nPara, pNewPortion);
    2886        4771 :     if ( IsCallParaInsertedOrDeleted() )
    2887        4771 :         GetEditEnginePtr()->ParagraphInserted( nPara );
    2888             : 
    2889        4771 :     return EditPaM( pNode, 0 );
    2890             : }
    2891             : 
    2892           0 : EditPaM ImpEditEngine::InsertParaBreak( EditSelection aCurSel )
    2893             : {
    2894           0 :     EditPaM aPaM( ImpInsertParaBreak( aCurSel ) );
    2895           0 :     if ( aStatus.DoAutoIndenting() )
    2896             :     {
    2897           0 :         sal_Int32 nPara = aEditDoc.GetPos( aPaM.GetNode() );
    2898             :         OSL_ENSURE( nPara > 0, "AutoIndenting: Error!" );
    2899           0 :         XubString aPrevParaText( GetEditDoc().GetParaAsString( nPara-1 ) );
    2900           0 :         sal_uInt16 n = 0;
    2901           0 :         while ( ( n < aPrevParaText.Len() ) &&
    2902           0 :                 ( ( aPrevParaText.GetChar(n) == ' ' ) || ( aPrevParaText.GetChar(n) == '\t' ) ) )
    2903             :         {
    2904           0 :             if ( aPrevParaText.GetChar(n) == '\t' )
    2905           0 :                 aPaM = ImpInsertFeature( aPaM, SfxVoidItem( EE_FEATURE_TAB ) );
    2906             :             else
    2907           0 :                 aPaM = ImpInsertText( aPaM, OUString(aPrevParaText.GetChar(n)) );
    2908           0 :             n++;
    2909           0 :         }
    2910             : 
    2911             :     }
    2912           0 :     return aPaM;
    2913             : }
    2914             : 
    2915           0 : EditPaM ImpEditEngine::InsertTab( EditSelection aCurSel )
    2916             : {
    2917           0 :     EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_TAB ) ) );
    2918           0 :     return aPaM;
    2919             : }
    2920             : 
    2921           0 : EditPaM ImpEditEngine::InsertField(const EditSelection& rCurSel, const SvxFieldItem& rFld)
    2922             : {
    2923           0 :     return ImpInsertFeature(rCurSel, rFld);
    2924             : }
    2925             : 
    2926        2521 : sal_Bool ImpEditEngine::UpdateFields()
    2927             : {
    2928        2521 :     bool bChanges = false;
    2929        2521 :     sal_Int32 nParas = GetEditDoc().Count();
    2930        5043 :     for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ )
    2931             :     {
    2932        2522 :         bool bChangesInPara = false;
    2933        2522 :         ContentNode* pNode = GetEditDoc().GetObject( nPara );
    2934             :         OSL_ENSURE( pNode, "NULL-Pointer in Doc" );
    2935        2522 :         CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
    2936        5779 :         for (size_t nAttr = 0; nAttr < rAttribs.size(); ++nAttr)
    2937             :         {
    2938        3257 :             EditCharAttrib& rAttr = rAttribs[nAttr];
    2939        3257 :             if (rAttr.Which() == EE_FEATURE_FIELD)
    2940             :             {
    2941        2760 :                 EditCharAttribField& rField = static_cast<EditCharAttribField&>(rAttr);
    2942        2760 :                 boost::scoped_ptr<EditCharAttribField> pCurrent(new EditCharAttribField(rField));
    2943        2760 :                 rField.Reset();
    2944             : 
    2945        2760 :                 if ( aStatus.MarkFields() )
    2946          44 :                     rField.GetFldColor() = new Color( GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor );
    2947             : 
    2948             :                 OUString aFldValue =
    2949        2760 :                     GetEditEnginePtr()->CalcFieldValue(
    2950        2760 :                         static_cast<const SvxFieldItem&>(*rField.GetItem()),
    2951        8280 :                         nPara, rField.GetStart(), rField.GetTxtColor(), rField.GetFldColor());
    2952             : 
    2953        2760 :                 rField.SetFieldValue(aFldValue);
    2954        2760 :                 if (rField != *pCurrent)
    2955             :                 {
    2956        2382 :                     bChanges = true;
    2957        2382 :                     bChangesInPara = true;
    2958        2760 :                 }
    2959             :             }
    2960             :         }
    2961        2522 :         if ( bChangesInPara )
    2962             :         {
    2963             :             // If possible be more precise when invalidate.
    2964        2191 :             ParaPortion* pPortion = GetParaPortions()[nPara];
    2965             :             OSL_ENSURE( pPortion, "NULL-Pointer in Doc" );
    2966        2191 :             pPortion->MarkSelectionInvalid( 0, pNode->Len() );
    2967             :         }
    2968             :     }
    2969        2521 :     return bChanges;
    2970             : }
    2971             : 
    2972          11 : EditPaM ImpEditEngine::InsertLineBreak(const EditSelection& aCurSel)
    2973             : {
    2974          11 :     EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_LINEBR ) ) );
    2975          11 :     return aPaM;
    2976             : }
    2977             : 
    2978             : //  ----------------------------------------------------------------------
    2979             : //  Helper functions
    2980             : //  ----------------------------------------------------------------------
    2981         936 : Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, sal_uInt16 nFlags )
    2982             : {
    2983             :     OSL_ENSURE( GetUpdateMode(), "Must not be reached when Update=FALSE: PaMtoEditCursor" );
    2984             : 
    2985         936 :     Rectangle aEditCursor;
    2986         936 :     long nY = 0;
    2987         936 :     for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
    2988             :     {
    2989         936 :         ParaPortion* pPortion = GetParaPortions()[nPortion];
    2990         936 :         ContentNode* pNode = pPortion->GetNode();
    2991             :         OSL_ENSURE( pNode, "Invalid Node in Portion!" );
    2992         936 :         if ( pNode != aPaM.GetNode() )
    2993             :         {
    2994           0 :             nY += pPortion->GetHeight();
    2995             :         }
    2996             :         else
    2997             :         {
    2998         936 :             aEditCursor = GetEditCursor( pPortion, aPaM.GetIndex(), nFlags );
    2999         936 :             aEditCursor.Top() += nY;
    3000         936 :             aEditCursor.Bottom() += nY;
    3001         936 :             return aEditCursor;
    3002             :         }
    3003             :     }
    3004             :     OSL_FAIL( "Portion not found!" );
    3005           0 :     return aEditCursor;
    3006             : }
    3007             : 
    3008          11 : EditPaM ImpEditEngine::GetPaM( Point aDocPos, sal_Bool bSmart )
    3009             : {
    3010             :     OSL_ENSURE( GetUpdateMode(), "Must not be reached when Update=FALSE: GetPaM" );
    3011             : 
    3012          11 :     long nY = 0;
    3013             :     long nTmpHeight;
    3014          11 :     EditPaM aPaM;
    3015             :     sal_Int32 nPortion;
    3016          11 :     for ( nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
    3017             :     {
    3018          11 :         ParaPortion* pPortion = GetParaPortions()[nPortion];
    3019          11 :         nTmpHeight = pPortion->GetHeight();     // should also be correct for !bVisible!
    3020          11 :         nY += nTmpHeight;
    3021          11 :         if ( nY > aDocPos.Y() )
    3022             :         {
    3023          11 :             nY -= nTmpHeight;
    3024          11 :             aDocPos.Y() -= nY;
    3025             :             // Skip invisible Portions:
    3026          22 :             while ( pPortion && !pPortion->IsVisible() )
    3027             :             {
    3028           0 :                 nPortion++;
    3029           0 :                 pPortion = GetParaPortions().SafeGetObject( nPortion );
    3030             :             }
    3031             :             OSL_ENSURE( pPortion, "No visible paragraph found: GetPaM" );
    3032          11 :             aPaM = GetPaM( pPortion, aDocPos, bSmart );
    3033          11 :             return aPaM;
    3034             : 
    3035             :         }
    3036             :     }
    3037             :     // Then search for the last visible:
    3038           0 :     nPortion = GetParaPortions().Count()-1;
    3039           0 :     while ( nPortion && !GetParaPortions()[nPortion]->IsVisible() )
    3040           0 :         nPortion--;
    3041             : 
    3042             :     OSL_ENSURE( GetParaPortions()[nPortion]->IsVisible(), "No visible paragraph found: GetPaM" );
    3043           0 :     aPaM.SetNode( GetParaPortions()[nPortion]->GetNode() );
    3044           0 :     aPaM.SetIndex( GetParaPortions()[nPortion]->GetNode()->Len() );
    3045           0 :     return aPaM;
    3046             : }
    3047             : 
    3048      223467 : sal_uInt32 ImpEditEngine::GetTextHeight() const
    3049             : {
    3050             :     OSL_ENSURE( GetUpdateMode(), "Should not be used for Update=FALSE: GetTextHeight" );
    3051             :     OSL_ENSURE( IsFormatted() || IsFormatting(), "GetTextHeight: Not formatted" );
    3052      223467 :     return nCurTextHeight;
    3053             : }
    3054             : 
    3055       45728 : sal_uInt32 ImpEditEngine::CalcTextWidth( sal_Bool bIgnoreExtraSpace )
    3056             : {
    3057             :     // If still not formatted and not in the process.
    3058             :     // Will be brought in the formatting for AutoPageSize.
    3059       45728 :     if ( !IsFormatted() && !IsFormatting() )
    3060           0 :         FormatDoc();
    3061             : 
    3062             :     EditLine* pLine;
    3063             : 
    3064       45728 :     long nMaxWidth = 0;
    3065       45728 :     long nCurWidth = 0;
    3066             : 
    3067             :     // --------------------------------------------------
    3068             :     // Over all the paragraphs ...
    3069             :     // --------------------------------------------------
    3070       45728 :     sal_Int32 nParas = GetParaPortions().Count();
    3071       93583 :     for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ )
    3072             :     {
    3073       47855 :         ParaPortion* pPortion = GetParaPortions()[nPara];
    3074       47855 :         if ( pPortion->IsVisible() )
    3075             :         {
    3076       47855 :             const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pPortion->GetNode() );
    3077       47855 :             sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pPortion->GetNode() );
    3078             : 
    3079             :             // --------------------------------------------------
    3080             :             // On the lines of the paragraph ...
    3081             :             // --------------------------------------------------
    3082       47855 :             sal_uLong nLines = pPortion->GetLines().Count();
    3083       98100 :             for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
    3084             :             {
    3085       50245 :                 pLine = pPortion->GetLines()[nLine];
    3086             :                 OSL_ENSURE( pLine, "NULL-Pointer in the line iterator in CalcWidth" );
    3087             :                 // nCurWidth = pLine->GetStartPosX();
    3088             :                 // For Center- or Right- alignment it depends on the paper
    3089             :                 // width, here not prefered. I general, it is best not leave it
    3090             :                 // to StartPosX, also the right indents have to be taken into
    3091             :                 // account!
    3092       50245 :                 nCurWidth = GetXValue( rLRItem.GetTxtLeft() + nSpaceBeforeAndMinLabelWidth );
    3093       50245 :                 if ( nLine == 0 )
    3094             :                 {
    3095       47855 :                     long nFI = GetXValue( rLRItem.GetTxtFirstLineOfst() );
    3096       47855 :                     nCurWidth -= nFI;
    3097       47855 :                     if ( pPortion->GetBulletX() > nCurWidth )
    3098             :                     {
    3099         247 :                         nCurWidth += nFI;   // LI?
    3100         247 :                         if ( pPortion->GetBulletX() > nCurWidth )
    3101           4 :                             nCurWidth = pPortion->GetBulletX();
    3102             :                     }
    3103             :                 }
    3104       50245 :                 nCurWidth += GetXValue( rLRItem.GetRight() );
    3105       50245 :                 nCurWidth += CalcLineWidth( pPortion, pLine, bIgnoreExtraSpace );
    3106       50245 :                 if ( nCurWidth > nMaxWidth )
    3107             :                 {
    3108       39236 :                     nMaxWidth = nCurWidth;
    3109             :                 }
    3110             :             }
    3111             :         }
    3112             :     }
    3113       45728 :     if ( nMaxWidth < 0 )
    3114           0 :         nMaxWidth = 0;
    3115             : 
    3116       45728 :     nMaxWidth++; // widen it, because in CreateLines for >= is wrapped.
    3117       45728 :     return (sal_uInt32)nMaxWidth;
    3118             : }
    3119             : 
    3120       50245 : sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, sal_Bool bIgnoreExtraSpace )
    3121             : {
    3122       50245 :     sal_Int32 nPara = GetEditDoc().GetPos( pPortion->GetNode() );
    3123             : 
    3124             :     // #114278# Saving both layout mode and language (since I'm
    3125             :     // potentially changing both)
    3126       50245 :     GetRefDevice()->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
    3127             : 
    3128       50245 :     ImplInitLayoutMode( GetRefDevice(), nPara, 0xFFFF );
    3129             : 
    3130       50245 :     SvxAdjust eJustification = GetJustification( nPara );
    3131             : 
    3132             :     // Calculation of the width without the Indents ...
    3133       50245 :     sal_uInt32 nWidth = 0;
    3134       50245 :     sal_uInt16 nPos = pLine->GetStart();
    3135      100606 :     for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
    3136             :     {
    3137       50361 :         const TextPortion* pTextPortion = pPortion->GetTextPortions()[nTP];
    3138       50361 :         switch ( pTextPortion->GetKind() )
    3139             :         {
    3140             :             case PORTIONKIND_FIELD:
    3141             :             case PORTIONKIND_HYPHENATOR:
    3142             :             case PORTIONKIND_TAB:
    3143             :             {
    3144         570 :                 nWidth += pTextPortion->GetSize().Width();
    3145             :             }
    3146         570 :             break;
    3147             :             case PORTIONKIND_TEXT:
    3148             :             {
    3149       49787 :                 if ( ( eJustification != SVX_ADJUST_BLOCK ) || ( !bIgnoreExtraSpace ) )
    3150             :                 {
    3151       49255 :                     nWidth += pTextPortion->GetSize().Width();
    3152             :                 }
    3153             :                 else
    3154             :                 {
    3155         532 :                     SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() );
    3156         532 :                     SeekCursor( pPortion->GetNode(), nPos+1, aTmpFont );
    3157         532 :                     aTmpFont.SetPhysFont( GetRefDevice() );
    3158         532 :                     ImplInitDigitMode(GetRefDevice(), aTmpFont.GetLanguage());
    3159         532 :                     nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), pPortion->GetNode()->GetString(), nPos, pTextPortion->GetLen(), NULL ).Width();
    3160             :                 }
    3161             :             }
    3162       49787 :             break;
    3163             :         }
    3164       50361 :         nPos = nPos + pTextPortion->GetLen();
    3165             :     }
    3166             : 
    3167       50245 :     GetRefDevice()->Pop();
    3168             : 
    3169       50245 :     return nWidth;
    3170             : }
    3171             : 
    3172          34 : sal_uInt32 ImpEditEngine::GetTextHeightNTP() const
    3173             : {
    3174             :     DBG_ASSERT( GetUpdateMode(), "Should not be used for Update=FALSE: GetTextHeight" );
    3175             :     DBG_ASSERT( IsFormatted() || IsFormatting(), "GetTextHeight: Not formatted" );
    3176          34 :     return nCurTextHeightNTP;
    3177             : }
    3178             : 
    3179      457261 : sal_uInt32 ImpEditEngine::CalcTextHeight( sal_uInt32* pHeightNTP )
    3180             : {
    3181             :     OSL_ENSURE( GetUpdateMode(), "Should not be used when Update=FALSE: CalcTextHeight" );
    3182      457261 :     sal_uInt32 nY = 0;
    3183             :     sal_uInt32 nPH;
    3184      457261 :     sal_uInt32 nEmptyHeight = 0;
    3185      920057 :     for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ ) {
    3186      462796 :         ParaPortion* pPortion = GetParaPortions()[nPortion];
    3187      462796 :         nPH = pPortion->GetHeight();
    3188      462796 :         nY += nPH;
    3189      462796 :         if( pHeightNTP ) {
    3190      462796 :             if ( pPortion->IsEmpty() )
    3191      323679 :                 nEmptyHeight += nPH;
    3192             :             else
    3193      139117 :                 nEmptyHeight = 0;
    3194             :         }
    3195             :     }
    3196             : 
    3197      457261 :     if ( pHeightNTP )
    3198      457261 :         *pHeightNTP = nY - nEmptyHeight;
    3199             : 
    3200      457261 :     return nY;
    3201             : }
    3202             : 
    3203           0 : sal_uInt16 ImpEditEngine::GetLineCount( sal_Int32 nParagraph ) const
    3204             : {
    3205             :     OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
    3206           0 :     const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph );
    3207             :     OSL_ENSURE( pPPortion, "Paragraph not found: GetLineCount" );
    3208           0 :     if ( pPPortion )
    3209           0 :         return pPPortion->GetLines().Count();
    3210             : 
    3211           0 :     return 0xFFFF;
    3212             : }
    3213             : 
    3214           0 : xub_StrLen ImpEditEngine::GetLineLen( sal_Int32 nParagraph, sal_uInt16 nLine ) const
    3215             : {
    3216             :     OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineLen: Out of range" );
    3217           0 :     const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph );
    3218             :     OSL_ENSURE( pPPortion, "Paragraph not found: GetLineLen" );
    3219           0 :     if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
    3220             :     {
    3221           0 :         const EditLine* pLine = pPPortion->GetLines()[nLine];
    3222             :         OSL_ENSURE( pLine, "Line not found: GetLineHeight" );
    3223           0 :         return pLine->GetLen();
    3224             :     }
    3225             : 
    3226           0 :     return 0xFFFF;
    3227             : }
    3228             : 
    3229           0 : void ImpEditEngine::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_Int32 nParagraph, sal_uInt16 nLine ) const
    3230             : {
    3231             :     OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
    3232           0 :     const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph );
    3233             :     OSL_ENSURE( pPPortion, "Paragraph not found: GetLineBoundaries" );
    3234           0 :     rStart = rEnd = 0xFFFF;     // default values in case of error
    3235           0 :     if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
    3236             :     {
    3237           0 :         const EditLine* pLine = pPPortion->GetLines()[nLine];
    3238             :         OSL_ENSURE( pLine, "Line not found: GetLineBoundaries" );
    3239           0 :         rStart = pLine->GetStart();
    3240           0 :         rEnd   = pLine->GetEnd();
    3241             :     }
    3242           0 : }
    3243             : 
    3244           0 : sal_uInt16 ImpEditEngine::GetLineNumberAtIndex( sal_Int32 nPara, sal_uInt16 nIndex ) const
    3245             : {
    3246           0 :     sal_uInt16 nLineNo = 0xFFFF;
    3247           0 :     const ContentNode* pNode = GetEditDoc().GetObject( nPara );
    3248             :     OSL_ENSURE( pNode, "GetLineNumberAtIndex: invalid paragraph index" );
    3249           0 :     if (pNode)
    3250             :     {
    3251             :         // we explicitly allow for the index to point at the character right behind the text
    3252           0 :         const bool bValidIndex = /*0 <= nIndex &&*/ nIndex <= pNode->Len();
    3253             :         OSL_ENSURE( bValidIndex, "GetLineNumberAtIndex: invalid index" );
    3254           0 :         const sal_uInt16 nLineCount = GetLineCount( nPara );
    3255           0 :         if (nIndex == pNode->Len())
    3256           0 :             nLineNo = nLineCount > 0 ? nLineCount - 1 : 0;
    3257           0 :         else if (bValidIndex)   // nIndex < pNode->Len()
    3258             :         {
    3259           0 :             sal_uInt16 nStart = USHRT_MAX, nEnd = USHRT_MAX;
    3260           0 :             for (sal_uInt16 i = 0;  i < nLineCount && nLineNo == 0xFFFF;  ++i)
    3261             :             {
    3262           0 :                 GetLineBoundaries( nStart, nEnd, nPara, i );
    3263           0 :                 if (nStart <= nIndex && nIndex < nEnd)
    3264           0 :                     nLineNo = i;
    3265             :             }
    3266             :         }
    3267             :     }
    3268           0 :     return nLineNo;
    3269             : }
    3270             : 
    3271           0 : sal_uInt16 ImpEditEngine::GetLineHeight( sal_Int32 nParagraph, sal_uInt16 nLine )
    3272             : {
    3273             :     OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
    3274           0 :     ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph );
    3275             :     OSL_ENSURE( pPPortion, "Paragraph not found: GetLineHeight" );
    3276           0 :     if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
    3277             :     {
    3278           0 :         const EditLine* pLine = pPPortion->GetLines()[nLine];
    3279             :         OSL_ENSURE( pLine, "Paragraph not found: GetLineHeight" );
    3280           0 :         return pLine->GetHeight();
    3281             :     }
    3282             : 
    3283           0 :     return 0xFFFF;
    3284             : }
    3285             : 
    3286         121 : sal_uInt32 ImpEditEngine::GetParaHeight( sal_Int32 nParagraph )
    3287             : {
    3288         121 :     sal_uInt32 nHeight = 0;
    3289             : 
    3290         121 :     ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph );
    3291             :     OSL_ENSURE( pPPortion, "Paragraph not found: GetParaHeight" );
    3292             : 
    3293         121 :     if ( pPPortion )
    3294         121 :         nHeight = pPPortion->GetHeight();
    3295             : 
    3296         121 :     return nHeight;
    3297             : }
    3298             : 
    3299         725 : void ImpEditEngine::UpdateSelections()
    3300             : {
    3301             :     // Check whether one of the selections is at a deleted node...
    3302             :     // If the node is valid, the index has yet to be examined!
    3303         739 :     for (size_t nView = 0; nView < aEditViews.size(); ++nView)
    3304             :     {
    3305          14 :         EditView* pView = aEditViews[nView];
    3306             :         DBG_CHKOBJ( pView, EditView, 0 );
    3307          14 :         EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
    3308          14 :         bool bChanged = false;
    3309          14 :         for (size_t i = 0, n = aDeletedNodes.size(); i < n; ++i)
    3310             :         {
    3311           0 :             const DeletedNodeInfo& rInf = aDeletedNodes[i];
    3312           0 :             if ( ( ( sal_uLong )(aCurSel.Min().GetNode()) == rInf.GetInvalidAdress() ) ||
    3313           0 :                  ( ( sal_uLong )(aCurSel.Max().GetNode()) == rInf.GetInvalidAdress() ) )
    3314             :             {
    3315             :                 // Use ParaPortions, as now also hidden paragraphs have to be
    3316             :                 // taken into account!
    3317           0 :                 sal_Int32 nPara = rInf.GetPosition();
    3318           0 :                 ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nPara );
    3319           0 :                 if ( !pPPortion ) // Last paragraph
    3320             :                 {
    3321           0 :                     nPara = GetParaPortions().Count()-1;
    3322           0 :                     pPPortion = GetParaPortions()[nPara];
    3323             :                 }
    3324             :                 OSL_ENSURE( pPPortion, "Empty Document in UpdateSelections ?" );
    3325             :                 // Do not end up from a hidden paragraph:
    3326           0 :                 sal_Int32 nCurPara = nPara;
    3327           0 :                 sal_Int32 nLastPara = GetParaPortions().Count()-1;
    3328           0 :                 while ( nPara <= nLastPara && !GetParaPortions()[nPara]->IsVisible() )
    3329           0 :                     nPara++;
    3330           0 :                 if ( nPara > nLastPara ) // then also backwards ...
    3331             :                 {
    3332           0 :                     nPara = nCurPara;
    3333           0 :                     while ( nPara && !GetParaPortions()[nPara]->IsVisible() )
    3334           0 :                         nPara--;
    3335             :                 }
    3336             :                 OSL_ENSURE( GetParaPortions()[nPara]->IsVisible(), "No visible paragraph found: UpdateSelections" );
    3337             : 
    3338           0 :                 ParaPortion* pParaPortion = GetParaPortions()[nPara];
    3339           0 :                 EditSelection aTmpSelection( EditPaM( pParaPortion->GetNode(), 0 ) );
    3340           0 :                 pView->pImpEditView->SetEditSelection( aTmpSelection );
    3341           0 :                 bChanged=sal_True;
    3342           0 :                 break;  // for loop
    3343             :             }
    3344             :         }
    3345          14 :         if ( !bChanged )
    3346             :         {
    3347             :             // Check Index if node shrunk.
    3348          14 :             if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() )
    3349             :             {
    3350           5 :                 aCurSel.Min().GetIndex() = aCurSel.Min().GetNode()->Len();
    3351           5 :                 pView->pImpEditView->SetEditSelection( aCurSel );
    3352             :             }
    3353          14 :             if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
    3354             :             {
    3355           6 :                 aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
    3356           6 :                 pView->pImpEditView->SetEditSelection( aCurSel );
    3357             :             }
    3358             :         }
    3359             :     }
    3360             : 
    3361         725 :     aDeletedNodes.clear();
    3362         725 : }
    3363             : 
    3364       24312 : EditSelection ImpEditEngine::ConvertSelection(
    3365             :     sal_Int32 nStartPara, sal_uInt16 nStartPos, sal_Int32 nEndPara, sal_uInt16 nEndPos )
    3366             : {
    3367       24312 :     EditSelection aNewSelection;
    3368             : 
    3369             :     // Start...
    3370       24312 :     ContentNode* pNode = aEditDoc.GetObject( nStartPara );
    3371       24312 :     sal_uInt16 nIndex = nStartPos;
    3372       24312 :     if ( !pNode )
    3373             :     {
    3374           0 :         pNode = aEditDoc[ aEditDoc.Count()-1 ];
    3375           0 :         nIndex = pNode->Len();
    3376             :     }
    3377       24312 :     else if ( nIndex > pNode->Len() )
    3378           1 :         nIndex = pNode->Len();
    3379             : 
    3380       24312 :     aNewSelection.Min().SetNode( pNode );
    3381       24312 :     aNewSelection.Min().SetIndex( nIndex );
    3382             : 
    3383             :     // End...
    3384       24312 :     pNode = aEditDoc.GetObject( nEndPara );
    3385       24312 :     nIndex = nEndPos;
    3386       24312 :     if ( !pNode )
    3387             :     {
    3388         264 :         pNode = aEditDoc[ aEditDoc.Count()-1 ];
    3389         264 :         nIndex = pNode->Len();
    3390             :     }
    3391       24048 :     else if ( nIndex > pNode->Len() )
    3392          67 :         nIndex = pNode->Len();
    3393             : 
    3394       24312 :     aNewSelection.Max().SetNode( pNode );
    3395       24312 :     aNewSelection.Max().SetIndex( nIndex );
    3396             : 
    3397       24312 :     return aNewSelection;
    3398             : }
    3399             : 
    3400         294 : void ImpEditEngine::SetActiveView( EditView* pView )
    3401             : {
    3402             :     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    3403             :     // Actually, now bHasVisSel and HideSelection would be necessary     !!!
    3404             : 
    3405         294 :     if ( pView == pActiveView )
    3406         294 :         return;
    3407             : 
    3408         294 :     if ( pActiveView && pActiveView->HasSelection() )
    3409           0 :         pActiveView->pImpEditView->DrawSelection();
    3410             : 
    3411         294 :     pActiveView = pView;
    3412             : 
    3413         294 :     if ( pActiveView && pActiveView->HasSelection() )
    3414           0 :         pActiveView->pImpEditView->DrawSelection();
    3415             : 
    3416             :     //  NN: Quick fix for #78668#:
    3417             :     //  When editing of a cell in Calc is ended, the edit engine is not deleted,
    3418             :     //  only the edit views are removed. If mpIMEInfos is still set in that case,
    3419             :     //  mpIMEInfos->aPos points to an invalid selection.
    3420             :     //  -> reset mpIMEInfos now
    3421             :     //  (probably something like this is necessary whenever the content is modified
    3422             :     //  from the outside)
    3423             : 
    3424         294 :     if ( !pView && mpIMEInfos )
    3425             :     {
    3426           0 :         delete mpIMEInfos;
    3427           0 :         mpIMEInfos = NULL;
    3428             :     }
    3429             : }
    3430             : 
    3431           0 : uno::Reference< datatransfer::XTransferable > ImpEditEngine::CreateTransferable( const EditSelection& rSelection )
    3432             : {
    3433           0 :     EditSelection aSelection( rSelection );
    3434           0 :     aSelection.Adjust( GetEditDoc() );
    3435             : 
    3436           0 :     EditDataObject* pDataObj = new EditDataObject;
    3437           0 :     uno::Reference< datatransfer::XTransferable > xDataObj;
    3438           0 :     xDataObj = pDataObj;
    3439             : 
    3440           0 :     XubString aText(convertLineEnd(GetSelected(aSelection), GetSystemLineEnd())); // System specific
    3441           0 :     pDataObj->GetString() = aText;
    3442             : 
    3443           0 :     SvxFontItem::EnableStoreUnicodeNames( sal_True );
    3444           0 :     WriteBin( pDataObj->GetStream(), aSelection, sal_True );
    3445           0 :     pDataObj->GetStream().Seek( 0 );
    3446           0 :     SvxFontItem::EnableStoreUnicodeNames( sal_False );
    3447             : 
    3448           0 :     ((ImpEditEngine*)this)->WriteRTF( pDataObj->GetRTFStream(), aSelection );
    3449           0 :     pDataObj->GetRTFStream().Seek( 0 );
    3450             : 
    3451           0 :     if ( ( aSelection.Min().GetNode() == aSelection.Max().GetNode() )
    3452           0 :             && ( aSelection.Max().GetIndex() == (aSelection.Min().GetIndex()+1) ) )
    3453             :     {
    3454           0 :         const EditCharAttrib* pAttr = aSelection.Min().GetNode()->GetCharAttribs().
    3455           0 :             FindFeature( aSelection.Min().GetIndex() );
    3456           0 :         if ( pAttr &&
    3457           0 :             ( pAttr->GetStart() == aSelection.Min().GetIndex() ) &&
    3458           0 :             ( pAttr->Which() == EE_FEATURE_FIELD ) )
    3459             :         {
    3460           0 :             const SvxFieldItem* pField = (const SvxFieldItem*)pAttr->GetItem();
    3461           0 :             const SvxFieldData* pFld = pField->GetField();
    3462           0 :             if ( pFld && pFld->ISA( SvxURLField ) )
    3463             :             {
    3464             :                 // Office-Bookmark
    3465           0 :                 String aURL( ((const SvxURLField*)pFld)->GetURL() );
    3466           0 :                 pDataObj->GetURL() = aURL;
    3467             :             }
    3468             :         }
    3469             :     }
    3470             : 
    3471           0 :     return xDataObj;
    3472             : }
    3473             : 
    3474           0 : EditSelection ImpEditEngine::InsertText( uno::Reference< datatransfer::XTransferable >& rxDataObj, const String& rBaseURL, const EditPaM& rPaM, sal_Bool bUseSpecial )
    3475             : {
    3476           0 :     EditSelection aNewSelection( rPaM );
    3477             : 
    3478           0 :     if ( rxDataObj.is() )
    3479             :     {
    3480           0 :         datatransfer::DataFlavor aFlavor;
    3481           0 :         sal_Bool bDone = sal_False;
    3482             : 
    3483           0 :         if ( bUseSpecial )
    3484             :         {
    3485             :             // BIN
    3486           0 :             SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EDITENGINE, aFlavor );
    3487           0 :             if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
    3488             :             {
    3489             :                 try
    3490             :                 {
    3491           0 :                     uno::Any aData = rxDataObj->getTransferData( aFlavor );
    3492           0 :                     uno::Sequence< sal_Int8 > aSeq;
    3493           0 :                     aData >>= aSeq;
    3494             :                     {
    3495           0 :                         SvMemoryStream aBinStream( aSeq.getArray(), aSeq.getLength(), STREAM_READ );
    3496           0 :                         aNewSelection = Read( aBinStream, rBaseURL, EE_FORMAT_BIN, rPaM );
    3497             :                     }
    3498           0 :                     bDone = sal_True;
    3499             :                 }
    3500           0 :                 catch( const ::com::sun::star::uno::Exception& )
    3501             :                 {
    3502             :                 }
    3503             :             }
    3504             : 
    3505           0 :             if ( !bDone )
    3506             :             {
    3507             :                 // RTF
    3508           0 :                 SotExchange::GetFormatDataFlavor( SOT_FORMAT_RTF, aFlavor );
    3509           0 :                 if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
    3510             :                 {
    3511             :                     try
    3512             :                     {
    3513           0 :                         uno::Any aData = rxDataObj->getTransferData( aFlavor );
    3514           0 :                         uno::Sequence< sal_Int8 > aSeq;
    3515           0 :                         aData >>= aSeq;
    3516             :                         {
    3517           0 :                             SvMemoryStream aRTFStream( aSeq.getArray(), aSeq.getLength(), STREAM_READ );
    3518           0 :                             aNewSelection = Read( aRTFStream, rBaseURL, EE_FORMAT_RTF, rPaM );
    3519             :                         }
    3520           0 :                         bDone = sal_True;
    3521             :                     }
    3522           0 :                     catch( const ::com::sun::star::uno::Exception& )
    3523             :                     {
    3524             :                     }
    3525             :                 }
    3526             :             }
    3527             :             if ( !bDone )
    3528             :             {
    3529             :                 // XML ?
    3530             :                 // Currently, there is nothing like "The" XML format, StarOffice doesn't offer plain XML in Clipboard...
    3531             :             }
    3532             :         }
    3533           0 :         if ( !bDone )
    3534             :         {
    3535           0 :             SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
    3536           0 :             if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
    3537             :             {
    3538             :                 try
    3539             :                 {
    3540           0 :                     uno::Any aData = rxDataObj->getTransferData( aFlavor );
    3541           0 :                     OUString aText;
    3542           0 :                     aData >>= aText;
    3543           0 :                     aNewSelection = ImpInsertText( rPaM, aText );
    3544           0 :                        bDone = sal_True;
    3545             :                 }
    3546           0 :                 catch( ... )
    3547             :                 {
    3548             :                     ; // #i9286# can happen, even if isDataFlavorSupported returns true...
    3549             :                 }
    3550             :             }
    3551           0 :         }
    3552             :     }
    3553             : 
    3554           0 :     return aNewSelection;
    3555             : }
    3556             : 
    3557      445767 : Range ImpEditEngine::GetInvalidYOffsets( ParaPortion* pPortion )
    3558             : {
    3559      445767 :     Range aRange( 0, 0 );
    3560             : 
    3561      445767 :     if ( pPortion->IsVisible() )
    3562             :     {
    3563      445767 :         const SvxULSpaceItem& rULSpace = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
    3564      445767 :         const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
    3565      445767 :         sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
    3566      445767 :                             ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
    3567             : 
    3568             :         // only from the top ...
    3569      445767 :         sal_uInt16 nFirstInvalid = 0xFFFF;
    3570             :         sal_uInt16 nLine;
    3571      445767 :         for ( nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
    3572             :         {
    3573      445767 :             const EditLine* pL = pPortion->GetLines()[nLine];
    3574      445767 :             if ( pL->IsInvalid() )
    3575             :             {
    3576      445767 :                 nFirstInvalid = nLine;
    3577      445767 :                 break;
    3578             :             }
    3579           0 :             if ( nLine && !aStatus.IsOutliner() )   // not the first line
    3580           0 :                 aRange.Min() += nSBL;
    3581           0 :             aRange.Min() += pL->GetHeight();
    3582             :         }
    3583             :         OSL_ENSURE( nFirstInvalid != 0xFFFF, "No invalid line found in GetInvalidYOffset(1)" );
    3584             : 
    3585             : 
    3586             :         // Syndicate and more ...
    3587      445767 :         aRange.Max() = aRange.Min();
    3588      445767 :         aRange.Max() += pPortion->GetFirstLineOffset();
    3589      445767 :         if ( nFirstInvalid != 0 )   // Only if the first line is invalid
    3590           0 :             aRange.Min() = aRange.Max();
    3591             : 
    3592      445767 :         sal_uInt16 nLastInvalid = pPortion->GetLines().Count()-1;
    3593      935866 :         for ( nLine = nFirstInvalid; nLine < pPortion->GetLines().Count(); nLine++ )
    3594             :         {
    3595      490099 :             const EditLine* pL = pPortion->GetLines()[nLine];
    3596      490099 :             if ( pL->IsValid() )
    3597             :             {
    3598           0 :                 nLastInvalid = nLine;
    3599           0 :                 break;
    3600             :             }
    3601             : 
    3602      490099 :             if ( nLine && !aStatus.IsOutliner() )
    3603       44332 :                 aRange.Max() += nSBL;
    3604      490099 :             aRange.Max() += pL->GetHeight();
    3605             :         }
    3606             : 
    3607      534242 :         if( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP ) && rLSItem.GetPropLineSpace() &&
    3608       88475 :             ( rLSItem.GetPropLineSpace() < 100 ) )
    3609             :         {
    3610         100 :             const EditLine* pL = pPortion->GetLines()[nFirstInvalid];
    3611         100 :             long n = pL->GetTxtHeight() * ( 100 - rLSItem.GetPropLineSpace() );
    3612         100 :             n /= 100;
    3613         100 :             aRange.Min() -= n;
    3614         100 :             aRange.Max() += n;
    3615             :         }
    3616             : 
    3617      445767 :         if ( ( nLastInvalid == pPortion->GetLines().Count()-1 ) && ( !aStatus.IsOutliner() ) )
    3618      445767 :             aRange.Max() += GetYValue( rULSpace.GetLower() );
    3619             :     }
    3620      445767 :     return aRange;
    3621             : }
    3622             : 
    3623          11 : EditPaM ImpEditEngine::GetPaM( ParaPortion* pPortion, Point aDocPos, sal_Bool bSmart )
    3624             : {
    3625             :     OSL_ENSURE( pPortion->IsVisible(), "Why GetPaM() for an invisible paragraph?" );
    3626             :     OSL_ENSURE( IsFormatted(), "GetPaM: Not formatted" );
    3627             : 
    3628          11 :     sal_uInt16 nCurIndex = 0;
    3629          11 :     EditPaM aPaM;
    3630          11 :     aPaM.SetNode( pPortion->GetNode() );
    3631             : 
    3632          11 :     const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
    3633          11 :     sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
    3634          11 :                         ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
    3635             : 
    3636          11 :     long nY = pPortion->GetFirstLineOffset();
    3637             : 
    3638             :     OSL_ENSURE( pPortion->GetLines().Count(), "Empty ParaPortion in GetPaM!" );
    3639             : 
    3640          11 :     const EditLine* pLine = NULL;
    3641          11 :     for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
    3642             :     {
    3643          11 :         const EditLine* pTmpLine = pPortion->GetLines()[nLine];
    3644          11 :         nY += pTmpLine->GetHeight();
    3645          11 :         if ( !aStatus.IsOutliner() )
    3646          11 :             nY += nSBL;
    3647          11 :         if ( nY > aDocPos.Y() )
    3648             :         {
    3649          11 :             pLine = pTmpLine;
    3650          11 :             break;                  // correct Y-position is not of interest
    3651             :         }
    3652             : 
    3653           0 :         nCurIndex = nCurIndex + pTmpLine->GetLen();
    3654             :     }
    3655             : 
    3656          11 :     if ( !pLine ) // may happen only in the range of SA!
    3657             :     {
    3658             : #if OSL_DEBUG_LEVEL > 0
    3659             :         const SvxULSpaceItem& rULSpace =(const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
    3660             :         OSL_ENSURE( nY+GetYValue( rULSpace.GetLower() ) >= aDocPos.Y() , "Index in no line, GetPaM ?" );
    3661             : #endif
    3662           0 :         aPaM.SetIndex( pPortion->GetNode()->Len() );
    3663           0 :         return aPaM;
    3664             :     }
    3665             : 
    3666             :     // If no line found, only just X-Position => Index
    3667          11 :     nCurIndex = GetChar( pPortion, pLine, aDocPos.X(), bSmart );
    3668          11 :     aPaM.SetIndex( nCurIndex );
    3669             : 
    3670          11 :     if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) &&
    3671           0 :          ( pLine != pPortion->GetLines()[pPortion->GetLines().Count()-1] ) )
    3672             :     {
    3673           0 :         aPaM = CursorLeft( aPaM, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL );
    3674             :     }
    3675             : 
    3676          11 :     return aPaM;
    3677             : }
    3678             : 
    3679          11 : sal_uInt16 ImpEditEngine::GetChar(
    3680             :     const ParaPortion* pParaPortion, const EditLine* pLine, long nXPos, bool bSmart)
    3681             : {
    3682             :     OSL_ENSURE( pLine, "No line received: GetChar" );
    3683             : 
    3684          11 :     sal_uInt16 nChar = 0xFFFF;
    3685          11 :     sal_uInt16 nCurIndex = pLine->GetStart();
    3686             : 
    3687             : 
    3688             :     // Search best matching portion with GetPortionXOffset()
    3689          22 :     for ( sal_uInt16 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ )
    3690             :     {
    3691          11 :         const TextPortion* pPortion = pParaPortion->GetTextPortions()[i];
    3692          11 :         long nXLeft = GetPortionXOffset( pParaPortion, pLine, i );
    3693          11 :         long nXRight = nXLeft + pPortion->GetSize().Width();
    3694          11 :         if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) )
    3695             :         {
    3696          10 :              nChar = nCurIndex;
    3697             : 
    3698             :             // Search within Portion...
    3699             : 
    3700             :             // Don't search within special portions...
    3701          10 :             if ( pPortion->GetKind() != PORTIONKIND_TEXT )
    3702             :             {
    3703             :                 // ...but check on which side
    3704           0 :                 if ( bSmart )
    3705             :                 {
    3706           0 :                     long nLeftDiff = nXPos-nXLeft;
    3707           0 :                     long nRightDiff = nXRight-nXPos;
    3708           0 :                     if ( nRightDiff < nLeftDiff )
    3709           0 :                         nChar++;
    3710             :                 }
    3711             :             }
    3712             :             else
    3713             :             {
    3714          10 :                 sal_uInt16 nMax = pPortion->GetLen();
    3715          10 :                 sal_uInt16 nOffset = 0xFFFF;
    3716          10 :                 sal_uInt16 nTmpCurIndex = nChar - pLine->GetStart();
    3717             : 
    3718          10 :                 long nXInPortion = nXPos - nXLeft;
    3719          10 :                 if ( pPortion->IsRightToLeft() )
    3720           0 :                     nXInPortion = nXRight - nXPos;
    3721             : 
    3722             :                 // Search in Array...
    3723          28 :                 for ( sal_uInt16 x = 0; x < nMax; x++ )
    3724             :                 {
    3725          28 :                     long nTmpPosMax = pLine->GetCharPosArray()[nTmpCurIndex+x];
    3726          28 :                     if ( nTmpPosMax > nXInPortion )
    3727             :                     {
    3728             :                         // Check whether this or the previous...
    3729          10 :                         long nTmpPosMin = x ? pLine->GetCharPosArray()[nTmpCurIndex+x-1] : 0;
    3730          10 :                         long nDiffLeft = nXInPortion - nTmpPosMin;
    3731          10 :                         long nDiffRight = nTmpPosMax - nXInPortion;
    3732             :                         OSL_ENSURE( nDiffLeft >= 0, "DiffLeft negative" );
    3733             :                         OSL_ENSURE( nDiffRight >= 0, "DiffRight negative" );
    3734          10 :                         nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x;
    3735             :                         // I18N: If there are character position with the length of 0,
    3736             :                         // they belong to the same character, we can not use this position as an index.
    3737             :                         // Skip all 0-positions, cheaper than using XBreakIterator:
    3738          10 :                         if ( nOffset < nMax )
    3739             :                         {
    3740          10 :                             const long nX = pLine->GetCharPosArray()[nOffset];
    3741          20 :                             while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray()[nOffset+1] == nX ) )
    3742           0 :                                 nOffset++;
    3743             :                         }
    3744          10 :                         break;
    3745             :                     }
    3746             :                 }
    3747             : 
    3748             :                 // There should not be any inaccuracies when using the
    3749             :                 // CharPosArray! Maybe for kerning?
    3750             :                 // 0xFFF happens for example for Outline-Font when at the very end.
    3751          10 :                 if ( nOffset == 0xFFFF )
    3752           0 :                     nOffset = nMax;
    3753             : 
    3754             :                 OSL_ENSURE( nOffset <= nMax, "nOffset > nMax" );
    3755             : 
    3756          10 :                 nChar = nChar + nOffset;
    3757             : 
    3758             :                 // Check if index is within a cell:
    3759          10 :                 if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) )
    3760             :                 {
    3761           7 :                     EditPaM aPaM( pParaPortion->GetNode(), nChar+1 );
    3762           7 :                     sal_uInt16 nScriptType = GetScriptType( aPaM );
    3763           7 :                     if ( nScriptType == i18n::ScriptType::COMPLEX )
    3764             :                     {
    3765           0 :                         uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
    3766           0 :                         sal_Int32 nCount = 1;
    3767           0 :                         lang::Locale aLocale = GetLocale( aPaM );
    3768           0 :                         sal_uInt16 nRight = (sal_uInt16)_xBI->nextCharacters(
    3769           0 :                             pParaPortion->GetNode()->GetString(), nChar, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
    3770           0 :                         sal_uInt16 nLeft = (sal_uInt16)_xBI->previousCharacters(
    3771           0 :                             pParaPortion->GetNode()->GetString(), nRight, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
    3772           0 :                         if ( ( nLeft != nChar ) && ( nRight != nChar ) )
    3773             :                         {
    3774           0 :                             nChar = ( std::abs( nRight - nChar ) < std::abs( nLeft - nChar ) ) ? nRight : nLeft;
    3775           0 :                         }
    3776             :                     }
    3777             :                 }
    3778             :             }
    3779             :         }
    3780             : 
    3781          11 :         nCurIndex = nCurIndex + pPortion->GetLen();
    3782             :     }
    3783             : 
    3784          11 :     if ( nChar == 0xFFFF )
    3785             :     {
    3786           1 :         nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd();
    3787             :     }
    3788             : 
    3789          11 :     return nChar;
    3790             : }
    3791             : 
    3792           4 : Range ImpEditEngine::GetLineXPosStartEnd( const ParaPortion* pParaPortion, const EditLine* pLine ) const
    3793             : {
    3794           4 :     Range aLineXPosStartEnd;
    3795             : 
    3796           4 :     sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
    3797           4 :     if ( !IsRightToLeft( nPara ) )
    3798             :     {
    3799           4 :         aLineXPosStartEnd.Min() = pLine->GetStartPosX();
    3800           4 :         aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth();
    3801             :     }
    3802             :     else
    3803             :     {
    3804           0 :         aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() );
    3805           0 :         aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX();
    3806             :     }
    3807             : 
    3808             : 
    3809           4 :     return aLineXPosStartEnd;
    3810             : }
    3811             : 
    3812       12981 : long ImpEditEngine::GetPortionXOffset(
    3813             :     const ParaPortion* pParaPortion, const EditLine* pLine, sal_uInt16 nTextPortion) const
    3814             : {
    3815       12981 :     long nX = pLine->GetStartPosX();
    3816             : 
    3817       13123 :     for ( sal_uInt16 i = pLine->GetStartPortion(); i < nTextPortion; i++ )
    3818             :     {
    3819         142 :         const TextPortion* pPortion = pParaPortion->GetTextPortions()[i];
    3820         142 :         switch ( pPortion->GetKind() )
    3821             :         {
    3822             :             case PORTIONKIND_FIELD:
    3823             :             case PORTIONKIND_TEXT:
    3824             :             case PORTIONKIND_HYPHENATOR:
    3825             :             case PORTIONKIND_TAB:
    3826             :             {
    3827         142 :                 nX += pPortion->GetSize().Width();
    3828             :             }
    3829         142 :             break;
    3830             :         }
    3831             :     }
    3832             : 
    3833       12981 :     sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
    3834       12981 :     sal_Bool bR2LPara = IsRightToLeft( nPara );
    3835             : 
    3836       12981 :     const TextPortion* pDestPortion = pParaPortion->GetTextPortions()[nTextPortion];
    3837       12981 :     if ( pDestPortion->GetKind() != PORTIONKIND_TAB )
    3838             :     {
    3839       12981 :         if ( !bR2LPara && pDestPortion->GetRightToLeft() )
    3840             :         {
    3841             :             // Portions behind must be added, visual before this portion
    3842           0 :             sal_uInt16 nTmpPortion = nTextPortion+1;
    3843           0 :             while ( nTmpPortion <= pLine->GetEndPortion() )
    3844             :             {
    3845           0 :                 const TextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
    3846           0 :                 if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
    3847           0 :                     nX += pNextTextPortion->GetSize().Width();
    3848             :                 else
    3849           0 :                     break;
    3850           0 :                 nTmpPortion++;
    3851             :             }
    3852             :             // Portions before must be removed, visual behind this portion
    3853           0 :             nTmpPortion = nTextPortion;
    3854           0 :             while ( nTmpPortion > pLine->GetStartPortion() )
    3855             :             {
    3856           0 :                 --nTmpPortion;
    3857           0 :                 const TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
    3858           0 :                 if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
    3859           0 :                     nX -= pPrevTextPortion->GetSize().Width();
    3860             :                 else
    3861           0 :                     break;
    3862             :             }
    3863             :         }
    3864       12981 :         else if ( bR2LPara && !pDestPortion->IsRightToLeft() )
    3865             :         {
    3866             :             // Portions behind must be removed, visual behind this portion
    3867         636 :             sal_uInt16 nTmpPortion = nTextPortion+1;
    3868        1272 :             while ( nTmpPortion <= pLine->GetEndPortion() )
    3869             :             {
    3870           0 :                 const TextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
    3871           0 :                 if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
    3872           0 :                     nX += pNextTextPortion->GetSize().Width();
    3873             :                 else
    3874           0 :                     break;
    3875           0 :                 nTmpPortion++;
    3876             :             }
    3877             :             // Portions before must be added, visual before this portion
    3878         636 :             nTmpPortion = nTextPortion;
    3879        1272 :             while ( nTmpPortion > pLine->GetStartPortion() )
    3880             :             {
    3881           0 :                 --nTmpPortion;
    3882           0 :                 const TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
    3883           0 :                 if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
    3884           0 :                     nX -= pPrevTextPortion->GetSize().Width();
    3885             :                 else
    3886           0 :                     break;
    3887             :             }
    3888             :         }
    3889             :     }
    3890       12981 :     if ( bR2LPara )
    3891             :     {
    3892             :         // Switch X postions...
    3893             :         OSL_ENSURE( GetTextRanger() || GetPaperSize().Width(), "GetPortionXOffset - paper size?!" );
    3894             :         OSL_ENSURE( GetTextRanger() || (nX <= GetPaperSize().Width()), "GetPortionXOffset - position out of paper size!" );
    3895         636 :         nX = GetPaperSize().Width() - nX;
    3896         636 :         nX -= pDestPortion->GetSize().Width();
    3897             :     }
    3898             : 
    3899       12981 :     return nX;
    3900             : }
    3901             : 
    3902         956 : long ImpEditEngine::GetXPos(
    3903             :     const ParaPortion* pParaPortion, const EditLine* pLine, sal_uInt16 nIndex, bool bPreferPortionStart) const
    3904             : {
    3905             :     OSL_ENSURE( pLine, "No line received: GetXPos" );
    3906             :     OSL_ENSURE( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "GetXPos has to be called properly!" );
    3907             : 
    3908         956 :     sal_Bool bDoPreferPortionStart = bPreferPortionStart;
    3909             :     // Assure that the portion belongs to this line:
    3910         956 :     if ( nIndex == pLine->GetStart() )
    3911         796 :         bDoPreferPortionStart = sal_True;
    3912         160 :     else if ( nIndex == pLine->GetEnd() )
    3913         110 :         bDoPreferPortionStart = sal_False;
    3914             : 
    3915         956 :     sal_uInt16 nTextPortionStart = 0;
    3916         956 :     sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart );
    3917             : 
    3918             :     OSL_ENSURE( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " );
    3919             : 
    3920         956 :     const TextPortion* pPortion = pParaPortion->GetTextPortions()[nTextPortion];
    3921             : 
    3922         956 :     long nX = GetPortionXOffset( pParaPortion, pLine, nTextPortion );
    3923             : 
    3924             :     // calc text width, portion size may include CJK/CTL spacing...
    3925             :     // But the array migh not be init yet, if using text ranger this method is called within CreateLines()...
    3926         956 :     long nPortionTextWidth = pPortion->GetSize().Width();
    3927         956 :     if ( ( pPortion->GetKind() == PORTIONKIND_TEXT ) && pPortion->GetLen() && !GetTextRanger() )
    3928         256 :         nPortionTextWidth = pLine->GetCharPosArray()[nTextPortionStart + pPortion->GetLen() - 1 - pLine->GetStart()];
    3929             : 
    3930         956 :     if ( nTextPortionStart != nIndex )
    3931             :     {
    3932             :         // Search within portion...
    3933         160 :         if ( nIndex == ( nTextPortionStart + pPortion->GetLen() ) )
    3934             :         {
    3935             :             // End of Portion
    3936         110 :             if ( pPortion->GetKind() == PORTIONKIND_TAB )
    3937             :             {
    3938           0 :                 if ( static_cast<size_t>(nTextPortion+1) < pParaPortion->GetTextPortions().Count() )
    3939             :                 {
    3940           0 :                     const TextPortion* pNextPortion = pParaPortion->GetTextPortions()[nTextPortion+1];
    3941           0 :                     if ( pNextPortion->GetKind() != PORTIONKIND_TAB )
    3942             :                     {
    3943           0 :                         if ( !bPreferPortionStart )
    3944           0 :                             nX = GetXPos( pParaPortion, pLine, nIndex, sal_True );
    3945           0 :                         else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
    3946           0 :                             nX += nPortionTextWidth;
    3947             :                     }
    3948             :                 }
    3949           0 :                 else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
    3950             :                 {
    3951           0 :                     nX += nPortionTextWidth;
    3952             :                 }
    3953             :             }
    3954         110 :             else if ( !pPortion->IsRightToLeft() )
    3955             :             {
    3956         110 :                 nX += nPortionTextWidth;
    3957             :             }
    3958             :         }
    3959          50 :         else if ( pPortion->GetKind() == PORTIONKIND_TEXT )
    3960             :         {
    3961             :             OSL_ENSURE( nIndex != pLine->GetStart(), "Strange behavior in new GetXPos()" );
    3962             :             OSL_ENSURE( pLine && pLine->GetCharPosArray().size(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" );
    3963             : 
    3964          50 :             if( pLine->GetCharPosArray().size() )
    3965             :             {
    3966          50 :                 sal_uInt16 nPos = nIndex - 1 - pLine->GetStart();
    3967          50 :                 if( nPos >= pLine->GetCharPosArray().size() )
    3968             :                 {
    3969           0 :                     nPos = pLine->GetCharPosArray().size()-1;
    3970             :                     OSL_FAIL("svx::ImpEditEngine::GetXPos(), index out of range!");
    3971             :                 }
    3972             : 
    3973             :                 // old code restored see #i112788 (which leaves #i74188 unfixed again)
    3974          50 :                 long nPosInPortion = pLine->GetCharPosArray()[nPos];
    3975             : 
    3976          50 :                 if ( !pPortion->IsRightToLeft() )
    3977             :                 {
    3978          50 :                     nX += nPosInPortion;
    3979             :                 }
    3980             :                 else
    3981             :                 {
    3982           0 :                     nX += nPortionTextWidth - nPosInPortion;
    3983             :                 }
    3984             : 
    3985          50 :                 if ( pPortion->GetExtraInfos() && pPortion->GetExtraInfos()->bCompressed )
    3986             :                 {
    3987           0 :                     nX += pPortion->GetExtraInfos()->nPortionOffsetX;
    3988           0 :                     if ( pPortion->GetExtraInfos()->nAsianCompressionTypes & CHAR_PUNCTUATIONRIGHT )
    3989             :                     {
    3990           0 :                         sal_uInt8 nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex ) );
    3991           0 :                         if ( nType == CHAR_PUNCTUATIONRIGHT )
    3992             :                         {
    3993           0 :                             sal_uInt16 n = nIndex - nTextPortionStart;
    3994           0 :                             const sal_Int32* pDXArray = NULL;
    3995           0 :                             if (!pLine->GetCharPosArray().empty())
    3996           0 :                                 pDXArray = &pLine->GetCharPosArray()[0]+( nTextPortionStart-pLine->GetStart() );
    3997           0 :                             sal_Int32 nCharWidth = ( ( (n+1) < pPortion->GetLen() ) ? pDXArray[n] : pPortion->GetSize().Width() )
    3998           0 :                                                             - ( n ? pDXArray[n-1] : 0 );
    3999           0 :                             if ( (n+1) < pPortion->GetLen() )
    4000             :                             {
    4001             :                                 // smaller, when char behind is CHAR_PUNCTUATIONRIGHT also
    4002           0 :                                 nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex+1 ) );
    4003           0 :                                 if ( nType == CHAR_PUNCTUATIONRIGHT )
    4004             :                                 {
    4005           0 :                                     sal_Int32 nNextCharWidth = ( ( (n+2) < pPortion->GetLen() ) ? pDXArray[n+1] : pPortion->GetSize().Width() )
    4006           0 :                                                                     - pDXArray[n];
    4007           0 :                                     sal_Int32 nCompressed = nNextCharWidth/2;
    4008           0 :                                     nCompressed *= pPortion->GetExtraInfos()->nMaxCompression100thPercent;
    4009           0 :                                     nCompressed /= 10000;
    4010           0 :                                     nCharWidth += nCompressed;
    4011             :                                 }
    4012             :                             }
    4013             :                             else
    4014             :                             {
    4015           0 :                                 nCharWidth *= 2;    // last char pos to portion end is only compressed size
    4016             :                             }
    4017           0 :                             nX += nCharWidth/2; // 50% compression
    4018             :                         }
    4019             :                     }
    4020             :                 }
    4021             :             }
    4022             :         }
    4023             :     }
    4024             :     else // if ( nIndex == pLine->GetStart() )
    4025             :     {
    4026         796 :         if ( pPortion->IsRightToLeft() )
    4027             :         {
    4028           0 :             nX += nPortionTextWidth;
    4029             :         }
    4030             :     }
    4031             : 
    4032         956 :     return nX;
    4033             : }
    4034             : 
    4035      451057 : void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
    4036             : {
    4037      451057 :     pPortion->nHeight = 0;
    4038      451057 :     pPortion->nFirstLineOffset = 0;
    4039             : 
    4040      451057 :     if ( pPortion->IsVisible() )
    4041             :     {
    4042             :         OSL_ENSURE( pPortion->GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight" );
    4043      948815 :         for (size_t nLine = 0; nLine < pPortion->GetLines().Count(); ++nLine)
    4044      497758 :             pPortion->nHeight += pPortion->GetLines()[nLine]->GetHeight();
    4045             : 
    4046      451057 :         if ( !aStatus.IsOutliner() )
    4047             :         {
    4048      451057 :             const SvxULSpaceItem& rULItem = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
    4049      451057 :             const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
    4050      451057 :             sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
    4051             : 
    4052      451057 :             if ( nSBL )
    4053             :             {
    4054         531 :                 if ( pPortion->GetLines().Count() > 1 )
    4055         293 :                     pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL;
    4056         531 :                 if ( aStatus.ULSpaceSummation() )
    4057           0 :                     pPortion->nHeight += nSBL;
    4058             :             }
    4059             : 
    4060      451057 :             sal_Int32 nPortion = GetParaPortions().GetPos( pPortion );
    4061      451057 :             if ( nPortion || aStatus.ULSpaceFirstParagraph() )
    4062             :             {
    4063        5089 :                 sal_uInt16 nUpper = GetYValue( rULItem.GetUpper() );
    4064        5089 :                 pPortion->nHeight += nUpper;
    4065        5089 :                 pPortion->nFirstLineOffset = nUpper;
    4066             :             }
    4067             : 
    4068      451057 :             if ( ( nPortion != (GetParaPortions().Count()-1) ) )
    4069             :             {
    4070        5152 :                 pPortion->nHeight += GetYValue( rULItem.GetLower() );   // not in the last
    4071             :             }
    4072             : 
    4073             : 
    4074      451057 :             if ( nPortion && !aStatus.ULSpaceSummation() )
    4075             :             {
    4076        5077 :                 ParaPortion* pPrev = GetParaPortions().SafeGetObject( nPortion-1 );
    4077        5077 :                 const SvxULSpaceItem& rPrevULItem = (const SvxULSpaceItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
    4078        5077 :                 const SvxLineSpacingItem& rPrevLSItem = (const SvxLineSpacingItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
    4079             : 
    4080             :                 // In realation between WinWord6/Writer3:
    4081             :                 // With a proportional line spacing the paragraph spacing is
    4082             :                 // also manipulated.
    4083             :                 // Only Writer3: Do not add up, but minimum distance.
    4084             : 
    4085             :                 // check if distance by LineSpacing > Upper:
    4086        5077 :                 sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPortion, rLSItem ) );
    4087        5077 :                 if ( nExtraSpace > pPortion->nFirstLineOffset )
    4088             :                 {
    4089             :                     // Paragraph becomes 'bigger':
    4090         269 :                     pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
    4091         269 :                     pPortion->nFirstLineOffset = nExtraSpace;
    4092             :                 }
    4093             : 
    4094             :                 // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev):
    4095        5077 :                 sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() );
    4096             : 
    4097             :                 // This PrevLower is still in the height of PrevPortion ...
    4098        5077 :                 if ( nPrevLower > pPortion->nFirstLineOffset )
    4099             :                 {
    4100             :                     // Paragraph is 'small':
    4101        1028 :                     pPortion->nHeight -= pPortion->nFirstLineOffset;
    4102        1028 :                     pPortion->nFirstLineOffset = 0;
    4103             :                 }
    4104        4049 :                 else if ( nPrevLower )
    4105             :                 {
    4106             :                     // Paragraph becomes 'somewhat smaller':
    4107         384 :                     pPortion->nHeight -= nPrevLower;
    4108             :                     pPortion->nFirstLineOffset =
    4109         384 :                         pPortion->nFirstLineOffset - nPrevLower;
    4110             :                 }
    4111             :                 // I find it not so good, but Writer3 feature:
    4112             :                 // Check if distance by LineSpacing > Lower: this value is not
    4113             :                 // stuck in the height of PrevPortion.
    4114        5077 :                 if ( !pPrev->IsInvalid() )
    4115             :                 {
    4116        4858 :                     nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPrev, rPrevLSItem ) );
    4117        4858 :                     if ( nExtraSpace > nPrevLower )
    4118             :                     {
    4119         342 :                         sal_uInt16 nMoreLower = nExtraSpace - nPrevLower;
    4120             :                         // Paragraph becomes 'bigger', 'grows' downwards:
    4121         342 :                         if ( nMoreLower > pPortion->nFirstLineOffset )
    4122             :                         {
    4123          90 :                             pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
    4124          90 :                             pPortion->nFirstLineOffset = nMoreLower;
    4125             :                         }
    4126             :                     }
    4127             :                 }
    4128             :             }
    4129             :         }
    4130             :     }
    4131      451057 : }
    4132             : 
    4133         944 : Rectangle ImpEditEngine::GetEditCursor( ParaPortion* pPortion, sal_uInt16 nIndex, sal_uInt16 nFlags )
    4134             : {
    4135             :     OSL_ENSURE( pPortion->IsVisible(), "Why GetEditCursor() for an invisible paragraph?" );
    4136             :     OSL_ENSURE( IsFormatted() || GetTextRanger(), "GetEditCursor: Not formatted" );
    4137             : 
    4138             :     /*
    4139             :      GETCRSR_ENDOFLINE: If after the last character of a wrapped line, remaining
    4140             :      at the end of the line, not the beginning of the next one.
    4141             :      Purpose:   - END => really after the last character
    4142             :                 - Selection....
    4143             :     */
    4144             : 
    4145         944 :     long nY = pPortion->GetFirstLineOffset();
    4146             : 
    4147         944 :     const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
    4148         944 :     sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
    4149         944 :                         ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
    4150             : 
    4151         944 :     sal_uInt16 nCurIndex = 0;
    4152             :     OSL_ENSURE( pPortion->GetLines().Count(), "Empty ParaPortion in GetEditCursor!" );
    4153         944 :     const EditLine* pLine = NULL;
    4154         944 :     sal_Bool bEOL = ( nFlags & GETCRSR_ENDOFLINE ) ? sal_True : sal_False;
    4155        1052 :     for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
    4156             :     {
    4157         944 :         const EditLine* pTmpLine = pPortion->GetLines()[nLine];
    4158         944 :         if ( ( pTmpLine->GetStart() == nIndex ) || ( pTmpLine->IsIn( nIndex, bEOL ) ) )
    4159             :         {
    4160         836 :             pLine = pTmpLine;
    4161         836 :             break;
    4162             :         }
    4163             : 
    4164         108 :         nCurIndex = nCurIndex + pTmpLine->GetLen();
    4165         108 :         nY += pTmpLine->GetHeight();
    4166         108 :         if ( !aStatus.IsOutliner() )
    4167         108 :             nY += nSBL;
    4168             :     }
    4169         944 :     if ( !pLine )
    4170             :     {
    4171             :         // Cursor at the End of the paragraph.
    4172             :         OSL_ENSURE( nIndex == nCurIndex, "Index dead wrong in GetEditCursor!" );
    4173             : 
    4174         108 :         pLine = pPortion->GetLines()[pPortion->GetLines().Count()-1];
    4175         108 :         nY -= pLine->GetHeight();
    4176         108 :         if ( !aStatus.IsOutliner() )
    4177         108 :             nY -= nSBL;
    4178         108 :         nCurIndex = nCurIndex - pLine->GetLen();
    4179             :     }
    4180             : 
    4181         944 :     Rectangle aEditCursor;
    4182             : 
    4183         944 :     aEditCursor.Top() = nY;
    4184         944 :     nY += pLine->GetHeight();
    4185         944 :     aEditCursor.Bottom() = nY-1;
    4186             : 
    4187             :     // Search within the line...
    4188             :     long nX;
    4189             : 
    4190         944 :     if ( ( nIndex == pLine->GetStart() ) && ( nFlags & GETCRSR_STARTOFLINE ) )
    4191             :     {
    4192           0 :         Range aXRange = GetLineXPosStartEnd( pPortion, pLine );
    4193           0 :         nX = !IsRightToLeft( GetEditDoc().GetPos( pPortion->GetNode() ) ) ? aXRange.Min() : aXRange.Max();
    4194             :     }
    4195         944 :     else if ( ( nIndex == pLine->GetEnd() ) && ( nFlags & GETCRSR_ENDOFLINE ) )
    4196             :     {
    4197           4 :         Range aXRange = GetLineXPosStartEnd( pPortion, pLine );
    4198           4 :         nX = !IsRightToLeft( GetEditDoc().GetPos( pPortion->GetNode() ) ) ? aXRange.Max() : aXRange.Min();
    4199             :     }
    4200             :     else
    4201             :     {
    4202         940 :         nX = GetXPos( pPortion, pLine, nIndex, ( nFlags & GETCRSR_PREFERPORTIONSTART ) ? sal_True : sal_False );
    4203             :     }
    4204             : 
    4205         944 :     aEditCursor.Left() = aEditCursor.Right() = nX;
    4206             : 
    4207         944 :     if ( nFlags & GETCRSR_TXTONLY )
    4208         936 :         aEditCursor.Top() = aEditCursor.Bottom() - pLine->GetTxtHeight() + 1;
    4209             :     else
    4210           8 :         aEditCursor.Top() = aEditCursor.Bottom() - std::min( pLine->GetTxtHeight(), pLine->GetHeight() ) + 1;
    4211             : 
    4212         944 :     return aEditCursor;
    4213             : }
    4214             : 
    4215      556695 : void ImpEditEngine::SetValidPaperSize( const Size& rNewSz )
    4216             : {
    4217      556695 :     aPaperSize = rNewSz;
    4218             : 
    4219      556695 :     long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0;
    4220      556695 :     long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF;
    4221      556695 :     long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0;
    4222      556695 :     long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF;
    4223             : 
    4224             :     // Minimum/Maximum width:
    4225      556695 :     if ( aPaperSize.Width() < nMinWidth )
    4226        3875 :         aPaperSize.Width() = nMinWidth;
    4227      552820 :     else if ( aPaperSize.Width() > nMaxWidth )
    4228          37 :         aPaperSize.Width() = nMaxWidth;
    4229             : 
    4230             :     // Minimum/Maximum height:
    4231      556695 :     if ( aPaperSize.Height() < nMinHeight )
    4232           0 :         aPaperSize.Height() = nMinHeight;
    4233      556695 :     else if ( aPaperSize.Height() > nMaxHeight )
    4234        5087 :         aPaperSize.Height() = nMaxHeight;
    4235      556695 : }
    4236             : 
    4237           0 : void ImpEditEngine::IndentBlock( EditView* pEditView, sal_Bool bRight )
    4238             : {
    4239           0 :     ESelection aESel( CreateESel( pEditView->pImpEditView->GetEditSelection() ) );
    4240           0 :     aESel.Adjust();
    4241             : 
    4242             :     // Only if more selected Paragraphs ...
    4243           0 :     if ( aESel.nEndPara > aESel.nStartPara )
    4244             :     {
    4245           0 :         ESelection aNewSel = aESel;
    4246           0 :         aNewSel.nStartPos = 0;
    4247           0 :         aNewSel.nEndPos = EE_TEXTPOS_ALL;
    4248             : 
    4249           0 :         if ( aESel.nEndPos == 0 )
    4250             :         {
    4251           0 :             aESel.nEndPara--;       // then not this paragraph ...
    4252           0 :             aNewSel.nEndPos = 0;
    4253             :         }
    4254             : 
    4255           0 :         pEditView->pImpEditView->DrawSelection();
    4256             :         pEditView->pImpEditView->SetEditSelection(
    4257           0 :                         pEditView->pImpEditView->GetEditSelection().Max() );
    4258           0 :         UndoActionStart( bRight ? EDITUNDO_INDENTBLOCK : EDITUNDO_UNINDENTBLOCK );
    4259             : 
    4260           0 :         for ( sal_Int32 nPara = aESel.nStartPara; nPara <= aESel.nEndPara; nPara++ )
    4261             :         {
    4262           0 :             ContentNode* pNode = GetEditDoc().GetObject( nPara );
    4263           0 :             if ( bRight )
    4264             :             {
    4265             :                 // Insert Tabs
    4266           0 :                 EditPaM aPaM( pNode, 0 );
    4267           0 :                 InsertTab( aPaM );
    4268             :             }
    4269             :             else
    4270             :             {
    4271             :                 // Remove Tabs
    4272           0 :                 const EditCharAttrib* pFeature = pNode->GetCharAttribs().FindFeature( 0 );
    4273           0 :                 if ( pFeature && ( pFeature->GetStart() == 0 ) &&
    4274           0 :                    ( pFeature->GetItem()->Which() == EE_FEATURE_TAB ) )
    4275             :                 {
    4276           0 :                     EditPaM aStartPaM( pNode, 0 );
    4277           0 :                     EditPaM aEndPaM( pNode, 1 );
    4278           0 :                     ImpDeleteSelection( EditSelection( aStartPaM, aEndPaM ) );
    4279             :                 }
    4280             :             }
    4281             :         }
    4282             : 
    4283           0 :         UndoActionEnd( bRight ? EDITUNDO_INDENTBLOCK : EDITUNDO_UNINDENTBLOCK );
    4284           0 :         UpdateSelections();
    4285           0 :         FormatAndUpdate( pEditView );
    4286             : 
    4287           0 :         ContentNode* pLastNode = GetEditDoc().GetObject( aNewSel.nEndPara );
    4288           0 :         if ( pLastNode->Len() < aNewSel.nEndPos )
    4289           0 :             aNewSel.nEndPos = pLastNode->Len();
    4290           0 :         pEditView->pImpEditView->SetEditSelection( CreateSel( aNewSel ) );
    4291           0 :         pEditView->pImpEditView->DrawSelection();
    4292           0 :         pEditView->pImpEditView->ShowCursor( sal_False, sal_True );
    4293             :     }
    4294           0 : }
    4295             : 
    4296       50431 : rtl::Reference<SvxForbiddenCharactersTable> ImpEditEngine::GetForbiddenCharsTable( sal_Bool bGetInternal ) const
    4297             : {
    4298       50431 :     rtl::Reference<SvxForbiddenCharactersTable> xF = xForbiddenCharsTable;
    4299       50431 :     if ( !xF.is() && bGetInternal )
    4300       50431 :         xF = EE_DLL().GetGlobalData()->GetForbiddenCharsTable();
    4301       50431 :     return xF;
    4302             : }
    4303             : 
    4304       25151 : void ImpEditEngine::SetForbiddenCharsTable( rtl::Reference<SvxForbiddenCharactersTable> xForbiddenChars )
    4305             : {
    4306       25151 :     EE_DLL().GetGlobalData()->SetForbiddenCharsTable( xForbiddenChars );
    4307       25151 : }
    4308             : 
    4309        9496 : svtools::ColorConfig& ImpEditEngine::GetColorConfig()
    4310             : {
    4311        9496 :     if ( !pColorConfig )
    4312         324 :         pColorConfig = new svtools::ColorConfig;
    4313             : 
    4314        9496 :     return *pColorConfig;
    4315             : }
    4316             : 
    4317           0 : sal_Bool ImpEditEngine::IsVisualCursorTravelingEnabled()
    4318             : {
    4319           0 :     sal_Bool bVisualCursorTravaling = sal_False;
    4320             : 
    4321           0 :     if( !pCTLOptions )
    4322           0 :         pCTLOptions = new SvtCTLOptions;
    4323             : 
    4324           0 :     if ( pCTLOptions->IsCTLFontEnabled() && ( pCTLOptions->GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) )
    4325             :     {
    4326           0 :         bVisualCursorTravaling = sal_True;
    4327             :     }
    4328             : 
    4329           0 :     return bVisualCursorTravaling;
    4330             : 
    4331             : }
    4332             : 
    4333           0 : sal_Bool ImpEditEngine::DoVisualCursorTraveling( const ContentNode* )
    4334             : {
    4335             :     // Don't check if it's necessary, because we also need it when leaving the paragraph
    4336           0 :     return IsVisualCursorTravelingEnabled();
    4337             : }
    4338             : 
    4339             : 
    4340         621 : void ImpEditEngine::CallNotify( EENotify& rNotify )
    4341             : {
    4342         621 :     if ( !nBlockNotifications )
    4343         510 :         GetNotifyHdl().Call( &rNotify );
    4344             :     else
    4345         111 :         aNotifyCache.push_back(rNotify);
    4346         621 : }
    4347             : 
    4348      879976 : void ImpEditEngine::EnterBlockNotifications()
    4349             : {
    4350      879976 :     if( !nBlockNotifications )
    4351             :     {
    4352             :         // #109864# Send out START notification immediately, to allow
    4353             :         // external, non-queued events to be captured as well from
    4354             :         // client side
    4355      667428 :         EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_START );
    4356      667428 :         aNotify.pEditEngine = GetEditEnginePtr();
    4357      667428 :         GetNotifyHdl().Call( &aNotify );
    4358             :     }
    4359             : 
    4360      879976 :     nBlockNotifications++;
    4361      879976 : }
    4362             : 
    4363      879976 : void ImpEditEngine::LeaveBlockNotifications()
    4364             : {
    4365             :     OSL_ENSURE( nBlockNotifications, "LeaveBlockNotifications - Why?" );
    4366             : 
    4367      879976 :     nBlockNotifications--;
    4368      879976 :     if ( !nBlockNotifications )
    4369             :     {
    4370             :         // Call blocked notify events...
    4371     1334967 :         while(!aNotifyCache.empty())
    4372             :         {
    4373         111 :             EENotify aNotify(aNotifyCache[0]);
    4374             :             // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
    4375         111 :             aNotifyCache.erase(aNotifyCache.begin());
    4376         111 :             GetNotifyHdl().Call( &aNotify );
    4377             :         }
    4378             : 
    4379      667428 :         EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_END );
    4380      667428 :         aNotify.pEditEngine = GetEditEnginePtr();
    4381      667428 :         GetNotifyHdl().Call( &aNotify );
    4382             :     }
    4383      879976 : }
    4384             : 
    4385     2206820 : IMPL_LINK_NOARG(ImpEditEngine, DocModified)
    4386             : {
    4387     1103410 :     aModifyHdl.Call( NULL /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner
    4388     1103410 :     return 0;
    4389         267 : }
    4390             : 
    4391             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10