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