1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26
27 #include <eeng_pch.hxx>
28
29 #include <impedit.hxx>
30 #include <editeng/editeng.hxx>
31 #include <editdbg.hxx>
32
33 #include <svl/smplhint.hxx>
34
35
36 #include <editeng/lrspitem.hxx>
37
SetStyleSheetPool(SfxStyleSheetPool * pSPool)38 void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
39 {
40 if ( pStylePool != pSPool )
41 {
42 // if ( pStylePool )
43 // EndListening( *pStylePool, sal_True );
44
45 pStylePool = pSPool;
46
47 // if ( pStylePool )
48 // StartListening( *pStylePool, sal_True );
49 }
50 }
51
GetStyleSheet(sal_uInt16 nPara) const52 SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_uInt16 nPara ) const
53 {
54 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
55 return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
56 }
57
SetStyleSheet(EditSelection aSel,SfxStyleSheet * pStyle)58 void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle )
59 {
60 aSel.Adjust( aEditDoc );
61
62 sal_uInt16 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
63 sal_uInt16 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
64
65 sal_Bool _bUpdate = GetUpdateMode();
66 SetUpdateMode( sal_False );
67
68 for ( sal_uInt16 n = nStartPara; n <= nEndPara; n++ )
69 SetStyleSheet( n, pStyle );
70
71 SetUpdateMode( _bUpdate, 0 );
72 }
73
SetStyleSheet(sal_uInt16 nPara,SfxStyleSheet * pStyle)74 void ImpEditEngine::SetStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pStyle )
75 {
76 DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
77 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
78 SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
79 if ( pStyle != pCurStyle )
80 {
81 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
82 {
83 XubString aPrevStyleName;
84 if ( pCurStyle )
85 aPrevStyleName = pCurStyle->GetName();
86
87 XubString aNewStyleName;
88 if ( pStyle )
89 aNewStyleName = pStyle->GetName();
90
91 InsertUndo(
92 new EditUndoSetStyleSheet( this, aEditDoc.GetPos( pNode ),
93 aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
94 aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
95 pNode->GetContentAttribs().GetItems() ) );
96 }
97 if ( pCurStyle )
98 EndListening( *pCurStyle, sal_False );
99 pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
100 if ( pStyle )
101 StartListening( *pStyle, sal_False );
102 ParaAttribsChanged( pNode );
103 }
104 FormatAndUpdate();
105 }
106
UpdateParagraphsWithStyleSheet(SfxStyleSheet * pStyle)107 void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle )
108 {
109 SvxFont aFontFromStyle;
110 CreateFont( aFontFromStyle, pStyle->GetItemSet() );
111
112 sal_Bool bUsed = sal_False;
113 for ( sal_uInt16 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
114 {
115 ContentNode* pNode = aEditDoc.GetObject( nNode );
116 if ( pNode->GetStyleSheet() == pStyle )
117 {
118 bUsed = sal_True;
119 if ( aStatus.UseCharAttribs() )
120 pNode->SetStyleSheet( pStyle, aFontFromStyle );
121 else
122 pNode->SetStyleSheet( pStyle, sal_False );
123
124 ParaAttribsChanged( pNode );
125 }
126 }
127 if ( bUsed )
128 {
129 GetEditEnginePtr()->StyleSheetChanged( pStyle );
130 FormatAndUpdate();
131 }
132 }
133
RemoveStyleFromParagraphs(SfxStyleSheet * pStyle)134 void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle )
135 {
136 for ( sal_uInt16 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
137 {
138 ContentNode* pNode = aEditDoc.GetObject(nNode);
139 if ( pNode->GetStyleSheet() == pStyle )
140 {
141 pNode->SetStyleSheet( NULL );
142 ParaAttribsChanged( pNode );
143 }
144 }
145 FormatAndUpdate();
146 }
147
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)148 void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
149 {
150 // Damit nicht beim Destruieren unnoetig formatiert wird:
151 if ( !bDowning )
152 {
153 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
154
155 SfxStyleSheet* pStyle = NULL;
156 sal_uLong nId = 0;
157
158 if ( rHint.ISA( SfxStyleSheetHint ) )
159 {
160 const SfxStyleSheetHint& rH = (const SfxStyleSheetHint&) rHint;
161 DBG_ASSERT( rH.GetStyleSheet()->ISA( SfxStyleSheet ), "Kein SfxStyleSheet!" );
162 pStyle = (SfxStyleSheet*) rH.GetStyleSheet();
163 nId = rH.GetHint();
164 }
165 else if ( ( rHint.Type() == TYPE(SfxSimpleHint ) ) && ( rBC.ISA( SfxStyleSheet ) ) )
166 {
167 pStyle = (SfxStyleSheet*)&rBC;
168 nId = ((SfxSimpleHint&)rHint).GetId();
169 }
170
171 if ( pStyle )
172 {
173 if ( ( nId == SFX_HINT_DYING ) ||
174 ( nId == SFX_STYLESHEET_INDESTRUCTION ) ||
175 ( nId == SFX_STYLESHEET_ERASED ) )
176 {
177 RemoveStyleFromParagraphs( pStyle );
178 }
179 else if ( ( nId == SFX_HINT_DATACHANGED ) ||
180 ( nId == SFX_STYLESHEET_MODIFIED ) )
181 {
182 UpdateParagraphsWithStyleSheet( pStyle );
183
184 // Alle Absaetze mit EditStyles, die das geaenderte Style
185 // irgendwie als Parent haben, muessen formatiert werden.
186 // sal_uLong nStyles = pMyStylePool->GetStyles().Count();
187 // for ( sal_uLong nStyle = 0; nStyle < nStyles; nStyle++ )
188 // {
189 // EditStyleSheet* pES = (EditStyleSheet*)pMyStylePool->GetStyles().GetObject( nStyle );
190 // DBG_ASSERT( pES, "NULL-Pointer im StyleSheetPool!" );
191 // if ( pES->IsUsed() && pES->HasStyleAsAnyParent( *pStyle ) )
192 // UpdateParagraphsWithStyleSheet( pES );
193 // }
194 }
195 }
196 }
197 }
198
CreateAttribUndo(EditSelection aSel,const SfxItemSet & rSet)199 EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
200 {
201 DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Fehlerhafte Selektion" );
202 aSel.Adjust( aEditDoc );
203
204 ESelection aESel( CreateESel( aSel ) );
205
206 sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
207 sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
208
209 DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
210
211 EditUndoSetAttribs* pUndo = NULL;
212 if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
213 {
214 SfxItemSet aTmpSet( GetEmptyItemSet() );
215 aTmpSet.Put( rSet );
216 pUndo = new EditUndoSetAttribs( this, aESel, aTmpSet );
217 }
218 else
219 {
220 pUndo = new EditUndoSetAttribs( this, aESel, rSet );
221 }
222
223 SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
224
225 for ( sal_uInt16 nPara = nStartNode; nPara <= nEndNode; nPara++ )
226 {
227 ContentNode* pNode = aEditDoc.GetObject( nPara );
228 DBG_ASSERT( aEditDoc.SaveGetObject( nPara ), "Node nicht gefunden: CreateAttribUndo" );
229 ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
230 pUndo->GetContentInfos().Insert( pInf, pUndo->GetContentInfos().Count() );
231
232 for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
233 {
234 EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
235 if ( pAttr->GetLen() )
236 {
237 EditCharAttribPtr pNew = MakeCharAttrib( *pPool, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
238 pInf->GetPrevCharAttribs().Insert( pNew, pInf->GetPrevCharAttribs().Count() );
239 }
240 }
241 }
242 return pUndo;
243 }
244
UndoActionStart(sal_uInt16 nId,const ESelection & aSel)245 void ImpEditEngine::UndoActionStart( sal_uInt16 nId, const ESelection& aSel )
246 {
247 if ( IsUndoEnabled() && !IsInUndo() )
248 {
249 GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
250 DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
251 pUndoMarkSelection = new ESelection( aSel );
252 }
253 }
254
UndoActionStart(sal_uInt16 nId)255 void ImpEditEngine::UndoActionStart( sal_uInt16 nId )
256 {
257 if ( IsUndoEnabled() && !IsInUndo() )
258 {
259 GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
260 DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
261 }
262 }
263
UndoActionEnd(sal_uInt16)264 void ImpEditEngine::UndoActionEnd( sal_uInt16 )
265 {
266 if ( IsUndoEnabled() && !IsInUndo() )
267 {
268 GetUndoManager().LeaveListAction();
269 delete pUndoMarkSelection;
270 pUndoMarkSelection = NULL;
271 }
272 }
273
InsertUndo(EditUndo * pUndo,sal_Bool bTryMerge)274 void ImpEditEngine::InsertUndo( EditUndo* pUndo, sal_Bool bTryMerge )
275 {
276 DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" );
277 if ( pUndoMarkSelection )
278 {
279 EditUndoMarkSelection* pU = new EditUndoMarkSelection( this, *pUndoMarkSelection );
280 GetUndoManager().AddUndoAction( pU, sal_False );
281 delete pUndoMarkSelection;
282 pUndoMarkSelection = NULL;
283 }
284 GetUndoManager().AddUndoAction( pUndo, bTryMerge );
285
286 mbLastTryMerge = bTryMerge;
287 }
288
ResetUndoManager()289 void ImpEditEngine::ResetUndoManager()
290 {
291 if ( HasUndoManager() )
292 GetUndoManager().Clear();
293 }
294
EnableUndo(sal_Bool bEnable)295 void ImpEditEngine::EnableUndo( sal_Bool bEnable )
296 {
297 // Beim Umschalten des Modus Liste loeschen:
298 if ( bEnable != IsUndoEnabled() )
299 ResetUndoManager();
300
301 bUndoEnabled = bEnable;
302 }
303
Undo(EditView * pView)304 sal_Bool ImpEditEngine::Undo( EditView* pView )
305 {
306 if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
307 {
308 SetActiveView( pView );
309 GetUndoManager().Undo();
310 return sal_True;
311 }
312 return sal_False;
313 }
314
Redo(EditView * pView)315 sal_Bool ImpEditEngine::Redo( EditView* pView )
316 {
317 if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
318 {
319 SetActiveView( pView );
320 GetUndoManager().Redo();
321 return sal_True;
322 }
323 return sal_False;
324 }
325
Repeat(EditView *)326 sal_Bool ImpEditEngine::Repeat( EditView* /* pView */ )
327 {
328 if ( HasUndoManager() && GetUndoManager().GetRepeatActionCount() )
329 {
330 DBG_WARNING( "Repeat nicht implementiert!" );
331 return sal_True;
332 }
333 return sal_False;
334 }
335
GetAttribs(EditSelection aSel,sal_Bool bOnlyHardAttrib)336 SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, sal_Bool bOnlyHardAttrib )
337 {
338 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
339
340 aSel.Adjust( aEditDoc );
341
342 #if OSL_DEBUG_LEVEL > 1
343 // if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) && ( bOnlyHardAttrib == EditEngineAttribs_All ) )
344 // return GetAttribs( aEditDoc.GetPos( aSel.Min().GetNode() ), aSel.Min().GetIndex(), aSel.Max().GetIndex(), GETATTRIBS_ALL );
345 #endif
346
347
348 SfxItemSet aCurSet( GetEmptyItemSet() );
349
350 sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
351 sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
352
353 // ueber die Absaetze iterieren...
354 for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
355 {
356 ContentNode* pNode = aEditDoc.GetObject( nNode );
357 DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetAttrib" );
358
359 xub_StrLen nStartPos = 0;
360 xub_StrLen nEndPos = pNode->Len();
361 if ( nNode == nStartNode )
362 nStartPos = aSel.Min().GetIndex();
363 if ( nNode == nEndNode ) // kann auch == nStart sein!
364 nEndPos = aSel.Max().GetIndex();
365
366 // Problem: Vorlagen....
367 // => Andersrum:
368 // 1) Harte Zeichenattribute, wie gehabt...
369 // 2) Nur wenn OFF, Style and Absatzattr. pruefen...
370
371 // Erst die ganz harte Formatierung...
372 aEditDoc.FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
373
374 if( bOnlyHardAttrib != EditEngineAttribs_OnlyHard )
375 {
376 // Und dann Absatzformatierung und Vorlage...
377 // SfxStyleSheet* pStyle = pNode->GetStyleSheet();
378 for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
379 {
380 if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
381 {
382 if ( bOnlyHardAttrib == EditEngineAttribs_All )
383 {
384 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
385 aCurSet.Put( rItem );
386 }
387 else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
388 {
389 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
390 aCurSet.Put( rItem );
391 }
392 }
393 else if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
394 {
395 const SfxPoolItem* pItem = NULL;
396 if ( bOnlyHardAttrib == EditEngineAttribs_All )
397 {
398 pItem = &pNode->GetContentAttribs().GetItem( nWhich );
399 }
400 else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
401 {
402 pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
403 }
404 // pItem can only be NULL when bOnlyHardAttrib...
405 if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
406 {
407 // Problem: Wenn Absatzvorlage mit z.B. Font,
408 // aber Font hart und anders und komplett in Selektion
409 // Falsch, wenn invalidiert....
410 // => Lieber nicht invalidieren, UMSTELLEN!
411 // Besser waere, Absatzweise ein ItemSet zu fuellen
412 // und dieses mit dem gesmten vergleichen.
413 // aCurSet.InvalidateItem( nWhich );
414 if ( nWhich <= EE_PARA_END )
415 aCurSet.InvalidateItem( nWhich );
416 }
417 }
418 }
419 }
420 }
421
422 // Leere Slots mit Defaults fuellen...
423 if ( bOnlyHardAttrib == EditEngineAttribs_All )
424 {
425 for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
426 {
427 if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
428 {
429 aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
430 }
431 }
432 }
433 return aCurSet;
434 }
435
436
GetAttribs(sal_uInt16 nPara,sal_uInt16 nStart,sal_uInt16 nEnd,sal_uInt8 nFlags) const437 SfxItemSet ImpEditEngine::GetAttribs( sal_uInt16 nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_uInt8 nFlags ) const
438 {
439 // MT: #94002# Optimized function with less Puts(), which cause unnecessary cloning from default items.
440 // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
441
442 DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
443
444 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
445 DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
446 DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
447
448 SfxItemSet aAttribs( ((ImpEditEngine*)this)->GetEmptyItemSet() );
449
450 if ( pNode )
451 {
452 if ( nEnd > pNode->Len() )
453 nEnd = pNode->Len();
454
455 if ( nStart > nEnd )
456 nStart = nEnd;
457
458 // StyleSheet / Parattribs...
459
460 if ( pNode->GetStyleSheet() && ( nFlags & GETATTRIBS_STYLESHEET ) )
461 aAttribs.Set( pNode->GetStyleSheet()->GetItemSet(), sal_True );
462
463 if ( nFlags & GETATTRIBS_PARAATTRIBS )
464 aAttribs.Put( pNode->GetContentAttribs().GetItems() );
465
466 // CharAttribs...
467
468 if ( nFlags & GETATTRIBS_CHARATTRIBS )
469 {
470 // Make testing easier...
471 pNode->GetCharAttribs().OptimizeRanges( ((ImpEditEngine*)this)->GetEditDoc().GetItemPool() );
472
473 const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
474 for ( sal_uInt16 nAttr = 0; nAttr < rAttrs.Count(); nAttr++ )
475 {
476 EditCharAttrib* pAttr = rAttrs.GetObject( nAttr );
477
478 if ( nStart == nEnd )
479 {
480 sal_uInt16 nCursorPos = nStart;
481 if ( ( pAttr->GetStart() <= nCursorPos ) && ( pAttr->GetEnd() >= nCursorPos ) )
482 {
483 // To be used the attribute has to start BEFORE the position, or it must be a
484 // new empty attr AT the position, or we are on position 0.
485 if ( ( pAttr->GetStart() < nCursorPos ) || pAttr->IsEmpty() || !nCursorPos )
486 {
487 // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
488 // but that s no problem, the empty item will come later and win.
489 aAttribs.Put( *pAttr->GetItem() );
490 }
491 }
492 }
493 else
494 {
495 // Check every attribute covering the area, partial or full.
496 if ( ( pAttr->GetStart() < nEnd ) && ( pAttr->GetEnd() > nStart ) )
497 {
498 if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
499 {
500 // full coverage
501 aAttribs.Put( *pAttr->GetItem() );
502 }
503 else
504 {
505 // OptimizeRagnge() assures that not the same attr can follow for full coverage
506 // only partial, check with current, when using para/styhe, otherwise invalid.
507 if ( !( nFlags & (GETATTRIBS_PARAATTRIBS|GETATTRIBS_STYLESHEET) ) ||
508 ( *pAttr->GetItem() != aAttribs.Get( pAttr->Which() ) ) )
509 {
510 aAttribs.InvalidateItem( pAttr->Which() );
511 }
512 }
513 }
514 }
515
516 if ( pAttr->GetStart() > nEnd )
517 {
518 break;
519 }
520 }
521 }
522 }
523
524 return aAttribs;
525 }
526
527
SetAttribs(EditSelection aSel,const SfxItemSet & rSet,sal_uInt8 nSpecial)528 void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, sal_uInt8 nSpecial )
529 {
530 aSel.Adjust( aEditDoc );
531
532 // Wenn keine Selektion => die Attribute aufs Wort anwenden.
533 // ( Der RTF-Perser sollte die Methode eigentlich nie ohne Range rufen )
534 if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
535 aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_False );
536
537 sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
538 sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
539
540 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
541 {
542 EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
543 pUndo->SetSpecial( nSpecial );
544 InsertUndo( pUndo );
545 }
546
547 sal_Bool bCheckLanguage = sal_False;
548 if ( GetStatus().DoOnlineSpelling() )
549 {
550 bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SFX_ITEM_ON ) ||
551 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SFX_ITEM_ON ) ||
552 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SFX_ITEM_ON );
553 }
554
555 // ueber die Absaetze iterieren...
556 for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
557 {
558 sal_Bool bParaAttribFound = sal_False;
559 sal_Bool bCharAttribFound = sal_False;
560
561 ContentNode* pNode = aEditDoc.GetObject( nNode );
562 ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
563
564 DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
565 DBG_ASSERT( GetParaPortions().GetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
566
567 xub_StrLen nStartPos = 0;
568 xub_StrLen nEndPos = pNode->Len();
569 if ( nNode == nStartNode )
570 nStartPos = aSel.Min().GetIndex();
571 if ( nNode == nEndNode ) // kann auch == nStart sein!
572 nEndPos = aSel.Max().GetIndex();
573
574 // ueber die Items iterieren...
575 #ifdef EDITDEBUG
576 // FILE* fp = fopen( "d:\\debug.log", "a" );
577 // if ( fp )
578 // {
579 // fprintf( fp, "\n\n=> Zeichen-Attribute: Absatz %i, %i-%i\n", nNode, nStartPos, nEndPos );
580 // DbgOutItemSet( fp, rSet, sal_True, sal_False );
581 // fclose( fp );
582 // }
583 #endif
584
585 for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
586 {
587 if ( rSet.GetItemState( nWhich ) == SFX_ITEM_ON )
588 {
589 const SfxPoolItem& rItem = rSet.Get( nWhich );
590 if ( nWhich <= EE_PARA_END )
591 {
592 pNode->GetContentAttribs().GetItems().Put( rItem );
593 bParaAttribFound = sal_True;
594 }
595 else
596 {
597 aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
598 bCharAttribFound = sal_True;
599 if ( nSpecial == ATTRSPECIAL_EDGE )
600 {
601 CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
602 sal_uInt16 nAttrs = rAttribs.Count();
603 for ( sal_uInt16 n = 0; n < nAttrs; n++ )
604 {
605 EditCharAttrib* pAttr = rAttribs.GetObject( n );
606 if ( pAttr->GetStart() > nEndPos )
607 break;
608
609 if ( ( pAttr->GetEnd() == nEndPos ) && ( pAttr->Which() == nWhich ) )
610 {
611 pAttr->SetEdge( sal_True );
612 break;
613 }
614 }
615 }
616 }
617 }
618 }
619
620 if ( bParaAttribFound )
621 {
622 ParaAttribsChanged( pPortion->GetNode() );
623 }
624 else if ( bCharAttribFound )
625 {
626 bFormatted = sal_False;
627 if ( !pNode->Len() || ( nStartPos != nEndPos ) )
628 {
629 pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
630 if ( bCheckLanguage )
631 pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos );
632 }
633 }
634 }
635 }
636
RemoveCharAttribs(EditSelection aSel,sal_Bool bRemoveParaAttribs,sal_uInt16 nWhich)637 void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
638 {
639 aSel.Adjust( aEditDoc );
640
641 sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
642 sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
643
644 const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
645
646 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
647 {
648 // Eventuel spezielles Undo, oder ItemSet*
649 EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
650 pUndo->SetRemoveAttribs( sal_True );
651 pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
652 pUndo->SetRemoveWhich( nWhich );
653 InsertUndo( pUndo );
654 }
655
656 // ueber die Absaetze iterieren...
657 for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
658 {
659 ContentNode* pNode = aEditDoc.GetObject( nNode );
660 ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
661
662 DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
663 DBG_ASSERT( GetParaPortions().SaveGetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
664
665 xub_StrLen nStartPos = 0;
666 xub_StrLen nEndPos = pNode->Len();
667 if ( nNode == nStartNode )
668 nStartPos = aSel.Min().GetIndex();
669 if ( nNode == nEndNode ) // kann auch == nStart sein!
670 nEndPos = aSel.Max().GetIndex();
671
672 // Optimieren: Wenn ganzer Absatz, dann RemoveCharAttribs( nPara )?!
673 sal_Bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
674 if ( bRemoveParaAttribs )
675 {
676 SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidiert
677 }
678 else
679 {
680 // Bei 'Format-Standard' sollen auch die Zeichenattribute verschwinden,
681 // die von der DrawingEngine als Absatzattribute eingestellt wurden.
682 // Diese koennen sowieso nicht vom Anwender eingestellt worden sein.
683
684 // #106871# Not when nWhich
685 // Would have been better to offer a separate method for format/standard...
686 if ( !nWhich )
687 {
688 SfxItemSet aAttribs( GetParaAttribs( nNode ) );
689 for ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
690 aAttribs.ClearItem( nW );
691 SetParaAttribs( nNode, aAttribs );
692 }
693 }
694
695 if ( bChanged && !bRemoveParaAttribs )
696 {
697 bFormatted = sal_False;
698 pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
699 }
700 }
701 }
702
703 typedef EditCharAttrib* EditCharAttribPtr;
704
RemoveCharAttribs(sal_uInt16 nPara,sal_uInt16 nWhich,sal_Bool bRemoveFeatures)705 void ImpEditEngine::RemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich, sal_Bool bRemoveFeatures )
706 {
707 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
708 ParaPortion* pPortion = GetParaPortions().SaveGetObject( nPara );
709
710 DBG_ASSERT( pNode, "Node nicht gefunden: RemoveCharAttribs" );
711 DBG_ASSERT( pPortion, "Portion nicht gefunden: RemoveCharAttribs" );
712
713 if ( !pNode )
714 return;
715
716 sal_uInt16 nAttr = 0;
717 EditCharAttribPtr pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
718 while ( pAttr )
719 {
720 if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
721 ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
722 {
723 pNode->GetCharAttribs().GetAttribs().Remove( nAttr );
724 delete pAttr;
725 nAttr--;
726 }
727 nAttr++;
728 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
729 }
730
731 pPortion->MarkSelectionInvalid( 0, pNode->Len() );
732 }
733
SetParaAttribs(sal_uInt16 nPara,const SfxItemSet & rSet)734 void ImpEditEngine::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet )
735 {
736 ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
737
738 if ( !pNode )
739 return;
740
741 #ifdef EDITDEBUG
742 // FILE* fp = fopen( "d:\\debug.log", "a" );
743 // if ( fp )
744 // {
745 // fprintf( fp, "\n\n=> Absatz-Attribute: Absatz %i\n", nPara );
746 // DbgOutItemSet( fp, rSet, sal_True, sal_False );
747 // fclose( fp );
748 // }
749 #endif
750
751 if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
752 {
753 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
754 {
755 if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
756 {
757 SfxItemSet aTmpSet( GetEmptyItemSet() );
758 aTmpSet.Put( rSet );
759 InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet ) );
760 }
761 else
762 {
763 InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), rSet ) );
764 }
765 }
766 pNode->GetContentAttribs().GetItems().Set( rSet );
767 if ( aStatus.UseCharAttribs() )
768 pNode->CreateDefFont();
769
770 ParaAttribsChanged( pNode );
771 }
772 }
773
GetParaAttribs(sal_uInt16 nPara) const774 const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_uInt16 nPara ) const
775 {
776 ContentNode* pNode = aEditDoc.GetObject( nPara );
777 DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttribs" );
778 return pNode->GetContentAttribs().GetItems();
779 }
780
HasParaAttrib(sal_uInt16 nPara,sal_uInt16 nWhich) const781 sal_Bool ImpEditEngine::HasParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
782 {
783 ContentNode* pNode = aEditDoc.GetObject( nPara );
784 DBG_ASSERT( pNode, "Node nicht gefunden: HasParaAttrib" );
785
786 return pNode->GetContentAttribs().HasItem( nWhich );
787 }
788
GetParaAttrib(sal_uInt16 nPara,sal_uInt16 nWhich) const789 const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
790 {
791 ContentNode* pNode = aEditDoc.GetObject( nPara );
792 DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttrib" );
793
794 return pNode->GetContentAttribs().GetItem( nWhich );
795 }
796
GetCharAttribs(sal_uInt16 nPara,EECharAttribArray & rLst) const797 void ImpEditEngine::GetCharAttribs( sal_uInt16 nPara, EECharAttribArray& rLst ) const
798 {
799 rLst.Remove( 0, rLst.Count() );
800 ContentNode* pNode = aEditDoc.GetObject( nPara );
801 if ( pNode )
802 {
803 for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
804 {
805 EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
806 EECharAttrib aEEAttr;
807 aEEAttr.pAttr = pAttr->GetItem();
808 aEEAttr.nPara = nPara;
809 aEEAttr.nStart = pAttr->GetStart();
810 aEEAttr.nEnd = pAttr->GetEnd();
811 rLst.Insert( aEEAttr, rLst.Count() );
812 }
813 }
814 }
815
ParaAttribsToCharAttribs(ContentNode * pNode)816 void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
817 {
818 pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
819 xub_StrLen nEndPos = pNode->Len();
820 for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
821 {
822 if ( pNode->GetContentAttribs().HasItem( nWhich ) )
823 {
824 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
825 // Die Luecken auffuellen:
826 sal_uInt16 nLastEnd = 0;
827 EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
828 while ( pAttr )
829 {
830 nLastEnd = pAttr->GetEnd();
831 if ( pAttr->GetStart() > nLastEnd )
832 aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
833 // #112831# Last Attr might go from 0xffff to 0x0000
834 pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : NULL;
835 }
836
837 // Und den Rest:
838 if ( nLastEnd < nEndPos )
839 aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
840 }
841 }
842 bFormatted = sal_False;
843 // Portion braucht hier nicht invalidiert werden, geschieht woanders.
844 }
845
IdleFormattter()846 IdleFormattter::IdleFormattter()
847 {
848 pView = 0;
849 nRestarts = 0;
850 }
851
~IdleFormattter()852 IdleFormattter::~IdleFormattter()
853 {
854 pView = 0;
855 }
856
DoIdleFormat(EditView * pV)857 void IdleFormattter::DoIdleFormat( EditView* pV )
858 {
859 pView = pV;
860
861 if ( IsActive() )
862 nRestarts++;
863
864 if ( nRestarts > 4 )
865 ForceTimeout();
866 else
867 Start();
868 }
869
ForceTimeout()870 void IdleFormattter::ForceTimeout()
871 {
872 if ( IsActive() )
873 {
874 Stop();
875 ((Link&)GetTimeoutHdl()).Call( this );
876 }
877 }
878
ImplIMEInfos(const EditPaM & rPos,const String & rOldTextAfterStartPos)879 ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const String& rOldTextAfterStartPos )
880 : aOldTextAfterStartPos( rOldTextAfterStartPos )
881 {
882 aPos = rPos;
883 nLen = 0;
884 bCursor = sal_True;
885 pAttribs = NULL;
886 bWasCursorOverwrite = sal_False;
887 }
888
~ImplIMEInfos()889 ImplIMEInfos::~ImplIMEInfos()
890 {
891 delete[] pAttribs;
892 }
893
CopyAttribs(const sal_uInt16 * pA,sal_uInt16 nL)894 void ImplIMEInfos::CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL )
895 {
896 nLen = nL;
897 delete pAttribs;
898 pAttribs = new sal_uInt16[ nL ];
899 memcpy( pAttribs, pA, nL*sizeof(sal_uInt16) );
900 }
901
DestroyAttribs()902 void ImplIMEInfos::DestroyAttribs()
903 {
904 delete[] pAttribs;
905 pAttribs = NULL;
906 nLen = 0;
907 }
908