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