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

Generated by: LCOV version 1.10