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