LibreOffice Module sw (master) 1
findtxt.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <memory>
21
22#include <com/sun/star/util/SearchFlags.hpp>
23#include <com/sun/star/util/SearchResult.hpp>
24#include <comphelper/lok.hxx>
25#include <o3tl/safeint.hxx>
26#include <rtl/ustrbuf.hxx>
27#include <svx/svdview.hxx>
28#include <svl/srchitem.hxx>
29#include <sfx2/sfxsids.hrc>
30#include <editeng/outliner.hxx>
31#include <osl/diagnose.h>
32
33#include <wrtsh.hxx>
34#include <txatritr.hxx>
35#include <fldbas.hxx>
36#include <fmtfld.hxx>
37#include <txtfld.hxx>
38#include <txtfrm.hxx>
39#include <rootfrm.hxx>
40#include <swcrsr.hxx>
41#include <redline.hxx>
42#include <doc.hxx>
43#include <IDocumentUndoRedo.hxx>
44#include <IDocumentState.hxx>
47#include <dcontact.hxx>
48#include <pamtyp.hxx>
49#include <ndtxt.hxx>
50#include <swundo.hxx>
51#include <UndoInsert.hxx>
52#include <breakit.hxx>
53#include <docsh.hxx>
54#include <PostItMgr.hxx>
55#include <view.hxx>
56
57using namespace ::com::sun::star;
58using namespace util;
59
60namespace {
61
64struct AmbiguousIndex
65{
66private:
67 sal_Int32 m_value;
68
69#ifndef NDEBUG
70 enum class tags : char { Any, Frame, Model };
71 tags m_tag;
72#endif
73
74public:
75 AmbiguousIndex() : m_value(-1)
76#ifndef NDEBUG
77 , m_tag(tags::Any)
78#endif
79 {}
80 explicit AmbiguousIndex(sal_Int32 const value
81#ifndef NDEBUG
82 , tags const tag
83#endif
84 ) : m_value(value)
85#ifndef NDEBUG
86 , m_tag(tag)
87#endif
88 {}
89
90 sal_Int32 & GetAnyIndex() { return m_value; }
91 sal_Int32 const& GetAnyIndex() const { return m_value; }
92 TextFrameIndex GetFrameIndex() const
93 {
94 assert(m_tag != tags::Model);
95 return TextFrameIndex(m_value);
96 }
97 sal_Int32 GetModelIndex() const
98 {
99 assert(m_tag != tags::Frame);
100 return m_value;
101 }
102 void SetFrameIndex(TextFrameIndex const value)
103 {
104#ifndef NDEBUG
105 m_tag = tags::Frame;
106#endif
107 m_value = sal_Int32(value);
108 }
109 void SetModelIndex(sal_Int32 const value)
110 {
111#ifndef NDEBUG
112 m_tag = tags::Model;
113#endif
114 m_value = value;
115 }
116
117 bool operator ==(AmbiguousIndex const& rOther) const
118 {
119 assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
120 return m_value == rOther.m_value;
121 }
122 bool operator <=(AmbiguousIndex const& rOther) const
123 {
124 assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
125 return m_value <= rOther.m_value;
126 }
127 bool operator < (AmbiguousIndex const& rOther) const
128 {
129 assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
130 return m_value < rOther.m_value;
131 }
132 AmbiguousIndex operator - (AmbiguousIndex const& rOther) const
133 {
134 assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
135 return AmbiguousIndex(m_value - rOther.m_value
136#ifndef NDEBUG
137 , std::max(m_tag, rOther.m_tag)
138#endif
139 );
140 }
141};
142
143class MaybeMergedIter
144{
145 std::optional<sw::MergedAttrIter> m_oMergedIter;
146 SwTextNode const*const m_pNode;
147 size_t m_HintIndex;
148
149public:
150 MaybeMergedIter(SwTextFrame const*const pFrame, SwTextNode const*const pNode)
151 : m_pNode(pNode)
152 , m_HintIndex(0)
153 {
154 if (pFrame)
155 {
156 m_oMergedIter.emplace(*pFrame);
157 }
158 }
159
160 SwTextAttr const* NextAttr(SwTextNode const*& rpNode)
161 {
162 if (m_oMergedIter)
163 {
164 return m_oMergedIter->NextAttr(&rpNode);
165 }
166 if (SwpHints const*const pHints = m_pNode->GetpSwpHints())
167 {
168 if (m_HintIndex < pHints->Count())
169 {
170 rpNode = m_pNode;
171 return pHints->Get(m_HintIndex++);
172 }
173 }
174 return nullptr;
175 }
176};
177
178}
179
180static OUString
182 SwTextFrame const*const pFrame,
183 SwRootFrame const*const pLayout,
184 AmbiguousIndex const nStart, AmbiguousIndex & rEnd,
185 std::vector<AmbiguousIndex> &rArr,
186 bool const bRemoveSoftHyphen, bool const bRemoveCommentAnchors)
187{
188 OUStringBuffer buf(pLayout ? pFrame->GetText() : rNd.GetText());
189 rArr.clear();
190
191 MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rNd);
192
193 AmbiguousIndex nSoftHyphen = nStart;
194 AmbiguousIndex nHintStart;
195 bool bNewHint = true;
196 bool bNewSoftHyphen = true;
197 const AmbiguousIndex nEnd = rEnd;
198 std::vector<AmbiguousIndex> aReplaced;
199 SwTextNode const* pNextHintNode(nullptr);
200 SwTextAttr const* pNextHint(iter.NextAttr(pNextHintNode));
201
202 do
203 {
204 if ( bNewHint )
205 {
206 if (pLayout)
207 {
208 nHintStart.SetFrameIndex(pNextHint
209 ? pFrame->MapModelToView(pNextHintNode, pNextHint->GetStart())
210 : TextFrameIndex(-1));
211 }
212 else
213 {
214 nHintStart.SetModelIndex(pNextHint ? pNextHint->GetStart() : -1);
215 }
216 }
217
218 if ( bNewSoftHyphen )
219 {
220 if (pLayout)
221 {
222 nSoftHyphen.SetFrameIndex(TextFrameIndex(bRemoveSoftHyphen
223 ? pFrame->GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen.GetAnyIndex())
224 : -1));
225 }
226 else
227 {
228 nSoftHyphen.SetModelIndex(bRemoveSoftHyphen
229 ? rNd.GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen.GetAnyIndex())
230 : -1);
231 }
232 }
233
234 bNewHint = false;
235 bNewSoftHyphen = false;
236 AmbiguousIndex nStt;
237
238 // Check if next stop is a hint.
239 if (0 <= nHintStart.GetAnyIndex()
240 && (-1 == nSoftHyphen.GetAnyIndex() || nHintStart < nSoftHyphen)
241 && nHintStart < nEnd )
242 {
243 nStt = nHintStart;
244 bNewHint = true;
245 }
246 // Check if next stop is a soft hyphen.
247 else if ( -1 != nSoftHyphen.GetAnyIndex()
248 && (-1 == nHintStart.GetAnyIndex() || nSoftHyphen < nHintStart)
249 && nSoftHyphen < nEnd)
250 {
251 nStt = nSoftHyphen;
252 bNewSoftHyphen = true;
253 }
254 // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
255 else if (-1 != nSoftHyphen.GetAnyIndex() && nSoftHyphen == nHintStart)
256 {
257 nStt = nSoftHyphen;
258 bNewHint = true;
259 bNewSoftHyphen = true;
260 }
261 else
262 break;
263
264 AmbiguousIndex nCurrent(nStt);
265 nCurrent.GetAnyIndex() -= rArr.size();
266
267 if ( bNewHint )
268 {
269 if (pNextHint && pNextHint->HasDummyChar() && (nStart <= nStt))
270 {
271 switch (pNextHint->Which())
272 {
274 case RES_TXTATR_FIELD:
277 case RES_TXTATR_META:
279 {
280 // (1998) they are desired as separators and
281 // belong not any longer to a word.
282 // they should also be ignored at a
283 // beginning/end of a sentence if blank. Those are
284 // simply removed if first. If at the end, we keep the
285 // replacement and remove afterwards all at a string's
286 // end (might be normal 0x7f).
287 const bool bEmpty = pNextHint->Which() != RES_TXTATR_FIELD
288 || (static_txtattr_cast<SwTextField const*>(pNextHint)->GetFormatField().GetField()->ExpandField(true, pLayout).isEmpty());
289 if ( bEmpty && nStart == nCurrent )
290 {
291 rArr.push_back( nCurrent );
292 if (rEnd.GetAnyIndex() > nCurrent.GetAnyIndex())
293 {
294 --rEnd.GetAnyIndex();
295 }
296 buf.remove(nCurrent.GetAnyIndex(), 1);
297 }
298 else
299 {
300 if ( bEmpty )
301 aReplaced.push_back( nCurrent );
302 buf[nCurrent.GetAnyIndex()] = '\x7f';
303 }
304 }
305 break;
307 {
308 if( bRemoveCommentAnchors )
309 {
310 rArr.push_back( nCurrent );
311 if (rEnd.GetAnyIndex() > nCurrent.GetAnyIndex())
312 {
313 --rEnd.GetAnyIndex();
314 }
315 buf.remove( nCurrent.GetAnyIndex(), 1 );
316 }
317 }
318 break;
319 default:
320 OSL_FAIL( "unknown case in lcl_CleanStr" );
321 break;
322 }
323 }
324 pNextHint = iter.NextAttr(pNextHintNode);
325 }
326
327 if ( bNewSoftHyphen )
328 {
329 rArr.push_back( nCurrent );
330
331 // If the soft hyphen to be removed is past the end of the range we're searching in,
332 // don't adjust the end.
333 if (rEnd.GetAnyIndex() > nCurrent.GetAnyIndex())
334 {
335 --rEnd.GetAnyIndex();
336 }
337
338 buf.remove(nCurrent.GetAnyIndex(), 1);
339 ++nSoftHyphen.GetAnyIndex();
340 }
341 }
342 while ( true );
343
344 for (auto i = aReplaced.size(); i; )
345 {
346 const AmbiguousIndex nTmp = aReplaced[ --i ];
347 if (nTmp.GetAnyIndex() == buf.getLength() - 1)
348 {
349 buf.truncate(nTmp.GetAnyIndex());
350 rArr.push_back( nTmp );
351 --rEnd.GetAnyIndex();
352 }
353 }
354
355 return buf.makeStringAndClear();
356}
357
358static bool DoSearch(SwPaM & rSearchPam,
359 const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText,
360 SwMoveFnCollection const & fnMove,
361 bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd,
362 AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex nTextLen,
363 SwTextNode const* pNode, SwTextFrame const* pTextFrame,
364 SwRootFrame const* pLayout, SwPaM* pPam);
365
366namespace sw {
367
368// @param xSearchItem allocate in parent so we can do so outside the calling loop
369bool FindTextImpl(SwPaM & rSearchPam,
370 const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
371 utl::TextSearch& rSText,
372 SwMoveFnCollection const & fnMove, const SwPaM & rRegion,
373 bool bInReadOnly, SwRootFrame const*const pLayout,
374 std::unique_ptr<SvxSearchItem>& xSearchItem)
375{
376 if( rSearchOpt.searchString.isEmpty() )
377 return false;
378
379 std::optional<SwPaM> oPam;
380 sw::MakeRegion(fnMove, rRegion, oPam);
381 const bool bSrchForward = &fnMove == &fnMoveForward;
382 SwPosition& rPtPos = *oPam->GetPoint();
383
384 // If bFound is true then the string was found and is between nStart and nEnd
385 bool bFound = false;
386 // start position in text or initial position
387 bool bFirst = true;
388 SwContentNode * pNode;
389
390 const bool bRegSearch = SearchAlgorithms2::REGEXP == rSearchOpt.AlgorithmType2;
391 const bool bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
392 ( rSearchOpt.searchString == "^$" ||
393 rSearchOpt.searchString == "$^" );
394 const bool bChkParaEnd = bRegSearch && rSearchOpt.searchString == "$";
395
396 if (!xSearchItem)
397 {
398 xSearchItem.reset(new SvxSearchItem(SID_SEARCH_ITEM)); // this is a very expensive operation (calling configmgr etc.)
399 xSearchItem->SetSearchOptions(rSearchOpt);
400 xSearchItem->SetBackward(!bSrchForward);
401 }
402
403 // LanguageType eLastLang = 0;
404 while (nullptr != (pNode = ::GetNode(*oPam, bFirst, fnMove, bInReadOnly, pLayout)))
405 {
406 if( pNode->IsTextNode() )
407 {
408 SwTextNode& rTextNode = *pNode->GetTextNode();
409 SwTextFrame const*const pFrame(pLayout
410 ? static_cast<SwTextFrame const*>(rTextNode.getLayoutFrame(pLayout))
411 : nullptr);
412 assert(!pLayout || pFrame);
413 AmbiguousIndex nTextLen;
414 if (pLayout)
415 {
416 nTextLen.SetFrameIndex(TextFrameIndex(pFrame->GetText().getLength()));
417 }
418 else
419 {
420 nTextLen.SetModelIndex(rTextNode.GetText().getLength());
421 }
422 AmbiguousIndex nEnd;
423 if (pLayout
424 ? FrameContainsNode(*pFrame, oPam->GetMark()->GetNodeIndex())
425 : rPtPos.GetNode() == oPam->GetMark()->GetNode())
426 {
427 if (pLayout)
428 {
429 nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*oPam->GetMark()));
430 }
431 else
432 {
433 nEnd.SetModelIndex(oPam->GetMark()->GetContentIndex());
434 }
435 }
436 else
437 {
438 if (bSrchForward)
439 {
440 nEnd = nTextLen;
441 }
442 else
443 {
444 if (pLayout)
445 {
446 nEnd.SetFrameIndex(TextFrameIndex(0));
447 }
448 else
449 {
450 nEnd.SetModelIndex(0);
451 }
452 }
453 }
454 AmbiguousIndex nStart;
455 if (pLayout)
456 {
457 nStart.SetFrameIndex(pFrame->MapModelToViewPos(*oPam->GetPoint()));
458 }
459 else
460 {
461 nStart.SetModelIndex(rPtPos.GetContentIndex());
462 }
463
464 /* #i80135# */
465 // if there are SwPostItFields inside our current node text, we
466 // split the text into separate pieces and search for text inside
467 // the pieces as well as inside the fields
468 MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rTextNode);
469
470 // count PostItFields by looping over all fields
471 std::vector<std::pair<SwTextAttr const*, AmbiguousIndex>> postits;
472 if (bSearchInNotes)
473 {
474 if (!bSrchForward)
475 {
476 std::swap(nStart, nEnd);
477 }
478
479 SwTextNode const* pTemp(nullptr);
480 while (SwTextAttr const*const pTextAttr = iter.NextAttr(pTemp))
481 {
482 if ( pTextAttr->Which()==RES_TXTATR_ANNOTATION )
483 {
484 AmbiguousIndex aPos;
485 aPos.SetModelIndex(pTextAttr->GetStart());
486 if (pLayout)
487 {
488 aPos.SetFrameIndex(pFrame->MapModelToView(pTemp, aPos.GetModelIndex()));
489 }
490 if ((nStart <= aPos) && (aPos <= nEnd))
491 {
492 postits.emplace_back(pTextAttr, aPos);
493 }
494 }
495 }
496
497 if (!bSrchForward)
498 {
499 std::swap(nStart, nEnd);
500 }
501
502 }
503
504 SwDocShell *const pDocShell = pNode->GetDoc().GetDocShell();
505 SwWrtShell *const pWrtShell = pDocShell ? pDocShell->GetWrtShell() : nullptr;
506 SwPostItMgr *const pPostItMgr = pWrtShell ? pWrtShell->GetPostItMgr() : nullptr;
507
508 // If there is an active text edit, then search there.
509 bool bEndedTextEdit = false;
510 SdrView* pSdrView = pWrtShell ? pWrtShell->GetDrawView() : nullptr;
511 if (pSdrView)
512 {
513 // If the edited object is not anchored to this node, then ignore it.
514 SdrObject* pObject = pSdrView->GetTextEditObject();
515 if (pObject)
516 {
517 if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject))
518 {
519 const SwPosition* pPosition = pFrameFormat->GetAnchor().GetContentAnchor();
520 if (!pPosition || (pLayout
521 ? !FrameContainsNode(*pFrame, pPosition->GetNodeIndex())
522 : pPosition->GetNodeIndex() != pNode->GetIndex()))
523 pObject = nullptr;
524 }
525 }
526
527 if (pObject)
528 {
529 sal_uInt16 nResult = pSdrView->GetTextEditOutlinerView()->StartSearchAndReplace(*xSearchItem);
530 if (!nResult)
531 {
532 // If not found, end the text edit.
533 pSdrView->SdrEndTextEdit();
534 const Point aPoint(pSdrView->GetAllMarkedRect().TopLeft());
535 pSdrView->UnmarkAll();
536 pWrtShell->CallSetCursor(&aPoint, true);
537 pWrtShell->Edit();
538 bEndedTextEdit = true;
539 }
540 else
541 {
542 bFound = true;
543 break;
544 }
545 }
546 }
547
549 {
550 // Writer and editeng selections are not supported in parallel.
551 SvxSearchItem* pSearchItem = SwView::GetSearchItem();
552 // If we just finished search in shape text, don't attempt to do that again.
553 if (!bEndedTextEdit && !(pSearchItem && pSearchItem->GetCommand() == SvxSearchCmd::FIND_ALL))
554 {
555 // If there are any shapes anchored to this node, search there.
556 SwPaM aPaM(pNode->GetDoc().GetNodes().GetEndOfContent());
557 if (pLayout)
558 {
559 *aPaM.GetPoint() = pFrame->MapViewToModelPos(nStart.GetFrameIndex());
560 }
561 else
562 {
563 aPaM.GetPoint()->Assign(rTextNode, nStart.GetModelIndex());
564 }
565 aPaM.SetMark();
566 if (pLayout)
567 {
568 aPaM.GetMark()->Assign( (pFrame->GetMergedPara()
569 ? *pFrame->GetMergedPara()->pLastNode
570 : rTextNode)
571 .GetIndex() + 1 );
572 }
573 else
574 {
575 aPaM.GetMark()->Assign( rTextNode.GetIndex() + 1 );
576 }
577 if (pNode->GetDoc().getIDocumentDrawModelAccess().Search(aPaM, *xSearchItem) && pSdrView)
578 {
579 if (SdrObject* pObject = pSdrView->GetTextEditObject())
580 {
581 if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject))
582 {
583 const SwPosition* pPosition = pFrameFormat->GetAnchor().GetContentAnchor();
584 if (pPosition)
585 {
586 // Set search position to the shape's anchor point.
587 rSearchPam.GetPoint()->Assign(pPosition->GetNode());
588 rSearchPam.SetMark();
589 bFound = true;
590 break;
591 }
592 }
593 }
594 }
595 }
596 }
597
598 // do we need to finish a note?
599 if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
600 {
601 if (bSearchInNotes)
602 {
603 if (!postits.empty())
604 {
605 if (bSrchForward)
606 {
607 postits.erase(postits.begin());
608 }
609 else
610 {
611 postits.pop_back(); // hope that's the right one?
612 }
613 }
614 //search inside, finish and put focus back into the doc
615 if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
616 {
617 bFound = true ;
618 break;
619 }
620 }
621 else
622 {
623 pPostItMgr->SetActiveSidebarWin(nullptr);
624 }
625 }
626
627 if (!postits.empty())
628 {
629 // now we have to split
630 AmbiguousIndex nStartInside;
631 AmbiguousIndex nEndInside;
632 sal_Int32 aLoop = bSrchForward ? 0 : postits.size();
633
634 while ((0 <= aLoop) && (o3tl::make_unsigned(aLoop) <= postits.size()))
635 {
636 if (bSrchForward)
637 {
638 if (aLoop == 0)
639 {
640 nStartInside = nStart;
641 }
642 else if (pLayout)
643 {
644 nStartInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + TextFrameIndex(1));
645 }
646 else
647 {
648 nStartInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1);
649 }
650 nEndInside = static_cast<size_t>(aLoop) == postits.size()
651 ? nEnd
652 : postits[aLoop].second;
653 nTextLen = nEndInside - nStartInside;
654 }
655 else
656 {
657 nStartInside = static_cast<size_t>(aLoop) == postits.size()
658 ? nStart
659 : postits[aLoop].second;
660 if (aLoop == 0)
661 {
662 nEndInside = nEnd;
663 }
664 else if (pLayout)
665 {
666 nEndInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + TextFrameIndex(1));
667 }
668 else
669 {
670 nEndInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1);
671 }
672 nTextLen = nStartInside - nEndInside;
673 }
674 // search inside the text between a note
675 bFound = DoSearch( rSearchPam,
676 rSearchOpt, rSText, fnMove, bSrchForward,
677 bRegSearch, bChkEmptyPara, bChkParaEnd,
678 nStartInside, nEndInside, nTextLen,
679 pNode->GetTextNode(), pFrame, pLayout,
680 oPam ? &*oPam : nullptr );
681 if ( bFound )
682 break;
683 else
684 {
685 // we should now be right in front of a note, search inside
686 if (bSrchForward
687 ? (static_cast<size_t>(aLoop) != postits.size())
688 : (aLoop != 0))
689 {
690 const SwTextAttr *const pTextAttr = bSrchForward
691 ? postits[aLoop].first
692 : postits[aLoop - 1].first;
693 if (pPostItMgr && pPostItMgr->SearchReplace(
694 static_txtattr_cast<SwTextField const*>(pTextAttr)->GetFormatField(),rSearchOpt,bSrchForward))
695 {
696 bFound = true ;
697 break;
698 }
699 }
700 }
701 aLoop = bSrchForward ? aLoop+1 : aLoop-1;
702 }
703 }
704 else
705 {
706 // if there is no SwPostItField inside or searching inside notes
707 // is disabled, we search the whole length just like before
708 bFound = DoSearch( rSearchPam,
709 rSearchOpt, rSText, fnMove, bSrchForward,
710 bRegSearch, bChkEmptyPara, bChkParaEnd,
711 nStart, nEnd, nTextLen,
712 pNode->GetTextNode(), pFrame, pLayout,
713 oPam ? &*oPam : nullptr );
714 }
715 if (bFound)
716 break;
717 }
718 }
719 return bFound;
720}
721
722} // namespace sw
723
724bool DoSearch(SwPaM & rSearchPam,
725 const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText,
726 SwMoveFnCollection const & fnMove, bool bSrchForward, bool bRegSearch,
727 bool bChkEmptyPara, bool bChkParaEnd,
728 AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex const nTextLen,
729 SwTextNode const*const pNode, SwTextFrame const*const pFrame,
730 SwRootFrame const*const pLayout, SwPaM* pPam)
731{
732 bool bFound = false;
733 SwPosition& rPtPos = *pPam->GetPoint();
734 OUString sCleanStr;
735 std::vector<AmbiguousIndex> aFltArr;
736 LanguageType eLastLang = LANGUAGE_SYSTEM;
737 // if the search string contains a soft hyphen,
738 // we don't strip them from the text:
739 bool bRemoveSoftHyphens = true;
740 // if the search string contains a comment, we don't strip them from the text
741 const bool bRemoveCommentAnchors = rSearchOpt.searchString.indexOf( CH_TXTATR_INWORD ) == -1;
742
743 if ( bRegSearch )
744 {
745 if ( -1 != rSearchOpt.searchString.indexOf("\\xAD")
746 || -1 != rSearchOpt.searchString.indexOf("\\x{00AD}")
747 || -1 != rSearchOpt.searchString.indexOf("\\u00AD")
748 || -1 != rSearchOpt.searchString.indexOf("\\U000000AD")
749 || -1 != rSearchOpt.searchString.indexOf("\\N{SOFT HYPHEN}"))
750 {
751 bRemoveSoftHyphens = false;
752 }
753 }
754 else
755 {
756 if ( 1 == rSearchOpt.searchString.getLength() &&
757 CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
758 bRemoveSoftHyphens = false;
759 }
760
761 if( bSrchForward )
762 sCleanStr = lcl_CleanStr(*pNode, pFrame, pLayout, nStart, nEnd,
763 aFltArr, bRemoveSoftHyphens, bRemoveCommentAnchors);
764 else
765 sCleanStr = lcl_CleanStr(*pNode, pFrame, pLayout, nEnd, nStart,
766 aFltArr, bRemoveSoftHyphens, bRemoveCommentAnchors);
767
768 std::unique_ptr<SwScriptIterator> pScriptIter;
769 sal_uInt16 nSearchScript = 0;
770 sal_uInt16 nCurrScript = 0;
771
772 if (SearchAlgorithms2::APPROXIMATE == rSearchOpt.AlgorithmType2)
773 {
774 pScriptIter.reset(new SwScriptIterator(sCleanStr, nStart.GetAnyIndex(), bSrchForward));
775 nSearchScript = g_pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
776 }
777
778 const AmbiguousIndex nStringEnd = nEnd;
779 bool bZeroMatch = false; // zero-length match, i.e. only $ anchor as regex
780 while ( ((bSrchForward && nStart < nStringEnd) ||
781 (!bSrchForward && nStringEnd < nStart)) && !bZeroMatch )
782 {
783 // SearchAlgorithms_APPROXIMATE works on a per word base so we have to
784 // provide the text searcher with the correct locale, because it uses
785 // the break-iterator
786 if ( pScriptIter )
787 {
788 nEnd.GetAnyIndex() = pScriptIter->GetScriptChgPos();
789 nCurrScript = pScriptIter->GetCurrScript();
790 if ( nSearchScript == nCurrScript )
791 {
792 const LanguageType eCurrLang = pLayout
793 ? pFrame->GetLangOfChar(bSrchForward
794 ? nStart.GetFrameIndex()
795 : nEnd.GetFrameIndex(),
796 0, true)
797 : pNode->GetLang(bSrchForward
798 ? nStart.GetModelIndex()
799 : nEnd.GetModelIndex());
800
801 if ( eCurrLang != eLastLang )
802 {
803 const lang::Locale aLocale(
804 g_pBreakIt->GetLocale( eCurrLang ) );
805 rSText.SetLocale( utl::TextSearch::UpgradeToSearchOptions2( rSearchOpt), aLocale );
806 eLastLang = eCurrLang;
807 }
808 }
809 pScriptIter->Next();
810 }
811 AmbiguousIndex nProxyStart = nStart;
812 AmbiguousIndex nProxyEnd = nEnd;
813 if( nSearchScript == nCurrScript &&
814 (rSText.*fnMove.fnSearch)( sCleanStr, &nProxyStart.GetAnyIndex(), &nProxyEnd.GetAnyIndex(), nullptr) &&
815 !(bZeroMatch = (nProxyStart == nProxyEnd)))
816 {
817 nStart = nProxyStart;
818 nEnd = nProxyEnd;
819 // set section correctly
820 *rSearchPam.GetPoint() = *pPam->GetPoint();
821 rSearchPam.SetMark();
822
823 // adjust start and end
824 if( !aFltArr.empty() )
825 {
826 // if backward search, switch positions temporarily
827 if (!bSrchForward) { std::swap(nStart, nEnd); }
828
829 AmbiguousIndex nNew = nStart;
830 for (size_t n = 0; n < aFltArr.size() && aFltArr[ n ] <= nStart; ++n )
831 {
832 ++nNew.GetAnyIndex();
833 }
834
835 nStart = nNew;
836 nNew = nEnd;
837 for( size_t n = 0; n < aFltArr.size() && aFltArr[ n ] < nEnd; ++n )
838 {
839 ++nNew.GetAnyIndex();
840 }
841
842 nEnd = nNew;
843 // if backward search, switch positions temporarily
844 if( !bSrchForward ) { std::swap(nStart, nEnd); }
845 }
846 if (pLayout)
847 {
848 *rSearchPam.GetMark() = pFrame->MapViewToModelPos(nStart.GetFrameIndex());
849 *rSearchPam.GetPoint() = pFrame->MapViewToModelPos(nEnd.GetFrameIndex());
850 }
851 else
852 {
853 rSearchPam.GetMark()->SetContent( nStart.GetModelIndex() );
854 rSearchPam.GetPoint()->SetContent( nEnd.GetModelIndex() );
855 }
856
857 // if backward search, switch point and mark
858 if( !bSrchForward )
859 rSearchPam.Exchange();
860 bFound = true;
861 break;
862 }
863 else
864 {
865 nEnd = nProxyEnd;
866 }
867 nStart = nEnd;
868 }
869
870 pScriptIter.reset();
871
872 if ( bFound )
873 return true;
874 else if ((bChkEmptyPara && !nStart.GetAnyIndex() && !nTextLen.GetAnyIndex())
875 || bChkParaEnd)
876 {
877 *rSearchPam.GetPoint() = *pPam->GetPoint();
878 if (pLayout)
879 {
880 *rSearchPam.GetPoint() = pFrame->MapViewToModelPos(
881 bChkParaEnd ? nTextLen.GetFrameIndex() : TextFrameIndex(0));
882 }
883 else
884 {
885 rSearchPam.GetPoint()->SetContent( bChkParaEnd ? nTextLen.GetModelIndex() : 0 );
886 }
887 rSearchPam.SetMark();
888 const SwNode *const pSttNd = bSrchForward
889 ? &rSearchPam.GetPoint()->GetNode() // end of the frame
890 : &rPtPos.GetNode(); // keep the bug as-is for now...
891 /* FIXME: this condition does not work for !bSrchForward backward
892 * search, it probably never did. (pSttNd != &rNdIdx.GetNode())
893 * is never true in this case. */
894 if( (bSrchForward || pSttNd != &rPtPos.GetNode()) &&
895 rSearchPam.Move(fnMoveForward, GoInContent) &&
896 (!bSrchForward || pSttNd != &rSearchPam.GetPoint()->GetNode()) &&
897 SwNodeOffset(1) == abs(rSearchPam.GetPoint()->GetNodeIndex() -
898 rSearchPam.GetMark()->GetNodeIndex()))
899 {
900 // if backward search, switch point and mark
901 if( !bSrchForward )
902 rSearchPam.Exchange();
903 return true;
904 }
905 }
906 return bFound;
907}
908
909namespace {
910
912struct SwFindParaText : public SwFindParas
913{
914 const i18nutil::SearchOptions2& m_rSearchOpt;
915 SwCursor& m_rCursor;
916 SwRootFrame const* m_pLayout;
917 utl::TextSearch m_aSText;
918 bool m_bReplace;
919 bool m_bSearchInNotes;
920
921 SwFindParaText(const i18nutil::SearchOptions2& rOpt, bool bSearchInNotes,
922 bool bRepl, SwCursor& rCursor, SwRootFrame const*const pLayout)
923 : m_rSearchOpt( rOpt )
924 , m_rCursor( rCursor )
925 , m_pLayout(pLayout)
926 , m_aSText( utl::TextSearch::UpgradeToSearchOptions2(rOpt) )
927 , m_bReplace( bRepl )
928 , m_bSearchInNotes( bSearchInNotes )
929 {}
930 virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly, std::unique_ptr<SvxSearchItem>& xSearchItem) override;
931 virtual bool IsReplaceMode() const override;
932 virtual ~SwFindParaText();
933};
934
935}
936
937SwFindParaText::~SwFindParaText()
938{
939}
940
941int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
942 const SwPaM & rRegion, bool bInReadOnly,
943 std::unique_ptr<SvxSearchItem>& xSearchItem)
944{
945 if( bInReadOnly && m_bReplace )
946 bInReadOnly = false;
947
948 const bool bFnd = sw::FindTextImpl(rCursor, m_rSearchOpt, m_bSearchInNotes,
949 m_aSText, fnMove, rRegion, bInReadOnly, m_pLayout, xSearchItem);
950
951 if( bFnd && m_bReplace ) // replace string
952 {
953 // use replace method in SwDoc
954 const bool bRegExp(SearchAlgorithms2::REGEXP == m_rSearchOpt.AlgorithmType2);
955 const sal_Int32 nSttCnt = rCursor.Start()->GetContentIndex();
956 // add to shell-cursor-ring so that the regions will be moved eventually
957 SwPaM* pPrev(nullptr);
958 if( bRegExp )
959 {
960 pPrev = const_cast<SwPaM&>(rRegion).GetPrev();
961 const_cast<SwPaM&>(rRegion).GetRingContainer().merge( m_rCursor.GetRingContainer() );
962 }
963
964 std::optional<OUString> xRepl;
965 if (bRegExp)
966 xRepl = sw::ReplaceBackReferences(m_rSearchOpt, &rCursor, m_pLayout);
967 bool const bReplaced = sw::ReplaceImpl(rCursor,
968 xRepl ? *xRepl : m_rSearchOpt.replaceString,
969 bRegExp, m_rCursor.GetDoc(), m_pLayout);
970
971 m_rCursor.SaveTableBoxContent( rCursor.GetPoint() );
972
973 if( bRegExp )
974 {
975 // and remove region again
976 SwPaM* p;
977 SwPaM* pNext(const_cast<SwPaM*>(&rRegion));
978 do {
979 p = pNext;
980 pNext = p->GetNext();
981 p->MoveTo(const_cast<SwPaM*>(&rRegion));
982 } while( p != pPrev );
983 }
984 if (bRegExp && !bReplaced)
985 { // fdo#80715 avoid infinite loop if join failed
986 bool bRet = ((&fnMoveForward == &fnMove) ? &GoNextPara : &GoPrevPara)
987 (rCursor, fnMove);
988 (void) bRet;
989 assert(bRet); // if join failed, next node must be SwTextNode
990 }
991 else
992 rCursor.Start()->SetContent(nSttCnt);
993 return FIND_NO_RING;
994 }
995 return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
996}
997
998bool SwFindParaText::IsReplaceMode() const
999{
1000 return m_bReplace;
1001}
1002
1003sal_Int32 SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
1004 SwDocPositions nStart, SwDocPositions nEnd,
1005 bool& bCancel, FindRanges eFndRngs, bool bReplace,
1006 SwRootFrame const*const pLayout)
1007{
1008 // switch off OLE-notifications
1009 SwDoc& rDoc = GetDoc();
1010 Link<bool,void> aLnk( rDoc.GetOle2Link() );
1011 rDoc.SetOle2Link( Link<bool,void>() );
1012
1013 bool const bStartUndo = rDoc.GetIDocumentUndoRedo().DoesUndo() && bReplace;
1014 if (bStartUndo)
1015 {
1017 }
1018
1019 bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
1020 if( bSearchSel )
1021 eFndRngs = static_cast<FindRanges>(eFndRngs | FindRanges::InSel);
1022 SwFindParaText aSwFindParaText(rSearchOpt, bSearchInNotes, bReplace, *this, pLayout);
1023 sal_Int32 nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel );
1024 rDoc.SetOle2Link( aLnk );
1025 if( nRet && bReplace )
1027
1028 if (bStartUndo)
1029 {
1031 nRet, rSearchOpt.searchString, rSearchOpt.replaceString));
1032 rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::REPLACE, & rewriter );
1033 }
1034 return nRet;
1035}
1036
1037namespace sw {
1038
1040 SwPaM & rCursor,
1041 OUString const& rReplacement,
1042 bool const bRegExp,
1043 SwDoc & rDoc,
1044 SwRootFrame const*const pLayout)
1045{
1046 bool bReplaced(true);
1048#if 0
1049 // FIXME there's some problem with multiple redlines here on Undo
1050 std::vector<std::shared_ptr<SwUnoCursor>> ranges;
1052 || !pLayout
1053 || !pLayout->IsHideRedlines()
1054 || sw::GetRanges(ranges, rDoc, rCursor))
1055 {
1056 bReplaced = rIDCO.ReplaceRange(rCursor, rReplacement, bRegExp);
1057 }
1058 else
1059 {
1060 assert(!ranges.empty());
1061 assert(ranges.front()->GetPoint()->GetNode() == ranges.front()->GetMark()->GetNode());
1062 bReplaced = rIDCO.ReplaceRange(*ranges.front(), rReplacement, bRegExp);
1063 for (auto it = ranges.begin() + 1; it != ranges.end(); ++it)
1064 {
1065 bReplaced &= rIDCO.DeleteAndJoin(**it);
1066 }
1067 }
1068#else
1070 if (pLayout && pLayout->IsHideRedlines()
1071 && !rIDRA.IsRedlineOn() // otherwise: ReplaceRange will handle it
1072 && (rIDRA.GetRedlineFlags() & RedlineFlags::ShowDelete)) // otherwise: ReplaceRange will DeleteRedline()
1073 {
1075 rIDRA.GetRedline(*rCursor.Start(), &tmp);
1076 while (tmp < rIDRA.GetRedlineTable().size())
1077 {
1078 SwRangeRedline const*const pRedline(rIDRA.GetRedlineTable()[tmp]);
1079 if (*rCursor.End() <= *pRedline->Start())
1080 {
1081 break;
1082 }
1083 if (*pRedline->End() <= *rCursor.Start())
1084 {
1085 ++tmp;
1086 continue;
1087 }
1088 if (pRedline->GetType() == RedlineType::Delete)
1089 {
1090 assert(*pRedline->Start() != *pRedline->End());
1091 // search in hidden layout can't overlap redlines
1092 assert(*rCursor.Start() <= *pRedline->Start() && *pRedline->End() <= *rCursor.End());
1093 SwPaM pam(*pRedline, nullptr);
1094 bReplaced &= rIDCO.DeleteAndJoin(pam);
1095 }
1096 else
1097 {
1098 ++tmp;
1099 }
1100 }
1101 }
1102 bReplaced &= rIDCO.ReplaceRange(rCursor, rReplacement, bRegExp);
1103#endif
1104 return bReplaced;
1105}
1106
1107std::optional<OUString> ReplaceBackReferences(const i18nutil::SearchOptions2& rSearchOpt,
1108 SwPaM *const pPam, SwRootFrame const*const pLayout)
1109{
1110 std::optional<OUString> xRet;
1111 if( pPam && pPam->HasMark() &&
1112 SearchAlgorithms2::REGEXP == rSearchOpt.AlgorithmType2 )
1113 {
1114 SwContentNode const*const pTextNode = pPam->GetPointContentNode();
1115 SwContentNode const*const pMarkTextNode = pPam->GetMarkContentNode();
1116 if (!pTextNode || !pTextNode->IsTextNode()
1117 || !pMarkTextNode || !pMarkTextNode->IsTextNode())
1118 {
1119 return xRet;
1120 }
1121 SwTextFrame const*const pFrame(pLayout
1122 ? static_cast<SwTextFrame const*>(pTextNode->getLayoutFrame(pLayout))
1123 : nullptr);
1124 const bool bParaEnd = rSearchOpt.searchString == "$" || rSearchOpt.searchString == "^$" || rSearchOpt.searchString == "$^";
1125 if (bParaEnd || (pLayout
1126 ? sw::FrameContainsNode(*pFrame, pPam->GetMark()->GetNodeIndex())
1127 : pTextNode == pMarkTextNode))
1128 {
1130 SearchResult aResult;
1131 OUString aReplaceStr( rSearchOpt.replaceString );
1132 if (bParaEnd)
1133 {
1134 OUString const aStr("\\n");
1135 aResult.subRegExpressions = 1;
1136 aResult.startOffset = { 0 };
1137 aResult.endOffset = { aStr.getLength() };
1138 aSText.ReplaceBackReferences( aReplaceStr, aStr, aResult );
1139 xRet = aReplaceStr;
1140 }
1141 else
1142 {
1143 AmbiguousIndex nStart;
1144 AmbiguousIndex nEnd;
1145 if (pLayout)
1146 {
1147 nStart.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->Start()));
1148 nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->End()));
1149 }
1150 else
1151 {
1152 nStart.SetModelIndex(pPam->Start()->GetContentIndex());
1153 nEnd.SetModelIndex(pPam->End()->GetContentIndex());
1154 }
1155 std::vector<AmbiguousIndex> aFltArr;
1156 OUString const aStr = lcl_CleanStr(*pTextNode->GetTextNode(), pFrame, pLayout,
1157 nStart, nEnd, aFltArr, false, false);
1158 if (aSText.SearchForward(aStr, &nStart.GetAnyIndex(), &nEnd.GetAnyIndex(), &aResult))
1159 {
1160 aSText.ReplaceBackReferences( aReplaceStr, aStr, aResult );
1161 xRet = aReplaceStr;
1162 }
1163 }
1164 }
1165 }
1166 return xRet;
1167}
1168
1169} // namespace sw
1170
1171/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ ShowDelete
show all deletes
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...
SwRewriter MakeUndoReplaceRewriter(sal_uLong const occurrences, OUString const &sOld, OUString const &sNew)
Definition: unins.cxx:528
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:34
Text operation/manipulation interface.
virtual bool DeleteAndJoin(SwPaM &, SwDeleteFlags flags=SwDeleteFlags::Default)=0
complete delete of a given PaM
virtual bool ReplaceRange(SwPaM &rPam, const OUString &rNewStr, const bool bRegExReplace)=0
Replace selected range in a TextNode with string.
virtual bool Search(const SwPaM &rPaM, const SvxSearchItem &rSearchItem)=0
Searches text in shapes anchored inside rPaM.
static bool IsRedlineOn(const RedlineFlags eM)
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
virtual void SetModified()=0
Must be called manually at changes of format.
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
virtual bool DoesUndo() const =0
Is Undo enabled?
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
sal_Int32 StartSearchAndReplace(const SvxSearchItem &rSearchItem)
const tools::Rectangle & GetAllMarkedRect() const
SdrTextObj * GetTextEditObject() const
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
const OutlinerView * GetTextEditOutlinerView() const
void UnmarkAll()
SvxSearchCmd GetCommand() const
const css::lang::Locale & GetLocale(const LanguageType aLang)
Definition: breakit.hxx:67
sal_uInt16 GetRealScriptOfText(const OUString &rText, sal_Int32 nPos) const
Definition: breakit.cxx:84
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1224
sal_Int32 Find_Text(const i18nutil::SearchOptions2 &rSearchOpt, bool bSearchInNotes, SwDocPositions nStart, SwDocPositions nEnd, bool &bCancel, FindRanges, bool bReplace=false, SwRootFrame const *const pLayout=nullptr)
Definition: findtxt.cxx:1003
sal_Int32 FindAll(SwFindParas &, SwDocPositions, SwDocPositions, FindRanges, bool &bCancel)
Definition: swcrsr.cxx:944
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
Definition: doc.hxx:192
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:395
void SetOle2Link(const Link< bool, void > &rLink)
Definition: doc.hxx:1331
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:316
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:145
SwNodes & GetNodes()
Definition: doc.hxx:413
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:336
const Link< bool, void > & GetOle2Link() const
Definition: doc.hxx:1332
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:156
SwDocShell * GetDocShell()
Definition: doc.hxx:1355
Style of a layout element.
Definition: frmfmt.hxx:62
Base class of the Writer document model elements.
Definition: node.hxx:84
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:876
SwNodeOffset GetIndex() const
Definition: node.hxx:296
SwDoc & GetDoc()
Definition: node.hxx:217
bool IsTextNode() const
Definition: node.hxx:664
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
const SwPosition * GetMark() const
Definition: pam.hxx:263
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:612
void Exchange()
Definition: pam.cxx:626
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:287
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:638
const SwPosition * End() const
Definition: pam.hxx:271
SwContentNode * GetMarkContentNode() const
Definition: pam.hxx:288
SwDoc & GetDoc() const
Definition: pam.hxx:299
const SwPosition * GetPoint() const
Definition: pam.hxx:261
const SwPosition * Start() const
Definition: pam.hxx:266
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:259
sal_uInt16 SearchReplace(const SwFormatField &pField, const i18nutil::SearchOptions2 &rSearchOptions, bool bSrchForward)
Definition: PostItMgr.cxx:2327
void SetActiveSidebarWin(sw::annotation::SwAnnotationWin *p)
Definition: PostItMgr.cxx:2206
sal_uInt16 FinishSearchReplace(const i18nutil::SearchOptions2 &rSearchOptions, bool bSrchForward)
Definition: PostItMgr.cxx:2315
SW_DLLPUBLIC bool HasActiveSidebarWin() const
Definition: PostItMgr.cxx:2378
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1934
size_type size() const
Definition: docary.hxx:267
vector_type::size_type size_type
Definition: docary.hxx:222
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding).
Definition: rootfrm.hxx:421
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
bool HasDummyChar() const
Definition: txatbase.hxx:107
sal_uInt16 Which() const
Definition: txatbase.hxx:116
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:165
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1246
LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript, bool bNoChar=false) const
Definition: txtfrm.cxx:1343
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:456
TextFrameIndex MapModelToView(SwTextNode const *pNode, sal_Int32 nIndex) const
Definition: txtfrm.cxx:1252
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1267
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1293
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:86
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:230
const OUString & GetText() const
Definition: ndtxt.hxx:222
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3464
const SwPostItMgr * GetPostItMgr() const
Definition: viewsh.hxx:569
SdrView * GetDrawView()
Definition: vnew.cxx:373
static SvxSearchItem * GetSearchItem()
Definition: view.hxx:652
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
tools::Long CallSetCursor(const Point *pPt, bool bProp)
Definition: wrtsh.hxx:123
void Edit()
Definition: wrtsh1.cxx:186
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
constexpr Point TopLeft() const
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
static i18nutil::SearchOptions2 UpgradeToSearchOptions2(const i18nutil::SearchOptions &rOptions)
void ReplaceBackReferences(OUString &rReplaceStr, std::u16string_view rStr, const css::util::SearchResult &rResult) const
void SetLocale(const i18nutil::SearchOptions2 &rOpt, const css::lang::Locale &rLocale)
Any value
SwDocPositions
Definition: cshtyp.hxx:104
FindRanges
Definition: cshtyp.hxx:91
@ InSel
Find in selections.
SwFrameFormat * FindFrameFormat(SdrObject *pObj)
The Get reverse way: seeks the format to the specified object.
Definition: dcontact.cxx:121
EmbeddedObjectRef * pObject
static OUString lcl_CleanStr(const SwTextNode &rNd, SwTextFrame const *const pFrame, SwRootFrame const *const pLayout, AmbiguousIndex const nStart, AmbiguousIndex &rEnd, std::vector< AmbiguousIndex > &rArr, bool const bRemoveSoftHyphen, bool const bRemoveCommentAnchors)
Definition: findtxt.cxx:181
static bool DoSearch(SwPaM &rSearchPam, const i18nutil::SearchOptions2 &rSearchOpt, utl::TextSearch &rSText, SwMoveFnCollection const &fnMove, bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd, AmbiguousIndex &nStart, AmbiguousIndex &nEnd, AmbiguousIndex nTextLen, SwTextNode const *pNode, SwTextFrame const *pTextFrame, SwRootFrame const *pLayout, SwPaM *pPam)
Definition: findtxt.cxx:724
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(60)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(58)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:174
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_METAFIELD(49)
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_META(48)
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
void * p
sal_Int64 n
#define LANGUAGE_SYSTEM
T m_value
aStr
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
Count
Dialog to specify the properties of date form field.
bool FindTextImpl(SwPaM &rSearchPam, const i18nutil::SearchOptions2 &rSearchOpt, bool bSearchInNotes, utl::TextSearch &rSText, SwMoveFnCollection const &fnMove, const SwPaM &rRegion, bool bInReadOnly, SwRootFrame const *const pLayout, std::unique_ptr< SvxSearchItem > &xSearchItem)
Search.
Definition: findtxt.cxx:369
std::optional< OUString > ReplaceBackReferences(const i18nutil::SearchOptions2 &rSearchOpt, SwPaM *const pPam, SwRootFrame const *const pLayout)
Helperfunction to resolve backward references in regular expressions.
Definition: findtxt.cxx:1107
void MakeRegion(SwMoveFnCollection const &fnMove, const SwPaM &rOrigRg, std::optional< SwPaM > &rPam)
make a new region
Definition: pam.cxx:657
bool FrameContainsNode(SwContentFrame const &rFrame, SwNodeOffset nNodeIndex)
Definition: txtfrm.cxx:290
bool GetRanges(std::vector< std::shared_ptr< SwUnoCursor > > &rRanges, SwDoc &rDoc, SwPaM const &rDelPam)
Definition: autofmt.cxx:1112
bool ReplaceImpl(SwPaM &rCursor, OUString const &rReplacement, bool const bRegExp, SwDoc &rDoc, SwRootFrame const *const pLayout)
Definition: findtxt.cxx:1039
sal_uInt32 tag
std::enable_if< std::is_signed< T >::value, SwNodeOffset >::type operator-(SwNodeOffset a, T n)
Definition: nodeoffset.hxx:29
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
bool GoPrevPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1174
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:982
bool GoNextPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1216
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1142
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
virtual bool IsReplaceMode() const =0
virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool, std::unique_ptr< SvxSearchItem > &xSearchItem)=0
SearchText fnSearch
Definition: pamtyp.hxx:81
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:230
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:266
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:77
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
SwTextNode const * pLastNode
mainly for sanity checks
Definition: txtfrm.hxx:974
const int FIND_NOT_FOUND
Definition: swcrsr.hxx:35
const int FIND_FOUND
Definition: swcrsr.hxx:36
const int FIND_NO_RING
Definition: swcrsr.hxx:37
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:163
bool operator<(const wwFont &r1, const wwFont &r2)
Definition: wrtw8sty.cxx:841