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