/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; using namespace ::com::sun::star::i18n; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::util; //Search Parameter struct SwSearchOptions { SwDocPositions eStart, eEnd; bool bDontWrap; SwSearchOptions( SwWrtShell const * pSh, bool bBackward ); }; /// Adds rMatches using rKey as a key to the rTree tree. static void lcl_addContainerToJson(boost::property_tree::ptree& rTree, const OString& rKey, const std::vector& rMatches) { boost::property_tree::ptree aChildren; for (const OString& rMatch : rMatches) { boost::property_tree::ptree aChild; aChild.put("part", "0"); aChild.put("rectangles", rMatch.getStr()); aChildren.push_back(std::make_pair("", aChild)); } rTree.add_child(rKey.getStr(), aChildren); } /// Emits LOK callbacks (count, selection) for search results. static void lcl_emitSearchResultCallbacks(SvxSearchItem const * pSearchItem, SwWrtShell const * pWrtShell, bool bHighlightAll) { // Emit a callback also about the selection rectangles, grouped by matches. SwPaM* pPaM = pWrtShell->GetCursor(); if (!pPaM) return; std::vector aMatches; for (SwPaM& rPaM : pPaM->GetRingContainer()) { if (SwShellCursor* pShellCursor = dynamic_cast(&rPaM)) { std::vector aSelectionRectangles; pShellCursor->SwSelPaintRects::Show(&aSelectionRectangles); std::vector aRect; for (const OString & rSelectionRectangle : aSelectionRectangles) { if (rSelectionRectangle.isEmpty()) continue; aRect.push_back(rSelectionRectangle); } OString sRect = comphelper::string::join("; ", aRect); aMatches.push_back(sRect); } } boost::property_tree::ptree aTree; aTree.put("searchString", pSearchItem->GetSearchString().toUtf8().getStr()); aTree.put("highlightAll", bHighlightAll); lcl_addContainerToJson(aTree, "searchResultSelection", aMatches); std::stringstream aStream; boost::property_tree::write_json(aStream, aTree); OString aPayload = aStream.str().c_str(); pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION, aPayload.getStr()); if(bHighlightAll) { // FindAll disables this during find, do it once when done. SfxLokHelper::notifyUpdate(pWrtShell->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION); SfxLokHelper::notifyOtherViewsUpdatePerViewId(pWrtShell->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION); } } void SwView::ExecSearch(SfxRequest& rReq) { GetWrtShell().addCurrentPosition(); const SfxItemSet* pArgs = rReq.GetArgs(); const SfxPoolItem* pItem = nullptr; bool bQuiet = false; if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SEARCH_QUIET, false, &pItem)) bQuiet = static_cast( pItem)->GetValue(); sal_uInt16 nSlot = rReq.GetSlot(); if (nSlot == FN_REPEAT_SEARCH && !s_pSrchItem) { if(bQuiet) { rReq.SetReturnValue(SfxBoolItem(nSlot, false)); nSlot = 0; } } if( m_pWrtShell->IsBlockMode() ) m_pWrtShell->LeaveBlockMode(); switch (nSlot) { // for now do nothing case SID_SEARCH_ITEM: { delete s_pSrchItem; s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone(); } break; case FID_SEARCH_ON: s_bJustOpened = true; GetViewFrame()->GetBindings().Invalidate(SID_SEARCH_ITEM); break; case FID_SEARCH_OFF: if(pArgs) { // Unregister dialog delete s_pSrchItem; s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone(); s_xSearchList.reset(); s_xReplaceList.reset(); SvxSearchDialog *const pSrchDlg(GetSearchDialog()); if (pSrchDlg) { // We will remember the search-/replace items. const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList(); if( nullptr != pList && pList->Count() ) s_xSearchList.reset(new SearchAttrItemList( *pList )); pList = pSrchDlg->GetReplaceItemList(); if (nullptr != pList && pList->Count()) s_xReplaceList.reset(new SearchAttrItemList( *pList )); } } break; case FN_REPEAT_SEARCH: case FID_SEARCH_NOW: { sal_uInt16 nMoveType = SwView::GetMoveType(); { if(FID_SEARCH_NOW == nSlot && !rReq.IsAPI()) SwView::SetMoveType(NID_SRCH_REP); } SvxSearchDialog * pSrchDlg(GetSearchDialog()); if (pSrchDlg) { s_xSearchList.reset(); s_xReplaceList.reset(); const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList(); if( nullptr != pList && pList->Count() ) s_xSearchList.reset(new SearchAttrItemList( *pList )); pList = pSrchDlg->GetReplaceItemList(); if (nullptr != pList && pList->Count()) s_xReplaceList.reset(new SearchAttrItemList( *pList )); } if (nSlot == FN_REPEAT_SEARCH) { OSL_ENSURE(s_pSrchItem, "SearchItem missing"); if( !s_pSrchItem ) s_pSrchItem = new SvxSearchItem(SID_SEARCH_ITEM); } else { // Get SearchItem from request OSL_ENSURE(pArgs, "Args missing"); if ( pArgs ) { delete s_pSrchItem; s_pSrchItem = pArgs->Get(SID_SEARCH_ITEM).Clone(); } } SvxSearchCmd eCommand = s_pSrchItem->GetCommand(); switch (eCommand) { case SvxSearchCmd::FIND: { bool bRet = SearchAndWrap(bQuiet); if( bRet ) { Scroll(m_pWrtShell->GetCharRect().SVRect()); if (comphelper::LibreOfficeKit::isActive()) lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ false); } rReq.SetReturnValue(SfxBoolItem(nSlot, bRet)); GetDocShell()->Broadcast(SfxHint(SfxHintId::SwNavigatorUpdateTracking)); } break; case SvxSearchCmd::FIND_ALL: { // Disable LOK selection notifications during search. m_pWrtShell->GetSfxViewShell()->setTiledSearching(true); bool bRet = SearchAll(); m_pWrtShell->GetSfxViewShell()->setTiledSearching(false); GetDocShell()->Broadcast( SfxHint(SfxHintId::SwNavigatorUpdateTracking)); GetDocShell()->Broadcast( SfxHint(SfxHintId::SwNavigatorSelectOutlinesWithSelections)); if( !bRet ) { #if HAVE_FEATURE_DESKTOP if( !bQuiet ) { m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr()); SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound); } #endif s_bFound = false; } else if (comphelper::LibreOfficeKit::isActive()) lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ true); rReq.SetReturnValue(SfxBoolItem(nSlot, bRet)); } break; case SvxSearchCmd::REPLACE: { // 1) Replace selection (Not if only attributes should be replaced) //JP 27.04.95: Why? // what if you only want to assign attributes to the found?? SvxSearchCmd nCmd = SvxSearchCmd::FIND; if( !s_pSrchItem->GetReplaceString().isEmpty() || !s_xReplaceList ) { // Prevent, that the replaced string will be found again // if the replacement string is containing the search string. bool bBack = s_pSrchItem->GetBackward(); if (bBack) m_pWrtShell->Push(); OUString aReplace( s_pSrchItem->GetReplaceString() ); i18nutil::SearchOptions2 aTmp( s_pSrchItem->GetSearchOptions() ); std::optional xBackRef = sw::ReplaceBackReferences(aTmp, m_pWrtShell->GetCursor(), m_pWrtShell->GetLayout()); if( xBackRef ) s_pSrchItem->SetReplaceString( *xBackRef ); Replace(); if( xBackRef ) { s_pSrchItem->SetReplaceString( aReplace ); } if (bBack) { m_pWrtShell->Pop(); m_pWrtShell->SwapPam(); } } else if( s_xReplaceList ) nCmd = SvxSearchCmd::REPLACE; // 2) Search further (without replacing!) SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand(); s_pSrchItem->SetCommand( nCmd ); bool bRet = SearchAndWrap(bQuiet); if( bRet ) Scroll( m_pWrtShell->GetCharRect().SVRect()); s_pSrchItem->SetCommand( nOldCmd ); rReq.SetReturnValue(SfxBoolItem(nSlot, bRet)); } break; case SvxSearchCmd::REPLACE_ALL: { SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() ); s_bExtra = false; sal_uLong nFound; { //Scope for SwWait-Object SwWait aWait( *GetDocShell(), true ); m_pWrtShell->StartAllAction(); // i#8288 "replace all" should not change cursor // position, so save current cursor m_pWrtShell->Push(); if (!s_pSrchItem->GetSelection()) { // if we don't want to search in the selection... m_pWrtShell->KillSelection(nullptr, false); if (SwDocPositions::Start == aOpts.eEnd) { m_pWrtShell->EndOfSection(); } else { m_pWrtShell->StartOfSection(); } } nFound = FUNC_Search( aOpts ); // create it just to overwrite it with stack cursor m_pWrtShell->CreateCursor(); // i#8288 restore the original cursor position m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); m_pWrtShell->EndAllAction(); } rReq.SetReturnValue(SfxBoolItem(nSlot, nFound != 0 && ULONG_MAX != nFound)); if( !nFound ) { #if HAVE_FEATURE_DESKTOP if( !bQuiet ) { m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr()); SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound); } #endif s_bFound = false; SwView::SetMoveType(nMoveType); return; } if( !bQuiet && ULONG_MAX != nFound) { OUString sText( SwResId( STR_NB_REPLACED ) ); sText = sText.replaceFirst("XX", OUString::number( nFound )); SvxSearchDialogWrapper::SetSearchLabel(sText); } } break; } uno::Reference< frame::XDispatchRecorder > xRecorder = GetViewFrame()->GetBindings().GetRecorder(); //prevent additional dialogs in recorded macros if ( xRecorder.is() ) rReq.AppendItem(SfxBoolItem(SID_SEARCH_QUIET, true)); rReq.Done(); m_eLastSearchCommand = s_pSrchItem->GetCommand(); SwView::SetMoveType(nMoveType); } break; case FID_SEARCH_SEARCHSET: case FID_SEARCH_REPLACESET: { static const WhichRangesContainer aNormalAttr(svl::Items< /* 0 */ RES_CHRATR_CASEMAP, RES_CHRATR_CASEMAP, /* 2 */ RES_CHRATR_COLOR, RES_CHRATR_POSTURE, /* 4 */ RES_CHRATR_SHADOWED, RES_CHRATR_WORDLINEMODE, /* 6 */ RES_CHRATR_BLINK, RES_CHRATR_BLINK, /* 8 */ RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND, /*10 */ RES_CHRATR_ROTATE, RES_CHRATR_ROTATE, /*12 */ RES_CHRATR_SCALEW, RES_CHRATR_RELIEF, /*14 */ RES_CHRATR_OVERLINE, RES_CHRATR_OVERLINE, /*16 */ RES_PARATR_LINESPACING, RES_PARATR_HYPHENZONE, /*18 */ RES_PARATR_REGISTER, RES_PARATR_REGISTER, /*20 */ RES_PARATR_VERTALIGN, RES_PARATR_VERTALIGN, /*22 */ RES_LR_SPACE, RES_UL_SPACE, /*24 */ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP >); SfxItemSet aSet(m_pWrtShell->GetAttrPool(), aNormalAttr); if( SW_MOD()->GetCTLOptions().IsCTLFontEnabled() ) { aSet.MergeRange(RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_WEIGHT); } if( SvtCJKOptions::IsAnyEnabled() ) { aSet.MergeRange(RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_WEIGHT); aSet.MergeRange(RES_CHRATR_EMPHASIS_MARK, RES_CHRATR_TWO_LINES); aSet.MergeRange(RES_PARATR_SCRIPTSPACE, RES_PARATR_FORBIDDEN_RULES); } TypedWhichId nWhich = SID_SEARCH_SEARCHSET; if ( FID_SEARCH_REPLACESET == nSlot ) { nWhich = SID_SEARCH_REPLACESET; if ( s_xReplaceList ) { s_xReplaceList->Get( aSet ); s_xReplaceList.reset(); } } else if ( s_xSearchList ) { s_xSearchList->Get( aSet ); s_xSearchList.reset(); } rReq.SetReturnValue( SvxSetItem( nWhich, aSet ) ); } break; default: SAL_WARN_IF( nSlot, "sw", "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)" ); return; } } bool SwView::SearchAndWrap(bool bApi) { SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() ); // Remember starting position of the search for wraparound // Start- / EndAction perhaps because existing selections of 'search all' m_pWrtShell->StartAllAction(); m_pWrtShell->Push(); // After a search all action we place the cursor at the beginning of // the document so that the single search selects the first matching // occurrence in the document instead of the second. if( m_eLastSearchCommand == SvxSearchCmd::FIND_ALL ) { if( SwDocPositions::Start == aOpts.eEnd ) m_pWrtShell->EndOfSection(); else m_pWrtShell->StartOfSection(); } // fdo#65014 : Ensure that the point of the cursor is at the extremity of the // selection closest to the end being searched to as to exclude the selected // region from the search. (This doesn't work in the case of multiple // selected regions as the cursor doesn't mark the selection in that case.) m_pWrtShell->GetCursor()->Normalize( s_pSrchItem->GetBackward() ); if (!m_pWrtShell->HasSelection() && (s_pSrchItem->HasStartPoint())) { // No selection -> but we have a start point (top left corner of the // current view), start searching from there, not from the current // cursor position. SwEditShell& rShell = GetWrtShell(); Point aPosition(s_pSrchItem->GetStartPointX(), s_pSrchItem->GetStartPointY()); rShell.SetCursor(aPosition); } // If you want to search in selected areas, they must not be unselected. if (!s_pSrchItem->GetSelection()) m_pWrtShell->KillSelection(nullptr, false); std::unique_ptr pWait(new SwWait( *GetDocShell(), true )); if( FUNC_Search( aOpts ) ) { s_bFound = true; if(m_pWrtShell->IsSelFrameMode()) { m_pWrtShell->UnSelectFrame(); m_pWrtShell->LeaveSelFrameMode(); } m_pWrtShell->Pop(); m_pWrtShell->EndAllAction(); return true; } pWait.reset(); // Search in the specialized areas when no search is present in selections. // When searching selections will already searched in these special areas. bool bHasSrchInOther = s_bExtra; if (!s_pSrchItem->GetSelection() && !s_bExtra ) { s_bExtra = true; if( FUNC_Search( aOpts ) ) { s_bFound = true; m_pWrtShell->Pop(); m_pWrtShell->EndAllAction(); return true; } s_bExtra = false; } else s_bExtra = !s_bExtra; // If starting position is at the end or beginning of the document. if (aOpts.bDontWrap) { m_pWrtShell->EndAllAction(); if( !bApi ) { #if HAVE_FEATURE_DESKTOP m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr()); SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound); #endif } s_bFound = false; m_pWrtShell->Pop(); return false; } m_pWrtShell->EndAllAction(); // Try again with WrapAround? m_pWrtShell->StartAllAction(); m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); pWait.reset(new SwWait( *GetDocShell(), true )); bool bSrchBkwrd = SwDocPositions::Start == aOpts.eEnd; aOpts.eEnd = bSrchBkwrd ? SwDocPositions::Start : SwDocPositions::End; aOpts.eStart = bSrchBkwrd ? SwDocPositions::End : SwDocPositions::Start; if (bHasSrchInOther) { m_pWrtShell->ClearMark(); // Select the start or the end of the entire document if (bSrchBkwrd) m_pWrtShell->SttEndDoc(false); else m_pWrtShell->SttEndDoc(true); } s_bFound = bool(FUNC_Search( aOpts )); // If WrapAround found no matches in the body text, search in the special // sections, too. if (!s_bFound && !s_pSrchItem->GetSelection() && !s_bExtra) { s_bExtra = true; if (FUNC_Search(aOpts)) s_bFound = true; else s_bExtra = false; } m_pWrtShell->EndAllAction(); pWait.reset(); #if HAVE_FEATURE_DESKTOP if (s_bFound) { if (!bSrchBkwrd) SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::End); else SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Start); } else if(!bApi) { m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr()); SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound); } #endif return s_bFound; } bool SwView::SearchAll() { SwWait aWait( *GetDocShell(), true ); m_pWrtShell->StartAllAction(); SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() ); if (!s_pSrchItem->GetSelection()) { // Cancel existing selections, if should not be sought in selected areas. m_pWrtShell->KillSelection(nullptr, false); if( SwDocPositions::Start == aOpts.eEnd ) m_pWrtShell->EndOfSection(); else m_pWrtShell->StartOfSection(); } s_bExtra = false; sal_uInt16 nFound = o3tl::narrowing(FUNC_Search( aOpts )); s_bFound = 0 != nFound; m_pWrtShell->EndAllAction(); return s_bFound; } void SwView::Replace() { SwWait aWait( *GetDocShell(), true ); m_pWrtShell->StartAllAction(); if( s_pSrchItem->GetPattern() ) // Templates? { SwRewriter aRewriter; aRewriter.AddRule(UndoArg1, s_pSrchItem->GetSearchString()); aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS)); aRewriter.AddRule(UndoArg3, s_pSrchItem->GetReplaceString()); m_pWrtShell->StartUndo(SwUndoId::UI_REPLACE_STYLE, &aRewriter); m_pWrtShell->SetTextFormatColl( m_pWrtShell->GetParaStyle( s_pSrchItem->GetReplaceString(), SwWrtShell::GETSTYLE_CREATESOME )); m_pWrtShell->EndUndo(); } else { if (GetPostItMgr()->HasActiveSidebarWin()) GetPostItMgr()->Replace(s_pSrchItem); bool bReqReplace = true; if(m_pWrtShell->HasSelection()) { /* check that the selection match the search string*/ //save state SwPosition aStartPos = * m_pWrtShell->GetCursor()->Start(); SwPosition aEndPos = * m_pWrtShell->GetCursor()->End(); bool bHasSelection = s_pSrchItem->GetSelection(); SvxSearchCmd nOldCmd = s_pSrchItem->GetCommand(); //set state for checking if current selection has a match s_pSrchItem->SetCommand( SvxSearchCmd::FIND ); s_pSrchItem->SetSelection(true); //check if it matches SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() ); if( ! FUNC_Search(aOpts) ) { //no matching therefore should not replace selection // => remove selection if(! s_pSrchItem->GetBackward() ) { (* m_pWrtShell->GetCursor()->Start()) = aStartPos; (* m_pWrtShell->GetCursor()->End()) = aEndPos; } else { (* m_pWrtShell->GetCursor()->Start()) = aEndPos; (* m_pWrtShell->GetCursor()->End()) = aStartPos; } bReqReplace = false; } //set back old search state s_pSrchItem->SetCommand( nOldCmd ); s_pSrchItem->SetSelection(bHasSelection); } /* * remove current selection * otherwise it is always replaced * no matter if the search string exists or not in the selection * Now the selection is removed and the next matching string is selected */ if( bReqReplace ) { bool bReplaced = m_pWrtShell->SwEditShell::Replace( s_pSrchItem->GetReplaceString(), s_pSrchItem->GetRegExp()); if( bReplaced && s_xReplaceList && s_xReplaceList->Count() && m_pWrtShell->HasSelection() ) { SfxItemSet aReplSet( m_pWrtShell->GetAttrPool(), aTextFormatCollSetRange ); if( s_xReplaceList->Get( aReplSet ).Count() ) { ::SfxToSwPageDescAttr( *m_pWrtShell, aReplSet ); m_pWrtShell->SwEditShell::SetAttrSet( aReplSet ); } } } } m_pWrtShell->EndAllAction(); } SwSearchOptions::SwSearchOptions( SwWrtShell const * pSh, bool bBackward ) : eStart(SwDocPositions::Curr) { if( bBackward ) { eEnd = SwDocPositions::Start; bDontWrap = pSh->IsEndOfDoc(); } else { eEnd = SwDocPositions::End; bDontWrap = pSh->IsStartOfDoc(); } } sal_uLong SwView::FUNC_Search( const SwSearchOptions& rOptions ) { #if HAVE_FEATURE_DESKTOP SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty); #endif bool bDoReplace = s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE || s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL; FindRanges eRanges = s_pSrchItem->GetSelection() ? FindRanges::InSel : s_bExtra ? FindRanges::InOther : FindRanges::InBody; if (s_pSrchItem->GetCommand() == SvxSearchCmd::FIND_ALL || s_pSrchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL) eRanges |= FindRanges::InSelAll; m_pWrtShell->SttSelect(); static const WhichRangesContainer aSearchAttrRange(svl::Items< RES_CHRATR_BEGIN, RES_CHRATR_END-1, RES_PARATR_BEGIN, RES_PARATR_END-1, RES_FRMATR_BEGIN, RES_FRMATR_END-1, SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP >); SfxItemSet aSrchSet( m_pWrtShell->GetAttrPool(), aSearchAttrRange); if( s_xSearchList && s_xSearchList->Count() ) { s_xSearchList->Get( aSrchSet ); // -- Page break with page template ::SfxToSwPageDescAttr( *m_pWrtShell, aSrchSet ); } std::optional xReplSet; if( bDoReplace && s_xReplaceList && s_xReplaceList->Count() ) { xReplSet.emplace( m_pWrtShell->GetAttrPool(), aSearchAttrRange ); s_xReplaceList->Get( *xReplSet ); // -- Page break with page template ::SfxToSwPageDescAttr( *m_pWrtShell, *xReplSet ); if( !xReplSet->Count() ) // too bad, we don't know xReplSet.reset(); // the attributes } // build SearchOptions to be used i18nutil::SearchOptions2 aSearchOpt( s_pSrchItem->GetSearchOptions() ); aSearchOpt.Locale = GetAppLanguageTag().getLocale(); if( !bDoReplace ) aSearchOpt.replaceString.clear(); sal_uLong nFound; if( aSrchSet.Count() || ( xReplSet && xReplSet->Count() )) { nFound = m_pWrtShell->SearchAttr( aSrchSet, !s_pSrchItem->GetPattern(), rOptions.eStart, rOptions.eEnd, eRanges, !s_pSrchItem->GetSearchString().isEmpty() ? &aSearchOpt : nullptr, xReplSet ? &*xReplSet : nullptr ); } else if( s_pSrchItem->GetPattern() ) { // Searching (and replacing) templates const OUString& sRplStr( s_pSrchItem->GetReplaceString() ); nFound = m_pWrtShell->SearchTempl( s_pSrchItem->GetSearchString(), rOptions.eStart, rOptions.eEnd, eRanges, bDoReplace ? &sRplStr : nullptr ); } else { // Normal search nFound = m_pWrtShell->SearchPattern(aSearchOpt, s_pSrchItem->GetNotes(), rOptions.eStart, rOptions.eEnd, eRanges, bDoReplace ); } m_pWrtShell->EndSelect(); return nFound; } SvxSearchDialog* SwView::GetSearchDialog() { #if HAVE_FEATURE_DESKTOP const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId(); SfxViewFrame* pFrame = SfxViewFrame::Current(); if (!pFrame) return nullptr; SvxSearchDialogWrapper *pWrp = static_cast(pFrame->GetChildWindow(nId)); if (!pWrp) return nullptr; return pWrp->getDialog(); #else return nullptr; #endif } void SwView::StateSearch(SfxItemSet &rSet) { SfxWhichIter aIter(rSet); sal_uInt16 nWhich = aIter.FirstWhich(); while(nWhich) { switch(nWhich) { case SID_SEARCH_OPTIONS: { SearchOptionFlags nOpt = SearchOptionFlags::ALL; if( GetDocShell()->IsReadOnly() ) nOpt &= ~SearchOptionFlags( SearchOptionFlags::REPLACE | SearchOptionFlags::REPLACE_ALL ); rSet.Put( SfxUInt16Item( SID_SEARCH_OPTIONS, static_cast(nOpt) )); } break; case SID_SEARCH_ITEM: { if ( !s_pSrchItem ) { s_pSrchItem = new SvxSearchItem( SID_SEARCH_ITEM ); s_pSrchItem->SetFamily(SfxStyleFamily::Para); s_pSrchItem->SetSearchString( m_pWrtShell->GetSelText() ); } if( s_bJustOpened && m_pWrtShell->IsSelection() ) { OUString aText; if( 1 == m_pWrtShell->GetCursorCnt() && !( aText = m_pWrtShell->SwCursorShell::GetSelText() ).isEmpty() ) { s_pSrchItem->SetSearchString( aText ); s_pSrchItem->SetSelection( false ); } else s_pSrchItem->SetSelection( true ); } s_bJustOpened = false; rSet.Put( *s_pSrchItem ); } break; } nWhich = aIter.NextWhich(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */