Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx
Warning:line 151, column 23
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name viewsrch.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx
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
57using namespace com::sun::star;
58using namespace ::com::sun::star::i18n;
59using namespace ::com::sun::star::lang;
60using namespace ::com::sun::star::util;
61
62//Search Parameter
63
64struct SwSearchOptions
65{
66 SwDocPositions eStart, eEnd;
67 bool bDontWrap;
68
69 SwSearchOptions( SwWrtShell const * pSh, bool bBackward );
70};
71
72/// Adds rMatches using rKey as a key to the rTree tree.
73static 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
88/// Emits LOK callbacks (count, selection) for search results.
89static 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
126void SwView::ExecSearch(SfxRequest& rReq)
127{
128 const SfxItemSet* pArgs = rReq.GetArgs();
1
'pArgs' initialized here
129 const SfxPoolItem* pItem = nullptr;
130 bool bQuiet = false;
131 if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SEARCH_QUIET(5000 + 1684), false, &pItem))
2
Assuming 'pArgs' is null
132 bQuiet = static_cast<const SfxBoolItem*>( pItem)->GetValue();
133
134 sal_uInt16 nSlot = rReq.GetSlot();
135 if (nSlot == FN_REPEAT_SEARCH((20000 + 100) + 50) && !s_pSrchItem)
3
Assuming the condition is false
136 {
137 if(bQuiet)
138 {
139 rReq.SetReturnValue(SfxBoolItem(nSlot, false));
140 nSlot = 0;
141 }
142 }
143 if( m_pWrtShell->IsBlockMode() )
4
Assuming the condition is false
5
Taking false branch
144 m_pWrtShell->LeaveBlockMode();
145 switch (nSlot)
6
Control jumps to 'case 10291:' at line 148
146 {
147 // for now do nothing
148 case SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291):
149 {
150 delete s_pSrchItem;
151 s_pSrchItem = pArgs->Get(SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291)).Clone();
7
Called C++ object pointer is null
152 }
153 break;
154
155 case FID_SEARCH_ON((10000 + 500) + 0):
156 s_bJustOpened = true;
157 GetViewFrame()->GetBindings().Invalidate(SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291));
158 break;
159
160 case FID_SEARCH_OFF((10000 + 500) + 1):
161 if(pArgs)
162 {
163 // Unregister dialog
164 delete s_pSrchItem;
165 s_pSrchItem = pArgs->Get(SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291)).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((20000 + 100) + 50):
186 case FID_SEARCH_NOW((10000 + 500) + 2):
187 {
188 sal_uInt16 nMoveType = SwView::GetMoveType();
189 {
190 if(FID_SEARCH_NOW((10000 + 500) + 2) == nSlot && !rReq.IsAPI())
191 SwView::SetMoveType(NID_SRCH_REP20014);
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((20000 + 100) + 50))
210 {
211 OSL_ENSURE(s_pSrchItem, "SearchItem missing")do { if (true && (!(s_pSrchItem))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx"
":" "211" ": "), "%s", "SearchItem missing"); } } while (false
)
;
212 if( !s_pSrchItem )
213 s_pSrchItem = new SvxSearchItem(SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291));
214 }
215 else
216 {
217 // Get SearchItem from request
218 OSL_ENSURE(pArgs, "Args missing")do { if (true && (!(pArgs))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx"
":" "218" ": "), "%s", "Args missing"); } } while (false)
;
219 if ( pArgs )
220 {
221 delete s_pSrchItem;
222 s_pSrchItem = pArgs->Get(SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291)).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());
234 if (comphelper::LibreOfficeKit::isActive())
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_DESKTOP1
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 }
263 else if (comphelper::LibreOfficeKit::isActive())
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(9223372036854775807L *2UL+1UL) != nFound));
352 if( !nFound )
353 {
354#if HAVE_FEATURE_DESKTOP1
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(9223372036854775807L *2UL+1UL) != nFound)
367 {
368 OUString sText( SwResId( STR_NB_REPLACEDreinterpret_cast<char const *>("STR_NB_REPLACED" "\004"
u8"Search key replaced XX times.")
) );
369 sText = sText.replaceFirst("XX", OUString::number( nFound ));
370 SvxSearchDialogWrapper::SetSearchLabel(sText);
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(5000 + 1684), true));
381
382 rReq.Done();
383 m_eLastSearchCommand = s_pSrchItem->GetCommand();
384 SwView::SetMoveType(nMoveType);
385 }
386 break;
387 case FID_SEARCH_SEARCHSET((10000 + 500) + 4):
388 case FID_SEARCH_REPLACESET((10000 + 500) + 5):
389 {
390 static const sal_uInt16 aNormalAttr[] =
391 {
392/* 0 */ RES_CHRATR_CASEMAP, RES_CHRATR_CASEMAP,
393/* 2 */ RES_CHRATR_COLOR, RES_CHRATR_POSTURE,
394/* 4 */ RES_CHRATR_SHADOWED, RES_CHRATR_WORDLINEMODE,
395/* 6 */ RES_CHRATR_BLINK, RES_CHRATR_BLINK,
396/* 8 */ RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND,
397/*10 */ RES_CHRATR_ROTATE, RES_CHRATR_ROTATE,
398/*12 */ RES_CHRATR_SCALEW, RES_CHRATR_RELIEF,
399/*14 */ RES_CHRATR_OVERLINE, RES_CHRATR_OVERLINE,
400/*16 */ RES_PARATR_LINESPACING, RES_PARATR_HYPHENZONE,
401/*18 */ RES_PARATR_REGISTER, RES_PARATR_REGISTER,
402/*20 */ RES_PARATR_VERTALIGN, RES_PARATR_VERTALIGN,
403/*22 */ RES_LR_SPACE, RES_UL_SPACE,
404/*24 */ SID_ATTR_PARA_MODEL( 10000 + 65 ), SID_ATTR_PARA_KEEP( 10000 + 66 ),
405/*26 */ 0
406 };
407
408 SfxItemSet aSet(m_pWrtShell->GetAttrPool(), aNormalAttr);
409
410 if( SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->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);
418 aSet.MergeRange(RES_CHRATR_EMPHASIS_MARK, RES_CHRATR_TWO_LINES);
419 aSet.MergeRange(RES_PARATR_SCRIPTSPACE, RES_PARATR_FORBIDDEN_RULES);
420 }
421
422 sal_uInt16 nWhich = SID_SEARCH_SEARCHSET( 10000 + 292 );
423
424 if ( FID_SEARCH_REPLACESET((10000 + 500) + 5) == nSlot )
425 {
426 nWhich = SID_SEARCH_REPLACESET( 10000 + 293 );
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)" )do { if (true && (nSlot)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "nSlot: " <<
nSlot << " wrong Dispatcher (viewsrch.cxx)") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw"), ("/home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx"
":" "443" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw"), (
"/home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx"
":" "443" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw"
), ("/home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx"
":" "443" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "nSlot: " << nSlot << " wrong Dispatcher (viewsrch.cxx)"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw"), (
"/home/maarten/src/libreoffice/core/sw/source/uibase/uiview/viewsrch.cxx"
":" "443" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
444 return;
445 }
446}
447
448bool 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_DESKTOP1
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_DESKTOP1
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
590bool SwView::SearchAll()
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
615void SwView::Replace()
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_YIELDSreinterpret_cast<char const *>("STR_YIELDS" "\004" u8"→"
)
));
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(),
632 SwWrtShell::GETSTYLE_CREATESOME ));
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(),
696 aTextFormatCollSetRange );
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
709SwSearchOptions::SwSearchOptions( SwWrtShell const * pSh, bool bBackward )
710 : eStart(SwDocPositions::Curr)
711{
712 if( bBackward )
713 {
714 eEnd = SwDocPositions::Start;
715 bDontWrap = pSh->IsEndOfDoc();
716 }
717 else
718 {
719 eEnd = SwDocPositions::End;
720 bDontWrap = pSh->IsStartOfDoc();
721 }
722}
723
724sal_uLong SwView::FUNC_Search( const SwSearchOptions& rOptions )
725{
726#if HAVE_FEATURE_DESKTOP1
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()
733 ? FindRanges::InSel
734 : s_bExtra
735 ? FindRanges::InOther : FindRanges::InBody;
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[] = {
743 RES_FRMATR_BEGIN, RES_FRMATR_END-1,
744 RES_CHRATR_BEGIN, RES_CHRATR_END-1,
745 RES_PARATR_BEGIN, RES_PARATR_END-1,
746 SID_ATTR_PARA_MODEL( 10000 + 65 ), SID_ATTR_PARA_KEEP( 10000 + 66 ),
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
774 i18nutil::SearchOptions2 aSearchOpt( s_pSrchItem->GetSearchOptions() );
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,
784 !s_pSrchItem->GetPattern(),
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
814SvxSearchDialog* SwView::GetSearchDialog()
815{
816#if HAVE_FEATURE_DESKTOP1
817 const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId();
818 SvxSearchDialogWrapper *pWrp = static_cast<SvxSearchDialogWrapper*>( SfxViewFrame::Current()->GetChildWindow(nId) );
819 auto pSrchDlg = pWrp ? pWrp->getDialog() : nullptr;
820 return pSrchDlg;
821#else
822 return nullptr;
823#endif
824}
825
826void SwView::StateSearch(SfxItemSet &rSet)
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(10000 + 281):
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(10000 + 281), static_cast<sal_uInt16>(nOpt) ));
842 }
843 break;
844 case SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291):
845 {
846 if ( !s_pSrchItem )
847 {
848 s_pSrchItem = new SvxSearchItem( SID_SEARCH_ITEMTypedWhichId<SvxSearchItem>(10000 + 291) );
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: */