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