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

Generated by: LCOV version 1.11