LibreOffice Module sw (master)  1
ednumber.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 <editsh.hxx>
22 #include <edimp.hxx>
23 #include <doc.hxx>
24 #include <IDocumentUndoRedo.hxx>
25 #include <IDocumentState.hxx>
26 #include <ndtxt.hxx>
27 #include <txtfrm.hxx>
28 #include <paratr.hxx>
29 #include <swundo.hxx>
30 #include <numrule.hxx>
31 
33 {
34  for(SwPaM& rTmp : const_cast<SwPaM*>(&rRing)->GetRingContainer())
35  Insert( rTmp.GetMark()->nNode, rTmp.GetPoint()->nNode );
36 }
37 
38 void SwPamRanges::Insert( const SwNodeIndex& rIdx1, const SwNodeIndex& rIdx2 )
39 {
40  SwPamRange aRg( rIdx1.GetIndex(), rIdx2.GetIndex() );
41  if( aRg.nEnd < aRg.nStart )
42  { aRg.nStart = aRg.nEnd; aRg.nEnd = rIdx1.GetIndex(); }
43 
44  o3tl::sorted_vector<SwPamRange>::const_iterator it = maVector.lower_bound(aRg); //search Insert Position
45  size_t nPos = it - maVector.begin();
46  if (!maVector.empty() && (it != maVector.end()) && (*it) == aRg)
47  {
48  // is the one in the Array smaller?
49  SwPamRange const& rTmp = maVector[nPos];
50  if( rTmp.nEnd < aRg.nEnd )
51  {
52  aRg.nEnd = rTmp.nEnd;
53  maVector.erase(maVector.begin() + nPos); // combine
54  }
55  else
56  return; // done, because by precondition everything is combined
57  }
58 
59  bool bEnd;
60  do {
61  bEnd = true;
62 
63  // combine with predecessor?
64  if( nPos > 0 )
65  {
66  SwPamRange const& rTmp = maVector[nPos-1];
67  if( rTmp.nEnd == aRg.nStart
68  || rTmp.nEnd+1 == aRg.nStart )
69  {
70  aRg.nStart = rTmp.nStart;
71  bEnd = false;
72  maVector.erase( maVector.begin() + --nPos ); // combine
73  }
74  // range contained in rTmp?
75  else if( rTmp.nStart <= aRg.nStart && aRg.nEnd <= rTmp.nEnd )
76  return;
77  }
78  // combine with successor?
79  if( nPos < maVector.size() )
80  {
81  SwPamRange const& rTmp = maVector[nPos];
82  if( rTmp.nStart == aRg.nEnd ||
83  rTmp.nStart == aRg.nEnd+1 )
84  {
85  aRg.nEnd = rTmp.nEnd;
86  bEnd = false;
87  maVector.erase( maVector.begin() + nPos ); // combine
88  }
89 
90  // range contained in rTmp?
91  else if( rTmp.nStart <= aRg.nStart && aRg.nEnd <= rTmp.nEnd )
92  return;
93  }
94  } while( !bEnd );
95 
96  maVector.insert( aRg );
97 }
98 
99 SwPaM& SwPamRanges::SetPam( size_t nArrPos, SwPaM& rPam )
100 {
101  assert( nArrPos < Count() );
102  const SwPamRange& rTmp = maVector[ nArrPos ];
103  rPam.GetPoint()->nNode = rTmp.nStart;
104  rPam.GetPoint()->nContent.Assign( rPam.GetContentNode(), 0 );
105  rPam.SetMark();
106  rPam.GetPoint()->nNode = rTmp.nEnd;
107  rPam.GetPoint()->nContent.Assign( rPam.GetContentNode(), 0 );
108  return rPam;
109 }
110 
111 // Rule book for outline numbering
112 
114 {
115  StartAllAction(); // bracketing for updating!
116  GetDoc()->SetOutlineNumRule(rRule);
117  EndAllAction();
118 }
119 
121 {
122  return GetDoc()->GetOutlineNumRule();
123 }
124 
125 // Set if there is no numbering yet, else update.
126 // Works with old and new rules. Update only differences.
127 
128 // paragraphs without numbering, with indentations
130 {
131  bool bRet = true;
132  StartAllAction();
133 
134  SwPaM* pCursor = GetCursor();
135  if( pCursor->GetNext() != pCursor ) // Multiple selection?
136  {
138  SwPamRanges aRangeArr( *pCursor );
139  SwPaM aPam( *pCursor->GetPoint() );
140  for( size_t n = 0; n < aRangeArr.Count(); ++n )
141  bRet = bRet && GetDoc()->NoNum( aRangeArr.SetPam( n, aPam ));
143  }
144  else
145  // sw_redlinehide: leave cursor as is, will be split at Point & apply to new node
146  bRet = GetDoc()->NoNum( *pCursor );
147 
148  EndAllAction();
149 }
150 
152 {
153  bool bResult = HasNumber();
154  const SwTextNode * pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
155  if (!bResult && pTextNd && pTextNd->Len()==0 && !pTextNd->GetNumRule()) {
156  SwPamRanges aRangeArr( *GetCursor() );
157  SwPaM aPam( *GetCursor()->GetPoint() );
158  for( size_t n = 0; n < aRangeArr.Count(); ++n )
159  {
160  aRangeArr.SetPam( n, aPam );
161  {
162  sal_uInt32 nStt = aPam.GetPoint()->nNode.GetIndex(),
163  nEnd = aPam.GetMark()->nNode.GetIndex();
164  if( nStt > nEnd )
165  {
166  sal_uInt32 nTmp = nStt; nStt = nEnd; nEnd = nTmp;
167  }
168  for (sal_uInt32 nPos = nStt; nPos<=nEnd; nPos++)
169  {
170  pTextNd = mxDoc->GetNodes()[nPos]->GetTextNode();
171  if (pTextNd)
172  {
173  pTextNd = sw::GetParaPropsNode(*GetLayout(), SwNodeIndex(*pTextNd));
174  }
175  if (pTextNd && pTextNd->Len()!=0)
176  {
177  bResult = pTextNd->HasNumber();
178 
179  // #b6340308# special case: outline numbered, not counted paragraph
180  if ( bResult &&
181  pTextNd->GetNumRule() == GetDoc()->GetOutlineNumRule() &&
182  !pTextNd->IsCountedInList() )
183  {
184  bResult = false;
185  }
186  if (!bResult) {
187  break;
188  }
189  }
190  }
191  }
192  }
193 
194  }
195 
196  return bResult;
197 }
198 
199 // add a new function to determine number on/off status
201 {
202  bool bResult = HasBullet();
203  const SwTextNode * pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
204  if (!bResult && pTextNd && pTextNd->Len()==0 && !pTextNd->GetNumRule()) {
205  SwPamRanges aRangeArr( *GetCursor() );
206  SwPaM aPam( *GetCursor()->GetPoint() );
207  for( size_t n = 0; n < aRangeArr.Count(); ++n )
208  {
209  aRangeArr.SetPam( n, aPam );
210  {
211  sal_uInt32 nStt = aPam.GetPoint()->nNode.GetIndex(),
212  nEnd = aPam.GetMark()->nNode.GetIndex();
213  if( nStt > nEnd )
214  {
215  sal_uInt32 nTmp = nStt; nStt = nEnd; nEnd = nTmp;
216  }
217  for (sal_uInt32 nPos = nStt; nPos<=nEnd; nPos++)
218  {
219  pTextNd = mxDoc->GetNodes()[nPos]->GetTextNode();
220  if (pTextNd)
221  {
222  pTextNd = sw::GetParaPropsNode(*GetLayout(), SwNodeIndex(*pTextNd));
223  }
224  if (pTextNd && pTextNd->Len()!=0)
225  {
226  bResult = pTextNd->HasBullet();
227 
228  if (!bResult) {
229  break;
230  }
231  }
232  }
233  }
234  }
235  }
236 
237  return bResult;
238 }
239 
240 // -> #i29560#
242 {
243  bool bResult = false;
244 
245  const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
246 
247  if (pTextNd)
248  {
249  bResult = pTextNd->HasNumber();
250 
251  // special case: outline numbered, not counted paragraph
252  if ( bResult &&
253  pTextNd->GetNumRule() == GetDoc()->GetOutlineNumRule() &&
254  !pTextNd->IsCountedInList() )
255  {
256  bResult = false;
257  }
258  }
259 
260  return bResult;
261 }
262 
264 {
265  bool bResult = false;
266 
267  const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
268 
269  if (pTextNd)
270  {
271  bResult = pTextNd->HasBullet();
272  }
273 
274  return bResult;
275 }
276 // <- #i29560#
277 
278 // delete, split list
280 {
281  StartAllAction();
282 
283  SwPaM* pCursor = GetCursor();
284  if( pCursor->IsMultiSelection() )
285  {
287  SwPamRanges aRangeArr( *pCursor );
288  SwPaM aPam( *pCursor->GetPoint() );
289  for( size_t n = 0; n < aRangeArr.Count(); ++n )
290  {
291  GetDoc()->DelNumRules(aRangeArr.SetPam( n, aPam ), GetLayout());
292  }
294  }
295  else
296  GetDoc()->DelNumRules(*pCursor, GetLayout());
297 
298  // Call AttrChangeNotify on the UI-side. Should actually be redundant but there was a bug once.
299  CallChgLnk();
300 
301  // Cursor cannot be in front of a label anymore, because numbering/bullet is deleted.
302  SetInFrontOfLabel( false );
303 
305  EndAllAction();
306 }
307 
308 // up- & downgrading
309 void SwEditShell::NumUpDown( bool bDown )
310 {
311  StartAllAction();
312 
313  bool bRet = true;
314  SwPaM* pCursor = GetCursor();
315  if( !pCursor->IsMultiSelection() )
316  bRet = GetDoc()->NumUpDown(*pCursor, bDown, GetLayout());
317  else
318  {
320  SwPamRanges aRangeArr( *pCursor );
321  SwPaM aPam( *pCursor->GetPoint() );
322  for( size_t n = 0; n < aRangeArr.Count(); ++n )
323  bRet = bRet && GetDoc()->NumUpDown(aRangeArr.SetPam( n, aPam ), bDown, GetLayout());
325  }
327 
328  // #i54693# Update marked numbering levels
329  if ( IsInFrontOfLabel() )
331 
332  CallChgLnk();
333 
334  EndAllAction();
335 }
336 
338 {
339  return SwDoc::IsFirstOfNumRuleAtPos(*GetCursor()->GetPoint(), *GetLayout());
340 }
341 
342 // -> #i23725#, #i90078#
343 void SwEditShell::ChangeIndentOfAllListLevels( const sal_Int32 nDiff )
344 {
345  StartAllAction();
346 
347  const SwNumRule *pCurNumRule = GetNumRuleAtCurrCursorPos();
348  if ( pCurNumRule != nullptr )
349  {
350  SwNumRule aRule(*pCurNumRule);
351  const SwNumFormat& aRootNumFormat(aRule.Get(0));
352  if( nDiff > 0 || aRootNumFormat.GetIndentAt() + nDiff > 0) // fdo#42708
353  {
354  // #i90078#
355  aRule.ChangeIndent( nDiff );
356  }
357  // no start of new list
358  SetCurNumRule( aRule, false );
359  }
360 
361  EndAllAction();
362 }
363 
364 // #i90078#
365 void SwEditShell::SetIndent(short nIndent, const SwPosition & rPos)
366 {
367  StartAllAction();
368 
369  SwPosition pos(rPos);
370  SwNumRule *pCurNumRule = SwDoc::GetNumRuleAtPos(pos, GetLayout());
371 
372  if (pCurNumRule)
373  {
374  SwNumRule aRule(*pCurNumRule);
376  {
378  }
379  else
380  {
381  const SwTextNode* pTextNode = pos.nNode.GetNode().GetTextNode();
382  if ( pTextNode != nullptr
383  && pTextNode->GetActualListLevel() >= 0 )
384  {
385  aRule.SetIndent( nIndent, static_cast< sal_uInt16 >( pTextNode->GetActualListLevel() ) );
386  }
387  }
388 
389  // change numbering rule - changed numbering rule is not applied at <aPaM>
390  SwPaM aPaM(pos);
391  GetDoc()->SetNumRule(aPaM, aRule, false, GetLayout(), OUString(), false);
392  }
393 
394  EndAllAction();
395 }
396 
397 bool SwEditShell::MoveParagraph( long nOffset )
398 {
399  StartAllAction();
400 
401  SwPaM *pCursor = GetCursor();
402 
403  bool bRet = GetDoc()->MoveParagraph( *pCursor, nOffset );
404 
406  EndAllAction();
407  return bRet;
408 }
409 
411 {
412  int nLevel = 0;
413 
414  SwPaM* pCursor = GetCursor();
415  const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->nNode);
416  if (pTextNd)
417  nLevel = pTextNd->GetAttrOutlineLevel();
418  return nLevel;
419 }
420 
422 {
423  SwPaM* pCursor = GetCursor();
424  SwPaM aCursor( *pCursor->Start() );
425  aCursor.SetMark();
426  if( pCursor->HasMark() )
427  *aCursor.GetPoint() = *pCursor->End();
428  SwDoc::GotoNextNum(*aCursor.GetPoint(), GetLayout(), false, &rUpper, &rLower);
429 }
430 
431 bool SwEditShell::MoveNumParas( bool bUpperLower, bool bUpperLeft )
432 {
433  StartAllAction();
434 
435  // On all selections?
436  SwPaM* pCursor = GetCursor();
437  SwPaM aCursor( *pCursor->Start() );
438  aCursor.SetMark();
439 
440  if( pCursor->HasMark() )
441  *aCursor.GetPoint() = *pCursor->End();
442 
443  bool bRet = false;
444  sal_uInt8 nUpperLevel, nLowerLevel;
445  if (SwDoc::GotoNextNum( *aCursor.GetPoint(), GetLayout(), false,
446  &nUpperLevel, &nLowerLevel ))
447  {
448  if( bUpperLower )
449  {
450  // on top of the next numbering
451  long nOffset = 0;
452  const SwNode* pNd;
453 
454  if( bUpperLeft ) // move up
455  {
456  SwPosition aPos( *aCursor.GetMark() );
457  if (SwDoc::GotoPrevNum( aPos, GetLayout(), false ))
458  nOffset = aPos.nNode.GetIndex() -
459  aCursor.GetMark()->nNode.GetIndex();
460  else
461  {
462  sal_uLong nStt = aPos.nNode.GetIndex(), nIdx = nStt - 1;
463 
464  if (SwTextNode const*const pStt = aPos.nNode.GetNode().GetTextNode())
465  {
466  std::pair<SwTextNode *, SwTextNode *> nodes(
468  nIdx = nodes.first->GetIndex() - 1;
469  }
470  while( nIdx && (
471  ( pNd = GetDoc()->GetNodes()[ nIdx ])->IsSectionNode() ||
472  ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode())))
473  --nIdx;
474  if( GetDoc()->GetNodes()[ nIdx ]->IsTextNode() )
475  nOffset = nIdx - nStt;
476  }
477  }
478  else // move down
479  {
480  assert(!aCursor.GetNode().IsTextNode()
481  || sw::IsParaPropsNode(*GetLayout(), *aCursor.GetNode().GetTextNode()));
482  const SwNumRule* pOrig = sw::GetParaPropsNode(*GetLayout(), *aCursor.GetNode(false).GetTextNode())->GetNumRule();
483  if( aCursor.GetNode().IsTextNode() &&
484  pOrig == aCursor.GetNode().GetTextNode()->GetNumRule() )
485  {
486  sal_uLong nStt = aCursor.GetPoint()->nNode.GetIndex(), nIdx = nStt+1;
487  if (SwTextNode const*const pStt = aCursor.GetPoint()->nNode.GetNode().GetTextNode())
488  {
489  std::pair<SwTextNode *, SwTextNode *> nodes(
491  nIdx = nodes.second->GetIndex() + 1;
492  }
493 
494  while (nIdx < GetDoc()->GetNodes().Count()-1)
495  {
496  pNd = GetDoc()->GetNodes()[ nIdx ];
497 
498  if (pNd->IsSectionNode() ||
499  (pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode()))
500  {
501  ++nIdx;
502  }
503  else if (pNd->IsTextNode())
504  {
505  SwTextNode const*const pTextNode =
507  if (pOrig == pTextNode->GetNumRule()
508  && pTextNode->GetActualListLevel() > nUpperLevel)
509  {
510  std::pair<SwTextNode *, SwTextNode *> nodes(
511  sw::GetFirstAndLastNode(*GetLayout(), *pTextNode));
512  nIdx = nodes.second->GetIndex() + 1;
513  }
514  else
515  {
516  break;
517  }
518  }
519  // #i57856#
520  else
521  {
522  break;
523  }
524  }
525 
526  if( nStt == nIdx || !GetDoc()->GetNodes()[ nIdx ]->IsTextNode() )
527  nOffset = 1;
528  else
529  nOffset = nIdx - nStt;
530  }
531  else
532  nOffset = 1;
533  }
534 
535  if( nOffset )
536  {
537  aCursor.Move( fnMoveBackward, GoInNode );
538  bRet = GetDoc()->MoveParagraph( aCursor, nOffset );
539  }
540  }
541  else if( (bUpperLeft ? nUpperLevel : nLowerLevel+1) < MAXLEVEL )
542  {
543  aCursor.Move( fnMoveBackward, GoInNode );
544  bRet = GetDoc()->NumUpDown(aCursor, !bUpperLeft, GetLayout());
545  }
546  }
547 
549  EndAllAction();
550  return bRet;
551 }
552 
553 bool SwEditShell::OutlineUpDown( short nOffset )
554 {
555  StartAllAction();
556 
557  bool bRet = true;
558  SwPaM* pCursor = GetCursor();
559  if( !pCursor->IsMultiSelection() )
560  bRet = GetDoc()->OutlineUpDown(*pCursor, nOffset, GetLayout());
561  else
562  {
564  SwPamRanges aRangeArr( *pCursor );
565  SwPaM aPam( *pCursor->GetPoint() );
566  for( size_t n = 0; n < aRangeArr.Count(); ++n )
567  bRet = bRet && GetDoc()->OutlineUpDown(
568  aRangeArr.SetPam(n, aPam), nOffset, GetLayout());
570  }
572  EndAllAction();
573  return bRet;
574 }
575 
577 {
578  StartAllAction();
579  bool bRet = GetDoc()->MoveOutlinePara( *GetCursor(), nOffset );
580  EndAllAction();
581  return bRet;
582 }
583 
584 // Outlines and SubOutline are ReadOnly?
586 {
587  bool bRet = false;
588  const SwNode& rNd = GetCursor()->Start()->nNode.GetNode();
589  if( rNd.IsTextNode() )
590  {
591  const SwOutlineNodes& rOutlNd = GetDoc()->GetNodes().GetOutLineNds();
592  SwNodePtr pNd = const_cast<SwNodePtr>(&rNd);
593  bool bFirst = true;
595  int nLvl(0);
596  if( !rOutlNd.Seek_Entry( pNd, &nPos ) && nPos )
597  --nPos;
598 
599  for( ; nPos < rOutlNd.size(); ++nPos )
600  {
601  SwNodePtr pTmpNd = rOutlNd[ nPos ];
602 
603  if (!sw::IsParaPropsNode(*GetLayout(), *pTmpNd->GetTextNode()))
604  {
605  continue;
606  }
607 
608  int nTmpLvl = pTmpNd->GetTextNode()->GetAttrOutlineLevel();
609 
610  OSL_ENSURE( nTmpLvl >= 0 && nTmpLvl <= MAXLEVEL,
611  "<SwEditShell::IsProtectedOutlinePara()>" );
612 
613  if( bFirst )
614  {
615  nLvl = nTmpLvl;
616  bFirst = false;
617  }
618  else if( nLvl >= nTmpLvl )
619  break;
620 
621  if( pTmpNd->IsProtect() )
622  {
623  bRet = true;
624  break;
625  }
626  }
627  }
628 #if OSL_DEBUG_LEVEL > 0
629  else
630  {
631  OSL_FAIL("Cursor not on an outline node");
632  }
633 #endif
634  return bRet;
635 }
636 
644 static bool lcl_IsOutlineMoveAndCopyable(SwEditShell const& rShell,
645  SwOutlineNodes::size_type const nIdx, bool const bCopy)
646 {
647  const SwNodes& rNds = rShell.GetDoc()->GetNodes();
648  const SwNode* pNd = rNds.GetOutLineNds()[ nIdx ];
649  return pNd->GetIndex() >= rNds.GetEndOfExtras().GetIndex() && // 1) body
650  !pNd->FindTableNode() && // 2) table
651  sw::IsParaPropsNode(*rShell.GetLayout(), *pNd->GetTextNode()) &&
652  ( bCopy || !pNd->IsProtect() ); // 3) write
653 }
654 
656 {
657  return lcl_IsOutlineMoveAndCopyable( *this, nIdx, false );
658 }
659 
661 {
662  return lcl_IsOutlineMoveAndCopyable( *this, nIdx, true );
663 }
664 
666  bool bNumOn,
667  bool bChkStart )
668 {
669  bool bRet = false;
670 
671  if ( !IsMultiSelection()
672  && !HasSelection()
673  && ( !bChkStart || IsSttPara() ) )
674  {
675  StartAllAction();
676  SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *GetCursor()->GetPoint()));
677  bRet = GetDoc()->NumOrNoNum(pos.nNode, !bNumOn);
678  EndAllAction();
679  }
680  return bRet;
681 }
682 
683 bool SwEditShell::IsNoNum( bool bChkStart ) const
684 {
685  // a Backspace in the paragraph without number becomes a Delete
686  bool bResult = false;
687 
688  if ( !IsMultiSelection()
689  && !HasSelection()
690  && ( !bChkStart || IsSttPara() ) )
691  {
692  const SwTextNode* pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode);
693  if ( pTextNd != nullptr )
694  {
695  bResult = !pTextNd->IsCountedInList();
696  }
697  }
698 
699  return bResult;
700 }
701 
703 {
704  // return current level where the point of the cursor is
705  sal_uInt8 nLevel = MAXLEVEL;
706 
707  SwPaM* pCursor = GetCursor();
708  const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->nNode);
709 
710  OSL_ENSURE( pTextNd, "GetNumLevel() without text node" );
711  if ( pTextNd == nullptr )
712  return nLevel;
713 
714  const SwNumRule* pRule = pTextNd->GetNumRule();
715  if ( pRule != nullptr )
716  {
717  const int nListLevelOfTextNode( pTextNd->GetActualListLevel() );
718  if ( nListLevelOfTextNode >= 0 )
719  {
720  nLevel = static_cast<sal_uInt8>( nListLevelOfTextNode );
721  }
722  }
723 
724  return nLevel;
725 }
726 
728 {
729  SwPosition pos(*GetCursor()->GetPoint());
730  return SwDoc::GetNumRuleAtPos( pos, GetLayout() );
731 }
732 
734 {
735  const SwNumRule* pNumRuleAtCurrentSelection = nullptr;
736 
737  bool bDifferentNumRuleFound = false;
738  for(const SwPaM& rCurrentCursor : GetCursor()->GetRingContainer())
739  {
740  const SwNodeIndex aEndNode = rCurrentCursor.End()->nNode;
741 
742  for ( SwNodeIndex aNode = rCurrentCursor.Start()->nNode; aNode <= aEndNode; ++aNode )
743  {
744  SwPosition pos(aNode);
745  const SwNumRule* pNumRule = SwDoc::GetNumRuleAtPos(pos, GetLayout());
746  if ( pNumRule == nullptr )
747  {
748  continue;
749  }
750  else if ( pNumRule != pNumRuleAtCurrentSelection )
751  {
752  if ( pNumRuleAtCurrentSelection == nullptr )
753  {
754  pNumRuleAtCurrentSelection = pNumRule;
755  }
756  else
757  {
758  pNumRuleAtCurrentSelection = nullptr;
759  bDifferentNumRuleFound = true;
760  break;
761  }
762  }
763  }
764  if(bDifferentNumRuleFound)
765  break;
766  }
767 
768  return pNumRuleAtCurrentSelection;
769 }
770 
772  bool bCreateNewList,
773  const OUString& rContinuedListId,
774  const bool bResetIndentAttrs )
775 {
776  StartAllAction();
777 
779 
780  SwPaM* pCursor = GetCursor();
781  if( IsMultiSelection() )
782  {
783  SwPamRanges aRangeArr( *pCursor );
784  SwPaM aPam( *pCursor->GetPoint() );
785  OUString sContinuedListId(rContinuedListId);
786  for( size_t n = 0; n < aRangeArr.Count(); ++n )
787  {
788  aRangeArr.SetPam( n, aPam );
789  OUString sListId = GetDoc()->SetNumRule( aPam, rRule,
790  bCreateNewList, GetLayout(), sContinuedListId,
791  true, bResetIndentAttrs );
792 
793  //tdf#87548 On creating a new list for a multi-selection only
794  //create a single new list for the multi-selection, not one per selection
795  if (bCreateNewList)
796  {
797  sContinuedListId = sListId;
798  bCreateNewList = false;
799  }
800 
801  GetDoc()->SetCounted(aPam, true, GetLayout());
802  }
803  }
804  else
805  {
806  GetDoc()->SetNumRule( *pCursor, rRule,
807  bCreateNewList, GetLayout(), rContinuedListId,
808  true, bResetIndentAttrs );
809  GetDoc()->SetCounted( *pCursor, true, GetLayout() );
810  }
812 
813  EndAllAction();
814 }
815 
817 {
818  return GetDoc()->GetUniqueNumRuleName();
819 }
820 
822 {
823  StartAllAction();
824  GetDoc()->ChgNumRuleFormats( rRule );
825  EndAllAction();
826 }
827 
828 void SwEditShell::ReplaceNumRule( const OUString& rOldRule, const OUString& rNewRule )
829 {
830  StartAllAction();
831  SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *GetCursor()->GetPoint()));
832  GetDoc()->ReplaceNumRule( pos, rOldRule, rNewRule );
833  EndAllAction();
834 }
835 
836 void SwEditShell::SetNumRuleStart( bool bFlag, SwPaM* pPaM )
837 {
838  StartAllAction();
839  SwPaM* pCursor = pPaM ? pPaM : GetCursor();
840  if( pCursor->IsMultiSelection() ) // multiple selection ?
841  {
843  SwPamRanges aRangeArr( *pCursor );
844  SwPaM aPam( *pCursor->GetPoint() );
845  for( size_t n = 0; n < aRangeArr.Count(); ++n )
846  {
847  SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *aRangeArr.SetPam( n, aPam ).GetPoint()));
848  GetDoc()->SetNumRuleStart( pos, bFlag );
849  }
851  }
852  else
853  {
854  SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *GetCursor()->GetPoint()));
855  GetDoc()->SetNumRuleStart(pos, bFlag);
856  }
857 
858  EndAllAction();
859 }
860 
862 {
863  SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
864  const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->nNode);
865  return pTextNd && pTextNd->IsListRestart();
866 }
867 
868 void SwEditShell::SetNodeNumStart( sal_uInt16 nStt )
869 {
870  StartAllAction();
871 
872  SwPaM* pCursor = GetCursor();
873  if( pCursor->IsMultiSelection() ) // multiple selection ?
874  {
876  SwPamRanges aRangeArr( *pCursor );
877  SwPaM aPam( *pCursor->GetPoint() );
878  for( size_t n = 0; n < aRangeArr.Count(); ++n )
879  {
880  SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *aRangeArr.SetPam( n, aPam ).GetPoint()));
881  GetDoc()->SetNodeNumStart( pos, nStt );
882  }
884  }
885  else
886  {
887  SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *pCursor->GetPoint()));
888  GetDoc()->SetNodeNumStart( pos, nStt );
889  }
890 
891  EndAllAction();
892 }
893 
894 sal_uInt16 SwEditShell::GetNodeNumStart( SwPaM* pPaM ) const
895 {
896  SwPaM* pCursor = pPaM ? pPaM : GetCursor();
897  const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->nNode);
898  // correction: check, if list restart value is set at text node and
899  // use new method <SwTextNode::GetAttrListRestartValue()>.
900  // return USHRT_MAX, if no list restart value is found.
901  if ( pTextNd && pTextNd->HasAttrListRestartValue() )
902  {
903  return static_cast<sal_uInt16>(pTextNd->GetAttrListRestartValue());
904  }
905  return USHRT_MAX;
906 }
907 
908 const SwNumRule * SwEditShell::SearchNumRule( const bool bNum,
909  OUString& sListId )
910 {
911  return GetDoc()->SearchNumRule( *(GetCursor()->Start()),
912  false/*bForward*/, bNum, false/*bOutline*/, -1/*nNonEmptyAllowe*/,
913  sListId, GetLayout() );
914 }
915 
916 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsNumRuleStart(SwPaM *pPaM=nullptr) const
Definition: ednumber.cxx:861
const_iterator lower_bound(const Value &x) const
sal_uLong GetIndex() const
Definition: node.hxx:282
bool HasBullet() const
Returns if this text node has a bullet.
Definition: ndtxt.cxx:3113
Marks a position in the document model.
Definition: pam.hxx:35
const SwNodes & GetNodes() const
Definition: viewsh.cxx:2090
bool IsSectionNode() const
Definition: node.hxx:644
bool IsMultiSelection() const
Definition: pam.hxx:272
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:185
void GetCurrentOutlineLevels(sal_uInt8 &rUpper, sal_uInt8 &rLower)
Detect highest and lowest level to check moving of outline levels.
Definition: ednumber.cxx:421
OUString GetUniqueNumRuleName() const
Definition: ednumber.cxx:816
const SwNumRule * GetNumRuleAtCurrCursorPos() const
Definition: ednumber.cxx:727
sal_uLong nEnd
Definition: edimp.hxx:31
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsSttPara() const
Definition: crsrsh.cxx:1083
std::vector< SwNode * >::difference_type difference_type
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:284
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
const SwPosition * GetMark() const
Definition: pam.hxx:209
bool NumOrNoNum(const SwNodeIndex &rIdx, bool bDel=false)
Definition: docnum.cxx:2356
bool MoveOutlinePara(const SwPaM &rPam, SwOutlineNodes::difference_type nOffset)
Outline - move up / move down.
Definition: docnum.cxx:443
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
bool SelectionHasNumber() const
Definition: ednumber.cxx:151
SwNode & GetNode() const
Definition: ndindex.hxx:118
void SetNumRuleStart(const SwPosition &rPos, bool bFlag=true)
Definition: docnum.cxx:1009
OUString GetUniqueNumRuleName(const OUString *pChkStr=nullptr, bool bAutoNum=true) const
Definition: docnum.cxx:2501
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:176
bool NumUpDown(const SwPaM &, bool bDown, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1720
bool HasNumber() const
Returns if this text node has a number.
Definition: ndtxt.cxx:3096
bool IsListRestart() const
Definition: ndtxt.cxx:4120
void EndAllAction()
Definition: edws.cxx:96
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4097
sal_uInt8 GetNumLevel() const
Definition: ednumber.cxx:702
int GetAttrOutlineLevel() const
Returns outline level of this text node.
Definition: ndtxt.cxx:4032
bool HasSelection() const
Does the current cursor create a selection?
Definition: crsrsh.cxx:2408
void ChangeIndentOfAllListLevels(sal_Int32 nDiff)
Remove unused default parameter and .
Definition: ednumber.cxx:343
void SetCurNumRule(const SwNumRule &, const bool bCreateNewList, const OUString &sContinuedListId=OUString(), const bool bResetIndentAttrs=false)
Optional parameter (default value false).
Definition: ednumber.cxx:771
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
bool IsInFrontOfLabel() const
Definition: crsrsh.cxx:1145
void SetNodeNumStart(sal_uInt16 nStt)
Definition: ednumber.cxx:868
static bool lcl_IsOutlineMoveAndCopyable(SwEditShell const &rShell, SwOutlineNodes::size_type const nIdx, bool const bCopy)
Test whether outline may be moved (bCopy == false) or copied (bCopy == true) Verify these conditions:...
Definition: ednumber.cxx:644
sal_uLong nStart
Definition: edimp.hxx:31
rtl::Reference< SwDoc > mxDoc
The document; never 0.
Definition: viewsh.hxx:174
SwIndex nContent
Definition: pam.hxx:38
static SwNumRule * GetNumRuleAtPos(SwPosition &rPos, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:2394
bool IsProtectedOutlinePara() const
Definition: ednumber.cxx:585
bool IsOutlineMovable(SwOutlineNodes::size_type nIdx) const
May an outline be moved or copied? Check whether it's in text body, not in table, and not read-only (...
Definition: ednumber.cxx:655
bool NoNum(const SwPaM &)
Definition: docnum.cxx:1308
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
bool IsFirstOfNumRuleAtCursorPos() const
Definition: ednumber.cxx:337
SwDoc * GetDoc() const
Definition: viewsh.hxx:284
sal_uInt16 GetNodeNumStart(SwPaM *pPaM) const
Definition: ednumber.cxx:894
void DelNumRules()
Delete, split enumeration list.
Definition: ednumber.cxx:279
size_type size() const
SwPaM * GetNext()
Definition: pam.hxx:264
SwPaM & SetPam(size_t nArrPos, SwPaM &rPam)
Definition: ednumber.cxx:99
void ChgNumRuleFormats(const SwNumRule &rRule)
Definition: ednumber.cxx:821
void SetCounted(const SwPaM &, bool bCounted, SwRootFrame const *pLayout)
Definition: docnum.cxx:994
void DelNumRules(const SwPaM &, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1331
void SetNodeNumStart(const SwPosition &rPos, sal_uInt16 nStt)
Definition: docnum.cxx:1031
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
size_t Count() const
Definition: edimp.hxx:49
o3tl::sorted_vector< SwPamRange > maVector
Definition: edimp.hxx:52
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:894
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
SAL_DLLPRIVATE void UpdateMarkedListLevel()
Updates the marked list level according to the cursor.
Definition: crsrsh.cxx:396
Count
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
bool MoveParagraph(long nOffset=1)
Definition: ednumber.cxx:397
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2814
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:426
Marks a node in the document model.
Definition: ndindex.hxx:31
bool IsEndNode() const
Definition: node.hxx:632
const SwOutlineNodes & GetOutLineNds() const
Array of all OutlineNodes.
Definition: ndarr.hxx:234
ring_container GetRingContainer()
const_iterator end() const
bool empty() const
void SetIndent(const short nNewIndent, const sal_uInt16 nListLevel)
set indent of certain list level to given value
Definition: number.cxx:922
const SwNumRule * GetOutlineNumRule() const
Definition: ednumber.cxx:120
bool IsProtect() const
Is node in something that is protected (range, frame, table cells ...
Definition: node.cxx:420
const SwPosition * Start() const
Definition: pam.hxx:212
void SetOutlineNumRule(const SwNumRule &rRule)
Definition: docnum.cxx:121
const SwNumRule * GetNumRuleAtCurrentSelection() const
Returns the numbering rule found at the paragraphs of the current selection, if all paragraphs of the...
Definition: ednumber.cxx:733
bool SelectionHasBullet() const
Definition: ednumber.cxx:200
bool ReplaceNumRule(const SwPosition &rPos, const OUString &rOldRule, const OUString &rNewRule)
Definition: docnum.cxx:1172
SwTextNode * GetParaPropsNode(SwRootFrame const &rLayout, SwNodeIndex const &rNode)
Definition: txtfrm.cxx:329
void ChangeIndent(const sal_Int32 nDiff)
change indent of all list levels by given difference
Definition: number.cxx:883
bool NumOrNoNum(bool bDelete=false, bool bChkStart=true)
Switch on/off of numbering via Delete/Backspace.
Definition: ednumber.cxx:665
const_iterator begin() const
SwPosition GetParaPropsPos(SwRootFrame const &rLayout, SwPosition const &rPos)
Definition: txtfrm.cxx:343
void CallChgLnk()
Definition: crsrsh.cxx:2414
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:83
bool OutlineUpDown(short nOffset=1)
Definition: ednumber.cxx:553
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
bool HasBullet() const
Definition: ednumber.cxx:263
bool IsMultiSelection() const
Definition: crsrsh.hxx:880
void ReplaceNumRule(const OUString &rOldRule, const OUString &rNewRule)
Definition: ednumber.cxx:828
SwNumberTree::tSwNumTreeNumber GetAttrListRestartValue() const
Definition: ndtxt.cxx:4174
unsigned char sal_uInt8
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:259
bool MoveParagraph(SwPaM &, long nOffset, bool bIsOutlMv=false)
Move selected paragraphes (not only numberings) according to offsets.
Definition: docnum.cxx:1836
bool IsCountedInList() const
Definition: ndtxt.cxx:4240
void SetOutlineNumRule(const SwNumRule &)
Definition: ednumber.cxx:113
SwNodes & GetNodes()
Definition: doc.hxx:403
const SwPosition * End() const
Definition: pam.hxx:217
void SetNumRuleStart(bool bFlag, SwPaM *pCursor)
Set (and query if) a numbering with StartFlag starts at current PointPos.
Definition: ednumber.cxx:836
bool IsNoNum(bool bChkStart=true) const
Definition: ednumber.cxx:683
void NumUpDown(bool bDown=true)
Definition: ednumber.cxx:309
static bool GotoNextNum(SwPosition &, SwRootFrame const *pLayout, bool bOverUpper=true, sal_uInt8 *pUpper=nullptr, sal_uInt8 *pLower=nullptr)
Definition: docnum.cxx:1628
void NoNum()
Paragraphs without enumeration but with indents.
Definition: ednumber.cxx:129
bool IsParaPropsNode(SwRootFrame const &rLayout, SwTextNode const &rNode)
Definition: txtfrm.cxx:312
void Insert(const SwNodeIndex &rIdx1, const SwNodeIndex &rIdx2)
Definition: ednumber.cxx:38
static bool IsFirstOfNumRuleAtPos(const SwPosition &rPos, SwRootFrame const &rLayout)
Definition: docnum.cxx:2615
static bool GotoPrevNum(SwPosition &, SwRootFrame const *pLayout, bool bOverUpper=true)
Definition: docnum.cxx:1714
SwPamRanges(const SwPaM &rRing)
Definition: ednumber.cxx:32
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:351
const SwNumRule * SearchNumRule(const bool bNum, OUString &sListId)
Searches for a text node with a numbering rule.
Definition: ednumber.cxx:908
bool IsOutlineCopyable(SwOutlineNodes::size_type nIdx) const
Definition: ednumber.cxx:660
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:457
bool Seek_Entry(SwNode *rP, size_type *pnPos) const
Definition: ndnum.cxx:34
int GetCurrentParaOutlineLevel() const
Get Outline level of current paragraph.
Definition: ednumber.cxx:410
bool MoveOutlinePara(SwOutlineNodes::difference_type nOffset)
Definition: ednumber.cxx:576
std::pair< const_iterator, bool > insert(Value &&x)
void SetIndent(short nIndent, const SwPosition &rPos)
Definition: ednumber.cxx:365
std::vector< SwNode * >::size_type size_type
const SwNumRule * SearchNumRule(const SwPosition &rPos, const bool bForward, const bool bNum, const bool bOutline, int nNonEmptyAllowed, OUString &sListId, SwRootFrame const *pLayout, const bool bInvestigateStartNode=false)
Searches for a text node with a numbering rule.
Definition: docnum.cxx:1634
OUString SetNumRule(const SwPaM &, const SwNumRule &, bool bCreateNewList, SwRootFrame const *pLayout=nullptr, const OUString &sContinuedListId=OUString(), bool bSetItem=true, const bool bResetIndentAttrs=false)
Accept changes of outline styles for OutlineRule.
Definition: docnum.cxx:861
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:162
bool HasAttrListRestartValue() const
Definition: ndtxt.cxx:4169
void StartAllAction()
For all views of this document.
Definition: edws.cxx:85
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2072
sal_Int32 nPos
bool HasNumber() const
Definition: ednumber.cxx:241
void SetIndentOfFirstListLevelAndChangeOthers(const short nNewIndent)
set indent of first list level to given value and change other list level's indents accordingly ...
Definition: number.cxx:951
bool IsTextNode() const
Definition: node.hxx:636
SwNumRule * GetNumRule(SwTextFormatColl &rTextFormatColl)
determines the list style, which directly set at the given paragraph style
Definition: fmtcol.cxx:75
bool OutlineUpDown(const SwPaM &rPam, short nOffset, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:195
std::vector< Value >::const_iterator const_iterator
std::pair< SwTextNode *, SwTextNode * > GetFirstAndLastNode(SwRootFrame const &rLayout, SwNodeIndex const &rPos)
Definition: txtfrm.cxx:356
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
size_type erase(const Value &x)
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1013
bool SetInFrontOfLabel(bool bNew)
Definition: crsrsh.cxx:1150
void ChgNumRuleFormats(const SwNumRule &rRule)
Definition: docnum.cxx:1093
bool MoveNumParas(bool bUpperLower, bool bUpperLeft)
Definition: ednumber.cxx:431
Base class of the Writer document model elements.
Definition: node.hxx:79