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