summaryrefslogtreecommitdiff
path: root/binfilter/bf_svx/source/editeng/svx_impedit2.cxx
diff options
context:
space:
mode:
authorBjoern Michaelsen <bjoern.michaelsen@canonical.com>2011-08-23 15:10:15 +0200
committerBjoern Michaelsen <bjoern.michaelsen@canonical.com>2011-08-23 15:10:15 +0200
commit5c22c7b613228daf8f46baf70928ae7da6485289 (patch)
tree75ae8ba4d004cdfbf539762aa8fd819d4760b56a /binfilter/bf_svx/source/editeng/svx_impedit2.cxx
parent62479cc5aa788ddebf9fa23e0124a0dc2495426c (diff)
recreated tag libreoffice-3.3.1.1 which had these commits:
commit 1163151cf51a15a68700eda522ba7a789e378361 (tag: refs/tags/libreoffice-3.3.1.1) Author: Petr Mladek <pmladek@suse.cz> Date: Tue Feb 8 18:07:43 2011 +0100 Version 3.3.1.1, tag libreoffice-3.3.1.1 (3.3.1-rc1) commit 3d8f2d6ee7f86ec048ffca70a7dd59efb64ab90c Author: Jan Holesovsky <kendy@suse.cz> Date: Mon Feb 7 21:23:24 2011 +0100 Branch libreoffice-3-3-1 This is 'libreoffice-3-3-1' - the stable branch for the 3.3.1 release. Only very safe changes, reviewed by three people are allowed. If you want to commit more complicated fix for the next 3.3.x release, please use the 'libreoffice-3-3' branch. If you want to build something cool, unstable, and risky, use master. commit 4d86423be75125185f7e220877839c68934bfedc Author: Joseph Powers <jpowers27@cox.net> Date: Mon Feb 7 16:32:57 2011 +0000 cherry picked from 0679158ebb6c84863e6e0e2fe877ea06eba4a2d4 Move XServiceInfo.hpp from DEBUG to main. Now that XServiceInfo is always used, it would be nice to always include if defination. This fixes a compile error on mac. PS: Also some trailing white space. The changed code all appears at the top of the patch. Signed-off-by: Noel Power <noel.power@novell.com> writerfilter/source/dmapper/DomainMapper_Impl.cxx | 144 ++++++++++---------- 1 files changed, 72 insertions(+), 72 deletions(-) commit 8efa2697b2a2737ee5951358878a17203073ac49 Author: Noel Power <noel.power@novell.com> Date: Mon Feb 7 12:01:46 2011 +0000 fix for bnc#655763 cherry picked from ae5d018c49d3ab61416cde7fb09c37bcce7d9566 reviewed in bug https://bugzilla.novell.com/show_bug.cgi?id=655763#c6 Signed-off-by: Cedric Bosdonnat <cbosdonnat@novell.com> writerfilter/source/dmapper/DomainMapper_Impl.cxx | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) commit 780535edc21bc230a859d672b7408f10e2691a38 Author: Petr Mladek <pmladek@suse.cz> Date: Wed Feb 2 17:09:03 2011 +0100 RTF export crasher (bnc#656503) Signed off by Cedric filter/source/msfilter/escherex.cxx | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) commit ecda6f3b42d84e88d35d4d6bd4ea5cc32b9b8c89 Author: Takeshi Kurosawa <taken.spc@gmail.com> Date: Thu Jan 27 14:31:57 2011 +0900 Use product name for EPS Creator header (cherry picked from commit 2d07f1d678dc868687a9ae8c326b766e7def21c2) Signed-off-by: Thorsten Behrens <tbehrens@novell.com> filter/source/graphicfilter/eps/eps.cxx | 16 +++++++++++++++- filter/source/graphicfilter/eps/makefile.mk | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) commit dd73734f0440787d84ddbe5737e7f996803dacf2 Author: Takeshi Kurosawa <taken.spc@gmail.com> Date: Thu Jan 27 13:45:16 2011 +0900 Parse 'color' property (fdo#33551) Parse 'color' property and store the value as currentColor. (cherry picked from commit d4bac116d0c35d8811a048fdd991363a32df14ca) Signed-off-by: Thorsten Behrens <tbehrens@novell.com> filter/source/svg/svgreader.cxx | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) commit 9a7fcfcf49e393c02e8d115dfa4a40811582375f Author: Fridrich Štrba <fridrich.strba@bluewin.ch> Date: Sun Jan 30 10:22:38 2011 +0100 Use double instead of float (cherry picked from commit c90c5d503543a960a05b43752a5dff9ccf4bcd30) Signed-off-by: Caolán McNamara <caolanm@redhat.com> writerperfect/source/filter/DocumentCollector.cxx | 2 +- writerperfect/source/filter/DocumentCollector.hxx | 2 +- writerperfect/source/filter/FilterInternal.hxx | 6 +++--- writerperfect/source/filter/ListStyle.cxx | 12 ++++++------ writerperfect/source/filter/SectionStyle.cxx | 2 +- writerperfect/source/filter/TextRunStyle.cxx | 6 +++--- writerperfect/source/filter/WriterProperties.hxx | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) commit 9fd267985820db81454cce1b4a76752769b471b7 Author: Thomas Klausner <wiz@NetBSD.org> Date: Sat Nov 6 00:30:42 2010 +0100 Use PYTHON as passed through by set_soenv.in. filter/source/config/fragments/makefile.mk | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) commit 82102abd307f911c400735eb6f9b43fa69d221d8 Author: Noel Power <noel.power@novell.com> Date: Tue Jan 18 12:58:17 2011 +0000 fdo#33237 remove debug line writerfilter/source/dmapper/DomainMapper_Impl.cxx | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) commit 9c976ba4f8e1fd2bcd40412873e22728ed83d5bd Author: Noel Power <noel.power@novell.com> Date: Tue Jan 18 12:43:50 2011 +0000 fdo#33237# fix ole object import for writer (docx) writerfilter/source/dmapper/DomainMapper_Impl.cxx | 41 +++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-) commit 8383f008c60c0615005f4bb22ae9ddaeca4540cf Author: Fridrich Štrba <fridrich.strba@bluewin.ch> Date: Tue Jan 18 11:12:52 2011 +0100 Fix a typo SolarMuexGuard -> SolarMutexGuard signoff: Jan Holesovsky <kendy@suse.cz> signoff: Thorsten Behrens <thb@documentfoundation.org> signoff: Tor Lillqvist <tlillqvist@novell.com> signoff: Petr Mladek <pmladek@suse.cz> binfilter/bf_so3/source/ole/socli.cxx | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) commit 247a91f1df71614fc8d9b2264d10f0952055c611 Author: Petr Mladek <pmladek@suse.cz> Date: Tue Jan 11 23:05:56 2011 +0100 Please, ignore the previous message; it was for the libreoffice-3-3-0 branch This is 'libreoffice-3-3' - the stable branch for the 3.3.x releases. Only safe changes, reviewed by anoter person are allowed. If you want to build something cool, unstable, and risky, use master. commit 9628deac573830fdfbce2c402f8574379ac71a35 Author: Petr Mladek <pmladek@suse.cz> Date: Tue Jan 11 22:39:07 2011 +0100 Branch libreoffice-3-3-0 This is 'libreoffice-3-3-0' - the stable branch for the 3.3.0 release. Only very safe changes, reviewed by three people are allowed. If you want to commit more complicated fix for the next 3.3.x release, please use the 'libreoffice-3-3' branch. If you want to build something cool, unstable, and risky, use master.
Notes
split repo tag: filters_libreoffice-3.3.1.1 split repo tag: filters_libreoffice-3.3.1.2
Diffstat (limited to 'binfilter/bf_svx/source/editeng/svx_impedit2.cxx')
-rw-r--r--binfilter/bf_svx/source/editeng/svx_impedit2.cxx2084
1 files changed, 2084 insertions, 0 deletions
diff --git a/binfilter/bf_svx/source/editeng/svx_impedit2.cxx b/binfilter/bf_svx/source/editeng/svx_impedit2.cxx
new file mode 100644
index 000000000000..794864bfb27a
--- /dev/null
+++ b/binfilter/bf_svx/source/editeng/svx_impedit2.cxx
@@ -0,0 +1,2084 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+
+#include "eeitem.hxx"
+#include "eeitemid.hxx"
+
+#include <lspcitem.hxx>
+
+
+
+#include "itemdata.hxx"
+
+#include <tools/date.hxx>
+
+#include <tools/time.hxx>
+
+
+
+
+#include <vcl/window.hxx>
+
+#include <impedit.hxx>
+#include <editeng.hxx>
+#include <editview.hxx>
+#include <eerdll2.hxx>
+#include <eerdll.hxx>
+#include <txtrange.hxx>
+#include <bf_svtools/colorcfg.hxx>
+#include <bf_svtools/ctloptions.hxx>
+
+#include <lrspitem.hxx>
+#include <ulspitem.hxx>
+#include <adjitem.hxx>
+#include <scripttypeitem.hxx>
+#include <frmdiritem.hxx>
+
+
+
+
+#include <vcl/cmdevt.h>
+
+#ifndef SVX_LIGHT
+#endif
+
+
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+#include <com/sun/star/text/CharacterCompressionType.hpp>
+
+
+
+#include <unicode/ubidi.h>
+namespace binfilter {
+
+#if defined(MACOSX) && ( __GNUC__ < 3 )
+// moved from editundo.hxx
+const EPaM& EditUndoRemoveChars::GetEPaM() { return aEPaM; }
+String& EditUndoRemoveChars::GetStr() { return aText; }
+#endif
+
+using namespace ::com::sun::star;
+
+/*N*/ USHORT lcl_CalcExtraSpace( ParaPortion* pPortion, const SvxLineSpacingItem& rLSItem )
+/*N*/ {
+/*N*/ USHORT nExtra = 0;
+ /* if ( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ && ( rLSItem.GetPropLineSpace() != 100 ) )
+ {
+ // ULONG nH = pPortion->GetNode()->GetCharAttribs().GetDefFont().GetSize().Height();
+ ULONG nH = pPortion->GetLines().GetObject( 0 )->GetHeight();
+ long n = nH * rLSItem.GetPropLineSpace();
+ n /= 100;
+ n -= nH; // nur den Abstand
+ if ( n > 0 )
+ nExtra = (USHORT)n;
+ }
+ else */
+/*N*/ if ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+/*N*/ {
+/*?*/ nExtra = rLSItem.GetInterLineSpace();
+/*N*/ }
+/*N*/
+/*N*/ return nExtra;
+/*N*/ }
+
+ // ----------------------------------------------------------------------
+// class ImpEditEngine
+// ----------------------------------------------------------------------
+
+/*N*/ ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) :
+/*N*/ aEditDoc( pItemPool ),
+/*N*/ aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
+/*N*/ aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
+/*N*/ aMinAutoPaperSize( 0x0, 0x0 ),
+/*N*/ aGroupChars( RTL_CONSTASCII_USTRINGPARAM( "{}()[]" ) ),
+/*N*/ aWordDelimiters( RTL_CONSTASCII_USTRINGPARAM( " .,;:-'`'?!_=\"{}()[]\0xFF" ) )
+/*N*/ {
+/*N*/ pEditEngine = pEE;
+/*N*/ pRefDev = NULL;
+/*N*/ pVirtDev = NULL;
+/*N*/ pEmptyItemSet = NULL;
+/*N*/ pActiveView = NULL;
+/*N*/ pTextObjectPool = NULL;
+/*N*/ mpIMEInfos = NULL;
+/*N*/ pStylePool = NULL;
+/*N*/ pUndoManager = NULL;
+/*N*/ pUndoMarkSelection = NULL;
+/*N*/ pTextRanger = NULL;
+/*N*/ pColorConfig = NULL;
+/*N*/ pCTLOptions = NULL;
+/*N*/
+/*N*/ nCurTextHeight = 0;
+/*N*/ nBlockNotifications = 0;
+/*N*/ nBigTextObjectStart = 20;
+/*N*/
+/*N*/ nStretchX = 100;
+/*N*/ nStretchY = 100;
+/*N*/
+/*N*/ bInSelection = FALSE;
+/*N*/ bOwnerOfRefDev = FALSE;
+/*N*/ bDowning = FALSE;
+/*N*/ bIsInUndo = FALSE;
+/*N*/ bIsFormatting = FALSE;
+/*N*/ bFormatted = FALSE;
+/*N*/ bUpdate = TRUE;
+/*N*/ bUseAutoColor = TRUE;
+/*N*/ bForceAutoColor = FALSE;
+/*N*/ #ifndef SVX_LIGHT
+/*N*/ bUndoEnabled = TRUE;
+/*N*/ #else
+/*N*/ bUndoEnabled = FALSE;
+/*N*/ #endif
+/*N*/ bCallParaInsertedOrDeleted = FALSE;
+/*N*/
+/*N*/ eDefLanguage = LANGUAGE_DONTKNOW;
+/*N*/ maBackgroundColor = COL_AUTO;
+/*N*/
+/*N*/ nAsianCompressionMode = text::CharacterCompressionType::NONE;
+/*N*/ bKernAsianPunctuation = FALSE;
+/*N*/
+/*N*/ eDefaultHorizontalTextDirection = EE_HTEXTDIR_DEFAULT;
+/*N*/
+/*N*/
+/*N*/ aStatus.GetControlWord() = EE_CNTRL_USECHARATTRIBS | EE_CNTRL_DOIDLEFORMAT |
+/*N*/ EE_CNTRL_PASTESPECIAL | EE_CNTRL_UNDOATTRIBS |
+/*N*/ EE_CNTRL_ALLOWBIGOBJS | EE_CNTRL_RTFSTYLESHEETS |
+/*N*/ EE_CNTRL_FORMAT100;
+/*N*/
+/*N*/ aSelEngine.SetFunctionSet( &aSelFuncSet );
+/*N*/
+/*N*/ pRefDev = EE_DLL()->GetGlobalData()->GetStdRefDevice();
+/*N*/
+/*N*/ // Ab hier wird schon auf Daten zugegriffen!
+/*N*/ SetRefDevice( pRefDev );
+/*N*/ InitDoc( FALSE );
+/*N*/
+/*N*/ bCallParaInsertedOrDeleted = TRUE;
+/*N*/
+/*N*/ }
+
+/*N*/ ImpEditEngine::~ImpEditEngine()
+/*N*/ {
+/*N*/ // das Zerstoeren von Vorlagen kann sonst unnoetiges Formatieren ausloesen,
+/*N*/ // wenn eine Parent-Vorlage zerstoert wird.
+/*N*/ // Und das nach dem Zerstoeren der Daten!
+/*N*/ bDowning = TRUE;
+/*N*/ SetUpdateMode( FALSE );
+/*N*/
+/*N*/ delete pVirtDev;
+/*N*/ delete pEmptyItemSet;
+/*N*/ delete pUndoManager;
+/*N*/ delete pTextRanger;
+/*N*/ delete mpIMEInfos;
+/*N*/ delete pColorConfig;
+/*N*/ delete pCTLOptions;
+/*N*/ if ( bOwnerOfRefDev )
+/*N*/ delete pRefDev;
+/*N*/ }
+
+/*N*/ void ImpEditEngine::SetRefDevice( OutputDevice* pRef )
+/*N*/ {
+/*N*/ if ( bOwnerOfRefDev )
+/*N*/ delete pRefDev;
+/*N*/
+/*N*/ pRefDev = pRef;
+/*N*/ bOwnerOfRefDev = FALSE;
+/*N*/
+/*N*/ if ( !pRef )
+/*N*/ pRefDev = EE_DLL()->GetGlobalData()->GetStdRefDevice();
+/*N*/
+/*N*/ nOnePixelInRef = (USHORT)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
+/*N*/
+/*N*/ if ( IsFormatted() )
+/*N*/ {
+/*N*/ FormatFullDoc();
+/*N*/ UpdateViews( (EditView*) 0);
+/*N*/ }
+/*N*/ }
+
+/*N*/ void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode )
+/*N*/ {
+/*N*/ if ( GetRefDevice()->GetMapMode() == rMapMode )
+/*N*/ return;
+/*N*/
+/*N*/ // Wenn RefDev == GlobalRefDev => eigenes anlegen!
+/*N*/ if ( !bOwnerOfRefDev && ( pRefDev == EE_DLL()->GetGlobalData()->GetStdRefDevice() ) )
+/*N*/ {
+/*N*/ pRefDev = new VirtualDevice;
+/*N*/ pRefDev->SetMapMode( MAP_TWIP );
+/*N*/ SetRefDevice( pRefDev );
+/*N*/ bOwnerOfRefDev = TRUE;
+/*N*/ }
+/*N*/ pRefDev->SetMapMode( rMapMode );
+/*N*/ nOnePixelInRef = (USHORT)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
+/*N*/ if ( IsFormatted() )
+/*N*/ {
+/*N*/ FormatFullDoc();
+/*N*/ UpdateViews( (EditView*) 0);
+/*N*/ }
+/*N*/ }
+
+/*N*/ void ImpEditEngine::InitDoc( BOOL bKeepParaAttribs )
+/*N*/ {
+/*N*/ USHORT nParas = aEditDoc.Count();
+/*N*/ for ( USHORT n = bKeepParaAttribs ? 1 : 0; n < nParas; n++ )
+/*N*/ {
+/*N*/ if ( aEditDoc[n]->GetStyleSheet() )
+/*N*/ EndListening( *aEditDoc[n]->GetStyleSheet(), FALSE );
+/*N*/ }
+/*N*/
+/*N*/ if ( bKeepParaAttribs )
+/*N*/ aEditDoc.RemoveText();
+/*N*/ else
+/*N*/ aEditDoc.Clear();
+/*N*/
+/*N*/ GetParaPortions().Reset();
+/*N*/
+/*N*/ ParaPortion* pIniPortion = new ParaPortion( aEditDoc[0] );
+/*N*/ GetParaPortions().Insert( pIniPortion, 0 );
+/*N*/
+/*N*/ bFormatted = FALSE;
+/*N*/
+/*N*/ if ( IsCallParaInsertedOrDeleted() )
+/*N*/ {
+/*N*/ GetEditEnginePtr()->ParagraphDeleted( EE_PARA_ALL );
+/*N*/ GetEditEnginePtr()->ParagraphInserted( 0 );
+/*N*/ }
+/*N*/ }
+
+
+/*N*/ XubString ImpEditEngine::GetSelected( const EditSelection& rSel, const LineEnd eEnd ) const
+/*N*/ {
+/*N*/ XubString aText;
+/*N*/ if ( !rSel.HasRange() )
+/*N*/ return aText;
+/*N*/
+/*N*/ String aSep = EditDoc::GetSepStr( eEnd );
+/*N*/
+/*N*/ EditSelection aSel( rSel );
+/*N*/ aSel.Adjust( aEditDoc );
+/*N*/
+/*N*/ ContentNode* pStartNode = aSel.Min().GetNode();
+/*N*/ ContentNode* pEndNode = aSel.Max().GetNode();
+/*N*/ USHORT nStartNode = aEditDoc.GetPos( pStartNode );
+/*N*/ USHORT nEndNode = aEditDoc.GetPos( pEndNode );
+/*N*/
+/*N*/ DBG_ASSERT( nStartNode <= nEndNode, "Selektion nicht sortiert ?" );
+/*N*/
+/*N*/ // ueber die Absaetze iterieren...
+/*N*/ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+/*N*/ {
+/*N*/ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetSelected" );
+/*N*/ ContentNode* pNode = aEditDoc.GetObject( nNode );
+/*N*/
+/*N*/ xub_StrLen nStartPos = 0;
+/*N*/ xub_StrLen nEndPos = pNode->Len();
+/*N*/ if ( nNode == nStartNode )
+/*N*/ nStartPos = aSel.Min().GetIndex();
+/*N*/ if ( nNode == nEndNode ) // kann auch == nStart sein!
+/*N*/ nEndPos = aSel.Max().GetIndex();
+/*N*/
+/*N*/ aText += aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
+/*N*/ if ( nNode < nEndNode )
+/*N*/ aText += aSep;
+/*N*/ }
+/*N*/ return aText;
+/*N*/ }
+
+
+
+
+
+
+/*N*/ EditPaM ImpEditEngine::Clear()
+/*N*/ {
+/*N*/ InitDoc( FALSE );
+/*N*/
+/*N*/ EditPaM aPaM = aEditDoc.GetStartPaM();
+/*N*/ EditSelection aSel( aPaM );
+/*N*/
+/*N*/ nCurTextHeight = 0;
+/*N*/
+/*N*/ ResetUndoManager();
+/*N*/
+/*N*/ for ( USHORT nView = aEditViews.Count(); nView; )
+/*N*/ {
+/*?*/ EditView* pView = aEditViews[--nView];
+/*?*/ DBG_CHKOBJ( pView, EditView, 0 );
+/*?*/ pView->pImpEditView->SetEditSelection( aSel );
+/*N*/ }
+/*N*/
+/*N*/ return aPaM;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::RemoveText()
+/*N*/ {
+/*N*/ InitDoc( TRUE );
+/*N*/
+/*N*/ EditPaM aStartPaM = aEditDoc.GetStartPaM();
+/*N*/ EditSelection aEmptySel( aStartPaM, aStartPaM );
+/*N*/ for ( USHORT nView = 0; nView < aEditViews.Count(); nView++ )
+/*N*/ {
+/*N*/ EditView* pView = aEditViews.GetObject(nView);
+/*N*/ DBG_CHKOBJ( pView, EditView, 0 );
+/*N*/ pView->pImpEditView->SetEditSelection( aEmptySel );
+/*N*/ }
+/*N*/ ResetUndoManager();
+/*N*/ return aEditDoc.GetStartPaM();
+/*N*/ }
+
+
+/*N*/ void ImpEditEngine::SetText( const XubString& rText )
+/*N*/ {
+/*N*/ // RemoveText loescht die Undo-Liste!
+/*N*/ EditPaM aStartPaM = RemoveText();
+/*N*/ BOOL bUndoCurrentlyEnabled = IsUndoEnabled();
+/*N*/ // Der von Hand reingesteckte Text kann nicht vom Anwender rueckgaengig gemacht werden.
+/*N*/ EnableUndo( FALSE );
+/*N*/
+/*N*/ EditSelection aEmptySel( aStartPaM, aStartPaM );
+/*N*/ EditPaM aPaM = aStartPaM;
+/*N*/ if ( rText.Len() )
+/*N*/ aPaM = ImpInsertText( aEmptySel, rText );
+/*N*/
+/*N*/ for ( USHORT nView = 0; nView < aEditViews.Count(); nView++ )
+/*N*/ {
+/*N*/ EditView* pView = aEditViews[nView];
+/*N*/ DBG_CHKOBJ( pView, EditView, 0 );
+/*N*/ pView->pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) );
+/*N*/ // Wenn kein Text, dann auch Kein Format&Update
+/*N*/ // => Der Text bleibt stehen.
+/*N*/ if ( !rText.Len() && GetUpdateMode() )
+/*N*/ {
+/*?*/ Rectangle aTmpRec( pView->GetOutputArea().TopLeft(),
+/*?*/ Size( aPaperSize.Width(), nCurTextHeight ) );
+/*?*/ aTmpRec.Intersection( pView->GetOutputArea() );
+/*?*/ pView->GetWindow()->Invalidate( aTmpRec );
+/*N*/ }
+/*N*/ }
+/*N*/ if( !rText.Len() ) // sonst muss spaeter noch invalidiert werden, !bFormatted reicht.
+/*N*/ nCurTextHeight = 0;
+/*N*/ EnableUndo( bUndoCurrentlyEnabled );
+/*N*/ #ifndef SVX_LIGHT
+/*N*/ DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo nach SetText?" );
+/*N*/ #endif
+/*N*/ }
+
+
+/*N*/ const SfxItemSet& ImpEditEngine::GetEmptyItemSet()
+/*N*/ {
+/*N*/ if ( !pEmptyItemSet )
+/*N*/ {
+/*N*/ pEmptyItemSet = new SfxItemSet( aEditDoc.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END );
+/*N*/ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
+/*N*/ {
+/*N*/ pEmptyItemSet->ClearItem( nWhich );
+/*N*/ }
+/*N*/ }
+/*N*/ return *pEmptyItemSet;
+/*N*/ }
+
+// ----------------------------------------------------------------------
+// MISC
+// ----------------------------------------------------------------------
+/*N*/ void ImpEditEngine::CursorMoved( ContentNode* pPrevNode )
+/*N*/ {
+/*N*/ // Leere Attribute loeschen, aber nur, wenn Absatz nicht leer!
+/*N*/ if ( pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len() )
+/*?*/ {DBG_BF_ASSERT(0, "STRIP");} //STRIP001 pPrevNode->GetCharAttribs().DeleteEmptyAttribs( aEditDoc.GetItemPool() );
+/*N*/ }
+
+/*N*/ void ImpEditEngine::TextModified()
+/*N*/ {
+/*N*/ bFormatted = FALSE;
+/*N*/
+/*N*/ if ( GetNotifyHdl().IsSet() )
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); //STRIP001 EENotify aNotify( EE_NOTIFY_TEXTMODIFIED );
+/*N*/ }
+/*N*/ }
+
+
+/*N*/ void ImpEditEngine::ParaAttribsChanged( ContentNode* pNode )
+/*N*/ {
+/*N*/ DBG_ASSERT( pNode, "ParaAttribsChanged: Welcher?" );
+/*N*/
+/*N*/ aEditDoc.SetModified( TRUE );
+/*N*/ bFormatted = FALSE;
+/*N*/
+/*N*/ ParaPortion* pPortion = FindParaPortion( pNode );
+/*N*/ DBG_ASSERT( pPortion, "ParaAttribsChanged: Portion?" );
+/*N*/ pPortion->MarkSelectionInvalid( 0, pNode->Len() );
+/*N*/
+/*N*/ USHORT nPara = aEditDoc.GetPos( pNode );
+/*N*/ pEditEngine->ParaAttribsChanged( nPara );
+/*N*/
+/*N*/ ParaPortion* pNextPortion = GetParaPortions().SaveGetObject( nPara+1 );
+/*N*/ // => wird sowieso noch formatiert, wenn Invalid.
+/*N*/ if ( pNextPortion && !pNextPortion->IsInvalid() )
+/*?*/ CalcHeight( pNextPortion );
+/*N*/ }
+
+// ----------------------------------------------------------------------
+// Cursorbewegungen
+// ----------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*N*/ EditPaM ImpEditEngine::WordRight( const EditPaM& rPaM, sal_Int16 nWordType )
+/*N*/ {
+/*N*/ xub_StrLen nMax = rPaM.GetNode()->Len();
+/*N*/ EditPaM aNewPaM( rPaM );
+/*N*/ if ( aNewPaM.GetIndex() < nMax )
+/*N*/ {
+/*N*/ uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
+/*N*/ i18n::Boundary aBoundary = xBI->nextWord( *aNewPaM.GetNode(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nWordType );
+/*N*/ aNewPaM.SetIndex( (USHORT)aBoundary.startPos );
+/*N*/ }
+/*N*/ // not 'else', maybe the index reached nMax now...
+/*N*/ if ( aNewPaM.GetIndex() >= nMax )
+/*N*/ {
+/*?*/ // Naechster Absatz...
+/*?*/ USHORT nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
+/*?*/ ContentNode* pNextNode = aEditDoc.SaveGetObject( ++nCurPara );
+/*?*/ if ( pNextNode )
+/*?*/ {
+/*?*/ aNewPaM.SetNode( pNextNode );
+/*?*/ aNewPaM.SetIndex( 0 );
+/*?*/ }
+/*N*/ }
+/*N*/ return aNewPaM;
+/*N*/ }
+
+
+
+/*N*/ EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, BOOL bAcceptStartOfWord )
+/*N*/ {
+/*N*/ EditSelection aNewSel( rCurSel );
+/*N*/ EditPaM aPaM( rCurSel.Max() );
+/*N*/ uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
+/*N*/ sal_Int16 nType = xBI->getWordType( *aPaM.GetNode(), aPaM.GetIndex(), GetLocale( aPaM ) );
+/*N*/ if ( nType == i18n::WordType::ANY_WORD )
+/*N*/ {
+/*N*/ i18n::Boundary aBoundary = xBI->getWordBoundary( *aPaM.GetNode(), aPaM.GetIndex(), GetLocale( aPaM ), nWordType, sal_True );
+/*N*/ // don't select when curser at end of word
+/*N*/ if ( ( aBoundary.endPos > aPaM.GetIndex() ) &&
+/*N*/ ( bAcceptStartOfWord || ( aBoundary.startPos < aPaM.GetIndex() ) ) )
+/*N*/ {
+/*N*/ aNewSel.Min().SetIndex( (USHORT)aBoundary.startPos );
+/*N*/ aNewSel.Max().SetIndex( (USHORT)aBoundary.endPos );
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ return aNewSel;
+/*N*/ }
+
+/*N*/ void ImpEditEngine::InitScriptTypes( USHORT nPara )
+/*N*/ {
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+/*N*/ rTypes.Remove( 0, rTypes.Count() );
+/*N*/
+/*N*/
+/*N*/ // pParaPortion->aExtraCharInfos.Remove( 0, pParaPortion->aExtraCharInfos.Count() );
+/*N*/
+/*N*/ ContentNode* pNode = pParaPortion->GetNode();
+/*N*/ if ( pNode->Len() )
+/*N*/ {
+/*N*/ uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
+/*N*/
+/*N*/ String aText( *pNode );
+/*N*/
+/*N*/ // To handle fields put the character from the field in the string,
+/*N*/ // because endOfScript( ... ) will skip the CH_FEATURE, because this is WEAK
+/*N*/ EditCharAttrib* pField = pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, 0 );
+/*N*/ while ( pField )
+/*N*/ {
+/*N*/ ::rtl::OUString aFldText( ((EditCharAttribField*)pField)->GetFieldValue() );
+/*N*/ if ( aFldText.getLength() )
+/*N*/ {
+/*N*/ aText.SetChar( pField->GetStart(), aFldText.getStr()[0] );
+/*N*/ short nFldScriptType = xBI->getScriptType( aFldText, 0 );
+/*N*/
+/*N*/ for ( USHORT nCharInField = 1; nCharInField < aFldText.getLength(); nCharInField++ )
+/*N*/ {
+/*N*/ short nTmpType = xBI->getScriptType( aFldText, nCharInField );
+/*N*/
+/*N*/ // First char from field wins...
+/*N*/ if ( nFldScriptType == i18n::ScriptType::WEAK )
+/*N*/ {
+/*?*/ nFldScriptType = nTmpType;
+/*?*/ aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
+/*N*/ }
+/*N*/
+/*N*/ // ... but if the first one is LATIN, and there are CJK or CTL chars too,
+/*N*/ // we prefer that ScripType because we need an other font.
+/*N*/ if ( ( nTmpType == i18n::ScriptType::ASIAN ) || ( nTmpType == i18n::ScriptType::COMPLEX ) )
+/*N*/ {
+/*?*/ aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
+/*?*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ pField = pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, pField->GetEnd() );
+/*N*/ }
+/*N*/
+/*N*/ ::rtl::OUString aOUText( aText );
+/*N*/ USHORT nTextLen = (USHORT)aOUText.getLength();
+/*N*/
+/*N*/ long nPos = 0;
+/*N*/ short nScriptType = xBI->getScriptType( aOUText, nPos );
+/*N*/ rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
+/*N*/ nPos = xBI->endOfScript( aOUText, nPos, nScriptType );
+/*N*/ while ( ( nPos != (-1) ) && ( nPos < nTextLen ) )
+/*N*/ {
+/*N*/ rTypes[rTypes.Count()-1].nEndPos = (USHORT)nPos;
+/*N*/
+/*N*/ nScriptType = xBI->getScriptType( aOUText, nPos );
+/*N*/ long nEndPos = xBI->endOfScript( aOUText, nPos, nScriptType );
+/*N*/
+/*N*/ // #96850# Handle blanks as weak, remove if BreakIterator returns WEAK for spaces.
+/*N*/ if ( ( nScriptType == i18n::ScriptType::LATIN ) && ( aOUText.getStr()[ nPos ] == 0x20 ) )
+/*N*/ {
+/*?*/ BOOL bOnlySpaces = TRUE;
+/*?*/ for ( USHORT n = nPos+1; ( n < nEndPos ) && bOnlySpaces; n++ )
+/*?*/ {
+/*?*/ if ( aOUText.getStr()[ n ] != 0x20 )
+/*?*/ bOnlySpaces = FALSE;
+/*?*/ }
+/*?*/ if ( bOnlySpaces )
+/*?*/ nScriptType = i18n::ScriptType::WEAK;
+/*N*/ }
+/*N*/
+/*N*/ if ( ( nScriptType == i18n::ScriptType::WEAK ) || ( nScriptType == rTypes[rTypes.Count()-1].nScriptType ) )
+/*N*/ {
+/*?*/ // Expand last ScriptTypePosInfo, don't create weak or unecessary portions
+/*?*/ rTypes[rTypes.Count()-1].nEndPos = (USHORT)nEndPos;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
+/*N*/ }
+/*N*/
+/*N*/ nPos = nEndPos;
+/*N*/ }
+/*N*/
+/*N*/ if ( rTypes[0].nScriptType == i18n::ScriptType::WEAK )
+/*N*/ rTypes[0].nScriptType = ( rTypes.Count() > 1 ) ? rTypes[1].nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
+/*N*/ }
+/*N*/ }
+
+/*N*/ USHORT ImpEditEngine::GetScriptType( const EditPaM& rPaM, USHORT* pEndPos ) const
+/*N*/ {
+/*N*/ USHORT nScriptType = 0;
+/*N*/
+/*N*/ if ( pEndPos )
+/*?*/ *pEndPos = rPaM.GetNode()->Len();
+/*N*/
+/*N*/ if ( rPaM.GetNode()->Len() )
+/*N*/ {
+/*N*/ USHORT nPara = GetEditDoc().GetPos( rPaM.GetNode() );
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ if ( !pParaPortion->aScriptInfos.Count() )
+/*?*/ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+/*N*/
+/*N*/ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+/*N*/ USHORT nPos = rPaM.GetIndex();
+/*N*/ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+/*N*/ {
+/*N*/ if ( ( rTypes[n].nStartPos <= nPos ) && ( rTypes[n].nEndPos >= nPos ) )
+/*N*/ {
+/*N*/ nScriptType = rTypes[n].nScriptType;
+/*N*/ if( pEndPos )
+/*?*/ *pEndPos = rTypes[n].nEndPos;
+/*N*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
+/*N*/ }
+
+/*N*/ USHORT ImpEditEngine::GetScriptType( const EditSelection& rSel ) const
+/*N*/ {
+/*N*/ EditSelection aSel( rSel );
+/*N*/ aSel.Adjust( aEditDoc );
+/*N*/
+/*N*/ short nScriptType = 0;
+/*N*/
+/*N*/ USHORT nStartPara = GetEditDoc().GetPos( aSel.Min().GetNode() );
+/*N*/ USHORT nEndPara = GetEditDoc().GetPos( aSel.Max().GetNode() );
+/*N*/
+/*N*/ for ( USHORT nPara = nStartPara; nPara <= nEndPara; nPara++ )
+/*N*/ {
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ if ( !pParaPortion->aScriptInfos.Count() )
+/*N*/ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+/*N*/
+/*N*/ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+/*N*/
+/*N*/ USHORT nS = ( nPara == nStartPara ) ? aSel.Min().GetIndex() : 0;
+/*N*/ USHORT nE = ( nPara == nEndPara ) ? aSel.Max().GetIndex() : pParaPortion->GetNode()->Len();
+/*N*/ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+/*N*/ {
+/*N*/ if ( ( rTypes[n].nStartPos <= nE ) && ( rTypes[n].nEndPos >= nS ) )
+/*N*/ {
+/*N*/ if ( rTypes[n].nScriptType != i18n::ScriptType::WEAK )
+/*N*/ {
+/*N*/ nScriptType |= GetItemScriptType ( rTypes[n].nScriptType );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ if ( !nScriptType && n )
+/*?*/ {
+/*?*/ // #93548# When starting with WEAK, use prev ScriptType...
+/*?*/ nScriptType = rTypes[n-1].nScriptType;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
+/*N*/ }
+
+/*N*/ BOOL ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const
+/*N*/ {
+/*N*/ BOOL bScriptChange = FALSE;
+/*N*/
+/*N*/ if ( rPaM.GetNode()->Len() )
+/*N*/ {
+/*N*/ USHORT nPara = GetEditDoc().GetPos( rPaM.GetNode() );
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ if ( !pParaPortion->aScriptInfos.Count() )
+/*?*/ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+/*N*/
+/*N*/ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+/*N*/ USHORT nPos = rPaM.GetIndex();
+/*N*/ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+/*N*/ {
+/*N*/ if ( rTypes[n].nStartPos == nPos )
+/*N*/ {
+/*N*/ bScriptChange = TRUE;
+/*N*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return bScriptChange;
+/*N*/ }
+
+/*N*/ BOOL ImpEditEngine::HasScriptType( USHORT nPara, USHORT nType ) const
+/*N*/ {
+/*N*/ BOOL bTypeFound = FALSE;
+/*N*/
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ if ( !pParaPortion->aScriptInfos.Count() )
+/*N*/ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+/*N*/
+/*N*/ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+/*N*/ for ( USHORT n = rTypes.Count(); n && !bTypeFound; )
+/*N*/ {
+/*N*/ if ( rTypes[--n].nScriptType == nType )
+/*N*/ bTypeFound = TRUE;
+/*N*/ }
+/*N*/ return bTypeFound;
+/*N*/ }
+
+/*N*/ void ImpEditEngine::InitWritingDirections( USHORT nPara )
+/*N*/ {
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos;
+/*N*/ rInfos.Remove( 0, rInfos.Count() );
+/*N*/
+/*N*/ BOOL bCTL = FALSE;
+/*N*/ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+/*N*/ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+/*N*/ {
+/*N*/ if ( rTypes[n].nScriptType == i18n::ScriptType::COMPLEX )
+/*N*/ {
+/*N*/ bCTL = TRUE;
+/*N*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ const BYTE nDefaultDir = IsRightToLeft( nPara ) ? UBIDI_RTL : UBIDI_LTR;
+/*N*/ if ( ( bCTL || ( nDefaultDir == UBIDI_RTL ) ) && pParaPortion->GetNode()->Len() )
+/*N*/ {
+/*?*/
+/*?*/ String aText( *pParaPortion->GetNode() );
+/*?*/
+/*?*/ //
+/*?*/ // Bidi functions from icu 2.0
+/*?*/ //
+/*?*/ UErrorCode nError = U_ZERO_ERROR;
+/*?*/ UBiDi* pBidi = ubidi_openSized( aText.Len(), 0, &nError );
+/*?*/ nError = U_ZERO_ERROR;
+/*?*/
+/*?*/ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aText.GetBuffer()), aText.Len(), nDefaultDir, NULL, &nError ); // UChar != sal_Unicode in MinGW
+/*?*/ nError = U_ZERO_ERROR;
+/*?*/
+/*?*/ long nCount = ubidi_countRuns( pBidi, &nError );
+/*?*/
+/*?*/ int32_t nStart = 0;
+/*?*/ int32_t nEnd;
+/*?*/ UBiDiLevel nCurrDir;
+/*?*/
+/*?*/ for ( USHORT nIdx = 0; nIdx < nCount; ++nIdx )
+/*?*/ {
+/*?*/ ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
+/*?*/ rInfos.Insert( WritingDirectionInfo( nCurrDir, (USHORT)nStart, (USHORT)nEnd ), rInfos.Count() );
+/*?*/ nStart = nEnd;
+/*?*/ }
+/*?*/
+/*?*/ ubidi_close( pBidi );
+/*N*/ }
+/*N*/
+/*N*/ // No infos mean no CTL and default dir is L2R...
+/*N*/ if ( !rInfos.Count() )
+/*N*/ rInfos.Insert( WritingDirectionInfo( 0, 0, (USHORT)pParaPortion->GetNode()->Len() ), rInfos.Count() );
+/*N*/
+/*N*/ }
+
+/*N*/ BOOL ImpEditEngine::IsRightToLeft( USHORT nPara ) const
+/*N*/ {
+/*N*/ BOOL bR2L = FALSE;
+/*N*/ const SvxFrameDirectionItem* pFrameDirItem = NULL;
+/*N*/
+/*N*/ if ( !IsVertical() )
+/*N*/ {
+/*N*/ bR2L = GetDefaultHorizontalTextDirection() == EE_HTEXTDIR_R2L;
+/*N*/ pFrameDirItem = &(const SvxFrameDirectionItem&)GetParaAttrib( nPara, EE_PARA_WRITINGDIR );
+/*N*/ if ( pFrameDirItem->GetValue() == FRMDIR_ENVIRONMENT )
+/*N*/ {
+/*N*/ // #103045# if DefaultHorizontalTextDirection is set, use that value, otherwise pool default.
+/*N*/ if ( GetDefaultHorizontalTextDirection() != EE_HTEXTDIR_DEFAULT )
+/*N*/ {
+/*?*/ pFrameDirItem = NULL; // bR2L allready set to default horizontal text direction
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ // Use pool default
+/*N*/ pFrameDirItem = &(const SvxFrameDirectionItem&)((ImpEditEngine*)this)->GetEmptyItemSet().Get( EE_PARA_WRITINGDIR );
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ if ( pFrameDirItem )
+/*N*/ bR2L = pFrameDirItem->GetValue() == FRMDIR_HORI_RIGHT_TOP;
+/*N*/
+/*N*/ return bR2L;
+/*N*/ }
+
+
+
+/*N*/ BYTE ImpEditEngine::GetRightToLeft( USHORT nPara, USHORT nPos, USHORT* pStart, USHORT* pEnd )
+/*N*/ {
+/*N*/ // BYTE nRightToLeft = IsRightToLeft( nPara ) ? 1 : 0;
+/*N*/ BYTE nRightToLeft = 0;
+/*N*/
+/*N*/ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+/*N*/ if ( pNode && pNode->Len() )
+/*N*/ {
+/*N*/ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+/*N*/ if ( !pParaPortion->aWritingDirectionInfos.Count() )
+/*N*/ InitWritingDirections( nPara );
+/*N*/
+/*N*/ BYTE nType = 0;
+/*N*/ WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
+/*N*/ for ( USHORT n = 0; n < rDirInfos.Count(); n++ )
+/*N*/ {
+/*N*/ if ( ( rDirInfos[n].nStartPos <= nPos ) && ( rDirInfos[n].nEndPos >= nPos ) )
+/*N*/ {
+/*N*/ nRightToLeft = rDirInfos[n].nType;
+/*N*/ if ( pStart )
+/*?*/ *pStart = rDirInfos[n].nStartPos;
+/*N*/ if ( pEnd )
+/*?*/ *pEnd = rDirInfos[n].nEndPos;
+/*N*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return nRightToLeft;
+/*N*/ }
+
+/*N*/ SvxAdjust ImpEditEngine::GetJustification( USHORT nPara ) const
+/*N*/ {
+/*N*/ SvxAdjust eJustification = SVX_ADJUST_LEFT;
+/*N*/
+/*N*/ if ( !aStatus.IsOutliner() )
+/*N*/ {
+/*N*/ eJustification = ((const SvxAdjustItem&) GetParaAttrib( nPara, EE_PARA_JUST )).GetAdjust();
+/*N*/
+/*N*/ if ( IsRightToLeft( nPara ) )
+/*N*/ {
+/*?*/ if ( eJustification == SVX_ADJUST_LEFT )
+/*?*/ eJustification = SVX_ADJUST_RIGHT;
+/*?*/ else if ( eJustification == SVX_ADJUST_RIGHT )
+/*?*/ eJustification = SVX_ADJUST_LEFT;
+/*N*/ }
+/*N*/ }
+/*N*/ return eJustification;
+/*N*/ }
+
+
+// ----------------------------------------------------------------------
+// Textaenderung
+// ----------------------------------------------------------------------
+
+/*N*/ void ImpEditEngine::ImpRemoveChars( const EditPaM& rPaM, USHORT nChars, EditUndoRemoveChars* pCurUndo )
+/*N*/ {
+/*N*/ aEditDoc.RemoveChars( rPaM, nChars );
+/*N*/ TextModified();
+/*N*/ }
+
+
+
+/*N*/ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, BOOL bBackward )
+/*N*/ {
+/*N*/ DBG_ASSERT( pLeft != pRight, "Den gleichen Absatz zusammenfuegen ?" );
+/*N*/ DBG_ASSERT( aEditDoc.GetPos( pLeft ) != USHRT_MAX, "Einzufuegenden Node nicht gefunden(1)" );
+/*N*/ DBG_ASSERT( aEditDoc.GetPos( pRight ) != USHRT_MAX, "Einzufuegenden Node nicht gefunden(2)" );
+/*N*/
+/*N*/ USHORT nParagraphTobeDeleted = aEditDoc.GetPos( pRight );
+/*N*/ DeletedNodeInfo* pInf = new DeletedNodeInfo( (ULONG)pRight, nParagraphTobeDeleted );
+/*N*/ aDeletedNodes.Insert( pInf, aDeletedNodes.Count() );
+/*N*/
+/*N*/ #ifndef SVX_LIGHT
+/*N*/ if ( IsUndoEnabled() && !IsInUndo() )
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); //STRIP001 InsertUndo( new EditUndoConnectParas( this,
+/*N*/ }
+/*N*/ #endif
+/*N*/
+/*N*/ if ( bBackward )
+/*N*/ {
+/*?*/ pLeft->SetStyleSheet( pRight->GetStyleSheet(), TRUE );
+/*?*/ pLeft->GetContentAttribs().GetItems().Set( pRight->GetContentAttribs().GetItems() );
+/*?*/ pLeft->GetCharAttribs().GetDefFont() = pRight->GetCharAttribs().GetDefFont();
+/*N*/ }
+/*N*/
+/*N*/ ParaAttribsChanged( pLeft );
+/*N*/
+/*N*/ // Erstmal Portions suchen, da pRight nach ConnectParagraphs weg.
+/*N*/ ParaPortion* pLeftPortion = FindParaPortion( pLeft );
+/*N*/ ParaPortion* pRightPortion = FindParaPortion( pRight );
+/*N*/ DBG_ASSERT( pLeftPortion, "Blinde Portion in ImpConnectParagraphs(1)" );
+/*N*/ DBG_ASSERT( pRightPortion, "Blinde Portion in ImpConnectParagraphs(2)" );
+/*N*/ DBG_ASSERT( nParagraphTobeDeleted == GetParaPortions().GetPos( pRightPortion ), "NodePos != PortionPos?" );
+/*N*/
+/*N*/ if ( IsCallParaInsertedOrDeleted() )
+/*N*/ GetEditEnginePtr()->ParagraphDeleted( nParagraphTobeDeleted );
+/*N*/
+/*N*/ EditPaM aPaM = aEditDoc.ConnectParagraphs( pLeft, pRight );
+/*N*/ GetParaPortions().Remove( nParagraphTobeDeleted );
+/*N*/ delete pRightPortion;
+/*N*/
+/*N*/ pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->Len() );
+/*N*/
+/*N*/ // der rechte Node wird von EditDoc::ConnectParagraphs() geloescht.
+/*N*/
+/*N*/ if ( GetTextRanger() )
+/*N*/ {
+/*?*/ // Durch das zusammenfuegen wird der linke zwar neu formatiert, aber
+/*?*/ // wenn sich dessen Hoehe nicht aendert bekommt die Formatierung die
+/*?*/ // Aenderung der Gesaamthoehe des Textes zu spaet mit...
+/*?*/ for ( USHORT n = nParagraphTobeDeleted; n < GetParaPortions().Count(); n++ )
+/*?*/ {
+/*?*/ ParaPortion* pPP = GetParaPortions().GetObject( n );
+/*?*/ pPP->MarkSelectionInvalid( 0, pPP->GetNode()->Len() );
+/*?*/ pPP->GetLines().Reset();
+/*?*/ }
+/*N*/ }
+/*N*/
+/*N*/ TextModified();
+/*N*/
+/*N*/ return aPaM;
+/*N*/ }
+
+
+/*N*/ EditPaM ImpEditEngine::ImpDeleteSelection( EditSelection aSel )
+/*N*/ {
+/*N*/ if ( !aSel.HasRange() )
+/*?*/ return aSel.Min();
+/*N*/
+/*N*/ aSel.Adjust( aEditDoc );
+/*N*/ EditPaM aStartPaM( aSel.Min() );
+/*N*/ EditPaM aEndPaM( aSel.Max() );
+/*N*/
+/*N*/ CursorMoved( aStartPaM.GetNode() ); // nur damit neu eingestellte Attribute verschwinden...
+/*N*/ CursorMoved( aEndPaM.GetNode() ); // nur damit neu eingestellte Attribute verschwinden...
+/*N*/
+/*N*/ DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in ImpDeleteSelection" );
+/*N*/ DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in ImpDeleteSelection" );
+/*N*/
+/*N*/ USHORT nStartNode = aEditDoc.GetPos( aStartPaM.GetNode() );
+/*N*/ USHORT nEndNode = aEditDoc.GetPos( aEndPaM.GetNode() );
+/*N*/
+/*N*/ DBG_ASSERT( nEndNode != USHRT_MAX, "Start > End ?!" );
+/*N*/ DBG_ASSERT( nStartNode <= nEndNode, "Start > End ?!" );
+/*N*/
+/*N*/ // Alle Nodes dazwischen entfernen....
+/*N*/ for ( ULONG z = nStartNode+1; z < nEndNode; z++ )
+/*N*/ {
+/*?*/ // Immer nStartNode+1, wegen Remove()!
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); //STRIP001 ImpRemoveParagraph( nStartNode+1 );
+/*N*/ }
+/*N*/
+/*N*/ if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
+/*N*/ {
+/*N*/ // Den Rest des StartNodes...
+/*N*/ USHORT nChars;
+/*N*/ nChars = aStartPaM.GetNode()->Len() - aStartPaM.GetIndex();
+/*N*/ ImpRemoveChars( aStartPaM, nChars );
+/*N*/ ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
+/*N*/ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(3)" );
+/*N*/ pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), aStartPaM.GetNode()->Len() );
+/*N*/
+/*N*/ // Den Anfang des EndNodes....
+/*N*/ nChars = aEndPaM.GetIndex();
+/*N*/ aEndPaM.SetIndex( 0 );
+/*N*/ ImpRemoveChars( aEndPaM, nChars );
+/*N*/ pPortion = FindParaPortion( aEndPaM.GetNode() );
+/*N*/ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(4)" );
+/*N*/ pPortion->MarkSelectionInvalid( 0, aEndPaM.GetNode()->Len() );
+/*N*/ // Zusammenfuegen....
+/*N*/ aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ USHORT nChars;
+/*N*/ nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex();
+/*N*/ ImpRemoveChars( aStartPaM, nChars );
+/*N*/ ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
+/*N*/ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(5)" );
+/*N*/ pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
+/*N*/ }
+/*N*/
+/*N*/ UpdateSelections();
+/*N*/ TextModified();
+/*N*/ return aStartPaM;
+/*N*/ }
+
+
+/*N*/ EditPaM ImpEditEngine::ImpInsertText( EditSelection aCurSel, const XubString& rStr )
+/*N*/ {
+/*N*/ EditPaM aPaM;
+/*N*/ if ( aCurSel.HasRange() )
+/*N*/ aPaM = ImpDeleteSelection( aCurSel );
+/*N*/ else
+/*N*/ aPaM = aCurSel.Max();
+/*N*/
+/*N*/ EditPaM aCurPaM( aPaM ); // fuers Invalidieren
+/*N*/
+/*N*/ XubString aText( rStr );
+/*N*/ aText.ConvertLineEnd( LINEEND_LF );
+/*N*/ SfxVoidItem aTabItem( EE_FEATURE_TAB );
+/*N*/
+/*N*/ // Konvertiert nach LineSep = \n
+/*N*/ // Token mit LINE_SEP abfragen,
+/*N*/ // da der MAC-Compiler aus \n etwas anderes macht!
+/*N*/
+/*N*/ USHORT nStart = 0;
+/*N*/ while ( nStart < aText.Len() )
+/*N*/ {
+/*N*/ USHORT nEnd = aText.Search( LINE_SEP, nStart );
+/*N*/ if ( nEnd == STRING_NOTFOUND )
+/*N*/ nEnd = aText.Len(); // nicht dereferenzieren!
+/*N*/
+/*N*/ // Start == End => Leerzeile
+/*N*/ if ( nEnd > nStart )
+/*N*/ {
+/*N*/ XubString aLine( aText, nStart, nEnd-nStart );
+/*N*/ xub_StrLen nChars = aPaM.GetNode()->Len() + aLine.Len();
+/*N*/ if ( nChars > MAXCHARSINPARA )
+/*N*/ {
+/*?*/ USHORT nMaxNewChars = MAXCHARSINPARA-aPaM.GetNode()->Len();
+/*?*/ nEnd -= ( aLine.Len() - nMaxNewChars ); // Dann landen die Zeichen im naechsten Absatz.
+/*?*/ aLine.Erase( nMaxNewChars ); // Del Rest...
+/*N*/ }
+/*N*/ #ifndef SVX_LIGHT
+/*N*/ if ( IsUndoEnabled() && !IsInUndo() )
+/*N*/ InsertUndo( new EditUndoInsertChars( this, CreateEPaM( aPaM ), aLine ) );
+/*N*/ #endif
+/*N*/ // Tabs ?
+/*N*/ if ( aLine.Search( '\t' ) == STRING_NOTFOUND )
+/*N*/ aPaM = aEditDoc.InsertText( aPaM, aLine );
+/*N*/ else
+/*N*/ {
+/*N*/ USHORT nStart2 = 0;
+/*N*/ while ( nStart2 < aLine.Len() )
+/*N*/ {
+/*N*/ USHORT nEnd2 = aLine.Search( '\t', nStart2 );
+/*N*/ if ( nEnd2 == STRING_NOTFOUND )
+/*?*/ nEnd2 = aLine.Len(); // nicht dereferenzieren!
+/*N*/
+/*N*/ if ( nEnd2 > nStart2 )
+/*?*/ aPaM = aEditDoc.InsertText( aPaM, XubString( aLine, nStart2, nEnd2-nStart2 ) );
+/*N*/ if ( nEnd2 < aLine.Len() )
+/*N*/ {
+/*N*/ // aPaM = ImpInsertFeature( EditSelection( aPaM, aPaM ), );
+/*N*/ aPaM = aEditDoc.InsertFeature( aPaM, aTabItem );
+/*N*/ }
+/*N*/ nStart2 = nEnd2+1;
+/*N*/ }
+/*N*/ }
+/*N*/ ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
+/*N*/ DBG_ASSERT( pPortion, "Blinde Portion in InsertText" );
+/*N*/ pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.Len() );
+/*N*/ }
+/*N*/ if ( nEnd < aText.Len() )
+/*N*/ aPaM = ImpInsertParaBreak( aPaM );
+/*N*/
+/*N*/ nStart = nEnd+1;
+/*N*/ }
+/*N*/
+/*N*/ TextModified();
+/*N*/ return aPaM;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const XubString& rStr )
+/*N*/ {
+/*N*/ DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "FastInsertText: Zeilentrenner nicht erlaubt!" );
+/*N*/ DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "FastInsertText: Zeilentrenner nicht erlaubt!" );
+/*N*/ DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "FastInsertText: Features nicht erlaubt!" );
+/*N*/
+/*N*/ if ( ( aPaM.GetNode()->Len() + rStr.Len() ) < MAXCHARSINPARA )
+/*N*/ {
+/*N*/ #ifndef SVX_LIGHT
+/*N*/ if ( IsUndoEnabled() && !IsInUndo() )
+/*?*/ InsertUndo( new EditUndoInsertChars( this, CreateEPaM( aPaM ), rStr ) );
+/*N*/ #endif
+/*N*/
+/*N*/ aPaM = aEditDoc.InsertText( aPaM, rStr );
+/*N*/ TextModified();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ aPaM = ImpInsertText( aPaM, rStr );
+/*N*/ }
+/*N*/
+/*N*/ return aPaM;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::ImpInsertFeature( EditSelection aCurSel, const SfxPoolItem& rItem )
+/*N*/ {
+/*N*/ EditPaM aPaM;
+/*N*/ if ( aCurSel.HasRange() )
+/*?*/ aPaM = ImpDeleteSelection( aCurSel );
+/*N*/ else
+/*N*/ aPaM = aCurSel.Max();
+/*N*/
+/*N*/ #ifndef SVX_LIGHT
+/*N*/ if ( IsUndoEnabled() && !IsInUndo() )
+/*N*/ InsertUndo( new EditUndoInsertFeature( this, CreateEPaM( aPaM ), rItem ) );
+/*N*/ #endif
+/*N*/ aPaM = aEditDoc.InsertFeature( aPaM, rItem );
+/*N*/
+/*N*/ ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
+/*N*/ DBG_ASSERT( pPortion, "Blinde Portion in InsertFeature" );
+/*N*/ pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 );
+/*N*/
+/*N*/ TextModified();
+/*N*/
+/*N*/ return aPaM;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::ImpInsertParaBreak( const EditPaM& rPaM, BOOL bKeepEndingAttribs )
+/*N*/ {
+/*N*/ EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) );
+/*N*/
+/*N*/ ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() );
+/*N*/ DBG_ASSERT( pPortion, "Blinde Portion in ImpInsertParaBreak" );
+/*N*/ pPortion->MarkInvalid( rPaM.GetIndex(), 0 );
+/*N*/
+/*N*/ // Optimieren: Nicht unnoetig viele GetPos auf die Listen ansetzen!
+/*N*/ // Hier z.B. bei Undo, aber auch in allen anderen Methoden.
+/*N*/ USHORT nPos = GetParaPortions().GetPos( pPortion );
+/*N*/ ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() );
+/*N*/ GetParaPortions().Insert( pNewPortion, nPos + 1 );
+/*N*/ ParaAttribsChanged( pNewPortion->GetNode() );
+/*N*/ if ( IsCallParaInsertedOrDeleted() )
+/*N*/ GetEditEnginePtr()->ParagraphInserted( nPos+1 );
+/*N*/
+/*N*/ CursorMoved( rPaM.GetNode() ); // falls leeres Attribut entstanden.
+/*N*/ TextModified();
+/*N*/ return aPaM;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::ImpFastInsertParagraph( USHORT nPara )
+/*N*/ {
+/*N*/ ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() );
+/*N*/ // Falls FlatMode, wird spaeter kein Font eingestellt:
+/*N*/ pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
+/*N*/
+/*N*/ aEditDoc.Insert( pNode, nPara );
+/*N*/
+/*N*/ ParaPortion* pNewPortion = new ParaPortion( pNode );
+/*N*/ GetParaPortions().Insert( pNewPortion, nPara );
+/*N*/ if ( IsCallParaInsertedOrDeleted() )
+/*N*/ GetEditEnginePtr()->ParagraphInserted( nPara );
+/*N*/
+/*N*/ return EditPaM( pNode, 0 );
+/*N*/ }
+
+/*N*/ BOOL ImpEditEngine::UpdateFields()
+/*N*/ {
+/*N*/ BOOL bChanges = FALSE;
+/*N*/ USHORT nParas = GetEditDoc().Count();
+/*N*/ for ( USHORT nPara = 0; nPara < nParas; nPara++ )
+/*N*/ {
+/*N*/ BOOL bChangesInPara = FALSE;
+/*N*/ ContentNode* pNode = GetEditDoc().GetObject( nPara );
+/*N*/ DBG_ASSERT( pNode, "NULL-Pointer im Doc" );
+/*N*/ CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
+/*N*/ USHORT nAttrs = rAttribs.Count();
+/*N*/ for ( USHORT nAttr = 0; nAttr < rAttribs.Count(); nAttr++ )
+/*N*/ {
+/*N*/ EditCharAttrib* pAttr = rAttribs[nAttr];
+/*N*/ if ( pAttr->Which() == EE_FEATURE_FIELD )
+/*N*/ {
+/*N*/ EditCharAttribField* pField = (EditCharAttribField*)pAttr;
+/*N*/ EditCharAttribField* pCurrent = new EditCharAttribField( *pField );
+/*N*/ pField->Reset();
+/*N*/
+/*N*/ if ( aStatus.MarkFields() )
+/*N*/ pField->GetFldColor() = new Color( GetColorConfig().GetColorValue( WRITERFIELDSHADINGS ).nColor );
+/*N*/
+/*N*/ XubString aFldValue = GetEditEnginePtr()->CalcFieldValue(
+/*N*/ (const SvxFieldItem&)*pField->GetItem(),
+/*N*/ nPara, pField->GetStart(),
+/*N*/ pField->GetTxtColor(), pField->GetFldColor() );
+/*N*/ pField->GetFieldValue() = aFldValue;
+/*N*/ if ( *pField != *pCurrent )
+/*N*/ {
+/*N*/ bChanges = TRUE;
+/*N*/ bChangesInPara = TRUE;
+/*N*/ }
+/*N*/ delete pCurrent;
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bChangesInPara )
+/*N*/ {
+/*N*/ // ggf. etwas genauer invalidieren.
+/*N*/ ParaPortion* pPortion = GetParaPortions().GetObject( nPara );
+/*N*/ DBG_ASSERT( pPortion, "NULL-Pointer im Doc" );
+/*N*/ pPortion->MarkSelectionInvalid( 0, pNode->Len() );
+/*N*/ }
+/*N*/ }
+/*N*/ return bChanges;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::InsertLineBreak( EditSelection aCurSel )
+/*N*/ {
+/*N*/ EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_LINEBR ) ) );
+/*N*/ return aPaM;
+/*N*/ }
+
+// ----------------------------------------------------------------------
+// Hilfsfunktionen
+// ----------------------------------------------------------------------
+
+/*N*/ EditPaM ImpEditEngine::GetPaM( Point aDocPos, BOOL bSmart )
+/*N*/ {
+/*N*/ DBG_ASSERT( GetUpdateMode(), "Darf bei Update=FALSE nicht erreicht werden: GetPaM" );
+/*N*/
+/*N*/ long nY = 0;
+/*N*/ long nTmpHeight;
+/*N*/ EditPaM aPaM;
+/*N*/ USHORT nPortion;
+/*N*/ for ( nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
+/*N*/ {
+/*N*/ ParaPortion* pPortion = GetParaPortions().GetObject(nPortion);
+/*N*/ nTmpHeight = pPortion->GetHeight(); // sollte auch bei !bVisible richtig sein!
+/*N*/ nY += nTmpHeight;
+/*N*/ if ( nY > aDocPos.Y() )
+/*N*/ {
+/*N*/ nY -= nTmpHeight;
+/*N*/ aDocPos.Y() -= nY;
+/*N*/ // unsichtbare Portions ueberspringen:
+/*N*/ while ( pPortion && !pPortion->IsVisible() )
+/*N*/ {
+/*?*/ nPortion++;
+/*?*/ pPortion = GetParaPortions().SaveGetObject( nPortion );
+/*N*/ }
+/*N*/ DBG_ASSERT( pPortion, "Keinen sichtbaren Absatz gefunden: GetPaM" );
+/*N*/ aPaM = GetPaM( pPortion, aDocPos, bSmart );
+/*N*/ return aPaM;
+/*N*/
+/*N*/ }
+/*N*/ }
+/*?*/ // Dann den letzten sichtbaren Suchen:
+/*?*/ nPortion = GetParaPortions().Count()-1;
+/*?*/ while ( nPortion && !GetParaPortions()[nPortion]->IsVisible() )
+/*?*/ nPortion--;
+/*?*/
+/*?*/ DBG_ASSERT( GetParaPortions()[nPortion]->IsVisible(), "Keinen sichtbaren Absatz gefunden: GetPaM" );
+/*?*/ aPaM.SetNode( GetParaPortions()[nPortion]->GetNode() );
+/*?*/ aPaM.SetIndex( GetParaPortions()[nPortion]->GetNode()->Len() );
+/*?*/ return aPaM;
+/*N*/ }
+
+/*N*/ sal_uInt32 ImpEditEngine::GetTextHeight() const
+/*N*/ {
+/*N*/ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=FALSE nicht verwendet werden: GetTextHeight" );
+/*N*/ DBG_ASSERT( IsFormatted() || IsFormatting(), "GetTextHeight: Nicht formatiert" );
+/*N*/ return nCurTextHeight;
+/*N*/ }
+
+/*N*/ sal_uInt32 ImpEditEngine::CalcTextWidth( BOOL bIgnoreExtraSpace )
+/*N*/ {
+/*N*/ // Wenn noch nicht formatiert und nicht gerade dabei.
+/*N*/ // Wird in der Formatierung bei AutoPageSize gerufen.
+/*N*/ if ( !IsFormatted() && !IsFormatting() )
+/*?*/ FormatDoc();
+/*N*/
+/*N*/ EditLine* pLine;
+/*N*/
+/*N*/ long nMaxWidth = 0;
+/*N*/ long nCurWidth = 0;
+/*N*/
+/*N*/ // --------------------------------------------------
+/*N*/ // Ueber alle Absaetze...
+/*N*/ // --------------------------------------------------
+/*N*/ USHORT nParas = GetParaPortions().Count();
+/*N*/ USHORT nBiggestPara = 0;
+/*N*/ USHORT nBiggestLine = 0;
+/*N*/ for ( USHORT nPara = 0; nPara < nParas; nPara++ )
+/*N*/ {
+/*N*/ ParaPortion* pPortion = GetParaPortions().GetObject( nPara );
+/*N*/ const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pPortion->GetNode() );
+/*N*/
+/*N*/ if ( pPortion->IsVisible() )
+/*N*/ {
+/*N*/ // --------------------------------------------------
+/*N*/ // Ueber die Zeilen des Absatzes...
+/*N*/ // --------------------------------------------------
+/*N*/ ULONG nLines = pPortion->GetLines().Count();
+/*N*/ for ( USHORT nLine = 0; nLine < nLines; nLine++ )
+/*N*/ {
+/*N*/ pLine = pPortion->GetLines().GetObject( nLine );
+/*N*/ DBG_ASSERT( pLine, "NULL-Pointer im Zeileniterator in CalcWidth" );
+/*N*/ // nCurWidth = pLine->GetStartPosX();
+/*N*/ // Bei Center oder Right haengt die breite von der
+/*N*/ // Papierbreite ab, hier nicht erwuenscht.
+/*N*/ // Am besten generell nicht auf StartPosX verlassen,
+/*N*/ // es muss auch die rechte Einrueckung beruecksichtigt werden!
+/*N*/ nCurWidth = GetXValue( rLRItem.GetTxtLeft() );
+/*N*/ if ( nLine == 0 )
+/*N*/ {
+/*N*/ long nFI = GetXValue( rLRItem.GetTxtFirstLineOfst() );
+/*N*/ nCurWidth += nFI;
+/*N*/ if ( pPortion->GetBulletX() > nCurWidth )
+/*N*/ {
+/*?*/ nCurWidth -= nFI; // LI?
+/*?*/ if ( pPortion->GetBulletX() > nCurWidth )
+/*?*/ nCurWidth = pPortion->GetBulletX();
+/*N*/ }
+/*N*/ }
+/*N*/ nCurWidth += GetXValue( rLRItem.GetRight() );
+/*N*/ nCurWidth += CalcLineWidth( pPortion, pLine, bIgnoreExtraSpace );
+/*N*/ if ( nCurWidth > nMaxWidth )
+/*N*/ {
+/*N*/ nMaxWidth = nCurWidth;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if ( nMaxWidth < 0 )
+/*?*/ nMaxWidth = 0;
+/*N*/
+/*N*/ nMaxWidth++; // Ein breiter, da in CreateLines bei >= umgebrochen wird.
+/*N*/ return (sal_uInt32)nMaxWidth;
+/*N*/ }
+
+/*N*/ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, BOOL bIgnoreExtraSpace )
+/*N*/ {
+/*N*/ USHORT nPara = GetEditDoc().GetPos( pPortion->GetNode() );
+/*N*/ ULONG nOldLayoutMode = GetRefDevice()->GetLayoutMode();
+/*N*/
+/*N*/ ImplInitLayoutMode( GetRefDevice(), nPara, 0xFFFF );
+/*N*/
+/*N*/ SvxAdjust eJustification = GetJustification( nPara );
+/*N*/
+/*N*/ // Berechnung der Breite ohne die Indents...
+/*N*/ sal_uInt32 nWidth = 0;
+/*N*/ USHORT nPos = pLine->GetStart();
+/*N*/ for ( USHORT nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
+/*N*/ {
+/*N*/ TextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( nTP );
+/*N*/ switch ( pTextPortion->GetKind() )
+/*N*/ {
+/*N*/ case PORTIONKIND_FIELD:
+/*N*/ case PORTIONKIND_HYPHENATOR:
+/*N*/ case PORTIONKIND_TAB:
+/*N*/ {
+/*N*/ nWidth += pTextPortion->GetSize().Width();
+/*N*/ }
+/*N*/ break;
+/*N*/ case PORTIONKIND_TEXT:
+/*N*/ {
+/*N*/ if ( ( eJustification != SVX_ADJUST_BLOCK ) || ( !bIgnoreExtraSpace ) )
+/*N*/ {
+/*N*/ nWidth += pTextPortion->GetSize().Width();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() );
+/*?*/ SeekCursor( pPortion->GetNode(), nPos+1, aTmpFont );
+/*?*/ aTmpFont.SetPhysFont( GetRefDevice() );
+/*?*/ nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), *pPortion->GetNode(), nPos, pTextPortion->GetLen(), NULL ).Width();
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ }
+/*N*/ nPos += pTextPortion->GetLen();
+/*N*/ }
+/*N*/
+/*N*/ GetRefDevice()->SetLayoutMode( nOldLayoutMode );
+/*N*/
+/*N*/ return nWidth;
+/*N*/ }
+
+/*N*/ sal_uInt32 ImpEditEngine::CalcTextHeight()
+/*N*/ {
+/*N*/ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=FALSE nicht verwendet werden: CalcTextHeight" );
+/*N*/ sal_uInt32 nY = 0;
+/*N*/ for ( USHORT nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
+/*N*/ nY += GetParaPortions()[nPortion]->GetHeight();
+/*N*/ return nY;
+/*N*/ }
+
+/*N*/ USHORT ImpEditEngine::GetLineCount( USHORT nParagraph ) const
+/*N*/ {
+/*N*/ DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
+/*N*/ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+/*N*/ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineCount" );
+/*N*/ if ( pPPortion )
+/*N*/ return pPPortion->GetLines().Count();
+/*N*/
+/*N*/ return 0xFFFF;
+/*N*/ }
+
+
+
+
+/*N*/ void ImpEditEngine::UpdateSelections()
+/*N*/ {
+/*N*/ USHORT nInvNodes = aDeletedNodes.Count();
+/*N*/
+/*N*/ // Pruefen, ob eine der Selektionen auf einem geloeschten Node steht...
+/*N*/ // Wenn der Node gueltig ist, muss noch der Index geprueft werden!
+/*N*/ for ( USHORT nView = 0; nView < aEditViews.Count(); nView++ )
+/*N*/ {
+/*N*/ EditView* pView = aEditViews.GetObject(nView);
+/*N*/ DBG_CHKOBJ( pView, EditView, 0 );
+/*N*/ EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
+/*N*/ BOOL bChanged = FALSE;
+/*N*/ for ( USHORT n = 0; n < nInvNodes; n++ )
+/*N*/ {
+/*?*/ DeletedNodeInfo* pInf = aDeletedNodes.GetObject( n );
+/*?*/ if ( ( ( ULONG )(aCurSel.Min().GetNode()) == pInf->GetInvalidAdress() ) ||
+/*?*/ ( ( ULONG )(aCurSel.Max().GetNode()) == pInf->GetInvalidAdress() ) )
+/*?*/ {
+/*?*/ // ParaPortions verwenden, da jetzt auch versteckte
+/*?*/ // Absaetze beruecksichtigt werden muessen!
+/*?*/ USHORT nPara = pInf->GetPosition();
+/*?*/ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nPara );
+/*?*/ if ( !pPPortion ) // letzter Absatz
+/*?*/ {
+/*?*/ nPara = GetParaPortions().Count()-1;
+/*?*/ pPPortion = GetParaPortions().GetObject( nPara );
+/*?*/ }
+/*?*/ DBG_ASSERT( pPPortion, "Leeres Document in UpdateSelections ?" );
+/*?*/ // Nicht aus einem verstecktem Absatz landen:
+/*?*/ USHORT nCurPara = nPara;
+/*?*/ USHORT nLastPara = GetParaPortions().Count()-1;
+/*?*/ while ( nPara <= nLastPara && !GetParaPortions()[nPara]->IsVisible() )
+/*?*/ nPara++;
+/*?*/ if ( nPara > nLastPara ) // dann eben rueckwaerts...
+/*?*/ {
+/*?*/ nPara = nCurPara;
+/*?*/ while ( nPara && !GetParaPortions()[nPara]->IsVisible() )
+/*?*/ nPara--;
+/*?*/ }
+/*?*/ DBG_ASSERT( GetParaPortions()[nPara]->IsVisible(), "Keinen sichtbaren Absatz gefunden: UpdateSelections" );
+/*?*/
+/*?*/ ParaPortion* pParaPortion = GetParaPortions()[nPara];
+/*?*/ EditSelection aTmpSelection( EditPaM( pParaPortion->GetNode(), 0 ) );
+/*?*/ pView->pImpEditView->SetEditSelection( aTmpSelection );
+/*?*/ bChanged=TRUE;
+/*?*/ break; // for-Schleife
+/*?*/ }
+/*N*/ }
+/*N*/ if ( !bChanged )
+/*N*/ {
+/*N*/ // Index prueffen, falls Node geschrumpft.
+/*N*/ if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() )
+/*N*/ {
+/*?*/ aCurSel.Min().GetIndex() = aCurSel.Min().GetNode()->Len();
+/*?*/ pView->pImpEditView->SetEditSelection( aCurSel );
+/*N*/ }
+/*N*/ if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
+/*N*/ {
+/*?*/ aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
+/*?*/ pView->pImpEditView->SetEditSelection( aCurSel );
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ // Loeschen...
+/*N*/ for ( USHORT n = 0; n < nInvNodes; n++ )
+/*N*/ {
+/*N*/ DeletedNodeInfo* pInf = aDeletedNodes.GetObject( n );
+/*N*/ delete pInf;
+/*N*/ }
+/*N*/ aDeletedNodes.Remove( 0, aDeletedNodes.Count() );
+/*N*/ }
+
+/*N*/ EditSelection ImpEditEngine::ConvertSelection( USHORT nStartPara, USHORT nStartPos,
+/*N*/ USHORT nEndPara, USHORT nEndPos ) const
+/*N*/ {
+/*N*/ EditSelection aNewSelection;
+/*N*/
+/*N*/ // Start...
+/*N*/ ContentNode* pNode = aEditDoc.SaveGetObject( nStartPara );
+/*N*/ USHORT nIndex = nStartPos;
+/*N*/ if ( !pNode )
+/*N*/ {
+/*?*/ pNode = aEditDoc[ aEditDoc.Count()-1 ];
+/*?*/ nIndex = pNode->Len();
+/*N*/ }
+/*N*/ else if ( nIndex > pNode->Len() )
+/*?*/ nIndex = pNode->Len();
+/*N*/
+/*N*/ aNewSelection.Min().SetNode( pNode );
+/*N*/ aNewSelection.Min().SetIndex( nIndex );
+/*N*/
+/*N*/ // End...
+/*N*/ pNode = aEditDoc.SaveGetObject( nEndPara );
+/*N*/ nIndex = nEndPos;
+/*N*/ if ( !pNode )
+/*N*/ {
+/*?*/ pNode = aEditDoc[ aEditDoc.Count()-1 ];
+/*?*/ nIndex = pNode->Len();
+/*N*/ }
+/*N*/ else if ( nIndex > pNode->Len() )
+/*?*/ nIndex = pNode->Len();
+/*N*/
+/*N*/ aNewSelection.Max().SetNode( pNode );
+/*N*/ aNewSelection.Max().SetIndex( nIndex );
+/*N*/
+/*N*/ return aNewSelection;
+/*N*/ }
+
+
+
+/*N*/ void ImpEditEngine::SetActiveView( EditView* pView )
+/*N*/ {
+/*N*/ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+/*N*/ // Eigentlich waere jetzt ein bHasVisSel und HideSelection notwendig !!!
+/*N*/
+/*N*/ if ( pView == pActiveView )
+/*N*/ return;
+/*N*/
+/*N*/ if ( pActiveView && pActiveView->HasSelection() )
+/*?*/ pActiveView->pImpEditView->DrawSelection(); // Wegzeichnen...
+/*N*/
+/*N*/ pActiveView = pView;
+/*N*/
+/*N*/ if ( pActiveView && pActiveView->HasSelection() )
+/*?*/ pActiveView->pImpEditView->DrawSelection(); // Wegzeichnen...
+/*N*/
+/*N*/ // NN: Quick fix for #78668#:
+/*N*/ // When editing of a cell in Calc is ended, the edit engine is not deleted,
+/*N*/ // only the edit views are removed. If mpIMEInfos is still set in that case,
+/*N*/ // mpIMEInfos->aPos points to an invalid selection.
+/*N*/ // -> reset mpIMEInfos now
+/*N*/ // (probably something like this is necessary whenever the content is modified
+/*N*/ // from the outside)
+/*N*/
+/*N*/ if ( !pView && mpIMEInfos )
+/*N*/ {
+/*?*/ delete mpIMEInfos;
+/*?*/ mpIMEInfos = NULL;
+/*N*/ }
+/*N*/ }
+
+
+
+/*N*/ Range ImpEditEngine::GetInvalidYOffsets( ParaPortion* pPortion )
+/*N*/ {
+/*N*/ Range aRange( 0, 0 );
+/*N*/
+/*N*/ if ( pPortion->IsVisible() )
+/*N*/ {
+/*N*/ const SvxULSpaceItem& rULSpace = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+/*N*/ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+/*N*/ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+/*N*/ ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+/*N*/
+/*N*/ // erst von vorne...
+/*N*/ USHORT nFirstInvalid = 0xFFFF;
+/*N*/ USHORT nLine;
+/*N*/ for ( nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+/*N*/ {
+/*N*/ EditLine* pL = pPortion->GetLines().GetObject( nLine );
+/*N*/ if ( pL->IsInvalid() )
+/*N*/ {
+/*N*/ nFirstInvalid = nLine;
+/*N*/ break;
+/*N*/ }
+/*?*/ if ( nLine && !aStatus.IsOutliner() ) // nicht die erste Zeile
+/*?*/ aRange.Min() += nSBL;
+/*?*/ aRange.Min() += pL->GetHeight();
+/*N*/ }
+/*N*/ DBG_ASSERT( nFirstInvalid != 0xFFFF, "Keine ungueltige Zeile gefunden in GetInvalidYOffset(1)" );
+/*N*/
+/*N*/
+/*N*/ // Abgleichen und weiter...
+/*N*/ aRange.Max() = aRange.Min();
+/*N*/ aRange.Max() += pPortion->GetFirstLineOffset();
+/*N*/ if ( nFirstInvalid != 0 ) // Nur wenn nicht die erste Zeile ungueltig
+/*?*/ aRange.Min() = aRange.Max();
+/*N*/
+/*N*/ USHORT nLastInvalid = pPortion->GetLines().Count()-1;
+/*N*/ for ( nLine = nFirstInvalid; nLine < pPortion->GetLines().Count(); nLine++ )
+/*N*/ {
+/*N*/ EditLine* pL = pPortion->GetLines().GetObject( nLine );
+/*N*/ if ( pL->IsValid() )
+/*N*/ {
+/*?*/ nLastInvalid = nLine;
+/*?*/ break;
+/*N*/ }
+/*N*/
+/*N*/ if ( nLine && !aStatus.IsOutliner() )
+/*N*/ aRange.Max() += nSBL;
+/*N*/ aRange.Max() += pL->GetHeight();
+/*N*/ }
+/*N*/
+/*N*/ // MT 07/00 SBL kann jetzt kleiner 100% sein => ggf. die Zeile davor neu ausgeben.
+/*N*/ if( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP ) && rLSItem.GetPropLineSpace() &&
+/*N*/ ( rLSItem.GetPropLineSpace() < 100 ) )
+/*N*/ {
+/*?*/ EditLine* pL = pPortion->GetLines().GetObject( nFirstInvalid );
+/*?*/ long n = pL->GetTxtHeight() * ( 100 - rLSItem.GetPropLineSpace() );
+/*?*/ n /= 100;
+/*?*/ aRange.Min() -= n;
+/*?*/ aRange.Max() += n;
+/*N*/ }
+/*N*/
+/*N*/ if ( ( nLastInvalid == pPortion->GetLines().Count()-1 ) && ( !aStatus.IsOutliner() ) )
+/*N*/ aRange.Max() += GetYValue( rULSpace.GetLower() );
+/*N*/ }
+/*N*/ return aRange;
+/*N*/ }
+
+/*N*/ EditPaM ImpEditEngine::GetPaM( ParaPortion* pPortion, Point aDocPos, BOOL bSmart )
+/*N*/ {
+/*N*/ DBG_ASSERT( pPortion->IsVisible(), "Wozu GetPaM() bei einem unsichtbaren Absatz?" );
+/*N*/ DBG_ASSERT( IsFormatted(), "GetPaM: Nicht formatiert" );
+/*N*/
+/*N*/ USHORT nCurIndex = 0;
+/*N*/ EditPaM aPaM;
+/*N*/ aPaM.SetNode( pPortion->GetNode() );
+/*N*/
+/*N*/ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+/*N*/ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+/*N*/ ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+/*N*/
+/*N*/ long nY = pPortion->GetFirstLineOffset();
+/*N*/
+/*N*/ DBG_ASSERT( pPortion->GetLines().Count(), "Leere ParaPortion in GetPaM!" );
+/*N*/
+/*N*/ EditLine* pLine = 0;
+/*N*/ for ( USHORT nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+/*N*/ {
+/*N*/ EditLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
+/*N*/ nY += pTmpLine->GetHeight();
+/*N*/ if ( !aStatus.IsOutliner() )
+/*N*/ nY += nSBL;
+/*N*/ if ( nY > aDocPos.Y() ) // das war 'se
+/*N*/ {
+/*N*/ pLine = pTmpLine;
+/*N*/ break; // richtige Y-Position intressiert nicht
+/*N*/ }
+/*N*/
+/*?*/ nCurIndex += pTmpLine->GetLen();
+/*N*/ }
+/*N*/
+/*N*/ if ( !pLine ) // darf nur im Bereich von SA passieren!
+/*N*/ {
+/*?*/ #ifdef DBG_UTIL
+/*?*/ const SvxULSpaceItem& rULSpace =(const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+/*?*/ DBG_ASSERT( nY+GetYValue( rULSpace.GetLower() ) >= aDocPos.Y() , "Index in keiner Zeile, GetPaM ?" );
+/*?*/ #endif
+/*?*/ aPaM.SetIndex( pPortion->GetNode()->Len() );
+/*?*/ return aPaM;
+/*N*/ }
+/*N*/
+/*N*/ // Wenn Zeile gefunden, nur noch X-Position => Index
+/*N*/ nCurIndex = GetChar( pPortion, pLine, aDocPos.X(), bSmart );
+/*N*/ aPaM.SetIndex( nCurIndex );
+/*N*/
+/*N*/ if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) &&
+/*N*/ ( pLine != pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1) ) )
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); //STRIP001 aPaM = CursorLeft( aPaM, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL );
+/*N*/ }
+/*N*/
+/*N*/ return aPaM;
+/*N*/ }
+
+/*N*/ USHORT ImpEditEngine::GetChar( ParaPortion* pParaPortion, EditLine* pLine, long nXPos, BOOL bSmart )
+/*N*/ {
+/*N*/ DBG_ASSERT( pLine, "Keine Zeile erhalten: GetChar" );
+/*N*/
+/*N*/ USHORT nChar = 0xFFFF;
+/*N*/ USHORT nCurIndex = pLine->GetStart();
+/*N*/
+/*N*/
+/*N*/ // Search best matching portion with GetPortionXOffset()
+/*N*/ for ( USHORT i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ )
+/*N*/ {
+/*N*/ TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
+/*N*/ long nXLeft = GetPortionXOffset( pParaPortion, pLine, i );
+/*N*/ long nXRight = nXLeft + pPortion->GetSize().Width();
+/*N*/ if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) )
+/*N*/ {
+/*N*/ nChar = nCurIndex;
+/*N*/
+/*N*/ // Search within Portion...
+/*N*/
+/*N*/ // Don't search within special portions...
+/*N*/ if ( pPortion->GetKind() != PORTIONKIND_TEXT )
+/*N*/ {
+/*?*/ // ...but check on which side
+/*?*/ if ( bSmart )
+/*?*/ {
+/*?*/ long nLeftDiff = nXPos-nXLeft;
+/*?*/ long nRightDiff = nXRight-nXPos;
+/*?*/ if ( nRightDiff < nLeftDiff )
+/*?*/ nChar++;
+/*?*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ USHORT nMax = pPortion->GetLen();
+/*N*/ USHORT nOffset = 0xFFFF;
+/*N*/ USHORT nTmpCurIndex = nChar - pLine->GetStart();
+/*N*/
+/*N*/ long nXInPortion = nXPos - nXLeft;
+/*N*/ if ( pPortion->IsRightToLeft() )
+/*?*/ nXInPortion = nXRight - nXPos;
+/*N*/
+/*N*/ // Search in Array...
+/*N*/ for ( USHORT x = 0; x < nMax; x++ )
+/*N*/ {
+/*N*/ long nTmpPosMax = pLine->GetCharPosArray().GetObject( nTmpCurIndex+x );
+/*N*/ if ( nTmpPosMax > nXInPortion )
+/*N*/ {
+/*N*/ // pruefen, ob dieser oder der davor...
+/*N*/ long nTmpPosMin = x ? pLine->GetCharPosArray().GetObject( nTmpCurIndex+x-1 ) : 0;
+/*N*/ long nDiffLeft = nXInPortion - nTmpPosMin;
+/*N*/ long nDiffRight = nTmpPosMax - nXInPortion;
+/*N*/ DBG_ASSERT( nDiffLeft >= 0, "DiffLeft negativ" );
+/*N*/ DBG_ASSERT( nDiffRight >= 0, "DiffRight negativ" );
+/*N*/ nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x;
+/*N*/ // I18N: If there are character position with the length of 0,
+/*N*/ // they belong to the same character, we can not use this position as an index.
+/*N*/ // Skip all 0-positions, cheaper than using XBreakIterator:
+/*N*/ if ( nOffset < nMax )
+/*N*/ {
+/*N*/ const long nX = pLine->GetCharPosArray().GetObject(nOffset);
+/*N*/ while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray().GetObject(nOffset+1) == nX ) )
+/*N*/ nOffset++;
+/*N*/ }
+/*N*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ // Bei Verwendung des CharPosArray duerfte es keine Ungenauigkeiten geben!
+/*N*/ // Vielleicht bei Kerning ?
+/*N*/ // 0xFFF passiert z.B. bei Outline-Font, wenn ganz hinten.
+/*N*/ if ( nOffset == 0xFFFF )
+/*N*/ nOffset = nMax;
+/*N*/
+/*N*/ DBG_ASSERT( nOffset <= nMax, "nOffset > nMax" );
+/*N*/
+/*N*/ nChar += nOffset;
+/*N*/
+/*N*/ // Check if index is within a cell:
+/*N*/ if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) )
+/*N*/ {
+/*N*/ EditPaM aPaM( pParaPortion->GetNode(), nChar+1 );
+/*N*/ USHORT nScriptType = GetScriptType( aPaM );
+/*N*/ if ( nScriptType == i18n::ScriptType::COMPLEX )
+/*N*/ {
+/*?*/ uno::Reference < i18n::XBreakIterator > xBI = ImplGetBreakIterator();
+/*?*/ sal_Int32 nCount = 1;
+/*?*/ lang::Locale aLocale = GetLocale( aPaM );
+/*?*/ USHORT nRight = (USHORT)xBI->nextCharacters( *pParaPortion->GetNode(), nChar, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
+/*?*/ USHORT nLeft = (USHORT)xBI->previousCharacters( *pParaPortion->GetNode(), nRight, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
+/*?*/ if ( ( nLeft != nChar ) && ( nRight != nChar ) )
+/*?*/ {
+/*?*/ nChar = ( Abs( nRight - nChar ) < Abs( nLeft - nChar ) ) ? nRight : nLeft;
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ nCurIndex += pPortion->GetLen();
+/*N*/ }
+/*N*/
+/*N*/ if ( nChar == 0xFFFF )
+/*N*/ {
+/*?*/ nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd();
+/*N*/ }
+/*N*/
+/*N*/ return nChar;
+/*N*/ }
+
+/*N*/ Range ImpEditEngine::GetLineXPosStartEnd( ParaPortion* pParaPortion, EditLine* pLine )
+/*N*/ {
+/*N*/ Range aLineXPosStartEnd;
+/*N*/
+/*N*/ USHORT nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
+/*N*/ if ( !IsRightToLeft( nPara ) )
+/*N*/ {
+/*N*/ aLineXPosStartEnd.Min() = pLine->GetStartPosX();
+/*N*/ aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() );
+/*?*/ aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX();
+/*N*/ }
+/*N*/
+/*N*/
+/*N*/ return aLineXPosStartEnd;
+/*N*/ }
+
+/*N*/ long ImpEditEngine::GetPortionXOffset( ParaPortion* pParaPortion, EditLine* pLine, USHORT nTextPortion )
+/*N*/ {
+/*N*/ long nX = pLine->GetStartPosX();
+/*N*/
+/*N*/ for ( USHORT i = pLine->GetStartPortion(); i < nTextPortion; i++ )
+/*N*/ {
+/*N*/ TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
+/*N*/ switch ( pPortion->GetKind() )
+/*N*/ {
+/*N*/ case PORTIONKIND_FIELD:
+/*N*/ case PORTIONKIND_TEXT:
+/*N*/ case PORTIONKIND_HYPHENATOR:
+/*N*/ case PORTIONKIND_TAB:
+/*N*/ // case PORTIONKIND_EXTRASPACE:
+/*N*/ {
+/*N*/ nX += pPortion->GetSize().Width();
+/*N*/ }
+/*N*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/
+/*N*/ USHORT nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
+/*N*/ BOOL bR2LPara = IsRightToLeft( nPara );
+/*N*/
+/*N*/ TextPortion* pDestPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+/*N*/ if ( pDestPortion->GetKind() != PORTIONKIND_TAB )
+/*N*/ {
+/*N*/ if ( !bR2LPara && pDestPortion->GetRightToLeft() )
+/*N*/ {
+/*?*/ // Portions behind must be added, visual before this portion
+/*?*/ sal_uInt16 nTmpPortion = nTextPortion+1;
+/*?*/ while ( nTmpPortion <= pLine->GetEndPortion() )
+/*?*/ {
+/*?*/ TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+/*?*/ if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
+/*?*/ nX += pNextTextPortion->GetSize().Width();
+/*?*/ else
+/*?*/ break;
+/*?*/ nTmpPortion++;
+/*?*/ }
+/*?*/ // Portions before must be removed, visual behind this portion
+/*?*/ nTmpPortion = nTextPortion;
+/*?*/ while ( nTmpPortion > pLine->GetStartPortion() )
+/*?*/ {
+/*?*/ --nTmpPortion;
+/*?*/ TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+/*?*/ if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
+/*?*/ nX -= pPrevTextPortion->GetSize().Width();
+/*?*/ else
+/*?*/ break;
+/*?*/ }
+/*N*/ }
+/*N*/ else if ( bR2LPara && !pDestPortion->IsRightToLeft() )
+/*N*/ {
+/*?*/ // Portions behind must be ermoved, visual behind this portion
+/*?*/ sal_uInt16 nTmpPortion = nTextPortion+1;
+/*?*/ while ( nTmpPortion <= pLine->GetEndPortion() )
+/*?*/ {
+/*?*/ TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+/*?*/ if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
+/*?*/ nX += pNextTextPortion->GetSize().Width();
+/*?*/ else
+/*?*/ break;
+/*?*/ nTmpPortion++;
+/*?*/ }
+/*?*/ // Portions before must be added, visual before this portion
+/*?*/ nTmpPortion = nTextPortion;
+/*?*/ while ( nTmpPortion > pLine->GetStartPortion() )
+/*?*/ {
+/*?*/ --nTmpPortion;
+/*?*/ TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+/*?*/ if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
+/*?*/ nX -= pPrevTextPortion->GetSize().Width();
+/*?*/ else
+/*?*/ break;
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bR2LPara )
+/*N*/ {
+/*?*/ // Switch X postions...
+/*?*/ DBG_ASSERT( GetTextRanger() || GetPaperSize().Width(), "GetPortionXOffset - paper size?!" );
+/*?*/ DBG_ASSERT( GetTextRanger() || (nX <= GetPaperSize().Width()), "GetPortionXOffset - position out of paper size!" );
+/*?*/ nX = GetPaperSize().Width() - nX;
+/*?*/ nX -= pDestPortion->GetSize().Width();
+/*N*/ }
+/*N*/
+/*N*/ return nX;
+/*N*/ }
+
+
+/*N*/ void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
+/*N*/ {
+/*N*/ pPortion->nHeight = 0;
+/*N*/ pPortion->nFirstLineOffset = 0;
+/*N*/
+/*N*/ if ( pPortion->IsVisible() )
+/*N*/ {
+/*N*/ DBG_ASSERT( pPortion->GetLines().Count(), "Absatz ohne Zeilen in ParaPortion::CalcHeight" );
+/*N*/ for ( USHORT nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+/*N*/ pPortion->nHeight += pPortion->GetLines().GetObject( nLine )->GetHeight();
+/*N*/
+/*N*/ if ( !aStatus.IsOutliner() )
+/*N*/ {
+/*N*/ const SvxULSpaceItem& rULItem = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+/*N*/ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+/*N*/ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+/*N*/
+/*N*/ if ( nSBL )
+/*N*/ {
+/*?*/ if ( pPortion->GetLines().Count() > 1 )
+/*?*/ pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL;
+/*?*/ if ( aStatus.ULSpaceSummation() )
+/*?*/ pPortion->nHeight += nSBL;
+/*N*/ }
+/*N*/
+/*N*/ USHORT nPortion = GetParaPortions().GetPos( pPortion );
+/*N*/ if ( nPortion || aStatus.ULSpaceFirstParagraph() )
+/*N*/ {
+/*N*/ USHORT nUpper = GetYValue( rULItem.GetUpper() );
+/*N*/ pPortion->nHeight += nUpper;
+/*N*/ pPortion->nFirstLineOffset = nUpper;
+/*N*/ }
+/*N*/
+/*N*/ if ( ( nPortion != (GetParaPortions().Count()-1) ) )
+/*N*/ {
+/*N*/ pPortion->nHeight += GetYValue( rULItem.GetLower() ); // nicht in letzter
+/*N*/ }
+/*N*/
+/*N*/
+/*N*/ if ( nPortion && !aStatus.ULSpaceSummation() )
+/*N*/ {
+/*N*/ ParaPortion* pPrev = GetParaPortions().SaveGetObject( nPortion-1 );
+/*N*/ const SvxULSpaceItem& rPrevULItem = (const SvxULSpaceItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+/*N*/ const SvxLineSpacingItem& rPrevLSItem = (const SvxLineSpacingItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+/*N*/
+/*N*/ // Verhalten WinWord6/Writer3:
+/*N*/ // Bei einem proportionalen Zeilenabstand wird auch der Absatzabstand
+/*N*/ // manipuliert.
+/*N*/ // Nur Writer3: Nicht aufaddieren, sondern Mindestabstand.
+/*N*/
+/*N*/ // Pruefen, ob Abstand durch LineSpacing > Upper:
+/*N*/ USHORT nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPortion, rLSItem ) );
+/*N*/ if ( nExtraSpace > pPortion->nFirstLineOffset )
+/*N*/ {
+/*?*/ // Absatz wird 'groesser':
+/*?*/ pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
+/*?*/ pPortion->nFirstLineOffset = nExtraSpace;
+/*N*/ }
+/*N*/
+/*N*/ // nFirstLineOffset jetzt f(pNode) => jetzt f(pNode, pPrev) ermitteln:
+/*N*/ USHORT nPrevLower = GetYValue( rPrevULItem.GetLower() );
+/*N*/
+/*N*/ // Dieser PrevLower steckt noch in der Hoehe der PrevPortion...
+/*N*/ if ( nPrevLower > pPortion->nFirstLineOffset )
+/*N*/ {
+/*N*/ // Absatz wird 'kleiner':
+/*N*/ pPortion->nHeight -= pPortion->nFirstLineOffset;
+/*N*/ pPortion->nFirstLineOffset = 0;
+/*N*/ }
+/*N*/ else if ( nPrevLower )
+/*N*/ {
+/*?*/ // Absatz wird 'etwas kleiner':
+/*?*/ pPortion->nHeight -= nPrevLower;
+/*?*/ pPortion->nFirstLineOffset -= nPrevLower;
+/*N*/ }
+/*N*/
+/*N*/ // Finde ich zwar nicht so gut, aber Writer3-Feature:
+/*N*/ // Pruefen, ob Abstand durch LineSpacing > Lower:
+/*N*/ // Dieser Wert steckt nicht in der Hoehe der PrevPortion.
+/*N*/ if ( !pPrev->IsInvalid() )
+/*N*/ {
+/*N*/ nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPrev, rPrevLSItem ) );
+/*N*/ if ( nExtraSpace > nPrevLower )
+/*N*/ {
+/*?*/ USHORT nMoreLower = nExtraSpace - nPrevLower;
+/*?*/ // Absatz wird 'groesser', 'waechst' nach unten:
+/*?*/ if ( nMoreLower > pPortion->nFirstLineOffset )
+/*?*/ {
+/*?*/ pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
+/*?*/ pPortion->nFirstLineOffset = nMoreLower;
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+
+/*N*/ void ImpEditEngine::SetValidPaperSize( const Size& rNewSz )
+/*N*/ {
+/*N*/ aPaperSize = rNewSz;
+/*N*/
+/*N*/ long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0;
+/*N*/ long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF;
+/*N*/ long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0;
+/*N*/ long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF;
+/*N*/
+/*N*/ // Minimale/Maximale Breite:
+/*N*/ if ( aPaperSize.Width() < nMinWidth )
+/*N*/ aPaperSize.Width() = nMinWidth;
+/*N*/ else if ( aPaperSize.Width() > nMaxWidth )
+/*?*/ aPaperSize.Width() = nMaxWidth;
+/*N*/
+/*N*/ // Minimale/Maximale Hoehe:
+/*N*/ if ( aPaperSize.Height() < nMinHeight )
+/*?*/ aPaperSize.Height() = nMinHeight;
+/*N*/ else if ( aPaperSize.Height() > nMaxHeight )
+/*?*/ aPaperSize.Height() = nMaxHeight;
+/*N*/ }
+
+
+/*N*/ rtl::Reference<SvxForbiddenCharactersTable> ImpEditEngine::GetForbiddenCharsTable( BOOL bGetInternal ) const
+/*N*/ {
+/*N*/ rtl::Reference<SvxForbiddenCharactersTable> xF = xForbiddenCharsTable;
+/*N*/ if ( !xF.is() && bGetInternal )
+/*N*/ xF = EE_DLL()->GetGlobalData()->GetForbiddenCharsTable();
+/*N*/ return xF;
+/*N*/ }
+
+/*N*/ void ImpEditEngine::SetForbiddenCharsTable( rtl::Reference<SvxForbiddenCharactersTable> xForbiddenChars )
+/*N*/ {
+/*N*/ EE_DLL()->GetGlobalData()->SetForbiddenCharsTable( xForbiddenChars );
+/*N*/ }
+
+ ColorConfig& ImpEditEngine::GetColorConfig()
+/*N*/ {
+/*N*/ if ( !pColorConfig )
+/*N*/ pColorConfig = new ColorConfig;
+/*N*/
+/*N*/ return *pColorConfig;
+/*N*/ }
+
+
+
+
+
+/*N*/ void ImpEditEngine::EnterBlockNotifications()
+/*N*/ {
+/*N*/ if( !nBlockNotifications )
+/*N*/ {
+/*N*/ // #109864# Send out START notification immediately, to allow
+/*N*/ // external, non-queued events to be captured as well from
+/*N*/ // client side
+/*N*/ EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_START );
+/*N*/ aNotify.pEditEngine = GetEditEnginePtr();
+/*N*/ GetNotifyHdl().Call( &aNotify );
+/*N*/ }
+/*N*/
+/*N*/ nBlockNotifications++;
+/*N*/ }
+
+/*N*/ void ImpEditEngine::LeaveBlockNotifications()
+/*N*/ {
+/*N*/ DBG_ASSERT( nBlockNotifications, "LeaveBlockNotifications - Why?" );
+/*N*/
+/*N*/ nBlockNotifications--;
+/*N*/ if ( !nBlockNotifications )
+/*N*/ {
+/*N*/ // Call blocked notify events...
+/*N*/ while ( aNotifyCache.Count() )
+/*N*/ {
+/*N*/ EENotify* pNotify = aNotifyCache[0];
+/*N*/ // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
+/*N*/ aNotifyCache.Remove( 0 );
+/*N*/ GetNotifyHdl().Call( pNotify );
+/*N*/ delete pNotify;
+/*N*/ }
+/*N*/
+/*N*/ EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_END );
+/*N*/ aNotify.pEditEngine = GetEditEnginePtr();
+/*N*/ GetNotifyHdl().Call( &aNotify );
+/*N*/ }
+/*N*/ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */