1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impedit5.cxx,v $
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
)
50 // EndListening( *pStylePool, TRUE );
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
;
92 aPrevStyleName
= pCurStyle
->GetName();
94 XubString aNewStyleName
;
96 aNewStyleName
= pStyle
->GetName();
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() ) );
105 EndListening( *pCurStyle
, FALSE
);
106 pNode
->SetStyleSheet( pStyle
, aStatus
.UseCharAttribs() );
108 StartListening( *pStyle
, FALSE
);
109 ParaAttribsChanged( pNode
);
114 void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet
* pStyle
)
116 SvxFont aFontFromStyle
;
117 CreateFont( aFontFromStyle
, pStyle
->GetItemSet() );
120 for ( USHORT nNode
= 0; nNode
< aEditDoc
.Count(); nNode
++ )
122 ContentNode
* pNode
= aEditDoc
.GetObject( nNode
);
123 if ( pNode
->GetStyleSheet() == pStyle
)
126 if ( aStatus
.UseCharAttribs() )
127 pNode
->SetStyleSheet( pStyle
, aFontFromStyle
);
129 pNode
->SetStyleSheet( pStyle
, FALSE
);
131 ParaAttribsChanged( pNode
);
136 GetEditEnginePtr()->StyleSheetChanged( pStyle
);
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
);
155 void ImpEditEngine::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
157 // Damit nicht beim Destruieren unnoetig formatiert wird:
160 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine
, 0 );
162 SfxStyleSheet
* pStyle
= NULL
;
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();
172 else if ( ( rHint
.Type() == TYPE(SfxSimpleHint
) ) && ( rBC
.ISA( SfxStyleSheet
) ) )
174 pStyle
= (SfxStyleSheet
*)&rBC
;
175 nId
= ((SfxSimpleHint
&)rHint
).GetId();
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++ )
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 );
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() );
223 pUndo
= new EditUndoSetAttribs( this, aESel
, aTmpSet
);
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() );
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() )
308 bUndoEnabled
= bEnable
;
311 BOOL
ImpEditEngine::Undo( EditView
* pView
)
313 if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
315 SetActiveView( pView
);
316 GetUndoManager().Undo( 1 );
322 BOOL
ImpEditEngine::Redo( EditView
* pView
)
324 if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
326 SetActiveView( pView
);
327 GetUndoManager().Redo( 0 );
333 BOOL
ImpEditEngine::Repeat( EditView
* /* pView */ )
335 if ( HasUndoManager() && GetUndoManager().GetRepeatActionCount() )
337 DBG_WARNING( "Repeat nicht implementiert!" );
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 );
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....
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
) );
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() );
459 if ( nEnd
> pNode
->Len() )
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() );
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() );
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
) )
508 aAttribs
.Put( *pAttr
->GetItem() );
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
)
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
);
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...
583 // FILE* fp = fopen( "d:\\debug.log", "a" );
586 // fprintf( fp, "\n\f\n=> Zeichen-Attribute: Absatz %i, %i-%i\n", nNode, nStartPos, nEndPos );
587 // DbgOutItemSet( fp, rSet, TRUE, FALSE );
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
;
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
)
616 if ( ( pAttr
->GetEnd() == nEndPos
) && ( pAttr
->Which() == nWhich
) )
618 pAttr
->SetEdge( TRUE
);
627 if ( bParaAttribFound
)
629 ParaAttribsChanged( pPortion
->GetNode() );
631 else if ( bCharAttribFound
)
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
);
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
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...
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
)
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" );
724 EditCharAttribPtr pAttr
= GetAttrib( pNode
->GetCharAttribs().GetAttribs(), nAttr
);
727 if ( ( !pAttr
->IsFeature() || bRemoveFeatures
) &&
728 ( !nWhich
|| ( pAttr
->GetItem()->Which() == nWhich
) ) )
730 pNode
->GetCharAttribs().GetAttribs().Remove( 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
);
749 // FILE* fp = fopen( "d:\\debug.log", "a" );
752 // fprintf( fp, "\n\f\n=> Absatz-Attribute: Absatz %i\n", nPara );
753 // DbgOutItemSet( fp, rSet, TRUE, FALSE );
758 if ( !( pNode
->GetContentAttribs().GetItems() == rSet
) )
760 if ( IsUndoEnabled() && !IsInUndo() && aStatus
.DoUndoAttribs() )
762 if ( rSet
.GetPool() != &aEditDoc
.GetItemPool() )
764 SfxItemSet
aTmpSet( GetEmptyItemSet() );
766 InsertUndo( new EditUndoSetParaAttribs( this, nPara
, pNode
->GetContentAttribs().GetItems(), aTmpSet
) );
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
);
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:
834 EditCharAttrib
* pAttr
= pNode
->GetCharAttribs().FindNextAttrib( nWhich
, nLastEnd
);
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
;
845 if ( nLastEnd
< nEndPos
)
846 aEditDoc
.InsertAttrib( pNode
, nLastEnd
, nEndPos
, rItem
);
850 // Portion braucht hier nicht invalidiert werden, geschieht woanders.
853 IdleFormattter::IdleFormattter()
859 IdleFormattter::~IdleFormattter()
864 void IdleFormattter::DoIdleFormat( EditView
* pV
)
877 void IdleFormattter::ForceTimeout()
882 ((Link
&)GetTimeoutHdl()).Call( this );
886 ImplIMEInfos::ImplIMEInfos( const EditPaM
& rPos
, const String
& rOldTextAfterStartPos
)
887 : aOldTextAfterStartPos( rOldTextAfterStartPos
)
893 bWasCursorOverwrite
= FALSE
;
896 ImplIMEInfos::~ImplIMEInfos()
901 void ImplIMEInfos::CopyAttribs( const USHORT
* pA
, USHORT nL
)
905 pAttribs
= new USHORT
[ nL
];
906 memcpy( pAttribs
, pA
, nL
*sizeof(USHORT
) );
909 void ImplIMEInfos::DestroyAttribs()