Add Marathi autocorrect
[LibreOffice.git] / sw / source / core / edit / ednumber.cxx
blob56f2779b20e82d07922de938788a6f6570890bea
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <editsh.hxx>
21 #include <edimp.hxx>
22 #include <doc.hxx>
23 #include <IDocumentUndoRedo.hxx>
24 #include <IDocumentState.hxx>
25 #include <ndtxt.hxx>
26 #include <txtfrm.hxx>
27 #include <swundo.hxx>
28 #include <numrule.hxx>
29 #include <osl/diagnose.h>
31 SwPamRanges::SwPamRanges( const SwPaM& rRing )
33 for(SwPaM& rTmp : const_cast<SwPaM*>(&rRing)->GetRingContainer())
34 Insert( rTmp.GetMark()->GetNode(), rTmp.GetPoint()->GetNode() );
37 void SwPamRanges::Insert( const SwNode& rIdx1, const SwNode& rIdx2 )
39 SwPamRange aRg( rIdx1.GetIndex(), rIdx2.GetIndex() );
40 if( aRg.nEnd < aRg.nStart )
41 { aRg.nStart = aRg.nEnd; aRg.nEnd = rIdx1.GetIndex(); }
43 o3tl::sorted_vector<SwPamRange>::const_iterator it = maVector.lower_bound(aRg); //search Insert Position
44 size_t nPos = it - maVector.begin();
45 if (!maVector.empty() && (it != maVector.end()) && (*it) == aRg)
47 // is the one in the Array smaller?
48 SwPamRange const& rTmp = maVector[nPos];
49 if( rTmp.nEnd < aRg.nEnd )
51 aRg.nEnd = rTmp.nEnd;
52 maVector.erase(maVector.begin() + nPos); // combine
54 else
55 return; // done, because by precondition everything is combined
58 bool bEnd;
59 do {
60 bEnd = true;
62 // combine with predecessor?
63 if( nPos > 0 )
65 SwPamRange const& rTmp = maVector[nPos-1];
66 if( rTmp.nEnd == aRg.nStart
67 || rTmp.nEnd+1 == aRg.nStart )
69 aRg.nStart = rTmp.nStart;
70 bEnd = false;
71 maVector.erase( maVector.begin() + --nPos ); // combine
73 // range contained in rTmp?
74 else if( rTmp.nStart <= aRg.nStart && aRg.nEnd <= rTmp.nEnd )
75 return;
77 // combine with successor?
78 if( nPos < maVector.size() )
80 SwPamRange const& rTmp = maVector[nPos];
81 if( rTmp.nStart == aRg.nEnd ||
82 rTmp.nStart == aRg.nEnd+1 )
84 aRg.nEnd = rTmp.nEnd;
85 bEnd = false;
86 maVector.erase( maVector.begin() + nPos ); // combine
89 // range contained in rTmp?
90 else if( rTmp.nStart <= aRg.nStart && aRg.nEnd <= rTmp.nEnd )
91 return;
93 } while( !bEnd );
95 maVector.insert( aRg );
98 SwPaM& SwPamRanges::SetPam( size_t nArrPos, SwPaM& rPam )
100 assert( nArrPos < Count() );
101 const SwPamRange& rTmp = maVector[ nArrPos ];
102 rPam.GetPoint()->Assign(rTmp.nStart);
103 rPam.SetMark();
104 rPam.GetPoint()->Assign(rTmp.nEnd);
105 return rPam;
108 // Rule book for outline numbering
110 void SwEditShell::SetOutlineNumRule(const SwNumRule& rRule)
112 StartAllAction(); // bracketing for updating!
113 GetDoc()->SetOutlineNumRule(rRule);
114 EndAllAction();
117 const SwNumRule* SwEditShell::GetOutlineNumRule() const
119 return GetDoc()->GetOutlineNumRule();
122 // Set if there is no numbering yet, else update.
123 // Works with old and new rules. Update only differences.
125 // paragraphs without numbering, with indentations
126 void SwEditShell::NoNum()
128 StartAllAction();
130 SwPaM* pCursor = GetCursor();
131 if( pCursor->GetNext() != pCursor ) // Multiple selection?
133 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
134 SwPamRanges aRangeArr( *pCursor );
135 SwPaM aPam( *pCursor->GetPoint() );
136 for( size_t n = 0; n < aRangeArr.Count(); ++n )
137 GetDoc()->NoNum( aRangeArr.SetPam( n, aPam ));
138 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
140 else
141 // sw_redlinehide: leave cursor as is, will be split at Point & apply to new node
142 GetDoc()->NoNum( *pCursor );
144 EndAllAction();
147 // The entire selection is numbered (ignoring unnumbered empty lines)
148 bool SwEditShell::SelectionHasNumber() const
150 bool bResult = false;
151 for (SwPaM& rPaM : GetCursor()->GetRingContainer())
153 SwNodeOffset nStt = rPaM.Start()->GetNodeIndex();
154 SwNodeOffset nEnd = rPaM.End()->GetNodeIndex();
155 for (SwNodeOffset nPos = nStt; nPos<=nEnd; nPos++)
157 SwTextNode* pTextNd = mxDoc->GetNodes()[nPos]->GetTextNode();
158 if (pTextNd)
160 pTextNd = sw::GetParaPropsNode(*GetLayout(), *pTextNd);
162 if (pTextNd && (!bResult || pTextNd->Len()!=0))
164 bResult = pTextNd->HasNumber();
166 // #b6340308# special case: outline numbered, not counted paragraph
167 if (bResult &&
168 pTextNd->GetNumRule() == GetDoc()->GetOutlineNumRule() &&
169 !pTextNd->IsCountedInList())
171 bResult = false;
173 if (!bResult && pTextNd->Len())
174 break;
179 return bResult;
182 // add a new function to determine number on/off status
183 bool SwEditShell::SelectionHasBullet() const
185 bool bResult = false;
186 for (SwPaM& rPaM : GetCursor()->GetRingContainer())
188 SwNodeOffset nStt = rPaM.Start()->GetNodeIndex();
189 SwNodeOffset nEnd = rPaM.End()->GetNodeIndex();
190 for (SwNodeOffset nPos = nStt; nPos<=nEnd; nPos++)
192 SwTextNode* pTextNd = mxDoc->GetNodes()[nPos]->GetTextNode();
193 if (pTextNd)
195 pTextNd = sw::GetParaPropsNode(*GetLayout(), *pTextNd);
197 if (pTextNd && (!bResult || pTextNd->Len()!=0))
199 bResult = pTextNd->HasBullet();
201 if (!bResult && pTextNd->Len())
202 break;
207 return bResult;
210 // -> #i29560#
211 bool SwEditShell::HasNumber() const
213 bool bResult = false;
215 const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
217 if (pTextNd)
219 bResult = pTextNd->HasNumber();
221 // special case: outline numbered, not counted paragraph
222 if ( bResult &&
223 pTextNd->GetNumRule() == GetDoc()->GetOutlineNumRule() &&
224 !pTextNd->IsCountedInList() )
226 bResult = false;
230 return bResult;
233 bool SwEditShell::HasBullet() const
235 bool bResult = false;
237 const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
239 if (pTextNd)
241 bResult = pTextNd->HasBullet();
244 return bResult;
246 // <- #i29560#
248 // delete, split list
249 void SwEditShell::DelNumRules()
251 StartAllAction();
253 SwPaM* pCursor = GetCursor();
254 if( pCursor->IsMultiSelection() )
256 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
257 for (SwPaM& rPaM : pCursor->GetRingContainer())
259 GetDoc()->DelNumRules(rPaM, GetLayout());
261 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
263 else
264 GetDoc()->DelNumRules(*pCursor, GetLayout());
266 // Call AttrChangeNotify on the UI-side. Should actually be redundant but there was a bug once.
267 CallChgLnk();
269 // Cursor cannot be in front of a label anymore, because numbering/bullet is deleted.
270 SetInFrontOfLabel( false );
272 GetDoc()->getIDocumentState().SetModified();
273 EndAllAction();
276 // up- & downgrading
277 void SwEditShell::NumUpDown( bool bDown )
279 StartAllAction();
281 SwPaM* pCursor = GetCursor();
282 if( !pCursor->IsMultiSelection() )
283 GetDoc()->NumUpDown(*pCursor, bDown, GetLayout());
284 else
286 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
287 SwPamRanges aRangeArr( *pCursor );
288 SwPaM aPam( *pCursor->GetPoint() );
289 for( size_t n = 0; n < aRangeArr.Count(); ++n )
290 GetDoc()->NumUpDown(aRangeArr.SetPam( n, aPam ), bDown, GetLayout());
291 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
293 GetDoc()->getIDocumentState().SetModified();
295 // #i54693# Update marked numbering levels
296 if ( IsInFrontOfLabel() )
297 UpdateMarkedListLevel();
299 CallChgLnk();
301 EndAllAction();
304 bool SwEditShell::IsFirstOfNumRuleAtCursorPos() const
306 return SwDoc::IsFirstOfNumRuleAtPos(*GetCursor()->GetPoint(), *GetLayout());
309 // -> #i23725#, #i90078#
310 void SwEditShell::ChangeIndentOfAllListLevels( const sal_Int32 nDiff )
312 StartAllAction();
314 const SwNumRule *pCurNumRule = GetNumRuleAtCurrCursorPos();
315 if ( pCurNumRule != nullptr )
317 SwNumRule aRule(*pCurNumRule);
318 const SwNumFormat& aRootNumFormat(aRule.Get(0));
319 if( nDiff > 0 || aRootNumFormat.GetIndentAt() + nDiff > 0) // fdo#42708
321 // #i90078#
322 aRule.ChangeIndent( nDiff );
324 // no start of new list
325 SetCurNumRule( aRule, false );
328 EndAllAction();
331 // #i90078#
332 void SwEditShell::SetIndent(short nIndent, const SwPosition & rPos)
334 StartAllAction();
336 SwPosition pos(rPos);
337 SwNumRule *pCurNumRule = SwDoc::GetNumRuleAtPos(pos, GetLayout());
339 if (pCurNumRule)
341 SwNumRule aRule(*pCurNumRule);
342 if ( !IsMultiSelection() && IsFirstOfNumRuleAtCursorPos() )
344 aRule.SetIndentOfFirstListLevelAndChangeOthers( nIndent );
346 else
348 const SwTextNode* pTextNode = pos.GetNode().GetTextNode();
349 if ( pTextNode != nullptr
350 && pTextNode->GetActualListLevel() >= 0 )
352 aRule.SetIndent( nIndent, static_cast< sal_uInt16 >( pTextNode->GetActualListLevel() ) );
356 // change numbering rule - changed numbering rule is not applied at <aPaM>
357 SwPaM aPaM(pos);
358 GetDoc()->SetNumRule(aPaM, aRule, SwDoc::SetNumRuleMode::DontSetItem, GetLayout(), OUString());
361 EndAllAction();
364 bool SwEditShell::MoveParagraph( SwNodeOffset nOffset )
366 StartAllAction();
368 SwPaM *pCursor = GetCursor();
370 bool bRet = GetDoc()->MoveParagraph( *pCursor, nOffset );
372 GetDoc()->getIDocumentState().SetModified();
373 EndAllAction();
374 return bRet;
377 int SwEditShell::GetCurrentParaOutlineLevel( ) const
379 int nLevel = 0;
381 SwPaM* pCursor = GetCursor();
382 const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
383 if (pTextNd)
384 nLevel = pTextNd->GetAttrOutlineLevel();
385 return nLevel;
388 void SwEditShell::GetCurrentOutlineLevels( sal_uInt8& rUpper, sal_uInt8& rLower )
390 SwPaM* pCursor = GetCursor();
391 SwPaM aCursor( *pCursor->Start() );
392 aCursor.SetMark();
393 if( pCursor->HasMark() )
394 *aCursor.GetPoint() = *pCursor->End();
395 SwDoc::GotoNextNum(*aCursor.GetPoint(), GetLayout(), false, &rUpper, &rLower);
398 bool SwEditShell::MoveNumParas( bool bUpperLower, bool bUpperLeft )
400 StartAllAction();
402 // On all selections?
403 SwPaM* pCursor = GetCursor();
404 SwPaM aCursor( *pCursor->Start() );
405 aCursor.SetMark();
407 if( pCursor->HasMark() )
408 *aCursor.GetPoint() = *pCursor->End();
410 bool bRet = false;
411 sal_uInt8 nUpperLevel, nLowerLevel;
412 if (SwDoc::GotoNextNum( *aCursor.GetPoint(), GetLayout(), false,
413 &nUpperLevel, &nLowerLevel ))
415 if( bUpperLower )
417 // on top of the next numbering
418 SwNodeOffset nOffset(0);
419 const SwNode* pNd;
421 if( bUpperLeft ) // move up
423 SwPosition aPos( *aCursor.GetMark() );
424 if (SwDoc::GotoPrevNum( aPos, GetLayout(), false ))
425 nOffset = aPos.GetNodeIndex() -
426 aCursor.GetMark()->GetNodeIndex();
427 else
429 SwNodeOffset nStt = aPos.GetNodeIndex(), nIdx = nStt - 1;
431 if (SwTextNode const*const pStart = aPos.GetNode().GetTextNode())
433 std::pair<SwTextNode *, SwTextNode *> nodes(
434 sw::GetFirstAndLastNode(*GetLayout(), *pStart));
435 nIdx = nodes.first->GetIndex() - 1;
437 while( nIdx && (
438 ( pNd = GetDoc()->GetNodes()[ nIdx ])->IsSectionNode() ||
439 ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode())))
440 --nIdx;
441 if( GetDoc()->GetNodes()[ nIdx ]->IsTextNode() )
442 nOffset = nIdx - nStt;
445 else // move down
447 assert(!aCursor.GetPointNode().IsTextNode()
448 || sw::IsParaPropsNode(*GetLayout(), *aCursor.GetPointNode().GetTextNode()));
449 const SwNumRule* pOrig = sw::GetParaPropsNode(*GetLayout(), *aCursor.GetMarkNode().GetTextNode())->GetNumRule();
450 if( aCursor.GetPointNode().IsTextNode() &&
451 pOrig == aCursor.GetPointNode().GetTextNode()->GetNumRule() )
453 SwNodeOffset nStt = aCursor.GetPoint()->GetNodeIndex(), nIdx = nStt+1;
454 if (SwTextNode const*const pStart = aCursor.GetPoint()->GetNode().GetTextNode())
456 std::pair<SwTextNode *, SwTextNode *> nodes(
457 sw::GetFirstAndLastNode(*GetLayout(), *pStart));
458 nIdx = nodes.second->GetIndex() + 1;
461 while (nIdx < GetDoc()->GetNodes().Count()-1)
463 pNd = GetDoc()->GetNodes()[ nIdx ];
465 if (pNd->IsSectionNode() ||
466 (pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode()))
468 ++nIdx;
470 else if (pNd->IsTextNode())
472 SwTextNode const*const pTextNode =
473 sw::GetParaPropsNode(*GetLayout(), *pNd);
474 if (pOrig == pTextNode->GetNumRule()
475 && pTextNode->GetActualListLevel() > nUpperLevel)
477 std::pair<SwTextNode *, SwTextNode *> nodes(
478 sw::GetFirstAndLastNode(*GetLayout(), *pTextNode));
479 nIdx = nodes.second->GetIndex() + 1;
481 else
483 break;
486 // #i57856#
487 else
489 break;
493 if( nStt == nIdx || !GetDoc()->GetNodes()[ nIdx ]->IsTextNode() )
494 nOffset = SwNodeOffset(1);
495 else
496 nOffset = nIdx - nStt;
498 else
499 nOffset = SwNodeOffset(1);
502 if( nOffset )
504 aCursor.Move( fnMoveBackward, GoInNode );
505 bRet = GetDoc()->MoveParagraph( aCursor, nOffset );
508 else if( (bUpperLeft ? nUpperLevel : nLowerLevel+1) < MAXLEVEL )
510 aCursor.Move( fnMoveBackward, GoInNode );
511 bRet = GetDoc()->NumUpDown(aCursor, !bUpperLeft, GetLayout());
515 GetDoc()->getIDocumentState().SetModified();
516 EndAllAction();
517 return bRet;
520 bool SwEditShell::OutlineUpDown( short nOffset )
522 StartAllAction();
524 bool bRet = true;
525 SwPaM* pCursor = GetCursor();
526 if( !pCursor->IsMultiSelection() )
527 bRet = GetDoc()->OutlineUpDown(*pCursor, nOffset, GetLayout());
528 else
530 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
531 SwPamRanges aRangeArr( *pCursor );
532 SwPaM aPam( *pCursor->GetPoint() );
533 for( size_t n = 0; n < aRangeArr.Count(); ++n )
534 bRet = bRet && GetDoc()->OutlineUpDown(
535 aRangeArr.SetPam(n, aPam), nOffset, GetLayout());
536 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
538 GetDoc()->getIDocumentState().SetModified();
539 EndAllAction();
540 return bRet;
543 bool SwEditShell::MoveOutlinePara( SwOutlineNodes::difference_type nOffset,
544 SwOutlineNodesInline* pOutlineNodesInline )
546 StartAllAction();
547 bool bRet = GetDoc()->MoveOutlinePara( *GetCursor(), nOffset, pOutlineNodesInline );
548 EndAllAction();
549 return bRet;
552 // Outlines and SubOutline are ReadOnly?
553 bool SwEditShell::IsProtectedOutlinePara() const
555 bool bRet = false;
556 const SwNode& rNd = GetCursor()->Start()->GetNode();
557 if( rNd.IsTextNode() )
559 const SwOutlineNodes& rOutlNd = GetDoc()->GetNodes().GetOutLineNds();
560 bool bFirst = true;
561 SwOutlineNodes::size_type nPos;
562 int nLvl(0);
563 if (!rOutlNd.Seek_Entry(&rNd, &nPos) && nPos)
564 --nPos;
566 for( ; nPos < rOutlNd.size(); ++nPos )
568 SwNode* pTmpNd = rOutlNd[ nPos ];
570 if (!sw::IsParaPropsNode(*GetLayout(), *pTmpNd->GetTextNode()))
572 continue;
575 int nTmpLvl = pTmpNd->GetTextNode()->GetAttrOutlineLevel();
577 OSL_ENSURE( nTmpLvl >= 0 && nTmpLvl <= MAXLEVEL,
578 "<SwEditShell::IsProtectedOutlinePara()>" );
580 if( bFirst )
582 nLvl = nTmpLvl;
583 bFirst = false;
585 else if( nLvl >= nTmpLvl )
586 break;
588 if( pTmpNd->IsProtect() )
590 bRet = true;
591 break;
595 #if OSL_DEBUG_LEVEL > 0
596 else
598 OSL_FAIL("Cursor not on an outline node");
600 #endif
601 return bRet;
604 /** Test whether outline may be moved (bCopy == false)
605 * or copied (bCopy == true)
606 * Verify these conditions:
607 * 1) outline must be within main body (and not in redline)
608 * 2) outline must not be within table
609 * 3) if bCopy is set, outline must not be write protected
611 static bool lcl_IsOutlineMoveAndCopyable(SwEditShell const& rShell,
612 SwOutlineNodes::size_type const nIdx, bool const bCopy)
614 const SwNodes& rNds = rShell.GetDoc()->GetNodes();
615 const SwNode* pNd = rNds.GetOutLineNds()[ nIdx ];
616 return pNd->GetIndex() >= rNds.GetEndOfExtras().GetIndex() && // 1) body
617 !pNd->FindTableNode() && // 2) table
618 sw::IsParaPropsNode(*rShell.GetLayout(), *pNd->GetTextNode()) &&
619 ( bCopy || !pNd->IsProtect() ); // 3) write
622 bool SwEditShell::IsOutlineMovable( SwOutlineNodes::size_type nIdx ) const
624 return lcl_IsOutlineMoveAndCopyable( *this, nIdx, false );
627 bool SwEditShell::IsOutlineCopyable( SwOutlineNodes::size_type nIdx ) const
629 return lcl_IsOutlineMoveAndCopyable( *this, nIdx, true );
632 bool SwEditShell::NumOrNoNum( bool bNumOn )
634 bool bRet = false;
636 if ( !IsMultiSelection()
637 && !HasSelection()
638 && IsSttPara() )
640 StartAllAction();
641 SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *GetCursor()->GetPoint()));
642 bRet = GetDoc()->NumOrNoNum(pos.GetNode(), !bNumOn);
643 EndAllAction();
645 return bRet;
648 bool SwEditShell::IsNoNum() const
650 // a Backspace in the paragraph without number becomes a Delete
651 bool bResult = false;
653 if ( !IsMultiSelection()
654 && !HasSelection()
655 && IsSttPara() )
657 const SwTextNode* pTextNd = sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
658 if ( pTextNd != nullptr )
660 bResult = !pTextNd->IsCountedInList();
664 return bResult;
667 sal_uInt8 SwEditShell::GetNumLevel() const
669 // return current level where the point of the cursor is
670 sal_uInt8 nLevel = MAXLEVEL;
672 SwPaM* pCursor = GetCursor();
673 const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
675 OSL_ENSURE( pTextNd, "GetNumLevel() without text node" );
676 if ( pTextNd == nullptr )
677 return nLevel;
679 const SwNumRule* pRule = pTextNd->GetNumRule();
680 if ( pRule != nullptr )
682 const int nListLevelOfTextNode( pTextNd->GetActualListLevel() );
683 if ( nListLevelOfTextNode >= 0 )
685 nLevel = static_cast<sal_uInt8>( nListLevelOfTextNode );
689 return nLevel;
692 const SwNumRule* SwEditShell::GetNumRuleAtCurrCursorPos() const
694 SwPosition pos(*GetCursor()->GetPoint());
695 return SwDoc::GetNumRuleAtPos( pos, GetLayout() );
698 const SwNumRule* SwEditShell::GetNumRuleAtCurrentSelection() const
700 const SwNumRule* pNumRuleAtCurrentSelection = nullptr;
702 bool bDifferentNumRuleFound = false;
703 for(const SwPaM& rCurrentCursor : GetCursor()->GetRingContainer())
705 const SwNode& rEndNode(rCurrentCursor.End()->GetNode());
707 for ( SwNodeIndex aNode(rCurrentCursor.Start()->GetNode()); aNode <= rEndNode; ++aNode )
709 SwPosition pos(aNode);
710 const SwNumRule* pNumRule = SwDoc::GetNumRuleAtPos(pos, GetLayout());
711 if ( pNumRule == nullptr )
713 continue;
715 else if ( pNumRule != pNumRuleAtCurrentSelection )
717 if ( pNumRuleAtCurrentSelection == nullptr )
719 pNumRuleAtCurrentSelection = pNumRule;
721 else
723 pNumRuleAtCurrentSelection = nullptr;
724 bDifferentNumRuleFound = true;
725 break;
729 if(bDifferentNumRuleFound)
730 break;
733 return pNumRuleAtCurrentSelection;
736 void SwEditShell::SetCurNumRule( const SwNumRule& rRule,
737 bool bCreateNewList,
738 const OUString& rContinuedListId,
739 const bool bResetIndentAttrs )
741 StartAllAction();
743 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSATTR, nullptr );
745 SwPaM* pCursor = GetCursor();
746 if( IsMultiSelection() )
748 OUString sContinuedListId(rContinuedListId);
749 for (SwPaM& rPaM : pCursor->GetRingContainer())
751 OUString sListId = GetDoc()->SetNumRule(rPaM, rRule,
752 (bCreateNewList ? SwDoc::SetNumRuleMode::CreateNewList : SwDoc::SetNumRuleMode::Default)
753 | (bResetIndentAttrs ? SwDoc::SetNumRuleMode::ResetIndentAttrs : SwDoc::SetNumRuleMode::Default),
754 GetLayout(), sContinuedListId);
756 //tdf#87548 On creating a new list for a multi-selection only
757 //create a single new list for the multi-selection, not one per selection
758 if (bCreateNewList)
760 sContinuedListId = sListId;
761 bCreateNewList = false;
764 GetDoc()->SetCounted(rPaM, true, GetLayout());
767 else
769 GetDoc()->SetNumRule( *pCursor, rRule,
770 (bCreateNewList ? SwDoc::SetNumRuleMode::CreateNewList : SwDoc::SetNumRuleMode::Default)
771 | (bResetIndentAttrs ? SwDoc::SetNumRuleMode::ResetIndentAttrs : SwDoc::SetNumRuleMode::Default),
772 GetLayout(), rContinuedListId);
773 GetDoc()->SetCounted( *pCursor, true, GetLayout() );
775 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSATTR, nullptr );
777 EndAllAction();
780 OUString SwEditShell::GetUniqueNumRuleName() const
782 return GetDoc()->GetUniqueNumRuleName();
785 void SwEditShell::ChgNumRuleFormats( const SwNumRule& rRule )
787 StartAllAction();
788 GetDoc()->ChgNumRuleFormats( rRule );
789 EndAllAction();
792 void SwEditShell::ReplaceNumRule( const OUString& rOldRule, const OUString& rNewRule )
794 StartAllAction();
795 SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *GetCursor()->GetPoint()));
796 GetDoc()->ReplaceNumRule( pos, rOldRule, rNewRule );
797 EndAllAction();
800 void SwEditShell::SetNumRuleStart( bool bFlag, SwPaM* pPaM )
802 StartAllAction();
803 SwPaM* pCursor = pPaM ? pPaM : GetCursor();
804 if( pCursor->IsMultiSelection() ) // multiple selection ?
806 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
807 SwPamRanges aRangeArr( *pCursor );
808 SwPaM aPam( *pCursor->GetPoint() );
809 for( size_t n = 0; n < aRangeArr.Count(); ++n )
811 SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *aRangeArr.SetPam( n, aPam ).GetPoint()));
812 GetDoc()->SetNumRuleStart( pos, bFlag );
814 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
816 else
818 SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *GetCursor()->GetPoint()));
819 GetDoc()->SetNumRuleStart(pos, bFlag);
822 EndAllAction();
825 bool SwEditShell::IsNumRuleStart( SwPaM* pPaM ) const
827 SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
828 const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
829 return pTextNd && pTextNd->IsListRestart();
832 void SwEditShell::SetNodeNumStart( sal_uInt16 nStt )
834 StartAllAction();
836 SwPaM* pCursor = GetCursor();
837 if( pCursor->IsMultiSelection() ) // multiple selection ?
839 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );
840 SwPamRanges aRangeArr( *pCursor );
841 SwPaM aPam( *pCursor->GetPoint() );
842 for( size_t n = 0; n < aRangeArr.Count(); ++n )
844 SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *aRangeArr.SetPam( n, aPam ).GetPoint()));
845 GetDoc()->SetNodeNumStart( pos, nStt );
847 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
849 else
851 SwPosition const pos(sw::GetParaPropsPos(*GetLayout(), *pCursor->GetPoint()));
852 GetDoc()->SetNodeNumStart( pos, nStt );
855 EndAllAction();
858 sal_uInt16 SwEditShell::GetNodeNumStart( SwPaM* pPaM ) const
860 SwPaM* pCursor = pPaM ? pPaM : GetCursor();
861 const SwTextNode *const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
862 // correction: check, if list restart value is set at text node and
863 // use new method <SwTextNode::GetAttrListRestartValue()>.
864 // return USHRT_MAX, if no list restart value is found.
865 if ( pTextNd && pTextNd->HasAttrListRestartValue() )
867 return o3tl::narrowing<sal_uInt16>(pTextNd->GetAttrListRestartValue());
869 return USHRT_MAX;
872 const SwNumRule * SwEditShell::SearchNumRule( const bool bNum,
873 OUString& sListId )
875 return GetDoc()->SearchNumRule( *(GetCursor()->Start()),
876 false/*bForward*/, bNum, false/*bOutline*/, -1/*nNonEmptyAllowe*/,
877 sListId, GetLayout() );
880 std::set<OUString> SwEditShell::GetUsedBullets()
882 return GetDoc()->GetUsedBullets();
885 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */