1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include <boost/property_tree/json_parser.hpp>
25 #include <hintids.hxx>
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 <sfx2/lokhelper.hxx>
38 #include <svx/srchdlg.hxx>
39 #include <swmodule.hxx>
41 #include <workctrl.hxx>
48 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
49 #include <comphelper/lok.hxx>
50 #include <comphelper/string.hxx>
52 #include <strings.hrc>
53 #include <SwRewriter.hxx>
55 #include <PostItMgr.hxx>
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
;
64 struct SwSearchOptions
66 SwDocPositions eStart
, eEnd
;
69 SwSearchOptions( SwWrtShell
const * pSh
, bool bBackward
);
72 /// Adds rMatches using rKey as a key to the rTree tree.
73 static void lcl_addContainerToJson(boost::property_tree::ptree
& rTree
, const OString
& rKey
, const std::vector
<OString
>& rMatches
)
75 boost::property_tree::ptree aChildren
;
77 for (const OString
& rMatch
: rMatches
)
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
));
85 rTree
.add_child(rKey
.getStr(), aChildren
);
88 /// Emits LOK callbacks (count, selection) for search results.
89 static void lcl_emitSearchResultCallbacks(SvxSearchItem
const * pSearchItem
, SwWrtShell
const * pWrtShell
, bool bHighlightAll
)
91 // Emit a callback also about the selection rectangles, grouped by matches.
92 SwPaM
* pPaM
= pWrtShell
->GetCursor();
96 std::vector
<OString
> aMatches
;
97 for (SwPaM
& rPaM
: pPaM
->GetRingContainer())
99 if (SwShellCursor
* pShellCursor
= dynamic_cast<SwShellCursor
*>(&rPaM
))
101 std::vector
<OString
> aSelectionRectangles
;
102 pShellCursor
->SwSelPaintRects::Show(&aSelectionRectangles
);
103 std::vector
<OString
> aRect
;
104 for (const OString
& rSelectionRectangle
: aSelectionRectangles
)
106 if (rSelectionRectangle
.isEmpty())
108 aRect
.push_back(rSelectionRectangle
);
110 OString sRect
= comphelper::string::join("; ", aRect
);
111 aMatches
.push_back(sRect
);
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
);
119 std::stringstream aStream
;
120 boost::property_tree::write_json(aStream
, aTree
);
121 OString
aPayload( aStream
.str() );
123 pWrtShell
->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION
, aPayload
);
126 { // FindAll disables this during find, do it once when done.
127 SfxLokHelper::notifyUpdate(pWrtShell
->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION
);
128 SfxLokHelper::notifyOtherViewsUpdatePerViewId(pWrtShell
->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION
);
132 void SwView::ExecSearch(SfxRequest
& rReq
)
134 GetWrtShell().addCurrentPosition();
136 const SfxItemSet
* pArgs
= rReq
.GetArgs();
137 const SfxPoolItem
* pItem
= nullptr;
139 if(pArgs
&& SfxItemState::SET
== pArgs
->GetItemState(SID_SEARCH_QUIET
, false, &pItem
))
140 bQuiet
= static_cast<const SfxBoolItem
*>( pItem
)->GetValue();
142 sal_uInt16 nSlot
= rReq
.GetSlot();
143 if (nSlot
== FN_REPEAT_SEARCH
&& !s_pSrchItem
)
147 rReq
.SetReturnValue(SfxBoolItem(nSlot
, false));
151 if( m_pWrtShell
->IsBlockMode() )
152 m_pWrtShell
->LeaveBlockMode();
155 // for now do nothing
156 case SID_SEARCH_ITEM
:
159 s_pSrchItem
= pArgs
->Get(SID_SEARCH_ITEM
).Clone();
164 s_bJustOpened
= true;
165 GetViewFrame().GetBindings().Invalidate(SID_SEARCH_ITEM
);
173 s_pSrchItem
= pArgs
->Get(SID_SEARCH_ITEM
).Clone();
175 s_xSearchList
.reset();
176 s_xReplaceList
.reset();
178 SvxSearchDialog
*const pSrchDlg(GetSearchDialog());
181 // We will remember the search-/replace items.
182 const SearchAttrItemList
* pList
= pSrchDlg
->GetSearchItemList();
183 if( nullptr != pList
&& pList
->Count() )
184 s_xSearchList
.reset(new SearchAttrItemList( *pList
));
186 pList
= pSrchDlg
->GetReplaceItemList();
187 if (nullptr != pList
&& pList
->Count())
188 s_xReplaceList
.reset(new SearchAttrItemList( *pList
));
193 case FN_REPEAT_SEARCH
:
196 sal_uInt16 nMoveType
= SwView::GetMoveType();
198 if(FID_SEARCH_NOW
== nSlot
&& !rReq
.IsAPI())
199 SwView::SetMoveType(NID_SRCH_REP
);
202 SvxSearchDialog
* pSrchDlg(GetSearchDialog());
205 s_xSearchList
.reset();
206 s_xReplaceList
.reset();
208 const SearchAttrItemList
* pList
= pSrchDlg
->GetSearchItemList();
209 if( nullptr != pList
&& pList
->Count() )
210 s_xSearchList
.reset(new SearchAttrItemList( *pList
));
212 pList
= pSrchDlg
->GetReplaceItemList();
213 if (nullptr != pList
&& pList
->Count())
214 s_xReplaceList
.reset(new SearchAttrItemList( *pList
));
217 if (nSlot
== FN_REPEAT_SEARCH
)
219 OSL_ENSURE(s_pSrchItem
, "SearchItem missing");
221 s_pSrchItem
= new SvxSearchItem(SID_SEARCH_ITEM
);
225 // Get SearchItem from request
226 OSL_ENSURE(pArgs
, "Args missing");
230 s_pSrchItem
= pArgs
->Get(SID_SEARCH_ITEM
).Clone();
233 SvxSearchCmd eCommand
= s_pSrchItem
->GetCommand();
236 case SvxSearchCmd::FIND
:
238 bool bRet
= SearchAndWrap(bQuiet
);
241 Scroll(m_pWrtShell
->GetCharRect().SVRect());
242 if (comphelper::LibreOfficeKit::isActive())
243 lcl_emitSearchResultCallbacks(s_pSrchItem
, m_pWrtShell
.get(), /* bHighlightAll = */ false);
245 rReq
.SetReturnValue(SfxBoolItem(nSlot
, bRet
));
247 GetDocShell()->Broadcast(SfxHint(SfxHintId::SwNavigatorUpdateTracking
));
250 case SvxSearchCmd::FIND_ALL
:
252 // Disable LOK selection notifications during search.
253 m_pWrtShell
->GetSfxViewShell()->setTiledSearching(true);
254 const auto nFound
= SearchAll();
255 m_pWrtShell
->GetSfxViewShell()->setTiledSearching(false);
257 GetDocShell()->Broadcast(
258 SfxHint(SfxHintId::SwNavigatorUpdateTracking
));
259 GetDocShell()->Broadcast(
260 SfxHint(SfxHintId::SwNavigatorSelectOutlinesWithSelections
));
264 #if HAVE_FEATURE_DESKTOP
267 m_pWrtShell
->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND
, s_pSrchItem
->GetSearchString().toUtf8());
268 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound
);
275 if (comphelper::LibreOfficeKit::isActive())
276 lcl_emitSearchResultCallbacks(s_pSrchItem
, m_pWrtShell
.get(), /* bHighlightAll = */ true);
279 OUString
sText(SwResId(STR_SEARCH_KEY_FOUND_TIMES
));
280 sText
= sText
.replaceFirst("%1", OUString::number(nFound
));
281 SvxSearchDialogWrapper::SetSearchLabel(sText
);
284 rReq
.SetReturnValue(SfxBoolItem(nSlot
, nFound
!= 0));
287 case SvxSearchCmd::REPLACE
:
290 // 1) Replace selection (Not if only attributes should be replaced)
292 // what if you only want to assign attributes to the found??
294 SvxSearchCmd nCmd
= SvxSearchCmd::FIND
;
295 if( !s_pSrchItem
->GetReplaceString().isEmpty() ||
298 // Prevent, that the replaced string will be found again
299 // if the replacement string is containing the search string.
300 bool bBack
= s_pSrchItem
->GetBackward();
303 OUString
aReplace( s_pSrchItem
->GetReplaceString() );
304 i18nutil::SearchOptions2
aTmp( s_pSrchItem
->GetSearchOptions() );
305 std::optional
<OUString
> xBackRef
= sw::ReplaceBackReferences(aTmp
,
306 m_pWrtShell
->GetCursor(), m_pWrtShell
->GetLayout());
308 s_pSrchItem
->SetReplaceString( *xBackRef
);
312 s_pSrchItem
->SetReplaceString( aReplace
);
317 m_pWrtShell
->SwapPam();
320 else if( s_xReplaceList
)
321 nCmd
= SvxSearchCmd::REPLACE
;
323 // 2) Search further (without replacing!)
325 SvxSearchCmd nOldCmd
= s_pSrchItem
->GetCommand();
326 s_pSrchItem
->SetCommand( nCmd
);
327 bool bRet
= SearchAndWrap(bQuiet
);
329 Scroll( m_pWrtShell
->GetCharRect().SVRect());
330 s_pSrchItem
->SetCommand( nOldCmd
);
331 rReq
.SetReturnValue(SfxBoolItem(nSlot
, bRet
));
335 case SvxSearchCmd::REPLACE_ALL
:
337 SwSearchOptions
aOpts( m_pWrtShell
.get(), s_pSrchItem
->GetBackward() );
341 { //Scope for SwWait-Object
342 SwWait
aWait( *GetDocShell(), true );
343 m_pWrtShell
->StartAllAction();
345 // i#8288 "replace all" should not change cursor
346 // position, so save current cursor
349 if (!s_pSrchItem
->GetSelection())
351 // if we don't want to search in the selection...
352 m_pWrtShell
->KillSelection(nullptr, false);
353 if (SwDocPositions::Start
== aOpts
.eEnd
)
355 m_pWrtShell
->EndOfSection();
359 m_pWrtShell
->StartOfSection();
362 nFound
= FUNC_Search( aOpts
);
363 // create it just to overwrite it with stack cursor
364 m_pWrtShell
->CreateCursor();
365 // i#8288 restore the original cursor position
366 m_pWrtShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
);
367 m_pWrtShell
->EndAllAction();
370 rReq
.SetReturnValue(SfxBoolItem(nSlot
, nFound
!= 0 && ULONG_MAX
!= nFound
));
373 #if HAVE_FEATURE_DESKTOP
376 m_pWrtShell
->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND
, s_pSrchItem
->GetSearchString().toUtf8());
377 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound
);
381 SwView::SetMoveType(nMoveType
);
385 if( !bQuiet
&& ULONG_MAX
!= nFound
)
387 OUString
sText( SwResId( STR_NB_REPLACED
) );
388 sText
= sText
.replaceFirst("XX", OUString::number( nFound
));
389 SvxSearchDialogWrapper::SetSearchLabel(sText
);
395 uno::Reference
< frame::XDispatchRecorder
> xRecorder
=
396 GetViewFrame().GetBindings().GetRecorder();
397 //prevent additional dialogs in recorded macros
398 if ( xRecorder
.is() )
399 rReq
.AppendItem(SfxBoolItem(SID_SEARCH_QUIET
, true));
402 m_eLastSearchCommand
= s_pSrchItem
->GetCommand();
403 SwView::SetMoveType(nMoveType
);
406 case FID_SEARCH_SEARCHSET
:
407 case FID_SEARCH_REPLACESET
:
409 static const WhichRangesContainer
aNormalAttr(svl::Items
<
410 /* 0 */ RES_CHRATR_CASEMAP
, RES_CHRATR_CASEMAP
,
411 /* 2 */ RES_CHRATR_COLOR
, RES_CHRATR_POSTURE
,
412 /* 4 */ RES_CHRATR_SHADOWED
, RES_CHRATR_WORDLINEMODE
,
413 /* 6 */ RES_CHRATR_BLINK
, RES_CHRATR_BLINK
,
414 /* 8 */ RES_CHRATR_BACKGROUND
, RES_CHRATR_BACKGROUND
,
415 /*10 */ RES_CHRATR_ROTATE
, RES_CHRATR_ROTATE
,
416 /*12 */ RES_CHRATR_SCALEW
, RES_CHRATR_RELIEF
,
417 /*14 */ RES_CHRATR_OVERLINE
, RES_CHRATR_OVERLINE
,
418 /*16 */ RES_PARATR_LINESPACING
, RES_PARATR_HYPHENZONE
,
419 /*18 */ RES_PARATR_REGISTER
, RES_PARATR_REGISTER
,
420 /*20 */ RES_PARATR_VERTALIGN
, RES_PARATR_VERTALIGN
,
421 RES_MARGIN_FIRSTLINE
, RES_MARGIN_RIGHT
,
422 RES_UL_SPACE
, RES_UL_SPACE
,
423 /*24 */ SID_ATTR_PARA_MODEL
, SID_ATTR_PARA_KEEP
426 SfxItemSet
aSet(m_pWrtShell
->GetAttrPool(), aNormalAttr
);
428 if( SvtCTLOptions::IsCTLFontEnabled() )
430 aSet
.MergeRange(RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_WEIGHT
);
432 if( SvtCJKOptions::IsAnyEnabled() )
434 aSet
.MergeRange(RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_WEIGHT
);
435 aSet
.MergeRange(RES_CHRATR_EMPHASIS_MARK
, RES_CHRATR_TWO_LINES
);
436 aSet
.MergeRange(RES_PARATR_SCRIPTSPACE
, RES_PARATR_FORBIDDEN_RULES
);
439 TypedWhichId
<SvxSetItem
> nWhich
= SID_SEARCH_SEARCHSET
;
441 if ( FID_SEARCH_REPLACESET
== nSlot
)
443 nWhich
= SID_SEARCH_REPLACESET
;
445 if ( s_xReplaceList
)
447 s_xReplaceList
->Get( aSet
);
448 s_xReplaceList
.reset();
451 else if ( s_xSearchList
)
453 s_xSearchList
->Get( aSet
);
454 s_xSearchList
.reset();
456 rReq
.SetReturnValue( SvxSetItem( nWhich
, aSet
) );
460 SAL_WARN_IF( nSlot
, "sw", "nSlot: " << nSlot
<< " wrong Dispatcher (viewsrch.cxx)" );
465 bool SwView::SearchAndWrap(bool bApi
)
467 SwSearchOptions
aOpts( m_pWrtShell
.get(), s_pSrchItem
->GetBackward() );
469 // Remember starting position of the search for wraparound
470 // Start- / EndAction perhaps because existing selections of 'search all'
471 m_pWrtShell
->StartAllAction();
474 // After a search all action we place the cursor at the beginning of
475 // the document so that the single search selects the first matching
476 // occurrence in the document instead of the second.
477 if( m_eLastSearchCommand
== SvxSearchCmd::FIND_ALL
)
479 if( SwDocPositions::Start
== aOpts
.eEnd
)
480 m_pWrtShell
->EndOfSection();
482 m_pWrtShell
->StartOfSection();
485 // fdo#65014 : Ensure that the point of the cursor is at the extremity of the
486 // selection closest to the end being searched to as to exclude the selected
487 // region from the search. (This doesn't work in the case of multiple
488 // selected regions as the cursor doesn't mark the selection in that case.)
489 m_pWrtShell
->GetCursor()->Normalize( s_pSrchItem
->GetBackward() );
491 if (!m_pWrtShell
->HasSelection() && (s_pSrchItem
->HasStartPoint()))
493 // No selection -> but we have a start point (top left corner of the
494 // current view), start searching from there, not from the current
496 SwEditShell
& rShell
= GetWrtShell();
497 Point
aPosition(s_pSrchItem
->GetStartPointX(), s_pSrchItem
->GetStartPointY());
498 rShell
.SetCursor(aPosition
);
501 // If you want to search in selected areas, they must not be unselected.
502 if (!s_pSrchItem
->GetSelection())
503 m_pWrtShell
->KillSelection(nullptr, false);
505 std::optional
<SwWait
> oWait( std::in_place
, *GetDocShell(), true );
506 if( FUNC_Search( aOpts
) )
509 if(m_pWrtShell
->IsSelFrameMode())
511 m_pWrtShell
->UnSelectFrame();
512 m_pWrtShell
->LeaveSelFrameMode();
515 m_pWrtShell
->EndAllAction();
520 // Search in the specialized areas when no search is present in selections.
521 // When searching selections will already searched in these special areas.
522 bool bHasSrchInOther
= s_bExtra
;
523 if (!s_pSrchItem
->GetSelection() && !s_bExtra
)
526 if( FUNC_Search( aOpts
) )
530 m_pWrtShell
->EndAllAction();
536 s_bExtra
= !s_bExtra
;
538 // If starting position is at the end or beginning of the document.
541 m_pWrtShell
->EndAllAction();
544 #if HAVE_FEATURE_DESKTOP
545 m_pWrtShell
->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND
, s_pSrchItem
->GetSearchString().toUtf8());
546 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound
);
553 m_pWrtShell
->EndAllAction();
554 // Try again with WrapAround?
556 m_pWrtShell
->StartAllAction();
557 m_pWrtShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
);
558 oWait
.emplace( *GetDocShell(), true );
560 bool bSrchBkwrd
= SwDocPositions::Start
== aOpts
.eEnd
;
562 aOpts
.eEnd
= bSrchBkwrd
? SwDocPositions::Start
: SwDocPositions::End
;
563 aOpts
.eStart
= bSrchBkwrd
? SwDocPositions::End
: SwDocPositions::Start
;
567 m_pWrtShell
->ClearMark();
568 // Select the start or the end of the entire document
570 m_pWrtShell
->SttEndDoc(false);
572 m_pWrtShell
->SttEndDoc(true);
575 s_bFound
= bool(FUNC_Search( aOpts
));
577 // If WrapAround found no matches in the body text, search in the special
579 if (!s_bFound
&& !s_pSrchItem
->GetSelection() && !s_bExtra
)
582 if (FUNC_Search(aOpts
))
588 m_pWrtShell
->EndAllAction();
590 #if HAVE_FEATURE_DESKTOP
594 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::End
);
596 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Start
);
600 m_pWrtShell
->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND
, s_pSrchItem
->GetSearchString().toUtf8());
601 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound
);
607 sal_uInt16
SwView::SearchAll()
609 SwWait
aWait( *GetDocShell(), true );
610 m_pWrtShell
->StartAllAction();
612 SwSearchOptions
aOpts( m_pWrtShell
.get(), s_pSrchItem
->GetBackward() );
614 if (!s_pSrchItem
->GetSelection())
616 // Cancel existing selections, if should not be sought in selected areas.
617 m_pWrtShell
->KillSelection(nullptr, false);
619 if( SwDocPositions::Start
== aOpts
.eEnd
)
620 m_pWrtShell
->EndOfSection();
622 m_pWrtShell
->StartOfSection();
625 sal_uInt16 nFound
= o3tl::narrowing
<sal_uInt16
>(FUNC_Search( aOpts
));
626 s_bFound
= 0 != nFound
;
628 m_pWrtShell
->EndAllAction();
632 void SwView::Replace()
634 SwWait
aWait( *GetDocShell(), true );
636 m_pWrtShell
->StartAllAction();
638 if( s_pSrchItem
->GetPattern() ) // Templates?
640 SwRewriter aRewriter
;
641 aRewriter
.AddRule(UndoArg1
, s_pSrchItem
->GetSearchString());
642 aRewriter
.AddRule(UndoArg2
, SwResId(STR_YIELDS
));
643 aRewriter
.AddRule(UndoArg3
, s_pSrchItem
->GetReplaceString());
645 m_pWrtShell
->StartUndo(SwUndoId::UI_REPLACE_STYLE
, &aRewriter
);
647 m_pWrtShell
->SetTextFormatColl( m_pWrtShell
->GetParaStyle(
648 s_pSrchItem
->GetReplaceString(),
649 SwWrtShell::GETSTYLE_CREATESOME
));
651 m_pWrtShell
->EndUndo();
655 if (GetPostItMgr()->HasActiveSidebarWin())
656 GetPostItMgr()->Replace(s_pSrchItem
);
658 bool bReqReplace
= true;
660 if(m_pWrtShell
->HasSelection())
662 /* check that the selection match the search string*/
664 SwPosition aStartPos
= * m_pWrtShell
->GetCursor()->Start();
665 SwPosition aEndPos
= * m_pWrtShell
->GetCursor()->End();
666 bool bHasSelection
= s_pSrchItem
->GetSelection();
667 SvxSearchCmd nOldCmd
= s_pSrchItem
->GetCommand();
669 //set state for checking if current selection has a match
670 s_pSrchItem
->SetCommand( SvxSearchCmd::FIND
);
671 s_pSrchItem
->SetSelection(true);
673 //check if it matches
674 SwSearchOptions
aOpts( m_pWrtShell
.get(), s_pSrchItem
->GetBackward() );
675 if( ! FUNC_Search(aOpts
) )
678 //no matching therefore should not replace selection
679 // => remove selection
681 if(! s_pSrchItem
->GetBackward() )
683 (* m_pWrtShell
->GetCursor()->Start()) = aStartPos
;
684 (* m_pWrtShell
->GetCursor()->End()) = aEndPos
;
688 (* m_pWrtShell
->GetCursor()->Start()) = aEndPos
;
689 (* m_pWrtShell
->GetCursor()->End()) = aStartPos
;
694 //set back old search state
695 s_pSrchItem
->SetCommand( nOldCmd
);
696 s_pSrchItem
->SetSelection(bHasSelection
);
699 * remove current selection
700 * otherwise it is always replaced
701 * no matter if the search string exists or not in the selection
702 * Now the selection is removed and the next matching string is selected
708 bool bReplaced
= m_pWrtShell
->SwEditShell::Replace( s_pSrchItem
->GetReplaceString(),
709 s_pSrchItem
->GetRegExp());
710 if( bReplaced
&& s_xReplaceList
&& s_xReplaceList
->Count() && m_pWrtShell
->HasSelection() )
712 SfxItemSet
aReplSet( m_pWrtShell
->GetAttrPool(),
713 aTextFormatCollSetRange
);
714 if( s_xReplaceList
->Get( aReplSet
).Count() )
716 ::SfxToSwPageDescAttr( *m_pWrtShell
, aReplSet
);
717 m_pWrtShell
->SwEditShell::SetAttrSet( aReplSet
);
723 m_pWrtShell
->EndAllAction();
726 SwSearchOptions::SwSearchOptions( SwWrtShell
const * pSh
, bool bBackward
)
727 : eStart(SwDocPositions::Curr
)
731 eEnd
= SwDocPositions::Start
;
732 bDontWrap
= pSh
->IsEndOfDoc();
736 eEnd
= SwDocPositions::End
;
737 bDontWrap
= pSh
->IsStartOfDoc();
741 sal_uLong
SwView::FUNC_Search( const SwSearchOptions
& rOptions
)
743 #if HAVE_FEATURE_DESKTOP
744 SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty
);
746 bool bDoReplace
= s_pSrchItem
->GetCommand() == SvxSearchCmd::REPLACE
||
747 s_pSrchItem
->GetCommand() == SvxSearchCmd::REPLACE_ALL
;
749 FindRanges eRanges
= s_pSrchItem
->GetSelection()
752 ? FindRanges::InOther
: FindRanges::InBody
;
753 if (s_pSrchItem
->GetCommand() == SvxSearchCmd::FIND_ALL
||
754 s_pSrchItem
->GetCommand() == SvxSearchCmd::REPLACE_ALL
)
755 eRanges
|= FindRanges::InSelAll
;
757 m_pWrtShell
->SttSelect();
759 static const WhichRangesContainer
aSearchAttrRange(svl::Items
<
760 RES_CHRATR_BEGIN
, RES_CHRATR_END
-1,
761 RES_PARATR_BEGIN
, RES_PARATR_END
-1,
762 RES_FRMATR_BEGIN
, RES_FRMATR_END
-1,
763 SID_ATTR_PARA_MODEL
, SID_ATTR_PARA_KEEP
766 SfxItemSet
aSrchSet( m_pWrtShell
->GetAttrPool(), aSearchAttrRange
);
767 if( s_xSearchList
&& s_xSearchList
->Count() )
769 s_xSearchList
->Get( aSrchSet
);
771 // -- Page break with page template
772 ::SfxToSwPageDescAttr( *m_pWrtShell
, aSrchSet
);
775 std::optional
<SfxItemSet
> xReplSet
;
776 if( bDoReplace
&& s_xReplaceList
&& s_xReplaceList
->Count() )
778 xReplSet
.emplace( m_pWrtShell
->GetAttrPool(), aSearchAttrRange
);
779 s_xReplaceList
->Get( *xReplSet
);
781 // -- Page break with page template
782 ::SfxToSwPageDescAttr( *m_pWrtShell
, *xReplSet
);
784 if( !xReplSet
->Count() ) // too bad, we don't know
785 xReplSet
.reset(); // the attributes
788 // build SearchOptions to be used
790 i18nutil::SearchOptions2
aSearchOpt( s_pSrchItem
->GetSearchOptions() );
791 aSearchOpt
.Locale
= GetAppLanguageTag().getLocale();
793 aSearchOpt
.replaceString
.clear();
796 if( aSrchSet
.Count() || ( xReplSet
&& xReplSet
->Count() ))
798 nFound
= m_pWrtShell
->SearchAttr(
800 !s_pSrchItem
->GetPattern(),
804 !s_pSrchItem
->GetSearchString().isEmpty() ? &aSearchOpt
: nullptr,
805 xReplSet
? &*xReplSet
: nullptr );
807 else if( s_pSrchItem
->GetPattern() )
809 // Searching (and replacing) templates
810 const OUString
& sRplStr( s_pSrchItem
->GetReplaceString() );
811 nFound
= m_pWrtShell
->SearchTempl( s_pSrchItem
->GetSearchString(),
815 bDoReplace
? &sRplStr
: nullptr );
820 nFound
= m_pWrtShell
->SearchPattern(aSearchOpt
, s_pSrchItem
->GetNotes(),
826 m_pWrtShell
->EndSelect();
830 SvxSearchDialog
* SwView::GetSearchDialog()
832 #if HAVE_FEATURE_DESKTOP
833 const sal_uInt16 nId
= SvxSearchDialogWrapper::GetChildWindowId();
834 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
837 SvxSearchDialogWrapper
*pWrp
= static_cast<SvxSearchDialogWrapper
*>(pViewFrm
->GetChildWindow(nId
));
840 return pWrp
->getDialog();
846 void SwView::StateSearch(SfxItemSet
&rSet
)
848 SfxWhichIter
aIter(rSet
);
849 sal_uInt16 nWhich
= aIter
.FirstWhich();
855 case SID_SEARCH_OPTIONS
:
857 SearchOptionFlags nOpt
= SearchOptionFlags::ALL
;
858 if( GetDocShell()->IsReadOnly() )
859 nOpt
&= ~SearchOptionFlags( SearchOptionFlags::REPLACE
|
860 SearchOptionFlags::REPLACE_ALL
);
861 rSet
.Put( SfxUInt16Item( SID_SEARCH_OPTIONS
, static_cast<sal_uInt16
>(nOpt
) ));
864 case SID_SEARCH_ITEM
:
868 s_pSrchItem
= new SvxSearchItem( SID_SEARCH_ITEM
);
869 s_pSrchItem
->SetFamily(SfxStyleFamily::Para
);
870 s_pSrchItem
->SetSearchString( m_pWrtShell
->GetSelText() );
873 if( s_bJustOpened
&& m_pWrtShell
->IsSelection() )
876 if( 1 == m_pWrtShell
->GetCursorCnt() &&
877 !( aText
= m_pWrtShell
->SwCursorShell::GetSelText() ).isEmpty() )
879 s_pSrchItem
->SetSearchString( aText
);
880 s_pSrchItem
->SetSelection( false );
883 s_pSrchItem
->SetSelection( true );
886 s_bJustOpened
= false;
887 rSet
.Put( *s_pSrchItem
);
891 nWhich
= aIter
.NextWhich();
895 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */