LibreOffice Module sw (master)  1
DocumentRedlineManager.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 */
20 #include <frmfmt.hxx>
21 #include <rootfrm.hxx>
22 #include <txtfrm.hxx>
23 #include <doc.hxx>
24 #include <docsh.hxx>
25 #include <fmtfld.hxx>
26 #include <frmtool.hxx>
27 #include <IDocumentUndoRedo.hxx>
30 #include <IDocumentState.hxx>
31 #include <redline.hxx>
32 #include <UndoRedline.hxx>
33 #include <docary.hxx>
34 #include <ndtxt.hxx>
35 #include <unocrsr.hxx>
36 #include <ftnidx.hxx>
37 #include <authfld.hxx>
38 #include <strings.hrc>
39 #include <swmodule.hxx>
40 #include <osl/diagnose.h>
41 
42 using namespace com::sun::star;
43 
44 #ifdef DBG_UTIL
45 
46  #define ERROR_PREFIX "redline table corrupted: "
47 
48  namespace
49  {
50  // helper function for lcl_CheckRedline
51  // 1. make sure that pPos->nContent points into pPos->nNode
52  // 2. check that position is valid and doesn't point after text
53  void lcl_CheckPosition( const SwPosition* pPos )
54  {
55  assert(dynamic_cast<SwIndexReg*>(&pPos->nNode.GetNode())
56  == pPos->nContent.GetIdxReg());
57 
58  SwTextNode* pTextNode = pPos->nNode.GetNode().GetTextNode();
59  if( pTextNode == nullptr )
60  {
61  assert(pPos->nContent == 0);
62  }
63  else
64  {
65  assert(pPos->nContent >= 0 && pPos->nContent <= pTextNode->Len());
66  }
67  }
68 
69  void lcl_CheckPam( const SwPaM* pPam )
70  {
71  assert(pPam);
72  lcl_CheckPosition( pPam->GetPoint() );
73  lcl_CheckPosition( pPam->GetMark() );
74  }
75 
76  // check validity of the redline table. Checks redline bounds, and make
77  // sure the redlines are sorted and non-overlapping.
78  void lcl_CheckRedline( IDocumentRedlineAccess& redlineAccess )
79  {
80  const SwRedlineTable& rTable = redlineAccess.GetRedlineTable();
81 
82  // verify valid redline positions
83  for(SwRangeRedline* i : rTable)
84  lcl_CheckPam( i );
85 
86  for(SwRangeRedline* j : rTable)
87  {
88  // check for empty redlines
89  // note: these can destroy sorting in SwTextNode::Update()
90  // if there's another one without mark on the same pos.
91  OSL_ENSURE( ( *(j->GetPoint()) != *(j->GetMark()) ) ||
92  ( j->GetContentIdx() != nullptr ),
93  ERROR_PREFIX "empty redline" );
94  }
95 
96  // verify proper redline sorting
97  for( size_t n = 1; n < rTable.size(); ++n )
98  {
99  const SwRangeRedline* pPrev = rTable[ n-1 ];
100  const SwRangeRedline* pCurrent = rTable[ n ];
101 
102  // check redline sorting
103  SAL_WARN_IF( *pPrev->Start() > *pCurrent->Start(), "sw",
104  ERROR_PREFIX "not sorted correctly" );
105 
106  // check for overlapping redlines
107  SAL_WARN_IF( *pPrev->End() > *pCurrent->Start(), "sw",
108  ERROR_PREFIX "overlapping redlines" );
109  }
110 
111  assert(std::is_sorted(rTable.begin(), rTable.end(), CompareSwRedlineTable()));
112  }
113  }
114 
115  #define CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
116 
117 #else
118 
119  #define CHECK_REDLINE( pDoc )
120 
121 #endif
122 
123 namespace sw {
124 
126 {
127  auto const pAuthType(static_cast<SwAuthorityFieldType*>(rIDFA.GetFieldType(
128  SwFieldIds::TableOfAuthorities, OUString(), false)));
129  if (pAuthType) // created on demand...
130  {
131  pAuthType->DelSequenceArray();
132  }
133  rIDFA.GetFieldType(SwFieldIds::RefPageGet, OUString(), false)->UpdateFields();
135  rIDFA.UpdateExpFields(nullptr, false);
136  rIDFA.UpdateRefFields();
137 }
138 
139 void UpdateFramesForAddDeleteRedline(SwDoc & rDoc, SwPaM const& rPam)
140 {
141  if (rDoc.IsClipBoard())
142  {
143  return;
144  }
145  // no need to call UpdateFootnoteNums for FTNNUM_PAGE:
146  // the AppendFootnote/RemoveFootnote will do it by itself!
147  rDoc.GetFootnoteIdxs().UpdateFootnote(rPam.Start()->nNode);
148  SwPosition currentStart(*rPam.Start());
149  SwTextNode * pStartNode(rPam.Start()->nNode.GetNode().GetTextNode());
150  while (!pStartNode)
151  {
152  // note: branch only taken for redlines, not fieldmarks
153  SwStartNode *const pTableOrSectionNode(
154  currentStart.nNode.GetNode().IsTableNode()
155  ? static_cast<SwStartNode*>(currentStart.nNode.GetNode().GetTableNode())
156  : static_cast<SwStartNode*>(currentStart.nNode.GetNode().GetSectionNode()));
157  assert(pTableOrSectionNode); // known pathology
158  for (sal_uLong j = pTableOrSectionNode->GetIndex(); j <= pTableOrSectionNode->EndOfSectionIndex(); ++j)
159  {
160  pTableOrSectionNode->GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
161  }
162  for (SwRootFrame const*const pLayout : rDoc.GetAllLayouts())
163  {
164  if (pLayout->HasMergedParas())
165  {
166  if (pTableOrSectionNode->IsTableNode())
167  {
168  static_cast<SwTableNode*>(pTableOrSectionNode)->DelFrames(pLayout);
169  }
170  else
171  {
172  static_cast<SwSectionNode*>(pTableOrSectionNode)->DelFrames(pLayout);
173  }
174  }
175  }
176  currentStart.nNode = pTableOrSectionNode->EndOfSectionIndex() + 1;
177  currentStart.nContent.Assign(currentStart.nNode.GetNode().GetContentNode(), 0);
178  pStartNode = currentStart.nNode.GetNode().GetTextNode();
179  }
180  if (currentStart < *rPam.End())
181  {
182  SwTextNode * pNode(pStartNode);
183  do
184  {
185  std::vector<SwTextFrame*> frames;
187  for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
188  {
189  if (pFrame->getRootFrame()->HasMergedParas())
190  {
191  frames.push_back(pFrame);
192  }
193  }
194  if (frames.empty())
195  {
196  auto const& layouts(rDoc.GetAllLayouts());
197  assert(std::none_of(layouts.begin(), layouts.end(),
198  [](SwRootFrame const*const pLayout) { return pLayout->IsHideRedlines(); }));
199  (void) layouts;
200  break;
201  }
203  SwTextNode * pLast(pNode);
204  for (SwTextFrame * pFrame : frames)
205  {
206  SwTextNode & rFirstNode(pFrame->GetMergedPara()
207  ? *pFrame->GetMergedPara()->pFirstNode
208  : *pNode);
209  assert(pNode == pStartNode
210  ? rFirstNode.GetIndex() <= pNode->GetIndex()
211  : &rFirstNode == pNode);
212  // clear old one first to avoid DelFrames confusing updates & asserts...
213  pFrame->SetMergedPara(nullptr);
214  pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
215  *pFrame, rFirstNode, eMode));
216  eMode = sw::FrameMode::New; // Existing is not idempotent!
217  // the first node of the new redline is not necessarily the first
218  // node of the merged frame, there could be another redline nearby
219  sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, *pNode, nullptr);
220  // if redline is split across table and table cell is empty, there's no redline in the cell and so no merged para
221  if (pFrame->GetMergedPara())
222  {
223  pLast = const_cast<SwTextNode*>(pFrame->GetMergedPara()->pLastNode);
224  }
225  }
226  SwNodeIndex tmp(*pLast);
227  // skip over hidden sections!
228  pNode = static_cast<SwTextNode*>(pLast->GetNodes().GoNextSection(&tmp, /*bSkipHidden=*/true, /*bSkipProtect=*/false));
229  }
230  while (pNode && pNode->GetIndex() <= rPam.End()->nNode.GetIndex());
231  }
232  // fields last - SwGetRefField::UpdateField requires up-to-date frames
233  UpdateFieldsForRedline(rDoc.getIDocumentFieldsAccess()); // after footnotes
234 
235  // update SwPostItMgr / notes in the margin
236  rDoc.GetDocShell()->Broadcast(
238 }
239 
241 {
242  if (rDoc.IsClipBoard())
243  {
244  return;
245  }
246  bool isAppendObjsCalled(false);
247  rDoc.GetFootnoteIdxs().UpdateFootnote(rPam.Start()->nNode);
248  SwPosition currentStart(*rPam.Start());
249  SwTextNode * pStartNode(rPam.Start()->nNode.GetNode().GetTextNode());
250  while (!pStartNode)
251  {
252  // note: branch only taken for redlines, not fieldmarks
253  SwStartNode const*const pTableOrSectionNode(
254  currentStart.nNode.GetNode().IsTableNode()
255  ? static_cast<SwStartNode*>(currentStart.nNode.GetNode().GetTableNode())
256  : static_cast<SwStartNode*>(currentStart.nNode.GetNode().GetSectionNode()));
257  assert(pTableOrSectionNode); // known pathology
258  for (sal_uLong j = pTableOrSectionNode->GetIndex(); j <= pTableOrSectionNode->EndOfSectionIndex(); ++j)
259  {
260  pTableOrSectionNode->GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::None);
261  }
263  {
264  // note: this will also create frames for all currently hidden flys
265  // because it calls AppendAllObjs
266  SwNodeIndex const end(*pTableOrSectionNode->EndOfSectionNode());
267  ::MakeFrames(&rDoc, currentStart.nNode, end);
268  isAppendObjsCalled = true;
269  }
270  currentStart.nNode = pTableOrSectionNode->EndOfSectionIndex() + 1;
271  currentStart.nContent.Assign(currentStart.nNode.GetNode().GetContentNode(), 0);
272  pStartNode = currentStart.nNode.GetNode().GetTextNode();
273  }
274  if (currentStart < *rPam.End())
275  {
276  SwTextNode * pNode(pStartNode);
277  do
278  {
279  std::vector<SwTextFrame*> frames;
281  for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
282  {
283  if (pFrame->getRootFrame()->HasMergedParas())
284  {
285  frames.push_back(pFrame);
286  }
287  }
288  if (frames.empty())
289  {
290  auto const& layouts(rDoc.GetAllLayouts());
291  assert(std::none_of(layouts.begin(), layouts.end(),
292  [](SwRootFrame const*const pLayout) { return pLayout->IsHideRedlines(); }));
293  (void) layouts;
294  break;
295  }
296 
297  // first, call CheckParaRedlineMerge on the first paragraph,
298  // to init flag on new merge range (if any) + 1st node post the merge
300  SwTextNode * pLast(pNode);
301  for (SwTextFrame * pFrame : frames)
302  {
303  if (auto const pMergedPara = pFrame->GetMergedPara())
304  {
305  pLast = const_cast<SwTextNode*>(pMergedPara->pLastNode);
306  assert(pNode == pStartNode
307  ? pMergedPara->pFirstNode->GetIndex() <= pNode->GetIndex()
308  : pMergedPara->pFirstNode == pNode);
309  // clear old one first to avoid DelFrames confusing updates & asserts...
310  SwTextNode & rFirstNode(*pMergedPara->pFirstNode);
311  pFrame->SetMergedPara(nullptr);
312  pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
313  *pFrame, rFirstNode, eMode));
314  eMode = sw::FrameMode::New; // Existing is not idempotent!
315  }
316  }
317  if (pLast != pNode)
318  {
319  // now start node until end of merge + 1 has proper flags; MakeFrames
320  // should pick up from the next node in need of frames by checking flags
321  SwNodeIndex const start(*pNode, +1);
322  SwNodeIndex const end(*pLast, +1); // end is exclusive
323  // note: this will also create frames for all currently hidden flys
324  // both on first and non-first nodes because it calls AppendAllObjs
325  ::MakeFrames(&rDoc, start, end);
326  isAppendObjsCalled = true;
327  // re-use this to move flys that are now on the wrong frame, with end
328  // of redline as "second" node; the nodes between start and end should
329  // be complete with MakeFrames already
330  sw::MoveMergedFlysAndFootnotes(frames, *pNode, *pLast, false);
331  }
332  SwNodeIndex tmp(*pLast);
333  // skip over hidden sections!
334  pNode = static_cast<SwTextNode*>(pLast->GetNodes().GoNextSection(&tmp, /*bSkipHidden=*/true, /*bSkipProtect=*/false));
335  }
336  while (pNode && pNode->GetIndex() <= rPam.End()->nNode.GetIndex());
337  }
338 
339  if (!isAppendObjsCalled)
340  { // recreate flys in the one node the hard way...
341  for (auto const& pLayout : rDoc.GetAllLayouts())
342  {
343  if (pLayout->HasMergedParas())
344  {
345  AppendAllObjs(rDoc.GetSpzFrameFormats(), pLayout);
346  break;
347  }
348  }
349  }
350  // fields last - SwGetRefField::UpdateField requires up-to-date frames
351  UpdateFieldsForRedline(rDoc.getIDocumentFieldsAccess()); // after footnotes
352 
353  // update SwPostItMgr / notes in the margin
354  rDoc.GetDocShell()->Broadcast(
356 }
357 
358 } // namespace sw
359 
360 namespace
361 {
362  bool IsPrevPos( const SwPosition & rPos1, const SwPosition & rPos2 )
363  {
364  const SwContentNode* pCNd;
365  if( 0 != rPos2.nContent.GetIndex() )
366  return false;
367  if( rPos2.nNode.GetIndex() - 1 != rPos1.nNode.GetIndex() )
368  return false;
369  pCNd = rPos1.nNode.GetNode().GetContentNode();
370  return pCNd && rPos1.nContent.GetIndex() == pCNd->Len();
371  }
372 
373  // copy style or return with SwRedlineExtra_FormatColl with reject data of the upcoming copy
374  SwRedlineExtraData_FormatColl* lcl_CopyStyle( const SwPosition & rFrom, const SwPosition & rTo, bool bCopy = true )
375  {
376  SwTextNode* pToNode = rTo.nNode.GetNode().GetTextNode();
377  SwTextNode* pFromNode = rFrom.nNode.GetNode().GetTextNode();
378  if (pToNode != nullptr && pFromNode != nullptr && pToNode != pFromNode)
379  {
380  const SwPaM aPam(*pToNode);
381  SwDoc& rDoc = aPam.GetDoc();
382  // using Undo, copy paragraph style
383  SwTextFormatColl* pFromColl = pFromNode->GetTextColl();
384  SwTextFormatColl* pToColl = pToNode->GetTextColl();
385  if (bCopy && pFromColl != pToColl)
386  rDoc.SetTextFormatColl(aPam, pFromColl);
387 
388  // using Undo, remove direct paragraph formatting of the "To" paragraph,
389  // and apply here direct paragraph formatting of the "From" paragraph
390  SfxItemSet aTmp(
391  rDoc.GetAttrPool(),
392  svl::Items<
393  RES_PARATR_BEGIN, RES_PARATR_END - 3, // skip RSID and GRABBAG
394  RES_PARATR_LIST_BEGIN, RES_UL_SPACE, // skip PAGEDESC and BREAK
395  RES_CNTNT, RES_FRMATR_END - 1>{});
396  SfxItemSet aTmp2(aTmp);
397 
398  pToNode->GetParaAttr(aTmp, 0, 0);
399  pFromNode->GetParaAttr(aTmp2, 0, 0);
400 
401  bool bSameSet = aTmp == aTmp2;
402 
403  if (!bSameSet)
404  {
405  for( sal_uInt16 nItem = 0; nItem < aTmp.TotalCount(); ++nItem)
406  {
407  sal_uInt16 nWhich = aTmp.GetWhichByPos(nItem);
408  if( SfxItemState::SET == aTmp.GetItemState( nWhich, false ) &&
409  SfxItemState::SET != aTmp2.GetItemState( nWhich, false ) )
410  aTmp2.Put( aTmp.GetPool()->GetDefaultItem(nWhich), nWhich );
411  }
412  }
413 
414  if (bCopy && !bSameSet)
415  rDoc.getIDocumentContentOperations().InsertItemSet(aPam, aTmp2);
416  else if (!bCopy && (!bSameSet || pFromColl != pToColl))
417  return new SwRedlineExtraData_FormatColl( pFromColl->GetName(), USHRT_MAX, &aTmp2 );
418  }
419  return nullptr;
420  }
421 
422  bool lcl_AcceptRedline( SwRedlineTable& rArr, SwRedlineTable::size_type& rPos,
423  bool bCallDelete,
424  const SwPosition* pSttRng = nullptr,
425  const SwPosition* pEndRng = nullptr )
426  {
427  bool bRet = true;
428  SwRangeRedline* pRedl = rArr[ rPos ];
429  SwPosition *pRStt = nullptr, *pREnd = nullptr;
431  if( pSttRng && pEndRng )
432  {
433  pRStt = pRedl->Start();
434  pREnd = pRedl->End();
435  eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
436  }
437 
439 
440  switch( pRedl->GetType() )
441  {
442  case RedlineType::Insert:
443  case RedlineType::Format:
444  {
445  bool bCheck = false, bReplace = false;
446  switch( eCmp )
447  {
449  if( *pSttRng == *pRStt )
450  pRedl->SetStart( *pEndRng, pRStt );
451  else
452  {
453  if( *pEndRng != *pREnd )
454  {
455  // split up
456  SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
457  pNew->SetStart( *pEndRng );
458  rArr.Insert( pNew ); ++rPos;
459  }
460  pRedl->SetEnd( *pSttRng, pREnd );
461  bCheck = true;
462  }
463  break;
464 
466  pRedl->SetStart( *pEndRng, pRStt );
467  bReplace = true;
468  break;
469 
471  pRedl->SetEnd( *pSttRng, pREnd );
472  bCheck = true;
473  break;
474 
477  rArr.DeleteAndDestroy( rPos-- );
478  break;
479 
480  default:
481  bRet = false;
482  }
483 
484  if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
485  {
486  // re-insert
487  rArr.Remove( pRedl );
488  rArr.Insert( pRedl );
489  }
490  }
491  break;
492  case RedlineType::Delete:
493  {
494  SwDoc& rDoc = pRedl->GetDoc();
495  const SwPosition *pDelStt = nullptr, *pDelEnd = nullptr;
496  bool bDelRedl = false;
497  switch( eCmp )
498  {
500  if( bCallDelete )
501  {
502  pDelStt = pSttRng;
503  pDelEnd = pEndRng;
504  }
505  break;
506 
508  if( bCallDelete )
509  {
510  pDelStt = pRStt;
511  pDelEnd = pEndRng;
512  }
513  break;
515  if( bCallDelete )
516  {
517  pDelStt = pREnd;
518  pDelEnd = pSttRng;
519  }
520  break;
521 
524  {
525  rArr.Remove( rPos-- );
526  bDelRedl = true;
527  if( bCallDelete )
528  {
529  pDelStt = pRedl->Start();
530  pDelEnd = pRedl->End();
531  }
532  }
533  break;
534  default:
535  bRet = false;
536  }
537 
538  if( pDelStt && pDelEnd )
539  {
540  SwPaM aPam( *pDelStt, *pDelEnd );
541  SwContentNode* pCSttNd = pDelStt->nNode.GetNode().GetContentNode();
542  SwContentNode* pCEndNd = pDelEnd->nNode.GetNode().GetContentNode();
543  pRStt = pRedl->Start();
544  pREnd = pRedl->End();
545 
546  // keep style of the empty paragraph after deletion of wholly paragraphs
547  if( pCSttNd && pCEndNd && pRStt && pREnd && pRStt->nContent == 0 )
548  lcl_CopyStyle(*pREnd, *pRStt);
549 
550  if( bDelRedl )
551  delete pRedl;
552 
555 
556  if( pCSttNd && pCEndNd )
558  else if (pCSttNd && !pCEndNd)
559  {
560  aPam.GetBound().nContent.Assign( nullptr, 0 );
561  aPam.GetBound( false ).nContent.Assign( nullptr, 0 );
563  }
564  else
565  {
567  }
569  }
570  else if( bDelRedl )
571  delete pRedl;
572  }
573  break;
574 
575  case RedlineType::FmtColl:
576  rArr.DeleteAndDestroy( rPos-- );
577  break;
578 
579  case RedlineType::ParagraphFormat:
580  rArr.DeleteAndDestroy( rPos-- );
581  break;
582 
583  default:
584  bRet = false;
585  }
586  return bRet;
587  }
588 
589  bool lcl_RejectRedline( SwRedlineTable& rArr, SwRedlineTable::size_type& rPos,
590  bool bCallDelete,
591  const SwPosition* pSttRng = nullptr,
592  const SwPosition* pEndRng = nullptr )
593  {
594  bool bRet = true;
595  SwRangeRedline* pRedl = rArr[ rPos ];
596  SwDoc& rDoc = pRedl->GetDoc();
597  SwPosition *pRStt = nullptr, *pREnd = nullptr;
599  if( pSttRng && pEndRng )
600  {
601  pRStt = pRedl->Start();
602  pREnd = pRedl->End();
603  eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
604  }
605 
607 
608  switch( pRedl->GetType() )
609  {
610  case RedlineType::Insert:
611  {
612  const SwPosition *pDelStt = nullptr, *pDelEnd = nullptr;
613  bool bDelRedl = false;
614  switch( eCmp )
615  {
617  if( bCallDelete )
618  {
619  pDelStt = pSttRng;
620  pDelEnd = pEndRng;
621  }
622  break;
623 
625  if( bCallDelete )
626  {
627  pDelStt = pRStt;
628  pDelEnd = pEndRng;
629  }
630  break;
632  if( bCallDelete )
633  {
634  pDelStt = pREnd;
635  pDelEnd = pSttRng;
636  }
637  break;
640  {
641  // delete the range again
642  rArr.Remove( rPos-- );
643  bDelRedl = true;
644  if( bCallDelete )
645  {
646  pDelStt = pRedl->Start();
647  pDelEnd = pRedl->End();
648  }
649  }
650  break;
651 
652  default:
653  bRet = false;
654  }
655  if( pDelStt && pDelEnd )
656  {
657  SwPaM aPam( *pDelStt, *pDelEnd );
658 
659  SwContentNode* pCSttNd = pDelStt->nNode.GetNode().GetContentNode();
660  SwContentNode* pCEndNd = pDelEnd->nNode.GetNode().GetContentNode();
661 
662  if( bDelRedl )
663  delete pRedl;
664 
667 
668  if( pCSttNd && pCEndNd )
670  else if (pCSttNd && !pCEndNd)
671  {
672  aPam.GetBound().nContent.Assign( nullptr, 0 );
673  aPam.GetBound( false ).nContent.Assign( nullptr, 0 );
674  if (aPam.End()->nNode.GetNode().IsStartNode())
675  { // end node will be deleted too! see nNodeDiff+1
676  --aPam.End()->nNode;
677  }
678  assert(!aPam.End()->nNode.GetNode().IsStartNode());
680  }
681  else
682  {
684  }
686  }
687  else if( bDelRedl )
688  delete pRedl;
689  }
690  break;
691  case RedlineType::Delete:
692  {
693  SwRangeRedline* pNew = nullptr;
694  bool bCheck = false, bReplace = false;
695  SwPaM const updatePaM(pSttRng ? *pSttRng : *pRedl->Start(),
696  pEndRng ? *pEndRng : *pRedl->End());
697 
698  if( pRedl->GetExtraData() )
699  pRedl->GetExtraData()->Reject( *pRedl );
700 
701  switch( eCmp )
702  {
704  {
705  if( 1 < pRedl->GetStackCount() )
706  {
707  pNew = new SwRangeRedline( *pRedl );
708  pNew->PopData();
709  }
710  if( *pSttRng == *pRStt )
711  {
712  pRedl->SetStart( *pEndRng, pRStt );
713  bReplace = true;
714  if( pNew )
715  pNew->SetEnd( *pEndRng );
716  }
717  else
718  {
719  if( *pEndRng != *pREnd )
720  {
721  // split up
722  SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
723  pCpy->SetStart( *pEndRng );
724  rArr.Insert( pCpy ); ++rPos;
725  if( pNew )
726  pNew->SetEnd( *pEndRng );
727  }
728 
729  pRedl->SetEnd( *pSttRng, pREnd );
730  bCheck = true;
731  if( pNew )
732  pNew->SetStart( *pSttRng );
733  }
734  }
735  break;
736 
738  if( 1 < pRedl->GetStackCount() )
739  {
740  pNew = new SwRangeRedline( *pRedl );
741  pNew->PopData();
742  }
743  pRedl->SetStart( *pEndRng, pRStt );
744  bReplace = true;
745  if( pNew )
746  pNew->SetEnd( *pEndRng );
747  break;
748 
750  if( 1 < pRedl->GetStackCount() )
751  {
752  pNew = new SwRangeRedline( *pRedl );
753  pNew->PopData();
754  }
755  pRedl->SetEnd( *pSttRng, pREnd );
756  bCheck = true;
757  if( pNew )
758  pNew->SetStart( *pSttRng );
759  break;
760 
763  if( !pRedl->PopData() )
764  // deleting the RedlineObject is enough
765  rArr.DeleteAndDestroy( rPos-- );
766  break;
767 
768  default:
769  bRet = false;
770  }
771 
772  if( pNew )
773  {
774  rArr.Insert( pNew ); ++rPos;
775  }
776 
777  if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
778  {
779  // re-insert
780  rArr.Remove( pRedl );
781  rArr.Insert( pRedl );
782  }
783 
785  }
786  break;
787 
788  case RedlineType::Format:
789  case RedlineType::FmtColl:
790  case RedlineType::ParagraphFormat:
791  {
792  // tdf#52391 instead of hidden acception at the requested
793  // rejection, remove direct text formatting to get the potential
794  // original state of the text (FIXME if the original text
795  // has already contained direct text formatting: unfortunately
796  // ODF 1.2 doesn't support rejection of format-only changes)
797  if ( pRedl->GetType() == RedlineType::Format )
798  {
799  SwPaM aPam( *(pRedl->Start()), *(pRedl->End()) );
800  rDoc.ResetAttrs(aPam);
801  }
802  else if ( pRedl->GetType() == RedlineType::ParagraphFormat )
803  {
804  // handle paragraph formatting changes
805  // (range is only a full paragraph or a part of it)
806  const SwPosition* pStt = pRedl->Start();
807  SwTextNode* pTNd = pStt->nNode.GetNode().GetTextNode();
808  if( pTNd )
809  {
810  // expand range to the whole paragraph
811  // and reset only the paragraph attributes
812  SwPaM aPam( *pTNd, pTNd->GetText().getLength() );
813  o3tl::sorted_vector<sal_uInt16> aResetAttrsArray;
814 
815  constexpr std::pair<sal_uInt16, sal_uInt16> aResetableSetRange[] = {
816  { RES_PARATR_BEGIN, RES_PARATR_END - 1 },
818  };
819 
820  for (const auto& [nBegin, nEnd] : aResetableSetRange)
821  {
822  for (sal_uInt16 i = nBegin; i <= nEnd; ++i)
823  aResetAttrsArray.insert( i );
824  }
825 
826  rDoc.ResetAttrs(aPam, false, aResetAttrsArray);
827 
828  // remove numbering
829  if ( pTNd->GetNumRule() )
830  rDoc.DelNumRules(aPam);
831  }
832  }
833 
834  if( pRedl->GetExtraData() )
835  pRedl->GetExtraData()->Reject( *pRedl );
836 
837  rArr.DeleteAndDestroy( rPos-- );
838  }
839  break;
840 
841  default:
842  bRet = false;
843  }
844  return bRet;
845  }
846 
847  typedef bool (*Fn_AcceptReject)( SwRedlineTable& rArr, SwRedlineTable::size_type& rPos,
848  bool bCallDelete,
849  const SwPosition* pSttRng,
850  const SwPosition* pEndRng);
851 
852 
853  int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
854  SwRedlineTable& rArr, bool bCallDelete,
855  const SwPaM& rPam)
856  {
858  int nCount = 0;
859 
860  const SwPosition* pStt = rPam.Start(),
861  * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
862  : rPam.GetPoint();
863  const SwRangeRedline* pFnd = rArr.FindAtPosition( *pStt, n );
864  if( pFnd && // Is new a part of it?
865  ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
866  {
867  // Only revoke the partial selection
868  if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
869  nCount++;
870  ++n;
871  }
872 
873  // tdf#119824 first we will accept only overlapping paragraph format changes
874  // in the first loop to avoid potential content changes during Redo
875  bool bHasParagraphFormatChange = false;
876  for( int m = 0 ; m < 2 && !bHasParagraphFormatChange; ++m )
877  {
878  for(SwRedlineTable::size_type o = n ; o < rArr.size(); ++o )
879  {
880  SwRangeRedline* pTmp = rArr[ o ];
881  if( pTmp->HasMark() && pTmp->IsVisible() )
882  {
883  if( *pTmp->End() <= *pEnd )
884  {
885  if( (m > 0 || RedlineType::ParagraphFormat == pTmp->GetType()) &&
886  (*fn_AcceptReject)( rArr, o, bCallDelete, nullptr, nullptr ))
887  {
888  bHasParagraphFormatChange = true;
889  nCount++;
890  }
891  }
892  else
893  {
894  if( *pTmp->Start() < *pEnd )
895  {
896  // Only revoke the partial selection
897  if( (m > 0 || RedlineType::ParagraphFormat == pTmp->GetType()) &&
898  (*fn_AcceptReject)( rArr, o, bCallDelete, pStt, pEnd ))
899  {
900  bHasParagraphFormatChange = true;
901  nCount++;
902  }
903  }
904  break;
905  }
906  }
907  }
908  }
909  return nCount;
910  }
911 
912  void lcl_AdjustRedlineRange( SwPaM& rPam )
913  {
914  // The Selection is only in the ContentSection. If there are Redlines
915  // to Non-ContentNodes before or after that, then the Selections
916  // expand to them.
917  SwPosition* pStt = rPam.Start(),
918  * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
919  : rPam.GetPoint();
920  SwDoc& rDoc = rPam.GetDoc();
921  if( !pStt->nContent.GetIndex() &&
922  !rDoc.GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsContentNode() )
923  {
924  const SwRangeRedline* pRedl = rDoc.getIDocumentRedlineAccess().GetRedline( *pStt, nullptr );
925  if( pRedl )
926  {
927  const SwPosition* pRStt = pRedl->Start();
928  if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() ==
929  pStt->nNode.GetIndex() - 1 )
930  *pStt = *pRStt;
931  }
932  }
933  if( pEnd->nNode.GetNode().IsContentNode() &&
934  !rDoc.GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsContentNode() &&
935  pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetContentNode()->Len() )
936  {
937  const SwRangeRedline* pRedl = rDoc.getIDocumentRedlineAccess().GetRedline( *pEnd, nullptr );
938  if( pRedl )
939  {
940  const SwPosition* pREnd = pRedl->End();
941  if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() ==
942  pEnd->nNode.GetIndex() + 1 )
943  *pEnd = *pREnd;
944  }
945  }
946  }
947 
950  class TemporaryRedlineUpdater
951  {
952  private:
953  SwRangeRedline & m_rRedline;
954  std::shared_ptr<SwUnoCursor> m_pCursor;
955  public:
956  TemporaryRedlineUpdater(SwDoc & rDoc, SwRangeRedline & rRedline)
957  : m_rRedline(rRedline)
958  , m_pCursor(rDoc.CreateUnoCursor(*rRedline.GetPoint(), false))
959  {
960  if (m_rRedline.HasMark())
961  {
962  m_pCursor->SetMark();
963  *m_pCursor->GetMark() = *m_rRedline.GetMark();
964  *m_rRedline.GetMark() = SwPosition(rDoc.GetNodes().GetEndOfContent());
965  }
966  *m_rRedline.GetPoint() = SwPosition(rDoc.GetNodes().GetEndOfContent());
967  }
968  ~TemporaryRedlineUpdater()
969  {
970  static_cast<SwPaM&>(m_rRedline) = *m_pCursor;
971  }
972  };
973 }
974 
975 namespace sw
976 {
977 
978 DocumentRedlineManager::DocumentRedlineManager(SwDoc& i_rSwdoc)
979  : m_rDoc(i_rSwdoc)
980  , meRedlineFlags(RedlineFlags::ShowInsert | RedlineFlags::ShowDelete)
981  , mpRedlineTable(new SwRedlineTable)
982  , mpExtraRedlineTable(new SwExtraRedlineTable)
983  , mbIsRedlineMove(false)
984  , mnAutoFormatRedlnCommentNo(0)
985 {
986 }
987 
989 {
990  return meRedlineFlags;
991 }
992 
994 {
995  if( meRedlineFlags == eMode )
996  return;
997 
999  || !(RedlineFlags::ShowMask & eMode) )
1000  {
1001  bool bSaveInXMLImportFlag = m_rDoc.IsInXMLImport();
1002  m_rDoc.SetInXMLImport( false );
1003  // and then hide/display everything
1004  void (SwRangeRedline::*pFnc)(sal_uInt16, size_t, bool); // Allow compiler warn if use of
1005  // uninitialized ptr is possible
1006 
1007  RedlineFlags eShowMode = RedlineFlags::ShowMask & eMode;
1009  pFnc = &SwRangeRedline::Show;
1010  else if (eShowMode == RedlineFlags::ShowInsert)
1011  pFnc = &SwRangeRedline::Hide;
1012  else if (eShowMode == RedlineFlags::ShowDelete)
1014  else
1015  {
1016  pFnc = &SwRangeRedline::Hide;
1017  eMode |= RedlineFlags::ShowInsert;
1018  }
1019 
1021  CHECK_REDLINE( *this )
1022 
1023  o3tl::sorted_vector<SwRootFrame *> hiddenLayouts;
1025  {
1026  // sw_redlinehide: the problem here is that MoveFromSection
1027  // creates the frames wrongly (non-merged), because its own
1028  // SwRangeRedline has wrong positions until after the nodes
1029  // are all moved, so fix things up by force by re-creating
1030  // all merged frames from scratch.
1032  for (SwRootFrame *const pLayout : layouts)
1033  {
1034  if (pLayout->IsHideRedlines())
1035  {
1036  pLayout->SetHideRedlines(false);
1037  hiddenLayouts.insert(pLayout);
1038  }
1039  }
1040  }
1041 
1042  for (sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop)
1043  for (size_t i = 0; i < mpRedlineTable->size(); ++i)
1044  {
1045  SwRangeRedline *const pRedline((*mpRedlineTable)[i]);
1046  (pRedline->*pFnc)(nLoop, i, false);
1047  while (mpRedlineTable->size() <= i
1048  || (*mpRedlineTable)[i] != pRedline)
1049  { // ensure current position
1050  --i; // a previous redline may have been deleted
1051  }
1052  }
1053 
1054  //SwRangeRedline::MoveFromSection routinely changes
1055  //the keys that mpRedlineTable is sorted by
1056  mpRedlineTable->Resort();
1057 
1059  CHECK_REDLINE( *this )
1060 
1061  for (SwRootFrame *const pLayout : hiddenLayouts)
1062  {
1063  pLayout->SetHideRedlines(true);
1064  }
1065 
1066  m_rDoc.SetInXMLImport( bSaveInXMLImportFlag );
1067  }
1068  meRedlineFlags = eMode;
1070 
1071  // #TODO - add 'SwExtraRedlineTable' also ?
1072 }
1073 
1075 {
1077 }
1078 
1080 {
1081  return bool(RedlineFlags::Ignore & meRedlineFlags);
1082 }
1083 
1085 {
1086  meRedlineFlags = eMode;
1087 }
1088 
1090 {
1091  return *mpRedlineTable;
1092 }
1093 
1095 {
1096  return *mpRedlineTable;
1097 }
1098 
1100 {
1101  return *mpExtraRedlineTable;
1102 }
1103 
1105 {
1106  return *mpExtraRedlineTable;
1107 }
1108 
1110 {
1111  return mpExtraRedlineTable != nullptr;
1112 }
1113 
1115 {
1116  SwPosition aPos(rNode);
1117  SwNode & rEndOfRedlines = m_rDoc.GetNodes().GetEndOfRedlines();
1118  SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
1119  SwPosition(rEndOfRedlines));
1120 
1121  return aPam.ContainsPosition(aPos);
1122 }
1123 
1125 {
1126  return mbIsRedlineMove;
1127 }
1128 
1130 {
1131  mbIsRedlineMove = bFlag;
1132 }
1133 
1134 /*
1135 Text means Text not "polluted" by Redlines.
1136 
1137 Behaviour of Insert-Redline:
1138  - in the Text - insert Redline Object
1139  - in InsertRedline (own) - ignore, existing is extended
1140  - in InsertRedline (others) - split up InsertRedline and
1141  insert Redline Object
1142  - in DeleteRedline - split up DeleteRedline or
1143  move at the end/beginning
1144 
1145 Behaviour of Delete-Redline:
1146  - in the Text - insert Redline Object
1147  - in DeleteRedline (own/others) - ignore
1148  - in InsertRedline (own) - ignore, but delete character
1149  - in InsertRedline (others) - split up InsertRedline and
1150  insert Redline Object
1151  - Text and own Insert overlap - delete Text in the own Insert,
1152  extend in the other Text
1153  (up to the Insert!)
1154  - Text and other Insert overlap - insert Redline Object, the
1155  other Insert is overlapped by
1156  the Delete
1157 */
1159 DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCallDelete)
1160 {
1161  bool bMerged = false;
1162  CHECK_REDLINE( *this )
1163 
1165  {
1167 
1168  if( m_rDoc.IsAutoFormatRedline() )
1169  {
1170  pNewRedl->SetAutoFormat();
1172  {
1173  pNewRedl->SetComment( *mpAutoFormatRedlnComment );
1174  pNewRedl->SetSeqNo( mnAutoFormatRedlnCommentNo );
1175  }
1176  }
1177 
1178  SwPosition* pStt = pNewRedl->Start(),
1179  * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark()
1180  : pNewRedl->GetPoint();
1181  {
1182  SwTextNode* pTextNode = pStt->nNode.GetNode().GetTextNode();
1183  if( pTextNode == nullptr )
1184  {
1185  if( pStt->nContent > 0 )
1186  {
1187  OSL_ENSURE( false, "Redline start: non-text-node with content" );
1188  pStt->nContent = 0;
1189  }
1190  }
1191  else
1192  {
1193  if( pStt->nContent > pTextNode->Len() )
1194  {
1195  OSL_ENSURE( false, "Redline start: index after text" );
1196  pStt->nContent = pTextNode->Len();
1197  }
1198  }
1199  pTextNode = pEnd->nNode.GetNode().GetTextNode();
1200  if( pTextNode == nullptr )
1201  {
1202  if( pEnd->nContent > 0 )
1203  {
1204  OSL_ENSURE( false, "Redline end: non-text-node with content" );
1205  pEnd->nContent = 0;
1206  }
1207  }
1208  else
1209  {
1210  if( pEnd->nContent > pTextNode->Len() )
1211  {
1212  OSL_ENSURE( false, "Redline end: index after text" );
1213  pEnd->nContent = pTextNode->Len();
1214  }
1215  }
1216  }
1217  if( ( *pStt == *pEnd ) &&
1218  ( pNewRedl->GetContentIdx() == nullptr ) )
1219  { // Do not insert empty redlines
1220  delete pNewRedl;
1221  return AppendResult::IGNORED;
1222  }
1223  bool bCompress = false;
1225  // look up the first Redline for the starting position
1226  if( !GetRedline( *pStt, &n ) && n )
1227  --n;
1228  bool bDec = false;
1229 
1230  for( ; pNewRedl && n < mpRedlineTable->size(); bDec ? n : ++n )
1231  {
1232  bDec = false;
1233 
1234  SwRangeRedline* pRedl = (*mpRedlineTable)[ n ];
1235  SwPosition* pRStt = pRedl->Start(),
1236  * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
1237  : pRedl->GetPoint();
1238 
1239  // #i8518# remove empty redlines while we're at it
1240  if( ( *pRStt == *pREnd ) &&
1241  ( pRedl->GetContentIdx() == nullptr ) )
1242  {
1243  mpRedlineTable->DeleteAndDestroy(n);
1244  continue;
1245  }
1246 
1247  SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
1248 
1249  switch( pNewRedl->GetType() )
1250  {
1251  case RedlineType::Insert:
1252  switch( pRedl->GetType() )
1253  {
1254  case RedlineType::Insert:
1255  if( pRedl->IsOwnRedline( *pNewRedl ) )
1256  {
1257  bool bDelete = false;
1258 
1259  // Merge if applicable?
1260  if( (( SwComparePosition::Behind == eCmpPos &&
1261  IsPrevPos( *pREnd, *pStt ) ) ||
1262  ( SwComparePosition::CollideStart == eCmpPos ) ||
1263  ( SwComparePosition::OverlapBehind == eCmpPos ) ) &&
1264  pRedl->CanCombine( *pNewRedl ) &&
1265  ( n+1 >= mpRedlineTable->size() ||
1266  ( *(*mpRedlineTable)[ n+1 ]->Start() >= *pEnd &&
1267  *(*mpRedlineTable)[ n+1 ]->Start() != *pREnd ) ) )
1268  {
1269  pRedl->SetEnd( *pEnd, pREnd );
1270  if( !pRedl->HasValidRange() )
1271  {
1272  // re-insert
1273  mpRedlineTable->Remove( n );
1274  mpRedlineTable->Insert( pRedl );
1275  }
1276 
1277  bMerged = true;
1278  bDelete = true;
1279  }
1280  else if( (( SwComparePosition::Before == eCmpPos &&
1281  IsPrevPos( *pEnd, *pRStt ) ) ||
1282  ( SwComparePosition::CollideEnd == eCmpPos ) ||
1283  ( SwComparePosition::OverlapBefore == eCmpPos ) ) &&
1284  pRedl->CanCombine( *pNewRedl ) &&
1285  ( !n ||
1286  *(*mpRedlineTable)[ n-1 ]->End() != *pRStt ))
1287  {
1288  pRedl->SetStart( *pStt, pRStt );
1289  // re-insert
1290  mpRedlineTable->Remove( n );
1291  mpRedlineTable->Insert( pRedl );
1292 
1293  bMerged = true;
1294  bDelete = true;
1295  }
1296  else if ( SwComparePosition::Outside == eCmpPos )
1297  {
1298  // own insert-over-insert redlines:
1299  // just scrap the inside ones
1300  mpRedlineTable->DeleteAndDestroy( n );
1301  bDec = true;
1302  }
1303  else if( SwComparePosition::OverlapBehind == eCmpPos )
1304  {
1305  *pStt = *pREnd;
1306  if( ( *pStt == *pEnd ) &&
1307  ( pNewRedl->GetContentIdx() == nullptr ) )
1308  bDelete = true;
1309  }
1310  else if( SwComparePosition::OverlapBefore == eCmpPos )
1311  {
1312  *pEnd = *pRStt;
1313  if( ( *pStt == *pEnd ) &&
1314  ( pNewRedl->GetContentIdx() == nullptr ) )
1315  bDelete = true;
1316  }
1317  else if( SwComparePosition::Inside == eCmpPos )
1318  {
1319  bDelete = true;
1320  bMerged = true;
1321  }
1322  else if( SwComparePosition::Equal == eCmpPos )
1323  bDelete = true;
1324 
1325  if( bDelete )
1326  {
1327  delete pNewRedl;
1328  pNewRedl = nullptr;
1329  bCompress = true;
1330  }
1331  }
1332  else if( SwComparePosition::Inside == eCmpPos )
1333  {
1334  // split up
1335  if( *pEnd != *pREnd )
1336  {
1337  SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
1338  pCpy->SetStart( *pEnd );
1339  mpRedlineTable->Insert( pCpy );
1340  }
1341  pRedl->SetEnd( *pStt, pREnd );
1342  if( ( *pStt == *pRStt ) &&
1343  ( pRedl->GetContentIdx() == nullptr ) )
1344  {
1345  mpRedlineTable->DeleteAndDestroy( n );
1346  bDec = true;
1347  }
1348  else if( !pRedl->HasValidRange() )
1349  {
1350  // re-insert
1351  mpRedlineTable->Remove( n );
1352  mpRedlineTable->Insert( pRedl );
1353  }
1354  }
1355  else if ( SwComparePosition::Outside == eCmpPos )
1356  {
1357  // handle overlapping redlines in broken documents
1358 
1359  // split up the new redline, since it covers the
1360  // existing redline. Insert the first part, and
1361  // progress with the remainder as usual
1362  SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl );
1363  pSplit->SetEnd( *pRStt );
1364  pNewRedl->SetStart( *pREnd );
1365  mpRedlineTable->Insert( pSplit );
1366  if( *pStt == *pEnd && pNewRedl->GetContentIdx() == nullptr )
1367  {
1368  delete pNewRedl;
1369  pNewRedl = nullptr;
1370  bCompress = true;
1371  }
1372  }
1373  else if ( SwComparePosition::OverlapBehind == eCmpPos )
1374  {
1375  // handle overlapping redlines in broken documents
1376  pNewRedl->SetStart( *pREnd );
1377  }
1378  else if ( SwComparePosition::OverlapBefore == eCmpPos )
1379  {
1380  // handle overlapping redlines in broken documents
1381  *pEnd = *pRStt;
1382  if( ( *pStt == *pEnd ) &&
1383  ( pNewRedl->GetContentIdx() == nullptr ) )
1384  {
1385  delete pNewRedl;
1386  pNewRedl = nullptr;
1387  bCompress = true;
1388  }
1389  }
1390  break;
1391  case RedlineType::Delete:
1392  if( SwComparePosition::Inside == eCmpPos )
1393  {
1394  // split up
1395  if( *pEnd != *pREnd )
1396  {
1397  SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
1398  pCpy->SetStart( *pEnd );
1399  mpRedlineTable->Insert( pCpy );
1400  }
1401  pRedl->SetEnd( *pStt, pREnd );
1402  if( ( *pStt == *pRStt ) &&
1403  ( pRedl->GetContentIdx() == nullptr ) )
1404  {
1405  mpRedlineTable->DeleteAndDestroy( n );
1406  bDec = true;
1407  }
1408  else if( !pRedl->HasValidRange() )
1409  {
1410  // re-insert
1411  mpRedlineTable->Remove( n );
1412  mpRedlineTable->Insert( pRedl, n );
1413  }
1414  }
1415  else if ( SwComparePosition::Outside == eCmpPos )
1416  {
1417  // handle overlapping redlines in broken documents
1418 
1419  // split up the new redline, since it covers the
1420  // existing redline. Insert the first part, and
1421  // progress with the remainder as usual
1422  SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl );
1423  pSplit->SetEnd( *pRStt );
1424  pNewRedl->SetStart( *pREnd );
1425  mpRedlineTable->Insert( pSplit );
1426  if( *pStt == *pEnd && pNewRedl->GetContentIdx() == nullptr )
1427  {
1428  delete pNewRedl;
1429  pNewRedl = nullptr;
1430  bCompress = true;
1431  }
1432  }
1433  else if ( SwComparePosition::Equal == eCmpPos )
1434  {
1435  // handle identical redlines in broken documents
1436  // delete old (delete) redline
1437  mpRedlineTable->DeleteAndDestroy( n );
1438  bDec = true;
1439  }
1440  else if ( SwComparePosition::OverlapBehind == eCmpPos )
1441  { // Another workaround for broken redlines
1442  pNewRedl->SetStart( *pREnd );
1443  }
1444  break;
1445  case RedlineType::Format:
1446  switch( eCmpPos )
1447  {
1449  pRedl->SetStart( *pEnd, pRStt );
1450  // re-insert
1451  mpRedlineTable->Remove( n );
1452  mpRedlineTable->Insert( pRedl, n );
1453  bDec = true;
1454  break;
1455 
1457  pRedl->SetEnd( *pStt, pREnd );
1458  if( *pStt == *pRStt && pRedl->GetContentIdx() == nullptr )
1459  {
1460  mpRedlineTable->DeleteAndDestroy( n );
1461  bDec = true;
1462  }
1463  break;
1464 
1467  // Overlaps the current one completely or has the
1468  // same dimension, delete the old one
1469  mpRedlineTable->DeleteAndDestroy( n );
1470  bDec = true;
1471  break;
1472 
1474  // Overlaps the current one completely,
1475  // split or shorten the new one
1476  if( *pEnd != *pREnd )
1477  {
1478  if( *pEnd != *pRStt )
1479  {
1480  SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
1481  pNew->SetStart( *pEnd );
1482  pRedl->SetEnd( *pStt, pREnd );
1483  if( *pStt == *pRStt && pRedl->GetContentIdx() == nullptr )
1484  mpRedlineTable->DeleteAndDestroy( n );
1485  AppendRedline( pNew, bCallDelete );
1486  n = 0; // re-initialize
1487  bDec = true;
1488  }
1489  }
1490  else
1491  pRedl->SetEnd( *pStt, pREnd );
1492  break;
1493  default:
1494  break;
1495  }
1496  break;
1497  default:
1498  break;
1499  }
1500  break;
1501 
1502  case RedlineType::Delete:
1503  switch( pRedl->GetType() )
1504  {
1505  case RedlineType::Delete:
1506  switch( eCmpPos )
1507  {
1509  {
1510  // Overlaps the current one completely,
1511  // split the new one
1512  if (*pEnd == *pREnd)
1513  {
1514  pNewRedl->SetEnd(*pRStt, pEnd);
1515  }
1516  else if (*pStt == *pRStt)
1517  {
1518  pNewRedl->SetStart(*pREnd, pStt);
1519  }
1520  else
1521  {
1522  SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl );
1523  pNew->SetStart( *pREnd );
1524  pNewRedl->SetEnd( *pRStt, pEnd );
1525  AppendRedline( pNew, bCallDelete );
1526  n = 0; // re-initialize
1527  bDec = true;
1528  }
1529  }
1530  break;
1531 
1534  delete pNewRedl;
1535  pNewRedl = nullptr;
1536  bCompress = true;
1537  break;
1538 
1541  if( pRedl->IsOwnRedline( *pNewRedl ) &&
1542  pRedl->CanCombine( *pNewRedl ))
1543  {
1544  // If that's the case we can merge it, meaning
1545  // the new one covers this well
1546  if( SwComparePosition::OverlapBehind == eCmpPos )
1547  pNewRedl->SetStart( *pRStt, pStt );
1548  else
1549  pNewRedl->SetEnd( *pREnd, pEnd );
1550  mpRedlineTable->DeleteAndDestroy( n );
1551  bDec = true;
1552  }
1553  else if( SwComparePosition::OverlapBehind == eCmpPos )
1554  pNewRedl->SetStart( *pREnd, pStt );
1555  else
1556  pNewRedl->SetEnd( *pRStt, pEnd );
1557  break;
1558 
1561  if( pRedl->IsOwnRedline( *pNewRedl ) &&
1562  pRedl->CanCombine( *pNewRedl ) )
1563  {
1565  {
1566  // Before we can merge, we make it visible!
1567  // We insert temporarily so that pNew is
1568  // also dealt with when moving the indices.
1569  mpRedlineTable->Insert(pNewRedl);
1570  pRedl->Show(0, mpRedlineTable->GetPos(pRedl));
1571  mpRedlineTable->Remove( pNewRedl );
1572  pRStt = pRedl->Start();
1573  pREnd = pRedl->End();
1574  }
1575 
1576  // If that's the case we can merge it, meaning
1577  // the new one covers this well
1578  if( SwComparePosition::CollideStart == eCmpPos )
1579  pNewRedl->SetStart( *pRStt, pStt );
1580  else
1581  pNewRedl->SetEnd( *pREnd, pEnd );
1582 
1583  // delete current (below), and restart process with
1584  // previous
1585  SwRedlineTable::size_type nToBeDeleted = n;
1586  bDec = true;
1587 
1588  if( *(pNewRedl->Start()) <= *pREnd )
1589  {
1590  // Whoooah, we just extended the new 'redline'
1591  // beyond previous redlines, so better start
1592  // again. Of course this is not supposed to
1593  // happen, and in an ideal world it doesn't,
1594  // but unfortunately this code is buggy and
1595  // totally rotten so it does happen and we
1596  // better fix it.
1597  n = 0;
1598  bDec = true;
1599  }
1600 
1601  mpRedlineTable->DeleteAndDestroy( nToBeDeleted );
1602  }
1603  break;
1604  default:
1605  break;
1606  }
1607  break;
1608 
1609  case RedlineType::Insert:
1610  {
1611  // b62341295: Do not throw away redlines
1612  // even if they are not allowed to be combined
1614  if( !( eOld & RedlineFlags::DontCombineRedlines ) &&
1615  pRedl->IsOwnRedline( *pNewRedl ) )
1616  {
1617 
1618  // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
1619  // The ShowMode needs to be retained!
1621  switch( eCmpPos )
1622  {
1624  bCompress = true;
1625  mpRedlineTable->DeleteAndDestroy( n );
1626  bDec = true;
1627  [[fallthrough]];
1628 
1630  if( bCallDelete )
1631  {
1632  // DeleteAndJoin does not yield the
1633  // desired result if there is no paragraph to
1634  // join with, i.e. at the end of the document.
1635  // For this case, we completely delete the
1636  // paragraphs (if, of course, we also start on
1637  // a paragraph boundary).
1638  if( (pStt->nContent == 0) &&
1639  pEnd->nNode.GetNode().IsEndNode() )
1640  {
1641  pEnd->nNode--;
1642  pEnd->nContent.Assign(
1643  pEnd->nNode.GetNode().GetTextNode(), 0);
1645  }
1646  else
1648 
1649  bCompress = true;
1650  }
1651  if( !bCallDelete && !bDec && *pEnd == *pREnd )
1652  {
1654  bCompress = true;
1655  }
1656  else if ( bCallDelete || !bDec )
1657  {
1658  // delete new redline, except in some cases of fallthrough from previous
1659  // case ::Equal (eg. same portion w:del in w:ins in OOXML import)
1660  delete pNewRedl;
1661  pNewRedl = nullptr;
1662  }
1663  break;
1664 
1666  {
1667  mpRedlineTable->Remove( n );
1668  bDec = true;
1669  if( bCallDelete )
1670  {
1671  TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl);
1673  n = 0; // re-initialize
1674  }
1675  delete pRedl;
1676  }
1677  break;
1678 
1680  {
1681  SwPaM aPam( *pRStt, *pEnd );
1682 
1683  if( *pEnd == *pREnd )
1684  mpRedlineTable->DeleteAndDestroy( n );
1685  else
1686  {
1687  pRedl->SetStart( *pEnd, pRStt );
1688  // re-insert
1689  mpRedlineTable->Remove( n );
1690  mpRedlineTable->Insert( pRedl, n );
1691  }
1692 
1693  if( bCallDelete )
1694  {
1695  TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl);
1697  n = 0; // re-initialize
1698  }
1699  bDec = true;
1700  }
1701  break;
1702 
1704  {
1705  SwPaM aPam( *pStt, *pREnd );
1706 
1707  if( *pStt == *pRStt )
1708  {
1709  mpRedlineTable->DeleteAndDestroy( n );
1710  bDec = true;
1711  }
1712  else
1713  pRedl->SetEnd( *pStt, pREnd );
1714 
1715  if( bCallDelete )
1716  {
1717  TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl);
1719  n = 0; // re-initialize
1720  bDec = true;
1721  }
1722  }
1723  break;
1724  default:
1725  break;
1726  }
1727 
1728  meRedlineFlags = eOld;
1729  }
1730  else
1731  {
1732  // it may be necessary to split the existing redline in
1733  // two. In this case, pRedl will be changed to cover
1734  // only part of its former range, and pNew will cover
1735  // the remainder.
1736  SwRangeRedline* pNew = nullptr;
1737 
1738  switch( eCmpPos )
1739  {
1741  {
1742  pRedl->PushData( *pNewRedl );
1743  delete pNewRedl;
1744  pNewRedl = nullptr;
1746  {
1747  pRedl->Hide(0, mpRedlineTable->GetPos(pRedl));
1748  }
1749  bCompress = true;
1750  }
1751  break;
1752 
1754  {
1755  if( *pRStt == *pStt )
1756  {
1757  // #i97421#
1758  // redline w/out extent loops
1759  if (*pStt != *pEnd)
1760  {
1761  pNewRedl->PushData( *pRedl, false );
1762  pRedl->SetStart( *pEnd, pRStt );
1763  // re-insert
1764  mpRedlineTable->Remove( n );
1765  mpRedlineTable->Insert( pRedl, n );
1766  bDec = true;
1767  }
1768  }
1769  else
1770  {
1771  pNewRedl->PushData( *pRedl, false );
1772  if( *pREnd != *pEnd )
1773  {
1774  pNew = new SwRangeRedline( *pRedl );
1775  pNew->SetStart( *pEnd );
1776  }
1777  pRedl->SetEnd( *pStt, pREnd );
1778  if( !pRedl->HasValidRange() )
1779  {
1780  // re-insert
1781  mpRedlineTable->Remove( n );
1782  mpRedlineTable->Insert( pRedl, n );
1783  }
1784  }
1785  }
1786  break;
1787 
1789  {
1790  pRedl->PushData( *pNewRedl );
1791  if( *pEnd == *pREnd )
1792  {
1793  pNewRedl->SetEnd( *pRStt, pEnd );
1794  }
1795  else if (*pStt == *pRStt)
1796  {
1797  pNewRedl->SetStart(*pREnd, pStt);
1798  }
1799  else
1800  {
1801  pNew = new SwRangeRedline( *pNewRedl );
1802  pNew->SetEnd( *pRStt );
1803  pNewRedl->SetStart( *pREnd, pStt );
1804  }
1805  bCompress = true;
1806  }
1807  break;
1808 
1810  {
1811  if( *pEnd == *pREnd )
1812  {
1813  pRedl->PushData( *pNewRedl );
1814  pNewRedl->SetEnd( *pRStt, pEnd );
1816  {
1817  mpRedlineTable->Insert(pNewRedl);
1818  pRedl->Hide(0, mpRedlineTable->GetPos(pRedl));
1819  mpRedlineTable->Remove( pNewRedl );
1820  }
1821  }
1822  else
1823  {
1824  pNew = new SwRangeRedline( *pRedl );
1825  pNew->PushData( *pNewRedl );
1826  pNew->SetEnd( *pEnd );
1827  pNewRedl->SetEnd( *pRStt, pEnd );
1828  pRedl->SetStart( *pNew->End(), pRStt ) ;
1829  // re-insert
1830  mpRedlineTable->Remove( n );
1831  mpRedlineTable->Insert( pRedl );
1832  bDec = true;
1833  }
1834  }
1835  break;
1836 
1838  {
1839  if( *pStt == *pRStt )
1840  {
1841  pRedl->PushData( *pNewRedl );
1842  pNewRedl->SetStart( *pREnd, pStt );
1844  {
1845  mpRedlineTable->Insert( pNewRedl );
1846  pRedl->Hide(0, mpRedlineTable->GetPos(pRedl));
1847  mpRedlineTable->Remove( pNewRedl );
1848  }
1849  }
1850  else
1851  {
1852  pNew = new SwRangeRedline( *pRedl );
1853  pNew->PushData( *pNewRedl );
1854  pNew->SetStart( *pStt );
1855  pNewRedl->SetStart( *pREnd, pStt );
1856  pRedl->SetEnd( *pNew->Start(), pREnd );
1857  if( !pRedl->HasValidRange() )
1858  {
1859  // re-insert
1860  mpRedlineTable->Remove( n );
1861  mpRedlineTable->Insert( pRedl );
1862  }
1863  }
1864  }
1865  break;
1866  default:
1867  break;
1868  }
1869 
1870  // insert the pNew part (if it exists)
1871  if( pNew )
1872  {
1873  mpRedlineTable->Insert( pNew );
1874 
1875  // pNew must be deleted if Insert() wasn't
1876  // successful. But that can't happen, since pNew is
1877  // part of the original pRedl redline.
1878  // OSL_ENSURE( bRet, "Can't insert existing redline?" );
1879 
1880  // restart (now with pRedl being split up)
1881  n = 0;
1882  bDec = true;
1883  }
1884  }
1885  }
1886  break;
1887 
1888  case RedlineType::Format:
1889  switch( eCmpPos )
1890  {
1892  pRedl->SetStart( *pEnd, pRStt );
1893  // re-insert
1894  mpRedlineTable->Remove( n );
1895  mpRedlineTable->Insert( pRedl, n );
1896  bDec = true;
1897  break;
1898 
1900  pRedl->SetEnd( *pStt, pREnd );
1901  break;
1902 
1905  // Overlaps the current one completely or has the
1906  // same dimension, delete the old one
1907  mpRedlineTable->DeleteAndDestroy( n );
1908  bDec = true;
1909  break;
1910 
1912  // Overlaps the current one completely,
1913  // split or shorten the new one
1914  if( *pEnd != *pREnd )
1915  {
1916  if( *pEnd != *pRStt )
1917  {
1918  SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
1919  pNew->SetStart( *pEnd );
1920  pRedl->SetEnd( *pStt, pREnd );
1921  if( ( *pStt == *pRStt ) &&
1922  ( pRedl->GetContentIdx() == nullptr ) )
1923  mpRedlineTable->DeleteAndDestroy( n );
1924  AppendRedline( pNew, bCallDelete );
1925  n = 0; // re-initialize
1926  bDec = true;
1927  }
1928  }
1929  else
1930  pRedl->SetEnd( *pStt, pREnd );
1931  break;
1932  default:
1933  break;
1934  }
1935  break;
1936  default:
1937  break;
1938  }
1939  break;
1940 
1941  case RedlineType::Format:
1942  switch( pRedl->GetType() )
1943  {
1944  case RedlineType::Insert:
1945  case RedlineType::Delete:
1946  switch( eCmpPos )
1947  {
1949  pNewRedl->SetEnd( *pRStt, pEnd );
1950  break;
1951 
1953  pNewRedl->SetStart( *pREnd, pStt );
1954  break;
1955 
1958  delete pNewRedl;
1959  pNewRedl = nullptr;
1960  break;
1961 
1963  // Overlaps the current one completely,
1964  // split or shorten the new one
1965  if (*pEnd == *pREnd)
1966  {
1967  pNewRedl->SetEnd(*pRStt, pEnd);
1968  }
1969  else if (*pStt == *pRStt)
1970  {
1971  pNewRedl->SetStart(*pREnd, pStt);
1972  }
1973  else
1974  {
1975  SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl );
1976  pNew->SetStart( *pREnd );
1977  pNewRedl->SetEnd( *pRStt, pEnd );
1978  AppendRedline( pNew, bCallDelete );
1979  n = 0; // re-initialize
1980  bDec = true;
1981  }
1982  break;
1983  default:
1984  break;
1985  }
1986  break;
1987  case RedlineType::Format:
1988  switch( eCmpPos )
1989  {
1992  {
1993  // Overlaps the current one completely or has the
1994  // same dimension, delete the old one
1995  mpRedlineTable->DeleteAndDestroy( n );
1996  bDec = true;
1997  }
1998  break;
1999 
2001  if( pRedl->IsOwnRedline( *pNewRedl ) &&
2002  pRedl->CanCombine( *pNewRedl ))
2003  {
2004  // own one can be ignored completely
2005  delete pNewRedl;
2006  pNewRedl = nullptr;
2007  }
2008  else if( *pREnd == *pEnd )
2009  // or else only shorten the current one
2010  pRedl->SetEnd( *pStt, pREnd );
2011  else if( *pRStt == *pStt )
2012  {
2013  // or else only shorten the current one
2014  pRedl->SetStart( *pEnd, pRStt );
2015  // re-insert
2016  mpRedlineTable->Remove( n );
2017  mpRedlineTable->Insert( pRedl, n );
2018  bDec = true;
2019  }
2020  else
2021  {
2022  // If it lies completely within the current one
2023  // we need to split it
2024  SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
2025  pNew->SetStart( *pEnd );
2026  pRedl->SetEnd( *pStt, pREnd );
2027  AppendRedline( pNew, bCallDelete );
2028  n = 0; // re-initialize
2029  bDec = true;
2030  }
2031  break;
2032 
2035  if( pRedl->IsOwnRedline( *pNewRedl ) &&
2036  pRedl->CanCombine( *pNewRedl ))
2037  {
2038  // If that's the case we can merge it, meaning
2039  // the new one covers this well
2040  if( SwComparePosition::OverlapBehind == eCmpPos )
2041  pNewRedl->SetStart( *pRStt, pStt );
2042  else
2043  pNewRedl->SetEnd( *pREnd, pEnd );
2044  mpRedlineTable->DeleteAndDestroy( n );
2045  bDec = false;
2046  }
2047  else if( SwComparePosition::OverlapBehind == eCmpPos )
2048  pNewRedl->SetStart( *pREnd, pStt );
2049  else
2050  pNewRedl->SetEnd( *pRStt, pEnd );
2051  break;
2052 
2054  if( pRedl->IsOwnRedline( *pNewRedl ) &&
2055  pRedl->CanCombine( *pNewRedl ) && n &&
2056  *(*mpRedlineTable)[ n-1 ]->End() < *pStt )
2057  {
2058  // If that's the case we can merge it, meaning
2059  // the new one covers this well
2060  pNewRedl->SetEnd( *pREnd, pEnd );
2061  mpRedlineTable->DeleteAndDestroy( n );
2062  bDec = true;
2063  }
2064  break;
2066  if( pRedl->IsOwnRedline( *pNewRedl ) &&
2067  pRedl->CanCombine( *pNewRedl ) &&
2068  n+1 < mpRedlineTable->size() &&
2069  *(*mpRedlineTable)[ n+1 ]->Start() < *pEnd )
2070  {
2071  // If that's the case we can merge it, meaning
2072  // the new one covers this well
2073  pNewRedl->SetStart( *pRStt, pStt );
2074  mpRedlineTable->DeleteAndDestroy( n );
2075  bDec = true;
2076  }
2077  break;
2078  default:
2079  break;
2080  }
2081  break;
2082  default:
2083  break;
2084  }
2085  break;
2086 
2087  case RedlineType::FmtColl:
2088  // How should we behave here?
2089  // insert as is
2090  break;
2091  default:
2092  break;
2093  }
2094  }
2095 
2096  if( pNewRedl )
2097  {
2098  if( ( *pStt == *pEnd ) &&
2099  ( pNewRedl->GetContentIdx() == nullptr ) )
2100  { // Do not insert empty redlines
2101  delete pNewRedl;
2102  pNewRedl = nullptr;
2103  }
2104  else
2105  {
2106  if ( bCallDelete && RedlineType::Delete == pNewRedl->GetType() )
2107  {
2108  if ( pStt->nContent != 0 )
2109  {
2110  // tdf#119571 update the style of the joined paragraph
2111  // after a partially deleted paragraph to show its correct style
2112  // in "Show changes" mode, too. All removed paragraphs
2113  // get the style of the first (partially deleted) paragraph
2114  // to avoid text insertion with bad style in the deleted
2115  // area later.
2116 
2117  SwContentNode* pDelNd = pStt->nNode.GetNode().GetContentNode();
2118  SwContentNode* pTextNd = pEnd->nNode.GetNode().GetContentNode();
2119  SwTextNode* pDelNode = pStt->nNode.GetNode().GetTextNode();
2120  SwTextNode* pTextNode;
2121  SwNodeIndex aIdx( pEnd->nNode.GetNode() );
2122  bool bFirst = true;
2123 
2124  while (pDelNode != nullptr && pTextNd != nullptr && pDelNd->GetIndex() < pTextNd->GetIndex())
2125  {
2126  pTextNode = pTextNd->GetTextNode();
2127  if (pTextNode && pDelNode != pTextNode )
2128  {
2129  SwPosition aPos(aIdx);
2130 
2132  {
2133  bCompress = true;
2134 
2135  // split redline to store ExtraData per paragraphs
2136  SwRangeRedline* pPar = new SwRangeRedline( *pNewRedl );
2137  pPar->SetStart( aPos );
2138  pNewRedl->SetEnd( aPos );
2139 
2140  // get extradata for reset formatting of the modified paragraph
2141  SwRedlineExtraData_FormatColl* pExtraData = lcl_CopyStyle(aPos, *pStt, false);
2142  if (pExtraData)
2143  {
2144  std::unique_ptr<SwRedlineExtraData_FormatColl> xRedlineExtraData;
2145  if (!bFirst)
2146  pExtraData->SetFormatAll(false);
2147  xRedlineExtraData.reset(pExtraData);
2148  pPar->SetExtraData( xRedlineExtraData.get() );
2149  }
2150 
2151  // skip empty redlines without ExtraData
2152  // FIXME: maybe checking pExtraData is redundant here
2153  if ( pExtraData || *pPar->Start() != *pPar->End() )
2154  mpRedlineTable->Insert( pPar );
2155  else
2156  delete pPar;
2157  }
2158 
2159  // modify paragraph formatting
2160  lcl_CopyStyle(*pStt, aPos);
2161  }
2162  pTextNd = SwNodes::GoPrevious( &aIdx );
2163 
2164  if (bFirst)
2165  bFirst = false;
2166  }
2167  }
2168  }
2169  bool const ret = mpRedlineTable->Insert( pNewRedl );
2170  assert(ret || !pNewRedl);
2171  if (ret && !pNewRedl)
2172  {
2173  bMerged = true; // treat InsertWithValidRanges as "merge"
2174  }
2175  }
2176  }
2177 
2178  if( bCompress )
2179  CompressRedlines();
2180  }
2181  else
2182  {
2183  if( bCallDelete && RedlineType::Delete == pNewRedl->GetType() )
2184  {
2186  // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
2187  // The ShowMode needs to be retained!
2190  meRedlineFlags = eOld;
2191  }
2192  delete pNewRedl;
2193  pNewRedl = nullptr;
2194  }
2195  CHECK_REDLINE( *this )
2196 
2197  return (nullptr != pNewRedl)
2200 }
2201 
2203 {
2204  // #TODO - equivalent for 'SwTableRowRedline'
2205  /*
2206  CHECK_REDLINE( this )
2207  */
2208 
2210  {
2211  // #TODO - equivalent for 'SwTableRowRedline'
2212  /*
2213  pNewRedl->InvalidateRange();
2214  */
2215 
2216  // Make equivalent of 'AppendRedline' checks inside here too
2217 
2218  mpExtraRedlineTable->Insert( pNewRedl );
2219  }
2220  else
2221  {
2222  // TO DO - equivalent for 'SwTableRowRedline'
2223  /*
2224  if( bCallDelete && RedlineType::Delete == pNewRedl->GetType() )
2225  {
2226  RedlineFlags eOld = meRedlineFlags;
2227  // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
2228  // The ShowMode needs to be retained!
2229  meRedlineFlags = eOld & ~(RedlineFlags::On | RedlineFlags::Ignore);
2230  DeleteAndJoin( *pNewRedl );
2231  meRedlineFlags = eOld;
2232  }
2233  delete pNewRedl, pNewRedl = 0;
2234  */
2235  }
2236  // #TODO - equivalent for 'SwTableRowRedline'
2237  /*
2238  CHECK_REDLINE( this )
2239  */
2240 
2241  return nullptr != pNewRedl;
2242 }
2243 
2245 {
2246  // #TODO - equivalent for 'SwTableCellRedline'
2247  /*
2248  CHECK_REDLINE( this )
2249  */
2250 
2252  {
2253  // #TODO - equivalent for 'SwTableCellRedline'
2254  /*
2255  pNewRedl->InvalidateRange();
2256  */
2257 
2258  // Make equivalent of 'AppendRedline' checks inside here too
2259 
2260  mpExtraRedlineTable->Insert( pNewRedl );
2261  }
2262  else
2263  {
2264  // TO DO - equivalent for 'SwTableCellRedline'
2265  /*
2266  if( bCallDelete && RedlineType::Delete == pNewRedl->GetType() )
2267  {
2268  RedlineFlags eOld = meRedlineFlags;
2269  // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
2270  // The ShowMode needs to be retained!
2271  meRedlineFlags = eOld & ~(RedlineFlags::On | RedlineFlags::Ignore);
2272  DeleteAndJoin( *pNewRedl );
2273  meRedlineFlags = eOld;
2274  }
2275  delete pNewRedl, pNewRedl = 0;
2276  */
2277  }
2278  // #TODO - equivalent for 'SwTableCellRedline'
2279  /*
2280  CHECK_REDLINE( this )
2281  */
2282 
2283  return nullptr != pNewRedl;
2284 }
2285 
2287 {
2288  CHECK_REDLINE( *this )
2289 
2290  void (SwRangeRedline::*pFnc)(sal_uInt16, size_t, bool) = nullptr;
2293  pFnc = &SwRangeRedline::Show;
2294  else if (eShow == RedlineFlags::ShowInsert)
2295  pFnc = &SwRangeRedline::Hide;
2296 
2297  // Try to merge identical ones
2298  for( SwRedlineTable::size_type n = 1; n < mpRedlineTable->size(); ++n )
2299  {
2300  SwRangeRedline* pPrev = (*mpRedlineTable)[ n-1 ],
2301  * pCur = (*mpRedlineTable)[ n ];
2302  const SwPosition* pPrevStt = pPrev->Start(),
2303  * pPrevEnd = pPrevStt == pPrev->GetPoint()
2304  ? pPrev->GetMark() : pPrev->GetPoint();
2305  const SwPosition* pCurStt = pCur->Start(),
2306  * pCurEnd = pCurStt == pCur->GetPoint()
2307  ? pCur->GetMark() : pCur->GetPoint();
2308  if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) &&
2309  pPrevStt->nNode.GetNode().StartOfSectionNode() ==
2310  pCurEnd->nNode.GetNode().StartOfSectionNode() &&
2311  !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
2312  {
2313  // we then can merge them
2314  SwRedlineTable::size_type nPrevIndex = n-1;
2315  pPrev->Show(0, nPrevIndex);
2316  pCur->Show(0, n);
2317 
2318  pPrev->SetEnd( *pCur->End() );
2319  mpRedlineTable->DeleteAndDestroy( n );
2320  --n;
2321  if( pFnc )
2322  (pPrev->*pFnc)(0, nPrevIndex, false);
2323  }
2324  }
2325  CHECK_REDLINE( *this )
2326 
2327  // #TODO - add 'SwExtraRedlineTable' also ?
2328 }
2329 
2331 {
2332  bool bChg = false;
2334  const SwPosition* pStt = rRange.Start();
2335  const SwPosition* pEnd = rRange.End();
2336  GetRedline( *pStt, &n );
2337  for ( ; n < mpRedlineTable->size(); ++n)
2338  {
2339  SwRangeRedline * pRedline = (*mpRedlineTable)[ n ];
2340  SwPosition *const pRedlineStart = pRedline->Start();
2341  SwPosition *const pRedlineEnd = pRedline->End();
2342  if (*pRedlineStart <= *pStt && *pStt <= *pRedlineEnd &&
2343  *pRedlineStart <= *pEnd && *pEnd <= *pRedlineEnd)
2344  {
2345  bChg = true;
2346  int nn = 0;
2347  if (*pStt == *pRedlineStart)
2348  nn += 1;
2349  if (*pEnd == *pRedlineEnd)
2350  nn += 2;
2351 
2352  SwRangeRedline* pNew = nullptr;
2353  switch( nn )
2354  {
2355  case 0:
2356  pNew = new SwRangeRedline( *pRedline );
2357  pRedline->SetEnd( *pStt, pRedlineEnd );
2358  pNew->SetStart( *pEnd );
2359  break;
2360 
2361  case 1:
2362  *pRedlineStart = *pEnd;
2363  break;
2364 
2365  case 2:
2366  *pRedlineEnd = *pStt;
2367  break;
2368 
2369  case 3:
2371  mpRedlineTable->DeleteAndDestroy( n-- );
2372  pRedline = nullptr;
2373  break;
2374  }
2375  if (pRedline && !pRedline->HasValidRange())
2376  {
2377  // re-insert
2378  mpRedlineTable->Remove( n );
2379  mpRedlineTable->Insert( pRedline, n );
2380  }
2381  if( pNew )
2382  mpRedlineTable->Insert( pNew, n );
2383  }
2384  else if (*pEnd < *pRedlineStart)
2385  break;
2386  }
2387  return bChg;
2388 
2389  // #TODO - add 'SwExtraRedlineTable' also ?
2390 }
2391 
2392 bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
2393  RedlineType nDelType )
2394 {
2395  if( !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
2396  return false;
2397 
2398  bool bChg = false;
2399 
2400  if (bSaveInUndo && m_rDoc.GetIDocumentUndoRedo().DoesUndo())
2401  {
2402  std::unique_ptr<SwUndoRedline> pUndo(new SwUndoRedline( SwUndoId::REDLINE, rRange ));
2403  if( pUndo->GetRedlSaveCount() )
2404  {
2405  m_rDoc.GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
2406  }
2407  }
2408 
2409  const SwPosition* pStt = rRange.Start(),
2410  * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
2411  : rRange.GetPoint();
2413  GetRedline( *pStt, &n );
2414  for( ; n < mpRedlineTable->size() ; ++n )
2415  {
2416  SwRangeRedline* pRedl = (*mpRedlineTable)[ n ];
2417  if( RedlineType::Any != nDelType && nDelType != pRedl->GetType() )
2418  continue;
2419 
2420  SwPosition* pRStt = pRedl->Start(),
2421  * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
2422  : pRedl->GetPoint();
2423  switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
2424  {
2428  mpRedlineTable->DeleteAndDestroy( n-- );
2429  bChg = true;
2430  break;
2431 
2434  pRedl->SetStart( *pEnd, pRStt );
2436  // re-insert
2437  mpRedlineTable->Remove( n );
2438  mpRedlineTable->Insert( pRedl );
2439  --n;
2440  break;
2441 
2444  pRedl->SetEnd( *pStt, pREnd );
2446  if( !pRedl->HasValidRange() )
2447  {
2448  // re-insert
2449  mpRedlineTable->Remove( n );
2450  mpRedlineTable->Insert( pRedl );
2451  --n;
2452  }
2453  break;
2454 
2456  {
2457  // this one needs to be split
2459  if( *pRStt == *pStt )
2460  {
2461  pRedl->SetStart( *pEnd, pRStt );
2463  // re-insert
2464  mpRedlineTable->Remove( n );
2465  mpRedlineTable->Insert( pRedl );
2466  --n;
2467  }
2468  else
2469  {
2470  SwRangeRedline* pCpy;
2471  if( *pREnd != *pEnd )
2472  {
2473  pCpy = new SwRangeRedline( *pRedl );
2474  pCpy->SetStart( *pEnd );
2476  }
2477  else
2478  pCpy = nullptr;
2479  pRedl->SetEnd( *pStt, pREnd );
2481  if( !pRedl->HasValidRange() )
2482  {
2483  // re-insert
2484  mpRedlineTable->Remove( n );
2485  mpRedlineTable->Insert( pRedl );
2486  --n;
2487  }
2488  if( pCpy )
2489  mpRedlineTable->Insert( pCpy );
2490  }
2491  }
2492  break;
2493 
2495  // remove (not hidden) empty redlines created for fixing tdf#119571
2496  // (Note: hidden redlines are all empty, i.e. start and end are equal.)
2497  if ( pRedl->HasMark() && *pRedl->GetMark() == *pRedl->GetPoint() )
2498  {
2500  mpRedlineTable->DeleteAndDestroy( n-- );
2501  bChg = true;
2502  break;
2503  }
2504  [[fallthrough]];
2505 
2507  n = mpRedlineTable->size();
2508  break;
2509  default:
2510  break;
2511  }
2512  }
2513 
2514  if( bChg )
2516 
2517  return bChg;
2518 
2519  // #TODO - add 'SwExtraRedlineTable' also ?
2520 }
2521 
2522 bool DocumentRedlineManager::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo,
2523  RedlineType nDelType )
2524 {
2525  SwPaM aTemp(*rNode.EndOfSectionNode(), rNode);
2526  return DeleteRedline(aTemp, bSaveInUndo, nDelType);
2527 }
2528 
2530 {
2531  const sal_uLong nNdIdx = rNd.GetIndex();
2532  for( SwRedlineTable::size_type n = 0; n < mpRedlineTable->size() ; ++n )
2533  {
2534  const SwRangeRedline* pTmp = (*mpRedlineTable)[ n ];
2535  sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
2536  nMk = pTmp->GetMark()->nNode.GetIndex();
2537  if( nPt < nMk ) { tools::Long nTmp = nMk; nMk = nPt; nPt = nTmp; }
2538 
2539  if( ( RedlineType::Any == nType || nType == pTmp->GetType()) &&
2540  nMk <= nNdIdx && nNdIdx <= nPt )
2541  return n;
2542 
2543  if( nMk > nNdIdx )
2544  break;
2545  }
2546  return SwRedlineTable::npos;
2547 
2548  // #TODO - add 'SwExtraRedlineTable' also ?
2549 }
2550 
2551 bool DocumentRedlineManager::HasRedline( const SwPaM& rPam, RedlineType nType, bool bStartOrEndInRange ) const // xxx
2552 {
2553  SwPosition currentStart(*rPam.Start());
2554  SwPosition currentEnd(*rPam.End());
2555  SwNodeIndex pEndNodeIndex(currentEnd.nNode.GetNode());
2556 
2557  for( SwRedlineTable::size_type n = GetRedlinePos( rPam.Start()->nNode.GetNode(), nType );
2558  n < mpRedlineTable->size(); ++n )
2559  {
2560  const SwRangeRedline* pTmp = (*mpRedlineTable)[ n ];
2561 
2562  if ( pTmp->Start()->nNode > pEndNodeIndex )
2563  break;
2564 
2565  if( RedlineType::Any != nType && nType != pTmp->GetType() )
2566  continue;
2567 
2568  // redline over the range
2569  if ( currentStart < *pTmp->End() && *pTmp->Start() <= currentEnd &&
2570  // starting or ending within the range
2571  ( !bStartOrEndInRange ||
2572  ( currentStart <= *pTmp->Start() || *pTmp->End() <= currentEnd ) ) )
2573  {
2574  return true;
2575  }
2576  }
2577  return false;
2578 }
2579 
2581  SwRedlineTable::size_type* pFndPos ) const
2582 {
2583  SwRedlineTable::size_type nO = mpRedlineTable->size(), nM, nU = 0;
2584  if( nO > 0 )
2585  {
2586  nO--;
2587  while( nU <= nO )
2588  {
2589  nM = nU + ( nO - nU ) / 2;
2590  const SwRangeRedline* pRedl = (*mpRedlineTable)[ nM ];
2591  const SwPosition* pStt = pRedl->Start();
2592  const SwPosition* pEnd = pStt == pRedl->GetPoint()
2593  ? pRedl->GetMark()
2594  : pRedl->GetPoint();
2595  if( pEnd == pStt
2596  ? *pStt == rPos
2597  : ( *pStt <= rPos && rPos < *pEnd ) )
2598  {
2599  while( nM && rPos == *(*mpRedlineTable)[ nM - 1 ]->End() &&
2600  rPos == *(*mpRedlineTable)[ nM - 1 ]->Start() )
2601  {
2602  --nM;
2603  pRedl = (*mpRedlineTable)[ nM ];
2604  }
2605  // if there are format and insert changes in the same position
2606  // show insert change first.
2607  // since the redlines are sorted by position, only check the redline
2608  // before and after the current redline
2609  if( RedlineType::Format == pRedl->GetType() )
2610  {
2611  if( nM && rPos >= *(*mpRedlineTable)[ nM - 1 ]->Start() &&
2612  rPos <= *(*mpRedlineTable)[ nM - 1 ]->End() &&
2613  ( RedlineType::Insert == (*mpRedlineTable)[ nM - 1 ]->GetType() ) )
2614  {
2615  --nM;
2616  pRedl = (*mpRedlineTable)[ nM ];
2617  }
2618  else if( ( nM + 1 ) <= nO && rPos >= *(*mpRedlineTable)[ nM + 1 ]->Start() &&
2619  rPos <= *(*mpRedlineTable)[ nM + 1 ]->End() &&
2620  ( RedlineType::Insert == (*mpRedlineTable)[ nM + 1 ]->GetType() ) )
2621  {
2622  ++nM;
2623  pRedl = (*mpRedlineTable)[ nM ];
2624  }
2625  }
2626 
2627  if( pFndPos )
2628  *pFndPos = nM;
2629  return pRedl;
2630  }
2631  else if( *pEnd <= rPos )
2632  nU = nM + 1;
2633  else if( nM == 0 )
2634  {
2635  if( pFndPos )
2636  *pFndPos = nU;
2637  return nullptr;
2638  }
2639  else
2640  nO = nM - 1;
2641  }
2642  }
2643  if( pFndPos )
2644  *pFndPos = nU;
2645  return nullptr;
2646 
2647  // #TODO - add 'SwExtraRedlineTable' also ?
2648 }
2649 
2651 {
2652  bool bRet = false;
2653 
2654  // Switch to visible in any case
2658 
2659  SwRangeRedline* pTmp = (*mpRedlineTable)[ nPos ];
2660  pTmp->Show(0, mpRedlineTable->GetPos(pTmp), /*bForced=*/true);
2661  pTmp->Show(1, mpRedlineTable->GetPos(pTmp), /*bForced=*/true);
2662  if( pTmp->HasMark() && pTmp->IsVisible() )
2663  {
2665  {
2666  SwRewriter aRewriter;
2667 
2668  aRewriter.AddRule(UndoArg1, pTmp->GetDescr());
2670  }
2671 
2672  int nLoopCnt = 2;
2673  sal_uInt16 nSeqNo = pTmp->GetSeqNo();
2674 
2675  do {
2676 
2678  {
2680  std::make_unique<SwUndoAcceptRedline>(*pTmp) );
2681  }
2682 
2683  bRet |= lcl_AcceptRedline( *mpRedlineTable, nPos, bCallDelete );
2684 
2685  if( nSeqNo )
2686  {
2687  if( SwRedlineTable::npos == nPos )
2688  nPos = 0;
2689  SwRedlineTable::size_type nFndPos = 2 == nLoopCnt
2690  ? mpRedlineTable->FindNextSeqNo( nSeqNo, nPos )
2691  : mpRedlineTable->FindPrevSeqNo( nSeqNo, nPos );
2692  if( SwRedlineTable::npos != nFndPos || ( 0 != ( --nLoopCnt ) &&
2693  SwRedlineTable::npos != ( nFndPos =
2694  mpRedlineTable->FindPrevSeqNo( nSeqNo, nPos ))) )
2695  {
2696  nPos = nFndPos;
2697  pTmp = (*mpRedlineTable)[ nPos ];
2698  }
2699  else
2700  nLoopCnt = 0;
2701  }
2702  else
2703  nLoopCnt = 0;
2704 
2705  } while( nLoopCnt );
2706 
2707  if( bRet )
2708  {
2709  CompressRedlines();
2711  }
2712 
2714  {
2716  }
2717  }
2718  return bRet;
2719 
2720  // #TODO - add 'SwExtraRedlineTable' also ?
2721 }
2722 
2723 bool DocumentRedlineManager::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
2724 {
2725  // Switch to visible in any case
2729 
2730  // The Selection is only in the ContentSection. If there are Redlines
2731  // to Non-ContentNodes before or after that, then the Selections
2732  // expand to them.
2733  SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2734  lcl_AdjustRedlineRange( aPam );
2735 
2737  {
2739  m_rDoc.GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoAcceptRedline>( aPam ));
2740  }
2741 
2742  int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *mpRedlineTable,
2743  bCallDelete, aPam );
2744  if( nRet > 0 )
2745  {
2746  CompressRedlines();
2748  }
2750  {
2751  OUString aTmpStr;
2752 
2753  {
2754  SwRewriter aRewriter;
2755  aRewriter.AddRule(UndoArg1, OUString::number(nRet));
2756  aTmpStr = aRewriter.Apply(SwResId(STR_N_REDLINES));
2757  }
2758 
2759  SwRewriter aRewriter;
2760  aRewriter.AddRule(UndoArg1, aTmpStr);
2761 
2763  }
2764  return nRet != 0;
2765 
2766  // #TODO - add 'SwExtraRedlineTable' also ?
2767 }
2768 
2770 {
2771  const SwPosition* pStt = rPam.Start(),
2772  * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
2773  : rPam.GetPoint();
2774 
2775  const sal_uLong nSttIdx = pStt->nNode.GetIndex();
2776  const sal_uLong nEndIdx = pEnd->nNode.GetIndex();
2777 
2778  for( SwRedlineTable::size_type n = 0; n < mpRedlineTable->size() ; ++n )
2779  {
2780  const SwRangeRedline* pTmp = (*mpRedlineTable)[ n ];
2781  sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
2782  nMk = pTmp->GetMark()->nNode.GetIndex();
2783  if( nPt < nMk ) { tools::Long nTmp = nMk; nMk = nPt; nPt = nTmp; }
2784 
2785  if( RedlineType::ParagraphFormat == pTmp->GetType() &&
2786  ( (nSttIdx <= nMk && nMk <= nEndIdx) || (nSttIdx <= nPt && nPt <= nEndIdx) ) )
2787  AcceptRedline( n, false );
2788 
2789  if( nMk > nEndIdx )
2790  break;
2791  }
2792 }
2793 
2795 {
2796  bool bRet = false;
2797 
2798  // Switch to visible in any case
2802 
2803  SwRangeRedline* pTmp = (*mpRedlineTable)[ nPos ];
2804  pTmp->Show(0, mpRedlineTable->GetPos(pTmp), /*bForced=*/true);
2805  pTmp->Show(1, mpRedlineTable->GetPos(pTmp), /*bForced=*/true);
2806  if( pTmp->HasMark() && pTmp->IsVisible() )
2807  {
2809  {
2810  SwRewriter aRewriter;
2811 
2812  aRewriter.AddRule(UndoArg1, pTmp->GetDescr());
2814  }
2815 
2816  int nLoopCnt = 2;
2817  sal_uInt16 nSeqNo = pTmp->GetSeqNo();
2818 
2819  do {
2820 
2822  {
2824  std::make_unique<SwUndoRejectRedline>( *pTmp ) );
2825  }
2826 
2827  bRet |= lcl_RejectRedline( *mpRedlineTable, nPos, bCallDelete );
2828 
2829  if( nSeqNo )
2830  {
2831  if( SwRedlineTable::npos == nPos )
2832  nPos = 0;
2833  SwRedlineTable::size_type nFndPos = 2 == nLoopCnt
2834  ? mpRedlineTable->FindNextSeqNo( nSeqNo, nPos )
2835  : mpRedlineTable->FindPrevSeqNo( nSeqNo, nPos );
2836  if( SwRedlineTable::npos != nFndPos || ( 0 != ( --nLoopCnt ) &&
2837  SwRedlineTable::npos != ( nFndPos =
2838  mpRedlineTable->FindPrevSeqNo( nSeqNo, nPos ))) )
2839  {
2840  nPos = nFndPos;
2841  pTmp = (*mpRedlineTable)[ nPos ];
2842  }
2843  else
2844  nLoopCnt = 0;
2845  }
2846  else
2847  nLoopCnt = 0;
2848 
2849  } while( nLoopCnt );
2850 
2851  if( bRet )
2852  {
2853  CompressRedlines();
2855  }
2856 
2858  {
2860  }
2861  }
2862  return bRet;
2863 
2864  // #TODO - add 'SwExtraRedlineTable' also ?
2865 }
2866 
2867 bool DocumentRedlineManager::RejectRedline( const SwPaM& rPam, bool bCallDelete )
2868 {
2869  // Switch to visible in any case
2873 
2874  // The Selection is only in the ContentSection. If there are Redlines
2875  // to Non-ContentNodes before or after that, then the Selections
2876  // expand to them.
2877  SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2878  lcl_AdjustRedlineRange( aPam );
2879 
2881  {
2883  m_rDoc.GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoRejectRedline>(aPam) );
2884  }
2885 
2886  int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *mpRedlineTable,
2887  bCallDelete, aPam );
2888  if( nRet > 0 )
2889  {
2890  CompressRedlines();
2892  }
2894  {
2895  OUString aTmpStr;
2896 
2897  {
2898  SwRewriter aRewriter;
2899  aRewriter.AddRule(UndoArg1, OUString::number(nRet));
2900  aTmpStr = aRewriter.Apply(SwResId(STR_N_REDLINES));
2901  }
2902 
2903  SwRewriter aRewriter;
2904  aRewriter.AddRule(UndoArg1, aTmpStr);
2905 
2907  }
2908 
2909  return nRet != 0;
2910 
2911  // #TODO - add 'SwExtraRedlineTable' also ?
2912 }
2913 
2915 {
2916  bool bSuccess = true;
2917  OUString sUndoStr;
2919 
2920  if (mpRedlineTable->size() > 1)
2921  {
2922  {
2923  SwRewriter aRewriter;
2924  aRewriter.AddRule(UndoArg1, OUString::number(mpRedlineTable->size()));
2925  sUndoStr = aRewriter.Apply(SwResId(STR_N_REDLINES));
2926  }
2927 
2928  SwRewriter aRewriter;
2929  aRewriter.AddRule(UndoArg1, sUndoStr);
2930  rUndoMgr.StartUndo(bAccept ? SwUndoId::ACCEPT_REDLINE : SwUndoId::REJECT_REDLINE, &aRewriter);
2931  }
2932 
2933  while (!mpRedlineTable->empty() && bSuccess)
2934  {
2935  if (bAccept)
2936  bSuccess = AcceptRedline(mpRedlineTable->size() - 1, true);
2937  else
2938  bSuccess = RejectRedline(mpRedlineTable->size() - 1, true);
2939  }
2940 
2941  if (!sUndoStr.isEmpty())
2942  {
2943  rUndoMgr.EndUndo(SwUndoId::EMPTY, nullptr);
2944  }
2945 }
2946 
2948 {
2949  rPam.DeleteMark();
2950  rPam.SetMark();
2951 
2952  SwPosition& rSttPos = *rPam.GetPoint();
2953  SwPosition aSavePos( rSttPos );
2954  bool bRestart;
2955 
2956  // If the starting position points to the last valid ContentNode,
2957  // we take the next Redline in any case.
2959  const SwRangeRedline* pFnd = GetRedlineTable().FindAtPosition( rSttPos, n );
2960  if( pFnd )
2961  {
2962  const SwPosition* pEnd = pFnd->End();
2963  if( !pEnd->nNode.GetNode().IsContentNode() )
2964  {
2965  SwNodeIndex aTmp( pEnd->nNode );
2966  SwContentNode* pCNd = SwNodes::GoPrevSection( &aTmp );
2967  if( !pCNd || ( aTmp == rSttPos.nNode &&
2968  pCNd->Len() == rSttPos.nContent.GetIndex() ))
2969  pFnd = nullptr;
2970  }
2971  if( pFnd )
2972  rSttPos = *pFnd->End();
2973  }
2974 
2975  do {
2976  bRestart = false;
2977 
2978  for( ; !pFnd && n < mpRedlineTable->size(); ++n )
2979  {
2980  pFnd = (*mpRedlineTable)[ n ];
2981  if( pFnd->HasMark() && pFnd->IsVisible() )
2982  {
2983  *rPam.GetMark() = *pFnd->Start();
2984  rSttPos = *pFnd->End();
2985  break;
2986  }
2987  else
2988  pFnd = nullptr;
2989  }
2990 
2991  if( pFnd )
2992  {
2993  // Merge all of the same type and author that are
2994  // consecutive into one Selection.
2995  const SwPosition* pPrevEnd = pFnd->End();
2996  while( ++n < mpRedlineTable->size() )
2997  {
2998  const SwRangeRedline* pTmp = (*mpRedlineTable)[ n ];
2999  if( pTmp->HasMark() && pTmp->IsVisible() )
3000  {
3001  const SwPosition *pRStt;
3002  if( pFnd->GetType() != pTmp->GetType() ||
3003  pFnd->GetAuthor() != pTmp->GetAuthor() )
3004  break;
3005  pRStt = pTmp->Start();
3006  if( *pPrevEnd == *pRStt || IsPrevPos( *pPrevEnd, *pRStt ) )
3007  {
3008  pPrevEnd = pTmp->End();
3009  rSttPos = *pPrevEnd;
3010  }
3011  else
3012  break;
3013  }
3014  }
3015  }
3016 
3017  if( pFnd )
3018  {
3019  const SwRangeRedline* pSaveFnd = pFnd;
3020 
3021  SwContentNode* pCNd;
3022  SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
3023  if( !pIdx->GetNode().IsContentNode() )
3024  {
3025  pCNd = m_rDoc.GetNodes().GoNextSection( pIdx );
3026  if( pCNd )
3027  {
3028  if( *pIdx <= rPam.GetPoint()->nNode )
3029  rPam.GetMark()->nContent.Assign( pCNd, 0 );
3030  else
3031  pFnd = nullptr;
3032  }
3033  }
3034 
3035  if( pFnd )
3036  {
3037  pIdx = &rPam.GetPoint()->nNode;
3038  if( !pIdx->GetNode().IsContentNode() )
3039  {
3040  pCNd = SwNodes::GoPrevSection( pIdx );
3041  if( pCNd )
3042  {
3043  if( *pIdx >= rPam.GetMark()->nNode )
3044  rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
3045  else
3046  pFnd = nullptr;
3047  }
3048  }
3049  }
3050 
3051  if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
3052  {
3053  if( n < mpRedlineTable->size() )
3054  {
3055  bRestart = true;
3056  *rPam.GetPoint() = *pSaveFnd->End();
3057  }
3058  else
3059  {
3060  rPam.DeleteMark();
3061  *rPam.GetPoint() = aSavePos;
3062  }
3063  pFnd = nullptr;
3064  }
3065  }
3066  } while( bRestart );
3067 
3068  return pFnd;
3069 
3070  // #TODO - add 'SwExtraRedlineTable' also ?
3071 }
3072 
3074 {
3075  rPam.DeleteMark();
3076  rPam.SetMark();
3077 
3078  SwPosition& rSttPos = *rPam.GetPoint();
3079  SwPosition aSavePos( rSttPos );
3080  bool bRestart;
3081 
3082  // If the starting position points to the last valid ContentNode,
3083  // we take the previous Redline in any case.
3085  const SwRangeRedline* pFnd = GetRedlineTable().FindAtPosition( rSttPos, n, false );
3086  if( pFnd )
3087  {
3088  const SwPosition* pStt = pFnd->Start();
3089  if( !pStt->nNode.GetNode().IsContentNode() )
3090  {
3091  SwNodeIndex aTmp( pStt->nNode );
3092  SwContentNode* pCNd = m_rDoc.GetNodes().GoNextSection( &aTmp );
3093  if( !pCNd || ( aTmp == rSttPos.nNode &&
3094  !rSttPos.nContent.GetIndex() ))
3095  pFnd = nullptr;
3096  }
3097  if( pFnd )
3098  rSttPos = *pFnd->Start();
3099  }
3100 
3101  do {
3102  bRestart = false;
3103 
3104  while( !pFnd && 0 < n )
3105  {
3106  pFnd = (*mpRedlineTable)[ --n ];
3107  if( pFnd->HasMark() && pFnd->IsVisible() )
3108  {
3109  *rPam.GetMark() = *pFnd->End();
3110  rSttPos = *pFnd->Start();
3111  }
3112  else
3113  pFnd = nullptr;
3114  }
3115 
3116  if( pFnd )
3117  {
3118  // Merge all of the same type and author that are
3119  // consecutive into one Selection.
3120  const SwPosition* pNextStt = pFnd->Start();
3121  while( 0 < n )
3122  {
3123  const SwRangeRedline* pTmp = (*mpRedlineTable)[ --n ];
3124  if( pTmp->HasMark() && pTmp->IsVisible() )
3125  {
3126  const SwPosition *pREnd;
3127  if( pFnd->GetType() == pTmp->GetType() &&
3128  pFnd->GetAuthor() == pTmp->GetAuthor() &&
3129  ( *pNextStt == *( pREnd = pTmp->End() ) ||
3130  IsPrevPos( *pREnd, *pNextStt )) )
3131  {
3132  pNextStt = pTmp->Start();
3133  rSttPos = *pNextStt;
3134  }
3135  else
3136  {
3137  ++n;
3138  break;
3139  }
3140  }
3141  }
3142  }
3143 
3144  if( pFnd )
3145  {
3146  const SwRangeRedline* pSaveFnd = pFnd;
3147 
3148  SwContentNode* pCNd;
3149  SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
3150  if( !pIdx->GetNode().IsContentNode() )
3151  {
3152  pCNd = SwNodes::GoPrevSection( pIdx );
3153  if( pCNd )
3154  {
3155  if( *pIdx >= rPam.GetPoint()->nNode )
3156  rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() );
3157  else
3158  pFnd = nullptr;
3159  }
3160  }
3161 
3162  if( pFnd )
3163  {
3164  pIdx = &rPam.GetPoint()->nNode;
3165  if( !pIdx->GetNode().IsContentNode() )
3166  {
3167  pCNd = m_rDoc.GetNodes().GoNextSection( pIdx );
3168  if( pCNd )
3169  {
3170  if( *pIdx <= rPam.GetMark()->nNode )
3171  rPam.GetPoint()->nContent.Assign( pCNd, 0 );
3172  else
3173  pFnd = nullptr;
3174  }
3175  }
3176  }
3177 
3178  if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
3179  {
3180  if( n )
3181  {
3182  bRestart = true;
3183  *rPam.GetPoint() = *pSaveFnd->Start();
3184  }
3185  else
3186  {
3187  rPam.DeleteMark();
3188  *rPam.GetPoint() = aSavePos;
3189  }
3190  pFnd = nullptr;
3191  }
3192  }
3193  } while( bRestart );
3194 
3195  return pFnd;
3196 
3197  // #TODO - add 'SwExtraRedlineTable' also ?
3198 }
3199 
3200 // Set comment at the Redline
3201 bool DocumentRedlineManager::SetRedlineComment( const SwPaM& rPaM, const OUString& rS )
3202 {
3203  bool bRet = false;
3204  const SwPosition* pStt = rPaM.Start(),
3205  * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
3206  : rPaM.GetPoint();
3208  if( GetRedlineTable().FindAtPosition( *pStt, n ) )
3209  {
3210  for( ; n < mpRedlineTable->size(); ++n )
3211  {
3212  bRet = true;
3213  SwRangeRedline* pTmp = (*mpRedlineTable)[ n ];
3214  if( pStt != pEnd && *pTmp->Start() > *pEnd )
3215  break;
3216 
3217  pTmp->SetComment( rS );
3218  if( *pTmp->End() >= *pEnd )
3219  break;
3220  }
3221  }
3222  if( bRet )
3224 
3225  return bRet;
3226 
3227  // #TODO - add 'SwExtraRedlineTable' also ?
3228 }
3229 
3230 // Create a new author if necessary
3232 {
3233  return SW_MOD()->GetRedlineAuthor();
3234 }
3235 
3237 std::size_t DocumentRedlineManager::InsertRedlineAuthor( const OUString& rNew )
3238 {
3239  return SW_MOD()->InsertRedlineAuthor(rNew);
3240 }
3241 
3243 {
3244  const SwRedlineTable& rTable = GetRedlineTable();
3245  for(SwRangeRedline* pRedl : rTable)
3246  {
3247  if( pRedl->IsVisible() )
3249  }
3250 
3251  // #TODO - add 'SwExtraRedlineTable' also ?
3252 }
3253 
3254 const uno::Sequence <sal_Int8>& DocumentRedlineManager::GetRedlinePassword() const
3255 {
3256  return maRedlinePasswd;
3257 }
3258 
3260  /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
3261 {
3262  maRedlinePasswd = rNewPassword;
3264 }
3265 
3270 void DocumentRedlineManager::SetAutoFormatRedlineComment( const OUString* pText, sal_uInt16 nSeqNo )
3271 {
3272  m_rDoc.SetAutoFormatRedline( nullptr != pText );
3273  if( pText )
3274  {
3275  mpAutoFormatRedlnComment.reset( new OUString( *pText ) );
3276  }
3277  else
3278  {
3279  mpAutoFormatRedlnComment.reset();
3280  }
3281 
3282  mnAutoFormatRedlnCommentNo = nSeqNo;
3283 }
3284 
3286 {
3287 }
3288 
3289 }
3290 
3291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:685
Starts a section of nodes in the document model.
Definition: node.hxx:311
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:151
virtual sal_Int32 Len() const
Definition: node.cxx:1241
void DeleteMark()
Definition: pam.hxx:177
std::unique_ptr< SwRedlineTable > mpRedlineTable
bool CanCombine(const SwRangeRedline &rRedl) const
Definition: docredln.cxx:1710
sal_uLong GetIndex() const
Definition: node.hxx:290
const SwRedlineExtraData * GetExtraData() const
Definition: redline.hxx:215
virtual AppendResult AppendRedline(SwRangeRedline *pPtr, bool bCallDelete) override
Append a new redline.
void Show(sal_uInt16 nLoop, size_t nMyPos, bool bForced=false)
Definition: docredln.cxx:1118
sal_uInt16 GetSeqNo() const
Definition: redline.hxx:221
Represents the style of a paragraph.
Definition: fmtcol.hxx:56
virtual std::size_t InsertRedlineAuthor(const OUString &rAuthor) override
Insert new author into the Table for the Readers etc.
Marks a position in the document model.
Definition: pam.hxx:35
void UpdateFramesForAddDeleteRedline(SwDoc &rDoc, SwPaM const &rPam)
SwComparePosition ComparePosition(const T &rStt1, const T &rEnd1, const T &rStt2, const T &rEnd2)
Definition: pam.hxx:77
const OUString & GetText() const
Definition: ndtxt.hxx:211
virtual const SwRootFrame * GetCurrentLayout() const =0
virtual std::size_t GetRedlineAuthor() override
SwDocShell * GetDocShell()
Definition: doc.hxx:1352
virtual void SetRedlineFlags(RedlineFlags eMode) override
Set a new redline mode.
virtual void SetRedlineFlags_intern(RedlineFlags eMode)=0
Set a new redline mode.
virtual SwFieldType * GetFieldType(SwFieldIds nResId, const OUString &rName, bool bDbFieldMatching) const =0
SwNodeIndex nNode
Definition: pam.hxx:37
virtual void InsertItemSet(const SwPaM &rRg, const SfxItemSet &, const SetAttrMode nFlags=SetAttrMode::DEFAULT, SwRootFrame const *pLayout=nullptr)=0
virtual const SwRedlineTable & GetRedlineTable() const override
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:274
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
long Long
Pos1 is as large as Pos2.
const SwPosition * GetMark() const
Definition: pam.hxx:209
Pos1 completely contained in Pos2.
sal_Int64 n
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
void Remove(size_type nPos)
Definition: docredln.cxx:616
void SetSeqNo(sal_uInt16 nNo)
Definition: redline.hxx:222
Definition: doc.hxx:186
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:1959
TElementType * Next()
Definition: calbck.hxx:339
#define ERROR_PREFIX
void SetEnd(const SwPosition &rPos, SwPosition *pEndPtr=nullptr)
Definition: docredln.cxx:1083
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, RedlineType nDelType) override
virtual void DeleteRange(SwPaM &)=0
Delete a range SwFlyFrameFormat.
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1301
SwNode & GetNode() const
Definition: ndindex.hxx:119
virtual const SwExtraRedlineTable & GetExtraRedlineTable() const override
virtual void UpdateRedlineAttr() override
Dialog to specify the properties of date form field.
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
virtual bool DeleteAndJoin(SwPaM &, const bool bForceJoinNext=false)=0
complete delete of a given PaM
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:743
bool HasValidRange() const
Do we have a valid selection?
Definition: docredln.cxx:1092
show all inserts
size_type size() const
Definition: docary.hxx:266
void UpdateFields() const
Definition: fldbas.cxx:148
virtual void UpdateExpFields(SwTextField *pField, bool bUpdateRefFields)=0
Pos1 end touches at Pos2 start.
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
SwDoc & m_rDoc
Definition: docbm.cxx:1205
bool IsOwnRedline(const SwRangeRedline &rRedl) const
Definition: redline.hxx:240
virtual const SwRangeRedline * SelPrevRedline(SwPaM &rPam) const override
virtual void Reject(SwPaM &rPam) const
Definition: docredln.cxx:754
constexpr sal_uInt16 RES_PARATR_BEGIN(RES_TXTATR_END)
SwIndex nContent
Definition: pam.hxx:38
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void ResetAttrs(const SwPaM &rRg, bool bTextAttr=true, const o3tl::sorted_vector< sal_uInt16 > &rAttrs=o3tl::sorted_vector< sal_uInt16 >(), const bool bSendDataChangedEvents=true, SwRootFrame const *pLayout=nullptr)
Reset attributes.
Definition: docfmt.cxx:242
bool SetTextFormatColl(const SwPaM &rRg, SwTextFormatColl *pFormat, const bool bReset=true, const bool bResetListAttrs=false, SwRootFrame const *pLayout=nullptr)
Add 4th optional parameter .
Definition: docfmt.cxx:1072
std::unique_ptr< sw::MergedPara > CheckParaRedlineMerge(SwTextFrame &rFrame, SwTextNode &rTextNode, FrameMode eMode)
Definition: redlnitr.cxx:205
const OUString & GetName() const
Definition: format.hxx:132
int nCount
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
Pos2 completely contained in Pos1.
void AddRemoveFlysAnchoredToFrameStartingAtNode(SwTextFrame &rFrame, SwTextNode &rTextNode, std::set< sal_uLong > *pSkipped)
rTextNode is the first one of the "new" merge - if rTextNode isn't the same as MergedPara::pFirstNode...
Definition: wsfrm.cxx:4248
void SetInXMLImport(bool bNew)
Definition: doc.hxx:972
Mode eMode
o3tl::sorted_vector< SwRootFrame * > GetAllLayouts()
Definition: doclay.cxx:1669
void ShowOriginal(sal_uInt16 nLoop, size_t nMyPos, bool bForced=false)
Definition: docredln.cxx:1208
Pos1 before Pos2.
RedlineFlags on.
virtual bool DoesUndo() const =0
Is Undo enabled?
sal_uInt16 GetStackCount() const
Definition: docredln.cxx:1742
void SetExtraData(const SwRedlineExtraData *pData)
ExtraData gets copied, the pointer is therefore not taken over by the RedLineObject.
Definition: redline.hxx:213
void MakeFrames(SwDoc *pDoc, const SwNodeIndex &rSttIdx, const SwNodeIndex &rEndIdx)
Definition: frmtool.cxx:1943
Redline that holds information about a table-cell that had some change.
Definition: redline.hxx:301
virtual void AcceptAllRedline(bool bAcceptReject) override
OUString GetDescr(bool bSimplified=false)
Returns textual description of a redline data element of this redline.
Definition: docredln.cxx:1801
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:163
bool ContainsPosition(const SwPosition &rPos) const
Definition: pam.hxx:257
void DelNumRules(const SwPaM &, SwRootFrame const *pLayout=nullptr)
Definition: docnum.cxx:1324
void InvalidateRange(Invalidation)
Initiate the layout.
Definition: docredln.cxx:1251
Table that holds 'extra' redlines, such as 'table row insert/delete', 'paragraph moves' etc...
Definition: docary.hxx:277
bool IsContentNode() const
Definition: node.hxx:631
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
virtual void UpdateRefFields()=0
virtual void AppendUndo(std::unique_ptr< SwUndo > pUndo)=0
Add new Undo action.
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
#define SW_MOD()
Definition: swmodule.hxx:255
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const override
int i
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
void DeleteAndDestroy(size_type nPos)
Definition: docredln.cxx:644
const SwPosition * GetPoint() const
Definition: pam.hxx:207
Pos1 start touches at Pos2 end.
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
OUString Apply(const OUString &rStr) const
Definition: SwRewriter.cxx:41
virtual void SetRedlinePassword(const css::uno::Sequence< sal_Int8 > &rNewPassword) override
void SetFormatAll(bool bAll)
Definition: redline.hxx:69
bool GetParaAttr(SfxItemSet &rSet, sal_Int32 nStt, sal_Int32 nEnd, const bool bOnlyTextAttr=false, const bool bGetFromChrFormat=true, const bool bMergeIndentValuesOfNumRule=false, SwRootFrame const *pLayout=nullptr) const
Query the attributes of textnode over the range.
Definition: thints.cxx:2110
Document fields related interfaces.
virtual void AcceptRedlineParagraphFormatting(const SwPaM &rPam) override
TElementType * First()
Definition: calbck.hxx:331
static bool IsShowOriginal(const RedlineFlags eM)
virtual const SwRangeRedline * SelNextRedline(SwPaM &rPam) const override
SwContentNode * GetContentNode()
Definition: node.hxx:618
vector_type::size_type size_type
Definition: docary.hxx:228
virtual bool HasExtraRedlineTable() const override
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
void Hide(sal_uInt16 nLoop, size_t nMyPos, bool bForced=false)
Definition: docredln.cxx:1172
float u
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:27
virtual RedlineFlags GetRedlineFlags() const override
Replaced by SwRootFrame::IsHideRedlines() (this is model-level redline hiding).
#define CHECK_REDLINE(pDoc)
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2775
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:394
const SwRangeRedline * FindAtPosition(const SwPosition &startPosition, size_type &tableIndex, bool next=true) const
Find the redline at the given position.
Definition: docredln.cxx:711
size
Marks a node in the document model.
Definition: ndindex.hxx:31
void MoveMergedFlysAndFootnotes(std::vector< SwTextFrame * > const &rFrames, SwTextNode const &rFirstNode, SwTextNode &rSecondNode, bool)
Definition: ndtxt.cxx:358
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:696
OUString SwResId(const char *pId)
Definition: swmodule.cxx:166
virtual bool SplitRedline(const SwPaM &rPam) override
virtual bool HasRedline(const SwPaM &rPam, RedlineType nType, bool bStartOrEndInRange) const override
std::unique_ptr< SwExtraRedlineTable > mpExtraRedlineTable
virtual bool IsInRedlines(const SwNode &rNode) const override
void SetAutoFormatRedlineComment(const OUString *pText, sal_uInt16 nSeqNo=0)
Set comment-text for Redline.
Redline that holds information about a table-row that had some change.
Definition: redline.hxx:280
show all deletes
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
enumrange< T >::Iterator end(enumrange< T >)
const SwPosition * Start() const
Definition: pam.hxx:212
bool IsVisible() const
Definition: redline.hxx:187
constexpr TypedWhichId< SwFormatContent > RES_CNTNT(95)
virtual void SetRedlineMove(bool bFlag) override
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
virtual bool RejectRedline(SwRedlineTable::size_type nPos, bool bCallDelete) override
void SetComment(const OUString &rS)
Definition: redline.hxx:209
ignore Redlines
virtual bool IsRedlineMove() const override
void UpdateFootnote(const SwNodeIndex &rStt)
Definition: ftnidx.cxx:60
constexpr sal_uInt16 RES_FRMATR_END(131)
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:680
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
std::unique_ptr< OUString > mpAutoFormatRedlnComment
sal_uInt16 mnAutoFormatRedlnCommentNo
SeqNo for conjoining of AutoFormat-Redlines.
std::size_t GetAuthor(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1750
void UpdateFramesForRemoveDeleteRedline(SwDoc &rDoc, SwPaM const &rPam)
#define SAL_WARN_IF(condition, area, stream)
void AppendAllObjs(const SwFrameFormats *pTable, const SwFrame *pSib)
Definition: frmtool.cxx:1332
Pos1 overlaps Pos2 at the end.
void PushData(const SwRangeRedline &rRedl, bool bOwnAsNext=true)
Definition: docredln.cxx:1716
virtual void CompressRedlines() override
static void UpdateFieldsForRedline(IDocumentFieldsAccess &rIDFA)
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:254
virtual void SetRedlineFlags_intern(RedlineFlags eMode) override
Set a new redline mode.
static bool IsHideChanges(const RedlineFlags eM)
virtual bool DelFullPara(SwPaM &)=0
Delete full paragraphs.
virtual bool SetRedlineComment(const SwPaM &rPam, const OUString &rComment) override
sal_Int32 GetIndex() const
Definition: index.hxx:91
bool IsClipBoard() const
Definition: doc.hxx:964
virtual bool IsRedlineOn() const =0
Query if redlining is on.
virtual bool AcceptRedline(SwRedlineTable::size_type nPos, bool bCallDelete) override
constexpr sal_uInt16 RES_PARATR_LIST_BEGIN(RES_PARATR_END)
SwNodes & GetNodes()
Definition: doc.hxx:407
void SetAutoFormat()
Definition: redline.hxx:199
const SwPosition * End() const
Definition: pam.hxx:217
constexpr sal_uInt16 RES_PARATR_END(82)
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1765
QPRO_FUNC_TYPE nType
bool IsAutoFormatRedline() const
Definition: doc.hxx:1447
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const override
virtual bool IsIgnoreRedline() const override
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:632
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
SwContentNode * GoNextSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true) const
Go to next content-node that is not protected or hidden (Both set FALSE ==> GoNext/GoPrevious!!!).
Definition: nodes.cxx:1907
bool IsTableNode() const
Definition: node.hxx:643
SwDoc & GetDoc() const
Definition: pam.hxx:243
bool HasMergedParas() const
Definition: rootfrm.hxx:424
virtual SwFieldType * GetSysFieldType(const SwFieldIds eWhich) const =0
RedlineType
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:476
Pos1 behind Pos2.
tuple m
css::uno::Sequence< sal_Int8 > maRedlinePasswd
virtual const SwRedlineTable & GetRedlineTable() const =0
bool Insert(SwRangeRedline *&p)
Definition: docredln.cxx:430
SwNode & GetEndOfRedlines() const
Section for all Redlines.
Definition: ndarr.hxx:158
std::pair< const_iterator, bool > insert(Value &&x)
const SwIndexReg * GetIdxReg() const
Definition: index.hxx:97
static constexpr size_type npos
Definition: docary.hxx:229
virtual const css::uno::Sequence< sal_Int8 > & GetRedlinePassword() const override
constexpr TypedWhichId< SvxULSpaceItem > RES_UL_SPACE(92)
SwNodeIndex * GetContentIdx() const
Definition: redline.hxx:183
virtual bool IsRedlineOn() const override
Query if redlining is on.
Pos1 overlaps Pos2 at the beginning.
virtual bool AppendTableRowRedline(SwTableRowRedline *pPtr) override
void SetStart(const SwPosition &rPos, SwPosition *pSttPtr=nullptr)
Definition: docredln.cxx:1075
bool IsInXMLImport() const
Definition: doc.hxx:971
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1319
SwComparePosition
Definition: pam.hxx:64
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:846
virtual bool AppendTableCellRedline(SwTableCellRedline *pPtr) override
void SetAutoFormatRedline(bool bFlag)
Definition: doc.hxx:1448
void CheckAnchoredFlyConsistency(SwDoc const &rDoc)
Definition: atrfrm.cxx:3576
Base class of the Writer document model elements.
Definition: node.hxx:79
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:840
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo