summaryrefslogtreecommitdiff
path: root/editeng/source/editeng/impedit5.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'editeng/source/editeng/impedit5.cxx')
-rw-r--r--editeng/source/editeng/impedit5.cxx911
1 files changed, 911 insertions, 0 deletions
diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx
new file mode 100644
index 000000000000..2efbb60b6c0f
--- /dev/null
+++ b/editeng/source/editeng/impedit5.cxx
@@ -0,0 +1,911 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <eeng_pch.hxx>
+
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editdbg.hxx>
+
+#include <svl/smplhint.hxx>
+
+
+#include <editeng/lrspitem.hxx>
+
+void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
+{
+ if ( pStylePool != pSPool )
+ {
+// if ( pStylePool )
+// EndListening( *pStylePool, TRUE );
+
+ pStylePool = pSPool;
+
+// if ( pStylePool )
+// StartListening( *pStylePool, TRUE );
+ }
+}
+
+SfxStyleSheet* ImpEditEngine::GetStyleSheet( USHORT nPara ) const
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
+}
+
+void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle )
+{
+ aSel.Adjust( aEditDoc );
+
+ USHORT nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ BOOL _bUpdate = GetUpdateMode();
+ SetUpdateMode( FALSE );
+
+ for ( USHORT n = nStartPara; n <= nEndPara; n++ )
+ SetStyleSheet( n, pStyle );
+
+ SetUpdateMode( _bUpdate, 0 );
+}
+
+void ImpEditEngine::SetStyleSheet( USHORT nPara, SfxStyleSheet* pStyle )
+{
+ DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
+ if ( pStyle != pCurStyle )
+ {
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ XubString aPrevStyleName;
+ if ( pCurStyle )
+ aPrevStyleName = pCurStyle->GetName();
+
+ XubString aNewStyleName;
+ if ( pStyle )
+ aNewStyleName = pStyle->GetName();
+
+ InsertUndo(
+ new EditUndoSetStyleSheet( this, aEditDoc.GetPos( pNode ),
+ aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
+ aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
+ pNode->GetContentAttribs().GetItems() ) );
+ }
+ if ( pCurStyle )
+ EndListening( *pCurStyle, FALSE );
+ pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
+ if ( pStyle )
+ StartListening( *pStyle, FALSE );
+ ParaAttribsChanged( pNode );
+ }
+ FormatAndUpdate();
+}
+
+void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle )
+{
+ SvxFont aFontFromStyle;
+ CreateFont( aFontFromStyle, pStyle->GetItemSet() );
+
+ BOOL bUsed = FALSE;
+ for ( USHORT nNode = 0; nNode < aEditDoc.Count(); nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ if ( pNode->GetStyleSheet() == pStyle )
+ {
+ bUsed = TRUE;
+ if ( aStatus.UseCharAttribs() )
+ pNode->SetStyleSheet( pStyle, aFontFromStyle );
+ else
+ pNode->SetStyleSheet( pStyle, FALSE );
+
+ ParaAttribsChanged( pNode );
+ }
+ }
+ if ( bUsed )
+ {
+ GetEditEnginePtr()->StyleSheetChanged( pStyle );
+ FormatAndUpdate();
+ }
+}
+
+void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle )
+{
+ for ( USHORT nNode = 0; nNode < aEditDoc.Count(); nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject(nNode);
+ if ( pNode->GetStyleSheet() == pStyle )
+ {
+ pNode->SetStyleSheet( NULL );
+ ParaAttribsChanged( pNode );
+ }
+ }
+ FormatAndUpdate();
+}
+
+void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ // Damit nicht beim Destruieren unnoetig formatiert wird:
+ if ( !bDowning )
+ {
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ SfxStyleSheet* pStyle = NULL;
+ ULONG nId = 0;
+
+ if ( rHint.ISA( SfxStyleSheetHint ) )
+ {
+ const SfxStyleSheetHint& rH = (const SfxStyleSheetHint&) rHint;
+ DBG_ASSERT( rH.GetStyleSheet()->ISA( SfxStyleSheet ), "Kein SfxStyleSheet!" );
+ pStyle = (SfxStyleSheet*) rH.GetStyleSheet();
+ nId = rH.GetHint();
+ }
+ else if ( ( rHint.Type() == TYPE(SfxSimpleHint ) ) && ( rBC.ISA( SfxStyleSheet ) ) )
+ {
+ pStyle = (SfxStyleSheet*)&rBC;
+ nId = ((SfxSimpleHint&)rHint).GetId();
+ }
+
+ if ( pStyle )
+ {
+ if ( ( nId == SFX_HINT_DYING ) ||
+ ( nId == SFX_STYLESHEET_INDESTRUCTION ) ||
+ ( nId == SFX_STYLESHEET_ERASED ) )
+ {
+ RemoveStyleFromParagraphs( pStyle );
+ }
+ else if ( ( nId == SFX_HINT_DATACHANGED ) ||
+ ( nId == SFX_STYLESHEET_MODIFIED ) )
+ {
+ UpdateParagraphsWithStyleSheet( pStyle );
+
+ // Alle Absaetze mit EditStyles, die das geaenderte Style
+ // irgendwie als Parent haben, muessen formatiert werden.
+ // ULONG nStyles = pMyStylePool->GetStyles().Count();
+ // for ( ULONG nStyle = 0; nStyle < nStyles; nStyle++ )
+ // {
+ // EditStyleSheet* pES = (EditStyleSheet*)pMyStylePool->GetStyles().GetObject( nStyle );
+ // DBG_ASSERT( pES, "NULL-Pointer im StyleSheetPool!" );
+ // if ( pES->IsUsed() && pES->HasStyleAsAnyParent( *pStyle ) )
+ // UpdateParagraphsWithStyleSheet( pES );
+ // }
+ }
+ }
+ }
+}
+
+EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
+{
+ DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Fehlerhafte Selektion" );
+ aSel.Adjust( aEditDoc );
+
+ ESelection aESel( CreateESel( aSel ) );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
+
+ EditUndoSetAttribs* pUndo = NULL;
+ if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
+ {
+ SfxItemSet aTmpSet( GetEmptyItemSet() );
+ aTmpSet.Put( rSet );
+ pUndo = new EditUndoSetAttribs( this, aESel, aTmpSet );
+ }
+ else
+ {
+ pUndo = new EditUndoSetAttribs( this, aESel, rSet );
+ }
+
+ SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
+
+ for ( USHORT nPara = nStartNode; nPara <= nEndNode; nPara++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( aEditDoc.SaveGetObject( nPara ), "Node nicht gefunden: CreateAttribUndo" );
+ ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
+ pUndo->GetContentInfos().Insert( pInf, pUndo->GetContentInfos().Count() );
+
+ for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
+ if ( pAttr->GetLen() )
+ {
+ EditCharAttribPtr pNew = MakeCharAttrib( *pPool, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
+ pInf->GetPrevCharAttribs().Insert( pNew, pInf->GetPrevCharAttribs().Count() );
+ }
+ }
+ }
+ return pUndo;
+}
+
+void ImpEditEngine::UndoActionStart( USHORT nId, const ESelection& aSel )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
+ DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
+ pUndoMarkSelection = new ESelection( aSel );
+ }
+}
+
+void ImpEditEngine::UndoActionStart( USHORT nId )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
+ DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
+ }
+}
+
+void ImpEditEngine::UndoActionEnd( USHORT )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ GetUndoManager().LeaveListAction();
+ delete pUndoMarkSelection;
+ pUndoMarkSelection = NULL;
+ }
+}
+
+void ImpEditEngine::InsertUndo( EditUndo* pUndo, BOOL bTryMerge )
+{
+ DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" );
+ if ( pUndoMarkSelection )
+ {
+ EditUndoMarkSelection* pU = new EditUndoMarkSelection( this, *pUndoMarkSelection );
+ GetUndoManager().AddUndoAction( pU, FALSE );
+ delete pUndoMarkSelection;
+ pUndoMarkSelection = NULL;
+ }
+ GetUndoManager().AddUndoAction( pUndo, bTryMerge );
+
+ mbLastTryMerge = bTryMerge;
+}
+
+void ImpEditEngine::ResetUndoManager()
+{
+ if ( HasUndoManager() )
+ GetUndoManager().Clear();
+}
+
+void ImpEditEngine::EnableUndo( BOOL bEnable )
+{
+ // Beim Umschalten des Modus Liste loeschen:
+ if ( bEnable != IsUndoEnabled() )
+ ResetUndoManager();
+
+ bUndoEnabled = bEnable;
+}
+
+BOOL ImpEditEngine::Undo( EditView* pView )
+{
+ if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
+ {
+ SetActiveView( pView );
+ GetUndoManager().Undo( 1 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ImpEditEngine::Redo( EditView* pView )
+{
+ if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
+ {
+ SetActiveView( pView );
+ GetUndoManager().Redo( 0 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ImpEditEngine::Repeat( EditView* /* pView */ )
+{
+ if ( HasUndoManager() && GetUndoManager().GetRepeatActionCount() )
+ {
+ DBG_WARNING( "Repeat nicht implementiert!" );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, BOOL bOnlyHardAttrib )
+{
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ aSel.Adjust( aEditDoc );
+
+#if OSL_DEBUG_LEVEL > 1
+// if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) && ( bOnlyHardAttrib == EditEngineAttribs_All ) )
+// return GetAttribs( aEditDoc.GetPos( aSel.Min().GetNode() ), aSel.Min().GetIndex(), aSel.Max().GetIndex(), GETATTRIBS_ALL );
+#endif
+
+
+ SfxItemSet aCurSet( GetEmptyItemSet() );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetAttrib" );
+
+ xub_StrLen nStartPos = 0;
+ xub_StrLen nEndPos = pNode->Len();
+ if ( nNode == nStartNode )
+ nStartPos = aSel.Min().GetIndex();
+ if ( nNode == nEndNode ) // kann auch == nStart sein!
+ nEndPos = aSel.Max().GetIndex();
+
+ // Problem: Vorlagen....
+ // => Andersrum:
+ // 1) Harte Zeichenattribute, wie gehabt...
+ // 2) Nur wenn OFF, Style and Absatzattr. pruefen...
+
+ // Erst die ganz harte Formatierung...
+ aEditDoc.FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
+
+ if( bOnlyHardAttrib != EditEngineAttribs_OnlyHard )
+ {
+ // Und dann Absatzformatierung und Vorlage...
+ // SfxStyleSheet* pStyle = pNode->GetStyleSheet();
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
+ {
+ if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
+ {
+ if ( bOnlyHardAttrib == EditEngineAttribs_All )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
+ aCurSet.Put( rItem );
+ }
+ else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
+ aCurSet.Put( rItem );
+ }
+ }
+ else if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem* pItem = NULL;
+ if ( bOnlyHardAttrib == EditEngineAttribs_All )
+ {
+ pItem = &pNode->GetContentAttribs().GetItem( nWhich );
+ }
+ else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
+ }
+ // pItem can only be NULL when bOnlyHardAttrib...
+ if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
+ {
+ // Problem: Wenn Absatzvorlage mit z.B. Font,
+ // aber Font hart und anders und komplett in Selektion
+ // Falsch, wenn invalidiert....
+ // => Lieber nicht invalidieren, UMSTELLEN!
+ // Besser waere, Absatzweise ein ItemSet zu fuellen
+ // und dieses mit dem gesmten vergleichen.
+ // aCurSet.InvalidateItem( nWhich );
+ if ( nWhich <= EE_PARA_END )
+ aCurSet.InvalidateItem( nWhich );
+ }
+ }
+ }
+ }
+ }
+
+ // Leere Slots mit Defaults fuellen...
+ if ( bOnlyHardAttrib == EditEngineAttribs_All )
+ {
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
+ {
+ aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
+ }
+ }
+ }
+ return aCurSet;
+}
+
+
+SfxItemSet ImpEditEngine::GetAttribs( USHORT nPara, USHORT nStart, USHORT nEnd, sal_uInt8 nFlags ) const
+{
+ // MT: #94002# Optimized function with less Puts(), which cause unnecessary cloning from default items.
+ // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
+
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
+ DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
+
+ SfxItemSet aAttribs( ((ImpEditEngine*)this)->GetEmptyItemSet() );
+
+ if ( pNode )
+ {
+ if ( nEnd > pNode->Len() )
+ nEnd = pNode->Len();
+
+ if ( nStart > nEnd )
+ nStart = nEnd;
+
+ // StyleSheet / Parattribs...
+
+ if ( pNode->GetStyleSheet() && ( nFlags & GETATTRIBS_STYLESHEET ) )
+ aAttribs.Set( pNode->GetStyleSheet()->GetItemSet(), TRUE );
+
+ if ( nFlags & GETATTRIBS_PARAATTRIBS )
+ aAttribs.Put( pNode->GetContentAttribs().GetItems() );
+
+ // CharAttribs...
+
+ if ( nFlags & GETATTRIBS_CHARATTRIBS )
+ {
+ // Make testing easier...
+ pNode->GetCharAttribs().OptimizeRanges( ((ImpEditEngine*)this)->GetEditDoc().GetItemPool() );
+
+ const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
+ for ( USHORT nAttr = 0; nAttr < rAttrs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttrs.GetObject( nAttr );
+
+ if ( nStart == nEnd )
+ {
+ USHORT nCursorPos = nStart;
+ if ( ( pAttr->GetStart() <= nCursorPos ) && ( pAttr->GetEnd() >= nCursorPos ) )
+ {
+ // To be used the attribute has to start BEFORE the position, or it must be a
+ // new empty attr AT the position, or we are on position 0.
+ if ( ( pAttr->GetStart() < nCursorPos ) || pAttr->IsEmpty() || !nCursorPos )
+ {
+ // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
+ // but that s no problem, the empty item will come later and win.
+ aAttribs.Put( *pAttr->GetItem() );
+ }
+ }
+ }
+ else
+ {
+ // Check every attribute covering the area, partial or full.
+ if ( ( pAttr->GetStart() < nEnd ) && ( pAttr->GetEnd() > nStart ) )
+ {
+ if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
+ {
+ // full coverage
+ aAttribs.Put( *pAttr->GetItem() );
+ }
+ else
+ {
+ // OptimizeRagnge() assures that not the same attr can follow for full coverage
+ // only partial, check with current, when using para/styhe, otherwise invalid.
+ if ( !( nFlags & (GETATTRIBS_PARAATTRIBS|GETATTRIBS_STYLESHEET) ) ||
+ ( *pAttr->GetItem() != aAttribs.Get( pAttr->Which() ) ) )
+ {
+ aAttribs.InvalidateItem( pAttr->Which() );
+ }
+ }
+ }
+ }
+
+ if ( pAttr->GetStart() > nEnd )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return aAttribs;
+}
+
+
+void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, BYTE nSpecial )
+{
+ aSel.Adjust( aEditDoc );
+
+ // Wenn keine Selektion => die Attribute aufs Wort anwenden.
+ // ( Der RTF-Perser sollte die Methode eigentlich nie ohne Range rufen )
+ if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
+ aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, FALSE );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
+ pUndo->SetSpecial( nSpecial );
+ InsertUndo( pUndo );
+ }
+
+ BOOL bCheckLanguage = FALSE;
+ if ( GetStatus().DoOnlineSpelling() )
+ {
+ bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SFX_ITEM_ON ) ||
+ ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SFX_ITEM_ON ) ||
+ ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SFX_ITEM_ON );
+ }
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ BOOL bParaAttribFound = FALSE;
+ BOOL bCharAttribFound = FALSE;
+
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
+
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
+ DBG_ASSERT( GetParaPortions().GetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
+
+ xub_StrLen nStartPos = 0;
+ xub_StrLen nEndPos = pNode->Len();
+ if ( nNode == nStartNode )
+ nStartPos = aSel.Min().GetIndex();
+ if ( nNode == nEndNode ) // kann auch == nStart sein!
+ nEndPos = aSel.Max().GetIndex();
+
+ // ueber die Items iterieren...
+#ifdef EDITDEBUG
+// FILE* fp = fopen( "d:\\debug.log", "a" );
+// if ( fp )
+// {
+// fprintf( fp, "\n \n=> Zeichen-Attribute: Absatz %i, %i-%i\n", nNode, nStartPos, nEndPos );
+// DbgOutItemSet( fp, rSet, TRUE, FALSE );
+// fclose( fp );
+// }
+#endif
+
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
+ {
+ if ( rSet.GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = rSet.Get( nWhich );
+ if ( nWhich <= EE_PARA_END )
+ {
+ pNode->GetContentAttribs().GetItems().Put( rItem );
+ bParaAttribFound = TRUE;
+ }
+ else
+ {
+ aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
+ bCharAttribFound = TRUE;
+ if ( nSpecial == ATTRSPECIAL_EDGE )
+ {
+ CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
+ USHORT nAttrs = rAttribs.Count();
+ for ( USHORT n = 0; n < nAttrs; n++ )
+ {
+ EditCharAttrib* pAttr = rAttribs.GetObject( n );
+ if ( pAttr->GetStart() > nEndPos )
+ break;
+
+ if ( ( pAttr->GetEnd() == nEndPos ) && ( pAttr->Which() == nWhich ) )
+ {
+ pAttr->SetEdge( TRUE );
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( bParaAttribFound )
+ {
+ ParaAttribsChanged( pPortion->GetNode() );
+ }
+ else if ( bCharAttribFound )
+ {
+ bFormatted = FALSE;
+ if ( !pNode->Len() || ( nStartPos != nEndPos ) )
+ {
+ pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
+ if ( bCheckLanguage )
+ pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos );
+ }
+ }
+ }
+}
+
+void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, BOOL bRemoveParaAttribs, USHORT nWhich )
+{
+ aSel.Adjust( aEditDoc );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
+
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ // Eventuel spezielles Undo, oder ItemSet*
+ EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
+ pUndo->SetRemoveAttribs( TRUE );
+ pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
+ pUndo->SetRemoveWhich( nWhich );
+ InsertUndo( pUndo );
+ }
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
+
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
+ DBG_ASSERT( GetParaPortions().SaveGetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
+
+ xub_StrLen nStartPos = 0;
+ xub_StrLen nEndPos = pNode->Len();
+ if ( nNode == nStartNode )
+ nStartPos = aSel.Min().GetIndex();
+ if ( nNode == nEndNode ) // kann auch == nStart sein!
+ nEndPos = aSel.Max().GetIndex();
+
+ // Optimieren: Wenn ganzer Absatz, dann RemoveCharAttribs( nPara )?!
+ BOOL bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
+ if ( bRemoveParaAttribs )
+ {
+ SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidiert
+ }
+ else
+ {
+ // Bei 'Format-Standard' sollen auch die Zeichenattribute verschwinden,
+ // die von der DrawingEngine als Absatzattribute eingestellt wurden.
+ // Diese koennen sowieso nicht vom Anwender eingestellt worden sein.
+
+ // #106871# Not when nWhich
+ // Would have been better to offer a separate method for format/standard...
+ if ( !nWhich )
+ {
+ SfxItemSet aAttribs( GetParaAttribs( nNode ) );
+ for ( USHORT nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
+ aAttribs.ClearItem( nW );
+ SetParaAttribs( nNode, aAttribs );
+ }
+ }
+
+ if ( bChanged && !bRemoveParaAttribs )
+ {
+ bFormatted = FALSE;
+ pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
+ }
+ }
+}
+
+typedef EditCharAttrib* EditCharAttribPtr;
+
+void ImpEditEngine::RemoveCharAttribs( USHORT nPara, USHORT nWhich, BOOL bRemoveFeatures )
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ ParaPortion* pPortion = GetParaPortions().SaveGetObject( nPara );
+
+ DBG_ASSERT( pNode, "Node nicht gefunden: RemoveCharAttribs" );
+ DBG_ASSERT( pPortion, "Portion nicht gefunden: RemoveCharAttribs" );
+
+ if ( !pNode )
+ return;
+
+ USHORT nAttr = 0;
+ EditCharAttribPtr pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttr )
+ {
+ if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
+ ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
+ {
+ pNode->GetCharAttribs().GetAttribs().Remove( nAttr );
+ delete pAttr;
+ nAttr--;
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+
+ pPortion->MarkSelectionInvalid( 0, pNode->Len() );
+}
+
+void ImpEditEngine::SetParaAttribs( USHORT nPara, const SfxItemSet& rSet )
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+
+ if ( !pNode )
+ return;
+
+#ifdef EDITDEBUG
+// FILE* fp = fopen( "d:\\debug.log", "a" );
+// if ( fp )
+// {
+// fprintf( fp, "\n \n=> Absatz-Attribute: Absatz %i\n", nPara );
+// DbgOutItemSet( fp, rSet, TRUE, FALSE );
+// fclose( fp );
+// }
+#endif
+
+ if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
+ {
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
+ {
+ SfxItemSet aTmpSet( GetEmptyItemSet() );
+ aTmpSet.Put( rSet );
+ InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet ) );
+ }
+ else
+ {
+ InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), rSet ) );
+ }
+ }
+ pNode->GetContentAttribs().GetItems().Set( rSet );
+ if ( aStatus.UseCharAttribs() )
+ pNode->CreateDefFont();
+
+ ParaAttribsChanged( pNode );
+ }
+}
+
+const SfxItemSet& ImpEditEngine::GetParaAttribs( USHORT nPara ) const
+{
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttribs" );
+ return pNode->GetContentAttribs().GetItems();
+}
+
+BOOL ImpEditEngine::HasParaAttrib( USHORT nPara, USHORT nWhich ) const
+{
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( pNode, "Node nicht gefunden: HasParaAttrib" );
+
+ return pNode->GetContentAttribs().HasItem( nWhich );
+}
+
+const SfxPoolItem& ImpEditEngine::GetParaAttrib( USHORT nPara, USHORT nWhich ) const
+{
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttrib" );
+
+ return pNode->GetContentAttribs().GetItem( nWhich );
+}
+
+void ImpEditEngine::GetCharAttribs( USHORT nPara, EECharAttribArray& rLst ) const
+{
+ rLst.Remove( 0, rLst.Count() );
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ if ( pNode )
+ {
+ for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
+ EECharAttrib aEEAttr;
+ aEEAttr.pAttr = pAttr->GetItem();
+ aEEAttr.nPara = nPara;
+ aEEAttr.nStart = pAttr->GetStart();
+ aEEAttr.nEnd = pAttr->GetEnd();
+ rLst.Insert( aEEAttr, rLst.Count() );
+ }
+ }
+}
+
+void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
+{
+ pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
+ xub_StrLen nEndPos = pNode->Len();
+ for ( USHORT nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ if ( pNode->GetContentAttribs().HasItem( nWhich ) )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
+ // Die Luecken auffuellen:
+ USHORT nLastEnd = 0;
+ EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
+ while ( pAttr )
+ {
+ nLastEnd = pAttr->GetEnd();
+ if ( pAttr->GetStart() > nLastEnd )
+ aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
+ // #112831# Last Attr might go from 0xffff to 0x0000
+ pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : NULL;
+ }
+
+ // Und den Rest:
+ if ( nLastEnd < nEndPos )
+ aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
+ }
+ }
+ bFormatted = FALSE;
+ // Portion braucht hier nicht invalidiert werden, geschieht woanders.
+}
+
+IdleFormattter::IdleFormattter()
+{
+ pView = 0;
+ nRestarts = 0;
+}
+
+IdleFormattter::~IdleFormattter()
+{
+ pView = 0;
+}
+
+void IdleFormattter::DoIdleFormat( EditView* pV )
+{
+ pView = pV;
+
+ if ( IsActive() )
+ nRestarts++;
+
+ if ( nRestarts > 4 )
+ ForceTimeout();
+ else
+ Start();
+}
+
+void IdleFormattter::ForceTimeout()
+{
+ if ( IsActive() )
+ {
+ Stop();
+ ((Link&)GetTimeoutHdl()).Call( this );
+ }
+}
+
+ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const String& rOldTextAfterStartPos )
+ : aOldTextAfterStartPos( rOldTextAfterStartPos )
+{
+ aPos = rPos;
+ nLen = 0;
+ bCursor = TRUE;
+ pAttribs = NULL;
+ bWasCursorOverwrite = FALSE;
+}
+
+ImplIMEInfos::~ImplIMEInfos()
+{
+ delete[] pAttribs;
+}
+
+void ImplIMEInfos::CopyAttribs( const USHORT* pA, USHORT nL )
+{
+ nLen = nL;
+ delete pAttribs;
+ pAttribs = new USHORT[ nL ];
+ memcpy( pAttribs, pA, nL*sizeof(USHORT) );
+}
+
+void ImplIMEInfos::DestroyAttribs()
+{
+ delete[] pAttribs;
+ pAttribs = NULL;
+ nLen = 0;
+}