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