LibreOffice Module sw (master)  1
redlnitr.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 <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <hintids.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <svl/whiter.hxx>
27 #include <com/sun/star/i18n/ScriptType.hpp>
28 #include <scriptinfo.hxx>
29 #include <swmodule.hxx>
30 #include <redline.hxx>
31 #include <txatbase.hxx>
32 #include <docary.hxx>
33 #include "itratr.hxx"
34 #include <ndtxt.hxx>
35 #include <doc.hxx>
38 #include <IDocumentMarkAccess.hxx>
39 #include <IMark.hxx>
40 #include <bookmark.hxx>
41 #include <rootfrm.hxx>
42 #include <breakit.hxx>
43 #include <vcl/commandevent.hxx>
44 #include <vcl/settings.hxx>
45 #include <txtfrm.hxx>
46 #include <ftnfrm.hxx>
47 #include <vcl/svapp.hxx>
48 #include "redlnitr.hxx"
49 #include <extinput.hxx>
50 #include <editeng/colritem.hxx>
52 #include <editeng/udlnitem.hxx>
53 
54 using namespace ::com::sun::star;
55 
56 namespace {
57 
58 class HideIterator
59 {
60 private:
61  IDocumentRedlineAccess const& m_rIDRA;
62  IDocumentMarkAccess const& m_rIDMA;
63  bool const m_isHideRedlines;
64  sw::FieldmarkMode const m_eFieldmarkMode;
65  SwPosition const m_Start;
67  SwRedlineTable::size_type m_RedlineIndex;
69  std::pair<sw::mark::IFieldmark const*, std::unique_ptr<SwPosition>> m_Fieldmark;
70  std::optional<SwPosition> m_oNextFieldmarkHide;
72  SwPosition const* m_pStartPos;
73  SwPosition const* m_pEndPos;
74 
75 public:
76  SwPosition const* GetStartPos() const { return m_pStartPos; }
77  SwPosition const* GetEndPos() const { return m_pEndPos; }
78 
79  HideIterator(SwTextNode & rTextNode,
80  bool const isHideRedlines, sw::FieldmarkMode const eMode)
81  : m_rIDRA(rTextNode.getIDocumentRedlineAccess())
82  , m_rIDMA(*rTextNode.getIDocumentMarkAccess())
83  , m_isHideRedlines(isHideRedlines)
84  , m_eFieldmarkMode(eMode)
85  , m_Start(rTextNode, 0)
86  , m_RedlineIndex(m_rIDRA.GetRedlinePos(rTextNode, RedlineType::Any))
87  , m_pStartPos(nullptr)
88  , m_pEndPos(&m_Start)
89  {
90  }
91 
92  // delete redlines and fieldmarks can't overlap, due to sw::CalcBreaks()
93  // and no combining of adjacent redlines
94  // -> dummy chars are delete-redlined *iff* entire fieldmark is
95  // Note: caller is responsible for checking for immediately adjacent hides
96  bool Next()
97  {
98  SwPosition const* pNextRedlineHide(nullptr);
99  assert(m_pEndPos);
100  if (m_isHideRedlines)
101  {
102  // position on current or next redline
103  for (; m_RedlineIndex < m_rIDRA.GetRedlineTable().size(); ++m_RedlineIndex)
104  {
105  SwRangeRedline const*const pRed = m_rIDRA.GetRedlineTable()[m_RedlineIndex];
106 
107  if (m_pEndPos->nNode.GetIndex() < pRed->Start()->nNode.GetIndex())
108  break;
109 
110  if (pRed->GetType() != RedlineType::Delete)
111  continue;
112 
113  SwPosition const*const pStart(pRed->Start());
114  SwPosition const*const pEnd(pRed->End());
115  if (*pStart == *pEnd)
116  { // only allowed while moving (either way?)
117 // assert(IDocumentRedlineAccess::IsHideChanges(rIDRA.GetRedlineFlags()));
118  continue;
119  }
120  if (pStart->nNode.GetNode().IsTableNode())
121  {
122  assert(pEnd->nNode == m_Start.nNode && pEnd->nContent.GetIndex() == 0);
123  continue; // known pathology, ignore it
124  }
125  if (*m_pEndPos <= *pStart)
126  {
127  pNextRedlineHide = pStart;
128  break; // the next one
129  }
130  }
131  }
132 
133  // position on current or next fieldmark
134  m_oNextFieldmarkHide.reset();
135  if (m_eFieldmarkMode != sw::FieldmarkMode::ShowBoth)
136  {
137  sal_Unicode const magic(m_eFieldmarkMode == sw::FieldmarkMode::ShowResult
140  SwTextNode* pTextNode = m_pEndPos->nNode.GetNode().GetTextNode();
141  sal_Int32 const nPos = pTextNode ? pTextNode->GetText().indexOf(
142  magic, m_pEndPos->nContent.GetIndex()) : -1;
143  if (nPos != -1)
144  {
145  m_oNextFieldmarkHide.emplace(*pTextNode, nPos);
146  sw::mark::IFieldmark const*const pFieldmark(
147  m_eFieldmarkMode == sw::FieldmarkMode::ShowResult
148  ? m_rIDMA.getFieldmarkAt(*m_oNextFieldmarkHide)
149  : m_rIDMA.getFieldmarkFor(*m_oNextFieldmarkHide));
150  assert(pFieldmark);
151  m_Fieldmark.first = pFieldmark;
152  // for cursor travelling, there should be 2 visible chars;
153  // whichever char is hidden, the cursor travelling needs to
154  // be adapted in any case to skip in some situation or other;
155  // always hide the CH_TXT_ATR_FIELDSEP for now
156  if (m_eFieldmarkMode == sw::FieldmarkMode::ShowResult)
157  {
158  m_Fieldmark.second.reset(
159  new SwPosition(sw::mark::FindFieldSep(*m_Fieldmark.first)));
160  ++m_Fieldmark.second->nContent;
161  ++m_oNextFieldmarkHide->nContent; // skip start
162  }
163  else
164  {
165  m_Fieldmark.second.reset(
166  new SwPosition(pFieldmark->GetMarkEnd()));
167  --m_Fieldmark.second->nContent;
168  }
169  }
170  }
171 
172  // == can happen only if redline starts inside field command, and in
173  // that case redline will end before field separator
174  assert(!pNextRedlineHide || !m_oNextFieldmarkHide
175  || *pNextRedlineHide != *m_oNextFieldmarkHide
176  || *m_rIDRA.GetRedlineTable()[m_RedlineIndex]->End() < *m_Fieldmark.second);
177  if (pNextRedlineHide
178  && (!m_oNextFieldmarkHide || *pNextRedlineHide < *m_oNextFieldmarkHide))
179  {
180  SwRangeRedline const*const pRed(m_rIDRA.GetRedlineTable()[m_RedlineIndex]);
181  m_pStartPos = pRed->Start();
182  m_pEndPos = pRed->End();
183  ++m_RedlineIndex;
184  return true;
185  }
186  else if (m_oNextFieldmarkHide)
187  {
188  assert(!pNextRedlineHide || *m_oNextFieldmarkHide <= *pNextRedlineHide);
189  m_pStartPos = &*m_oNextFieldmarkHide;
190  m_pEndPos = m_Fieldmark.second.get();
191  return true;
192  }
193  else // nothing
194  {
195  assert(!pNextRedlineHide && !m_oNextFieldmarkHide);
196  m_pStartPos = nullptr;
197  m_pEndPos = nullptr;
198  return false;
199  }
200  }
201 };
202 
203 }
204 
205 namespace sw {
206 
207 std::unique_ptr<sw::MergedPara>
209  FrameMode const eMode)
210 {
211  if (!rFrame.getRootFrame()->HasMergedParas())
212  {
213  return nullptr;
214  }
215  bool bHaveRedlines(false);
216  std::vector<SwTextNode *> nodes{ &rTextNode };
217  std::vector<SwTableNode *> tables;
218  std::vector<SwSectionNode *> sections;
219  std::vector<sw::Extent> extents;
220  OUStringBuffer mergedText;
221  SwTextNode * pParaPropsNode(nullptr);
222  SwTextNode * pNode(&rTextNode);
223  sal_Int32 nLastEnd(0);
224  for (auto iter = HideIterator(rTextNode,
225  rFrame.getRootFrame()->IsHideRedlines(),
226  rFrame.getRootFrame()->GetFieldmarkMode()); iter.Next(); )
227  {
228  SwPosition const*const pStart(iter.GetStartPos());
229  SwPosition const*const pEnd(iter.GetEndPos());
230  bHaveRedlines = true;
231  assert(pNode != &rTextNode || &pStart->nNode.GetNode() == &rTextNode); // detect calls with wrong start node
232  if (pStart->nContent != nLastEnd) // not 0 so we eliminate adjacent deletes
233  {
234  extents.emplace_back(pNode, nLastEnd, pStart->nContent.GetIndex());
235  mergedText.append(pNode->GetText().subView(nLastEnd, pStart->nContent.GetIndex() - nLastEnd));
236  }
237  if (&pEnd->nNode.GetNode() != pNode)
238  {
239  if (pNode == &rTextNode)
240  {
242  } // else: was already set before
243  int nLevel(0);
244  for (SwNodeOffset j = pNode->GetIndex() + 1; j < pEnd->nNode.GetIndex(); ++j)
245  {
246  SwNode *const pTmp(pNode->GetNodes()[j]);
247  if (nLevel == 0)
248  {
249  if (pTmp->IsTextNode())
250  {
251  nodes.push_back(pTmp->GetTextNode());
252  }
253  else if (pTmp->IsTableNode())
254  {
255  tables.push_back(pTmp->GetTableNode());
256  }
257  else if (pTmp->IsSectionNode())
258  {
259  sections.push_back(pTmp->GetSectionNode());
260  }
261  }
262  if (pTmp->IsStartNode())
263  {
264  ++nLevel;
265  }
266  else if (pTmp->IsEndNode())
267  {
268  --nLevel;
269  }
271  }
272  // note: in DelLastPara() case, the end node is not actually merged
273  // and is likely a SwTableNode!
274  if (!pEnd->nNode.GetNode().IsTextNode())
275  {
276  assert(pEnd->nNode != pStart->nNode);
277  // must set pNode too because it will mark the last node
278  pNode = nodes.back();
279  assert(pNode == pNode->GetNodes()[pEnd->nNode.GetIndex() - 1]);
280  if (pNode != &rTextNode)
281  { // something might depend on last merged one being NonFirst?
283  }
284  nLastEnd = pNode->Len();
285  }
286  else
287  {
288  pNode = pEnd->nNode.GetNode().GetTextNode();
289  nodes.push_back(pNode);
291  nLastEnd = pEnd->nContent.GetIndex();
292  }
293  }
294  else
295  {
296  nLastEnd = pEnd->nContent.GetIndex();
297  }
298  }
299  if (pNode == &rTextNode)
300  {
301  if (rTextNode.GetRedlineMergeFlag() != SwNode::Merge::None)
302  {
304  }
305  }
306  // Reset flag of the following text node since we know it's not merged;
307  // also any table/sections in between.
308  // * the following SwTextNode is in same nodes section as pNode (nLevel=0)
309  // * the start nodes that don't have a SwTextNode before them
310  // on their level, and their corresponding end nodes
311  // * the first SwTextNode inside each start node of the previous point
312  // Other (non-first) SwTextNodes in nested sections shouldn't be reset!
313  int nLevel(0);
314  for (SwNodeOffset j = pNode->GetIndex() + 1; j < pNode->GetNodes().Count(); ++j)
315  {
316  SwNode *const pTmp(pNode->GetNodes()[j]);
317  if (!pTmp->IsCreateFrameWhenHidingRedlines())
318  { // clear stale flag caused by editing with redlines shown
320  }
321  if (pTmp->IsStartNode())
322  {
323  ++nLevel;
324  }
325  else if (pTmp->IsEndNode())
326  {
327  if (nLevel == 0)
328  {
329  break; // there is no following text node; avoid leaving section
330  }
331  --nLevel;
332  }
333  else if (pTmp->IsTextNode())
334  {
335  if (nLevel == 0)
336  {
337  break; // done
338  }
339  else
340  { // skip everything other than 1st text node in section!
341  j = pTmp->EndOfSectionIndex() - 1; // will be incremented again
342  }
343  }
344  }
345  if (!bHaveRedlines)
346  {
347  if (rTextNode.IsInList() && !rTextNode.GetNum(rFrame.getRootFrame()))
348  {
349  rTextNode.AddToListRLHidden(); // try to add it...
350  }
351  return nullptr;
352  }
353  if (nLastEnd != pNode->Len())
354  {
355  extents.emplace_back(pNode, nLastEnd, pNode->Len());
356  mergedText.append(pNode->GetText().subView(nLastEnd, pNode->Len() - nLastEnd));
357  }
358  if (extents.empty()) // there was no text anywhere
359  {
360  assert(mergedText.isEmpty());
361  pParaPropsNode = pNode; // if every node is empty, the last one wins
362  }
363  else
364  {
365  assert(!mergedText.isEmpty());
366  pParaPropsNode = extents.begin()->pNode; // para props from first node that isn't empty
367  }
368 // pParaPropsNode = &rTextNode; // well, actually...
369  // keep lists up to date with visible nodes
370  if (pParaPropsNode->IsInList() && !pParaPropsNode->GetNum(rFrame.getRootFrame()))
371  {
372  pParaPropsNode->AddToListRLHidden(); // try to add it...
373  }
374  for (auto const pTextNode : nodes)
375  {
376  if (pTextNode != pParaPropsNode)
377  {
378  pTextNode->RemoveFromListRLHidden();
379  }
380  }
381  if (eMode == FrameMode::Existing)
382  {
383  // remove existing footnote frames for first node;
384  // for non-first nodes with own frames, DelFrames will remove all
385  // (could possibly call lcl_ChangeFootnoteRef, not sure if worth it)
386  // note: must be done *before* changing listeners!
387  // for non-first nodes that are already merged with this frame,
388  // need to remove here too, otherwise footnotes can be removed only
389  // by lucky accident, e.g. TruncLines().
390  auto itExtent(extents.begin());
391  for (auto const pTextNode : nodes)
392  {
393  sal_Int32 nLast(0);
394  std::vector<std::pair<sal_Int32, sal_Int32>> hidden;
395  for ( ; itExtent != extents.end(); ++itExtent)
396  {
397  if (itExtent->pNode != pTextNode)
398  {
399  break;
400  }
401  if (itExtent->nStart != 0)
402  {
403  assert(itExtent->nStart != nLast);
404  hidden.emplace_back(nLast, itExtent->nStart);
405  }
406  nLast = itExtent->nEnd;
407  }
408  if (nLast != pTextNode->Len())
409  {
410  hidden.emplace_back(nLast, pTextNode->Len());
411  }
412  sw::RemoveFootnotesForNode(*rFrame.getRootFrame(), *pTextNode, &hidden);
413  }
414  // unfortunately DelFrames() must be done before StartListening too,
415  // otherwise footnotes cannot be deleted by SwTextFootnote::DelFrames!
416  auto const end(--nodes.rend());
417  for (auto iter = nodes.rbegin(); iter != end; ++iter)
418  {
419  (**iter).DelFrames(rFrame.getRootFrame());
420  }
421  // also delete tables & sections here; not necessary, but convenient
422  for (auto const pTableNode : tables)
423  {
424  pTableNode->DelFrames(rFrame.getRootFrame());
425  }
426  for (auto const pSectionNode : sections)
427  {
428  pSectionNode->DelFrames(rFrame.getRootFrame());
429  }
430  }
431  auto pRet(std::make_unique<sw::MergedPara>(rFrame, std::move(extents),
432  mergedText.makeStringAndClear(), pParaPropsNode, &rTextNode,
433  nodes.back()));
434  for (SwTextNode * pTmp : nodes)
435  {
436  pRet->listener.StartListening(pTmp);
437  }
438  rFrame.EndListeningAll();
439  return pRet;
440 }
441 
442 } // namespace sw
443 
445  SwTextNode const& rPropsNode,
446  SwTextNode const& rTextNode,
447  OUString const& rText,
448  bool const*const pbVertLayout,
449  bool const*const pbVertLayoutLRBT)
450 {
451  // Build a font matching the default paragraph style:
452  SwFontAccess aFontAccess( &rPropsNode.GetAnyFormatColl(), m_pViewShell );
453  // It is possible that Init is called more than once, e.g., in a
454  // SwTextFrame::FormatOnceMore situation or (since sw_redlinehide)
455  // from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt
456  // is an alias of m_pFont so it must not be deleted!
457  if (m_pFont)
458  {
459  *m_pFont = aFontAccess.Get()->GetFont();
460  }
461  else
462  {
463  m_pFont = new SwFont( aFontAccess.Get()->GetFont() );
464  }
465 
466  // set font to vertical if frame layout is vertical
467  // if it's a re-init, the vert flag never changes
468  bool bVertLayoutLRBT = false;
469  if (pbVertLayoutLRBT)
470  bVertLayoutLRBT = *pbVertLayoutLRBT;
471  if (pbVertLayout ? *pbVertLayout : m_aAttrHandler.IsVertLayout())
472  {
473  m_pFont->SetVertical(m_pFont->GetOrientation(), true, bVertLayoutLRBT);
474  }
475 
476  // Initialize the default attribute of the attribute handler
477  // based on the attribute array cached together with the font.
478  // If any further attributes for the paragraph are given in pAttrSet
479  // consider them during construction of the default array, and apply
480  // them to the font
481  m_aAttrHandler.Init(aFontAccess.Get()->GetDefault(), rTextNode.GetpSwAttrSet(),
483  pbVertLayout ? *pbVertLayout : m_aAttrHandler.IsVertLayout(),
484  bVertLayoutLRBT );
485 
487 
488  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
489 
490  m_pFont->SetActual( m_pScriptInfo->WhichFont(TextFrameIndex(0)) );
491 
492  TextFrameIndex nChg(0);
493  size_t nCnt = 0;
494 
495  do
496  {
497  if ( nCnt >= m_pScriptInfo->CountScriptChg() )
498  break;
499  nChg = m_pScriptInfo->GetScriptChg( nCnt );
500  SwFontScript nTmp = SW_SCRIPTS;
501  switch ( m_pScriptInfo->GetScriptType( nCnt++ ) ) {
502  case i18n::ScriptType::ASIAN :
504  break;
505  case i18n::ScriptType::COMPLEX :
507  break;
508  default:
510  }
511  if( nTmp < SW_SCRIPTS )
512  {
513  m_pFont->CheckFontCacheId( m_pViewShell, nTmp );
514  m_pFont->GetFontCacheId( m_aFontCacheIds[ nTmp ], m_aFontIdx[ nTmp ], nTmp );
515  }
516  }
517  while (nChg < TextFrameIndex(rText.getLength()));
518 }
519 
521  SwScriptInfo & rScriptInfo, SwTextFrame const*const pFrame)
522 {
523  // during HTML-Import it can happen, that no layout exists
524  SwRootFrame* pRootFrame = rTextNode.getIDocumentLayoutAccess().GetCurrentLayout();
525  m_pViewShell = pRootFrame ? pRootFrame->GetCurrShell() : nullptr;
526 
527  m_pScriptInfo = &rScriptInfo;
528 
529  // set font to vertical if frame layout is vertical
530  bool bVertLayout = false;
531  bool bVertLayoutLRBT = false;
532  bool bRTL = false;
533  if ( pFrame )
534  {
535  if ( pFrame->IsVertical() )
536  {
537  bVertLayout = true;
538  }
539  if (pFrame->IsVertLRBT())
540  {
541  bVertLayoutLRBT = true;
542  }
543  bRTL = pFrame->IsRightToLeft();
544  m_pMergedPara = pFrame->GetMergedPara();
545  }
546 
547  // determine script changes if not already done for current paragraph
548  assert(m_pScriptInfo);
550  m_pScriptInfo->InitScriptInfo(rTextNode, m_pMergedPara, bRTL);
551 
554  rTextNode,
555  m_pMergedPara ? m_pMergedPara->mergedText : rTextNode.GetText(),
556  & bVertLayout,
557  & bVertLayoutLRBT);
558 
560  m_nPropFont = 0;
561  SwDoc& rDoc = rTextNode.GetDoc();
562  const IDocumentRedlineAccess& rIDRA = rTextNode.getIDocumentRedlineAccess();
563 
564  // sw_redlinehide: this is a Ring - pExtInp is the first PaM that's inside
565  // the node. It's not clear whether there can be more than 1 PaM in the
566  // Ring, and this code doesn't handle that case; neither did the old code.
567  const SwExtTextInput* pExtInp = rDoc.GetExtTextInput( rTextNode );
568  if (!pExtInp && m_pMergedPara)
569  {
570  SwTextNode const* pNode(&rTextNode);
571  for (auto const& rExtent : m_pMergedPara->extents)
572  {
573  if (rExtent.pNode != pNode)
574  {
575  pNode = rExtent.pNode;
576  pExtInp = rDoc.GetExtTextInput(*pNode);
577  if (pExtInp)
578  break;
579  }
580  }
581  }
582  const bool bShow = IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags())
583  && pRootFrame && !pRootFrame->IsHideRedlines();
584  if (!(pExtInp || m_pMergedPara || bShow))
585  return;
586 
587  SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, RedlineType::Any );
588  if (SwRedlineTable::npos == nRedlPos && m_pMergedPara)
589  {
590  SwTextNode const* pNode(&rTextNode);
591  for (auto const& rExtent : m_pMergedPara->extents)
592  { // note: have to search because extents based only on Delete
593  if (rExtent.pNode != pNode)
594  {
595  pNode = rExtent.pNode;
596  nRedlPos = rIDRA.GetRedlinePos(*pNode, RedlineType::Any);
597  if (SwRedlineTable::npos != nRedlPos)
598  break;
599  }
600  }
601  // TODO this is true initially but after delete ops it may be false... need to delete m_pMerged somewhere?
602  // assert(SwRedlineTable::npos != nRedlPos);
603  // false now with fieldmarks
604  assert(!pRootFrame
606  || SwRedlineTable::npos != nRedlPos || m_pMergedPara->extents.size() <= 1);
607  }
608  if (!(pExtInp || m_pMergedPara || SwRedlineTable::npos != nRedlPos))
609  return;
610 
611  const std::vector<ExtTextInputAttr> *pArr = nullptr;
612  if( pExtInp )
613  {
614  pArr = &pExtInp->GetAttrs();
615  Seek( TextFrameIndex(0) );
616  }
617 
618  m_pRedline.reset(new SwRedlineItr( rTextNode, *m_pFont, m_aAttrHandler, nRedlPos,
619  (pRootFrame && pRootFrame->IsHideRedlines())
621  : bShow
624  pArr, pExtInp ? pExtInp->Start() : nullptr));
625 
626  if( m_pRedline->IsOn() )
627  ++m_nChgCnt;
628 }
629 
630 // The Redline-Iterator
631 // The following information/states exist in RedlineIterator:
632 //
633 // m_nFirst is the first index of RedlineTable, which overlaps with the paragraph.
634 //
635 // m_nAct is the currently active (if m_bOn is set) or the next possible index.
636 // m_nStart and m_nEnd give you the borders of the object within the paragraph.
637 //
638 // If m_bOn is set, the font has been manipulated according to it.
639 //
640 // If m_nAct is set to SwRedlineTable::npos (via Reset()), then currently no
641 // Redline is active, m_nStart and m_nEnd are invalid.
643  SwAttrHandler& rAH, sal_Int32 nRed,
644  Mode const mode,
645  const std::vector<ExtTextInputAttr> *pArr,
646  SwPosition const*const pExtInputStart)
647  : m_rDoc( rTextNd.GetDoc() )
648  , m_rAttrHandler( rAH )
649  , m_nNdIdx( rTextNd.GetIndex() )
650  , m_nFirst( nRed )
651  , m_nAct( SwRedlineTable::npos )
652  , m_bOn( false )
653  , m_eMode( mode )
654 {
655  if( pArr )
656  {
657  assert(pExtInputStart);
658  m_pExt.reset( new SwExtend(*pArr, pExtInputStart->nNode.GetIndex(),
659  pExtInputStart->nContent.GetIndex()) );
660  }
661  else
662  m_pExt = nullptr;
663  assert(m_pExt || m_eMode != Mode::Ignore); // only create if necessary
664  Seek(rFnt, m_nNdIdx, 0, COMPLETE_STRING);
665 }
666 
667 SwRedlineItr::~SwRedlineItr() COVERITY_NOEXCEPT_FALSE
668 {
669  Clear( nullptr );
670  m_pExt.reset();
671 }
672 
673 // The return value of SwRedlineItr::Seek tells you if the current font
674 // has been manipulated by leaving (-1) or accessing (+1) of a section
676  SwNodeOffset const nNode, sal_Int32 const nNew, sal_Int32 const nOld)
677 {
678  short nRet = 0;
679  if( ExtOn() )
680  return 0; // Abbreviation: if we're within an ExtendTextInputs
681  // there can't be other changes of attributes (not even by redlining)
682  if (m_eMode == Mode::Show)
683  {
684  if (m_bOn)
685  {
686  if (nNew >= m_nEnd)
687  {
688  --nRet;
689  Clear_( &rFnt ); // We go behind the current section
690  ++m_nAct; // and check the next one
691  }
692  else if (nNew < m_nStart)
693  {
694  --nRet;
695  Clear_( &rFnt ); // We go in front of the current section
696  if (m_nAct > m_nFirst)
697  m_nAct = m_nFirst; // the test has to run from the beginning
698  else
699  return nRet + EnterExtend(rFnt, nNode, nNew); // There's none prior to us
700  }
701  else
702  return nRet + EnterExtend(rFnt, nNode, nNew); // We stayed in the same section
703  }
704  if (SwRedlineTable::npos == m_nAct || nOld > nNew)
705  m_nAct = m_nFirst;
706 
710 
711  for ( ; m_nAct < rTable.size() ; ++m_nAct)
712  {
713  rTable[ m_nAct ]->CalcStartEnd(nNode, m_nStart, m_nEnd);
714 
715  if (nNew < m_nEnd)
716  {
717  if (nNew >= m_nStart) // only possible candidate
718  {
719  m_bOn = true;
720  const SwRangeRedline *pRed = rTable[ m_nAct ];
721 
722  if (m_pSet)
723  m_pSet->ClearItem();
724  else
725  {
726  SwAttrPool& rPool =
727  const_cast<SwDoc&>(m_rDoc).GetAttrPool();
728  m_pSet = std::make_unique<SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1>>(rPool);
729  }
730 
731  if( 1 < pRed->GetStackCount() )
732  FillHints( pRed->GetAuthor( 1 ), pRed->GetType( 1 ) );
733  FillHints( pRed->GetAuthor(), pRed->GetType() );
734 
735  SfxWhichIter aIter( *m_pSet );
736 
737  // moved text: dark green with double underline or strikethrough
738  if ( pRed->IsMoved() )
739  {
741  if (SfxItemState::SET == m_pSet->GetItemState(RES_CHRATR_CROSSEDOUT, true))
743  else
745  }
746 
747  sal_uInt16 nWhich = aIter.FirstWhich();
748  while( nWhich )
749  {
750  const SfxPoolItem* pItem;
751  if( ( nWhich < RES_CHRATR_END ) &&
752  ( SfxItemState::SET == m_pSet->GetItemState( nWhich, true, &pItem ) ) )
753  {
755  const_cast<SwDoc&>(m_rDoc),
756  *const_cast<SfxPoolItem*>(pItem) );
757  pAttr->SetPriorityAttr( true );
758  m_Hints.push_back(pAttr);
759  m_rAttrHandler.PushAndChg( *pAttr, rFnt );
760  }
761  nWhich = aIter.NextWhich();
762  }
763 
764  ++nRet;
765  }
766  break;
767  }
770  }
771  }
772  else if (m_eMode == Mode::Hide)
773  { // ... just iterate to update m_nAct for GetNextRedln();
774  // there is no need to care about formatting in this mode
775  if (m_nAct == SwRedlineTable::npos || nOld == COMPLETE_STRING)
776  { // reset, or move backward
777  m_nAct = m_nFirst;
778  }
780  { // only Start matters in this mode
781  // Seeks until it finds a RL that starts at or behind the seek pos.
782  // - then update m_nStart/m_nEnd to the intersection of it with the
783  // current node (if any).
784  // The only way to skip to a different node is if there is a Delete
785  // RL, so if there is no intersection we'll never skip again.
786  // Note: here, assume that delete can't nest inside delete!
787  SwRangeRedline const*const pRedline(
789  SwPosition const*const pStart(pRedline->Start());
790  if (pRedline->GetType() == RedlineType::Delete
791  && (nNode < pStart->nNode.GetIndex()
792  || (nNode == pStart->nNode.GetIndex()
793  && nNew <= pStart->nContent.GetIndex())))
794  {
795  pRedline->CalcStartEnd(nNode, m_nStart, m_nEnd);
796  break;
797  }
800  }
801  }
802  return nRet + EnterExtend(rFnt, nNode, nNew);
803 }
804 
805 void SwRedlineItr::FillHints( std::size_t nAuthor, RedlineType eType )
806 {
807  switch ( eType )
808  {
809  case RedlineType::Insert:
810  SW_MOD()->GetInsertAuthorAttr(nAuthor, *m_pSet);
811  break;
812  case RedlineType::Delete:
813  SW_MOD()->GetDeletedAuthorAttr(nAuthor, *m_pSet);
814  break;
815  case RedlineType::Format:
816  case RedlineType::FmtColl:
817  SW_MOD()->GetFormatAuthorAttr(nAuthor, *m_pSet);
818  break;
819  default:
820  break;
821  }
822 }
823 
824 void SwRedlineItr::ChangeTextAttr( SwFont* pFnt, SwTextAttr const &rHt, bool bChg )
825 {
826  OSL_ENSURE( IsOn(), "SwRedlineItr::ChangeTextAttr: Off?" );
827 
828  if (m_eMode != Mode::Show && !m_pExt)
829  return;
830 
831  if( bChg )
832  {
833  if (m_pExt && m_pExt->IsOn())
834  m_rAttrHandler.PushAndChg( rHt, *m_pExt->GetFont() );
835  else
836  m_rAttrHandler.PushAndChg( rHt, *pFnt );
837  }
838  else
839  {
840  OSL_ENSURE( ! m_pExt || ! m_pExt->IsOn(), "Pop of attribute during opened extension" );
841  m_rAttrHandler.PopAndChg( rHt, *pFnt );
842  }
843 }
844 
846 {
847  OSL_ENSURE( m_bOn, "SwRedlineItr::Clear: Off?" );
848  m_bOn = false;
849  for (auto const& hint : m_Hints)
850  {
851  if( pFnt )
852  m_rAttrHandler.PopAndChg( *hint, *pFnt );
853  else
854  m_rAttrHandler.Pop( *hint );
855  SwTextAttr::Destroy(hint, const_cast<SwDoc&>(m_rDoc).GetAttrPool() );
856  }
857  m_Hints.clear();
858 }
859 
864 std::pair<sal_Int32, std::pair<SwRangeRedline const*, size_t>>
865 SwRedlineItr::GetNextRedln(sal_Int32 nNext, SwTextNode const*const pNode,
867 {
868  sal_Int32 nStart(m_nStart);
869  sal_Int32 nEnd(m_nEnd);
870  nNext = NextExtend(pNode->GetIndex(), nNext);
872  return std::make_pair(nNext, std::make_pair(nullptr, 0));
873  if (SwRedlineTable::npos == rAct)
874  {
875  rAct = m_nFirst;
876  }
877  if (rAct != m_nAct)
878  {
880  {
881  SwRangeRedline const*const pRedline(
883  pRedline->CalcStartEnd(pNode->GetIndex(), nStart, nEnd);
884  if (m_eMode != Mode::Hide
885  || pRedline->GetType() == RedlineType::Delete)
886  {
887  break;
888  }
889  ++rAct; // Hide mode: search a Delete RL
890  }
891  }
893  {
894  return std::make_pair(nNext, std::make_pair(nullptr, 0)); // no Delete here
895  }
896  if (m_bOn || (m_eMode == Mode::Show && nStart == 0))
897  { // in Ignore mode, the end of redlines isn't relevant, except as returned in the second in the pair!
898  if (nEnd < nNext)
899  nNext = nEnd;
900  }
901  else if (nStart <= nNext)
902  {
903  if (m_eMode == Mode::Show)
904  {
905  nNext = nStart;
906  }
907  else
908  {
909  assert(m_eMode == Mode::Hide);
910  SwRangeRedline const* pRedline(
912  assert(pRedline->GetType() == RedlineType::Delete); //?
913  if (pRedline->GetType() == RedlineType::Delete)
914  {
915  nNext = nStart;
916  size_t nSkipped(1); // (consecutive) candidates to be skipped
917  while (rAct + nSkipped <
919  {
920  SwRangeRedline const*const pNext =
921  m_rDoc.getIDocumentRedlineAccess().GetRedlineTable()[rAct + nSkipped];
922  if (*pRedline->End() < *pNext->Start())
923  {
924  break; // done for now
925  }
926  else if (*pNext->Start() == *pRedline->End() &&
927  pNext->GetType() == RedlineType::Delete)
928  {
929  // consecutive delete - continue
930  pRedline = pNext;
931  }
932  ++nSkipped;
933  }
934  return std::make_pair(nNext, std::make_pair(pRedline, nSkipped));
935  }
936  }
937  }
938  return std::make_pair(nNext, std::make_pair(nullptr, 0));
939 }
940 
942 {
943  // If the underlining or the escapement is caused by redlining,
944  // we always apply the SpecialUnderlining, i.e. the underlining
945  // below the base line
946  for (SwTextAttr* pHint : m_Hints)
947  {
948  const sal_uInt16 nWhich = pHint->Which();
949  if( RES_CHRATR_UNDERLINE == nWhich ||
950  RES_CHRATR_ESCAPEMENT == nWhich )
951  return true;
952  }
953  return false;
954 }
955 
957  SwNodeOffset const nStartNode, sal_Int32 const nChkStart,
958  SwNodeOffset const nEndNode, sal_Int32 nChkEnd, OUString& rRedlineText,
959  bool& bRedlineEnd, RedlineType& eRedlineEnd, size_t* pAuthorAtPos)
960 {
961  // note: previously this would return true in the (!m_bShow && m_pExt)
962  // case, but surely that was a bug?
964  return false;
965  if( nChkEnd == nChkStart && pAuthorAtPos == nullptr ) // empty lines look one char further
966  ++nChkEnd;
967  sal_Int32 nOldStart = m_nStart;
968  sal_Int32 nOldEnd = m_nEnd;
969  SwRedlineTable::size_type const nOldAct = m_nAct;
970  bool bRet = bRedlineEnd = false;
971  eRedlineEnd = RedlineType::None;
972 
973  SwPosition const start(*m_rDoc.GetNodes()[nStartNode]->GetContentNode(), nChkStart);
974  SwPosition const end(*m_rDoc.GetNodes()[nEndNode]->GetContentNode(), nChkEnd);
975  SwRangeRedline const* pPrevRedline = nullptr;
976  bool isBreak(false);
978  {
979  SwRangeRedline const*const pRedline(
981  // collect text of the hidden redlines at the end of the line
982  bool isExtendText(false);
983  switch (ComparePosition(*pRedline->Start(), *pRedline->End(), start, end))
984  {
986  isBreak = true;
987  break;
992  // store redlining at line end (for line break formatting)
993  eRedlineEnd = pRedline->GetType();
994  bRedlineEnd = true;
995  isBreak = true;
996  if (pAuthorAtPos)
997  *pAuthorAtPos = pRedline->GetAuthor();
998  [[fallthrough]];
1002  {
1003  bRet = true;
1004  // start to collect text of invisible redlines for ChangesInMargin layout
1005  if (rRedlineText.isEmpty() && !pRedline->IsVisible())
1006  {
1007  rRedlineText = const_cast<SwRangeRedline*>(pRedline)->GetDescr(/*bSimplified=*/true);
1008  pPrevRedline = pRedline;
1009  isExtendText = true;
1010  }
1011  // join the text of the next invisible redlines in the same position
1012  // i.e. characters deleted by pressing backspace or delete
1013  else if (pPrevRedline && !pRedline->IsVisible() &&
1014  *pRedline->Start() == *pPrevRedline->Start() && *pRedline->End() == *pPrevRedline->End() )
1015  {
1016  OUString sExtendText(const_cast<SwRangeRedline*>(pRedline)->GetDescr(/*bSimplified=*/true));
1017  if (!sExtendText.isEmpty())
1018  {
1019  if (rRedlineText.getLength() < 12)
1020  {
1021  // TODO: remove extra space from GetDescr(true),
1022  // but show deletion of paragraph or line break
1023  rRedlineText = rRedlineText +
1024  const_cast<SwRangeRedline*>(pRedline)->GetDescr(/*bSimplified=*/true).subView(1);
1025  }
1026  else
1027  rRedlineText = OUString::Concat(rRedlineText.subView(0, rRedlineText.getLength() - 3)) + "...";
1028  }
1029  isExtendText = true;
1030  }
1031  break;
1032  }
1034  break; // -Werror=switch
1035  }
1036  if (isBreak && !isExtendText)
1037  {
1038  break;
1039  }
1040  }
1041 
1042  m_nStart = nOldStart;
1043  m_nEnd = nOldEnd;
1044  m_nAct = nOldAct;
1045  return bRet;
1046 }
1047 
1049 {
1050  if ( nAttr & ExtTextInputAttr::Underline )
1052  else if ( nAttr & ExtTextInputAttr::BoldUnderline )
1053  rFnt.SetUnderline( LINESTYLE_BOLD );
1054  else if ( nAttr & ExtTextInputAttr::DottedUnderline )
1056  else if ( nAttr & ExtTextInputAttr::DashDotUnderline )
1058 
1059  if ( nAttr & ExtTextInputAttr::RedText )
1060  rFnt.SetColor( COL_RED );
1061 
1062  if ( nAttr & ExtTextInputAttr::Highlight )
1063  {
1064  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1065  rFnt.SetColor( rStyleSettings.GetHighlightTextColor() );
1066  rFnt.SetBackColor( rStyleSettings.GetHighlightColor() );
1067  }
1068  if ( nAttr & ExtTextInputAttr::GrayWaveline )
1069  rFnt.SetGreyWave( true );
1070 }
1071 
1072 short SwExtend::Enter(SwFont& rFnt, SwNodeOffset const nNode, sal_Int32 const nNew)
1073 {
1074  OSL_ENSURE( !m_pFont, "SwExtend: Enter with Font" );
1075  if (nNode != m_nNode)
1076  return 0;
1077  OSL_ENSURE( !Inside(), "SwExtend: Enter without Leave" );
1078  m_nPos = nNew;
1079  if( Inside() )
1080  {
1081  m_pFont.reset( new SwFont(rFnt) );
1082  ActualizeFont( rFnt, m_rArr[m_nPos - m_nStart] );
1083  return 1;
1084  }
1085  return 0;
1086 }
1087 
1088 bool SwExtend::Leave_(SwFont& rFnt, SwNodeOffset const nNode, sal_Int32 const nNew)
1089 {
1090  OSL_ENSURE(nNode == m_nNode && Inside(), "SwExtend: Leave without Enter");
1091  if (nNode != m_nNode)
1092  return true;
1093  const ExtTextInputAttr nOldAttr = m_rArr[m_nPos - m_nStart];
1094  m_nPos = nNew;
1095  if( Inside() )
1096  { // We stayed within the ExtendText-section
1097  const ExtTextInputAttr nAttr = m_rArr[m_nPos - m_nStart];
1098  if( nOldAttr != nAttr ) // Is there an (inner) change of attributes?
1099  {
1100  rFnt = *m_pFont;
1101  ActualizeFont( rFnt, nAttr );
1102  }
1103  }
1104  else
1105  {
1106  rFnt = *m_pFont;
1107  m_pFont.reset();
1108  return true;
1109  }
1110  return false;
1111 }
1112 
1113 sal_Int32 SwExtend::Next(SwNodeOffset const nNode, sal_Int32 nNext)
1114 {
1115  if (nNode != m_nNode)
1116  return nNext;
1117  if (m_nPos < m_nStart)
1118  {
1119  if (nNext > m_nStart)
1120  nNext = m_nStart;
1121  }
1122  else if (m_nPos < m_nEnd)
1123  {
1124  sal_Int32 nIdx = m_nPos - m_nStart;
1125  const ExtTextInputAttr nAttr = m_rArr[ nIdx ];
1126  while (o3tl::make_unsigned(++nIdx) < m_rArr.size() && nAttr == m_rArr[nIdx])
1127  ; //nothing
1128  nIdx = nIdx + m_nStart;
1129  if( nNext > nIdx )
1130  nNext = nIdx;
1131  }
1132  return nNext;
1133 }
1134 
1135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 m_nEnd
Definition: redlnitr.hxx:82
SwScriptInfo * m_pScriptInfo
Definition: itratr.hxx:40
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:159
constexpr TypedWhichId< SvxCrossedOutItem > RES_CHRATR_CROSSEDOUT(5)
std::deque< SwTextAttr * > m_Hints
Definition: redlnitr.hxx:72
SwFontScript WhichFont(TextFrameIndex nIdx) const
Definition: porlay.cxx:878
TextFrameIndex GetInvalidityA() const
Definition: scriptinfo.hxx:118
virtual ::sw::mark::IFieldmark * getFieldmarkAt(const SwPosition &rPos) const =0
get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos
Marks a position in the document model.
Definition: pam.hxx:36
constexpr TypedWhichId< SvxEscapementItem > RES_CHRATR_ESCAPEMENT(6)
void Pop(const SwTextAttr &rAttr)
Only used during redlining.
Definition: atrstck.cxx:462
const SwNodeNum * GetNum(SwRootFrame const *pLayout=nullptr) const
Definition: ndtxt.cxx:3994
SwComparePosition ComparePosition(const T &rStt1, const T &rEnd1, const T &rStt2, const T &rEnd2)
Definition: pam.hxx:78
const OUString & GetText() const
Definition: ndtxt.hxx:218
virtual const SwRootFrame * GetCurrentLayout() const =0
void PopAndChg(const SwTextAttr &rAttr, SwFont &rFnt)
Definition: atrstck.cxx:422
std::unique_ptr< SwFont > m_pFont
Definition: redlnitr.hxx:39
const Color & GetHighlightTextColor() const
SwNodeIndex nNode
Definition: pam.hxx:38
constexpr::Color COL_RED(0x80, 0x00, 0x00)
void SetPriorityAttr(bool bFlag)
Definition: txatbase.hxx:104
LINESTYLE_BOLD
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:277
SwNodeOffset const m_nNdIdx
Definition: redlnitr.hxx:78
#define SW_SCRIPTS
Definition: swfont.hxx:129
Pos1 is as large as Pos2.
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
size_t m_nEndIndex
current iteration index in HintEnds
Definition: itratr.hxx:50
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:451
const sal_uInt32 magic
void SetGreyWave(const bool bNew)
Definition: swfont.hxx:822
Pos1 completely contained in Pos2.
Provides access to the marks of a document.
Definition: doc.hxx:187
void CalcStartEnd(SwNodeOffset nNdIdx, sal_Int32 &rStart, sal_Int32 &rEnd) const
Calculates the intersection with text node number nNdIdx.
Definition: docredln.cxx:1422
sal_Int32 const m_nStart
Definition: redlnitr.hxx:43
SwPosition FindFieldSep(IFieldmark const &rMark)
return position of the CH_TXT_ATR_FIELDSEP for rMark
constexpr TypedWhichId< SvxUnderlineItem > RES_CHRATR_UNDERLINE(14)
SwNode & GetNode() const
Definition: ndindex.hxx:119
SwFont * m_pFont
Definition: itratr.hxx:39
Dialog to specify the properties of date form field.
The root element of a Writer document layout.
Definition: rootfrm.hxx:81
Degree10 GetOrientation(const bool bVertLayout=false, const bool bVertFormatLRBT=false) const
Definition: swfont.cxx:412
bool Seek(TextFrameIndex nPos)
Enables the attributes used at char pos nPos in the logical font.
Definition: itratr.cxx:302
const Color & GetHighlightColor() const
static bool IsShowChanges(const RedlineFlags eM)
bool IsVertLRBT() const
Definition: frame.hxx:983
FieldmarkMode
Definition: rootfrm.hxx:49
void SetColor(const Color &rColor)
Definition: swfont.hxx:418
size_type size() const
Definition: docary.hxx:267
sal_Int32 m_nStart
Definition: redlnitr.hxx:81
Pos1 end touches at Pos2 start.
SwDoc & m_rDoc
Definition: docbm.cxx:1201
sal_Int32 m_nPosition
current iteration index in text node
Definition: itratr.hxx:52
sal_uInt16 sal_Unicode
void RemoveFromListRLHidden()
Definition: ndtxt.cxx:4367
void CtorInitAttrIter(SwTextNode &rTextNode, SwScriptInfo &rScrInf, SwTextFrame const *pFrame=nullptr)
Definition: redlnitr.cxx:520
SwIndex nContent
Definition: pam.hxx:39
o3tl::enumarray< SwFontScript, sal_uInt16 > m_aFontIdx
Definition: itratr.hxx:55
SwRedlineTable::size_type m_nAct
Definition: redlnitr.hxx:80
void FillHints(std::size_t nAuthor, RedlineType eType)
Definition: redlnitr.cxx:805
A wrapper around SfxPoolItem to store the start position of (usually) a text portion, with an optional end.
Definition: txatbase.hxx:43
virtual ::sw::mark::IFieldmark * getFieldmarkFor(const SwPosition &pos) const =0
bool ExtOn()
Definition: redlnitr.hxx:125
std::unique_ptr< sw::MergedPara > CheckParaRedlineMerge(SwTextFrame &rFrame, SwTextNode &rTextNode, FrameMode eMode)
Definition: redlnitr.cxx:208
bool IsOn() const
Definition: redlnitr.hxx:108
Used by Attribute Iterators to organize attributes on stacks to find the valid attribute in each cate...
Definition: atrhndl.hxx:37
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
sal_Int32 NextExtend(SwNodeOffset const nNode, sal_Int32 const nNext)
Definition: redlnitr.hxx:97
short Enter(SwFont &rFnt, SwNodeOffset nNode, sal_Int32 nNew)
Definition: redlnitr.cxx:1072
void InitScriptInfo(const SwTextNode &rNode, sw::MergedPara const *pMerged, bool bRTL)
Definition: porlay.cxx:1064
Pos2 completely contained in Pos1.
void SetUnderline(const FontLineStyle eUnderline)
Definition: swfont.hxx:549
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:152
Pos1 before Pos2.
std::unique_ptr< SwRedlineItr, o3tl::default_delete< SwRedlineItr > > m_pRedline
Definition: itratr.hxx:46
sal_uInt16 GetStackCount() const
Definition: docredln.cxx:1906
sal_Int32 m_nPos
current position (inside)
Definition: redlnitr.hxx:45
SwFormatColl & GetAnyFormatColl() const
Definition: node.hxx:717
void EndListeningAll()
Definition: calbck.cxx:136
FrameMode
Definition: txtfrm.hxx:104
std::vector< Extent > extents
Definition: txtfrm.hxx:960
void InitFontAndAttrHandler(SwTextNode const &rPropsNode, SwTextNode const &rTextNode, OUString const &rText, bool const *pbVertLayout, bool const *pbVertLayoutLRBT)
Definition: redlnitr.cxx:444
bool Inside() const
Definition: redlnitr.hxx:49
std::unique_ptr< SfxItemSet > m_pSet
Definition: redlnitr.hxx:75
sw::MergedPara const * m_pMergedPara
Definition: itratr.hxx:58
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:457
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
SwNodeOffset const m_nNode
position of start of SwExtTextInput
Definition: redlnitr.hxx:42
#define SW_MOD()
Definition: swmodule.hxx:255
void Init(const SwAttrSet &rAttrSet, const IDocumentSettingAccess &rIDocumentSettingAccess)
Definition: atrstck.cxx:277
short EnterExtend(SwFont &rFnt, SwNodeOffset const nNode, sal_Int32 const nNew)
Definition: redlnitr.hxx:92
Pos1 start touches at Pos2 end.
sw::FieldmarkMode GetFieldmarkMode() const
Definition: rootfrm.hxx:423
bool IsVertLayout() const
Definition: atrhndl.hxx:79
void SetVertical(Degree10 nDir, const bool bVertLayout=false, const bool bVertLayoutLRBT=false)
Definition: swfont.cxx:417
SwNodeOffset GetIndex() const
Definition: node.hxx:292
vector_type::size_type size_type
Definition: docary.hxx:222
std::unique_ptr< SwExtend > m_pExt
Definition: redlnitr.hxx:76
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
LINESTYLE_SINGLE
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:182
sal_Int32 const m_nEnd
position of end of SwExtTextInput (in same node as start)
Definition: redlnitr.hxx:47
SwTextNode * pParaPropsNode
most paragraph properties are taken from the first non-empty node
Definition: txtfrm.hxx:965
~SwRedlineItr() COVERITY_NOEXCEPT_FALSE
Definition: redlnitr.cxx:667
void RemoveFootnotesForNode(SwRootFrame const &rLayout, SwTextNode const &rTextNode, std::vector< std::pair< sal_Int32, sal_Int32 >> const *const pExtents)
Definition: txtfrm.cxx:807
const IDocumentSettingAccess * getIDocumentSettingAccess() const
Provides access to the document setting interface.
Definition: node.cxx:2094
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:703
OUString mergedText
note: cannot be const currently to avoid UB because SwTextGuess::Guess const_casts it and modifies it...
Definition: txtfrm.hxx:963
enumrange< T >::Iterator end(enumrange< T >)
const SwPosition * Start() const
Definition: pam.hxx:213
size_t m_nStartIndex
current iteration index in HintStarts
Definition: itratr.hxx:48
sal_uInt8 m_nPropFont
Definition: itratr.hxx:53
const IDocumentLayoutAccess & getIDocumentLayoutAccess() const
Provides access to the document layout interface.
Definition: node.cxx:2099
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
const SwDoc & m_rDoc
Definition: redlnitr.hxx:73
bool Leave_(SwFont &rFnt, SwNodeOffset nNode, sal_Int32 nNew)
Definition: redlnitr.cxx:1088
constexpr TypedWhichId< SvxColorItem > RES_CHRATR_COLOR(3)
SwRedlineTable::size_type const m_nFirst
Definition: redlnitr.hxx:79
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
Mode const m_eMode
Definition: redlnitr.hxx:87
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
bool IsMoved() const
Definition: redline.hxx:273
void Clear_(SwFont *pFnt)
Definition: redlnitr.cxx:845
o3tl::enumarray< SwFontScript, const void * > m_aFontCacheIds
Definition: itratr.hxx:54
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
bool CheckLine(SwNodeOffset nStartNode, sal_Int32 nChkStart, SwNodeOffset nEndNode, sal_Int32 nChkEnd, OUString &rRedlineText, bool &bRedlineEnd, RedlineType &eRedlineEnd, size_t *pAuthorAtPos=nullptr)
Definition: redlnitr.cxx:956
STRIKEOUT_DOUBLE
std::size_t GetAuthor(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1914
void SetBackColor(std::optional< Color > xNewColor)
Definition: swfont.cxx:64
std::pair< sal_Int32, std::pair< SwRangeRedline const *, size_t > > GetNextRedln(sal_Int32 nNext, SwTextNode const *pNode, SwRedlineTable::size_type &rAct)
Ignore mode: does nothing.
Definition: redlnitr.cxx:865
Pos1 overlaps Pos2 at the end.
constexpr::Color COL_GREEN(0x00, 0x80, 0x00)
LINESTYLE_DOTTED
SwAttrHandler m_aAttrHandler
Definition: itratr.hxx:37
sal_uInt8 GetScriptType(const size_t nCnt) const
Definition: scriptinfo.hxx:133
sal_Int32 GetIndex() const
Definition: index.hxx:91
SwNodes & GetNodes()
Definition: doc.hxx:408
const SwPosition * End() const
Definition: pam.hxx:218
bool IsRightToLeft() const
Definition: frame.hxx:987
static void Destroy(SwTextAttr *pToDestroy, SfxItemPool &rPool)
destroy instance
Definition: txatbase.cxx:58
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1929
bool ChkSpecialUnderline_() const
Definition: redlnitr.cxx:941
SwFontScript
Definition: swfont.hxx:123
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:421
constexpr sal_uInt16 RES_CHRATR_END(46)
void ChangeTextAttr(SwFont *pFnt, SwTextAttr const &rHt, bool bChg)
Definition: redlnitr.cxx:824
void PushAndChg(const SwTextAttr &rAttr, SwFont &rFnt)
Definition: atrstck.cxx:337
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
SwNodeOffset Count() const
Definition: ndarr.hxx:141
const std::vector< ExtTextInputAttr > & m_rArr
Definition: redlnitr.hxx:40
bool IsVertical() const
Definition: frame.hxx:973
TextFrameIndex GetScriptChg(const size_t nCnt) const
Definition: scriptinfo.hxx:128
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
size_t CountScriptChg() const
Definition: scriptinfo.hxx:127
void AddToListRLHidden()
Definition: ndtxt.cxx:4336
short Seek(SwFont &rFnt, SwNodeOffset nNode, sal_Int32 nNew, sal_Int32 nOld)
Definition: redlnitr.cxx:675
SwRedlineItr(const SwTextNode &rTextNd, SwFont &rFnt, SwAttrHandler &rAH, sal_Int32 nRedlPos, Mode mode, const std::vector< ExtTextInputAttr > *pArr=nullptr, SwPosition const *pExtInputStart=nullptr)
Definition: redlnitr.cxx:642
ExtTextInputAttr
bool IsInList() const
Definition: ndtxt.cxx:4379
bool HasMergedParas() const
Definition: rootfrm.hxx:425
RedlineType
LINESTYLE_DOUBLE
Pos1 behind Pos2.
SwAttrHandler & m_rAttrHandler
Definition: redlnitr.hxx:74
SwViewShell * m_pViewShell
Definition: itratr.hxx:38
virtual const SwRedlineTable & GetRedlineTable() const =0
short m_nChgCnt
count currently open hints, redlines, ext-input
Definition: itratr.hxx:45
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:183
void SetRedlineMergeFlag(Merge const eMerge)
Definition: node.hxx:98
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:206
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
static constexpr size_type npos
Definition: docary.hxx:223
static void ActualizeFont(SwFont &rFnt, ExtTextInputAttr nAttr)
Definition: redlnitr.cxx:1048
Merge GetRedlineMergeFlag() const
Definition: node.hxx:99
void Clear(SwFont *pFnt)
Definition: redlnitr.hxx:109
SwRootFrame * getRootFrame()
Definition: frame.hxx:679
Pos1 overlaps Pos2 at the beginning.
sal_uInt16 nPos
SwExtTextInput * GetExtTextInput(const SwNode &rNd, sal_Int32 nContentPos=-1) const
Definition: extinput.cxx:274
const std::vector< ExtTextInputAttr > & GetAttrs() const
Definition: extinput.hxx:39
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:864
bool m_bDetectedRangeSegmentation false
Base class of the Writer document model elements.
Definition: node.hxx:81
sal_Int32 Next(SwNodeOffset nNode, sal_Int32 nNext)
Definition: redlnitr.cxx:1113
SwTextAttr * MakeRedlineTextAttr(SwDoc &rDoc, SfxPoolItem const &rAttr)
create redline dummy text hint that must not be inserted into hints array
Definition: thints.cxx:997