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, sal_uInt16 marker,
63 SwRootFrame const*const pLayout)
64 {
65 const o3tl::sorted_vector<sal_uInt16> aResetAttrsArray{ marker };
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 {
981 ::lcl_ResetIndentAttrs(this, aPam, RES_LR_SPACE, pLayout);
982 }
983
984 if (GetIDocumentUndoRedo().DoesUndo())
985 {
986 GetIDocumentUndoRedo().EndUndo( SwUndoId::INSNUM, nullptr );
987 }
988
990
991 return sListId;
992}
993
994void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted,
995 SwRootFrame const*const pLayout)
996{
997 if ( bCounted )
998 {
999 ::lcl_ResetIndentAttrs(this, rPam, RES_PARATR_LIST_ISCOUNTED, pLayout);
1000 }
1001 else
1002 {
1005 SetAttrMode::DEFAULT, pLayout);
1006 }
1007}
1008
1009void SwDoc::SetNumRuleStart( const SwPosition& rPos, bool bFlag )
1010{
1011 SwTextNode* pTextNd = rPos.GetNode().GetTextNode();
1012
1013 if (!pTextNd)
1014 return;
1015
1016 const SwNumRule* pRule = pTextNd->GetNumRule();
1017 if( pRule && !bFlag != !pTextNd->IsListRestart())
1018 {
1019 if (GetIDocumentUndoRedo().DoesUndo())
1020 {
1021 GetIDocumentUndoRedo().AppendUndo(
1022 std::make_unique<SwUndoNumRuleStart>(rPos, bFlag) );
1023 }
1024
1025 pTextNd->SetListRestart(bFlag);
1026
1028 }
1029}
1030
1031void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
1032{
1033 SwTextNode* pTextNd = rPos.GetNode().GetTextNode();
1034
1035 if (!pTextNd)
1036 return;
1037
1038 if ( !pTextNd->HasAttrListRestartValue() ||
1039 pTextNd->GetAttrListRestartValue() != nStt )
1040 {
1041 if (GetIDocumentUndoRedo().DoesUndo())
1042 {
1043 GetIDocumentUndoRedo().AppendUndo(
1044 std::make_unique<SwUndoNumRuleStart>(rPos, nStt) );
1045 }
1046 pTextNd->SetAttrListRestartValue( nStt );
1047
1049 }
1050}
1051
1052// We can only delete if the Rule is unused!
1053bool SwDoc::DelNumRule( const OUString& rName, bool bBroadcast )
1054{
1055 sal_uInt16 nPos = FindNumRule( rName );
1056
1057 if (nPos == USHRT_MAX)
1058 return false;
1059
1060 if ( (*mpNumRuleTable)[ nPos ] == GetOutlineNumRule() )
1061 {
1062 OSL_FAIL( "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect" );
1063 return false;
1064 }
1065
1066 if( !IsUsed( *(*mpNumRuleTable)[ nPos ] ))
1067 {
1068 if (GetIDocumentUndoRedo().DoesUndo())
1069 {
1070 GetIDocumentUndoRedo().AppendUndo(
1071 std::make_unique<SwUndoNumruleDelete>(*(*mpNumRuleTable)[nPos], *this));
1072 }
1073
1074 if (bBroadcast)
1075 BroadcastStyleOperation(rName, SfxStyleFamily::Pseudo,
1076 SfxHintId::StyleSheetErased);
1077
1080 // #i34097# DeleteAndDestroy deletes rName if
1081 // rName is directly taken from the numrule.
1082 const OUString aTmpName( rName );
1083 delete (*mpNumRuleTable)[ nPos ];
1084 mpNumRuleTable->erase( mpNumRuleTable->begin() + nPos );
1085 maNumRuleMap.erase(aTmpName);
1086
1088 return true;
1089 }
1090 return false;
1091}
1092
1094{
1095 SwNumRule* pRule = FindNumRulePtr( rRule.GetName() );
1096 if( !pRule )
1097 return;
1098
1099 SwUndoInsNum* pUndo = nullptr;
1100 if (GetIDocumentUndoRedo().DoesUndo())
1101 {
1102 pUndo = new SwUndoInsNum( *pRule, rRule, *this );
1103 pUndo->GetHistory();
1104 GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pUndo) );
1105 }
1106 ::lcl_ChgNumRule( *this, rRule );
1107 if (pUndo)
1108 {
1109 pUndo->SetLRSpaceEndPos();
1110 }
1111
1113}
1114
1115bool SwDoc::RenameNumRule(const OUString & rOldName, const OUString & rNewName,
1116 bool bBroadcast)
1117{
1118 assert(!FindNumRulePtr(rNewName));
1119
1120 bool bResult = false;
1121 SwNumRule * pNumRule = FindNumRulePtr(rOldName);
1122
1123 if (pNumRule)
1124 {
1125 if (GetIDocumentUndoRedo().DoesUndo())
1126 {
1127 GetIDocumentUndoRedo().AppendUndo(
1128 std::make_unique<SwUndoNumruleRename>(rOldName, rNewName, *this));
1129 }
1130
1131 SwNumRule::tTextNodeList aTextNodeList;
1132 pNumRule->GetTextNodeList( aTextNodeList );
1133
1134 pNumRule->SetName( rNewName, getIDocumentListsAccess() );
1135
1136 SwNumRuleItem aItem(rNewName);
1137
1138 for ( SwTextNode* pTextNd : aTextNodeList )
1139 {
1140 pTextNd->SetAttr(aItem);
1141 }
1142
1143 bResult = true;
1144
1145 if (bBroadcast)
1146 BroadcastStyleOperation(rOldName, SfxStyleFamily::Pseudo,
1147 SfxHintId::StyleSheetModified);
1148 }
1149
1150 return bResult;
1151}
1152
1154{
1155 for( sal_uInt16 n = GetNumRuleTable().size(); n; )
1156 {
1157 SwNumRule::tTextNodeList aTextNodeList;
1158 GetNumRuleTable()[ --n ]->GetTextNodeList( aTextNodeList );
1159 for ( SwTextNode* pTNd : aTextNodeList )
1160 {
1162 for(SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
1163 if (pFrame->HasAnimation() &&
1164 (!pFrame->GetMergedPara() || pFrame->GetMergedPara()->pParaPropsNode == pTNd))
1165 {
1166 pFrame->StopAnimation( pOut );
1167 }
1168 }
1169 }
1170}
1171
1173 const OUString& rOldRule, const OUString& rNewRule )
1174{
1175 SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
1176 *pNewRule = FindNumRulePtr( rNewRule );
1177 if( !pOldRule || !pNewRule || pOldRule == pNewRule )
1178 return;
1179
1180 SwUndoInsNum* pUndo = nullptr;
1181 if (GetIDocumentUndoRedo().DoesUndo())
1182 {
1183 // Start/End for attributes!
1184 GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
1185 pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
1186 GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
1187 }
1188
1189 SwNumRule::tTextNodeList aTextNodeList;
1190 pOldRule->GetTextNodeList( aTextNodeList );
1191 if ( !aTextNodeList.empty() )
1192 {
1193 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : nullptr );
1194
1195 const SwTextNode* pGivenTextNode = rPos.GetNode().GetTextNode();
1196 SwNumRuleItem aRule( rNewRule );
1197 for ( SwTextNode* pTextNd : aTextNodeList )
1198 {
1199 if ( pGivenTextNode &&
1200 pGivenTextNode->GetListId() == pTextNd->GetListId() )
1201 {
1202 aRegH.RegisterInModify( pTextNd, *pTextNd );
1203
1204 pTextNd->SetAttr( aRule );
1205 pTextNd->NumRuleChgd();
1206 }
1207 }
1208 GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
1210 }
1211}
1212
1213namespace
1214{
1215 struct ListStyleData
1216 {
1217 SwNumRule* pReplaceNumRule;
1218 bool bCreateNewList;
1219 OUString sListId;
1220
1221 ListStyleData()
1222 : pReplaceNumRule( nullptr ),
1223 bCreateNewList( false )
1224 {}
1225 };
1226}
1227
1229{
1230 OSL_ENSURE( &rPaM.GetDoc() == this, "need same doc" );
1231
1232 std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
1233
1234 bool bFirst = true;
1235
1236 const SwNodeOffset nStt = rPaM.Start()->GetNodeIndex();
1237 const SwNodeOffset nEnd = rPaM.End()->GetNodeIndex();
1238 for (SwNodeOffset n = nStt; n <= nEnd; n++)
1239 {
1240 SwTextNode * pCNd = GetNodes()[n]->GetTextNode();
1241
1242 if (pCNd)
1243 {
1244 SwNumRule * pRule = pCNd->GetNumRule();
1245
1246 if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
1247 {
1248 ListStyleData aListStyleData = aMyNumRuleMap[pRule];
1249
1250 if ( aListStyleData.pReplaceNumRule == nullptr )
1251 {
1252 if (bFirst)
1253 {
1254 SwPosition aPos(*pCNd);
1255 aListStyleData.pReplaceNumRule =
1256 const_cast<SwNumRule *>
1257 (SearchNumRule( aPos, false, pCNd->HasNumber(),
1258 false, 0,
1259 aListStyleData.sListId, nullptr, true ));
1260 }
1261
1262 if ( aListStyleData.pReplaceNumRule == nullptr )
1263 {
1264 aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
1265 aListStyleData.pReplaceNumRule->SetName( GetUniqueNumRuleName(), getIDocumentListsAccess() );
1266 aListStyleData.bCreateNewList = true;
1267 }
1268
1269 aMyNumRuleMap[pRule] = aListStyleData;
1270 }
1271
1272 SwPaM aPam(*pCNd);
1273
1274 SetNumRule( aPam,
1275 *aListStyleData.pReplaceNumRule,
1276 aListStyleData.bCreateNewList,
1277 nullptr,
1278 aListStyleData.sListId );
1279 if ( aListStyleData.bCreateNewList )
1280 {
1281 aListStyleData.bCreateNewList = false;
1282 aListStyleData.sListId = pCNd->GetListId();
1283 aMyNumRuleMap[pRule] = aListStyleData;
1284 }
1285
1286 bFirst = false;
1287 }
1288 }
1289 }
1290}
1291
1292bool SwDoc::NoNum( const SwPaM& rPam )
1293{
1294
1295 bool bRet = getIDocumentContentOperations().SplitNode( *rPam.GetPoint(), false );
1296 // Do we actually use Numbering at all?
1297 if( bRet )
1298 {
1299 // Set NoNum and Update
1300 SwTextNode* pNd = rPam.GetPoint()->GetNode().GetTextNode();
1301 const SwNumRule* pRule = pNd->GetNumRule();
1302 if( pRule )
1303 {
1304 pNd->SetCountedInList(false);
1305
1307 }
1308 else
1309 bRet = false; // no Numbering or just always true?
1310 }
1311 return bRet;
1312}
1313
1314void SwDoc::DelNumRules(const SwPaM& rPam, SwRootFrame const*const pLayout)
1315{
1316 SwPaM aPam(rPam, nullptr);
1317 ExpandPamForParaPropsNodes(aPam, pLayout);
1318 SwNodeOffset nStt = aPam.Start()->GetNodeIndex();
1319 SwNodeOffset const nEnd = aPam.End()->GetNodeIndex();
1320
1321 SwUndoDelNum* pUndo;
1322 if (GetIDocumentUndoRedo().DoesUndo())
1323 {
1324 pUndo = new SwUndoDelNum( aPam );
1325 GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
1326 }
1327 else
1328 pUndo = nullptr;
1329
1330 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : nullptr );
1331
1332 SwNumRuleItem aEmptyRule;
1333 const SwNode* pOutlNd = nullptr;
1334 for( ; nStt <= nEnd; ++nStt )
1335 {
1336 SwTextNode* pTNd = GetNodes()[ nStt ]->GetTextNode();
1337 if (pLayout && pTNd)
1338 {
1339 pTNd = sw::GetParaPropsNode(*pLayout, *pTNd);
1340 }
1341 SwNumRule* pNumRuleOfTextNode = pTNd ? pTNd->GetNumRule() : nullptr;
1342 if ( pTNd && pNumRuleOfTextNode )
1343 {
1344 // recognize changes of attribute for undo
1345 aRegH.RegisterInModify( pTNd, *pTNd );
1346
1347 if( pUndo )
1348 pUndo->AddNode( *pTNd );
1349
1350 // directly set list style attribute is reset, otherwise empty
1351 // list style is applied
1352 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
1353 if ( pAttrSet &&
1354 pAttrSet->GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET )
1356 else
1357 pTNd->SetAttr( aEmptyRule );
1358
1364
1365 if( RES_CONDTXTFMTCOLL == pTNd->GetFormatColl()->Which() )
1366 {
1367 pTNd->ChkCondColl();
1368 }
1369 else if( !pOutlNd &&
1371 {
1372 pOutlNd = pTNd;
1373 }
1374 }
1375 }
1376
1377 // Finally, update all
1378 UpdateNumRule();
1379
1380 if( pOutlNd )
1381 GetNodes().UpdateOutlineIdx( *pOutlNd );
1382}
1383
1385{
1386 for (size_t n = 0; n < mpNumRuleTable->size(); ++n)
1387 (*mpNumRuleTable)[n]->SetInvalidRule(true);
1388}
1389
1390// To the next/preceding Bullet at the same Level
1391static bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
1392 bool bOverUpper, sal_uInt8 nNumber )
1393{
1394 OSL_ENSURE( nNumber < MAXLEVEL,
1395 "<lcl_IsNumOk(..)> - misusage of method" );
1396
1397 bool bRet = false;
1398 {
1399 if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
1400 bRet = true;
1401 else if( nNumber > rLower )
1402 rLower = nNumber;
1403 else if( nNumber < rUpper )
1404 rUpper = nNumber;
1405 }
1406 return bRet;
1407}
1408
1409static bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
1410{
1411 bool bRet = false;
1412 const SwNode& rNd = rIdx.GetNode();
1413 switch( rNd.GetNodeType() )
1414 {
1415 case SwNodeType::End:
1418 break;
1419
1420 case SwNodeType::Start:
1421 bRet = SwTableBoxStartNode == static_cast<const SwStartNode&>(rNd).GetStartNodeType();
1422 break;
1423
1424 case SwNodeType::Section: // that one's valid, so proceed
1425 bRet = true;
1426 break;
1427
1428 default: break;
1429 }
1430 return bRet;
1431}
1432
1433namespace sw {
1434
1435void
1437{
1438 if (pLayout && pLayout->HasMergedParas())
1439 {
1440 if (rIndex.GetNode().IsTextNode())
1441 {
1443 // not a tracked row deletion in Hide Changes mode
1444 rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout) )
1445 {
1446 rIndex = *static_cast<SwTextFrame*>(rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))->GetMergedPara()->pFirstNode;
1447 }
1448 }
1449 else if (rIndex.GetNode().IsEndNode())
1450 {
1452 {
1453 rIndex = *rIndex.GetNode().StartOfSectionNode();
1454 assert(rIndex.GetNode().IsTableNode());
1455 }
1456 }
1457 }
1458 --rIndex;
1459 if (pLayout && rIndex.GetNode().IsTextNode())
1460 {
1461 rIndex = *sw::GetParaPropsNode(*pLayout, *rIndex.GetNode().GetTextNode());
1462 }
1463}
1464
1465void
1467{
1468 if (pLayout && pLayout->HasMergedParas())
1469 {
1470 if (rIndex.GetNode().IsTextNode())
1471 {
1473 {
1474 rIndex = *static_cast<SwTextFrame*>(rIndex.GetNode().GetTextNode()->getLayoutFrame(pLayout))->GetMergedPara()->pLastNode;
1475 }
1476 }
1477 else if (rIndex.GetNode().IsTableNode())
1478 {
1480 {
1481 rIndex = *rIndex.GetNode().EndOfSectionNode();
1482 }
1483 }
1484 }
1485 ++rIndex;
1486 if (pLayout && rIndex.GetNode().IsTextNode())
1487 {
1488 rIndex = *sw::GetParaPropsNode(*pLayout, *rIndex.GetNode().GetTextNode());
1489 }
1490}
1491
1492} // namespace sw
1493
1494static bool lcl_GotoNextPrevNum( SwPosition& rPos, bool bNext,
1495 bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower,
1496 SwRootFrame const*const pLayout)
1497{
1498 const SwTextNode* pNd = rPos.GetNode().GetTextNode();
1499 if (pNd && pLayout)
1500 {
1501 pNd = sw::GetParaPropsNode(*pLayout, *pNd);
1502 }
1503 if( !pNd || nullptr == pNd->GetNumRule() )
1504 return false;
1505
1506 sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1507
1508 SwNodeIndex aIdx( rPos.GetNode() );
1509 if( ! pNd->IsCountedInList() )
1510 {
1511 bool bError = false;
1512 do {
1513 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1514 if( aIdx.GetNode().IsTextNode() )
1515 {
1516 pNd = aIdx.GetNode().GetTextNode();
1517 const SwNumRule* pRule = pNd->GetNumRule();
1518
1519 if( pRule )
1520 {
1521 sal_uInt8 nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1522 if( pNd->IsCountedInList() || (nTmpNum < nSrchNum ) )
1523 break; // found it!
1524 }
1525 else
1526 bError = true;
1527 }
1528 else
1529 bError = !lcl_IsValidPrevNextNumNode( aIdx );
1530
1531 } while( !bError );
1532 if( bError )
1533 return false;
1534 }
1535
1536 sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
1537 bool bRet = false;
1538
1539 const SwTextNode* pLast;
1540 if( bNext )
1541 {
1542 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1543 pLast = pNd;
1544 }
1545 else
1546 {
1547 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1548 pLast = nullptr;
1549 }
1550
1551 while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
1552 : aIdx.GetIndex() != SwNodeOffset(0) )
1553 {
1554 if( aIdx.GetNode().IsTextNode() )
1555 {
1556 pNd = aIdx.GetNode().GetTextNode();
1557 const SwNumRule* pRule = pNd->GetNumRule();
1558 if( pRule )
1559 {
1560 if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
1561 static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
1562 {
1563 rPos.Assign(aIdx);
1564 bRet = true;
1565 break;
1566 }
1567 else
1568 pLast = pNd;
1569 }
1570 else
1571 break;
1572 }
1573 else if( !lcl_IsValidPrevNextNumNode( aIdx ))
1574 break;
1575
1576 if( bNext )
1577 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1578 else
1579 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1580 }
1581
1582 if( !bRet && !bOverUpper && pLast ) // do not iterate over higher numbers, but still to the end
1583 {
1584 if( bNext )
1585 rPos.Assign(aIdx);
1586 else
1587 rPos.Assign( *pLast );
1588 bRet = true;
1589 }
1590
1591 if( bRet )
1592 {
1593 if( pUpper )
1594 *pUpper = nUpper;
1595 if( pLower )
1596 *pLower = nLower;
1597 }
1598 return bRet;
1599}
1600
1601bool SwDoc::GotoNextNum(SwPosition& rPos, SwRootFrame const*const pLayout,
1602 bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower)
1603{
1604 return ::lcl_GotoNextPrevNum(rPos, true, bOverUpper, pUpper, pLower, pLayout);
1605}
1606
1608 const bool bForward,
1609 const bool bNum,
1610 const bool bOutline,
1611 int nNonEmptyAllowed,
1612 OUString& sListId,
1613 SwRootFrame const* pLayout,
1614 const bool bInvestigateStartNode)
1615{
1616 const SwNumRule * pResult = nullptr;
1617 SwTextNode * pTextNd = rPos.GetNode().GetTextNode();
1618 if (pLayout)
1619 {
1620 pTextNd = sw::GetParaPropsNode(*pLayout, rPos.GetNode());
1621 }
1622 SwNode * pStartFromNode = pTextNd;
1623
1624 if (pTextNd)
1625 {
1626 SwNodeIndex aIdx(rPos.GetNode());
1627
1628 // - the start node has also been investigated, if requested.
1629 const SwNode * pNode = nullptr;
1630 do
1631 {
1632 if ( !bInvestigateStartNode )
1633 {
1634 if (bForward)
1635 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1636 else
1637 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1638 }
1639
1640 if (aIdx.GetNode().IsTextNode())
1641 {
1642 pTextNd = aIdx.GetNode().GetTextNode();
1643
1644 const SwNumRule * pNumRule = pTextNd->GetNumRule();
1645 if (pNumRule)
1646 {
1647 if ( ( pNumRule->IsOutlineRule() == bOutline ) &&
1648 ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
1649 ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
1650 {
1651 pResult = pTextNd->GetNumRule();
1652 // provide also the list id, to which the text node belongs.
1653 sListId = pTextNd->GetListId();
1654 }
1655
1656 break;
1657 }
1658 else if (pTextNd->Len() > 0 || nullptr != pTextNd->GetNumRule())
1659 {
1660 if (nNonEmptyAllowed == 0)
1661 break;
1662
1663 nNonEmptyAllowed--;
1664
1665 if (nNonEmptyAllowed < 0)
1666 nNonEmptyAllowed = -1;
1667 }
1668 }
1669
1670 if ( bInvestigateStartNode )
1671 {
1672 if (bForward)
1673 sw::GotoNextLayoutTextFrame(aIdx, pLayout);
1674 else
1675 sw::GotoPrevLayoutTextFrame(aIdx, pLayout);
1676 }
1677
1678 pNode = &aIdx.GetNode();
1679 }
1680 while (pNode != GetNodes().DocumentSectionStartNode(pStartFromNode) &&
1681 pNode != GetNodes().DocumentSectionEndNode(pStartFromNode));
1682 }
1683
1684 return pResult;
1685}
1686
1687bool SwDoc::GotoPrevNum(SwPosition& rPos, SwRootFrame const*const pLayout,
1688 bool bOverUpper)
1689{
1690 return ::lcl_GotoNextPrevNum(rPos, false, bOverUpper, nullptr, nullptr, pLayout);
1691}
1692
1693bool SwDoc::NumUpDown(const SwPaM& rPam, bool bDown, SwRootFrame const*const pLayout)
1694{
1695 SwPaM aPam(rPam, nullptr);
1696 ExpandPamForParaPropsNodes(aPam, pLayout);
1697 SwNodeOffset nStt = aPam.Start()->GetNodeIndex();
1698 SwNodeOffset const nEnd = aPam.End()->GetNodeIndex();
1699
1700 // -> outline nodes are promoted or demoted differently
1701 bool bOnlyOutline = true;
1702 bool bOnlyNonOutline = true;
1703 for (SwNodeOffset n = nStt; n <= nEnd; n++)
1704 {
1705 SwTextNode * pTextNd = GetNodes()[n]->GetTextNode();
1706
1707 if (pTextNd)
1708 {
1709 if (pLayout)
1710 {
1711 pTextNd = sw::GetParaPropsNode(*pLayout, *pTextNd);
1712 }
1713 SwNumRule * pRule = pTextNd->GetNumRule();
1714
1715 if (pRule)
1716 {
1717 if (pRule->IsOutlineRule())
1718 bOnlyNonOutline = false;
1719 else
1720 bOnlyOutline = false;
1721 }
1722 }
1723 }
1724
1725 bool bRet = true;
1726 sal_Int8 nDiff = bDown ? 1 : -1;
1727
1728 if (bOnlyOutline)
1729 bRet = OutlineUpDown(rPam, nDiff, pLayout);
1730 else if (bOnlyNonOutline)
1731 {
1732 /* #i24560#
1733 Only promote or demote if all selected paragraphs are
1734 promotable resp. demotable.
1735 */
1736 for (SwNodeOffset nTmp = nStt; nTmp <= nEnd; ++nTmp)
1737 {
1738 SwTextNode* pTNd = GetNodes()[ nTmp ]->GetTextNode();
1739
1740 // Make code robust: consider case that the node doesn't denote a
1741 // text node.
1742 if ( pTNd )
1743 {
1744 if (pLayout)
1745 {
1746 pTNd = sw::GetParaPropsNode(*pLayout, *pTNd);
1747 }
1748
1749 SwNumRule * pRule = pTNd->GetNumRule();
1750
1751 if (pRule)
1752 {
1753 sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1754 if( (-1 == nDiff && 0 >= nLevel) ||
1755 (1 == nDiff && MAXLEVEL - 1 <= nLevel))
1756 bRet = false;
1757 }
1758 }
1759 }
1760
1761 if( bRet )
1762 {
1763 if (GetIDocumentUndoRedo().DoesUndo())
1764 {
1765 GetIDocumentUndoRedo().AppendUndo(
1766 std::make_unique<SwUndoNumUpDown>(aPam, nDiff) );
1767 }
1768
1769 SwTextNode* pPrev = nullptr;
1770 for(SwNodeOffset nTmp = nStt; nTmp <= nEnd; ++nTmp )
1771 {
1772 SwTextNode* pTNd = GetNodes()[ nTmp ]->GetTextNode();
1773
1774 if( pTNd)
1775 {
1776 if (pLayout)
1777 {
1778 pTNd = sw::GetParaPropsNode(*pLayout, *pTNd);
1779 if (pTNd == pPrev)
1780 {
1781 continue;
1782 }
1783 pPrev = pTNd;
1784 }
1785
1786 SwNumRule * pRule = pTNd->GetNumRule();
1787
1788 if (pRule)
1789 {
1790 sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1791 nLevel = nLevel + nDiff;
1792
1793 pTNd->SetAttrListLevel(nLevel);
1794 }
1795 }
1796 }
1797
1798 ChkCondColls();
1800 }
1801 }
1802
1803 return bRet;
1804}
1805
1806// this function doesn't contain any numbering-related code, but it is
1807// primarily called to move numbering-relevant paragraphs around, hence
1808// it will expand its selection to include full SwTextFrames.
1809bool SwDoc::MoveParagraph(SwPaM& rPam, SwNodeOffset nOffset, bool const bIsOutlMv)
1810{
1812
1813 // sw_redlinehide: as long as a layout with Hide mode exists, only
1814 // move nodes that have merged frames *completely*
1815 SwRootFrame const* pLayout(nullptr);
1816 for (SwRootFrame const*const pLay : GetAllLayouts())
1817 {
1818 if (pLay->HasMergedParas())
1819 {
1820 pLayout = pLay;
1821 }
1822 }
1823 if (pLayout)
1824 {
1825 std::pair<SwTextNode *, SwTextNode *> nodes(
1826 sw::GetFirstAndLastNode(*pLayout, rPam.Start()->GetNode()));
1827 if (nodes.first && nodes.first != &rPam.Start()->GetNode())
1828 {
1829 assert(nodes.second);
1830 if (nOffset < SwNodeOffset(0))
1831 {
1832 nOffset += rPam.Start()->GetNodeIndex() - nodes.first->GetIndex();
1833 if (SwNodeOffset(0) <= nOffset) // hack: there are callers that know what
1834 { // node they want; those should never need
1835 nOffset = SwNodeOffset(-1); // this; other callers just pass in -1
1836 } // and those should still move
1837 }
1838 if (!rPam.HasMark())
1839 {
1840 rPam.SetMark();
1841 }
1842 assert(nodes.first->GetIndex() < rPam.Start()->GetNodeIndex());
1843 rPam.Start()->Assign(*nodes.first);
1844 }
1845 nodes = sw::GetFirstAndLastNode(*pLayout, rPam.End()->GetNode());
1846 if (nodes.second && nodes.second != &rPam.End()->GetNode())
1847 {
1848 assert(nodes.first);
1849 if (SwNodeOffset(0) < nOffset)
1850 {
1851 nOffset -= nodes.second->GetIndex() - rPam.End()->GetNodeIndex();
1852 if (nOffset <= SwNodeOffset(0)) // hack: there are callers that know what
1853 { // node they want; those should never need
1854 nOffset = SwNodeOffset(+1); // this; other callers just pass in +1
1855 } // and those should still move
1856 }
1857 if (!rPam.HasMark())
1858 {
1859 rPam.SetMark();
1860 }
1861 assert(rPam.End()->GetNodeIndex() < nodes.second->GetIndex());
1862 // until end, otherwise Impl will detect overlapping redline
1863 rPam.End()->Assign(*nodes.second, nodes.second->GetTextNode()->Len());
1864 }
1865
1866 if (nOffset > SwNodeOffset(0))
1867 { // sw_redlinehide: avoid moving into delete redline, skip forward
1868 if (GetNodes().GetEndOfContent().GetIndex() <= rPam.End()->GetNodeIndex() + nOffset)
1869 {
1870 return false; // can't move
1871 }
1872 SwNode const* pNode(GetNodes()[rPam.End()->GetNodeIndex() + nOffset + 1]);
1875 {
1876 for ( ; ; ++nOffset)
1877 {
1878 pNode = GetNodes()[rPam.End()->GetNodeIndex() + nOffset];
1879 if (pNode->IsTextNode())
1880 {
1881 nodes = GetFirstAndLastNode(*pLayout, *pNode->GetTextNode());
1882 assert(nodes.first && nodes.second);
1883 nOffset += nodes.second->GetIndex() - pNode->GetIndex();
1884 // on last; will be incremented below to behind-last
1885 break;
1886 }
1887 }
1888 }
1889 }
1890 else
1891 { // sw_redlinehide: avoid moving into delete redline, skip backward
1892 if (rPam.Start()->GetNodeIndex() + nOffset < SwNodeOffset(1))
1893 {
1894 return false; // can't move
1895 }
1896 SwNode const* pNode(GetNodes()[rPam.Start()->GetNodeIndex() + nOffset]);
1899 {
1900 for ( ; ; --nOffset)
1901 {
1902 pNode = GetNodes()[rPam.Start()->GetNodeIndex() + nOffset];
1903 if (pNode->IsTextNode())
1904 {
1905 nodes = GetFirstAndLastNode(*pLayout, *pNode->GetTextNode());
1906 assert(nodes.first && nodes.second);
1907 nOffset -= pNode->GetIndex() - nodes.first->GetIndex();
1908 // on first
1909 break;
1910 }
1911 }
1912 }
1913 }
1914 }
1915 return MoveParagraphImpl(rPam, nOffset, bIsOutlMv, pLayout);
1916}
1917
1919 bool const bIsOutlMv, SwRootFrame const*const pLayout)
1920{
1921 auto [pStt, pEnd] = rPam.StartEnd(); // SwPosition*
1922
1923 SwNodeOffset nStIdx = pStt->GetNodeIndex();
1924 SwNodeOffset nEndIdx = pEnd->GetNodeIndex();
1925
1926 // Here are some sophisticated checks whether the wished PaM will be moved or not.
1927 // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
1928 // checks...
1929 SwNode *pTmp1;
1930 SwNode *pTmp2;
1931 if( bIsOutlMv )
1932 {
1933 // For moving chapters (outline) the following reason will deny the move:
1934 // if a start node is inside the moved range and its end node outside or vice versa.
1935 // If a start node is the first moved paragraph, its end node has to be within the moved
1936 // range, too (e.g. as last node).
1937 // If an end node is the last node of the moved range, its start node has to be a part of
1938 // the moved section, too.
1939 pTmp1 = GetNodes()[ nStIdx ];
1940 if( pTmp1->IsStartNode() )
1941 {
1942 // coverity[copy_paste_error : FALSE] - First is a start node
1943 pTmp2 = pTmp1->EndOfSectionNode();
1944 if( pTmp2->GetIndex() > nEndIdx )
1945 return false; // Its end node is behind the moved range
1946 }
1947 pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
1948 if( pTmp1->GetIndex() <= nEndIdx )
1949 return false; // End node inside but start node before moved range => no.
1950 pTmp1 = GetNodes()[ nEndIdx ];
1951 if( pTmp1->IsEndNode() )
1952 { // The last one is an end node
1953 pTmp1 = pTmp1->StartOfSectionNode();
1954 if( pTmp1->GetIndex() < nStIdx )
1955 return false; // Its start node is before the moved range.
1956 }
1957 pTmp1 = pTmp1->StartOfSectionNode();
1958 if( pTmp1->GetIndex() >= nStIdx )
1959 return false; // A start node which ends behind the moved range => no.
1960 }
1961
1962 SwNodeOffset nInStIdx, nInEndIdx;
1963 SwNodeOffset nOffs = nOffset;
1964 if( nOffset > SwNodeOffset(0) )
1965 {
1966 nInEndIdx = nEndIdx;
1967 nEndIdx += nOffset;
1968 ++nOffs;
1969 }
1970 else
1971 {
1972 // Impossible to move to negative index
1973 if( abs( nOffset ) > nStIdx)
1974 return false;
1975
1976 nInEndIdx = nStIdx - 1;
1977 nStIdx += nOffset;
1978 }
1979 nInStIdx = nInEndIdx + 1;
1980 // The following paragraphs shall be swapped:
1981 // Swap [ nStIdx, nInEndIdx ] with [ nInStIdx, nEndIdx ]
1982
1983 if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
1984 return false;
1985
1986 if( !bIsOutlMv )
1987 { // And here the restrictions for moving paragraphs other than chapters (outlines)
1988 // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
1989 // It will checked if the both "start" nodes as well as the both "end" notes belongs to
1990 // the same start-end-section. This is more restrictive than the conditions checked above.
1991 // E.g. a paragraph will not escape from a section or be inserted to another section.
1992 pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
1993 pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
1994 if( pTmp1 != pTmp2 )
1995 return false; // "start" nodes in different sections
1996 pTmp1 = GetNodes()[ nEndIdx ];
1997 bool bIsEndNode = pTmp1->IsEndNode();
1998 if( !pTmp1->IsStartNode() )
1999 {
2000 pTmp1 = pTmp1->StartOfSectionNode();
2001 if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
2002 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
2003 }
2004 pTmp1 = pTmp1->EndOfSectionNode();
2005 pTmp2 = GetNodes()[ nInEndIdx ];
2006 if( !pTmp2->IsStartNode() )
2007 {
2008 bIsEndNode = pTmp2->IsEndNode();
2009 pTmp2 = pTmp2->StartOfSectionNode();
2010 if( bIsEndNode )
2011 pTmp2 = pTmp2->StartOfSectionNode();
2012 }
2013 pTmp2 = pTmp2->EndOfSectionNode();
2014 if( pTmp1 != pTmp2 )
2015 return false; // The "end" notes are in different sections
2016 }
2017
2018 // Test for Redlining - Can the Selection be moved at all, actually?
2019 if( !getIDocumentRedlineAccess().IsIgnoreRedline() )
2020 {
2021 SwRedlineTable::size_type nRedlPos = getIDocumentRedlineAccess().GetRedlinePos( pStt->GetNode(), RedlineType::Delete );
2022 if( SwRedlineTable::npos != nRedlPos )
2023 {
2024 SwContentNode* pCNd = pEnd->GetNode().GetContentNode();
2025 SwPosition aStPos( pStt->GetNode() );
2026 SwPosition aEndPos( pEnd->GetNode(), pCNd, pCNd ? pCNd->Len() : 1 );
2027 bool bCheckDel = true;
2028
2029 // There is a some Redline Delete Object for the range
2030 for( ; nRedlPos < getIDocumentRedlineAccess().GetRedlineTable().size(); ++nRedlPos )
2031 {
2032 const SwRangeRedline* pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ];
2033 if( !bCheckDel || RedlineType::Delete == pTmp->GetType() )
2034 {
2035 auto [pRStt, pREnd] = pTmp->StartEnd(); // SwPosition*
2036 switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
2037 {
2039 case SwComparePosition::Behind: // Pos1 comes after Pos2
2041 break;
2042
2044 case SwComparePosition::Before: // Pos1 comes before Pos2
2045 break;
2046 case SwComparePosition::Inside: // Pos1 is completely inside Pos2
2047 // that's valid, but check all following for overlapping
2048 bCheckDel = false;
2049 break;
2050
2051 case SwComparePosition::Outside: // Pos2 is completely inside Pos1
2052 case SwComparePosition::Equal: // Pos1 is equal to Pos2
2053 case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 in the beginning
2054 case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at the end
2055 return false;
2056 }
2057 }
2058 }
2059 }
2060 }
2061
2062 {
2063 // Send DataChanged before moving. We then can detect
2064 // which objects are still in the range.
2065 // After the move they could come before/after the
2066 // Position.
2067 SwDataChanged aTmp( rPam );
2068 }
2069
2070 SwNodeIndex aIdx( nOffset > SwNodeOffset(0) ? pEnd->GetNode() : pStt->GetNode(), nOffs );
2071 SwNodeRange aMvRg( pStt->GetNode(), SwNodeOffset(0), pEnd->GetNode(), SwNodeOffset(+1) );
2072
2073 SwRangeRedline* pOwnRedl = nullptr;
2074 if( getIDocumentRedlineAccess().IsRedlineOn() )
2075 {
2076 // If the range is completely in the own Redline, we can move it!
2077 SwRedlineTable::size_type nRedlPos = getIDocumentRedlineAccess().GetRedlinePos( pStt->GetNode(), RedlineType::Insert );
2078 if( SwRedlineTable::npos != nRedlPos )
2079 {
2081 auto [pRStt, pREnd] = pTmp->StartEnd(); // SwPosition*
2082 SwRangeRedline aTmpRedl( RedlineType::Insert, rPam );
2083 const SwContentNode* pCEndNd = pEnd->GetNode().GetContentNode();
2084 // Is completely in the range and is the own Redline too?
2085 if( aTmpRedl.IsOwnRedline( *pTmp ) &&
2086 (pRStt->GetNode() < pStt->GetNode() ||
2087 (pRStt->GetNode() == pStt->GetNode() && !pRStt->GetContentIndex()) ) &&
2088 (pEnd->GetNode() < pREnd->GetNode() ||
2089 (pEnd->GetNode() == pREnd->GetNode() &&
2090 pCEndNd ? pREnd->GetContentIndex() == pCEndNd->Len()
2091 : !pREnd->GetContentIndex() )) )
2092 {
2093 pOwnRedl = pTmp;
2094 if( nRedlPos + 1 < getIDocumentRedlineAccess().GetRedlineTable().size() )
2095 {
2096 pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos+1 ];
2097 if( *pTmp->Start() == *pREnd )
2098 // then don't!
2099 pOwnRedl = nullptr;
2100 }
2101
2102 if( pOwnRedl &&
2103 ( pRStt->GetNode() > aIdx.GetNode() || aIdx > pREnd->GetNode() ||
2104 // pOwnRedl doesn't start at the beginning of a node, so it's not
2105 // possible to resize it to contain the line moved before it
2106 ( pRStt->GetNode() == aIdx.GetNode() && pRStt->GetContentIndex() > 0 ) ) )
2107 {
2108 // it's not in itself, so don't move it
2109 pOwnRedl = nullptr;
2110 }
2111 }
2112 }
2113
2114 if( !pOwnRedl )
2115 {
2116 GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
2117
2118 // First the Insert, then the Delete
2119 SwPosition aInsPos( aIdx );
2120
2121 std::optional<SwPaM> oPam( std::in_place, pStt->GetNode(), 0, aMvRg.aEnd.GetNode(), 0 );
2122
2123 SwPaM& rOrigPam(rPam);
2124 rOrigPam.DeleteMark();
2125 rOrigPam.GetPoint()->Assign(aIdx.GetIndex() - 1);
2126
2127 bool bDelLastPara = !aInsPos.GetNode().IsContentNode();
2128 SwNodeOffset nOrigIdx = aIdx.GetIndex();
2129
2130 /* When copying to a non-content node Copy will
2131 insert a paragraph before that node and insert before
2132 that inserted node. Copy creates an SwUndoInserts that
2133 does not cover the extra paragraph. Thus we insert the
2134 extra paragraph ourselves, _with_ correct undo
2135 information. */
2136 if (bDelLastPara)
2137 {
2138 /* aInsPos points to the non-content node. Move it to
2139 the previous content node. */
2140 SwPaM aInsPam(aInsPos);
2141 const bool bMoved = aInsPam.Move(fnMoveBackward);
2142 OSL_ENSURE(bMoved, "No content node found!");
2143
2144 if (bMoved)
2145 {
2146 /* Append the new node after the content node
2147 found. The new position to insert the moved
2148 paragraph at is before the inserted
2149 paragraph. */
2151 aInsPos = *aInsPam.GetPoint();
2152 }
2153 }
2154
2155 --aIdx; // move before insertion
2156
2157 // adjust empty nodes later
2158 SwTextNode const*const pIsEmptyNode(nOffset < SwNodeOffset(0)
2159 ? aInsPos.GetNode().GetTextNode()
2160 : aIdx.GetNode().GetTextNode());
2161 bool bIsEmptyNode = pIsEmptyNode && pIsEmptyNode->Len() == 0;
2162
2164
2165 // now delete all the delete redlines that were copied
2166#ifndef NDEBUG
2167 size_t nRedlines(getIDocumentRedlineAccess().GetRedlineTable().size());
2168#endif
2169 if (nOffset > SwNodeOffset(0))
2170 assert(oPam->End()->GetNodeIndex() - oPam->Start()->GetNodeIndex() + nOffset == aInsPos.GetNodeIndex() - oPam->End()->GetNodeIndex());
2171 else
2172 assert(oPam->Start()->GetNodeIndex() - oPam->End()->GetNodeIndex() + nOffset == aInsPos.GetNodeIndex() - oPam->End()->GetNodeIndex());
2174 getIDocumentRedlineAccess().GetRedline(*oPam->End(), &i);
2175 for ( ; 0 < i; --i)
2176 { // iterate backwards and offset via the start nodes difference
2177 SwRangeRedline const*const pRedline = getIDocumentRedlineAccess().GetRedlineTable()[i - 1];
2178 if (*pRedline->End() < *oPam->Start())
2179 {
2180 break;
2181 }
2182 if (pRedline->GetType() == RedlineType::Delete &&
2183 // tdf#145066 skip full-paragraph deletion which was jumped over
2184 // in Show Changes mode to avoid of deleting an extra row
2185 *oPam->Start() <= *pRedline->Start())
2186 {
2187 SwRangeRedline* pNewRedline;
2188 {
2189 SwPaM pam(*pRedline, nullptr);
2190 SwNodeOffset const nCurrentOffset(
2191 nOrigIdx - oPam->Start()->GetNodeIndex());
2192 pam.GetPoint()->Assign(pam.GetPoint()->GetNodeIndex() + nCurrentOffset,
2193 pam.GetPoint()->GetContentIndex());
2194 pam.GetMark()->Assign(pam.GetMark()->GetNodeIndex() + nCurrentOffset,
2195 pam.GetMark()->GetContentIndex());
2196
2197 pNewRedline = new SwRangeRedline( RedlineType::Delete, pam );
2198 }
2199 // note: effectively this will DeleteAndJoin the pam!
2200 getIDocumentRedlineAccess().AppendRedline(pNewRedline, true);
2201 assert(getIDocumentRedlineAccess().GetRedlineTable().size() <= nRedlines);
2202 }
2203 }
2204
2205 if( bDelLastPara )
2206 {
2207 // We need to remove the last empty Node again
2208 aIdx = aInsPos.GetNode();
2209 SwContentNode* pCNd = SwNodes::GoPrevious( &aInsPos );
2210 if (pCNd)
2211 aInsPos.AssignEndIndex( *pCNd );
2212
2213 // All, that are in the to-be-deleted Node, need to be
2214 // moved to the next Node
2215 for(SwRangeRedline* pTmp : getIDocumentRedlineAccess().GetRedlineTable())
2216 {
2217 SwPosition* pPos = &pTmp->GetBound();
2218 if( pPos->GetNode() == aIdx.GetNode() )
2219 {
2220 pPos->Adjust(SwNodeOffset(1));
2221 }
2222 pPos = &pTmp->GetBound(false);
2223 if( pPos->GetNode() == aIdx.GetNode() )
2224 {
2225 pPos->Adjust(SwNodeOffset(1));
2226 }
2227 }
2228 CorrRel( aIdx.GetNode(), aInsPos );
2229
2230 if (pCNd)
2231 pCNd->JoinNext();
2232 }
2233
2234 rOrigPam.GetPoint()->Adjust(SwNodeOffset(1));
2235 assert(*oPam->GetMark() < *oPam->GetPoint());
2236 if (oPam->GetPoint()->GetNode().IsEndNode())
2237 { // ensure redline ends on content node
2238 oPam->GetPoint()->Adjust(SwNodeOffset(-1));
2239 assert(oPam->GetPoint()->GetNode().IsTextNode());
2240 SwTextNode *const pNode(oPam->GetPoint()->GetNode().GetTextNode());
2241 oPam->GetPoint()->SetContent(pNode->Len());
2242 }
2243
2245 if (GetIDocumentUndoRedo().DoesUndo())
2246 {
2247 // this should no longer happen in calls from the UI but maybe via API
2249 "sw.core", "redlines will be moved in DeleteAndJoin");
2250
2253 GetIDocumentUndoRedo().AppendUndo(
2254 std::make_unique<SwUndoRedlineDelete>(*oPam, SwUndoId::DELETE));
2255 }
2256
2257 SwRangeRedline* pNewRedline = new SwRangeRedline( RedlineType::Delete, *oPam );
2258
2259 // prevent assertion from aPam's target being deleted
2260 SwNodeIndex bound1(oPam->GetBound().GetNode());
2261 SwNodeIndex bound2(oPam->GetBound(false).GetNode());
2262 oPam.reset();
2263
2264 getIDocumentRedlineAccess().AppendRedline( pNewRedline, true );
2265
2266 oPam.emplace(bound1, bound2);
2268
2269 // avoid setting empty nodes to tracked insertion
2270 if ( bIsEmptyNode )
2271 {
2273 SwRedlineTable::size_type nRedlPosWithEmpty =
2274 getIDocumentRedlineAccess().GetRedlinePos( pStt->GetNode(), RedlineType::Insert );
2275 if ( SwRedlineTable::npos != nRedlPosWithEmpty )
2276 {
2277 pOwnRedl = rTable[nRedlPosWithEmpty];
2278 SwPosition *pRPos = nOffset < SwNodeOffset(0) ? pOwnRedl->End() : pOwnRedl->Start();
2279 SwNodeIndex aIdx2 ( pRPos->GetNode() );
2280 SwTextNode const*const pEmptyNode0(aIdx2.GetNode().GetTextNode());
2281 if ( nOffset < SwNodeOffset(0) )
2282 {
2283 // move up
2284 --aIdx2;
2285 SwTextNode const*const pEmptyNode(aIdx2.GetNode().GetTextNode());
2286 if ( pEmptyNode && pEmptyNode->Len() == 0 )
2287 pRPos->Adjust(SwNodeOffset(-1));
2288 }
2289 else if ( pEmptyNode0 && pEmptyNode0->Len() == 0 )
2290 {
2291 // move down
2292 ++aIdx2;
2293 SwTextNode const*const pEmptyNode(aIdx2.GetNode().GetTextNode());
2294 if (pEmptyNode)
2295 pRPos->Adjust(SwNodeOffset(+1));
2296 }
2297
2298 // sort redlines, when the trimmed range results bad redline order
2299 if ( nRedlPosWithEmpty + 1 < rTable.size() &&
2300 *rTable[nRedlPosWithEmpty + 1] < *rTable[nRedlPosWithEmpty] )
2301 {
2302 rTable.Remove(nRedlPosWithEmpty);
2303 rTable.Insert(pOwnRedl);
2304 }
2305 }
2306 }
2307
2309 GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
2311
2312 return true;
2313 }
2314 }
2315
2316 if( !pOwnRedl && !getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() )
2317 {
2318 SwPaM aTemp(aIdx);
2320 }
2321
2322 SwNodeOffset nRedlSttNd(0), nRedlEndNd(0);
2323 if( pOwnRedl )
2324 {
2325 const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2326 nRedlSttNd = pRStt->GetNodeIndex();
2327 nRedlEndNd = pREnd->GetNodeIndex();
2328 }
2329
2330 std::unique_ptr<SwUndoMoveNum> pUndo;
2331 SwNodeOffset nMoved(0);
2332 if (GetIDocumentUndoRedo().DoesUndo())
2333 {
2334 pUndo.reset(new SwUndoMoveNum( rPam, nOffset, bIsOutlMv ));
2335 nMoved = rPam.End()->GetNodeIndex() - rPam.Start()->GetNodeIndex() + 1;
2336 }
2337
2338 (void) pLayout; // note: move will insert between aIdx-1 and aIdx
2339 assert(!pLayout // check not moving *into* delete redline (caller's fault)
2343
2344 if( pUndo )
2345 {
2346 // i57907: Under circumstances (sections at the end of a chapter)
2347 // the rPam.Start() is not moved to the new position.
2348 // But aIdx should be at the new end position and as long as the
2349 // number of moved paragraphs is nMoved, I know, where the new
2350 // position is.
2351 pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
2352 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
2353 }
2354
2355 if( pOwnRedl )
2356 {
2357 auto [pRStt, pREnd] = pOwnRedl->StartEnd(); // SwPosition*
2358 if( pRStt->GetNodeIndex() != nRedlSttNd )
2359 {
2360 pRStt->Assign(nRedlSttNd);
2361 }
2362 if( pREnd->GetNodeIndex() != nRedlEndNd )
2363 {
2364 pREnd->Assign(nRedlEndNd);
2365 SwContentNode* pCNd = pREnd->GetNode().GetContentNode();
2366 if(pCNd)
2367 pREnd->SetContent( pCNd->Len() );
2368 }
2369 }
2370
2372 return true;
2373}
2374
2375bool SwDoc::NumOrNoNum( SwNode& rIdx, bool bDel )
2376{
2377 bool bResult = false;
2378 SwTextNode * pTextNd = rIdx.GetTextNode();
2379
2380 if (pTextNd && pTextNd->GetNumRule() != nullptr &&
2381 (pTextNd->HasNumber() || pTextNd->HasBullet()))
2382 {
2383 if ( !pTextNd->IsCountedInList() == !bDel)
2384 {
2385 bool bOldNum = bDel;
2386 bool bNewNum = !bDel;
2387 pTextNd->SetCountedInList(bNewNum);
2388
2390
2391 bResult = true;
2392
2393 if (GetIDocumentUndoRedo().DoesUndo())
2394 {
2395 GetIDocumentUndoRedo().AppendUndo(
2396 std::make_unique<SwUndoNumOrNoNum>(rIdx, bOldNum, bNewNum));
2397 }
2398 }
2399 else if (bDel && pTextNd->GetNumRule(false) &&
2400 pTextNd->GetActualListLevel() >= 0 &&
2401 pTextNd->GetActualListLevel() < MAXLEVEL)
2402 {
2403 SwPaM aPam(*pTextNd);
2404 DelNumRules(aPam);
2405
2406 bResult = true;
2407 }
2408 }
2409
2410 return bResult;
2411}
2412
2414 SwRootFrame const*const pLayout)
2415{
2416 SwNumRule* pRet = nullptr;
2417 SwTextNode* pTNd = rPos.GetNode().GetTextNode();
2418
2419 if ( pTNd != nullptr )
2420 {
2421 if (pLayout && !sw::IsParaPropsNode(*pLayout, *pTNd))
2422 {
2423 pTNd = static_cast<SwTextFrame*>(pTNd->getLayoutFrame(pLayout))->GetMergedPara()->pParaPropsNode;
2424 rPos.Assign(*pTNd);
2425 }
2426 pRet = pTNd->GetNumRule();
2427 }
2428
2429 return pRet;
2430}
2431
2432sal_uInt16 SwDoc::FindNumRule( std::u16string_view rName ) const
2433{
2434 for( sal_uInt16 n = mpNumRuleTable->size(); n; )
2435 if( (*mpNumRuleTable)[ --n ]->GetName() == rName )
2436 return n;
2437
2438 return USHRT_MAX;
2439}
2440
2441SwNumRule* SwDoc::FindNumRulePtr( const OUString& rName ) const
2442{
2443 SwNumRule * pResult = maNumRuleMap[rName];
2444
2445 if ( !pResult )
2446 {
2447 for (size_t n = 0; n < mpNumRuleTable->size(); ++n)
2448 {
2449 if ((*mpNumRuleTable)[n]->GetName() == rName)
2450 {
2451 pResult = (*mpNumRuleTable)[n];
2452
2453 break;
2454 }
2455 }
2456 }
2457
2458 return pResult;
2459}
2460
2462{
2463 if ((SAL_MAX_UINT16 - 1) <= mpNumRuleTable->size())
2464 {
2465 OSL_ENSURE(false, "SwDoc::AddNumRule: table full.");
2466 abort(); // this should never happen on real documents
2467 }
2468 mpNumRuleTable->push_back(pRule);
2469 maNumRuleMap[pRule->GetName()] = pRule;
2470 pRule->SetNumRuleMap(&maNumRuleMap);
2471
2473}
2474
2475sal_uInt16 SwDoc::MakeNumRule( const OUString &rName,
2476 const SwNumRule* pCpy,
2477 bool bBroadcast,
2478 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
2479{
2480 SwNumRule* pNew;
2481 if( pCpy )
2482 {
2483 pNew = new SwNumRule( *pCpy );
2484
2486
2487 if( pNew->GetName() != rName )
2488 {
2489 pNew->SetPoolFormatId( USHRT_MAX );
2490 pNew->SetPoolHelpId( USHRT_MAX );
2491 pNew->SetPoolHlpFileId( UCHAR_MAX );
2492 pNew->SetDefaultListId( OUString() );
2493 }
2494 pNew->CheckCharFormats( *this );
2495 }
2496 else
2497 {
2498 pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
2499 eDefaultNumberFormatPositionAndSpaceMode );
2500 }
2501
2502 sal_uInt16 nRet = mpNumRuleTable->size();
2503
2504 AddNumRule(pNew);
2505
2506 if (GetIDocumentUndoRedo().DoesUndo())
2507 {
2508 GetIDocumentUndoRedo().AppendUndo(
2509 std::make_unique<SwUndoNumruleCreate>(pNew, *this));
2510 }
2511
2512 if (bBroadcast)
2513 BroadcastStyleOperation(pNew->GetName(), SfxStyleFamily::Pseudo,
2514 SfxHintId::StyleSheetCreated);
2515
2516 return nRet;
2517}
2518
2519OUString SwDoc::GetUniqueNumRuleName( const OUString* pChkStr, bool bAutoNum ) const
2520{
2521 // If we got pChkStr, then the caller expects that in case it's not yet
2522 // used, it'll be returned.
2523 if( IsInMailMerge() && !pChkStr )
2524 {
2525 OUString newName = "MailMergeNumRule"
2526 + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
2527 + OUString::number( mpNumRuleTable->size() + 1 );
2528 return newName;
2529 }
2530
2531 OUString aName;
2532 if( bAutoNum )
2533 {
2534 static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
2535
2536 if (bHack)
2537 {
2538 static sal_Int64 nIdCounter = SAL_CONST_INT64(8000000000);
2539 aName = OUString::number(nIdCounter++);
2540 }
2541 else
2542 {
2543 unsigned int const n(comphelper::rng::uniform_uint_distribution(0,
2544 std::numeric_limits<unsigned int>::max()));
2545 aName = OUString::number(n);
2546 }
2547 if( pChkStr && pChkStr->isEmpty() )
2548 pChkStr = nullptr;
2549 }
2550 else if( pChkStr && !pChkStr->isEmpty() )
2551 aName = *pChkStr;
2552 else
2553 {
2554 pChkStr = nullptr;
2555 aName = SwResId( STR_NUMRULE_DEFNAME );
2556 }
2557
2558 sal_uInt16 nNum(0), nTmp, nFlagSize = ( mpNumRuleTable->size() / 8 ) +2;
2559 std::unique_ptr<sal_uInt8[]> pSetFlags(new sal_uInt8[ nFlagSize ]);
2560 memset( pSetFlags.get(), 0, nFlagSize );
2561
2562 sal_Int32 nNmLen = aName.getLength();
2563 if( !bAutoNum && pChkStr )
2564 {
2565 while( nNmLen-- && '0' <= aName[nNmLen] && aName[nNmLen] <= '9' )
2566 ; //nop
2567
2568 if( ++nNmLen < aName.getLength() )
2569 {
2570 aName = aName.copy(0, nNmLen );
2571 pChkStr = nullptr;
2572 }
2573 }
2574
2575 for( auto const & pNumRule: *mpNumRuleTable )
2576 if( nullptr != pNumRule )
2577 {
2578 const OUString sNm = pNumRule->GetName();
2579 if( sNm.startsWith( aName ) )
2580 {
2581 // Determine Number and set the Flag
2582 nNum = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sNm.subView( nNmLen )));
2583 if( nNum-- && nNum < mpNumRuleTable->size() )
2584 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2585 }
2586 if( pChkStr && *pChkStr==sNm )
2587 pChkStr = nullptr;
2588 }
2589
2590 if( !pChkStr )
2591 {
2592 // All Numbers have been flagged accordingly, so identify the right Number
2593 nNum = mpNumRuleTable->size();
2594 for( sal_uInt16 n = 0; n < nFlagSize; ++n )
2595 {
2596 nTmp = pSetFlags[ n ];
2597 if( 0xff != nTmp )
2598 {
2599 // identify the Number
2600 nNum = n * 8;
2601 while( nTmp & 1 )
2602 {
2603 ++nNum;
2604 nTmp >>= 1;
2605 }
2606 break;
2607 }
2608 }
2609 }
2610 if( pChkStr && !pChkStr->isEmpty() )
2611 return *pChkStr;
2612 return aName + OUString::number( ++nNum );
2613}
2614
2616{
2617 const SwNumRuleTable& rNmTable = GetNumRuleTable();
2618 for( size_t n = 0; n < rNmTable.size(); ++n )
2619 if( rNmTable[ n ]->IsInvalidRule() )
2620 rNmTable[ n ]->Validate(*this);
2621}
2622
2623void SwDoc::MarkListLevel( const OUString& sListId,
2624 const int nListLevel,
2625 const bool bValue )
2626{
2627 SwList* pList = getIDocumentListsAccess().getListByName( sListId );
2628
2629 if ( pList )
2630 {
2631 // Set new marked list level and notify all affected nodes of the changed mark.
2632 pList->MarkListLevel( nListLevel, bValue );
2633 }
2634}
2635
2637 SwRootFrame const& rLayout)
2638{
2639 bool bResult = false;
2640
2641 const SwTextNode *const pTextNode = sw::GetParaPropsNode(rLayout, rPos.GetNode());
2642 if ( pTextNode != nullptr )
2643 {
2644 bResult = pTextNode->IsFirstOfNumRule(rLayout);
2645 }
2646
2647 return bResult;
2648}
2649
2650/* 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
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:1230
virtual SwContentNode * JoinNext()
Definition: node.cxx:1567
void ChkCondColl(const SwTextFormatColl *pColl=nullptr)
Definition: node.cxx:2037
virtual sal_Int32 Len() const
Definition: node.cxx:1263
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:493
Definition: doc.hxx:194
void MarkListLevel(const OUString &sListId, const int nListLevel, const bool bValue)
Marks/Unmarks a list level of a certain list.
Definition: docnum.cxx:2623
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:306
void AddNumRule(SwNumRule *pRule)
Add numbering rule to document.
Definition: docnum.cxx:2461
std::unordered_map< OUString, SwNumRule * > maNumRuleMap
Definition: doc.hxx:279
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:638
void SetNodeNumStart(const SwPosition &rPos, sal_uInt16 nStt)
Definition: docnum.cxx:1031
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:1687
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:400
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:2375
OUString GetUniqueNumRuleName(const OUString *pChkStr=nullptr, bool bAutoNum=true) const
Definition: docnum.cxx:2519
std::unique_ptr< SwTextFormatColls > mpTextFormatCollTable
Definition: doc.hxx:251
sal_uInt16 FindNumRule(std::u16string_view rName) const
Definition: docnum.cxx:2432
o3tl::sorted_vector< SwRootFrame * > GetAllLayouts()
Definition: doclay.cxx:1683
bool IsUsed(const sw::BroadcastingModify &) const
Definition: poolfmt.cxx:86
void ReplaceNumRule(const SwPosition &rPos, const OUString &rOldRule, const OUString &rNewRule)
Definition: docnum.cxx:1172
void UpdateNumRule()
Definition: docnum.cxx:2615
bool NoNum(const SwPaM &)
Definition: docnum.cxx:1292
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2441
void PropagateOutlineRule()
Definition: docnum.cxx:176
void StopNumRuleAnimations(const OutputDevice *)
Definition: docnum.cxx:1153
const SwNumRuleTable & GetNumRuleTable() const
Definition: doc.hxx:1074
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1032
SwNumRule * mpOutlineRule
Definition: doc.hxx:260
bool MoveParagraph(SwPaM &, SwNodeOffset nOffset, bool bIsOutlMv=false)
Move selected paragraphs (not only numberings) according to offsets.
Definition: docnum.cxx:1809
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:321
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:150
SwNodes & GetNodes()
Definition: doc.hxx:417
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:363
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:341
void InvalidateNumRules()
Definition: docnum.cxx:1384
void DelNumRules(const SwPaM &, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1314
void SetNumRuleStart(const SwPosition &rPos, bool bFlag=true)
Definition: docnum.cxx:1009
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:642
bool RenameNumRule(const OUString &aOldName, const OUString &aNewName, bool bBroadcast=false)
Definition: docnum.cxx:1115
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:1093
void ChkCondColls()
Definition: doc.cxx:1791
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:432
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:1607
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:243
std::unique_ptr< SwNumRuleTable > mpNumRuleTable
Definition: doc.hxx:276
static bool IsFirstOfNumRuleAtPos(const SwPosition &rPos, SwRootFrame const &rLayout)
Definition: docnum.cxx:2636
void SetCounted(const SwPaM &, bool bCounted, SwRootFrame const *pLayout)
Definition: docnum.cxx:994
bool DelNumRule(const OUString &rName, bool bBroadCast=false)
Definition: docnum.cxx:1053
bool IsInMailMerge() const
Definition: doc.hxx:968
bool NumUpDown(const SwPaM &, bool bDown, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1693
void MakeUniqueNumRules(const SwPaM &rPaM)
Definition: docnum.cxx:1228
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:1918
static bool GotoNextNum(SwPosition &, SwRootFrame const *pLayout, bool bOverUpper=true, sal_uInt8 *pUpper=nullptr, sal_uInt8 *pLower=nullptr)
Definition: docnum.cxx:1601
static SwNumRule * GetNumRuleAtPos(SwPosition &rPos, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:2413
IDocumentListsAccess const & getIDocumentListsAccess() const
Definition: doc.cxx:299
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:2475
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:232
TElementType * Next()
Definition: calbck.hxx:373
TElementType * First()
Definition: calbck.hxx:365
Definition: list.hxx:40
void MarkListLevel(const int nListLevel, const bool bValue)
Definition: list.cxx:129
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:175
SwNode & GetNode() const
Definition: ndindex.hxx:136
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:171
SwNodeIndex aEnd
Definition: ndindex.hxx:150
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:897
SwNodeOffset GetIndex() const
Definition: node.hxx:312
bool IsContentNode() const
Definition: node.hxx:677
bool IsEndNode() const
Definition: node.hxx:681
bool IsStartNode() const
Definition: node.hxx:673
bool IsSectionNode() const
Definition: node.hxx:693
bool IsTableNode() const
Definition: node.hxx:689
bool IsTextNode() const
Definition: node.hxx:685
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:664
SwNodeType GetNodeType() const
Definition: node.hxx:166
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:731
const SwOutlineNodes & GetOutLineNds() const
Array of all OutlineNodes.
Definition: ndarr.hxx:240
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:1328
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:187
const SwPosition * GetMark() const
Definition: pam.hxx:263
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:642
std::pair< const SwPosition *, const SwPosition * > StartEnd() const
Because sometimes the cost of the operator<= can add up.
Definition: pam.hxx:277
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:668
const SwPosition * End() const
Definition: pam.hxx:271
SwDoc & GetDoc() const
Definition: pam.hxx:299
void DeleteMark()
Definition: pam.hxx:231
const SwPosition * GetPoint() const
Definition: pam.hxx:261
const SwPosition * Start() const
Definition: pam.hxx:266
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:259
bool IsOwnRedline(const SwRangeRedline &rRedl) const
Definition: redline.hxx:250
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1940
bool Insert(SwRangeRedline *&p)
Definition: docredln.cxx:415
static constexpr size_type npos
Definition: docary.hxx:223
size_type size() const
Definition: docary.hxx:267
void Remove(size_type nPos)
Definition: docredln.cxx:634
vector_type::size_type size_type
Definition: docary.hxx:222
void RegisterInModify(sw::BroadcastingModify *pRegIn, const SwNode &rNd)
Definition: rolbck.cxx:1489
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
bool HasMergedParas() const
Definition: rootfrm.hxx:425
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:59
bool IsAssignedToListLevelOfOutlineStyle() const
Definition: fmtcol.hxx:120
int GetAssignedOutlineStyleLevel() const
Definition: fmtcol.cxx:614
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:165
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:111
bool HasBullet() const
Returns if this text node has a bullet.
Definition: ndtxt.cxx:3215
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:3485
void SetAttrListLevel(int nLevel)
Sets the list level of this text node.
Definition: ndtxt.cxx:4198
SwNumberTree::tSwNumTreeNumber GetAttrListRestartValue() const
Definition: ndtxt.cxx:4312
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:290
void SetAttrOutlineLevel(int nLevel)
Sets the out line level at a text node.
Definition: ndtxt.cxx:4153
bool IsFirstOfNumRule(SwRootFrame const &rLayout) const
Definition: ndtxt.cxx:4531
OUString GetListId() const
Definition: ndtxt.cxx:4560
void SetListRestart(bool bRestart)
Definition: ndtxt.cxx:4237
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:5032
const SwNodeNum * GetNum(SwRootFrame const *pLayout=nullptr, SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Definition: ndtxt.cxx:4075
bool IsInList() const
Definition: ndtxt.cxx:4526
virtual SwFormatColl * ChgFormatColl(SwFormatColl *) override
Definition: ndtxt.cxx:4040
bool IsCountedInList() const
Definition: ndtxt.cxx:4373
void SetCountedInList(bool bCounted)
Definition: ndtxt.cxx:4358
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2907
bool HasNumber(SwRootFrame const *pLayout=nullptr) const
Returns if this text node has a number.
Definition: ndtxt.cxx:3199
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:4228
bool HasAttrListRestartValue() const
Definition: ndtxt.cxx:4307
bool IsListRestart() const
Definition: ndtxt.cxx:4253
void AddToList()
Definition: ndtxt.cxx:4403
int GetAttrOutlineLevel() const
Returns outline level of this text node.
Definition: ndtxt.cxx:4148
void SetAttrListRestartValue(SwNumberTree::tSwNumTreeNumber nNum)
Definition: ndtxt.cxx:4286
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:891
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5259
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:87
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:1494
static bool lcl_IsNumOk(sal_uInt8 nSrchNum, sal_uInt8 &rLower, sal_uInt8 &rUpper, bool bOverUpper, sal_uInt8 nNumber)
Definition: docnum.cxx:1391
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:1409
static void lcl_ChgNumRule(SwDoc &rDoc, const SwNumRule &rRule)
Definition: docnum.cxx:795
@ FTNNUM_CHAPTER
Definition: ftninfo.hxx:87
constexpr TypedWhichId< SfxStringItem > RES_PARATR_LIST_ID(RES_PARATR_LIST_BEGIN)
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< SfxBoolItem > RES_PARATR_LIST_ISCOUNTED(86)
constexpr TypedWhichId< SwConditionTextFormatColl > RES_CONDTXTFMTCOLL(160)
constexpr TypedWhichId< SfxBoolItem > RES_PARATR_LIST_ISRESTART(84)
constexpr TypedWhichId< SvxLRSpaceItem > RES_LR_SPACE(91)
OUString aName
sal_Int64 n
uno_Any a
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
const char * sName
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:1466
void GotoPrevLayoutTextFrame(SwNodeIndex &rIndex, SwRootFrame const *const pLayout)
Definition: docnum.cxx:1436
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:122
@ 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:37
void Adjust(SwNodeOffset nDelta)
Adjust node position, and resets content position to zero.
Definition: pam.cxx:256
SwNode & GetNode() const
Definition: pam.hxx:80
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:230
void AssignEndIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the end of rNd.
Definition: pam.cxx:276
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:77
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
SVX_NUM_NUMBER_NONE
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:165
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