LibreOffice Module sw (master)  1
XMLRedlineImportHelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
23 
24 #include <cstddef>
25 
27 #include <unotextcursor.hxx>
28 #include <unotextrange.hxx>
29 #include <unocrsr.hxx>
30 #include <ndtxt.hxx>
31 #include <doc.hxx>
34 #include <tools/datetime.hxx>
35 #include <poolfmt.hxx>
36 #include <unoredline.hxx>
38 #include "xmlimp.hxx"
39 #include <o3tl/any.hxx>
40 #include <xmloff/xmltoken.hxx>
41 #include <vcl/svapp.hxx>
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45 using namespace ::xmloff::token;
46 
47 using ::com::sun::star::text::XTextCursor;
48 using ::com::sun::star::text::XTextRange;
49 using ::com::sun::star::text::XWordCursor;
50 using ::com::sun::star::lang::XUnoTunnel;
51 using ::com::sun::star::beans::XPropertySet;
52 using ::com::sun::star::beans::XPropertySetInfo;
53 // collision with tools/DateTime: use UNO DateTime as util::DateTime
54 // using util::DateTime;
55 
56 // a few helper functions
57 static SwDoc* lcl_GetDocViaTunnel( Reference<XTextCursor> const & rCursor )
58 {
59  Reference<XUnoTunnel> xTunnel( rCursor, UNO_QUERY);
60  OSL_ENSURE(xTunnel.is(), "missing XUnoTunnel for XTextCursor");
61  OTextCursorHelper *const pXCursor =
62  comphelper::getFromUnoTunnel<OTextCursorHelper>(xTunnel);
63  OSL_ENSURE( pXCursor, "OTextCursorHelper missing" );
64  return pXCursor ? pXCursor->GetDoc() : nullptr;
65 }
66 
67 static SwDoc* lcl_GetDocViaTunnel( Reference<XTextRange> const & rRange )
68 {
69  Reference<XUnoTunnel> xTunnel(rRange, UNO_QUERY);
70  OSL_ENSURE(xTunnel.is(), "missing XUnoTunnel for XTextRange");
71  SwXTextRange *const pXRange =
72  comphelper::getFromUnoTunnel<SwXTextRange>(xTunnel);
73  // #i115174#: this may be a SvxUnoTextRange
74  // OSL_ENSURE( pXRange, "SwXTextRange missing" );
75  return pXRange ? &pXRange->GetDoc() : nullptr;
76 }
77 
78 // XTextRangeOrNodeIndexPosition: store a position into the text
79 // *either* as an XTextRange or as an SwNodeIndex. The reason is that
80 // we must store either pointers to StartNodes (because redlines may
81 // start on start nodes) or to a text position, and there appears to
82 // be no existing type that could do both. Things are complicated by
83 // the matter that (e.g in section import) we delete a few characters,
84 // which may cause bookmarks (as used by XTextRange) to be deleted.
85 
86 namespace {
87 
88 class XTextRangeOrNodeIndexPosition
89 {
90  Reference<XTextRange> m_xRange;
91  std::unique_ptr<SwNodeIndex> m_pIndex; // pIndex will point to the *previous* node
92 
93 public:
94  XTextRangeOrNodeIndexPosition();
95 
96  void Set( Reference<XTextRange> const & rRange );
97  void Set( SwNodeIndex const & rIndex );
98  void SetAsNodeIndex( Reference<XTextRange> const & rRange );
99 
100  void CopyPositionInto(SwPosition& rPos, SwDoc & rDoc);
101  SwDoc* GetDoc();
102 
103  bool IsValid() const;
104 };
105 
106 }
107 
108 XTextRangeOrNodeIndexPosition::XTextRangeOrNodeIndexPosition()
109 {
110 }
111 
112 void XTextRangeOrNodeIndexPosition::Set( Reference<XTextRange> const & rRange )
113 {
114  m_xRange = rRange->getStart(); // set bookmark
115  m_pIndex.reset();
116 }
117 
118 void XTextRangeOrNodeIndexPosition::Set( SwNodeIndex const & rIndex )
119 {
120  m_pIndex.reset( new SwNodeIndex(rIndex) );
121  (*m_pIndex)-- ; // previous node!!!
122  m_xRange = nullptr;
123 }
124 
125 void XTextRangeOrNodeIndexPosition::SetAsNodeIndex(
126  Reference<XTextRange> const & rRange )
127 {
128  // XTextRange -> XTunnel -> SwXTextRange
129  SwDoc* pDoc = lcl_GetDocViaTunnel(rRange);
130 
131  if (!pDoc)
132  {
133  SAL_WARN("sw", "no SwDoc");
134  return;
135  }
136 
137  // SwXTextRange -> PaM
138  SwUnoInternalPaM aPaM(*pDoc);
139  bool bSuccess = ::sw::XTextRangeToSwPaM(aPaM, rRange);
140  OSL_ENSURE(bSuccess, "illegal range");
141 
142  // PaM -> Index
143  Set(aPaM.GetPoint()->nNode);
144 }
145 
146 void
147 XTextRangeOrNodeIndexPosition::CopyPositionInto(SwPosition& rPos, SwDoc & rDoc)
148 {
149  OSL_ENSURE(IsValid(), "Can't get Position");
150 
151  // create PAM from start cursor (if no node index is present)
152  if (nullptr == m_pIndex)
153  {
154  SwUnoInternalPaM aUnoPaM(rDoc);
155  bool bSuccess = ::sw::XTextRangeToSwPaM(aUnoPaM, m_xRange);
156  OSL_ENSURE(bSuccess, "illegal range");
157 
158  rPos = *aUnoPaM.GetPoint();
159  }
160  else
161  {
162  rPos.nNode = *m_pIndex;
163  rPos.nNode++; // pIndex points to previous index !!!
164  rPos.nContent.Assign( rPos.nNode.GetNode().GetContentNode(), 0 );
165  }
166 }
167 
168 SwDoc* XTextRangeOrNodeIndexPosition::GetDoc()
169 {
170  OSL_ENSURE(IsValid(), "Can't get Doc");
171 
172  return (nullptr != m_pIndex) ? &m_pIndex->GetNodes().GetDoc() : lcl_GetDocViaTunnel(m_xRange);
173 }
174 
175 bool XTextRangeOrNodeIndexPosition::IsValid() const
176 {
177  return ( m_xRange.is() || (m_pIndex != nullptr) );
178 }
179 
180 // RedlineInfo: temporary storage for redline data
182 {
183 public:
184  RedlineInfo();
185  ~RedlineInfo();
186 
187  // redline type (insert, delete, ...)
189 
190  // info fields:
191  OUString sAuthor; // change author string
192  OUString sComment; // change comment string
193  util::DateTime aDateTime; // change DateTime
194  bool bMergeLastParagraph; // the SwRangeRedline::IsDelLastPara flag
195 
196  // each position can may be either empty, an XTextRange, or an SwNodeIndex
197 
198  // start pos of anchor (may be empty)
199  XTextRangeOrNodeIndexPosition aAnchorStart;
200 
201  // end pos of anchor (may be empty)
202  XTextRangeOrNodeIndexPosition aAnchorEnd;
203 
204  // index of content node (maybe NULL)
206 
207  // next redline info (for hierarchical redlines)
209 
210  // store whether we expect an adjustment for this redline
212 };
213 
216  bMergeLastParagraph( false ),
217  pContentIndex(nullptr),
218  pNextRedline(nullptr),
219  bNeedsAdjustment( false )
220 {
221 }
222 
224 {
225  delete pContentIndex;
226  delete pNextRedline;
227 }
228 
229 constexpr OUStringLiteral g_sShowChanges = u"ShowChanges";
230 constexpr OUStringLiteral g_sRecordChanges = u"RecordChanges";
231 constexpr OUStringLiteral g_sRedlineProtectionKey = u"RedlineProtectionKey";
232 
234  SvXMLImport & rImport,
235  bool bNoRedlinesPlease,
236  const Reference<XPropertySet> & rModel,
237  const Reference<XPropertySet> & rImportInfo )
238  : m_rImport(rImport),
239  m_sInsertion( GetXMLToken( XML_INSERTION )),
240  m_sDeletion( GetXMLToken( XML_DELETION )),
241  m_sFormatChange( GetXMLToken( XML_FORMAT_CHANGE )),
242  m_bIgnoreRedlines(bNoRedlinesPlease),
243  m_xModelPropertySet(rModel),
244  m_xImportInfoPropertySet(rImportInfo)
245 {
246  // check to see if redline mode is handled outside of component
247  bool bHandleShowChanges = true;
248  bool bHandleRecordChanges = true;
249  bool bHandleProtectionKey = true;
250  if ( m_xImportInfoPropertySet.is() )
251  {
252  Reference<XPropertySetInfo> xInfo =
253  m_xImportInfoPropertySet->getPropertySetInfo();
254 
255  bHandleShowChanges = ! xInfo->hasPropertyByName( g_sShowChanges );
256  bHandleRecordChanges = ! xInfo->hasPropertyByName( g_sRecordChanges );
257  bHandleProtectionKey = ! xInfo->hasPropertyByName( g_sRedlineProtectionKey );
258  }
259 
260  // get redline mode
261  m_bShowChanges = *o3tl::doAccess<bool>(
262  ( bHandleShowChanges ? m_xModelPropertySet : m_xImportInfoPropertySet )
263  ->getPropertyValue( g_sShowChanges ));
264  m_bRecordChanges = *o3tl::doAccess<bool>(
265  ( bHandleRecordChanges ? m_xModelPropertySet : m_xImportInfoPropertySet )
266  ->getPropertyValue( g_sRecordChanges ));
267  {
268  Any aAny = (bHandleProtectionKey ? m_xModelPropertySet
270  ->getPropertyValue( g_sRedlineProtectionKey );
271  aAny >>= m_aProtectionKey;
272  }
273 
274  // set redline mode to "don't record changes"
275  if( bHandleRecordChanges )
276  {
277  m_xModelPropertySet->setPropertyValue( g_sRecordChanges, makeAny(false) );
278  }
279 }
280 
282 {
283  // delete all left over (and obviously incomplete) RedlineInfos (and map)
284  for( const auto& rEntry : m_aRedlineMap )
285  {
286  RedlineInfo* pInfo = rEntry.second;
287 
288  // left-over redlines. Insert them if possible (but assert),
289  // and delete the incomplete ones. Finally, delete it.
290  if( IsReady(pInfo) )
291  {
292  OSL_FAIL("forgotten RedlineInfo; now inserted");
293  InsertIntoDocument( pInfo );
294  }
295  else
296  {
297  // try if only the adjustment was missing
298  pInfo->bNeedsAdjustment = false;
299  if( IsReady(pInfo) )
300  {
301  OSL_FAIL("RedlineInfo without adjustment; now inserted");
302  InsertIntoDocument( pInfo );
303  }
304  else
305  {
306  // this situation occurs if redlines aren't closed
307  // (i.e. end without start, or start without
308  // end). This may well be a problem in the file,
309  // rather than the code.
310  OSL_FAIL("incomplete redline (maybe file was corrupt); "
311  "now deleted");
312  }
313  }
314  delete pInfo;
315  }
316  m_aRedlineMap.clear();
317 
318  // set redline mode, either to info property set, or directly to
319  // the document
320  bool bHandleShowChanges = true;
321  bool bHandleRecordChanges = true;
322  bool bHandleProtectionKey = true;
323  if ( m_xImportInfoPropertySet.is() )
324  {
325  Reference<XPropertySetInfo> xInfo =
326  m_xImportInfoPropertySet->getPropertySetInfo();
327 
328  bHandleShowChanges = ! xInfo->hasPropertyByName( g_sShowChanges );
329  bHandleRecordChanges = ! xInfo->hasPropertyByName( g_sRecordChanges );
330  bHandleProtectionKey = ! xInfo->hasPropertyByName( g_sRedlineProtectionKey );
331  }
332 
333  // set redline mode & key
334  try
335  {
336  Any aAny;
337 
338  aAny <<= m_bShowChanges;
339  if ( bHandleShowChanges )
340  {
341  aAny <<= true;
342  m_xModelPropertySet->setPropertyValue( g_sShowChanges, aAny );
343  // TODO maybe we need some property for the view-setting?
345  assert(pDoc);
347  }
348  else
349  m_xImportInfoPropertySet->setPropertyValue( g_sShowChanges, aAny );
350 
351  aAny <<= m_bRecordChanges;
352  if ( bHandleRecordChanges )
353  m_xModelPropertySet->setPropertyValue( g_sRecordChanges, aAny );
354  else
355  m_xImportInfoPropertySet->setPropertyValue( g_sRecordChanges, aAny );
356 
357  aAny <<= m_aProtectionKey;
358  if ( bHandleProtectionKey )
359  m_xModelPropertySet->setPropertyValue( g_sRedlineProtectionKey, aAny );
360  else
361  m_xImportInfoPropertySet->setPropertyValue( g_sRedlineProtectionKey, aAny);
362  }
363  catch (const uno::RuntimeException &) // fdo#65882
364  {
365  SAL_WARN( "sw", "potentially benign ordering issue during shutdown" );
366  }
367 }
368 
370  std::u16string_view rType,
371  const OUString& rId,
372  const OUString& rAuthor,
373  const OUString& rComment,
374  const util::DateTime& rDateTime,
375  bool bMergeLastPara)
376 {
377  // we need to do the following:
378  // 1) parse type string
379  // 2) create RedlineInfo and fill it with data
380  // 3) check for existing redline with same ID
381  // 3a) insert redline into map
382  // 3b) attach to existing redline
383 
384  // ad 1)
386  if (rType == m_sInsertion)
387  {
388  eType = RedlineType::Insert;
389  }
390  else if (rType == m_sDeletion)
391  {
392  eType = RedlineType::Delete;
393  }
394  else if (rType == m_sFormatChange)
395  {
396  eType = RedlineType::Format;
397  }
398  else
399  {
400  // no proper type found: early out!
401  return;
402  }
403 
404  // ad 2) create a new RedlineInfo
405  RedlineInfo* pInfo = new RedlineInfo();
406 
407  // fill entries
408  pInfo->eType = eType;
409  pInfo->sAuthor = rAuthor;
410  pInfo->sComment = rComment;
411  pInfo->aDateTime = rDateTime;
412  pInfo->bMergeLastParagraph = bMergeLastPara;
413 
414  // ad 3)
415  auto itPair = m_aRedlineMap.emplace(rId, pInfo);
416  if (itPair.second)
417  return;
418 
419  // 3b) we already have a redline with this name: hierarchical redlines
420  // insert pInfo as last element in the chain.
421  // (hierarchy sanity checking happens on inserting into the document)
422 
423  // find last element
424  RedlineInfo* pInfoChain;
425  for( pInfoChain = itPair.first->second;
426  nullptr != pInfoChain->pNextRedline;
427  pInfoChain = pInfoChain->pNextRedline) ; // empty loop
428 
429  // insert as last element
430  pInfoChain->pNextRedline = pInfo;
431 }
432 
434  Reference<XTextCursor> const & xOldCursor,
435  const OUString& rId)
436 {
437  Reference<XTextCursor> xReturn;
438 
439  // this method will modify the document directly -> lock SolarMutex
440  SolarMutexGuard aGuard;
441 
442  // get RedlineInfo
443  RedlineMapType::iterator aFind = m_aRedlineMap.find(rId);
444  if (m_aRedlineMap.end() != aFind)
445  {
446  // get document from old cursor (via tunnel)
447  SwDoc* pDoc = lcl_GetDocViaTunnel(xOldCursor);
448 
449  if (!pDoc)
450  {
451  SAL_WARN("sw", "no SwDoc => cannot create section.");
452  return nullptr;
453  }
454 
455  // create text section for redline
457  (RES_POOLCOLL_STANDARD, false );
458  SwStartNode* pRedlineNode = pDoc->GetNodes().MakeTextSection(
459  pDoc->GetNodes().GetEndOfRedlines(),
461  pColl);
462 
463  // remember node-index in RedlineInfo
464  SwNodeIndex aIndex(*pRedlineNode);
465  aFind->second->pContentIndex = new SwNodeIndex(aIndex);
466 
467  // create XText for document
468  rtl::Reference<SwXRedlineText> pXText = new SwXRedlineText(pDoc, aIndex);
469 
470  // create (UNO-) cursor
471  SwPosition aPos(*pRedlineNode);
473  new SwXTextCursor(*pDoc, pXText, CursorType::Redline, aPos);
474  pXCursor->GetCursor().Move(fnMoveForward, GoInNode);
475  // cast to avoid ambiguity
476  xReturn = static_cast<text::XWordCursor*>(pXCursor.get());
477  }
478  // else: unknown redline -> Ignore
479 
480  return xReturn;
481 }
482 
484  const OUString& rId,
485  bool bStart,
486  Reference<XTextRange> const & rRange,
487  bool bIsOutsideOfParagraph)
488 {
489  RedlineMapType::iterator aFind = m_aRedlineMap.find(rId);
490  if (m_aRedlineMap.end() == aFind)
491  return;
492 
493  // RedlineInfo found; now set Cursor
494  RedlineInfo* pInfo = aFind->second;
495  if (bIsOutsideOfParagraph)
496  {
497  // outside of paragraph: remember SwNodeIndex
498  if (bStart)
499  {
500  pInfo->aAnchorStart.SetAsNodeIndex(rRange);
501  }
502  else
503  {
504  pInfo->aAnchorEnd.SetAsNodeIndex(rRange);
505  }
506 
507  // also remember that we expect an adjustment for this redline
508  pInfo->bNeedsAdjustment = true;
509  }
510  else
511  {
512  // inside of a paragraph: use regular XTextRanges (bookmarks)
513  if (bStart)
514  pInfo->aAnchorStart.Set(rRange);
515  else
516  pInfo->aAnchorEnd.Set(rRange);
517  }
518 
519  // if this Cursor was the last missing info, we insert the
520  // node into the document
521  // then we can remove the entry from the map and destroy the object
522  if (IsReady(pInfo))
523  {
524  InsertIntoDocument(pInfo);
525  m_aRedlineMap.erase(rId);
526  delete pInfo;
527  }
528  // else: unknown Id -> ignore
529 }
530 
532  const OUString& rId)
533 {
534  // this method will modify the document directly -> lock SolarMutex
535  SolarMutexGuard aGuard;
536 
537  // start + end nodes are treated the same. For either it's
538  // necessary that the target node already exists.
539 
540  RedlineMapType::iterator aFind = m_aRedlineMap.find(rId);
541  if (m_aRedlineMap.end() == aFind)
542  return;
543 
544  // RedlineInfo found; now set Cursor
545  RedlineInfo* pInfo = aFind->second;
546 
547  pInfo->bNeedsAdjustment = false;
548 
549  // if now ready, insert into document
550  if( IsReady(pInfo) )
551  {
552  InsertIntoDocument(pInfo);
553  m_aRedlineMap.erase(rId);
554  delete pInfo;
555  }
556  // else: can't find redline -> ignore
557 }
558 
559 inline bool XMLRedlineImportHelper::IsReady(const RedlineInfo* pRedline)
560 {
561  // we can insert a redline if we have start & end, and we don't
562  // expect adjustments for either of these
563  return ( pRedline->aAnchorEnd.IsValid() &&
564  pRedline->aAnchorStart.IsValid() &&
565  !pRedline->bNeedsAdjustment );
566 }
567 
569 {
570  OSL_ENSURE(nullptr != pRedlineInfo, "need redline info");
571  OSL_ENSURE(IsReady(pRedlineInfo), "redline info not complete yet!");
572 
573  // this method will modify the document directly -> lock SolarMutex
574  SolarMutexGuard aGuard;
575 
576  // Insert the Redline as described by pRedlineInfo into the
577  // document. If we are in insert mode, don't insert any redlines
578  // (and delete 'deleted' inline redlines)
579 
580  // get the document (from one of the positions)
581  SwDoc* pDoc = pRedlineInfo->aAnchorStart.GetDoc();
582 
583  if (!pDoc)
584  {
585  SAL_WARN("sw", "no SwDoc => cannot insert redline.");
586  return;
587  }
588 
589  // now create the PaM for the redline
590  SwPaM aPaM(pDoc->GetNodes().GetEndOfContent());
591  pRedlineInfo->aAnchorStart.CopyPositionInto(*aPaM.GetPoint(), *pDoc);
592  aPaM.SetMark();
593  pRedlineInfo->aAnchorEnd.CopyPositionInto(*aPaM.GetPoint(), *pDoc);
594 
595  // collapse PaM if (start == end)
596  if (*aPaM.GetPoint() == *aPaM.GetMark())
597  {
598  aPaM.DeleteMark();
599  }
600 
601  // cover three cases:
602  // 1) empty redlines (no range, no content)
603  // 2) check for:
604  // a) bIgnoreRedline (e.g. insert mode)
605  // b) illegal PaM range (CheckNodesRange())
606  // c) redline with empty content section (quite useless)
607  // 3) normal case: insert redline
608  SwTextNode const* pTempNode(nullptr);
609  if( !aPaM.HasMark() && (pRedlineInfo->pContentIndex == nullptr) )
610  {
611  // these redlines have no function, and will thus be ignored (just as
612  // in sw3io), so no action here
613  }
614  else if ( m_bIgnoreRedlines ||
615  !CheckNodesRange( aPaM.GetPoint()->nNode,
616  aPaM.GetMark()->nNode,
617  true )
618  || (pRedlineInfo->pContentIndex
619  && (pRedlineInfo->pContentIndex->GetIndex() + 2
620  == pRedlineInfo->pContentIndex->GetNode().EndOfSectionIndex())
621  && (pTempNode = pDoc->GetNodes()[pRedlineInfo->pContentIndex->GetIndex() + 1]->GetTextNode()) != nullptr
622  && pTempNode->GetText().isEmpty()
623  && !pTempNode->GetpSwpHints()
624  && pTempNode->GetAnchoredFlys().empty()))
625  {
626  // ignore redline (e.g. file loaded in insert mode):
627  // delete 'deleted' redlines and forget about the whole thing
628  if (RedlineType::Delete == pRedlineInfo->eType)
629  {
631  // And what about the "deleted nodes"?
632  // They have to be deleted as well (#i80689)!
633  if( m_bIgnoreRedlines && pRedlineInfo->pContentIndex != nullptr )
634  {
635  SwNodeIndex aIdx( *pRedlineInfo->pContentIndex );
636  const SwNode* pEnd = aIdx.GetNode().EndOfSectionNode();
637  if( pEnd )
638  {
639  SwNodeIndex aEnd( *pEnd, 1 );
640  SwPaM aDel( aIdx, aEnd );
642  }
643  }
644  }
645  }
646  else
647  {
648  // regular file loading: insert redline
649 
650  // create redline (using pRedlineData which gets copied in SwRangeRedline())
651  SwRedlineData* pRedlineData = ConvertRedline(pRedlineInfo, pDoc);
652  SwRangeRedline* pRedline =
653  new SwRangeRedline( pRedlineData, *aPaM.GetPoint(),
654  !pRedlineInfo->bMergeLastParagraph );
655 
656  // set mark
657  if( aPaM.HasMark() )
658  {
659  pRedline->SetMark();
660  *(pRedline->GetMark()) = *aPaM.GetMark();
661  }
662 
663  // set content node (if necessary)
664  if (nullptr != pRedlineInfo->pContentIndex)
665  {
666  sal_uLong nPoint = aPaM.GetPoint()->nNode.GetIndex();
667  if( nPoint < pRedlineInfo->pContentIndex->GetIndex() ||
668  nPoint > pRedlineInfo->pContentIndex->GetNode().EndOfSectionIndex() )
669  pRedline->SetContentIdx(pRedlineInfo->pContentIndex);
670 #if OSL_DEBUG_LEVEL > 1
671  else
672  OSL_FAIL( "Recursive change tracking" );
673 #endif
674  }
675 
676  // set redline mode (without doing the associated book-keeping)
678  pDoc->getIDocumentRedlineAccess().AppendRedline(pRedline, false);
680  }
681 }
682 
684  RedlineInfo* pRedlineInfo,
685  SwDoc* pDoc)
686 {
687  // convert info:
688  // 1) Author String -> Author ID (default to zero)
689  std::size_t nAuthorId = (nullptr == pDoc) ? 0 :
690  pDoc->getIDocumentRedlineAccess().InsertRedlineAuthor( pRedlineInfo->sAuthor );
691 
692  // 2) util::DateTime -> DateTime
693  DateTime aDT( DateTime::EMPTY );
694  aDT.SetYear( pRedlineInfo->aDateTime.Year );
695  aDT.SetMonth( pRedlineInfo->aDateTime.Month );
696  aDT.SetDay( pRedlineInfo->aDateTime.Day );
697  aDT.SetHour( pRedlineInfo->aDateTime.Hours );
698  aDT.SetMin( pRedlineInfo->aDateTime.Minutes );
699  aDT.SetSec( pRedlineInfo->aDateTime.Seconds );
700  aDT.SetNanoSec( pRedlineInfo->aDateTime.NanoSeconds );
701 
702  // 3) recursively convert next redline
703  // ( check presence and sanity of hierarchical redline info )
704  SwRedlineData* pNext = nullptr;
705  if ( (nullptr != pRedlineInfo->pNextRedline) &&
706  (RedlineType::Delete == pRedlineInfo->eType) &&
707  (RedlineType::Insert == pRedlineInfo->pNextRedline->eType) )
708  {
709  pNext = ConvertRedline(pRedlineInfo->pNextRedline, pDoc);
710  }
711 
712  // create redline data
713  SwRedlineData* pData = new SwRedlineData(pRedlineInfo->eType,
714  nAuthorId, aDT,
715  pRedlineInfo->sComment,
716  pNext); // next data (if available)
717 
718  return pData;
719 }
720 
722 {
723  m_bShowChanges = bShow;
724 }
725 
727 {
728  m_bRecordChanges = bRecord;
729 }
730 
732  const Sequence<sal_Int8> & rKey )
733 {
734  m_aProtectionKey = rKey;
735 }
736 
737 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:683
Starts a section of nodes in the document model.
Definition: node.hxx:312
Represents the style of a paragraph.
Definition: fmtcol.hxx:56
Marks a position in the document model.
Definition: pam.hxx:35
constexpr OUStringLiteral g_sShowChanges
void SetContentIdx(const SwNodeIndex *)
Definition: docredln.cxx:1766
const OUString & GetText() const
Definition: ndtxt.hxx:215
void SetSec(sal_uInt16 nNewSec)
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:223
std::unique_ptr< ContentProperties > pData
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
virtual void SetRedlineFlags_intern(RedlineFlags eMode)=0
Set a new redline mode.
SwNodeIndex nNode
Definition: pam.hxx:37
css::uno::Sequence< sal_Int8 > m_aProtectionKey
sal_uIntPtr sal_uLong
XML_INSERTION
const SwPosition * GetMark() const
Definition: pam.hxx:209
XMLRedlineImportHelper(SvXMLImport &rImport, bool bIgnoreRedlines, const css::uno::Reference< css::beans::XPropertySet > &rModel, const css::uno::Reference< css::beans::XPropertySet > &rImportInfoSet)
XML_FORMAT_CHANGE
Definition: doc.hxx:188
RedlineInfo * pNextRedline
virtual void DeleteRange(SwPaM &)=0
Delete a range SwFlyFrameFormat.
::sw::DocumentRedlineManager const & GetDocumentRedlineManager() const
Definition: doc.cxx:345
SwNode & GetNode() const
Definition: ndindex.hxx:119
static bool IsReady(const RedlineInfo *pRedline)
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
void SetRecordChanges(bool bRecordChanges)
void SetHour(sal_uInt16 nNewHour)
const SwDoc & GetDoc() const
Definition: unoobj2.cxx:767
SwIndex nContent
Definition: pam.hxx:38
void SetProtectionKey(const css::uno::Sequence< sal_Int8 > &rKey)
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:426
void SetShowChanges(bool bShowChanges)
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
constexpr OUStringLiteral g_sRecordChanges
void SetYear(sal_Int16 nNewYear)
bool CheckNodesRange(const SwNodeIndex &rStt, const SwNodeIndex &rEnd, bool bChkSection)
Check if the given range is inside one of the defined top-level sections.
Definition: pam.cxx:259
std::vector< SwFrameFormat * > const & GetAnchoredFlys() const
Definition: node.hxx:297
RedlineFlags on.
css::uno::Reference< css::text::XTextCursor > CreateRedlineTextSection(css::uno::Reference< css::text::XTextCursor > const &xOldCursor, const OUString &rId)
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:163
DocumentType eType
SwStartNode * MakeTextSection(const SwNodeIndex &rWhere, SwStartNodeType eSttNdTyp, SwTextFormatColl *pColl)
Definition: nodes.cxx:1893
XTextRangeOrNodeIndexPosition aAnchorEnd
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
static SwDoc * lcl_GetDocViaTunnel(Reference< XTextCursor > const &rCursor)
css::uno::Reference< css::beans::XPropertySet > m_xImportInfoPropertySet
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:961
void SetDay(sal_uInt16 nNewDay)
SwXRedlineText provides an XText which may be used to write directly into a redline node...
Definition: unoredline.hxx:34
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
SwContentNode * GetContentNode()
Definition: node.hxx:616
float u
void SetHideRedlines(bool const bHideRedlines)
Marks a node in the document model.
Definition: ndindex.hxx:31
virtual std::size_t InsertRedlineAuthor(const OUString &rAuthor)=0
bool XTextRangeToSwPaM(SwUnoInternalPaM &rToFill, const uno::Reference< text::XTextRange > &xTextRange,::sw::TextRangeMode const eMode)
Definition: unoobj2.cxx:1107
void SetCursor(const OUString &rId, bool bStart, css::uno::Reference< css::text::XTextRange > const &rRange, bool bIsOutsideOfParagraph)
void AdjustStartNodeCursor(const OUString &rId)
Adjust the start (end) position for a redline that begins in a start node.
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:678
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
std::deque< AttacherIndex_Impl > aIndex
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
const SvXMLImport & m_rImport
SwNodes & GetNodes()
Definition: doc.hxx:409
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
void Add(std::u16string_view rType, const OUString &rId, const OUString &rAuthor, const OUString &rComment, const css::util::DateTime &rDateTime, bool bMergeLastParagraph)
void SetNanoSec(sal_uInt32 nNewNanoSec)
void SetMin(sal_uInt16 nNewMin)
XML_DELETION
css::uno::Reference< css::beans::XPropertySet > m_xModelPropertySet
SwRedlineData * ConvertRedline(RedlineInfo *pRedline, SwDoc *pDoc)
XTextRangeOrNodeIndexPosition aAnchorStart
#define SAL_WARN(area, stream)
RedlineType
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:478
util::DateTime aDateTime
SwNode & GetEndOfRedlines() const
Section for all Redlines.
Definition: ndarr.hxx:158
SwDoc * GetDocFromXMLImport(SvXMLImport const &)
Definition: xmlimp.cxx:1617
SwNodeIndex * pContentIndex
void InsertIntoDocument(RedlineInfo *pRedline)
void SetMonth(sal_uInt16 nNewMonth)
no RedlineFlags
constexpr OUStringLiteral g_sRedlineProtectionKey
Base class of the Writer document model elements.
Definition: node.hxx:80
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)