diff options
Diffstat (limited to '')
-rw-r--r-- | sw/source/uibase/uiview/viewsrch.cxx | 885 |
1 files changed, 885 insertions, 0 deletions
diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx new file mode 100644 index 000000000..118116423 --- /dev/null +++ b/sw/source/uibase/uiview/viewsrch.cxx @@ -0,0 +1,885 @@ +/* -*- 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 <string> + +#include <memory> +#include <boost/property_tree/json_parser.hpp> + +#include <hintids.hxx> + +#include <sal/log.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <svx/pageitem.hxx> +#include <svl/whiter.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/eitem.hxx> +#include <svl/srchitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <sfx2/lokhelper.hxx> +#include <svx/srchdlg.hxx> +#include <swmodule.hxx> +#include <swwait.hxx> +#include <workctrl.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <swundo.hxx> +#include <uitool.hxx> +#include <cmdid.h> +#include <docsh.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <comphelper/lok.hxx> +#include <comphelper/string.hxx> + +#include <strings.hrc> +#include <SwRewriter.hxx> + +#include <PostItMgr.hxx> + +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<OString>& 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<OString> aMatches; + for (SwPaM& rPaM : pPaM->GetRingContainer()) + { + if (SwShellCursor* pShellCursor = dynamic_cast<SwShellCursor*>(&rPaM)) + { + std::vector<OString> aSelectionRectangles; + pShellCursor->SwSelPaintRects::Show(&aSelectionRectangles); + std::vector<OString> 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<const SfxBoolItem*>( 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<OUString> 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<SvxSetItem> 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<SwWait> 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<sal_uInt16>(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<SfxItemSet> 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<SvxSearchDialogWrapper*>(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<sal_uInt16>(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: */ |