merge the formfield patch from ooo-build
[ooovba.git] / svx / source / editeng / impedit5.cxx
blobfde4e22e8caff8eaabf9ba20e671c869311ea36f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impedit5.cxx,v $
10 * $Revision: 1.34 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <eeng_pch.hxx>
36 #include <impedit.hxx>
37 #include <svx/editeng.hxx>
38 #include <editdbg.hxx>
40 #include <svtools/smplhint.hxx>
43 #include <svx/lrspitem.hxx>
45 void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
47 if ( pStylePool != pSPool )
49 // if ( pStylePool )
50 // EndListening( *pStylePool, TRUE );
52 pStylePool = pSPool;
54 // if ( pStylePool )
55 // StartListening( *pStylePool, TRUE );
59 SfxStyleSheet* ImpEditEngine::GetStyleSheet( USHORT nPara ) const
61 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
62 return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
65 void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle )
67 aSel.Adjust( aEditDoc );
69 USHORT nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
70 USHORT nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
72 BOOL _bUpdate = GetUpdateMode();
73 SetUpdateMode( FALSE );
75 for ( USHORT n = nStartPara; n <= nEndPara; n++ )
76 SetStyleSheet( n, pStyle );
78 SetUpdateMode( _bUpdate, 0 );
81 void ImpEditEngine::SetStyleSheet( USHORT nPara, SfxStyleSheet* pStyle )
83 DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
84 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
85 SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
86 if ( pStyle != pCurStyle )
88 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
90 XubString aPrevStyleName;
91 if ( pCurStyle )
92 aPrevStyleName = pCurStyle->GetName();
94 XubString aNewStyleName;
95 if ( pStyle )
96 aNewStyleName = pStyle->GetName();
98 InsertUndo(
99 new EditUndoSetStyleSheet( this, aEditDoc.GetPos( pNode ),
100 aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
101 aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
102 pNode->GetContentAttribs().GetItems() ) );
104 if ( pCurStyle )
105 EndListening( *pCurStyle, FALSE );
106 pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
107 if ( pStyle )
108 StartListening( *pStyle, FALSE );
109 ParaAttribsChanged( pNode );
111 FormatAndUpdate();
114 void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle )
116 SvxFont aFontFromStyle;
117 CreateFont( aFontFromStyle, pStyle->GetItemSet() );
119 BOOL bUsed = FALSE;
120 for ( USHORT nNode = 0; nNode < aEditDoc.Count(); nNode++ )
122 ContentNode* pNode = aEditDoc.GetObject( nNode );
123 if ( pNode->GetStyleSheet() == pStyle )
125 bUsed = TRUE;
126 if ( aStatus.UseCharAttribs() )
127 pNode->SetStyleSheet( pStyle, aFontFromStyle );
128 else
129 pNode->SetStyleSheet( pStyle, FALSE );
131 ParaAttribsChanged( pNode );
134 if ( bUsed )
136 GetEditEnginePtr()->StyleSheetChanged( pStyle );
137 FormatAndUpdate();
141 void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle )
143 for ( USHORT nNode = 0; nNode < aEditDoc.Count(); nNode++ )
145 ContentNode* pNode = aEditDoc.GetObject(nNode);
146 if ( pNode->GetStyleSheet() == pStyle )
148 pNode->SetStyleSheet( NULL );
149 ParaAttribsChanged( pNode );
152 FormatAndUpdate();
155 void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
157 // Damit nicht beim Destruieren unnoetig formatiert wird:
158 if ( !bDowning )
160 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
162 SfxStyleSheet* pStyle = NULL;
163 ULONG nId = 0;
165 if ( rHint.ISA( SfxStyleSheetHint ) )
167 const SfxStyleSheetHint& rH = (const SfxStyleSheetHint&) rHint;
168 DBG_ASSERT( rH.GetStyleSheet()->ISA( SfxStyleSheet ), "Kein SfxStyleSheet!" );
169 pStyle = (SfxStyleSheet*) rH.GetStyleSheet();
170 nId = rH.GetHint();
172 else if ( ( rHint.Type() == TYPE(SfxSimpleHint ) ) && ( rBC.ISA( SfxStyleSheet ) ) )
174 pStyle = (SfxStyleSheet*)&rBC;
175 nId = ((SfxSimpleHint&)rHint).GetId();
178 if ( pStyle )
180 if ( ( nId == SFX_HINT_DYING ) ||
181 ( nId == SFX_STYLESHEET_INDESTRUCTION ) ||
182 ( nId == SFX_STYLESHEET_ERASED ) )
184 RemoveStyleFromParagraphs( pStyle );
186 else if ( ( nId == SFX_HINT_DATACHANGED ) ||
187 ( nId == SFX_STYLESHEET_MODIFIED ) )
189 UpdateParagraphsWithStyleSheet( pStyle );
191 // Alle Absaetze mit EditStyles, die das geaenderte Style
192 // irgendwie als Parent haben, muessen formatiert werden.
193 // ULONG nStyles = pMyStylePool->GetStyles().Count();
194 // for ( ULONG nStyle = 0; nStyle < nStyles; nStyle++ )
195 // {
196 // EditStyleSheet* pES = (EditStyleSheet*)pMyStylePool->GetStyles().GetObject( nStyle );
197 // DBG_ASSERT( pES, "NULL-Pointer im StyleSheetPool!" );
198 // if ( pES->IsUsed() && pES->HasStyleAsAnyParent( *pStyle ) )
199 // UpdateParagraphsWithStyleSheet( pES );
200 // }
206 EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
208 DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Fehlerhafte Selektion" );
209 aSel.Adjust( aEditDoc );
211 ESelection aESel( CreateESel( aSel ) );
213 USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
214 USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
216 DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
218 EditUndoSetAttribs* pUndo = NULL;
219 if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
221 SfxItemSet aTmpSet( GetEmptyItemSet() );
222 aTmpSet.Put( rSet );
223 pUndo = new EditUndoSetAttribs( this, aESel, aTmpSet );
225 else
227 pUndo = new EditUndoSetAttribs( this, aESel, rSet );
230 SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
232 for ( USHORT nPara = nStartNode; nPara <= nEndNode; nPara++ )
234 ContentNode* pNode = aEditDoc.GetObject( nPara );
235 DBG_ASSERT( aEditDoc.SaveGetObject( nPara ), "Node nicht gefunden: CreateAttribUndo" );
236 ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
237 pUndo->GetContentInfos().Insert( pInf, pUndo->GetContentInfos().Count() );
239 for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
241 EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
242 if ( pAttr->GetLen() )
244 EditCharAttribPtr pNew = MakeCharAttrib( *pPool, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
245 pInf->GetPrevCharAttribs().Insert( pNew, pInf->GetPrevCharAttribs().Count() );
249 return pUndo;
252 void ImpEditEngine::UndoActionStart( USHORT nId, const ESelection& aSel )
254 if ( IsUndoEnabled() && !IsInUndo() )
256 GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
257 DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
258 pUndoMarkSelection = new ESelection( aSel );
262 void ImpEditEngine::UndoActionStart( USHORT nId )
264 if ( IsUndoEnabled() && !IsInUndo() )
266 GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
267 DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
271 void ImpEditEngine::UndoActionEnd( USHORT )
273 if ( IsUndoEnabled() && !IsInUndo() )
275 GetUndoManager().LeaveListAction();
276 delete pUndoMarkSelection;
277 pUndoMarkSelection = NULL;
281 void ImpEditEngine::InsertUndo( EditUndo* pUndo, BOOL bTryMerge )
283 DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" );
284 if ( pUndoMarkSelection )
286 EditUndoMarkSelection* pU = new EditUndoMarkSelection( this, *pUndoMarkSelection );
287 GetUndoManager().AddUndoAction( pU, FALSE );
288 delete pUndoMarkSelection;
289 pUndoMarkSelection = NULL;
291 GetUndoManager().AddUndoAction( pUndo, bTryMerge );
293 mbLastTryMerge = bTryMerge;
296 void ImpEditEngine::ResetUndoManager()
298 if ( HasUndoManager() )
299 GetUndoManager().Clear();
302 void ImpEditEngine::EnableUndo( BOOL bEnable )
304 // Beim Umschalten des Modus Liste loeschen:
305 if ( bEnable != IsUndoEnabled() )
306 ResetUndoManager();
308 bUndoEnabled = bEnable;
311 BOOL ImpEditEngine::Undo( EditView* pView )
313 if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
315 SetActiveView( pView );
316 GetUndoManager().Undo( 1 );
317 return TRUE;
319 return FALSE;
322 BOOL ImpEditEngine::Redo( EditView* pView )
324 if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
326 SetActiveView( pView );
327 GetUndoManager().Redo( 0 );
328 return TRUE;
330 return FALSE;
333 BOOL ImpEditEngine::Repeat( EditView* /* pView */ )
335 if ( HasUndoManager() && GetUndoManager().GetRepeatActionCount() )
337 DBG_WARNING( "Repeat nicht implementiert!" );
338 return TRUE;
340 return FALSE;
343 SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, BOOL bOnlyHardAttrib )
345 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
347 aSel.Adjust( aEditDoc );
349 #if OSL_DEBUG_LEVEL > 1
350 // if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) && ( bOnlyHardAttrib == EditEngineAttribs_All ) )
351 // return GetAttribs( aEditDoc.GetPos( aSel.Min().GetNode() ), aSel.Min().GetIndex(), aSel.Max().GetIndex(), GETATTRIBS_ALL );
352 #endif
355 SfxItemSet aCurSet( GetEmptyItemSet() );
357 USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
358 USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
360 // ueber die Absaetze iterieren...
361 for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
363 ContentNode* pNode = aEditDoc.GetObject( nNode );
364 DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetAttrib" );
366 xub_StrLen nStartPos = 0;
367 xub_StrLen nEndPos = pNode->Len();
368 if ( nNode == nStartNode )
369 nStartPos = aSel.Min().GetIndex();
370 if ( nNode == nEndNode ) // kann auch == nStart sein!
371 nEndPos = aSel.Max().GetIndex();
373 // Problem: Vorlagen....
374 // => Andersrum:
375 // 1) Harte Zeichenattribute, wie gehabt...
376 // 2) Nur wenn OFF, Style and Absatzattr. pruefen...
378 // Erst die ganz harte Formatierung...
379 aEditDoc.FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
381 if( bOnlyHardAttrib != EditEngineAttribs_OnlyHard )
383 // Und dann Absatzformatierung und Vorlage...
384 // SfxStyleSheet* pStyle = pNode->GetStyleSheet();
385 for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
387 if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
389 if ( bOnlyHardAttrib == EditEngineAttribs_All )
391 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
392 aCurSet.Put( rItem );
394 else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
396 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
397 aCurSet.Put( rItem );
400 else if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
402 const SfxPoolItem* pItem = NULL;
403 if ( bOnlyHardAttrib == EditEngineAttribs_All )
405 pItem = &pNode->GetContentAttribs().GetItem( nWhich );
407 else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
409 pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
411 // pItem can only be NULL when bOnlyHardAttrib...
412 if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
414 // Problem: Wenn Absatzvorlage mit z.B. Font,
415 // aber Font hart und anders und komplett in Selektion
416 // Falsch, wenn invalidiert....
417 // => Lieber nicht invalidieren, UMSTELLEN!
418 // Besser waere, Absatzweise ein ItemSet zu fuellen
419 // und dieses mit dem gesmten vergleichen.
420 // aCurSet.InvalidateItem( nWhich );
421 if ( nWhich <= EE_PARA_END )
422 aCurSet.InvalidateItem( nWhich );
429 // Leere Slots mit Defaults fuellen...
430 if ( bOnlyHardAttrib == EditEngineAttribs_All )
432 for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
434 if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
436 aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
440 return aCurSet;
444 SfxItemSet ImpEditEngine::GetAttribs( USHORT nPara, USHORT nStart, USHORT nEnd, sal_uInt8 nFlags ) const
446 // MT: #94002# Optimized function with less Puts(), which cause unnecessary cloning from default items.
447 // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
449 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
451 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
452 DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
453 DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
455 SfxItemSet aAttribs( ((ImpEditEngine*)this)->GetEmptyItemSet() );
457 if ( pNode )
459 if ( nEnd > pNode->Len() )
460 nEnd = pNode->Len();
462 if ( nStart > nEnd )
463 nStart = nEnd;
465 // StyleSheet / Parattribs...
467 if ( pNode->GetStyleSheet() && ( nFlags & GETATTRIBS_STYLESHEET ) )
468 aAttribs.Set( pNode->GetStyleSheet()->GetItemSet(), TRUE );
470 if ( nFlags & GETATTRIBS_PARAATTRIBS )
471 aAttribs.Put( pNode->GetContentAttribs().GetItems() );
473 // CharAttribs...
475 if ( nFlags & GETATTRIBS_CHARATTRIBS )
477 // Make testing easier...
478 pNode->GetCharAttribs().OptimizeRanges( ((ImpEditEngine*)this)->GetEditDoc().GetItemPool() );
480 const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
481 for ( USHORT nAttr = 0; nAttr < rAttrs.Count(); nAttr++ )
483 EditCharAttrib* pAttr = rAttrs.GetObject( nAttr );
485 if ( nStart == nEnd )
487 USHORT nCursorPos = nStart;
488 if ( ( pAttr->GetStart() <= nCursorPos ) && ( pAttr->GetEnd() >= nCursorPos ) )
490 // To be used the attribute has to start BEFORE the position, or it must be a
491 // new empty attr AT the position, or we are on position 0.
492 if ( ( pAttr->GetStart() < nCursorPos ) || pAttr->IsEmpty() || !nCursorPos )
494 // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
495 // but that s no problem, the empty item will come later and win.
496 aAttribs.Put( *pAttr->GetItem() );
500 else
502 // Check every attribute covering the area, partial or full.
503 if ( ( pAttr->GetStart() < nEnd ) && ( pAttr->GetEnd() > nStart ) )
505 if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
507 // full coverage
508 aAttribs.Put( *pAttr->GetItem() );
510 else
512 // OptimizeRagnge() assures that not the same attr can follow for full coverage
513 // only partial, check with current, when using para/styhe, otherwise invalid.
514 if ( !( nFlags & (GETATTRIBS_PARAATTRIBS|GETATTRIBS_STYLESHEET) ) ||
515 ( *pAttr->GetItem() != aAttribs.Get( pAttr->Which() ) ) )
517 aAttribs.InvalidateItem( pAttr->Which() );
523 if ( pAttr->GetStart() > nEnd )
525 break;
531 return aAttribs;
535 void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, BYTE nSpecial )
537 aSel.Adjust( aEditDoc );
539 // Wenn keine Selektion => die Attribute aufs Wort anwenden.
540 // ( Der RTF-Perser sollte die Methode eigentlich nie ohne Range rufen )
541 if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
542 aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, FALSE );
544 USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
545 USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
547 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
549 EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
550 pUndo->SetSpecial( nSpecial );
551 InsertUndo( pUndo );
554 BOOL bCheckLanguage = FALSE;
555 if ( GetStatus().DoOnlineSpelling() )
557 bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SFX_ITEM_ON ) ||
558 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SFX_ITEM_ON ) ||
559 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SFX_ITEM_ON );
562 // ueber die Absaetze iterieren...
563 for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
565 BOOL bParaAttribFound = FALSE;
566 BOOL bCharAttribFound = FALSE;
568 ContentNode* pNode = aEditDoc.GetObject( nNode );
569 ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
571 DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
572 DBG_ASSERT( GetParaPortions().GetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
574 xub_StrLen nStartPos = 0;
575 xub_StrLen nEndPos = pNode->Len();
576 if ( nNode == nStartNode )
577 nStartPos = aSel.Min().GetIndex();
578 if ( nNode == nEndNode ) // kann auch == nStart sein!
579 nEndPos = aSel.Max().GetIndex();
581 // ueber die Items iterieren...
582 #ifdef EDITDEBUG
583 // FILE* fp = fopen( "d:\\debug.log", "a" );
584 // if ( fp )
585 // {
586 // fprintf( fp, "\n\f\n=> Zeichen-Attribute: Absatz %i, %i-%i\n", nNode, nStartPos, nEndPos );
587 // DbgOutItemSet( fp, rSet, TRUE, FALSE );
588 // fclose( fp );
589 // }
590 #endif
592 for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
594 if ( rSet.GetItemState( nWhich ) == SFX_ITEM_ON )
596 const SfxPoolItem& rItem = rSet.Get( nWhich );
597 if ( nWhich <= EE_PARA_END )
599 pNode->GetContentAttribs().GetItems().Put( rItem );
600 bParaAttribFound = TRUE;
602 else
604 aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
605 bCharAttribFound = TRUE;
606 if ( nSpecial == ATTRSPECIAL_EDGE )
608 CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
609 USHORT nAttrs = rAttribs.Count();
610 for ( USHORT n = 0; n < nAttrs; n++ )
612 EditCharAttrib* pAttr = rAttribs.GetObject( n );
613 if ( pAttr->GetStart() > nEndPos )
614 break;
616 if ( ( pAttr->GetEnd() == nEndPos ) && ( pAttr->Which() == nWhich ) )
618 pAttr->SetEdge( TRUE );
619 break;
627 if ( bParaAttribFound )
629 ParaAttribsChanged( pPortion->GetNode() );
631 else if ( bCharAttribFound )
633 bFormatted = FALSE;
634 if ( !pNode->Len() || ( nStartPos != nEndPos ) )
636 pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
637 if ( bCheckLanguage )
638 pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos );
644 void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, BOOL bRemoveParaAttribs, USHORT nWhich )
646 aSel.Adjust( aEditDoc );
648 USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
649 USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
651 const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
653 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
655 // Eventuel spezielles Undo, oder ItemSet*
656 EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
657 pUndo->SetRemoveAttribs( TRUE );
658 pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
659 pUndo->SetRemoveWhich( nWhich );
660 InsertUndo( pUndo );
663 // ueber die Absaetze iterieren...
664 for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
666 ContentNode* pNode = aEditDoc.GetObject( nNode );
667 ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
669 DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
670 DBG_ASSERT( GetParaPortions().SaveGetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
672 xub_StrLen nStartPos = 0;
673 xub_StrLen nEndPos = pNode->Len();
674 if ( nNode == nStartNode )
675 nStartPos = aSel.Min().GetIndex();
676 if ( nNode == nEndNode ) // kann auch == nStart sein!
677 nEndPos = aSel.Max().GetIndex();
679 // Optimieren: Wenn ganzer Absatz, dann RemoveCharAttribs( nPara )?!
680 BOOL bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
681 if ( bRemoveParaAttribs )
683 SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidiert
685 else
687 // Bei 'Format-Standard' sollen auch die Zeichenattribute verschwinden,
688 // die von der DrawingEngine als Absatzattribute eingestellt wurden.
689 // Diese koennen sowieso nicht vom Anwender eingestellt worden sein.
691 // #106871# Not when nWhich
692 // Would have been better to offer a separate method for format/standard...
693 if ( !nWhich )
695 SfxItemSet aAttribs( GetParaAttribs( nNode ) );
696 for ( USHORT nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
697 aAttribs.ClearItem( nW );
698 SetParaAttribs( nNode, aAttribs );
702 if ( bChanged && !bRemoveParaAttribs )
704 bFormatted = FALSE;
705 pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
710 typedef EditCharAttrib* EditCharAttribPtr;
712 void ImpEditEngine::RemoveCharAttribs( USHORT nPara, USHORT nWhich, BOOL bRemoveFeatures )
714 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
715 ParaPortion* pPortion = GetParaPortions().SaveGetObject( nPara );
717 DBG_ASSERT( pNode, "Node nicht gefunden: RemoveCharAttribs" );
718 DBG_ASSERT( pPortion, "Portion nicht gefunden: RemoveCharAttribs" );
720 if ( !pNode )
721 return;
723 USHORT nAttr = 0;
724 EditCharAttribPtr pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
725 while ( pAttr )
727 if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
728 ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
730 pNode->GetCharAttribs().GetAttribs().Remove( nAttr );
731 delete pAttr;
732 nAttr--;
734 nAttr++;
735 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
738 pPortion->MarkSelectionInvalid( 0, pNode->Len() );
741 void ImpEditEngine::SetParaAttribs( USHORT nPara, const SfxItemSet& rSet )
743 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
745 if ( !pNode )
746 return;
748 #ifdef EDITDEBUG
749 // FILE* fp = fopen( "d:\\debug.log", "a" );
750 // if ( fp )
751 // {
752 // fprintf( fp, "\n\f\n=> Absatz-Attribute: Absatz %i\n", nPara );
753 // DbgOutItemSet( fp, rSet, TRUE, FALSE );
754 // fclose( fp );
755 // }
756 #endif
758 if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
760 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
762 if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
764 SfxItemSet aTmpSet( GetEmptyItemSet() );
765 aTmpSet.Put( rSet );
766 InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet ) );
768 else
770 InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), rSet ) );
773 pNode->GetContentAttribs().GetItems().Set( rSet );
774 if ( aStatus.UseCharAttribs() )
775 pNode->CreateDefFont();
777 ParaAttribsChanged( pNode );
781 const SfxItemSet& ImpEditEngine::GetParaAttribs( USHORT nPara ) const
783 ContentNode* pNode = aEditDoc.GetObject( nPara );
784 DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttribs" );
785 return pNode->GetContentAttribs().GetItems();
788 BOOL ImpEditEngine::HasParaAttrib( USHORT nPara, USHORT nWhich ) const
790 ContentNode* pNode = aEditDoc.GetObject( nPara );
791 DBG_ASSERT( pNode, "Node nicht gefunden: HasParaAttrib" );
793 return pNode->GetContentAttribs().HasItem( nWhich );
796 const SfxPoolItem& ImpEditEngine::GetParaAttrib( USHORT nPara, USHORT nWhich ) const
798 ContentNode* pNode = aEditDoc.GetObject( nPara );
799 DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttrib" );
801 return pNode->GetContentAttribs().GetItem( nWhich );
804 void ImpEditEngine::GetCharAttribs( USHORT nPara, EECharAttribArray& rLst ) const
806 rLst.Remove( 0, rLst.Count() );
807 ContentNode* pNode = aEditDoc.GetObject( nPara );
808 if ( pNode )
810 for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
812 EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
813 EECharAttrib aEEAttr;
814 aEEAttr.pAttr = pAttr->GetItem();
815 aEEAttr.nPara = nPara;
816 aEEAttr.nStart = pAttr->GetStart();
817 aEEAttr.nEnd = pAttr->GetEnd();
818 rLst.Insert( aEEAttr, rLst.Count() );
823 void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
825 pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
826 xub_StrLen nEndPos = pNode->Len();
827 for ( USHORT nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
829 if ( pNode->GetContentAttribs().HasItem( nWhich ) )
831 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
832 // Die Luecken auffuellen:
833 USHORT nLastEnd = 0;
834 EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
835 while ( pAttr )
837 nLastEnd = pAttr->GetEnd();
838 if ( pAttr->GetStart() > nLastEnd )
839 aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
840 // #112831# Last Attr might go from 0xffff to 0x0000
841 pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : NULL;
844 // Und den Rest:
845 if ( nLastEnd < nEndPos )
846 aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
849 bFormatted = FALSE;
850 // Portion braucht hier nicht invalidiert werden, geschieht woanders.
853 IdleFormattter::IdleFormattter()
855 pView = 0;
856 nRestarts = 0;
859 IdleFormattter::~IdleFormattter()
861 pView = 0;
864 void IdleFormattter::DoIdleFormat( EditView* pV )
866 pView = pV;
868 if ( IsActive() )
869 nRestarts++;
871 if ( nRestarts > 4 )
872 ForceTimeout();
873 else
874 Start();
877 void IdleFormattter::ForceTimeout()
879 if ( IsActive() )
881 Stop();
882 ((Link&)GetTimeoutHdl()).Call( this );
886 ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const String& rOldTextAfterStartPos )
887 : aOldTextAfterStartPos( rOldTextAfterStartPos )
889 aPos = rPos;
890 nLen = 0;
891 bCursor = TRUE;
892 pAttribs = NULL;
893 bWasCursorOverwrite = FALSE;
896 ImplIMEInfos::~ImplIMEInfos()
898 delete[] pAttribs;
901 void ImplIMEInfos::CopyAttribs( const USHORT* pA, USHORT nL )
903 nLen = nL;
904 delete pAttribs;
905 pAttribs = new USHORT[ nL ];
906 memcpy( pAttribs, pA, nL*sizeof(USHORT) );
909 void ImplIMEInfos::DestroyAttribs()
911 delete[] pAttribs;
912 pAttribs = NULL;
913 nLen = 0;