Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <vcl/wrkwin.hxx>
21 : #include <vcl/dialog.hxx>
22 : #include <vcl/msgbox.hxx>
23 : #include <vcl/svapp.hxx>
24 : #include <impedit.hxx>
25 : #include <editeng/editeng.hxx>
26 : #include <editdbg.hxx>
27 : #include <svl/smplhint.hxx>
28 : #include <editeng/lrspitem.hxx>
29 :
30 34085 : void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
31 : {
32 34085 : if ( pStylePool != pSPool )
33 : {
34 5334 : pStylePool = pSPool;
35 : }
36 34085 : }
37 :
38 0 : const SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara ) const
39 : {
40 0 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
41 0 : return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
42 : }
43 :
44 29997 : SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara )
45 : {
46 29997 : ContentNode* pNode = aEditDoc.GetObject( nPara );
47 29997 : return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
48 : }
49 :
50 0 : void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle )
51 : {
52 0 : aSel.Adjust( aEditDoc );
53 :
54 0 : sal_Int32 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
55 0 : sal_Int32 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
56 :
57 0 : bool _bUpdate = GetUpdateMode();
58 0 : SetUpdateMode( false );
59 :
60 0 : for ( sal_Int32 n = nStartPara; n <= nEndPara; n++ )
61 0 : SetStyleSheet( n, pStyle );
62 :
63 0 : SetUpdateMode( _bUpdate, 0 );
64 0 : }
65 :
66 84287 : void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle )
67 : {
68 : DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
69 84287 : ContentNode* pNode = aEditDoc.GetObject( nPara );
70 84287 : SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
71 84287 : if ( pStyle != pCurStyle )
72 : {
73 67065 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
74 : {
75 8431 : OUString aPrevStyleName;
76 8431 : if ( pCurStyle )
77 6353 : aPrevStyleName = pCurStyle->GetName();
78 :
79 16862 : OUString aNewStyleName;
80 8431 : if ( pStyle )
81 8431 : aNewStyleName = pStyle->GetName();
82 :
83 : InsertUndo(
84 8431 : new EditUndoSetStyleSheet(pEditEngine, aEditDoc.GetPos( pNode ),
85 6353 : aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
86 8431 : aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
87 31646 : pNode->GetContentAttribs().GetItems() ) );
88 : }
89 67065 : if ( pCurStyle )
90 6756 : EndListening( *pCurStyle, false );
91 67065 : pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
92 67065 : if ( pStyle )
93 67065 : StartListening( *pStyle, false );
94 67065 : ParaAttribsChanged( pNode );
95 : }
96 84287 : FormatAndUpdate();
97 84287 : }
98 :
99 0 : void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle )
100 : {
101 0 : SvxFont aFontFromStyle;
102 0 : CreateFont( aFontFromStyle, pStyle->GetItemSet() );
103 :
104 0 : bool bUsed = false;
105 0 : for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
106 : {
107 0 : ContentNode* pNode = aEditDoc.GetObject( nNode );
108 0 : if ( pNode->GetStyleSheet() == pStyle )
109 : {
110 0 : bUsed = true;
111 0 : if ( aStatus.UseCharAttribs() )
112 0 : pNode->SetStyleSheet( pStyle, aFontFromStyle );
113 : else
114 0 : pNode->SetStyleSheet( pStyle, false );
115 :
116 0 : ParaAttribsChanged( pNode );
117 : }
118 : }
119 0 : if ( bUsed )
120 : {
121 0 : GetEditEnginePtr()->StyleSheetChanged( pStyle );
122 0 : FormatAndUpdate();
123 0 : }
124 0 : }
125 :
126 0 : void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle )
127 : {
128 0 : for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
129 : {
130 0 : ContentNode* pNode = aEditDoc.GetObject(nNode);
131 0 : if ( pNode->GetStyleSheet() == pStyle )
132 : {
133 0 : pNode->SetStyleSheet( NULL );
134 0 : ParaAttribsChanged( pNode );
135 : }
136 : }
137 0 : FormatAndUpdate();
138 0 : }
139 :
140 0 : void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
141 : {
142 : // So that not a lot of unnecessary formatting is done when destructing:
143 0 : if ( !bDowning )
144 : {
145 :
146 0 : SfxStyleSheet* pStyle = NULL;
147 0 : sal_uLong nId = 0;
148 :
149 0 : const SfxStyleSheetHint* pStyleSheetHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint);
150 0 : if ( pStyleSheetHint )
151 : {
152 : DBG_ASSERT( pStyleSheetHint->GetStyleSheet()->ISA( SfxStyleSheet ), "No SfxStyleSheet!" );
153 0 : pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() );
154 0 : nId = pStyleSheetHint->GetHint();
155 : }
156 0 : else if ( dynamic_cast<const SfxSimpleHint*>(&rHint) && rBC.ISA( SfxStyleSheet ) )
157 : {
158 0 : pStyle = static_cast<SfxStyleSheet*>(&rBC);
159 0 : nId = dynamic_cast<const SfxSimpleHint*>(&rHint)->GetId();
160 : }
161 :
162 0 : if ( pStyle )
163 : {
164 0 : if ( ( nId == SFX_HINT_DYING ) ||
165 0 : ( nId == SfxStyleSheetHintId::INDESTRUCTION ) ||
166 : ( nId == SfxStyleSheetHintId::ERASED ) )
167 : {
168 0 : RemoveStyleFromParagraphs( pStyle );
169 : }
170 0 : else if ( ( nId == SFX_HINT_DATACHANGED ) ||
171 : ( nId == SfxStyleSheetHintId::MODIFIED ) )
172 : {
173 0 : UpdateParagraphsWithStyleSheet( pStyle );
174 : }
175 : }
176 : }
177 0 : }
178 :
179 5929 : EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
180 : {
181 : DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Incorrect selection ");
182 5929 : aSel.Adjust( aEditDoc );
183 :
184 5929 : ESelection aESel( CreateESel( aSel ) );
185 :
186 5929 : sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
187 5929 : sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
188 :
189 : DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
190 :
191 5929 : EditUndoSetAttribs* pUndo = NULL;
192 5929 : if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
193 : {
194 0 : SfxItemSet aTmpSet( GetEmptyItemSet() );
195 0 : aTmpSet.Put( rSet );
196 0 : pUndo = new EditUndoSetAttribs(pEditEngine, aESel, aTmpSet);
197 : }
198 : else
199 : {
200 5929 : pUndo = new EditUndoSetAttribs(pEditEngine, aESel, rSet);
201 : }
202 :
203 5929 : SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
204 :
205 12245 : for ( sal_Int32 nPara = nStartNode; nPara <= nEndNode; nPara++ )
206 : {
207 6316 : ContentNode* pNode = aEditDoc.GetObject( nPara );
208 : DBG_ASSERT( aEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" );
209 6316 : ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
210 6316 : pUndo->AppendContentInfo(pInf);
211 :
212 57139 : for ( sal_Int32 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
213 : {
214 50823 : const EditCharAttrib& rAttr = pNode->GetCharAttribs().GetAttribs()[nAttr];
215 50823 : if (rAttr.GetLen())
216 : {
217 41049 : EditCharAttrib* pNew = MakeCharAttrib(*pPool, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
218 41049 : pInf->AppendCharAttrib(pNew);
219 : }
220 : }
221 : }
222 5929 : return pUndo;
223 : }
224 :
225 0 : void ImpEditEngine::UndoActionStart( sal_uInt16 nId, const ESelection& aSel )
226 : {
227 0 : if ( IsUndoEnabled() && !IsInUndo() )
228 : {
229 0 : GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId );
230 : DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
231 0 : pUndoMarkSelection = new ESelection( aSel );
232 : }
233 0 : }
234 :
235 206011 : void ImpEditEngine::UndoActionStart( sal_uInt16 nId )
236 : {
237 206011 : if ( IsUndoEnabled() && !IsInUndo() )
238 : {
239 178618 : GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId );
240 : DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
241 : }
242 206011 : }
243 :
244 206011 : void ImpEditEngine::UndoActionEnd( sal_uInt16 )
245 : {
246 206011 : if ( IsUndoEnabled() && !IsInUndo() )
247 : {
248 178618 : GetUndoManager().LeaveListAction();
249 178618 : delete pUndoMarkSelection;
250 178618 : pUndoMarkSelection = NULL;
251 : }
252 206011 : }
253 :
254 82255 : void ImpEditEngine::InsertUndo( EditUndo* pUndo, bool bTryMerge )
255 : {
256 : DBG_ASSERT( !IsInUndo(), "InsertUndo in Undomodus!" );
257 82255 : if ( pUndoMarkSelection )
258 : {
259 0 : EditUndoMarkSelection* pU = new EditUndoMarkSelection(pEditEngine, *pUndoMarkSelection);
260 0 : GetUndoManager().AddUndoAction( pU, false );
261 0 : delete pUndoMarkSelection;
262 0 : pUndoMarkSelection = NULL;
263 : }
264 82255 : GetUndoManager().AddUndoAction( pUndo, bTryMerge );
265 :
266 82255 : mbLastTryMerge = bTryMerge;
267 82255 : }
268 :
269 2040294 : void ImpEditEngine::ResetUndoManager()
270 : {
271 2040294 : if ( HasUndoManager() )
272 1939513 : GetUndoManager().Clear();
273 2040294 : }
274 :
275 2686807 : void ImpEditEngine::EnableUndo( bool bEnable )
276 : {
277 : // When switching the mode Delete list:
278 2686807 : if ( bEnable != IsUndoEnabled() )
279 1381541 : ResetUndoManager();
280 :
281 2686807 : bUndoEnabled = bEnable;
282 2686807 : }
283 :
284 0 : bool ImpEditEngine::Undo( EditView* pView )
285 : {
286 0 : if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
287 : {
288 0 : SetActiveView( pView );
289 0 : GetUndoManager().Undo();
290 0 : return true;
291 : }
292 0 : return false;
293 : }
294 :
295 0 : bool ImpEditEngine::Redo( EditView* pView )
296 : {
297 0 : if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
298 : {
299 0 : SetActiveView( pView );
300 0 : GetUndoManager().Redo();
301 0 : return true;
302 : }
303 0 : return false;
304 : }
305 :
306 4463 : SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnlyHardAttrib )
307 : {
308 :
309 4463 : aSel.Adjust( aEditDoc );
310 :
311 4463 : SfxItemSet aCurSet( GetEmptyItemSet() );
312 :
313 4463 : sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
314 4463 : sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
315 :
316 : // iterate over the paragraphs ...
317 9517 : for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
318 : {
319 5054 : ContentNode* pNode = aEditDoc.GetObject( nNode );
320 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: GetAttrib" );
321 :
322 5054 : const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0;
323 5054 : const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // Can also be == nStart!
324 :
325 : // Problem: Templates ....
326 : // => Other way:
327 : // 1) Hard character attributes, as usual ...
328 : // 2) Examine Style and paragraph attributes only when OFF ...
329 :
330 : // First the very hard formatting ...
331 5054 : EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
332 :
333 5054 : if( nOnlyHardAttrib != EditEngineAttribs_OnlyHard )
334 : {
335 : // and then paragraph formatting and template...
336 251524 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
337 : {
338 246687 : if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
339 : {
340 205116 : if ( nOnlyHardAttrib == EditEngineAttribs_All )
341 : {
342 205116 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
343 205116 : aCurSet.Put( rItem );
344 : }
345 0 : else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SfxItemState::SET )
346 : {
347 0 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
348 0 : aCurSet.Put( rItem );
349 : }
350 : }
351 41571 : else if ( aCurSet.GetItemState( nWhich ) == SfxItemState::SET )
352 : {
353 40885 : const SfxPoolItem* pItem = NULL;
354 40885 : if ( nOnlyHardAttrib == EditEngineAttribs_All )
355 : {
356 40885 : pItem = &pNode->GetContentAttribs().GetItem( nWhich );
357 : }
358 0 : else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SfxItemState::SET )
359 : {
360 0 : pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
361 : }
362 : // pItem can only be NULL when nOnlyHardAttrib...
363 40885 : if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
364 : {
365 : // Problem: When Paragraph style with for example font,
366 : // but the Font is hard and completely different,
367 : // wrong in selection if invalidated....
368 : // => better not invalidate, instead CHANGE!
369 : // It would be better to fill each paragraph with
370 : // a itemset and compare this in large.
371 15419 : if ( nWhich <= EE_PARA_END )
372 19 : aCurSet.InvalidateItem( nWhich );
373 : }
374 : }
375 : }
376 : }
377 : }
378 :
379 : // fill empty slots with defaults ...
380 4463 : if ( nOnlyHardAttrib == EditEngineAttribs_All )
381 : {
382 220792 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
383 : {
384 216546 : if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
385 : {
386 0 : aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
387 : }
388 : }
389 : }
390 4463 : return aCurSet;
391 : }
392 :
393 :
394 26701 : SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags ) const
395 : {
396 : // Optimized function with less Puts(), which cause unnecessary cloning from default items.
397 : // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
398 :
399 :
400 26701 : ContentNode* pNode = const_cast<ContentNode*>(aEditDoc.GetObject(nPara));
401 : DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
402 : DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
403 :
404 26701 : SfxItemSet aAttribs( const_cast<ImpEditEngine*>(this)->GetEmptyItemSet() );
405 :
406 26701 : if ( pNode )
407 : {
408 26701 : if ( nEnd > pNode->Len() )
409 0 : nEnd = pNode->Len();
410 :
411 26701 : if ( nStart > nEnd )
412 0 : nStart = nEnd;
413 :
414 : // StyleSheet / Parattribs...
415 :
416 26701 : if ( pNode->GetStyleSheet() && ( nFlags & GetAttribsFlags::STYLESHEET ) )
417 9484 : aAttribs.Set(pNode->GetStyleSheet()->GetItemSet(), true);
418 :
419 26701 : if ( nFlags & GetAttribsFlags::PARAATTRIBS )
420 24417 : aAttribs.Put( pNode->GetContentAttribs().GetItems() );
421 :
422 : // CharAttribs...
423 :
424 26701 : if ( nFlags & GetAttribsFlags::CHARATTRIBS )
425 : {
426 : // Make testing easier...
427 26701 : const SfxItemPool& rPool = GetEditDoc().GetItemPool();
428 26701 : pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool));
429 :
430 26701 : const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
431 189682 : for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr)
432 : {
433 163623 : const EditCharAttrib& rAttr = rAttrs[nAttr];
434 :
435 163623 : if ( nStart == nEnd )
436 : {
437 102364 : sal_Int32 nCursorPos = nStart;
438 102364 : if ( ( rAttr.GetStart() <= nCursorPos ) && ( rAttr.GetEnd() >= nCursorPos ) )
439 : {
440 : // To be used the attribute has to start BEFORE the position, or it must be a
441 : // new empty attr AT the position, or we are on position 0.
442 102021 : if ( ( rAttr.GetStart() < nCursorPos ) || rAttr.IsEmpty() || !nCursorPos )
443 : {
444 : // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
445 : // but that s no problem, the empty item will come later and win.
446 102021 : aAttribs.Put( *rAttr.GetItem() );
447 : }
448 : }
449 : }
450 : else
451 : {
452 : // Check every attribute covering the area, partial or full.
453 61259 : if ( ( rAttr.GetStart() < nEnd ) && ( rAttr.GetEnd() > nStart ) )
454 : {
455 52454 : if ( ( rAttr.GetStart() <= nStart ) && ( rAttr.GetEnd() >= nEnd ) )
456 : {
457 : // full coverage
458 51168 : aAttribs.Put( *rAttr.GetItem() );
459 : }
460 : else
461 : {
462 : // OptimizeRagnge() assures that not the same attr can follow for full coverage
463 : // only partial, check with current, when using para/styhe, otherwise invalid.
464 2572 : if ( !( nFlags & (GetAttribsFlags::PARAATTRIBS|GetAttribsFlags::STYLESHEET) ) ||
465 1286 : ( *rAttr.GetItem() != aAttribs.Get( rAttr.Which() ) ) )
466 : {
467 1242 : aAttribs.InvalidateItem( rAttr.Which() );
468 : }
469 : }
470 : }
471 : }
472 :
473 163623 : if ( rAttr.GetStart() > nEnd )
474 : {
475 642 : break;
476 : }
477 : }
478 : }
479 : }
480 :
481 26701 : return aAttribs;
482 : }
483 :
484 :
485 11345 : void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, sal_uInt8 nSpecial )
486 : {
487 11345 : aSel.Adjust( aEditDoc );
488 :
489 : // When no selection => use the Attribute on the word.
490 : // ( the RTF-parser should actually never call the Method without a Range )
491 11345 : if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
492 181 : aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false );
493 :
494 11345 : sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
495 11345 : sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
496 :
497 11345 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
498 : {
499 4728 : EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
500 4728 : pUndo->SetSpecial( nSpecial );
501 4728 : InsertUndo( pUndo );
502 : }
503 :
504 11345 : bool bCheckLanguage = false;
505 11345 : if ( GetStatus().DoOnlineSpelling() )
506 : {
507 3234 : bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SfxItemState::SET ) ||
508 3234 : ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SfxItemState::SET ) ||
509 3234 : ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SfxItemState::SET );
510 : }
511 :
512 : // iterate over the paragraphs ...
513 23194 : for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
514 : {
515 11849 : bool bParaAttribFound = false;
516 11849 : bool bCharAttribFound = false;
517 :
518 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not founden: SetAttribs" );
519 : DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" );
520 :
521 11849 : ContentNode* pNode = aEditDoc.GetObject( nNode );
522 11849 : ParaPortion* pPortion = GetParaPortions()[nNode];
523 :
524 11849 : const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0;
525 11849 : const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart!
526 :
527 : // Iterate over the Items...
528 616148 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
529 : {
530 604299 : if ( rSet.GetItemState( nWhich ) == SfxItemState::SET )
531 : {
532 83852 : const SfxPoolItem& rItem = rSet.Get( nWhich );
533 83852 : if ( nWhich <= EE_PARA_END )
534 : {
535 7229 : pNode->GetContentAttribs().GetItems().Put( rItem );
536 7229 : bParaAttribFound = true;
537 : }
538 : else
539 : {
540 76623 : aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
541 76623 : bCharAttribFound = true;
542 76623 : if ( nSpecial == ATTRSPECIAL_EDGE )
543 : {
544 0 : CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
545 0 : for (size_t i = 0, n = rAttribs.size(); i < n; ++i)
546 : {
547 0 : EditCharAttrib& rAttr = rAttribs[i];
548 0 : if (rAttr.GetStart() > nEndPos)
549 0 : break;
550 :
551 0 : if (rAttr.GetEnd() == nEndPos && rAttr.Which() == nWhich)
552 : {
553 0 : rAttr.SetEdge(true);
554 0 : break;
555 : }
556 : }
557 : }
558 : }
559 : }
560 : }
561 :
562 11849 : if ( bParaAttribFound )
563 : {
564 1397 : ParaAttribsChanged( pPortion->GetNode() );
565 : }
566 10452 : else if ( bCharAttribFound )
567 : {
568 8630 : bFormatted = false;
569 8630 : if ( !pNode->Len() || ( nStartPos != nEndPos ) )
570 : {
571 8082 : pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
572 8082 : if ( bCheckLanguage )
573 1306 : pNode->GetWrongList()->SetInvalidRange(nStartPos, nEndPos);
574 : }
575 : }
576 : }
577 11345 : }
578 :
579 969 : void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, bool bRemoveParaAttribs, sal_uInt16 nWhich )
580 : {
581 969 : aSel.Adjust( aEditDoc );
582 :
583 969 : sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
584 969 : sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
585 :
586 969 : const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
587 :
588 969 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
589 : {
590 : // Possibly a special Undo, or itemset*
591 969 : EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
592 969 : pUndo->SetRemoveAttribs( true );
593 969 : pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
594 969 : pUndo->SetRemoveWhich( nWhich );
595 969 : InsertUndo( pUndo );
596 : }
597 :
598 : // iterate over the paragraphs ...
599 1938 : for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
600 : {
601 969 : ContentNode* pNode = aEditDoc.GetObject( nNode );
602 969 : ParaPortion* pPortion = GetParaPortions()[nNode];
603 :
604 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" );
605 : DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" );
606 :
607 969 : const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0;
608 969 : const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart!
609 :
610 : // Optimize: If whole paragraph, then RemoveCharAttribs (nPara)?
611 969 : bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
612 969 : if ( bRemoveParaAttribs )
613 : {
614 501 : SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidated
615 : }
616 : else
617 : {
618 : // For 'Format-Standard' also the character attributes should
619 : // disappear, which were set as paragraph attributes by the
620 : // DrawingEngine. These could not have been set by the user anyway.
621 :
622 : // #106871# Not when nWhich
623 : // Would have been better to offer a separate method for format/standard...
624 468 : if ( !nWhich )
625 : {
626 468 : SfxItemSet aAttribs( GetParaAttribs( nNode ) );
627 15912 : for ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
628 15444 : aAttribs.ClearItem( nW );
629 468 : SetParaAttribs( nNode, aAttribs );
630 : }
631 : }
632 :
633 969 : if ( bChanged && !bRemoveParaAttribs )
634 : {
635 235 : bFormatted = false;
636 235 : pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
637 : }
638 : }
639 969 : }
640 :
641 144903 : void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures )
642 : {
643 144903 : ContentNode* pNode = aEditDoc.GetObject( nPara );
644 144903 : ParaPortion* pPortion = GetParaPortions().SafeGetObject( nPara );
645 :
646 : DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" );
647 : DBG_ASSERT( pPortion, "Portion not found: RemoveCharAttribs" );
648 :
649 144903 : if ( !pNode )
650 144903 : return;
651 :
652 144903 : size_t nAttr = 0;
653 144903 : CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
654 144903 : EditCharAttrib* pAttr = GetAttrib(rAttrs, nAttr);
655 300063 : while ( pAttr )
656 : {
657 12313 : if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
658 5610 : ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
659 : {
660 2056 : pNode->GetCharAttribs().Remove(nAttr);
661 2056 : nAttr--;
662 : }
663 10257 : nAttr++;
664 10257 : pAttr = GetAttrib(rAttrs, nAttr);
665 : }
666 :
667 : #if OSL_DEBUG_LEVEL > 0
668 : CharAttribList::DbgCheckAttribs(pNode->GetCharAttribs());
669 : #endif
670 :
671 144903 : pPortion->MarkSelectionInvalid( 0, pNode->Len() );
672 : }
673 :
674 1061501 : void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
675 : {
676 1061501 : ContentNode* pNode = aEditDoc.GetObject( nPara );
677 :
678 1061501 : if ( !pNode )
679 1061501 : return;
680 :
681 1061501 : if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
682 : {
683 546408 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
684 : {
685 36411 : if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
686 : {
687 0 : SfxItemSet aTmpSet( GetEmptyItemSet() );
688 0 : aTmpSet.Put( rSet );
689 0 : InsertUndo(new EditUndoSetParaAttribs(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet));
690 : }
691 : else
692 : {
693 36411 : InsertUndo(new EditUndoSetParaAttribs(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet));
694 : }
695 : }
696 546408 : pNode->GetContentAttribs().GetItems().Set( rSet );
697 546408 : if ( aStatus.UseCharAttribs() )
698 546408 : pNode->CreateDefFont();
699 :
700 546408 : ParaAttribsChanged( pNode );
701 : }
702 : }
703 :
704 886400 : const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_Int32 nPara ) const
705 : {
706 886400 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
707 : assert(pNode && "Node not found: GetParaAttribs");
708 886400 : return pNode->GetContentAttribs().GetItems();
709 : }
710 :
711 14405 : bool ImpEditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const
712 : {
713 14405 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
714 : assert(pNode && "Node not found: HasParaAttrib");
715 14405 : return pNode->GetContentAttribs().HasItem( nWhich );
716 : }
717 :
718 1850955 : const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const
719 : {
720 1850955 : const ContentNode* pNode = aEditDoc.GetObject(nPara);
721 : assert(pNode && "Node not found: GetParaAttrib");
722 1850955 : return pNode->GetContentAttribs().GetItem(nWhich);
723 : }
724 :
725 2053 : void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const
726 : {
727 2053 : rLst.clear();
728 2053 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
729 2053 : if ( pNode )
730 : {
731 2053 : rLst.reserve(pNode->GetCharAttribs().Count());
732 2053 : const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
733 16143 : for (size_t i = 0; i < rAttrs.size(); ++i)
734 : {
735 14090 : const EditCharAttrib& rAttr = rAttrs[i];
736 : EECharAttrib aEEAttr;
737 14090 : aEEAttr.pAttr = rAttr.GetItem();
738 14090 : aEEAttr.nPara = nPara;
739 14090 : aEEAttr.nStart = rAttr.GetStart();
740 14090 : aEEAttr.nEnd = rAttr.GetEnd();
741 14090 : rLst.push_back(aEEAttr);
742 : }
743 : }
744 2053 : }
745 :
746 0 : void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
747 : {
748 0 : pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
749 0 : sal_Int32 nEndPos = pNode->Len();
750 0 : for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
751 : {
752 0 : if ( pNode->GetContentAttribs().HasItem( nWhich ) )
753 : {
754 0 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
755 : // Fill the gap:
756 0 : sal_Int32 nLastEnd = 0;
757 0 : const EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
758 0 : while ( pAttr )
759 : {
760 0 : nLastEnd = pAttr->GetEnd();
761 0 : if ( pAttr->GetStart() > nLastEnd )
762 0 : aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
763 : // #112831# Last Attr might go from 0xffff to 0x0000
764 0 : pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : NULL;
765 : }
766 :
767 : // And the Rest:
768 0 : if ( nLastEnd < nEndPos )
769 0 : aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
770 : }
771 : }
772 0 : bFormatted = false;
773 : // Portion does not need to be invalidated here, happens elsewhere.
774 0 : }
775 :
776 42102 : IdleFormattter::IdleFormattter()
777 : {
778 42102 : pView = 0;
779 42102 : nRestarts = 0;
780 42102 : }
781 :
782 79542 : IdleFormattter::~IdleFormattter()
783 : {
784 39771 : pView = 0;
785 39771 : }
786 :
787 0 : void IdleFormattter::DoIdleFormat( EditView* pV )
788 : {
789 0 : pView = pV;
790 :
791 0 : if ( IsActive() )
792 0 : nRestarts++;
793 :
794 0 : if ( nRestarts > 4 )
795 0 : ForceTimeout();
796 : else
797 0 : Start();
798 0 : }
799 :
800 2943 : void IdleFormattter::ForceTimeout()
801 : {
802 2943 : if ( IsActive() )
803 : {
804 0 : Stop();
805 0 : ((Link<Idle *, void>&)GetIdleHdl()).Call( this );
806 : }
807 2943 : }
808 :
809 0 : ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const OUString& rOldTextAfterStartPos )
810 0 : : aOldTextAfterStartPos( rOldTextAfterStartPos )
811 : {
812 0 : aPos = rPos;
813 0 : nLen = 0;
814 0 : bCursor = true;
815 0 : pAttribs = NULL;
816 0 : bWasCursorOverwrite = false;
817 0 : }
818 :
819 0 : ImplIMEInfos::~ImplIMEInfos()
820 : {
821 0 : delete[] pAttribs;
822 0 : }
823 :
824 0 : void ImplIMEInfos::CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL )
825 : {
826 0 : nLen = nL;
827 0 : delete[] pAttribs;
828 0 : pAttribs = new sal_uInt16[ nL ];
829 0 : memcpy( pAttribs, pA, nL*sizeof(sal_uInt16) );
830 0 : }
831 :
832 0 : void ImplIMEInfos::DestroyAttribs()
833 : {
834 0 : delete[] pAttribs;
835 0 : pAttribs = NULL;
836 0 : nLen = 0;
837 0 : }
838 :
839 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|