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 SwNode* pAnchorNode = pFrameFormat->GetAnchor().GetAnchorNode();
520 if (!pAnchorNode || (pLayout
521 ? !FrameContainsNode(*pFrame, pAnchorNode->GetIndex())
522 : pAnchorNode->GetIndex() != 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 SwNode* pAnchorNode = pFrameFormat->GetAnchor().GetAnchorNode();
584 if (pAnchorNode)
585 {
586 // Set search position to the shape's anchor point.
587 rSearchPam.GetPoint()->Assign(*pAnchorNode);
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("\\u00ad")
749 || -1 != rSearchOpt.searchString.indexOf("\\U000000AD")
750 || -1 != rSearchOpt.searchString.indexOf("\\N{SOFT HYPHEN}"))
751 {
752 bRemoveSoftHyphens = false;
753 }
754 }
755 else
756 {
757 if ( 1 == rSearchOpt.searchString.getLength() &&
758 CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
759 bRemoveSoftHyphens = false;
760 }
761
762 if( bSrchForward )
763 sCleanStr = lcl_CleanStr(*pNode, pFrame, pLayout, nStart, nEnd,
764 aFltArr, bRemoveSoftHyphens, bRemoveCommentAnchors);
765 else
766 sCleanStr = lcl_CleanStr(*pNode, pFrame, pLayout, nEnd, nStart,
767 aFltArr, bRemoveSoftHyphens, bRemoveCommentAnchors);
768
769 std::unique_ptr<SwScriptIterator> pScriptIter;
770 sal_uInt16 nSearchScript = 0;
771 sal_uInt16 nCurrScript = 0;
772
773 if (SearchAlgorithms2::APPROXIMATE == rSearchOpt.AlgorithmType2)
774 {
775 pScriptIter.reset(new SwScriptIterator(sCleanStr, nStart.GetAnyIndex(), bSrchForward));
776 nSearchScript = g_pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
777 }
778
779 const AmbiguousIndex nStringEnd = nEnd;
780 bool bZeroMatch = false; // zero-length match, i.e. only $ anchor as regex
781 while ( ((bSrchForward && nStart < nStringEnd) ||
782 (!bSrchForward && nStringEnd < nStart)) && !bZeroMatch )
783 {
784 // SearchAlgorithms_APPROXIMATE works on a per word base so we have to
785 // provide the text searcher with the correct locale, because it uses
786 // the break-iterator
787 if ( pScriptIter )
788 {
789 nEnd.GetAnyIndex() = pScriptIter->GetScriptChgPos();
790 nCurrScript = pScriptIter->GetCurrScript();
791 if ( nSearchScript == nCurrScript )
792 {
793 const LanguageType eCurrLang = pLayout
794 ? pFrame->GetLangOfChar(bSrchForward
795 ? nStart.GetFrameIndex()
796 : nEnd.GetFrameIndex(),
797 0, true)
798 : pNode->GetLang(bSrchForward
799 ? nStart.GetModelIndex()
800 : nEnd.GetModelIndex());
801
802 if ( eCurrLang != eLastLang )
803 {
804 const lang::Locale aLocale(
805 g_pBreakIt->GetLocale( eCurrLang ) );
806 rSText.SetLocale(rSearchOpt, aLocale);
807 eLastLang = eCurrLang;
808 }
809 }
810 pScriptIter->Next();
811 }
812 AmbiguousIndex nProxyStart = nStart;
813 AmbiguousIndex nProxyEnd = nEnd;
814 if( nSearchScript == nCurrScript &&
815 (rSText.*fnMove.fnSearch)( sCleanStr, &nProxyStart.GetAnyIndex(), &nProxyEnd.GetAnyIndex(), nullptr) &&
816 !(bZeroMatch = (nProxyStart == nProxyEnd)))
817 {
818 nStart = nProxyStart;
819 nEnd = nProxyEnd;
820 // set section correctly
821 *rSearchPam.GetPoint() = *pPam->GetPoint();
822 rSearchPam.SetMark();
823
824 // adjust start and end
825 if( !aFltArr.empty() )
826 {
827 // if backward search, switch positions temporarily
828 if (!bSrchForward) { std::swap(nStart, nEnd); }
829
830 AmbiguousIndex nNew = nStart;
831 for (size_t n = 0; n < aFltArr.size() && aFltArr[ n ] <= nStart; ++n )
832 {
833 ++nNew.GetAnyIndex();
834 }
835
836 nStart = nNew;
837 nNew = nEnd;
838 for( size_t n = 0; n < aFltArr.size() && aFltArr[ n ] < nEnd; ++n )
839 {
840 ++nNew.GetAnyIndex();
841 }
842
843 nEnd = nNew;
844 // if backward search, switch positions temporarily
845 if( !bSrchForward ) { std::swap(nStart, nEnd); }
846 }
847 if (pLayout)
848 {
849 *rSearchPam.GetMark() = pFrame->MapViewToModelPos(nStart.GetFrameIndex());
850 *rSearchPam.GetPoint() = pFrame->MapViewToModelPos(nEnd.GetFrameIndex());
851 }
852 else
853 {
854 rSearchPam.GetMark()->SetContent( nStart.GetModelIndex() );
855 rSearchPam.GetPoint()->SetContent( nEnd.GetModelIndex() );
856 }
857
858 // if backward search, switch point and mark
859 if( !bSrchForward )
860 rSearchPam.Exchange();
861 bFound = true;
862 break;
863 }
864 else
865 {
866 nEnd = nProxyEnd;
867 }
868 nStart = nEnd;
869 }
870
871 pScriptIter.reset();
872
873 if ( bFound )
874 return true;
875 else if ((bChkEmptyPara && !nStart.GetAnyIndex() && !nTextLen.GetAnyIndex())
876 || bChkParaEnd)
877 {
878 *rSearchPam.GetPoint() = *pPam->GetPoint();
879 if (pLayout)
880 {
881 *rSearchPam.GetPoint() = pFrame->MapViewToModelPos(
882 bChkParaEnd ? nTextLen.GetFrameIndex() : TextFrameIndex(0));
883 }
884 else
885 {
886 rSearchPam.GetPoint()->SetContent( bChkParaEnd ? nTextLen.GetModelIndex() : 0 );
887 }
888 rSearchPam.SetMark();
889 const SwNode *const pSttNd = bSrchForward
890 ? &rSearchPam.GetPoint()->GetNode() // end of the frame
891 : &rPtPos.GetNode(); // keep the bug as-is for now...
892 /* FIXME: this condition does not work for !bSrchForward backward
893 * search, it probably never did. (pSttNd != &rNdIdx.GetNode())
894 * is never true in this case. */
895 if( (bSrchForward || pSttNd != &rPtPos.GetNode()) &&
896 rSearchPam.Move(fnMoveForward, GoInContent) &&
897 (!bSrchForward || pSttNd != &rSearchPam.GetPoint()->GetNode()) &&
898 SwNodeOffset(1) == abs(rSearchPam.GetPoint()->GetNodeIndex() -
899 rSearchPam.GetMark()->GetNodeIndex()))
900 {
901 // if backward search, switch point and mark
902 if( !bSrchForward )
903 rSearchPam.Exchange();
904 return true;
905 }
906 }
907 return bFound;
908}
909
910namespace {
911
913struct SwFindParaText : public SwFindParas
914{
915 const i18nutil::SearchOptions2& m_rSearchOpt;
916 SwCursor& m_rCursor;
917 SwRootFrame const* m_pLayout;
918 utl::TextSearch m_aSText;
919 bool m_bReplace;
920 bool m_bSearchInNotes;
921
922 SwFindParaText(const i18nutil::SearchOptions2& rOpt, bool bSearchInNotes,
923 bool bRepl, SwCursor& rCursor, SwRootFrame const*const pLayout)
924 : m_rSearchOpt( rOpt )
925 , m_rCursor( rCursor )
926 , m_pLayout(pLayout)
927 , m_aSText(rOpt)
928 , m_bReplace( bRepl )
929 , m_bSearchInNotes( bSearchInNotes )
930 {}
931 virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly, std::unique_ptr<SvxSearchItem>& xSearchItem) override;
932 virtual bool IsReplaceMode() const override;
933 virtual ~SwFindParaText();
934};
935
936}
937
938SwFindParaText::~SwFindParaText()
939{
940}
941
942int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
943 const SwPaM & rRegion, bool bInReadOnly,
944 std::unique_ptr<SvxSearchItem>& xSearchItem)
945{
946 if( bInReadOnly && m_bReplace )
947 bInReadOnly = false;
948
949 const bool bFnd = sw::FindTextImpl(rCursor, m_rSearchOpt, m_bSearchInNotes,
950 m_aSText, fnMove, rRegion, bInReadOnly, m_pLayout, xSearchItem);
951
952 if( bFnd && m_bReplace ) // replace string
953 {
954 // use replace method in SwDoc
955 const bool bRegExp(SearchAlgorithms2::REGEXP == m_rSearchOpt.AlgorithmType2);
956 const sal_Int32 nSttCnt = rCursor.Start()->GetContentIndex();
957 // add to shell-cursor-ring so that the regions will be moved eventually
958 SwPaM* pPrev(nullptr);
959 if( bRegExp )
960 {
961 pPrev = const_cast<SwPaM&>(rRegion).GetPrev();
962 const_cast<SwPaM&>(rRegion).GetRingContainer().merge( m_rCursor.GetRingContainer() );
963 }
964
965 std::optional<OUString> xRepl;
966 if (bRegExp)
967 xRepl = sw::ReplaceBackReferences(m_rSearchOpt, &rCursor, m_pLayout);
968 bool const bReplaced = sw::ReplaceImpl(rCursor,
969 xRepl ? *xRepl : m_rSearchOpt.replaceString,
970 bRegExp, m_rCursor.GetDoc(), m_pLayout);
971
972 m_rCursor.SaveTableBoxContent( rCursor.GetPoint() );
973
974 if( bRegExp )
975 {
976 // and remove region again
977 SwPaM* p;
978 SwPaM* pNext(const_cast<SwPaM*>(&rRegion));
979 do {
980 p = pNext;
981 pNext = p->GetNext();
982 p->MoveTo(const_cast<SwPaM*>(&rRegion));
983 } while( p != pPrev );
984 }
985 if (bRegExp && !bReplaced)
986 { // fdo#80715 avoid infinite loop if join failed
987 bool bRet = ((&fnMoveForward == &fnMove) ? &GoNextPara : &GoPrevPara)
988 (rCursor, fnMove);
989 (void) bRet;
990 assert(bRet); // if join failed, next node must be SwTextNode
991 }
992 else
993 rCursor.Start()->SetContent(nSttCnt);
994 return FIND_NO_RING;
995 }
996 return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
997}
998
999bool SwFindParaText::IsReplaceMode() const
1000{
1001 return m_bReplace;
1002}
1003
1004sal_Int32 SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
1005 SwDocPositions nStart, SwDocPositions nEnd,
1006 bool& bCancel, FindRanges eFndRngs, bool bReplace,
1007 SwRootFrame const*const pLayout)
1008{
1009 // switch off OLE-notifications
1010 SwDoc& rDoc = GetDoc();
1011 Link<bool,void> aLnk( rDoc.GetOle2Link() );
1012 rDoc.SetOle2Link( Link<bool,void>() );
1013
1014 bool const bStartUndo = rDoc.GetIDocumentUndoRedo().DoesUndo() && bReplace;
1015 if (bStartUndo)
1016 {
1017 rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::REPLACE, nullptr );
1018 }
1019
1020 bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
1021 if( bSearchSel )
1022 eFndRngs = static_cast<FindRanges>(eFndRngs | FindRanges::InSel);
1023 SwFindParaText aSwFindParaText(rSearchOpt, bSearchInNotes, bReplace, *this, pLayout);
1024 sal_Int32 nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel );
1025 rDoc.SetOle2Link( aLnk );
1026 if( nRet && bReplace )
1028
1029 if (bStartUndo)
1030 {
1032 nRet, rSearchOpt.searchString, rSearchOpt.replaceString));
1033 rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::REPLACE, & rewriter );
1034 }
1035 return nRet;
1036}
1037
1038namespace sw {
1039
1041 SwPaM & rCursor,
1042 OUString const& rReplacement,
1043 bool const bRegExp,
1044 SwDoc & rDoc,
1045 SwRootFrame const*const pLayout)
1046{
1047 bool bReplaced(true);
1049#if 0
1050 // FIXME there's some problem with multiple redlines here on Undo
1051 std::vector<std::shared_ptr<SwUnoCursor>> ranges;
1053 || !pLayout
1054 || !pLayout->IsHideRedlines()
1055 || sw::GetRanges(ranges, rDoc, rCursor))
1056 {
1057 bReplaced = rIDCO.ReplaceRange(rCursor, rReplacement, bRegExp);
1058 }
1059 else
1060 {
1061 assert(!ranges.empty());
1062 assert(ranges.front()->GetPoint()->GetNode() == ranges.front()->GetMark()->GetNode());
1063 bReplaced = rIDCO.ReplaceRange(*ranges.front(), rReplacement, bRegExp);
1064 for (auto it = ranges.begin() + 1; it != ranges.end(); ++it)
1065 {
1066 bReplaced &= rIDCO.DeleteAndJoin(**it);
1067 }
1068 }
1069#else
1071 if (pLayout && pLayout->IsHideRedlines()
1072 && !rIDRA.IsRedlineOn() // otherwise: ReplaceRange will handle it
1073 && (rIDRA.GetRedlineFlags() & RedlineFlags::ShowDelete)) // otherwise: ReplaceRange will DeleteRedline()
1074 {
1076 rIDRA.GetRedline(*rCursor.Start(), &tmp);
1077 while (tmp < rIDRA.GetRedlineTable().size())
1078 {
1079 SwRangeRedline const*const pRedline(rIDRA.GetRedlineTable()[tmp]);
1080 if (*rCursor.End() <= *pRedline->Start())
1081 {
1082 break;
1083 }
1084 if (*pRedline->End() <= *rCursor.Start())
1085 {
1086 ++tmp;
1087 continue;
1088 }
1089 if (pRedline->GetType() == RedlineType::Delete)
1090 {
1091 assert(*pRedline->Start() != *pRedline->End());
1092 // search in hidden layout can't overlap redlines
1093 assert(*rCursor.Start() <= *pRedline->Start() && *pRedline->End() <= *rCursor.End());
1094 SwPaM pam(*pRedline, nullptr);
1095 bReplaced &= rIDCO.DeleteAndJoin(pam);
1096 }
1097 else
1098 {
1099 ++tmp;
1100 }
1101 }
1102 }
1103 bReplaced &= rIDCO.ReplaceRange(rCursor, rReplacement, bRegExp);
1104#endif
1105 return bReplaced;
1106}
1107
1108std::optional<OUString> ReplaceBackReferences(const i18nutil::SearchOptions2& rSearchOpt,
1109 SwPaM *const pPam, SwRootFrame const*const pLayout)
1110{
1111 std::optional<OUString> xRet;
1112 if( pPam && pPam->HasMark() &&
1113 SearchAlgorithms2::REGEXP == rSearchOpt.AlgorithmType2 )
1114 {
1115 SwContentNode const*const pTextNode = pPam->GetPointContentNode();
1116 SwContentNode const*const pMarkTextNode = pPam->GetMarkContentNode();
1117 if (!pTextNode || !pTextNode->IsTextNode()
1118 || !pMarkTextNode || !pMarkTextNode->IsTextNode())
1119 {
1120 return xRet;
1121 }
1122 SwTextFrame const*const pFrame(pLayout
1123 ? static_cast<SwTextFrame const*>(pTextNode->getLayoutFrame(pLayout))
1124 : nullptr);
1125 const bool bParaEnd = rSearchOpt.searchString == "$" || rSearchOpt.searchString == "^$" || rSearchOpt.searchString == "$^";
1126 if (bParaEnd || (pLayout
1127 ? sw::FrameContainsNode(*pFrame, pPam->GetMark()->GetNodeIndex())
1128 : pTextNode == pMarkTextNode))
1129 {
1130 utl::TextSearch aSText(rSearchOpt);
1131 SearchResult aResult;
1132 OUString aReplaceStr( rSearchOpt.replaceString );
1133 if (bParaEnd)
1134 {
1135 static constexpr OUStringLiteral aStr(u"\\n");
1136 aResult.subRegExpressions = 1;
1137 aResult.startOffset = { 0 };
1138 aResult.endOffset = { aStr.getLength() };
1139 aSText.ReplaceBackReferences( aReplaceStr, aStr, aResult );
1140 xRet = aReplaceStr;
1141 }
1142 else
1143 {
1144 AmbiguousIndex nStart;
1145 AmbiguousIndex nEnd;
1146 if (pLayout)
1147 {
1148 nStart.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->Start()));
1149 nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->End()));
1150 }
1151 else
1152 {
1153 nStart.SetModelIndex(pPam->Start()->GetContentIndex());
1154 nEnd.SetModelIndex(pPam->End()->GetContentIndex());
1155 }
1156 std::vector<AmbiguousIndex> aFltArr;
1157 OUString const aStr = lcl_CleanStr(*pTextNode->GetTextNode(), pFrame, pLayout,
1158 nStart, nEnd, aFltArr, false, false);
1159 if (aSText.SearchForward(aStr, &nStart.GetAnyIndex(), &nEnd.GetAnyIndex(), &aResult))
1160 {
1161 aSText.ReplaceBackReferences( aReplaceStr, aStr, aResult );
1162 xRet = aReplaceStr;
1163 }
1164 }
1165 }
1166 }
1167 return xRet;
1168}
1169
1170} // namespace sw
1171
1172/* 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.
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:68
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:1223
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:1004
sal_Int32 FindAll(SwFindParas &, SwDocPositions, SwDocPositions, FindRanges, bool &bCancel)
Definition: swcrsr.cxx:949
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
Definition: doc.hxx:197
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:408
void SetOle2Link(const Link< bool, void > &rLink)
Definition: doc.hxx:1346
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:329
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:158
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:349
const Link< bool, void > & GetOle2Link() const
Definition: doc.hxx:1347
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:169
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
Style of a layout element.
Definition: frmfmt.hxx:72
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwDoc & GetDoc()
Definition: node.hxx:233
bool IsTextNode() const
Definition: node.hxx:190
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:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
void Exchange()
Definition: pam.hxx:242
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:279
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * End() const
Definition: pam.hxx:263
SwContentNode * GetMarkContentNode() const
Definition: pam.hxx:280
SwDoc & GetDoc() const
Definition: pam.hxx:291
const SwPosition * GetPoint() const
Definition: pam.hxx:253
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
sal_uInt16 SearchReplace(const SwFormatField &pField, const i18nutil::SearchOptions2 &rSearchOptions, bool bSrchForward)
Definition: PostItMgr.cxx:2321
void SetActiveSidebarWin(sw::annotation::SwAnnotationWin *p)
Definition: PostItMgr.cxx:2200
sal_uInt16 FinishSearchReplace(const i18nutil::SearchOptions2 &rSearchOptions, bool bSrchForward)
Definition: PostItMgr.cxx:2309
SW_DLLPUBLIC bool HasActiveSidebarWin() const
Definition: PostItMgr.cxx:2372
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1975
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
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding).
Definition: rootfrm.hxx:434
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:168
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1333
LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript, bool bNoChar=false) const
Definition: txtfrm.cxx:1430
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:465
TextFrameIndex MapModelToView(SwTextNode const *pNode, sal_Int32 nIndex) const
Definition: txtfrm.cxx:1339
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1354
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1380
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:252
const OUString & GetText() const
Definition: ndtxt.hxx:244
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3474
const SwPostItMgr * GetPostItMgr() const
Definition: viewsh.hxx:583
SdrView * GetDrawView()
Definition: vnew.cxx:386
static SvxSearchItem * GetSearchItem()
Definition: view.hxx:666
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:188
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)
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
float u
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:175
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)
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:1108
void MakeRegion(SwMoveFnCollection const &fnMove, const SwPaM &rOrigRg, std::optional< SwPaM > &rPam)
make a new region
Definition: pam.cxx:676
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:1111
bool ReplaceImpl(SwPaM &rCursor, OUString const &rReplacement, bool const bRegExp, SwDoc &rDoc, SwRootFrame const *const pLayout)
Definition: findtxt.cxx:1040
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:1235
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:1043
bool GoNextPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1275
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1203
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
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:85
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:267
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
SwTextNode const * pLastNode
mainly for sanity checks
Definition: txtfrm.hxx:1002
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:175
Count
bool operator<(const wwFont &r1, const wwFont &r2)
Definition: wrtw8sty.cxx:885