diff options
Diffstat (limited to 'binfilter/bf_svx/source/editeng/svx_impedit2.cxx')
-rw-r--r-- | binfilter/bf_svx/source/editeng/svx_impedit2.cxx | 2084 |
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: */ |