LibreOffice Module sw (master)  1
viewsrch.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 <string>
21 
22 #include <memory>
23 #include <boost/property_tree/json_parser.hpp>
24 
25 #include <hintids.hxx>
26 
27 #include <sal/log.hxx>
28 #include <svl/cjkoptions.hxx>
29 #include <svl/ctloptions.hxx>
30 #include <svx/pageitem.hxx>
31 #include <svl/whiter.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <svl/eitem.hxx>
34 #include <svl/srchitem.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <sfx2/request.hxx>
37 #include <svx/srchdlg.hxx>
38 #include <edtwin.hxx>
39 #include <swmodule.hxx>
40 #include <swwait.hxx>
41 #include <workctrl.hxx>
42 #include <view.hxx>
43 #include <wrtsh.hxx>
44 #include <swundo.hxx>
45 #include <uitool.hxx>
46 #include <cmdid.h>
47 #include <docsh.hxx>
48 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
49 #include <comphelper/lok.hxx>
50 #include <comphelper/string.hxx>
51 
52 #include <strings.hrc>
53 #include <SwRewriter.hxx>
54 
55 #include <PostItMgr.hxx>
56 
57 using namespace com::sun::star;
58 using namespace ::com::sun::star::i18n;
59 using namespace ::com::sun::star::lang;
60 using namespace ::com::sun::star::util;
61 
62 //Search Parameter
63 
65 {
67  bool bDontWrap;
68 
69  SwSearchOptions( SwWrtShell const * pSh, bool bBackward );
70 };
71 
73 static void lcl_addContainerToJson(boost::property_tree::ptree& rTree, const OString& rKey, const std::vector<OString>& rMatches)
74 {
75  boost::property_tree::ptree aChildren;
76 
77  for (const OString& rMatch : rMatches)
78  {
79  boost::property_tree::ptree aChild;
80  aChild.put("part", "0");
81  aChild.put("rectangles", rMatch.getStr());
82  aChildren.push_back(std::make_pair("", aChild));
83  }
84 
85  rTree.add_child(rKey.getStr(), aChildren);
86 }
87 
89 static void lcl_emitSearchResultCallbacks(SvxSearchItem const * pSearchItem, SwWrtShell const * pWrtShell, bool bHighlightAll)
90 {
91  // Emit a callback also about the selection rectangles, grouped by matches.
92  if (SwPaM* pPaM = pWrtShell->GetCursor())
93  {
94  std::vector<OString> aMatches;
95  for (SwPaM& rPaM : pPaM->GetRingContainer())
96  {
97  if (SwShellCursor* pShellCursor = dynamic_cast<SwShellCursor*>(&rPaM))
98  {
99  std::vector<OString> aSelectionRectangles;
100  pShellCursor->SwSelPaintRects::Show(&aSelectionRectangles);
101  std::vector<OString> aRect;
102  for (const OString & rSelectionRectangle : aSelectionRectangles)
103  {
104  if (rSelectionRectangle.isEmpty())
105  continue;
106  aRect.push_back(rSelectionRectangle);
107  }
108  OString sRect = comphelper::string::join("; ", aRect);
109  aMatches.push_back(sRect);
110  }
111  }
112  boost::property_tree::ptree aTree;
113  aTree.put("searchString", pSearchItem->GetSearchString().toUtf8().getStr());
114  aTree.put("highlightAll", bHighlightAll);
115  lcl_addContainerToJson(aTree, "searchResultSelection", aMatches);
116 
117  std::stringstream aStream;
118  boost::property_tree::write_json(aStream, aTree);
119  OString aPayload = aStream.str().c_str();
120 
121  pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION, aPayload.getStr());
122  }
123 }
124 
126 {
127  const SfxItemSet* pArgs = rReq.GetArgs();
128  const SfxPoolItem* pItem = nullptr;
129  bool bQuiet = false;
130  if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SEARCH_QUIET, false, &pItem))
131  bQuiet = static_cast<const SfxBoolItem*>( pItem)->GetValue();
132 
133  sal_uInt16 nSlot = rReq.GetSlot();
134  if (nSlot == FN_REPEAT_SEARCH && !s_pSrchItem)
135  {
136  if(bQuiet)
137  {
138  rReq.SetReturnValue(SfxBoolItem(nSlot, false));
139  nSlot = 0;
140  }
141  }
142  if( m_pWrtShell->IsBlockMode() )
143  m_pWrtShell->LeaveBlockMode();
144  switch (nSlot)
145  {
146  // for now do nothing
147  case SID_SEARCH_ITEM:
148  {
149  delete s_pSrchItem;
150  s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
151  }
152  break;
153 
154  case FID_SEARCH_ON:
155  s_bJustOpened = true;
156  GetViewFrame()->GetBindings().Invalidate(SID_SEARCH_ITEM);
157  break;
158 
159  case FID_SEARCH_OFF:
160  if(pArgs)
161  {
162  // Unregister dialog
163  delete s_pSrchItem;
164  s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
165 
166  DELETEZ( s_pSearchList );
167  DELETEZ( s_pReplaceList );
168 
169  SvxSearchDialog *const pSrchDlg(GetSearchDialog());
170  if (pSrchDlg)
171  {
172  // We will remember the search-/replace items.
173  const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList();
174  if( nullptr != pList && pList->Count() )
175  s_pSearchList = new SearchAttrItemList( *pList );
176 
177  pList = pSrchDlg->GetReplaceItemList();
178  if (nullptr != pList && pList->Count())
179  s_pReplaceList = new SearchAttrItemList( *pList );
180  }
181  }
182  break;
183 
184  case FN_REPEAT_SEARCH:
185  case FID_SEARCH_NOW:
186  {
187  sal_uInt16 nMoveType = SwView::GetMoveType();
188  {
189  if(FID_SEARCH_NOW == nSlot && !rReq.IsAPI())
191  }
192 
193  SvxSearchDialog * pSrchDlg(GetSearchDialog());
194  if (pSrchDlg)
195  {
196  DELETEZ( s_pSearchList );
197  DELETEZ( s_pReplaceList );
198 
199  const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList();
200  if( nullptr != pList && pList->Count() )
201  s_pSearchList = new SearchAttrItemList( *pList );
202 
203  pList = pSrchDlg->GetReplaceItemList();
204  if (nullptr != pList && pList->Count())
205  s_pReplaceList = new SearchAttrItemList( *pList );
206  }
207 
208  if (nSlot == FN_REPEAT_SEARCH)
209  {
210  OSL_ENSURE(s_pSrchItem, "SearchItem missing");
211  if( !s_pSrchItem )
212  s_pSrchItem = new SvxSearchItem(SID_SEARCH_ITEM);
213  }
214  else
215  {
216  // Get SearchItem from request
217  OSL_ENSURE(pArgs, "Args missing");
218  if ( pArgs )
219  {
220  delete s_pSrchItem;
221  s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone();
222  }
223  }
224  SvxSearchCmd eCommand = s_pSrchItem->GetCommand();
225  switch (eCommand)
226  {
227  case SvxSearchCmd::FIND:
228  {
229  bool bRet = SearchAndWrap(bQuiet);
230  if( bRet )
231  {
232  Scroll(m_pWrtShell->GetCharRect().SVRect());
234  lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ false);
235  }
236  rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
237 #if HAVE_FEATURE_DESKTOP
238  {
239  pSrchDlg = GetSearchDialog();
240  if (pSrchDlg)
241  {
242  pSrchDlg->SetDocWin(m_pEditWin, eCommand);
243  pSrchDlg->SetSrchFlag(false);
244  }
245  }
246 #endif
247  }
248  break;
249  case SvxSearchCmd::FIND_ALL:
250  {
251  // Disable LOK selection notifications during search.
252  m_pWrtShell->GetSfxViewShell()->setTiledSearching(true);
253  bool bRet = SearchAll();
254  m_pWrtShell->GetSfxViewShell()->setTiledSearching(false);
255 
256  if( !bRet )
257  {
258 #if HAVE_FEATURE_DESKTOP
259  if( !bQuiet )
260  {
261  m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr());
262  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
263  }
264 #endif
265  s_bFound = false;
266  }
268  lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ true);
269  rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
270 #if HAVE_FEATURE_DESKTOP
271  {
272  pSrchDlg = GetSearchDialog();
273  if (pSrchDlg)
274  {
275  pSrchDlg->SetDocWin(m_pEditWin, eCommand);
276  pSrchDlg->SetSrchFlag(false);
277  }
278  }
279 #endif
280  }
281  break;
282  case SvxSearchCmd::REPLACE:
283  {
284 
285  // 1) Replace selection (Not if only attributes should be replaced)
286 //JP 27.04.95: Why?
287 // what if you only want to assign attributes to the found??
288 
289  SvxSearchCmd nCmd = SvxSearchCmd::FIND;
290  if( !s_pSrchItem->GetReplaceString().isEmpty() ||
291  !s_pReplaceList )
292  {
293  // Prevent, that the replaced string will be found again
294  // if the replacement string is containing the search string.
295  bool bBack = s_pSrchItem->GetBackward();
296  if (bBack)
297  m_pWrtShell->Push();
298  OUString aReplace( s_pSrchItem->GetReplaceString() );
299  i18nutil::SearchOptions2 aTmp( s_pSrchItem->GetSearchOptions() );
300  std::optional<OUString> xBackRef = sw::ReplaceBackReferences(aTmp,
301  m_pWrtShell->GetCursor(), m_pWrtShell->GetLayout());
302  if( xBackRef )
303  s_pSrchItem->SetReplaceString( *xBackRef );
304  Replace();
305  if( xBackRef )
306  {
307  s_pSrchItem->SetReplaceString( aReplace );
308  }
309  if (bBack)
310  {
311  m_pWrtShell->Pop();
312  m_pWrtShell->SwapPam();
313  }
314  }
315  else if( s_pReplaceList )
316  nCmd = SvxSearchCmd::REPLACE;
317 
318  // 2) Search further (without replacing!)
319 
320  SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand();
321  s_pSrchItem->SetCommand( nCmd );
322  bool bRet = SearchAndWrap(bQuiet);
323  if( bRet )
324  Scroll( m_pWrtShell->GetCharRect().SVRect());
325  s_pSrchItem->SetCommand( nOldCmd );
326  rReq.SetReturnValue(SfxBoolItem(nSlot, bRet));
327  }
328 #if HAVE_FEATURE_DESKTOP
329  {
330  pSrchDlg = GetSearchDialog();
331  if (pSrchDlg)
332  {
333  pSrchDlg->SetDocWin(m_pEditWin, eCommand);
334  pSrchDlg->SetSrchFlag(false);
335  }
336  }
337 #endif
338  break;
339 
340  case SvxSearchCmd::REPLACE_ALL:
341  {
342  SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
343  s_bExtra = false;
344  sal_uLong nFound;
345 
346  { //Scope for SwWait-Object
347  SwWait aWait( *GetDocShell(), true );
348  m_pWrtShell->StartAllAction();
349 
350  // i#8288 "replace all" should not change cursor
351  // position, so save current cursor
352  m_pWrtShell->Push();
353 
354  if (!s_pSrchItem->GetSelection())
355  {
356  // if we don't want to search in the selection...
357  m_pWrtShell->KillSelection(nullptr, false);
358  if (SwDocPositions::Start == aOpts.eEnd)
359  {
360  m_pWrtShell->EndOfSection();
361  }
362  else
363  {
364  m_pWrtShell->StartOfSection();
365  }
366  }
367  nFound = FUNC_Search( aOpts );
368  // create it just to overwrite it with stack cursor
369  m_pWrtShell->CreateCursor();
370  // i#8288 restore the original cursor position
371  m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
372  m_pWrtShell->EndAllAction();
373  }
374 
375  rReq.SetReturnValue(SfxBoolItem(nSlot, nFound != 0 && ULONG_MAX != nFound));
376  if( !nFound )
377  {
378 #if HAVE_FEATURE_DESKTOP
379  if( !bQuiet )
380  {
381  m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr());
382  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
383  }
384 #endif
385  s_bFound = false;
386  SwView::SetMoveType(nMoveType);
387  return;
388  }
389 
390  if( !bQuiet && ULONG_MAX != nFound)
391  {
392  OUString sText( SwResId( STR_NB_REPLACED ) );
393  sText = sText.replaceFirst("XX", OUString::number( nFound ));
395  }
396  }
397 #if HAVE_FEATURE_DESKTOP
398  pSrchDlg = GetSearchDialog();
399  if (pSrchDlg)
400  {
401  pSrchDlg->SetDocWin(m_pEditWin, eCommand);
402  pSrchDlg->SetSrchFlag(false);
403  }
404 #endif
405  break;
406  }
407 
408  uno::Reference< frame::XDispatchRecorder > xRecorder =
409  GetViewFrame()->GetBindings().GetRecorder();
410  //prevent additional dialogs in recorded macros
411  if ( xRecorder.is() )
412  rReq.AppendItem(SfxBoolItem(SID_SEARCH_QUIET, true));
413 
414  rReq.Done();
415  m_eLastSearchCommand = s_pSrchItem->GetCommand();
416  SwView::SetMoveType(nMoveType);
417  }
418  break;
419  case FID_SEARCH_SEARCHSET:
420  case FID_SEARCH_REPLACESET:
421  {
422  static const sal_uInt16 aNormalAttr[] =
423  {
435 /*22 */ RES_LR_SPACE, RES_UL_SPACE,
436 /*24 */ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
437 /*26 */ 0
438  };
439 
440  SfxItemSet aSet(m_pWrtShell->GetAttrPool(), aNormalAttr);
441 
442  if( SW_MOD()->GetCTLOptions().IsCTLFontEnabled() )
443  {
444  aSet.MergeRange(RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_WEIGHT);
445  }
446  SvtCJKOptions aCJKOpt;
447  if( aCJKOpt.IsAnyEnabled() )
448  {
449  aSet.MergeRange(RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_WEIGHT);
452  }
453 
454  sal_uInt16 nWhich = SID_SEARCH_SEARCHSET;
455 
456  if ( FID_SEARCH_REPLACESET == nSlot )
457  {
458  nWhich = SID_SEARCH_REPLACESET;
459 
460  if ( s_pReplaceList )
461  {
462  s_pReplaceList->Get( aSet );
463  DELETEZ( s_pReplaceList );
464  }
465  }
466  else if ( s_pSearchList )
467  {
468  s_pSearchList->Get( aSet );
469  DELETEZ( s_pSearchList );
470  }
471  rReq.SetReturnValue( SvxSetItem( nWhich, aSet ) );
472  }
473  break;
474  default:
475  SAL_WARN_IF( nSlot, "sw", "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)" );
476  return;
477  }
478 }
479 
480 bool SwView::SearchAndWrap(bool bApi)
481 {
482  SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
483 
484  // Remember starting position of the search for wraparound
485  // Start- / EndAction perhaps because existing selections of 'search all'
486  m_pWrtShell->StartAllAction();
487  m_pWrtShell->Push();
488 
489  // After a search all action we place the cursor at the beginning of
490  // the document so that the single search selects the first matching
491  // occurrence in the document instead of the second.
492  if( m_eLastSearchCommand == SvxSearchCmd::FIND_ALL )
493  {
494  if( SwDocPositions::Start == aOpts.eEnd )
495  m_pWrtShell->EndOfSection();
496  else
497  m_pWrtShell->StartOfSection();
498  }
499 
500  // fdo#65014 : Ensure that the point of the cursor is at the extremity of the
501  // selection closest to the end being searched to as to exclude the selected
502  // region from the search. (This doesn't work in the case of multiple
503  // selected regions as the cursor doesn't mark the selection in that case.)
504  m_pWrtShell->GetCursor()->Normalize( s_pSrchItem->GetBackward() );
505 
506  if (!m_pWrtShell->HasSelection() && (s_pSrchItem->HasStartPoint()))
507  {
508  // No selection -> but we have a start point (top left corner of the
509  // current view), start searching from there, not from the current
510  // cursor position.
511  SwEditShell& rShell = GetWrtShell();
512  Point aPosition(s_pSrchItem->GetStartPointX(), s_pSrchItem->GetStartPointY());
513  rShell.SetCursor(aPosition);
514  }
515 
516  // If you want to search in selected areas, they must not be unselected.
517  if (!s_pSrchItem->GetSelection())
518  m_pWrtShell->KillSelection(nullptr, false);
519 
520  std::unique_ptr<SwWait> pWait(new SwWait( *GetDocShell(), true ));
521  if( FUNC_Search( aOpts ) )
522  {
523  s_bFound = true;
524  if(m_pWrtShell->IsSelFrameMode())
525  {
526  m_pWrtShell->UnSelectFrame();
527  m_pWrtShell->LeaveSelFrameMode();
528  }
529  m_pWrtShell->Pop();
530  m_pWrtShell->EndAllAction();
531  return true;
532  }
533  pWait.reset();
534 
535  // Search in the specialized areas when no search is present in selections.
536  // When searching selections will already searched in these special areas.
537  bool bHasSrchInOther = s_bExtra;
538  if (!s_pSrchItem->GetSelection() && !s_bExtra )
539  {
540  s_bExtra = true;
541  if( FUNC_Search( aOpts ) )
542  {
543  s_bFound = true;
544  m_pWrtShell->Pop();
545  m_pWrtShell->EndAllAction();
546  return true;
547  }
548  s_bExtra = false;
549  }
550  else
551  s_bExtra = !s_bExtra;
552 
553  // If starting position is at the end or beginning of the document.
554  if (aOpts.bDontWrap)
555  {
556  m_pWrtShell->EndAllAction();
557  if( !bApi )
558  {
559 #if HAVE_FEATURE_DESKTOP
560  m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr());
561  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
562 #endif
563  }
564  s_bFound = false;
565  m_pWrtShell->Pop();
566  return false;
567  }
568  m_pWrtShell->EndAllAction();
569  // Try again with WrapAround?
570 
571  m_pWrtShell->StartAllAction();
572  m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
573  pWait.reset(new SwWait( *GetDocShell(), true ));
574 
575  bool bSrchBkwrd = SwDocPositions::Start == aOpts.eEnd;
576 
577  aOpts.eEnd = bSrchBkwrd ? SwDocPositions::Start : SwDocPositions::End;
578  aOpts.eStart = bSrchBkwrd ? SwDocPositions::End : SwDocPositions::Start;
579 
580  if (bHasSrchInOther)
581  {
582  m_pWrtShell->ClearMark();
583  // Select the start or the end of the entire document
584  if (bSrchBkwrd)
585  m_pWrtShell->SttEndDoc(false);
586  else
587  m_pWrtShell->SttEndDoc(true);
588  }
589 
590  s_bFound = bool(FUNC_Search( aOpts ));
591 
592  // If WrapAround found no matches in the body text, search in the special
593  // sections, too.
594  if (!s_bFound && !s_pSrchItem->GetSelection() && !s_bExtra)
595  {
596  s_bExtra = true;
597  if (FUNC_Search(aOpts))
598  s_bFound = true;
599  else
600  s_bExtra = false;
601  }
602 
603  m_pWrtShell->EndAllAction();
604  pWait.reset();
605 #if HAVE_FEATURE_DESKTOP
606  if (s_bFound)
607  {
608  if (!bSrchBkwrd)
609  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::End);
610  else
611  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Start);
612  }
613  else if(!bApi)
614  {
615  m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr());
616  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound);
617  }
618 #endif
619  return s_bFound;
620 }
621 
623 {
624  SwWait aWait( *GetDocShell(), true );
625  m_pWrtShell->StartAllAction();
626 
627  SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
628 
629  if (!s_pSrchItem->GetSelection())
630  {
631  // Cancel existing selections, if should not be sought in selected areas.
632  m_pWrtShell->KillSelection(nullptr, false);
633 
634  if( SwDocPositions::Start == aOpts.eEnd )
635  m_pWrtShell->EndOfSection();
636  else
637  m_pWrtShell->StartOfSection();
638  }
639  s_bExtra = false;
640  sal_uInt16 nFound = static_cast<sal_uInt16>(FUNC_Search( aOpts ));
641  s_bFound = 0 != nFound;
642 
643  m_pWrtShell->EndAllAction();
644  return s_bFound;
645 }
646 
648 {
649  SwWait aWait( *GetDocShell(), true );
650 
651  m_pWrtShell->StartAllAction();
652 
653  if( s_pSrchItem->GetPattern() ) // Templates?
654  {
655  SwRewriter aRewriter;
656  aRewriter.AddRule(UndoArg1, s_pSrchItem->GetSearchString());
657  aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
658  aRewriter.AddRule(UndoArg3, s_pSrchItem->GetReplaceString());
659 
660  m_pWrtShell->StartUndo(SwUndoId::UI_REPLACE_STYLE, &aRewriter);
661 
662  m_pWrtShell->SetTextFormatColl( m_pWrtShell->GetParaStyle(
663  s_pSrchItem->GetReplaceString(),
665 
666  m_pWrtShell->EndUndo();
667  }
668  else
669  {
670  if (GetPostItMgr()->HasActiveSidebarWin())
671  GetPostItMgr()->Replace(s_pSrchItem);
672 
673  bool bReqReplace = true;
674 
675  if(m_pWrtShell->HasSelection())
676  {
677  /* check that the selection match the search string*/
678  //save state
679  SwPosition aStartPos = * m_pWrtShell->GetSwCursor()->Start();
680  SwPosition aEndPos = * m_pWrtShell->GetSwCursor()->End();
681  bool bHasSelection = s_pSrchItem->GetSelection();
682  SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand();
683 
684  //set state for checking if current selection has a match
685  s_pSrchItem->SetCommand( SvxSearchCmd::FIND );
686  s_pSrchItem->SetSelection(true);
687 
688  //check if it matches
689  SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );
690  if( ! FUNC_Search(aOpts) )
691  {
692 
693  //no matching therefore should not replace selection
694  // => remove selection
695 
696  if(! s_pSrchItem->GetBackward() )
697  {
698  (* m_pWrtShell->GetSwCursor()->Start()) = aStartPos;
699  (* m_pWrtShell->GetSwCursor()->End()) = aEndPos;
700  }
701  else
702  {
703  (* m_pWrtShell->GetSwCursor()->Start()) = aEndPos;
704  (* m_pWrtShell->GetSwCursor()->End()) = aStartPos;
705  }
706  bReqReplace = false;
707  }
708 
709  //set back old search state
710  s_pSrchItem->SetCommand( nOldCmd );
711  s_pSrchItem->SetSelection(bHasSelection);
712  }
713  /*
714  * remove current selection
715  * otherwise it is always replaced
716  * no matter if the search string exists or not in the selection
717  * Now the selection is removed and the next matching string is selected
718  */
719 
720  if( bReqReplace )
721  {
722 
723  bool bReplaced = m_pWrtShell->SwEditShell::Replace( s_pSrchItem->GetReplaceString(),
724  s_pSrchItem->GetRegExp());
725  if( bReplaced && s_pReplaceList && s_pReplaceList->Count() && m_pWrtShell->HasSelection() )
726  {
727  SfxItemSet aReplSet( m_pWrtShell->GetAttrPool(),
729  if( s_pReplaceList->Get( aReplSet ).Count() )
730  {
731  ::SfxToSwPageDescAttr( *m_pWrtShell, aReplSet );
732  m_pWrtShell->SwEditShell::SetAttrSet( aReplSet );
733  }
734  }
735  }
736  }
737 
738  m_pWrtShell->EndAllAction();
739 }
740 
741 SwSearchOptions::SwSearchOptions( SwWrtShell const * pSh, bool bBackward )
742  : eStart(SwDocPositions::Curr)
743 {
744  if( bBackward )
745  {
747  bDontWrap = pSh->IsEndOfDoc();
748  }
749  else
750  {
752  bDontWrap = pSh->IsStartOfDoc();
753  }
754 }
755 
757 {
758 #if HAVE_FEATURE_DESKTOP
759  SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty);
760 #endif
761  bool bDoReplace = s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE ||
762  s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL;
763 
764  FindRanges eRanges = s_pSrchItem->GetSelection()
766  : s_bExtra
768  if (s_pSrchItem->GetCommand() == SvxSearchCmd::FIND_ALL ||
769  s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL)
770  eRanges |= FindRanges::InSelAll;
771 
772  m_pWrtShell->SttSelect();
773 
774  static const sal_uInt16 aSearchAttrRange[] = {
778  SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
779  0 };
780 
781  SfxItemSet aSrchSet( m_pWrtShell->GetAttrPool(), aSearchAttrRange);
782  if( s_pSearchList && s_pSearchList->Count() )
783  {
784  s_pSearchList->Get( aSrchSet );
785 
786  // -- Page break with page template
787  ::SfxToSwPageDescAttr( *m_pWrtShell, aSrchSet );
788  }
789 
790  std::unique_ptr<SfxItemSet> pReplSet;
791  if( bDoReplace && s_pReplaceList && s_pReplaceList->Count() )
792  {
793  pReplSet.reset( new SfxItemSet( m_pWrtShell->GetAttrPool(),
794  aSearchAttrRange ) );
795  s_pReplaceList->Get( *pReplSet );
796 
797  // -- Page break with page template
798  ::SfxToSwPageDescAttr( *m_pWrtShell, *pReplSet );
799 
800  if( !pReplSet->Count() ) // too bad, we don't know
801  pReplSet.reset(); // the attributes
802  }
803 
804  // build SearchOptions to be used
805 
807  aSearchOpt.Locale = GetAppLanguageTag().getLocale();
808  if( !bDoReplace )
809  aSearchOpt.replaceString.clear();
810 
811  sal_uLong nFound;
812  if( aSrchSet.Count() || ( pReplSet && pReplSet->Count() ))
813  {
814  nFound = m_pWrtShell->SearchAttr(
815  aSrchSet,
817  rOptions.eStart,
818  rOptions.eEnd,
819  eRanges,
820  !s_pSrchItem->GetSearchString().isEmpty() ? &aSearchOpt : nullptr,
821  pReplSet.get() );
822  }
823  else if( s_pSrchItem->GetPattern() )
824  {
825  // Searching (and replacing) templates
826  const OUString& sRplStr( s_pSrchItem->GetReplaceString() );
827  nFound = m_pWrtShell->SearchTempl( s_pSrchItem->GetSearchString(),
828  rOptions.eStart,
829  rOptions.eEnd,
830  eRanges,
831  bDoReplace ? &sRplStr : nullptr );
832  }
833  else
834  {
835  // Normal search
836  nFound = m_pWrtShell->SearchPattern(aSearchOpt, s_pSrchItem->GetNotes(),
837  rOptions.eStart,
838  rOptions.eEnd,
839  eRanges,
840  bDoReplace );
841  }
842  m_pWrtShell->EndSelect();
843  return nFound;
844 }
845 
847 {
848 #if HAVE_FEATURE_DESKTOP
849  const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId();
851  auto pSrchDlg = pWrp ? pWrp->getDialog() : nullptr;
852  return pSrchDlg;
853 #else
854  return nullptr;
855 #endif
856 }
857 
859 {
860  SfxWhichIter aIter(rSet);
861  sal_uInt16 nWhich = aIter.FirstWhich();
862 
863  while(nWhich)
864  {
865  switch(nWhich)
866  {
867  case SID_SEARCH_OPTIONS:
868  {
869  SearchOptionFlags nOpt = SearchOptionFlags::ALL;
870  if( GetDocShell()->IsReadOnly() )
871  nOpt &= ~SearchOptionFlags( SearchOptionFlags::REPLACE |
872  SearchOptionFlags::REPLACE_ALL );
873  rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast<sal_uInt16>(nOpt) ));
874  }
875  break;
876  case SID_SEARCH_ITEM:
877  {
878  if ( !s_pSrchItem )
879  {
880  s_pSrchItem = new SvxSearchItem( SID_SEARCH_ITEM );
881  s_pSrchItem->SetFamily(SfxStyleFamily::Para);
882  s_pSrchItem->SetSearchString( m_pWrtShell->GetSelText() );
883  }
884 
885  if( s_bJustOpened && m_pWrtShell->IsSelection() )
886  {
887  OUString aText;
888  if( 1 == m_pWrtShell->GetCursorCnt() &&
889  !( aText = m_pWrtShell->SwCursorShell::GetSelText() ).isEmpty() )
890  {
891  s_pSrchItem->SetSearchString( aText );
892  s_pSrchItem->SetSelection( false );
893  }
894  else
895  s_pSrchItem->SetSelection( true );
896  }
897 
898  s_bJustOpened = false;
899  rSet.Put( *s_pSrchItem );
900  }
901  break;
902  }
903  nWhich = aIter.NextWhich();
904  }
905 }
906 
907 /* 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:1098
SwDocPositions eStart
Definition: viewsrch.cxx:66
constexpr TypedWhichId< SvxBlinkItem > RES_CHRATR_BLINK(18)
static void lcl_addContainerToJson(boost::property_tree::ptree &rTree, const OString &rKey, const std::vector< OString > &rMatches)
Adds rMatches using rKey as a key to the rTree tree.
Definition: viewsrch.cxx:73
Marks a position in the document model.
Definition: pam.hxx:35
bool IsAnyEnabled() const
SfxChildWindow * GetChildWindow(sal_uInt16)
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_CTL_FONT(27)
static sal_uInt16 GetMoveType()
Definition: viewmdi.cxx:643
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:188
static void lcl_emitSearchResultCallbacks(SvxSearchItem const *pSearchItem, SwWrtShell const *pWrtShell, bool bHighlightAll)
Emits LOK callbacks (count, selection) for search results.
Definition: viewsrch.cxx:89
std::unique_ptr< SwWrtShell > m_pWrtShell
Definition: view.hxx:183
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const =0
void SetSearchString(const OUString &rNewString)
bool IsReadOnly(const OUString &rURL, bool *pbExist)
bool IsStartOfDoc() const
Definition: crsrsh.cxx:2729
sal_uIntPtr sal_uLong
Find "all" in Footer/Header/Fly...
constexpr TypedWhichId< SwRegisterItem > RES_PARATR_REGISTER(71)
SAL_DLLPRIVATE void Replace()
Definition: viewsrch.cxx:647
static SvxSearchDialog * GetSearchDialog()
Definition: viewsrch.cxx:846
sal_Int16 nId
sal_uInt16 FirstWhich()
void Done(bool bRemove=false)
OString join(const OString &rSeparator, const std::vector< OString > &rSequence)
SfxViewShell * GetSfxViewShell() const
Definition: viewsh.hxx:444
void StateSearch(SfxItemSet &)
Definition: viewsrch.cxx:858
const SfxItemSet * GetArgs() const
void SfxToSwPageDescAttr(const SwWrtShell &rShell, SfxItemSet &rSet)
Definition: uitool.cxx:588
SfxItemSet & Get(SfxItemSet &rSet)
sal_uInt16 const aTextFormatCollSetRange[]
Definition: init.cxx:150
Find in selections.
constexpr TypedWhichId< SvxTwoLinesItem > RES_CHRATR_TWO_LINES(34)
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
sal_uInt16 NextWhich()
#define NID_SRCH_REP
Definition: workctrl.hxx:45
const i18nutil::SearchOptions2 & GetSearchOptions() const
static SearchAttrItemList * s_pReplaceList
Definition: view.hxx:164
SwDocPositions
Definition: cshtyp.hxx:103
Used by the UI to modify the document model.
Definition: wrtsh.hxx:90
constexpr TypedWhichId< SvxCaseMapItem > RES_CHRATR_CASEMAP(RES_CHRATR_BEGIN)
constexpr sal_uInt16 RES_PARATR_BEGIN(RES_TXTATR_END)
void SetSrchFlag(bool bSuccess)
FindRanges
Definition: cshtyp.hxx:90
void libreOfficeKitViewCallback(int nType, const char *pPayload) const override
int SetCursor(const Point &rPt, bool bOnlyText=false, bool bBlock=true)
Definition: crsrsh.cxx:758
constexpr TypedWhichId< SvxCharReliefItem > RES_CHRATR_RELIEF(36)
static bool s_bJustOpened
Definition: view.hxx:161
bool GetPattern() const
constexpr TypedWhichId< SvxHyphenZoneItem > RES_PARATR_HYPHENZONE(69)
css::lang::Locale Locale
constexpr TypedWhichId< SvxParaVertAlignItem > RES_PARATR_VERTALIGN(76)
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
#define SW_MOD()
Definition: swmodule.hxx:256
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
SvxSearchCmd GetCommand() const
bool GetNotes() const
constexpr TypedWhichId< SvxShadowedItem > RES_CHRATR_SHADOWED(13)
const OUString & GetReplaceString() const
All (only in non-body and selections).
bool GetSelection() const
void AddRule(SwUndoArg eWhat, const OUString &rWith)
Definition: SwRewriter.cxx:29
sal_uInt16 Count() const
constexpr TypedWhichId< SvxLineSpacingItem > RES_PARATR_LINESPACING(RES_PARATR_BEGIN)
ring_container GetRingContainer()
Definition: ring.hxx:240
OUString SwResId(const char *pId)
Definition: swmodule.cxx:178
static void SetMoveType(sal_uInt16 nSet)
Definition: viewmdi.cxx:648
constexpr TypedWhichId< SvxOverlineItem > RES_CHRATR_OVERLINE(38)
constexpr TypedWhichId< SvxEmphasisMarkItem > RES_CHRATR_EMPHASIS_MARK(33)
#define DELETEZ(p)
static void SetSearchLabel(const SearchLabel &rSL)
void SetFamily(SfxStyleFamily eNewFamily)
SwDocShell * GetDocShell()
Definition: view.cxx:1107
constexpr TypedWhichId< SvxCharScaleWidthItem > RES_CHRATR_SCALEW(35)
SAL_DLLPRIVATE bool SearchAndWrap(bool bApi)
Definition: viewsrch.cxx:480
void SetReturnValue(const SfxPoolItem &)
const LanguageTag & GetAppLanguageTag()
Definition: init.cxx:736
constexpr TypedWhichId< SvxColorItem > RES_CHRATR_COLOR(3)
constexpr TypedWhichId< SvxScriptSpaceItem > RES_PARATR_SCRIPTSPACE(73)
constexpr sal_uInt16 RES_FRMATR_END(131)
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
constexpr TypedWhichId< SvxBrushItem > RES_CHRATR_BACKGROUND(21)
sal_uInt16 GetSlot() const
SAL_DLLPRIVATE sal_uLong FUNC_Search(const SwSearchOptions &rOptions)
Definition: viewsrch.cxx:756
static SfxViewFrame * Current()
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_CJK_WEIGHT(26)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
#define SAL_WARN_IF(condition, area, stream)
constexpr TypedWhichId< SvxWordLineModeItem > RES_CHRATR_WORDLINEMODE(16)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_CTL_WEIGHT(31)
constexpr TypedWhichId< SvxForbiddenRuleItem > RES_PARATR_FORBIDDEN_RULES(75)
void ExecSearch(SfxRequest &)
Definition: viewsrch.cxx:125
SvxSearchDialog * getDialog()
const OUString & GetSearchString() const
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_CJK_FONT(22)
SwDocPositions eEnd
Definition: viewsrch.cxx:66
constexpr sal_uInt16 RES_PARATR_END(82)
void SetSelection(bool bNewSelection)
void SetDocWin(vcl::Window *pDocWin, SvxSearchCmd eCommand)
constexpr TypedWhichId< SvxLRSpaceItem > RES_LR_SPACE(91)
constexpr sal_uInt16 RES_CHRATR_END(46)
SvxSearchCmd
Find "one" only in body text.
bool IsEndOfDoc() const
Definition: crsrsh.cxx:2741
#define FN_REPEAT_SEARCH
Definition: cmdid.h:103
void AppendItem(const SfxPoolItem &)
const SearchAttrItemList * GetReplaceItemList() const
bool IsAPI() const
constexpr TypedWhichId< SvxCharRotateItem > RES_CHRATR_ROTATE(32)
SAL_DLLPRIVATE bool SearchAll()
Definition: viewsrch.cxx:622
static SvxSearchItem * s_pSrchItem
Definition: view.hxx:154
static SearchAttrItemList * s_pSearchList
Definition: view.hxx:163
SearchOptionFlags
constexpr sal_uInt16 RES_FRMATR_BEGIN(RES_PARATR_LIST_END)
constexpr TypedWhichId< SvxULSpaceItem > RES_UL_SPACE(92)
SwSearchOptions(SwWrtShell const *pSh, bool bBackward)
Definition: viewsrch.cxx:741
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_POSTURE(11)
static bool s_bExtra
Definition: view.hxx:159
const SearchAttrItemList * GetSearchItemList() const