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