LibreOffice Module sw (master) 1
ndtxt.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 <hintids.hxx>
21#include <hints.hxx>
22
23#include <comphelper/lok.hxx>
24#include <comphelper/string.hxx>
25#include <editeng/fontitem.hxx>
27#include <editeng/lrspitem.hxx>
28#include <editeng/rsiditem.hxx>
29#include <sal/log.hxx>
30#include <osl/diagnose.h>
31#include <anchoredobject.hxx>
32#include <txtfld.hxx>
33#include <txtinet.hxx>
34#include <fmtanchr.hxx>
35#include <fmtinfmt.hxx>
36#include <fmtrfmrk.hxx>
37#include <txttxmrk.hxx>
38#include <fchrfmt.hxx>
39#include <txtftn.hxx>
40#include <fmtflcnt.hxx>
41#include <fmtfld.hxx>
42#include <frmatr.hxx>
43#include <ftnidx.hxx>
44#include <ftninfo.hxx>
45#include <fmtftn.hxx>
46#include <charfmt.hxx>
47#include <ndtxt.hxx>
48#include <doc.hxx>
49#include <IDocumentUndoRedo.hxx>
54#include <docary.hxx>
55#include <pam.hxx>
56#include <fldbas.hxx>
57#include <paratr.hxx>
58#include <txtfrm.hxx>
59#include <ftnfrm.hxx>
60#include <pagefrm.hxx>
61#include <rootfrm.hxx>
62#include <expfld.hxx>
63#include <section.hxx>
64#include <mvsave.hxx>
65#include <SwGrammarMarkUp.hxx>
66#include <redline.hxx>
67#include <IMark.hxx>
68#include <scriptinfo.hxx>
69#include <istyleaccess.hxx>
70#include <SwStyleNameMapper.hxx>
71#include <numrule.hxx>
72#include <docsh.hxx>
73#include <SwNodeNum.hxx>
74#include <svl/grabbagitem.hxx>
75#include <svl/intitem.hxx>
76#include <sortedobjs.hxx>
77#include <calbck.hxx>
78#include <attrhint.hxx>
79#include <memory>
80#include <unoparagraph.hxx>
81#include <wrtsh.hxx>
82#include <fmtpdsc.hxx>
84#include <svl/itemiter.hxx>
85
86using namespace ::com::sun::star;
87
88typedef std::vector<SwTextAttr*> SwpHts;
89
90namespace sw {
94 public:
96 : m_rNode(rNode)
97 , m_bWasNotifiable(rNode.m_bNotifiable)
98 {
99 m_rNode.m_bNotifiable = false;
100 }
102 {
104 }
105 };
106}
107
108// unfortunately everyone can change Hints without ensuring order or the linking between them
109#ifdef DBG_UTIL
110#define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \
111 !pNd->GetDoc().IsInReading() ) \
112 pNd->GetpSwpHints()->Check(true); }
113#define CHECK_SWPHINTS_IF_FRM(pNd) { if( pNd->GetpSwpHints() && \
114 !pNd->GetDoc().IsInReading() ) \
115 pNd->GetpSwpHints()->Check(getLayoutFrame(nullptr, nullptr, nullptr) != nullptr); }
116#else
117#define CHECK_SWPHINTS(pNd)
118#define CHECK_SWPHINTS_IF_FRM(pNd)
119#endif
120
122 SwTextFormatColl *pColl, bool const bNewFrames)
123{
124 OSL_ENSURE( pColl, "Collection pointer is 0." );
125
126 SwTextNode *pNode = new SwTextNode( rWhere, pColl, nullptr );
127
128 SwNodeIndex aIdx( *pNode );
129
130 // if there is no layout or it is in a hidden section, MakeFrames is not needed
131 const SwSectionNode* pSectNd;
132 if (!bNewFrames ||
133 !GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell() ||
134 ( nullptr != (pSectNd = pNode->FindSectionNode()) &&
135 pSectNd->GetSection().IsHiddenFlag() ))
136 return pNode;
137
138 SwNodeIndex aTmp( rWhere );
139 do {
140 // max. 2 loops:
141 // 1. take the successor
142 // 2. take the predecessor
143
144 SwNode * pNd = & aTmp.GetNode();
145 switch (pNd->GetNodeType())
146 {
148 static_cast<SwTableNode*>(pNd)->MakeFramesForAdjacentContentNode(aIdx);
149 return pNode;
150
152 if( static_cast<SwSectionNode*>(pNd)->GetSection().IsHidden() ||
153 static_cast<SwSectionNode*>(pNd)->IsContentHidden() )
154 {
155 pNd = FindPrvNxtFrameNode( *pNode, pNode );
156 if( !pNd )
157 return pNode;
158 aTmp = *pNd;
159 break;
160 }
161 static_cast<SwSectionNode*>(pNd)->MakeFramesForAdjacentContentNode(aIdx);
162 return pNode;
163
164 case SwNodeType::Text:
165 case SwNodeType::Grf:
166 case SwNodeType::Ole:
167 static_cast<SwContentNode*>(pNd)->MakeFramesForAdjacentContentNode(*pNode);
168 return pNode;
169
170 case SwNodeType::End:
171 if( pNd->StartOfSectionNode()->IsSectionNode() &&
172 aTmp.GetIndex() < rWhere.GetIndex() )
173 {
175 {
176 if( !GoPrevSection( &aTmp, true, false ) ||
177 aTmp.GetNode().FindTableNode() !=
178 pNode->FindTableNode() )
179 return pNode;
180 }
181 else
182 aTmp = *pNd->StartOfSectionNode();
183 break;
184 }
185 else if( pNd->StartOfSectionNode()->IsTableNode() &&
186 aTmp.GetIndex() < rWhere.GetIndex() )
187 {
188 // after a table node
189 aTmp = *pNd->StartOfSectionNode();
190 break;
191 }
192 [[fallthrough]];
193 default:
194 if( &rWhere == &aTmp.GetNode() )
195 aTmp -= SwNodeOffset(2);
196 else
197 return pNode;
198 break;
199 }
200 } while( true );
201}
202
203SwTextNode::SwTextNode( SwNode& rWhere, SwTextFormatColl *pTextColl, const SfxItemSet* pAutoAttr )
204: SwContentNode( rWhere, SwNodeType::Text, pTextColl ),
205 m_bContainsHiddenChars(false),
206 m_bHiddenCharsHidePara(false),
207 m_bRecalcHiddenCharFlags(false),
208 m_bLastOutlineState( false ),
209 m_bNotifiable( true ),
210 mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
211 mbInSetOrResetAttr( false ),
212 m_bInUndo(false)
213{
214 {
216
217 if( pAutoAttr )
218 SetAttr( *pAutoAttr );
219
220 if (!IsInList() && GetNumRule() && !GetListId().isEmpty())
221 {
222 // #i101516#
223 // apply paragraph style's assigned outline style list level as
224 // list level of the paragraph, if it has none set already.
225 if ( !HasAttrListLevel() &&
226 pTextColl && pTextColl->IsAssignedToListLevelOfOutlineStyle() )
227 {
229 }
230 AddToList();
231 }
232
233 // call method <UpdateOutlineNode(..)> only for the document nodes array
234 if (GetNodes().IsDocNodes())
236 }
237
240}
241
243{
244 // delete only removes the pointer not the array elements!
245 if ( m_pSwpHints )
246 {
247 // do not delete attributes twice when those delete their content
248 std::unique_ptr<SwpHints> pTmpHints(std::move(m_pSwpHints));
249
250 for( size_t j = pTmpHints->Count(); j; )
251 {
252 // first remove the attribute from the array otherwise
253 // if would delete itself
254 DestroyAttr( pTmpHints->Get( --j ) );
255 }
256 }
257
258 // must be removed from outline nodes by now
259#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
261 assert(!GetNodes().GetOutLineNds().Seek_Entry(this, &foo));
262#endif
263
265
266 DelFrames(nullptr); // must be called here while it's still a SwTextNode
268#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
269 if (!GetDoc().IsInDtor())
271#else
273#endif
275}
276
278{
279 if (m_pSwpHints)
280 {
281 m_pSwpHints->MergePortions(*this);
282 }
283}
284
286{
288 return pFrame;
289}
290
291sal_Int32 SwTextNode::Len() const
292{
293 return m_Text.getLength();
294}
295
296// After a split node, it's necessary to actualize the ref-pointer of the ftnfrms.
298{
299 SwpHints *pSwpHints = rNode.GetpSwpHints();
300 if( !(pSwpHints && rNode.GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell()) )
301 return;
302
303 SwContentFrame* pFrame = nullptr;
304 // OD 07.11.2002 #104840# - local variable to remember first footnote
305 // of node <rNode> in order to invalidate position of its first content.
306 // Thus, in its <MakeAll()> it will checked its position relative to its reference.
307 SwFootnoteFrame* pFirstFootnoteOfNode = nullptr;
308 for( size_t j = pSwpHints->Count(); j; )
309 {
310 SwTextAttr* pHt = pSwpHints->Get(--j);
311 if (RES_TXTATR_FTN == pHt->Which())
312 {
313 if( !pFrame )
314 {
316 if (!pFrame)
317 return;
318 }
319 SwTextFootnote *pAttr = static_cast<SwTextFootnote*>(pHt);
320 OSL_ENSURE( pAttr->GetStartNode(), "FootnoteAtr without StartNode." );
321 SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
322 SwContentNode *pNd = aIdx.GetNode().GetContentNode();
323 if ( !pNd )
324 pNd = pFrame->GetAttrSet()->GetDoc()->
325 GetNodes().GoNextSection( &aIdx, true, false );
326 if ( !pNd )
327 continue;
328
330 SwContentFrame* pContent = aIter.First();
331 if( pContent )
332 {
333 OSL_ENSURE( pContent->getRootFrame() == pFrame->getRootFrame(),
334 "lcl_ChangeFootnoteRef: Layout double?" );
335 SwFootnoteFrame *pFootnote = pContent->FindFootnoteFrame();
336 if( pFootnote && pFootnote->GetAttr() == pAttr )
337 {
338 while( pFootnote->GetMaster() )
339 pFootnote = pFootnote->GetMaster();
340 // #104840# - remember footnote frame
341 pFirstFootnoteOfNode = pFootnote;
342 while ( pFootnote )
343 {
344 pFootnote->SetRef( pFrame );
345 pFootnote = pFootnote->GetFollow();
346 static_cast<SwTextFrame*>(pFrame)->SetFootnote( true );
347 }
348 }
349#if OSL_DEBUG_LEVEL > 0
350 while( nullptr != (pContent = aIter.Next()) )
351 {
352 SwFootnoteFrame *pDbgFootnote = pContent->FindFootnoteFrame();
353 OSL_ENSURE( !pDbgFootnote || pDbgFootnote->GetRef() == pFrame,
354 "lcl_ChangeFootnoteRef: Who's that guy?" );
355 }
356#endif
357 }
358 }
359 } // end of for-loop on <SwpHints>
360 // #104840# - invalidate
361 if ( pFirstFootnoteOfNode )
362 {
363 SwContentFrame* pContent = pFirstFootnoteOfNode->ContainsContent();
364 if ( pContent )
365 {
366 pContent->InvalidatePos_();
367 }
368 }
369}
370
371namespace sw {
372
373// check if there are flys on the existing frames (now on "pNode")
374// that need to be moved to the new frames of "this"
375void MoveMergedFlysAndFootnotes(std::vector<SwTextFrame*> const& rFrames,
376 SwTextNode const& rFirstNode, SwTextNode & rSecondNode,
377 bool isSplitNode)
378{
379 if (!isSplitNode)
380 {
381 lcl_ChangeFootnoteRef(rSecondNode);
382 }
383 for (SwNodeOffset nIndex = rSecondNode.GetIndex() + 1; ; ++nIndex)
384 {
385 SwNode *const pTmp(rSecondNode.GetNodes()[nIndex]);
386 if (pTmp->IsCreateFrameWhenHidingRedlines() || pTmp->IsEndNode())
387 {
388 break;
389 }
390 else if (pTmp->IsStartNode())
391 {
392 nIndex = pTmp->EndOfSectionIndex();
393 }
395 && pTmp->IsTextNode())
396 {
398 }
399 }
400 for (SwTextFrame *const pFrame : rFrames)
401 {
402 if (SwSortedObjs *const pObjs = pFrame->GetDrawObjs())
403 {
404 std::vector<SwAnchoredObject*> objs;
405 objs.reserve(pObjs->size());
406 for (SwAnchoredObject *const pObj : *pObjs)
407 {
408 objs.push_back(pObj);
409 }
410 for (SwAnchoredObject *const pObj : objs)
411 {
412 SwFrameFormat & rFormat(pObj->GetFrameFormat());
413 SwFormatAnchor const& rAnchor(rFormat.GetAnchor());
414 if (rFirstNode.GetIndex() < rAnchor.GetAnchorNode()->GetIndex())
415 {
416 // move it to the new frame of "this"
417 rFormat.CallSwClientNotify(sw::LegacyModifyHint(&rAnchor, &rAnchor));
418 // note pObjs will be deleted if it becomes empty
419 assert(!pFrame->GetDrawObjs() || !pObjs->Contains(*pObj));
420 }
421 }
422 }
423 }
424}
425
426} // namespace
427
429 std::function<void (SwTextNode *, sw::mark::RestoreMode, bool AtStart)> const*const pContentIndexRestore)
430{
431 bool isHide(false);
432 SwNode::Merge const eOldMergeFlag(GetRedlineMergeFlag());
433 bool parentIsOutline = IsOutline();
434
435 // create a node "in front" of me
436 const sal_Int32 nSplitPos = rPos.GetContentIndex();
437 const sal_Int32 nTextLen = m_Text.getLength();
438 SwTextNode* const pNode =
439 MakeNewTextNode( rPos.GetNode(), false, nSplitPos==nTextLen );
440
441 // the first paragraph gets the XmlId,
442 // _except_ if it is empty and the second is not empty
443 if (nSplitPos != 0) {
444 pNode->RegisterAsCopyOf(*this, true);
445 if (nSplitPos == nTextLen)
446 {
447 RemoveMetadataReference();
448 // NB: SwUndoSplitNode will call pNode->JoinNext,
449 // which is sufficient even in this case!
450 }
451 }
452
456 if ( GetNumRule() == nullptr || (parentIsOutline && !IsOutline()) )
457 {
460 }
461
462 if ( HasWriterListeners() && !m_Text.isEmpty() && (nTextLen / 2) < nSplitPos )
463 {
464 // optimization for SplitNode: If a split is at the end of a node then
465 // move the frames from the current to the new one and create new ones
466 // for the current one.
467
468 // If fly frames are moved, they don't need to destroy their layout
469 // frames. Set a flag that is checked in SwTextFlyCnt::SetAnchor.
470 if ( HasHints() )
471 {
472 pNode->GetOrCreateSwpHints().SetInSplitNode(true);
473 }
474
475 // Move the first part of the content to the new node and delete
476 // it in the old node.
477 SwContentIndex aIdx( this );
478 CutText( pNode, aIdx, nSplitPos );
479
480 if( GetWrong() )
481 {
482 pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
483 }
485
486 if( GetGrammarCheck() )
487 {
488 pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) );
489 }
490 SetGrammarCheckDirty( true );
491
492 SetWordCountDirty( true );
493
494 if( GetSmartTags() )
495 {
496 pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) );
497 }
498 SetSmartTagDirty( true );
499
502
503 if ( pNode->HasHints() )
504 {
505 if ( pNode->m_pSwpHints->CanBeDeleted() )
506 {
507 pNode->m_pSwpHints.reset();
508 }
509 else
510 {
511 pNode->m_pSwpHints->SetInSplitNode(false);
512 }
513
514 // All fly frames anchored as char that are moved to the new
515 // node must have their layout frames deleted.
516 // This comment is sort of silly because we actually delete the
517 // layout frames of those which were not moved?
518 // JP 01.10.96: delete all empty and not-to-be-expanded attributes
519 if ( HasHints() )
520 {
521 for ( size_t j = m_pSwpHints->Count(); j; )
522 {
523 SwTextAttr* const pHt = m_pSwpHints->Get( --j );
524 if ( RES_TXTATR_FLYCNT == pHt ->Which() )
525 {
527 }
528 else if ( pHt->DontExpand() )
529 {
530 const sal_Int32* const pEnd = pHt->GetEnd();
531 if (pEnd && pHt->GetStart() == *pEnd )
532 {
533 // delete it!
534 m_pSwpHints->DeleteAtPos( j );
535 DestroyAttr( pHt );
536 }
537 }
538 }
539 }
540
541 }
542
543 if (pContentIndexRestore)
544 { // call before making frames and before RegisterToNode
545 (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys, false);
546 }
547 if (eOldMergeFlag != SwNode::Merge::None)
548 { // clear before making frames and before RegisterToNode
550 } // now RegisterToNode will set merge flags in both nodes properly!
551
552 std::vector<SwTextFrame*> frames;
554 for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
555 {
556 if (pFrame->getRootFrame()->HasMergedParas())
557 {
558 isHide = true;
559 }
560 frames.push_back(pFrame);
561 }
562 for (SwTextFrame * pFrame : frames)
563 {
564 pFrame->RegisterToNode( *pNode );
565 if (!pFrame->IsFollow() && pFrame->GetOffset())
566 {
567 pFrame->SetOffset( TextFrameIndex(0) );
568 }
569 }
570
572
573 if ( HasHints() )
574 {
576 }
577 // in case there are frames, the RegisterToNode has set the merge flag
579 lcl_ChangeFootnoteRef( *this );
580 if (pContentIndexRestore)
581 { // call after making frames; listeners will take care of adding to the right frame
582 (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys, false);
583 }
584 if (eOldMergeFlag != SwNode::Merge::None)
585 {
586 MoveMergedFlysAndFootnotes(frames, *pNode, *this, true);
587 }
588 }
589 else
590 {
591 std::unique_ptr<SwWrongList> pList = ReleaseWrong();
593
594 std::unique_ptr<SwGrammarMarkUp> pList3 = ReleaseGrammarCheck();
595 SetGrammarCheckDirty( true );
596
597 SetWordCountDirty( true );
598
599 std::unique_ptr<SwWrongList> pList2 = ReleaseSmartTags();
600 SetSmartTagDirty( true );
601
602 SwContentIndex aIdx( this );
603 CutText( pNode, aIdx, nSplitPos );
604
605 // JP 01.10.96: delete all empty and not-to-be-expanded attributes
606 if ( HasHints() )
607 {
608 for ( size_t j = m_pSwpHints->Count(); j; )
609 {
610 SwTextAttr* const pHt = m_pSwpHints->Get( --j );
611 const sal_Int32* const pEnd = pHt->GetEnd();
612 if ( pHt->DontExpand() && pEnd && (pHt->GetStart() == *pEnd) )
613 {
614 // delete it!
615 m_pSwpHints->DeleteAtPos( j );
616 DestroyAttr( pHt );
617 }
618 }
620 }
621
622 if( pList )
623 {
624 pNode->SetWrong( pList->SplitList( nSplitPos ) );
625 SetWrong( std::move(pList) );
626 }
627
628 if( pList3 )
629 {
630 pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
631 SetGrammarCheck( std::move(pList3) );
632 }
633
634 if( pList2 )
635 {
636 pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
637 SetSmartTags( std::move(pList2) );
638 }
639
642
643 if (pContentIndexRestore)
644 { // call before making frames and before RegisterToNode
645 (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys, false);
646 }
647
648 std::vector<SwTextFrame*> frames;
650 for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
651 {
652 frames.push_back(pFrame);
653 if (pFrame->getRootFrame()->HasMergedParas())
654 {
655 isHide = true;
656 }
657 }
658 bool bNonMerged(false);
659 bool bRecreateThis(false);
660 for (SwTextFrame * pFrame : frames)
661 {
662 // sw_redlinehide: for this to work properly with hidden nodes,
663 // the frame needs to listen on them too.
664 // also: have to check the frame; this->GetRedlineMergeFlag()
665 // is None in case there's a delete redline inside the paragraph,
666 // but that could still result in a merged frame after split...
667 if (pFrame->GetMergedPara())
668 {
669 // Can't special case this == First here - that could (if
670 // both nodes are still merged by redline) lead to
671 // duplicate frames on "this".
672 // Update the extents with new node; also inits merge flag,
673 // so the MakeFramesForAdjacentContentNode below respects it
674 pFrame->RegisterToNode(*pNode);
675 if (nSplitPos == 0)
676 {
677 // in this case, it was not
678 // invalidated because Cut didn't sent it any hints,
679 // so we have to invalidate it here!
680 pFrame->Prepare(PrepareHint::Clear, nullptr, false);
681 }
682 if (!pFrame->GetMergedPara() ||
683 !pFrame->GetMergedPara()->listener.IsListeningTo(this))
684 {
685 // it's no longer listening - need to recreate frame
686 // (note this is idempotent, can be done once per frame)
688 bRecreateThis = true;
689 }
690 }
691 else
692 {
693 bNonMerged = true;
694 }
695 }
696 assert(!(bNonMerged && bRecreateThis)); // 2 layouts not handled yet - maybe best to simply use the other branch then?
697 if (!frames.empty() && bNonMerged)
698 {
699 // the existing frame on "this" should have been updated by Cut
701 lcl_ChangeFootnoteRef(*pNode);
702 }
703 else if (bRecreateThis)
704 {
705 assert(pNode->HasWriterListeners()); // was just moved there
708 }
709
710 if (pContentIndexRestore)
711 { // call after making frames; listeners will take care of adding to the right frame
712 (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys, nSplitPos == 0);
713 }
714
715 if (bRecreateThis)
716 {
717 MoveMergedFlysAndFootnotes(frames, *pNode, *this, true);
718 }
719 }
720
721 // pNode is the previous node, 'this' is the next node from the split.
722 if (nSplitPos == nTextLen && m_pSwpHints)
723 {
724 // We just created an empty next node: avoid unwanted superscript in the new node if it's
725 // there.
726 for (size_t i = 0; i < m_pSwpHints->Count(); ++i)
727 {
728 SwTextAttr* pHt = m_pSwpHints->Get(i);
729 if (pHt->Which() != RES_TXTATR_AUTOFMT)
730 {
731 continue;
732 }
733
734 const sal_Int32* pEnd = pHt->GetEnd();
735 if (!pEnd || pHt->GetStart() != *pEnd)
736 {
737 continue;
738 }
739
740 const std::shared_ptr<SfxItemSet>& pSet = pHt->GetAutoFormat().GetStyleHandle();
741 if (!pSet || pSet->Count() != 1 || !pSet->HasItem(RES_CHRATR_ESCAPEMENT))
742 {
743 continue;
744 }
745
746 m_pSwpHints->DeleteAtPos(i);
747 SwTextAttr::Destroy(pHt, GetDoc().GetAttrPool());
748 --i;
749 }
750 }
751
752#ifndef NDEBUG
753 if (isHide) // otherwise flags won't be set anyway
754 {
755 // First
756 // -> First,NonFirst
757 // -> First,Hidden
758 // -> None,First
759 // Hidden
760 // -> Hidden,Hidden (if still inside merge rl)
761 // -> NonFirst,First (if redline was split)
762 // NonFirst
763 // -> NonFirst,First (if split after end of "incoming" redline &
764 // before start of "outgoing" redline)
765 // -> NonFirst,None (if split after end of "incoming" redline)
766 // -> NonFirst,Hidden (if split after start of "outgoing" redline)
767 // -> Hidden, NonFirst (if split before end of "incoming" redline)
768 // None
769 // -> None,None
770 // -> First,NonFirst (if splitting inside a delete redline)
771 SwNode::Merge const eFirst(pNode->GetRedlineMergeFlag());
772 SwNode::Merge const eSecond(GetRedlineMergeFlag());
773 switch (eOldMergeFlag)
774 {
775 case Merge::First:
776 assert((eFirst == Merge::First && eSecond == Merge::NonFirst)
777 || (eFirst == Merge::First && eSecond == Merge::Hidden)
778 || (eFirst == Merge::None && eSecond == Merge::First));
779 break;
780 case Merge::Hidden:
781 assert((eFirst == Merge::Hidden && eSecond == Merge::Hidden)
782 || (eFirst == Merge::NonFirst && eSecond == Merge::First)
783 // next ones can happen temp. in UndoDelete :(
784 || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst)
785 || (eFirst == Merge::NonFirst && eSecond == Merge::None));
786 break;
787 case Merge::NonFirst:
788 assert((eFirst == Merge::NonFirst && eSecond == Merge::First)
789 || (eFirst == Merge::NonFirst && eSecond == Merge::None)
790 || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden)
791 || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst));
792 break;
793 case Merge::None:
794 assert((eFirst == Merge::None && eSecond == Merge::None)
795 || (eFirst == Merge::First && eSecond == Merge::NonFirst));
796 break;
797 }
798 }
799#else
800 (void) isHide;
801#endif
802
803 {
804 // Send Hint for PageDesc. This should be done in the Layout when
805 // pasting the frames, but that causes other problems that look
806 // expensive to solve.
807 const SwFormatPageDesc *pItem;
808 if(HasWriterListeners() && (pItem = pNode->GetSwAttrSet().GetItemIfSet(RES_PAGEDESC)))
809 pNode->TriggerNodeUpdate(sw::LegacyModifyHint(pItem, pItem));
810 }
811 return pNode;
812}
813
815{
816 OSL_ENSURE( m_pSwpHints, "MoveTextAttr_To_AttrSet without SwpHints?" );
817 for ( size_t i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
818 {
819 SwTextAttr *pHt = m_pSwpHints->Get(i);
820
821 if( pHt->GetStart() )
822 break;
823
824 const sal_Int32* pHtEndIdx = pHt->GetEnd();
825
826 if( !pHtEndIdx )
827 continue;
828
829 if (*pHtEndIdx < m_Text.getLength() || pHt->IsCharFormatAttr())
830 break;
831
832 if( !pHt->IsDontMoveAttr() &&
833 SetAttr( pHt->GetAttr() ) )
834 {
835 m_pSwpHints->DeleteAtPos(i);
836 DestroyAttr( pHt );
837 --i;
838 }
839 }
840
841}
842
843namespace sw {
844
848void MoveDeletedPrevFrames(const SwTextNode & rDeletedPrev, SwTextNode & rNode)
849{
850 std::vector<SwTextFrame*> frames;
852 for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
853 {
854 if (pFrame->getRootFrame()->HasMergedParas())
855 {
856 frames.push_back(pFrame);
857 }
858 }
859 {
860 auto frames2(frames);
862 for (SwTextFrame* pFrame = aIt.First(); pFrame; pFrame = aIt.Next())
863 {
864 if (pFrame->getRootFrame()->HasMergedParas())
865 {
866 auto const it(std::find(frames2.begin(), frames2.end(), pFrame));
867 assert(it != frames2.end());
868 frames2.erase(it);
869 }
870 }
871 assert(frames2.empty());
872 }
873 for (SwTextFrame *const pFrame : frames)
874 {
875 pFrame->RegisterToNode(rNode, true);
876 }
877}
878
879// typical Join:
880// None,Node->None
881// None,First->First
882// First,NonFirst->First
883// NonFirst,First->NonFirst
884// NonFirst,None->NonFirst
885
888void CheckResetRedlineMergeFlag(SwTextNode & rNode, Recreate const eRecreateMerged)
889{
890 if (eRecreateMerged != sw::Recreate::No)
891 {
892 SwTextNode * pMergeNode(&rNode);
893 if (eRecreateMerged == sw::Recreate::Predecessor
894 // tdf#135018 check that there is a predecessor node, i.e. rNode
895 // isn't the first node after the body start node
896 && rNode.GetNodes()[rNode.GetIndex() - 1]->StartOfSectionIndex() != SwNodeOffset(0))
897 {
898 for (SwNodeOffset i = rNode.GetIndex() - 1; ; --i)
899 {
900 SwNode *const pNode(rNode.GetNodes()[i]);
901 assert(!pNode->IsStartNode());
902 if (pNode->IsEndNode())
903 {
904 i = pNode->StartOfSectionIndex();
905 }
906 else if (pNode->IsTextNode())
907 {
908 pMergeNode = pNode->GetTextNode(); // use predecessor to merge
909 break;
910 }
911 }
912 }
913 std::vector<SwTextFrame*> frames;
915 for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
916 {
917 if (pFrame->getRootFrame()->HasMergedParas())
918 {
919 frames.push_back(pFrame);
920 }
921 }
923 for (SwTextFrame * pFrame : frames)
924 {
925 SwTextNode & rFirstNode(pFrame->GetMergedPara()
926 ? *pFrame->GetMergedPara()->pFirstNode
927 : *pMergeNode);
928 assert(rFirstNode.GetIndex() <= rNode.GetIndex());
929 pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
930 *pFrame, rFirstNode, eMode));
931 // there is no merged para in case the deleted node had one but
932 // nothing was actually hidden
933 if (pFrame->GetMergedPara())
934 {
935 assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode));
936 assert(rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex());
937 // tdf#135978 Join: recreate fly frames anchored to subsequent nodes
938 if (eRecreateMerged == sw::Recreate::ThisNode)
939 {
940 AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, rNode, nullptr);
941 }
942 }
943 eMode = sw::FrameMode::New; // Existing is not idempotent!
944 }
945 }
946 else if (rNode.GetRedlineMergeFlag() != SwNode::Merge::None)
947 {
949 for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
950 {
951 if (auto const pMergedPara = pFrame->GetMergedPara())
952 {
953 if (pMergedPara->pFirstNode == pMergedPara->pLastNode)
954 {
955 assert(pMergedPara->pFirstNode == &rNode);
957 }
958 break; // checking once is enough
959 }
960 else if (pFrame->getRootFrame()->HasMergedParas())
961 {
963 break; // checking once is enough
964 }
965 }
966 }
967}
968
970{
971 const SwNodeNum* pNodeNum = rTextNode.GetNum();
972 if (!pNodeNum)
973 {
974 return false;
975 }
976
977 const SwNumRule* pNumRule = pNodeNum->GetNumRule();
978 if (!pNumRule)
979 {
980 return false;
981 }
982
983 const SwNumFormat* pFormat
984 = pNumRule->GetNumFormat(o3tl::narrowing<sal_uInt16>(rTextNode.GetAttrListLevel()));
985 if (!pFormat)
986 {
987 return false;
988 }
989
990 switch (pFormat->GetNumberingType())
991 {
994 case SVX_NUM_BITMAP:
995 return false;
996 default:
997 return true;
998 }
999}
1000} // namespace
1001
1003{
1004 SwNodes& rNds = GetNodes();
1005 SwNodeIndex aIdx( *this );
1006 if( SwContentNode::CanJoinNext( &aIdx ) )
1007 {
1008 SwDoc& rDoc = rNds.GetDoc();
1009 const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
1010 pContentStore->Save(rDoc, aIdx.GetIndex(), SAL_MAX_INT32);
1011 SwTextNode *pTextNode = aIdx.GetNode().GetTextNode();
1012 sal_Int32 nOldLen = m_Text.getLength();
1013
1014 // METADATA: merge
1015 JoinMetadatable(*pTextNode, !Len(), !pTextNode->Len());
1016
1017 std::unique_ptr<SwWrongList> pList = ReleaseWrong();
1018 if( pList )
1019 {
1020 pList->JoinList( pTextNode->GetWrong(), nOldLen );
1022 }
1023 else
1024 {
1025 pList = pTextNode->ReleaseWrong();
1026 if( pList )
1027 {
1028 pList->Move( 0, nOldLen );
1030 }
1031 }
1032
1033 std::unique_ptr<SwGrammarMarkUp> pList3 = ReleaseGrammarCheck();
1034 if( pList3 )
1035 {
1036 pList3->JoinGrammarList( pTextNode->GetGrammarCheck(), nOldLen );
1037 SetGrammarCheckDirty( true );
1038 }
1039 else
1040 {
1041 pList3 = pTextNode->ReleaseGrammarCheck();
1042 if( pList3 )
1043 {
1044 pList3->MoveGrammar( 0, nOldLen );
1045 SetGrammarCheckDirty( true );
1046 }
1047 }
1048
1049 std::unique_ptr<SwWrongList> pList2 = ReleaseSmartTags();
1050 if( pList2 )
1051 {
1052 pList2->JoinList( pTextNode->GetSmartTags(), nOldLen );
1053 SetSmartTagDirty( true );
1054 }
1055 else
1056 {
1057 pList2 = pTextNode->ReleaseSmartTags();
1058 if( pList2 )
1059 {
1060 pList2->Move( 0, nOldLen );
1061 SetSmartTagDirty( true );
1062 }
1063 }
1064
1065 { // scope for SwContentIndex
1066 pTextNode->CutText( this, SwContentIndex(pTextNode), pTextNode->Len() );
1067 }
1068 // move all Bookmarks/TOXMarks
1069 if( !pContentStore->Empty())
1070 pContentStore->Restore( rDoc, GetIndex(), nOldLen );
1071
1072 if( pTextNode->HasAnyIndex() )
1073 {
1074 // move all ShellCursor/StackCursor/UnoCursor out of delete range
1075 rDoc.CorrAbs( aIdx.GetNode(), SwPosition( *this ), nOldLen, true );
1076 }
1077 SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag());
1078 auto eRecreateMerged(eOldMergeFlag == SwNode::Merge::First
1081 if (eRecreateMerged == sw::Recreate::No)
1082 {
1083 // tdf#137318 if a delete is inside one node, flag is still None!
1085 for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
1086 {
1087 if (pFrame->GetMergedPara())
1088 {
1089 eRecreateMerged = sw::Recreate::ThisNode;
1090 break;
1091 }
1092 }
1093 }
1094 bool bOldHasNumberingWhichNeedsLayoutUpdate = HasNumberingWhichNeedsLayoutUpdate(*pTextNode);
1095
1096 rNds.Delete(aIdx);
1097 SetWrong( std::move(pList) );
1098 SetGrammarCheck( std::move(pList3) );
1099 SetSmartTags( std::move(pList2) );
1100
1102
1103 if (bOldHasNumberingWhichNeedsLayoutUpdate || HasNumberingWhichNeedsLayoutUpdate(*this))
1104 {
1105 // Repaint all text frames that belong to this numbering to avoid outdated generated
1106 // numbers.
1108 }
1109
1110 CheckResetRedlineMergeFlag(*this, eRecreateMerged);
1111 }
1112 else {
1113 OSL_FAIL( "No TextNode." );
1114 }
1115
1116 return this;
1117}
1118
1120{
1121 SwNodes& rNds = GetNodes();
1122 SwNodeIndex aIdx( *this );
1123 if( SwContentNode::CanJoinPrev( &aIdx ) )
1124 {
1125 SwDoc& rDoc = rNds.GetDoc();
1126 const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
1127 pContentStore->Save( rDoc, aIdx.GetIndex(), SAL_MAX_INT32);
1128 SwTextNode *pTextNode = aIdx.GetNode().GetTextNode();
1129 const sal_Int32 nLen = pTextNode->Len();
1130
1131 std::unique_ptr<SwWrongList> pList = pTextNode->ReleaseWrong();
1132 if( pList )
1133 {
1134 pList->JoinList( GetWrong(), Len() );
1136 ClearWrong();
1137 }
1138 else
1139 {
1140 pList = ReleaseWrong();
1141 if( pList )
1142 {
1143 pList->Move( 0, nLen );
1145 }
1146 }
1147
1148 std::unique_ptr<SwGrammarMarkUp> pList3 = pTextNode->ReleaseGrammarCheck();
1149 if( pList3 )
1150 {
1151 pList3->JoinGrammarList( GetGrammarCheck(), Len() );
1152 SetGrammarCheckDirty( true );
1154 }
1155 else
1156 {
1157 pList3 = ReleaseGrammarCheck();
1158 if( pList3 )
1159 {
1160 pList3->MoveGrammar( 0, nLen );
1161 SetGrammarCheckDirty( true );
1162 }
1163 }
1164
1165 std::unique_ptr<SwWrongList> pList2 = pTextNode->ReleaseSmartTags();
1166 if( pList2 )
1167 {
1168 pList2->JoinList( GetSmartTags(), Len() );
1169 SetSmartTagDirty( true );
1171 }
1172 else
1173 {
1174 pList2 = ReleaseSmartTags();
1175 if( pList2 )
1176 {
1177 pList2->Move( 0, nLen );
1178 SetSmartTagDirty( true );
1179 }
1180 }
1181
1182 { // scope for SwContentIndex
1183 pTextNode->CutText( this, SwContentIndex(this), SwContentIndex(pTextNode), nLen );
1184 }
1185 // move all Bookmarks/TOXMarks
1186 if( !pContentStore->Empty() )
1187 pContentStore->Restore( rDoc, GetIndex() );
1188
1189 if( pTextNode->HasAnyIndex() )
1190 {
1191 // move all ShellCursor/StackCursor/UnoCursor out of delete range
1192 rDoc.CorrAbs( aIdx.GetNode(), SwPosition( *this ), nLen, true );
1193 }
1194 SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag());
1195 if (eOldMergeFlag == SwNode::Merge::First
1197 {
1198 sw::MoveDeletedPrevFrames(*pTextNode, *this);
1199 }
1200 rNds.Delete(aIdx);
1201 SetWrong( std::move(pList) );
1202 SetGrammarCheck( std::move(pList3) );
1203 SetSmartTags( std::move(pList2) );
1207 eOldMergeFlag == SwNode::Merge::NonFirst
1210 }
1211 else {
1212 OSL_FAIL( "No TextNode." );
1213 }
1214}
1215
1216// create an AttrSet with ranges for Frame-/Para/Char-attributes
1218{
1219 OSL_ENSURE( !mpAttrSet, "AttrSet is set after all" );
1220 SwAttrSet aNewAttrSet( rPool, aTextNodeSetRange );
1221
1222 // put names of parent style and conditional style:
1223 const SwFormatColl* pAnyFormatColl = &GetAnyFormatColl();
1224 const SwFormatColl* pFormatColl = GetFormatColl();
1225 OUString sVal;
1227 SfxStringItem aAnyFormatColl( RES_FRMATR_STYLE_NAME, sVal );
1228 if ( pFormatColl != pAnyFormatColl )
1231 aNewAttrSet.Put( aAnyFormatColl );
1232 aNewAttrSet.Put( aFormatColl );
1233
1234 aNewAttrSet.SetParent( &pAnyFormatColl->GetAttrSet() );
1236}
1237
1238namespace
1239{
1240class SwContentNodeTmp : public SwContentNode
1241{
1242public:
1243 SwContentNodeTmp() : SwContentNode() {}
1244 virtual void NewAttrSet(SwAttrPool&) override {}
1245 virtual SwContentFrame *MakeFrame(SwFrame*) override { return nullptr; }
1246 virtual SwContentNode* MakeCopy(SwDoc&, SwNode&, bool /*bNewFrames*/) const override { return nullptr; };
1247};
1248};
1249
1250// override SwContentIndexReg::Update => text hints do not need SwContentIndex for start/end!
1252 SwContentIndex const & rPos,
1253 const sal_Int32 nChangeLen,
1254 UpdateMode const eMode)
1255{
1256 assert(rPos.GetContentNode() == this);
1258
1259 std::unique_ptr<SwpHts> pCollector;
1260 const sal_Int32 nChangePos = rPos.GetIndex();
1261
1262 if ( HasHints() )
1263 {
1264 if (eMode & UpdateMode::Negative)
1265 {
1266 std::vector<SwTextInputField*> aTextInputFields;
1267
1268 const sal_Int32 nChangeEnd = nChangePos + nChangeLen;
1269 for ( size_t n = 0; n < m_pSwpHints->Count(); ++n )
1270 {
1271 bool bTextAttrChanged = false;
1272 bool bStartOfTextAttrChanged = false;
1273 SwTextAttr * const pHint = m_pSwpHints->GetWithoutResorting(n);
1274 if ( pHint->GetStart() > nChangePos )
1275 {
1276 if ( pHint->GetStart() > nChangeEnd )
1277 {
1278 pHint->SetStart( pHint->GetStart() - nChangeLen );
1279 }
1280 else
1281 {
1282 pHint->SetStart( nChangePos );
1283 }
1284 bStartOfTextAttrChanged = true;
1285 }
1286
1287 const sal_Int32 * const pEnd = pHint->GetEnd();
1288 if (pEnd && *pEnd > nChangePos )
1289 {
1290 if( *pEnd > nChangeEnd )
1291 {
1292 pHint->SetEnd(*pEnd - nChangeLen);
1293 }
1294 else
1295 {
1296 pHint->SetEnd(nChangePos);
1297 }
1298 bTextAttrChanged = !bStartOfTextAttrChanged;
1299 }
1300
1301 if ( bTextAttrChanged
1302 && pHint->Which() == RES_TXTATR_INPUTFIELD )
1303 {
1304 SwTextInputField* pTextInputField = dynamic_cast<SwTextInputField*>(pHint);
1305 if ( pTextInputField )
1306 aTextInputFields.push_back(pTextInputField);
1307 }
1308 }
1309
1310 //wait until all the attribute positions are correct
1311 //before updating the field contents
1312 for (SwTextInputField* pTextInputField : aTextInputFields)
1313 {
1314 pTextInputField->UpdateFieldContent();
1315 }
1316
1317 m_pSwpHints->MergePortions( *this );
1318 }
1319 else
1320 {
1321 bool bNoExp = false;
1322 bool bResort = false;
1323 bool bMergePortionsNeeded = false;
1324 const int coArrSz = RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN;
1325 std::vector<SwTextInputField*> aTextInputFields;
1326
1327 bool aDontExp[ coArrSz ] = {};
1328
1329 for ( size_t n = 0; n < m_pSwpHints->Count(); ++n )
1330 {
1331 bool bTextAttrChanged = false;
1332 SwTextAttr * const pHint = m_pSwpHints->GetWithoutResorting(n);
1333 const sal_Int32 * const pEnd = pHint->GetEnd();
1334 if ( pHint->GetStart() >= nChangePos )
1335 {
1336 pHint->SetStart( pHint->GetStart() + nChangeLen );
1337 if ( pEnd )
1338 {
1339 pHint->SetEnd(*pEnd + nChangeLen);
1340 }
1341 }
1342 else if ( pEnd && (*pEnd >= nChangePos) )
1343 {
1344 if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() )
1345 {
1346 pHint->SetEnd(*pEnd + nChangeLen);
1347 bTextAttrChanged = true;
1348 }
1349 else // *pEnd == nChangePos
1350 {
1351 const sal_uInt16 nWhich = pHint->Which();
1352
1353 OSL_ENSURE(!isCHRATR(nWhich), "Update: char attr hint?");
1354 if (!(isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)))
1355 continue;
1356
1357 const sal_uInt16 nWhPos = nWhich - RES_CHRATR_BEGIN;
1358
1359 if( aDontExp[ nWhPos ] )
1360 continue;
1361
1362 if ( pHint->DontExpand() )
1363 {
1364 pHint->SetDontExpand( false );
1365 bResort = true;
1366 // could have a continuation with IgnoreStart()...
1367 if (pHint->IsFormatIgnoreEnd())
1368 {
1369 bMergePortionsNeeded = true;
1370 }
1371 if ( pHint->IsCharFormatAttr() )
1372 {
1373 bNoExp = true;
1374 aDontExp[ RES_TXTATR_CHARFMT - RES_CHRATR_BEGIN ] = true;
1375 aDontExp[ RES_TXTATR_INETFMT - RES_CHRATR_BEGIN ] = true;
1376 }
1377 else
1378 aDontExp[ nWhPos ] = true;
1379 }
1380 else if( bNoExp )
1381 {
1382 if (!pCollector)
1383 {
1384 pCollector.reset( new SwpHts );
1385 }
1386 auto it = std::find_if(pCollector->begin(), pCollector->end(),
1387 [nWhich](const SwTextAttr *pTmp) { return nWhich == pTmp->Which(); });
1388 if (it != pCollector->end())
1389 {
1390 SwTextAttr *pTmp = *it;
1391 pCollector->erase( it );
1392 SwTextAttr::Destroy( pTmp, GetDoc().GetAttrPool() );
1393 }
1394 SwTextAttr * const pTmp =
1396 pHint->GetAttr(), nChangePos, nChangePos + nChangeLen);
1397 pCollector->push_back( pTmp );
1398 }
1399 else
1400 {
1401 pHint->SetEnd(*pEnd + nChangeLen);
1402 bTextAttrChanged = true;
1403 }
1404 }
1405 }
1406
1407 if ( bTextAttrChanged
1408 && pHint->Which() == RES_TXTATR_INPUTFIELD )
1409 {
1410 SwTextInputField* pTextInputField = dynamic_cast<SwTextInputField*>(pHint);
1411 if ( pTextInputField )
1412 aTextInputFields.push_back(pTextInputField);
1413 }
1414 }
1415
1416 //wait until all the attribute positions are correct
1417 //before updating the field contents
1418 for (SwTextInputField* pTextInputField : aTextInputFields)
1419 {
1420 pTextInputField->UpdateFieldContent();
1421 }
1422
1423 if (bMergePortionsNeeded)
1424 {
1425 m_pSwpHints->MergePortions(*this); // does Resort too
1426 }
1427 else if (bResort)
1428 {
1429 m_pSwpHints->Resort();
1430 }
1431 }
1432 }
1433
1434 bool bSortMarks = false;
1435 SwContentNodeTmp aTmpIdxReg;
1436 if (!(eMode & UpdateMode::Negative) && !(eMode & UpdateMode::Delete))
1437 {
1438 std::vector<SwRangeRedline*> vMyRedlines;
1439 // walk the list of SwIndex attached to me and see if any of them are redlines
1440 const SwContentIndex* pContentNodeIndex = GetFirstIndex();
1441 while (pContentNodeIndex)
1442 {
1443 SwRangeRedline* pRedl = pContentNodeIndex->GetRedline();
1444 if (pRedl)
1445 vMyRedlines.push_back(pRedl);
1446 pContentNodeIndex = pContentNodeIndex->GetNext();
1447 }
1448 std::sort(vMyRedlines.begin(), vMyRedlines.end());
1449 vMyRedlines.erase( std::unique( vMyRedlines.begin(), vMyRedlines.end() ), vMyRedlines.end() );
1450 for (SwRangeRedline* pRedl : vMyRedlines)
1451 {
1452 if ( pRedl->HasMark() )
1453 {
1454 SwPosition* const pEnd = pRedl->End();
1455 if ( *this == pEnd->GetNode() &&
1456 *pRedl->GetPoint() != *pRedl->GetMark() )
1457 {
1458 SwContentIndex & rIdx = pEnd->nContent;
1459 if (nChangePos == rIdx.GetIndex())
1460 {
1461 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1462 }
1463 }
1464 }
1465 else if ( this == &pRedl->GetPoint()->GetNode() )
1466 {
1467 SwContentIndex & rIdx = pRedl->GetPoint()->nContent;
1468 if (nChangePos == rIdx.GetIndex())
1469 {
1470 rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1471 }
1472 // the unused position must not be on a SwTextNode
1473 bool const isOneUsed(&pRedl->GetBound() == pRedl->GetPoint());
1474 assert(!pRedl->GetBound(!isOneUsed).GetNode().IsTextNode());
1475 assert(!pRedl->GetBound(!isOneUsed).GetContentNode()); (void)isOneUsed;
1476 }
1477 }
1478
1479 // Bookmarks must never grow to either side, when editing (directly)
1480 // to the left or right (i#29942)! Exception: if the bookmark has
1481 // 2 positions and start == end, then expand it (tdf#96479)
1482 if (!(eMode & UpdateMode::Replace)) // Exception: Replace
1483 {
1484 bool bAtLeastOneBookmarkMoved = false;
1485 bool bAtLeastOneExpandedBookmarkAtInsertionPosition = false;
1486 // A text node already knows its marks via its SwContentIndexes.
1488 const SwContentIndex* next;
1489 for (const SwContentIndex* pIndex = GetFirstIndex(); pIndex; pIndex = next )
1490 {
1491 next = pIndex->GetNext();
1492 const sw::mark::IMark* pMark = pIndex->GetMark();
1493 if (!pMark)
1494 continue;
1495 // Only handle bookmarks once, if they start and end at this node as well.
1496 if (!aSeenMarks.insert(pMark).second)
1497 continue;
1498 const SwPosition* pEnd = &pMark->GetMarkEnd();
1499 SwContentIndex & rEndIdx = const_cast<SwContentIndex&>(pEnd->nContent);
1500 if( *this == pEnd->GetNode() &&
1501 rPos.GetIndex() == rEndIdx.GetIndex() )
1502 {
1503 if (&rEndIdx == next) // nasty corner case:
1504 { // don't switch to iterating aTmpIdxReg!
1505 next = rEndIdx.GetNext();
1506 }
1507 // tdf#96479: if start == end, ignore the other position
1508 // so it is moved!
1509 rEndIdx.Assign( &aTmpIdxReg, rEndIdx.GetIndex() );
1510 bAtLeastOneBookmarkMoved = true;
1511 }
1512 else if ( !bAtLeastOneExpandedBookmarkAtInsertionPosition )
1513 {
1514 if ( pMark->IsExpanded() )
1515 {
1516 const SwPosition* pStart = &pMark->GetMarkStart();
1517 if ( this == &pStart->GetNode()
1518 && rPos.GetIndex() == pStart->GetContentIndex() )
1519 {
1520 bAtLeastOneExpandedBookmarkAtInsertionPosition = true;
1521 }
1522 }
1523 }
1524 }
1525
1526 bSortMarks = bAtLeastOneBookmarkMoved && bAtLeastOneExpandedBookmarkAtInsertionPosition;
1527 }
1528
1529 // at-char anchored flys shouldn't be moved, either.
1530 if (!m_bInUndo)
1531 {
1532 std::vector<SwFrameFormat*> const& rFlys(GetAnchoredFlys());
1533 for (size_t i = 0; i != rFlys.size(); ++i)
1534 {
1535 SwFrameFormat const*const pFormat = rFlys[i];
1536 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
1537 const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
1538 if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR && pAnchorNode)
1539 {
1540 // The fly is at-char anchored and has an anchor position.
1541 SwContentIndex& rEndIdx = const_cast<SwContentIndex&>(rAnchor.GetContentAnchor()->nContent);
1542 if (*pAnchorNode == *this && rEndIdx.GetIndex() == rPos.GetIndex())
1543 {
1544 // The anchor position is exactly our insert position.
1545 rEndIdx.Assign(&aTmpIdxReg, rEndIdx.GetIndex());
1546 }
1547 }
1548 }
1549 }
1550
1551 // The cursors of other shells shouldn't be moved, either.
1552 if (SwDocShell* pDocShell = GetDoc().GetDocShell())
1553 {
1554 if (pDocShell->GetWrtShell())
1555 {
1556 for (SwViewShell& rShell : pDocShell->GetWrtShell()->GetRingContainer())
1557 {
1558 auto pWrtShell = dynamic_cast<SwWrtShell*>(&rShell);
1559 if (!pWrtShell || pWrtShell == pDocShell->GetWrtShell())
1560 continue;
1561
1562 SwShellCursor* pCursor = pWrtShell->GetCursor_();
1563 if (!pCursor)
1564 continue;
1565
1566 SwContentIndex& rIndex = pCursor->Start()->nContent;
1567 if (pCursor->Start()->GetNode() == *this && rIndex.GetIndex() == rPos.GetIndex())
1568 {
1569 // The cursor position of this other shell is exactly our insert position.
1570 rIndex.Assign(&aTmpIdxReg, rIndex.GetIndex());
1571 }
1572 }
1573 }
1574 }
1575 }
1576
1577 // base class
1578 SwContentIndexReg::Update(rPos, nChangeLen, eMode);
1579
1580 if (pCollector)
1581 {
1582 const size_t nCount = pCollector->size();
1583 for ( size_t i = 0; i < nCount; ++i )
1584 {
1585 m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
1586 }
1587 }
1588
1589 aTmpIdxReg.MoveTo( *this );
1590 if ( bSortMarks )
1591 {
1593 }
1594
1595 //Any drawing objects anchored into this text node may be sorted by their
1596 //anchor position which may have changed here, so resort them
1598 for (SwTextFrame* pFrame = iter.First(); pFrame; pFrame = iter.Next())
1599 {
1600 SwSortedObjs * pSortedObjs(pFrame->GetDrawObjs());
1601 if (pSortedObjs)
1602 {
1603 pSortedObjs->UpdateAll();
1604 }
1605 // also sort the objs on the page frame
1606 if (SwPageFrame *pPage = pFrame->FindPageFrame())
1607 pSortedObjs = pPage->GetSortedObjs();
1608
1609 if (pSortedObjs) // doesn't exist yet if called for inserting as-char fly
1610 {
1611 pSortedObjs->UpdateAll();
1612 }
1613 }
1614
1615 // Update the paragraph signatures.
1616 if (SwEditShell* pEditShell = GetDoc().GetEditShell())
1617 {
1618 pEditShell->ValidateParagraphSignatures(this, true);
1619 }
1620
1621 // Inform LOK clients about change in position of redlines (if any)
1622 // Don't emit notifications during save: redline flags are temporarily changed during save, but
1623 // it's not useful to let clients know about such changes.
1624 if (!comphelper::LibreOfficeKit::isActive() || GetDoc().IsInWriting())
1625 return;
1626
1628 for (SwRedlineTable::size_type nRedlnPos = 0; nRedlnPos < rTable.size(); ++nRedlnPos)
1629 {
1630 SwRangeRedline* pRedln = rTable[nRedlnPos];
1631 if (pRedln->HasMark())
1632 {
1633 if (*this == pRedln->End()->GetNode() && *pRedln->GetPoint() != *pRedln->GetMark())
1634 {
1635 // Redline is changed only when some change occurs before it
1636 if (nChangePos <= pRedln->Start()->GetContentIndex())
1637 {
1639 }
1640 }
1641 }
1642 else if (this == &pRedln->GetPoint()->GetNode())
1644 }
1645}
1646
1648 const SwTextFormatColl *pNewColl)
1649{
1650 SwDoc& rDoc = GetDoc();
1651 // query the OutlineLevel and if it changed, notify the Nodes-Array!
1652 const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
1654 const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
1656
1657 if ( MAXLEVEL != nNewLevel && -1 != nNewLevel )
1658 {
1659 SetAttrListLevel(nNewLevel);
1660 }
1661 rDoc.GetNodes().UpdateOutlineNode(*this);
1662
1663 SwNodes& rNds = GetNodes();
1664 // If Level 0 (Chapter), update the footnotes!
1665 if( ( !nNewLevel || !nOldLevel) && !rDoc.GetFootnoteIdxs().empty() &&
1667 rNds.IsDocNodes() )
1668 {
1669 rDoc.GetFootnoteIdxs().UpdateFootnote( *rNds[GetIndex()] );
1670 }
1671
1672 if( pNewColl && RES_CONDTXTFMTCOLL == pNewColl->Which() )
1673 {
1674 // check the condition of the text node again
1675 ChkCondColl();
1676 }
1677}
1678
1679// If positioned exactly at the end of a CharStyle or Hyperlink,
1680// set its DontExpand flag.
1681bool SwTextNode::DontExpandFormat( sal_Int32 nIdx, bool bFlag,
1682 bool bFormatToTextAttributes )
1683{
1684 if (bFormatToTextAttributes && nIdx == m_Text.getLength())
1685 {
1686 FormatToTextAttr( this );
1687 }
1688
1689 bool bRet = false;
1690 if ( HasHints() )
1691 {
1692 m_pSwpHints->SortIfNeedBe();
1693 int nPos = m_pSwpHints->GetLastPosSortedByEnd(nIdx);
1694 for ( ; nPos >= 0; --nPos)
1695 {
1696 SwTextAttr *pTmp = m_pSwpHints->GetSortedByEnd( nPos );
1697 const sal_Int32 *pEnd = pTmp->GetEnd();
1698 if( !pEnd )
1699 continue;
1700 assert( *pEnd <= nIdx );
1701 if( nIdx != *pEnd )
1702 break;
1703 if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
1704 && *pEnd > pTmp->GetStart())
1705 {
1706 bRet = true;
1707 m_pSwpHints->NoteInHistory( pTmp );
1708 pTmp->SetDontExpand( bFlag );
1709 }
1710 }
1711 }
1712 return bRet;
1713}
1714
1715static bool lcl_GetTextAttrDefault(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd)
1716{
1717 return ((nHintStart <= nIndex) && (nIndex < nHintEnd));
1718}
1719static bool lcl_GetTextAttrExpand(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd)
1720{
1721 return ((nHintStart < nIndex) && (nIndex <= nHintEnd));
1722}
1723static bool lcl_GetTextAttrParent(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd)
1724{
1725 return ((nHintStart < nIndex) && (nIndex < nHintEnd));
1726}
1727
1728static void
1730 std::vector<SwTextAttr *> *const pVector,
1731 SwTextAttr **const ppTextAttr,
1732 SwpHints const *const pSwpHints,
1733 sal_Int32 const nIndex, sal_uInt16 const nWhich,
1734 ::sw::GetTextAttrMode const eMode)
1735{
1736 assert(nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END);
1737 if (!pSwpHints)
1738 return;
1739 size_t const nSize = pSwpHints->Count();
1740 sal_Int32 nPreviousIndex(0); // index of last hint with nWhich
1741 bool (*pMatchFunc)(sal_Int32, sal_Int32, sal_Int32)=nullptr;
1742 switch (eMode)
1743 {
1744 case ::sw::GetTextAttrMode::Default: pMatchFunc = &lcl_GetTextAttrDefault;
1745 break;
1746 case ::sw::GetTextAttrMode::Expand: pMatchFunc = &lcl_GetTextAttrExpand;
1747 break;
1748 case ::sw::GetTextAttrMode::Parent: pMatchFunc = &lcl_GetTextAttrParent;
1749 break;
1750 default: assert(false);
1751 }
1752
1753 for( size_t i = pSwpHints->GetFirstPosSortedByWhichAndStart(nWhich); i < nSize; ++i )
1754 {
1755 SwTextAttr *const pHint = pSwpHints->GetSortedByWhichAndStart(i);
1756 if (pHint->Which() != nWhich)
1757 break; // hints are sorted by which&start, so we are done...
1758
1759 sal_Int32 const nHintStart = pHint->GetStart();
1760 if (nIndex < nHintStart)
1761 break; // hints are sorted by which&start, so we are done...
1762
1763 sal_Int32 const*const pEndIdx = pHint->GetEnd();
1764 // cannot have hint with no end and no dummy char
1765 assert(pEndIdx || pHint->HasDummyChar());
1766 // If EXPAND is set, simulate the text input behavior, i.e.
1767 // move the start, and expand the end.
1768 bool const bContained( pEndIdx
1769 ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx)
1770 : (nHintStart == nIndex) );
1771 if (bContained)
1772 {
1773 if (pVector)
1774 {
1775 if (nPreviousIndex < nHintStart)
1776 {
1777 pVector->clear(); // clear hints that are outside pHint
1778 nPreviousIndex = nHintStart;
1779 }
1780 pVector->push_back(pHint);
1781 }
1782 else
1783 {
1784 *ppTextAttr = pHint; // and possibly overwrite outer hint
1785 }
1786 if (!pEndIdx)
1787 {
1788 break;
1789 }
1790 }
1791 }
1792}
1793
1794std::vector<SwTextAttr *>
1795SwTextNode::GetTextAttrsAt(sal_Int32 const nIndex, sal_uInt16 const nWhich) const
1796{
1797 assert(nWhich >= RES_TXTATR_BEGIN && nWhich < RES_TXTATR_END);
1798 std::vector<SwTextAttr *> ret;
1799 lcl_GetTextAttrs(&ret, nullptr, m_pSwpHints.get(), nIndex, nWhich, ::sw::GetTextAttrMode::Default);
1800 return ret;
1801}
1802
1803SwTextAttr *
1804SwTextNode::GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich,
1805 ::sw::GetTextAttrMode const eMode) const
1806{
1807 assert( (nWhich == RES_TXTATR_META)
1808 || (nWhich == RES_TXTATR_METAFIELD)
1809 || (nWhich == RES_TXTATR_AUTOFMT)
1810 || (nWhich == RES_TXTATR_INETFMT)
1811 || (nWhich == RES_TXTATR_CJK_RUBY)
1812 || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER)
1813 || (nWhich == RES_TXTATR_CONTENTCONTROL)
1814 || (nWhich == RES_TXTATR_INPUTFIELD ) );
1815 // "GetTextAttrAt() will give wrong result for this hint!")
1816
1817 SwTextAttr * pRet(nullptr);
1818 lcl_GetTextAttrs(nullptr, & pRet, m_pSwpHints.get(), nIndex, nWhich, eMode);
1819 return pRet;
1820}
1821
1823{
1824 const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextAttrAt(rTextAttr.GetStart(), RES_TXTATR_INPUTFIELD, ::sw::GetTextAttrMode::Parent));
1825
1826 if ( pTextInputField == nullptr && rTextAttr.End() != nullptr )
1827 {
1828 pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextAttrAt(*(rTextAttr.End()), RES_TXTATR_INPUTFIELD, ::sw::GetTextAttrMode::Parent));
1829 }
1830
1831 return pTextInputField;
1832}
1833
1835{
1836 SetWrong( nullptr );
1838
1839 SetGrammarCheck( nullptr );
1840 SetGrammarCheckDirty( true );
1841
1842 SetSmartTags( nullptr );
1843 SetSmartTagDirty( true );
1844
1845 SetWordCountDirty( true );
1847}
1848
1850 const sal_Int32 nIndex,
1851 ::sw::GetTextAttrMode const eMode) const
1852{
1853 SwTextField* pTextField = dynamic_cast<SwTextField*>(GetTextAttrForCharAt( nIndex, RES_TXTATR_FIELD ));
1854 if ( pTextField == nullptr )
1855 {
1856 pTextField = dynamic_cast<SwTextField*>(GetTextAttrForCharAt( nIndex, RES_TXTATR_ANNOTATION ));
1857 }
1858 if ( pTextField == nullptr )
1859 {
1860 pTextField =
1861 dynamic_cast<SwTextField*>( GetTextAttrAt(
1862 nIndex,
1864 eMode));
1865 }
1866
1867 return pTextField;
1868}
1869
1870static SwCharFormat* lcl_FindCharFormat( const SwCharFormats* pCharFormats, std::u16string_view rName )
1871{
1872 if( !rName.empty() )
1873 {
1874 const size_t nArrLen = pCharFormats->size();
1875 for( size_t i = 1; i < nArrLen; i++ )
1876 {
1877 SwCharFormat* pFormat = (*pCharFormats)[ i ];
1878 if( pFormat->GetName()==rName )
1879 return pFormat;
1880 }
1881 }
1882 return nullptr;
1883}
1884
1885static void lcl_CopyHint(
1886 const sal_uInt16 nWhich,
1887 const SwTextAttr * const pHt,
1888 SwTextAttr *const pNewHt,
1889 SwDoc *const pOtherDoc,
1890 SwTextNode *const pDest )
1891{
1892 assert(nWhich == pHt->Which()); // wrong hint-id
1893 switch( nWhich )
1894 {
1895 // copy nodesarray section with footnote content
1896 case RES_TXTATR_FTN :
1897 assert(pDest); // "lcl_CopyHint: no destination text node?"
1898 static_cast<const SwTextFootnote*>(pHt)->CopyFootnote( *static_cast<SwTextFootnote*>(pNewHt), *pDest);
1899 break;
1900
1901 // Fields that are copied into different SwDocs must be registered
1902 // at their new FieldTypes.
1903
1904 case RES_TXTATR_FIELD :
1905 {
1906 if( pOtherDoc != nullptr )
1907 {
1908 static_txtattr_cast<const SwTextField*>(pHt)->CopyTextField(
1909 static_txtattr_cast<SwTextField*>(pNewHt));
1910 }
1911
1912 // Table Formula must be copied relative.
1913 const SwFormatField& rField = pHt->GetFormatField();
1914 if( SwFieldIds::Table == rField.GetField()->GetTyp()->Which()
1915 && static_cast<const SwTableField*>(rField.GetField())->IsIntrnlName())
1916 {
1917 // convert internal formula to external
1918 const SwTableNode* const pDstTableNd =
1919 static_txtattr_cast<const SwTextField*>(pHt)->GetTextNode().FindTableNode();
1920 if( pDstTableNd )
1921 {
1922 SwTableField* const pTableField =
1923 const_cast<SwTableField*>(static_cast<const SwTableField*>(
1924 pNewHt->GetFormatField().GetField()));
1925 pTableField->PtrToBoxNm( &pDstTableNd->GetTable() );
1926 }
1927 }
1928 }
1929 break;
1930
1933 if( pOtherDoc != nullptr )
1934 {
1935 static_txtattr_cast<const SwTextField*>(pHt)->CopyTextField(
1936 static_txtattr_cast<SwTextField*>(pNewHt));
1937 }
1938 break;
1939
1940 case RES_TXTATR_TOXMARK :
1941 if( pOtherDoc && pDest && pDest->GetpSwpHints()
1942 && pDest->GetpSwpHints()->Contains( pNewHt ) )
1943 {
1944 // ToXMarks that are copied to different SwDocs must register
1945 // at their new ToX (sw::BroadcastingModify).
1946 static_txtattr_cast<SwTextTOXMark*>(pNewHt)->CopyTOXMark(*pOtherDoc);
1947 }
1948 break;
1949
1950 case RES_TXTATR_CHARFMT :
1951 // For CharacterStyles, the format must be copied too.
1952 if( pDest && pDest->GetpSwpHints()
1953 && pDest->GetpSwpHints()->Contains( pNewHt ) )
1954 {
1955 SwCharFormat* pFormat = pHt->GetCharFormat().GetCharFormat();
1956
1957 if (pOtherDoc)
1958 {
1959 pFormat = pOtherDoc->CopyCharFormat( *pFormat );
1960 }
1961 const_cast<SwFormatCharFormat&>(
1962 pNewHt->GetCharFormat() ).SetCharFormat( pFormat );
1963 }
1964 break;
1965 case RES_TXTATR_INETFMT :
1966 {
1967 // For Hyperlinks, the format must be copied too.
1968 if( pOtherDoc && pDest && pDest->GetpSwpHints()
1969 && pDest->GetpSwpHints()->Contains( pNewHt ) )
1970 {
1971 const SwDoc& rDoc = static_txtattr_cast<
1972 const SwTextINetFormat*>(pHt)->GetTextNode().GetDoc();
1973 const SwCharFormats* pCharFormats = rDoc.GetCharFormats();
1974 const SwFormatINetFormat& rFormat = pHt->GetINetFormat();
1975 SwCharFormat* pFormat;
1976 pFormat = lcl_FindCharFormat( pCharFormats, rFormat.GetINetFormat() );
1977 if( pFormat )
1978 pOtherDoc->CopyCharFormat( *pFormat );
1979 pFormat = lcl_FindCharFormat( pCharFormats, rFormat.GetVisitedFormat() );
1980 if( pFormat )
1981 pOtherDoc->CopyCharFormat( *pFormat );
1982 }
1983 //JP 24.04.98: The attribute must point to a text node, so that
1984 // the styles can be created.
1985 SwTextINetFormat *const pINetHt = static_txtattr_cast<SwTextINetFormat*>(pNewHt);
1986 if ( !pINetHt->GetpTextNode() )
1987 {
1988 pINetHt->ChgTextNode( pDest );
1989 }
1990
1991 //JP 22.10.97: set up link to char style
1992 pINetHt->GetCharFormat();
1993 break;
1994 }
1995 case RES_TXTATR_META:
1997 OSL_ENSURE( pNewHt, "copying Meta should not fail!" );
1998 OSL_ENSURE( pDest
1999 && (CH_TXTATR_INWORD == pDest->GetText()[pNewHt->GetStart()]),
2000 "missing CH_TXTATR?");
2001 break;
2002 }
2003}
2004
2006// BP 7.6.93: Intentionally copy only attributes _with_ EndIdx!
2007// CopyAttr is usually called when attributes are set on a
2008// node with no text.
2009void SwTextNode::CopyAttr( SwTextNode *pDest, const sal_Int32 nTextStartIdx,
2010 const sal_Int32 nOldPos )
2011{
2012 if ( HasHints() )
2013 {
2014 SwDoc* const pOtherDoc = (&pDest->GetDoc() != &GetDoc()) ?
2015 &pDest->GetDoc() : nullptr;
2016
2017 for ( size_t i = 0; i < m_pSwpHints->Count(); ++i )
2018 {
2019 SwTextAttr *const pHt = m_pSwpHints->Get(i);
2020 sal_Int32 const nAttrStartIdx = pHt->GetStart();
2021 if ( nTextStartIdx < nAttrStartIdx )
2022 break; // beyond end of text, because nLen == 0
2023
2024 const sal_Int32 *const pEndIdx = pHt->GetEnd();
2025 if ( pEndIdx && !pHt->HasDummyChar() )
2026 {
2027 sal_uInt16 const nWhich = pHt->Which();
2028 if (RES_TXTATR_INPUTFIELD != nWhich // fdo#74981 skip fields
2029 && ( *pEndIdx > nTextStartIdx
2030 || (*pEndIdx == nTextStartIdx
2031 && nAttrStartIdx == nTextStartIdx)))
2032 {
2033 if ( RES_TXTATR_REFMARK != nWhich )
2034 {
2035 // attribute in the area => copy
2036 SwTextAttr *const pNewHt =
2037 pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos, SetAttrMode::IS_COPY);
2038 if ( pNewHt )
2039 {
2040 lcl_CopyHint( nWhich, pHt, pNewHt,
2041 pOtherDoc, pDest );
2042 }
2043 }
2044 else if( !pOtherDoc
2045 ? GetDoc().IsCopyIsMove()
2046 : nullptr == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) )
2047 {
2048 pDest->InsertItem(
2049 pHt->GetAttr(), nOldPos, nOldPos, SetAttrMode::IS_COPY);
2050 }
2051 }
2052 }
2053 }
2054 }
2055
2056 if( this != pDest )
2057 {
2058 // notify layout frames, to prevent disappearance of footnote numbers
2059 SwUpdateAttr aHint(
2060 nOldPos,
2061 nOldPos,
2062 0);
2063
2064 pDest->TriggerNodeUpdate(sw::LegacyModifyHint(&aHint, &aHint));
2065 }
2066}
2067
2070 const SwContentIndex &rStart,
2071 const sal_Int32 nLen,
2072 const bool bForceCopyOfAllAttrs )
2073{
2074 SwContentIndex const aIdx( pDest, pDest->m_Text.getLength() );
2075 CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
2076}
2077
2079 const SwContentIndex &rDestStart,
2080 const SwPosition &rStart,
2081 sal_Int32 nLen,
2082 const bool bForceCopyOfAllAttrs )
2083{
2084 CopyText( pDest, rDestStart, rStart.nContent, nLen, bForceCopyOfAllAttrs );
2085}
2086
2088 const SwContentIndex &rDestStart,
2089 const SwContentIndex &rStart,
2090 sal_Int32 nLen,
2091 const bool bForceCopyOfAllAttrs )
2092{
2094 CHECK_SWPHINTS(pDest);
2095 assert(rDestStart.GetContentNode() == pDest);
2096 assert(rStart.GetContentNode() == this);
2097 sal_Int32 nTextStartIdx = rStart.GetIndex();
2098 sal_Int32 nDestStart = rDestStart.GetIndex(); // remember old Pos
2099
2100 if (pDest->GetDoc().IsClipBoard() && GetNum())
2101 {
2102 // #i111677# cache expansion of source (for clipboard)
2103 pDest->m_oNumStringCache = (nTextStartIdx != 0)
2104 ? OUString() // fdo#49076: numbering only if copy from para start
2105 : GetNumString();
2106 }
2107
2108 if( !nLen )
2109 {
2110 // if no length is given, copy attributes at position rStart
2111 CopyAttr( pDest, nTextStartIdx, nDestStart );
2112
2113 // copy hard attributes on whole paragraph
2114 if( HasSwAttrSet() )
2115 {
2116 // i#96213 all or just the Char attributes?
2117 if ( !bForceCopyOfAllAttrs &&
2118 ( nDestStart ||
2119 pDest->HasSwAttrSet() ||
2120 nLen != pDest->GetText().getLength()))
2121 {
2126 aCharSet( pDest->GetDoc().GetAttrPool() );
2127 aCharSet.Put( *GetpSwAttrSet() );
2128 if( aCharSet.Count() )
2129 {
2130 pDest->SetAttr( aCharSet, nDestStart, nDestStart );
2131 }
2132 }
2133 else
2134 {
2135 GetpSwAttrSet()->CopyToModify( *pDest );
2136 }
2137 }
2138 return;
2139 }
2140
2141 // 1. copy text
2142 const sal_Int32 oldLen = pDest->m_Text.getLength();
2143 // JP 15.02.96: missing attribute handling at the end!
2144 // hence call InsertText and don't modify m_Text directly
2145 pDest->InsertText( m_Text.copy(nTextStartIdx, nLen), rDestStart,
2147
2148 // update with actual new size
2149 nLen = pDest->m_Text.getLength() - oldLen;
2150 if ( !nLen ) // string not longer?
2151 return;
2152
2153 SwDoc* const pOtherDoc = (&pDest->GetDoc() != &GetDoc()) ? &pDest->GetDoc() : nullptr;
2154
2155 // copy hard attributes on whole paragraph
2156 if( HasSwAttrSet() )
2157 {
2158 // i#96213 all or just the Char attributes?
2159 if ( !bForceCopyOfAllAttrs &&
2160 ( nDestStart ||
2161 pDest->HasSwAttrSet() ||
2162 nLen != pDest->GetText().getLength()))
2163 {
2168 aCharSet( pDest->GetDoc().GetAttrPool() );
2169 aCharSet.Put( *GetpSwAttrSet() );
2170 if( aCharSet.Count() )
2171 {
2172 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
2173 }
2174 }
2175 else
2176 {
2177 GetpSwAttrSet()->CopyToModify( *pDest );
2178 }
2179 }
2180
2181 bool const bUndoNodes = !pOtherDoc
2182 && GetDoc().GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
2183
2184 // Fetch end only now, because copying into self updates the start index
2185 // and all attributes
2186 nTextStartIdx = rStart.GetIndex();
2187 const sal_Int32 nEnd = nTextStartIdx + nLen;
2188
2189 // 2. copy attributes
2190 // Iterate over attribute array until the start of the attribute
2191 // is behind the copied range
2192 const size_t nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
2193
2194 // If copying into self, inserting can delete attributes!
2195 // Hence first copy into temp-array, and then move that into hints array.
2196 SwpHts aArr;
2197
2198 // Del-Array for all RefMarks without extent
2199 SwpHts aRefMrkArr;
2200
2201 std::vector<std::pair<sal_Int32, sal_Int32>> metaFieldRanges;
2202 sal_Int32 nDeletedDummyChars(0);
2203 for (size_t n = 0; n < nSize; ++n)
2204 {
2205 SwTextAttr * const pHt = m_pSwpHints->Get(n);
2206
2207 const sal_Int32 nAttrStartIdx = pHt->GetStart();
2208 if ( nAttrStartIdx >= nEnd )
2209 break;
2210
2211 const sal_Int32 * const pEndIdx = pHt->GetEnd();
2212 const sal_uInt16 nWhich = pHt->Which();
2213
2214 // JP 26.04.94: RefMarks are never copied. If the refmark doesn't have
2215 // an extent, there is a dummy char in the text, which
2216 // must be removed. So we first copy the attribute,
2217 // but remember it, and when we're done delete it,
2218 // which also deletes the dummy character!
2219 // JP 14.08.95: May RefMarks be moved?
2220 const bool bCopyRefMark = RES_TXTATR_REFMARK == nWhich
2221 && ( bUndoNodes
2222 || ( !pOtherDoc
2223 ? GetDoc().IsCopyIsMove()
2224 : nullptr == pOtherDoc->GetRefMark( pHt->GetRefMark().GetRefName() ) ) );
2225
2226 if ( pEndIdx
2227 && RES_TXTATR_REFMARK == nWhich
2228 && !bCopyRefMark )
2229 {
2230 continue;
2231 }
2232
2233 // Input Fields are only copied, if completely covered by copied text
2234 if ( nWhich == RES_TXTATR_INPUTFIELD )
2235 {
2236 assert(pEndIdx != nullptr &&
2237 "<SwTextNode::CopyText(..)> - RES_TXTATR_INPUTFIELD without EndIndex!" );
2238 if ( nAttrStartIdx < nTextStartIdx
2239 || ( pEndIdx != nullptr
2240 && *pEndIdx > nEnd ) )
2241 {
2242 continue;
2243 }
2244 }
2245
2246 if (nWhich == RES_TXTATR_METAFIELD)
2247 {
2248 // Skip metadata fields. Also remember the range to strip the text later.
2249 metaFieldRanges.emplace_back(nAttrStartIdx, pEndIdx ? *pEndIdx : nEnd);
2250 continue;
2251 }
2252
2253 sal_Int32 nAttrStt = 0;
2254 sal_Int32 nAttrEnd = 0;
2255
2256 if( nAttrStartIdx < nTextStartIdx )
2257 {
2258 // start is before selection
2259 // copy hints with end and CH_TXTATR only if dummy char is copied
2260 if ( pEndIdx && (*pEndIdx > nTextStartIdx) && !pHt->HasDummyChar() )
2261 {
2262 // attribute with extent and the end is in the selection
2263 nAttrStt = nDestStart;
2264 nAttrEnd = (*pEndIdx > nEnd)
2265 ? rDestStart.GetIndex()
2266 : nDestStart + (*pEndIdx) - nTextStartIdx;
2267 }
2268 else
2269 {
2270 continue;
2271 }
2272 }
2273 else
2274 {
2275 // start is in the selection
2276 nAttrStt = nDestStart + ( nAttrStartIdx - nTextStartIdx );
2277 if( pEndIdx )
2278 {
2279 nAttrEnd = *pEndIdx > nEnd
2280 ? rDestStart.GetIndex()
2281 : nDestStart + ( *pEndIdx - nTextStartIdx );
2282 }
2283 else
2284 {
2285 nAttrEnd = nAttrStt;
2286 }
2287 }
2288
2289 SwTextAttr * pNewHt = nullptr;
2290
2291 if( pDest == this )
2292 {
2293 // copy the hint here, but insert it later
2294 pNewHt = MakeTextAttr( GetDoc(), pHt->GetAttr(),
2295 nAttrStt, nAttrEnd, CopyOrNewType::Copy, pDest );
2296
2297 lcl_CopyHint(nWhich, pHt, pNewHt, nullptr, pDest);
2298 aArr.push_back( pNewHt );
2299 }
2300 else
2301 {
2302 pNewHt = pDest->InsertItem(
2303 pHt->GetAttr(),
2304 nAttrStt - nDeletedDummyChars,
2305 nAttrEnd - nDeletedDummyChars,
2307 if (pNewHt)
2308 {
2309 lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
2310 }
2311 else if (pHt->HasDummyChar())
2312 {
2313 // The attribute that has failed to be copied would insert
2314 // dummy char, so positions of the following attributes have
2315 // to be shifted by one to compensate for that missing char.
2316 ++nDeletedDummyChars;
2317 }
2318 }
2319
2320 if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
2321 {
2322 aRefMrkArr.push_back( pNewHt );
2323 }
2324 }
2325
2326 // Strip the metadata fields, since we don't copy the RDF entries
2327 // yet and so they are inconsistent upon copy/pasting.
2328 if (!metaFieldRanges.empty())
2329 {
2330 // Reverse to remove without messing the offsets.
2331 std::reverse(metaFieldRanges.begin(), metaFieldRanges.end());
2332 for (const auto& pair : metaFieldRanges)
2333 {
2334 const SwContentIndex aIdx(pDest, pair.first);
2335 pDest->EraseText(aIdx, pair.second - pair.first);
2336 }
2337 }
2338
2339 // this can only happen when copying into self
2340 for (SwTextAttr* i : aArr)
2341 {
2343 }
2344
2345 if( pDest->GetpSwpHints() )
2346 {
2347 for (SwTextAttr* pNewHt : aRefMrkArr)
2348 {
2349 if( pNewHt->GetEnd() )
2350 {
2351 pDest->GetpSwpHints()->Delete( pNewHt );
2352 pDest->DestroyAttr( pNewHt );
2353 }
2354 else
2355 {
2356 const SwContentIndex aIdx( pDest, pNewHt->GetStart() );
2357 pDest->EraseText( aIdx, 1 );
2358 }
2359 }
2360 }
2361
2363 CHECK_SWPHINTS(pDest);
2364}
2365
2366OUString SwTextNode::InsertText( const OUString & rStr, const SwPosition & rIdx,
2367 const SwInsertFlags nMode )
2368{
2369 return InsertText(rStr, rIdx.nContent, nMode);
2370}
2371
2372OUString SwTextNode::InsertText( const OUString & rStr, const SwContentIndex & rIdx,
2373 const SwInsertFlags nMode )
2374{
2375 assert(rIdx.GetContentNode() == this);
2376 assert(rIdx <= m_Text.getLength()); // invalid index
2377
2378 const sal_Int32 aPos = rIdx.GetIndex();
2379 sal_Int32 nLen = m_Text.getLength() - aPos;
2380 sal_Int32 const nOverflow(rStr.getLength() - GetSpaceLeft());
2381 SAL_WARN_IF(nOverflow > 0, "sw.core",
2382 "SwTextNode::InsertText: node text with insertion > capacity.");
2383 OUString const sInserted(
2384 (nOverflow > 0) ? rStr.copy(0, rStr.getLength() - nOverflow) : rStr);
2385 if (sInserted.isEmpty())
2386 {
2387 return sInserted;
2388 }
2389 if (aPos == 0 && m_Text.isEmpty())
2390 m_Text = sInserted;
2391 else
2392 m_Text = m_Text.replaceAt(aPos, 0, sInserted);
2393 assert(GetSpaceLeft()>=0);
2394 nLen = m_Text.getLength() - aPos - nLen;
2395 assert(nLen != 0);
2396
2397 bool bOldExpFlg = IsIgnoreDontExpand();
2399 {
2400 SetIgnoreDontExpand( true );
2401 }
2402
2403 Update(rIdx, nLen, UpdateMode::Default); // text content changed!
2404
2406 {
2407 SetIgnoreDontExpand( bOldExpFlg );
2408 }
2409
2410 if ( HasWriterListeners() )
2411 { // send this before messing with hints, which will send RES_UPDATE_ATTR
2412 auto aInsHint = sw::MakeInsertText(*this, aPos, nLen);
2413 CallSwClientNotify(aInsHint);
2414 }
2415
2416 if ( HasHints() )
2417 {
2418 m_pSwpHints->SortIfNeedBe();
2419 bool const bHadHints(!m_pSwpHints->CanBeDeleted());
2420 bool bMergePortionsNeeded(false);
2421 for ( size_t i = 0; i < m_pSwpHints->Count() &&
2422 rIdx >= m_pSwpHints->GetWithoutResorting(i)->GetStart(); ++i )
2423 {
2424 SwTextAttr * const pHt = m_pSwpHints->GetWithoutResorting( i );
2425 const sal_Int32 * const pEndIdx = pHt->GetEnd();
2426 if( !pEndIdx )
2427 continue;
2428
2429 if( rIdx == *pEndIdx )
2430 {
2431 if ( (nMode & SwInsertFlags::NOHINTEXPAND) ||
2433 && pHt->DontExpand()) )
2434 {
2435 m_pSwpHints->DeleteAtPos(i);
2436 // on empty attributes also adjust Start
2437 if( rIdx == pHt->GetStart() )
2438 pHt->SetStart( pHt->GetStart() - nLen );
2439 pHt->SetEnd(*pEndIdx - nLen);
2440 // could be that pHt has IsFormatIgnoreEnd set, and it's
2441 // not a RSID-only hint - now we have the inserted text
2442 // between pHt and its continuation... which we don't know.
2443 // punt the job to MergePortions below.
2444 if (pHt->IsFormatIgnoreEnd())
2445 {
2446 bMergePortionsNeeded = true;
2447 }
2449 }
2450 // empty hints at insert position?
2451 else if ( (nMode & SwInsertFlags::EMPTYEXPAND)
2452 && (*pEndIdx == pHt->GetStart()) )
2453 {
2454 m_pSwpHints->DeleteAtPos(i);
2455 pHt->SetStart( pHt->GetStart() - nLen );
2456 const size_t nCurrentLen = m_pSwpHints->Count();
2457 InsertHint( pHt/* AUTOSTYLES:, SetAttrMode::NOHINTADJUST*/ );
2458 if ( nCurrentLen > m_pSwpHints->Count() && i )
2459 {
2460 --i;
2461 }
2462 continue;
2463 }
2464 else
2465 {
2466 continue;
2467 }
2468 }
2469 if ( !(nMode & SwInsertFlags::NOHINTEXPAND) &&
2470 rIdx == nLen && pHt->GetStart() == rIdx.GetIndex() &&
2471 !pHt->IsDontExpandStartAttr() )
2472 {
2473 // no field, at paragraph start, HintExpand
2474 m_pSwpHints->DeleteAtPos(i);
2475 pHt->SetStart( pHt->GetStart() - nLen );
2476 // no effect on format ignore flags here (para start)
2478 }
2479 }
2480 if (bMergePortionsNeeded)
2481 {
2482 m_pSwpHints->MergePortions(*this);
2483 }
2484 SAL_WARN_IF(bHadHints && m_pSwpHints->CanBeDeleted(), "sw.core",
2485 "SwTextNode::InsertText: unexpected loss of hints");
2486 }
2487
2488 // By inserting a character, the hidden flags
2489 // at the TextNode can become invalid:
2491
2492 CHECK_SWPHINTS(this);
2493 return sInserted;
2494}
2495
2497 const SwContentIndex & rStart, const sal_Int32 nLen )
2498{
2499 assert(pDest); // Cut requires a destination
2500 SwContentIndex aDestStt(pDest, pDest->GetText().getLength());
2501 CutImpl( pDest, aDestStt, rStart, nLen, false );
2502}
2503
2504void SwTextNode::CutImpl( SwTextNode * const pDest, const SwContentIndex & rDestStart,
2505 const SwContentIndex & rStart, sal_Int32 nLen, const bool bUpdate )
2506{
2507 assert(pDest); // Cut requires a destination
2508
2509 assert(&GetDoc() == &pDest->GetDoc()); // must be same document
2510
2511 assert(pDest != this); // destination must be different node
2512
2513 assert(rDestStart.GetContentNode() == pDest);
2514 assert(rStart.GetContentNode() == this);
2515
2516 if( !nLen )
2517 {
2518 // if no length is given, copy attributes at position rStart
2519 CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
2520 return;
2521 }
2522
2523 sal_Int32 nTextStartIdx = rStart.GetIndex();
2524 sal_Int32 nDestStart = rDestStart.GetIndex(); // remember old Pos
2525 const sal_Int32 nInitSize = pDest->m_Text.getLength();
2526
2527 if (pDest->GetSpaceLeft() < nLen)
2528 { // FIXME: could only happen when called from SwRangeRedline::Show.
2529 // unfortunately can't really do anything here to handle that...
2530 abort();
2531 }
2532 pDest->m_Text = pDest->m_Text.replaceAt(nDestStart, 0,
2533 m_Text.subView(nTextStartIdx, nLen));
2534 OUString const newText = m_Text.replaceAt(nTextStartIdx, nLen, u"");
2535 nLen = pDest->m_Text.getLength() - nInitSize; // update w/ current size!
2536 if (!nLen) // String didn't grow?
2537 return;
2538
2539 if (bUpdate)
2540 {
2541 // Update all SwContentIndex
2542 pDest->Update(rDestStart, nLen, UpdateMode::Default);
2543 }
2544
2545 CHECK_SWPHINTS(pDest);
2546
2547 const sal_Int32 nEnd = rStart.GetIndex() + nLen;
2548 bool const bUndoNodes =
2549 GetDoc().GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
2550
2551 // copy hard attributes on whole paragraph
2552 if (HasSwAttrSet())
2553 {
2554 bool hasSwAttrSet = pDest->HasSwAttrSet();
2555 if (hasSwAttrSet)
2556 {
2557 // if we have our own property set it doesn't mean
2558 // that this set defines any style different to Standard one.
2559 hasSwAttrSet = false;
2560
2561 // so, let's check deeper if property set has defined any property
2562 if (pDest->GetpSwAttrSet())
2563 {
2564 // check all items in the property set
2565 SfxItemIter aIter( *pDest->GetpSwAttrSet() );
2566 const SfxPoolItem* pItem = aIter.GetCurItem();
2567 do
2568 {
2569 // check current item
2570 const sal_uInt16 nWhich = IsInvalidItem( pItem )
2571 ? pDest->GetpSwAttrSet()->GetWhichByPos( aIter.GetCurPos() )
2572 : pItem->Which();
2573 if( RES_FRMATR_STYLE_NAME != nWhich &&
2575 RES_PAGEDESC != nWhich &&
2576 RES_BREAK != nWhich &&
2577 SfxItemState::SET == pDest->GetpSwAttrSet()->GetItemState( nWhich, false ) )
2578 {
2579 // check if parent value (original value in style) has the same value as in [pItem]
2580 const SfxPoolItem& rParentItem = pDest->GetpSwAttrSet()->GetParent()->Get( nWhich, true );
2581
2582 hasSwAttrSet = (rParentItem != *pItem);
2583
2584 // property set is not empty => no need to make anymore checks
2585 if (hasSwAttrSet)
2586 break;
2587 }
2588
2589 // let's check next item
2590 pItem = aIter.NextItem();
2591 } while (pItem);
2592 }
2593 }
2594
2595 // all or just the Char attributes?
2596 if( nInitSize || hasSwAttrSet ||
2597 nLen != pDest->GetText().getLength())
2598 {
2603 aCharSet( pDest->GetDoc().GetAttrPool() );
2604 aCharSet.Put( *GetpSwAttrSet() );
2605 if( aCharSet.Count() )
2606 pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
2607 }
2608 else
2609 {
2610 // Copy all attrs except RES_PARATR_LIST_LEVEL: it was initialized before
2611 // and current SwTextNode can contain not suitable for pDest value
2614 aCharSet(pDest->GetDoc().GetAttrPool());
2615 aCharSet.Put(*GetpSwAttrSet());
2616 if (aCharSet.Count())
2617 pDest->SetAttr(aCharSet, nDestStart, nDestStart + nLen);
2618 }
2619 }
2620
2621 // notify frames - before moving hints, because footnotes
2622 // want to find their anchor text frame in the follow chain
2623 // (also ignore fieldmarks, the caller will recreate frames)
2624 const sw::InsertText aInsHint(nDestStart, nLen, false, false);
2625 pDest->HandleNonLegacyHint(aInsHint);
2626 const sw::MoveText aMoveHint(pDest, nDestStart, nTextStartIdx, nLen);
2627 CallSwClientNotify(aMoveHint);
2628 const sw::DeleteText aDelText(nTextStartIdx, nLen);
2629 HandleNonLegacyHint(aDelText);
2630
2631 // 2. move attributes
2632 // Iterate over attribute array until the start of the attribute
2633 // is behind the moved range
2634 bool bMergePortionsNeeded(false);
2635 size_t nAttrCnt = 0;
2636 while (m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()))
2637 {
2638 SwTextAttr * const pHt = m_pSwpHints->Get(nAttrCnt);
2639 const sal_Int32 nAttrStartIdx = pHt->GetStart();
2640 if ( nAttrStartIdx >= nEnd )
2641 break;
2642 const sal_Int32 * const pEndIdx = pHt->GetEnd();
2643 const sal_uInt16 nWhich = pHt->Which();
2644 SwTextAttr *pNewHt = nullptr;
2645
2646 // if the hint has a dummy character, then it must not be split!
2647 if(nAttrStartIdx < nTextStartIdx)
2648 {
2649 // start is before the range
2650 if (!pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
2651 || bUndoNodes ) && pEndIdx && *pEndIdx > nTextStartIdx)
2652 {
2653 // attribute with extent and end of attribute is in the range
2654 pNewHt = MakeTextAttr( pDest->GetDoc(), pHt->GetAttr(),
2655 nDestStart,
2656 nDestStart + (
2657 *pEndIdx > nEnd
2658 ? nLen
2659 : *pEndIdx - nTextStartIdx ) );
2660 }
2661 }
2662 else
2663 {
2664 // start is inside the range
2665 if (!pEndIdx || *pEndIdx < nEnd ||
2666 (!bUndoNodes && RES_TXTATR_REFMARK == nWhich)
2667 || pHt->HasDummyChar() )
2668 {
2669 // do not delete note and later add it -> sidebar flickering
2670 if (GetDoc().GetDocShell())
2671 {
2672 GetDoc().GetDocShell()->Broadcast( SfxHint(SfxHintId::SwSplitNodeOperation));
2673 }
2674 // move attribute
2675 m_pSwpHints->Delete( pHt );
2676 // reset start/end indexes
2677 if (pHt->IsFormatIgnoreStart() || pHt->IsFormatIgnoreEnd())
2678 {
2679 bMergePortionsNeeded = true;
2680 }
2681 pHt->SetStart(nDestStart + (nAttrStartIdx - nTextStartIdx));
2682 if (pEndIdx)
2683 {
2684 pHt->SetEnd( nDestStart + (
2685 *pEndIdx > nEnd
2686 ? nLen
2687 : *pEndIdx - nTextStartIdx ) );
2688 }
2689 pDest->InsertHint( pHt,
2692 if (GetDoc().GetDocShell())
2693 {
2694 GetDoc().GetDocShell()->Broadcast( SfxHint(SfxHintId::SwSplitNodeOperation));
2695 }
2696 continue; // iterate while loop, no ++ !
2697 }
2698 // the end is behind the range
2699 else if (RES_TXTATR_REFMARK != nWhich || bUndoNodes)
2700 {
2701 pNewHt = MakeTextAttr( GetDoc(), pHt->GetAttr(),
2702 nDestStart + (nAttrStartIdx - nTextStartIdx),
2703 nDestStart + (*pEndIdx > nEnd
2704 ? nLen
2705 : *pEndIdx - nTextStartIdx));
2706 }
2707 }
2708 if (pNewHt)
2709 {
2710 const bool bSuccess( pDest->InsertHint( pNewHt,
2714 if (bSuccess)
2715 {
2716 lcl_CopyHint( nWhich, pHt, pNewHt, nullptr, pDest );
2717 }
2718 }
2719 ++nAttrCnt;
2720 }
2721 // If there are still empty attributes around, they have a higher priority
2722 // than any attributes that become empty due to the move.
2723 // So temporarily remove them and Update the array, then re-insert the
2724 // removed ones so they overwrite the others.
2725 if (m_pSwpHints && nAttrCnt < m_pSwpHints->Count())
2726 {
2727 SwpHts aArr;
2728 while (nAttrCnt < m_pSwpHints->Count())
2729 {
2730 SwTextAttr * const pHt = m_pSwpHints->Get(nAttrCnt);
2731 if (nEnd != pHt->GetStart())
2732 break;
2733 const sal_Int32 * const pEndIdx = pHt->GetEnd();
2734 if (pEndIdx && *pEndIdx == nEnd)
2735 {
2736 aArr.push_back( pHt );
2737 m_pSwpHints->Delete( pHt );
2738 }
2739 else
2740 {
2741 ++nAttrCnt;
2742 }
2743 }
2744 Update(rStart, nLen, UpdateMode::Negative|UpdateMode::Delete);
2745
2746 for (SwTextAttr* pHt : aArr)
2747 {
2748 pHt->SetStart( rStart.GetIndex() );
2749 pHt->SetEnd( rStart.GetIndex() );
2750 InsertHint( pHt );
2751 }
2752 }
2753 else
2754 {
2755 Update(rStart, nLen, UpdateMode::Negative|UpdateMode::Delete);
2756 }
2757
2758 // set after moving hints
2759 m_Text = newText;
2760
2761 if (bMergePortionsNeeded)
2762 {
2763 m_pSwpHints->MergePortions(*this);
2764 }
2765
2766 CHECK_SWPHINTS(this);
2767
2769}
2770
2771void SwTextNode::EraseText(const SwPosition &rIdx, const sal_Int32 nCount,
2772 const SwInsertFlags nMode )
2773{
2774 EraseText(rIdx.nContent, nCount, nMode);
2775}
2776
2777void SwTextNode::EraseText(const SwContentIndex &rIdx, const sal_Int32 nCount,
2778 const SwInsertFlags nMode )
2779{
2780 assert(rIdx.GetContentNode() == this);
2781 assert(rIdx <= m_Text.getLength()); // invalid index
2782
2783 const sal_Int32 nStartIdx = rIdx.GetIndex();
2784 const sal_Int32 nCnt = (nCount==SAL_MAX_INT32)
2785 ? m_Text.getLength() - nStartIdx : nCount;
2786 const sal_Int32 nEndIdx = nStartIdx + nCnt;
2787 if (nEndIdx <= m_Text.getLength())
2788 m_Text = m_Text.replaceAt(nStartIdx, nCnt, u"");
2789
2790 // GCAttr(); don't remove all empty ones, just the ones that are in the
2791 // range but not at the end of the range.
2792
2793 for ( size_t i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2794 {
2795 SwTextAttr *pHt = m_pSwpHints->Get(i);
2796
2797 const sal_Int32 nHintStart = pHt->GetStart();
2798
2799 if ( nHintStart < nStartIdx )
2800 continue;
2801
2802 if ( nHintStart > nEndIdx )
2803 break; // hints are sorted by end, so break here
2804
2805 const sal_Int32* pHtEndIdx = pHt->GetEnd();
2806 const sal_uInt16 nWhich = pHt->Which();
2807
2808 if( !pHtEndIdx )
2809 {
2810 // attribute with neither end nor CH_TXTATR?
2811 assert(pHt->HasDummyChar());
2812 if (isTXTATR(nWhich) && (nHintStart < nEndIdx))
2813 {
2814 m_pSwpHints->DeleteAtPos(i);
2815 DestroyAttr( pHt );
2816 --i;
2817 }
2818 continue;
2819 }
2820
2821 assert(!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
2822 && pHt->HasDummyChar() )
2823 // next line: deleting exactly dummy char: DeleteAttributes
2824 || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)));
2825 // "ERROR: deleting left-overlapped attribute with CH_TXTATR");
2826
2827 // Delete the hint if:
2828 // 1. The hint ends before the deletion end position or
2829 // 2. The hint ends at the deletion end position and
2830 // we are not in empty expand mode and
2831 // the hint is a [toxmark|refmark|ruby|inputfield] text attribute
2832 // 3. deleting exactly the dummy char of an hint with end and dummy
2833 // char deletes the hint
2834 if ( (*pHtEndIdx < nEndIdx)
2835 || ( (*pHtEndIdx == nEndIdx) &&
2836 !(SwInsertFlags::EMPTYEXPAND & nMode) &&
2837 ( (RES_TXTATR_TOXMARK == nWhich) ||
2838 (RES_TXTATR_REFMARK == nWhich) ||
2839 (RES_TXTATR_CJK_RUBY == nWhich) ||
2840 (RES_TXTATR_INPUTFIELD == nWhich) ) )
2841 || ( (nHintStart < nEndIdx) &&
2842 pHt->HasDummyChar() )
2843 )
2844 {
2845 m_pSwpHints->DeleteAtPos(i);
2846 DestroyAttr( pHt );
2847 --i;
2848 }
2849 }
2850
2851 OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2852
2854
2855 Update(rIdx, nCnt, UpdateMode::Negative);
2856
2857 if(1 == nCnt)
2858 {
2859 const auto aHint = sw::DeleteChar(nStartIdx);
2860 CallSwClientNotify(aHint);
2861 } else {
2862 const auto aHint = sw::DeleteText(nStartIdx, nCnt);
2863 CallSwClientNotify(aHint);
2864 }
2865
2866 OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2867
2868 // By deleting a character, the hidden flags
2869 // at the TextNode can become invalid:
2871
2872 CHECK_SWPHINTS(this);
2873}
2874
2876{
2877 if ( !HasHints() )
2878 return;
2879
2880 bool bChanged = false;
2881 sal_Int32 nMin = m_Text.getLength();
2882 sal_Int32 nMax = 0;
2883 const bool bAll = nMin != 0; // on empty paragraphs only remove INetFormats
2884
2885 for ( size_t i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2886 {
2887 SwTextAttr * const pHt = m_pSwpHints->Get(i);
2888
2889 // if end and start are equal, delete it
2890 const sal_Int32 * const pEndIdx = pHt->GetEnd();
2891 if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == pHt->GetStart())
2892 && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
2893 {
2894 bChanged = true;
2895 nMin = std::min( nMin, pHt->GetStart() );
2896 nMax = std::max( nMax, *pHt->GetEnd() );
2897 DestroyAttr( m_pSwpHints->Cut(i) );
2898 --i;
2899 }
2900 else
2901 {
2902 pHt->SetDontExpand( false );
2903 }
2904 }
2906
2907 if(bChanged)
2908 {
2909 // textframes react to aHint, others to aNew
2910 SwUpdateAttr aHint(
2911 nMin,
2912 nMax,
2913 0);
2914
2915 CallSwClientNotify(sw::LegacyModifyHint(nullptr, &aHint));
2916 SwFormatChg aNew( GetTextColl() );
2917 CallSwClientNotify(sw::LegacyModifyHint(nullptr, &aNew));
2918 }
2919}
2920
2921SwNumRule* SwTextNode::GetNumRule(bool bInParent) const
2922{
2923 SwNumRule* pRet = nullptr;
2924
2925 const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
2926 bool bNoNumRule = false;
2927 if ( pItem )
2928 {
2929 OUString sNumRuleName =
2930 static_cast<const SwNumRuleItem *>(pItem)->GetValue();
2931 if (!sNumRuleName.isEmpty())
2932 {
2933 pRet = GetDoc().FindNumRulePtr( sNumRuleName );
2934 }
2935 else // numbering is turned off
2936 bNoNumRule = true;
2937 }
2938
2939 if ( !bNoNumRule )
2940 {
2941 if ( pRet && pRet == GetDoc().GetOutlineNumRule() &&
2942 ( !HasSwAttrSet() ||
2943 SfxItemState::SET !=
2944 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, false ) ) )
2945 {
2946 SwTextFormatColl* pColl = GetTextColl();
2947 if ( pColl )
2948 {
2949 const SwNumRuleItem& rDirectItem = pColl->GetNumRule( false );
2950 if ( rDirectItem.GetValue().isEmpty() )
2951 {
2952 pRet = nullptr;
2953 }
2954 }
2955 }
2956 }
2957
2958 return pRet;
2959}
2960
2962{
2963 if ( IsInList() )
2964 {
2965 SwNumRule* pNumRule = GetNumRule();
2966 if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
2967 {
2968 mpNodeNum->ChangeNumRule( *pNumRule );
2970 {
2971 mpNodeNumRLHidden->ChangeNumRule(*pNumRule);
2972 }
2973 }
2974 }
2975
2976 // Sending "noop" modify in order to cause invalidations of registered
2977 // <SwTextFrame> instances to get the list style change respectively the change
2978 // in the list tree reflected in the layout.
2979 // Important note:
2980 {
2982 CallSwClientNotify(sw::LegacyModifyHint(&rLR, &rLR));
2983 }
2984
2985 SetWordCountDirty( true );
2986}
2987
2988// -> #i27615#
2989bool SwTextNode::IsNumbered(SwRootFrame const*const pLayout) const
2990{
2991 SwNumRule* pRule = GetNum(pLayout) ? GetNum(pLayout)->GetNumRule() : nullptr;
2992 return pRule && IsCountedInList();
2993}
2994
2996{
2997 bool bResult = false;
2998
2999 if ( IsInList() )
3000 {
3001 bResult =
3003 }
3004
3005 return bResult;
3006}
3007// <- #i27615#
3008
3010 bool bChgFollow )
3011{
3012 // ignore hard PageBreak/PageDesc/ColumnBreak from Auto-Set
3013 std::optional<SwAttrSet> oNewAttrSet;
3014 // #i75353#
3015 bool bClearHardSetNumRuleWhenFormatCollChanges( false );
3016 if( HasSwAttrSet() )
3017 {
3018 oNewAttrSet.emplace( *GetpSwAttrSet() );
3019 const SfxItemSet* pTmpSet = GetpSwAttrSet();
3020
3021 if (bNext) // successor doesn't inherit breaks!
3022 pTmpSet = &*oNewAttrSet;
3023
3024 // !bNext: remove PageBreaks/PageDesc/ColBreak from this
3025 bool bRemoveFromCache = false;
3026 std::vector<sal_uInt16> aClearWhichIds;
3027 if ( bNext )
3028 bRemoveFromCache = ( 0 != oNewAttrSet->ClearItem( RES_PAGEDESC ) );
3029 else
3030 aClearWhichIds.push_back( RES_PAGEDESC );
3031
3032 if( SfxItemState::SET == pTmpSet->GetItemState( RES_BREAK, false ) )
3033 {
3034 if ( bNext )
3035 oNewAttrSet->ClearItem( RES_BREAK );
3036 else
3037 aClearWhichIds.push_back( RES_BREAK );
3038 bRemoveFromCache = true;
3039 }
3040 if( SfxItemState::SET == pTmpSet->GetItemState( RES_KEEP, false ) )
3041 {
3042 if ( bNext )
3043 oNewAttrSet->ClearItem( RES_KEEP );
3044 else
3045 aClearWhichIds.push_back( RES_KEEP );
3046 bRemoveFromCache = true;
3047 }
3048 if( SfxItemState::SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, false ) )
3049 {
3050 if ( bNext )
3051 oNewAttrSet->ClearItem( RES_PARATR_SPLIT );
3052 else
3053 aClearWhichIds.push_back( RES_PARATR_SPLIT );
3054 bRemoveFromCache = true;
3055 }
3056 if(SfxItemState::SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, false))
3057 {
3058 SwNumRule * pRule = GetNumRule();
3059
3060 if (pRule && IsOutline())
3061 {
3062 if ( bNext )
3063 oNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
3064 else
3065 {
3066 // #i75353#
3067 // No clear of hard set numbering rule at an outline paragraph at this point.
3068 // Only if the paragraph style changes - see below.
3069 bClearHardSetNumRuleWhenFormatCollChanges = true;
3070 }
3071 bRemoveFromCache = true;
3072 }
3073 }
3074
3075 if ( !aClearWhichIds.empty() )
3076 bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );
3077
3078 if( !bNext && bRemoveFromCache )
3079 {
3081 }
3082 }
3083 SwNodes& rNds = GetNodes();
3084
3085 SwTextFormatColl* pColl = GetTextColl();
3086
3087 SwTextNode *pNode = new SwTextNode( rPosNd, pColl, oNewAttrSet ? &*oNewAttrSet : nullptr );
3088
3089 oNewAttrSet.reset();
3090
3091 const SwNumRule* pRule = GetNumRule();
3092 if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() )
3093 {
3094 // #i55459#
3095 // - correction: parameter <bNext> has to be checked, as it was in the
3096 // previous implementation.
3097 if ( !bNext && !IsCountedInList() )
3098 SetCountedInList(true);
3099 }
3100
3101 // In case the numbering caused a style from the pool to be assigned to
3102 // the new node, don't overwrite that here!
3103 if( pColl != pNode->GetTextColl() ||
3104 ( bChgFollow && pColl != GetTextColl() ))
3105 return pNode; // that ought to be enough?
3106
3107 pNode->ChgTextCollUpdateNum( nullptr, pColl ); // for numbering/outline
3108 if( bNext || !bChgFollow )
3109 return pNode;
3110
3111 SwTextFormatColl *pNextColl = &pColl->GetNextTextFormatColl();
3112 // i#101870 perform action on different paragraph styles before applying
3113 // the new paragraph style
3114 if (pNextColl != pColl)
3115 {
3116 // #i75353#
3117 if ( bClearHardSetNumRuleWhenFormatCollChanges )
3118 {
3119 if ( ClearItemsFromAttrSet( { RES_PARATR_NUMRULE } ) != 0 )
3120 {
3122 }
3123 }
3124 }
3125 ChgFormatColl( pNextColl );
3126
3127 return pNode;
3128}
3129
3131{
3132 // position behind which it will be inserted
3133 SwTextNode* pNew = MakeNewTextNode( *rPos.GetNodes()[rPos.GetNodeIndex() + 1] );
3134
3135 // reset list attributes at appended text node
3139 if ( pNew->GetNumRule() == nullptr )
3140 {
3143 }
3144
3145 if (!IsInList() && GetNumRule() && !GetListId().isEmpty())
3146 {
3147 AddToList();
3148 }
3149
3150 if( HasWriterListeners() )
3152 return pNew;
3153}
3154
3156 const sal_Int32 nIndex,
3157 const sal_uInt16 nWhich ) const
3158{
3159 assert(nWhich >= RES_TXTATR_BEGIN && nWhich <= RES_TXTATR_END);
3160 if ( HasHints() )
3161 {
3162 for ( size_t i = 0; i < m_pSwpHints->Count(); ++i )
3163 {
3164 SwTextAttr * const pHint = m_pSwpHints->Get(i);
3165 const sal_Int32 nStartPos = pHint->GetStart();
3166 if ( nIndex < nStartPos )
3167 {
3168 return nullptr;
3169 }
3170 if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
3171 {
3172 return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
3173 ? pHint : nullptr;
3174 }
3175 }
3176 }
3177 return nullptr;
3178}
3179
3180SwTextAttr* SwTextNode::GetTextAttrForEndCharAt(sal_Int32 nIndex, sal_uInt16 nWhich) const
3181{
3183 if (!pAttr)
3184 {
3185 return nullptr;
3186 }
3187
3188 if (!pAttr->End())
3189 {
3190 return nullptr;
3191 }
3192
3193 // The start-end range covers the end dummy character.
3194 if (*pAttr->End() - 1 != nIndex)
3195 {
3196 return nullptr;
3197 }
3198
3199 return pAttr;
3200}
3201
3202namespace
3203{
3204
3205sal_uInt16 lcl_BoundListLevel(const int nActualLevel)
3206{
3207 return o3tl::narrowing<sal_uInt16>( std::clamp( nActualLevel, 0, MAXLEVEL-1 ) );
3208}
3209
3210}
3211
3212// -> #i29560#
3213bool SwTextNode::HasNumber(SwRootFrame const*const pLayout) const
3214{
3215 bool bResult = false;
3216
3217 const SwNumRule *const pRule = GetNum(pLayout) ? GetNum(pLayout)->GetNumRule() : nullptr;
3218 if ( pRule )
3219 {
3220 const SwNumFormat& aFormat(pRule->Get(lcl_BoundListLevel(GetActualListLevel())));
3221
3222 // #i40041#
3223 bResult = aFormat.IsEnumeration();
3224 }
3225
3226 return bResult;
3227}
3228
3230{
3231 bool bResult = false;
3232
3233 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
3234 if ( pRule )
3235 {
3236 const SwNumFormat& aFormat(pRule->Get(lcl_BoundListLevel(GetActualListLevel())));
3237
3238 bResult = aFormat.IsItemize();
3239 }
3240
3241 return bResult;
3242}
3243// <- #i29560#
3244
3245// #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
3246//i53420 added max outline parameter
3247OUString SwTextNode::GetNumString( const bool _bInclPrefixAndSuffixStrings,
3248 const unsigned int _nRestrictToThisLevel,
3249 SwRootFrame const*const pLayout, SwListRedlineType eRedline) const
3250{
3251 if (GetDoc().IsClipBoard() && m_oNumStringCache)
3252 {
3253 // #i111677# do not expand number strings in clipboard documents
3254 return *m_oNumStringCache;
3255 }
3256 const SwNumRule* pRule = GetNum(pLayout, eRedline) ? GetNum(pLayout, eRedline)->GetNumRule() : nullptr;
3257 if ( pRule &&
3258 IsCountedInList() )
3259 {
3260 SvxNumberType const& rNumberType(
3261 pRule->Get( lcl_BoundListLevel(GetActualListLevel(eRedline)) ) );
3262 if (rNumberType.IsTextFormat() ||
3263
3264 (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType()))
3265 {
3266 return pRule->MakeNumString( GetNum(pLayout, eRedline)->GetNumberVector(),
3267 _bInclPrefixAndSuffixStrings,
3268 _nRestrictToThisLevel,
3269 nullptr,
3270 GetLang(0));
3271 }
3272 }
3273
3274 return OUString();
3275}
3276
3278{
3279 tools::Long nRet = 0;
3280 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
3281 if( pRule )
3282 {
3283 const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
3284
3286 {
3287 nRet = rFormat.GetAbsLSpace();
3288
3289 if( !bTextLeft )
3290 {
3291 if( 0 > rFormat.GetFirstLineOffset() &&
3292 nRet > -rFormat.GetFirstLineOffset() )
3293 nRet = nRet + rFormat.GetFirstLineOffset();
3294 else
3295 nRet = 0;
3296 }
3297
3298 if( pRule->IsAbsSpaces() )
3299 {
3300 SvxFirstLineIndentItem const& rFirst(GetSwAttrSet().GetFirstLineIndent());
3301 nRet = nRet - GetSwAttrSet().GetTextLeftMargin().GetLeft(rFirst);
3302 }
3303 }
3305 {
3307 // note: the result is *always* added to either the left-margin
3308 // or the text-left-margin of the node itself by the caller.
3309 // so first, subtract what the caller has computed anyway,
3310 // and then add the value according to combination of
3311 // list/paragraph items. (this is rather inelegant)
3312 SvxFirstLineIndentItem firstLine(GetSwAttrSet().GetFirstLineIndent());
3313 SvxTextLeftMarginItem leftMargin(GetSwAttrSet().GetTextLeftMargin());
3314 nRet = bTextLeft
3315 ? - leftMargin.GetTextLeft()
3316 : - leftMargin.GetLeft(firstLine);
3318 {
3319 leftMargin.SetTextLeft(rFormat.GetIndentAt());
3320 }
3321 if (indents & ::sw::ListLevelIndents::FirstLine)
3322 {
3323 firstLine.SetTextFirstLineOffset(rFormat.GetFirstLineIndent());
3324 }
3325 nRet += bTextLeft
3326 ? leftMargin.GetTextLeft()
3327 : leftMargin.GetLeft(firstLine);
3328 }
3329 }
3330
3331 return nRet;
3332}
3333
3334bool SwTextNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
3335{
3336 // #i95907#
3337 rFLOffset = 0;
3338
3339 // #i51089#
3340 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
3341 if ( pRule )
3342 {
3343 if ( IsCountedInList() )
3344 {
3345 const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
3347 {
3348 rFLOffset = rFormat.GetFirstLineOffset(); //TODO: overflow
3349
3351 {
3352 SvxFirstLineIndentItem const aItem(GetSwAttrSet().GetFirstLineIndent());
3353 rFLOffset = rFLOffset + aItem.GetTextFirstLineOffset();
3354 }
3355 }
3357 {
3358 if (AreListLevelIndentsApplicable() & ::sw::ListLevelIndents::FirstLine)
3359 {
3360 rFLOffset = rFormat.GetFirstLineIndent();
3361 }
3363 {
3364 SvxFirstLineIndentItem const aItem(GetSwAttrSet().GetFirstLineIndent());
3365 rFLOffset = aItem.GetTextFirstLineOffset();
3366 }
3367 }
3368 }
3369
3370 return true;
3371 }
3372
3374 return false;
3375}
3376
3378{
3379 SwTwips nAdditionalIndent = 0;
3380
3381 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
3382 if ( pRule )
3383 {
3384 const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
3386 {
3387 SvxFirstLineIndentItem const& rFirst(GetSwAttrSet().GetFirstLineIndent());
3388 nAdditionalIndent = GetSwAttrSet().GetTextLeftMargin().GetLeft(rFirst);
3389
3391 {
3392 nAdditionalIndent = nAdditionalIndent -
3394 }
3395 }
3397 {
3398 // note: there was an apparent bug here, list GetIndentAt()
3399 // was interpreted as left-margin not text-left-margin unlike every
3400 // other use of it.
3402 SvxFirstLineIndentItem const& rFirst(
3403 indents & ::sw::ListLevelIndents::FirstLine
3405 : GetSwAttrSet().GetFirstLineIndent());
3406 SvxTextLeftMarginItem const& rLeft(
3409 : GetSwAttrSet().GetTextLeftMargin());
3410 nAdditionalIndent = rLeft.GetLeft(rFirst);
3411 if (!(indents & ::sw::ListLevelIndents::FirstLine))
3412 {
3414 {
3415 nAdditionalIndent = nAdditionalIndent - rFirst.GetTextFirstLineOffset();
3416 }
3417 }
3418 }
3419 }
3420 else
3421 {
3422 SvxFirstLineIndentItem const& rFirst(GetSwAttrSet().GetFirstLineIndent());
3423 nAdditionalIndent = GetSwAttrSet().GetTextLeftMargin().GetLeft(rFirst);
3424 }
3425
3426 return nAdditionalIndent;
3427}
3428
3429// #i91133#
3431{
3432 tools::Long nLeftMarginForTabCalc = 0;
3433
3434 bool bLeftMarginForTabCalcSetToListLevelIndent( false );
3435 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
3436 if( pRule )
3437 {
3438 const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
3440 {
3442 {
3443 nLeftMarginForTabCalc = rFormat.GetIndentAt();
3444 bLeftMarginForTabCalcSetToListLevelIndent = true;
3445 }
3446 }
3447 }
3448 if ( !bLeftMarginForTabCalcSetToListLevelIndent )
3449 {
3450 nLeftMarginForTabCalc = GetSwAttrSet().GetTextLeftMargin().GetTextLeft();
3451 }
3452
3453 return nLeftMarginForTabCalc;
3454}
3455
3456static void Replace0xFF(
3457 SwTextNode const& rNode,
3458 OUStringBuffer & rText,
3459 sal_Int32 & rTextStt,
3460 sal_Int32 nEndPos )
3461{
3462 if (!rNode.GetpSwpHints())
3463 return;
3464
3466 for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter, cSrchChr = CH_TXTATR_INWORD )
3467 {
3468 sal_Int32 nPos = rText.indexOf(cSrchChr);
3469 while (-1 != nPos && nPos < nEndPos)
3470 {
3471 const SwTextAttr* const pAttr =
3472 rNode.GetTextAttrForCharAt(rTextStt + nPos);
3473 if( pAttr )
3474 {
3475 switch( pAttr->Which() )
3476 {
3477 case RES_TXTATR_FIELD:
3479 rText.remove(nPos, 1);
3480 ++rTextStt;
3481 break;
3482
3483 case RES_TXTATR_FTN:
3484 rText.remove(nPos, 1);
3485 ++rTextStt;
3486 break;
3487
3488 default:
3489 rText.remove(nPos, 1);
3490 ++rTextStt;
3491 }
3492 }
3493 else
3494 {
3495 ++nPos;
3496 ++nEndPos;
3497 }
3498 nPos = rText.indexOf(cSrchChr, nPos);
3499 }
3500 }
3501}
3502
3503// Expand fields
3504// #i83479# - handling of new parameters
3505OUString SwTextNode::GetExpandText(SwRootFrame const*const pLayout,
3506 const sal_Int32 nIdx,
3507 const sal_Int32 nLen,
3508 const bool bWithNum,
3509 const bool bAddSpaceAfterListLabelStr,
3510 const bool bWithSpacesForLevel,
3511 const ExpandMode eAdditionalMode) const
3512
3513{
3514 ExpandMode eMode = ExpandMode::ExpandFields | eAdditionalMode;
3515 if (pLayout && pLayout->IsHideRedlines())
3516 {
3518 }
3519
3520 ModelToViewHelper aConversionMap(*this, pLayout, eMode);
3521 const OUString aExpandText = aConversionMap.getViewText();
3522 const sal_Int32 nExpandBegin = aConversionMap.ConvertToViewPosition( nIdx );
3523 sal_Int32 nEnd = nLen == -1 ? GetText().getLength() : nIdx + nLen;
3524 const sal_Int32 nExpandEnd = aConversionMap.ConvertToViewPosition( nEnd );
3525 OUStringBuffer aText(aExpandText.subView(nExpandBegin, nExpandEnd-nExpandBegin));
3526
3527 // remove dummy characters of Input Fields
3531
3532 if( bWithNum )
3533 {
3534 if (!GetNumString(true, MAXLEVEL, pLayout).isEmpty())
3535 {
3536 if ( bAddSpaceAfterListLabelStr )
3537 {
3538 const sal_Unicode aSpace = ' ';
3539 aText.insert(0, aSpace);
3540 }
3541 aText.insert(0, GetNumString(true, MAXLEVEL, pLayout));
3542 }
3543 }
3544
3545 if (bWithSpacesForLevel)
3546 {
3547 const sal_Unicode aSpace = ' ';
3548 for (int nLevel = GetActualListLevel(); nLevel > 0; --nLevel)
3549 {
3550 aText.insert(0, aSpace);
3551 aText.insert(0, aSpace);
3552 }
3553 }
3554
3555 return aText.makeStringAndClear();
3556}
3557
3559 sal_Int32 nIdx, sal_Int32 nLen,
3560 SwRootFrame const*const pLayout, bool bWithNum,
3561 bool bWithFootnote, bool bReplaceTabsWithSpaces ) const
3562{
3563 if( &rDestNd == this )
3564 return false;
3565 assert(!pDestIdx || pDestIdx->GetContentNode() == &rDestNd);
3566
3567 SwContentIndex aDestIdx(&rDestNd, rDestNd.GetText().getLength());
3568 if( pDestIdx )
3569 aDestIdx = *pDestIdx;
3570 const sal_Int32 nDestStt = aDestIdx.GetIndex();
3571
3572 // first, start with the text
3573 OUStringBuffer buf(GetText());
3574 if( bReplaceTabsWithSpaces )
3575 buf.replace('\t', ' ');
3576
3577 // mask hidden characters
3578 const sal_Unicode cChar = CH_TXTATR_BREAKWORD;
3579 SwScriptInfo::MaskHiddenRanges(*this, buf, 0, buf.getLength(), cChar);
3580
3581 buf.remove(0, nIdx);
3582 if (nLen != -1)
3583 {
3584 buf.truncate(nLen);
3585 }
3586 // remove dummy characters of Input Fields
3587 {
3590 }
3591 rDestNd.InsertText(buf.makeStringAndClear(), aDestIdx);
3592 nLen = aDestIdx.GetIndex() - nDestStt;
3593
3594 // set all char attributes with Symbol font
3595 if ( HasHints() )
3596 {
3597 sal_Int32 nInsPos = nDestStt - nIdx;
3598 for ( size_t i = 0; i < m_pSwpHints->Count(); ++i )
3599 {
3600 const SwTextAttr* pHt = m_pSwpHints->Get(i);
3601 const sal_Int32 nAttrStartIdx = pHt->GetStart();
3602 const sal_uInt16 nWhich = pHt->Which();
3603 if (nIdx + nLen <= nAttrStartIdx)
3604 break; // behind end of text
3605
3606 const sal_Int32 *pEndIdx = pHt->End();
3607 if( pEndIdx && *pEndIdx > nIdx &&
3608 ( RES_CHRATR_FONT == nWhich ||
3609 RES_TXTATR_CHARFMT == nWhich ||
3610 RES_TXTATR_AUTOFMT == nWhich ))
3611 {
3612 const SvxFontItem* const pFont =
3614 if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
3615 {
3616 // attribute in area => copy
3617 rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
3618 nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
3619 }
3620 }
3621 else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
3622 {
3623 aDestIdx = nInsPos + nAttrStartIdx;
3624 switch( nWhich )
3625 {
3626 case RES_TXTATR_FIELD:
3628 {
3629 OUString const aExpand(
3630 static_txtattr_cast<SwTextField const*>(pHt)->GetFormatField().GetField()->ExpandField(true, pLayout));
3631 if (!aExpand.isEmpty())
3632 {
3633 ++aDestIdx; // insert behind
3634 OUString const ins(
3635 rDestNd.InsertText( aExpand, aDestIdx));
3636 SAL_INFO_IF(ins.getLength() != aExpand.getLength(),
3637 "sw.core", "GetExpandText lossage");
3638 aDestIdx = nInsPos + nAttrStartIdx;
3639 nInsPos += ins.getLength();
3640 }
3641 rDestNd.EraseText( aDestIdx, 1 );
3642 --nInsPos;
3643 }
3644 break;
3645
3646 case RES_TXTATR_FTN:
3647 {
3648 if ( bWithFootnote )
3649 {
3650 const SwFormatFootnote& rFootnote = pHt->GetFootnote();
3651 OUString sExpand;
3652 auto const number(pLayout && pLayout->IsHideRedlines()
3653 ? rFootnote.GetNumberRLHidden()
3654 : rFootnote.GetNumber());
3655 if( !rFootnote.GetNumStr().isEmpty() )
3656 sExpand = rFootnote.GetNumStr();
3657 else if( rFootnote.IsEndNote() )
3658 sExpand = GetDoc().GetEndNoteInfo().m_aFormat.
3659 GetNumStr(number);
3660 else
3661 sExpand = GetDoc().GetFootnoteInfo().m_aFormat.
3662 GetNumStr(number);
3663 if( !sExpand.isEmpty() )
3664 {
3665 ++aDestIdx; // insert behind
3666 SvxEscapementItem aItem( SvxEscapement::Superscript, RES_CHRATR_ESCAPEMENT );
3667 rDestNd.InsertItem(
3668 aItem,
3669 aDestIdx.GetIndex(),
3670 aDestIdx.GetIndex() );
3671 OUString const ins( rDestNd.InsertText(sExpand, aDestIdx, SwInsertFlags::EMPTYEXPAND));
3672 SAL_INFO_IF(ins.getLength() != sExpand.getLength(),
3673 "sw.core", "GetExpandText lossage");
3674 aDestIdx = nInsPos + nAttrStartIdx;
3675 nInsPos += ins.getLength();
3676 }
3677 }
3678 rDestNd.EraseText( aDestIdx, 1 );
3679 --nInsPos;
3680 }
3681 break;
3682
3683 default:
3684 rDestNd.EraseText( aDestIdx, 1 );
3685 --nInsPos;
3686 }
3687 }
3688 }
3689 }
3690
3691 if( bWithNum )
3692 {
3693 aDestIdx = nDestStt;
3694 rDestNd.InsertText( GetNumString(true, MAXLEVEL, pLayout), aDestIdx );
3695 }
3696
3697 aDestIdx = 0;
3698 sal_Int32 nStartDelete(-1);
3699 while (aDestIdx < rDestNd.GetText().getLength())
3700 {
3701 sal_Unicode const cur(rDestNd.GetText()[aDestIdx.GetIndex()]);
3702 if ( (cChar == cur) // filter substituted hidden text
3703 || (CH_TXT_ATR_FIELDSTART == cur) // filter all fieldmarks
3704 || (CH_TXT_ATR_FIELDSEP == cur)
3705 || (CH_TXT_ATR_FIELDEND == cur)
3706 || (CH_TXT_ATR_FORMELEMENT == cur))
3707 {
3708 if (-1 == nStartDelete)
3709 {
3710 nStartDelete = aDestIdx.GetIndex(); // start deletion range
3711 }
3712 ++aDestIdx;
3713 if (aDestIdx < rDestNd.GetText().getLength())
3714 {
3715 continue;
3716 } // else: end of paragraph => delete, see below
3717 }
3718 else
3719 {
3720 if (-1 == nStartDelete)
3721 {
3722 ++aDestIdx;
3723 continue;
3724 } // else: delete, see below
3725 }
3726 assert(-1 != nStartDelete); // without delete range, would have continued
3727 rDestNd.EraseText(
3728 SwContentIndex(&rDestNd, nStartDelete),
3729 aDestIdx.GetIndex() - nStartDelete);
3730 assert(aDestIdx.GetIndex() == nStartDelete);
3731 nStartDelete = -1; // reset
3732 }
3733
3734 return true;
3735}
3736
3738{
3739 std::vector<sal_Int32> aRedlArr;
3740 const SwDoc& rDoc = GetDoc();
3741 SwRedlineTable::size_type nRedlPos = rDoc.getIDocumentRedlineAccess().GetRedlinePos( *this, RedlineType::Delete );
3742 if( SwRedlineTable::npos != nRedlPos )
3743 {
3744 // some redline-delete object exists for the node
3745 const SwNodeOffset nNdIdx = GetIndex();
3746 for( ; nRedlPos < rDoc.getIDocumentRedlineAccess().GetRedlineTable().size() ; ++nRedlPos )
3747 {
3748 const SwRangeRedline* pTmp = rDoc.getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ];
3749 if( RedlineType::Delete == pTmp->GetType() )
3750 {
3751 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
3752 if( pRStt->GetNodeIndex() < nNdIdx )
3753 {
3754 if( pREnd->GetNodeIndex() > nNdIdx )
3755 // paragraph is fully deleted
3756 return OUString();
3757 else if( pREnd->GetNodeIndex() == nNdIdx )
3758 {
3759 // deleted from 0 to nContent
3760 aRedlArr.push_back( 0 );
3761 aRedlArr.push_back( pREnd->GetContentIndex() );
3762 }
3763 }
3764 else if( pRStt->GetNodeIndex() == nNdIdx )
3765 {
3766 //aRedlArr.Insert( pRStt->GetContentIndex(), aRedlArr.Count() );
3767 aRedlArr.push_back( pRStt->GetContentIndex() );
3768 if( pREnd->GetNodeIndex() == nNdIdx )
3769 aRedlArr.push_back( pREnd->GetContentIndex() );
3770 else
3771 {
3772 aRedlArr.push_back(GetText().getLength());
3773 break; // that was all
3774 }
3775 }
3776 else
3777 break; // that was all
3778 }
3779 }
3780 }
3781
3782 OUStringBuffer aText(GetText());
3783
3784 sal_Int32 nTextStt = 0;
3785 sal_Int32 nIdxEnd = aText.getLength();
3786 for( size_t n = 0; n < aRedlArr.size(); n += 2 )
3787 {
3788 sal_Int32 nStt = aRedlArr[ n ];
3789 sal_Int32 nEnd = aRedlArr[ n+1 ];
3790 if( ( 0 <= nStt && nStt <= nIdxEnd ) ||
3791 ( 0 <= nEnd && nEnd <= nIdxEnd ))
3792 {
3793 if( nStt < 0 ) nStt = 0;
3794 if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
3795 const sal_Int32 nDelCnt = nEnd - nStt;
3796 aText.remove(nStt - nTextStt, nDelCnt);
3797 Replace0xFF(*this, aText, nTextStt, nStt - nTextStt);
3798 nTextStt += nDelCnt;
3799 }
3800 else if( nStt >= nIdxEnd )
3801 break;
3802 }
3803 Replace0xFF(*this, aText, nTextStt, aText.getLength());
3804
3805 return aText.makeStringAndClear();
3806}
3807
3808void SwTextNode::ReplaceText( const SwContentIndex& rStart, const sal_Int32 nDelLen,
3809 const OUString & rStr)
3810{
3811 assert(rStart.GetContentNode() == this);
3812 assert( rStart.GetIndex() < m_Text.getLength() // index out of bounds
3813 && rStart.GetIndex() + nDelLen <= m_Text.getLength());
3814
3815 sal_Int32 const nOverflow(rStr.getLength() - nDelLen - GetSpaceLeft());
3816 SAL_WARN_IF(nOverflow > 0, "sw.core",
3817 "SwTextNode::ReplaceText: node text with insertion > node capacity.");
3818 OUString const sInserted(
3819 (nOverflow > 0) ? rStr.copy(0, rStr.getLength() - nOverflow) : rStr);
3820 if (sInserted.isEmpty() && 0 == nDelLen)
3821 {
3822 return; // nothing to do
3823 }
3824
3825 const sal_Int32 nStartPos = rStart.GetIndex();
3826 sal_Int32 nEndPos = nStartPos + nDelLen;
3827 sal_Int32 nLen = nDelLen;
3828 for( sal_Int32 nPos = nStartPos; nPos < nEndPos; ++nPos )
3829 {
3830 if ((CH_TXTATR_BREAKWORD == m_Text[nPos]) ||
3832 {
3833 SwTextAttr *const pHint = GetTextAttrForCharAt( nPos );
3834 if (pHint)
3835 {
3836 assert(!( pHint->GetEnd() && pHint->HasDummyChar()
3837 && (pHint->GetStart() < nEndPos)
3838 && (*pHint->GetEnd() > nEndPos) ));
3839 // "deleting left-overlapped attribute with CH_TXTATR"
3840 DeleteAttribute( pHint );
3841 --nEndPos;
3842 --nLen;
3843 }
3844 }
3845 }
3846
3847 bool bOldExpFlg = IsIgnoreDontExpand();
3848 SetIgnoreDontExpand( true );
3849
3850 if (nLen && sInserted.getLength())
3851 {
3852 // Replace the 1st char, then delete the rest and insert.
3853 // This way the attributes of the 1st char are expanded!
3854 m_Text = m_Text.replaceAt(nStartPos, 1, sInserted.subView(0, 1));
3855
3856 ++const_cast<SwContentIndex&>(rStart);
3857 m_Text = m_Text.replaceAt(rStart.GetIndex(), nLen - 1, u"");
3858 Update(rStart, nLen - 1, UpdateMode::Negative);
3859
3860 std::u16string_view aTmpText( sInserted.subView(1) );
3861 m_Text = m_Text.replaceAt(rStart.GetIndex(), 0, aTmpText);
3862 Update(rStart, aTmpText.size(), UpdateMode::Replace);
3863 }
3864 else
3865 {
3866 m_Text = m_Text.replaceAt(nStartPos, nLen, u"");
3867 Update(rStart, nLen, UpdateMode::Negative);
3868
3869 m_Text = m_Text.replaceAt(nStartPos, 0, sInserted);
3870 Update(rStart, sInserted.getLength(), UpdateMode::Replace);
3871 }
3872
3873 SetIgnoreDontExpand( bOldExpFlg );
3874 auto aDelHint = sw::DeleteText(nStartPos, nDelLen);
3875 CallSwClientNotify(aDelHint);
3876
3877 if (sInserted.getLength())
3878 {
3879 auto aInsHint = sw::MakeInsertText(*this, nStartPos, sInserted.getLength());
3880 CallSwClientNotify(aInsHint);
3881 }
3882}
3883
3884void SwTextNode::ReplaceText( SwPosition& rStart, const sal_Int32 nDelLen,
3885 const OUString & rStr)
3886{
3887 ReplaceText(rStart.nContent, nDelLen, rStr);
3888}
3889
3890namespace {
3891 void lcl_ResetParAttrs( SwTextNode &rTextNode )
3892 {
3897 SwPaM aPam( rTextNode );
3898 // #i96644#
3899 // suppress side effect "send data changed events"
3900 rTextNode.GetDoc().ResetAttrs( aPam, false, aAttrs, false );
3901 }
3902
3903 // Helper method for special handling of modified attributes at text node.
3904 // The following is handled:
3905 // (1) on changing the paragraph style - RES_FMT_CHG:
3906 // Check, if list style of the text node is changed. If yes, add respectively
3907 // remove the text node to the corresponding list.
3908 // (2) on changing the attributes - RES_ATTRSET_CHG:
3909 // Same as (1).
3910 // (3) on changing the list style - RES_PARATR_NUMRULE:
3911 // Same as (1).
3912 void HandleModifyAtTextNode( SwTextNode& rTextNode,
3913 const SfxPoolItem* pOldValue,
3914 const SfxPoolItem* pNewValue )
3915 {
3916 const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
3917 pNewValue ? pNewValue->Which() : 0 ;
3918 bool bNumRuleSet = false;
3919 bool bParagraphStyleChanged = false;
3920 OUString sNumRule;
3921 OUString sOldNumRule;
3922 switch ( nWhich )
3923 {
3924 case RES_FMT_CHG:
3925 {
3926 bParagraphStyleChanged = true;
3927 if( rTextNode.GetNodes().IsDocNodes() )
3928 {
3929 const SwNumRule* pFormerNumRuleAtTextNode =
3930 rTextNode.GetNum() ? rTextNode.GetNum()->GetNumRule() : nullptr;
3931 if ( pFormerNumRuleAtTextNode )
3932 {
3933 sOldNumRule = pFormerNumRuleAtTextNode->GetName();
3934 }
3936 {
3937 const SwNumRuleItem& rNumRuleItem = rTextNode.GetTextColl()->GetNumRule();
3938 if ( !rNumRuleItem.GetValue().isEmpty() )
3939 {
3941 }
3942 }
3943 const SwNumRule* pNumRuleAtTextNode = rTextNode.GetNumRule();
3944 if ( pNumRuleAtTextNode )
3945 {
3946 bNumRuleSet = true;
3947 sNumRule = pNumRuleAtTextNode->GetName();
3948 }
3949 }
3950 break;
3951 }
3952 case RES_ATTRSET_CHG:
3953 {
3954 const SwNumRule* pFormerNumRuleAtTextNode =
3955 rTextNode.GetNum() ? rTextNode.GetNum()->GetNumRule() : nullptr;
3956 if ( pFormerNumRuleAtTextNode )
3957 {
3958 sOldNumRule = pFormerNumRuleAtTextNode->GetName();
3959 }
3960
3961 const SwAttrSetChg* pSet = dynamic_cast<const SwAttrSetChg*>(pNewValue);
3962 if ( pSet && pSet->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, false ) ==
3963 SfxItemState::SET )
3964 {
3965 // #i70748#
3967 bNumRuleSet = true;
3968 }
3969 // #i70748#
3970 // The new list style set at the paragraph.
3971 const SwNumRule* pNumRuleAtTextNode = rTextNode.GetNumRule();
3972 if ( pNumRuleAtTextNode )
3973 {
3974 sNumRule = pNumRuleAtTextNode->GetName();
3975 }
3976 break;
3977 }
3978 case RES_PARATR_NUMRULE:
3979 {
3980 if ( rTextNode.GetNodes().IsDocNodes() )
3981 {
3982 const SwNumRule* pFormerNumRuleAtTextNode =
3983 rTextNode.GetNum() ? rTextNode.GetNum()->GetNumRule() : nullptr;
3984 if ( pFormerNumRuleAtTextNode )
3985 {
3986 sOldNumRule = pFormerNumRuleAtTextNode->GetName();
3987 }
3988
3989 if ( pNewValue )
3990 {
3991 // #i70748#
3993 bNumRuleSet = true;
3994 }
3995 // #i70748#
3996 // The new list style set at the paragraph.
3997 const SwNumRule* pNumRuleAtTextNode = rTextNode.GetNumRule();
3998 if ( pNumRuleAtTextNode )
3999 {
4000 sNumRule = pNumRuleAtTextNode->GetName();
4001 }
4002 }
4003 break;
4004 }
4005 }
4006 if ( sNumRule != sOldNumRule )
4007 {
4008 if ( bNumRuleSet )
4009 {
4010 if (sNumRule.isEmpty())
4011 {
4012 rTextNode.RemoveFromList();
4013 if ( bParagraphStyleChanged )
4014 {
4015 lcl_ResetParAttrs(rTextNode);
4016 }
4017 }
4018 else
4019 {
4020 rTextNode.RemoveFromList();
4021 // If new list style is the outline style, apply outline
4022 // level as the list level.
4023 if (sNumRule==SwNumRule::GetOutlineRuleName())
4024 {
4025 // #i70748#
4026 OSL_ENSURE( rTextNode.GetTextColl()->IsAssignedToListLevelOfOutlineStyle(),
4027 "<HandleModifyAtTextNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
4028 const int nNewListLevel =
4030 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
4031 {
4032 rTextNode.SetAttrListLevel( nNewListLevel );
4033 }
4034 }
4035 rTextNode.AddToList();
4036 }
4037 }
4038 else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
4039 {
4040 rTextNode.RemoveFromList();
4041 if ( bParagraphStyleChanged )
4042 {
4043 lcl_ResetParAttrs(rTextNode);
4044 // #i70748#
4045 if ( rTextNode.GetAttr( RES_PARATR_OUTLINELEVEL, false ).GetValue() > 0 )
4046 {
4048 }
4049 }
4050 }
4051 }
4052 else if (!sNumRule.isEmpty() && !rTextNode.IsInList())
4053 {
4054 rTextNode.AddToList();
4055 }
4056 }
4057 // End of method <HandleModifyAtTextNode>
4058}
4059
4061{
4062 OSL_ENSURE( pNewColl,"ChgFormatColl: Collectionpointer has value 0." );
4063 assert( dynamic_cast<const SwTextFormatColl *>(pNewColl) && "ChgFormatColl: is not a Text Collection pointer." );
4064
4065 SwTextFormatColl *pOldColl = GetTextColl();
4066 if( pNewColl != pOldColl )
4067 {
4069 SwContentNode::ChgFormatColl( pNewColl );
4070 OSL_ENSURE( !mbInSetOrResetAttr,
4071 "DEBUG OSL_ENSURE(ON - <SwTextNode::ChgFormatColl(..)> called during <Set/ResetAttr(..)>" );
4072 if ( !mbInSetOrResetAttr )
4073 {
4074 SwFormatChg aTmp1( pOldColl );
4075 SwFormatChg aTmp2( pNewColl );
4076 HandleModifyAtTextNode( *this, &aTmp1, &aTmp2 );
4077 }
4078
4079 // reset fill information on parent style change
4081 {
4082 maFillAttributes.reset();
4083 }
4084 }
4085
4086 // only for real nodes-array
4087 if( GetNodes().IsDocNodes() )
4088 {
4089 ChgTextCollUpdateNum( pOldColl, static_cast<SwTextFormatColl *>(pNewColl) );
4090 }
4091
4092 return pOldColl;
4093}
4094
4095const SwNodeNum* SwTextNode::GetNum(SwRootFrame const*const pLayout, SwListRedlineType eRedline) const
4096{
4097 // invariant: it's only in list in Hide mode if it's in list in normal mode
4098 assert(mpNodeNum || !mpNodeNumRLHidden);
4099 return (pLayout && pLayout->IsHideRedlines()) || SwListRedlineType::HIDDEN == eRedline
4100 ? mpNodeNumRLHidden.get()
4101 : ( SwListRedlineType::ORIGTEXT == eRedline ? mpNodeNumOrig.get() : mpNodeNum.get() );
4102}
4103
4104void SwTextNode::DoNum(std::function<void (SwNodeNum &)> const& rFunc)
4105{
4106 // temp. clear because GetActualListLevel() may be called and the assert
4107 // there triggered during update, which is unhelpful
4108 std::unique_ptr<SwNodeNum> pBackup = std::move(mpNodeNumRLHidden);
4109 std::unique_ptr<SwNodeNum> pBackup2 = std::move(mpNodeNumOrig);
4110 assert(mpNodeNum);
4111 rFunc(*mpNodeNum);
4112 if (pBackup)
4113 {
4114 mpNodeNumRLHidden = std::move(pBackup);
4115 rFunc(*mpNodeNumRLHidden);
4116 }
4117 if (pBackup2)
4118 {
4119 mpNodeNumOrig = std::move(pBackup2);
4120 rFunc(*mpNodeNumOrig);
4121 }
4122}
4123
4126{
4127 if (SwNodeNum const*const pNum = GetNum(pLayout, eRedline))
4128 {
4129 return pNum->GetNumberVector();
4130 }
4131 else
4132 {
4134 return aResult;
4135 }
4136}
4137
4139{
4140 bool bResult = false;
4141
4142 if ( GetAttrOutlineLevel() > 0 )
4143 {
4144 bResult = !IsInRedlines();
4145 }
4146 else
4147 {
4148 const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : nullptr );
4149 if ( pRule && pRule->IsOutlineRule() )
4150 {
4151 bResult = !IsInRedlines();
4152 }
4153 }
4154
4155 return bResult;
4156}
4157
4159{
4160 return IsOutline() != m_bLastOutlineState;
4161}
4162
4164{
4166}
4167
4169{
4170 return GetAttr(RES_PARATR_OUTLINELEVEL).GetValue();
4171}
4172
4174{
4175 assert(0 <= nLevel && nLevel <= MAXLEVEL); // Level Out Of Range
4176 if ( 0 <= nLevel && nLevel <= MAXLEVEL )
4177 {
4179 o3tl::narrowing<sal_uInt16>(nLevel) ) );
4180 }
4181}
4182
4183void SwTextNode::GetAttrOutlineContentVisible(bool& bOutlineContentVisibleAttr)
4184{
4185 const SfxGrabBagItem & rGrabBagItem = GetAttr(RES_PARATR_GRABBAG);
4186 auto it = rGrabBagItem.GetGrabBag().find("OutlineContentVisibleAttr");
4187 if (it != rGrabBagItem.GetGrabBag().end())
4188 it->second >>= bOutlineContentVisibleAttr;
4189}
4190
4192{
4193 SfxGrabBagItem aGrabBagItem(RES_PARATR_GRABBAG);
4194 aGrabBagItem.GetGrabBag()["OutlineContentVisibleAttr"] <<= bVisible;
4195 SetAttr(aGrabBagItem);
4196}
4197
4198// #i70748#
4199
4201{
4203 {
4206 }
4207}
4208
4210{
4212 {
4215 }
4216}
4217
4219{
4220 if ( nLevel < 0 || nLevel >= MAXLEVEL )
4221 {
4222 assert(false); // invalid level
4223 return;
4224 }
4225
4226 SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
4227 static_cast<sal_Int16>(nLevel) );
4228 SetAttr( aNewListLevelItem );
4229}
4230
4232{
4233 return GetpSwAttrSet() &&
4234 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, false ) == SfxItemState::SET;
4235}
4236
4238{
4239 int nAttrListLevel = 0;
4240
4241 const SfxInt16Item& aListLevelItem =
4243 nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());
4244
4245 return nAttrListLevel;
4246}
4247
4249{
4250 assert(SwListRedlineType::SHOW != eRedline ||
4251 !GetNum(nullptr, SwListRedlineType::SHOW) || !mpNodeNumRLHidden || // must be in sync
4252 GetNum(nullptr, SwListRedlineType::SHOW)->GetLevelInListTree() ==
4253 mpNodeNumRLHidden->GetLevelInListTree());
4254 return GetNum(nullptr, eRedline) ? GetNum(nullptr, eRedline)->GetLevelInListTree() : -1;
4255}
4256
4257void SwTextNode::SetListRestart( bool bRestart )
4258{
4259 if ( !bRestart )
4260 {
4261 // attribute not contained in paragraph style's attribute set. Thus,
4262 // it can be reset to the attribute pool default by resetting the attribute.
4264 }
4265 else
4266 {
4267 SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
4268 true );
4269 SetAttr( aNewIsRestartItem );
4270 }
4271}
4272
4274{
4275 const SfxBoolItem& aIsRestartItem = GetAttr( RES_PARATR_LIST_ISRESTART );
4276
4277 return aIsRestartItem.GetValue();
4278}
4279
4285{
4286 const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
4287 if ( pRule && IsCountedInList())
4288 {
4289 const SwNumFormat& rFormat = pRule->Get(lcl_BoundListLevel(GetActualListLevel()));
4291 // True if we have something in label text or there is a non-empty
4292 // FollowedBy separator (space, tab or whatsoever)
4293 return rFormat.GetLabelFollowedBy() != SvxNumberFormat::LabelFollowedBy::NOTHING ||
4294 !pRule->MakeNumString(*GetNum()).isEmpty();
4295 else
4296 // #i87154#
4297 // Correction of #newlistlevelattrs#:
4298 // The numbering type has to be checked for bullet lists.
4299 return SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() ||
4300 !pRule->MakeNumString(*(GetNum())).isEmpty();
4301 }
4302
4303 return false;
4304}
4305
4307{
4308 const bool bChanged( HasAttrListRestartValue()
4309 ? GetAttrListRestartValue() != nNumber
4310 : nNumber != USHRT_MAX );
4311
4312 if ( !bChanged && HasAttrListRestartValue() )
4313 return;
4314
4315 if ( nNumber == USHRT_MAX )
4316 {
4318 }
4319 else
4320 {
4321 SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
4322 static_cast<sal_Int16>(nNumber) );
4323 SetAttr( aNewListRestartValueItem );
4324 }
4325}
4326
4328{
4329 return GetpSwAttrSet() &&
4330 GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, false ) == SfxItemState::SET;
4331}
4333{
4334 OSL_ENSURE( HasAttrListRestartValue(),
4335 "<SwTextNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );
4336
4337 const SfxInt16Item& aListRestartValueItem =
4339 return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
4340}
4341
4343{
4344 SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;
4345
4347 {
4348 nListRestartValue = GetAttrListRestartValue();
4349 }
4350 else
4351 {
4352 SwNumRule* pRule = GetNumRule();
4353 if ( pRule )
4354 {
4355 const SwNumFormat* pFormat =
4356 pRule->GetNumFormat( o3tl::narrowing<sal_uInt16>(GetAttrListLevel()) );
4357 if ( pFormat )
4358 {
4359 nListRestartValue = pFormat->GetStart();
4360 }
4361 }
4362 }
4363
4364 return nListRestartValue;
4365}
4366
4368{
4370}
4371
4373{
4374 const SwDoc& rDoc = GetDoc();
4375 return !rDoc.IsInReading() && !rDoc.IsInDtor();
4376}
4377
4378void SwTextNode::SetCountedInList( bool bCounted )
4379{
4380 if ( bCounted )
4381 {
4382 // attribute not contained in paragraph style's attribute set. Thus,
4383 // it can be reset to the attribute pool default by resetting the attribute.
4385 }
4386 else
4387 {
4388 SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, false );
4389 SetAttr( aIsCountedInListItem );
4390 }
4391}
4392
4394{
4395 const SfxBoolItem& aIsCountedInListItem = GetAttr( RES_PARATR_LIST_ISCOUNTED );
4396
4397 return aIsCountedInListItem.GetValue();
4398}
4399
4400static SwList * FindList(SwTextNode *const pNode)
4401{
4402 const OUString sListId = pNode->GetListId();
4403 if (!sListId.isEmpty())
4404 {
4405 auto & rIDLA(pNode->GetDoc().getIDocumentListsAccess());
4406 SwList* pList = rIDLA.getListByName( sListId );
4407 if ( pList == nullptr )
4408 {
4409 // Create corresponding list.
4410 SwNumRule* pNumRule = pNode->GetNumRule();
4411 if ( pNumRule )
4412 {
4413 pList = rIDLA.createList(sListId, pNode->GetNumRule()->GetName());
4414 }
4415 }
4416 OSL_ENSURE( pList != nullptr,
4417 "<SwTextNode::AddToList()> - no list for given list id. Serious defect" );
4418 return pList;
4419 }
4420 return nullptr;
4421}
4422
4424{
4425 if ( IsInList() )
4426 {
4427 OSL_FAIL( "<SwTextNode::AddToList()> - the text node is already added to a list. Serious defect" );
4428 return;
4429 }
4430
4431 SwList *const pList(FindList(this));
4432 if (!(pList && GetNodes().IsDocNodes())) // not for undo nodes
4433 return;
4434
4435 assert(!mpNodeNum);
4436 mpNodeNum.reset(new SwNodeNum(this, false));
4438
4439 // set redline lists
4440 // "default" list: visible items in Show Changes mode (tracked insertions and deletions)
4441 // "hidden" list: visible items in Hide Changes mode (tracked insertions, but not deletions)
4442 // "orig" list: visible items rejecting all changes (no tracked insertions and deletions)
4443 bool bRecordChanges = GetDoc().GetDocShell() && GetDoc().GetDocShell()->IsChangeRecording();
4444 if (!bRecordChanges || GetDoc().IsInXMLImport() || GetDoc().IsInWriterfilterImport() )
4445 {
4447 SwRedlineTable::size_type nRedlPos = GetDoc().getIDocumentRedlineAccess().GetRedlinePos(*this, RedlineType::Insert);
4448 // paragraph start is not in a tracked insertion
4449 if ( SwRedlineTable::npos == nRedlPos || GetIndex() <= rRedTable[nRedlPos]->Start()->GetNode().GetIndex() )
4450 {
4451 AddToListOrig();
4452
4453 // if the paragraph is not deleted, add to the "hidden" list, too
4454 SwRedlineTable::size_type nRedlPosDel = GetDoc().getIDocumentRedlineAccess().GetRedlinePos(*this, RedlineType::Delete);
4455 if ( SwRedlineTable::npos == nRedlPosDel )
4457 }
4458 // inserted paragraph, e.g. during file load, add to the "hidden" list
4459 else if ( SwRedlineTable::npos != nRedlPos )
4461 }
4462 else if ( bRecordChanges )
4464
4465 // iterate all frames & if there's one with hidden layout...
4467 for (SwTextFrame* pFrame = iter.First(); pFrame && !mpNodeNumRLHidden; pFrame = iter.Next())
4468 {
4469 if (pFrame->getRootFrame()->IsHideRedlines())
4470 {
4471 if (pFrame->GetTextNodeForParaProps() == this)
4472 {
4474 }
4475 break; // assume it's consistent, need to check only once
4476 }
4477 }
4478}
4479
4481{
4483 return;
4484
4485 SwList *const pList(FindList(this));
4486 if (pList)
4487 {
4488 assert(!mpNodeNumRLHidden);
4489 mpNodeNumRLHidden.reset(new SwNodeNum(this, true));
4491 }
4492}
4493
4495{
4496 if (mpNodeNumOrig)
4497 return;
4498
4499 SwList *const pList(FindList(this));
4500 if (pList)
4501 {
4502 assert(!mpNodeNumOrig);
4503 mpNodeNumOrig.reset(new SwNodeNum(this, true));
4505 }
4506}
4507
4509{
4510 // sw_redlinehide: ensure it's removed from the other half too!
4513 if ( IsInList() )
4514 {
4516 mpNodeNum.reset();
4517
4518 SetWordCountDirty( true );
4519 }
4520}
4521
4523{
4524 if (mpNodeNumRLHidden) // direct access because RemoveFromList doesn't have layout
4525 {
4526 assert(mpNodeNumRLHidden->GetParent() || !GetNodes().IsDocNodes());
4528 mpNodeNumRLHidden.reset();
4529
4530 SetWordCountDirty( true );
4531 }
4532}
4533
4535{
4536 if (mpNodeNumOrig) // direct access because RemoveFromList doesn't have layout
4537 {
4538 assert(mpNodeNumOrig->GetParent() || !GetNodes().IsDocNodes());
4540 mpNodeNumOrig.reset();
4541
4542 SetWordCountDirty( true );
4543 }
4544}
4545
4547{
4548 return GetNum() != nullptr && GetNum()->GetParent() != nullptr;
4549}
4550
4552{
4553 bool bResult = false;
4554
4555 SwNodeNum const*const pNum(GetNum(&rLayout));
4556 if (pNum && pNum->GetNumRule())
4557 bResult = pNum->IsFirst();
4558
4559 return bResult;
4560}
4561
4562void SwTextNode::SetListId(OUString const& rListId)
4563{
4564 const SfxStringItem& rListIdItem =
4566 if (rListIdItem.GetValue() != rListId)
4567 {
4568 if (rListId.isEmpty())
4569 {
4571 }
4572 else
4573 {
4574 SfxStringItem aNewListIdItem(RES_PARATR_LIST_ID, rListId);
4575 SetAttr( aNewListIdItem );
4576 }
4577 }
4578}
4579
4581{
4582 const SfxStringItem& rListIdItem =
4584 const OUString& sListId {rListIdItem.GetValue()};
4585
4586 // As long as no explicit list id attribute is set, use the list id of
4587 // the list, which has been created for the applied list style.
4588 if (sListId.isEmpty())
4589 {
4590 SwNumRule* pRule = GetNumRule();
4591 if ( pRule )
4592 {
4593 return pRule->GetDefaultListId();
4594 }
4595 }
4596
4597 return sListId;
4598}
4599
4615{
4618 {
4619 ret |= ::sw::ListLevelIndents::FirstLine;
4620 }
4622 {
4624 }
4625 return ret;
4626}
4627
4628bool SwTextNode::AreListLevelIndentsApplicableImpl(sal_uInt16 const nWhich) const
4629{
4630 bool bAreListLevelIndentsApplicable( true );
4631
4632 if ( !GetNum() || !GetNum()->GetNumRule() )
4633 {
4634 // no list style applied to paragraph
4635 bAreListLevelIndentsApplicable = false;
4636 }
4637 else if ( HasSwAttrSet() &&
4638 GetpSwAttrSet()->GetItemState(nWhich, false) == SfxItemState::SET)
4639 {
4640 // paragraph has hard-set indent attributes
4641 bAreListLevelIndentsApplicable = false;
4642 }
4643 else if ( HasSwAttrSet() &&
4644 GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET )
4645 {
4646 // list style is directly applied to paragraph and paragraph has no
4647 // hard-set indent attributes
4648 bAreListLevelIndentsApplicable = true;
4649 }
4650 else
4651 {
4652 // list style is applied through one of the paragraph styles and
4653 // paragraph has no hard-set indent attributes
4654
4655 // check, paragraph's
4656 const SwTextFormatColl* pColl = GetTextColl();
4657 while ( pColl )
4658 {
4659 if (pColl->GetAttrSet().GetItemState(nWhich, false) == SfxItemState::SET)
4660 {
4661 // indent attributes found in the paragraph style hierarchy.
4662 bAreListLevelIndentsApplicable = false;
4663 break;
4664 }
4665
4666 if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET )
4667 {
4668 // paragraph style with the list style found and until now no
4669 // indent attributes are found in the paragraph style hierarchy.
4670 bAreListLevelIndentsApplicable = true;
4671 break;
4672 }
4673
4674 pColl = dynamic_cast<const SwTextFormatColl*>(pColl->DerivedFrom());
4675 OSL_ENSURE( pColl,
4676 "<SwTextNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
4677 }
4678 }
4679
4680 return bAreListLevelIndentsApplicable;
4681}
4682
4691bool SwTextNode::GetListTabStopPosition( tools::Long& nListTabStopPosition ) const
4692{
4693 bool bListTabStopPositionProvided(false);
4694
4695 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
4696 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4697 {
4698 const SwNumFormat& rFormat = pNumRule->Get( o3tl::narrowing<sal_uInt16>(GetActualListLevel()) );
4701 {
4702 bListTabStopPositionProvided = true;
4703 nListTabStopPosition = rFormat.GetListtabPos();
4704
4706 {
4707 // tab stop position are treated to be relative to the "before text"
4708 // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
4710 {
4711 nListTabStopPosition -= rFormat.GetIndentAt();
4712 }
4714 {
4715 SvxTextLeftMarginItem const aItem(GetSwAttrSet().GetTextLeftMargin());
4716 nListTabStopPosition -= aItem.GetTextLeft();
4717 }
4718 }
4719 }
4720 }
4721
4722 return bListTabStopPositionProvided;
4723}
4724
4726{
4727 const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : nullptr;
4728 if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4729 {
4730 const SwNumFormat& rFormat = pNumRule->Get( o3tl::narrowing<sal_uInt16>(GetActualListLevel()) );
4732 {
4733 return rFormat.GetLabelFollowedByAsString();
4734 }
4735 }
4736
4737 return OUString();
4738}
4739
4741{
4742 sal_Int32 nStartPos;
4743 sal_Int32 nEndPos;
4744 // Update of the flags is done inside GetBoundsOfHiddenRange()
4745 SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
4746}
4747
4748// #i12836# enhanced pdf export
4750{
4752 return true;
4753
4754 const SwSectionNode* pSectNd = FindSectionNode();
4755 return pSectNd && pSectNd->GetSection().IsHiddenFlag();
4756}
4757
4758namespace {
4759 // Helper class for special handling of setting attributes at text node:
4760 // In constructor an instance of the helper class recognize whose attributes
4761 // are set and perform corresponding actions before the intrinsic set of
4762 // attributes has been taken place.
4763 // In the destructor - after the attributes have been set at the text
4764 // node - corresponding actions are performed.
4765 // The following is handled:
4766 // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
4767 // (A) list style attribute is empty -> the text node is removed from
4768 // its list.
4769 // (B) list style attribute is not empty
4770 // (a) text node has no list style -> add text node to its list after
4771 // the attributes have been set.
4772 // (b) text node has list style -> change of list style is notified
4773 // after the attributes have been set.
4774 // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
4775 // the text node is removed from its current list before the attributes
4776 // are set and added to its new list after the attributes have been set.
4777 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
4778 // and changed after the attributes have been set
4779 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
4780 // and changed after the attributes have been set
4781 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
4782 // is set and changed after the attributes have been set
4783 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
4784 // and changed after the attributes have been set
4785 // (7) Set or Reset empty list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
4786 class HandleSetAttrAtTextNode
4787 {
4788 public:
4789 HandleSetAttrAtTextNode( SwTextNode& rTextNode,
4790 const SfxPoolItem& pItem );
4791 HandleSetAttrAtTextNode( SwTextNode& rTextNode,
4792 const SfxItemSet& rItemSet );
4793 ~HandleSetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE;
4794
4795 private:
4796 SwTextNode& mrTextNode;
4797 bool mbAddTextNodeToList;
4798 bool mbUpdateListLevel;
4799 bool mbUpdateListRestart;
4800 bool mbUpdateListCount;
4801 // #i70748#
4802 bool mbOutlineLevelSet;
4803 };
4804
4805 HandleSetAttrAtTextNode::HandleSetAttrAtTextNode( SwTextNode& rTextNode,
4806 const SfxPoolItem& pItem )
4807 : mrTextNode( rTextNode ),
4808 mbAddTextNodeToList( false ),
4809 mbUpdateListLevel( false ),
4810 mbUpdateListRestart( false ),
4811 mbUpdateListCount( false ),
4812 // #i70748#
4813 mbOutlineLevelSet( false )
4814 {
4815 switch ( pItem.Which() )
4816 {
4817 // handle RES_PARATR_NUMRULE
4818 case RES_PARATR_NUMRULE:
4819 {
4820 mrTextNode.RemoveFromList();
4821
4822 const SwNumRuleItem& rNumRuleItem =
4823 dynamic_cast<const SwNumRuleItem&>(pItem);
4824 if ( !rNumRuleItem.GetValue().isEmpty() )
4825 {
4826 mbAddTextNodeToList = true;
4827 // #i105562#
4828
4829 mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4830 }
4831 }
4832 break;
4833
4834 // handle RES_PARATR_LIST_ID
4835 case RES_PARATR_LIST_ID:
4836 {
4837 const SfxStringItem& rListIdItem =
4838 dynamic_cast<const SfxStringItem&>(pItem);
4839 OSL_ENSURE( rListIdItem.GetValue().getLength() > 0,
4840 "<HandleSetAttrAtTextNode(..)> - empty list id attribute not expected. Serious defect." );
4841 const OUString sListIdOfTextNode = rTextNode.GetListId();
4842 if ( rListIdItem.GetValue() != sListIdOfTextNode )
4843 {
4844 mbAddTextNodeToList = true;
4845 if ( mrTextNode.IsInList() )
4846 {
4847 mrTextNode.RemoveFromList();
4848 }
4849 }
4850 }
4851 break;
4852
4853 // handle RES_PARATR_LIST_LEVEL
4855 {
4856 const SfxInt16Item& aListLevelItem =
4857 dynamic_cast<const SfxInt16Item&>(pItem);
4858 if ( aListLevelItem.GetValue() != mrTextNode.GetAttrListLevel() )
4859 {
4860 mbUpdateListLevel = true;
4861 }
4862 }
4863 break;
4864
4865 // handle RES_PARATR_LIST_ISRESTART
4867 {
4868 const SfxBoolItem& aListIsRestartItem =
4869 dynamic_cast<const SfxBoolItem&>(pItem);
4870 if ( aListIsRestartItem.GetValue() !=
4871 mrTextNode.IsListRestart() )
4872 {
4873 mbUpdateListRestart = true;
4874 }
4875 }
4876 break;
4877
4878 // handle RES_PARATR_LIST_RESTARTVALUE
4880 {
4881 const SfxInt16Item& aListRestartValueItem =
4882 dynamic_cast<const SfxInt16Item&>(pItem);
4883 if ( !mrTextNode.HasAttrListRestartValue() ||
4884 aListRestartValueItem.GetValue() != mrTextNode.GetAttrListRestartValue() )
4885 {
4886 mbUpdateListRestart = true;
4887 }
4888 }
4889 break;
4890
4891 // handle RES_PARATR_LIST_ISCOUNTED
4893 {
4894 const SfxBoolItem& aIsCountedInListItem =
4895 dynamic_cast<const SfxBoolItem&>(pItem);
4896 if ( aIsCountedInListItem.GetValue() !=
4897 mrTextNode.IsCountedInList() )
4898 {
4899 mbUpdateListCount = true;
4900 }
4901 }
4902 break;
4903
4904 // #i70748#
4905 // handle RES_PARATR_OUTLINELEVEL
4907 {
4908 const SfxUInt16Item& aOutlineLevelItem =
4909 dynamic_cast<const SfxUInt16Item&>(pItem);
4910 if ( aOutlineLevelItem.GetValue() != mrTextNode.GetAttrOutlineLevel() )
4911 {
4912 mbOutlineLevelSet = true;
4913 }
4914 }
4915 break;
4916 }
4917
4918 }
4919
4920 HandleSetAttrAtTextNode::HandleSetAttrAtTextNode( SwTextNode& rTextNode,
4921 const SfxItemSet& rItemSet )
4922 : mrTextNode( rTextNode ),
4923 mbAddTextNodeToList( false ),
4924 mbUpdateListLevel( false ),
4925 mbUpdateListRestart( false ),
4926 mbUpdateListCount( false ),
4927 // #i70748#
4928 mbOutlineLevelSet( false )
4929 {
4930 // handle RES_PARATR_NUMRULE
4931 if ( const SwNumRuleItem* pNumRuleItem = rItemSet.GetItemIfSet( RES_PARATR_NUMRULE, false ) )
4932 {
4933 mrTextNode.RemoveFromList();
4934
4935 if ( !pNumRuleItem->GetValue().isEmpty() )
4936 {
4937 mbAddTextNodeToList = true;
4938 // #i70748#
4939 mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4940 }
4941 }
4942
4943 // handle RES_PARATR_LIST_ID
4944 if ( const SfxStringItem* pListIdItem = rItemSet.GetItemIfSet( RES_PARATR_LIST_ID, false ) )
4945 {
4946 const OUString sListIdOfTextNode = mrTextNode.GetListId();
4947 if ( pListIdItem->GetValue() != sListIdOfTextNode )
4948 {
4949 mbAddTextNodeToList = true;
4950 if ( mrTextNode.IsInList() )
4951 {
4952 mrTextNode.RemoveFromList();
4953 }
4954 }
4955 }
4956
4957 // handle RES_PARATR_LIST_LEVEL
4958 if ( const SfxInt16Item* pListLevelItem = rItemSet.GetItemIfSet( RES_PARATR_LIST_LEVEL, false ) )
4959 {
4960 if (pListLevelItem->GetValue() != mrTextNode.GetAttrListLevel())
4961 {
4962 mbUpdateListLevel = true;
4963 }
4964 }
4965
4966 // handle RES_PARATR_LIST_ISRESTART
4967 if ( const SfxBoolItem* pListIsRestartItem = rItemSet.GetItemIfSet( RES_PARATR_LIST_ISRESTART, false ) )
4968 {
4969 if (pListIsRestartItem->GetValue() != mrTextNode.IsListRestart())
4970 {
4971 mbUpdateListRestart = true;
4972 }
4973 }
4974
4975 // handle RES_PARATR_LIST_RESTARTVALUE
4976 if ( const SfxInt16Item* pListRestartValueItem = rItemSet.GetItemIfSet( RES_PARATR_LIST_RESTARTVALUE, false ) )
4977 {
4978 if ( !mrTextNode.HasAttrListRestartValue() ||
4979 pListRestartValueItem->GetValue() != mrTextNode.GetAttrListRestartValue() )
4980 {
4981 mbUpdateListRestart = true;
4982 }
4983 }
4984
4985 // handle RES_PARATR_LIST_ISCOUNTED
4986 if ( const SfxBoolItem* pIsCountedInListItem = rItemSet.GetItemIfSet( RES_PARATR_LIST_ISCOUNTED, false ) )
4987 {
4988 if (pIsCountedInListItem->GetValue() != mrTextNode.IsCountedInList())
4989 {
4990 mbUpdateListCount = true;
4991 }
4992 }
4993
4994 // #i70748#
4995 // handle RES_PARATR_OUTLINELEVEL
4996 if ( const SfxUInt16Item* pOutlineLevelItem = rItemSet.GetItemIfSet( RES_PARATR_OUTLINELEVEL, false ) )
4997 {
4998 if (pOutlineLevelItem->GetValue() != mrTextNode.GetAttrOutlineLevel())
4999 {
5000 mbOutlineLevelSet = true;
5001 }
5002 }
5003 }
5004
5005 HandleSetAttrAtTextNode::~HandleSetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE
5006 {
5007 if ( mbAddTextNodeToList )
5008 {
5009 SwNumRule* pNumRuleAtTextNode = mrTextNode.GetNumRule();
5010 if ( pNumRuleAtTextNode )
5011 {
5012 mrTextNode.AddToList();
5013 }
5014 }
5015 else
5016 {
5017 if ( mbUpdateListLevel && mrTextNode.IsInList() )
5018 {
5019 auto const nLevel(mrTextNode.GetAttrListLevel());
5020 const SwDoc& rDoc(mrTextNode.GetDoc());
5021 mrTextNode.DoNum(
5022 [nLevel, &rDoc](SwNodeNum & rNum) { rNum.SetLevelInListTree(nLevel, rDoc); });
5023 }
5024
5025 if ( mbUpdateListRestart && mrTextNode.IsInList() )
5026 {
5027 const SwDoc& rDoc(mrTextNode.GetDoc());
5028 mrTextNode.DoNum(
5029 [&rDoc](SwNodeNum & rNum) {
5030 rNum.InvalidateMe();
5031 rNum.NotifyInvalidSiblings(rDoc);
5032 });
5033 }
5034
5035 if (mbUpdateListCount && mrTextNode.IsInList() && HasNumberingWhichNeedsLayoutUpdate(mrTextNode))
5036 {
5037 // Repaint all text frames that belong to this numbering to avoid outdated generated
5038 // numbers.
5039 const SwDoc& rDoc(mrTextNode.GetDoc());
5040 mrTextNode.DoNum(
5041 [&rDoc](SwNodeNum & rNum) { rNum.InvalidateAndNotifyTree(rDoc); });
5042 }
5043 }
5044
5045 // #i70748#
5046 if (!mbOutlineLevelSet)
5047 return;
5048
5049 mrTextNode.GetNodes().UpdateOutlineNode(mrTextNode);
5050 if (mrTextNode.GetAttrOutlineLevel() == 0)
5051 {
5052 mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
5053 }
5054 else
5055 {
5056 if ( mrTextNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE )
5057 != SfxItemState::SET )
5058 {
5059 mrTextNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
5060 }
5061 }
5062 }
5063 // End of class <HandleSetAttrAtTextNode>
5064}
5065
5067{
5068 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
5069 mbInSetOrResetAttr = true;
5070
5071 HandleSetAttrAtTextNode aHandleSetAttr( *this, pItem );
5072
5073 bool bRet = SwContentNode::SetAttr( pItem );
5074
5075 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
5076
5077 return bRet;
5078}
5079
5081{
5082 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
5083 mbInSetOrResetAttr = true;
5084
5085 HandleSetAttrAtTextNode aHandleSetAttr( *this, rSet );
5086
5087 bool bRet = SwContentNode::SetAttr( rSet );
5088
5089 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
5090
5091 return bRet;
5092}
5093
5094void SwTextNode::SetInSwUndo(bool bInUndo)
5095{
5096 m_bInUndo = bInUndo;
5097}
5098
5099namespace {
5100 // Helper class for special handling of resetting attributes at text node:
5101 // In constructor an instance of the helper class recognize whose attributes
5102 // are reset and perform corresponding actions before the intrinsic reset of
5103 // attributes has been taken place.
5104 // In the destructor - after the attributes have been reset at the text
5105 // node - corresponding actions are performed.
5106 // The following is handled:
5107 // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
5108 // the text is removed from its list before the attributes have been reset.
5109 // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
5110 // the text is removed from its list before the attributes have been reset.
5111 // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
5112 // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
5113 // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
5114 // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
5115 // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
5116 class HandleResetAttrAtTextNode
5117 {
5118 public:
5119 HandleResetAttrAtTextNode( SwTextNode& rTextNode,
5120 const sal_uInt16 nWhich1,
5121 sal_uInt16 nWhich2 );
5122 HandleResetAttrAtTextNode( SwTextNode& rTextNode,
5123 const std::vector<sal_uInt16>& rWhichArr );
5124 explicit HandleResetAttrAtTextNode( SwTextNode& rTextNode );
5125
5126 ~HandleResetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE;
5127
5128 private:
5129 SwTextNode& mrTextNode;
5130 bool mbListStyleOrIdReset;
5131 bool mbUpdateListLevel;
5132 bool mbUpdateListRestart;
5133 bool mbUpdateListCount;
5134
5135 void init( sal_uInt16 nWhich, bool& rbRemoveFromList );
5136 };
5137
5138 HandleResetAttrAtTextNode::HandleResetAttrAtTextNode( SwTextNode& rTextNode,
5139 const sal_uInt16 nWhich1,
5140 sal_uInt16 nWhich2 )
5141 : mrTextNode( rTextNode ),
5142 mbListStyleOrIdReset( false ),
5143 mbUpdateListLevel( false ),
5144 mbUpdateListRestart( false ),
5145 mbUpdateListCount( false )
5146 {
5147 if ( nWhich2 < nWhich1 )
5148 nWhich2 = nWhich1;
5149 bool bRemoveFromList( false );
5150 for ( sal_uInt16 nWhich = nWhich1; nWhich <= nWhich2; ++nWhich )
5151 init( nWhich, bRemoveFromList );
5152 if ( bRemoveFromList && mrTextNode.IsInList() )
5153 mrTextNode.RemoveFromList();
5154 }
5155
5156 HandleResetAttrAtTextNode::HandleResetAttrAtTextNode( SwTextNode& rTextNode,
5157 const std::vector<sal_uInt16>& rWhichArr )
5158 : mrTextNode( rTextNode ),
5159 mbListStyleOrIdReset( false ),
5160 mbUpdateListLevel( false ),
5161 mbUpdateListRestart( false ),
5162 mbUpdateListCount( false )
5163 {
5164 bool bRemoveFromList( false );
5165 for ( sal_uInt16 nWhich : rWhichArr )
5166 init( nWhich, bRemoveFromList );
5167 if ( bRemoveFromList && mrTextNode.IsInList() )
5168 mrTextNode.RemoveFromList();
5169 }
5170
5171 HandleResetAttrAtTextNode::HandleResetAttrAtTextNode( SwTextNode& rTextNode )
5172 : mrTextNode( rTextNode ),
5173 mbListStyleOrIdReset( true ),
5174 mbUpdateListLevel( false ),
5175 mbUpdateListRestart( false ),
5176 mbUpdateListCount( false )
5177 {
5178 if ( rTextNode.IsInList() )
5179 {
5180 rTextNode.RemoveFromList();
5181 }
5182 // #i70748#
5183 mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
5184 }
5185
5186 void HandleResetAttrAtTextNode::init( sal_uInt16 rWhich, bool& rbRemoveFromList )
5187 {
5188 if ( rWhich == RES_PARATR_NUMRULE )
5189 {
5190 rbRemoveFromList = rbRemoveFromList ||
5191 mrTextNode.GetNumRule() != nullptr;
5192 mbListStyleOrIdReset = true;
5193 }
5194 else if ( rWhich == RES_PARATR_LIST_ID )
5195 {
5196 rbRemoveFromList = rbRemoveFromList ||
5197 ( mrTextNode.GetpSwAttrSet() &&
5198 mrTextNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, false ) == SfxItemState::SET );
5199 mbListStyleOrIdReset = true;
5200 }
5201 else if ( rWhich == RES_PARATR_OUTLINELEVEL )
5202 mrTextNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
5203 else if ( rWhich == RES_BACKGROUND )
5204 mrTextNode.ResetAttr( XATTR_FILL_FIRST, XATTR_FILL_LAST );
5205
5206 if ( !rbRemoveFromList )
5207 {
5208 // RES_PARATR_LIST_LEVEL
5209 mbUpdateListLevel = mbUpdateListLevel ||
5210 ( rWhich == RES_PARATR_LIST_LEVEL &&
5211 mrTextNode.HasAttrListLevel() );
5212
5213 // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
5214 mbUpdateListRestart = mbUpdateListRestart ||
5215 ( rWhich == RES_PARATR_LIST_ISRESTART &&
5216 mrTextNode.IsListRestart() ) ||
5217 ( rWhich == RES_PARATR_LIST_RESTARTVALUE &&
5218 mrTextNode.HasAttrListRestartValue() );
5219
5220 // RES_PARATR_LIST_ISCOUNTED
5221 mbUpdateListCount = mbUpdateListCount ||
5222 ( rWhich == RES_PARATR_LIST_ISCOUNTED &&
5223 !mrTextNode.IsCountedInList() );
5224 }
5225 }
5226
5227 HandleResetAttrAtTextNode::~HandleResetAttrAtTextNode() COVERITY_NOEXCEPT_FALSE
5228 {
5229 if ( mbListStyleOrIdReset && !mrTextNode.IsInList() )
5230 {
5231 // check, if in spite of the reset of the list style or the list id
5232 // the paragraph still has to be added to a list.
5233 if (mrTextNode.GetNumRule() && !mrTextNode.GetListId().isEmpty())
5234 {
5235 // #i96062#
5236 // If paragraph has no list level attribute set and list style
5237 // is the outline style, apply outline level as the list level.
5238 if ( !mrTextNode.HasAttrListLevel() &&
5239 mrTextNode.GetNumRule()->GetName()==SwNumRule::GetOutlineRuleName() &&
5240 mrTextNode.GetTextColl()->IsAssignedToListLevelOfOutlineStyle() )
5241 {
5242 int nNewListLevel = mrTextNode.GetTextColl()->GetAssignedOutlineStyleLevel();
5243 if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
5244 {
5245 mrTextNode.SetAttrListLevel( nNewListLevel );
5246 }
5247 }
5248 mrTextNode.AddToList();
5249 }
5250 // #i70748#
5251 // #i105562#
5252 else
5253 {
5254 if (mrTextNode.GetpSwAttrSet()
5255 && mrTextNode.GetAttr(RES_PARATR_OUTLINELEVEL, false).GetValue() > 0)
5256 {
5257 mrTextNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
5258 }
5259 }
5260 }
5261
5262 if ( !mrTextNode.IsInList() )
5263 return;
5264
5265 if ( mbUpdateListLevel )
5266 {
5267 auto const nLevel(mrTextNode.GetAttrListLevel());
5268 const SwDoc& rDoc(mrTextNode.GetDoc());
5269 mrTextNode.DoNum(
5270 [nLevel, &rDoc](SwNodeNum & rNum) { rNum.SetLevelInListTree(nLevel, rDoc); });
5271 }
5272
5273 if ( mbUpdateListRestart )
5274 {
5275 const SwDoc& rDoc(mrTextNode.GetDoc());
5276 mrTextNode.DoNum(
5277 [&rDoc](SwNodeNum & rNum) {
5278 rNum.InvalidateMe();
5279 rNum.NotifyInvalidSiblings(rDoc);
5280 });
5281 }
5282
5283 if ( mbUpdateListCount )
5284 {
5285 const SwDoc& rDoc(mrTextNode.GetDoc());
5286 mrTextNode.DoNum(
5287 [&rDoc](SwNodeNum & rNum) { rNum.InvalidateAndNotifyTree(rDoc); });
5288 }
5289 }
5290 // End of class <HandleResetAttrAtTextNode>
5291}
5292
5293bool SwTextNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
5294{
5295 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
5296 mbInSetOrResetAttr = true;
5297
5298 HandleResetAttrAtTextNode aHandleResetAttr( *this, nWhich1, nWhich2 );
5299
5300 bool bRet = SwContentNode::ResetAttr( nWhich1, nWhich2 );
5301
5302 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
5303
5304 return bRet;
5305}
5306
5307bool SwTextNode::ResetAttr( const std::vector<sal_uInt16>& rWhichArr )
5308{
5309 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
5310 mbInSetOrResetAttr = true;
5311
5312 HandleResetAttrAtTextNode aHandleResetAttr( *this, rWhichArr );
5313
5314 bool bRet = SwContentNode::ResetAttr( rWhichArr );
5315
5316 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
5317
5318 return bRet;
5319}
5320
5322{
5323 const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
5324 mbInSetOrResetAttr = true;
5325
5326 HandleResetAttrAtTextNode aHandleResetAttr( *this );
5327
5328 const sal_uInt16 nRet = SwContentNode::ResetAllAttr();
5329
5330 mbInSetOrResetAttr = bOldIsSetOrResetAttr;
5331
5332 return nRet;
5333}
5334
5336{
5337 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextNode"));
5338 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
5339 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("index"), BAD_CAST(OString::number(sal_Int32(GetIndex())).getStr()));
5340
5341 OUString sText = GetText();
5342 for (int i = 0; i < 32; ++i)
5343 sText = sText.replace(i, '*');
5344 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_Text"));
5345 (void)xmlTextWriterWriteString(pWriter, BAD_CAST(sText.toUtf8().getStr()));
5346 (void)xmlTextWriterEndElement(pWriter);
5347
5348 if (GetFormatColl())
5349 {
5350 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextFormatColl"));
5351 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetFormatColl()->GetName().toUtf8().getStr()));
5352 (void)xmlTextWriterEndElement(pWriter);
5353 }
5354
5355 if (HasSwAttrSet())
5356 {
5357 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwAttrSet"));
5358 GetSwAttrSet().dumpAsXml(pWriter);
5359 (void)xmlTextWriterEndElement(pWriter);
5360 }
5361
5362 if (HasHints())
5363 {
5364 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwpHints"));
5365 const SwpHints& rHints = GetSwpHints();
5366 for (size_t i = 0; i < rHints.Count(); ++i)
5367 rHints.Get(i)->dumpAsXml(pWriter);
5368 (void)xmlTextWriterEndElement(pWriter);
5369 }
5370
5371 (void)xmlTextWriterEndElement(pWriter);
5372}
5373
5374sal_uInt32 SwTextNode::GetRsid( sal_Int32 nStt, sal_Int32 nEnd ) const
5375{
5376 SfxItemSetFixed<RES_CHRATR_RSID, RES_CHRATR_RSID> aSet( const_cast<SwAttrPool&>((GetDoc().GetAttrPool())) );
5377 if (GetParaAttr(aSet, nStt, nEnd))
5378 {
5379 const SvxRsidItem* pRsid = aSet.GetItem<SvxRsidItem>(RES_CHRATR_RSID);
5380 if( pRsid )
5381 return pRsid->GetValue();
5382 }
5383
5384 return 0;
5385}
5386
5387sal_uInt32 SwTextNode::GetParRsid() const
5388{
5389 return reinterpret_cast<const SvxRsidItem&>(GetAttr( RES_PARATR_RSID )).GetValue();
5390}
5391
5392bool SwTextNode::CompareParRsid( const SwTextNode &rTextNode ) const
5393{
5394 sal_uInt32 nThisRsid = GetParRsid();
5395 sal_uInt32 nRsid = rTextNode.GetParRsid();
5396
5397 return nThisRsid == nRsid;
5398}
5399
5400bool SwTextNode::CompareRsid( const SwTextNode &rTextNode, sal_Int32 nStt1, sal_Int32 nStt2 ) const
5401{
5402 sal_uInt32 nThisRsid = GetRsid( nStt1, nStt1 );
5403 sal_uInt32 nRsid = rTextNode.GetRsid( nStt2, nStt2 );
5404
5405 return nThisRsid == nRsid;
5406}
5407
5408// sw::Metadatable
5410{
5411 return GetDoc().GetXmlIdRegistry();
5412}
5413
5415{
5416 return GetDoc().IsClipBoard();
5417}
5418
5420{
5421 return GetDoc().GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
5422}
5423
5425{
5426 return !GetDoc().IsInHeaderFooter( *this );
5427}
5428
5430{
5431 assert(!dynamic_cast<const sw::LegacyModifyHint*>(&rHint));
5433 CallSwClientNotify(rHint);
5434
5435 SwDoc& rDoc = GetDoc();
5436 // #125329# - assure that text node is in document nodes array
5437 if ( !rDoc.IsInDtor() && &rDoc.GetNodes() == &GetNodes() )
5438 {
5439 rDoc.GetNodes().UpdateOutlineNode(*this);
5440 }
5441}
5442
5443void SwTextNode::UpdateDocPos(const SwTwips nDocPos, const sal_uInt32 nIndex)
5444{
5445 const sw::DocPosUpdateAtIndex aHint(nDocPos, *this, nIndex);
5446 CallSwClientNotify(aHint);
5447}
5448
5450{
5451 const auto pOldValue = rHint.m_pOld;
5452 const auto pNewValue = rHint.m_pNew;
5453 {
5455
5456 // Override Modify so that deleting styles works properly (outline
5457 // numbering!).
5458 // Never call ChgTextCollUpdateNum for Nodes in Undo.
5459 if( pOldValue
5460 && pNewValue
5461 && RES_FMT_CHG == pOldValue->Which()
5462 && GetRegisteredIn() == static_cast<const SwFormatChg*>(pNewValue)->pChangedFormat
5463 && GetNodes().IsDocNodes() )
5464 {
5465 assert(dynamic_cast<SwTextFormatColl const*>(static_cast<const SwFormatChg*>(pOldValue)->pChangedFormat));
5466 assert(dynamic_cast<SwTextFormatColl const*>(static_cast<const SwFormatChg*>(pNewValue)->pChangedFormat));
5468 static_cast<const SwTextFormatColl*>(static_cast<const SwFormatChg*>(pOldValue)->pChangedFormat),
5469 static_cast<const SwTextFormatColl*>(static_cast<const SwFormatChg*>(pNewValue)->pChangedFormat) );
5470 }
5471
5472 // reset fill information
5473 if (maFillAttributes && pNewValue)
5474 {
5475 const sal_uInt16 nWhich = pNewValue->Which();
5476 bool bReset(RES_FMT_CHG == nWhich); // ..on format change (e.g. style changed)
5477
5478 if(!bReset && RES_ATTRSET_CHG == nWhich) // ..on ItemChange from DrawingLayer FillAttributes
5479 {
5480 SfxItemIter aIter(*static_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet());
5481
5482 for(const SfxPoolItem* pItem = aIter.GetCurItem(); pItem && !bReset; pItem = aIter.NextItem())
5483 {
5484 bReset = !IsInvalidItem(pItem) && pItem->Which() >= XATTR_FILL_FIRST && pItem->Which() <= XATTR_FILL_LAST;
5485 }
5486 }
5487
5488 if(bReset)
5489 {
5490 maFillAttributes.reset();
5491 }
5492 }
5493
5494 if ( !mbInSetOrResetAttr )
5495 {
5496 HandleModifyAtTextNode( *this, pOldValue, pNewValue );
5497 }
5498
5499 SwContentNode::SwClientNotify(*this, rHint);
5500
5501 SwDoc& rDoc = GetDoc();
5502 // #125329# - assure that text node is in document nodes array
5503 if ( !rDoc.IsInDtor() && &rDoc.GetNodes() == &GetNodes() )
5504 {
5505 rDoc.GetNodes().UpdateOutlineNode(*this);
5506 }
5507 }
5508
5509 if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which()))
5510 { // invalidate cached uno object
5511 SetXParagraph(nullptr);
5512 }
5513}
5514
5515void SwTextNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint )
5516{
5517 if (rHint.GetId() == SfxHintId::SwLegacyModify)
5518 {
5519 auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
5520 TriggerNodeUpdate(*pLegacyHint);
5521 }
5522 else if (dynamic_cast<const SwAttrHint*>(&rHint))
5523 {
5524 if (&rModify == GetRegisteredIn())
5525 ChkCondColl();
5526 }
5527}
5528
5529uno::Reference< rdf::XMetadatable >
5531{
5532 const uno::Reference<rdf::XMetadatable> xMeta(
5534 return xMeta;
5535}
5536
5538{
5539 // create SdrAllFillAttributesHelper on demand
5540 if(!maFillAttributes)
5541 {
5542 const_cast< SwTextNode* >(this)->maFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(GetSwAttrSet());
5543 }
5544
5545 return maFillAttributes;
5546}
5547
5549{
5550 m_wXParagraph = xParagraph.get();
5551}
5552
5553/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ IGNORE_FIRST_LINE_INDENT_IN_NUMBERING
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
FILE * init(int, char **)
sal_uInt16 GetValue() const
const OUString & GetValue() const
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
virtual SwList * getListByName(const OUString &rListId) const =0
virtual void assureSortedMarkContainers() const =0
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual std::shared_ptr< SfxItemSet > getAutomaticStyle(const SfxItemSet &rSet, SwAutoStyleFamily eFamily, const OUString *pParentName=nullptr)=0
const OUString & getViewText() const
sal_Int32 ConvertToViewPosition(sal_Int32 nModelPos) const
Converts a model position into a view position.
bool GetValue() const
const std::map< OUString, css::uno::Any > & GetGrabBag() const
SfxHintId GetId() const
sal_Int16 GetValue() const
const SfxPoolItem * GetCurItem() const
sal_uInt16 GetCurPos() const
const SfxPoolItem * NextItem()
void SetParent(const SfxItemSet *pNew)
void dumpAsXml(xmlTextWriterPtr pWriter) const
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
const SfxItemSet * GetParent() const
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
sal_uInt16 GetWhichByPos(sal_uInt16 nPos) const
sal_uInt16 Which() const
void SetTextFirstLineOffset(const short nF, const sal_uInt16 nProp=100)
short GetTextFirstLineOffset() const
rtl_TextEncoding GetCharSet() const
tools::Long GetIndentAt() const
sal_Int32 GetFirstLineOffset() const
tools::Long GetFirstLineIndent() const
sal_uInt16 GetStart() const
sal_Int32 GetAbsLSpace() const
LabelFollowedBy GetLabelFollowedBy() const
tools::Long GetListtabPos() const
SvxNumPositionAndSpaceMode GetPositionAndSpaceMode() const
OUString GetLabelFollowedByAsString() const
bool IsTextFormat() const
SvxNumType GetNumberingType() const
void SetTextLeft(const tools::Long nL, const sal_uInt16 nProp=100)
tools::Long GetLeft(SvxFirstLineIndentItem const &rFirstLine) const
tools::Long GetTextLeft() const
wrapper class for the positioning of Writer fly frames and drawing objects
const SwAttrSet * GetChgSet() const
What has changed.
Definition: hints.hxx:347
const SvxFirstLineIndentItem & GetFirstLineIndent(bool=true) const
Definition: frmatr.hxx:48
const SwDoc * GetDoc() const
Definition: swatrset.hxx:204
void CopyToModify(sw::BroadcastingModify &rMod) const
Definition: swatrset.cxx:251
const SvxTextLeftMarginItem & GetTextLeftMargin(bool=true) const
Definition: frmatr.hxx:46
Represents the style of a text portion.
Definition: charfmt.hxx:27
size_t size() const
Definition: charformats.hxx:71
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:59
Marks a character position inside a document model content node (SwContentNode)
const SwContentIndex * GetNext() const
sal_Int32 GetIndex() const
const SwContentNode * GetContentNode() const
SwRangeRedline * GetRedline() const
SwContentIndex & Assign(const SwContentNode *, sal_Int32)
Definition: index.cxx:206
void MakeFramesForAdjacentContentNode(SwContentNode &rNode)
Method creates all views of document for given node.
Definition: node.cxx:1381
SwFormatColl * GetFormatColl() const
Definition: node.hxx:497
virtual void SwClientNotify(const SwModify &, const SfxHint &rHint) override
Definition: node.cxx:1123
bool InvalidateNumRule()
Invalidates NumRule at the node.
Definition: node.cxx:1208
bool HasSwAttrSet() const
Definition: node.hxx:494
virtual SwContentFrame * MakeFrame(SwFrame *pSib)=0
MakeFrame will be called for a certain layout pSib is another SwFrame of the same layout (e....
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:727
bool CanJoinNext(SwNodeIndex *pIdx=nullptr) const
Is it possible to join two nodes? In pIdx the second position can be returned.
Definition: node.cxx:1844
void DelFrames(SwRootFrame const *pLayout)
Method deletes all views of document for the node.
Definition: node.cxx:1432
sal_uInt16 ClearItemsFromAttrSet(const std::vector< sal_uInt16 > &rWhichIds)
There some functions that like to remove items from the internal SwAttrSet (handle):
Definition: node.cxx:1786
std::shared_ptr< const SfxItemSet > mpAttrSet
Attribute-set for all auto attributes of a ContentNode.
Definition: node.hxx:413
virtual bool SetAttr(const SfxPoolItem &)
made virtual
Definition: node.cxx:1586
void ChkCondColl(const SwTextFormatColl *pColl=nullptr)
Definition: node.cxx:2022
bool CanJoinPrev(SwNodeIndex *pIdx=nullptr) const
Can we join two Nodes? We can return the 2nd position in pIdx.
Definition: node.cxx:1892
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:493
virtual SwContentNode * MakeCopy(SwDoc &, SwNode &rWhere, bool bNewFrames) const =0
virtual SwFormatColl * ChgFormatColl(SwFormatColl *)
Definition: node.cxx:1258
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: node.cxx:1679
const SfxPoolItem * GetNoCondAttr(sal_uInt16 nWhich, bool bInParents) const
Obtains attribute that is not delivered via conditional style!
Definition: node.cxx:1804
virtual sal_uInt16 ResetAllAttr()
Definition: node.cxx:1749
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:720
virtual void NewAttrSet(SwAttrPool &)=0
Make respective nodes create the specific AttrSets.
virtual bool IsChangeRecording() const override
passwword protection for Writer (derived from SfxObjectShell) see also: FN_REDLINE_ON,...
Definition: docsh.cxx:1341
Definition: doc.hxx:197
bool IsInReading() const
Definition: doc.hxx:969
bool IsCopyIsMove() const
Definition: doc.hxx:1390
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:645
bool IsInDtor() const
Definition: doc.hxx:417
void CorrAbs(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset=0, bool bMoveCursor=false)
Definition: doccorr.cxx:171
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2454
bool IsClipBoard() const
Definition: doc.hxx:978
const SwCharFormats * GetCharFormats() const
Definition: doc.hxx:755
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:158
SwNodes & GetNodes()
Definition: doc.hxx:422
IStyleAccess & GetIStyleAccess()
Definition: doc.hxx:772
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:349
::sfx2::IXmlIdRegistry & GetXmlIdRegistry()
Definition: docnew.cxx:820
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:419
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:649
SwCharFormat * CopyCharFormat(const SwCharFormat &)
copy the char format
Definition: docfmt.cxx:1184
const SwEndNoteInfo & GetEndNoteInfo() const
Definition: doc.hxx:647
void ResetAttrs(const SwPaM &rRg, bool bTextAttr=true, const o3tl::sorted_vector< sal_uInt16 > &rAttrs=o3tl::sorted_vector< sal_uInt16 >(), const bool bSendDataChangedEvents=true, SwRootFrame const *pLayout=nullptr)
Reset attributes.
Definition: docfmt.cxx:249
const SwFormatRefMark * GetRefMark(std::u16string_view rName) const
Definition: doc.cxx:1060
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1337
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
IDocumentListsAccess const & getIDocumentListsAccess() const
Definition: doc.cxx:307
bool IsInHeaderFooter(const SwNode &) const
Definition: doclay.cxx:1582
SvxNumberType m_aFormat
Definition: ftninfo.hxx:46
SwFieldIds Which() const
Definition: fldbas.hxx:276
SwFieldType * GetTyp() const
Definition: fldbas.hxx:402
Represents one footnote or endnote in the layout.
Definition: ftnfrm.hxx:84
const SwFootnoteFrame * GetFollow() const
Definition: ftnfrm.hxx:120
void SetRef(SwContentFrame *pNew)
Definition: ftnfrm.hxx:131
const SwFootnoteFrame * GetMaster() const
Definition: ftnfrm.hxx:123
const SwTextFootnote * GetAttr() const
Definition: ftnfrm.hxx:126
const SwContentFrame * GetRef() const
Definition: ftnfrm.cxx:2909
void UpdateFootnote(const SwNode &rStt)
Definition: ftnidx.cxx:59
SwFootnoteNum m_eNum
Definition: ftninfo.hxx:98
FlyAnchors.
Definition: fmtanchr.hxx:37
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:74
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1614
const std::shared_ptr< SfxItemSet > & GetStyleHandle() const
Definition: fmtautofmt.hxx:49
SwCharFormat * GetCharFormat() const
Definition: fchrfmt.hxx:70
SwFormatColl is just an SwFormat subclass that defaults to m_bAutoFormat=false, expressing that this ...
Definition: fmtcol.hxx:38
const SwField * GetField() const
Definition: fmtfld.hxx:131
SwFrameFormat * GetFrameFormat() const
Definition: fmtflcnt.hxx:45
SfxPoolItem subclass for footnotes and endnotes, stored in the anchor text node.
Definition: fmtftn.hxx:47
sal_uInt16 GetNumber() const
Definition: fmtftn.hxx:73
const OUString & GetNumStr() const
Definition: fmtftn.hxx:72
sal_uInt16 GetNumberRLHidden() const
Definition: fmtftn.hxx:74
bool IsEndNote() const
Definition: fmtftn.hxx:75
const OUString & GetINetFormat() const
Definition: fmtinfmt.hxx:102
const OUString & GetVisitedFormat() const
Definition: fmtinfmt.hxx:120
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:36
OUString & GetRefName()
Definition: fmtrfmrk.hxx:63
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
const OUString & GetName() const
Definition: format.hxx:131
const SwNumRuleItem & GetNumRule(bool=true) const
Definition: paratr.hxx:241
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
SwFormat * DerivedFrom() const
Definition: format.hxx:128
Style of a layout element.
Definition: frmfmt.hxx:72
virtual void DelFrames()
Destroys all Frames in aDepend (Frames are identified via dynamic_cast).
Definition: atrfrm.cxx:2733
Base class of the Writer layout elements.
Definition: frame.hxx:315
void InvalidatePos_()
Definition: frame.hxx:793
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame,...
Definition: findfrm.cxx:762
SwRootFrame * getRootFrame()
Definition: frame.hxx:685
SwPageFrame * FindPageFrame()
Definition: frame.hxx:686
SwFootnoteFrame * FindFootnoteFrame()
Definition: frame.hxx:1113
TElementType * Next()
Definition: calbck.hxx:380
TElementType * First()
Definition: calbck.hxx:372
const SwContentFrame * ContainsContent() const
Checks if the frame contains one or more ContentFrame's anywhere in his subsidiary structure; if so t...
Definition: findfrm.cxx:72
Definition: list.hxx:40
void InsertListItem(SwNodeNum &rNodeNum, SwListRedlineType eRedlines, const int nLevel, const SwDoc &rDoc)
Definition: list.cxx:89
static void RemoveListItem(SwNodeNum &rNodeNum, const SwDoc &rDoc)
Definition: list.cxx:114
bool IsListLevelMarked(const int nListLevel) const
Definition: list.cxx:170
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
SwNumRule * GetNumRule() const
Definition: SwNodeNum.hxx:38
Base class of the Writer document model elements.
Definition: node.hxx:98
bool IsIgnoreDontExpand() const
Definition: node.hxx:163
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwSectionNode * GetSectionNode()
Definition: node.hxx:658
void SetIgnoreDontExpand(bool bNew)
Definition: node.hxx:164
SwNodeOffset GetIndex() const
Definition: node.hxx:312
void resetAndQueueAccessibilityCheck()
Definition: node.cxx:2182
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:706
SwDoc & GetDoc()
Definition: node.hxx:233
Merge
sw_redlinehide: redline node merge state
Definition: node.hxx:111
bool IsInRedlines() const
Checks if this node is in redlines.
Definition: node.cxx:2155
bool IsEndNode() const
Definition: node.hxx:189
bool IsStartNode() const
Definition: node.hxx:187
SwNodeOffset StartOfSectionIndex() const
Definition: node.hxx:687
void SetRedlineMergeFlag(Merge const eMerge)
Definition: node.hxx:115
bool IsSectionNode() const
Definition: node.hxx:192
bool IsTableNode() const
Definition: node.hxx:191
bool IsTextNode() const
Definition: node.hxx:190
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:968
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
const IDocumentMarkAccess * getIDocumentMarkAccess() const
Provides access to the document bookmark interface.
Definition: node.cxx:2152
Merge GetRedlineMergeFlag() const
Definition: node.hxx:116
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
bool IsCreateFrameWhenHidingRedlines() const
Definition: node.hxx:112
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwNodeType GetNodeType() const
Definition: node.hxx:166
std::vector< SwFrameFormat * > const & GetAnchoredFlys() const
Definition: node.hxx:318
const IDocumentSettingAccess * getIDocumentSettingAccess() const
Provides access to the document setting interface.
Definition: node.cxx:2138
SwTextNode * MakeTextNode(SwNode &rWhere, SwTextFormatColl *pColl, bool bNewFrames=true)
Implementations of "Make...Node" are in the given .cxx-files.
Definition: ndtxt.cxx:121
bool IsDocNodes() const
Is the NodesArray the regular one of Doc? (and not the UndoNds, ...) Implementation in doc....
Definition: nodes.cxx:2555
void Delete(const SwNodeIndex &rPos, SwNodeOffset nNodes=SwNodeOffset(1))
Definition: nodes.cxx:1070
void UpdateOutlineNode(SwNode &rNd)
Update all Nodes - Rule/Format-Change.
Definition: ndnum.cxx:39
SwDoc & GetDoc()
Which Doc contains the nodes-array?
Definition: ndarr.hxx:307
SwNode * FindPrvNxtFrameNode(const SwNode &rFrameNd, const SwNode *pEnd, SwRootFrame const *pLayout=nullptr) const
Search previous / next content node or table node with frames.
Definition: nodes.cxx:2188
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:2064
bool IsEnumeration() const
Definition: number.cxx:237
bool IsItemize() const
Definition: number.cxx:245
bool IsOutlineRule() const
Definition: numrule.hxx:241
const SwNumFormat * GetNumFormat(sal_uInt16 i) const
Definition: number.cxx:97
const OUString & GetDefaultListId() const
Definition: numrule.hxx:194
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:87
const OUString & GetName() const
Definition: numrule.hxx:224
static OUString GetOutlineRuleName()
Definition: number.cxx:82
OUString MakeNumString(const SwNodeNum &, bool bInclStrings=true) const
Definition: number.cxx:643
bool IsAbsSpaces() const
Definition: numrule.hxx:238
int GetLevelInListTree() const
Return level of this node.
bool IsFirst(const SwNumberTreeNode *pNode) const
Return if a node is first non-phantom child of this node.
void SetLevelInListTree(const int nLevel, const SwDoc &rDoc)
set level of this node
void NotifyInvalidSiblings(const SwDoc &rDoc)
Notifies all invalid siblings of this node.
SwNumberTreeNode * GetParent() const
Returns the parent of this node.
void InvalidateMe()
Notifies the node.
void InvalidateAndNotifyTree(const SwDoc &rDoc)
Invalidation and notification of complete numbering tree.
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
const SwPosition * End() const
Definition: pam.hxx:263
const SwPosition * GetPoint() const
Definition: pam.hxx:253
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
A page of the document layout.
Definition: pagefrm.hxx:60
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1975
static void LOKRedlineNotification(RedlineNotification eType, SwRangeRedline *pRedline)
Emits LOK notification about one addition / removal of a redline item.
Definition: docredln.cxx:344
static constexpr size_type npos
Definition: docary.hxx:224
size_type size() const
Definition: docary.hxx:268
vector_type::size_type size_type
Definition: docary.hxx:223
The root element of a Writer document layout.
Definition: rootfrm.hxx:85
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding).
Definition: rootfrm.hxx:434
static bool GetBoundsOfHiddenRange(const SwTextNode &rNode, sal_Int32 nPos, sal_Int32 &rnStartPos, sal_Int32 &rnEndPos, std::vector< sal_Int32 > *pList=nullptr)
Hidden text range information - static and non-version.
Definition: porlay.cxx:2025
static sal_Int32 MaskHiddenRanges(const SwTextNode &rNode, OUStringBuffer &rText, const sal_Int32 nStt, const sal_Int32 nEnd, const sal_Unicode cChar)
Hidden text attribute handling.
Definition: porlay.cxx:1971
A section node represents the start of a section on the UI, i.e.
Definition: node.hxx:575
const SwSection & GetSection() const
Definition: node.hxx:590
bool IsHiddenFlag() const
Definition: section.hxx:190
bool IsHidden() const
Definition: section.hxx:181
Represents the current text cursor of one opened edit window.
Definition: viscrs.hxx:140
class for collecting anchored objects
Definition: sortedobjs.hxx:49
void UpdateAll()
Definition: sortedobjs.cxx:272
static void FillProgName(const OUString &rName, OUString &rFillName, SwGetPoolIdFromName)
bool IsIntrnlName() const
Definition: cellfml.hxx:131
void PtrToBoxNm(const SwTable *pTable)
create from the internal formula (for CORE) the external formula (for UI)
Definition: cellfml.cxx:580
const SwTable & GetTable() const
Definition: node.hxx:542
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
static void Destroy(SwTextAttr *pToDestroy, SfxItemPool &rPool)
destroy instance
Definition: txatbase.cxx:58
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:167
virtual const sal_Int32 * GetEnd() const
end position
Definition: txatbase.cxx:48
const SwFormatRefMark & GetRefMark() const
Definition: txatbase.hxx:238
bool IsFormatIgnoreStart() const
Definition: txatbase.hxx:108
const sal_Int32 * End() const
Definition: txatbase.hxx:156
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: txatbase.cxx:89
const SwFormatFlyCnt & GetFlyCnt() const
Definition: txatbase.hxx:226
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:208
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
const SwFormatINetFormat & GetINetFormat() const
Definition: txatbase.hxx:244
const SwFormatCharFormat & GetCharFormat() const
Definition: txatbase.hxx:187
virtual void SetEnd(sal_Int32)
Definition: txatbase.cxx:53
void SetStart(sal_Int32 n)
start position
Definition: txatbase.hxx:87
bool IsDontMoveAttr() const
Definition: txatbase.hxx:100
bool IsCharFormatAttr() const
Definition: txatbase.hxx:101
bool DontExpand() const
Definition: txatbase.hxx:98
const SwFormatAutoFormat & GetAutoFormat() const
Definition: txatbase.hxx:193
void SetDontExpand(bool bDontExpand)
Definition: txatbase.hxx:179
bool HasDummyChar() const
Definition: txatbase.hxx:107
bool IsDontExpandStartAttr() const
Definition: txatbase.hxx:105
sal_uInt16 Which() const
Definition: txatbase.hxx:116
bool IsLockExpandFlag() const
Definition: txatbase.hxx:99
bool IsFormatIgnoreEnd() const
Definition: txatbase.hxx:109
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
SwTextAttr subclass for footnotes and endnotes.
Definition: txtftn.hxx:34
const SwNodeIndex * GetStartNode() const
Definition: txtftn.hxx:43
Represents the style of a paragraph.
Definition: fmtcol.hxx:61
bool IsAssignedToListLevelOfOutlineStyle() const
Definition: fmtcol.hxx:122
SwTextFormatColl & GetNextTextFormatColl() const
Definition: fmtcol.hxx:106
int GetAssignedOutlineStyleLevel() const
Definition: fmtcol.cxx:678
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
SwTextAttr subclass that tracks the location of the wrapped SwFormatURL.
Definition: txtinet.hxx:30
void ChgTextNode(SwTextNode *pNew)
Definition: txtinet.hxx:49
SwCharFormat * GetCharFormat()
Definition: txtatr2.cxx:111
const SwTextNode * GetpTextNode() const
Definition: txtinet.hxx:46
void UpdateFieldContent()
Definition: atrfld.cxx:722
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
bool HasBullet() const
Returns if this text node has a bullet.
Definition: ndtxt.cxx:3229
OUString m_Text
Definition: ndtxt.hxx:129
OUString GetExpandText(SwRootFrame const *pLayout, const sal_Int32 nIdx=0, const sal_Int32 nLen=-1, const bool bWithNum=false, const bool bAddSpaceAfterListLabelStr=false, const bool bWithSpacesForLevel=false, const ExpandMode eAdditionalMode=ExpandMode::ExpandFootnote|ExpandMode::HideFieldmarkCommands) const
add 4th optional parameter <bAddSpaceAfterListLabelStr> indicating, when <bWithNum = true> that a spa...
Definition: ndtxt.cxx:3505
SwTextAttr * GetTextAttrForEndCharAt(sal_Int32 nIndex, sal_uInt16 nWhich) const
Get the text attribute of an end dummy character at nIndex.
Definition: ndtxt.cxx:3180
bool IsEmptyListStyleDueToSetOutlineLevelAttr() const
Definition: ndtxt.hxx:658
void SetAttrListLevel(int nLevel)
Sets the list level of this text node.
Definition: ndtxt.cxx:4218
SwNumberTree::tSwNumTreeNumber GetAttrListRestartValue() const
Definition: ndtxt.cxx:4332
const SwTextInputField * GetOverlappingInputField(const SwTextAttr &rTextAttr) const
Definition: ndtxt.cxx:1822
void SetWrongDirty(sw::WrongState eNew) const
Definition: txtedt.cxx:2345
void DoNum(std::function< void(SwNodeNum &)> const &)
Definition: ndtxt.cxx:4104
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
sal_Int32 GetSpaceLeft() const
Definition: ndtxt.hxx:918
SwNumberTree::tSwNumTreeNumber GetActualListStartValue() const
Definition: ndtxt.cxx:4342
tools::Long GetLeftMarginWithNum(bool bTextLeft=false) const
Returns the additional indents of this text node and its numbering.
Definition: ndtxt.cxx:3277
void SetAttrOutlineLevel(int nLevel)
Sets the out line level at a text node.
Definition: ndtxt.cxx:4173
SAL_DLLPRIVATE void CopyAttr(SwTextNode *pDest, const sal_Int32 nStart, const sal_Int32 nOldPos)
Copies the attributes at nStart to pDest.
Definition: ndtxt.cxx:2009
SwNumberTree::tNumberVector GetNumberVector(SwRootFrame const *pLayout=nullptr, SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Definition: ndtxt.cxx:4125
SwWrongList * GetSmartTags()
Definition: txtedt.cxx:2325
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: ndtxt.cxx:5515
bool m_bRecalcHiddenCharFlags
The last two flags have to be recalculated if this flag is set:
Definition: ndtxt.hxx:139
SAL_DLLPRIVATE void MoveTextAttr_To_AttrSet()
Move all comprising hard attributes to the AttrSet of the paragraph.
Definition: ndtxt.cxx:814
SwpHints & GetOrCreateSwpHints()
Definition: ndtxt.hxx:878
virtual SwContentNode * JoinNext() override
Definition: ndtxt.cxx:1002
void ResetEmptyListStyleDueToResetOutlineLevelAttr()
Definition: ndtxt.cxx:4209
bool GetParaAttr(SfxItemSet &rSet, sal_Int32 nStt, sal_Int32 nEnd, const bool bOnlyTextAttr=false, const bool bGetFromChrFormat=true, const bool bMergeIndentValuesOfNumRule=false, SwRootFrame const *pLayout=nullptr) const
Query the attributes of textnode over the range.
Definition: thints.cxx:2140
virtual SwContentFrame * MakeFrame(SwFrame *) override
Virtual methods from ContentNode.
Definition: ndtxt.cxx:285
void FileLoadedInitHints()
initialize the hints after file loading (which takes shortcuts)
Definition: ndtxt.cxx:277
void UpdateDocPos(const SwTwips nDocPos, const sal_uInt32 nIndex)
Definition: ndtxt.cxx:5443
bool IsFirstOfNumRule(SwRootFrame const &rLayout) const
Definition: ndtxt.cxx:4551
void ClearSmartTags()
Definition: txtedt.cxx:2315
void CutText(SwTextNode *const pDest, const SwContentIndex &rStart, const sal_Int32 nLen)
Definition: ndtxt.cxx:2496
bool GetListTabStopPosition(tools::Long &nListTabStopPosition) const
Retrieves the list tab stop position, if the paragraph's list level defines one and this list tab sto...
Definition: ndtxt.cxx:4691
void DeleteAttribute(SwTextAttr *const pTextAttr)
delete the attribute pTextAttr
Definition: thints.cxx:1763
SwContentNode * AppendNode(const SwPosition &)
Definition: ndtxt.cxx:3130
bool HasVisibleNumberingOrBullet() const
Returns if the paragraph has a visible numbering or bullet.
Definition: ndtxt.cxx:4284
std::unique_ptr< SwNodeNum > mpNodeNum
Numbering for this paragraph.
Definition: ndtxt.hxx:125
void DestroyAttr(SwTextAttr *pAttr)
Definition: thints.cxx:1186
OUString GetListId() const
Definition: ndtxt.cxx:4580
void GCAttr()
Definition: ndtxt.cxx:2875
virtual SAL_DLLPRIVATE void NewAttrSet(SwAttrPool &) override
Create the specific AttrSet.
Definition: ndtxt.cxx:1217
bool IsHiddenByParaField() const
is the paragraph visible?
Definition: ndtxt.hxx:769
sal_uInt32 GetParRsid() const
Definition: ndtxt.cxx:5387
SwTextAttr * InsertItem(SfxPoolItem &rAttr, const sal_Int32 nStart, const sal_Int32 nEnd, const SetAttrMode nMode=SetAttrMode::DEFAULT)
create new text attribute from rAttr and insert it
Definition: thints.cxx:1305
void FormatToTextAttr(SwTextNode *pNd)
Convey attributes of an AttrSet (AutoFormat) to SwpHintsArray.
Definition: thints.cxx:2539
bool AreListLevelIndentsApplicableImpl(sal_uInt16 nWhich) const
Definition: ndtxt.cxx:4628
::sw::ListLevelIndents AreListLevelIndentsApplicable() const
Determines, if the list level indent attributes can be applied to the paragraph.
Definition: ndtxt.cxx:4614
SwTextField * GetFieldTextAttrAt(const sal_Int32 nIndex, ::sw::GetTextAttrMode const eMode=::sw::GetTextAttrMode::Expand) const
Definition: ndtxt.cxx:1849
void TryDeleteSwpHints()
Definition: ndtxt.hxx:887
virtual bool IsInUndo() const override
Is this node in the undo array?
Definition: ndtxt.cxx:5419
void SetListRestart(bool bRestart)
Definition: ndtxt.cxx:4257
SwWrongList * GetWrong()
Definition: txtedt.cxx:2271
void JoinPrev()
Definition: ndtxt.cxx:1119
void CopyText(SwTextNode *const pDest, const SwContentIndex &rStart, const sal_Int32 nLen, const bool bForceCopyOfAllAttrs)
Actions on text and attributes.
Definition: ndtxt.cxx:2069
void HandleNonLegacyHint(const SfxHint &)
Definition: ndtxt.cxx:5429
sal_uInt32 GetRsid(sal_Int32 nStt, sal_Int32 nEnd) const
Definition: ndtxt.cxx:5374
OUString GetLabelFollowedBy() const
Retrieves the character following the list label, if the paragraph's list level defines one.
Definition: ndtxt.cxx:4725
const SfxPoolItem & GetAttr(sal_uInt16 nWhich, bool bInParent=true) const
End: Data collected during idle time.
Definition: node.hxx:732
int GetAttrListLevel() const
Definition: ndtxt.cxx:4237
bool IsOutline() const
Returns if this text node is an outline.
Definition: ndtxt.cxx:4138
void SetWordCountDirty(bool bNew) const
Definition: txtedt.cxx:2335
void SetGrammarCheckDirty(bool bNew) const
Definition: txtedt.cxx:2360
std::optional< OUString > m_oNumStringCache
Definition: ndtxt.hxx:154
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:5066
virtual bool IsInClipboard() const override
Definition: ndtxt.cxx:5414
void SetSmartTags(std::unique_ptr< SwWrongList > pNew)
Definition: txtedt.cxx:2307
void SetSmartTagDirty(bool bNew) const
Definition: txtedt.cxx:2370
const SwNodeNum * GetNum(SwRootFrame const *pLayout=nullptr, SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Definition: ndtxt.cxx:4095
bool IsInList() const
Definition: ndtxt.cxx:4546
std::unique_ptr< SwpHints > m_pSwpHints
May be 0.
Definition: ndtxt.hxx:123
bool HasAttrListLevel() const
Definition: ndtxt.cxx:4231
void EraseText(const SwContentIndex &rIdx, const sal_Int32 nCount=SAL_MAX_INT32, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
delete text content ATTENTION: must not be called with a range that overlaps the start of an attribut...
Definition: ndtxt.cxx:2777
void ClearGrammarCheck()
Definition: txtedt.cxx:2287
virtual SwFormatColl * ChgFormatColl(SwFormatColl *) override
Definition: ndtxt.cxx:4060
bool HasHints() const
Definition: ndtxt.hxx:254
void SetAutoCompleteWordDirty(bool bNew) const
Definition: txtedt.cxx:2380
bool m_bContainsHiddenChars
Some of the chars this para are hidden.
Definition: ndtxt.hxx:135
void ClearWrong()
Definition: txtedt.cxx:2261
virtual ~SwTextNode() override
Definition: ndtxt.cxx:242
SAL_DLLPRIVATE SwTextNode(SwNode &rWhere, SwTextFormatColl *pTextColl, const SfxItemSet *pAutoAttr=nullptr)
Definition: ndtxt.cxx:203
void GetAttrOutlineContentVisible(bool &bOutlineContentVisibleAttr)
GetAttrOutlineContentVisible.
Definition: ndtxt.cxx:4183
unotools::WeakReference< SwXParagraph > m_wXParagraph
Definition: ndtxt.hxx:156
std::unique_ptr< SwWrongList > ReleaseSmartTags()
Definition: txtedt.cxx:2320
bool IsCountedInList() const
Definition: ndtxt.cxx:4393
void AddToListOrig()
Definition: ndtxt.cxx:4494
virtual ::sfx2::IXmlIdRegistry & GetRegistry() override
sfx2::Metadatable
Definition: ndtxt.cxx:5409
void SetCountedInList(bool bCounted)
Definition: ndtxt.cxx:4378
OUString InsertText(const OUString &rStr, const SwContentIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2372
bool CompareParRsid(const SwTextNode &rTextNode) const
Definition: ndtxt.cxx:5392
void SetCalcHiddenCharFlags() const
Definition: ndtxt.hxx:781
void SetListId(OUString const &rListId)
Definition: ndtxt.cxx:4562
void RemoveFromList()
Definition: ndtxt.cxx:4508
void ReplaceText(const SwContentIndex &rStart, const sal_Int32 nDelLen, const OUString &rText)
replace nDelLen characters at rStart with rText in case the replacement does not fit,...
Definition: ndtxt.cxx:3808
SwpHints & GetSwpHints()
getters for SwpHints
Definition: ndtxt.hxx:867
void UpdateOutlineState()
Definition: ndtxt.cxx:4163
bool m_bHiddenCharsHidePara
The whole paragraph is hidden because of the hidden text attribute.
Definition: ndtxt.hxx:137
SwTwips GetAdditionalIndentForStartingNewList() const
Definition: ndtxt.cxx:3377
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2921
bool m_bInUndo
Is an undo operation in progress?
Definition: ndtxt.hxx:152
bool HasNumber(SwRootFrame const *pLayout=nullptr) const
Returns if this text node has a number.
Definition: ndtxt.cxx:3213
int GetActualListLevel(SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4248
bool HasAttrListRestartValue() const
Definition: ndtxt.cxx:4327
bool IsListRestart() const
Definition: ndtxt.cxx:4273
bool m_bLastOutlineState
Definition: ndtxt.hxx:141
virtual bool IsInContent() const override
Definition: ndtxt.cxx:5424
drawinglayer::attribute::SdrAllFillAttributesHelperPtr maFillAttributes
Definition: ndtxt.hxx:159
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2989
bool IsNotificationEnabled() const
Checks some global conditions like loading or destruction of document to economize notifications.
Definition: ndtxt.cxx:4372
std::unique_ptr< SwGrammarMarkUp > ReleaseGrammarCheck()
Definition: txtedt.cxx:2292
SwGrammarMarkUp * GetGrammarCheck()
Definition: txtedt.cxx:2297
bool mbEmptyListStyleSetDueToSetOutlineLevelAttr
Definition: ndtxt.hxx:144
void AddToList()
Definition: ndtxt.cxx:4423
bool IsOutlineStateChanged() const
Definition: ndtxt.cxx:4158
int GetAttrOutlineLevel() const
Returns outline level of this text node.
Definition: ndtxt.cxx:4168
void DelFrames_TextNodePart()
Definition: ndtxt.cxx:1834
void SetAttrListRestartValue(SwNumberTree::tSwNumTreeNumber nNum)
Definition: ndtxt.cxx:4306
bool GetFirstLineOfsWithNum(short &rFirstOffset) const
Returns the combined first line indent of this text node and its numbering.
Definition: ndtxt.cxx:3334
void RemoveFromListOrig()
Definition: ndtxt.cxx:4534
virtual css::uno::Reference< css::rdf::XMetadatable > MakeUnoObject() override
Definition: ndtxt.cxx:5530
virtual drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const override
Definition: ndtxt.cxx:5537
tools::Long GetLeftMarginForTabCalculation() const
return left margin for tab stop position calculation
Definition: ndtxt.cxx:3430
SAL_DLLPRIVATE void CutImpl(SwTextNode *const pDest, const SwContentIndex &rDestStart, const SwContentIndex &rStart, sal_Int32 nLen, const bool bUpdate=true)
Definition: ndtxt.cxx:2504
virtual void Update(SwContentIndex const &rPos, const sal_Int32 nChangeLen, UpdateMode eMode) override
override SwContentIndexReg
Definition: ndtxt.cxx:1251
bool CopyExpandText(SwTextNode &rDestNd, const SwContentIndex *pDestIdx, sal_Int32 nIdx, sal_Int32 nLen, SwRootFrame const *pLayout, bool bWithNum=false, bool bWithFootnote=true, bool bReplaceTabsWithSpaces=false) const
Definition: ndtxt.cxx:3558
bool IsHidden() const
Definition: ndtxt.cxx:4749
bool CompareRsid(const SwTextNode &rTextNode, sal_Int32 nStt1, sal_Int32 nStt2) const
Definition: ndtxt.cxx:5400
OUString GetNumString(const bool _bInclPrefixAndSuffixStrings=true, const unsigned int _nRestrictToThisLevel=MAXLEVEL, SwRootFrame const *pLayout=nullptr, SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Returns outline of numbering string.
Definition: ndtxt.cxx:3247
std::vector< SwTextAttr * > GetTextAttrsAt(sal_Int32 const nIndex, sal_uInt16 const nWhich) const
get the innermost text attributes covering position nIndex.
Definition: ndtxt.cxx:1795
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override
Dumps the node structure to the given destination (file nodes.xml in the current directory by default...
Definition: ndtxt.cxx:5335
bool HasMarkedLabel() const
Returns if this text node has a marked label.
Definition: ndtxt.cxx:2995
SwTextNode * SplitContentNode(const SwPosition &, std::function< void(SwTextNode *, sw::mark::RestoreMode, bool AtStart)> const *pContentIndexRestore)
Definition: ndtxt.cxx:428
SwTextAttr * GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, ::sw::GetTextAttrMode const eMode=::sw::GetTextAttrMode::Default) const
get the innermost text attribute covering position nIndex.
Definition: ndtxt.cxx:1804
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:252
void SetWrong(std::unique_ptr< SwWrongList > pNew)
Definition: txtedt.cxx:2256
const OUString & GetText() const
Definition: ndtxt.hxx:244
bool mbInSetOrResetAttr
boolean, indicating that a <SetAttr(..)> or <ResetAttr(..)> or <ResetAllAttr(..)> method is running.
Definition: ndtxt.hxx:149
void TriggerNodeUpdate(const sw::LegacyModifyHint &)
for hanging TextFormatCollections somewhere else (Outline-Numbering!)
Definition: ndtxt.cxx:5449
SAL_DLLPRIVATE void CalcHiddenCharFlags() const
Definition: ndtxt.cxx:4740
void AddToListRLHidden()
Definition: ndtxt.cxx:4480
SAL_DLLPRIVATE SwTextNode * MakeNewTextNode(SwNode &, bool bNext=true, bool bChgFollow=true)
Definition: ndtxt.cxx:3009
void SetEmptyListStyleDueToSetOutlineLevelAttr()
Definition: ndtxt.cxx:4200
void RemoveFromListRLHidden()
Definition: ndtxt.cxx:4522
bool InsertHint(SwTextAttr *const pAttr, const SetAttrMode nMode=SetAttrMode::DEFAULT)
Insert pAttr into hints array.
Definition: thints.cxx:1340
bool HasHiddenCharAttribute(bool bWholePara) const
Hidden Paragraph Field:
Definition: ndtxt.hxx:774
SAL_DLLPRIVATE void SetXParagraph(rtl::Reference< SwXParagraph > const &xParagraph)
Definition: ndtxt.cxx:5548
void SetAttrOutlineContentVisible(bool bVisible)
Definition: ndtxt.cxx:4191
bool IsNotifiable() const
Checks a temporary notification blocker and the global conditions of IsNotificationEnabled()
Definition: ndtxt.cxx:4367
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3474
void SetGrammarCheck(std::unique_ptr< SwGrammarMarkUp > pNew)
Definition: txtedt.cxx:2282
OUString GetRedlineText() const
Definition: ndtxt.cxx:3737
SwTextAttr * GetTextAttrForCharAt(const sal_Int32 nIndex, const sal_uInt16 nWhich=RES_TXTATR_END) const
get the text attribute at position nIndex which owns the dummy character CH_TXTATR_* at that position...
Definition: ndtxt.cxx:3155
bool DontExpandFormat(sal_Int32 nContentIdx, bool bFlag=true, bool bFormatToTextAttributes=true)
When appropriate set DontExpand-flag at INet or character styles respectively.
Definition: ndtxt.cxx:1681
bool m_bNotifiable
Definition: ndtxt.hxx:142
std::unique_ptr< SwNodeNum > mpNodeNumOrig
Numbering for this paragraph (before changes)
Definition: ndtxt.hxx:127
void ChgTextCollUpdateNum(const SwTextFormatColl *pOld, const SwTextFormatColl *pNew)
Definition: ndtxt.cxx:1647
std::unique_ptr< SwWrongList > ReleaseWrong()
Definition: txtedt.cxx:2266
void NumRuleChgd()
Notify this textnode that its numbering rule has changed.
Definition: ndtxt.cxx:2961
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:895
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5293
virtual sal_uInt16 ResetAllAttr() override
Definition: ndtxt.cxx:5321
std::unique_ptr< SwNodeNum > mpNodeNumRLHidden
Numbering for this paragraph (hidden redlines)
Definition: ndtxt.hxx:126
void SetInSwUndo(bool bInUndo)
Definition: ndtxt.cxx:5094
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
static rtl::Reference< SwXParagraph > CreateXParagraph(SwDoc &rDoc, SwTextNode *pTextNode, css::uno::Reference< css::text::XText > const &xParentText=nullptr, const sal_Int32 nSelStart=-1, const sal_Int32 nSelEnd=- 1)
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
size_t GetFirstPosSortedByWhichAndStart(sal_uInt16 nWhich) const
Definition: ndhints.cxx:458
bool Contains(const SwTextAttr *pHt) const
Definition: ndhints.cxx:169
void Delete(SwTextAttr const *pTextHt)
Delete the given Hint. The Hint must actually be in the array!
Definition: thints.cxx:3429
size_t Count() const
Definition: ndhints.hxx:142
void SetInSplitNode(bool bInSplit)
Definition: ndhints.hxx:109
SwTextAttr * GetSortedByWhichAndStart(size_t nPos) const
Definition: ndhints.hxx:167
bool empty() const
std::pair< const_iterator, bool > insert(Value &&x)
void InvalidateInSwCache(const sal_uInt16)
text is moved into pDestNode
Definition: hints.hxx:85
ring_container GetRingContainer()
Definition: ring.hxx:240
TextNodeNotificationSuppressor(SwTextNode &rNode)
Definition: ndtxt.cxx:95
static std::shared_ptr< ContentIdxStore > Create()
virtual bool IsExpanded() const =0
virtual const SwPosition & GetMarkEnd() const =0
virtual const SwPosition & GetMarkStart() const =0
int nCount
struct _xmlTextWriter * xmlTextWriterPtr
virtual OUString GetName() const override
float u
@ FTNNUM_CHAPTER
Definition: ftninfo.hxx:87
constexpr TypedWhichId< SfxStringItem > RES_FRMATR_STYLE_NAME(134)
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:184
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_REMOVE_UNO_OBJECT(181)
#define CH_TXT_ATR_INPUTFIELDSTART
Definition: hintids.hxx:178
constexpr TypedWhichId< SvxFormatKeepItem > RES_KEEP(116)
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:181
constexpr TypedWhichId< SfxStringItem > RES_PARATR_LIST_ID(RES_PARATR_LIST_BEGIN)
bool isTXTATR_WITHEND(const sal_uInt16 nWhich)
Definition: hintids.hxx:472
bool isTXTATR(const sal_uInt16 nWhich)
Definition: hintids.hxx:480
constexpr TypedWhichId< SwFormatFootnote > RES_TXTATR_FTN(59)
bool isCHRATR(const sal_uInt16 nWhich)
Definition: hintids.hxx:468
constexpr sal_uInt16 RES_CHRATR_END(46)
constexpr TypedWhichId< SvxFirstLineIndentItem > RES_MARGIN_FIRSTLINE(91)
constexpr sal_uInt16 RES_UNKNOWNATR_END(160)
constexpr TypedWhichId< SwConditionTextFormatColl > RES_CONDTXTFMTCOLL(166)
constexpr sal_uInt16 RES_TXTATR_WITHEND_END(57)
constexpr TypedWhichId< SfxInt16Item > RES_PARATR_LIST_LEVEL(83)
constexpr TypedWhichId< SwFormatAutoFormat > RES_TXTATR_AUTOFMT(50)
constexpr TypedWhichId< SfxStringItem > RES_FRMATR_CONDITIONAL_STYLE_NAME(135)
constexpr TypedWhichId< SfxInt16Item > RES_PARATR_LIST_RESTARTVALUE(85)
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(99)
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(111)
constexpr TypedWhichId< SvxEscapementItem > RES_CHRATR_ESCAPEMENT(6)
constexpr TypedWhichId< SwAttrSetChg > RES_ATTRSET_CHG(169)
constexpr sal_uInt16 RES_TXTATR_BEGIN(RES_CHRATR_END)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(60)
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
constexpr TypedWhichId< SfxStringItem > HINT_END(RES_TBX_DUMMY)
constexpr TypedWhichId< SwNumRuleItem > RES_PARATR_NUMRULE(72)
constexpr TypedWhichId< SwFormatContentControl > RES_TXTATR_CONTENTCONTROL(56)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwFormatCharFormat > RES_TXTATR_CHARFMT(52)
constexpr sal_uInt16 RES_UNKNOWNATR_BEGIN(RES_BOXATR_END)
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(58)
constexpr TypedWhichId< SvxRsidItem > RES_CHRATR_RSID(39)
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(100)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:175
constexpr TypedWhichId< SvxTextLeftMarginItem > RES_MARGIN_TEXTLEFT(92)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_METAFIELD(49)
constexpr TypedWhichId< SvXMLAttrContainerItem > RES_TXTATR_UNKNOWN_CONTAINER(54)
constexpr TypedWhichId< SfxGrabBagItem > RES_PARATR_GRABBAG(81)
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_META(48)
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
constexpr TypedWhichId< SfxUInt16Item > RES_PARATR_OUTLINELEVEL(79)
#define CH_TXT_ATR_INPUTFIELDEND
Definition: hintids.hxx:179
constexpr TypedWhichId< SfxBoolItem > RES_PARATR_LIST_ISCOUNTED(86)
constexpr TypedWhichId< SvxFormatSplitItem > RES_PARATR_SPLIT(65)
constexpr TypedWhichId< SfxBoolItem > RES_PARATR_LIST_ISRESTART(84)
constexpr TypedWhichId< SvxRsidItem > RES_PARATR_RSID(80)
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
constexpr TypedWhichId< SwFormatRuby > RES_TXTATR_CJK_RUBY(53)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:185
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_OBJECTDYING(RES_FORMAT_MSG_BEGIN)
constexpr sal_uInt16 RES_TXTATR_END(RES_TXTATR_NOEND_END)
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:183
constexpr TypedWhichId< SwFormatChg > RES_FMT_CHG(168)
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:174
WhichRangesContainer const aTextNodeSetRange(svl::Items< RES_CHRATR_BEGIN, RES_CHRATR_END-1, RES_PARATR_BEGIN, RES_PARATR_END-1, RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1, RES_FRMATR_BEGIN, RES_FRMATR_END-1, RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, XATTR_FILL_FIRST, XATTR_FILL_LAST >)
sal_Int32 nIndex
Mode eMode
sal_Int64 n
sal_uInt16 nPos
SwListRedlineType
Definition: list.hxx:33
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
ExpandMode
Some helpers for converting model strings to view strings.
const SfxPoolItem * GetItem(const SwTextAttr &rAttr, sal_uInt16 nWhich)
Extracts pool item of type nWhich from rAttr.
Definition: atrstck.cxx:157
tools::Long tSwNumTreeNumber
std::vector< tSwNumTreeNumber > tNumberVector
double getLength(const B2DPolygon &rCandidate)
size
OUStringBuffer & remove(OUStringBuffer &rIn, sal_Unicode c)
std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr
Definition: format.hxx:41
int i
RestoreMode
Definition: mvsave.hxx:73
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
const SvxPageUsage aArr[]
Dialog to specify the properties of date form field.
void CheckResetRedlineMergeFlag(SwTextNode &rNode, Recreate eRecreateMerged)
if first node is First, its frames may need to be moved, never deleted.
Definition: ndtxt.cxx:888
bool HasNumberingWhichNeedsLayoutUpdate(const SwTextNode &rTextNode)
Decides if rTextNode has a numbering which has layout-level values (e.g.
Definition: ndtxt.cxx:969
void MoveMergedFlysAndFootnotes(std::vector< SwTextFrame * > const &rFrames, SwTextNode const &rFirstNode, SwTextNode &rSecondNode, bool)
Definition: ndtxt.cxx:375
SwTextFrame * MakeTextFrame(SwTextNode &rNode, SwFrame *, sw::FrameMode eMode)
Definition: txtfrm.cxx:885
Recreate
Definition: txtfrm.hxx:135
InsertText MakeInsertText(SwTextNode &rNode, const sal_Int32 nPos, const sal_Int32 nLen)
Definition: docbm.cxx:2094
void AddRemoveFlysAnchoredToFrameStartingAtNode(SwTextFrame &rFrame, SwTextNode &rTextNode, std::set< SwNodeOffset > *pSkipped)
rTextNode is the first one of the "new" merge - if rTextNode isn't the same as MergedPara::pFirstNode...
Definition: wsfrm.cxx:4325
void MoveDeletedPrevFrames(const SwTextNode &rDeletedPrev, SwTextNode &rNode)
if first node is deleted & second survives, then the first node's frame will be deleted too; prevent ...
Definition: ndtxt.cxx:848
std::unique_ptr< sw::MergedPara > CheckParaRedlineMerge(SwTextFrame &rFrame, SwTextNode &rTextNode, FrameMode eMode)
Definition: redlnitr.cxx:268
ListLevelIndents
Definition: paratr.hxx:52
GetTextAttrMode
Definition: swtypes.hxx:163
@ Parent
EXPAND : (Start < nIndex <= End)
@ Expand
DEFAULT: (Start <= nIndex < End)
long Long
static bool lcl_GetTextAttrExpand(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd)
Definition: ndtxt.cxx:1719
static bool lcl_GetTextAttrParent(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd)
Definition: ndtxt.cxx:1723
static void Replace0xFF(SwTextNode const &rNode, OUStringBuffer &rText, sal_Int32 &rTextStt, sal_Int32 nEndPos)
Definition: ndtxt.cxx:3456
static SwCharFormat * lcl_FindCharFormat(const SwCharFormats *pCharFormats, std::u16string_view rName)
Definition: ndtxt.cxx:1870
#define CHECK_SWPHINTS(pNd)
Definition: ndtxt.cxx:110
static bool lcl_GetTextAttrDefault(sal_Int32 nIndex, sal_Int32 nHintStart, sal_Int32 nHintEnd)
Definition: ndtxt.cxx:1715
static SwList * FindList(SwTextNode *const pNode)
Definition: ndtxt.cxx:4400
static void lcl_CopyHint(const sal_uInt16 nWhich, const SwTextAttr *const pHt, SwTextAttr *const pNewHt, SwDoc *const pOtherDoc, SwTextNode *const pDest)
Definition: ndtxt.cxx:1885
#define CHECK_SWPHINTS_IF_FRM(pNd)
Definition: ndtxt.cxx:113
static void lcl_GetTextAttrs(std::vector< SwTextAttr * > *const pVector, SwTextAttr **const ppTextAttr, SwpHints const *const pSwpHints, sal_Int32 const nIndex, sal_uInt16 const nWhich, ::sw::GetTextAttrMode const eMode)
Definition: ndtxt.cxx:1729
static void lcl_ChangeFootnoteRef(SwTextNode &rNode)
Definition: ndtxt.cxx:297
std::vector< SwTextAttr * > SwpHts
Definition: ndtxt.cxx:88
SwNodeType
Definition: ndtyp.hxx:28
@ Table
SwTableNode is derived from SwStartNode.
@ Section
SwSectionNode is derived from SwStartNode.
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
const char GetValue[]
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:1043
bool IsInvalidItem(const SfxPoolItem *pItem)
static SfxItemSet & rSet
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
const SwNodes & GetNodes() const
Definition: pam.hxx:79
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
SwContentIndex nContent
Definition: pam.hxx:40
const SfxPoolItem * m_pOld
Definition: calbck.hxx:77
const SfxPoolItem * m_pNew
Definition: calbck.hxx:78
SVX_NUM_NUMBER_NONE
SVX_NUM_BITMAP
SVX_NUM_CHAR_SPECIAL
@ IS_COPY
The inserted item is a copy – intended for use in ndtxt.cxx.
@ NOHINTADJUST
attention: NOHINTADJUST prevents MergePortions! when using this need to pay attention to ignore start...
tools::Long SwTwips
Definition: swtypes.hxx:51
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:92
SwTextAttr * MakeTextAttr(SwDoc &rDoc, SfxPoolItem &rAttr, sal_Int32 const nStt, sal_Int32 const nEnd, CopyOrNewType const bIsCopy, SwTextNode *const pTextNode)
if COPY then pTextNode must be given!
Definition: thints.cxx:1030
bool bVisible
T static_txtattr_cast(S *s)
Definition: txatbase.hxx:257
#define SAL_MAX_INT32
sal_uInt16 sal_Unicode
Count
constexpr sal_uInt16 XATTR_FILL_FIRST(XATTRSET_LINE+1)
constexpr sal_uInt16 XATTR_FILL_LAST(XATTR_FILLUSESLIDEBACKGROUND)