/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_editeng.hxx" #include #include #include #include #include #include void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) { if ( pStylePool != pSPool ) { // if ( pStylePool ) // EndListening( *pStylePool, sal_True ); pStylePool = pSPool; // if ( pStylePool ) // StartListening( *pStylePool, sal_True ); } } SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_uInt32 nPara ) const { ContentNode* pNode = aEditDoc.SaveGetObject( nPara ); return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL; } void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle ) { aSel.Adjust( aEditDoc ); sal_uInt32 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() ); sal_uInt32 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() ); sal_Bool _bUpdate = GetUpdateMode(); SetUpdateMode( sal_False ); for ( sal_uInt32 n = nStartPara; n <= nEndPara; n++ ) SetStyleSheet( n, pStyle ); SetUpdateMode( _bUpdate, 0 ); } void ImpEditEngine::SetStyleSheet( sal_uInt32 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, sal_False ); pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() ); if ( pStyle ) StartListening( *pStyle, sal_False ); ParaAttribsChanged( pNode ); } FormatAndUpdate(); } void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ) { SvxFont aFontFromStyle; CreateFont( aFontFromStyle, pStyle->GetItemSet() ); sal_Bool bUsed = sal_False; for ( sal_uInt32 nNode = 0; nNode < aEditDoc.Count(); nNode++ ) { ContentNode* pNode = aEditDoc.GetObject( nNode ); if ( pNode->GetStyleSheet() == pStyle ) { bUsed = sal_True; if ( aStatus.UseCharAttribs() ) pNode->SetStyleSheet( pStyle, aFontFromStyle ); else pNode->SetStyleSheet( pStyle, sal_False ); ParaAttribsChanged( pNode ); } } if ( bUsed ) { GetEditEnginePtr()->StyleSheetChanged( pStyle ); FormatAndUpdate(); } } void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle ) { for ( sal_uInt32 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; sal_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. // sal_uLong nStyles = pMyStylePool->GetStyles().Count(); // for ( sal_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 ) ); sal_uInt32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); sal_uInt32 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 ( sal_uInt32 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 ( sal_uInt16 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( sal_uInt16 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( sal_uInt16 nId ) { if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId ); DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" ); } } void ImpEditEngine::UndoActionEnd( sal_uInt16 ) { if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().LeaveListAction(); delete pUndoMarkSelection; pUndoMarkSelection = NULL; } } void ImpEditEngine::InsertUndo( EditUndo* pUndo, sal_Bool bTryMerge ) { DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" ); if ( pUndoMarkSelection ) { EditUndoMarkSelection* pU = new EditUndoMarkSelection( this, *pUndoMarkSelection ); GetUndoManager().AddUndoAction( pU, sal_False ); delete pUndoMarkSelection; pUndoMarkSelection = NULL; } GetUndoManager().AddUndoAction( pUndo, bTryMerge ); mbLastTryMerge = bTryMerge; } void ImpEditEngine::ResetUndoManager() { if ( HasUndoManager() ) GetUndoManager().Clear(); } void ImpEditEngine::EnableUndo( sal_Bool bEnable ) { // Beim Umschalten des Modus Liste loeschen: if ( bEnable != IsUndoEnabled() ) ResetUndoManager(); bUndoEnabled = bEnable; } sal_Bool ImpEditEngine::Undo( EditView* pView ) { if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() ) { SetActiveView( pView ); GetUndoManager().Undo(); return sal_True; } return sal_False; } sal_Bool ImpEditEngine::Redo( EditView* pView ) { if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() ) { SetActiveView( pView ); GetUndoManager().Redo(); return sal_True; } return sal_False; } sal_Bool ImpEditEngine::Repeat( EditView* /* pView */ ) { if ( HasUndoManager() && GetUndoManager().GetRepeatActionCount() ) { DBG_WARNING( "Repeat nicht implementiert!" ); return sal_True; } return sal_False; } SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, sal_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() ); sal_uInt32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); sal_uInt32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); // ueber die Absaetze iterieren... for ( sal_uInt32 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 ( sal_uInt16 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 ( sal_uInt16 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( sal_uInt32 nPara, sal_uInt16 nStart, sal_uInt16 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(), sal_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 ( sal_uInt16 nAttr = 0; nAttr < rAttrs.Count(); nAttr++ ) { EditCharAttrib* pAttr = rAttrs.GetObject( nAttr ); if ( nStart == nEnd ) { sal_uInt16 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, sal_uInt8 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, sal_False ); sal_uInt32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); sal_uInt32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) { EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet ); pUndo->SetSpecial( nSpecial ); InsertUndo( pUndo ); } sal_Bool bCheckLanguage = sal_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 ( sal_uInt32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { sal_Bool bParaAttribFound = sal_False; sal_Bool bCharAttribFound = sal_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, sal_True, sal_False ); // fclose( fp ); // } #endif for ( sal_uInt16 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 = sal_True; } else { aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); bCharAttribFound = sal_True; if ( nSpecial == ATTRSPECIAL_EDGE ) { CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs(); sal_uInt16 nAttrs = rAttribs.Count(); for ( sal_uInt16 n = 0; n < nAttrs; n++ ) { EditCharAttrib* pAttr = rAttribs.GetObject( n ); if ( pAttr->GetStart() > nEndPos ) break; if ( ( pAttr->GetEnd() == nEndPos ) && ( pAttr->Which() == nWhich ) ) { pAttr->SetEdge( sal_True ); break; } } } } } } if ( bParaAttribFound ) { ParaAttribsChanged( pPortion->GetNode() ); } else if ( bCharAttribFound ) { bFormatted = sal_False; if ( !pNode->Len() || ( nStartPos != nEndPos ) ) { pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos ); if ( bCheckLanguage ) pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos ); } } } } void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ) { aSel.Adjust( aEditDoc ); sal_uInt32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); sal_uInt32 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( sal_True ); pUndo->SetRemoveParaAttribs( bRemoveParaAttribs ); pUndo->SetRemoveWhich( nWhich ); InsertUndo( pUndo ); } // ueber die Absaetze iterieren... for ( sal_uInt32 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 )?! sal_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 ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ ) aAttribs.ClearItem( nW ); SetParaAttribs( nNode, aAttribs ); } } if ( bChanged && !bRemoveParaAttribs ) { bFormatted = sal_False; pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos ); } } } typedef EditCharAttrib* EditCharAttribPtr; void ImpEditEngine::RemoveCharAttribs( sal_uInt32 nPara, sal_uInt16 nWhich, sal_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; sal_uInt16 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( sal_uInt32 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, sal_True, sal_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( sal_uInt32 nPara ) const { ContentNode* pNode = aEditDoc.GetObject( nPara ); DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttribs" ); return pNode->GetContentAttribs().GetItems(); } sal_Bool ImpEditEngine::HasParaAttrib( sal_uInt32 nPara, sal_uInt16 nWhich ) const { ContentNode* pNode = aEditDoc.GetObject( nPara ); DBG_ASSERT( pNode, "Node nicht gefunden: HasParaAttrib" ); return pNode->GetContentAttribs().HasItem( nWhich ); } const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_uInt32 nPara, sal_uInt16 nWhich ) const { ContentNode* pNode = aEditDoc.GetObject( nPara ); DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttrib" ); return pNode->GetContentAttribs().GetItem( nWhich ); } void ImpEditEngine::GetCharAttribs( sal_uInt32 nPara, EECharAttribArray& rLst ) const { rLst.Remove( 0, rLst.Count() ); ContentNode* pNode = aEditDoc.GetObject( nPara ); if ( pNode ) { for ( sal_uInt16 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 ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ ) { if ( pNode->GetContentAttribs().HasItem( nWhich ) ) { const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich ); // Die Luecken auffuellen: sal_uInt16 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 = sal_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 = sal_True; pAttribs = NULL; bWasCursorOverwrite = sal_False; } ImplIMEInfos::~ImplIMEInfos() { delete[] pAttribs; } void ImplIMEInfos::CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL ) { nLen = nL; delete pAttribs; pAttribs = new sal_uInt16[ nL ]; memcpy( pAttribs, pA, nL*sizeof(sal_uInt16) ); } void ImplIMEInfos::DestroyAttribs() { delete[] pAttribs; pAttribs = NULL; nLen = 0; }