Bug Summary

File:home/maarten/src/libreoffice/core/sw/inc/crsrsh.hxx
Warning:line 881, column 29
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 viscrs.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/core/crsr/viscrs.cxx

/home/maarten/src/libreoffice/core/sw/source/core/crsr/viscrs.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 <config_features.h>
21
22#include <vcl/weld.hxx>
23#include <vcl/svapp.hxx>
24#include <vcl/settings.hxx>
25#include <viewopt.hxx>
26#include <frmtool.hxx>
27#include <viscrs.hxx>
28#include <crsrsh.hxx>
29#include <doc.hxx>
30#include <swtable.hxx>
31#include <viewimp.hxx>
32#include <dview.hxx>
33#include <rootfrm.hxx>
34#include <txtfrm.hxx>
35#include <ndtxt.hxx>
36#include <txtfld.hxx>
37#include <scriptinfo.hxx>
38#include <view.hxx>
39#include <IDocumentLayoutAccess.hxx>
40
41#include <svx/sdr/overlay/overlaymanager.hxx>
42#include <svx/sdrpaintwindow.hxx>
43#include <svx/srchdlg.hxx>
44#include <svx/sdr/overlay/overlayselection.hxx>
45#include "overlayrangesoutline.hxx"
46
47#include <memory>
48
49#include <LibreOfficeKit/LibreOfficeKitEnums.h>
50#include <comphelper/lok.hxx>
51#include <sfx2/lokhelper.hxx>
52#include <boost/property_tree/json_parser.hpp>
53#include <comphelper/string.hxx>
54#include <paintfrm.hxx>
55#include <PostItMgr.hxx>
56#include <SwGrammarMarkUp.hxx>
57#include <docsh.hxx>
58
59#include <cellfrm.hxx>
60#include <wrtsh.hxx>
61
62// Here static members are defined. They will get changed on alteration of the
63// MapMode. This is done so that on ShowCursor the same size does not have to be
64// expensively determined again and again.
65
66long SwSelPaintRects::s_nPixPtX = 0;
67long SwSelPaintRects::s_nPixPtY = 0;
68MapMode* SwSelPaintRects::s_pMapMode = nullptr;
69
70// Starting from here: classes / methods for the non-text-cursor
71SwVisibleCursor::SwVisibleCursor( const SwCursorShell * pCShell )
72 : m_pCursorShell( pCShell )
73 , m_nPageLastTime(0)
74{
75 pCShell->GetWin()->SetCursor( &m_aTextCursor );
76 m_bIsVisible = m_aTextCursor.IsVisible();
77 m_bIsDragCursor = false;
78 m_aTextCursor.SetWidth( 0 );
79}
80
81SwVisibleCursor::~SwVisibleCursor()
82{
83 if( m_bIsVisible && m_aTextCursor.IsVisible() )
84 m_aTextCursor.Hide();
85
86 m_pCursorShell->GetWin()->SetCursor( nullptr );
87}
88
89void SwVisibleCursor::Show()
90{
91 if( !m_bIsVisible )
1
Assuming field 'm_bIsVisible' is false
2
Taking true branch
92 {
93 m_bIsVisible = true;
94
95 // display at all?
96 if( m_pCursorShell->VisArea().IsOver( m_pCursorShell->m_aCharRect ) || comphelper::LibreOfficeKit::isActive() )
3
Assuming the condition is true
97 SetPosAndShow(nullptr);
4
Calling 'SwVisibleCursor::SetPosAndShow'
98 }
99}
100
101void SwVisibleCursor::Hide()
102{
103 if( m_bIsVisible )
104 {
105 m_bIsVisible = false;
106
107 if( m_aTextCursor.IsVisible() ) // Shouldn't the flags be in effect?
108 m_aTextCursor.Hide();
109 }
110}
111
112namespace
113{
114
115// Build JSON message to be sent to Online
116OString buildHyperlinkJSON(const OUString& sText, const OUString& sLink)
117{
118 boost::property_tree::ptree aTree;
119 aTree.put("text", sText);
120 aTree.put("link", sLink);
121 std::stringstream aStream;
122 boost::property_tree::write_json(aStream, aTree, false);
123
124 return OString(aStream.str().c_str()).trim();
125}
126
127}
128
129void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell)
130{
131 SwRect aRect;
132 long nTmpY = m_pCursorShell->m_aCursorHeight.getY();
133 if( 0 > nTmpY )
5
Assuming 'nTmpY' is >= 0
6
Taking false branch
134 {
135 nTmpY = -nTmpY;
136 m_aTextCursor.SetOrientation( 900 );
137 aRect = SwRect( m_pCursorShell->m_aCharRect.Pos(),
138 Size( m_pCursorShell->m_aCharRect.Height(), nTmpY ) );
139 aRect.Pos().setX(aRect.Pos().getX() + m_pCursorShell->m_aCursorHeight.getX());
140 if( m_pCursorShell->IsOverwriteCursor() )
141 aRect.Pos().setY(aRect.Pos().getY() + aRect.Width());
142 }
143 else
144 {
145 m_aTextCursor.SetOrientation();
146 aRect = SwRect( m_pCursorShell->m_aCharRect.Pos(),
147 Size( m_pCursorShell->m_aCharRect.Width(), nTmpY ) );
148 aRect.Pos().setY(aRect.Pos().getY() + m_pCursorShell->m_aCursorHeight.getX());
149 }
150
151 // check if cursor should show the current cursor bidi level
152 m_aTextCursor.SetDirection();
153 const SwCursor* pTmpCursor = m_pCursorShell->GetCursor_();
154
155 if ( pTmpCursor && !m_pCursorShell->IsOverwriteCursor() )
7
Assuming 'pTmpCursor' is null
156 {
157 SwNode& rNode = pTmpCursor->GetPoint()->nNode.GetNode();
158 if( rNode.IsTextNode() )
159 {
160 const SwTextNode& rTNd = *rNode.GetTextNode();
161 const SwFrame* pFrame = rTNd.getLayoutFrame(m_pCursorShell->GetLayout(), nullptr, nullptr);
162 if ( pFrame )
163 {
164 const SwScriptInfo* pSI = static_cast<const SwTextFrame*>(pFrame)->GetScriptInfo();
165 // cursor level has to be shown
166 if ( pSI && pSI->CountDirChg() > 1 )
167 {
168 m_aTextCursor.SetDirection(
169 ( pTmpCursor->GetCursorBidiLevel() % 2 ) ?
170 CursorDirection::RTL :
171 CursorDirection::LTR );
172 }
173 if ( pFrame->IsRightToLeft() )
174 {
175 const OutputDevice *pOut = m_pCursorShell->GetOut();
176 if ( pOut )
177 {
178 long nSize = pOut->GetSettings().GetStyleSettings().GetCursorSize();
179 Size aSize( nSize, nSize );
180 aSize = pOut->PixelToLogic( aSize );
181 aRect.Left( aRect.Left() - aSize.Width() );
182 }
183 }
184 }
185 }
186 }
187
188 if( aRect.Height())
8
Assuming the condition is false
9
Taking false branch
189 {
190 ::SwCalcPixStatics( m_pCursorShell->GetOut() );
191
192 // Disable pixel alignment when tiled rendering, so that twip values of
193 // the cursor don't depend on statics.
194 if (!comphelper::LibreOfficeKit::isActive())
195 ::SwAlignRect( aRect, static_cast<SwViewShell const *>(m_pCursorShell), m_pCursorShell->GetOut() );
196 }
197 if( !m_pCursorShell->IsOverwriteCursor() || m_bIsDragCursor ||
10
Assuming the condition is false
11
Assuming field 'm_bIsDragCursor' is false
198 m_pCursorShell->IsSelection() )
12
Calling 'SwCursorShell::IsSelection'
199 aRect.Width( 0 );
200
201 m_aTextCursor.SetSize( aRect.SSize() );
202
203 m_aTextCursor.SetPos( aRect.Pos() );
204
205 bool bPostItActive = false;
206 SwView* pView = dynamic_cast<SwView*>(m_pCursorShell->GetSfxViewShell());
207 if (pView)
208 {
209 if (SwPostItMgr* pPostItMgr = pView->GetPostItMgr())
210 bPostItActive = pPostItMgr->GetActiveSidebarWin() != nullptr;
211 }
212
213 if (comphelper::LibreOfficeKit::isActive() && !bPostItActive)
214 {
215 // notify about page number change (if that happened)
216 sal_uInt16 nPage, nVirtPage;
217 // bCalcFrame=false is important to avoid calculating the layout when
218 // we're in the middle of doing that already.
219 const_cast<SwCursorShell*>(m_pCursorShell)->GetPageNum(nPage, nVirtPage, /*bAtCursorPos=*/true, /*bCalcFrame=*/false);
220 if (nPage != m_nPageLastTime)
221 {
222 m_nPageLastTime = nPage;
223 OString aPayload = OString::number(nPage - 1);
224 m_pCursorShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SET_PART, aPayload.getStr());
225 }
226
227 // notify about the cursor position & size
228 tools::Rectangle aSVRect(aRect.Pos().getX(), aRect.Pos().getY(), aRect.Pos().getX() + aRect.SSize().Width(), aRect.Pos().getY() + aRect.SSize().Height());
229 OString sRect = aSVRect.toString();
230
231 // is cursor at a misspelled word ?
232 bool bIsWrong = false;
233 if (pView && pView->GetWrtShellPtr())
234 {
235 const SwViewOption* pVOpt = pView->GetWrtShell().GetViewOptions();
236 if(pVOpt && pVOpt->IsOnlineSpell())
237 {
238 SwPaM* pCursor = m_pCursorShell->GetCursor();
239 SwPosition aPos(*pCursor->GetPoint());
240 Point aPt = aRect.Pos();
241 SwCursorMoveState eTmpState(CursorMoveState::SetOnlyText);
242 SwTextNode *pNode = nullptr;
243 if (m_pCursorShell->GetLayout()->GetModelPositionForViewPoint(&aPos, aPt, &eTmpState))
244 pNode = aPos.nNode.GetNode().GetTextNode();
245 if (pNode && !pNode->IsInProtectSect())
246 {
247 sal_Int32 nBegin = aPos.nContent.GetIndex();
248 sal_Int32 nLen = 1;
249
250 SwWrongList *pWrong = nullptr;
251 pWrong = pNode->GetWrong();
252 if (!pWrong)
253 pWrong = pNode->GetGrammarCheck();
254 if (pWrong)
255 bIsWrong = pWrong->InWrongWord(nBegin,nLen) && !pNode->IsSymbolAt(nBegin);
256 }
257 }
258 }
259
260 OString sHyperlink;
261 SwContentAtPos aContentAtPos(IsAttrAtPos::InetAttr);
262 bool bIsSelection = m_pCursorShell->IsSelection();
263
264 if (const_cast<SwCursorShell*>(m_pCursorShell)->GetContentAtPos(aRect.Pos(), aContentAtPos))
265 {
266 const SwFormatINetFormat* pItem = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr);
267 sHyperlink = buildHyperlinkJSON(aContentAtPos.sStr, pItem->GetValue());
268 }
269 else if (bIsSelection)
270 {
271 SwWrtShell* pShell = m_pCursorShell->GetDoc()->GetDocShell()->GetWrtShell();
272
273 if (pShell)
274 {
275 SfxItemSet aSet(m_pCursorShell->GetSfxViewShell()->GetPool(),
276 svl::Items<RES_TXTATR_INETFMT,
277 RES_TXTATR_INETFMT>{});
278 pShell->GetCurAttr(aSet);
279 if(SfxItemState::SET <= aSet.GetItemState( RES_TXTATR_INETFMT ))
280 {
281 sHyperlink = buildHyperlinkJSON(m_pCursorShell->GetSelText(),
282 aSet.GetItem(RES_TXTATR_INETFMT)->GetValue());
283 }
284 }
285 }
286
287 if (pViewShell)
288 {
289 if (pViewShell == m_pCursorShell->GetSfxViewShell())
290 {
291 SfxLokHelper::notifyVisCursorInvalidation(pViewShell, sRect, bIsWrong, sHyperlink);
292 }
293 else
294 SfxLokHelper::notifyOtherView(m_pCursorShell->GetSfxViewShell(), pViewShell, LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect);
295 }
296 else
297 {
298 SfxLokHelper::notifyVisCursorInvalidation(m_pCursorShell->GetSfxViewShell(), sRect, bIsWrong, sHyperlink);
299 SfxLokHelper::notifyOtherViews(m_pCursorShell->GetSfxViewShell(), LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect);
300 }
301 }
302
303 if ( m_pCursorShell->IsCursorReadonly() && !m_pCursorShell->GetViewOptions()->IsSelectionInReadonly() )
304 return;
305
306 if ( m_pCursorShell->GetDrawView() )
307 const_cast<SwDrawView*>(static_cast<const SwDrawView*>(m_pCursorShell->GetDrawView()))->SetAnimationEnabled(
308 !m_pCursorShell->IsSelection() );
309
310 sal_uInt16 nStyle = m_bIsDragCursor ? CURSOR_SHADOW(sal_uInt16(0x0001)) : 0;
311 if( nStyle != m_aTextCursor.GetStyle() )
312 {
313 m_aTextCursor.SetStyle( nStyle );
314 m_aTextCursor.SetWindow( m_bIsDragCursor ? m_pCursorShell->GetWin() : nullptr );
315 }
316
317 m_aTextCursor.Show();
318}
319
320const vcl::Cursor& SwVisibleCursor::GetTextCursor() const
321{
322 return m_aTextCursor;
323}
324
325SwSelPaintRects::SwSelPaintRects( const SwCursorShell& rCSh )
326 : SwRects()
327 , m_pCursorShell( &rCSh )
328#if HAVE_FEATURE_DESKTOP1
329 , m_bShowTextInputFieldOverlay(true)
330#endif
331{
332}
333
334SwSelPaintRects::~SwSelPaintRects()
335{
336 Hide();
337}
338
339void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap)
340{
341 SwRects::swap(rSwap);
342
343#if HAVE_FEATURE_DESKTOP1
344 // #i75172# also swap m_pCursorOverlay
345 std::swap(m_pCursorOverlay, rSwap.m_pCursorOverlay);
346 std::swap(m_bShowTextInputFieldOverlay, rSwap.m_bShowTextInputFieldOverlay);
347 std::swap(m_pTextInputFieldOverlay, rSwap.m_pTextInputFieldOverlay);
348#endif
349}
350
351void SwSelPaintRects::Hide()
352{
353#if HAVE_FEATURE_DESKTOP1
354 m_pCursorOverlay.reset();
355 m_pTextInputFieldOverlay.reset();
356#endif
357
358 SwRects::clear();
359}
360
361/**
362 * Return a layout rectangle (typically with minimal width) that represents a
363 * cursor at rPosition.
364 *
365 * @param rPoint layout position as a hint about what layout frame contains
366 * rPosition (there might be multiple frames for a single node)
367 * @param rPosition the doc model position (paragraph / character index)
368 */
369static SwRect lcl_getLayoutRect(const Point& rPoint, const SwPosition& rPosition)
370{
371 const SwContentNode* pNode = rPosition.nNode.GetNode().GetContentNode();
372 std::pair<Point, bool> const tmp(rPoint, true);
373 const SwContentFrame* pFrame = pNode->getLayoutFrame(
374 pNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
375 &rPosition, &tmp);
376 SwRect aRect;
377 pFrame->GetCharRect(aRect, rPosition);
378 return aRect;
379}
380
381void SwShellCursor::FillStartEnd(SwRect& rStart, SwRect& rEnd) const
382{
383 const SwShellCursor* pCursor = GetShell()->getShellCursor(false);
384 rStart = lcl_getLayoutRect(pCursor->GetSttPos(), *pCursor->Start());
385 rEnd = lcl_getLayoutRect(pCursor->GetEndPos(), *pCursor->End());
386}
387
388void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles)
389{
390 SdrView *const pView = const_cast<SdrView*>(m_pCursorShell->GetDrawView());
391
392 if(!(pView && pView->PaintWindowCount()))
393 return;
394
395 // reset rects
396 SwRects::clear();
397 FillRects();
398
399#if HAVE_FEATURE_DESKTOP1
400 // get new rects
401 std::vector< basegfx::B2DRange > aNewRanges;
402 aNewRanges.reserve(size());
403 for(size_type a = 0; a < size(); ++a)
404 {
405 const SwRect aNextRect((*this)[a]);
406 const tools::Rectangle aPntRect(aNextRect.SVRect());
407
408 aNewRanges.emplace_back(
409 aPntRect.Left(), aPntRect.Top(),
410 aPntRect.Right() + 1, aPntRect.Bottom() + 1);
411 }
412
413 if (m_pCursorOverlay)
414 {
415 if(!aNewRanges.empty())
416 {
417 static_cast<sdr::overlay::OverlaySelection*>(m_pCursorOverlay.get())->setRanges(aNewRanges);
418 }
419 else
420 {
421 m_pCursorOverlay.reset();
422 }
423 }
424 else if(!empty())
425 {
426 SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
427 const rtl::Reference< sdr::overlay::OverlayManager >& xTargetOverlay = pCandidate->GetOverlayManager();
428
429 if (xTargetOverlay.is())
430 {
431 // get the system's highlight color
432 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
433 const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
434
435 // create correct selection
436 m_pCursorOverlay.reset( new sdr::overlay::OverlaySelection(
437 sdr::overlay::OverlayType::Transparent,
438 aHighlight,
439 aNewRanges,
440 true) );
441
442 xTargetOverlay->add(*m_pCursorOverlay);
443 }
444 }
445
446 HighlightInputField();
447#endif
448
449 // Tiled editing does not expose the draw and writer cursor, it just
450 // talks about "the" cursor at the moment. As long as that's true,
451 // don't say anything about the Writer cursor till a draw object is
452 // being edited.
453 if (!comphelper::LibreOfficeKit::isActive() || pView->GetTextEditObject())
454 return;
455
456 // If pSelectionRectangles is set, we're just collecting the text selections -> don't emit start/end.
457 if (!empty() && !pSelectionRectangles)
458 {
459 // The selection may be a complex polygon, emit the logical
460 // start/end cursor rectangle of the selection as separate
461 // events, if there is a real selection.
462 // This can be used to easily show selection handles on the
463 // client side.
464 SwRect aStartRect;
465 SwRect aEndRect;
466 FillStartEnd(aStartRect, aEndRect);
467
468 if (aStartRect.HasArea())
469 {
470 OString sRect = aStartRect.SVRect().toString();
471 GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, sRect.getStr());
472 }
473 if (aEndRect.HasArea())
474 {
475 OString sRect = aEndRect.SVRect().toString();
476 GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, sRect.getStr());
477 }
478 }
479
480 std::vector<OString> aRect;
481 aRect.reserve(size());
482 for (size_type i = 0; i < size(); ++i)
483 {
484 const SwRect& rRect = (*this)[i];
485 aRect.push_back(rRect.SVRect().toString());
486 }
487 OString sRect = comphelper::string::join("; ", aRect);
488 if (!pSelectionRectangles)
489 {
490 GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr());
491 SfxLokHelper::notifyOtherViews(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRect);
492 }
493 else
494 pSelectionRectangles->push_back(sRect);
495}
496
497void SwSelPaintRects::HighlightInputField()
498{
499 std::vector< basegfx::B2DRange > aInputFieldRanges;
500
501 if (m_bShowTextInputFieldOverlay)
502 {
503 SwTextInputField* pCurTextInputFieldAtCursor =
504 dynamic_cast<SwTextInputField*>(SwCursorShell::GetTextFieldAtPos( GetShell()->GetCursor()->Start(), false ));
505 if ( pCurTextInputFieldAtCursor != nullptr )
506 {
507 SwTextNode* pTextNode = pCurTextInputFieldAtCursor->GetpTextNode();
508 std::unique_ptr<SwShellCursor> pCursorForInputTextField(
509 new SwShellCursor( *GetShell(), SwPosition( *pTextNode, pCurTextInputFieldAtCursor->GetStart() ) ) );
510 pCursorForInputTextField->SetMark();
511 pCursorForInputTextField->GetMark()->nNode = *pTextNode;
512 pCursorForInputTextField->GetMark()->nContent.Assign( pTextNode, *(pCurTextInputFieldAtCursor->End()) );
513
514 pCursorForInputTextField->FillRects();
515 SwRects* pRects = static_cast<SwRects*>(pCursorForInputTextField.get());
516 for (const SwRect & rNextRect : *pRects)
517 {
518 const tools::Rectangle aPntRect(rNextRect.SVRect());
519
520 aInputFieldRanges.emplace_back(
521 aPntRect.Left(), aPntRect.Top(),
522 aPntRect.Right() + 1, aPntRect.Bottom() + 1);
523 }
524 }
525 }
526
527 if ( !aInputFieldRanges.empty() )
528 {
529 if (m_pTextInputFieldOverlay != nullptr)
530 {
531 m_pTextInputFieldOverlay->setRanges( aInputFieldRanges );
532 }
533 else
534 {
535 SdrView* pView = const_cast<SdrView*>(GetShell()->GetDrawView());
536 SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
537 const rtl::Reference<sdr::overlay::OverlayManager>& xTargetOverlay = pCandidate->GetOverlayManager();
538
539 if (xTargetOverlay.is())
540 {
541 // use system's highlight color with decreased luminance as highlight color
542 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
543 Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
544 aHighlight.DecreaseLuminance( 128 );
545
546 m_pTextInputFieldOverlay.reset( new sw::overlay::OverlayRangesOutline(
547 aHighlight, aInputFieldRanges ) );
548 xTargetOverlay->add( *m_pTextInputFieldOverlay );
549 }
550 }
551 }
552 else
553 {
554 m_pTextInputFieldOverlay.reset();
555 }
556}
557
558void SwSelPaintRects::Invalidate( const SwRect& rRect )
559{
560 size_type nSz = size();
561 if( !nSz )
562 return;
563
564 SwRegionRects aReg( GetShell()->VisArea() );
565 aReg.assign( begin(), end() );
566 aReg -= rRect;
567 SwRects::erase( begin(), begin() + nSz );
568 SwRects::insert( begin(), aReg.begin(), aReg.end() );
569
570 // If the selection is to the right or at the bottom, outside the
571 // visible area, it is never aligned on one pixel at the right/bottom.
572 // This has to be determined here and if that is the case the
573 // rectangle has to be expanded.
574 if( !(GetShell()->m_bVisPortChgd && 0 != ( nSz = size())) )
575 return;
576
577 SwSelPaintRects::Get1PixelInLogic( *GetShell() );
578 iterator it = begin();
579 for( ; nSz--; ++it )
580 {
581 SwRect& rRectIt = *it;
582 if( rRectIt.Right() == GetShell()->m_aOldRBPos.X() )
583 rRectIt.AddRight( s_nPixPtX );
584 if( rRectIt.Bottom() == GetShell()->m_aOldRBPos.Y() )
585 rRectIt.AddBottom( s_nPixPtY );
586 }
587}
588
589// check current MapMode of the shell and set possibly the static members.
590// Optional set the parameters pX, pY
591void SwSelPaintRects::Get1PixelInLogic( const SwViewShell& rSh,
592 long* pX, long* pY )
593{
594 const OutputDevice* pOut = rSh.GetWin();
595 if ( ! pOut )
596 pOut = rSh.GetOut();
597
598 const MapMode& rMM = pOut->GetMapMode();
599 if (s_pMapMode->GetMapUnit() != rMM.GetMapUnit() ||
600 s_pMapMode->GetScaleX() != rMM.GetScaleX() ||
601 s_pMapMode->GetScaleY() != rMM.GetScaleY())
602 {
603 *s_pMapMode = rMM;
604 Size aTmp( 1, 1 );
605 aTmp = pOut->PixelToLogic( aTmp );
606 s_nPixPtX = aTmp.Width();
607 s_nPixPtY = aTmp.Height();
608 }
609 if( pX )
610 *pX = s_nPixPtX;
611 if( pY )
612 *pY = s_nPixPtY;
613}
614
615SwShellCursor::SwShellCursor(
616 const SwCursorShell& rCShell,
617 const SwPosition &rPos )
618 : SwCursor(rPos,nullptr)
619 , SwSelPaintRects(rCShell)
620 , m_pInitialPoint(SwPaM::GetPoint())
621{}
622
623SwShellCursor::SwShellCursor(
624 const SwCursorShell& rCShell,
625 const SwPosition &rPos,
626 const Point& rPtPos,
627 SwPaM* pRing )
628 : SwCursor(rPos, pRing)
629 , SwSelPaintRects(rCShell)
630 , m_MarkPt(rPtPos)
631 , m_PointPt(rPtPos)
632 , m_pInitialPoint(SwPaM::GetPoint())
633{}
634
635SwShellCursor::SwShellCursor( SwShellCursor& rICursor )
636 : SwCursor(rICursor, &rICursor)
637 , SwSelPaintRects(*rICursor.GetShell())
638 , m_MarkPt(rICursor.GetMkPos())
639 , m_PointPt(rICursor.GetPtPos())
640 , m_pInitialPoint(SwPaM::GetPoint())
641{}
642
643SwShellCursor::~SwShellCursor()
644{}
645
646bool SwShellCursor::IsReadOnlyAvailable() const
647{
648 return GetShell()->IsReadOnlyAvailable();
649}
650
651void SwShellCursor::SetMark()
652{
653 if (SwPaM::GetPoint() == m_pInitialPoint)
654 m_MarkPt = m_PointPt;
655 else
656 m_PointPt = m_MarkPt;
657 SwPaM::SetMark();
658}
659
660void SwShellCursor::FillRects()
661{
662 // calculate the new rectangles
663 if( HasMark() &&
664 GetPoint()->nNode.GetNode().IsContentNode() &&
665 GetPoint()->nNode.GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) &&
666 (GetMark()->nNode == GetPoint()->nNode ||
667 (GetMark()->nNode.GetNode().IsContentNode() &&
668 GetMark()->nNode.GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) ) ))
669 GetShell()->GetLayout()->CalcFrameRects( *this );
670}
671
672void SwShellCursor::Show(SfxViewShell const * pViewShell)
673{
674 std::vector<OString> aSelectionRectangles;
675 for(SwPaM& rPaM : GetRingContainer())
676 {
677 SwShellCursor* pShCursor = dynamic_cast<SwShellCursor*>(&rPaM);
678 if(pShCursor)
679 pShCursor->SwSelPaintRects::Show(&aSelectionRectangles);
680 }
681
682 if (!comphelper::LibreOfficeKit::isActive())
683 return;
684
685 std::vector<OString> aRect;
686 for (const OString & rSelectionRectangle : aSelectionRectangles)
687 {
688 if (rSelectionRectangle.isEmpty())
689 continue;
690 aRect.push_back(rSelectionRectangle);
691 }
692 OString sRect = comphelper::string::join("; ", aRect);
693 if (pViewShell)
694 {
695 // Just notify pViewShell about our existing selection.
696 if (pViewShell != GetShell()->GetSfxViewShell())
697 SfxLokHelper::notifyOtherView(GetShell()->GetSfxViewShell(), pViewShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRect);
698 }
699 else
700 {
701 GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr());
702 SfxLokHelper::notifyOtherViews(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRect);
703 }
704}
705
706// This rectangle gets painted anew, therefore the SSelection in this
707// area is invalid.
708void SwShellCursor::Invalidate( const SwRect& rRect )
709{
710 for(SwPaM& rPaM : GetRingContainer())
711 {
712 SwShellCursor* pShCursor = dynamic_cast<SwShellCursor*>(&rPaM);
713 // skip any non SwShellCursor objects in the ring
714 // see also: SwAutoFormat::DeleteSel()
715 if(pShCursor)
716 pShCursor->SwSelPaintRects::Invalidate(rRect);
717 }
718}
719
720void SwShellCursor::Hide()
721{
722 for(SwPaM& rPaM : GetRingContainer())
723 {
724 SwShellCursor* pShCursor = dynamic_cast<SwShellCursor*>(&rPaM);
725 if(pShCursor)
726 pShCursor->SwSelPaintRects::Hide();
727 }
728}
729
730SwCursor* SwShellCursor::Create( SwPaM* pRing ) const
731{
732 return new SwShellCursor( *GetShell(), *GetPoint(), GetPtPos(), pRing );
733}
734
735short SwShellCursor::MaxReplaceArived()
736{
737 short nRet = RET_YES;
738 SvxSearchDialog* pDlg = SwView::GetSearchDialog();
739 if( pDlg )
740 {
741 // Terminate old actions. The table-frames get constructed and
742 // a SSelection can be created.
743 std::vector<sal_uInt16> vActionCounts;
744 for(SwViewShell& rShell : const_cast< SwCursorShell* >( GetShell() )->GetRingContainer())
745 {
746 sal_uInt16 nActCnt = 0;
747 while(rShell.ActionPend())
748 {
749 rShell.EndAction();
750 ++nActCnt;
751 }
752 vActionCounts.push_back(nActCnt);
753 }
754 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pDlg->getDialog(), "modules/swriter/ui/asksearchdialog.ui"));
755 std::unique_ptr<weld::MessageDialog> xDialog(xBuilder->weld_message_dialog("AskSearchDialog"));
756 nRet = xDialog->run();
757 auto pActionCount = vActionCounts.begin();
758 for(SwViewShell& rShell : const_cast< SwCursorShell* >( GetShell() )->GetRingContainer())
759 {
760 while(*pActionCount)
761 {
762 rShell.StartAction();
763 --(*pActionCount);
764 }
765 ++pActionCount;
766 }
767 }
768 else
769 // otherwise from the Basic, and then switch to RET_YES
770 nRet = RET_YES;
771
772 return nRet;
773}
774
775void SwShellCursor::SaveTableBoxContent( const SwPosition* pPos )
776{
777 const_cast<SwCursorShell*>(GetShell())->SaveTableBoxContent( pPos );
778}
779
780bool SwShellCursor::UpDown( bool bUp, sal_uInt16 nCnt )
781{
782 return SwCursor::UpDown( bUp, nCnt,
783 &GetPtPos(), GetShell()->GetUpDownX(),
784 *GetShell()->GetLayout());
785}
786
787// if <true> than the cursor can be set to the position.
788bool SwShellCursor::IsAtValidPos( bool bPoint ) const
789{
790 if( GetShell() && ( GetShell()->IsAllProtect() ||
791 GetShell()->GetViewOptions()->IsReadonly() ||
792 ( GetShell()->Imp()->GetDrawView() &&
793 GetShell()->Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )))
794 return true;
795
796 return SwCursor::IsAtValidPos( bPoint );
797}
798
799SwShellTableCursor::SwShellTableCursor( const SwCursorShell& rCursorSh,
800 const SwPosition& rPos )
801 : SwCursor(rPos,nullptr), SwShellCursor(rCursorSh, rPos), SwTableCursor(rPos)
802{
803}
804
805SwShellTableCursor::SwShellTableCursor( const SwCursorShell& rCursorSh,
806 const SwPosition& rMkPos, const Point& rMkPt,
807 const SwPosition& rPtPos, const Point& rPtPt )
808 : SwCursor(rPtPos,nullptr), SwShellCursor(rCursorSh, rPtPos), SwTableCursor(rPtPos)
809{
810 SetMark();
811 *GetMark() = rMkPos;
812 GetMkPos() = rMkPt;
813 GetPtPos() = rPtPt;
814}
815
816SwShellTableCursor::~SwShellTableCursor() {}
817
818void SwShellTableCursor::SetMark() { SwShellCursor::SetMark(); }
819
820SwCursor* SwShellTableCursor::Create( SwPaM* pRing ) const
821{
822 return SwShellCursor::Create( pRing );
823}
824
825short SwShellTableCursor::MaxReplaceArived()
826{
827 return SwShellCursor::MaxReplaceArived();
828}
829
830void SwShellTableCursor::SaveTableBoxContent( const SwPosition* pPos )
831{
832 SwShellCursor::SaveTableBoxContent( pPos );
833}
834
835void SwShellTableCursor::FillRects()
836{
837 // Calculate the new rectangles. If the cursor is still "parked" do nothing
838 if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->nNode.GetIndex())
839 return;
840
841 bool bStart = true;
842 SwRegionRects aReg( GetShell()->VisArea() );
843 if (comphelper::LibreOfficeKit::isActive())
844 aReg = GetShell()->getIDocumentLayoutAccess().GetCurrentLayout()->getFrameArea();
845 SwNodes& rNds = GetDoc().GetNodes();
846 SwFrame* pEndFrame = nullptr;
847 for (size_t n = 0; n < m_SelectedBoxes.size(); ++n)
848 {
849 const SwStartNode* pSttNd = m_SelectedBoxes[n]->GetSttNd();
850 const SwTableNode* pSelTableNd = pSttNd->FindTableNode();
851
852 SwNodeIndex aIdx( *pSttNd );
853 SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false );
854
855 // table in table
856 // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different
857 // version to do this)
858 const SwTableNode* pCurTableNd = pCNd ? pCNd->FindTableNode() : nullptr;
859 while ( pSelTableNd != pCurTableNd && pCurTableNd )
860 {
861 aIdx = pCurTableNd->EndOfSectionIndex();
862 pCNd = rNds.GoNextSection( &aIdx, true, false );
863 pCurTableNd = pCNd->FindTableNode();
864 }
865
866 if( !pCNd )
867 continue;
868
869 std::pair<Point, bool> const tmp(GetSttPos(), false);
870 SwFrame* pFrame = pCNd->getLayoutFrame(GetShell()->GetLayout(), nullptr, &tmp);
871 while( pFrame && !pFrame->IsCellFrame() )
872 pFrame = pFrame->GetUpper();
873
874 OSL_ENSURE( pFrame, "Node not in a table" )do { if (true && (!(pFrame))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/viscrs.cxx"
":" "874" ": "), "%s", "Node not in a table"); } } while (false
)
;
875
876 while ( pFrame )
877 {
878 if( aReg.GetOrigin().IsOver( pFrame->getFrameArea() ) )
879 {
880 aReg -= pFrame->getFrameArea();
881 if (bStart)
882 {
883 bStart = false;
884 m_aStart = SwRect(pFrame->getFrameArea().Left(), pFrame->getFrameArea().Top(), 1, pFrame->getFrameArea().Height());
885 }
886 }
887
888 pEndFrame = pFrame;
889 pFrame = pFrame->GetNextCellLeaf();
890 }
891 }
892 if (pEndFrame)
893 m_aEnd = SwRect(pEndFrame->getFrameArea().Right(), pEndFrame->getFrameArea().Top(), 1, pEndFrame->getFrameArea().Height());
894 aReg.Invert();
895 insert( begin(), aReg.begin(), aReg.end() );
896}
897
898void SwShellTableCursor::FillStartEnd(SwRect& rStart, SwRect& rEnd) const
899{
900 rStart = m_aStart;
901 rEnd = m_aEnd;
902}
903
904// Check if the SPoint is within the Table-SSelection.
905bool SwShellTableCursor::IsInside( const Point& rPt ) const
906{
907 // Calculate the new rectangles. If the cursor is still "parked" do nothing
908 if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->nNode.GetIndex())
909 return false;
910
911 SwNodes& rNds = GetDoc().GetNodes();
912 for (size_t n = 0; n < m_SelectedBoxes.size(); ++n)
913 {
914 SwNodeIndex aIdx( *m_SelectedBoxes[n]->GetSttNd() );
915 SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false );
916 if( !pCNd )
917 continue;
918
919 std::pair<Point, bool> const tmp(GetPtPos(), true);
920 SwFrame* pFrame = pCNd->getLayoutFrame(GetShell()->GetLayout(), nullptr, &tmp);
921 while( pFrame && !pFrame->IsCellFrame() )
922 pFrame = pFrame->GetUpper();
923 OSL_ENSURE( pFrame, "Node not in a table" )do { if (true && (!(pFrame))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/viscrs.cxx"
":" "923" ": "), "%s", "Node not in a table"); } } while (false
)
;
924 if( pFrame && pFrame->getFrameArea().IsInside( rPt ) )
925 return true;
926
927 for ( SwCellFrame* pCellFrame = static_cast<SwCellFrame*>(pFrame); pCellFrame; pCellFrame = pCellFrame->GetFollowCell() )
928 {
929 if( pCellFrame->getFrameArea().IsInside( rPt ) )
930 return true;
931 }
932 }
933 return false;
934}
935
936bool SwShellTableCursor::IsAtValidPos( bool bPoint ) const
937{
938 return SwShellCursor::IsAtValidPos( bPoint );
939}
940
941/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/sw/inc/crsrsh.hxx

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#ifndef INCLUDED_SW_INC_CRSRSH_HXX
20#define INCLUDED_SW_INC_CRSRSH_HXX
21
22#include <com/sun/star/i18n/WordType.hpp>
23
24#include <rtl/ustring.hxx>
25#include <tools/link.hxx>
26#include <vcl/keycod.hxx>
27#include <o3tl/typed_flags_set.hxx>
28
29#include "IShellCursorSupplier.hxx"
30#include "swdllapi.h"
31#include "docary.hxx"
32#include "viewsh.hxx"
33#include "calbck.hxx"
34#include "cshtyp.hxx"
35#include "crstate.hxx"
36#include "toxe.hxx"
37#include "tblsel.hxx"
38#include "viscrs.hxx"
39#include "node.hxx"
40#include "fldbas.hxx"
41#include "IDocumentMarkAccess.hxx"
42
43class SfxItemSet;
44class SfxPoolItem;
45class SwContentFrame;
46class SwUnoCursor;
47class SwFormatField;
48class SwTextFormatColl;
49class SwTextINetFormat;
50class SwFormatINetFormat;
51class SwTextAttr;
52class SwTableBox;
53class SwTOXMark;
54class SwRangeRedline;
55class SwBlockCursor;
56class SwPostItField;
57class SwTextField;
58
59namespace i18nutil {
60 struct SearchOptions2;
61}
62namespace com::sun::star::text { class XTextRange; }
63namespace com::sun::star::container { class XStringKeyMap; }
64
65// enum and struct to get information via the Doc-Position
66
67enum class IsAttrAtPos
68{
69 NONE = 0x0000,
70 Field = 0x0001,
71 ClickField = 0x0002,
72 Ftn = 0x0004,
73 InetAttr = 0x0008,
74 TableBoxFml = 0x0010,
75 Redline = 0x0020,
76 Outline = 0x0040,
77 ToxMark = 0x0080,
78 RefMark = 0x0100,
79 NumLabel = 0x0200,
80 ContentCheck = 0x0400,
81 SmartTag = 0x0800,
82 FormControl = 0x1000
83#ifdef DBG_UTIL
84 ,CurrAttrs = 0x2000 ///< only for debugging
85 ,TableBoxValue = 0x4000 ///< only for debugging
86#endif
87};
88namespace o3tl {
89 template<> struct typed_flags<IsAttrAtPos> : is_typed_flags<IsAttrAtPos, 0x7fff> {};
90}
91
92struct SwContentAtPos
93{
94 union {
95 const SwField* pField;
96 const SfxPoolItem* pAttr;
97 const SwRangeRedline* pRedl;
98 SwContentNode * pNode;
99 const sw::mark::IFieldmark* pFieldmark;
100 } aFnd;
101 IsAttrAtPos eContentAtPos;
102 int nDist;
103 OUString sStr;
104 const SwTextAttr* pFndTextAttr;
105
106 SwContentAtPos( IsAttrAtPos eGetAtPos )
107 : eContentAtPos( eGetAtPos )
108 {
109 aFnd.pField = nullptr;
110 pFndTextAttr = nullptr;
111 nDist = 0; // #i23726#
112 }
113
114 bool IsInProtectSect() const;
115 bool IsInRTLText() const;
116};
117
118// return values of SetCursor (can be combined via ||)
119const int CRSR_POSOLD = 0x01, // cursor stays at old position
120 CRSR_POSCHG = 0x02; // position changed by the layout
121
122namespace sw {
123
124bool ReplaceImpl(SwPaM & rCursor, OUString const& rReplacement,
125 bool const bRegExp, SwDoc & rDoc, SwRootFrame const*const pLayout);
126
127/// Helperfunction to resolve backward references in regular expressions
128std::optional<OUString> ReplaceBackReferences(const i18nutil::SearchOptions2& rSearchOpt,
129 SwPaM* pPam, SwRootFrame const* pLayout );
130
131bool GetRanges(std::vector<std::shared_ptr<SwUnoCursor>> & rRanges,
132 SwDoc & rDoc, SwPaM const& rDelPam);
133
134} // namespace sw
135
136class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwCursorShell
137 : public SwViewShell
138 , public SwModify
139 , public ::sw::IShellCursorSupplier
140{
141 friend class SwCallLink;
142 friend class SwVisibleCursor;
143 friend class SwSelPaintRects;
144
145 // requires the Cursor as InternalCursor
146 friend bool GetAutoSumSel( const SwCursorShell&, SwCellFrames& );
147
148public:
149
150 /** for calling UpdateCursor */
151 enum CursorFlag {
152 UPDOWN = (1 << 0), ///< keep Up/Down on columns
153 SCROLLWIN = (1 << 1), ///< scroll window
154 CHKRANGE = (1 << 2), ///< check overlapping PaMs
155 READONLY = (1 << 3) ///< make visible in spite of Readonly
156 };
157
158 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void UpdateCursor(
159 sal_uInt16 eFlags = SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE,
160 bool bIdleEnd = false );
161
162private:
163
164 SwRect m_aCharRect; ///< Char-SRectangle on which the cursor is located
165 Point m_aCursorHeight; ///< height & offset from visible Cursor
166 Point m_aOldRBPos; ///< Right/Bottom of last VisArea
167 // (used in Invalidate by Cursor)
168
169 Link<const SwFlyFrameFormat*,void> m_aFlyMacroLnk; /**< Link will be called, if the Cursor is set
170 into a fly. A macro can then be called */
171 Link<LinkParamNone*,void> m_aChgLnk; /**< link will be called by every attribute/
172 format changes at cursor position.*/
173 Link<SwCursorShell&,void> m_aGrfArrivedLnk; ///< Link calls to UI if a graphic is arrived
174
175 SwShellCursor* m_pCurrentCursor; ///< current cursor
176 SwShellCursor* m_pStackCursor; ///< stack for the cursor
177 SwVisibleCursor *m_pVisibleCursor; ///< the visible cursor
178
179 SwBlockCursor *m_pBlockCursor; ///< interface of cursor for block (=rectangular) selection
180
181 SwShellTableCursor* m_pTableCursor; /**< table Cursor; only in tables when the
182 selection lays over 2 columns */
183
184 SwNodeIndex* m_pBoxIdx; ///< for recognizing of the changed
185 SwTableBox* m_pBoxPtr; ///< table row
186
187 long m_nUpDownX; /**< try to move the cursor on up/down always
188 in the same column */
189 long m_nLeftFramePos;
190 sal_uLong m_nCurrentNode; // save CursorPos at Start-Action
191 sal_Int32 m_nCurrentContent;
192 SwNodeType m_nCurrentNdTyp;
193
194 /*
195 * Via the Method SttCursorMove and EndCursorMove this counter gets
196 * incremented/decremented. As long as the counter is inequal to 0, the
197 * current Cursor gets no update. This way, "complicated" cursor movements
198 * (via Find()) can be realised.
199 */
200 sal_uInt16 m_nCursorMove;
201 CursorMoveState m_eMvState; ///< Status for Cursor-Travelling - GetModelPositionForViewPoint
202 SwTable::SearchType m_eEnhancedTableSel; /// table rows or columns selected by not cell by cell
203
204 OUString m_sMarkedListId;
205 int m_nMarkedListLevel;
206
207 bool m_bHasFocus : 1; ///< Shell is "active" in a window
208 bool m_bSVCursorVis : 1; ///< SV-Cursor visible/invisible
209 bool m_bChgCallFlag : 1; ///< attribute change inside Start- and EndAction
210 bool m_bVisPortChgd : 1; ///< in VisPortChg-Call
211 // (used in Invalidate by the Cursor)
212
213 bool m_bCallChgLnk : 1; ///< flag for derived classes
214 // true -> call ChgLnk
215 // access only via SwChgLinkFlag
216 bool m_bAllProtect : 1; ///< Flag for areas
217 // true -> everything protected / hidden
218 bool m_bInCMvVisportChgd : 1; ///< Flag for CursorMoves
219 // true -> view was moved
220 bool m_bGCAttr : 1; // true -> non expanded attributes exist.
221 bool m_bIgnoreReadonly : 1; // true -> make the cursor visible on next
222 // EndAction in spite of Readonly
223 bool m_bSelTableCells : 1; // true -> select cells over the InputWin
224 bool m_bAutoUpdateCells : 1; // true -> autoformat cells
225 bool m_bBasicHideCursor : 1; // true -> HideCursor from Basic
226 bool m_bSetCursorInReadOnly : 1;// true -> Cursor is allowed in ReadOnly-Areas
227 bool m_bOverwriteCursor : 1; // true -> show Overwrite Cursor
228
229 bool m_bMacroExecAllowed : 1;
230
231 SwFrame* m_oldColFrame;
232
233 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void MoveCursorToNum();
234
235 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing );
236
237 /** Mark a certain list level of a certain list
238
239 levels of a certain lists are marked now
240
241 @param sListId list Id of the list whose level is marked
242 @param nLevel to be marked list level
243
244 An empty sListId denotes that no level of a list is marked.
245 */
246 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void MarkListLevel( const OUString& sListId,
247 const int nLevel );
248
249 // private method(s) accessed from public inline method(s) must be exported.
250 bool LeftRight( bool, sal_uInt16, sal_uInt16, bool );
251 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool UpDown( bool, sal_uInt16 );
252 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool LRMargin( bool, bool bAPI = false );
253 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool IsAtLRMargin( bool, bool bAPI = false ) const;
254
255 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool isInHiddenTextFrame(SwShellCursor* pShellCursor);
256
257 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoStartWordImpl();
258 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoEndWordImpl();
259 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoNextWordImpl();
260 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoPrevWordImpl();
261 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoNextSentenceImpl();
262 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoEndSentenceImpl();
263 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool GoStartSentenceImpl();
264
265 typedef bool (SwCursor::*FNCursor)();
266 typedef bool (SwCursorShell::*FNCursorShell)();
267 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool CallCursorFN( FNCursor );
268 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool CallCursorShellFN( FNCursorShell );
269
270 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) const SwRangeRedline* GotoRedline_( SwRedlineTable::size_type nArrPos, bool bSelect );
271
272 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void sendLOKCursorUpdates();
273protected:
274
275 inline SwMoveFnCollection const & MakeFindRange( SwDocPositions, SwDocPositions, SwPaM* ) const;
276
277 /*
278 * Compare-Method for the StackCursor and the current Cursor.
279 * The Methods return -1, 0, 1 for lower, equal, greater.
280 */
281 int CompareCursorStackMkCurrPt() const;
282
283 bool SelTableRowOrCol( bool bRow, bool bRowSimple = false );
284
285 bool SetInFrontOfLabel( bool bNew );
286
287 void RefreshBlockCursor();
288
289 /** Updates the marked list level according to the cursor.
290 */
291 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void UpdateMarkedListLevel();
292
293protected:
294 virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew) override;
295
296public:
297 SwCursorShell( SwDoc& rDoc, vcl::Window *pWin, const SwViewOption *pOpt );
298 // disguised copy constructor
299 SwCursorShell( SwCursorShell& rShell, vcl::Window *pWin );
300 virtual ~SwCursorShell() override;
301
302 // create new cursor and append the old one
303 virtual SwPaM & CreateNewShellCursor() override;
304 virtual SwPaM & GetCurrentShellCursor() override;
305
306 SwPaM * CreateCursor();
307 ///< delete the current cursor and make the following into the current
308 void DestroyCursor();
309 ///< transform TableCursor to normal cursor, nullify Tablemode
310 void TableCursorToCursor();
311 ///< enter block mode, change normal cursor into block cursor
312 void CursorToBlockCursor();
313 ///< leave block mode, change block cursor into normal cursor
314 void BlockCursorToCursor();
315
316 // SelAll() selects the document body content
317 // if ExtendedSelect() is called afterwards, the whole nodes array is selected
318 // only for usage in special cases allowed!
319 void ExtendedSelectAll(bool bFootnotes = true);
320 /// If ExtendedSelectAll() was called and selection didn't change since then.
321 bool ExtendedSelectedAll();
322 /// If document body starts with a table.
323 bool StartsWithTable();
324
325 SwPaM* GetCursor( bool bMakeTableCursor = true ) const;
326 inline SwCursor* GetSwCursor() const;
327 // return only the current cursor
328 SwShellCursor* GetCursor_() { return m_pCurrentCursor; }
329 const SwShellCursor* GetCursor_() const { return m_pCurrentCursor; }
330
331 // show passed cursor - for UNO
332 void SetSelection(const SwPaM& rCursor);
333
334 // remove all cursors from ContentNodes and set to 0
335 void ParkCursor( const SwNodeIndex &rIdx );
336
337 // return the current cursor stack
338 // (required in EditShell when deleting contents)
339 inline SwPaM* GetStackCursor() const;
340
341 // start parenthesing, hide SV-Cursor and selected areas
342 void StartAction();
343 // end parenthesing, show SV-Cursor and selected areas
344 void EndAction( const bool bIdleEnd = false, const bool DoSetPosX = false );
345
346 // basic cursor travelling
347 long GetUpDownX() const { return m_nUpDownX; }
348
349 bool Left( sal_uInt16 nCnt, sal_uInt16 nMode, bool bAllowVisual = false )
350 { return LeftRight( true, nCnt, nMode, bAllowVisual ); }
351 bool Right( sal_uInt16 nCnt, sal_uInt16 nMode, bool bAllowVisual = false )
352 { return LeftRight( false, nCnt, nMode, bAllowVisual ); }
353 bool Up( sal_uInt16 nCnt = 1 ) { return UpDown( true, nCnt ); }
354 bool Down( sal_uInt16 nCnt = 1 ) { return UpDown( false, nCnt ); }
355 bool LeftMargin() { return LRMargin( true ); }
356 bool RightMargin(bool bAPI = false) { return LRMargin( false, bAPI ); }
357 bool SttEndDoc( bool bStt );
358
359 bool MovePage( SwWhichPage, SwPosPage );
360 bool MovePara( SwWhichPara, SwMoveFnCollection const & );
361 bool MoveSection( SwWhichSection, SwMoveFnCollection const & );
362 bool MoveTable( SwWhichTable, SwMoveFnCollection const & );
363 void MoveColumn( SwWhichColumn, SwPosColumn );
364 bool MoveRegion( SwWhichRegion, SwMoveFnCollection const & );
365
366 // note: DO NOT call it FindText because windows.h
367 sal_uLong Find_Text( const i18nutil::SearchOptions2& rSearchOpt,
368 bool bSearchInNotes,
369 SwDocPositions eStart, SwDocPositions eEnd,
370 bool& bCancel,
371 FindRanges eRng, bool bReplace = false );
372
373 sal_uLong FindFormat( const SwTextFormatColl& rFormatColl,
374 SwDocPositions eStart, SwDocPositions eEnd,
375 bool& bCancel,
376 FindRanges eRng, const SwTextFormatColl* pReplFormat );
377
378 sal_uLong FindAttrs( const SfxItemSet& rSet, bool bNoCollections,
379 SwDocPositions eStart, SwDocPositions eEnd,
380 bool& bCancel,
381 FindRanges eRng,
382 const i18nutil::SearchOptions2* pSearchOpt,
383 const SfxItemSet* rReplSet );
384
385 // Position the Cursor
386 // return values:
387 // CRSR_POSCHG: when cursor was corrected from SPoint by the layout
388 // CRSR_POSOLD: when the cursor was not changed
389 int SetCursor( const Point &rPt, bool bOnlyText = false, bool bBlock = true );
390
391 /*
392 * Notification that the visible area was changed. m_aVisArea is reset, then
393 * scrolling is done. The passed Rectangle lays on pixel borders to avoid
394 * pixel errors.
395 */
396 virtual void VisPortChgd( const SwRect & ) override;
397
398 /*
399 * virtual paint method to make selection visible again after Paint
400 */
401 void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle & rRect) override;
402
403 // Areas
404 inline void SetMark();
405 inline bool HasMark() const;
406
407 void ClearMark();
408
409 /**
410 Ensure point and mark of the current PaM are in a specific order.
411
412 @param bPointFirst true: If the point is behind the mark then
413 swap the PaM. false: If the mark is behind the point then swap
414 the PaM.
415 */
416 void NormalizePam(bool bPointFirst = true);
417
418 void SwapPam();
419 bool TestCurrPam( const Point & rPt,
420 bool bTstHit = false); // only exact matches
421 void KillPams();
422
423 /// store a copy of the current cursor on the cursor stack
424 void Push();
425 enum class PopMode { DeleteCurrent, DeleteStack };
426 /*
427 * Delete a cursor
428 * - either from the top of the stack
429 * - or delete the current one and replace it with the cursor from the
430 * stack
431 * @return <true> if there was one on the stack, <false> otherwise
432 */
433 bool Pop(PopMode);
434 /*
435 * Combine 2 Cursors.
436 * Delete the topmost from the stack and move its Mark into the current.
437 */
438 void Combine();
439
440 void SttCursorMove();
441 void EndCursorMove( const bool bIdleEnd = false );
442
443 /*
444 * When the focus is lost the selected ranges are not displayed anymore.
445 * On the other hand, on receiving the focus all selected ranges are displayed again
446 * (ranges must be recalculated!).
447 */
448 bool HasShellFocus() const { return m_bHasFocus; }
449 void ShellLoseFocus();
450 void ShellGetFocus();
451
452 // Methods for displaying or hiding the visible text cursor.
453 void ShowCursor();
454 void HideCursor();
455 // Methods for displaying or hiding the selected ranges with visible cursor.
456 void ShowCursors( bool bCursorVis );
457 void HideCursors();
458
459 bool IsOverwriteCursor() const { return m_bOverwriteCursor; }
460 void SetOverwriteCursor( bool bFlag ) { m_bOverwriteCursor = bFlag; }
461
462 // Return current frame in which the cursor is placed.
463 SwContentFrame *GetCurrFrame( const bool bCalcFrame = true ) const;
464
465 //true if cursor is hidden because of readonly.
466 //false if it is working despite readonly.
467 bool IsCursorReadonly() const;
468
469 // Cursor is placed in something that is protected or selection contains
470 // something that is protected.
471 bool HasReadonlySel() const;
472
473 // Can the cursor be set to read only ranges?
474 bool IsReadOnlyAvailable() const { return m_bSetCursorInReadOnly; }
475 void SetReadOnlyAvailable( bool bFlag );
476 bool IsOverReadOnlyPos( const Point& rPt ) const;
477
478 // Methods for aFlyMacroLnk.
479 void SetFlyMacroLnk( const Link<const SwFlyFrameFormat*,void>& rLnk ) { m_aFlyMacroLnk = rLnk; }
480 const Link<const SwFlyFrameFormat*,void>& GetFlyMacroLnk() const { return m_aFlyMacroLnk; }
481
482 // Methods returning/altering link for changes of attributes/formats.
483 void SetChgLnk( const Link<LinkParamNone*,void> &rLnk ) { m_aChgLnk = rLnk; }
484 const Link<LinkParamNone*,void>& GetChgLnk() const { return m_aChgLnk; }
485
486 // Methods returning/altering link for "graphic completely loaded".
487 void SetGrfArrivedLnk( const Link<SwCursorShell&,void> &rLnk ) { m_aGrfArrivedLnk = rLnk; }
488 const Link<SwCursorShell&,void>& GetGrfArrivedLnk() const { return m_aGrfArrivedLnk; }
489
490 //Call ChgLink. When within an action calling will be delayed.
491 void CallChgLnk();
492
493 // Check if the current cursor contains a selection, i.e.
494 // if Mark is set and SPoint and Mark are different.
495 bool HasSelection() const;
496
497 // Check if a selection exists, i.e. if the current cursor comprises a selection.
498 inline bool IsSelection() const;
499 // returns if multiple cursors are available
500 inline bool IsMultiSelection() const;
501
502 // Check if a complete paragraph was selected.
503 bool IsSelFullPara() const;
504
505 // Check if selection is within one paragraph.
506
507 //Should WaitPtr be activated for Clipboard.
508 bool ShouldWait() const;
509
510 // Check if selection is within one paragraph.
511 bool IsSelOnePara() const;
512
513 /*
514 * Returns SRectangle, at which the cursor is located.
515 */
516 const SwRect &GetCharRect() const { return m_aCharRect; }
517 /*
518 * Returns if cursor is wholly or partly within visible range.
519 */
520 bool IsCursorVisible() const { return VisArea().IsOver( GetCharRect() ); }
521 /*
522 * Returns SwRect, at which the character is located.
523 */
524 void GetCharRectAt(SwRect& rRect, const SwPosition* pPos);
525
526 // Return current page number:
527 // true: in which cursor is located.
528 // false: which is visible at the upper margin.
529 void GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
530 bool bAtCursorPos = true, const bool bCalcFrame = true );
531 // Returns current page's sequential number (1-based),in which cursor is located, ignoring autoinserted empty pages.
532 // Returns 0 on error
533 sal_uInt16 GetPageNumSeqNonEmpty();
534 // Determine how "empty pages" are handled
535 // (used in PhyPage).
536 sal_uInt16 GetNextPrevPageNum( bool bNext = true );
537
538 // Move cursor at the beginning of page "nPage".
539 bool GotoPage( sal_uInt16 nPage );
540
541 sal_uInt16 GetPageCnt();
542
543 bool GoNextCursor();
544
545 bool GoPrevCursor();
546
547 bool GoNextPrevCursorSetSearchLabel(const bool bNext);
548
549 // at CurrentCursor.SPoint
550 ::sw::mark::IMark* SetBookmark(
551 const vcl::KeyCode&,
552 const OUString& rName,
553 IDocumentMarkAccess::MarkType eMark = IDocumentMarkAccess::MarkType::BOOKMARK);
554 ::sw::mark::IMark* SetBookmark2(
555 const vcl::KeyCode&,
556 const OUString& rName,
557 bool bHide,
558 const OUString& rCondition);
559 bool GotoMark( const ::sw::mark::IMark* const pMark ); // sets CurrentCursor.SPoint
560 bool GotoMark( const ::sw::mark::IMark* const pMark, bool bAtStart );
561 bool GoNextBookmark(); // true, if there was one
562 bool GoPrevBookmark();
563
564 bool IsFormProtected();
565 ::sw::mark::IFieldmark* GetCurrentFieldmark();
566 ::sw::mark::IFieldmark* GetFieldmarkAfter();
567 ::sw::mark::IFieldmark* GetFieldmarkBefore();
568 bool GotoFieldmark( const ::sw::mark::IFieldmark* const pMark );
569
570 // update Cursr, i.e. reset it into content should only be called when the
571 // cursor was set to a random position e.g. when deleting frames
572 void UpdateCursorPos();
573
574 // get the selected text at the current cursor. It will be filled with
575 // fields etc.
576 OUString GetSelText() const;
577
578 // Check of SPoint or Mark of current cursor are placed within a table.
579 inline const SwTableNode* IsCursorInTable() const;
580
581 bool IsCursorInFootnote() const;
582
583 inline Point& GetCursorDocPos() const;
584 inline bool IsCursorPtAtEnd() const;
585
586 inline const SwPaM* GetTableCrs() const;
587 inline SwPaM* GetTableCrs();
588
589 bool IsTableComplexForChart();
590 // get current table selection as text
591 OUString GetBoxNms() const;
592
593 // set Cursor to the next/previous cell
594 bool GoNextCell( bool bAppendLine = true );
595 bool GoPrevCell();
596 // go to this box (if available and inside of table)
597 bool GotoTable( const OUString& rName );
598
599 // select a table row, column or box (based on the current cursor)
600 bool SelTableRow() { return SelTableRowOrCol( true ); }
601 bool SelTableCol() { return SelTableRowOrCol( false ); }
602 bool SelTableBox();
603
604 bool SelTable();
605
606 void GotoNextNum();
607 void GotoPrevNum();
608
609 bool GotoOutline( const OUString& rName );
610 // to the next/previous or the given OutlineNode
611 void GotoOutline( SwOutlineNodes::size_type nIdx );
612 // find the "outline position" in the nodes array of the current chapter
613 SwOutlineNodes::size_type GetOutlinePos(sal_uInt8 nLevel = UCHAR_MAX(127*2 +1), SwPaM* pPaM = nullptr);
614 // select the given range of OutlineNodes. Optionally including the children
615 // the sal_uInt16s are the positions in OutlineNodes-Array (EditShell)
616 bool MakeOutlineSel(SwOutlineNodes::size_type nSttPos, SwOutlineNodes::size_type nEndPos,
617 bool bWithChildren, bool bKillPams = true );
618
619 bool GotoNextOutline();
620 bool GotoPrevOutline();
621
622 /** Delivers the current shell cursor
623
624 Some operations have to run on the current cursor ring,
625 some on the m_pTableCursor (if exist) or the current cursor ring and
626 some on the m_pTableCursor or m_pBlockCursor or the current cursor ring.
627 This small function checks the existence and delivers the wished cursor.
628
629 @param bBlock [bool]
630 if the block cursor is of interest or not
631
632 @return m_pTableCursor if exist,
633 m_pBlockCursor if exist and of interest (param bBlock)
634 otherwise m_pCurrentCursor
635 */
636 SwShellCursor* getShellCursor( bool bBlock );
637 const SwShellCursor* getShellCursor( bool bBlock ) const
638 { return const_cast<SwCursorShell*>(this)->getShellCursor( bBlock ); }
639
640 bool IsBlockMode() const { return nullptr != m_pBlockCursor; }
641
642 // is the Cursor in a table and is the selection over 2 columns
643 bool IsTableMode() const { return nullptr != m_pTableCursor; }
14
Assuming the condition is false
15
Returning zero, which participates in a condition later
644
645 const SwShellTableCursor* GetTableCursor() const { return m_pTableCursor; }
646 SwShellTableCursor* GetTableCursor() { return m_pTableCursor; }
647 size_t UpdateTableSelBoxes();
648
649 bool GotoFootnoteText(); ///< jump from content to footnote
650 bool GotoFootnoteAnchor(); ///< jump from footnote to anchor
651 bool GotoPrevFootnoteAnchor();
652 bool GotoNextFootnoteAnchor();
653
654 void GotoFlyAnchor(); ///< jump from the frame to the anchor
655 bool GotoHeaderText(); ///< jump from the content to the header
656 bool GotoFooterText(); ///< jump from the content to the footer
657 // jump to the header/footer of the given or current PageDesc
658 bool SetCursorInHdFt( size_t nDescNo, bool bInHeader );
659 // is point of cursor in header/footer. pbInHeader return true if it is
660 // in a headerframe otherwise in a footerframe
661 bool IsInHeaderFooter( bool* pbInHeader = nullptr ) const;
662
663 bool GotoNextTOXBase( const OUString* = nullptr );
664 bool GotoPrevTOXBase( const OUString* = nullptr );
665 void GotoTOXMarkBase();
666 // jump to the next or previous index entry
667 bool GotoNxtPrvTOXMark( bool bNext = true );
668 // jump to the next/previous index mark of this type
669 const SwTOXMark& GotoTOXMark( const SwTOXMark& rStart, SwTOXSearch eDir );
670
671 // jump to the next or previous table formula
672 // optionally only to broken formulas
673 bool GotoNxtPrvTableFormula( bool bNext = true,
674 bool bOnlyErrors = false );
675 // jump to the next / previous hyperlink - inside text and also
676 // on graphics
677 bool SelectNxtPrvHyperlink( bool bNext );
678
679 bool GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType,
680 sal_uInt16 nSeqNo );
681
682 // get the nth character from the start or end of the current selection
683 sal_Unicode GetChar( bool bEnd = true, long nOffset = 0 );
684 bool ExtendSelection( bool bEnd = true, sal_Int32 nCount = 1 );
685
686 // Place only the visible cursor at the given position in the document.
687 // Return false if SPoint was corrected by layout.
688 // (This is needed for displaying the Drag&Drop/Copy-Cursor.)
689 bool SetVisibleCursor( const Point &rPt );
690 inline void UnSetVisibleCursor();
691 SwVisibleCursor* GetVisibleCursor() const;
692
693 // jump to the next or previous field of the corresponding type
694 bool MoveFieldType(
695 const SwFieldType* pFieldType,
696 const bool bNext,
697 const SwFieldIds nResType = SwFieldIds::Unknown,
698 const bool bAddSetExpressionFieldsToInputFields = true );
699
700 bool GotoFormatField( const SwFormatField& rField );
701
702 static SwTextField* GetTextFieldAtPos(
703 const SwPosition* pPos,
704 const bool bIncludeInputFieldAtStart );
705 static SwTextField* GetTextFieldAtCursor(
706 const SwPaM* pCursor,
707 const bool bIncludeInputFieldAtStart );
708 static SwField* GetFieldAtCursor(
709 const SwPaM* pCursor,
710 const bool bIncludeInputFieldAtStart );
711 SwField* GetCurField( const bool bIncludeInputFieldAtStart = false ) const;
712 bool CursorInsideInputField() const;
713 static bool PosInsideInputField( const SwPosition& rPos );
714 bool DocPtInsideInputField( const Point& rDocPt ) const;
715 static sal_Int32 StartOfInputFieldAtPos( const SwPosition& rPos );
716 static sal_Int32 EndOfInputFieldAtPos( const SwPosition& rPos );
717
718 // Return number of cursors in ring (The flag indicates whether
719 // only cursors containing selections are requested).
720 sal_uInt16 GetCursorCnt( bool bAll = true ) const;
721
722 // Char Travelling - methods (in crstrvl1.cxx)
723 bool GoStartWord();
724 bool GoEndWord();
725 bool GoNextWord();
726 bool GoPrevWord();
727 bool GoNextSentence();
728 bool GoStartSentence();
729 bool GoEndSentence();
730 bool SelectWord( const Point* pPt );
731 void ExpandToSentenceBorders();
732
733 // get position from current cursor
734 bool IsStartWord( sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES )const;
735 bool IsEndWord( sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES ) const;
736 bool IsInWord( sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES ) const;
737 bool IsStartSentence() const;
738 bool IsEndSentence() const;
739 bool IsSttPara() const;
740 bool IsEndPara() const;
741 bool IsEndOfTable() const; ///< at the very last SwPosition inside a table
742 bool IsStartOfDoc() const;
743 bool IsEndOfDoc() const;
744 bool IsInFrontOfLabel() const;
745 bool IsAtLeftMargin() const { return IsAtLRMargin( true ); }
746 bool IsAtRightMargin() const { return IsAtLRMargin( false, true/*bAPI*/ ); }
747
748 // delete all created cursors, set the table cursor and the last cursor to
749 // its TextNode (or StartNode?)
750 // They all get created on the next ::GetCursor again
751 // Used for Drag&Drop/Clipboard-Paste in tables
752 bool ParkTableCursor();
753
754 // Non expanded attributes?
755 bool IsGCAttr() const { return m_bGCAttr; }
756 void ClearGCAttr() { m_bGCAttr = false; }
757 void UpdateAttr() { m_bGCAttr = true; }
758
759 // is the whole document protected/hidden (for UI...)
760 bool IsAllProtect() const { return m_bAllProtect; }
761
762 bool GotoRegion( const OUString& rName );
763
764 // show the current selection
765 virtual void MakeSelVisible();
766
767 // set the cursor to a NOT protected/hidden node
768 bool FindValidContentNode( bool bOnlyText );
769
770 bool GetContentAtPos( const Point& rPt,
771 SwContentAtPos& rContentAtPos,
772 bool bSetCursor = false,
773 SwRect* pFieldRect = nullptr );
774
775 const SwPostItField* GetPostItFieldAtCursor() const;
776
777 // get smart tags rectangle for the given point
778 void GetSmartTagRect( const Point& rPt, SwRect& rSelectRect );
779
780 // get smart tags at current cursor position
781 void GetSmartTagTerm( std::vector< OUString >& rSmartTagTypes,
782 css::uno::Sequence< css::uno::Reference< css::container::XStringKeyMap > >& rStringKeyMaps,
783 css::uno::Reference<css::text::XTextRange>& rRange ) const;
784
785 bool IsPageAtPos( const Point &rPt ) const;
786
787 bool SelectTextAttr( sal_uInt16 nWhich, bool bExpand, const SwTextAttr* pAttr = nullptr );
788 bool GotoINetAttr( const SwTextINetFormat& rAttr );
789 const SwFormatINetFormat* FindINetAttr( const OUString& rName ) const;
790
791 bool SelectText( const sal_Int32 nStart,
792 const sal_Int32 nEnd );
793
794 bool CheckTableBoxContent( const SwPosition* pPos = nullptr );
795 void SaveTableBoxContent( const SwPosition* pPos = nullptr );
796 void ClearTableBoxContent();
797 bool EndAllTableBoxEdit();
798
799 void SetSelTableCells( bool bFlag ) { m_bSelTableCells = bFlag; }
800 bool IsSelTableCells() const { return m_bSelTableCells; }
801
802 void UnsetEnhancedTableSelection() { m_eEnhancedTableSel = SwTable::SEARCH_NONE; }
803 SwTable::SearchType GetEnhancedTableSelection() const { return m_eEnhancedTableSel; }
804
805 bool IsAutoUpdateCells() const { return m_bAutoUpdateCells; }
806 void SetAutoUpdateCells( bool bFlag ) { m_bAutoUpdateCells = bFlag; }
807
808 bool GetShadowCursorPos( const Point& rPt, SwFillMode eFillMode,
809 SwRect& rRect, sal_Int16& rOrient );
810 bool SetShadowCursorPos( const Point& rPt, SwFillMode eFillMode );
811
812 const SwRangeRedline* SelNextRedline();
813 const SwRangeRedline* SelPrevRedline();
814 const SwRangeRedline* GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect );
815
816 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) SvxFrameDirection GetTextDirection( const Point* pPt = nullptr ) const;
817 // is cursor or the point in/over a vertical formatted text?
818 bool IsInVerticalText( const Point* pPt = nullptr ) const;
819 // is cursor or the point in/over a right to left formatted text?
820 bool IsInRightToLeftText() const;
821
822 static void FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage);
823 bool bColumnChange();
824 static void FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection);
825 static void FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn);
826 // If the current cursor position is inside a hidden range, the hidden range
827 // is selected and true is returned:
828 bool SelectHiddenRange();
829
830 // remove all invalid cursors
831 void ClearUpCursors();
832
833 void SetMacroExecAllowed( const bool _bMacroExecAllowed )
834 {
835 m_bMacroExecAllowed = _bMacroExecAllowed;
836 }
837 bool IsMacroExecAllowed() const
838 {
839 return m_bMacroExecAllowed;
840 }
841
842 /**
843 Returns textual description of the current selection.
844
845 - If the current selection is a multi-selection the result is
846 STR_MULTISEL.
847 - Else the result is the text of the selection.
848
849 @return the textual description of the current selection
850 */
851 OUString GetCursorDescr() const;
852
853 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override;
854 /// Implementation of lok::Document::getPartPageRectangles() for Writer.
855 OUString getPageRectangles();
856
857 /// See SwView::NotifyCursor().
858 void NotifyCursor(SfxViewShell* pViewShell) const;
859};
860
861// Cursor Inlines:
862inline SwMoveFnCollection const & SwCursorShell::MakeFindRange(
863 SwDocPositions nStt, SwDocPositions nEnd, SwPaM* pPam ) const
864{
865 return m_pCurrentCursor->MakeFindRange( nStt, nEnd, pPam );
866}
867
868inline SwCursor* SwCursorShell::GetSwCursor() const
869{
870 return static_cast<SwCursor*>(GetCursor());
871}
872
873inline SwPaM* SwCursorShell::GetStackCursor() const { return m_pStackCursor; }
874
875inline void SwCursorShell::SetMark() { m_pCurrentCursor->SetMark(); }
876
877inline bool SwCursorShell::HasMark() const { return m_pCurrentCursor->HasMark(); }
878
879inline bool SwCursorShell::IsSelection() const
880{
881 return IsTableMode() || m_pCurrentCursor->HasMark() ||
13
Calling 'SwCursorShell::IsTableMode'
16
Returning from 'SwCursorShell::IsTableMode'
17
Called C++ object pointer is null
882 m_pCurrentCursor->GetNext() != m_pCurrentCursor;
883}
884inline bool SwCursorShell::IsMultiSelection() const
885{
886 return m_pCurrentCursor->GetNext() != m_pCurrentCursor;
887}
888
889inline const SwTableNode* SwCursorShell::IsCursorInTable() const
890{
891 return m_pCurrentCursor->GetNode().FindTableNode();
892}
893
894inline bool SwCursorShell::IsCursorPtAtEnd() const
895{
896 return m_pCurrentCursor->End() == m_pCurrentCursor->GetPoint();
897}
898
899inline Point& SwCursorShell::GetCursorDocPos() const
900{
901 return m_pCurrentCursor->GetPtPos();
902}
903
904inline const SwPaM* SwCursorShell::GetTableCrs() const
905{
906 return m_pTableCursor;
907}
908
909inline SwPaM* SwCursorShell::GetTableCrs()
910{
911 return m_pTableCursor;
912}
913
914inline void SwCursorShell::UnSetVisibleCursor()
915{
916 m_pVisibleCursor->Hide();
917 m_pVisibleCursor->SetDragCursor( false );
918}
919
920#endif // _CRSRSH_HXX
921
922/* vim:set shiftwidth=4 softtabstop=4 expandtab: */