LibreOffice Module sw (master) 1
crsrsh.cxx
Go to the documentation of this file.
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_wasm_strip.h>
21
22#include <com/sun/star/text/XTextRange.hpp>
23
24#include <hintids.hxx>
25#include <svx/srchdlg.hxx>
26#include <sfx2/viewsh.hxx>
27#include <SwSmartTagMgr.hxx>
28#include <doc.hxx>
29#include <rootfrm.hxx>
30#include <pagefrm.hxx>
31#include <cntfrm.hxx>
32#include <viewimp.hxx>
33#include <pam.hxx>
34#include <swselectionlist.hxx>
35#include "BlockCursor.hxx"
36#include <ndtxt.hxx>
37#include <flyfrm.hxx>
38#include <dview.hxx>
39#include <viewopt.hxx>
40#include <crsrsh.hxx>
41#include <tabfrm.hxx>
42#include <txtfrm.hxx>
43#include <sectfrm.hxx>
44#include <swtable.hxx>
45#include "callnk.hxx"
46#include <viscrs.hxx>
47#include <section.hxx>
48#include <docsh.hxx>
49#include <scriptinfo.hxx>
50#include <globdoc.hxx>
51#include <pamtyp.hxx>
52#include <mdiexp.hxx>
53#include <fmteiro.hxx>
54#include <wrong.hxx>
55#include <unotextrange.hxx>
56#include <vcl/svapp.hxx>
57#include <vcl/settings.hxx>
58#include <GrammarContact.hxx>
61#include <strings.hrc>
63#include <LibreOfficeKit/LibreOfficeKitEnums.h>
64#include <comphelper/lok.hxx>
66#include <sfx2/lokhelper.hxx>
67#include <editeng/editview.hxx>
68#include <editeng/frmdir.hxx>
69#include <sal/log.hxx>
70#include <PostItMgr.hxx>
72#include <vcl/uitest/logger.hxx>
74#include <tabcol.hxx>
75#include <wrtsh.hxx>
76#include <undobj.hxx>
77#include <view.hxx>
78#include <hints.hxx>
79#include <tools/json_writer.hxx>
80
81using namespace com::sun::star;
82using namespace util;
83
88static void CheckRange( SwCursor* pCurrentCursor )
89{
90 auto [pStt, pEnd] = pCurrentCursor->StartEnd(); // SwPosition*
91
92 SwPaM *pTmpDel = nullptr,
93 *pTmp = pCurrentCursor->GetNext();
94
95 // Search the complete ring
96 while( pTmp != pCurrentCursor )
97 {
98 auto [pTmpStt, pTmpEnd] = pTmp->StartEnd(); // SwPosition*
99 if( *pStt <= *pTmpStt )
100 {
101 if( *pEnd > *pTmpStt ||
102 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
103 pTmpDel = pTmp;
104 }
105 else
106 if( *pStt < *pTmpEnd )
107 pTmpDel = pTmp;
108
109 // If Point or Mark is within the Cursor range, we need to remove the old
110 // range. Take note that Point does not belong to the range anymore.
111 pTmp = pTmp->GetNext();
112 delete pTmpDel; // Remove old range
113 pTmpDel = nullptr;
114 }
115}
116
117// SwCursorShell
118
124{
125 // don't create new Cursor with active table Selection
126 assert(!IsTableMode());
127
128 // ensure that m_pCurrentCursor is valid; if it's invalid it would be
129 // copied to pNew and then pNew would be deleted in UpdateCursor() below
131
132 // New cursor as copy of current one. Add to the ring.
133 // Links point to previously created one, ie forward.
135
136 // Hide PaM logically, to avoid undoing the inverting from
137 // copied PaM (#i75172#)
139
141
143 return pNew;
144}
145
152{
153 // don't delete Cursor with active table Selection
154 assert(!IsTableMode());
155
156 // Is there a next one? Don't do anything if not.
158 return;
159
160 SwCallLink aLk( *this ); // watch Cursor-Moves
161 SwCursor* pNextCursor = static_cast<SwCursor*>(m_pCurrentCursor->GetNext());
162 delete m_pCurrentCursor;
163 m_pCurrentCursor = dynamic_cast<SwShellCursor*>(pNextCursor);
164 UpdateCursor();
165}
166
173{
174 if (HasSelection())
175 {
176 (void) CreateCursor(); // n.b. returns old cursor
177 }
178 return *GetCursor();
179}
180
186{
187 return *GetCursor();
188}
189
194SwCursor* SwCursorShell::GetCursor( bool bMakeTableCursor ) const
195{
196 if( m_pTableCursor )
197 {
198 if( bMakeTableCursor && m_pTableCursor->IsCursorMovedUpdate() )
199 {
200 //don't re-create 'parked' cursors
203 {
205 if( pCNd && pCNd->getLayoutFrame( GetLayout() ) )
206 {
208 if( pCNd && pCNd->getLayoutFrame( GetLayout() ) )
209 {
211 GetLayout()->MakeTableCursors( *pTC );
212 }
213 }
214 }
215 }
216
217 if( m_pTableCursor->IsChgd() )
218 {
219 const_cast<SwCursorShell*>(this)->m_pCurrentCursor =
221 }
222 }
223 return m_pCurrentCursor;
224}
225
227{
228 if( !ActionPend() )
229 {
230 // save for update of the ribbon bar
231 const SwNode& rNd = m_pCurrentCursor->GetPoint()->GetNode();
232 m_nCurrentNode = rNd.GetIndex();
235 if( rNd.IsTextNode() )
237 else
238 m_nLeftFramePos = 0;
239 }
240 SwViewShell::StartAction(); // to the SwViewShell
241}
242
243void SwCursorShell::EndAction( const bool bIdleEnd )
244{
246 bool bVis = m_bSVCursorVis;
247
248 // Idle-formatting?
249 if( bIdleEnd && Imp()->HasPaintRegion() )
250 {
252 }
253
254 // Update all invalid numberings before the last action
255 if( 1 == mnStartAction )
257
258 // #i76923#: Don't show the cursor in the SwViewShell::EndAction() - call.
259 // Only the UpdateCursor shows the cursor.
260 bool bSavSVCursorVis = m_bSVCursorVis;
261 m_bSVCursorVis = false;
262
263 SwViewShell::EndAction( bIdleEnd ); // have SwViewShell go first
264
265 m_bSVCursorVis = bSavSVCursorVis;
266
267 if( ActionPend() )
268 {
269 if( bVis ) // display SV-Cursor again
271
272 return;
273 }
274
275 sal_uInt16 eFlags = SwCursorShell::CHKRANGE;
276 if ( !bIdleEnd )
277 eFlags |= SwCursorShell::SCROLLWIN;
278
279 UpdateCursor( eFlags, bIdleEnd ); // Show Cursor changes
280
281 {
282 SwCallLink aLk( *this ); // Watch cursor moves,
283 aLk.m_nNode = m_nCurrentNode; // possibly call the link
287
288 if( !m_nCursorMove ||
290 // display Cursor & Selections again
292 }
293 // call ChgCall if there is still one
295 {
296 m_aChgLnk.Call(nullptr);
297 m_bChgCallFlag = false; // reset flag
298 }
299}
300
302{
303#ifdef DBG_UTIL
304 OSL_ENSURE( m_nCursorMove < USHRT_MAX, "Too many nested CursorMoves." );
305#endif
307 StartAction();
308}
309
310void SwCursorShell::EndCursorMove( const bool bIdleEnd )
311{
312#ifdef DBG_UTIL
313 OSL_ENSURE( m_nCursorMove, "EndCursorMove() without SttCursorMove()." );
314#endif
315 EndAction( bIdleEnd );
317#ifdef DBG_UTIL
318 if( !m_nCursorMove )
319 m_bInCMvVisportChgd = false;
320#endif
321}
322
323bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, SwCursorSkipMode nMode,
324 bool bVisualAllowed )
325{
326 if( IsTableMode() )
327 return bLeft ? GoPrevCell() : GoNextCell();
328
329 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
330 bool bRet = false;
331
332 // #i27615# Handle cursor in front of label.
333 const SwTextNode* pTextNd = nullptr;
334
335 if( m_pBlockCursor )
337
338 // 1. CASE: Cursor is in front of label. A move to the right
339 // will simply reset the bInFrontOfLabel flag:
340 SwShellCursor* pShellCursor = getShellCursor( true );
341 if ( !bLeft && pShellCursor->IsInFrontOfLabel() )
342 {
343 SetInFrontOfLabel( false );
344 bRet = true;
345 }
346 // 2. CASE: Cursor is at beginning of numbered paragraph. A move
347 // to the left will simply set the bInFrontOfLabel flag:
348 else if (bLeft
349 && pShellCursor->GetPoint()->GetNode().IsTextNode()
350 && static_cast<SwTextFrame const*>(
351 pShellCursor->GetPoint()->GetNode().GetTextNode()->getLayoutFrame(GetLayout())
352 )->MapModelToViewPos(*pShellCursor->GetPoint()) == TextFrameIndex(0)
353 && !pShellCursor->IsInFrontOfLabel()
354 && !pShellCursor->HasMark()
355 && nullptr != (pTextNd = sw::GetParaPropsNode(*GetLayout(), pShellCursor->GetPoint()->GetNode()))
356 && pTextNd->HasVisibleNumberingOrBullet())
357 {
358 SetInFrontOfLabel( true );
359 bRet = true;
360 }
361 // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
362 else
363 {
364 const bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
365 // #i107447#
366 // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
367 // reflected in the return value <bRet>.
368 const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( false );
369 bRet = pShellCursor->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
370 bSkipHidden, !IsOverwriteCursor(),
371 GetLayout(),
372 GetViewOptions()->IsFieldName());
373 if ( !bRet && bLeft && bResetOfInFrontOfLabel )
374 {
375 // undo reset of <bInFrontOfLabel> flag
376 SetInFrontOfLabel( true );
377 }
378 }
379
380 if( bRet )
381 {
382 UpdateCursor();
383 }
384
385 return bRet;
386}
387
388void SwCursorShell::MarkListLevel( const OUString& sListId,
389 const int nListLevel )
390{
391 if (sListId == m_sMarkedListId && nListLevel == m_nMarkedListLevel)
392 return;
393
394 // Writer redraws the "marked" list with the field shading, if there
395 // is no field shading then the marked list would be redrawn for no
396 // visually identifiable reason, so skip the mark if field shadings
397 // are disabled.
398 const bool bVisuallyMarked(GetViewOptions()->IsFieldShadings());
399 if (bVisuallyMarked)
400 {
401 if ( !m_sMarkedListId.isEmpty() )
402 mxDoc->MarkListLevel( m_sMarkedListId, m_nMarkedListLevel, false );
403
404 if ( !sListId.isEmpty() )
405 mxDoc->MarkListLevel( sListId, nListLevel, true );
406 }
407
408 m_sMarkedListId = sListId;
409 m_nMarkedListLevel = nListLevel;
410}
411
413{
414 SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(),
415 GetCursor_()->GetPoint()->GetNode());
416
417 if ( !pTextNd )
418 return;
419
420 if (!pTextNd->IsNumbered(GetLayout()))
421 {
423 MarkListLevel( OUString(), 0 );
424 }
426 {
427 if ( pTextNd->IsInList() )
428 {
429 assert(pTextNd->GetActualListLevel() >= 0 &&
430 pTextNd->GetActualListLevel() < MAXLEVEL);
431 MarkListLevel( pTextNd->GetListId(),
432 pTextNd->GetActualListLevel() );
433 }
434 }
435 else
436 {
437 MarkListLevel( OUString(), 0 );
438 }
439}
440
441void SwCursorShell::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage)
442{
443#ifdef ACCESSIBLE_LAYOUT
444 if( Imp()->IsAccessible() )
445 Imp()->FirePageChangeEvent( nOldPage, nNewPage );
446#else
447 (void)nOldPage;
448 (void)nNewPage;
449#endif
450}
451
452void SwCursorShell::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn)
453{
454#ifdef ACCESSIBLE_LAYOUT
455 if( Imp()->IsAccessible() )
456 Imp()->FireColumnChangeEvent( nOldColumn, nNewColumn);
457#else
458 (void)nOldColumn;
459 (void)nNewColumn;
460#endif
461}
462
463void SwCursorShell::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection)
464{
465#ifdef ACCESSIBLE_LAYOUT
466 if( Imp()->IsAccessible() )
467 Imp()->FireSectionChangeEvent( nOldSection, nNewSection );
468#else
469 (void)nOldSection;
470 (void)nNewSection;
471#endif
472}
473
475{
476 SwFrame* pCurrFrame = GetCurrFrame(false);
477
478 if (pCurrFrame == nullptr)
479 {
480 return false;
481 }
482
483 SwFrame* pCurrCol=pCurrFrame->FindColFrame();
484
485 while(pCurrCol== nullptr && pCurrFrame!=nullptr )
486 {
487 SwLayoutFrame* pParent = pCurrFrame->GetUpper();
488 if(pParent!=nullptr)
489 {
490 pCurrCol=static_cast<SwFrame*>(pParent)->FindColFrame();
491 pCurrFrame = pParent;
492 }
493 else
494 {
495 break;
496 }
497 }
498
499 if(m_oldColFrame == pCurrCol)
500 return false;
501 else
502 {
503 m_oldColFrame = pCurrCol;
504 return true;
505 }
506}
507
508bool SwCursorShell::UpDown( bool bUp, sal_uInt16 nCnt )
509{
510 CurrShell aCurr( this );
511 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
512
513 bool bTableMode = IsTableMode();
514 SwShellCursor* pTmpCursor = getShellCursor( true );
515
516 bool bRet = pTmpCursor->UpDown( bUp, nCnt );
517 // #i40019# UpDown should always reset the bInFrontOfLabel flag:
518 bRet |= SetInFrontOfLabel(false);
519
520 if( m_pBlockCursor )
522
523 if( bRet )
524 {
525 m_eMvState = CursorMoveState::UpDown; // status for Cursor travelling - GetModelPositionForViewPoint
526 if( !ActionPend() )
527 {
529 if( !bTableMode )
530 eUpdateMode = static_cast<CursorFlag>(eUpdateMode
532 UpdateCursor( o3tl::narrowing<sal_uInt16>(eUpdateMode) );
533 }
534 }
535 return bRet;
536}
537
538bool SwCursorShell::LRMargin( bool bLeft, bool bAPI)
539{
540 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
541 CurrShell aCurr( this );
542 m_eMvState = CursorMoveState::LeftMargin; // status for Cursor travelling - GetModelPositionForViewPoint
543
544 const bool bTableMode = IsTableMode();
545 SwShellCursor* pTmpCursor = getShellCursor( true );
546
547 if( m_pBlockCursor )
549
550 const bool bWasAtLM = GetCursor_()->IsAtLeftRightMargin(*GetLayout(), true, bAPI);
551
552 bool bRet = pTmpCursor->LeftRightMargin(*GetLayout(), bLeft, bAPI);
553
554 if ( bLeft && !bTableMode && bRet && bWasAtLM && !GetCursor_()->HasMark() )
555 {
556 const SwTextNode * pTextNd = GetCursor_()->GetPointNode().GetTextNode();
557 assert(sw::GetParaPropsNode(*GetLayout(), GetCursor_()->GetPoint()->GetNode()) == pTextNd);
558 if ( pTextNd && pTextNd->HasVisibleNumberingOrBullet() )
560 }
561 else if ( !bLeft )
562 {
563 bRet = SetInFrontOfLabel( false ) || bRet;
564 }
565
566 if( bRet )
567 {
568 UpdateCursor();
569 }
570 return bRet;
571}
572
573bool SwCursorShell::IsAtLRMargin( bool bLeft, bool bAPI ) const
574{
575 const SwShellCursor* pTmpCursor = getShellCursor( true );
576 return pTmpCursor->IsAtLeftRightMargin(*GetLayout(), bLeft, bAPI);
577}
578
580{
581 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
582
584 bool bRet = pTmpCursor->SttEndDoc( bStt );
585 if( bRet )
586 {
587 if( bStt )
588 pTmpCursor->GetPtPos().setY( 0 ); // set to 0 explicitly (table header)
589 if( m_pBlockCursor )
590 {
593 }
594
596 }
597 return bRet;
598}
599
601{
602 if (m_pTableCursor)
603 { // find the table that has the selected boxes
604 return m_pTableCursor->GetSelectedBoxes()[0]->GetSttNd()->FindTableNode();
605 }
607}
608
609// fun cases to consider:
610// * outermost table
611// - into para => SA/ESA
612// - into prev/next table => continue...
613// - no prev/next => done
614// * inner table
615// - into containing cell => SA/ESA
616// - into prev/next of containing cell
617// + into para
618// + into table nested in prev/next cell
619// - out of table -> as above
620// => iterate in one direction until a node is reached that is a parent or a sibling of a parent of the current table
621// - parent reached => SA/ESA depending
622// - not in parent but in *prev/next* sibling of outer cell => TrySelectOuterTable
623// - not in parent but in *prev/next* sibling of outer table => TrySelectOuterTable
624// => select-all cannot select a sequence of table with no para at same level; only 1 table
625// - no parent, no prev/next => TrySelectOuterTable
626
628{
629 SwPosition const point(*getShellCursor(false)->GetPoint());
630 SwPosition const mark(*getShellCursor(false)->GetMark());
631
632 for (auto const fnMove : {&fnMoveBackward, &fnMoveForward})
633 {
634 Push();
635 SwCursor *const pCursor(getShellCursor(false));
636
637 pCursor->Normalize(fnMove == &fnMoveBackward);
638 pCursor->DeleteMark();
639 SwTableNode const*const pTable(pCursor->GetPoint()->GetNode().FindTableNode());
640 assert(pTable);
641 while (MovePara(GoInContent, *fnMove))
642 {
643 SwStartNode const*const pBox(pCursor->GetPoint()->GetNode().FindTableBoxStartNode());
644 if (!pBox)
645 {
647 return true; // moved to paragraph at top-level of text
648 }
649 if (pBox->GetIndex() < pTable->GetIndex()
650 && pTable->EndOfSectionIndex() < pBox->EndOfSectionIndex())
651 {
653 return true; // pBox contains start position (pTable)
654 }
655 }
656
658 // FIXME: Pop doesn't restore original cursor if nested tables
659 *getShellCursor(false)->GetPoint() = point;
660 getShellCursor(false)->SetMark();
661 *getShellCursor(false)->GetMark() = mark;
662 }
663 return false;
664}
665
667{
668 assert(m_pTableCursor);
669 SwTableNode const& rInnerTable(*m_pTableCursor->GetPoint()->GetNode().FindTableNode());
670 SwNodes const& rNodes(rInnerTable.GetNodes());
671 SwTableNode const*const pOuterTable(rInnerTable.GetNodes()[rInnerTable.GetIndex()-1]->FindTableNode());
672 if (!pOuterTable)
673 {
674 return false;
675 }
676
677 // manually select boxes of pOuterTable
678 SwNodeIndex firstCell(*pOuterTable, +1);
679 SwNodeIndex lastCell(*rNodes[pOuterTable->EndOfSectionIndex()-1]->StartOfSectionNode());
680 SwSelBoxes aNew;
681 pOuterTable->GetTable().CreateSelection(&firstCell.GetNode(), &lastCell.GetNode(),
682 aNew, SwTable::SEARCH_NONE, false);
683 // set table cursor to 1st / last content which may be in inner table
684 SwContentNode *const pStart = rNodes.GoNext(&firstCell);
685 assert(pStart); // must at least find the previous point node
686 lastCell = *lastCell.GetNode().EndOfSectionNode();
687 SwContentNode *const pEnd = SwNodes::GoPrevious(&lastCell);
688 assert(pEnd); // must at least find the previous point node
689 delete m_pTableCursor;
690 m_pTableCursor = new SwShellTableCursor(*this, SwPosition(*pStart, 0), Point(),
691 SwPosition(*pEnd, 0), Point());
693 m_pTableCursor->IsCursorMovedUpdate(); // clear this so GetCursor() doesn't recreate our SwSelBoxes
694
695 // this will update m_pCurrentCursor based on m_pTableCursor
697
698 return true;
699}
700
702static SwStartNode const* FindTextStart(SwPosition const& rPos)
703{
704 SwStartNode const* pStartNode(rPos.GetNode().StartOfSectionNode());
705 while (pStartNode && (pStartNode->IsSectionNode() || pStartNode->IsTableNode()))
706 {
707 pStartNode = pStartNode->StartOfSectionNode();
708 }
709 return pStartNode;
710}
711
712static SwStartNode const* FindParentText(SwShellCursor const& rCursor)
713{
714 // find closest section containing both start and end - ignore Sections
715 SwStartNode const* pStartNode(FindTextStart(*rCursor.Start()));
716 SwEndNode const* pEndNode(FindTextStart(*rCursor.End())->EndOfSectionNode());
717 while (pStartNode->EndOfSectionNode()->GetIndex() < pEndNode->GetIndex())
718 {
719 pStartNode = pStartNode->StartOfSectionNode();
720 }
721 while (pStartNode->GetIndex() < pEndNode->StartOfSectionNode()->GetIndex())
722 {
723 pEndNode = pEndNode->StartOfSectionNode()->StartOfSectionNode()->EndOfSectionNode();
724 }
725 assert(pStartNode->EndOfSectionNode() == pEndNode);
726
727 return (pStartNode->IsSectionNode() || pStartNode->IsTableNode())
728 ? FindTextStart(SwPosition(*pStartNode))
729 : pStartNode;
730}
731
733{
734 SwPosition const old(*m_pCurrentCursor->GetPoint());
735 SwStartNode const*const pStartNode(FindParentText(*getShellCursor(false)));
736 assert(pStartNode);
737 SwTableNode const*const pTable(pStartNode->FindTableNode());
738 m_pCurrentCursor->GetPoint()->Assign(*pStartNode);
740 while (m_pCurrentCursor->GetPoint()->GetNode().FindTableNode() != pTable
741 && (!pTable || pTable->GetIndex() < m_pCurrentCursor->GetPoint()->GetNode().FindTableNode()->GetIndex())
742 && MoveOutOfTable());
744 return old != *m_pCurrentCursor->GetPoint();
745}
746
747// select all inside the current XText, with table or hidden para at start/end
749{
750 // find common ancestor node of both ends of cursor
751 SwStartNode const*const pStartNode(FindParentText(*getShellCursor(false)));
752 assert(pStartNode);
753 if (IsTableMode())
754 { // convert m_pTableCursor to m_pCurrentCursor after determining pStartNode
756 }
757 SwNodes& rNodes = GetDoc()->GetNodes();
760 pPos->Assign(bFootnotes ? rNodes.GetEndOfPostIts() : static_cast<SwNode const&>(*pStartNode));
761 rNodes.GoNext( pPos );
762 pPos = m_pCurrentCursor->GetMark();
763 pPos->Assign(bFootnotes ? rNodes.GetEndOfContent() : static_cast<SwNode const&>(*pStartNode->EndOfSectionNode()));
764 SwContentNode* pCNd = SwNodes::GoPrevious( pPos );
765 if (pCNd)
766 pPos->AssignEndIndex(*pCNd);
767}
768
770{
771 for (auto i = rStart.GetIndex() + 1; i < rStart.EndOfSectionIndex(); ++i)
772 {
773 SwNode const& rNode(*rStart.GetNodes()[i]);
774 switch (rNode.GetNodeType())
775 {
777 continue;
780 case SwNodeType::Text:
781 if (rNode.GetTextNode()->IsHidden())
782 {
784 }
786 default:
788 }
789 }
791}
792
793static typename SwCursorShell::StartsWith EndsWith(SwStartNode const& rStart)
794{
795 for (auto i = rStart.EndOfSectionIndex() - 1; rStart.GetIndex() < i; --i)
796 {
797 SwNode const& rNode(*rStart.GetNodes()[i]);
798 switch (rNode.GetNodeType())
799 {
800 case SwNodeType::End:
801 if (rNode.StartOfSectionNode()->IsTableNode())
802 {
804 }
805//TODO buggy SwUndoRedline in testTdf137503? assert(rNode.StartOfSectionNode()->IsSectionNode());
806 break;
807 case SwNodeType::Text:
808 if (rNode.GetTextNode()->IsHidden())
809 {
811 }
813 default:
815 }
816 }
818}
819
820// return the node that is the start of the extended selection (to include table
821// or section start nodes; looks like extending for end nodes is not required)
822::std::optional<::std::pair<SwNode const*, ::std::vector<SwTableNode*>>>
824{
825 if (m_pTableCursor)
826 {
827 return {};
828 }
829
830 SwNodes& rNodes = GetDoc()->GetNodes();
831 SwShellCursor const*const pShellCursor = getShellCursor(false);
832 SwStartNode const* pStartNode(FindParentText(*pShellCursor));
833
834 SwNodeIndex nNode(*pStartNode);
835 SwContentNode* pStart = rNodes.GoNext(&nNode);
836 if (!pStart)
837 {
838 return {};
839 }
840
841 nNode = *pStartNode->EndOfSectionNode();
842 SwContentNode* pEnd = SwNodes::GoPrevious(&nNode);
843 if (!pEnd)
844 {
845 return {};
846 }
847
848 SwPosition aStart(*pStart, 0);
849 SwPosition aEnd(*pEnd, pEnd->Len());
850 if (!(aStart == *pShellCursor->Start() && aEnd == *pShellCursor->End()))
851 {
852 return {};
853 }
854
855 auto const ends(::EndsWith(*pStartNode));
856 if (::StartsWith(*pStartNode) == StartsWith::None
857 && ends == StartsWith::None)
858 {
859 return {}; // "ordinary" selection will work
860 }
861
862 ::std::vector<SwTableNode*> tablesAtEnd;
863 if (ends == StartsWith::Table)
864 {
865 SwNode * pLastNode(rNodes[pStartNode->EndOfSectionIndex() - 1]);
866 while (pLastNode->IsEndNode())
867 {
868 SwNode *const pNode(pLastNode->StartOfSectionNode());
869 if (pNode->IsTableNode())
870 {
871 tablesAtEnd.push_back(pNode->GetTableNode());
872 pLastNode = rNodes[pNode->GetIndex() - 1];
873 }
874 else if (pNode->IsSectionNode())
875 {
876 pLastNode = rNodes[pLastNode->GetIndex() - 1];
877 }
878 }
879 assert(!tablesAtEnd.empty());
880 }
881
882 // tdf#133990 ensure directly containing section is included in SwUndoDelete
883 while (pStartNode->IsSectionNode()
884 && pStartNode->GetIndex() == pStartNode->StartOfSectionNode()->GetIndex() + 1
885 && pStartNode->EndOfSectionNode()->GetIndex() + 1 == pStartNode->StartOfSectionNode()->EndOfSectionNode()->GetIndex())
886 {
887 pStartNode = pStartNode->StartOfSectionNode();
888 }
889
890 // pStartNode is the node that fully contains the selection - the first
891 // node of the selection is the first node inside pStartNode
892 return ::std::make_pair(rNodes[pStartNode->GetIndex() + 1], tablesAtEnd);
893}
894
896{
897 SwShellCursor const*const pShellCursor = getShellCursor(false);
898 // first, check if this is invalid; ExtendedSelectAll(true) may result in
899 // a) an ordinary selection that is valid
900 // b) a selection that is extended
901 // c) a selection that is invalid and will cause FindParentText to loop
902 SwNode const& rEndOfExtras(GetDoc()->GetNodes().GetEndOfExtras());
903 if (pShellCursor->Start()->nNode.GetIndex() <= rEndOfExtras.GetIndex()
904 && rEndOfExtras.GetIndex() < pShellCursor->End()->nNode.GetIndex())
905 {
906 return StartsWith::None; // *very* extended, no ExtendedSelectedAll handling!
907 }
908 SwStartNode const*const pStartNode(FindParentText(*pShellCursor));
909 if (auto const ret = ::StartsWith(*pStartNode); ret != StartsWith::None)
910 {
911 return ret;
912 }
913 if (auto const ret = ::EndsWith(*pStartNode); ret != StartsWith::None)
914 {
915 return ret;
916 }
917 return StartsWith::None;
918}
919
920bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
921{
922 bool bRet = false;
923
924 // never jump of section borders at selection
926 {
927 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
928 CurrShell aCurr( this );
929
930 SwCursorSaveState aSaveState( *m_pCurrentCursor );
932 std::pair<Point, bool> tmp(rPt, false);
934 getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint(), &tmp);
935 if( pFrame && GetFrameInPage( pFrame, fnWhichPage, fnPosPage, m_pCurrentCursor ) &&
938 {
939 UpdateCursor();
940 bRet = true;
941 }
942 }
943 return bRet;
944}
945
947{
948 SwContentNode *pCNode = pShellCursor->GetPointContentNode();
949 std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false);
950 SwContentFrame *const pFrame = pCNode
951 ? pCNode->getLayoutFrame(GetLayout(), pShellCursor->GetPoint(), &tmp)
952 : nullptr;
953 return !pFrame || (pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow());
954}
955
956// sw_redlinehide: this should work for all cases: GoCurrPara, GoNextPara, GoPrevPara
957static bool IsAtStartOrEndOfFrame(SwCursorShell const*const pShell,
958 SwShellCursor const*const pShellCursor, SwMoveFnCollection const& fnPosPara)
959{
960 SwContentNode *const pCNode = pShellCursor->GetPointContentNode();
961 assert(pCNode); // surely can't have moved otherwise?
962 std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false);
963 SwContentFrame const*const pFrame = pCNode->getLayoutFrame(
964 pShell->GetLayout(), pShellCursor->GetPoint(), &tmp);
965 if (!pFrame || !pFrame->IsTextFrame())
966 {
967 return false;
968 }
969 SwTextFrame const& rTextFrame(static_cast<SwTextFrame const&>(*pFrame));
970 TextFrameIndex const ix(rTextFrame.MapModelToViewPos(*pShellCursor->GetPoint()));
971 if (&fnParaStart == &fnPosPara)
972 {
973 return ix == TextFrameIndex(0);
974 }
975 else
976 {
977 assert(&fnParaEnd == &fnPosPara);
978 return ix == TextFrameIndex(rTextFrame.GetText().getLength());
979 }
980}
981
982bool SwCursorShell::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPosPara )
983{
984 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
985 SwShellCursor* pTmpCursor = getShellCursor( true );
986 bool bRet = pTmpCursor->MovePara( fnWhichPara, fnPosPara );
987 if( bRet )
988 {
989 //keep going until we get something visible, i.e. skip
990 //over hidden paragraphs, don't get stuck at the start
991 //which is what SwCursorShell::UpdateCursorPos will reset
992 //the position to if we pass it a position in an
993 //invisible hidden paragraph field
994 while (isInHiddenTextFrame(pTmpCursor)
995 || !IsAtStartOrEndOfFrame(this, pTmpCursor, fnPosPara))
996 {
997 if (!pTmpCursor->MovePara(fnWhichPara, fnPosPara))
998 break;
999 }
1000
1001 UpdateCursor();
1002 }
1003 return bRet;
1004}
1005
1007 SwMoveFnCollection const & fnPosSect)
1008{
1009 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1010 SwCursor* pTmpCursor = getShellCursor( true );
1011 bool bRet = pTmpCursor->MoveSection( fnWhichSect, fnPosSect );
1012 if( bRet )
1013 UpdateCursor();
1014 return bRet;
1015
1016}
1017
1018// position cursor
1019
1021{
1022 SwFrame* pFrame = nullptr;
1023 SwContentNode* pCNd = rNd.GetContentNode();
1024 if( pCNd )
1025 {
1026 std::pair<Point, bool> tmp(rPt, false);
1027 SwContentFrame *pContentFrame = pCNd->getLayoutFrame(
1029 nullptr, &tmp);
1030 pFrame = pContentFrame ? pContentFrame->GetUpper() : nullptr;
1031 while( pFrame && !pFrame->IsHeaderFrame() && !pFrame->IsFooterFrame() )
1032 pFrame = pFrame->IsFlyFrame() ? static_cast<SwFlyFrame*>(pFrame)->AnchorFrame()
1033 : pFrame->GetUpper();
1034 }
1035 return pFrame;
1036}
1037
1038bool SwCursorShell::IsInHeaderFooter( bool* pbInHeader ) const
1039{
1040 Point aPt;
1042 if( pFrame && pbInHeader )
1043 *pbInHeader = pFrame->IsHeaderFrame();
1044 return nullptr != pFrame;
1045}
1046
1047int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
1048{
1049 CurrShell aCurr( this );
1050
1051 SwShellCursor* pCursor = getShellCursor( bBlock );
1052 SwPosition aPos( *pCursor->GetPoint() );
1053 Point aPt( rLPt );
1054 Point & rCurrentCursorPt = pCursor->GetPtPos();
1058
1059 SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
1060
1061 if ( pTextNd && !IsTableMode() &&
1062 // #i37515# No bInFrontOfLabel during selection
1063 !pCursor->HasMark() &&
1064 pTextNd->HasVisibleNumberingOrBullet() )
1065 {
1066 aTmpState.m_bInFrontOfLabel = true; // #i27615#
1067 }
1068 else
1069 {
1070 aTmpState.m_bInFrontOfLabel = false;
1071 }
1072
1073 int bRet = CRSR_POSOLD |
1074 ( GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState )
1075 ? 0 : CRSR_POSCHG );
1076
1077 const bool bOldInFrontOfLabel = IsInFrontOfLabel();
1078 const bool bNewInFrontOfLabel = aTmpState.m_bInFrontOfLabel;
1079
1080 pCursor->SetCursorBidiLevel( aTmpState.m_nCursorBidiLevel );
1081
1082 if( CursorMoveState::RightMargin == aTmpState.m_eState )
1084 // is the new position in header or footer?
1085 SwFrame* pFrame = lcl_IsInHeaderFooter( aPos.GetNode(), aPt );
1086 if( IsTableMode() && !pFrame && aPos.GetNode().StartOfSectionNode() ==
1087 pCursor->GetPoint()->GetNode().StartOfSectionNode() )
1088 // same table column and not in header/footer -> back
1089 return bRet;
1090
1091 if( m_pBlockCursor && bBlock )
1092 {
1093 m_pBlockCursor->setEndPoint( rLPt );
1094 if( !pCursor->HasMark() )
1096 else if( !m_pBlockCursor->getStartPoint() )
1097 m_pBlockCursor->setStartPoint( pCursor->GetMkPos() );
1098 }
1099 if( !pCursor->HasMark() )
1100 {
1101 // is at the same position and if in header/footer -> in the same
1102 if( aPos == *pCursor->GetPoint() &&
1103 bOldInFrontOfLabel == bNewInFrontOfLabel )
1104 {
1105 if( pFrame )
1106 {
1107 if( pFrame->getFrameArea().Contains( rCurrentCursorPt ))
1108 return bRet;
1109 }
1110 else if( aPos.GetNode().IsContentNode() )
1111 {
1112 // in the same frame?
1113 std::pair<Point, bool> tmp(m_aCharRect.Pos(), false);
1114 SwFrame* pOld = static_cast<SwContentNode&>(aPos.GetNode()).getLayoutFrame(
1115 GetLayout(), nullptr, &tmp);
1116 tmp.first = aPt;
1117 SwFrame* pNew = static_cast<SwContentNode&>(aPos.GetNode()).getLayoutFrame(
1118 GetLayout(), nullptr, &tmp);
1119 if( pNew == pOld )
1120 return bRet;
1121 }
1122 }
1123 }
1124 else
1125 {
1126 // SSelection over not allowed sections or if in header/footer -> different
1127 if( !CheckNodesRange( aPos.GetNode(), pCursor->GetMark()->GetNode(), true )
1128 || ( pFrame && !pFrame->getFrameArea().Contains( pCursor->GetMkPos() ) ))
1129 return bRet;
1130
1131 // is at same position but not in header/footer
1132 if( aPos == *pCursor->GetPoint() )
1133 return bRet;
1134 }
1135
1136 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1137 SwCursorSaveState aSaveState( *pCursor );
1138
1139 *pCursor->GetPoint() = aPos;
1140 rCurrentCursorPt = aPt;
1141
1142 // #i41424# Only update the marked number levels if necessary
1143 // Force update of marked number levels if necessary.
1144 if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
1145 m_pCurrentCursor->SetInFrontOfLabel_( !bNewInFrontOfLabel );
1146 SetInFrontOfLabel( bNewInFrontOfLabel );
1147
1148 if( !pCursor->IsSelOvr( SwCursorSelOverFlags::ChangePos ) )
1149 {
1151 bRet &= ~CRSR_POSOLD;
1152 }
1153 else if( bOnlyText && !m_pCurrentCursor->HasMark() )
1154 {
1155 if( FindValidContentNode( bOnlyText ) )
1156 {
1157 // position cursor in a valid content
1158 if( aPos == *pCursor->GetPoint() )
1159 bRet = CRSR_POSOLD;
1160 else
1161 {
1162 UpdateCursor();
1163 bRet &= ~CRSR_POSOLD;
1164 }
1165 }
1166 else
1167 {
1168 // there is no valid content -> hide cursor
1169 m_pVisibleCursor->Hide(); // always hide visible cursor
1170 m_eMvState = CursorMoveState::NONE; // status for Cursor travelling
1171 m_bAllProtect = true;
1172 if( GetDoc()->GetDocShell() )
1173 {
1175 CallChgLnk(); // notify UI
1176 }
1177 }
1178 }
1179 return bRet;
1180}
1181
1183{
1184 assert(m_pTableCursor);
1185 delete m_pTableCursor;
1186 m_pTableCursor = nullptr;
1187}
1188
1190{
1191 assert(m_pBlockCursor);
1192 if( m_pBlockCursor && !HasSelection() )
1193 {
1196 *m_pCurrentCursor->GetPoint() = *rPam.GetPoint();
1197 if( rPam.HasMark() )
1198 *m_pCurrentCursor->GetMark() = *rPam.GetMark();
1199 else
1201 }
1202 delete m_pBlockCursor;
1203 m_pBlockCursor = nullptr;
1204}
1205
1207{
1208 if( !m_pBlockCursor )
1209 {
1211 m_pBlockCursor = new SwBlockCursor( *this, aPos );
1213 rBlock.GetPtPos() = m_pCurrentCursor->GetPtPos();
1214 if( m_pCurrentCursor->HasMark() )
1215 {
1216 rBlock.SetMark();
1217 *rBlock.GetMark() = *m_pCurrentCursor->GetMark();
1218 rBlock.GetMkPos() = m_pCurrentCursor->GetMkPos();
1219 }
1220 }
1223}
1224
1226{
1227 // is there any GetMark?
1228 if( m_pTableCursor )
1229 {
1230 std::vector<SwPaM*> vCursors;
1231 for(auto& rCursor : m_pCurrentCursor->GetRingContainer())
1232 if(&rCursor != m_pCurrentCursor)
1233 vCursors.push_back(&rCursor);
1234 for(auto pCursor : vCursors)
1235 delete pCursor;
1237
1239
1242 delete m_pTableCursor;
1243 m_pTableCursor = nullptr;
1244 m_pCurrentCursor->SwSelPaintRects::Show();
1245 }
1246 else
1247 {
1248 if( !m_pCurrentCursor->HasMark() )
1249 return;
1251 if( !m_nCursorMove )
1252 m_pCurrentCursor->SwSelPaintRects::Show();
1253 }
1254}
1255
1256void SwCursorShell::NormalizePam(bool bPointFirst)
1257{
1258 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1259 m_pCurrentCursor->Normalize(bPointFirst);
1260}
1261
1263{
1264 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1266}
1267
1268//TODO: provide documentation
1278 const Point & rPt,
1279 bool bTstHit )
1280{
1281 CurrShell aCurr( this );
1282
1283 // check if the SPoint is in a table selection
1284 if( m_pTableCursor )
1285 return m_pTableCursor->Contains( rPt );
1286
1287 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1288 // search position <rPt> in document
1289 SwPosition aPtPos( *m_pCurrentCursor->GetPoint() );
1290 Point aPt( rPt );
1291
1294 if ( !GetLayout()->GetModelPositionForViewPoint( &aPtPos, aPt, &aTmpState ) && bTstHit )
1295 return false;
1296
1297 // search in all selections for this position
1298 SwShellCursor* pCmp = m_pCurrentCursor; // keep the pointer on cursor
1299 do
1300 {
1301 if (pCmp->HasMark() && *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos)
1302 return true; // return without update
1303 pCmp = pCmp->GetNext();
1304 } while (m_pCurrentCursor != pCmp);
1305 return false;
1306}
1307
1309{
1310 // Does any exist for deletion?
1312 return;
1313
1315 delete m_pCurrentCursor->GetNext();
1317
1318 if( m_pTableCursor )
1319 {
1320 // delete the ring of cursors
1324 delete m_pTableCursor;
1325 m_pTableCursor = nullptr;
1326 }
1327 else if( m_pBlockCursor )
1328 {
1329 // delete the ring of cursors
1332 *m_pCurrentCursor->GetPoint() = *rBlock.GetPoint();
1333 m_pCurrentCursor->GetPtPos() = rBlock.GetPtPos();
1334 rBlock.DeleteMark();
1336 }
1338}
1339
1341{
1342 int nRet = 0;
1343 const SwPosition *pFirst = nullptr, *pSecond = nullptr;
1344 const SwCursor *pCur = GetCursor(), *pStack = m_pStackCursor;
1345 // cursor on stack is needed if we compare against stack
1346 if( pStack )
1347 {
1348 pFirst = pStack->GetMark();
1349 pSecond = pCur->GetPoint();
1350 }
1351 if( !pFirst || !pSecond )
1352 nRet = INT_MAX;
1353 else if( *pFirst < *pSecond )
1354 nRet = -1;
1355 else if( *pFirst == *pSecond )
1356 nRet = 0;
1357 else
1358 nRet = 1;
1359 return nRet;
1360}
1361
1363{
1365 {
1366 return false;
1367 }
1369 {
1370 return true;
1371 }
1372 if (GetLayout()->HasMergedParas())
1373 {
1374 SwContentFrame const*const pFrame(GetCurrFrame(false));
1375 auto const n(m_pCurrentCursor->GetMark()->GetNodeIndex());
1376 return FrameContainsNode(*pFrame, n);
1377 }
1378 return false;
1379}
1380
1382{
1383 if (GetLayout()->HasMergedParas())
1384 {
1385 SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode());
1386 if (pNode)
1387 {
1388 SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
1389 pNode->getLayoutFrame(GetLayout())));
1390 if (pFrame)
1391 {
1392 return pFrame->MapModelToViewPos(*m_pCurrentCursor->GetPoint())
1393 == TextFrameIndex(0);
1394 }
1395 }
1396 }
1397 return m_pCurrentCursor->GetPoint()->GetContentIndex() == 0;
1398}
1399
1401{
1402 if (GetLayout()->HasMergedParas())
1403 {
1404 SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode());
1405 if (pNode)
1406 {
1407 SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
1408 pNode->getLayoutFrame(GetLayout())));
1409 if (pFrame)
1410 {
1411 return pFrame->MapModelToViewPos(*m_pCurrentCursor->GetPoint())
1412 == TextFrameIndex(pFrame->GetText().getLength());
1413 }
1414 }
1415 }
1417}
1418
1420{
1421 if (IsTableMode() || IsBlockMode() || !IsEndPara())
1422 {
1423 return false;
1424 }
1425 SwTableNode const*const pTableNode( IsCursorInTable() );
1426 if (!pTableNode)
1427 {
1428 return false;
1429 }
1430 SwEndNode const*const pEndTableNode(pTableNode->EndOfSectionNode());
1431 SwNodeIndex const lastNode(*pEndTableNode, -2);
1432 SAL_WARN_IF(!lastNode.GetNode().GetTextNode(), "sw.core",
1433 "text node expected");
1434 return (lastNode == m_pCurrentCursor->GetPoint()->GetNode());
1435}
1436
1438{
1440 return aStartNodeType == SwStartNodeType::SwFootnoteStartNode;
1441}
1442
1444{
1445 Point aRet(-1, -1);
1446 if (SwFrame *pFrame = GetCurrFrame())
1447 {
1448 if (SwPageFrame* pCurrentPage = pFrame->FindPageFrame())
1449 {
1450 const Point& rDocPos = GetCursorDocPos();
1451 aRet = rDocPos - pCurrentPage->getFrameArea().TopLeft();
1452 }
1453 }
1454 return aRet;
1455}
1456
1458{
1460}
1461
1463{
1464 if ( bNew != IsInFrontOfLabel() )
1465 {
1468 return true;
1469 }
1470 return false;
1471}
1472
1473namespace {
1474
1475void collectUIInformation(const OUString& aPage)
1476{
1477 EventDescription aDescription;
1478 aDescription.aAction = "GOTO";
1479 aDescription.aParameters = {{"PAGE", aPage}};
1480 aDescription.aID = "writer_edit";
1481 aDescription.aKeyWord = "SwEditWinUIObject";
1482 aDescription.aParent = "MainWindow";
1483 UITestLogger::getInstance().logEvent(aDescription);
1484}
1485
1486}
1487
1488bool SwCursorShell::GotoPage( sal_uInt16 nPage )
1489{
1490 CurrShell aCurr( this );
1491 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1492 SwCursorSaveState aSaveState( *m_pCurrentCursor );
1493 bool bRet = GetLayout()->SetCurrPage( m_pCurrentCursor, nPage ) &&
1496 if( bRet )
1498
1499 collectUIInformation(OUString::number(nPage));
1500 return bRet;
1501}
1502
1504{
1505 SwContentFrame* pFrame = GetCurrFrame();
1506 pFrame->GetCharRect( rRect, *pPos );
1507}
1508
1509void SwCursorShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
1510 bool bAtCursorPos, const bool bCalcFrame )
1511{
1512 CurrShell aCurr( this );
1513 // page number: first visible page or the one at the cursor
1514 const SwContentFrame* pCFrame;
1515 const SwPageFrame *pPg = nullptr;
1516
1517 if( !bAtCursorPos || nullptr == (pCFrame = GetCurrFrame( bCalcFrame )) ||
1518 nullptr == (pPg = pCFrame->FindPageFrame()) )
1519 {
1520 pPg = Imp()->GetFirstVisPage(GetOut());
1521 while( pPg && pPg->IsEmptyPage() )
1522 pPg = static_cast<const SwPageFrame *>(pPg->GetNext());
1523 }
1524 // pPg has to exist with a default of 1 for the special case "Writerstart"
1525 rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
1526 rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
1527}
1528
1530{
1531 CurrShell aCurr(this);
1532 // page number: first visible page or the one at the cursor
1533 const SwContentFrame* pCFrame = GetCurrFrame(/*bCalcFrame*/true);
1534 const SwPageFrame* pPg = nullptr;
1535
1536 if (pCFrame == nullptr || nullptr == (pPg = pCFrame->FindPageFrame()))
1537 {
1538 pPg = Imp()->GetFirstVisPage(GetOut());
1539 while (pPg && pPg->IsEmptyPage())
1540 pPg = static_cast<const SwPageFrame*>(pPg->GetNext());
1541 }
1542
1543 sal_uInt16 nPageNo = 0;
1544 while (pPg)
1545 {
1546 if (!pPg->IsEmptyPage())
1547 ++nPageNo;
1548 pPg = static_cast<const SwPageFrame*>(pPg->GetPrev());
1549 }
1550 return nPageNo;
1551}
1552
1554{
1555 CurrShell aCurr( this );
1556 // page number: first visible page or the one at the cursor
1557 const SwPageFrame *pPg = Imp()->GetFirstVisPage(GetOut());
1558 if( pPg )
1559 {
1560 const SwTwips nPageTop = pPg->getFrameArea().Top();
1561
1562 if( bNext )
1563 {
1564 // go to next view layout row:
1565 do
1566 {
1567 pPg = static_cast<const SwPageFrame *>(pPg->GetNext());
1568 }
1569 while( pPg && pPg->getFrameArea().Top() == nPageTop );
1570
1571 while( pPg && pPg->IsEmptyPage() )
1572 pPg = static_cast<const SwPageFrame *>(pPg->GetNext());
1573 }
1574 else
1575 {
1576 // go to previous view layout row:
1577 do
1578 {
1579 pPg = static_cast<const SwPageFrame *>(pPg->GetPrev());
1580 }
1581 while( pPg && pPg->getFrameArea().Top() == nPageTop );
1582
1583 while( pPg && pPg->IsEmptyPage() )
1584 pPg = static_cast<const SwPageFrame *>(pPg->GetPrev());
1585 }
1586 }
1587 // pPg has to exist with a default of 1 for the special case "Writerstart"
1588 return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
1589}
1590
1592{
1593 CurrShell aCurr( this );
1594 // return number of pages
1595 return GetLayout()->GetPageNum();
1596}
1597
1599{
1600 CurrShell aCurr(this);
1601 SwRootFrame* pLayout = GetLayout();
1602 OUStringBuffer aBuf;
1603 for (const SwFrame* pFrame = pLayout->GetLower(); pFrame; pFrame = pFrame->GetNext())
1604 {
1605 aBuf.append(OUString::number(pFrame->getFrameArea().Left())
1606 + ", "
1607 + OUString::number(pFrame->getFrameArea().Top())
1608 + ", "
1609 + OUString::number(pFrame->getFrameArea().Width())
1610 + ", "
1611 + OUString::number(pFrame->getFrameArea().Height())
1612 + "; ");
1613 }
1614 if (!aBuf.isEmpty())
1615 aBuf.setLength( aBuf.getLength() - 2); // remove the last "; "
1616 return aBuf.makeStringAndClear();
1617}
1618
1620{
1621 auto pView = const_cast<SdrView*>(GetDrawView());
1622 if (pView->GetTextEditObject())
1623 {
1624 // Blinking cursor.
1625 EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
1626 rEditView.RegisterOtherShell(pOtherShell);
1627 rEditView.ShowCursor();
1628 rEditView.RegisterOtherShell(nullptr);
1629 // Text selection, if any.
1630 rEditView.DrawSelectionXOR(pOtherShell);
1631
1632 // Shape text lock.
1633 if (OutlinerView* pOutlinerView = pView->GetTextEditOutlinerView())
1634 {
1635 OString sRect = pOutlinerView->GetOutputArea().toString();
1636 SfxLokHelper::notifyOtherView(GetSfxViewShell(), pOtherShell, LOK_CALLBACK_VIEW_LOCK, "rectangle", sRect);
1637 }
1638 }
1639 else
1640 {
1641 // Cursor position.
1642 m_pVisibleCursor->SetPosAndShow(pOtherShell);
1643 // Cursor visibility.
1644 if (GetSfxViewShell() != pOtherShell)
1645 {
1646 OString aPayload = OString::boolean(m_bSVCursorVis);
1647 SfxLokHelper::notifyOtherView(GetSfxViewShell(), pOtherShell, LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload);
1648 }
1649 // Text selection.
1650 m_pCurrentCursor->Show(pOtherShell);
1651 // Graphic selection.
1652 pView->AdjustMarkHdl(pOtherShell);
1653 }
1654}
1655
1658{
1660 return false;
1661
1662 CurrShell aCurr( this );
1663 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1665
1666 // #i24086#: show also all others
1667 if( !ActionPend() )
1668 {
1669 UpdateCursor();
1670 m_pCurrentCursor->Show(nullptr);
1671 }
1672 return true;
1673}
1674
1677{
1679 return false;
1680
1681 CurrShell aCurr( this );
1682 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
1684
1685 // #i24086#: show also all others
1686 if( !ActionPend() )
1687 {
1688 UpdateCursor();
1689 m_pCurrentCursor->Show(nullptr);
1690 }
1691 return true;
1692}
1693
1695{
1696 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
1697
1699 {
1700 if( !m_pCurrentCursor->HasMark() )
1701 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
1702 return;
1703 }
1704
1705 if (bNext)
1706 GoNextCursor();
1707 else
1708 GoPrevCursor();
1709}
1710
1712{
1714 CurrShell aCurr( this );
1715
1716 // always switch off all cursors when painting
1717 SwRect aRect( rRect );
1718
1719 bool bVis = false;
1720 // if a cursor is visible then hide the SV cursor
1721 if( m_pVisibleCursor->IsVisible() && !aRect.Overlaps( m_aCharRect ) )
1722 {
1723 bVis = true;
1725 }
1726
1727 // re-paint area
1728 SwViewShell::Paint(rRenderContext, rRect);
1729
1731 {
1733
1734 if( !ActionPend() )
1735 {
1736 // so that right/bottom borders will not be cropped
1737 pCurrentCursor->Invalidate( VisArea() );
1738 pCurrentCursor->Show(nullptr);
1739 }
1740 else
1741 pCurrentCursor->Invalidate( aRect );
1742
1743 }
1744
1745 if (SwPostItMgr* pPostItMgr = GetPostItMgr())
1746 {
1747 // No point in showing the cursor for Writer text when there is an
1748 // active annotation edit.
1749 if (bVis)
1750 bVis = !pPostItMgr->HasActiveSidebarWin();
1751 }
1752
1753 if( m_bSVCursorVis && bVis ) // also show SV cursor again
1755}
1756
1758{
1759 CurrShell aCurr( this );
1760 bool bVis; // switch off all cursors when scrolling
1761
1762 // if a cursor is visible then hide the SV cursor
1763 bVis = m_pVisibleCursor->IsVisible();
1764 if( bVis )
1766
1767 m_bVisPortChgd = true;
1770
1771 // For not having problems with the SV cursor, Update() is called for the
1772 // Window in SwViewShell::VisPo...
1773 // During painting no selections should be shown, thus the call is encapsulated. <- TODO: old artefact?
1774 SwViewShell::VisPortChgd( rRect ); // move area
1775
1776 if( m_bSVCursorVis && bVis ) // show SV cursor again
1778
1779 if( m_nCursorMove )
1780 m_bInCMvVisportChgd = true;
1781
1782 m_bVisPortChgd = false;
1783}
1784
1792{
1793 CurrShell aCurr( this );
1794 ++mnStartAction;
1795 SwShellCursor* pShellCursor = getShellCursor( true );
1796 Size aOldSz( GetDocSize() );
1797
1798 if (isInHiddenTextFrame(pShellCursor) && !ExtendedSelectedAll())
1799 {
1802 GetLayout()->GetModelPositionForViewPoint( pShellCursor->GetPoint(), pShellCursor->GetPtPos(),
1803 &aTmpState );
1804 pShellCursor->DeleteMark();
1805 }
1806 auto* pDoc = GetDoc();
1807 if (pDoc)
1808 {
1809 pDoc->getGrammarContact()->updateCursorPosition(*m_pCurrentCursor->GetPoint());
1810 pDoc->getOnlineAccessibilityCheck()->update(*m_pCurrentCursor->GetPoint());
1811 }
1812
1813 --mnStartAction;
1814 if( aOldSz != GetDocSize() )
1815 SizeChgNotify();
1816}
1817
1818// #i65475# - if Point/Mark in hidden sections, move them out
1820{
1821 bool bOk = true;
1822 const SwSectionNode* pSectNd = rPos.GetNode().FindSectionNode();
1823 if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1824 {
1825 const SwNode* pFrameNd =
1826 rPos.GetNodes().FindPrvNxtFrameNode( *pSectNd, pSectNd->EndOfSectionNode() );
1827 bOk = pFrameNd != nullptr;
1828 SAL_WARN_IF(!bOk, "sw.core", "found no Node with Frames");
1829 rPos.Assign( *(bOk ? pFrameNd : pSectNd) );
1830 }
1831 return bOk;
1832}
1833
1836{
1837 SwNodeIndex aTmp( rPos.GetNode() );
1838 SwTextNode* pTextNd = aTmp.GetNode().GetTextNode();
1839 while( pTextNd && pTextNd->HasHiddenCharAttribute( true ) )
1840 {
1841 SwContentNode* pContent = aTmp.GetNodes().GoNext( &aTmp );
1842 if ( pContent && pContent->IsTextNode() )
1843 pTextNd = pContent->GetTextNode();
1844 else
1845 pTextNd = nullptr;
1846 }
1847
1848 if ( pTextNd )
1849 rPos.Assign( *pTextNd, 0 );
1850}
1851
1852#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1853namespace {
1854
1855// #i27301# - helper class that notifies the accessibility about invalid text
1856// selections in its destructor
1857class SwNotifyAccAboutInvalidTextSelections
1858{
1859 private:
1860 SwCursorShell& mrCursorSh;
1861
1862 public:
1863 explicit SwNotifyAccAboutInvalidTextSelections( SwCursorShell& _rCursorSh )
1864 : mrCursorSh( _rCursorSh )
1865 {}
1866
1867 ~SwNotifyAccAboutInvalidTextSelections() COVERITY_NOEXCEPT_FALSE
1868 {
1870 }
1871};
1872
1873}
1874#endif
1875
1876void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
1877{
1878 CurrShell aCurr( this );
1880
1881 if (ActionPend())
1882 {
1883 if ( eFlags & SwCursorShell::READONLY )
1884 m_bIgnoreReadonly = true;
1885 return; // if not then no update
1886 }
1887
1888#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1889 SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1890#endif
1891
1892 if ( m_bIgnoreReadonly )
1893 {
1894 m_bIgnoreReadonly = false;
1895 eFlags |= SwCursorShell::READONLY;
1896 }
1897
1898 if( eFlags & SwCursorShell::CHKRANGE ) // check all cursor moves for
1899 CheckRange( m_pCurrentCursor ); // overlapping ranges
1900
1901 if( !bIdleEnd )
1903
1904 // If the current cursor is in a table and point/mark in different boxes,
1905 // then the table mode is active (also if it is already active: m_pTableCursor)
1906 SwPaM* pTstCursor = getShellCursor( true );
1907 if( pTstCursor->HasMark() && !m_pBlockCursor &&
1908 SwDoc::IsInTable( pTstCursor->GetPoint()->GetNode() ) &&
1909 ( m_pTableCursor ||
1910 pTstCursor->GetPointNode().StartOfSectionNode() !=
1911 pTstCursor->GetMarkNode().StartOfSectionNode() ) && !mbSelectAll)
1912 {
1913 SwShellCursor* pITmpCursor = getShellCursor( true );
1914 Point aTmpPt( pITmpCursor->GetPtPos() );
1915 Point aTmpMk( pITmpCursor->GetMkPos() );
1916 SwPosition* pPos = pITmpCursor->GetPoint();
1917
1918 // Bug 65475 (1999) - if Point/Mark in hidden sections, move them out
1919 lcl_CheckHiddenSection( *pPos );
1920 lcl_CheckHiddenSection( *pITmpCursor->GetMark() );
1921
1922 // Move cursor out of hidden paragraphs
1923 if ( !GetViewOptions()->IsShowHiddenChar() )
1924 {
1925 lcl_CheckHiddenPara( *pPos );
1926 lcl_CheckHiddenPara( *pITmpCursor->GetMark() );
1927 }
1928
1929 std::pair<Point, bool> const tmp(aTmpPt, false);
1930 SwContentFrame *pTableFrame = pPos->GetNode().GetContentNode()->
1931 getLayoutFrame( GetLayout(), pPos, &tmp);
1932
1933 OSL_ENSURE( pTableFrame, "Table Cursor not in Content ??" );
1934
1935 // --> Make code robust. The table cursor may point
1936 // to a table in a currently inactive header.
1937 SwTabFrame *pTab = pTableFrame ? pTableFrame->FindTabFrame() : nullptr;
1938
1939 if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1940 {
1941 // First check if point is in repeated headline:
1942 bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTableFrame );
1943
1944 // Second check if mark is in repeated headline:
1945 if ( !bInRepeatedHeadline )
1946 {
1947 std::pair<Point, bool> const tmp1(aTmpMk, false);
1948 SwContentFrame* pMarkTableFrame = pITmpCursor->GetMarkContentNode()->
1949 getLayoutFrame(GetLayout(), pITmpCursor->GetMark(), &tmp1);
1950 OSL_ENSURE( pMarkTableFrame, "Table Cursor not in Content ??" );
1951
1952 if ( pMarkTableFrame )
1953 {
1954 SwTabFrame* pMarkTab = pMarkTableFrame->FindTabFrame();
1955 OSL_ENSURE( pMarkTab, "Table Cursor not in Content ??" );
1956
1957 // Make code robust:
1958 if ( pMarkTab )
1959 {
1960 bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTableFrame );
1961 }
1962 }
1963 }
1964
1965 // No table cursor in repeated headlines:
1966 if ( bInRepeatedHeadline )
1967 {
1968 pTableFrame = nullptr;
1969
1970 SwMoveFnCollection const & fnPosSect = *pPos < *pITmpCursor->GetMark()
1972 : fnSectionEnd;
1973
1974 // then only select inside the Box
1975 if( m_pTableCursor )
1976 {
1981 m_pTableCursor->SwSelPaintRects::Hide();
1982 }
1983
1985 GoCurrSection( *m_pCurrentCursor, fnPosSect );
1986 }
1987 }
1988
1989 // we really want a table selection
1990 if( pTab && pTableFrame )
1991 {
1992 if( !m_pTableCursor )
1993 {
1996 *pPos, aTmpPt );
1998 m_pCurrentCursor->SwSelPaintRects::Hide();
1999
2001 if(!m_pTableCursor)
2002 {
2003 SAL_WARN("sw.core", "fdo#74854: "
2004 "this should not happen, but better lose the selection "
2005 "rather than crashing");
2006 return;
2007 }
2008 }
2009
2011 aTmpState.m_bRealHeight = true;
2012 {
2014 if (!pTableFrame->GetCharRect( m_aCharRect, *m_pTableCursor->GetPoint(), &aTmpState))
2015 {
2016 Point aCentrPt( m_aCharRect.Center() );
2018 pTableFrame->GetModelPositionForViewPoint(m_pTableCursor->GetPoint(), aCentrPt, &aTmpState);
2019 bool const bResult =
2021 OSL_ENSURE( bResult, "GetCharRect failed." );
2022 }
2023 }
2024
2025 m_pVisibleCursor->Hide(); // always hide visible Cursor
2026 // scroll Cursor to visible area
2027 if( eFlags & SwCursorShell::SCROLLWIN &&
2028 (HasSelection() || eFlags & SwCursorShell::READONLY ||
2029 !IsCursorReadonly()) )
2030 {
2031 SwFrame* pBoxFrame = pTableFrame;
2032 while( pBoxFrame && !pBoxFrame->IsCellFrame() )
2033 pBoxFrame = pBoxFrame->GetUpper();
2034 if( pBoxFrame && pBoxFrame->getFrameArea().HasArea() )
2035 MakeVisible( pBoxFrame->getFrameArea() );
2036 else
2038 }
2039
2040 // let Layout create the Cursors in the Boxes
2044 m_pTableCursor->Show(nullptr);
2045
2046 // set Cursor-Points to the new Positions
2049
2050 if( m_bSVCursorVis )
2051 {
2053 m_aCursorHeight.setY(aTmpState.m_aRealHeight.getY() < 0 ?
2055 m_pVisibleCursor->Show(); // show again
2056 }
2057 m_eMvState = CursorMoveState::NONE; // state for cursor travelling - GetModelPositionForViewPoint
2058#if !ENABLE_WASM_STRIP_ACCESSIBILITY
2059 if (Imp()->IsAccessible() && m_bSendAccessibleCursorEvents)
2060 Imp()->InvalidateAccessibleCursorPosition( pTableFrame );
2061#endif
2062 return;
2063 }
2064 }
2065
2066 if( m_pTableCursor )
2067 {
2068 // delete Ring
2070 delete m_pCurrentCursor->GetNext();
2074 delete m_pTableCursor;
2075 m_pTableCursor = nullptr;
2076 }
2077
2078 m_pVisibleCursor->Hide(); // always hide visible Cursor
2079
2080 // are we perhaps in a protected / hidden Section ?
2081 {
2082 SwShellCursor* pShellCursor = getShellCursor( true );
2083 bool bChgState = true;
2084 const SwSectionNode* pSectNd = pShellCursor->GetPointNode().FindSectionNode();
2085 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2086 ( !IsReadOnlyAvailable() &&
2087 pSectNd->GetSection().IsProtectFlag() &&
2088 ( !mxDoc->GetDocShell() ||
2089 !mxDoc->GetDocShell()->IsReadOnly() || m_bAllProtect )) ) )
2090 {
2092 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
2093 {
2094 // everything protected/hidden -> special mode
2096 pSectNd->GetSection().IsProtectFlag() )
2097 bChgState = false;
2098 else
2099 {
2100 m_eMvState = CursorMoveState::NONE; // state for cursor travelling
2101 m_bAllProtect = true;
2102 if( GetDoc()->GetDocShell() )
2103 {
2105 CallChgLnk(); // notify UI!
2106 }
2107 return;
2108 }
2109 }
2110 }
2111 if( bChgState )
2112 {
2113 bool bWasAllProtect = m_bAllProtect;
2114 m_bAllProtect = false;
2115 if( bWasAllProtect && GetDoc()->GetDocShell() &&
2116 GetDoc()->GetDocShell()->IsReadOnlyUI() )
2117 {
2118 GetDoc()->GetDocShell()->SetReadOnlyUI( false );
2119 CallChgLnk(); // notify UI!
2120 }
2121 }
2122 }
2123
2125
2126 // The cursor must always point into content; there's some code
2127 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
2128 // loops _behind_ the last node in the selection, which always works if you
2129 // are in content.) To achieve this, we'll force cursor(s) to point into
2130 // content, if UpdateCursorPos() hasn't already done so.
2132 {
2133 // start will move forwards, end will move backwards
2134 bool bPointIsStart = ( rCmp.Start() == rCmp.GetPoint() );
2135
2136 // move point; forward if it's the start, backwards if it's the end
2137 if( ! rCmp.GetPoint()->GetNode().IsContentNode() )
2138 rCmp.Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
2139 GoInContent );
2140
2141 // move mark (if exists); forward if it's the start, else backwards
2142 if( rCmp.HasMark() )
2143 {
2144 if( ! rCmp.GetMark()->GetNode().IsContentNode() )
2145 {
2146 rCmp.Exchange();
2147 rCmp.Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
2148 GoInContent );
2149 rCmp.Exchange();
2150 }
2151 }
2152 }
2153
2154 SwRect aOld( m_aCharRect );
2155 bool bFirst = true;
2156 SwContentFrame *pFrame;
2157 int nLoopCnt = 100;
2158 SwShellCursor* pShellCursor = getShellCursor( true );
2159
2160 do {
2161 bool bAgainst;
2162 do {
2163 bAgainst = false;
2164 std::pair<Point, bool> const tmp1(pShellCursor->GetPtPos(), false);
2165 pFrame = pShellCursor->GetPointContentNode()->getLayoutFrame(GetLayout(),
2166 pShellCursor->GetPoint(), &tmp1);
2167 // if the Frame doesn't exist anymore, the complete Layout has to be
2168 // created, because there used to be a Frame here!
2169 if ( !pFrame )
2170 {
2171 do
2172 {
2173 CalcLayout();
2174 std::pair<Point, bool> const tmp(pShellCursor->GetPtPos(), false);
2175 pFrame = pShellCursor->GetPointContentNode()->getLayoutFrame(
2176 GetLayout(), pShellCursor->GetPoint(), &tmp);
2177 } while( !pFrame );
2178 }
2179 else if ( Imp()->IsIdleAction() )
2180 // Guarantee everything's properly formatted
2181 pFrame->PrepareCursor();
2182
2183 // In protected Fly? but ignore in case of frame selection
2184 if( !IsReadOnlyAvailable() && pFrame->IsProtected() &&
2185 ( !Imp()->GetDrawView() ||
2186 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
2187 (!mxDoc->GetDocShell() ||
2188 !mxDoc->GetDocShell()->IsReadOnly() || m_bAllProtect ) )
2189 {
2190 // look for a valid position
2191 bool bChgState = true;
2193 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
2194 {
2195 // everything is protected / hidden -> special Mode
2196 if( m_bAllProtect )
2197 bChgState = false;
2198 else
2199 {
2200 m_eMvState = CursorMoveState::NONE; // state for cursor travelling
2201 m_bAllProtect = true;
2202 if( GetDoc()->GetDocShell() )
2203 {
2205 CallChgLnk(); // notify UI!
2206 }
2207 return;
2208 }
2209 }
2210
2211 if( bChgState )
2212 {
2213 bool bWasAllProtect = m_bAllProtect;
2214 m_bAllProtect = false;
2215 if( bWasAllProtect && GetDoc()->GetDocShell() &&
2216 GetDoc()->GetDocShell()->IsReadOnlyUI() )
2217 {
2218 GetDoc()->GetDocShell()->SetReadOnlyUI( false );
2219 CallChgLnk(); // notify UI!
2220 }
2221 m_bAllProtect = false;
2222 bAgainst = true; // look for the right Frame again
2223 }
2224 }
2225 } while( bAgainst );
2226
2227 SwCursorMoveState aTmpState( m_eMvState );
2229 aTmpState.m_bRealHeight = true;
2230 aTmpState.m_bRealWidth = IsOverwriteCursor();
2231 aTmpState.m_nCursorBidiLevel = pShellCursor->GetCursorBidiLevel();
2232
2233 // #i27615#,#i30453#
2234 SwSpecialPos aSpecialPos;
2236 if (pShellCursor->IsInFrontOfLabel())
2237 {
2238 aTmpState.m_pSpecialPos = &aSpecialPos;
2239 }
2240
2241 {
2242 DisableCallbackAction a(*GetLayout()); // tdf#91602 prevent recursive Action
2243 if (!pFrame->GetCharRect(m_aCharRect, *pShellCursor->GetPoint(), &aTmpState))
2244 {
2245 Point& rPt = pShellCursor->GetPtPos();
2246 rPt = m_aCharRect.Center();
2247 pFrame->GetModelPositionForViewPoint( pShellCursor->GetPoint(), rPt, &aTmpState );
2248 }
2249 }
2250 UISizeNotify(); // tdf#96256 update view size
2251
2252 if( !pShellCursor->HasMark() )
2253 m_aCursorHeight = aTmpState.m_aRealHeight;
2254 else
2255 {
2257 m_aCursorHeight.setY(aTmpState.m_aRealHeight.getY() < 0 ?
2259 }
2260
2261 if( !bFirst && aOld == m_aCharRect )
2262 break;
2263
2264 // if the layout says that we are after the 100th iteration still in
2265 // flow then we should always take the current position for granted.
2266 // (see bug: 29658)
2267 if( !--nLoopCnt )
2268 {
2269 OSL_ENSURE( false, "endless loop? CharRect != OldCharRect ");
2270 break;
2271 }
2272 aOld = m_aCharRect;
2273 bFirst = false;
2274
2275 // update cursor Points to the new Positions
2276 pShellCursor->GetPtPos().setX(m_aCharRect.Left());
2277 pShellCursor->GetPtPos().setY(m_aCharRect.Top());
2278
2279 if( !(eFlags & SwCursorShell::UPDOWN )) // delete old Pos. of Up/Down
2280 {
2282 pFrame->Calc(GetOut());
2283 m_nUpDownX = pFrame->IsVertical() ?
2284 m_aCharRect.Top() - pFrame->getFrameArea().Top() :
2285 m_aCharRect.Left() - pFrame->getFrameArea().Left();
2286 }
2287
2288 // scroll Cursor to visible area
2289 if( m_bHasFocus && eFlags & SwCursorShell::SCROLLWIN &&
2290 (HasSelection() || eFlags & SwCursorShell::READONLY ||
2291 !IsCursorReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
2292 {
2293 // in case of scrolling this EndAction doesn't show the SV cursor
2294 // again, thus save and reset the flag here
2295 bool bSav = m_bSVCursorVis;
2296 m_bSVCursorVis = false;
2298 m_bSVCursorVis = bSav;
2299 }
2300
2301 } while( eFlags & SwCursorShell::SCROLLWIN );
2302
2303 assert(pFrame);
2304
2305 if( m_pBlockCursor )
2307
2308 // We should not restrict cursor update to the active view when using LOK
2309 bool bCheckFocus = m_bHasFocus || comphelper::LibreOfficeKit::isActive();
2310
2311 if( !bIdleEnd && bCheckFocus && !m_bBasicHideCursor )
2312 {
2313 if( m_pTableCursor )
2314 m_pTableCursor->SwSelPaintRects::Show();
2315 else
2316 {
2317 m_pCurrentCursor->SwSelPaintRects::Show();
2318 if( m_pBlockCursor )
2319 {
2321 while( pNxt && pNxt != m_pCurrentCursor )
2322 {
2323 pNxt->SwSelPaintRects::Show();
2324 pNxt = pNxt->GetNext();
2325 }
2326 }
2327 }
2328 }
2329
2330 m_eMvState = CursorMoveState::NONE; // state for cursor travelling - GetModelPositionForViewPoint
2331
2332#if !ENABLE_WASM_STRIP_ACCESSIBILITY
2333 if (Imp()->IsAccessible() && m_bSendAccessibleCursorEvents)
2335#endif
2336
2337 // switch from blinking cursor to read-only-text-selection cursor
2338 const sal_uInt64 nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
2339 GetCursorBlinkTime();
2340
2341 if ( (IsCursorReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
2342 ( nBlinkTime != STYLE_CURSOR_NOBLINKTIME ) )
2343 {
2344 // non blinking cursor in read only - text selection mode
2345 AllSettings aSettings = GetOut()->GetSettings();
2346 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
2347 const sal_uInt64 nNewBlinkTime = nBlinkTime == STYLE_CURSOR_NOBLINKTIME ?
2350 aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
2351 aSettings.SetStyleSettings( aStyleSettings );
2352 GetOut()->SetSettings( aSettings );
2353 }
2354
2355 if( m_bSVCursorVis )
2356 m_pVisibleCursor->Show(); // show again
2357
2360
2362}
2363
2365{
2366 SwView* pView = static_cast<SwView*>(GetSfxViewShell());
2367 if (!pView || !pView->GetWrtShellPtr())
2368 return;
2369
2370 SwWrtShell* pShell = &pView->GetWrtShell();
2371
2372 SwFrame* pCurrentFrame = GetCurrFrame();
2374
2375 tools::JsonWriter aJsonWriter;
2376
2377 if (pCurrentFrame && (eType & SelectionType::Table) && pCurrentFrame->IsInTab())
2378 {
2379 const SwRect& rPageRect = pShell->GetAnyCurRect(CurRectType::Page, nullptr);
2380
2381 {
2382 auto columnsNode = aJsonWriter.startNode("columns");
2383 SwTabCols aTabCols;
2384 pShell->GetTabCols(aTabCols);
2385
2386 const int nColumnOffset = aTabCols.GetLeftMin() + rPageRect.Left();
2387
2388 aJsonWriter.put("left", aTabCols.GetLeft());
2389 aJsonWriter.put("right", aTabCols.GetRight());
2390 aJsonWriter.put("tableOffset", static_cast<sal_Int64>(nColumnOffset));
2391
2392 {
2393 auto entriesNode = aJsonWriter.startArray("entries");
2394 for (size_t i = 0; i < aTabCols.Count(); ++i)
2395 {
2396 auto entryNode = aJsonWriter.startStruct();
2397 auto const & rEntry = aTabCols.GetEntry(i);
2398 aJsonWriter.put("position", rEntry.nPos);
2399 aJsonWriter.put("min", rEntry.nMin);
2400 aJsonWriter.put("max", rEntry.nMax);
2401 aJsonWriter.put("hidden", rEntry.bHidden);
2402 }
2403 }
2404 }
2405
2406 {
2407 auto rowsNode = aJsonWriter.startNode("rows");
2408 SwTabCols aTabRows;
2409 pShell->GetTabRows(aTabRows);
2410
2411 const int nRowOffset = aTabRows.GetLeftMin() + rPageRect.Top();
2412
2413 aJsonWriter.put("left", aTabRows.GetLeft());
2414 aJsonWriter.put("right", aTabRows.GetRight());
2415 aJsonWriter.put("tableOffset", static_cast<sal_Int64>(nRowOffset));
2416
2417 {
2418 auto entriesNode = aJsonWriter.startArray("entries");
2419 for (size_t i = 0; i < aTabRows.Count(); ++i)
2420 {
2421 auto entryNode = aJsonWriter.startStruct();
2422 auto const & rEntry = aTabRows.GetEntry(i);
2423 aJsonWriter.put("position", rEntry.nPos);
2424 aJsonWriter.put("min", rEntry.nMin);
2425 aJsonWriter.put("max", rEntry.nMax);
2426 aJsonWriter.put("hidden", rEntry.bHidden);
2427 }
2428 }
2429 }
2430 }
2431
2432 OString pChar = aJsonWriter.finishAndGetAsOString();
2433 GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, pChar);
2434}
2435
2437{
2438 assert(m_pBlockCursor);
2440 Point aPt = rBlock.GetPtPos();
2441 std::pair<Point, bool> const tmp(aPt, false);
2443 GetLayout(), rBlock.GetPoint(), &tmp);
2444 Point aMk;
2446 {
2447 aPt = *m_pBlockCursor->getStartPoint();
2448 aMk = *m_pBlockCursor->getEndPoint();
2449 }
2450 else
2451 {
2452 aPt = rBlock.GetPtPos();
2453 if( pFrame )
2454 {
2455 if( pFrame->IsVertical() )
2456 aPt.setY(pFrame->getFrameArea().Top() + GetUpDownX());
2457 else
2458 aPt.setX(pFrame->getFrameArea().Left() + GetUpDownX());
2459 }
2460 aMk = rBlock.GetMkPos();
2461 }
2462 SwRect aRect( aMk, aPt );
2463 aRect.Justify();
2464 SwSelectionList aSelList( pFrame );
2465
2466 if( !GetLayout()->FillSelection( aSelList, aRect ) )
2467 return;
2468
2469 SwCursor* pNxt = static_cast<SwCursor*>(m_pCurrentCursor->GetNext());
2470 while( pNxt != m_pCurrentCursor )
2471 {
2472 delete pNxt;
2473 pNxt = static_cast<SwCursor*>(m_pCurrentCursor->GetNext());
2474 }
2475
2476 std::list<SwPaM*>::iterator pStart = aSelList.getStart();
2477 std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
2478 OSL_ENSURE( pPam != pStart, "FillSelection should deliver at least one PaM" );
2480 --pPam;
2481 // If there is only one text portion inside the rectangle, a simple
2482 // selection is created
2483 if( pPam == pStart )
2484 {
2485 *m_pCurrentCursor->GetPoint() = *(*pPam)->GetPoint();
2486 if( (*pPam)->HasMark() )
2487 *m_pCurrentCursor->GetMark() = *(*pPam)->GetMark();
2488 else
2490 delete *pPam;
2492 }
2493 else
2494 {
2495 // The order of the SwSelectionList has to be preserved but
2496 // the order inside the ring created by CreateCursor() is not like
2497 // expected => First create the selections before the last one
2498 // downto the first selection.
2499 // At least create the cursor for the last selection
2500 --pPam;
2501 *m_pCurrentCursor->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
2502 if( (*pPam)->HasMark() )
2503 *m_pCurrentCursor->GetMark() = *(*pPam)->GetMark();
2504 else
2506 delete *pPam;
2508 while( pPam != pStart )
2509 {
2510 --pPam;
2511
2513 pNew->insert( pNew->begin(), m_pCurrentCursor->begin(), m_pCurrentCursor->end());
2514 m_pCurrentCursor->clear();
2516
2517 *m_pCurrentCursor->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
2518 if( (*pPam)->HasMark() )
2519 {
2521 *m_pCurrentCursor->GetMark() = *(*pPam)->GetMark();
2522 }
2523 else
2526 delete *pPam;
2527 }
2528 {
2530 pNew->insert( pNew->begin(), m_pCurrentCursor->begin(), m_pCurrentCursor->end() );
2531 m_pCurrentCursor->clear();
2533 }
2534 pPam = aSelList.getEnd();
2535 --pPam;
2536 *m_pCurrentCursor->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
2537 if( (*pPam)->HasMark() )
2538 {
2540 *m_pCurrentCursor->GetMark() = *(*pPam)->GetMark();
2541 }
2542 else
2545 delete *pPam;
2546 }
2547}
2548
2551{
2552 // fdo#60513: if we have a table cursor, copy that; else copy current.
2553 // This seems to work because UpdateCursor() will fix this up on Pop(),
2554 // then MakeBoxSels() will re-create the current m_pCurrentCursor cell ring.
2556 m_pStackCursor = new SwShellCursor( *this, *pCurrent->GetPoint(),
2557 pCurrent->GetPtPos(), m_pStackCursor );
2558
2559 if (pCurrent->HasMark())
2560 {
2562 *m_pStackCursor->GetMark() = *pCurrent->GetMark();
2563 }
2564}
2565
2572bool SwCursorShell::Pop(PopMode const eDelete)
2573{
2574 std::optional<SwCallLink> aLink(std::in_place, *this); // watch Cursor-Moves; call Link if needed
2575 return Pop(eDelete, aLink);
2576}
2577
2578bool SwCursorShell::Pop(PopMode const eDelete,
2579 [[maybe_unused]] std::optional<SwCallLink>& roLink)
2580{
2581 // parameter exists only to be deleted before return
2582 assert(roLink);
2583 comphelper::ScopeGuard aGuard( [&]() { roLink.reset(); } );
2584
2585 // are there any left?
2586 if (nullptr == m_pStackCursor)
2587 return false;
2588
2589 SwShellCursor *pTmp = nullptr, *pOldStack = m_pStackCursor;
2590
2591 // the successor becomes the current one
2593 {
2594 pTmp = m_pStackCursor->GetNext();
2595 }
2596
2597 if (PopMode::DeleteStack == eDelete)
2598 delete m_pStackCursor;
2599
2600 m_pStackCursor = pTmp; // assign new one
2601
2602 if (PopMode::DeleteCurrent == eDelete)
2603 {
2604 ::std::optional<SwCursorSaveState> oSaveState( *m_pCurrentCursor );
2605
2606 // If the visible SSelection was not changed
2607 const Point& rPoint = pOldStack->GetPtPos();
2608 if (rPoint == m_pCurrentCursor->GetPtPos() || rPoint == m_pCurrentCursor->GetMkPos())
2609 {
2610 // move "Selections Rectangles"
2611 m_pCurrentCursor->insert( m_pCurrentCursor->begin(), pOldStack->begin(), pOldStack->end() );
2612 pOldStack->clear();
2613 }
2614
2615 if( pOldStack->HasMark() )
2616 {
2618 *m_pCurrentCursor->GetMark() = *pOldStack->GetMark();
2619 m_pCurrentCursor->GetMkPos() = pOldStack->GetMkPos();
2620 }
2621 else
2622 // no selection so revoke old one and set to old position
2624 *m_pCurrentCursor->GetPoint() = *pOldStack->GetPoint();
2625 m_pCurrentCursor->GetPtPos() = pOldStack->GetPtPos();
2626 delete pOldStack;
2627
2628 if( !m_pCurrentCursor->IsInProtectTable( true ) &&
2631 {
2632 oSaveState.reset(); // prevent UAF
2633 UpdateCursor(); // update current cursor
2634 if (m_pTableCursor)
2635 { // tdf#106929 ensure m_pCurrentCursor ring is recreated from table
2637 }
2638 }
2639 }
2640 return true;
2641}
2642
2648{
2649 // any others left?
2650 if (nullptr == m_pStackCursor)
2651 return;
2652
2653 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
2654 // rhbz#689053: IsSelOvr must restore the saved stack position, not the
2655 // current one, because current point + stack mark may be invalid PaM
2656 SwCursorSaveState aSaveState(*m_pStackCursor);
2657 // stack cursor & current cursor in same Section?
2658 assert(!m_pStackCursor->HasMark() ||
2660 m_pCurrentCursor->GetPoint()->GetNode(), true));
2663
2664 SwShellCursor * pTmp = nullptr;
2666 {
2667 pTmp = m_pStackCursor->GetNext();
2668 }
2669 delete m_pCurrentCursor;
2671 m_pStackCursor->MoveTo(nullptr); // remove from ring
2672 m_pStackCursor = pTmp;
2673 if( !m_pCurrentCursor->IsInProtectTable( true ) &&
2676 {
2677 UpdateCursor(); // update current cursor
2678 }
2679}
2680
2682{
2684 return;
2685
2686 // if cursor is visible then hide SV cursor
2688 {
2689 CurrShell aCurr( this );
2691 }
2692 // revoke inversion of SSelection
2694 pCurrentCursor->Hide();
2695}
2696
2697void SwCursorShell::ShowCursors( bool bCursorVis )
2698{
2700 return;
2701
2702 CurrShell aCurr( this );
2704 pCurrentCursor->Show(nullptr);
2705
2706 if( m_bSVCursorVis && bCursorVis ) // also show SV cursor again
2708}
2709
2711{
2712 if( m_bBasicHideCursor )
2713 return;
2714
2716
2717 m_bSVCursorVis = true;
2720
2722 {
2723 const OString aPayload = OString::boolean(m_bSVCursorVis);
2724 GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload);
2725 SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload);
2726 }
2727
2728 UpdateCursor();
2729}
2730
2732{
2733 if( m_bBasicHideCursor )
2734 return;
2735
2736 m_bSVCursorVis = false;
2737 // possibly reverse selected areas!!
2738 CurrShell aCurr( this );
2742
2744 {
2745 OString aPayload = OString::boolean(m_bSVCursorVis);
2746 GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload);
2747 SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload);
2748 }
2749}
2750
2752{
2753 if( !m_bBasicHideCursor )
2754 HideCursors();
2755 m_bHasFocus = false;
2756}
2757
2759{
2761
2762 m_bHasFocus = true;
2763 if( !m_bBasicHideCursor && VisArea().Width() )
2764 {
2765 UpdateCursor( o3tl::narrowing<sal_uInt16>( SwCursorShell::CHKRANGE ) );
2767 }
2768}
2769
2771SwContentFrame *SwCursorShell::GetCurrFrame( const bool bCalcFrame ) const
2772{
2773 CurrShell aCurr( const_cast<SwCursorShell*>(this) );
2774 SwContentFrame *pRet = nullptr;
2776 if ( pNd )
2777 {
2778 if ( bCalcFrame )
2779 {
2780 sal_uInt16* pST = const_cast<sal_uInt16*>(&mnStartAction);
2781 ++(*pST);
2782 const Size aOldSz( GetDocSize() );
2783 std::pair<Point, bool> const tmp(m_pCurrentCursor->GetPtPos(), true);
2784 pRet = pNd->getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint(), &tmp);
2785 --(*pST);
2786 if( aOldSz != GetDocSize() )
2787 const_cast<SwCursorShell*>(this)->SizeChgNotify();
2788 }
2789 else
2790 {
2791 std::pair<Point, bool> const tmp(m_pCurrentCursor->GetPtPos(), false);
2792 pRet = pNd->getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint(), &tmp);
2793 }
2794 }
2795 return pRet;
2796}
2797
2798//TODO: provide documentation
2805{
2806 if(dynamic_cast<const sw::PostGraphicArrivedHint*>(&rHint) && m_aGrfArrivedLnk.IsSet())
2807 {
2808 m_aGrfArrivedLnk.Call(*this);
2809 return;
2810 }
2811 if (rHint.GetId() != SfxHintId::SwLegacyModify)
2812 return;
2813 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
2814 auto nWhich = pLegacy->GetWhich();
2815 if(!nWhich)
2816 nWhich = RES_OBJECTDYING;
2817 if( m_bCallChgLnk &&
2818 ( !isFormatMessage(nWhich)
2819 || nWhich == RES_FMT_CHG
2820 || nWhich == RES_UPDATE_ATTR
2821 || nWhich == RES_ATTRSET_CHG ))
2822 // messages are not forwarded
2823 // #i6681#: RES_UPDATE_ATTR is implicitly unset in
2824 // SwTextNode::Insert(SwTextHint*, sal_uInt16); we react here and thus do
2825 // not need to send the expensive RES_FMT_CHG in Insert.
2826 CallChgLnk();
2827 if( nWhich == RES_OBJECTDYING )
2828 {
2829 EndListeningAll();
2830 }
2831
2832}
2833
2839{
2840 const SwPaM* pCursor = getShellCursor( true );
2841 return IsTableMode()
2842 || (pCursor->HasMark() &&
2843 (*pCursor->GetPoint() != *pCursor->GetMark()
2844 || IsFlySelectedByCursor(*GetDoc(), *pCursor->Start(), *pCursor->End())));
2845}
2846
2848{
2849 // Do not make any call in StartAction/EndAction but just set the flag.
2850 // This will be handled in EndAction.
2851 if (ActionPend())
2852 m_bChgCallFlag = true; // remember change
2853 else if( m_aChgLnk.IsSet() )
2854 {
2855 if( m_bCallChgLnk )
2856 m_aChgLnk.Call(nullptr);
2857 m_bChgCallFlag = false; // reset flag
2858 }
2859}
2860
2863{
2864 OUString aText;
2865 if (GetLayout()->HasMergedParas())
2866 {
2867 SwContentFrame const*const pFrame(GetCurrFrame(false));
2868 if (pFrame && FrameContainsNode(*pFrame, m_pCurrentCursor->GetMark()->GetNodeIndex()))
2869 {
2870 OUStringBuffer buf;
2871 SwPosition const*const pStart(m_pCurrentCursor->Start());
2872 SwPosition const*const pEnd(m_pCurrentCursor->End());
2873 for (SwNodeOffset i = pStart->GetNodeIndex(); i <= pEnd->GetNodeIndex(); ++i)
2874 {
2875 SwNode const& rNode(*pStart->GetNodes()[i]);
2876 assert(!rNode.IsEndNode());
2877 if (rNode.IsStartNode())
2878 {
2879 i = rNode.EndOfSectionIndex();
2880 }
2881 else if (rNode.IsTextNode())
2882 {
2883 sal_Int32 const nStart(i == pStart->GetNodeIndex()
2884 ? pStart->GetContentIndex()
2885 : 0);
2886 sal_Int32 const nEnd(i == pEnd->GetNodeIndex()
2887 ? pEnd->GetContentIndex()
2888 : rNode.GetTextNode()->Len());
2889 buf.append(rNode.GetTextNode()->GetExpandText(
2890 GetLayout(),
2891 nStart, nEnd - nStart, false, false, false,
2893
2894 }
2895 }
2896 aText = buf.makeStringAndClear();
2897 }
2898 }
2899 else if( m_pCurrentCursor->GetPoint()->GetNodeIndex() ==
2901 {
2903 if( pTextNd )
2904 {
2905 const sal_Int32 nStt = m_pCurrentCursor->Start()->GetContentIndex();
2906 aText = pTextNd->GetExpandText(GetLayout(), nStt,
2907 m_pCurrentCursor->End()->GetContentIndex() - nStt );
2908 }
2909 }
2910 return aText;
2911}
2912
2919{
2920 if( IsTableMode() ) // not possible in table mode
2921 return 0;
2922
2924 : bEnd ? m_pCurrentCursor->End() : m_pCurrentCursor->Start();
2925 SwTextNode* pTextNd = pPos->GetNode().GetTextNode();
2926 if( !pTextNd )
2927 return 0;
2928
2929 const sal_Int32 nPos = pPos->GetContentIndex();
2930 const OUString& rStr = pTextNd->GetText();
2931 sal_Unicode cCh = 0;
2932
2933 if (((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.getLength())
2934 cCh = rStr[nPos + nOffset];
2935
2936 return cCh;
2937}
2938
2944bool SwCursorShell::ExtendSelection( bool bEnd, sal_Int32 nCount )
2945{
2946 if( !m_pCurrentCursor->HasMark() || IsTableMode() )
2947 return false; // no selection
2948
2949 SwPosition* pPos = bEnd ? m_pCurrentCursor->End() : m_pCurrentCursor->Start();
2950 SwTextNode* pTextNd = pPos->GetNode().GetTextNode();
2951 assert(pTextNd);
2952
2953 sal_Int32 nPos = pPos->GetContentIndex();
2954 if( bEnd )
2955 {
2956 if ((nPos + nCount) <= pTextNd->GetText().getLength())
2957 nPos = nPos + nCount;
2958 else
2959 return false; // not possible
2960 }
2961 else if( nPos >= nCount )
2962 nPos = nPos - nCount;
2963 else
2964 return false; // not possible anymore
2965
2966 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
2967
2968 pPos->SetContent(nPos) ;
2969 UpdateCursor();
2970
2971 return true;
2972}
2973
2980{
2981 CurrShell aCurr( this );
2982 Point aPt( rPt );
2986 aTmpState.m_bRealHeight = true;
2987
2988 const bool bRet = GetLayout()->GetModelPositionForViewPoint( &aPos, aPt /*, &aTmpState*/ );
2989
2990 SetInFrontOfLabel( false ); // #i27615#
2991
2992 // show only in TextNodes
2993 SwTextNode* pTextNd = aPos.GetNode().GetTextNode();
2994 if( !pTextNd )
2995 return false;
2996
2997 const SwSectionNode* pSectNd = pTextNd->FindSectionNode();
2998 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2999 ( !IsReadOnlyAvailable() &&
3000 pSectNd->GetSection().IsProtectFlag())) )
3001 return false;
3002
3003 std::pair<Point, bool> const tmp(aPt, true);
3004 SwContentFrame *pFrame = pTextNd->getLayoutFrame(GetLayout(), &aPos, &tmp);
3005 if ( Imp()->IsIdleAction() )
3006 pFrame->PrepareCursor();
3007 SwRect aTmp( m_aCharRect );
3008
3009 pFrame->GetCharRect( m_aCharRect, aPos, &aTmpState );
3010
3011 // #i10137#
3012 if( aTmp == m_aCharRect && m_pVisibleCursor->IsVisible() )
3013 return true;
3014
3015 m_pVisibleCursor->Hide(); // always hide visible cursor
3016 if( IsScrollMDI( this, m_aCharRect ))
3017 {
3019 m_pCurrentCursor->Show(nullptr);
3020 }
3021
3022 {
3023 if( aTmpState.m_bRealHeight )
3024 m_aCursorHeight = aTmpState.m_aRealHeight;
3025 else
3026 {
3029 }
3030
3032 m_pVisibleCursor->Show(); // show again
3033 }
3034 return bRet;
3035}
3036
3038{
3039 return m_pVisibleCursor;
3040}
3041
3043{
3044 Point aPt( rPt );
3045 SwPaM aPam( *m_pCurrentCursor->GetPoint() );
3047 // form view
3048 return aPam.HasReadonlySel(GetViewOptions()->IsFormView(), false);
3049}
3050
3055sal_uInt16 SwCursorShell::GetCursorCnt( bool bAll ) const
3056{
3057 SwPaM* pTmp = GetCursor()->GetNext();
3058 sal_uInt16 n = (bAll || ( m_pCurrentCursor->HasMark() &&
3060 while( pTmp != m_pCurrentCursor )
3061 {
3062 if( bAll || ( pTmp->HasMark() &&
3063 *pTmp->GetPoint() != *pTmp->GetMark()))
3064 ++n;
3065 pTmp = pTmp->GetNext();
3066 }
3067 return n;
3068}
3069
3071{
3073 return false;
3074
3075 // after EndOfIcons comes the content selection (EndNd+StNd+ContentNd)
3076 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
3077 if( !aIdx.GetNode().IsContentNode() )
3078 GetDoc()->GetNodes().GoNext( &aIdx );
3079 return aIdx == m_pCurrentCursor->GetPoint()->GetNode();
3080}
3081
3083{
3084 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
3085 SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3086 if( !pCNd )
3087 pCNd = SwNodes::GoPrevious( &aIdx );
3088
3089 return aIdx == m_pCurrentCursor->GetPoint()->GetNode() && pCNd &&
3091}
3092
3101{
3102 if( !m_pTableCursor )
3103 return false;
3104
3106
3108 delete m_pCurrentCursor->GetNext();
3109
3110 // *always* move cursor's Point and Mark
3113
3114 return true;
3115}
3116
3117void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing )
3118{
3119 auto [pStt, pEnd] = pDelRg->StartEnd(); // SwPosition*
3120
3121 SwPaM *pTmpDel = nullptr, *pTmp = *ppDelRing;
3122
3123 // search over the whole ring
3124 bool bGoNext;
3125 do {
3126
3127 if (!pTmp)
3128 break;
3129
3130 auto [pTmpStt, pTmpEnd] = pTmp->StartEnd(); // SwPosition*
3131 // If a SPoint or GetMark are in a cursor area then cancel the old area.
3132 // During comparison keep in mind that End() is outside the area.
3133 if( *pStt <= *pTmpStt )
3134 {
3135 if( *pEnd > *pTmpStt ||
3136 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
3137 pTmpDel = pTmp;
3138 }
3139 else
3140 if( *pStt < *pTmpEnd )
3141 pTmpDel = pTmp;
3142
3143 bGoNext = true;
3144 if (pTmpDel) // is the pam in the range -> delete
3145 {
3146 bool bDelete = true;
3147 if( *ppDelRing == pTmpDel )
3148 {
3149 if( *ppDelRing == m_pCurrentCursor )
3150 {
3151 bDelete = GoNextCursor();
3152 if( bDelete )
3153 {
3154 bGoNext = false;
3155 pTmp = pTmp->GetNext();
3156 }
3157 }
3158 else
3159 bDelete = false; // never delete the StackCursor
3160 }
3161
3162 if( bDelete )
3163 {
3164 if (pTmp == pTmpDel)
3165 pTmp = nullptr;
3166 delete pTmpDel; // invalidate old area
3167 }
3168 else
3169 {
3170 pTmpDel->GetPoint()->Assign(SwNodeOffset(0));
3171 pTmpDel->DeleteMark();
3172 }
3173 pTmpDel = nullptr;
3174 }
3175 if( bGoNext && pTmp )
3176 pTmp = pTmp->GetNext();
3177
3178 } while( !bGoNext || *ppDelRing != pTmp );
3179}
3180
3181//TODO: provide documentation
3189{
3190 const SwNode *pNode = &rIdx;
3191
3192 // create a new PaM
3193 SwPaM aNew( *GetCursor()->GetPoint() );
3194 if( pNode->GetStartNode() )
3195 {
3196 pNode = pNode->StartOfSectionNode();
3197 if( pNode->IsTableNode() )
3198 {
3199 // the given node is in a table, thus park cursor to table node
3200 // (outside of the table)
3201 aNew.GetPoint()->Assign( *pNode->StartOfSectionNode() );
3202 }
3203 else
3204 // Also on the start node itself. Then we need to request the start
3205 // node always via its end node! (StartOfSelection of StartNode is
3206 // the parent)
3207 aNew.GetPoint()->Assign( *pNode->EndOfSectionNode()->StartOfSectionNode() );
3208 }
3209 else
3210 aNew.GetPoint()->Assign( *pNode->StartOfSectionNode() );
3211 aNew.SetMark();
3212 aNew.GetPoint()->Assign(*pNode->EndOfSectionNode());
3213
3214 // take care of all shells
3215 for(SwViewShell& rTmp : GetRingContainer())
3216 {
3217 if( auto pSh = dynamic_cast<SwCursorShell *>(&rTmp))
3218 {
3219 if (pSh->m_pStackCursor)
3220 pSh->ParkPams(&aNew, &pSh->m_pStackCursor);
3221
3222 pSh->ParkPams( &aNew, &pSh->m_pCurrentCursor );
3223 if( pSh->m_pTableCursor )
3224 {
3225 // set table cursor always to 0 and the current one always to
3226 // the beginning of the table
3227 SwPaM* pTCursor = pSh->GetTableCrs();
3228 SwNode* pTableNd = pTCursor->GetPoint()->GetNode().FindTableNode();
3229 if ( pTableNd )
3230 {
3231 pTCursor->GetPoint()->Assign(SwNodeOffset(0));
3232 pTCursor->DeleteMark();
3233 pSh->m_pCurrentCursor->GetPoint()->Assign( *pTableNd );
3234 }
3235 }
3236 }
3237 }
3238}
3239
3246 : SwViewShell( rShell, pInitWin )
3247 , sw::BroadcastingModify()
3248 , m_pStackCursor( nullptr )
3249 , m_pBlockCursor( nullptr )
3250 , m_pTableCursor( nullptr )
3251 , m_pBoxIdx( nullptr )
3252 , m_pBoxPtr( nullptr )
3253 , m_nUpDownX(0)
3254 , m_nLeftFramePos(0)
3255 , m_nCurrentNode(0)
3256 , m_nCurrentContent(0)
3257 , m_nCurrentNdTyp(SwNodeType::NONE)
3258 , m_nCursorMove( 0 )
3259 , m_eMvState( CursorMoveState::NONE )
3260 , m_eEnhancedTableSel(SwTable::SEARCH_NONE)
3261 , m_nMarkedListLevel( 0 )
3262 , m_oldColFrame(nullptr)
3263{
3264 CurrShell aCurr( this );
3265 // only keep the position of the current cursor of the copy shell
3266 m_pCurrentCursor = new SwShellCursor( *this, *(rShell.m_pCurrentCursor->GetPoint()) );
3267 m_pCurrentCursor->GetPointContentNode()->Add( this );
3268
3271 m_bOverwriteCursor = false;
3274 m_bSVCursorVis = true;
3276 m_pVisibleCursor = new SwVisibleCursor( this );
3278}
3279
3282 const SwViewOption *pInitOpt )
3283 : SwViewShell( rDoc, pInitWin, pInitOpt )
3284 , sw::BroadcastingModify()
3285 , m_pStackCursor( nullptr )
3286 , m_pBlockCursor( nullptr )
3287 , m_pTableCursor( nullptr )
3288 , m_pBoxIdx( nullptr )
3289 , m_pBoxPtr( nullptr )
3290 , m_nUpDownX(0)
3291 , m_nLeftFramePos(0)
3292 , m_nCurrentNode(0)
3293 , m_nCurrentContent(0)
3294 , m_nCurrentNdTyp(SwNodeType::NONE)
3295 , m_nCursorMove( 0 )
3296 , m_eMvState( CursorMoveState::NONE ) // state for crsr-travelling - GetModelPositionForViewPoint
3297 , m_eEnhancedTableSel(SwTable::SEARCH_NONE)
3298 , m_nMarkedListLevel( 0 )
3299 , m_oldColFrame(nullptr)
3300{
3301 CurrShell aCurr( this );
3302 // create initial cursor and set it to first content position
3303 SwNodes& rNds = rDoc.GetNodes();
3304
3305 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
3306 SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to the first ContentNode
3307
3308 m_pCurrentCursor = new SwShellCursor( *this, SwPosition( aNodeIdx, pCNd, 0 ) );
3309
3310 // Register shell as dependent at current node. As a result all attribute
3311 // changes can be forwarded via the Link.
3312 pCNd->Add( this );
3313
3316 m_bOverwriteCursor = false;
3319 m_bSVCursorVis = true;
3321
3322 m_pVisibleCursor = new SwVisibleCursor( this );
3323 m_bMacroExecAllowed = true;
3324}
3325
3327{
3328 // if it is not the last view then at least the field should be updated
3329 if( !unique() )
3331 else
3333
3334 delete m_pVisibleCursor;
3335 delete m_pBlockCursor;
3336 delete m_pTableCursor;
3337
3338 // release cursors
3340 delete m_pCurrentCursor->GetNext();
3341 delete m_pCurrentCursor;
3342
3343 // free stack
3344 if (m_pStackCursor)
3345 {
3347 delete m_pStackCursor->GetNext();
3348 delete m_pStackCursor;
3349 }
3350
3351 // #i54025# - do not give a HTML parser that might potentially hang as
3352 // a client at the cursor shell the chance to hang itself on a TextNode
3353 EndListeningAll();
3354}
3355
3357{
3358 if( m_pTableCursor )
3359 return m_pTableCursor;
3360 if( m_pBlockCursor && bBlock )
3361 return &m_pBlockCursor->getShellCursor();
3362 return m_pCurrentCursor;
3363}
3364
3370{
3371 if ( IsTableMode() || GetCursorCnt() > 1 )
3372 return true;
3373
3374 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
3375 return true;
3376
3377 SwPaM* pPam = GetCursor();
3378 return pPam->Start()->GetNodeIndex() + SwNodeOffset(10) <
3379 pPam->End()->GetNodeIndex();
3380}
3381
3383{
3385 {
3387 }
3389}
3390
3393{
3394 OSL_ENSURE( m_bHasFocus, "no focus but cursor should be made visible?" );
3396 {
3397 SwRect aTmp( m_aCharRect );
3399 if( nDiff < m_aCursorHeight.getX() )
3400 aTmp.Top( nDiff + m_aCharRect.Top() );
3401 else
3402 {
3403 aTmp.Top( m_aCursorHeight.getX() + m_aCharRect.Top() );
3404 aTmp.Height( m_aCursorHeight.getY() );
3405 }
3406 if( !aTmp.HasArea() )
3407 {
3408 aTmp.AddHeight(1 );
3409 aTmp.AddWidth(1 );
3410 }
3411 MakeVisible( aTmp );
3412 }
3413 else
3414 {
3415 if( m_aCharRect.HasArea() )
3417 else
3418 {
3419 SwRect aTmp( m_aCharRect );
3420 aTmp.AddHeight(1 );
3421 aTmp.AddWidth(1 );
3422 MakeVisible( aTmp );
3423 }
3424 }
3425}
3426
3429{
3430 if( m_pTableCursor )
3431 {
3432 assert(!"Did not remove table selection!");
3433 return false;
3434 }
3435
3436 // #i45129# - everything is allowed in UI-readonly
3437 if( !m_bAllProtect && GetDoc()->GetDocShell() &&
3438 GetDoc()->GetDocShell()->IsReadOnlyUI() )
3439 return true;
3440
3441 if( m_pCurrentCursor->HasMark() )
3442 ClearMark();
3443
3444 // first check for frames
3445 SwPosition& rNdPos = *m_pCurrentCursor->GetPoint();
3446 SwNodeOffset nNdIdx = rNdPos.GetNodeIndex(); // keep backup
3447 SwNodes& rNds = mxDoc->GetNodes();
3448 SwContentNode* pCNd = rNdPos.GetNode().GetContentNode();
3449 const SwContentFrame * pFrame;
3450
3451 if (pCNd && nullptr != (pFrame = pCNd->getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint())) &&
3452 !IsReadOnlyAvailable() && pFrame->IsProtected() &&
3453 nNdIdx < rNds.GetEndOfExtras().GetIndex() )
3454 {
3455 // skip protected frame
3456 SwPaM aPam( *m_pCurrentCursor->GetPoint() );
3457 aPam.SetMark();
3458 aPam.GetMark()->Assign( rNds.GetEndOfContent() );
3459 aPam.GetPoint()->Assign( *pCNd->EndOfSectionNode() );
3460
3461 bool bFirst = false;
3462 if( nullptr == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward )))
3463 {
3464 aPam.GetMark()->Assign( *rNds.GetEndOfPostIts().StartOfSectionNode() );
3465 pCNd = ::GetNode( aPam, bFirst, fnMoveBackward );
3466 }
3467
3468 if( !pCNd ) // should *never* happen
3469 {
3470 rNdPos.Assign(nNdIdx); // back to old node
3471 return false;
3472 }
3473 *m_pCurrentCursor->GetPoint() = *aPam.GetPoint();
3474 }
3475 else if( bOnlyText && pCNd && pCNd->IsNoTextNode() )
3476 {
3477 // set to beginning of document
3478 rNdPos.Assign( mxDoc->GetNodes().GetEndOfExtras() );
3479 mxDoc->GetNodes().GoNext( &rNdPos );
3480 nNdIdx = rNdPos.GetNodeIndex();
3481 }
3482
3483 bool bOk = true;
3484
3485 // #i9059# cursor may not stand in protected cells
3486 // (unless cursor in protected areas is OK.)
3487 const SwTableNode* pTableNode = rNdPos.GetNode().FindTableNode();
3488 if( !IsReadOnlyAvailable() &&
3489 pTableNode != nullptr && rNdPos.GetNode().IsProtect() )
3490 {
3491 // we're in a table, and we're in a protected area, so we're
3492 // probably in a protected cell.
3493
3494 // move forward into non-protected area.
3495 SwPaM aPam( rNdPos.GetNode(), 0 );
3496 while( aPam.GetPointNode().IsProtect() &&
3497 aPam.Move( fnMoveForward, GoInContent ) )
3498 ; // nothing to do in the loop; the aPam.Move does the moving!
3499
3500 // didn't work? then go backwards!
3501 if( aPam.GetPointNode().IsProtect() )
3502 {
3503 SwPaM aTmpPaM( rNdPos.GetNode(), 0 );
3504 aPam = aTmpPaM;
3505 while( aPam.GetPointNode().IsProtect() &&
3507 ; // nothing to do in the loop; the aPam.Move does the moving!
3508 }
3509
3510 // if we're successful, set the new position
3511 if( ! aPam.GetPointNode().IsProtect() )
3512 {
3513 *m_pCurrentCursor->GetPoint() = *aPam.GetPoint();
3514 }
3515 }
3516
3517 // in a protected frame
3518 const SwSectionNode* pSectNd = rNdPos.GetNode().FindSectionNode();
3519 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
3520 ( !IsReadOnlyAvailable() &&
3521 pSectNd->GetSection().IsProtectFlag() )) )
3522 {
3523 bOk = false;
3524 bool bGoNextSection = true;
3525 for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
3526 {
3527 bool bContinue;
3528 do {
3529 bContinue = false;
3530 for (;;)
3531 {
3532 if (bGoNextSection)
3533 pCNd = rNds.GoNextSection( &rNdPos,
3534 true, !IsReadOnlyAvailable() );
3535 else
3536 pCNd = SwNodes::GoPrevSection( &rNdPos,
3537 true, !IsReadOnlyAvailable() );
3538 if ( pCNd == nullptr) break;
3539 // moved inside a table -> check if it is protected
3540 if( pCNd->FindTableNode() )
3541 {
3542 SwCallLink aTmp( *this );
3543 SwCursorSaveState aSaveState( *m_pCurrentCursor );
3544 aTmp.m_nNodeType = SwNodeType::NONE; // don't do anything in DTOR
3545 if( !m_pCurrentCursor->IsInProtectTable( true ) )
3546 {
3547 const SwSectionNode* pSNd = pCNd->FindSectionNode();
3548 if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
3549 || (!IsReadOnlyAvailable() &&
3550 pSNd->GetSection().IsProtectFlag() ))
3551 {
3552 bOk = true;
3553 break; // found non-protected cell
3554 }
3555 continue; // continue search
3556 }
3557 }
3558 else
3559 {
3560 bOk = true;
3561 break; // found non-protected cell
3562 }
3563 }
3564
3565 if( bOk && rNdPos.GetNodeIndex() < rNds.GetEndOfExtras().GetIndex() )
3566 {
3567 // also check for Fly - might be protected as well
3568 pFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, nullptr);
3569 if (nullptr == pFrame ||
3570 ( !IsReadOnlyAvailable() && pFrame->IsProtected() ) ||
3571 ( bOnlyText && pCNd->IsNoTextNode() ) )
3572 {
3573 // continue search
3574 bOk = false;
3575 bContinue = true;
3576 }
3577 }
3578 } while( bContinue );
3579
3580 if( !bOk )
3581 {
3582 if( !nLoopCnt )
3583 bGoNextSection = false;
3584 rNdPos.Assign( nNdIdx );
3585 }
3586 }
3587 }
3588 if( bOk )
3589 {
3590 pCNd = rNdPos.GetNode().GetContentNode();
3591 const sal_Int32 nContent = rNdPos.GetNodeIndex() < nNdIdx ? pCNd->Len() : 0;
3592 m_pCurrentCursor->GetPoint()->SetContent( nContent );
3593 }
3594 else
3595 {
3596 pCNd = rNdPos.GetNode().GetContentNode();
3597 // if cursor in hidden frame, always move it
3598 if (!pCNd || !pCNd->getLayoutFrame(GetLayout(), nullptr, nullptr))
3599 {
3603 &aTmpState );
3604 }
3605 }
3606 return bOk;
3607}
3608
3610{
3611 if ( GetViewOptions()->IsReadonly() ||
3612 GetViewOptions()->IsFormView() /* Formula view */ )
3613 {
3614 SwFrame *pFrame = GetCurrFrame( false );
3615 const SwFlyFrame* pFly;
3616 const SwSection* pSection;
3617
3618 if( pFrame && pFrame->IsInFly() &&
3619 (pFly = pFrame->FindFlyFrame())->GetFormat()->GetEditInReadonly().GetValue() &&
3620 pFly->Lower() &&
3621 !pFly->Lower()->IsNoTextFrame() &&
3622 !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
3623 {
3624 return false;
3625 }
3626 // edit in readonly sections
3627 else if ( pFrame && pFrame->IsInSct() &&
3628 nullptr != ( pSection = pFrame->FindSctFrame()->GetSection() ) &&
3629 pSection->IsEditInReadonlyFlag() )
3630 {
3631 return false;
3632 }
3633 else if ( !IsMultiSelection() && CursorInsideInputField() )
3634 {
3635 return false;
3636 }
3637
3638 return true;
3639 }
3640 return false;
3641}
3642
3645{
3646 // *never* switch in GlobalDoc
3647 if( (!GetDoc()->GetDocShell() ||
3648 dynamic_cast<const SwGlobalDocShell*>(GetDoc()->GetDocShell()) == nullptr ) &&
3649 bFlag != m_bSetCursorInReadOnly )
3650 {
3651 // If the flag is switched off then all selections need to be
3652 // invalidated. Otherwise we would trust that nothing protected is selected.
3653 if( !bFlag )
3654 {
3655 ClearMark();
3656 }
3657 m_bSetCursorInReadOnly = bFlag;
3658 UpdateCursor();
3659 }
3660}
3661
3662bool SwCursorShell::HasReadonlySel(bool const isReplace) const
3663{
3664 // Treat selections that span over start or end of paragraph of an outline node
3665 // with folded outline content as read-only.
3666 if (GetViewOptions()->IsShowOutlineContentVisibilityButton())
3667 {
3668 SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell();
3669 if (pWrtSh && pWrtSh->HasFoldedOutlineContentSelected())
3670 return true;
3671 }
3672 bool bRet = false;
3673 // If protected area is to be ignored, then selections are never read-only.
3674 if ((IsReadOnlyAvailable() || GetViewOptions()->IsFormView() ||
3675 GetDoc()->GetDocumentSettingManager().get( DocumentSettingId::PROTECT_FORM )) &&
3677 {
3678 if ( m_pTableCursor != nullptr )
3679 {
3680 // TODO: handling when a table cell (cells) is selected
3682 || m_pTableCursor->HasReadonlySel(GetViewOptions()->IsFormView(), isReplace);
3683 }
3684 else
3685 {
3686 for(const SwPaM& rCursor : m_pCurrentCursor->GetRingContainer())
3687 {
3688 if (rCursor.HasReadonlySel(GetViewOptions()->IsFormView(), isReplace))
3689 {
3690 bRet = true;
3691 break;
3692 }
3693 }
3694 }
3695 }
3696 return bRet;
3697}
3698
3700{
3701 // Treat selections that span over start or end of paragraph of an outline node
3702 // with folded outline content as read-only.
3703 if (GetViewOptions()->IsShowOutlineContentVisibilityButton())
3704 {
3705 SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell();
3706 if (pWrtSh && pWrtSh->HasFoldedOutlineContentSelected())
3707 return true;
3708 }
3709 bool bRet = false;
3710
3711 if ( m_pTableCursor != nullptr )
3712 {
3715 }
3716 else
3717 {
3718 for(const SwPaM& rCursor : m_pCurrentCursor->GetRingContainer())
3719 {
3720 if (rCursor.HasHiddenSections())
3721 {
3722 bRet = true;
3723 break;
3724 }
3725 }
3726 }
3727
3728 return bRet;
3729}
3730
3732{
3733 bool bRet = false;
3734
3737 {
3738 sal_Int32 nStt = m_pCurrentCursor->GetPoint()->GetContentIndex();
3739 sal_Int32 nEnd = m_pCurrentCursor->GetMark()->GetContentIndex();
3740 if( nStt > nEnd )
3741 std::swap( nStt, nEnd );
3743 bRet = pCNd && !nStt && nEnd == pCNd->Len();
3744 }
3745 return bRet;
3746}
3747
3749{
3751 Point aPt( pPt ? *pPt : m_pCurrentCursor->GetPtPos() );
3752 if( pPt )
3753 {
3756
3757 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState );
3758 }
3759
3760 return mxDoc->GetTextDirection( aPos, &aPt );
3761}
3762
3764{
3765 const SvxFrameDirection nDir = GetTextDirection( pPt );
3766 return SvxFrameDirection::Vertical_RL_TB == nDir || SvxFrameDirection::Vertical_LR_TB == nDir
3767 || nDir == SvxFrameDirection::Vertical_LR_BT;
3768}
3769
3771{
3772 const SvxFrameDirection nDir = GetTextDirection();
3773 // GetTextDirection uses SvxFrameDirection::Vertical_LR_TB to indicate RTL in
3774 // vertical environment
3775 return SvxFrameDirection::Vertical_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir;
3776}
3777
3780bool SwCursorShell::IsInHiddenRange(const bool bSelect)
3781{
3782 bool bRet = false;
3783 if ( !GetViewOptions()->IsShowHiddenChar() && !m_pCurrentCursor->HasMark() )
3784 {
3786 const SwTextNode* pNode = rPt.GetNode().GetTextNode();
3787 if ( pNode )
3788 {
3789 const sal_Int32 nPos = rPt.GetContentIndex();
3790
3791 // check if nPos is in hidden range
3792 sal_Int32 nHiddenStart;
3793 sal_Int32 nHiddenEnd;
3794 SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3795 if ( COMPLETE_STRING != nHiddenStart )
3796 {
3797 if (bSelect)
3798 {
3799 // make selection:
3801 m_pCurrentCursor->GetMark()->SetContent(nHiddenEnd);
3802 }
3803 bRet = true;
3804 }
3805 }
3806 }
3807
3808 return bRet;
3809}
3810
3812 bool bSearchInNotes,
3813 SwDocPositions eStart, SwDocPositions eEnd,
3814 bool& bCancel,
3815 FindRanges eRng,
3816 bool bReplace )
3817{
3818 if( m_pTableCursor )
3819 GetCursor();
3820 delete m_pTableCursor;
3821 m_pTableCursor = nullptr;
3822 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
3823 sal_Int32 nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd,
3824 bCancel, eRng, bReplace, GetLayout());
3825 if( nRet || bCancel )
3826 UpdateCursor();
3827 return nRet;
3828}
3829
3830sal_Int32 SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl,
3831 SwDocPositions eStart, SwDocPositions eEnd,
3832 bool& bCancel,
3833 FindRanges eRng,
3834 const SwTextFormatColl* pReplFormat )
3835{
3836 if( m_pTableCursor )
3837 GetCursor();
3838 delete m_pTableCursor;
3839 m_pTableCursor = nullptr;
3840 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
3841 sal_Int32 nRet = m_pCurrentCursor->FindFormat(rFormatColl, eStart, eEnd, bCancel, eRng,
3842 pReplFormat );
3843 if( nRet )
3844 UpdateCursor();
3845 return nRet;
3846}
3847
3849 bool bNoCollections,
3850 SwDocPositions eStart, SwDocPositions eEnd,
3851 bool& bCancel,
3852 FindRanges eRng,
3853 const i18nutil::SearchOptions2* pSearchOpt,
3854 const SfxItemSet* rReplSet )
3855{
3856 if( m_pTableCursor )
3857 GetCursor();
3858 delete m_pTableCursor;
3859 m_pTableCursor = nullptr;
3860 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
3861 sal_Int32 nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd,
3862 bCancel, eRng, pSearchOpt, rReplSet, GetLayout());
3863 if( nRet )
3864 UpdateCursor();
3865 return nRet;
3866}
3867
3869{
3870 StartAction();
3871 SwCursor* pCursor = GetCursor();
3872 *pCursor->GetPoint() = *rCursor.GetPoint();
3873 if(rCursor.GetNext() != &rCursor)
3874 {
3875 const SwPaM *_pStartCursor = rCursor.GetNext();
3876 do
3877 {
3878 SwPaM* pCurrentCursor = CreateCursor();
3879 *pCurrentCursor->GetPoint() = *_pStartCursor->GetPoint();
3880 if(_pStartCursor->HasMark())
3881 {
3882 pCurrentCursor->SetMark();
3883 *pCurrentCursor->GetMark() = *_pStartCursor->GetMark();
3884 }
3885 } while( (_pStartCursor = _pStartCursor->GetNext()) != &rCursor );
3886 }
3887 // CreateCursor() adds a copy of current cursor after current, and then deletes mark of current
3888 // cursor; therefore set current cursor's mark only after creating all other cursors
3889 if (rCursor.HasMark())
3890 {
3891 pCursor->SetMark();
3892 *pCursor->GetMark() = *rCursor.GetMark();
3893 }
3894 EndAction();
3895}
3896
3897static const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3898{
3899 const SwStartNode *pRet = rNode.StartOfSectionNode();
3900 while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3902 {
3903 pRet = pRet->StartOfSectionNode();
3904 }
3905 return pRet;
3906}
3907
3914static bool sw_PosOk(const SwPosition & aPos)
3915{
3916 return nullptr != aPos.GetNode().GetContentNode() &&
3917 aPos.GetContentNode();
3918}
3919
3926static bool lcl_CursorOk(SwPaM & aPam)
3927{
3928 return sw_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3929 || sw_PosOk(*aPam.GetMark()));
3930}
3931
3933{
3934 // start of the ring
3935 SwPaM * pStartCursor = GetCursor();
3936 // start loop with second entry of the ring
3937 SwPaM * pCursor = pStartCursor->GetNext();
3938 SwPaM * pTmpCursor;
3939 bool bChanged = false;
3940
3941 // For all entries in the ring except the start entry delete the entry if
3942 // it is invalid.
3943 while (pCursor != pStartCursor)
3944 {
3945 pTmpCursor = pCursor->GetNext();
3946 if ( ! lcl_CursorOk(*pCursor))
3947 {
3948 delete pCursor;
3949 bChanged = true;
3950 }
3951 pCursor = pTmpCursor;
3952 }
3953
3954 if( pStartCursor->HasMark() && !sw_PosOk( *pStartCursor->GetMark() ) )
3955 {
3956 pStartCursor->DeleteMark();
3957 bChanged = true;
3958 }
3959 if (pStartCursor->GetPoint()->GetNode().IsTableNode())
3960 {
3961 // tdf#106959: When cursor points to start of a table, the proper content
3962 // node is the first one inside the table, not the previous one
3963 SwNodes& aNodes = GetDoc()->GetNodes();
3964 SwNodeIndex aIdx(pStartCursor->GetPoint()->GetNode());
3965 if (SwNode* pNode = aNodes.GoNext(&aIdx))
3966 {
3967 SwPaM aTmpPam(*pNode);
3968 *pStartCursor = aTmpPam;
3969 bChanged = true;
3970 }
3971 }
3972 if( !sw_PosOk( *pStartCursor->GetPoint() ) )
3973 {
3974 SwNodes & aNodes = GetDoc()->GetNodes();
3975 const SwNode* pStart = lcl_NodeContext( pStartCursor->GetPoint()->GetNode() );
3976 SwNodeIndex aIdx( pStartCursor->GetPoint()->GetNode() );
3977 SwNode * pNode = SwNodes::GoPrevious(&aIdx);
3978 if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart )
3979 {
3980 pNode = aNodes.GoNext( &aIdx );
3981 if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart )
3982 {
3983 // If the start entry of the ring is invalid replace it with a
3984 // cursor pointing to the beginning of the first content node in the
3985 // document.
3986 aIdx = *(aNodes.GetEndOfContent().StartOfSectionNode());
3987 pNode = aNodes.GoNext( &aIdx );
3988 }
3989 }
3990 bool bFound = (pNode != nullptr);
3991
3992 assert(bFound);
3993
3994 if (bFound)
3995 {
3996 SwPaM aTmpPam(*pNode);
3997 *pStartCursor = aTmpPam;
3998 }
3999
4000 bChanged = true;
4001 }
4002
4003 // If at least one of the cursors in the ring have been deleted or replaced,
4004 // remove the table cursor.
4005 if (m_pTableCursor != nullptr && bChanged)
4007}
4008
4010{
4011 OUString aResult;
4012
4013 if (IsMultiSelection())
4014 aResult += SwResId(STR_MULTISEL);
4015 else
4016 aResult = SwDoc::GetPaMDescr(*GetCursor());
4017
4018 return aResult;
4019}
4020
4022{
4023 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwCursorShell"));
4024
4025 SwViewShell::dumpAsXml(pWriter);
4026
4027 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_pCurrentCursor"));
4028 for (const SwPaM& rPaM : m_pCurrentCursor->GetRingContainer())
4029 rPaM.dumpAsXml(pWriter);
4030 (void)xmlTextWriterEndElement(pWriter);
4031
4032 (void)xmlTextWriterEndElement(pWriter);
4033}
4034
4035static void lcl_FillRecognizerData( std::vector< OUString >& rSmartTagTypes,
4036 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
4037 const SwWrongList& rSmartTagList, sal_Int32 nCurrent )
4038{
4039 // Insert smart tag information
4040 std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
4041
4042 for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
4043 {
4044 const sal_Int32 nSTPos = rSmartTagList.Pos( i );
4045 const sal_Int32 nSTLen = rSmartTagList.Len( i );
4046
4047 if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
4048 {
4049 const SwWrongArea* pArea = rSmartTagList.GetElement( i );
4050 if ( pArea )
4051 {
4052 rSmartTagTypes.push_back( pArea->maType );
4053 aStringKeyMaps.push_back( pArea->mxPropertyBag );
4054 }
4055 }
4056 }
4057
4058 if ( !rSmartTagTypes.empty() )
4059 {
4060 rStringKeyMaps = comphelper::containerToSequence(aStringKeyMaps);
4061 }
4062}
4063
4064static void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
4065 SwTextNode& rNode, sal_Int32 nBegin, sal_Int32 nLen )
4066{
4067 // create SwPosition for nStartIndex
4068 SwPosition aStartPos( rNode, nBegin );
4069 // create SwPosition for nEndIndex
4070 SwPosition aEndPos( rNode, nBegin + nLen );
4071
4072 const rtl::Reference<SwXTextRange> xRange =
4073 SwXTextRange::CreateXTextRange(rNode.GetDoc(), aStartPos, &aEndPos);
4074
4075 rRange = xRange;
4076}
4077
4078void SwCursorShell::GetSmartTagTerm( std::vector< OUString >& rSmartTagTypes,
4079 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
4080 uno::Reference< text::XTextRange>& rRange ) const
4081{
4082 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
4083 return;
4084
4085 SwPaM* pCursor = GetCursor();
4086 SwPosition aPos( *pCursor->GetPoint() );
4087 SwTextNode *pNode = aPos.GetNode().GetTextNode();
4088 if ( !pNode || pNode->IsInProtectSect() )
4089 return;
4090
4091 const SwWrongList *pSmartTagList = pNode->GetSmartTags();
4092 if ( !pSmartTagList )
4093 return;
4094
4095 sal_Int32 nCurrent = aPos.GetContentIndex();
4096 sal_Int32 nBegin = nCurrent;
4097 sal_Int32 nLen = 1;
4098
4099 if (!pSmartTagList->InWrongWord(nBegin, nLen) || pNode->IsSymbolAt(nBegin))
4100 return;
4101
4102 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
4103 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
4104 if ( pSubList )
4105 {
4106 pSmartTagList = pSubList;
4107 nCurrent = 0;
4108 }
4109
4110 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
4111 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
4112}
4113
4114// see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
4115void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect )
4116{
4117 SwPaM* pCursor = GetCursor();
4118 SwPosition aPos( *pCursor->GetPoint() );
4119 Point aPt( rPt );
4121 SwSpecialPos aSpecialPos;
4122 eTmpState.m_pSpecialPos = &aSpecialPos;
4123 SwTextNode *pNode;
4124 const SwWrongList *pSmartTagList;
4125
4126 if( !GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &eTmpState ) )
4127 return;
4128 pNode = aPos.GetNode().GetTextNode();
4129 if( !pNode )
4130 return;
4131 pSmartTagList = pNode->GetSmartTags();
4132 if( !pSmartTagList )
4133 return;
4134 if( pNode->IsInProtectSect() )
4135 return;
4136
4137 sal_Int32 nBegin = aPos.GetContentIndex();
4138 sal_Int32 nLen = 1;
4139
4140 if (!pSmartTagList->InWrongWord(nBegin, nLen) || pNode->IsSymbolAt(nBegin))
4141 return;
4142
4143 // get smarttag word
4144 OUString aText( pNode->GetText().copy(nBegin, nLen) );
4145
4146 //save the start and end positions of the line and the starting point
4147 Push();
4148 LeftMargin();
4149 const sal_Int32 nLineStart = GetCursor()->GetPoint()->GetContentIndex();
4150 RightMargin();
4151 const sal_Int32 nLineEnd = GetCursor()->GetPoint()->GetContentIndex();
4153
4154 // make sure the selection build later from the data below does not
4155 // include "in word" character to the left and right in order to
4156 // preserve those. Therefore count those "in words" in order to
4157 // modify the selection accordingly.
4158 const sal_Unicode* pChar = aText.getStr();
4159 sal_Int32 nLeft = 0;
4160 while (*pChar++ == CH_TXTATR_INWORD)
4161 ++nLeft;
4162 pChar = aText.getLength() ? aText.getStr() + aText.getLength() - 1 : nullptr;
4163 sal_Int32 nRight = 0;
4164 while (pChar && *pChar-- == CH_TXTATR_INWORD)
4165 ++nRight;
4166
4167 aPos.SetContent( nBegin + nLeft );
4168 pCursor = GetCursor();
4169 *pCursor->GetPoint() = aPos;
4170 pCursor->SetMark();
4171 ExtendSelection( true, nLen - nLeft - nRight );
4172 // do not determine the rectangle in the current line
4173 const sal_Int32 nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
4174 // take one less than the line end - otherwise the next line would
4175 // be calculated
4176 const sal_Int32 nWordEnd = std::min(nBegin + nLen - nLeft - nRight, nLineEnd);
4177 Push();
4178 pCursor->DeleteMark();
4179 SwPosition& rPos = *GetCursor()->GetPoint();
4180 rPos.SetContent( nWordStart );
4181 SwRect aStartRect;
4182 SwCursorMoveState aState;
4183 aState.m_bRealWidth = true;
4184 SwContentNode* pContentNode = pCursor->GetPointContentNode();
4185 std::pair<Point, bool> const tmp(rPt, false);
4186 SwContentFrame *pContentFrame = pContentNode->getLayoutFrame(
4187 GetLayout(), pCursor->GetPoint(), &tmp);
4188
4189 pContentFrame->GetCharRect( aStartRect, *pCursor->GetPoint(), &aState );
4190 rPos.SetContent( nWordEnd - 1 );
4191 SwRect aEndRect;
4192 pContentFrame->GetCharRect( aEndRect, *pCursor->GetPoint(),&aState );
4193 rSelectRect = aStartRect.Union( aEndRect );
4195}
4196
4197/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
const StyleSettings & GetStyleSettings() const
void SetStyleSettings(const StyleSettings &rSet)
static const AllSettings & GetSettings()
helper class to disable creation of an action by a callback event in particular, change event from a ...
Definition: rootfrm.hxx:465
void DrawSelectionXOR(OutlinerViewShell *pOtherShell)
void RegisterOtherShell(OutlinerViewShell *pOtherShell)
void ShowCursor(bool bGotoCursor=true, bool bForceVisCursor=true, bool bActivate=false)
virtual const SwRootFrame * GetCurrentLayout() const =0
virtual void NotifyCursorUpdate(const SwCursorShell &rCursorShell)=0
virtual void SetSettings(const AllSettings &rSettings)
const AllSettings & GetSettings() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
constexpr tools::Long getX() const
constexpr tools::Long getY() const
SfxHintId GetId() const
static void notifyOtherView(const SfxViewShell *pThisView, SfxViewShell const *pOtherView, int nType, std::string_view rKey, const OString &rPayload)
static void notifyOtherViews(const SfxViewShell *pThisView, int nType, std::string_view rKey, const OString &rPayload)
void SetReadOnlyUI(bool bReadOnly=true)
virtual void libreOfficeKitViewCallback(int nType, const OString &pPayload) const override
void SetCursorBlinkTime(sal_uInt64 nBlinkTime)
sal_uInt64 GetCursorBlinkTime() const
static void SetSearchLabel(const SearchLabel &rSL)
Access to the block cursor.
Definition: BlockCursor.hxx:40
SwShellCursor & getShellCursor()
Access to the shell cursor.
Definition: BlockCursor.cxx:25
std::optional< Point > const & getStartPoint() const
The document coordinates where the block selection has been started.
Definition: BlockCursor.hxx:72
void clearPoints()
Deletion of the mouse created rectangle.
Definition: BlockCursor.hxx:84
void setEndPoint(const Point &rPt)
Defines the ending vertex of the block selection.
Definition: BlockCursor.hxx:67
std::optional< Point > const & getEndPoint() const
The document coordinates where the block selection ends (at the moment)
Definition: BlockCursor.hxx:77
void setStartPoint(const Point &rPt)
Defines the starting vertex of the block selection.
Definition: BlockCursor.hxx:60
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:59
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1223
virtual sal_Int32 Len() const
Definition: node.cxx:1256
A helper class to save cursor state (position).
Definition: swcrsr.hxx:233
tools::Long m_nLeftFramePos
Definition: crsrsh.hxx:200
void ExtendedSelectAll(bool bFootnotes=true)
Definition: crsrsh.cxx:748
bool Pop(PopMode, ::std::optional< SwCallLink > &roLink)
SAL_DLLPRIVATE void UpdateCursor(sal_uInt16 eFlags=SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE, bool bIdleEnd=false)
Definition: crsrsh.cxx:1876
tools::Long GetUpDownX() const
Definition: crsrsh.hxx:362
SwVisibleCursor * GetVisibleCursor() const
Definition: crsrsh.cxx:3037
static void FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection)
Definition: crsrsh.cxx:463
SAL_DLLPRIVATE void MarkListLevel(const OUString &sListId, const int nLevel)
Mark a certain list level of a certain list.
Definition: crsrsh.cxx:388
bool m_bSetCursorInReadOnly
Definition: crsrsh.hxx:237
bool LeftMargin()
Definition: crsrsh.hxx:370
bool GoPrevCell()
Definition: trvltbl.cxx:101
OUString GetCursorDescr() const
Returns textual description of the current selection.
Definition: crsrsh.cxx:4009
bool m_bMacroExecAllowed
Definition: crsrsh.hxx:244
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2550
SAL_DLLPRIVATE void ParkPams(SwPaM *pDelRg, SwShellCursor **ppDelRing)
Definition: crsrsh.cxx:3117
void ShowCursors(bool bCursorVis)
Definition: crsrsh.cxx:2697
bool IsSelOnePara() const
Definition: crsrsh.cxx:1362
void ShowCursor()
Definition: crsrsh.cxx:2710
bool IsReadOnlyAvailable() const
Definition: crsrsh.hxx:494
void ClearTableBoxContent()
Definition: trvltbl.cxx:906
void StartAction()
Definition: crsrsh.cxx:226
const SwTableNode * IsCursorInTable() const
Check if Point of current cursor is placed within a table.
Definition: crsrsh.cxx:600
bool TrySelectOuterTable()
Definition: crsrsh.cxx:666
bool m_bInCMvVisportChgd
Flag for CursorMoves.
Definition: crsrsh.hxx:229
friend class SwVisibleCursor
Definition: crsrsh.hxx:153
bool IsEndOfTable() const
at the very last SwPosition inside a table
Definition: crsrsh.cxx:1419
sal_uInt16 GetNextPrevPageNum(bool bNext=true)
Definition: crsrsh.cxx:1553
bool IsInVerticalText(const Point *pPt=nullptr) const
Definition: crsrsh.cxx:3763
bool GoPrevCursor()
go to the previous SSelection
Definition: crsrsh.cxx:1676
void HideCursors()
Definition: crsrsh.cxx:2681
bool m_bSendAccessibleCursorEvents
Definition: crsrsh.hxx:242
void SttCursorMove()
Definition: crsrsh.cxx:301
void BlockCursorToCursor()
Definition: crsrsh.cxx:1189
SwShellCursor * GetCursor_()
Definition: crsrsh.hxx:343
bool m_bIgnoreReadonly
Definition: crsrsh.hxx:232
void SwapPam()
Definition: crsrsh.cxx:1262
void ShellGetFocus()
Definition: crsrsh.cxx:2758
static void FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage)
Definition: crsrsh.cxx:441
sal_uInt16 GetCursorCnt(bool bAll=true) const
Get the number of elements in the ring of cursors.
Definition: crsrsh.cxx:3055
bool IsMacroExecAllowed() const
Definition: crsrsh.hxx:873
Point & GetCursorDocPos() const
Definition: crsrsh.hxx:925
void ParkCursor(const SwNode &rIdx)
Remove selections and additional cursors of all shells.
Definition: crsrsh.cxx:3188
Point m_aOldRBPos
Right/Bottom of last VisArea.
Definition: crsrsh.hxx:177
virtual SwCursor & CreateNewShellCursor() override
Create and return a new shell cursor.
Definition: crsrsh.cxx:172
StartsWith StartsWith_()
If document body starts with a table or starts/ends with hidden paragraph.
Definition: crsrsh.cxx:895
bool IsInHiddenRange(const bool bSelect)
If the current cursor position is inside a hidden range true is returned.
Definition: crsrsh.cxx:3780
static void FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn)
Definition: crsrsh.cxx:452
tools::Long m_nUpDownX
try to move the cursor on up/down always in the same column
Definition: crsrsh.hxx:198
bool m_bChgCallFlag
attribute change inside Start- and EndAction
Definition: crsrsh.hxx:220
void HideCursor()
Definition: crsrsh.cxx:2731
void SetSelection(const SwPaM &rCursor)
Definition: crsrsh.cxx:3868
int SetCursor(const Point &rPt, bool bOnlyText=false, bool bBlock=true)
Definition: crsrsh.cxx:1047
bool HasSelection() const
Does the current cursor create a selection?
Definition: crsrsh.cxx:2838
bool IsMultiSelection() const
Definition: crsrsh.hxx:915
CursorMoveState m_eMvState
Status for Cursor-Travelling - GetModelPositionForViewPoint.
Definition: crsrsh.hxx:212
bool SttEndDoc(bool bStt)
Definition: crsrsh.cxx:579
void ClearUpCursors()
Definition: crsrsh.cxx:3932
Point m_aCursorHeight
height & offset from visible Cursor
Definition: crsrsh.hxx:176
void SetReadOnlyAvailable(bool bFlag)
is the cursor allowed to enter ReadOnly sections?
Definition: crsrsh.cxx:3644
virtual SwCursor & GetCurrentShellCursor() override
Return the current shell cursor.
Definition: crsrsh.cxx:185
void NormalizePam(bool bPointFirst=true)
Ensure point and mark of the current PaM are in a specific order.
Definition: crsrsh.cxx:1256
SwBlockCursor * m_pBlockCursor
interface of cursor for block (=rectangular) selection
Definition: crsrsh.hxx:190
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: crsrsh.cxx:982
bool MoveStartText()
Definition: crsrsh.cxx:732
bool m_bAllProtect
Flag for areas.
Definition: crsrsh.hxx:227
bool IsCursorReadonly() const
Definition: crsrsh.cxx:3609
bool IsEndPara() const
Definition: crsrsh.cxx:1400
bool RightMargin(bool bAPI=false)
Definition: crsrsh.hxx:371
int CompareCursorStackMkCurrPt() const
Definition: crsrsh.cxx:1340
void GetSmartTagTerm(std::vector< OUString > &rSmartTagTypes, css::uno::Sequence< css::uno::Reference< css::container::XStringKeyMap > > &rStringKeyMaps, css::uno::Reference< css::text::XTextRange > &rRange) const
Definition: crsrsh.cxx:4078
bool m_bSelTableCells
Definition: crsrsh.hxx:234
bool ParkTableCursor()
Invalidate cursors.
Definition: crsrsh.cxx:3100
void GetSmartTagRect(const Point &rPt, SwRect &rSelectRect)
Definition: crsrsh.cxx:4115
bool bColumnChange()
Definition: crsrsh.cxx:474
bool GotoPage(sal_uInt16 nPage)
Definition: crsrsh.cxx:1488
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
OUString GetSelText() const
get selected text of a node at current cursor
Definition: crsrsh.cxx:2862
void TableCursorToCursor()
enter block mode, change normal cursor into block cursor
Definition: crsrsh.cxx:1182
bool m_bGCAttr
Definition: crsrsh.hxx:231
bool ExtendSelection(bool bEnd=true, sal_Int32 nCount=1)
extend current SSelection by n characters
Definition: crsrsh.cxx:2944
bool MoveOutOfTable()
Definition: crsrsh.cxx:627
bool IsSttPara() const
Definition: crsrsh.cxx:1381
void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: crsrsh.cxx:1711
bool m_bCallChgLnk
flag for derived classes
Definition: crsrsh.hxx:224
bool IsOverReadOnlyPos(const Point &rPt) const
Definition: crsrsh.cxx:3042
bool ShouldWait() const
Should WaitPtr be switched on for the clipboard?
Definition: crsrsh.cxx:3369
bool GoNextCursor()
go to the next SSelection
Definition: crsrsh.cxx:1657
void CursorToBlockCursor()
leave block mode, change block cursor into normal cursor
Definition: crsrsh.cxx:1206
int m_nMarkedListLevel
Definition: crsrsh.hxx:216
bool LeftRight(bool, sal_uInt16, SwCursorSkipMode, bool)
Definition: crsrsh.cxx:323
bool CursorInsideInputField() const
Definition: crstrvl.cxx:1094
void Combine()
Combine two cursors.
Definition: crsrsh.cxx:2647
bool CheckTableBoxContent(const SwPosition *pPos=nullptr)
Definition: trvltbl.cxx:804
SwPaM * CreateCursor()
delete the current cursor and make the following into the current
Definition: crsrsh.cxx:123
bool SetVisibleCursor(const Point &rPt)
Move visible cursor to given position in document.
Definition: crsrsh.cxx:2979
void GetPageNum(sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum, bool bAtCursorPos=true, const bool bCalcFrame=true)
Definition: crsrsh.cxx:1509
SAL_DLLPRIVATE bool IsAtLRMargin(bool, bool bAPI=false) const
Definition: crsrsh.cxx:573
bool HasMark() const
Definition: crsrsh.hxx:908
bool IsSelFullPara() const
Definition: crsrsh.cxx:3731
SAL_DLLPRIVATE SvxFrameDirection GetTextDirection(const Point *pPt=nullptr) const
Definition: crsrsh.cxx:3748
bool IsStartOfDoc() const
Definition: crsrsh.cxx:3070
void EndAction(const bool bIdleEnd=false)
Definition: crsrsh.cxx:243
SwCursorShell(SwDoc &rDoc, vcl::Window *pWin, const SwViewOption *pOpt)
default constructor
Definition: crsrsh.cxx:3281
Point GetCursorPagePos() const
Definition: crsrsh.cxx:1443
virtual ~SwCursorShell() override
Definition: crsrsh.cxx:3326
SAL_DLLPRIVATE bool UpDown(bool, sal_uInt16)
Definition: crsrsh.cxx:508
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
forward all attribute/format changes at the current node to the Link
Definition: crsrsh.cxx:2804
sal_Int32 FindFormat(const SwTextFormatColl &rFormatColl, SwDocPositions eStart, SwDocPositions eEnd, bool &bCancel, FindRanges eRng, const SwTextFormatColl *pReplFormat)
Definition: crsrsh.cxx:3830
bool TestCurrPam(const Point &rPt, bool bTstHit=false)
Search in the selected area for a Selection that covers the given point.
Definition: crsrsh.cxx:1277
bool MovePage(SwWhichPage, SwPosPage)
Definition: crsrsh.cxx:920
sal_uInt16 m_nCursorMove
Definition: crsrsh.hxx:211
bool m_bBasicHideCursor
Definition: crsrsh.hxx:236
void ShellLoseFocus()
Definition: crsrsh.cxx:2751
bool Right(sal_uInt16 nCnt, SwCursorSkipMode nMode, bool bAllowVisual=false)
Definition: crsrsh.hxx:366
SwContentFrame * GetCurrFrame(const bool bCalcFrame=true) const
Get current frame in which the cursor is positioned.
Definition: crsrsh.cxx:2771
SwVisibleCursor * m_pVisibleCursor
the visible cursor
Definition: crsrsh.hxx:188
SwShellCursor * m_pStackCursor
stack for the cursor
Definition: crsrsh.hxx:187
SAL_DLLPRIVATE bool LRMargin(bool, bool bAPI=false)
Definition: crsrsh.cxx:538
virtual void VisPortChgd(const SwRect &) override
Definition: crsrsh.cxx:1757
sal_Int32 Find_Text(const i18nutil::SearchOptions2 &rSearchOpt, bool bSearchInNotes, SwDocPositions eStart, SwDocPositions eEnd, bool &bCancel, FindRanges eRng, bool bReplace=false)
Definition: crsrsh.cxx:3811
virtual void MakeSelVisible()
show the current selected "object"
Definition: crsrsh.cxx:3392
SAL_DLLPRIVATE bool isInHiddenTextFrame(SwShellCursor *pShellCursor)
Definition: crsrsh.cxx:946
bool IsInRightToLeftText() const
Definition: crsrsh.cxx:3770
void ClearMark()
Definition: crsrsh.cxx:1225
bool SetInFrontOfLabel(bool bNew)
Definition: crsrsh.cxx:1462
Link< SwCursorShell &, void > m_aGrfArrivedLnk
Link calls to UI if a graphic is arrived.
Definition: crsrsh.hxx:184
SwNodeType m_nCurrentNdTyp
Definition: crsrsh.hxx:203
sal_Int32 FindAttrs(const SfxItemSet &rSet, bool bNoCollections, SwDocPositions eStart, SwDocPositions eEnd, bool &bCancel, FindRanges eRng, const i18nutil::SearchOptions2 *pSearchOpt, const SfxItemSet *rReplSet)
Definition: crsrsh.cxx:3848
bool IsOverwriteCursor() const
Definition: crsrsh.hxx:475
bool m_bSVCursorVis
SV-Cursor visible/invisible.
Definition: crsrsh.hxx:219
bool IsEndOfDoc() const
Definition: crsrsh.cxx:3082
void CallChgLnk()
Definition: crsrsh.cxx:2847
SwShellCursor * getShellCursor(bool bBlock)
Delivers the current shell cursor.
Definition: crsrsh.cxx:3356
void DestroyCursor()
transform TableCursor to normal cursor, nullify Tablemode
Definition: crsrsh.cxx:151
OUString m_sMarkedListId
table rows or columns selected by not cell by cell
Definition: crsrsh.hxx:215
bool MoveSection(SwWhichSection, SwMoveFnCollection const &)
Definition: crsrsh.cxx:1006
SwRect m_aCharRect
Char-SRectangle on which the cursor is located.
Definition: crsrsh.hxx:175
SAL_DLLPRIVATE void UpdateMarkedListLevel()
Updates the marked list level according to the cursor.
Definition: crsrsh.cxx:412
SwShellTableCursor * m_pTableCursor
table Cursor; only in tables when the selection lays over 2 columns
Definition: crsrsh.hxx:192
CursorFlag
for calling UpdateCursor
Definition: crsrsh.hxx:162
@ READONLY
make visible in spite of Readonly
Definition: crsrsh.hxx:166
@ CHKRANGE
check overlapping PaMs
Definition: crsrsh.hxx:165
@ SCROLLWIN
scroll window
Definition: crsrsh.hxx:164
@ UPDOWN
keep Up/Down on columns
Definition: crsrsh.hxx:163
void GetCharRectAt(SwRect &rRect, const SwPosition *pPos)
Definition: crsrsh.cxx:1503
void RefreshBlockCursor()
Definition: crsrsh.cxx:2436
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override
Definition: crsrsh.cxx:4021
void KillPams()
Definition: crsrsh.cxx:1308
SwNodeOffset m_nCurrentNode
Definition: crsrsh.hxx:201
sal_uInt16 GetPageNumSeqNonEmpty()
Definition: crsrsh.cxx:1529
Link< LinkParamNone *, void > m_aChgLnk
link will be called by every attribute/ format changes at cursor position.
Definition: crsrsh.hxx:182
SwFrame * m_oldColFrame
Definition: crsrsh.hxx:246
void GoNextPrevCursorSetSearchLabel(const bool bNext)
Definition: crsrsh.cxx:1694
bool m_bHasFocus
Shell is "active" in a window.
Definition: crsrsh.hxx:218
bool HasReadonlySel(bool isReplace=false) const
Definition: crsrsh.cxx:3662
SwShellCursor * m_pCurrentCursor
current cursor
Definition: crsrsh.hxx:186
bool IsInHeaderFooter(bool *pbInHeader=nullptr) const
Definition: crsrsh.cxx:1038
size_t UpdateTableSelBoxes()
Definition: crsrsh.cxx:3382
bool m_bOverwriteCursor
Definition: crsrsh.hxx:238
bool m_bAutoUpdateCells
Definition: crsrsh.hxx:235
void UpdateCursorPos()
Set the cursor back into content.
Definition: crsrsh.cxx:1791
bool IsTableMode() const
Definition: crsrsh.hxx:668
SAL_DLLPRIVATE void sendLOKCursorUpdates()
Definition: crsrsh.cxx:2364
bool IsInFrontOfLabel() const
Definition: crsrsh.cxx:1457
bool IsCursorInFootnote() const
Definition: crsrsh.cxx:1437
void EndCursorMove(const bool bIdleEnd=false)
Definition: crsrsh.cxx:310
bool IsBlockMode() const
Definition: crsrsh.hxx:665
sal_Int32 m_nCurrentContent
Definition: crsrsh.hxx:202
bool GoNextCell(bool bAppendLine=true)
set cursor into next/previous cell
Definition: trvltbl.cxx:39
bool HasHiddenSections() const
Definition: crsrsh.cxx:3699
sal_Unicode GetChar(bool bEnd=true, tools::Long nOffset=0)
get the nth character of the current SSelection
Definition: crsrsh.cxx:2918
OUString getPageRectangles()
Implementation of lok::Document::getPartPageRectangles() for Writer.
Definition: crsrsh.cxx:1598
sal_uInt16 GetPageCnt()
Definition: crsrsh.cxx:1591
::std::optional<::std::pair< SwNode const *, ::std::vector< SwTableNode * > > > ExtendedSelectedAll() const
If ExtendedSelectAll() was called and selection didn't change since then.
Definition: crsrsh.cxx:823
bool FindValidContentNode(bool bOnlyText)
search a valid content position (not protected/hidden)
Definition: crsrsh.cxx:3428
void NotifyCursor(SfxViewShell *pViewShell) const
See SwView::NotifyCursor().
Definition: crsrsh.cxx:1619
bool m_bVisPortChgd
in VisPortChg-Call
Definition: crsrsh.hxx:221
bool MoveSection(SwWhichSection, SwMoveFnCollection const &)
Definition: swcrsr.cxx:2329
bool IsNoContent() const
determine if point is outside of the node-array's content area
Definition: swcrsr.cxx:181
sal_uInt8 GetCursorBidiLevel() const
Definition: swcrsr.hxx:211
bool LeftRightMargin(SwRootFrame const &rLayout, bool bLeftMargin, bool bAPI)
Definition: swcrsr.cxx:2129
virtual bool IsSelOvr(SwCursorSelOverFlags eFlags=SwCursorSelOverFlags::CheckNodeSection|SwCursorSelOverFlags::Toggle|SwCursorSelOverFlags::ChangePos)
Definition: swcrsr.cxx:222
SwCursor * GetNext()
Definition: swcrsr.hxx:219
sal_Int32 FindAttrs(const SfxItemSet &rSet, bool bNoCollections, SwDocPositions nStart, SwDocPositions nEnd, bool &bCancel, FindRanges, const i18nutil::SearchOptions2 *pSearchOpt, const SfxItemSet *rReplSet=nullptr, SwRootFrame const *const pLayout=nullptr)
search for attributes
Definition: findattr.cxx:1409
sal_Int32 Find_Text(const i18nutil::SearchOptions2 &rSearchOpt, bool bSearchInNotes, SwDocPositions nStart, SwDocPositions nEnd, bool &bCancel, FindRanges, bool bReplace=false, SwRootFrame const *const pLayout=nullptr)
Definition: findtxt.cxx:1004
bool IsInProtectTable(bool bMove=false, bool bChgCursor=true)
Definition: swcrsr.cxx:557
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: swcrsr.cxx:2290
sal_Int32 FindFormat(const SwTextFormatColl &rFormatColl, SwDocPositions nStart, SwDocPositions nEnd, bool &bCancel, FindRanges, const SwTextFormatColl *pReplFormat, SwRootFrame const *const pLayout=nullptr)
search for Format-Collections
Definition: findcoll.cxx:75
bool SttEndDoc(bool bSttDoc)
Definition: swcrsr.cxx:2167
void SetCursorBidiLevel(sal_uInt8 nNewLevel)
Definition: swcrsr.hxx:212
virtual bool LeftRight(bool bLeft, sal_uInt16 nCnt, SwCursorSkipMode nMode, bool bAllowVisual, bool bSkipHidden, bool bInsertCursor, SwRootFrame const *pLayout, bool isFieldNames)
Definition: swcrsr.cxx:1730
void SetColumnSelection(bool bNew)
Definition: swcrsr.hxx:215
bool IsAtLeftRightMargin(SwRootFrame const &rLayout, bool bLeftMargin, bool bAPI) const
Definition: swcrsr.cxx:2146
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
Definition: doc.hxx:197
static SwTableNode * IsInTable(const SwNode &)
Definition: ndtbl.cxx:219
void UpdateNumRule()
Definition: docnum.cxx:2628
static OUString GetPaMDescr(const SwPaM &rPaM)
Returns a textual description of a PaM.
Definition: doc.cxx:1772
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:419
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
Ends a section of nodes in the document model.
Definition: node.hxx:378
void GetTabCols(SwTabCols &rToFill) const
Info about columns and margins.
Definition: fetab.cxx:815
void GetTabRows(SwTabCols &rToFill) const
Definition: fetab.cxx:832
const SwRect & GetAnyCurRect(CurRectType eType, const Point *pPt=nullptr, const css::uno::Reference< css::embed::XEmbeddedObject > &=css::uno::Reference< css::embed::XEmbeddedObject >()) const
Definition: fews.cxx:90
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
const SwRect & getFrameArea() const
Definition: frame.hxx:179
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsCellFrame() const
Definition: frame.hxx:1232
bool IsTextFrame() const
Definition: frame.hxx:1240
sal_uInt16 GetVirtPageNum() const
Definition: trvlfrm.cxx:1817
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1117
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1121
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1105
SwFrame * GetNext()
Definition: frame.hxx:682
bool IsHeaderFrame() const
Definition: frame.hxx:1196
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1799
bool IsInTab() const
Definition: frame.hxx:961
bool IsProtected() const
Is the Frame or rather the Section in which it lies protected?
Definition: trvlfrm.cxx:1639
SwFrame * GetLower()
Definition: findfrm.cxx:196
bool IsInFly() const
Definition: frame.hxx:967
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const
Definition: unusedf.cxx:47
void PrepareCursor()
Definition: calcmove.cxx:403
bool IsFooterFrame() const
Definition: frame.hxx:1200
SwLayoutFrame * GetUpper()
Definition: frame.hxx:684
bool IsVertical() const
Definition: frame.hxx:979
bool IsNoTextFrame() const
Definition: frame.hxx:1244
bool IsFlyFrame() const
Definition: frame.hxx:1216
SwFrame * GetPrev()
Definition: frame.hxx:683
SwFrame * FindColFrame()
Definition: findfrm.cxx:615
SwPageFrame * FindPageFrame()
Definition: frame.hxx:686
virtual bool GetCharRect(SwRect &, const SwPosition &, SwCursorMoveState *=nullptr, bool bAllowFarAway=true) const
Definition: unusedf.cxx:72
bool IsInSct() const
Definition: frame.hxx:973
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame.
Definition: layfrm.hxx:36
const SwFrame * Lower() const
Definition: layfrm.hxx:101
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNodes & GetNodes() const
Definition: ndindex.hxx:119
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
Base class of the Writer document model elements.
Definition: node.hxx:98
SwStartNode * GetStartNode()
Definition: node.hxx:642
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:218
bool IsProtect() const
Is node in something that is protected (range, frame, table cells ... including anchor in case of fra...
Definition: node.cxx:449
bool IsNoTextNode() const
Definition: node.hxx:194
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:706
bool IsInProtectSect() const
Is node in a protected area?
Definition: node.cxx:439
bool IsContentNode() const
Definition: node.hxx:188
SwDoc & GetDoc()
Definition: node.hxx:233
bool IsEndNode() const
Definition: node.hxx:189
bool IsStartNode() const
Definition: node.hxx:187
bool IsSectionNode() const
Definition: node.hxx:192
bool IsTableNode() const
Definition: node.hxx:191
bool IsTextNode() const
Definition: node.hxx:190
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:968
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwTableNode * GetTableNode()
Definition: node.hxx:650
SwNodeType GetNodeType() const
Definition: node.hxx:166
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:695
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:163
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1333
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
SwContentNode * GoNextSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true) const
Go to next content-node that is not protected or hidden (Both set FALSE ==> GoNext/GoPrevious!...
Definition: nodes.cxx:1948
SwNode & GetEndOfPostIts() const
A still empty section.
Definition: ndarr.hxx:154
SwNode * FindPrvNxtFrameNode(const SwNode &rFrameNd, const SwNode *pEnd, SwRootFrame const *pLayout=nullptr) const
Search previous / next content node or table node with frames.
Definition: nodes.cxx:2188
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:2064
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
void SetInFrontOfLabel_(bool bNew)
Definition: pam.hxx:227
SwNode & GetPointNode() const
Definition: pam.hxx:275
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
void Exchange()
Definition: pam.hxx:242
bool IsInFrontOfLabel() const
Definition: pam.hxx:226
void Normalize(bool bPointFirst=true)
Normalizes PaM, i.e.
Definition: pam.cxx:689
std::pair< const SwPosition *, const SwPosition * > StartEnd() const
Because sometimes the cost of the operator<= can add up.
Definition: pam.hxx:269
bool IsMultiSelection() const
Definition: pam.hxx:322
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:279
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * End() const
Definition: pam.hxx:263
SwPaM * GetNext()
Definition: pam.hxx:314
SwContentNode * GetMarkContentNode() const
Definition: pam.hxx:280
void DeleteMark()
Definition: pam.hxx:232
SwNode & GetMarkNode() const
Definition: pam.hxx:276
bool HasReadonlySel(bool bFormView, bool isReplace) const
Is in something protected (readonly) or selection contains something protected.
Definition: pam.cxx:746
const SwPosition * GetPoint() const
Definition: pam.hxx:253
bool HasHiddenSections() const
Is there hidden sections in the selected area.
Definition: pam.cxx:1005
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
A page of the document layout.
Definition: pagefrm.hxx:60
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:209
bool IsEmptyPage() const
Definition: pagefrm.hxx:161
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void Height(tools::Long nNew)
Definition: swrect.hxx:193
bool HasArea() const
Definition: swrect.hxx:300
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:35
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
void Pos(const Point &rNew)
Definition: swrect.hxx:171
bool Contains(const Point &rPOINT) const
Definition: swrect.hxx:356
Point Center() const
Definition: swrect.hxx:338
void AddHeight(const tools::Long nAdd)
Definition: swrect.cxx:124
bool Overlaps(const SwRect &rRect) const
Definition: swrect.hxx:374
void AddWidth(const tools::Long nAdd)
Definition: swrect.cxx:123
void Justify()
Definition: swrect.cxx:94
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
void Width(tools::Long nNew)
Definition: swrect.hxx:189
The root element of a Writer document layout.
Definition: rootfrm.hxx:85
sal_uInt16 GetPageNum() const
Definition: rootfrm.hxx:321
sal_uInt16 SetCurrPage(SwCursor *, sal_uInt16 nPageNum)
Returns a PaM which sits at the beginning of the requested page.
Definition: trvlfrm.cxx:994
bool MakeTableCursors(SwTableCursor &)
Calculates the cells included from the current selection.
Definition: trvlfrm.cxx:1871
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Primary passes the call to the first page.
Definition: trvlfrm.cxx:425
static bool GetBoundsOfHiddenRange(const SwTextNode &rNode, sal_Int32 nPos, sal_Int32 &rnStartPos, sal_Int32 &rnEndPos, std::vector< sal_Int32 > *pList=nullptr)
Hidden text range information - static and non-version.
Definition: porlay.cxx:2025
SwSection * GetSection()
Definition: sectfrm.hxx:97
A section node represents the start of a section on the UI, i.e.
Definition: node.hxx:575
const SwSection & GetSection() const
Definition: node.hxx:590
bool IsProtectFlag() const
Definition: section.hxx:191
bool IsHiddenFlag() const
Definition: section.hxx:190
bool IsEditInReadonlyFlag() const
Definition: section.hxx:192
void SetShowContentControlOverlay(const bool bShow)
Definition: viscrs.hxx:123
void swapContent(SwSelPaintRects &rSwap)
Definition: viscrs.cxx:370
void SetShowTextInputFieldOverlay(const bool bShow)
Definition: viscrs.hxx:118
This class is used as parameter for creation of a block cursor selection.
std::list< SwPaM * >::iterator getStart()
Start of the container for the selected text portions.
std::list< SwPaM * >::iterator getEnd()
End of the container for the selected text portions.
Represents the current text cursor of one opened edit window.
Definition: viscrs.hxx:140
bool UpDown(bool bUp, sal_uInt16 nCnt)
Definition: viscrs.cxx:1068
void Show(SfxViewShell const *pViewShell)
Definition: viscrs.cxx:960
void Hide()
Definition: viscrs.cxx:1008
void Invalidate(const SwRect &rRect)
Definition: viscrs.cxx:996
SwShellCursor * GetNext()
Definition: viscrs.hxx:188
const Point & GetPtPos() const
Definition: viscrs.hxx:165
SwShellCursor * GetPrev()
Definition: viscrs.hxx:190
virtual void SetMark() override
Unless this is called, the getter method of Mark will return Point.
Definition: viscrs.cxx:939
const Point & GetMkPos() const
Definition: viscrs.hxx:167
bool Contains(const Point &rPt) const
Definition: viscrs.cxx:1220
static SwSmartTagMgr & Get()
Starts a section of nodes in the document model.
Definition: node.hxx:348
SwStartNodeType GetStartNodeType() const
Definition: node.hxx:364
const SwTabColsEntry & GetEntry(size_t nPos) const
Definition: tabcol.hxx:74
size_t Count() const
Definition: tabcol.hxx:65
tools::Long GetLeft() const
Definition: tabcol.hxx:78
tools::Long GetLeftMin() const
Definition: tabcol.hxx:77
tools::Long GetRight() const
Definition: tabcol.hxx:79
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:49
const SwTable * GetTable() const
Definition: tabfrm.hxx:162
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5966
bool HasReadOnlyBoxSel() const
Definition: swcrsr.cxx:2610
void SetChgd()
Definition: swcrsr.hxx:301
bool HasHiddenBoxSel() const
Definition: swcrsr.cxx:2624
bool IsCursorMovedUpdate()
Definition: swcrsr.cxx:2580
SwCursor * MakeBoxSels(SwCursor *pCurrentCursor)
Definition: swcrsr.cxx:2409
void ActualizeSelection(const SwSelBoxes &rBoxes)
Definition: swcrsr.cxx:2545
bool IsChgd() const
Definition: swcrsr.hxx:300
const SwSelBoxes & GetSelectedBoxes() const
Definition: swcrsr.hxx:280
size_t GetSelectedBoxesCount() const
Definition: swcrsr.hxx:279
void ParkCursor()
park table cursor on the boxes' start node
Definition: swcrsr.cxx:2593
const SwTable & GetTable() const
Definition: node.hxx:542
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
void CreateSelection(const SwPaM &rPam, SwSelBoxes &rBoxes, const SearchType eSearchType, bool bProtect) const
void SwTable::CreateSelection(..) fills the selection structure with table cells for a given SwPaM,...
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:201
@ SEARCH_NONE
Definition: swtable.hxx:146
Represents the style of a paragraph.
Definition: fmtcol.hxx:61
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1354
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1380
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
OUString GetExpandText(SwRootFrame const *pLayout, const sal_Int32 nIdx=0, const sal_Int32 nLen=-1, const bool bWithNum=false, const bool bAddSpaceAfterListLabelStr=false, const bool bWithSpacesForLevel=false, const ExpandMode eAdditionalMode=ExpandMode::ExpandFootnote|ExpandMode::HideFieldmarkCommands) const
add 4th optional parameter <bAddSpaceAfterListLabelStr> indicating, when <bWithNum = true> that a spa...
Definition: ndtxt.cxx:3505
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
SwWrongList * GetSmartTags()
Definition: txtedt.cxx:2325
bool HasVisibleNumberingOrBullet() const
Returns if the paragraph has a visible numbering or bullet.
Definition: ndtxt.cxx:4284
OUString GetListId() const
Definition: ndtxt.cxx:4580
bool IsInList() const
Definition: ndtxt.cxx:4546
bool IsSymbolAt(sal_Int32 nBegin) const
in ndcopy.cxx
Definition: itratr.cxx:859
int GetActualListLevel(SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4248
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2989
bool IsHidden() const
Definition: ndtxt.cxx:4749
const OUString & GetText() const
Definition: ndtxt.hxx:244
bool HasHiddenCharAttribute(bool bWholePara) const
Hidden Paragraph Field:
Definition: ndtxt.hxx:774
static bool IsIgnoreProtectedArea()
Definition: viewopt.cxx:597
bool IsShowHiddenChar(bool bHard=false) const
Definition: viewopt.hxx:487
const SwPageFrame * GetFirstVisPage(OutputDevice const *pRenderContext) const
Management of the first visible Page.
Definition: viewimp.cxx:315
void InvalidateAccessibleCursorPosition(const SwFrame *pFrame)
Invalidate accessible frame's cursor position.
Definition: viewimp.cxx:412
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:365
void SizeChgNotify()
Definition: viewsh.cxx:1135
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: viewsh.cxx:157
bool HasDrawView() const
Definition: vnew.cxx:371
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
Definition: viewsh.cxx:1851
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:452
const SwNodes & GetNodes() const
Definition: viewsh.cxx:2181
void StartAction()
Definition: viewsh.hxx:619
rtl::Reference< SwDoc > mxDoc
The document; never 0.
Definition: viewsh.hxx:199
const IDocumentMarkAccess * getIDocumentMarkAccess() const
Provides access to the document bookmark interface.
Definition: viewsh.cxx:2821
SwViewShellImp * Imp()
Definition: viewsh.hxx:211
void EndAction(const bool bIdleEnd=false)
Definition: viewsh.hxx:625
bool ActionPend() const
Definition: viewsh.hxx:225
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2163
Size GetDocSize() const
Definition: viewsh.cxx:2190
void UISizeNotify()
Definition: viewsh.cxx:2531
const SwRect & VisArea() const
Definition: viewsh.cxx:642
sal_uInt16 mnStartAction
!= 0 if at least one Action is active.
Definition: viewsh.hxx:201
SwDoc * GetDoc() const
Definition: viewsh.hxx:308
SfxViewShell * GetSfxViewShell() const
Definition: viewsh.hxx:470
virtual void CalcLayout()
Definition: viewsh.cxx:1075
const SwPostItMgr * GetPostItMgr() const
Definition: viewsh.hxx:583
virtual void VisPortChgd(const SwRect &)
Definition: viewsh.cxx:1165
bool mbSelectAll
Special select all mode: whole document selected, even if doc starts with table.
Definition: viewsh.hxx:204
void MakeVisible(const SwRect &)
Definition: viewsh.cxx:649
SdrView * GetDrawView()
Definition: vnew.cxx:386
void InvalidateAccessibleParaTextSelection()
invalidate text selection for paragraphs
Definition: viewsh.cxx:2614
Definition: view.hxx:146
SwWrtShell & GetWrtShell() const
Definition: view.hxx:423
SwWrtShell * GetWrtShellPtr() const
Definition: view.hxx:424
bool IsVisible() const
Definition: viscrs.hxx:61
void SetDragCursor(bool bFlag=true)
Definition: viscrs.hxx:62
void Show()
Definition: viscrs.cxx:96
void SetPosAndShow(SfxViewShell const *pViewShell)
Definition: viscrs.cxx:136
OUString maType
Definition: wrong.hxx:68
css::uno::Reference< css::container::XStringKeyMap > mxPropertyBag
Definition: wrong.hxx:69
sal_uInt16 Count() const
Definition: wrong.hxx:323
const SwWrongArea * GetElement(sal_uInt16 nIdx) const
Definition: wrong.hxx:349
sal_Int32 Pos(sal_uInt16 nIdx) const
Definition: wrong.hxx:318
sal_uInt16 GetWrongPos(sal_Int32 nValue) const
Find the first position that is greater or equal to the given value.
Definition: wrong.cxx:191
bool InWrongWord(sal_Int32 &rChk, sal_Int32 &rLn) const
If a word is incorrectly selected, this method returns begin and length of it.
Definition: wrong.cxx:103
SwWrongList * SubList(sal_uInt16 nIdx) const
Definition: wrong.hxx:342
sal_Int32 Len(sal_uInt16 nIdx) const
Definition: wrong.hxx:313
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
bool HasFoldedOutlineContentSelected() const
Definition: wrtsh1.cxx:2644
SelectionType GetSelectionType() const
Definition: wrtsh1.cxx:1723
static rtl::Reference< SwXTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1221
static UITestLogger & getInstance()
void logEvent(const EventDescription &rDescription)
bool unique() const
Definition: ring.hxx:96
void MoveTo(value_type *pDestRing)
Removes this item from its current ring container and adds it to another ring container.
Definition: ring.hxx:135
ring_container GetRingContainer()
Definition: ring.hxx:240
void put(std::u16string_view pPropName, const OUString &rPropValue)
ScopedJsonWriterStruct startStruct()
OString finishAndGetAsOString()
ScopedJsonWriterNode startNode(std::string_view)
ScopedJsonWriterArray startArray(std::string_view)
bool GetFrameInPage(const SwContentFrame *, SwWhichPage, SwPosPage, SwPaM *)
Returns the first/last Contentframe (controlled using the parameter fnPosPage) of the current/previou...
Definition: trvlfrm.cxx:1091
static bool lcl_CursorOk(SwPaM &aPam)
Checks if a PaM is valid.
Definition: crsrsh.cxx:3926
static bool IsAtStartOrEndOfFrame(SwCursorShell const *const pShell, SwShellCursor const *const pShellCursor, SwMoveFnCollection const &fnPosPara)
Definition: crsrsh.cxx:957
static SwCursorShell::StartsWith StartsWith(SwStartNode const &rStart)
Definition: crsrsh.cxx:769
static void lcl_FillRecognizerData(std::vector< OUString > &rSmartTagTypes, uno::Sequence< uno::Reference< container::XStringKeyMap > > &rStringKeyMaps, const SwWrongList &rSmartTagList, sal_Int32 nCurrent)
Definition: crsrsh.cxx:4035
static bool lcl_CheckHiddenSection(SwPosition &rPos)
Definition: crsrsh.cxx:1819
static void CheckRange(SwCursor *pCurrentCursor)
Check if pCurrentCursor points into already existing ranges and delete those.
Definition: crsrsh.cxx:88
static void lcl_FillTextRange(uno::Reference< text::XTextRange > &rRange, SwTextNode &rNode, sal_Int32 nBegin, sal_Int32 nLen)
Definition: crsrsh.cxx:4064
static bool sw_PosOk(const SwPosition &aPos)
Checks if a position is valid.
Definition: crsrsh.cxx:3914
static SwStartNode const * FindParentText(SwShellCursor const &rCursor)
Definition: crsrsh.cxx:712
static SwStartNode const * FindTextStart(SwPosition const &rPos)
find XText start node
Definition: crsrsh.cxx:702
static SwFrame * lcl_IsInHeaderFooter(SwNode &rNd, Point &rPt)
Definition: crsrsh.cxx:1020
static void lcl_CheckHiddenPara(SwPosition &rPos)
Try to set the cursor to the next visible content node.
Definition: crsrsh.cxx:1835
static SwCursorShell::StartsWith EndsWith(SwStartNode const &rStart)
Definition: crsrsh.cxx:793
static const SwStartNode * lcl_NodeContext(const SwNode &rNode)
Definition: crsrsh.cxx:3897
const int CRSR_POSCHG
Definition: crsrsh.hxx:131
const int CRSR_POSOLD
Definition: crsrsh.hxx:130
CursorMoveState
Definition: crstate.hxx:122
@ SetOnlyText
stay with the cursor inside text
@ UpDown
Cursor Up/Down.
@ RightMargin
at right margin
@ LeftMargin
at left margin
@ TableSel
not in repeated headlines
bool(* SwWhichPara)(SwPaM &, SwMoveFnCollection const &)
Definition: cshtyp.hxx:43
SwDocPositions
Definition: cshtyp.hxx:104
FindRanges
Definition: cshtyp.hxx:91
SwLayoutFrame *(* SwWhichPage)(const SwLayoutFrame *)
Definition: cshtyp.hxx:34
SwContentFrame *(* SwPosPage)(const SwLayoutFrame *)
Definition: cshtyp.hxx:38
bool(* SwWhichSection)(SwPaM &, SwMoveFnCollection const &)
Definition: cshtyp.hxx:51
int nCount
struct _xmlTextWriter * xmlTextWriterPtr
bool IsScrollMDI(SwViewShell const *pVwSh, const SwRect &rRect)
Definition: edtwin3.cxx:45
@ Page
Rect of current page.
DocumentType eType
SvxFrameDirection
SelectionType
bool isFormatMessage(const sal_uInt16 nWhich)
Definition: hintids.hxx:512
constexpr TypedWhichId< SwAttrSetChg > RES_ATTRSET_CHG(169)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:175
constexpr TypedWhichId< SwUpdateAttr > RES_UPDATE_ATTR(170)
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_OBJECTDYING(RES_FORMAT_MSG_BEGIN)
constexpr TypedWhichId< SwFormatChg > RES_FMT_CHG(168)
sal_Int32 nIndex
sal_Int64 n
uno_Any a
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
aBuf
def point()
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Dialog to specify the properties of date form field.
bool FrameContainsNode(SwContentFrame const &rFrame, SwNodeOffset nNodeIndex)
Definition: txtfrm.cxx:290
SwTextNode * GetParaPropsNode(SwRootFrame const &rLayout, SwNode const &rNode)
Definition: txtfrm.cxx:330
long Long
SwStartNodeType
Definition: ndtyp.hxx:51
@ SwTableBoxStartNode
Definition: ndtyp.hxx:53
@ SwFootnoteStartNode
Definition: ndtyp.hxx:55
SwNodeType
Definition: ndtyp.hxx:28
@ Table
SwTableNode is derived from SwStartNode.
@ Section
SwSectionNode is derived from SwStartNode.
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:1043
bool CheckNodesRange(const SwNode &rStt, const SwNode &rEnd, bool bChkSection)
Check if the given range is inside one of the defined top-level sections.
Definition: pam.cxx:349
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1203
bool GoCurrSection(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1288
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:48
SwMoveFnCollection const & fnSectionEnd
Definition: paminit.cxx:52
SwMoveFnCollection const & fnParaEnd
Definition: paminit.cxx:49
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:60
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
SwMoveFnCollection const & fnSectionStart
Definition: paminit.cxx:51
#define STYLE_CURSOR_NOBLINKTIME
static SfxItemSet & rSet
std::map< OUString, OUString > aParameters
sal_uInt8 m_nCursorBidiLevel
Definition: crstate.hxx:139
CursorMoveState m_eState
Definition: crstate.hxx:138
bool m_bRealHeight
should the real height be calculated?
Definition: crstate.hxx:141
SwSpecialPos * m_pSpecialPos
for positions inside fields
Definition: crstate.hxx:136
bool m_bRealWidth
Calculation of the width required.
Definition: crstate.hxx:149
bool m_bInFrontOfLabel
cursor in front of label
Definition: crstate.hxx:162
Point m_aRealHeight
contains then the position/height of the cursor
Definition: crstate.hxx:137
bool m_bSetInReadOnly
ReadOnly areas may be entered.
Definition: crstate.hxx:148
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
void AssignEndIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the end of rNd.
Definition: pam.cxx:277
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:267
SwNodeIndex nNode
Definition: pam.hxx:39
const SwContentNode * GetContentNode() const
Definition: pam.hxx:84
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
const SwNodes & GetNodes() const
Definition: pam.hxx:79
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
SwSPExtendRange nExtendRange
Definition: crstate.hxx:112
sal_uInt16 GetWhich() const
Definition: calbck.hxx:75
SwCursorSkipMode
Definition: swcrsr.hxx:65
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
tools::Long SwTwips
Definition: swtypes.hxx:51
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:92
sal_uInt16 sal_Unicode
bool IsFlySelectedByCursor(SwDoc const &rDoc, SwPosition const &rStart, SwPosition const &rEnd)
check at-char and at-para flys in rDoc
Definition: undobj.cxx:1730
const char * pChar