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