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