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