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