LibreOffice Module sw (master) 1
docnum.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 <ftninfo.hxx>
22#include <ftnidx.hxx>
23#include <doc.hxx>
24#include <IDocumentUndoRedo.hxx>
28#include <IDocumentState.hxx>
30#include <pam.hxx>
31#include <ndtxt.hxx>
32#include <poolfmt.hxx>
33#include <UndoCore.hxx>
34#include <UndoRedline.hxx>
35#include <UndoNumbering.hxx>
36#include <swundo.hxx>
37#include <SwUndoFmt.hxx>
38#include <rolbck.hxx>
39#include <paratr.hxx>
40#include <docary.hxx>
41#include <mvsave.hxx>
42#include <txtfrm.hxx>
43#include <rootfrm.hxx>
44#include <redline.hxx>
45#include <strings.hrc>
46#include <SwNodeNum.hxx>
47#include <list.hxx>
48#include <calbck.hxx>
49#include <comphelper/string.hxx>
50#include <comphelper/random.hxx>
51#include <o3tl/safeint.hxx>
52#include <o3tl/string_view.hxx>
53#include <osl/diagnose.h>
55
56#include <map>
57#include <stdlib.h>
58
59#include <wrtsh.hxx>
60
61namespace {
62 void lcl_ResetIndentAttrs(SwDoc *pDoc, const SwPaM &rPam,
63 const o3tl::sorted_vector<sal_uInt16> aResetAttrsArray,
64 SwRootFrame const*const pLayout)
65 {
66 // #i114929#
67 // On a selection setup a corresponding Point-and-Mark in order to get
68 // the indentation attribute reset on all paragraphs touched by the selection
69 if ( rPam.HasMark() &&
70 rPam.End()->GetNode().GetTextNode() )
71 {
72 SwPaM aPam( rPam.Start()->GetNode(), 0,
73 rPam.End()->GetNode(), rPam.End()->GetNode().GetTextNode()->Len() );
74 pDoc->ResetAttrs( aPam, false, aResetAttrsArray, true, pLayout );
75 }
76 else
77 {
78 pDoc->ResetAttrs( rPam, false, aResetAttrsArray, true, pLayout );
79 }
80 }
81
82 void ExpandPamForParaPropsNodes(SwPaM& rPam, SwRootFrame const*const pLayout)
83 {
84 if (!pLayout)
85 return;
86
87 // ensure that selection from the Shell includes the para-props node
88 // to which the attributes should be applied
89 if (rPam.GetPoint()->GetNode().IsTextNode())
90 {
91 rPam.GetPoint()->Assign( *sw::GetParaPropsNode(*pLayout, rPam.GetPoint()->GetNode()) );
92 }
93 if (rPam.GetMark()->GetNode().IsTextNode())
94 {
95 rPam.GetMark()->Assign( *sw::GetParaPropsNode(*pLayout, rPam.GetMark()->GetNode()) );
96 }
97 }
98}
99
100static sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask )
101{
102 if( 1 < nLevel )
103 {
104 if( nCurLvl + 1 >= nLevel )
105 nCurLvl -= nLevel - 1;
106 else
107 nCurLvl = 0;
108 }
109 return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
110}
111
113{
114 if (GetIDocumentUndoRedo().DoesUndo())
115 {
116 GetIDocumentUndoRedo().StartUndo(SwUndoId::OUTLINE_EDIT, nullptr);
117 if (mpOutlineRule)
118 {
119 GetIDocumentUndoRedo().AppendUndo(
120 std::make_unique<SwUndoOutlineEdit>(*mpOutlineRule, rRule, *this));
121 }
122 }
123
124 if( mpOutlineRule )
125 (*mpOutlineRule) = rRule;
126 else
127 {
128 mpOutlineRule = new SwNumRule( rRule );
129
130 AddNumRule(mpOutlineRule); // #i36749#
131 }
132
135
136 // assure that the outline numbering rule is an automatic rule
137 mpOutlineRule->SetAutoRule( true );
138
139 // test whether the optional CharFormats are defined in this Document
141
142 // notify text nodes, which are registered at the outline style, about the
143 // changed outline style
144 SwNumRule::tTextNodeList aTextNodeList;
145 mpOutlineRule->GetTextNodeList( aTextNodeList );
146 for ( SwTextNode* pTextNd : aTextNodeList )
147 {
148 pTextNd->NumRuleChgd();
149
150 // assure that list level corresponds to outline level
151 if ( pTextNd->GetTextColl()->IsAssignedToListLevelOfOutlineStyle() &&
152 pTextNd->GetAttrListLevel() != pTextNd->GetTextColl()->GetAssignedOutlineStyleLevel() )
153 {
154 pTextNd->SetAttrListLevel( pTextNd->GetTextColl()->GetAssignedOutlineStyleLevel() );
155 }
156 }
157
161
162 // update if we have foot notes && numbering by chapter
163 if( !GetFootnoteIdxs().empty() && FTNNUM_CHAPTER == GetFootnoteInfo().m_eNum )
165
167
168 if (GetIDocumentUndoRedo().DoesUndo())
169 {
171 }
172
174}
175
177{
178 SwNumRule* pMyOutlineRule = GetOutlineNumRule();
179 if (!pMyOutlineRule)
180 return;
181
182 for (auto pColl : *mpTextFormatCollTable)
183 {
184 if(pColl->IsAssignedToListLevelOfOutlineStyle())
185 {
186 // Check only the list style, which is set at the paragraph style
187 const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( false );
188
189 if ( rCollRuleItem.GetValue().isEmpty() )
190 {
191 SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
192 pColl->SetFormatAttr(aNumItem);
193 }
194 }
195 }
196}
197
198// Increase/Decrease
199bool SwDoc::OutlineUpDown(const SwPaM& rPam, short nOffset,
200 SwRootFrame const*const pLayout)
201{
202 if( GetNodes().GetOutLineNds().empty() || !nOffset )
203 return false;
204
205 // calculate the range
206 SwPaM aPam(rPam, nullptr);
207 ExpandPamForParaPropsNodes(aPam, pLayout);
208 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
209 SwNode* const pSttNd = &aPam.Start()->GetNode();
210 SwNode* const pEndNd = &aPam.End()->GetNode();
211 SwOutlineNodes::size_type nSttPos, nEndPos;
212
213 if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
214 !nSttPos-- )
215 // we're not in an "Outline section"
216 return false;
217
218 if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
219 ++nEndPos;
220
221 // We now have the wanted range in the OutlineNodes array,
222 // so check now if we're not invalidating sublevels
223 // (stepping over the limits)
224
225 // Here we go:
226 // 1. Create the style array:
227 SwTextFormatColl* aCollArr[ MAXLEVEL ];
228 memset( aCollArr, 0, sizeof( SwTextFormatColl* ) * MAXLEVEL );
229
230 for( auto pTextFormatColl : *mpTextFormatCollTable )
231 {
232 if (pTextFormatColl->IsAssignedToListLevelOfOutlineStyle())
233 {
234 const int nLevel = pTextFormatColl->GetAssignedOutlineStyleLevel();
235 aCollArr[ nLevel ] = pTextFormatColl;
236 }
237 }
238
239 int n;
240
241 /* Find the last occupied level (backward). */
242 for (n = MAXLEVEL - 1; n > 0; n--)
243 {
244 if (aCollArr[n] != nullptr)
245 break;
246 }
247
248 /* If an occupied level is found, choose next level (which IS
249 unoccupied) until a valid level is found. If no occupied level
250 was found n is 0 and aCollArr[0] is 0. In this case no demoting
251 is possible. */
252 if (aCollArr[n] != nullptr)
253 {
254 while (n < MAXLEVEL - 1)
255 {
256 n++;
257
258 SwTextFormatColl *aTmpColl =
260
261 if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
262 aTmpColl->GetAssignedOutlineStyleLevel() == n )
263 {
264 aCollArr[n] = aTmpColl;
265 break;
266 }
267 }
268 }
269
270 /* Find the first occupied level (forward). */
271 for (n = 0; n < MAXLEVEL - 1; n++)
272 {
273 if (aCollArr[n] != nullptr)
274 break;
275 }
276
277 /* If an occupied level is found, choose previous level (which IS
278 unoccupied) until a valid level is found. If no occupied level
279 was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In
280 this case no demoting is possible. */
281 if (aCollArr[n] != nullptr)
282 {
283 while (n > 0)
284 {
285 n--;
286
287 SwTextFormatColl *aTmpColl =
289
290 if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
291 aTmpColl->GetAssignedOutlineStyleLevel() == n )
292 {
293 aCollArr[n] = aTmpColl;
294 break;
295 }
296 }
297 }
298
299 /* --> #i13747#
300
301 Build a move table that states from which level to which other level
302 an outline will be moved.
303
304 the move table:
305 aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
306 */
307 int aMoveArr[MAXLEVEL];
308 int nStep; // step size for searching in aCollArr: -1 or 1
309 int nNum; // amount of steps for stepping in aCollArr
310
311 if (nOffset < 0)
312 {
313 nStep = -1;
314 nNum = -nOffset;
315 }
316 else
317 {
318 nStep = 1;
319 nNum = nOffset;
320 }
321
322 /* traverse aCollArr */
323 for (n = 0; n < MAXLEVEL; n++)
324 {
325 /* If outline level n has an assigned paragraph style step
326 nNum steps forwards (nStep == 1) or backwards (nStep ==
327 -1). One step is to go to the next non-null entry in
328 aCollArr in the selected direction. If nNum steps were
329 possible write the index of the entry found to aCollArr[n],
330 i.e. outline level n will be replaced by outline level
331 aCollArr[n].
332
333 If outline level n has no assigned paragraph style
334 aMoveArr[n] is set to -1.
335 */
336 if (aCollArr[n] != nullptr)
337 {
338 int m = n;
339 int nCount = nNum;
340
341 while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
342 {
343 m += nStep;
344
345 if (aCollArr[m] != nullptr)
346 nCount--;
347 }
348
349 if (nCount == 0)
350 aMoveArr[n] = m;
351 else
352 aMoveArr[n] = -1;
353 }
354 else
355 aMoveArr[n] = -1;
356 }
357
358 /* If moving of the outline levels is applicable, i.e. for all
359 outline levels occurring in the document there has to be a valid
360 target outline level implied by aMoveArr. */
361 bool bMoveApplicable = true;
362 for (auto i = nSttPos; i < nEndPos; ++i)
363 {
364 SwTextNode* pTextNd = rOutlNds[ i ]->GetTextNode();
365 if (pLayout && !sw::IsParaPropsNode(*pLayout, *pTextNd))
366 {
367 continue;
368 }
369 SwTextFormatColl* pColl = pTextNd->GetTextColl();
370
372 {
373 const int nLevel = pColl->GetAssignedOutlineStyleLevel();
374 if (aMoveArr[nLevel] == -1)
375 bMoveApplicable = false;
376 }
377
378 // Check on outline level attribute of text node, if text node is
379 // not an outline via a to outline style assigned paragraph style.
380 else
381 {
382 const int nNewOutlineLevel = pTextNd->GetAttrOutlineLevel() + nOffset;
383 if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
384 {
385 bMoveApplicable = false;
386 }
387 }
388 }
389
390 if (! bMoveApplicable )
391 return false;
392
393 if (GetIDocumentUndoRedo().DoesUndo())
394 {
395 GetIDocumentUndoRedo().StartUndo(SwUndoId::OUTLINE_LR, nullptr);
396 GetIDocumentUndoRedo().AppendUndo(
397 std::make_unique<SwUndoOutlineLeftRight>(aPam, nOffset) );
398 }
399
400 // 2. Apply the new style to all Nodes
401 for (auto i = nSttPos; i < nEndPos; ++i)
402 {
403 SwTextNode* pTextNd = rOutlNds[ i ]->GetTextNode();
404 if (pLayout && !sw::IsParaPropsNode(*pLayout, *pTextNd))
405 {
406 continue;
407 }
408 SwTextFormatColl* pColl = pTextNd->GetTextColl();
409
411 {
412 const int nLevel = pColl->GetAssignedOutlineStyleLevel();
413
414 OSL_ENSURE(aMoveArr[nLevel] >= 0,
415 "move table: current TextColl not found when building table!");
416
417 if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
418 {
419 pColl = aCollArr[ aMoveArr[nLevel] ];
420
421 if (pColl != nullptr)
422 pTextNd->ChgFormatColl( pColl );
423 }
424
425 }
426 else if( pTextNd->GetAttrOutlineLevel() > 0)
427 {
428 int nLevel = pTextNd->GetAttrOutlineLevel() + nOffset;
429 if( 0 <= nLevel && nLevel <= MAXLEVEL)
430 pTextNd->SetAttrOutlineLevel( nLevel );
431
432 }
433 // Undo ???
434 }
435 if (GetIDocumentUndoRedo().DoesUndo())
436 {
437 GetIDocumentUndoRedo().EndUndo(SwUndoId::OUTLINE_LR, nullptr);
438 }
439
440 ChkCondColls();
442
443 return true;
444}
445
446// Move up/down
448{
449 // Do not move to special sections in the nodes array
450 const SwPosition& rStt = *rPam.Start(),
451 & rEnd = *rPam.End();
452 if( GetNodes().GetOutLineNds().empty() || !nOffset ||
453 (rStt.GetNodeIndex() < GetNodes().GetEndOfExtras().GetIndex()) ||
454 (rEnd.GetNodeIndex() < GetNodes().GetEndOfExtras().GetIndex()))
455 {
456 return false;
457 }
458
459 SwOutlineNodes::size_type nCurrentPos = 0;
460 SwNodeIndex aSttRg( rStt.GetNode() ), aEndRg( rEnd.GetNode() );
461
462 int nOutLineLevel = MAXLEVEL;
463 SwNode* pSrch = &aSttRg.GetNode();
464
465 if( pSrch->IsTextNode())
466 nOutLineLevel = static_cast<sal_uInt8>(pSrch->GetTextNode()->GetAttrOutlineLevel()-1);
467 SwNode* pEndSrch = &aEndRg.GetNode();
468 if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nCurrentPos ) )
469 {
470 if( !nCurrentPos )
471 return false; // Promoting or demoting before the first outline => no.
472 if( --nCurrentPos )
473 aSttRg = *GetNodes().GetOutLineNds()[ nCurrentPos ];
474 else if( 0 > nOffset )
475 return false; // Promoting at the top of document?!
476 else
478 }
479 SwOutlineNodes::size_type nTmpPos = 0;
480 // If the given range ends at an outlined text node we have to decide if it has to be a part of
481 // the moving range or not. Normally it will be a sub outline of our chapter
482 // and has to be moved, too. But if the chapter ends with a table(or a section end),
483 // the next text node will be chosen and this could be the next outline of the same level.
484 // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
485 if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
486 {
487 if( !pEndSrch->IsTextNode() || pEndSrch == pSrch ||
488 nOutLineLevel < pEndSrch->GetTextNode()->GetAttrOutlineLevel()-1 )
489 ++nTmpPos; // For sub outlines only!
490 }
491
492 aEndRg = nTmpPos < GetNodes().GetOutLineNds().size()
493 ? *GetNodes().GetOutLineNds()[ nTmpPos ]
495 if( nOffset >= 0 )
496 nCurrentPos = nTmpPos;
497 if( aEndRg == aSttRg )
498 {
499 OSL_FAIL( "Moving outlines: Surprising selection" );
500 ++aEndRg;
501 }
502
503 const SwNode* pNd;
504 // The following code corrects the range to handle sections (start/end nodes)
505 // The range will be extended if the least node before the range is a start node
506 // which ends inside the range => The complete section will be moved.
507 // The range will be shrunk if the last position is a start node.
508 // The range will be shrunk if the last node is an end node which starts before the range.
509 --aSttRg;
510 while( aSttRg.GetNode().IsStartNode() )
511 {
512 pNd = aSttRg.GetNode().EndOfSectionNode();
513 if( pNd->GetIndex() >= aEndRg.GetIndex() )
514 break;
515 --aSttRg;
516 }
517 ++aSttRg;
518
519 --aEndRg;
520 while( aEndRg.GetNode().IsStartNode() )
521 --aEndRg;
522
523 while( aEndRg.GetNode().IsEndNode() )
524 {
525 pNd = aEndRg.GetNode().StartOfSectionNode();
526 if( pNd->GetIndex() >= aSttRg.GetIndex() )
527 break;
528 --aEndRg;
529 }
530 ++aEndRg;
531
532 // calculation of the new position
533 if( nOffset < 0 && nCurrentPos < o3tl::make_unsigned(-nOffset) )
535 else if( nCurrentPos + nOffset >= GetNodes().GetOutLineNds().size() )
536 pNd = &GetNodes().GetEndOfContent();
537 else
538 pNd = GetNodes().GetOutLineNds()[ nCurrentPos + nOffset ];
539
540 SwNodeOffset nNewPos = pNd->GetIndex();
541
542 // And now a correction of the insert position if necessary...
543 SwNodeIndex aInsertPos( *pNd, -1 );
544 while( aInsertPos.GetNode().IsStartNode() )
545 {
546 // Just before the insert position starts a section:
547 // when I'm moving forward I do not want to enter the section,
548 // when I'm moving backward I want to stay in the section if I'm already a part of,
549 // I want to stay outside if I was outside before.
550 if( nOffset < 0 )
551 {
552 pNd = aInsertPos.GetNode().EndOfSectionNode();
553 if( pNd->GetIndex() >= aEndRg.GetIndex() )
554 break;
555 }
556 --aInsertPos;
557 --nNewPos;
558 }
559
560 if( nOffset >= 0 )
561 {
562 // When just before the insert position a section ends, it is okay when I'm moving backward
563 // because I want to stay outside the section.
564 // When moving forward I've to check if I started inside or outside the section
565 // because I don't want to enter of leave such a section
566 while( aInsertPos.GetNode().IsEndNode() )
567 {
568 pNd = aInsertPos.GetNode().StartOfSectionNode();
569 if( pNd->GetIndex() >= aSttRg.GetIndex() )
570 break;
571 --aInsertPos;
572 --nNewPos;
573 }
574 }
575 // We do not want to move into tables (at the moment)
576 ++aInsertPos;
577 pNd = &aInsertPos.GetNode();
578 if( pNd->IsTableNode() )
579 pNd = pNd->StartOfSectionNode();
580 if( pNd->FindTableNode() )
581 return false;
582
583 OSL_ENSURE( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
584 "Position lies within Move range" );
585
586 // If a Position inside the special nodes array sections was calculated,
587 // set it to document start instead.
588 // Sections or Tables at the document start will be pushed backwards.
589 nNewPos = std::max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + SwNodeOffset(2) );
590
591 SwNodeOffset nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
592 SwPaM aPam( aSttRg, aEndRg, SwNodeOffset(0), SwNodeOffset(-1) );
593 return MoveParagraph( aPam, nOffs, true );
594}
595
597 SwRootFrame const*const pLayout, std::u16string_view aName, bool const bExact)
598{
599 SwTextNode * pExactButDeleted(nullptr);
600 SwTextNode* pSavedNode = nullptr;
601 for( auto pOutlNd : rOutlNds )
602 {
603 SwTextNode* pTextNd = pOutlNd->GetTextNode();
604 const OUString sText( pTextNd->GetExpandText(pLayout) );
605 if (sText.startsWith(aName))
606 {
607 if (sText.getLength() == sal_Int32(aName.size()))
608 {
609 if (pLayout && !sw::IsParaPropsNode(*pLayout, *pTextNd))
610 {
611 pExactButDeleted = pTextNd;
612 }
613 else
614 {
615 // Found "exact", set Pos to the Node
616 return pTextNd;
617 }
618 }
619 if (!bExact && !pSavedNode
620 && (!pLayout || sw::IsParaPropsNode(*pLayout, *pTextNd)))
621 {
622 // maybe we just found the text's first part
623 pSavedNode = pTextNd;
624 }
625 }
626 }
627
628 return bExact ? pExactButDeleted : pSavedNode;
629}
630
632 OUString& rName, SwRootFrame const*const pLayout)
633{
634 // Valid numbers are (always just offsets!):
635 // ([Number]+\.)+ (as a regular expression!)
636 // (Number followed by a period, with 5 repetitions)
637 // i.e.: "1.1.", "1.", "1.1.1."
638 sal_Int32 nPos = 0;
639 std::u16string_view sNum = o3tl::getToken(rName, 0, '.', nPos );
640 if( -1 == nPos )
641 return nullptr; // invalid number!
642
643 sal_uInt16 nLevelVal[ MAXLEVEL ]; // numbers of all levels
644 memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
645 int nLevel = 0;
646 std::u16string_view sName( rName );
647
648 while( -1 != nPos )
649 {
650 sal_uInt16 nVal = 0;
651 for( size_t n = 0; n < sNum.size(); ++n )
652 {
653 const sal_Unicode c {sNum[ n ]};
654 if( '0' <= c && c <= '9' )
655 {
656 nVal *= 10;
657 nVal += c - '0';
658 }
659 else if( nLevel )
660 break; // "almost" valid number
661 else
662 return nullptr; // invalid number!
663 }
664
665 if( MAXLEVEL > nLevel )
666 nLevelVal[ nLevel++ ] = nVal;
667
668 sName = sName.substr( nPos );
669 nPos = 0;
670 sNum = o3tl::getToken(sName, 0, '.', nPos );
671 // #i4533# without this check all parts delimited by a dot are treated as outline numbers
673 break;
674 }
675 rName = sName; // that's the follow-up text
676
677 // read all levels, so search the document for this outline
678
679 // Without OutlineNodes searching doesn't pay off
680 // and we save a crash
681 if( rOutlNds.empty() )
682 return nullptr;
683
684 // search in the existing outline nodes for the required outline num array
685 for( auto pOutlNd : rOutlNds )
686 {
687 SwTextNode* pNd = pOutlNd->GetTextNode();
688 if ( pNd->GetAttrOutlineLevel() == nLevel )
689 {
690 // #i51089#, #i68289#
691 // Assure, that text node has the correct numbering level. Otherwise,
692 // its number vector will not fit to the searched level.
693 if (pNd->GetNum(pLayout) && pNd->GetActualListLevel() == nLevel - 1)
694 {
695 const SwNodeNum & rNdNum = *(pNd->GetNum(pLayout));
696 SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
697 // now compare with the one searched for
698 bool bEqual = true;
699 nLevel = std::min<int>(nLevel, MAXLEVEL);
700 for( int n = 0; n < nLevel; ++n )
701 {
702 if ( aLevelVal[n] != nLevelVal[n] )
703 {
704 bEqual = false;
705 break;
706 }
707 }
708 if (bEqual)
709 return pNd;
710 }
711 else
712 {
713 // A text node, which has an outline paragraph style applied and
714 // has as hard attribute 'no numbering' set, has an outline level,
715 // but no numbering tree node. Thus, consider this situation in
716 // the assertion condition.
717 OSL_ENSURE( !pNd->GetNumRule(),
718 "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect" );
719 }
720 }
721 }
722
723 return nullptr;
724}
725
726// rName can contain a Number and/or the Text.
727// First, we try to find the correct Entry via the Number.
728// If it exists, we compare the Text to see if it's the right one.
729// If that's not the case, we search again via the Text. If it is
730// found, we got the right entry. Or else we use the one found by
731// searching for the Number.
732// If we don't have a Number, we search via the Text only.
733bool SwDoc::GotoOutline(SwPosition& rPos, const OUString& rName, SwRootFrame const*const pLayout) const
734{
735 if( !rName.isEmpty() )
736 {
737 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
738
739 // 1. step: via the Number:
740 OUString sName( rName );
741 SwTextNode* pNd = ::lcl_FindOutlineNum(rOutlNds, sName, pLayout);
742 if ( pNd )
743 {
744 OUString sExpandedText = pNd->GetExpandText(pLayout);
745 //#i4533# leading numbers followed by a dot have been remove while
746 //searching for the outline position
747 //to compensate this they must be removed from the paragraphs text content, too
748 while(!sExpandedText.isEmpty())
749 {
750 sal_Int32 nPos = 0;
751 std::u16string_view sTempNum = o3tl::getToken(sExpandedText, 0, '.', nPos);
752 if( sTempNum.empty() || -1 == nPos ||
754 break;
755 sExpandedText = sExpandedText.copy(nPos);
756 }
757
758 if( sExpandedText != sName )
759 {
760 SwTextNode *pTmpNd = ::lcl_FindOutlineName(rOutlNds, pLayout, sName, true);
761 if ( pTmpNd ) // found via the Name
762 {
763 if (pLayout && !sw::IsParaPropsNode(*pLayout, *pTmpNd))
764 { // found the correct node but it's deleted!
765 return false; // avoid fallback to inexact search
766 }
767 pNd = pTmpNd;
768 }
769 }
770 rPos.Assign(*pNd);
771 return true;
772 }
773
774 pNd = ::lcl_FindOutlineName(rOutlNds, pLayout, rName, false);
775 if ( pNd )
776 {
777 rPos.Assign(*pNd);
778 return true;
779 }
780
781 // #i68289# additional search on hyperlink URL without its outline numbering part
782 if ( sName != rName )
783 {
784 pNd = ::lcl_FindOutlineName(rOutlNds, pLayout, sName, false);
785 if ( pNd )
786 {
787 rPos.Assign(*pNd);
788 return true;
789 }
790 }
791 }
792 return false;
793}
794
795static void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
796{
797 SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
798 if (!pOld) //we cannot proceed without the old NumRule
799 return;
800
801 sal_uInt16 nChgFormatLevel = 0;
802 sal_uInt16 nMask = 1;
803
804 for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
805 {
806 const SwNumFormat& rOldFormat = pOld->Get( n ), &rNewFormat = rRule.Get( n );
807
808 if ( rOldFormat != rNewFormat )
809 {
810 nChgFormatLevel |= nMask;
811 }
812 else if ( SVX_NUM_NUMBER_NONE > rNewFormat.GetNumberingType()
813 && 1 < rNewFormat.GetIncludeUpperLevels()
814 && 0 != ( nChgFormatLevel & GetUpperLvlChg( n, rNewFormat.GetIncludeUpperLevels(), nMask ) ) )
815 {
816 nChgFormatLevel |= nMask;
817 }
818 }
819
820 if( !nChgFormatLevel ) // Nothing has been changed?
821 {
822 const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
823 pOld->CheckCharFormats( rDoc );
824 pOld->SetContinusNum( rRule.IsContinusNum() );
825
826 if ( bInvalidateNumRule )
827 {
828 pOld->SetInvalidRule(true);
829 }
830
831 return ;
832 }
833
834 SwNumRule::tTextNodeList aTextNodeList;
835 pOld->GetTextNodeList( aTextNodeList );
836 sal_uInt8 nLvl( 0 );
837 for ( SwTextNode* pTextNd : aTextNodeList )
838 {
839 nLvl = static_cast<sal_uInt8>(pTextNd->GetActualListLevel());
840
841 if( nLvl < MAXLEVEL )
842 {
843 if( nChgFormatLevel & ( 1 << nLvl ))
844 {
845 pTextNd->NumRuleChgd();
846 }
847 }
848 }
849
850 for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
851 if ( nChgFormatLevel & ( 1 << n ) )
852 pOld->Set( n, rRule.GetNumFormat( n ) );
853
854 pOld->CheckCharFormats( rDoc );
855 pOld->SetInvalidRule( true );
856 pOld->SetContinusNum( rRule.IsContinusNum() );
857
858 rDoc.UpdateNumRule();
859}
860
861OUString SwDoc::SetNumRule( const SwPaM& rPam,
862 const SwNumRule& rRule,
863 const bool bCreateNewList,
864 SwRootFrame const*const pLayout,
865 const OUString& sContinuedListId,
866 bool bSetItem,
867 const bool bResetIndentAttrs )
868{
869 OUString sListId;
870
871 SwPaM aPam(rPam, nullptr);
872 ExpandPamForParaPropsNodes(aPam, pLayout);
873
874 SwUndoInsNum * pUndo = nullptr;
875 if (GetIDocumentUndoRedo().DoesUndo())
876 {
877 // Start/End for attributes!
878 GetIDocumentUndoRedo().StartUndo( SwUndoId::INSNUM, nullptr );
879 pUndo = new SwUndoInsNum( aPam, rRule );
880 GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
881 }
882
883 SwNumRule* pNewOrChangedNumRule = FindNumRulePtr( rRule.GetName() );
884 bool bNewNumRuleCreated = false;
885 if ( pNewOrChangedNumRule == nullptr )
886 {
887 // create new numbering rule based on given one
888 pNewOrChangedNumRule = ( *mpNumRuleTable )[MakeNumRule( rRule.GetName(), &rRule )];
889 bNewNumRuleCreated = true;
890 }
891 else if ( rRule != *pNewOrChangedNumRule )
892 {
893 // change existing numbering rule
894 if (pUndo)
895 {
896 pUndo->SaveOldNumRule( *pNewOrChangedNumRule );
897 }
898 ::lcl_ChgNumRule( *this, rRule );
899 if (pUndo)
900 {
901 pUndo->SetLRSpaceEndPos();
902 }
903 }
904
905 if ( bSetItem )
906 {
907 if ( bCreateNewList )
908 {
909 if ( bNewNumRuleCreated )
910 {
911 // apply list id of list, which has been created for the new list style
912 sListId = pNewOrChangedNumRule->GetDefaultListId();
913 }
914 else
915 {
916 // create new list and apply its list id
917 const SwList* pNewList = getIDocumentListsAccess().createList( OUString(), pNewOrChangedNumRule->GetName() );
918 OSL_ENSURE( pNewList,
919 "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect." );
920 sListId = pNewList->GetListId();
921 }
922 }
923 else if ( !sContinuedListId.isEmpty() )
924 {
925 // apply given list id
926 sListId = sContinuedListId;
927 }
928 if (!sListId.isEmpty())
929 {
932 SetAttrMode::DEFAULT, pLayout);
933 }
934 }
935
936 if (!aPam.HasMark())
937 {
938 SwTextNode * pTextNd = aPam.GetPoint()->GetNode().GetTextNode();
939 // robust code: consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
940 if ( pTextNd != nullptr )
941 {
942 assert(!pLayout || sw::IsParaPropsNode(*pLayout, *pTextNd));
943 SwNumRule * pRule = pTextNd->GetNumRule();
944
945 if (pRule && pRule->GetName() == pNewOrChangedNumRule->GetName())
946 {
947 bSetItem = false;
948 if ( !pTextNd->IsInList() )
949 {
950 pTextNd->AddToList();
951 }
952 }
953 // Only clear numbering attribute at text node, if at paragraph
954 // style the new numbering rule is found.
955 else if ( !pRule )
956 {
957 SwTextFormatColl* pColl = pTextNd->GetTextColl();
958 if ( pColl )
959 {
960 SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
961 if ( pCollRule && pCollRule->GetName() == pNewOrChangedNumRule->GetName() )
962 {
963 pTextNd->ResetAttr( RES_PARATR_NUMRULE );
964 bSetItem = false;
965 }
966 }
967 }
968 }
969 }
970
971 if ( bSetItem )
972 {
974 SwNumRuleItem(pNewOrChangedNumRule->GetName()),
975 SetAttrMode::DEFAULT, pLayout);
976 }
977
978 if ( bResetIndentAttrs
979 && pNewOrChangedNumRule->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
980 {
982 ::lcl_ResetIndentAttrs(this, aPam, attrs, pLayout);
983 }
984
985 if (GetIDocumentUndoRedo().DoesUndo())
986 {
987 GetIDocumentUndoRedo().EndUndo( SwUndoId::INSNUM, nullptr );
988 }
989
991
992 return sListId;
993}
994
995void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted,
996 SwRootFrame const*const pLayout)
997{
998 if ( bCounted )
999 {
1001 ::lcl_ResetIndentAttrs(this, rPam, attrs, pLayout);
1002 }
1003 else
1004 {
1007 SetAttrMode::DEFAULT, pLayout);
1008 }
1009}
1010
1011void SwDoc::SetNumRuleStart( const SwPosition& rPos, bool bFlag )
1012{
1013 SwTextNode* pTextNd = rPos.GetNode().GetTextNode();
1014
1015 if (!pTextNd)
1016 return;
1017
1018 const SwNumRule* pRule = pTextNd->GetNumRule();
1019 if( pRule && !bFlag != !pTextNd->IsListRestart())
1020 {
1021 if (GetIDocumentUndoRedo().DoesUndo())
1022 {
1023 GetIDocumentUndoRedo().AppendUndo(
1024 std::make_unique<SwUndoNumRuleStart>(rPos, bFlag) );
1025 }
1026
1027 pTextNd->SetListRestart(bFlag);
1028
1030 }
1031}
1032
1033void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
1034{
1035 SwTextNode* pTextNd = rPos.GetNode().GetTextNode();
1036
1037 if (!pTextNd)
1038 return;
1039
1040 if ( !pTextNd->HasAttrListRestartValue() ||
1041 pTextNd->GetAttrListRestartValue() != nStt )
1042 {
1043 if (GetIDocumentUndoRedo().DoesUndo())
1044 {
1045 GetIDocumentUndoRedo().AppendUndo(
1046 std::make_unique<SwUndoNumRuleStart>(rPos, nStt) );
1047 }
1048 pTextNd->SetAttrListRestartValue( nStt );
1049
1051 }
1052}
1053
1054// We can only delete if the Rule is unused!
1055bool SwDoc::DelNumRule( const OUString& rName, bool bBroadcast )
1056{
1057 sal_uInt16 nPos = FindNumRule( rName );
1058
1059 if (nPos == USHRT_MAX)
1060 return false;
1061
1062 if ( (*mpNumRuleTable)[ nPos ] == GetOutlineNumRule() )
1063 {
1064 OSL_FAIL( "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect" );
1065 return false;
1066 }
1067
1068 if( !IsUsed( *(*mpNumRuleTable)[ nPos ] ))
1069 {
1070 if (GetIDocumentUndoRedo().DoesUndo())
1071 {
1072 GetIDocumentUndoRedo().AppendUndo(
1073 std::make_unique<SwUndoNumruleDelete>(*(*mpNumRuleTable)[nPos], *this));
1074 }
1075
1076 if (bBroadcast)
1077 BroadcastStyleOperation(rName, SfxStyleFamily::Pseudo,
1078 SfxHintId::StyleSheetErased);
1079
1082 // #i34097# DeleteAndDestroy deletes rName if
1083 // rName is directly taken from the numrule.
1084 const OUString aTmpName( rName );
1085 delete (*mpNumRuleTable)[ nPos ];
1086 mpNumRuleTable->erase( mpNumRuleTable->begin() + nPos );
1087 maNumRuleMap.erase(aTmpName);
1088
1090 return true;
1091 }
1092 return false;
1093}
1094
1096{
1097 SwNumRule* pRule = FindNumRulePtr( rRule.GetName() );
1098 if( !pRule )
1099 return;
1100
1101 SwUndoInsNum* pUndo = nullptr;
1102 if (GetIDocumentUndoRedo().DoesUndo())
1103 {
1104 pUndo = new SwUndoInsNum( *pRule, rRule, *this );
1105 pUndo->GetHistory();
1106 GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pUndo) );
1107 }
1108 ::lcl_ChgNumRule( *this, rRule );
1109 if (pUndo)
1110 {
1111 pUndo->SetLRSpaceEndPos();
1112 }
1113
1115}
1116
1117bool SwDoc::RenameNumRule(const OUString & rOldName, const OUString & rNewName,
1118 bool bBroadcast)
1119{
1120 assert(!FindNumRulePtr(rNewName));
1121
1122 bool bResult = false;
1123 SwNumRule * pNumRule = FindNumRulePtr(rOldName);
1124
1125 if (pNumRule)
1126 {
1127 if (GetIDocumentUndoRedo().DoesUndo())
1128 {
1129 GetIDocumentUndoRedo().AppendUndo(
1130 std::make_unique<SwUndoNumruleRename>(rOldName, rNewName, *this));
1131 }
1132
1133 SwNumRule::tTextNodeList aTextNodeList;
1134 pNumRule->GetTextNodeList( aTextNodeList );
1135
1136 pNumRule->SetName( rNewName, getIDocumentListsAccess() );
1137
1138 SwNumRuleItem aItem(rNewName);
1139
1140 for ( SwTextNode* pTextNd : aTextNodeList )
1141 {
1142 pTextNd->SetAttr(aItem);
1143 }
1144
1145 bResult = true;
1146
1147 if (bBroadcast)
1148 BroadcastStyleOperation(rOldName, SfxStyleFamily::Pseudo,
1149 SfxHintId::StyleSheetModified);
1150 }
1151
1152 return bResult;
1153}
1154
1156{
1157 for( sal_uInt16 n = GetNumRuleTable().size(); n; )
1158 {
1159 SwNumRule::tTextNodeList aTextNodeList;
1160 GetNumRuleTable()[ --n ]->GetTextNodeList( aTextNodeList );
1161 for ( SwTextNode* pTNd : aTextNodeList )
1162 {
1164 for(SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
1165 if (pFrame->HasAnimation() &&
1166 (!pFrame->GetMergedPara() || pFrame->GetMergedPara()->pParaPropsNode == pTNd))
1167 {
1168 pFrame->StopAnimation( pOut );
1169 }
1170 }
1171 }
1172}
1173
1175 const OUString& rOldRule, const OUString& rNewRule )
1176{
1177 SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
1178 *pNewRule = FindNumRulePtr( rNewRule );
1179 if( !pOldRule || !pNewRule || pOldRule == pNewRule )
1180 return;
1181
1182 SwUndoInsNum* pUndo = nullptr;
1183 if (GetIDocumentUndoRedo().DoesUndo())
1184 {
1185 // Start/End for attributes!
1186 GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
1187 pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
1188 GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
1189 }
1190
1191 SwNumRule::tTextNodeList aTextNodeList;
1192 pOldRule->GetTextNodeList( aTextNodeList );
1193 if ( !aTextNodeList.empty() )
1194 {
1195 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : nullptr );
1196
1197 const SwTextNode* pGivenTextNode = rPos.GetNode().GetTextNode();
1198 SwNumRuleItem aRule( rNewRule );
1199 for ( SwTextNode* pTextNd : aTextNodeList )
1200 {
1201 if ( pGivenTextNode &&
1202 pGivenTextNode->GetListId() == pTextNd->GetListId() )
1203 {
1204 aRegH.RegisterInModify( pTextNd, *pTextNd );
1205
1206 pTextNd->SetAttr( aRule );
1207 pTextNd->NumRuleChgd();
1208 }
1209 }
1210 GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
1212 }
1213}
1214
1215namespace
1216{
1217 struct ListStyleData
1218 {
1219 SwNumRule* pReplaceNumRule;
1220 bool bCreateNewList;
1221 OUString sListId;
1222
1223 ListStyleData()
1224 : pReplaceNumRule( nullptr ),
1225 bCreateNewList( false )
1226 {}
1227 };
1228}
1229
1231{
1232 OSL_ENSURE( &rPaM.GetDoc() == this, "need same doc" );
1233
1234 std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
1235
1236 bool bFirst = true;
1237
1238 const SwNodeOffset nStt = rPaM.Start()->GetNodeIndex();
1239 const SwNodeOffset nEnd = rPaM.End()->GetNodeIndex();
1240 for (SwNodeOffset n = nStt; n <= nEnd; n++)
1241 {
1242 SwTextNode * pCNd = GetNodes()[n]->GetTextNode();
1243
1244 if (pCNd)
1245 {
1246 SwNumRule * pRule = pCNd->GetNumRule();
1247
1248 if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
1249 {
1250 ListStyleData aListStyleData = aMyNumRuleMap[pRule];
1251
1252 if ( aListStyleData.pReplaceNumRule == nullptr )
1253 {
1254 if (bFirst)
1255 {
1256 SwPosition aPos(*pCNd);
1257 aListStyleData.pReplaceNumRule =
1258 const_cast<SwNumRule *>
1259 (SearchNumRule( aPos, false, pCNd->HasNumber(),
1260 false, 0,
1261 aListStyleData.sListId, nullptr, true ));
1262 }
1263
1264 if ( aListStyleData.pReplaceNumRule == nullptr )
1265 {
1266 aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
1267 aListStyleData.pReplaceNumRule->SetName( GetUniqueNumRuleName(), getIDocumentListsAccess() );
1268 aListStyleData.bCreateNewList = true;
1269 }
1270
1271 aMyNumRuleMap[pRule] = aListStyleData;
1272 }
1273
1274 SwPaM aPam(*pCNd);
1275
1276 SetNumRule( aPam,
1277 *aListStyleData.pReplaceNumRule,
1278 aListStyleData.bCreateNewList,
1279 nullptr,
1280 aListStyleData.sListId );
1281 if ( aListStyleData.bCreateNewList )
1282 {
1283 aListStyleData.bCreateNewList = false;
1284 aListStyleData.sListId = pCNd->GetListId();
1285 aMyNumRuleMap[pRule] = aListStyleData;
1286 }
1287
1288 bFirst = false;
1289 }
1290 }
1291 }
1292}
1293
1294bool SwDoc::NoNum( const SwPaM& rPam )
1295{
1296
1297 bool bRet = getIDocumentContentOperations().SplitNode( *rPam.GetPoint(), false );
1298 // Do we actually use Numbering at all?
1299 if( bRet )
1300 {
1301 // Set NoNum and Update
1302 SwTextNode* pNd = rPam.GetPoint()->GetNode().GetTextNode();
1303 const SwNumRule* pRule = pNd->GetNumRule();
1304 if( pRule )
1305 {
1306 pNd->SetCountedInList(false);
1307
1309 }
1310 else
1311 bRet = false; // no Numbering or just always true?
1312 }
1313 return bRet;
1314}
1315
1316void SwDoc::DelNumRules(const SwPaM& rPam, SwRootFrame const*const pLayout)
1317{
1318 SwPaM aPam(rPam, nullptr);
1319 ExpandPamForParaPropsNodes(aPam, pLayout);
1320 SwNodeOffset nStt = aPam.Start()->GetNodeIndex();
1321 SwNodeOffset const nEnd = aPam.End()->GetNodeIndex();
1322
1323 SwUndoDelNum* pUndo;
1324 if (GetIDocumentUndoRedo().DoesUndo())
1325 {
1326 pUndo = new SwUndoDelNum( aPam );
1327 GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
1328 }
1329 else
1330 pUndo = nullptr;
1331
1332 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : nullptr );
1333
1334 SwNumRuleItem aEmptyRule;
1335 const SwNode* pOutlNd = nullptr;
1336 for( ; nStt <= nEnd; ++nStt )
1337 {
1338 SwTextNode* pTNd = GetNodes()[ nStt ]->GetTextNode();
1339 if (pLayout && pTNd)
1340 {
1341 pTNd = sw::GetParaPropsNode(*pLayout, *pTNd);
1342 }
1343 SwNumRule* pNumRuleOfTextNode = pTNd ? pTNd->GetNumRule() : nullptr;
1344 if ( pTNd && pNumRuleOfTextNode )
1345 {
1346 // recognize changes of attribute for undo
1347 aRegH.RegisterInModify( pTNd, *pTNd );
1348
1349 if( pUndo )
1350 pUndo->AddNode( *pTNd );
1351
1352 // directly set list style attribute is reset, otherwise empty
1353 // list style is applied
1354 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
1355 if ( pAttrSet &&
1356 pAttrSet->GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET )
1358 else
1359 pTNd->SetAttr( aEmptyRule );
1360
1366
1367 if( RES_CONDTXTFMTCOLL == pTNd->GetFormatColl()->Which() )
1368 {
1369 pTNd->ChkCondColl();
1370 }
1371 else if( !pOutlNd &&
1373 {
1374 pOutlNd = pTNd;
1375 }
1376 }
1377 }
1378
1379 // Finally, update all
1380 UpdateNumRule();
1381
1382 if( pOutlNd )
1383 GetNodes().UpdateOutlineIdx( *pOutlNd );
1384}
1385
1387{
1388 for (size_t n = 0; n < mpNumRuleTable->size(); ++n)
1389 (*mpNumRuleTable)[n]->SetInvalidRule(true);
1390}
1391
1392// To the next/preceding Bullet at the same Level
1393static bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
1394 bool bOverUpper, sal_uInt8 nNumber )
1395{
1396 OSL_ENSURE( nNumber < MAXLEVEL,
1397 "<lcl_IsNumOk(..)> - misusage of method" );
1398
1399 bool bRet = false;
1400 {
1401 if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
1402 bRet = true;
1403 else if( nNumber > rLower )
1404 rLower = nNumber;
1405 else if( nNumber < rUpper )
1406 rUpper = nNumber;
1407 }
1408 return bRet;
1409}
1410
1411static bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
1412{
1413 bool bRet = false;
1414 const SwNode& rNd = rIdx.GetNode();
1415 switch( rNd.GetNodeType() )
1416 {
1417 case SwNodeType::End:
1420 break;
1421
1422 case SwNodeType::Start:
1423 bRet = SwTableBoxStartNode == static_cast<const SwStartNode&>(rNd).GetStartNodeType();
1424 break;
1425
1426 case SwNodeType::Section: // that one's valid, so proceed
1427 bRet = true;
1428 break;
1429
1430 default: break;
1431 }
1432 return bRet;
1433}
1434
1435namespace sw {
1436
1437void
1439{
1440 if (pLayout && pLayout->HasMergedParas())
1441 {
1442 if (rIndex.GetNode().IsTextNode())
1443 {
1445 {
1446 // not a tracked row deletion in Hide Changes mode
1447 if (SwContentFrame* pFrame = rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))
1448 {
1449 if (sw::MergedPara* pMerged = static_cast<SwTextFrame*>(pFrame)->GetMergedPara())
1450 {
1451 rIndex = pMerged->pFirstNode->GetIndex();
1452 }
1453 }
1454 }
1455 }
1456 else if (rIndex.GetNode().IsEndNode())
1457 {
1459 {
1460 rIndex = *rIndex.GetNode().StartOfSectionNode();
1461 assert(rIndex.GetNode().IsTableNode());
1462 }
1463 }
1464 }
1465 --rIndex;
1466 if (pLayout && rIndex.GetNode().IsTextNode())
1467 {
1468 rIndex = *sw::GetParaPropsNode(*pLayout, *rIndex.GetNode().GetTextNode());
1469 }
1470}
1471
1472void
1474{
1475 if (pLayout && pLayout->HasMergedParas())
1476 {
1477 if (rIndex.GetNode().IsTextNode())
1478 {
1480 {
1481 if (SwContentFrame* pFrame = rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))
1482 {
1483 if (sw::MergedPara* pMerged = static_cast<SwTextFrame*>(pFrame)->GetMergedPara())
1484 {
1485 rIndex = pMerged->pLastNode->GetIndex();
1486 }
1487 }
1488 }
1489 }
1490 else if (rIndex.GetNode().IsTableNode())
1491 {
1493 {
1494 rIndex = *rIndex.GetNode().EndOfSectionNode();
1495 }
1496 }
1497 }
1498 ++rIndex;
1499 if (pLayout && rIndex.GetNode().IsTextNode())
1500 {
1501 rIndex = *sw::GetParaPropsNode(*pLayout, *rIndex.GetNode().GetTextNode());
1502 }
1503}
1504
1505} // namespace sw
1506
1507static bool lcl_GotoNextPrevNum( SwPosition& rPos, bool bNext,
1508 bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower,
1509 SwRootFrame const*const pLayout)
1510{
1511 const SwTextNode* pNd = rPos.GetNode().GetTextNode();
1512 if (pNd && pLayout)
1513 {
1514 pNd = sw::GetParaPropsNode(*pLayout, *pNd);
1515 }
1516 if( !pNd || nullptr == pNd->GetNumRule() )
1517 return false;
1518
1519 sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1520
1521 SwNodeIndex aIdx( rPos.GetNode() );
1522 if( ! pNd->IsCountedInList() )
1523 {
1524 bool bError = false;
1525 do {
1526 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1527 if( aIdx.GetNode().IsTextNode() )
1528 {
1529 pNd = aIdx.GetNode().GetTextNode();
1530 const SwNumRule* pRule = pNd->GetNumRule();
1531
1532 if( pRule )
1533 {
1534 sal_uInt8 nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1535 if( pNd->IsCountedInList() || (nTmpNum < nSrchNum ) )
1536 break; // found it!
1537 }
1538 else
1539 bError = true;
1540 }
1541 else
1542 bError = !lcl_IsValidPrevNextNumNode( aIdx );
1543
1544 } while( !bError );
1545 if( bError )
1546 return false;
1547 }
1548
1549 sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
1550 bool bRet = false;
1551
1552 const SwTextNode* pLast;
1553 if( bNext )
1554 {
1555 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1556 pLast = pNd;
1557 }
1558 else
1559 {
1560 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1561 pLast = nullptr;
1562 }
1563
1564 while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
1565 : aIdx.GetIndex() != SwNodeOffset(0) )
1566 {
1567 if( aIdx.GetNode().IsTextNode() )
1568 {
1569 pNd = aIdx.GetNode().GetTextNode();
1570 const SwNumRule* pRule = pNd->GetNumRule();
1571 if( pRule )
1572 {
1573 if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
1574 static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
1575 {
1576 rPos.Assign(aIdx);
1577 bRet = true;
1578 break;
1579 }
1580 else
1581 pLast = pNd;
1582 }
1583 else
1584 break;
1585 }
1586 else if( !lcl_IsValidPrevNextNumNode( aIdx ))
1587 break;
1588
1589 if( bNext )
1590 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1591 else
1592 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1593 }
1594
1595 if( !bRet && !bOverUpper && pLast ) // do not iterate over higher numbers, but still to the end
1596 {
1597 if( bNext )
1598 rPos.Assign(aIdx);
1599 else
1600 rPos.Assign( *pLast );
1601 bRet = true;
1602 }
1603
1604 if( bRet )
1605 {
1606 if( pUpper )
1607 *pUpper = nUpper;
1608 if( pLower )
1609 *pLower = nLower;
1610 }
1611 return bRet;
1612}
1613
1614bool SwDoc::GotoNextNum(SwPosition& rPos, SwRootFrame const*const pLayout,
1615 bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower)
1616{
1617 return ::lcl_GotoNextPrevNum(rPos, true, bOverUpper, pUpper, pLower, pLayout);
1618}
1619
1621 const bool bForward,
1622 const bool bNum,
1623 const bool bOutline,
1624 int nNonEmptyAllowed,
1625 OUString& sListId,
1626 SwRootFrame const* pLayout,
1627 const bool bInvestigateStartNode)
1628{
1629 const SwNumRule * pResult = nullptr;
1630 SwTextNode * pTextNd = rPos.GetNode().GetTextNode();
1631 if (pLayout)
1632 {
1633 pTextNd = sw::GetParaPropsNode(*pLayout, rPos.GetNode());
1634 }
1635 SwNode * pStartFromNode = pTextNd;
1636
1637 if (pTextNd)
1638 {
1639 SwNodeIndex aIdx(rPos.GetNode());
1640
1641 // - the start node has also been investigated, if requested.
1642 const SwNode * pNode = nullptr;
1643 do
1644 {
1645 if ( !bInvestigateStartNode )
1646 {
1647 if (bForward)
1648 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1649 else
1650 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1651 }
1652
1653 if (aIdx.GetNode().IsTextNode())
1654 {
1655 pTextNd = aIdx.GetNode().GetTextNode();
1656
1657 const SwNumRule * pNumRule = pTextNd->GetNumRule();
1658 if (pNumRule)
1659 {
1660 if ( ( pNumRule->IsOutlineRule() == bOutline ) &&
1661 ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
1662 ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
1663 {
1664 pResult = pTextNd->GetNumRule();
1665 // provide also the list id, to which the text node belongs.
1666 sListId = pTextNd->GetListId();
1667 }
1668
1669 break;
1670 }
1671 else if (pTextNd->Len() > 0 || nullptr != pTextNd->GetNumRule())
1672 {
1673 if (nNonEmptyAllowed == 0)
1674 break;
1675
1676 nNonEmptyAllowed--;
1677
1678 if (nNonEmptyAllowed < 0)
1679 nNonEmptyAllowed = -1;
1680 }
1681 }
1682
1683 if ( bInvestigateStartNode )
1684 {
1685 if (bForward)
1686 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1687 else
1688 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1689 }
1690
1691 pNode = &aIdx.GetNode();
1692 }
1693 while (pNode != GetNodes().DocumentSectionStartNode(pStartFromNode) &&
1694 pNode != GetNodes().DocumentSectionEndNode(pStartFromNode));
1695 }
1696
1697 return pResult;
1698}
1699
1700bool SwDoc::GotoPrevNum(SwPosition& rPos, SwRootFrame const*const pLayout,
1701 bool bOverUpper)
1702{
1703 return ::lcl_GotoNextPrevNum(rPos, false, bOverUpper, nullptr, nullptr, pLayout);
1704}
1705
1706bool SwDoc::NumUpDown(const SwPaM& rPam, bool bDown, SwRootFrame const*const pLayout)
1707{
1708 SwPaM aPam(rPam, nullptr);
1709 ExpandPamForParaPropsNodes(aPam, pLayout);
1710 SwNodeOffset nStt = aPam.Start()->GetNodeIndex();
1711 SwNodeOffset const nEnd = aPam.End()->GetNodeIndex();
1712
1713 // -> outline nodes are promoted or demoted differently
1714 bool bOnlyOutline = true;
1715 bool bOnlyNonOutline = true;
1716 for (SwNodeOffset n = nStt; n <= nEnd; n++)
1717 {
1718 SwTextNode * pTextNd = GetNodes()[n]->GetTextNode();
1719
1720 if (pTextNd)
1721 {
1722 if (pLayout)
1723 {
1724 pTextNd = sw::GetParaPropsNode(*pLayout, *pTextNd);
1725 }
1726 SwNumRule * pRule = pTextNd->GetNumRule();
1727
1728 if (pRule)
1729 {
1730 if (pRule->IsOutlineRule())
1731 bOnlyNonOutline = false;
1732 else
1733 bOnlyOutline = false;
1734 }
1735 }
1736 }
1737
1738 bool bRet = true;
1739 sal_Int8 nDiff = bDown ? 1 : -1;
1740
1741 if (bOnlyOutline)
1742 bRet = OutlineUpDown(rPam, nDiff, pLayout);
1743 else if (bOnlyNonOutline)
1744 {
1745 /* #i24560#
1746 Only promote or demote if all selected paragraphs are
1747 promotable resp. demotable.
1748 */
1749 for (SwNodeOffset nTmp = nStt; nTmp <= nEnd; ++nTmp)
1750 {
1751 SwTextNode* pTNd = GetNodes()[ nTmp ]->GetTextNode();
1752
1753 // Make code robust: consider case that the node doesn't denote a
1754 // text node.
1755 if ( pTNd )
1756 {
1757 if (pLayout)
1758 {
1759 pTNd = sw::GetParaPropsNode(*pLayout, *pTNd);
1760 }
1761
1762 SwNumRule * pRule = pTNd->GetNumRule();
1763
1764 if (pRule)
1765 {
1766 sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1767 if( (-1 == nDiff && 0 >= nLevel) ||
1768 (1 == nDiff && MAXLEVEL - 1 <= nLevel))
1769 bRet = false;
1770 }
1771 }
1772 }
1773
1774 if( bRet )
1775 {
1776 if (GetIDocumentUndoRedo().DoesUndo())
1777 {
1778 GetIDocumentUndoRedo().AppendUndo(
1779 std::make_unique<SwUndoNumUpDown>(aPam, nDiff) );
1780 }
1781
1782 SwTextNode* pPrev = nullptr;
1783 for(SwNodeOffset nTmp = nStt; nTmp <= nEnd; ++nTmp )
1784 {
1785 SwTextNode* pTNd = GetNodes()[ nTmp ]->GetTextNode();
1786
1787 if( pTNd)
1788 {
1789 if (pLayout)
1790 {
1791 pTNd = sw::GetParaPropsNode(*pLayout, *pTNd);
1792 if (pTNd == pPrev)
1793 {
1794 continue;
1795 }
1796 pPrev = pTNd;
1797 }
1798
1799 SwNumRule * pRule = pTNd->GetNumRule();
1800
1801 if (pRule)
1802 {
1803 sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1804 nLevel = nLevel + nDiff;
1805
1806 pTNd->SetAttrListLevel(nLevel);
1807 }
1808 }
1809 }
1810
1811 ChkCondColls();
1813 }
1814 }
1815
1816 return bRet;
1817}
1818
1819// this function doesn't contain any numbering-related code, but it is
1820// primarily called to move numbering-relevant paragraphs around, hence
1821// it will expand its selection to include full SwTextFrames.
1822bool SwDoc::MoveParagraph(SwPaM& rPam, SwNodeOffset nOffset, bool const bIsOutlMv)
1823{
1825
1826 // sw_redlinehide: as long as a layout with Hide mode exists, only
1827 // move nodes that have merged frames *completely*
1828 SwRootFrame const* pLayout(nullptr);
1829 for (SwRootFrame const*const pLay : GetAllLayouts())
1830 {
1831 if (pLay->HasMergedParas())
1832 {
1833 pLayout = pLay;
1834 }
1835 }
1836 if (pLayout)
1837 {
1838 std::pair<SwTextNode *, SwTextNode *> nodes(
1839 sw::GetFirstAndLastNode(*pLayout, rPam.Start()->GetNode()));
1840 if (nodes.first && nodes.first != &rPam.Start()->GetNode())
1841 {
1842 assert(nodes.second);
1843 if (nOffset < SwNodeOffset(0))
1844 {
1845 nOffset += rPam.Start()->GetNodeIndex() - nodes.first->GetIndex();
1846 if (SwNodeOffset(0) <= nOffset) // hack: there are callers that know what
1847 { // node they want; those should never need
1848 nOffset = SwNodeOffset(-1); // this; other callers just pass in -1
1849 } // and those should still move
1850 }
1851 if (!rPam.HasMark())
1852 {
1853 rPam.SetMark();
1854 }
1855 assert(nodes.first->GetIndex() < rPam.Start()->GetNodeIndex());
1856 rPam.Start()->Assign(*nodes.first);
1857 }
1858 nodes = sw::GetFirstAndLastNode(*pLayout, rPam.End()->GetNode());
1859 if (nodes.second && nodes.second != &rPam.End()->GetNode())
1860 {
1861 assert(nodes.first);
1862 if (SwNodeOffset(0) < nOffset)
1863 {
1864 nOffset -= nodes.second->GetIndex() - rPam.End()->GetNodeIndex();
1865 if (nOffset <= SwNodeOffset(0)) // hack: there are callers that know what
1866 { // node they want; those should never need
1867 nOffset = SwNodeOffset(+1); // this; other callers just pass in +1
1868 } // and those should still move
1869 }
1870 if (!rPam.HasMark())
1871 {
1872 rPam.SetMark();
1873 }
1874 assert(rPam.End()->GetNodeIndex() < nodes.second->GetIndex());
1875 // until end, otherwise Impl will detect overlapping redline
1876 rPam.End()->Assign(*nodes.second, nodes.second->GetTextNode()->Len());
1877 }
1878
1879 if (nOffset > SwNodeOffset(0))
1880 { // sw_redlinehide: avoid moving into delete redline, skip forward
1881 if (GetNodes().GetEndOfContent().GetIndex() <= rPam.End()->GetNodeIndex() + nOffset)
1882 {
1883 return false; // can't move
1884 }
1885 SwNode const* pNode(GetNodes()[rPam.End()->GetNodeIndex() + nOffset + 1]);
1888 {
1889 for ( ; ; ++nOffset)
1890 {
1891 pNode = GetNodes()[rPam.End()->GetNodeIndex() + nOffset];
1892 if (pNode->IsTextNode())
1893 {
1894 nodes = GetFirstAndLastNode(*pLayout, *pNode->GetTextNode());
1895 assert(nodes.first && nodes.second);
1896 nOffset += nodes.second->GetIndex() - pNode->GetIndex();
1897 // on last; will be incremented below to behind-last
1898 break;
1899 }
1900 }
1901 }
1902 }
1903 else
1904 { // sw_redlinehide: avoid moving into delete redline, skip backward
1905 if (rPam.Start()->GetNodeIndex() + nOffset < SwNodeOffset(1))
1906 {
1907 return false; // can't move
1908 }
1909 SwNode const* pNode(GetNodes()[rPam.Start()->GetNodeIndex() + nOffset]);
1912 {
1913 for ( ; ; --nOffset)
1914 {
1915 pNode = GetNodes()[rPam.Start()->GetNodeIndex() + nOffset];
1916 if (pNode->IsTextNode())
1917 {
1918 nodes = GetFirstAndLastNode(*pLayout, *pNode->GetTextNode());
1919 assert(nodes.first && nodes.second);
1920 nOffset -= pNode->GetIndex() - nodes.first->GetIndex();
1921 // on first
1922 break;
1923 }
1924 }
1925 }
1926 }
1927 }
1928 return MoveParagraphImpl(rPam, nOffset, bIsOutlMv, pLayout);
1929}
1930
1932 bool const bIsOutlMv, SwRootFrame const*const pLayout)
1933{
1934 auto [pStt, pEnd] = rPam.StartEnd(); // SwPosition*
1935
1936 SwNodeOffset nStIdx = pStt->GetNodeIndex();
1937 SwNodeOffset nEndIdx = pEnd->GetNodeIndex();
1938
1939 // Here are some sophisticated checks whether the wished PaM will be moved or not.
1940 // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
1941 // checks...
1942 SwNode *pTmp1;
1943 SwNode *pTmp2;
1944 if( bIsOutlMv )
1945 {
1946 // For moving chapters (outline) the following reason will deny the move:
1947 // if a start node is inside the moved range and its end node outside or vice versa.
1948 // If a start node is the first moved paragraph, its end node has to be within the moved
1949 // range, too (e.g. as last node).
1950 // If an end node is the last node of the moved range, its start node has to be a part of
1951 // the moved section, too.
1952 pTmp1 = GetNodes()[ nStIdx ];
1953 if( pTmp1->IsStartNode() )
1954 {
1955 // coverity[copy_paste_error : FALSE] - First is a start node
1956 pTmp2 = pTmp1->EndOfSectionNode();
1957 if( pTmp2->GetIndex() > nEndIdx )
1958 return false; // Its end node is behind the moved range
1959 }
1960 pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
1961 if( pTmp1->GetIndex() <= nEndIdx )
1962 return false; // End node inside but start node before moved range => no.
1963 pTmp1 = GetNodes()[ nEndIdx ];
1964 if( pTmp1->IsEndNode() )
1965 { // The last one is an end node
1966 pTmp1 = pTmp1->StartOfSectionNode();
1967 if( pTmp1->GetIndex() < nStIdx )
1968 return false; // Its start node is before the moved range.
1969 }
1970 pTmp1 = pTmp1->StartOfSectionNode();
1971 if( pTmp1->GetIndex() >= nStIdx )
1972 return false; // A start node which ends behind the moved range => no.
1973 }
1974
1975 SwNodeOffset nInStIdx, nInEndIdx;
1976 SwNodeOffset nOffs = nOffset;
1977 if( nOffset > SwNodeOffset(0) )
1978 {
1979 nInEndIdx = nEndIdx;
1980 nEndIdx += nOffset;
1981 ++nOffs;
1982 }
1983 else
1984 {
1985 // Impossible to move to negative index
1986 if( abs( nOffset ) > nStIdx)
1987 return false;
1988
1989 nInEndIdx = nStIdx - 1;
1990 nStIdx += nOffset;
1991 }
1992 nInStIdx = nInEndIdx + 1;
1993 // The following paragraphs shall be swapped:
1994 // Swap [ nStIdx, nInEndIdx ] with [ nInStIdx, nEndIdx ]
1995
1996 if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
1997 return false;
1998
1999 if( !bIsOutlMv )
2000 { // And here the restrictions for moving paragraphs other than chapters (outlines)
2001 // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
2002 // It will checked if the both "start" nodes as well as the both "end" notes belongs to
2003 // the same start-end-section. This is more restrictive than the conditions checked above.
2004 // E.g. a paragraph will not escape from a section or be inserted to another section.
2005 pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
2006 pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
2007 if( pTmp1 != pTmp2 )
2008 return false; // "start" nodes in different sections
2009 pTmp1 = GetNodes()[ nEndIdx ];
2010 bool bIsEndNode = pTmp1->IsEndNode();
2011 if( !pTmp1->IsStartNode() )
2012 {
2013 pTmp1 = pTmp1->StartOfSectionNode();
2014 if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
2015 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
2016 }
2017 pTmp1 = pTmp1->EndOfSectionNode();
2018 pTmp2 = GetNodes()[ nInEndIdx ];
2019 if( !pTmp2->IsStartNode() )
2020 {
2021 bIsEndNode = pTmp2->IsEndNode();
2022 pTmp2 = pTmp2->StartOfSectionNode();
2023 if( bIsEndNode )
2024 pTmp2 = pTmp2->StartOfSectionNode();
2025 }
2026 pTmp2 = pTmp2->EndOfSectionNode();
2027 if( pTmp1 != pTmp2 )
2028 return false; // The "end" notes are in different sections
2029 }
2030
2031 // Test for Redlining - Can the Selection be moved at all, actually?
2032 if( !getIDocumentRedlineAccess().IsIgnoreRedline() )
2033 {
2034 SwRedlineTable::size_type nRedlPos = getIDocumentRedlineAccess().GetRedlinePos( pStt->GetNode(), RedlineType::Delete );
2035 if( SwRedlineTable::npos != nRedlPos )
2036 {
2037 SwContentNode* pCNd = pEnd->GetNode().GetContentNode();
2038 SwPosition aStPos( pStt->GetNode() );
2039 SwPosition aEndPos( pEnd->GetNode(), pCNd, pCNd ? pCNd->Len() : 1 );
2040 bool bCheckDel = true;
2041
2042 // There is a some Redline Delete Object for the range
2043 for( ; nRedlPos < getIDocumentRedlineAccess().GetRedlineTable().size(); ++nRedlPos )
2044 {
2045 const SwRangeRedline* pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ];
2046 if( !bCheckDel || RedlineType::Delete == pTmp->GetType() )
2047 {
2048 auto [pRStt, pREnd] = pTmp->StartEnd(); // SwPosition*
2049 switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
2050 {
2052 case SwComparePosition::Behind: // Pos1 comes after Pos2
2054 break;
2055
2057 case SwComparePosition::Before: // Pos1 comes before Pos2
2058 break;
2059 case SwComparePosition::Inside: // Pos1 is completely inside Pos2
2060 // that's valid, but check all following for overlapping
2061 bCheckDel = false;
2062 break;
2063
2064 case SwComparePosition::Outside: // Pos2 is completely inside Pos1
2065 case SwComparePosition::Equal: // Pos1 is equal to Pos2
2066 case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 in the beginning
2067 case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at the end
2068 return false;
2069 }
2070 }
2071 }
2072 }
2073 }
2074
2075 {
2076 // Send DataChanged before moving. We then can detect
2077 // which objects are still in the range.
2078 // After the move they could come before/after the
2079 // Position.
2080 SwDataChanged aTmp( rPam );
2081 }
2082
2083 SwNodeIndex aIdx( nOffset > SwNodeOffset(0) ? pEnd->GetNode() : pStt->GetNode(), nOffs );
2084 SwNodeRange aMvRg( pStt->GetNode(), SwNodeOffset(0), pEnd->GetNode(), SwNodeOffset(+1) );
2085
2086 SwRangeRedline* pOwnRedl = nullptr;
2087 if( getIDocumentRedlineAccess().IsRedlineOn() )
2088 {
2089 // If the range is completely in the own Redline, we can move it!
2090 SwRedlineTable::size_type nRedlPos = getIDocumentRedlineAccess().GetRedlinePos( pStt->GetNode(), RedlineType::Insert );
2091 if( SwRedlineTable::npos != nRedlPos )
2092 {
2094 auto [pRStt, pREnd] = pTmp->StartEnd(); // SwPosition*
2095 SwRangeRedline aTmpRedl( RedlineType::Insert, rPam );
2096 const SwContentNode* pCEndNd = pEnd->GetNode().GetContentNode();
2097 // Is completely in the range and is the own Redline too?
2098 if( aTmpRedl.IsOwnRedline( *pTmp ) &&
2099 (pRStt->GetNode() < pStt->GetNode() ||
2100 (pRStt->GetNode() == pStt->GetNode() && !pRStt->GetContentIndex()) ) &&
2101 (pEnd->GetNode() < pREnd->GetNode() ||
2102 (pEnd->GetNode() == pREnd->GetNode() &&
2103 pCEndNd ? pREnd->GetContentIndex() == pCEndNd->Len()
2104 : !pREnd->GetContentIndex() )) )
2105 {
2106 pOwnRedl = pTmp;
2107 if( nRedlPos + 1 < getIDocumentRedlineAccess().GetRedlineTable().size() )
2108 {
2109 pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos+1 ];
2110 if( *pTmp->Start() == *pREnd )
2111 // then don't!
2112 pOwnRedl = nullptr;
2113 }
2114
2115 if( pOwnRedl &&
2116 ( pRStt->GetNode() > aIdx.GetNode() || aIdx > pREnd->GetNode() ||
2117 // pOwnRedl doesn't start at the beginning of a node, so it's not
2118 // possible to resize it to contain the line moved before it
2119 ( pRStt->GetNode() == aIdx.GetNode() && pRStt->GetContentIndex() > 0 ) ) )
2120 {
2121 // it's not in itself, so don't move it
2122 pOwnRedl = nullptr;
2123 }
2124 }
2125 }
2126
2127 if( !pOwnRedl )
2128 {
2129 GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
2130
2131 // First the Insert, then the Delete
2132 SwPosition aInsPos( aIdx );
2133
2134 std::optional<SwPaM> oPam( std::in_place, pStt->GetNode(), 0, aMvRg.aEnd.GetNode(), 0 );
2135
2136 SwPaM& rOrigPam(rPam);
2137 rOrigPam.DeleteMark();
2138 rOrigPam.GetPoint()->Assign(aIdx.GetIndex() - 1);
2139
2140 bool bDelLastPara = !aInsPos.GetNode().IsContentNode();
2141 SwNodeOffset nOrigIdx = aIdx.GetIndex();
2142
2143 /* When copying to a non-content node Copy will
2144 insert a paragraph before that node and insert before
2145 that inserted node. Copy creates an SwUndoInserts that
2146 does not cover the extra paragraph. Thus we insert the
2147 extra paragraph ourselves, _with_ correct undo
2148 information. */
2149 if (bDelLastPara)
2150 {
2151 /* aInsPos points to the non-content node. Move it to
2152 the previous content node. */
2153 SwPaM aInsPam(aInsPos);
2154 const bool bMoved = aInsPam.Move(fnMoveBackward);
2155 OSL_ENSURE(bMoved, "No content node found!");
2156
2157 if (bMoved)
2158 {
2159 /* Append the new node after the content node
2160 found. The new position to insert the moved
2161 paragraph at is before the inserted
2162 paragraph. */
2164 aInsPos = *aInsPam.GetPoint();
2165 }
2166 }
2167
2168 --aIdx; // move before insertion
2169
2170 // adjust empty nodes later
2171 SwTextNode const*const pIsEmptyNode(nOffset < SwNodeOffset(0)
2172 ? aInsPos.GetNode().GetTextNode()
2173 : aIdx.GetNode().GetTextNode());
2174 bool bIsEmptyNode = pIsEmptyNode && pIsEmptyNode->Len() == 0;
2175
2177
2178 // now delete all the delete redlines that were copied
2179#ifndef NDEBUG
2180 size_t nRedlines(getIDocumentRedlineAccess().GetRedlineTable().size());
2181#endif
2182 if (nOffset > SwNodeOffset(0))
2183 assert(oPam->End()->GetNodeIndex() - oPam->Start()->GetNodeIndex() + nOffset == aInsPos.GetNodeIndex() - oPam->End()->GetNodeIndex());
2184 else
2185 assert(oPam->Start()->GetNodeIndex() - oPam->End()->GetNodeIndex() + nOffset == aInsPos.GetNodeIndex() - oPam->End()->GetNodeIndex());
2187 getIDocumentRedlineAccess().GetRedline(*oPam->End(), &i);
2188 for ( ; 0 < i; --i)
2189 { // iterate backwards and offset via the start nodes difference
2190 SwRangeRedline const*const pRedline = getIDocumentRedlineAccess().GetRedlineTable()[i - 1];
2191 if (*pRedline->End() < *oPam->Start())
2192 {
2193 break;
2194 }
2195 if (pRedline->GetType() == RedlineType::Delete &&
2196 // tdf#145066 skip full-paragraph deletion which was jumped over
2197 // in Show Changes mode to avoid of deleting an extra row
2198 *oPam->Start() <= *pRedline->Start())
2199 {
2200 SwRangeRedline* pNewRedline;
2201 {
2202 SwPaM pam(*pRedline, nullptr);
2203 SwNodeOffset const nCurrentOffset(
2204 nOrigIdx - oPam->Start()->GetNodeIndex());
2205 pam.GetPoint()->Assign(pam.GetPoint()->GetNodeIndex() + nCurrentOffset,
2206 pam.GetPoint()->GetContentIndex());
2207 pam.GetMark()->Assign(pam.GetMark()->GetNodeIndex() + nCurrentOffset,
2208 pam.GetMark()->GetContentIndex());
2209
2210 pNewRedline = new SwRangeRedline( RedlineType::Delete, pam );
2211 }
2212 // note: effectively this will DeleteAndJoin the pam!
2213 getIDocumentRedlineAccess().AppendRedline(pNewRedline, true);
2214 assert(getIDocumentRedlineAccess().GetRedlineTable().size() <= nRedlines);
2215 }
2216 }
2217
2218 if( bDelLastPara )
2219 {
2220 // We need to remove the last empty Node again
2221 aIdx = aInsPos.GetNode();
2222 SwContentNode* pCNd = SwNodes::GoPrevious( &aInsPos );
2223 if (pCNd)
2224 aInsPos.AssignEndIndex( *pCNd );
2225
2226 // All, that are in the to-be-deleted Node, need to be
2227 // moved to the next Node
2228 for(SwRangeRedline* pTmp : getIDocumentRedlineAccess().GetRedlineTable())
2229 {
2230 SwPosition* pPos = &pTmp->GetBound();
2231 if( pPos->GetNode() == aIdx.GetNode() )
2232 {
2233 pPos->Adjust(SwNodeOffset(1));
2234 }
2235 pPos = &pTmp->GetBound(false);
2236 if( pPos->GetNode() == aIdx.GetNode() )
2237 {
2238 pPos->Adjust(SwNodeOffset(1));
2239 }
2240 }
2241 CorrRel( aIdx.GetNode(), aInsPos );
2242
2243 if (pCNd)
2244 pCNd->JoinNext();
2245 }
2246
2247 rOrigPam.GetPoint()->Adjust(SwNodeOffset(1));
2248 assert(*oPam->GetMark() < *oPam->GetPoint());
2249 if (oPam->GetPoint()->GetNode().IsEndNode())
2250 { // ensure redline ends on content node
2251 oPam->GetPoint()->Adjust(SwNodeOffset(-1));
2252 assert(oPam->GetPoint()->GetNode().IsTextNode());
2253 SwTextNode *const pNode(oPam->GetPoint()->GetNode().GetTextNode());
2254 oPam->GetPoint()->SetContent(pNode->Len());
2255 }
2256
2258 if (GetIDocumentUndoRedo().DoesUndo())
2259 {
2260 // this should no longer happen in calls from the UI but maybe via API
2262 "sw.core", "redlines will be moved in DeleteAndJoin");
2263
2266 GetIDocumentUndoRedo().AppendUndo(
2267 std::make_unique<SwUndoRedlineDelete>(*oPam, SwUndoId::DELETE));
2268 }
2269
2270 SwRangeRedline* pNewRedline = new SwRangeRedline( RedlineType::Delete, *oPam );
2271
2272 // prevent assertion from aPam's target being deleted
2273 SwNodeIndex bound1(oPam->GetBound().GetNode());
2274 SwNodeIndex bound2(oPam->GetBound(false).GetNode());
2275 oPam.reset();
2276
2277 getIDocumentRedlineAccess().AppendRedline( pNewRedline, true );
2278
2279 oPam.emplace(bound1, bound2);
2281
2282 // avoid setting empty nodes to tracked insertion
2283 if ( bIsEmptyNode )
2284 {
2286 SwRedlineTable::size_type nRedlPosWithEmpty =
2287 getIDocumentRedlineAccess().GetRedlinePos( pStt->GetNode(), RedlineType::Insert );
2288 if ( SwRedlineTable::npos != nRedlPosWithEmpty )
2289 {
2290 pOwnRedl = rTable[nRedlPosWithEmpty];
2291 SwPosition *pRPos = nOffset < SwNodeOffset(0) ? pOwnRedl->End() : pOwnRedl->Start();
2292 SwNodeIndex aIdx2 ( pRPos->GetNode() );
2293 SwTextNode const*const pEmptyNode0(aIdx2.GetNode().GetTextNode());
2294 if ( nOffset < SwNodeOffset(0) )
2295 {
2296 // move up
2297 --aIdx2;
2298 SwTextNode const*const pEmptyNode(aIdx2.GetNode().GetTextNode());
2299 if ( pEmptyNode && pEmptyNode->Len() == 0 )
2300 pRPos->Adjust(SwNodeOffset(-1));
2301 }
2302 else if ( pEmptyNode0 && pEmptyNode0->Len() == 0 )
2303 {
2304 // move down
2305 ++aIdx2;
2306 SwTextNode const*const pEmptyNode(aIdx2.GetNode().GetTextNode());
2307 if (pEmptyNode)
2308 pRPos->Adjust(SwNodeOffset(+1));
2309 }
2310
2311 // sort redlines, when the trimmed range results bad redline order
2312 if ( nRedlPosWithEmpty + 1 < rTable.size() &&
2313 *rTable[nRedlPosWithEmpty + 1] < *rTable[nRedlPosWithEmpty] )
2314 {
2315 rTable.Remove(nRedlPosWithEmpty);
2316 rTable.Insert(pOwnRedl);
2317 }
2318 }
2319 }
2320
2322 GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
2324
2325 return true;
2326 }
2327 }
2328
2329 if( !pOwnRedl && !getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() )
2330 {
2331 SwPaM aTemp(aIdx);
2333 }
2334
2335 SwNodeOffset nRedlSttNd(0), nRedlEndNd(0);
2336 if( pOwnRedl )
2337 {
2338 const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2339 nRedlSttNd = pRStt->GetNodeIndex();
2340 nRedlEndNd = pREnd->GetNodeIndex();
2341 }
2342
2343 std::unique_ptr<SwUndoMoveNum> pUndo;
2344 SwNodeOffset nMoved(0);
2345 if (GetIDocumentUndoRedo().DoesUndo())
2346 {
2347 pUndo.reset(new SwUndoMoveNum( rPam, nOffset, bIsOutlMv ));
2348 nMoved = rPam.End()->GetNodeIndex() - rPam.Start()->GetNodeIndex() + 1;
2349 }
2350
2351 (void) pLayout; // note: move will insert between aIdx-1 and aIdx
2352 assert(!pLayout // check not moving *into* delete redline (caller's fault)
2356
2357 if( pUndo )
2358 {
2359 // i57907: Under circumstances (sections at the end of a chapter)
2360 // the rPam.Start() is not moved to the new position.
2361 // But aIdx should be at the new end position and as long as the
2362 // number of moved paragraphs is nMoved, I know, where the new
2363 // position is.
2364 pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
2365 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
2366 }
2367
2368 if( pOwnRedl )
2369 {
2370 auto [pRStt, pREnd] = pOwnRedl->StartEnd(); // SwPosition*
2371 if( pRStt->GetNodeIndex() != nRedlSttNd )
2372 {
2373 pRStt->Assign(nRedlSttNd);
2374 }
2375 if( pREnd->GetNodeIndex() != nRedlEndNd )
2376 {
2377 pREnd->Assign(nRedlEndNd);
2378 SwContentNode* pCNd = pREnd->GetNode().GetContentNode();
2379 if(pCNd)
2380 pREnd->SetContent( pCNd->Len() );
2381 }
2382 }
2383
2385 return true;
2386}
2387
2388bool SwDoc::NumOrNoNum( SwNode& rIdx, bool bDel )
2389{
2390 bool bResult = false;
2391 SwTextNode * pTextNd = rIdx.GetTextNode();
2392
2393 if (pTextNd && pTextNd->GetNumRule() != nullptr &&
2394 (pTextNd->HasNumber() || pTextNd->HasBullet()))
2395 {
2396 if ( !pTextNd->IsCountedInList() == !bDel)
2397 {
2398 bool bOldNum = bDel;
2399 bool bNewNum = !bDel;
2400 pTextNd->SetCountedInList(bNewNum);
2401
2403
2404 bResult = true;
2405
2406 if (GetIDocumentUndoRedo().DoesUndo())
2407 {
2408 GetIDocumentUndoRedo().AppendUndo(
2409 std::make_unique<SwUndoNumOrNoNum>(rIdx, bOldNum, bNewNum));
2410 }
2411 }
2412 else if (bDel && pTextNd->GetNumRule(false) &&
2413 pTextNd->GetActualListLevel() >= 0 &&
2414 pTextNd->GetActualListLevel() < MAXLEVEL)
2415 {
2416 SwPaM aPam(*pTextNd);
2417 DelNumRules(aPam);
2418
2419 bResult = true;
2420 }
2421 }
2422
2423 return bResult;
2424}
2425
2427 SwRootFrame const*const pLayout)
2428{
2429 SwNumRule* pRet = nullptr;
2430 SwTextNode* pTNd = rPos.GetNode().GetTextNode();
2431
2432 if ( pTNd != nullptr )
2433 {
2434 if (pLayout && !sw::IsParaPropsNode(*pLayout, *pTNd))
2435 {
2436 pTNd = static_cast<SwTextFrame*>(pTNd->getLayoutFrame(pLayout))->GetMergedPara()->pParaPropsNode;
2437 rPos.Assign(*pTNd);
2438 }
2439 pRet = pTNd->GetNumRule();
2440 }
2441
2442 return pRet;
2443}
2444
2445sal_uInt16 SwDoc::FindNumRule( std::u16string_view rName ) const
2446{
2447 for( sal_uInt16 n = mpNumRuleTable->size(); n; )
2448 if( (*mpNumRuleTable)[ --n ]->GetName() == rName )
2449 return n;
2450
2451 return USHRT_MAX;
2452}
2453
2454SwNumRule* SwDoc::FindNumRulePtr( const OUString& rName ) const
2455{
2456 SwNumRule * pResult = maNumRuleMap[rName];
2457
2458 if ( !pResult )
2459 {
2460 for (size_t n = 0; n < mpNumRuleTable->size(); ++n)
2461 {
2462 if ((*mpNumRuleTable)[n]->GetName() == rName)
2463 {
2464 pResult = (*mpNumRuleTable)[n];
2465
2466 break;
2467 }
2468 }
2469 }
2470
2471 return pResult;
2472}
2473
2475{
2476 if ((SAL_MAX_UINT16 - 1) <= mpNumRuleTable->size())
2477 {
2478 OSL_ENSURE(false, "SwDoc::AddNumRule: table full.");
2479 abort(); // this should never happen on real documents
2480 }
2481 mpNumRuleTable->push_back(pRule);
2482 maNumRuleMap[pRule->GetName()] = pRule;
2483 pRule->SetNumRuleMap(&maNumRuleMap);
2484
2486}
2487
2488sal_uInt16 SwDoc::MakeNumRule( const OUString &rName,
2489 const SwNumRule* pCpy,
2490 bool bBroadcast,
2491 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
2492{
2493 SwNumRule* pNew;
2494 if( pCpy )
2495 {
2496 pNew = new SwNumRule( *pCpy );
2497
2499
2500 if( pNew->GetName() != rName )
2501 {
2502 pNew->SetPoolFormatId( USHRT_MAX );
2503 pNew->SetPoolHelpId( USHRT_MAX );
2504 pNew->SetPoolHlpFileId( UCHAR_MAX );
2505 pNew->SetDefaultListId( OUString() );
2506 }
2507 pNew->CheckCharFormats( *this );
2508 }
2509 else
2510 {
2511 pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
2512 eDefaultNumberFormatPositionAndSpaceMode );
2513 }
2514
2515 sal_uInt16 nRet = mpNumRuleTable->size();
2516
2517 AddNumRule(pNew);
2518
2519 if (GetIDocumentUndoRedo().DoesUndo())
2520 {
2521 GetIDocumentUndoRedo().AppendUndo(
2522 std::make_unique<SwUndoNumruleCreate>(pNew, *this));
2523 }
2524
2525 if (bBroadcast)
2526 BroadcastStyleOperation(pNew->GetName(), SfxStyleFamily::Pseudo,
2527 SfxHintId::StyleSheetCreated);
2528
2529 return nRet;
2530}
2531
2532OUString SwDoc::GetUniqueNumRuleName( const OUString* pChkStr, bool bAutoNum ) const
2533{
2534 // If we got pChkStr, then the caller expects that in case it's not yet
2535 // used, it'll be returned.
2536 if( IsInMailMerge() && !pChkStr )
2537 {
2538 OUString newName = "MailMergeNumRule"
2539 + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
2540 + OUString::number( mpNumRuleTable->size() + 1 );
2541 return newName;
2542 }
2543
2544 OUString aName;
2545 if( bAutoNum )
2546 {
2547 static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
2548
2549 if (bHack)
2550 {
2551 static sal_Int64 nIdCounter = SAL_CONST_INT64(8000000000);
2552 aName = OUString::number(nIdCounter++);
2553 }
2554 else
2555 {
2556 unsigned int const n(comphelper::rng::uniform_uint_distribution(0,
2557 std::numeric_limits<unsigned int>::max()));
2558 aName = OUString::number(n);
2559 }
2560 if( pChkStr && pChkStr->isEmpty() )
2561 pChkStr = nullptr;
2562 }
2563 else if( pChkStr && !pChkStr->isEmpty() )
2564 aName = *pChkStr;
2565 else
2566 {
2567 pChkStr = nullptr;
2568 aName = SwResId( STR_NUMRULE_DEFNAME );
2569 }
2570
2571 sal_uInt16 nNum(0), nTmp, nFlagSize = ( mpNumRuleTable->size() / 8 ) +2;
2572 std::unique_ptr<sal_uInt8[]> pSetFlags(new sal_uInt8[ nFlagSize ]);
2573 memset( pSetFlags.get(), 0, nFlagSize );
2574
2575 sal_Int32 nNmLen = aName.getLength();
2576 if( !bAutoNum && pChkStr )
2577 {
2578 while( nNmLen-- && '0' <= aName[nNmLen] && aName[nNmLen] <= '9' )
2579 ; //nop
2580
2581 if( ++nNmLen < aName.getLength() )
2582 {
2583 aName = aName.copy(0, nNmLen );
2584 pChkStr = nullptr;
2585 }
2586 }
2587
2588 for( auto const & pNumRule: *mpNumRuleTable )
2589 if( nullptr != pNumRule )
2590 {
2591 const OUString sNm = pNumRule->GetName();
2592 if( sNm.startsWith( aName ) )
2593 {
2594 // Determine Number and set the Flag
2595 nNum = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sNm.subView( nNmLen )));
2596 if( nNum-- && nNum < mpNumRuleTable->size() )
2597 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2598 }
2599 if( pChkStr && *pChkStr==sNm )
2600 pChkStr = nullptr;
2601 }
2602
2603 if( !pChkStr )
2604 {
2605 // All Numbers have been flagged accordingly, so identify the right Number
2606 nNum = mpNumRuleTable->size();
2607 for( sal_uInt16 n = 0; n < nFlagSize; ++n )
2608 {
2609 nTmp = pSetFlags[ n ];
2610 if( 0xff != nTmp )
2611 {
2612 // identify the Number
2613 nNum = n * 8;
2614 while( nTmp & 1 )
2615 {
2616 ++nNum;
2617 nTmp >>= 1;
2618 }
2619 break;
2620 }
2621 }
2622 }
2623 if( pChkStr && !pChkStr->isEmpty() )
2624 return *pChkStr;
2625 return aName + OUString::number( ++nNum );
2626}
2627
2629{
2630 const SwNumRuleTable& rNmTable = GetNumRuleTable();
2631 for( size_t n = 0; n < rNmTable.size(); ++n )
2632 if( rNmTable[ n ]->IsInvalidRule() )
2633 rNmTable[ n ]->Validate(*this);
2634}
2635
2636void SwDoc::MarkListLevel( const OUString& sListId,
2637 const int nListLevel,
2638 const bool bValue )
2639{
2640 SwList* pList = getIDocumentListsAccess().getListByName( sListId );
2641
2642 if ( pList )
2643 {
2644 // Set new marked list level and notify all affected nodes of the changed mark.
2645 pList->MarkListLevel( nListLevel, bValue );
2646 }
2647}
2648
2650 SwRootFrame const& rLayout)
2651{
2652 bool bResult = false;
2653
2654 const SwTextNode *const pTextNode = sw::GetParaPropsNode(rLayout, rPos.GetNode());
2655 if ( pTextNode != nullptr )
2656 {
2657 bResult = pTextNode->IsFirstOfNumRule(rLayout);
2658 }
2659
2660 return bResult;
2661}
2662
2663/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ CheckPosInFly
check if target position is in fly anchored at source range
@ ShowDelete
show all deletes
@ On
RedlineFlags on.
@ ShowInsert
show all inserts
const OUString & GetValue() const
virtual bool AppendTextNode(SwPosition &rPos)=0
virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart)=0
Split a node at rPos (implemented only for TextNode).
virtual bool CopyRange(SwPaM &rPam, SwPosition &rPos, SwCopyFlags flags) const =0
Copy a selected content range to a position.
virtual bool MoveNodeRange(SwNodeRange &, SwNode &, SwMoveFlags)=0
virtual bool InsertPoolItem(const SwPaM &rRg, const SfxPoolItem &, const SetAttrMode nFlags=SetAttrMode::DEFAULT, SwRootFrame const *pLayout=nullptr, SwTextAttr **ppNewTextAttr=nullptr)=0
Insert an attribute.
virtual void UpdateExpFields(SwTextField *pField, bool bUpdateRefFields)=0
virtual void deleteListForListStyle(const OUString &rListStyleName)=0
virtual void deleteListsByDefaultListStyle(const OUString &rListStyleName)=0
virtual SwList * getListByName(const OUString &rListId) const =0
virtual void createListForListStyle(const OUString &rListStyleName)=0
virtual SwList * createList(const OUString &rListId, const OUString &rDefaultListStyleName)=0
virtual bool SplitRedline(const SwPaM &rPam)=0
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
virtual void SetRedlineFlags(RedlineFlags eMode)=0
Set a new redline mode.
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
virtual void SetModified()=0
Must be called manually at changes of format.
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
SvxNumPositionAndSpaceMode GetPositionAndSpaceMode() const
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:59
SwFormatColl * GetFormatColl() const
Definition: node.hxx:497
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1223
virtual SwContentNode * JoinNext()
Definition: node.cxx:1560
void ChkCondColl(const SwTextFormatColl *pColl=nullptr)
Definition: node.cxx:2022
virtual sal_Int32 Len() const
Definition: node.cxx:1256
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:493
Definition: doc.hxx:197
void MarkListLevel(const OUString &sListId, const int nListLevel, const bool bValue)
Marks/Unmarks a list level of a certain list.
Definition: docnum.cxx:2636
bool MoveOutlinePara(const SwPaM &rPam, SwOutlineNodes::difference_type nOffset)
Outline - move up / move down.
Definition: docnum.cxx:447
void CorrRel(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset=0, bool bMoveCursor=false)
Definition: doccorr.cxx:307
void AddNumRule(SwNumRule *pRule)
Add numbering rule to document.
Definition: docnum.cxx:2474
std::unordered_map< OUString, SwNumRule * > maNumRuleMap
Definition: doc.hxx:282
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:645
void SetNodeNumStart(const SwPosition &rPos, sal_uInt16 nStt)
Definition: docnum.cxx:1033
void BroadcastStyleOperation(const OUString &rName, SfxStyleFamily eFamily, SfxHintId nOp)
Definition: docdesc.cxx:723
static bool GotoPrevNum(SwPosition &, SwRootFrame const *pLayout, bool bOverUpper=true)
Definition: docnum.cxx:1700
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:408
bool GotoOutline(SwPosition &rPos, const OUString &rName, SwRootFrame const *=nullptr) const
Definition: docnum.cxx:733
bool NumOrNoNum(SwNode &rIdx, bool bDel=false)
Definition: docnum.cxx:2388
OUString GetUniqueNumRuleName(const OUString *pChkStr=nullptr, bool bAutoNum=true) const
Definition: docnum.cxx:2532
std::unique_ptr< SwTextFormatColls > mpTextFormatCollTable
Definition: doc.hxx:254
sal_uInt16 FindNumRule(std::u16string_view rName) const
Definition: docnum.cxx:2445
o3tl::sorted_vector< SwRootFrame * > GetAllLayouts()
Definition: doclay.cxx:1699
bool IsUsed(const sw::BroadcastingModify &) const
Definition: poolfmt.cxx:86
void ReplaceNumRule(const SwPosition &rPos, const OUString &rOldRule, const OUString &rNewRule)
Definition: docnum.cxx:1174
void UpdateNumRule()
Definition: docnum.cxx:2628
bool NoNum(const SwPaM &)
Definition: docnum.cxx:1294
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2454
void PropagateOutlineRule()
Definition: docnum.cxx:176
void StopNumRuleAnimations(const OutputDevice *)
Definition: docnum.cxx:1155
const SwNumRuleTable & GetNumRuleTable() const
Definition: doc.hxx:1081
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1039
SwNumRule * mpOutlineRule
Definition: doc.hxx:263
bool MoveParagraph(SwPaM &, SwNodeOffset nOffset, bool bIsOutlMv=false)
Move selected paragraphs (not only numberings) according to offsets.
Definition: docnum.cxx:1822
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:329
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:158
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:371
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:349
void InvalidateNumRules()
Definition: docnum.cxx:1386
void DelNumRules(const SwPaM &, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1316
void SetNumRuleStart(const SwPosition &rPos, bool bFlag=true)
Definition: docnum.cxx:1011
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:649
bool RenameNumRule(const OUString &aOldName, const OUString &aNewName, bool bBroadcast=false)
Definition: docnum.cxx:1117
OUString SetNumRule(const SwPaM &, const SwNumRule &, bool bCreateNewList, SwRootFrame const *pLayout=nullptr, const OUString &sContinuedListId=OUString(), bool bSetItem=true, const bool bResetIndentAttrs=false)
Accept changes of outline styles for OutlineRule.
Definition: docnum.cxx:861
void ChgNumRuleFormats(const SwNumRule &rRule)
Definition: docnum.cxx:1095
void ChkCondColls()
Definition: doc.cxx:1822
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:440
const SwNumRule * SearchNumRule(const SwPosition &rPos, const bool bForward, const bool bNum, const bool bOutline, int nNonEmptyAllowed, OUString &sListId, SwRootFrame const *pLayout, const bool bInvestigateStartNode=false)
Searches for a text node with a numbering rule.
Definition: docnum.cxx:1620
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
std::unique_ptr< SwNumRuleTable > mpNumRuleTable
Definition: doc.hxx:279
static bool IsFirstOfNumRuleAtPos(const SwPosition &rPos, SwRootFrame const &rLayout)
Definition: docnum.cxx:2649
void SetCounted(const SwPaM &, bool bCounted, SwRootFrame const *pLayout)
Definition: docnum.cxx:995
bool DelNumRule(const OUString &rName, bool bBroadCast=false)
Definition: docnum.cxx:1055
bool IsInMailMerge() const
Definition: doc.hxx:975
bool NumUpDown(const SwPaM &, bool bDown, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1706
void MakeUniqueNumRules(const SwPaM &rPaM)
Definition: docnum.cxx:1230
bool OutlineUpDown(const SwPaM &rPam, short nOffset, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:199
bool MoveParagraphImpl(SwPaM &, SwNodeOffset nOffset, bool bIsOutlMv, SwRootFrame const *)
Definition: docnum.cxx:1931
static bool GotoNextNum(SwPosition &, SwRootFrame const *pLayout, bool bOverUpper=true, sal_uInt8 *pUpper=nullptr, sal_uInt8 *pLower=nullptr)
Definition: docnum.cxx:1614
static SwNumRule * GetNumRuleAtPos(SwPosition &rPos, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:2426
IDocumentListsAccess const & getIDocumentListsAccess() const
Definition: doc.cxx:307
sal_uInt16 MakeNumRule(const OUString &rName, const SwNumRule *pCpy=nullptr, bool bBroadcast=false, const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode=SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
Definition: docnum.cxx:2488
void SetOutlineNumRule(const SwNumRule &rRule)
Definition: docnum.cxx:112
void UpdateAllFootnote()
Definition: ftnidx.cxx:266
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
const SwNumRuleItem & GetNumRule(bool=true) const
Definition: paratr.hxx:241
TElementType * Next()
Definition: calbck.hxx:380
TElementType * First()
Definition: calbck.hxx:372
Definition: list.hxx:40
void MarkListLevel(const int nListLevel, const bool bValue)
Definition: list.cxx:139
const OUString & GetListId() const
Definition: list.hxx:47
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNodes & GetNodes() const
Definition: ndindex.hxx:119
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
SwNodeIndex aEnd
Definition: ndindex.hxx:137
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
bool IsContentNode() const
Definition: node.hxx:188
bool IsEndNode() const
Definition: node.hxx:189
bool IsStartNode() const
Definition: node.hxx:187
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
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
Merge GetRedlineMergeFlag() const
Definition: node.hxx:116
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwNodeType GetNodeType() const
Definition: node.hxx:166
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:695
const SwOutlineNodes & GetOutLineNds() const
Array of all OutlineNodes.
Definition: ndarr.hxx:236
void UpdateOutlineIdx(const SwNode &)
Update all OutlineNodes starting from Node.
Definition: ndnum.cxx:77
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1333
SwNodeOffset Count() const
Definition: ndarr.hxx:142
bool IsEnumeration() const
Definition: number.cxx:237
bool IsItemize() const
Definition: number.cxx:245
void SetAutoRule(bool bFlag)
Definition: numrule.hxx:230
bool IsAutoRule() const
Definition: numrule.hxx:229
void SetRuleType(SwNumRuleType eNew)
Definition: numrule.hxx:212
void SetNumRuleMap(std::unordered_map< OUString, SwNumRule * > *pNumRuleMap)
Register this rule in a "name->numrule" map.
Definition: number.cxx:163
bool IsOutlineRule() const
Definition: numrule.hxx:241
void SetPoolHelpId(sal_uInt16 nId)
Definition: numrule.hxx:255
const SwNumFormat * GetNumFormat(sal_uInt16 i) const
Definition: number.cxx:97
void SetName(const OUString &rNm, IDocumentListsAccess &rDocListAccess)
Definition: number.cxx:111
bool IsContinusNum() const
Definition: numrule.hxx:235
const OUString & GetDefaultListId() const
Definition: numrule.hxx:194
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:87
void Set(sal_uInt16 i, const SwNumFormat *)
Definition: number.cxx:618
void SetInvalidRule(bool bFlag)
Definition: number.cxx:958
void SetDefaultListId(const OUString &sDefaultListId)
Definition: numrule.hxx:190
const OUString & GetName() const
Definition: numrule.hxx:224
static OUString GetOutlineRuleName()
Definition: number.cxx:82
void SetPoolHlpFileId(sal_uInt8 nId)
Definition: numrule.hxx:257
std::vector< SwTextNode * > tTextNodeList
Definition: numrule.hxx:97
void SetPoolFormatId(sal_uInt16 nId)
Definition: numrule.hxx:251
void SetContinusNum(bool bFlag)
Definition: numrule.hxx:236
void CheckCharFormats(SwDoc &rDoc)
Tests whether the CharFormats are from the given doc and copies them if appropriate.
Definition: number.cxx:527
void GetTextNodeList(SwNumRule::tTextNodeList &rTextNodeList) const
Definition: number.cxx:131
SwNumberTree::tNumberVector GetNumberVector() const
Returns level numbers of this node.
bool Seek_Entry(SwNode *rP, size_type *pnPos) const
Definition: ndnum.cxx:32
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
std::pair< const SwPosition *, const SwPosition * > StartEnd() const
Because sometimes the cost of the operator<= can add up.
Definition: pam.hxx:269
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * End() const
Definition: pam.hxx:263
SwDoc & GetDoc() const
Definition: pam.hxx:291
void DeleteMark()
Definition: pam.hxx:232
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
bool IsOwnRedline(const SwRangeRedline &rRedl) const
Definition: redline.hxx:256
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1975
bool Insert(SwRangeRedline *&p)
Definition: docredln.cxx:416
static constexpr size_type npos
Definition: docary.hxx:224
size_type size() const
Definition: docary.hxx:268
void Remove(size_type nPos)
Definition: docredln.cxx:669
vector_type::size_type size_type
Definition: docary.hxx:223
void RegisterInModify(sw::BroadcastingModify *pRegIn, const SwNode &rNd)
Definition: rolbck.cxx:1490
The root element of a Writer document layout.
Definition: rootfrm.hxx:85
bool HasMergedParas() const
Definition: wsfrm.cxx:4773
Starts a section of nodes in the document model.
Definition: node.hxx:348
SwStartNodeType GetStartNodeType() const
Definition: node.hxx:364
Represents the style of a paragraph.
Definition: fmtcol.hxx:61
bool IsAssignedToListLevelOfOutlineStyle() const
Definition: fmtcol.hxx:122
int GetAssignedOutlineStyleLevel() const
Definition: fmtcol.cxx:678
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
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 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
void SetAttrListLevel(int nLevel)
Sets the list level of this text node.
Definition: ndtxt.cxx:4218
SwNumberTree::tSwNumTreeNumber GetAttrListRestartValue() const
Definition: ndtxt.cxx:4332
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
void SetAttrOutlineLevel(int nLevel)
Sets the out line level at a text node.
Definition: ndtxt.cxx:4173
bool IsFirstOfNumRule(SwRootFrame const &rLayout) const
Definition: ndtxt.cxx:4551
OUString GetListId() const
Definition: ndtxt.cxx:4580
void SetListRestart(bool bRestart)
Definition: ndtxt.cxx:4257
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:5066
const SwNodeNum * GetNum(SwRootFrame const *pLayout=nullptr, SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Definition: ndtxt.cxx:4095
bool IsInList() const
Definition: ndtxt.cxx:4546
virtual SwFormatColl * ChgFormatColl(SwFormatColl *) override
Definition: ndtxt.cxx:4060
bool IsCountedInList() const
Definition: ndtxt.cxx:4393
void SetCountedInList(bool bCounted)
Definition: ndtxt.cxx:4378
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2921
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
void AddToList()
Definition: ndtxt.cxx:4423
int GetAttrOutlineLevel() const
Returns outline level of this text node.
Definition: ndtxt.cxx:4168
void SetAttrListRestartValue(SwNumberTree::tSwNumTreeNumber nNum)
Definition: ndtxt.cxx:4306
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:895
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5293
SwHistory * GetHistory()
void AddNode(const SwTextNode &rNd)
Definition: unnum.cxx:199
void SaveOldNumRule(const SwNumRule &rOld)
Definition: unnum.cxx:150
SwHistory * GetHistory()
Definition: unnum.cxx:143
void SetLRSpaceEndPos()
Definition: unnum.cxx:120
size_t size() const
Definition: docary.hxx:88
std::vector< Value >::difference_type difference_type
bool empty() const
size_type size() const
int nCount
TOOLS_DLLPUBLIC OString DateTimeToOString(const DateTime &rDateTime)
virtual OUString GetName() const override
static bool lcl_GotoNextPrevNum(SwPosition &rPos, bool bNext, bool bOverUpper, sal_uInt8 *pUpper, sal_uInt8 *pLower, SwRootFrame const *const pLayout)
Definition: docnum.cxx:1507
static bool lcl_IsNumOk(sal_uInt8 nSrchNum, sal_uInt8 &rLower, sal_uInt8 &rUpper, bool bOverUpper, sal_uInt8 nNumber)
Definition: docnum.cxx:1393
static sal_uInt8 GetUpperLvlChg(sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask)
Definition: docnum.cxx:100
static SwTextNode * lcl_FindOutlineName(const SwOutlineNodes &rOutlNds, SwRootFrame const *const pLayout, std::u16string_view aName, bool const bExact)
Definition: docnum.cxx:596
static SwTextNode * lcl_FindOutlineNum(const SwOutlineNodes &rOutlNds, OUString &rName, SwRootFrame const *const pLayout)
Definition: docnum.cxx:631
static bool lcl_IsValidPrevNextNumNode(const SwNodeIndex &rIdx)
Definition: docnum.cxx:1411
static void lcl_ChgNumRule(SwDoc &rDoc, const SwNumRule &rRule)
Definition: docnum.cxx:795
OUString sName
@ FTNNUM_CHAPTER
Definition: ftninfo.hxx:87
constexpr TypedWhichId< SfxStringItem > RES_PARATR_LIST_ID(RES_PARATR_LIST_BEGIN)
constexpr TypedWhichId< SvxFirstLineIndentItem > RES_MARGIN_FIRSTLINE(91)
constexpr TypedWhichId< SwConditionTextFormatColl > RES_CONDTXTFMTCOLL(166)
constexpr TypedWhichId< SfxInt16Item > RES_PARATR_LIST_LEVEL(83)
constexpr TypedWhichId< SfxInt16Item > RES_PARATR_LIST_RESTARTVALUE(85)
constexpr TypedWhichId< SwNumRuleItem > RES_PARATR_NUMRULE(72)
constexpr TypedWhichId< SvxRightMarginItem > RES_MARGIN_RIGHT(93)
constexpr TypedWhichId< SvxTextLeftMarginItem > RES_MARGIN_TEXTLEFT(92)
constexpr TypedWhichId< SfxBoolItem > RES_PARATR_LIST_ISCOUNTED(86)
constexpr TypedWhichId< SfxBoolItem > RES_PARATR_LIST_ISRESTART(84)
OUString aName
sal_Int64 n
uno_Any a
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
std::vector< tSwNumTreeNumber > tNumberVector
size
unsigned int uniform_uint_distribution(unsigned int a, unsigned int b)
bool isdigitAsciiString(std::string_view rString)
OUString newName(std::u16string_view aNewPrefix, std::u16string_view aOldPrefix, std::u16string_view old_Name)
int i
m
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
Dialog to specify the properties of date form field.
void GotoNextLayoutTextFrame(SwNodeIndex &rIndex, SwRootFrame const *const pLayout)
Definition: docnum.cxx:1473
void GotoPrevLayoutTextFrame(SwNodeIndex &rIndex, SwRootFrame const *const pLayout)
Definition: docnum.cxx:1438
std::pair< SwTextNode *, SwTextNode * > GetFirstAndLastNode(SwRootFrame const &rLayout, SwNode const &rPos)
Definition: txtfrm.cxx:354
bool IsParaPropsNode(SwRootFrame const &rLayout, SwTextNode const &rNode)
Definition: txtfrm.cxx:313
void UpdateFramesForAddDeleteRedline(SwDoc &rDoc, SwPaM const &rPam)
SwTextNode * GetParaPropsNode(SwRootFrame const &rLayout, SwNode const &rNode)
Definition: txtfrm.cxx:330
@ SwTableBoxStartNode
Definition: ndtyp.hxx:53
@ Section
SwSectionNode is derived from SwStartNode.
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
@ OUTLINE_RULE
Definition: numrule.hxx:92
SwComparePosition ComparePosition(const T &rStt1, const T &rEnd1, const T &rStt2, const T &rEnd2)
Definition: pam.hxx:123
@ OverlapBehind
Pos1 overlaps Pos2 at the end.
@ CollideEnd
Pos1 end touches at Pos2 start.
@ Behind
Pos1 behind Pos2.
@ OverlapBefore
Pos1 overlaps Pos2 at the beginning.
@ Outside
Pos2 completely contained in Pos1.
@ Before
Pos1 before Pos2.
@ Inside
Pos1 completely contained in Pos2.
@ CollideStart
Pos1 start touches at Pos2 end.
@ Equal
Pos1 is as large as Pos2.
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:60
@ RES_POOLCOLL_HEADLINE1
Heading 1.
Definition: poolfmt.hxx:262
Marks a position in the document model.
Definition: pam.hxx:38
void Adjust(SwNodeOffset nDelta)
Adjust node position, and resets content position to zero.
Definition: pam.cxx:257
SwNode & GetNode() const
Definition: pam.hxx:81
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
void AssignEndIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the end of rNd.
Definition: pam.cxx:277
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
Describes parts of multiple text nodes, which will form a text frame, even when redlines are hidden a...
Definition: txtfrm.hxx:991
SVX_NUM_NUMBER_NONE
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:92
unsigned char sal_uInt8
#define SAL_MAX_UINT16
sal_uInt16 sal_Unicode
signed char sal_Int8
oslFileHandle & pOut