LibreOffice Module editeng (master) 1
impedit5.cxx
Go to the documentation of this file.
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 <memory>
21#include "impedit.hxx"
22#include <editeng/editeng.hxx>
23#include <svl/hint.hxx>
24#include <sfx2/app.hxx>
25#include <utility>
26
28{
29 if ( pStylePool != pSPool )
30 {
31 pStylePool = pSPool;
32 }
33}
34
35const SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara ) const
36{
37 const ContentNode* pNode = aEditDoc.GetObject( nPara );
38 return pNode ? pNode->GetContentAttribs().GetStyleSheet() : nullptr;
39}
40
42{
43 ContentNode* pNode = aEditDoc.GetObject( nPara );
44 return pNode ? pNode->GetContentAttribs().GetStyleSheet() : nullptr;
45}
46
48{
49 aSel.Adjust( aEditDoc );
50
51 sal_Int32 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
52 sal_Int32 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
53
54 bool _bUpdate = SetUpdateLayout( false );
55
56 for ( sal_Int32 n = nStartPara; n <= nEndPara; n++ )
57 SetStyleSheet( n, pStyle );
58
59 SetUpdateLayout( _bUpdate );
60}
61
62void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle )
63{
64 DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
65 ContentNode* pNode = aEditDoc.GetObject( nPara );
66 SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
67 if ( pStyle != pCurStyle )
68 {
70 {
71 OUString aPrevStyleName;
72 if ( pCurStyle )
73 aPrevStyleName = pCurStyle->GetName();
74
75 OUString aNewStyleName;
76 if ( pStyle )
77 aNewStyleName = pStyle->GetName();
78
80 std::make_unique<EditUndoSetStyleSheet>(pEditEngine, aEditDoc.GetPos( pNode ),
81 aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SfxStyleFamily::Para,
82 aNewStyleName, pStyle ? pStyle->GetFamily() : SfxStyleFamily::Para,
83 pNode->GetContentAttribs().GetItems() ) );
84 }
85 if ( pCurStyle )
86 EndListening( *pCurStyle );
87 pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
88 if ( pStyle )
89 StartListening(*pStyle, DuplicateHandling::Allow);
90
91 if (pNode->GetWrongList())
92 pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len());
93 ParaAttribsChanged( pNode );
94 }
95 if (IsUpdateLayout())
97}
98
100{
101 SvxFont aFontFromStyle;
102 CreateFont( aFontFromStyle, pStyle->GetItemSet() );
103
104 bool bUsed = false;
105 for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
106 {
107 ContentNode* pNode = aEditDoc.GetObject( nNode );
108 if ( pNode->GetStyleSheet() == pStyle )
109 {
110 bUsed = true;
111 if ( aStatus.UseCharAttribs() )
112 pNode->SetStyleSheet( pStyle, aFontFromStyle );
113 else
114 pNode->SetStyleSheet( pStyle, false );
115
116 if (pNode->GetWrongList())
117 pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len());
118 ParaAttribsChanged( pNode );
119 }
120 }
121 if ( bUsed )
122 {
124 if (IsUpdateLayout())
126 }
127}
128
130{
131 for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
132 {
133 ContentNode* pNode = aEditDoc.GetObject(nNode);
134 if ( pNode->GetStyleSheet() == pStyle )
135 {
136 pNode->SetStyleSheet( nullptr );
137 ParaAttribsChanged( pNode );
138 }
139 }
140 if (IsUpdateLayout())
142}
143
145{
146 // So that not a lot of unnecessary formatting is done when destructing:
147 if ( !bDowning )
148 {
149 SfxHintId nId = rHint.GetId();
150 if ( ( nId == SfxHintId::StyleSheetInDestruction ) ||
151 ( nId == SfxHintId::StyleSheetErased ) )
152 {
153 const SfxStyleSheetHint* pStyleSheetHint = static_cast<const SfxStyleSheetHint*>(&rHint);
154 SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() );
156 }
157 else if ( nId == SfxHintId::StyleSheetModified )
158 {
159 const SfxStyleSheetHint* pStyleSheetHint = static_cast<const SfxStyleSheetHint*>(&rHint);
160 SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() );
162 }
163 else if ( nId == SfxHintId::Dying )
164 {
165 if ( auto pStyle = dynamic_cast< SfxStyleSheet* >(&rBC) )
167 }
168 else if ( nId == SfxHintId::DataChanged )
169 {
170 if ( auto pStyle = dynamic_cast< SfxStyleSheet* >(&rBC) )
172 }
173 }
174 if (rHint.GetId() == SfxHintId::Dying && dynamic_cast<const SfxApplication*>(&rBC))
175 Dispose();
176}
177
178std::unique_ptr<EditUndoSetAttribs> ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
179{
180 DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Incorrect selection ");
181 aSel.Adjust( aEditDoc );
182
183 ESelection aESel( CreateESel( aSel ) );
184
185 sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
186 sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
187
188 DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
189
190 std::unique_ptr<EditUndoSetAttribs> pUndo;
191 if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
192 {
193 SfxItemSet aTmpSet( GetEmptyItemSet() );
194 aTmpSet.Put( rSet );
195 pUndo.reset( new EditUndoSetAttribs(pEditEngine, aESel, std::move(aTmpSet)) );
196 }
197 else
198 {
199 pUndo.reset( new EditUndoSetAttribs(pEditEngine, aESel, rSet) );
200 }
201
202 SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
203
204 for ( sal_Int32 nPara = nStartNode; nPara <= nEndNode; nPara++ )
205 {
206 ContentNode* pNode = aEditDoc.GetObject( nPara );
207 DBG_ASSERT( aEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" );
208 ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
209 pUndo->AppendContentInfo(pInf);
210
211 for ( sal_Int32 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
212 {
213 const EditCharAttrib& rAttr = *pNode->GetCharAttribs().GetAttribs()[nAttr];
214 if (rAttr.GetLen())
215 {
216 EditCharAttrib* pNew = MakeCharAttrib(*pPool, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
217 pInf->AppendCharAttrib(pNew);
218 }
219 }
220 }
221 return pUndo;
222}
223
224ViewShellId ImpEditEngine::CreateViewShellId()
225{
226 ViewShellId nRet(-1);
227
228 const EditView* pEditView = pEditEngine ? pEditEngine->GetActiveView() : nullptr;
229 const OutlinerViewShell* pViewShell = pEditView ? pEditView->GetImpEditView()->GetViewShell() : nullptr;
230 if (pViewShell)
231 nRet = pViewShell->GetViewShellId();
232
233 return nRet;
234}
235
236void ImpEditEngine::UndoActionStart( sal_uInt16 nId, const ESelection& aSel )
237{
238 if ( IsUndoEnabled() && !IsInUndo() )
239 {
240 GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId, CreateViewShellId() );
241 DBG_ASSERT( !moUndoMarkSelection, "UndoAction SelectionMarker?" );
242 moUndoMarkSelection = aSel;
243 }
244}
245
246void ImpEditEngine::UndoActionStart( sal_uInt16 nId )
247{
248 if ( IsUndoEnabled() && !IsInUndo() )
249 {
250 GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId, CreateViewShellId() );
251 DBG_ASSERT( !moUndoMarkSelection, "UndoAction SelectionMarker?" );
252 }
253}
254
255void ImpEditEngine::UndoActionEnd()
256{
257 if ( IsUndoEnabled() && !IsInUndo() )
258 {
259 GetUndoManager().LeaveListAction();
260 moUndoMarkSelection.reset();
261 }
262}
263
264void ImpEditEngine::InsertUndo( std::unique_ptr<EditUndo> pUndo, bool bTryMerge )
265{
266 DBG_ASSERT( !IsInUndo(), "InsertUndo in Undo mode!" );
267 if ( moUndoMarkSelection )
268 {
269 GetUndoManager().AddUndoAction( std::make_unique<EditUndoMarkSelection>(pEditEngine, *moUndoMarkSelection) );
270 moUndoMarkSelection.reset();
271 }
272 GetUndoManager().AddUndoAction( std::move(pUndo), bTryMerge );
273
274 mbLastTryMerge = bTryMerge;
275}
276
277void ImpEditEngine::ResetUndoManager()
278{
279 if ( HasUndoManager() )
280 GetUndoManager().Clear();
281}
282
283void ImpEditEngine::EnableUndo( bool bEnable )
284{
285 // When switching the mode Delete list:
286 if ( bEnable != IsUndoEnabled() )
287 ResetUndoManager();
288
289 bUndoEnabled = bEnable;
290}
291
292void ImpEditEngine::Undo( EditView* pView )
293{
294 if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
295 {
296 SetActiveView( pView );
297 GetUndoManager().Undo();
298 }
299}
300
301void ImpEditEngine::Redo( EditView* pView )
302{
303 if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
304 {
305 SetActiveView( pView );
306 GetUndoManager().Redo();
307 }
308}
309
310SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnlyHardAttrib )
311{
312
313 aSel.Adjust( aEditDoc );
314
315 SfxItemSet aCurSet( GetEmptyItemSet() );
316
317 sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
318 sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
319
320 // iterate over the paragraphs ...
321 for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
322 {
323 ContentNode* pNode = aEditDoc.GetObject( nNode );
324 DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: GetAttrib" );
325
326 const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0;
327 const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // Can also be == nStart!
328
329 // Problem: Templates...
330 // => Other way:
331 // 1) Hard character attributes, as usual...
332 // 2) Examine Style and paragraph attributes only when OFF...
333
334 // First the very hard formatting...
335 EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
336
337 if( nOnlyHardAttrib != EditEngineAttribs::OnlyHard )
338 {
339 // and then paragraph formatting and template...
340 for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
341 {
342 if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
343 {
344 if ( nOnlyHardAttrib == EditEngineAttribs::All )
345 {
346 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
347 aCurSet.Put( rItem );
348 }
349 else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SfxItemState::SET )
350 {
351 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
352 aCurSet.Put( rItem );
353 }
354 }
355 else if ( aCurSet.GetItemState( nWhich ) == SfxItemState::SET )
356 {
357 const SfxPoolItem* pItem = nullptr;
358 if ( nOnlyHardAttrib == EditEngineAttribs::All )
359 {
360 pItem = &pNode->GetContentAttribs().GetItem( nWhich );
361 }
362 else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SfxItemState::SET )
363 {
364 pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
365 }
366 // pItem can only be NULL when nOnlyHardAttrib...
367 if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
368 {
369 // Problem: When Paragraph style with for example font,
370 // but the Font is hard and completely different,
371 // wrong in selection if invalidated....
372 // => better not invalidate, instead CHANGE!
373 // It would be better to fill each paragraph with
374 // an itemset and compare this in large.
375 if ( nWhich <= EE_PARA_END )
376 aCurSet.InvalidateItem( nWhich );
377 }
378 }
379 }
380 }
381 }
382
383 // fill empty slots with defaults ...
384 if ( nOnlyHardAttrib == EditEngineAttribs::All )
385 {
386 for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
387 {
388 if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
389 {
390 aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
391 }
392 }
393 }
394 return aCurSet;
395}
396
397
398SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags ) const
399{
400 // Optimized function with fewer Puts(), which cause unnecessary cloning from default items.
401 // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
402
403
404 ContentNode* pNode = const_cast<ContentNode*>(aEditDoc.GetObject(nPara));
405 DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
406 DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
407
408 SfxItemSet aAttribs(GetEmptyItemSet());
409
410 if ( pNode )
411 {
412 if ( nEnd > pNode->Len() )
413 nEnd = pNode->Len();
414
415 if ( nStart > nEnd )
416 nStart = nEnd;
417
418 // StyleSheet / Parattribs...
419
420 if ( pNode->GetStyleSheet() && ( nFlags & GetAttribsFlags::STYLESHEET ) )
421 aAttribs.Set(pNode->GetStyleSheet()->GetItemSet());
422
423 if ( nFlags & GetAttribsFlags::PARAATTRIBS )
424 aAttribs.Put( pNode->GetContentAttribs().GetItems() );
425
426 // CharAttribs...
427
428 if ( nFlags & GetAttribsFlags::CHARATTRIBS )
429 {
430 // Make testing easier...
431 const SfxItemPool& rPool = GetEditDoc().GetItemPool();
432 pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool));
433
434 const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
435 for (const auto & nAttr : rAttrs)
436 {
437 const EditCharAttrib& rAttr = *nAttr;
438
439 if ( nStart == nEnd )
440 {
441 sal_Int32 nCursorPos = nStart;
442 if ( ( rAttr.GetStart() <= nCursorPos ) && ( rAttr.GetEnd() >= nCursorPos ) )
443 {
444 // To be used the attribute has to start BEFORE the position, or it must be a
445 // new empty attr AT the position, or we are on position 0.
446 if ( ( rAttr.GetStart() < nCursorPos ) || rAttr.IsEmpty() || !nCursorPos )
447 {
448 // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
449 // but that s no problem, the empty item will come later and win.
450 aAttribs.Put( *rAttr.GetItem() );
451 }
452 }
453 }
454 else
455 {
456 // Check every attribute covering the area, partial or full.
457 if ( ( rAttr.GetStart() < nEnd ) && ( rAttr.GetEnd() > nStart ) )
458 {
459 if ( ( rAttr.GetStart() <= nStart ) && ( rAttr.GetEnd() >= nEnd ) )
460 {
461 // full coverage
462 aAttribs.Put( *rAttr.GetItem() );
463 }
464 else
465 {
466 // OptimizeRanges() assures that not the same attr can follow for full coverage
467 // only partial, check with current, when using para/style, otherwise invalid.
468 if ( !( nFlags & (GetAttribsFlags::PARAATTRIBS|GetAttribsFlags::STYLESHEET) ) ||
469 ( *rAttr.GetItem() != aAttribs.Get( rAttr.Which() ) ) )
470 {
471 aAttribs.InvalidateItem( rAttr.Which() );
472 }
473 }
474 }
475 }
476
477 if ( rAttr.GetStart() > nEnd )
478 {
479 break;
480 }
481 }
482 }
483 }
484
485 return aAttribs;
486}
487
488
489void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetAttribsMode nSpecial, bool bSetSelection )
490{
491 aSel.Adjust( aEditDoc );
492
493 // When no selection => use the Attribute on the word.
494 // ( the RTF-parser should actually never call the Method without a Range )
495 if ( nSpecial == SetAttribsMode::WholeWord && !aSel.HasRange() )
496 aSel = SelectWord( aSel, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false );
497
498 sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
499 sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
500
501 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
502 {
503 std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, rSet );
504 pUndo->SetSpecial( nSpecial );
505 pUndo->SetUpdateSelection(bSetSelection);
506 InsertUndo( std::move(pUndo) );
507 }
508
509 bool bCheckLanguage = false;
510 if ( GetStatus().DoOnlineSpelling() )
511 {
512 bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SfxItemState::SET ) ||
513 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SfxItemState::SET ) ||
514 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SfxItemState::SET );
515 }
516
517 // iterate over the paragraphs ...
518 for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
519 {
520 bool bParaAttribFound = false;
521 bool bCharAttribFound = false;
522
523 DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" );
524 DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" );
525
526 ContentNode* pNode = aEditDoc.GetObject( nNode );
527 ParaPortion* pPortion = GetParaPortions()[nNode];
528
529 const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0;
530 const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart!
531
532 // Iterate over the Items...
533 for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
534 {
535 if ( rSet.GetItemState( nWhich ) == SfxItemState::SET )
536 {
537 const SfxPoolItem& rItem = rSet.Get( nWhich );
538 if ( nWhich <= EE_PARA_END )
539 {
540 pNode->GetContentAttribs().GetItems().Put( rItem );
541 bParaAttribFound = true;
542 }
543 else
544 {
545 aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
546 bCharAttribFound = true;
547 if ( nSpecial == SetAttribsMode::Edge )
548 {
549 CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
550 for (std::unique_ptr<EditCharAttrib> & rAttrib : rAttribs)
551 {
552 EditCharAttrib& rAttr = *rAttrib;
553 if (rAttr.GetStart() > nEndPos)
554 break;
555
556 if (rAttr.GetEnd() == nEndPos && rAttr.Which() == nWhich)
557 {
558 rAttr.SetEdge(true);
559 break;
560 }
561 }
562 }
563 }
564 }
565 }
566
567 if ( bParaAttribFound )
568 {
569 ParaAttribsChanged( pPortion->GetNode() );
570 }
571 else if ( bCharAttribFound )
572 {
573 bFormatted = false;
574 if ( !pNode->Len() || ( nStartPos != nEndPos ) )
575 {
576 pPortion->MarkSelectionInvalid( nStartPos );
577 if ( bCheckLanguage )
578 pNode->GetWrongList()->SetInvalidRange(nStartPos, nEndPos);
579 }
580 }
581 }
582}
583
584void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich )
585{
586 aSel.Adjust( aEditDoc );
587
588 sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
589 sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
590 bool bRemoveParaAttribs = eMode == EERemoveParaAttribsMode::RemoveAll;
591 const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : nullptr;
592
593 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
594 {
595 // Possibly a special Undo, or itemset*
596 std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
597 pUndo->SetRemoveAttribs( true );
598 pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
599 pUndo->SetRemoveWhich( nWhich );
600 InsertUndo( std::move(pUndo) );
601 }
602
603 // iterate over the paragraphs ...
604 for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
605 {
606 ContentNode* pNode = aEditDoc.GetObject( nNode );
607 ParaPortion* pPortion = GetParaPortions()[nNode];
608
609 DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" );
610 DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" );
611
612 const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0;
613 const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart!
614
615 // Optimize: If whole paragraph, then RemoveCharAttribs (nPara)?
616 bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
617 if ( bRemoveParaAttribs )
618 {
619 SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidated
620 }
621 else if (eMode == EERemoveParaAttribsMode::RemoveCharItems)
622 {
623 // For 'Format-Standard' also the character attributes should
624 // disappear, which were set as paragraph attributes by the
625 // DrawingEngine. These could not have been set by the user anyway.
626
627 // #106871# Not when nWhich
628 // Would have been better to offer a separate method for format/standard...
629 if ( !nWhich )
630 {
631 SfxItemSet aAttribs( GetParaAttribs( nNode ) );
632 for ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
633 aAttribs.ClearItem( nW );
634 SetParaAttribs( nNode, aAttribs );
635 }
636 }
637
638 if ( bChanged && !bRemoveParaAttribs )
639 {
640 bFormatted = false;
641 pPortion->MarkSelectionInvalid( nStartPos );
642 }
643 }
644}
645
646void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures )
647{
648 ContentNode* pNode = aEditDoc.GetObject( nPara );
649 ParaPortion* pPortion = GetParaPortions().SafeGetObject( nPara );
650
651 DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" );
652 DBG_ASSERT( pPortion, "Portion not found: RemoveCharAttribs" );
653
654 if ( !pNode || !pPortion )
655 return;
656
657 size_t nAttr = 0;
658 CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
659 EditCharAttrib* pAttr = GetAttrib(rAttrs, nAttr);
660 while ( pAttr )
661 {
662 if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
663 ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
664 {
665 pNode->GetCharAttribs().Remove(nAttr);
666 nAttr--;
667 }
668 nAttr++;
669 pAttr = GetAttrib(rAttrs, nAttr);
670 }
671
672#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
673 CharAttribList::DbgCheckAttribs(pNode->GetCharAttribs());
674#endif
675
676 pPortion->MarkSelectionInvalid( 0 );
677}
678
679void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
680{
681 ContentNode* pNode = aEditDoc.GetObject( nPara );
682
683 if ( !pNode )
684 return;
685
686 if ( pNode->GetContentAttribs().GetItems() == rSet )
687 return;
688
689 if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
690 {
691 if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
692 {
693 SfxItemSet aTmpSet( GetEmptyItemSet() );
694 aTmpSet.Put( rSet );
695 InsertUndo(std::make_unique<EditUndoSetParaAttribs>(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet));
696 }
697 else
698 {
699 InsertUndo(std::make_unique<EditUndoSetParaAttribs>(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet));
700 }
701 }
702
703 bool bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SfxItemState::SET ) ||
704 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SfxItemState::SET ) ||
705 ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SfxItemState::SET );
706
707 pNode->GetContentAttribs().GetItems().Set( rSet );
708
709 if ( bCheckLanguage && pNode->GetWrongList() )
710 pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len());
711
712 if ( aStatus.UseCharAttribs() )
713 pNode->CreateDefFont();
714
715 ParaAttribsChanged( pNode );
716}
717
718const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_Int32 nPara ) const
719{
720 const ContentNode* pNode = aEditDoc.GetObject( nPara );
721 assert(pNode && "Node not found: GetParaAttribs");
722 return pNode->GetContentAttribs().GetItems();
723}
724
725bool ImpEditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const
726{
727 const ContentNode* pNode = aEditDoc.GetObject( nPara );
728 assert(pNode && "Node not found: HasParaAttrib");
729 return pNode->GetContentAttribs().HasItem( nWhich );
730}
731
732const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const
733{
734 const ContentNode* pNode = aEditDoc.GetObject(nPara);
735 assert(pNode && "Node not found: GetParaAttrib");
736 return pNode->GetContentAttribs().GetItem(nWhich);
737}
738
739void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const
740{
741 rLst.clear();
742 const ContentNode* pNode = aEditDoc.GetObject( nPara );
743 if ( !pNode )
744 return;
745
746 rLst.reserve(pNode->GetCharAttribs().Count());
747 const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
748 for (const auto & i : rAttrs)
749 {
750 const EditCharAttrib& rAttr = *i;
751 EECharAttrib aEEAttr(rAttr.GetStart(), rAttr.GetEnd(), rAttr.GetItem());
752 rLst.push_back(aEEAttr);
753 }
754}
755
756void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
757{
758 pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
759 sal_Int32 nEndPos = pNode->Len();
760 for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
761 {
762 if ( pNode->GetContentAttribs().HasItem( nWhich ) )
763 {
764 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
765 // Fill the gap:
766 sal_Int32 nLastEnd = 0;
767 const EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
768 while ( pAttr )
769 {
770 nLastEnd = pAttr->GetEnd();
771 if ( pAttr->GetStart() > nLastEnd )
772 aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
773 // #112831# Last Attr might go from 0xffff to 0x0000
774 pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : nullptr;
775 }
776
777 // And the Rest:
778 if ( nLastEnd < nEndPos )
779 aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
780 }
781 }
782 bFormatted = false;
783 // Portion does not need to be invalidated here, happens elsewhere.
784}
785
786IdleFormattter::IdleFormattter()
787 : Idle("editeng::ImpEditEngine aIdleFormatter")
788{
789 pView = nullptr;
790 nRestarts = 0;
791}
792
793IdleFormattter::~IdleFormattter()
794{
795 pView = nullptr;
796}
797
798void IdleFormattter::DoIdleFormat( EditView* pV )
799{
800 pView = pV;
801
802 if ( IsActive() )
803 nRestarts++;
804
805 if ( nRestarts > 4 )
806 ForceTimeout();
807 else
808 Start();
809}
810
811void IdleFormattter::ForceTimeout()
812{
813 if ( IsActive() )
814 {
815 Stop();
816 Invoke();
817 }
818}
819
820ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, OUString _aOldTextAfterStartPos )
821 : aOldTextAfterStartPos(std::move( _aOldTextAfterStartPos )),
822 aPos(rPos),
823 nLen(0),
824 bWasCursorOverwrite(false)
825 {
826 }
827
828ImplIMEInfos::~ImplIMEInfos()
829{
830}
831
832void ImplIMEInfos::CopyAttribs( const ExtTextInputAttr* pA, sal_uInt16 nL )
833{
834 nLen = nL;
835 pAttribs.reset( new ExtTextInputAttr[ nL ] );
836 memcpy( pAttribs.get(), pA, nL*sizeof(ExtTextInputAttr) );
837}
838
839void ImplIMEInfos::DestroyAttribs()
840{
841 pAttribs.reset();
842 nLen = 0;
843}
844
845/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxItemSet & GetItems()
Definition: editdoc.hxx:166
const SfxStyleSheet * GetStyleSheet() const
Definition: editdoc.hxx:168
ContentAttribs & GetContentAttribs()
Definition: editdoc.hxx:254
WrongList * GetWrongList()
Definition: editdoc.cxx:1777
SfxStyleSheet * GetStyleSheet()
Definition: editdoc.hxx:266
sal_Int32 Len() const
Definition: editdoc.cxx:1615
void SetStyleSheet(SfxStyleSheet *pS, bool bRecalcFont=true)
Definition: editdoc.cxx:1603
sal_Int32 GetPos(const ContentNode *pNode) const
Definition: editdoc.cxx:2086
const ContentNode * GetObject(sal_Int32 nPos) const
Definition: editdoc.cxx:2091
sal_Int32 Count() const
Definition: editdoc.cxx:2143
virtual void StyleSheetChanged(SfxStyleSheet *pStyle)
Definition: editeng.cxx:2547
const ContentNode * GetNode() const
Definition: editdoc.hxx:312
EditPaM & Min()
Definition: editdoc.hxx:705
bool DbgIsBuggy(EditDoc const &rDoc) const
Definition: editdoc.cxx:1134
EditPaM & Max()
Definition: editdoc.hxx:706
void Adjust(const EditDoc &rNodes)
Definition: editdoc.cxx:1162
SfxStyleSheetPool * GetStyleSheetPool() const
Definition: impedit.hxx:1012
void RemoveCharAttribs(EditSelection aSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich)
Definition: impedit5.cxx:584
const SfxItemSet & GetParaAttribs(sal_Int32 nPara) const
Definition: impedit5.cxx:718
void Undo(EditView *pView)
Definition: impedit5.cxx:292
EditEngine * GetEditEnginePtr() const
Definition: impedit.hxx:1136
const SfxStyleSheet * GetStyleSheet(sal_Int32 nPara) const
Definition: impedit5.cxx:35
bool HasParaAttrib(sal_Int32 nPara, sal_uInt16 nWhich) const
Definition: impedit5.cxx:725
SfxItemSet GetAttribs(sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags=GetAttribsFlags::ALL) const
Definition: impedit5.cxx:398
void Dispose()
Definition: impedit2.cxx:160
void RemoveStyleFromParagraphs(SfxStyleSheet const *pStyle)
Definition: impedit5.cxx:129
bool IsInUndo() const
Definition: impedit.hxx:911
InternalEditStatus aStatus
Definition: impedit.hxx:556
void SetAttribs(EditSelection aSel, const SfxItemSet &rSet, SetAttribsMode nSpecial=SetAttribsMode::NONE, bool bSetSelection=true)
Definition: impedit5.cxx:489
void FormatAndLayout(EditView *pCurView=nullptr, bool bCalledFromUndo=false)
Definition: impedit3.cxx:4412
void SetStyleSheetPool(SfxStyleSheetPool *pSPool)
Definition: impedit5.cxx:27
EditEngine * pEditEngine
Definition: impedit.hxx:508
std::unique_ptr< EditUndoSetAttribs > CreateAttribUndo(EditSelection aSel, const SfxItemSet &rSet)
Definition: impedit5.cxx:178
void UpdateParagraphsWithStyleSheet(SfxStyleSheet *pStyle)
Definition: impedit5.cxx:99
const SfxPoolItem & GetParaAttrib(sal_Int32 nPara, sal_uInt16 nWhich) const
Definition: impedit5.cxx:732
ESelection CreateESel(const EditSelection &rSel) const
Definition: impedit.hxx:1246
void InsertUndo(std::unique_ptr< EditUndo > pUndo, bool bTryMerge=false)
Definition: impedit5.cxx:264
void ParaAttribsChanged(ContentNode const *pNode, bool bIgnoreUndoCheck=false)
Definition: impedit2.cxx:780
bool SetUpdateLayout(bool bUpdate, EditView *pCurView=nullptr, bool bForceUpdate=false)
Definition: impedit3.cxx:4146
SfxStyleSheetPool * pStylePool
Definition: impedit.hxx:513
bool IsUpdateLayout() const
Definition: impedit.hxx:847
IdleFormattter aIdleFormatter
Definition: impedit.hxx:570
EditDoc aEditDoc
Definition: impedit.hxx:505
bool IsUndoEnabled() const
Definition: impedit.hxx:909
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: impedit5.cxx:144
void SetStyleSheet(EditSelection aSel, SfxStyleSheet *pStyle)
Definition: impedit5.cxx:47
bool DoUndoAttribs() const
Definition: editstt2.hxx:46
bool UseCharAttribs() const
Definition: editstt2.hxx:34
SfxHintId GetId() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
const OUString & GetName() const
SfxStyleFamily GetFamily() const
virtual SfxItemSet & GetItemSet()
SfxStyleSheetBase * GetStyleSheet() const
void ResetInvalidRange(size_t nStart, size_t nEnd)
Definition: edtspell.cxx:178
#define DBG_ASSERT(sCon, aError)
void CreateFont(SvxFont &rFont, const SfxItemSet &rSet, bool bSearchInParent, SvtScriptType nScriptType)
Definition: editdoc.cxx:1975
EditCharAttrib * GetAttrib(CharAttribList::AttribsType &rAttribs, std::size_t nAttr)
Definition: editdoc.hxx:839
SfxHintId
sal_Int64 n
sal_Int16 nId