LibreOffice Module sw (master)  1
swcrsr.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 <hintids.hxx>
21 #include <editeng/protitem.hxx>
22 #include <com/sun/star/i18n/WordType.hpp>
23 #include <com/sun/star/i18n/XBreakIterator.hpp>
24 #include <unotools/charclass.hxx>
25 #include <svl/ctloptions.hxx>
26 #include <svl/srchitem.hxx>
27 #include <swmodule.hxx>
28 #include <fmtcntnt.hxx>
29 #include <swtblfmt.hxx>
30 #include <swcrsr.hxx>
31 #include <unocrsr.hxx>
32 #include <bookmark.hxx>
33 #include <doc.hxx>
34 #include <IDocumentUndoRedo.hxx>
37 #include <docary.hxx>
38 #include <ndtxt.hxx>
39 #include <section.hxx>
40 #include <swtable.hxx>
41 #include <cntfrm.hxx>
42 #include <rootfrm.hxx>
43 #include <txtfrm.hxx>
44 #include <notxtfrm.hxx>
45 #include <scriptinfo.hxx>
46 #include <crstate.hxx>
47 #include <docsh.hxx>
48 #include <viewsh.hxx>
49 #include <frmatr.hxx>
50 #include <breakit.hxx>
51 #include <mdiexp.hxx>
52 #include <strings.hrc>
53 #include <redline.hxx>
54 #include <txatbase.hxx>
55 #include <IDocumentMarkAccess.hxx>
56 #include <memory>
57 #include <comphelper/lok.hxx>
58 #include <editsh.hxx>
59 
60 #include <viewopt.hxx>
61 
62 using namespace ::com::sun::star::i18n;
63 
64 const sal_uInt16 coSrchRplcThreshold = 60000;
65 
66 namespace {
67 
68 struct PercentHdl
69 {
70  SwDocShell* pDSh;
71  sal_uLong nActPos;
72  bool bBack, bNodeIdx;
73 
74  PercentHdl( sal_uLong nStt, sal_uLong nEnd, SwDocShell* pSh )
75  : pDSh(pSh), nActPos(nStt), bBack(false), bNodeIdx(false)
76  {
77  bBack = (nStt > nEnd);
78  if( bBack )
79  {
80  sal_uLong n = nStt; nStt = nEnd; nEnd = n;
81  }
82  ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd );
83  }
84 
85  explicit PercentHdl( const SwPaM& rPam )
86  : pDSh( rPam.GetDoc().GetDocShell() )
87  {
88  sal_uLong nStt, nEnd;
89  if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
90  {
91  bNodeIdx = false;
92  nStt = rPam.GetMark()->nContent.GetIndex();
93  nEnd = rPam.GetPoint()->nContent.GetIndex();
94  }
95  else
96  {
97  bNodeIdx = true;
98  nStt = rPam.GetMark()->nNode.GetIndex();
99  nEnd = rPam.GetPoint()->nNode.GetIndex();
100  }
101  nActPos = nStt;
102  bBack = (nStt > nEnd );
103  if( bBack )
104  {
105  sal_uLong n = nStt; nStt = nEnd; nEnd = n;
106  }
107  ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh );
108  }
109 
110  ~PercentHdl() { ::EndProgress( pDSh ); }
111 
112  void NextPos( sal_uLong nPos ) const
113  { ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); }
114 
115  void NextPos( SwPosition const & rPos ) const
116  {
117  sal_uLong nPos;
118  if( bNodeIdx )
119  nPos = rPos.nNode.GetIndex();
120  else
121  nPos = rPos.nContent.GetIndex();
122  ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh );
123  }
124 };
125 
126 }
127 
128 SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing )
129  : SwPaM( rPos, pRing )
130  , m_nRowSpanOffset(0)
131  , m_nCursorBidiLevel(0)
132  , m_bColumnSelection(false)
133 {
134 }
135 
136 // @@@ semantic: no copy ctor.
137 SwCursor::SwCursor(SwCursor const& rCpy, SwPaM *const pRing)
138  : SwPaM( rCpy, pRing )
139  , m_nRowSpanOffset(rCpy.m_nRowSpanOffset)
140  , m_nCursorBidiLevel(rCpy.m_nCursorBidiLevel)
141  , m_bColumnSelection(rCpy.m_bColumnSelection)
142 {
143 }
144 
146 {
147 }
148 
150 {
151  return new SwCursor( *GetPoint(), pRing );
152 }
153 
155 {
156  return false;
157 }
158 
160 {
161  return true;
162 }
163 
165 {
166  return !IsReadOnlyAvailable();
167 }
168 
169 // CreateNewSavePos is virtual so that derived classes of cursor can implement
170 // own SaveObjects if needed and validate them in the virtual check routines.
172 {
173  m_vSavePos.emplace_back( *this );
174 }
175 
177 {
178  if (!m_vSavePos.empty()) // Robust
179  {
180  m_vSavePos.pop_back();
181  }
182 }
183 
186 {
187  return GetPoint()->nNode.GetIndex() <
189 }
190 
192 {
193  return false;
194 }
195 
196 // extracted from IsSelOvr()
198 {
199  SwNodes& rNds = GetDoc().GetNodes();
200  // check sections of nodes array
202  && HasMark() )
203  {
204  SwNodeIndex aOldPos( rNds, GetSavePos()->nNode );
205  if( !CheckNodesRange( aOldPos, GetPoint()->nNode, true ))
206  {
207  GetPoint()->nNode = aOldPos;
208  GetPoint()->nContent.Assign( GetContentNode(), GetSavePos()->nContent );
209  return true;
210  }
211  }
212  return SwCursor::IsSelOvrCheck(eFlags);
213 }
214 
215 namespace
216 {
217  const SwTextAttr* InputFieldAtPos(SwPosition const *pPos)
218  {
219  SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode();
220  if (!pTextNd)
221  return nullptr;
223  }
224 }
225 
227 {
228  SwDoc& rDoc = GetDoc();
229  SwNodes& rNds = rDoc.GetNodes();
230 
231  bool bSkipOverHiddenSections = IsSkipOverHiddenSections();
232  bool bSkipOverProtectSections = IsSkipOverProtectSections();
233 
234  if ( IsSelOvrCheck( eFlags ) )
235  {
236  return true;
237  }
238 
239  if (m_vSavePos.back().nNode != GetPoint()->nNode.GetIndex() &&
240  // (1997) in UI-ReadOnly everything is allowed
241  ( !rDoc.GetDocShell() || !rDoc.GetDocShell()->IsReadOnlyUI() ))
242  {
243  // check new sections
244  SwNodeIndex& rPtIdx = GetPoint()->nNode;
245  const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode();
246  if( pSectNd &&
247  ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) ||
248  (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() )))
249  {
250  if( !( SwCursorSelOverFlags::ChangePos & eFlags ) )
251  {
252  // then we're already done
253  RestoreSavePos();
254  return true;
255  }
256 
257  // set cursor to new position:
258  SwNodeIndex aIdx( rPtIdx );
259  sal_Int32 nContentPos = m_vSavePos.back().nContent;
260  bool bGoNxt = m_vSavePos.back().nNode < rPtIdx.GetIndex();
261  SwContentNode* pCNd = bGoNxt
262  ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
263  : SwNodes::GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
264  if( !pCNd && ( SwCursorSelOverFlags::EnableRevDirection & eFlags ))
265  {
266  bGoNxt = !bGoNxt;
267  pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
268  : SwNodes::GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
269  }
270 
271  bool bIsValidPos = nullptr != pCNd;
272  const bool bValidNodesRange = bIsValidPos &&
273  ::CheckNodesRange( rPtIdx, aIdx, true );
274  if( !bValidNodesRange )
275  {
276  rPtIdx = m_vSavePos.back().nNode;
277  pCNd = rPtIdx.GetNode().GetContentNode();
278  if( !pCNd )
279  {
280  bIsValidPos = false;
281  nContentPos = 0;
282  rPtIdx = aIdx;
283  pCNd = rPtIdx.GetNode().GetContentNode();
284  if( !pCNd )
285  {
286  // then to the beginning of the document
287  rPtIdx = rNds.GetEndOfExtras();
288  pCNd = rNds.GoNext( &rPtIdx );
289  }
290  }
291  }
292 
293  // register ContentIndex:
294  const sal_Int32 nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nContentPos;
295  GetPoint()->nContent.Assign( pCNd, nTmpPos );
296  if( !bIsValidPos || !bValidNodesRange ||
297  IsInProtectTable( true ) )
298  return true;
299  }
300 
301  // is there a protected section in the section?
302  if( HasMark() && bSkipOverProtectSections)
303  {
304  sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
305  nEndIdx = GetPoint()->nNode.GetIndex();
306  if( nEndIdx <= nSttIdx )
307  {
308  sal_uLong nTmp = nSttIdx;
309  nSttIdx = nEndIdx;
310  nEndIdx = nTmp;
311  }
312 
313  const SwSectionFormats& rFormats = rDoc.GetSections();
314  for( SwSectionFormats::size_type n = 0; n < rFormats.size(); ++n )
315  {
316  const SwSectionFormat* pFormat = rFormats[n];
317  const SvxProtectItem& rProtect = pFormat->GetProtect();
318  if( rProtect.IsContentProtected() )
319  {
320  const SwFormatContent& rContent = pFormat->GetContent(false);
321  OSL_ENSURE( rContent.GetContentIdx(), "No SectionNode?" );
322  sal_uLong nIdx = rContent.GetContentIdx()->GetIndex();
323  if( nSttIdx <= nIdx && nEndIdx >= nIdx )
324  {
325  // if it is no linked section then we cannot select it
326  const SwSection& rSect = *pFormat->GetSection();
327  if( SectionType::Content == rSect.GetType() )
328  {
329  RestoreSavePos();
330  return true;
331  }
332  }
333  }
334  }
335  }
336  }
337 
338  const SwNode* pNd = &GetPoint()->nNode.GetNode();
339  if( pNd->IsContentNode() && !dynamic_cast<SwUnoCursor*>(this) )
340  {
341  const SwContentFrame* pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() );
342  if ( (SwCursorSelOverFlags::ChangePos & eFlags) //allowed to change position if it's a bad one
343  && pFrame && pFrame->isFrameAreaDefinitionValid()
344  && !pFrame->getFrameArea().Height() //a bad zero height position
345  && !InputFieldAtPos(GetPoint()) ) //unless it's a (vertical) input field
346  {
347  // skip to the next/prev valid paragraph with a layout
348  SwNodeIndex& rPtIdx = GetPoint()->nNode;
349  bool bGoNxt = m_vSavePos.back().nNode < rPtIdx.GetIndex();
350  for (;;)
351  {
352  pFrame = bGoNxt ? pFrame->GetNextContentFrame() : pFrame->GetPrevContentFrame();
353  if (!pFrame || 0 != pFrame->getFrameArea().Height() )
354  break;
355  }
356 
357  // #i72394# skip to prev/next valid paragraph with a layout in case
358  // the first search did not succeed:
359  if( !pFrame )
360  {
361  bGoNxt = !bGoNxt;
362  pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() );
363  while ( pFrame && 0 == pFrame->getFrameArea().Height() )
364  {
365  pFrame = bGoNxt ? pFrame->GetNextContentFrame()
366  : pFrame->GetPrevContentFrame();
367  }
368  }
369 
370  if (pFrame != nullptr)
371  {
372  if (pFrame->IsTextFrame())
373  {
374  SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(pFrame));
375  *GetPoint() = pTextFrame->MapViewToModelPos(TextFrameIndex(
376  bGoNxt ? 0 : pTextFrame->GetText().getLength()));
377  }
378  else
379  {
380  assert(pFrame->IsNoTextFrame());
381  SwContentNode *const pCNd = const_cast<SwContentNode*>(
382  static_cast<SwNoTextFrame const*>(pFrame)->GetNode());
383  assert(pCNd);
384 
385  // set this ContentNode as new position
386  rPtIdx = *pCNd;
387  // assign corresponding ContentIndex
388  const sal_Int32 nTmpPos = bGoNxt ? 0 : pCNd->Len();
389  GetPoint()->nContent.Assign( pCNd, nTmpPos );
390  }
391 
392 
393  if (rPtIdx.GetIndex() == m_vSavePos.back().nNode
394  && GetPoint()->nContent.GetIndex() == m_vSavePos.back().nContent)
395  {
396  // new position equals saved one
397  // --> trigger restore of saved pos by setting <pFrame> to NULL - see below
398  pFrame = nullptr;
399  }
400 
401  if ( IsInProtectTable( true ) )
402  {
403  // new position in protected table
404  // --> trigger restore of saved pos by setting <pFrame> to NULL - see below
405  pFrame = nullptr;
406  }
407  }
408  }
409 
410  if( !pFrame )
411  {
412  DeleteMark();
413  RestoreSavePos();
414  return true; // we need a frame
415  }
416  }
417 
418  // is the cursor allowed to be in a protected node?
419  if( !( SwCursorSelOverFlags::ChangePos & eFlags ) && !IsAtValidPos() )
420  {
421  DeleteMark();
422  RestoreSavePos();
423  return true;
424  }
425 
426  if( !HasMark() )
427  return false;
428 
429  // check for invalid sections
430  if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, true ))
431  {
432  DeleteMark();
433  RestoreSavePos();
434  return true; // we need a frame
435  }
436 
437  pNd = &GetMark()->nNode.GetNode();
438  if( pNd->IsContentNode()
439  && !static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
440  && !dynamic_cast<SwUnoCursor*>(this) )
441  {
442  DeleteMark();
443  RestoreSavePos();
444  return true; // we need a frame
445  }
446 
447  // ensure that selection is only inside an InputField or contains the InputField completely
448  {
449  const SwTextAttr* pInputFieldTextAttrAtPoint = InputFieldAtPos(GetPoint());
450  const SwTextAttr* pInputFieldTextAttrAtMark = InputFieldAtPos(GetMark());
451 
452  if ( pInputFieldTextAttrAtPoint != pInputFieldTextAttrAtMark )
453  {
454  const sal_uLong nRefNodeIdx =
455  ( SwCursorSelOverFlags::Toggle & eFlags )
456  ? m_vSavePos.back().nNode
457  : GetMark()->nNode.GetIndex();
458  const sal_Int32 nRefContentIdx =
459  ( SwCursorSelOverFlags::Toggle & eFlags )
460  ? m_vSavePos.back().nContent
461  : GetMark()->nContent.GetIndex();
462  const bool bIsForwardSelection =
463  nRefNodeIdx < GetPoint()->nNode.GetIndex()
464  || ( nRefNodeIdx == GetPoint()->nNode.GetIndex()
465  && nRefContentIdx < GetPoint()->nContent.GetIndex() );
466 
467  if ( pInputFieldTextAttrAtPoint != nullptr )
468  {
469  const sal_Int32 nNewPointPos =
470  bIsForwardSelection ? *(pInputFieldTextAttrAtPoint->End()) : pInputFieldTextAttrAtPoint->GetStart();
471  SwTextNode* pTextNdAtPoint = GetPoint()->nNode.GetNode().GetTextNode();
472  GetPoint()->nContent.Assign( pTextNdAtPoint, nNewPointPos );
473  }
474 
475  if ( pInputFieldTextAttrAtMark != nullptr )
476  {
477  const sal_Int32 nNewMarkPos =
478  bIsForwardSelection ? pInputFieldTextAttrAtMark->GetStart() : *(pInputFieldTextAttrAtMark->End());
479  SwTextNode* pTextNdAtMark = GetMark()->nNode.GetNode().GetTextNode();
480  GetMark()->nContent.Assign( pTextNdAtMark, nNewMarkPos );
481  }
482  }
483  }
484 
485  const SwTableNode* pPtNd = GetPoint()->nNode.GetNode().FindTableNode();
486  const SwTableNode* pMrkNd = GetMark()->nNode.GetNode().FindTableNode();
487  // both in no or in same table node
488  if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd )
489  return false;
490 
491  // in different tables or only mark in table
492  if( pMrkNd )
493  {
494  // not allowed, so go back to old position
495  RestoreSavePos();
496  // Cursor stays at old position
497  return true;
498  }
499 
500  // Note: this cannot happen in TableMode
501  // Only Point in Table then go behind/in front of table
502  if (SwCursorSelOverFlags::ChangePos & eFlags)
503  {
504  bool bSelTop = GetPoint()->nNode.GetIndex() <
505  ((SwCursorSelOverFlags::Toggle & eFlags)
506  ? m_vSavePos.back().nNode : GetMark()->nNode.GetIndex());
507 
508  do { // loop for table after table
509  sal_uLong nSEIdx = pPtNd->EndOfSectionIndex();
510  sal_uLong nSttEndTable = nSEIdx + 1;
511 
512  if( bSelTop )
513  nSttEndTable = rNds[ nSEIdx ]->StartOfSectionIndex() - 1;
514 
515  GetPoint()->nNode = nSttEndTable;
516  const SwNode* pMyNd = &(GetNode());
517 
518  if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() &&
519  pMyNd->StartOfSectionNode()->IsSectionNode() ) )
520  {
521  pMyNd = bSelTop
522  ? SwNodes::GoPrevSection( &GetPoint()->nNode,true,false )
523  : rNds.GoNextSection( &GetPoint()->nNode,true,false );
524 
525  /* #i12312# Handle failure of Go{Prev|Next}Section */
526  if ( nullptr == pMyNd)
527  break;
528 
529  pPtNd = pMyNd->FindTableNode();
530  if( pPtNd )
531  continue;
532  }
533 
534  // we permit these
535  if( pMyNd->IsContentNode() &&
536  ::CheckNodesRange( GetMark()->nNode,
537  GetPoint()->nNode, true ))
538  {
539  // table in table
540  const SwTableNode* pOuterTableNd = pMyNd->FindTableNode();
541  if ( pOuterTableNd )
542  pMyNd = pOuterTableNd;
543  else
544  {
545  SwContentNode* pCNd = const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pMyNd));
546  GetPoint()->nContent.Assign( pCNd, bSelTop ? pCNd->Len() : 0 );
547  return false;
548  }
549  }
550  if( bSelTop )
551  {
552  if ( !pMyNd->IsEndNode() )
553  break;
554  pPtNd = pMyNd->FindTableNode();
555  }
556  else
557  pPtNd = pMyNd->GetTableNode();
558  if (!pPtNd)
559  break;
560  } while( true );
561  }
562 
563  // stay on old position
564  RestoreSavePos();
565  return true;
566 }
567 
568 bool SwCursor::IsInProtectTable( bool bMove, bool bChgCursor )
569 {
570  SwContentNode* pCNd = GetContentNode();
571  if( !pCNd )
572  return false;
573 
574  // No table, no protected cell:
575  const SwTableNode* pTableNode = pCNd->FindTableNode();
576  if ( !pTableNode )
577  return false;
578 
579  // Current position == last save position?
580  if (m_vSavePos.back().nNode == GetPoint()->nNode.GetIndex())
581  return false;
582 
583  // Check for covered cell:
584  bool bInCoveredCell = false;
585  const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
586  OSL_ENSURE( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" );
587  const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTableBox( pTmpSttNode->GetIndex() ) : nullptr; //Robust #151355
588  if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
589  bInCoveredCell = true;
590 
591  // Positions of covered cells are not acceptable:
592  if ( !bInCoveredCell )
593  {
594  // Position not protected?
595  if ( !pCNd->IsProtect() )
596  return false;
597 
598  // Cursor in protected cells allowed?
599  if ( IsReadOnlyAvailable() )
600  return false;
601  }
602 
603  // If we reach this point, we are in a protected or covered table cell!
604 
605  if( !bMove )
606  {
607  if( bChgCursor )
608  // restore the last save position
609  RestoreSavePos();
610 
611  return true; // Cursor stays at old position
612  }
613 
614  // We are in a protected table cell. Traverse top to bottom?
615  if (m_vSavePos.back().nNode < GetPoint()->nNode.GetIndex())
616  {
617  // search next valid box
618  // if there is another StartNode after the EndNode of a cell then
619  // there is another cell
620  SwNodeIndex aCellStt( *GetNode().FindTableBoxStartNode()->EndOfSectionNode(), 1 );
621  bool bProt = true;
622 GoNextCell:
623  for (;;) {
624  if( !aCellStt.GetNode().IsStartNode() )
625  break;
626  ++aCellStt;
627  pCNd = aCellStt.GetNode().GetContentNode();
628  if( !pCNd )
629  pCNd = aCellStt.GetNodes().GoNext( &aCellStt );
630  bProt = pCNd->IsProtect();
631  if( !bProt )
632  break;
633  aCellStt.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
634  }
635 
636 SetNextCursor:
637  if( !bProt ) // found free cell
638  {
639  GetPoint()->nNode = aCellStt;
640  SwContentNode* pTmpCNd = GetContentNode();
641  if( pTmpCNd )
642  {
643  GetPoint()->nContent.Assign( pTmpCNd, 0 );
644  return false;
645  }
648  }
649  // end of table, so go to next node
650  ++aCellStt;
651  SwNode* pNd = &aCellStt.GetNode();
652  if( pNd->IsEndNode() || HasMark())
653  {
654  // if only table in FlyFrame or SSelection then stay on old position
655  if( bChgCursor )
656  RestoreSavePos();
657  return true;
658  }
659  else if( pNd->IsTableNode() && aCellStt++ )
660  goto GoNextCell;
661 
662  bProt = false; // index is now on a content node
663  goto SetNextCursor;
664  }
665 
666  // search for the previous valid box
667  {
668  // if there is another EndNode in front of the StartNode than there
669  // exists a previous cell
670  SwNodeIndex aCellStt( *GetNode().FindTableBoxStartNode(), -1 );
671  SwNode* pNd;
672  bool bProt = true;
673 GoPrevCell:
674  for (;;) {
675  pNd = &aCellStt.GetNode();
676  if( !pNd->IsEndNode() )
677  break;
678  aCellStt.Assign( *pNd->StartOfSectionNode(), +1 );
679  pCNd = aCellStt.GetNode().GetContentNode();
680  if( !pCNd )
681  pCNd = pNd->GetNodes().GoNext( &aCellStt );
682  bProt = pCNd->IsProtect();
683  if( !bProt )
684  break;
685  aCellStt.Assign( *pNd->FindTableBoxStartNode(), -1 );
686  }
687 
688 SetPrevCursor:
689  if( !bProt ) // found free cell
690  {
691  GetPoint()->nNode = aCellStt;
692  SwContentNode* pTmpCNd = GetContentNode();
693  if( pTmpCNd )
694  {
695  GetPoint()->nContent.Assign( pTmpCNd, 0 );
696  return false;
697  }
700  }
701  // at the beginning of a table, so go to next node
702  --aCellStt;
703  pNd = &aCellStt.GetNode();
704  if( pNd->IsStartNode() || HasMark() )
705  {
706  // if only table in FlyFrame or SSelection then stay on old position
707  if( bChgCursor )
708  RestoreSavePos();
709  return true;
710  }
711  else if( pNd->StartOfSectionNode()->IsTableNode() && aCellStt-- )
712  goto GoPrevCell;
713 
714  bProt = false; // index is now on a content node
715  goto SetPrevCursor;
716  }
717 }
718 
720 bool SwCursor::IsAtValidPos( bool bPoint ) const
721 {
722  const SwDoc& rDoc = GetDoc();
723  const SwPosition* pPos = bPoint ? GetPoint() : GetMark();
724  const SwNode* pNd = &pPos->nNode.GetNode();
725 
726  if( pNd->IsContentNode() && !static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) &&
727  !dynamic_cast<const SwUnoCursor*>(this) )
728  {
729  return false;
730  }
731 
732  // #i45129# - in UI-ReadOnly everything is allowed
733  if( !rDoc.GetDocShell() || !rDoc.GetDocShell()->IsReadOnlyUI() )
734  return true;
735 
736  const bool bCursorInReadOnly = IsReadOnlyAvailable();
737  if( !bCursorInReadOnly && pNd->IsProtect() )
738  return false;
739 
740  const SwSectionNode* pSectNd = pNd->FindSectionNode();
741  return !pSectNd
742  || !(pSectNd->GetSection().IsHiddenFlag() ||
743  ( !bCursorInReadOnly && pSectNd->GetSection().IsProtectFlag() ));
744 }
745 
747 
750  SwDocPositions nEnd, SwPaM* pRange ) const
751 {
752  pRange->SetMark();
753  FillFindPos( nStart, *pRange->GetMark() );
754  FillFindPos( nEnd, *pRange->GetPoint() );
755 
756  // determine direction of search
757  return ( SwDocPositions::Start == nStart || SwDocPositions::OtherStart == nStart ||
758  (SwDocPositions::Curr == nStart &&
759  (SwDocPositions::End == nEnd || SwDocPositions::OtherEnd == nEnd ) ))
761 }
762 
763 static sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurrentCursor,
764  SwMoveFnCollection const & fnMove, SwCursor*& pFndRing,
765  SwPaM& aRegion, FindRanges eFndRngs,
766  bool bInReadOnly, bool& bCancel )
767 {
768  SwDoc& rDoc = pCurrentCursor->GetDoc();
769  bool const bDoesUndo = rDoc.GetIDocumentUndoRedo().DoesUndo();
770  int nFndRet = 0;
771  sal_uLong nFound = 0;
772  const bool bSrchBkwrd = &fnMove == &fnMoveBackward;
773  SwPaM *pTmpCursor = pCurrentCursor, *pSaveCursor = pCurrentCursor;
774  std::unique_ptr<SvxSearchItem> xSearchItem;
775 
776  // only create progress bar for ShellCursor
777  bool bIsUnoCursor = dynamic_cast<SwUnoCursor*>(pCurrentCursor) != nullptr;
778  std::unique_ptr<PercentHdl> pPHdl;
779  sal_uInt16 nCursorCnt = 0;
780  if( FindRanges::InSel & eFndRngs )
781  {
782  while( pCurrentCursor != ( pTmpCursor = pTmpCursor->GetNext() ))
783  ++nCursorCnt;
784  if( nCursorCnt && !bIsUnoCursor )
785  pPHdl.reset(new PercentHdl( 0, nCursorCnt, rDoc.GetDocShell() ));
786  }
787  else
788  pSaveCursor = pSaveCursor->GetPrev();
789 
790  bool bEnd = false;
791  do {
792  aRegion.SetMark();
793  // independent from search direction: SPoint is always bigger than mark
794  // if the search area is valid
795  SwPosition *pSttPos = aRegion.GetMark(),
796  *pEndPos = aRegion.GetPoint();
797  *pSttPos = *pTmpCursor->Start();
798  *pEndPos = *pTmpCursor->End();
799  if( bSrchBkwrd )
800  aRegion.Exchange();
801 
802  if( !nCursorCnt && !pPHdl && !bIsUnoCursor )
803  pPHdl.reset(new PercentHdl( aRegion ));
804 
805  // as long as found and not at same position
806  while( *pSttPos <= *pEndPos )
807  {
808  nFndRet = rParas.DoFind(*pCurrentCursor, fnMove, aRegion, bInReadOnly, xSearchItem);
809  if( 0 == nFndRet ||
810  ( pFndRing &&
811  *pFndRing->GetPoint() == *pCurrentCursor->GetPoint() &&
812  *pFndRing->GetMark() == *pCurrentCursor->GetMark() ))
813  break;
814  if( !( FIND_NO_RING & nFndRet ))
815  {
816  // #i24084# - create ring similar to the one in CreateCursor
817  SwCursor* pNew = pCurrentCursor->Create( pFndRing );
818  if( !pFndRing )
819  pFndRing = pNew;
820 
821  pNew->SetMark();
822  *pNew->GetMark() = *pCurrentCursor->GetMark();
823  }
824 
825  ++nFound;
826 
827  if( !( eFndRngs & FindRanges::InSelAll) )
828  {
829  bEnd = true;
830  break;
831  }
832 
833  if ((coSrchRplcThreshold == nFound)
834  && rDoc.GetIDocumentUndoRedo().DoesUndo()
835  && rParas.IsReplaceMode())
836  {
837  short nRet = pCurrentCursor->MaxReplaceArived();
838  if( RET_YES == nRet )
839  {
841  rDoc.GetIDocumentUndoRedo().DoUndo(false);
842  }
843  else
844  {
845  bEnd = true;
846  if(RET_CANCEL == nRet)
847  {
848  bCancel = true;
849  }
850  break;
851  }
852  }
853 
854  if( bSrchBkwrd )
855  // move pEndPos in front of the found area
856  *pEndPos = *pCurrentCursor->Start();
857  else
858  // move pSttPos behind the found area
859  *pSttPos = *pCurrentCursor->End();
860 
861  if( *pSttPos == *pEndPos )
862  // in area but at the end => done
863  break;
864 
865  if( !nCursorCnt && pPHdl )
866  {
867  pPHdl->NextPos( *aRegion.GetMark() );
868  }
869  }
870 
871  if( bEnd || !( eFndRngs & ( FindRanges::InSelAll | FindRanges::InSel )) )
872  break;
873 
874  pTmpCursor = pTmpCursor->GetNext();
875  if( nCursorCnt && pPHdl )
876  {
877  pPHdl->NextPos( ++pPHdl->nActPos );
878  }
879 
880  } while( pTmpCursor != pSaveCursor && pTmpCursor->GetNext() != pTmpCursor);
881 
882  if( nFound && !pFndRing ) // if no ring should be created
883  pFndRing = pCurrentCursor->Create();
884 
885  rDoc.GetIDocumentUndoRedo().DoUndo(bDoesUndo);
886  return nFound;
887 }
888 
889 static bool lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
890  SwPaM& rPam, bool bFirst )
891 {
892  if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() )
893  return false;
894 
895  SwNodes& rNds = rPam.GetDoc().GetNodes();
896  rPam.DeleteMark();
897  SwContentNode* pCNd;
898  if( !bFirst )
899  {
900  rPam.GetPoint()->nNode = rSttNd;
901  pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
902  if( !pCNd )
903  return false;
904  pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
905  }
906  else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
907  rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() )
908  // not in this section
909  return false;
910 
911  rPam.SetMark();
912  rPam.GetPoint()->nNode = rEndNd;
913  pCNd = SwNodes::GoPrevious( &rPam.GetPoint()->nNode );
914  if( !pCNd )
915  return false;
916  pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
917 
918  return *rPam.GetMark() < *rPam.GetPoint();
919 }
920 
921 static bool lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
922  SwPaM& rPam, bool bFirst )
923 {
924  if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() )
925  return false;
926 
927  SwNodes& rNds = rPam.GetDoc().GetNodes();
928  rPam.DeleteMark();
929  SwContentNode* pCNd;
930  if( !bFirst )
931  {
932  rPam.GetPoint()->nNode = rSttNd;
933  pCNd = SwNodes::GoPrevious( &rPam.GetPoint()->nNode );
934  if( !pCNd )
935  return false;
936  pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
937  }
938  else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
939  rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() )
940  return false; // not in this section
941 
942  rPam.SetMark();
943  rPam.GetPoint()->nNode = rEndNd;
944  pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
945  if( !pCNd )
946  return false;
947  pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
948 
949  return *rPam.GetPoint() < *rPam.GetMark();
950 }
951 
952 // this method "searches" for all use cases because in SwFindParas is always the
953 // correct parameters and respective search method
955  SwDocPositions nStart, SwDocPositions nEnd,
956  FindRanges eFndRngs, bool& bCancel )
957 {
958  bCancel = false;
959  SwCursorSaveState aSaveState( *this );
960 
961  // create region without adding it to the ring
962  SwPaM aRegion( *GetPoint() );
963  SwMoveFnCollection const & fnMove = MakeFindRange( nStart, nEnd, &aRegion );
964 
965  sal_uLong nFound = 0;
966  const bool bMvBkwrd = &fnMove == &fnMoveBackward;
967  bool bInReadOnly = IsReadOnlyAvailable();
968  std::unique_ptr<SvxSearchItem> xSearchItem;
969 
970  SwCursor* pFndRing = nullptr;
971  SwNodes& rNds = GetDoc().GetNodes();
972 
973  // search in sections?
974  if( FindRanges::InSel & eFndRngs )
975  {
976  // if string was not found in region then get all sections (cursors
977  // stays unchanged)
978  nFound = lcl_FindSelection( rParas, this, fnMove,
979  pFndRing, aRegion, eFndRngs,
980  bInReadOnly, bCancel );
981  if( 0 == nFound )
982  return nFound;
983 
984  // found string at least once; it's all in new Cursor ring thus delete old one
985  while( GetNext() != this )
986  delete GetNext();
987 
988  *GetPoint() = *pFndRing->GetPoint();
989  SetMark();
990  *GetMark() = *pFndRing->GetMark();
991  pFndRing->GetRingContainer().merge( GetRingContainer() );
992  delete pFndRing;
993  }
994  else if( FindRanges::InOther & eFndRngs )
995  {
996  // put cursor as copy of current into ring
997  // chaining points always to first created, so forward
998  SwCursor* pSav = Create( this ); // save the current cursor
999 
1000  // if already outside of body text search from this position or start at
1001  // 1. base section
1002  if( bMvBkwrd
1003  ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
1005  *this, rNds.GetEndOfExtras().GetIndex() >=
1006  GetPoint()->nNode.GetIndex() )
1008  rNds.GetEndOfExtras(), *this,
1009  rNds.GetEndOfExtras().GetIndex() >=
1010  GetPoint()->nNode.GetIndex() ))
1011  {
1012  nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
1013  aRegion, eFndRngs, bInReadOnly, bCancel );
1014  }
1015 
1016  if( !nFound )
1017  {
1018  // put back the old one
1019  *GetPoint() = *pSav->GetPoint();
1020  if( pSav->HasMark() )
1021  {
1022  SetMark();
1023  *GetMark() = *pSav->GetMark();
1024  }
1025  else
1026  DeleteMark();
1027  return 0;
1028  }
1029 
1030  if( !( FindRanges::InSelAll & eFndRngs ))
1031  {
1032  // there should only be a single one, thus add it
1033  // independent from search direction: SPoint is always bigger than
1034  // mark if the search area is valid
1035  *GetPoint() = *pFndRing->GetPoint();
1036  SetMark();
1037  *GetMark() = *pFndRing->GetMark();
1038  }
1039  else
1040  {
1041  // found string at least once; it's all in new Cursor ring thus delete old one
1042  while( GetNext() != this )
1043  delete GetNext();
1044 
1045  *GetPoint() = *pFndRing->GetPoint();
1046  SetMark();
1047  *GetMark() = *pFndRing->GetMark();
1048  pFndRing->GetRingContainer().merge( GetRingContainer() );
1049  }
1050  delete pFndRing;
1051  }
1052  else if( FindRanges::InSelAll & eFndRngs )
1053  {
1054  SwCursor* pSav = Create( this ); // save the current cursor
1055 
1056  const SwNode* pSttNd = ( FindRanges::InBodyOnly & eFndRngs )
1059 
1060  if( bMvBkwrd
1061  ? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd, *this, false )
1062  : lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, false ))
1063  {
1064  nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
1065  aRegion, eFndRngs, bInReadOnly, bCancel );
1066  }
1067 
1068  if( !nFound )
1069  {
1070  // put back the old one
1071  *GetPoint() = *pSav->GetPoint();
1072  if( pSav->HasMark() )
1073  {
1074  SetMark();
1075  *GetMark() = *pSav->GetMark();
1076  }
1077  else
1078  DeleteMark();
1079  return 0;
1080  }
1081  while( GetNext() != this )
1082  delete GetNext();
1083 
1084  *GetPoint() = *pFndRing->GetPoint();
1085  SetMark();
1086  *GetMark() = *pFndRing->GetMark();
1087  pFndRing->GetRingContainer().merge( GetRingContainer() );
1088  delete pFndRing;
1089  }
1090  else
1091  {
1092  // if a GetMark is set then keep the GetMark of the found object
1093  // This allows spanning an area with this search.
1094  SwPosition aMarkPos( *GetMark() );
1095  const bool bMarkPos = HasMark() && (eFndRngs == FindRanges::InBody);
1096 
1097  nFound = rParas.DoFind(*this, fnMove, aRegion, bInReadOnly, xSearchItem) ? 1 : 0;
1098  if (0 != nFound && bMarkPos)
1099  *GetMark() = aMarkPos;
1100  }
1101 
1103  nFound = 0;
1104  return nFound;
1105 }
1106 
1108 {
1109  bool bIsStart = true;
1110  SwContentNode* pCNd = nullptr;
1111  SwNodes& rNds = GetDoc().GetNodes();
1112 
1113  switch( ePos )
1114  {
1115  case SwDocPositions::Start:
1116  rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
1117  pCNd = rNds.GoNext( &rPos.nNode );
1118  break;
1119  case SwDocPositions::End:
1120  rPos.nNode = rNds.GetEndOfContent();
1121  pCNd = SwNodes::GoPrevious( &rPos.nNode );
1122  bIsStart = false;
1123  break;
1125  rPos.nNode = *rNds[ sal_uLong(0) ];
1126  pCNd = rNds.GoNext( &rPos.nNode );
1127  break;
1129  rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
1130  pCNd = SwNodes::GoPrevious( &rPos.nNode );
1131  bIsStart = false;
1132  break;
1133  default:
1134  rPos = *GetPoint();
1135  }
1136 
1137  if( pCNd )
1138  {
1139  rPos.nContent.Assign( pCNd, bIsStart ? 0 : pCNd->Len() );
1140  }
1141 }
1142 
1144 {
1145  return RET_YES;
1146 }
1147 
1148 namespace {
1149 
1150 struct HideWrapper
1151 {
1152  // either the frame's text or the node's text (possibly pre-filtered)
1153  OUString const* m_pText;
1154  // this is actually a TextFrameIndex but all of the i18n code uses sal_Int32
1155  sal_Int32 m_nPtIndex;
1156  // if mapping is needed, use this frame
1157  SwTextFrame * m_pFrame;
1158  // input in the constructor, output (via mapping) in the destructor
1159  SwTextNode *& m_rpTextNode;
1160  sal_Int32 & m_rPtPos;
1161 
1162  HideWrapper(SwRootFrame const*const pLayout,
1163  SwTextNode *& rpTextNode, sal_Int32 & rPtPos,
1164  OUString const*const pFilteredNodeText = nullptr)
1165  : m_pText(pFilteredNodeText)
1166  , m_pFrame(nullptr)
1167  , m_rpTextNode(rpTextNode)
1168  , m_rPtPos(rPtPos)
1169  {
1170  if (pLayout && pLayout->HasMergedParas())
1171  {
1172  m_pFrame = static_cast<SwTextFrame*>(rpTextNode->getLayoutFrame(pLayout));
1173  m_pText = &m_pFrame->GetText();
1174  m_nPtIndex = sal_Int32(m_pFrame->MapModelToView(rpTextNode, rPtPos));
1175  }
1176  else
1177  {
1178  if (!m_pText)
1179  {
1180  m_pText = &rpTextNode->GetText();
1181  }
1182  m_nPtIndex = rPtPos;
1183  }
1184  }
1185  ~HideWrapper()
1186  {
1187  AssignBack(m_rpTextNode, m_rPtPos);
1188  }
1189  void AssignBack(SwTextNode *& rpTextNode, sal_Int32 & rPtPos)
1190  {
1191  if (0 <= m_nPtIndex && m_pFrame)
1192  {
1193  std::pair<SwTextNode*, sal_Int32> const pos(
1194  m_pFrame->MapViewToModel(TextFrameIndex(m_nPtIndex)));
1195  rpTextNode = pos.first;
1196  rPtPos = pos.second;
1197  }
1198  else
1199  {
1200  rPtPos = m_nPtIndex;
1201  }
1202  }
1203 };
1204 
1205 } // namespace
1206 
1207 bool SwCursor::SelectWord( SwViewShell const * pViewShell, const Point* pPt )
1208 {
1209  return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt );
1210 }
1211 
1212 bool SwCursor::IsStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const
1213 {
1214  bool bRet = false;
1215  SwTextNode* pTextNd = GetNode().GetTextNode();
1216  if (pTextNd)
1217  {
1218  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1219 
1220  HideWrapper w(pLayout, pTextNd, nPtPos);
1221 
1222  bRet = g_pBreakIt->GetBreakIter()->isBeginWord(
1223  *w.m_pText, w.m_nPtIndex,
1224  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos )),
1225  nWordType );
1226  }
1227  return bRet;
1228 }
1229 
1230 bool SwCursor::IsEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const
1231 {
1232  bool bRet = false;
1233  SwTextNode* pTextNd = GetNode().GetTextNode();
1234  if (pTextNd)
1235  {
1236  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1237 
1238  HideWrapper w(pLayout, pTextNd, nPtPos);
1239 
1240  bRet = g_pBreakIt->GetBreakIter()->isEndWord(
1241  *w.m_pText, w.m_nPtIndex,
1242  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
1243  nWordType );
1244 
1245  }
1246  return bRet;
1247 }
1248 
1249 bool SwCursor::IsInWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const
1250 {
1251  bool bRet = false;
1252  SwTextNode* pTextNd = GetNode().GetTextNode();
1253  if (pTextNd)
1254  {
1255  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1256 
1257  {
1258  HideWrapper w(pLayout, pTextNd, nPtPos);
1259 
1260  Boundary aBoundary = g_pBreakIt->GetBreakIter()->getWordBoundary(
1261  *w.m_pText, w.m_nPtIndex,
1262  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
1263  nWordType,
1264  true );
1265 
1266  bRet = aBoundary.startPos != aBoundary.endPos &&
1267  aBoundary.startPos <= w.m_nPtIndex &&
1268  w.m_nPtIndex <= aBoundary.endPos;
1269  w.m_nPtIndex = aBoundary.startPos; // hack: convert startPos back...
1270  }
1271  if(bRet)
1272  {
1273  const CharClass& rCC = GetAppCharClass();
1274  bRet = rCC.isLetterNumeric(pTextNd->GetText(), nPtPos);
1275  }
1276  }
1277  return bRet;
1278 }
1279 
1280 bool SwCursor::IsStartEndSentence(bool bEnd, SwRootFrame const*const pLayout) const
1281 {
1282  bool bRet = bEnd ?
1284  GetPoint()->nContent.GetIndex() == 0;
1285 
1286  if ((pLayout != nullptr && pLayout->HasMergedParas()) || !bRet)
1287  {
1288  SwCursor aCursor(*GetPoint(), nullptr);
1289  SwPosition aOrigPos = *aCursor.GetPoint();
1290  aCursor.GoSentence(bEnd ? SwCursor::END_SENT : SwCursor::START_SENT, pLayout);
1291  bRet = aOrigPos == *aCursor.GetPoint();
1292  }
1293  return bRet;
1294 }
1295 
1296 bool SwCursor::GoStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
1297 {
1298  bool bRet = false;
1299  SwTextNode* pTextNd = GetNode().GetTextNode();
1300  if (pTextNd)
1301  {
1302  SwCursorSaveState aSave( *this );
1303  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1304 
1305  {
1306  HideWrapper w(pLayout, pTextNd, nPtPos);
1307 
1308  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->getWordBoundary(
1309  *w.m_pText, w.m_nPtIndex,
1310  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
1311  nWordType,
1312  false ).startPos;
1313  }
1314 
1315  if (nPtPos < pTextNd->GetText().getLength() && nPtPos >= 0)
1316  {
1317  *GetPoint() = SwPosition(*pTextNd, nPtPos);
1318  if( !IsSelOvr() )
1319  bRet = true;
1320  }
1321  }
1322  return bRet;
1323 }
1324 
1325 bool SwCursor::GoEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
1326 {
1327  bool bRet = false;
1328  SwTextNode* pTextNd = GetNode().GetTextNode();
1329  if (pTextNd)
1330  {
1331  SwCursorSaveState aSave( *this );
1332  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1333 
1334  {
1335  HideWrapper w(pLayout, pTextNd, nPtPos);
1336 
1337  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->getWordBoundary(
1338  *w.m_pText, w.m_nPtIndex,
1339  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
1340  nWordType,
1341  true ).endPos;
1342  }
1343 
1344  if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0 &&
1345  GetPoint()->nContent.GetIndex() != nPtPos )
1346  {
1347  *GetPoint() = SwPosition(*pTextNd, nPtPos);
1348  if( !IsSelOvr() )
1349  bRet = true;
1350  }
1351  }
1352  return bRet;
1353 }
1354 
1355 bool SwCursor::GoNextWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
1356 {
1357  bool bRet = false;
1358  SwTextNode* pTextNd = GetNode().GetTextNode();
1359  if (pTextNd)
1360  {
1361  SwCursorSaveState aSave( *this );
1362  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1363 
1364  {
1365  HideWrapper w(pLayout, pTextNd, nPtPos);
1366 
1367  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->nextWord(
1368  *w.m_pText, w.m_nPtIndex,
1369  g_pBreakIt->GetLocale( pTextNd->GetLang(nPtPos, 1) ),
1370  nWordType ).startPos;
1371  }
1372 
1373  if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0)
1374  {
1375  *GetPoint() = SwPosition(*pTextNd, nPtPos);
1376  if( !IsSelOvr() )
1377  bRet = true;
1378  }
1379  }
1380  return bRet;
1381 }
1382 
1383 bool SwCursor::GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
1384 {
1385  bool bRet = false;
1386  SwTextNode* pTextNd = GetNode().GetTextNode();
1387  if (pTextNd)
1388  {
1389  SwCursorSaveState aSave( *this );
1390  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1391 
1392  {
1393  HideWrapper w(pLayout, pTextNd, nPtPos);
1394 
1395  const sal_Int32 nPtStart = w.m_nPtIndex;
1396  if (w.m_nPtIndex)
1397  {
1398  --w.m_nPtIndex;
1399  w.AssignBack(pTextNd, nPtPos);
1400  }
1401 
1402  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->previousWord(
1403  *w.m_pText, nPtStart,
1404  g_pBreakIt->GetLocale( pTextNd->GetLang(nPtPos, 1) ),
1405  nWordType ).startPos;
1406  }
1407 
1408  if (nPtPos < pTextNd->GetText().getLength() && nPtPos >= 0)
1409  {
1410  *GetPoint() = SwPosition(*pTextNd, nPtPos);
1411  if( !IsSelOvr() )
1412  bRet = true;
1413  }
1414  }
1415  return bRet;
1416 }
1417 
1418 bool SwCursor::SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType, const Point* pPt )
1419 {
1420  SwCursorSaveState aSave( *this );
1421 
1422  bool bRet = false;
1423  DeleteMark();
1424  const SwRootFrame* pLayout = pViewShell->GetLayout();
1425  if( pPt && nullptr != pLayout )
1426  {
1427  // set the cursor to the layout position
1428  Point aPt( *pPt );
1429  pLayout->GetModelPositionForViewPoint( GetPoint(), aPt );
1430  }
1431 
1432  SwTextNode* pTextNd = GetNode().GetTextNode();
1433  if (pTextNd)
1434  {
1435  // Should we select the whole fieldmark?
1436  const IDocumentMarkAccess* pMarksAccess = GetDoc().getIDocumentMarkAccess( );
1437  sw::mark::IFieldmark const*const pMark(pMarksAccess->getFieldmarkFor(*GetPoint()));
1440  {
1441  *GetPoint() = sw::mark::FindFieldSep(*pMark);
1442  ++GetPoint()->nContent; // Don't select the separator
1443 
1444  const SwPosition& rEnd = pMark->GetMarkEnd();
1445 
1446  assert(pMark->GetMarkEnd() != *GetPoint());
1447  SetMark();
1448  GetMark()->nNode = rEnd.nNode;
1449  GetMark()->nContent = rEnd.nContent;
1450  --GetMark()->nContent; // Don't select the end delimiter
1451 
1452  bRet = true;
1453  }
1454  else
1455  {
1456  bool bForward = true;
1457  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1458 
1459  HideWrapper w(pViewShell->GetLayout(), pTextNd, nPtPos);
1460 
1461  Boundary aBndry( g_pBreakIt->GetBreakIter()->getWordBoundary(
1462  *w.m_pText, w.m_nPtIndex,
1463  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
1464  nWordType,
1465  bForward ));
1466 
1467  if (comphelper::LibreOfficeKit::isActive() && aBndry.startPos == aBndry.endPos && w.m_nPtIndex > 0)
1468  {
1469  // nPtPos is the end of the paragraph, select the last word then.
1470  --w.m_nPtIndex;
1471  w.AssignBack(pTextNd, nPtPos);
1472 
1473  aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary(
1474  *w.m_pText, w.m_nPtIndex,
1475  g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
1476  nWordType,
1477  bForward );
1478 
1479  }
1480 
1481  SwTextNode * pStartNode(pTextNd);
1482  sal_Int32 nStartIndex;
1483  w.m_nPtIndex = aBndry.startPos;
1484  w.AssignBack(pStartNode, nStartIndex);
1485 
1486  SwTextNode * pEndNode(pTextNd);
1487  sal_Int32 nEndIndex;
1488  w.m_nPtIndex = aBndry.endPos;
1489  w.AssignBack(pEndNode, nEndIndex);
1490 
1491  if( aBndry.startPos != aBndry.endPos )
1492  {
1493  *GetPoint() = SwPosition(*pEndNode, nEndIndex);
1494  if( !IsSelOvr() )
1495  {
1496  SetMark();
1497  *GetMark() = SwPosition(*pStartNode, nStartIndex);
1498  if (sw::mark::IMark* pAnnotationMark = pMarksAccess->getAnnotationMarkFor(*GetPoint()))
1499  {
1500  // An annotation mark covers the selected word. Check
1501  // if it covers only the word: in that case we select
1502  // the comment anchor as well.
1503  bool bStartMatch = GetMark()->nNode == pAnnotationMark->GetMarkStart().nNode &&
1504  GetMark()->nContent == pAnnotationMark->GetMarkStart().nContent;
1505  bool bEndMatch = GetPoint()->nNode == pAnnotationMark->GetMarkEnd().nNode &&
1506  GetPoint()->nContent.GetIndex() + 1 == pAnnotationMark->GetMarkEnd().nContent.GetIndex();
1507  if (bStartMatch && bEndMatch)
1508  ++GetPoint()->nContent;
1509  }
1510  if( !IsSelOvr() )
1511  bRet = true;
1512  }
1513  }
1514  }
1515  }
1516 
1517  if( !bRet )
1518  {
1519  DeleteMark();
1520  RestoreSavePos();
1521  }
1522  return bRet;
1523 }
1524 
1525 static OUString lcl_MaskDeletedRedlines( const SwTextNode* pTextNd )
1526 {
1527  OUString aRes;
1528  if (pTextNd)
1529  {
1530  //mask deleted redlines
1531  OUString sNodeText(pTextNd->GetText());
1532  const SwDoc& rDoc = pTextNd->GetDoc();
1533  const bool bShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() );
1534  if ( bShowChg )
1535  {
1536  SwRedlineTable::size_type nAct = rDoc.getIDocumentRedlineAccess().GetRedlinePos( *pTextNd, RedlineType::Any );
1537  for ( ; nAct < rDoc.getIDocumentRedlineAccess().GetRedlineTable().size(); nAct++ )
1538  {
1539  const SwRangeRedline* pRed = rDoc.getIDocumentRedlineAccess().GetRedlineTable()[ nAct ];
1540  if ( pRed->Start()->nNode > pTextNd->GetIndex() )
1541  break;
1542 
1543  if( RedlineType::Delete == pRed->GetType() )
1544  {
1545  sal_Int32 nStart, nEnd;
1546  pRed->CalcStartEnd( pTextNd->GetIndex(), nStart, nEnd );
1547 
1548  while ( nStart < nEnd && nStart < sNodeText.getLength() )
1549  sNodeText = sNodeText.replaceAt( nStart++, 1, OUString(CH_TXTATR_INWORD) );
1550  }
1551  }
1552  }
1553  aRes = sNodeText;
1554  }
1555  return aRes;
1556 }
1557 
1558 bool SwCursor::GoSentence(SentenceMoveType eMoveType, SwRootFrame const*const pLayout)
1559 {
1560  bool bRet = false;
1561  SwTextNode* pTextNd = GetNode().GetTextNode();
1562  if (pTextNd)
1563  {
1564  OUString const sNodeText(lcl_MaskDeletedRedlines(pTextNd));
1565 
1566  SwCursorSaveState aSave( *this );
1567  sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
1568 
1569  {
1570  HideWrapper w(pLayout, pTextNd, nPtPos, &sNodeText);
1571 
1572  switch ( eMoveType )
1573  {
1574  case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
1575  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
1576  *w.m_pText, w.m_nPtIndex,
1577  g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
1578  break;
1579  case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
1580  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
1581  *w.m_pText, w.m_nPtIndex,
1582  g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
1583  break;
1584  case NEXT_SENT:
1585  {
1586  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
1587  *w.m_pText, w.m_nPtIndex,
1588  g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
1589  if (w.m_nPtIndex >= 0 && w.m_nPtIndex < w.m_pText->getLength())
1590  {
1591  do
1592  {
1593  ++w.m_nPtIndex;
1594  }
1595  while (w.m_nPtIndex < w.m_pText->getLength()
1596  && (*w.m_pText)[w.m_nPtIndex] == ' ');
1597  }
1598  break;
1599  }
1600  case PREV_SENT:
1601  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
1602  *w.m_pText, w.m_nPtIndex,
1603  g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
1604 
1605  if (w.m_nPtIndex == 0)
1606  return false; // the previous sentence is not in this paragraph
1607  if (w.m_nPtIndex > 0)
1608  {
1609  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
1610  *w.m_pText, w.m_nPtIndex - 1,
1611  g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
1612  }
1613  break;
1614  }
1615  }
1616 
1617  // it is allowed to place the PaM just behind the last
1618  // character in the text thus <= ...Len
1619  if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0)
1620  {
1621  *GetPoint() = SwPosition(*pTextNd, nPtPos);
1622  if( !IsSelOvr() )
1623  bRet = true;
1624  }
1625  }
1626  return bRet;
1627 }
1628 
1630 {
1631  SwTextNode* pStartNd = Start()->nNode.GetNode().GetTextNode();
1632  SwTextNode* pEndNd = End()->nNode.GetNode().GetTextNode();
1633  if (pStartNd && pEndNd)
1634  {
1635  if (!HasMark())
1636  SetMark();
1637 
1638  OUString sStartText( lcl_MaskDeletedRedlines( pStartNd ) );
1639  OUString sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) );
1640 
1641  SwCursorSaveState aSave( *this );
1642  sal_Int32 nStartPos = Start()->nContent.GetIndex();
1643  sal_Int32 nEndPos = End()->nContent.GetIndex();
1644 
1645  {
1646  HideWrapper w(pLayout, pStartNd, nStartPos, &sStartText);
1647 
1648  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
1649  *w.m_pText, w.m_nPtIndex,
1650  g_pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
1651  }
1652  {
1653  HideWrapper w(pLayout, pEndNd, nEndPos, &sEndText);
1654 
1655  w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
1656  *w.m_pText, w.m_nPtIndex,
1657  g_pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
1658  }
1659 
1660  // it is allowed to place the PaM just behind the last
1661  // character in the text thus <= ...Len
1662  if (nStartPos <= pStartNd->GetText().getLength() && nStartPos >= 0)
1663  {
1664  *GetMark() = SwPosition(*pStartNd, nStartPos);
1665  }
1666  if (nEndPos <= pEndNd->GetText().getLength() && nEndPos >= 0)
1667  {
1668  *GetPoint() = SwPosition(*pEndNd, nEndPos);
1669  }
1670  }
1671 }
1672 
1673 bool SwTableCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/,
1674  bool /*bVisualAllowed*/, bool /*bSkipHidden*/, bool /*bInsertCursor*/,
1675  SwRootFrame const*, bool /*isFieldNames*/)
1676 {
1677  return bLeft ? GoPrevCell( nCnt )
1678  : GoNextCell( nCnt );
1679 }
1680 
1681 // calculate cursor bidi level: extracted from LeftRight()
1682 const SwContentFrame*
1684  bool & io_rbLeft, bool bVisualAllowed, bool bInsertCursor)
1685 {
1686  // calculate cursor bidi level
1687  const SwContentFrame* pSttFrame = nullptr;
1688  SwNode& rNode = GetPoint()->nNode.GetNode();
1689 
1690  if( rNode.IsTextNode() )
1691  {
1692  const SwTextNode& rTNd = *rNode.GetTextNode();
1693  SwIndex& rIdx = GetPoint()->nContent;
1694  sal_Int32 nPos = rIdx.GetIndex();
1695 
1696  const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
1697  if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() &&
1699  rCTLOptions.GetCTLCursorMovement() )
1700  {
1701  // for visual cursor travelling (used in bidi layout)
1702  // we first have to convert the logic to a visual position
1703  Point aPt;
1704  std::pair<Point, bool> const tmp(aPt, true);
1705  pSttFrame = rTNd.getLayoutFrame(
1706  GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
1707  GetPoint(), &tmp);
1708  if( pSttFrame )
1709  {
1710  sal_uInt8 nCursorLevel = GetCursorBidiLevel();
1711  bool bForward = ! io_rbLeft;
1712  SwTextFrame *const pTF(const_cast<SwTextFrame*>(
1713  static_cast<const SwTextFrame*>(pSttFrame)));
1714  TextFrameIndex nTFIndex(pTF->MapModelToViewPos(*GetPoint()));
1715  pTF->PrepareVisualMove( nTFIndex, nCursorLevel,
1716  bForward, bInsertCursor );
1717  *GetPoint() = pTF->MapViewToModelPos(nTFIndex);
1718  SetCursorBidiLevel( nCursorLevel );
1719  io_rbLeft = ! bForward;
1720  }
1721  }
1722  else
1723  {
1724  SwTextFrame const* pFrame;
1725  const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo(rTNd, &pFrame);
1726  if ( pSI )
1727  {
1728  const sal_Int32 nMoveOverPos = io_rbLeft ?
1729  ( nPos ? nPos - 1 : 0 ) :
1730  nPos;
1731  TextFrameIndex nIndex(pFrame->MapModelToView(&rTNd, nMoveOverPos));
1733  }
1734  }
1735  }
1736  return pSttFrame;
1737 }
1738 
1739 bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
1740  bool bVisualAllowed,bool bSkipHidden, bool bInsertCursor,
1741  SwRootFrame const*const pLayout, bool isFieldNames)
1742 {
1743  // calculate cursor bidi level
1744  SwNode& rNode = GetPoint()->nNode.GetNode();
1745  const SwContentFrame* pSttFrame = // may side-effect bLeft!
1746  DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCursor);
1747 
1748  // can the cursor be moved n times?
1749  SwCursorSaveState aSave( *this );
1750  SwMoveFnCollection const & fnMove = bLeft ? fnMoveBackward : fnMoveForward;
1751 
1752  SwGoInDoc fnGo;
1753  if ( bSkipHidden )
1755  else
1756  fnGo = CRSR_SKIP_CELLS == nMode ? GoInContentCells : GoInContent;
1757 
1758  SwTextFrame const* pFrame(nullptr);
1759  if (pLayout)
1760  {
1761  pFrame = static_cast<SwTextFrame*>(rNode.GetContentNode()->getLayoutFrame(pLayout));
1762  if (pFrame)
1763  {
1764  while (pFrame->GetPrecede())
1765  {
1766  pFrame = static_cast<SwTextFrame const*>(pFrame->GetPrecede());
1767  }
1768  }
1769  }
1770 
1771  while( nCnt )
1772  {
1773  SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
1774 
1775  TextFrameIndex beforeIndex(-1);
1776  if (pFrame)
1777  {
1778  beforeIndex = pFrame->MapModelToViewPos(*GetPoint());
1779  }
1780 
1781  if (!bLeft && pLayout && pLayout->GetFieldmarkMode() == sw::FieldmarkMode::ShowResult)
1782  {
1783  SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode());
1784  assert(pNode);
1785  if (pNode->Len() != GetPoint()->nContent.GetIndex()
1786  && pNode->GetText()[GetPoint()->nContent.GetIndex()] == CH_TXT_ATR_FIELDSTART)
1787  {
1788  IDocumentMarkAccess const& rIDMA(*GetDoc().getIDocumentMarkAccess());
1789  sw::mark::IFieldmark const*const pMark(rIDMA.getFieldmarkAt(*GetPoint()));
1790  assert(pMark);
1791  *GetPoint() = sw::mark::FindFieldSep(*pMark);
1792  }
1793  }
1794 
1795  if ( !Move( fnMove, fnGo ) )
1796  {
1797  SwEditShell* rSh = GetDoc().GetEditShell();
1798  if (rSh && rSh->GetViewOptions() &&
1800  // Fixes crash that occurs in documents with outline content folded at the end of
1801  // the document. When the cursor is at the end of the visible document and
1802  // right arrow key is pressed Move fails after moving the cursor to the
1803  // end of the document model, which doesn't have a node frame and causes
1804  // weird numbers to be displayed in the statusbar page number count. Left
1805  // arrow, when in this state, causes a crash without RestoredSavePos() added here.
1806  RestoreSavePos();
1807  break;
1808  }
1809 
1810  if (pFrame)
1811  {
1812  SwTextFrame const* pNewFrame(static_cast<SwTextFrame const*>(
1813  GetPoint()->nNode.GetNode().GetContentNode()->getLayoutFrame(pLayout)));
1814  if (pNewFrame)
1815  {
1816  while (pNewFrame->GetPrecede())
1817  {
1818  pNewFrame = static_cast<SwTextFrame const*>(pNewFrame->GetPrecede());
1819  }
1820  }
1821  // sw_redlinehide: fully redline-deleted nodes don't have frames...
1822  if (pFrame == pNewFrame || !pNewFrame)
1823  {
1824  if (!pNewFrame || beforeIndex == pFrame->MapModelToViewPos(*GetPoint()))
1825  {
1826  continue; // moving inside delete redline, doesn't count...
1827  }
1828  }
1829  else
1830  {
1831  // assume iteration is stable & returns the same frame
1832  assert(!pFrame->IsAnFollow(pNewFrame) && !pNewFrame->IsAnFollow(pFrame));
1833  pFrame = pNewFrame;
1834  }
1835  }
1836 
1837  if (bLeft && pLayout && pLayout->GetFieldmarkMode() == sw::FieldmarkMode::ShowCommand)
1838  {
1839  SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode());
1840  assert(pNode);
1841  if (pNode->Len() != GetPoint()->nContent.GetIndex()
1842  && pNode->GetText()[GetPoint()->nContent.GetIndex()] == CH_TXT_ATR_FIELDEND)
1843  {
1844  IDocumentMarkAccess const& rIDMA(*GetDoc().getIDocumentMarkAccess());
1845  sw::mark::IFieldmark const*const pMark(rIDMA.getFieldmarkAt(*GetPoint()));
1846  assert(pMark);
1847  *GetPoint() = sw::mark::FindFieldSep(*pMark);
1848  }
1849  }
1850 
1851  if (isFieldNames)
1852  {
1853  SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode());
1854  assert(pNode);
1855  SwTextAttr const*const pInputField(pNode->GetTextAttrAt(
1856  GetPoint()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTextNode::PARENT));
1857  if (pInputField)
1858  {
1859  continue; // skip over input fields
1860  }
1861  }
1862 
1863  // If we were located inside a covered cell but our position has been
1864  // corrected, we check if the last move has moved the cursor to a
1865  // different table cell. In this case we set the cursor to the stored
1866  // covered position and redo the move:
1867  if (m_nRowSpanOffset)
1868  {
1869  const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode();
1870  const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : nullptr;
1871  const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1872  const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : nullptr;
1873 
1874  const bool bCellChanged = pOldTabSttNode && pNewTabSttNode &&
1875  pOldTabSttNode == pNewTabSttNode &&
1876  pOldTabBoxSttNode && pNewTabBoxSttNode &&
1877  pOldTabBoxSttNode != pNewTabBoxSttNode;
1878 
1879  if ( bCellChanged )
1880  {
1881  // Set cursor to start/end of covered cell:
1882  SwTableBox* pTableBox = pOldTabBoxSttNode->GetTableBox();
1883  if ( pTableBox && pTableBox->getRowSpan() > 1 )
1884  {
1885  pTableBox = & pTableBox->FindEndOfRowSpan(
1886  pOldTabSttNode->GetTable(),
1887  o3tl::narrowing<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset));
1888  SwNodeIndex& rPtIdx = GetPoint()->nNode;
1889  SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1890  rPtIdx = aNewIdx;
1891 
1892  GetDoc().GetNodes().GoNextSection( &rPtIdx, false, false );
1893  SwContentNode* pContentNode = GetContentNode();
1894  if ( pContentNode )
1895  {
1896  GetPoint()->nContent.Assign( pContentNode, bLeft ? pContentNode->Len() : 0 );
1897 
1898  // Redo the move:
1899  if ( !Move( fnMove, fnGo ) )
1900  break;
1901  }
1902  }
1903  m_nRowSpanOffset = 0;
1904  }
1905  }
1906 
1907  // Check if I'm inside a covered cell. Correct cursor if necessary and
1908  // store covered cell:
1909  const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1910  if ( pTableBoxStartNode )
1911  {
1912  const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox();
1913  if ( pTableBox && pTableBox->getRowSpan() < 1 )
1914  {
1915  // Store the row span offset:
1916  m_nRowSpanOffset = pTableBox->getRowSpan();
1917 
1918  // Move cursor to non-covered cell:
1919  const SwTableNode* pTableNd = pTableBoxStartNode->FindTableNode();
1920  pTableBox = & pTableBox->FindStartOfRowSpan( pTableNd->GetTable() );
1921  SwNodeIndex& rPtIdx = GetPoint()->nNode;
1922  SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1923  rPtIdx = aNewIdx;
1924 
1925  GetDoc().GetNodes().GoNextSection( &rPtIdx, false, false );
1926  SwContentNode* pContentNode = GetContentNode();
1927  if ( pContentNode )
1928  {
1929  GetPoint()->nContent.Assign( pContentNode, bLeft ? pContentNode->Len() : 0 );
1930  }
1931  }
1932  }
1933  --nCnt;
1934  }
1935 
1936  // here come some special rules for visual cursor travelling
1937  if ( pSttFrame )
1938  {
1939  SwNode& rTmpNode = GetPoint()->nNode.GetNode();
1940  if ( &rTmpNode != &rNode && rTmpNode.IsTextNode() )
1941  {
1942  Point aPt;
1943  std::pair<Point, bool> const tmp(aPt, true);
1944  const SwContentFrame* pEndFrame = rTmpNode.GetTextNode()->getLayoutFrame(
1945  GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
1946  GetPoint(), &tmp);
1947  if ( pEndFrame )
1948  {
1949  if ( ! pEndFrame->IsRightToLeft() != ! pSttFrame->IsRightToLeft() )
1950  {
1951  if ( ! bLeft )
1952  pEndFrame->RightMargin( this );
1953  else
1954  pEndFrame->LeftMargin( this );
1955  }
1956  }
1957  }
1958  }
1959 
1960  return 0 == nCnt && !IsInProtectTable( true ) &&
1963 }
1964 
1965 // calculate cursor bidi level: extracted from UpDown()
1967 {
1968  SwNode& rNode = GetPoint()->nNode.GetNode();
1969  if ( !rNode.IsTextNode() )
1970  return;
1971 
1972  SwTextFrame const* pFrame;
1973  const SwScriptInfo* pSI =
1974  SwScriptInfo::GetScriptInfo( *rNode.GetTextNode(), &pFrame );
1975  if ( !pSI )
1976  return;
1977 
1978  SwIndex& rIdx = GetPoint()->nContent;
1979  const sal_Int32 nPos = rIdx.GetIndex();
1980 
1981  if (!(nPos && nPos < rNode.GetTextNode()->GetText().getLength()))
1982  return;
1983 
1984  TextFrameIndex const nIndex(pFrame->MapModelToView(rNode.GetTextNode(), nPos));
1985  const sal_uInt8 nCurrLevel = pSI->DirType( nIndex );
1986  const sal_uInt8 nPrevLevel = pSI->DirType( nIndex - TextFrameIndex(1) );
1987 
1988  if ( nCurrLevel % 2 != nPrevLevel % 2 )
1989  {
1990  // set cursor level to the lower of the two levels
1991  SetCursorBidiLevel( std::min( nCurrLevel, nPrevLevel ) );
1992  }
1993  else
1994  SetCursorBidiLevel( nCurrLevel );
1995 }
1996 
1997 bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
1998  Point const * pPt, tools::Long nUpDownX,
1999  SwRootFrame & rLayout)
2000 {
2001  SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(this);
2002  bool bAdjustTableCursor = false;
2003 
2004  // If the point/mark of the table cursor in the same box then set cursor to
2005  // beginning of the box
2006  if( pTableCursor && GetNode().StartOfSectionNode() ==
2007  GetNode( false ).StartOfSectionNode() )
2008  {
2009  if ( End() != GetPoint() )
2010  Exchange();
2011  bAdjustTableCursor = true;
2012  }
2013 
2014  bool bRet = false;
2015  Point aPt;
2016  if( pPt )
2017  aPt = *pPt;
2018  std::pair<Point, bool> const temp(aPt, true);
2019  SwContentFrame* pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &temp);
2020 
2021  if( pFrame )
2022  {
2023  SwCursorSaveState aSave( *this );
2024 
2025  if( !pPt )
2026  {
2027  SwRect aTmpRect;
2028  pFrame->GetCharRect( aTmpRect, *GetPoint() );
2029  aPt = aTmpRect.Pos();
2030 
2031  nUpDownX = pFrame->IsVertical() ?
2032  aPt.getY() - pFrame->getFrameArea().Top() :
2033  aPt.getX() - pFrame->getFrameArea().Left();
2034  }
2035 
2036  // It is allowed to move footnotes in other footnotes but not sections
2037  const bool bChkRange = !pFrame->IsInFootnote() || HasMark();
2038  const SwPosition aOldPos( *GetPoint() );
2039  const bool bInReadOnly = IsReadOnlyAvailable();
2040 
2041  if ( bAdjustTableCursor && !bUp )
2042  {
2043  // Special case: We have a table cursor but the start box has more
2044  // than one paragraph. If we want to go down, we have to set the
2045  // point to the last frame in the table box. This is only necessary
2046  // if we do not already have a table selection
2047  const SwStartNode* pTableNd = GetNode().FindTableBoxStartNode();
2048  OSL_ENSURE( pTableNd, "pTableCursor without SwTableNode?" );
2049 
2050  if ( pTableNd ) // safety first
2051  {
2052  const SwNode* pEndNd = pTableNd->EndOfSectionNode();
2053  GetPoint()->nNode = *pEndNd;
2054  pTableCursor->Move( fnMoveBackward, GoInNode );
2055  std::pair<Point, bool> const tmp(aPt, true);
2056  pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp);
2057  }
2058  }
2059 
2060  while( nCnt &&
2061  (bUp ? pFrame->UnitUp( this, nUpDownX, bInReadOnly )
2062  : pFrame->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
2063  CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
2064  {
2065  std::pair<Point, bool> const tmp(aPt, true);
2066  pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp);
2067  --nCnt;
2068  }
2069 
2070  // iterate over whole number of items?
2071  if( !nCnt && !IsSelOvr( SwCursorSelOverFlags::Toggle |
2073  {
2074  if( !pTableCursor )
2075  {
2076  // try to position the cursor at half of the char-rect's height
2077  DisableCallbackAction a(rLayout);
2078  std::pair<Point, bool> const tmp(aPt, true);
2079  pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp);
2081  eTmpState.m_bSetInReadOnly = bInReadOnly;
2082  SwRect aTmpRect;
2083  pFrame->GetCharRect( aTmpRect, *GetPoint(), &eTmpState );
2084  if ( pFrame->IsVertical() )
2085  {
2086  aPt.setX(aTmpRect.Center().getX());
2087  pFrame->Calc(rLayout.GetCurrShell()->GetOut());
2088  aPt.setY(pFrame->getFrameArea().Top() + nUpDownX);
2089  }
2090  else
2091  {
2092  aPt.setY(aTmpRect.Center().getY());
2093  pFrame->Calc(rLayout.GetCurrShell()->GetOut());
2094  aPt.setX(pFrame->getFrameArea().Left() + nUpDownX);
2095  }
2096  pFrame->GetModelPositionForViewPoint( GetPoint(), aPt, &eTmpState );
2097  }
2099  }
2100  else
2101  {
2102  sal_Int32 nOffset = 0;
2103 
2104  // Jump to beginning or end of line when the cursor at first or last line.
2105  if(!bUp)
2106  {
2107  SwTextNode* pTextNd = GetPoint()->nNode.GetNode().GetTextNode();
2108  if (pTextNd)
2109  nOffset = pTextNd->GetText().getLength();
2110  }
2111  const SwPosition aPos(*GetContentNode(), nOffset);
2112 
2113  //if cursor has already been at start or end of file,
2114  //Update cursor to change nUpDownX.
2115  if ( aOldPos.nContent.GetIndex() == nOffset )
2116  {
2118  bRet = false;
2119  }
2120  else{
2121  *GetPoint() = aPos; // just give a new position
2122  bRet = true;
2123  }
2124 
2125  }
2126 
2127  DoSetBidiLevelUpDown(); // calculate cursor bidi level
2128  }
2129  return bRet;
2130 }
2131 
2132 bool SwCursor::LeftRightMargin(SwRootFrame const& rLayout, bool bLeft, bool bAPI)
2133 {
2134  Point aPt;
2135  std::pair<Point, bool> const tmp(aPt, true);
2136  SwContentFrame const*const pFrame = GetContentNode()->getLayoutFrame(
2137  &rLayout, GetPoint(), &tmp);
2138 
2139  // calculate cursor bidi level
2140  if ( pFrame )
2141  SetCursorBidiLevel( pFrame->IsRightToLeft() ? 1 : 0 );
2142 
2143  SwCursorSaveState aSave( *this );
2144  return pFrame
2145  && (bLeft ? pFrame->LeftMargin( this ) : pFrame->RightMargin( this, bAPI ) )
2147 }
2148 
2149 bool SwCursor::IsAtLeftRightMargin(SwRootFrame const& rLayout, bool bLeft, bool bAPI) const
2150 {
2151  bool bRet = false;
2152  Point aPt;
2153  std::pair<Point, bool> const tmp(aPt, true);
2154  SwContentFrame const*const pFrame = GetContentNode()->getLayoutFrame(
2155  &rLayout, GetPoint(), &tmp);
2156  if( pFrame )
2157  {
2158  SwPaM aPam( *GetPoint() );
2159  if( !bLeft && aPam.GetPoint()->nContent.GetIndex() )
2160  --aPam.GetPoint()->nContent;
2161  bRet = (bLeft ? pFrame->LeftMargin( &aPam )
2162  : pFrame->RightMargin( &aPam, bAPI ))
2163  && (!pFrame->IsTextFrame()
2164  || static_cast<SwTextFrame const*>(pFrame)->MapModelToViewPos(*aPam.GetPoint())
2165  == static_cast<SwTextFrame const*>(pFrame)->MapModelToViewPos(*GetPoint()));
2166  }
2167  return bRet;
2168 }
2169 
2170 bool SwCursor::SttEndDoc( bool bStt )
2171 {
2172  SwCursorSaveState aSave( *this );
2173  // Never jump over section boundaries during selection!
2174  // Can the cursor still moved on?
2175  SwMoveFnCollection const & fnMove = bStt ? fnMoveBackward : fnMoveForward;
2176  bool bRet = (!HasMark() || !IsNoContent() ) &&
2177  Move( fnMove, GoInDoc ) &&
2178  !IsInProtectTable( true ) &&
2182  return bRet;
2183 }
2184 
2185 bool SwCursor::GoPrevNextCell( bool bNext, sal_uInt16 nCnt )
2186 {
2187  const SwTableNode* pTableNd = GetPoint()->nNode.GetNode().FindTableNode();
2188  if( !pTableNd )
2189  return false;
2190 
2191  // If there is another EndNode in front of the cell's StartNode then there
2192  // exists a previous cell
2193  SwCursorSaveState aSave( *this );
2194  SwNodeIndex& rPtIdx = GetPoint()->nNode;
2195 
2196  while( nCnt-- )
2197  {
2198  const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
2199  const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox();
2200 
2201  // Check if we have to move the cursor to a covered cell before
2202  // proceeding:
2203  if (m_nRowSpanOffset)
2204  {
2205  if ( pTableBox && pTableBox->getRowSpan() > 1 )
2206  {
2207  pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
2208  o3tl::narrowing<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset));
2209  SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
2210  rPtIdx = aNewIdx;
2211  pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
2212  }
2213  m_nRowSpanOffset = 0;
2214  }
2215 
2216  const SwNode* pTmpNode = bNext ?
2217  pTableBoxStartNode->EndOfSectionNode() :
2218  pTableBoxStartNode;
2219 
2220  SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 );
2221  if( (bNext && !aCellIdx.GetNode().IsStartNode()) ||
2222  (!bNext && !aCellIdx.GetNode().IsEndNode()) )
2223  return false;
2224 
2225  if (bNext)
2226  rPtIdx = aCellIdx;
2227  else
2228  rPtIdx.Assign(*aCellIdx.GetNode().StartOfSectionNode());
2229 
2230  pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
2231  pTableBox = pTableBoxStartNode->GetTableBox();
2232  if ( pTableBox && pTableBox->getRowSpan() < 1 )
2233  {
2234  m_nRowSpanOffset = pTableBox->getRowSpan();
2235  // move cursor to non-covered cell:
2236  pTableBox = & pTableBox->FindStartOfRowSpan( pTableNd->GetTable() );
2237  SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
2238  rPtIdx = aNewIdx;
2239  }
2240  }
2241 
2242  ++rPtIdx;
2243  if( !rPtIdx.GetNode().IsContentNode() )
2244  GetDoc().GetNodes().GoNextSection( &rPtIdx, true, false );
2246 
2247  return !IsInProtectTable( true );
2248 }
2249 
2250 bool SwTableCursor::GotoTable( const OUString& )
2251 {
2252  return false; // invalid action
2253 }
2254 
2255 bool SwCursor::GotoTable( const OUString& rName )
2256 {
2257  bool bRet = false;
2258  if ( !HasMark() )
2259  {
2260  SwTable* pTmpTable = SwTable::FindTable( GetDoc().FindTableFormatByName( rName ) );
2261  if( pTmpTable )
2262  {
2263  // a table in a normal nodes array
2264  SwCursorSaveState aSave( *this );
2265  GetPoint()->nNode = *pTmpTable->GetTabSortBoxes()[ 0 ]->
2266  GetSttNd()->FindTableNode();
2268  bRet = !IsSelOvr();
2269  }
2270  }
2271  return bRet;
2272 }
2273 
2274 bool SwCursor::GotoTableBox( const OUString& rName )
2275 {
2276  bool bRet = false;
2277  const SwTableNode* pTableNd = GetPoint()->nNode.GetNode().FindTableNode();
2278  if( pTableNd )
2279  {
2280  // retrieve box by name
2281  const SwTableBox* pTableBox = pTableNd->GetTable().GetTableBox( rName );
2282  if( pTableBox && pTableBox->GetSttNd() &&
2283  ( !pTableBox->GetFrameFormat()->GetProtect().IsContentProtected() ||
2284  IsReadOnlyAvailable() ) )
2285  {
2286  SwCursorSaveState aSave( *this );
2287  GetPoint()->nNode = *pTableBox->GetSttNd();
2289  bRet = !IsSelOvr();
2290  }
2291  }
2292  return bRet;
2293 }
2294 
2295 bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPosPara )
2296 {
2297  // for optimization test something before
2298  const SwNode* pNd = &GetPoint()->nNode.GetNode();
2299  bool bShortCut = false;
2300  if ( fnWhichPara == GoCurrPara )
2301  {
2302  // #i41048#
2303  // If fnWhichPara == GoCurrPara then (*fnWhichPara)( *this, fnPosPara )
2304  // can already move the cursor to a different text node. In this case
2305  // we better check if IsSelOvr().
2306  const SwContentNode* pContentNd = pNd->GetContentNode();
2307  if ( pContentNd )
2308  {
2309  const sal_Int32 nSttEnd = &fnPosPara == &fnMoveForward ? 0 : pContentNd->Len();
2310  if ( GetPoint()->nContent.GetIndex() != nSttEnd )
2311  bShortCut = true;
2312  }
2313  }
2314  else
2315  {
2316  if ( pNd->IsTextNode() &&
2317  pNd->GetNodes()[ pNd->GetIndex() +
2318  (fnWhichPara == GoNextPara ? 1 : -1 ) ]->IsTextNode() )
2319  bShortCut = true;
2320  }
2321 
2322  if ( bShortCut )
2323  return (*fnWhichPara)( *this, fnPosPara );
2324 
2325  // else we must use the SaveStructure, because the next/prev is not
2326  // a same node type.
2327  SwCursorSaveState aSave( *this );
2328  return (*fnWhichPara)( *this, fnPosPara ) &&
2329  !IsInProtectTable( true ) &&
2332 }
2333 
2335  SwMoveFnCollection const & fnPosSect)
2336 {
2337  SwCursorSaveState aSave( *this );
2338  return (*fnWhichSect)( *this, fnPosSect ) &&
2339  !IsInProtectTable( true ) &&
2342 }
2343 
2345 {
2346  // This method is not supposed to be used in cases when nodes may be
2347  // deleted; detect such cases, but do not crash (example: fdo#40831).
2348  sal_uLong uNodeCount = GetPoint()->nNode.GetNodes().Count();
2349  OSL_ENSURE(m_vSavePos.empty() || m_vSavePos.back().nNode < uNodeCount,
2350  "SwCursor::RestoreSavePos: invalid node: "
2351  "probably something was deleted; consider using SwUnoCursor instead");
2352  if (m_vSavePos.empty() || m_vSavePos.back().nNode >= uNodeCount)
2353  return;
2354 
2355  GetPoint()->nNode = m_vSavePos.back().nNode;
2356 
2357  sal_Int32 nIdx = 0;
2358  if ( GetContentNode() )
2359  {
2360  if (m_vSavePos.back().nContent <= GetContentNode()->Len())
2361  nIdx = m_vSavePos.back().nContent;
2362  else
2363  {
2364  nIdx = GetContentNode()->Len();
2365  OSL_FAIL("SwCursor::RestoreSavePos: invalid content index");
2366  }
2367  }
2368  GetPoint()->nContent.Assign( GetContentNode(), nIdx );
2369 }
2370 
2372  : SwCursor( rPos, nullptr )
2373 {
2374  m_bParked = false;
2375  m_bChanged = false;
2376  m_nTablePtNd = 0;
2377  m_nTableMkNd = 0;
2378  m_nTablePtCnt = 0;
2379  m_nTableMkCnt = 0;
2380 }
2381 
2383 
2384 static bool
2385 lcl_SeekEntry(const SwSelBoxes& rTmp, SwStartNode const*const pSrch,
2386  size_t & o_rFndPos)
2387 {
2388  sal_uLong nIdx = pSrch->GetIndex();
2389 
2390  size_t nO = rTmp.size();
2391  if( nO > 0 )
2392  {
2393  nO--;
2394  size_t nU = 0;
2395  while( nU <= nO )
2396  {
2397  size_t nM = nU + ( nO - nU ) / 2;
2398  if( rTmp[ nM ]->GetSttNd() == pSrch )
2399  {
2400  o_rFndPos = nM;
2401  return true;
2402  }
2403  else if( rTmp[ nM ]->GetSttIdx() < nIdx )
2404  nU = nM + 1;
2405  else if( nM == 0 )
2406  return false;
2407  else
2408  nO = nM - 1;
2409  }
2410  }
2411  return false;
2412 }
2413 
2415 {
2416  if (m_bChanged)
2417  {
2418  if (m_bParked)
2419  {
2420  // move back into content
2421  Exchange();
2422  Move( fnMoveForward );
2423  Exchange();
2424  Move( fnMoveForward );
2425  m_bParked = false;
2426  }
2427 
2428  m_bChanged = false;
2429 
2430  // create temporary copies so that all boxes that
2431  // have already cursors can be removed
2433 
2434  // compare old and new ones
2435  SwNodes& rNds = pCurrentCursor->GetDoc().GetNodes();
2436  const SwStartNode* pSttNd;
2437  SwPaM* pCur = pCurrentCursor;
2438  do {
2439  size_t nPos;
2440  bool bDel = false;
2441  pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
2442  if( !pCur->HasMark() || !pSttNd ||
2443  pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() )
2444  bDel = true;
2445 
2446  else if( lcl_SeekEntry( aTmp, pSttNd, nPos ))
2447  {
2448  SwNodeIndex aIdx( *pSttNd, 1 );
2449  const SwNode* pNd = &aIdx.GetNode();
2450  if( !pNd->IsContentNode() )
2451  pNd = rNds.GoNextSection( &aIdx, true, false );
2452 
2453  SwPosition* pPos = pCur->GetMark();
2454  if( pNd != &pPos->nNode.GetNode() )
2455  pPos->nNode = *pNd;
2456  pPos->nContent.Assign( const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd)), 0 );
2457 
2458  aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 );
2459  pNd = &aIdx.GetNode();
2460  if( !pNd->IsContentNode() )
2461  pNd = SwNodes::GoPrevSection( &aIdx, true, false );
2462 
2463  pPos = pCur->GetPoint();
2464  if (pNd && pNd != &pPos->nNode.GetNode())
2465  pPos->nNode = *pNd;
2466  pPos->nContent.Assign(const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd)), pNd ? static_cast<const SwContentNode*>(pNd)->Len() : 0);
2467 
2468  aTmp.erase( aTmp.begin() + nPos );
2469  }
2470  else
2471  bDel = true;
2472 
2473  pCur = pCur->GetNext();
2474  if( bDel )
2475  {
2476  SwPaM* pDel = pCur->GetPrev();
2477 
2478  if( pDel == pCurrentCursor )
2479  pCurrentCursor->DeleteMark();
2480  else
2481  delete pDel;
2482  }
2483  } while ( pCurrentCursor != pCur );
2484 
2485  for (size_t nPos = 0; nPos < aTmp.size(); ++nPos)
2486  {
2487  pSttNd = aTmp[ nPos ]->GetSttNd();
2488 
2489  SwNodeIndex aIdx( *pSttNd, 1 );
2490  if( &aIdx.GetNodes() != &rNds )
2491  break;
2492  SwNode* pNd = &aIdx.GetNode();
2493  if( !pNd->IsContentNode() )
2494  pNd = rNds.GoNextSection( &aIdx, true, false );
2495 
2496  SwPaM *const pNew = (!pCurrentCursor->IsMultiSelection() && !pCurrentCursor->HasMark())
2497  ? pCurrentCursor
2498  : pCurrentCursor->Create( pCurrentCursor );
2499  pNew->GetPoint()->nNode = *pNd;
2500  pNew->GetPoint()->nContent.Assign( static_cast<SwContentNode*>(pNd), 0 );
2501  pNew->SetMark();
2502 
2503  SwPosition* pPos = pNew->GetPoint();
2504  pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 );
2505  pNd = &pPos->nNode.GetNode();
2506  if( !pNd->IsContentNode() )
2507  pNd = SwNodes::GoPrevSection( &pPos->nNode, true, false );
2508 
2509  pPos->nContent.Assign(static_cast<SwContentNode*>(pNd), pNd ? static_cast<SwContentNode*>(pNd)->Len() : 0);
2510  }
2511  }
2512  return pCurrentCursor;
2513 }
2514 
2515 void SwTableCursor::InsertBox( const SwTableBox& rTableBox )
2516 {
2517  SwTableBox* pBox = const_cast<SwTableBox*>(&rTableBox);
2518  m_SelectedBoxes.insert(pBox);
2519  m_bChanged = true;
2520 }
2521 
2522 void SwTableCursor::DeleteBox(size_t const nPos)
2523 {
2525  m_bChanged = true;
2526 }
2527 
2529 {
2530  bool bRet = false;
2531  const SwNode *pStart = GetNode().FindTableBoxStartNode();
2532  const SwNode *pEnd = GetNode(false).FindTableBoxStartNode();
2533  if( pStart && pEnd )
2534  {
2535  const SwTableNode *pTableNode = pStart->FindTableNode();
2536  if( pTableNode == pEnd->FindTableNode() &&
2537  pTableNode->GetTable().IsNewModel() )
2538  {
2539  bRet = true;
2541  pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew,
2542  SwTable::SEARCH_NONE, false );
2543  ActualizeSelection( aNew );
2544  }
2545  }
2546  return bRet;
2547 }
2548 
2550 {
2551  size_t nOld = 0, nNew = 0;
2552  while (nOld < m_SelectedBoxes.size() && nNew < rNew.size())
2553  {
2554  SwTableBox const*const pPOld = m_SelectedBoxes[ nOld ];
2555  const SwTableBox* pPNew = rNew[ nNew ];
2556  if( pPOld == pPNew )
2557  { // this box will stay
2558  ++nOld;
2559  ++nNew;
2560  }
2561  else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
2562  {
2563  DeleteBox( nOld ); // this box has to go
2564  }
2565  else
2566  {
2567  InsertBox( *pPNew ); // this is a new one
2568  ++nOld;
2569  ++nNew;
2570  }
2571  }
2572 
2573  while (nOld < m_SelectedBoxes.size())
2574  {
2575  DeleteBox( nOld ); // some more to delete
2576  }
2577 
2578  for ( ; nNew < rNew.size(); ++nNew ) // some more to insert
2579  {
2580  InsertBox( *rNew[ nNew ] );
2581  }
2582 }
2583 
2585 {
2586  if( !IsCursorMoved() )
2587  return false;
2588 
2593  return true;
2594 }
2595 
2598 {
2599  // de-register index from text node
2600  SwNode* pNd = &GetPoint()->nNode.GetNode();
2601  if( !pNd->IsStartNode() )
2602  pNd = pNd->StartOfSectionNode();
2603  GetPoint()->nNode = *pNd;
2604  GetPoint()->nContent.Assign( nullptr, 0 );
2605 
2606  pNd = &GetMark()->nNode.GetNode();
2607  if( !pNd->IsStartNode() )
2608  pNd = pNd->StartOfSectionNode();
2609  GetMark()->nNode = *pNd;
2610  GetMark()->nContent.Assign( nullptr, 0 );
2611 
2612  m_bChanged = true;
2613  m_bParked = true;
2614 }
2615 
2617 {
2618  bool bRet = false;
2619  for (size_t n = m_SelectedBoxes.size(); n; )
2620  {
2621  if (m_SelectedBoxes[--n]->GetFrameFormat()->GetProtect().IsContentProtected())
2622  {
2623  bRet = true;
2624  break;
2625  }
2626  }
2627  return bRet;
2628 }
2629 
2630 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool SttEndDoc(bool bSttDoc)
Definition: swcrsr.cxx:2170
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:339
bool GoSentence(SentenceMoveType eMoveType, SwRootFrame const *pLayout=nullptr)
Definition: swcrsr.cxx:1558
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:983
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:683
Starts a section of nodes in the document model.
Definition: node.hxx:312
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: swcrsr.cxx:2295
bool IsCursorMoved() const
Definition: swcrsr.hxx:290
void merge(RingContainer< value_type > aDestRing)
Merges two ring containers.
Definition: ring.hxx:182
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
virtual sal_Int32 Len() const
Definition: node.cxx:1246
static bool lcl_SeekEntry(const SwSelBoxes &rTmp, SwStartNode const *const pSrch, size_t &o_rFndPos)
Definition: swcrsr.cxx:2385
virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool, std::unique_ptr< SvxSearchItem > &xSearchItem)=0
void DeleteMark()
Definition: pam.hxx:177
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_uLong GetIndex() const
Definition: node.hxx:291
SAL_DLLPRIVATE void UpdateCursor(sal_uInt16 eFlags=SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE, bool bIdleEnd=false)
Definition: crsrsh.cxx:1571
void InsertBox(const SwTableBox &rTableBox)
Definition: swcrsr.cxx:2515
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
SwCursorSelOverFlags
Definition: swcrsr.hxx:49
sal_Int32 nIndex
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:970
SwTableCursor(const SwPosition &rPos)
Definition: swcrsr.cxx:2371
sal_uLong Count() const
Definition: ndarr.hxx:139
bool IsStartEndSentence(bool bEnd, SwRootFrame const *pLayout) const
Definition: swcrsr.cxx:1280
virtual ::sw::mark::IFieldmark * getFieldmarkAt(const SwPosition &rPos) const =0
get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos
Marks a position in the document model.
Definition: pam.hxx:35
bool IsInProtectTable(bool bMove=false, bool bChgCursor=true)
Definition: swcrsr.cxx:568
bool IsSectionNode() const
Definition: node.hxx:645
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:115
bool IsMultiSelection() const
Definition: pam.hxx:272
void FillFindPos(SwDocPositions ePos, SwPosition &rPos) const
Definition: swcrsr.cxx:1107
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1336
SwTableBox * GetTableBox() const
If node is in a table return the respective table box.
Definition: node.cxx:754
bool GoEndWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr)
Definition: swcrsr.cxx:1325
bool GoPrevCell(sal_uInt16 nCnt=1)
Definition: swcrsr.hxx:175
const OUString & GetText() const
Definition: ndtxt.hxx:218
virtual const SwRootFrame * GetCurrentLayout() const =0
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1911
bool MoveSection(SwWhichSection, SwMoveFnCollection const &)
Definition: swcrsr.cxx:2334
SwDocShell * GetDocShell()
Definition: doc.hxx:1352
bool GoCurrPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1016
virtual short MaxReplaceArived()
Definition: swcrsr.cxx:1143
bool IsAtLeftRightMargin(SwRootFrame const &rLayout, bool bLeftMargin, bool bAPI) const
Definition: swcrsr.cxx:2149
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsInFootnote() const
Definition: frame.hxx:950
sal_uIntPtr sal_uLong
long Long
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:478
const SwPosition * GetMark() const
Definition: pam.hxx:209
Find "all" in Footer/Header/Fly...
bool IsEndWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr) const
Definition: swcrsr.cxx:1230
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1213
sal_Int64 n
Provides access to the marks of a document.
virtual bool IsSelOvr(SwCursorSelOverFlags eFlags=SwCursorSelOverFlags::CheckNodeSection|SwCursorSelOverFlags::Toggle|SwCursorSelOverFlags::ChangePos)
Definition: swcrsr.cxx:226
Definition: doc.hxx:188
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:1968
SentenceMoveType
Definition: swcrsr.hxx:153
helper class to disable creation of an action by a callback event in particular, change event from a ...
Definition: rootfrm.hxx:451
bool m_bSetInReadOnly
ReadOnly areas may be entered.
Definition: crstate.hxx:148
virtual SwCursor * Create(SwPaM *pRing=nullptr) const
Definition: swcrsr.cxx:149
static SwScriptInfo * GetScriptInfo(const SwTextNode &rNode, SwTextFrame const **o_pFrame=nullptr, bool bAllowInvalid=false)
return a frame for the node, ScriptInfo is its member...
Definition: porlay.cxx:2455
sal_uLong m_nTableMkNd
Definition: swcrsr.hxx:258
SwPosition FindFieldSep(IFieldmark const &rMark)
return position of the CH_TXT_ATR_FIELDSEP for rMark
virtual bool LeftRight(bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, bool bAllowVisual, bool bSkipHidden, bool bInsertCursor, SwRootFrame const *pLayout, bool isFieldNames)
Definition: swcrsr.cxx:1739
sal_uInt8 GetCursorBidiLevel() const
Definition: swcrsr.hxx:211
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1310
SwNode & GetNode() const
Definition: ndindex.hxx:119
SwCursor * MakeBoxSels(SwCursor *pCurrentCursor)
Definition: swcrsr.cxx:2414
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:31
void EndProgress(SwDocShell const *pDocShell)
Definition: mainwn.cxx:92
void Pos(const Point &rNew)
Definition: swrect.hxx:171
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1790
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
SwNode & GetEndOfPostIts() const
A still empty section.
Definition: ndarr.hxx:149
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1788
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
virtual ~SwCursor() override
Definition: swcrsr.cxx:145
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1294
SwTextAttr * GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, enum GetTextAttrMode const eMode=DEFAULT) const
get the innermost text attribute covering position nIndex.
Definition: ndtxt.cxx:1691
bool IsCTLFontEnabled() const
void StartProgress(TranslateId pMessResId, tools::Long nStartValue, tools::Long nEndValue, SwDocShell *pDocShell)
Definition: mainwn.cxx:52
virtual bool LeftMargin(SwPaM *) const =0
void CalcStartEnd(sal_uLong nNdIdx, sal_Int32 &rStart, sal_Int32 &rEnd) const
Calculates the intersection with text node number nNdIdx.
Definition: docredln.cxx:1333
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
RET_CANCEL
bool IsReadOnlyUI() const
sal_uInt8 DirType(const TextFrameIndex nPos) const
Definition: porlay.cxx:1769
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:172
Find in selections.
bool SelectWord(SwViewShell const *pViewShell, const Point *pPt)
Definition: swcrsr.cxx:1207
static bool IsShowChanges(const RedlineFlags eM)
virtual bool IsSkipOverHiddenSections() const
Definition: swcrsr.cxx:159
Array of Undo-history.
Definition: docary.hxx:192
sal_Int32 getRowSpan() const
Definition: swtable.cxx:76
SwDocPositions
Definition: cshtyp.hxx:103
const SwSection & GetSection() const
Definition: node.hxx:542
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const
Definition: unusedf.cxx:47
sal_uLong m_nTablePtNd
Definition: swcrsr.hxx:257
bool isLetterNumeric(const OUString &rStr, sal_Int32 nPos) const
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Primary passes the call to the first page.
Definition: trvlfrm.cxx:425
virtual bool IsSelOvrCheck(SwCursorSelOverFlags eFlags)
Definition: swcrsr.cxx:191
#define CH_TXTATR_INWORD
Definition: hintids.hxx:171
SwTableNode * GetTableNode()
Definition: node.hxx:600
RET_YES
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:180
Cursor Up/Down.
size_t pos
auto(*)(SwPaM &rPam, SwMoveFnCollection const &fnMove) -> bool SwGoInDoc
Definition: pam.hxx:126
A wrapper around SfxPoolItem to store the start position of (usually) a text portion, with an optional end.
Definition: txatbase.hxx:41
virtual ::sw::mark::IFieldmark * getFieldmarkFor(const SwPosition &pos) const =0
static OUString lcl_MaskDeletedRedlines(const SwTextNode *pTextNd)
Definition: swcrsr.cxx:1525
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
bool GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr)
Definition: swcrsr.cxx:1383
static sal_uLong lcl_FindSelection(SwFindParas &rParas, SwCursor *pCurrentCursor, SwMoveFnCollection const &fnMove, SwCursor *&pFndRing, SwPaM &aRegion, FindRanges eFndRngs, bool bInReadOnly, bool &bCancel)
Definition: swcrsr.cxx:763
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
virtual void DelAllUndoObj()=0
Delete all Undo actions.
virtual bool GotoTable(const OUString &rName) override
Definition: swcrsr.cxx:2250
FindRanges
Definition: cshtyp.hxx:90
bool IsTextFrame() const
Definition: frame.hxx:1235
sal_Int32 GetStart() const
Definition: txatbase.hxx:86
virtual bool UnitUp(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:966
virtual void DoUndo(bool const bDoUndo)=0
Enable/Disable Undo.
bool IsStartNode() const
Definition: node.hxx:625
bool IsCursorMovedUpdate()
Definition: swcrsr.cxx:2584
virtual void DoSetBidiLevelUpDown()
Definition: swcrsr.cxx:1966
std::vector< SwCursor_SavePos > m_vSavePos
Definition: swcrsr.hxx:74
CursorMovement GetCTLCursorMovement() const
bool CheckNodesRange(const SwNodeIndex &rStt, const SwNodeIndex &rEnd, bool bChkSection)
Check if the given range is inside one of the defined top-level sections.
Definition: pam.cxx:259
const SwTable & GetTable() const
Definition: node.hxx:499
bool SelectWordWT(SwViewShell const *pViewShell, sal_Int16 nWordType, const Point *pPt)
Definition: swcrsr.cxx:1418
bool IsProtectFlag() const
Definition: section.hxx:188
SwContentFrame * GetPrevContentFrame() const
Definition: cntfrm.hxx:123
SwMoveFnCollection const & MakeFindRange(SwDocPositions, SwDocPositions, SwPaM *) const
set range for search in document
Definition: swcrsr.cxx:749
virtual bool UnitDown(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:971
size_type size() const
virtual bool DoesUndo() const =0
Is Undo enabled?
const SwCursor_SavePos * GetSavePos() const
Definition: swcrsr.hxx:313
virtual bool GotoTable(const OUString &rName)
Definition: swcrsr.cxx:2255
SwPaM * GetNext()
Definition: pam.hxx:264
virtual bool GetCharRect(SwRect &, const SwPosition &, SwCursorMoveState *=nullptr, bool bAllowFarAway=true) const
Definition: unusedf.cxx:72
void SaveState()
Definition: swcrsr.cxx:171
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:160
bool GoNextCell(sal_uInt16 nCnt=1)
Definition: swcrsr.hxx:174
bool IsShowOutlineContentVisibilityButton() const
Definition: viewopt.cxx:99
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:262
bool IsContentNode() const
Definition: node.hxx:629
OUString GetText() const
Definition: pam.cxx:1076
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:504
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:1966
sal_Int32 m_nTablePtCnt
Definition: swcrsr.hxx:259
virtual bool IsReplaceMode() const =0
bool m_bChanged
Definition: swcrsr.hxx:262
A helper class to save cursor state (position).
Definition: swcrsr.hxx:232
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1268
#define SW_MOD()
Definition: swmodule.hxx:256
sal_uLong FindAll(SwFindParas &, SwDocPositions, SwDocPositions, FindRanges, bool &bCancel)
Definition: swcrsr.cxx:954
bool(* SwWhichPara)(SwPaM &, SwMoveFnCollection const &)
Definition: cshtyp.hxx:43
SwCursor * GetNext()
Definition: swcrsr.hxx:219
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:961
uno_Any a
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:132
SwDoc & GetDoc()
Definition: node.hxx:212
const SwPosition * GetPoint() const
Definition: pam.hxx:207
std::vector< SwSectionFormat * >::size_type size_type
Definition: docary.hxx:67
bool GoInContentCells(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:978
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:328
sw::FieldmarkMode GetFieldmarkMode() const
Definition: rootfrm.hxx:424
bool GoNextWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr)
Definition: swcrsr.cxx:1355
bool IsInWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr) const
Definition: swcrsr.cxx:1249
bool GoInContentCellsSkipHidden(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:994
void Exchange()
Definition: pam.cxx:492
tools::Long m_nRowSpanOffset
Definition: swcrsr.hxx:75
bool IsHiddenFlag() const
Definition: section.hxx:187
SwContentNode * GetContentNode()
Definition: node.hxx:616
vector_type::size_type size_type
Definition: docary.hxx:223
void MakeStartIndex(SwIndex *pIdx)
Definition: node.hxx:398
void ExpandToSentenceBorders(SwRootFrame const *pLayout)
Definition: swcrsr.cxx:1629
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
All (only in non-body and selections).
Marks a character position inside a document model node.
Definition: index.hxx:33
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:179
size_t size() const
Definition: docary.hxx:88
bool IsNoContent() const
determine if point is outside of the node-array's content area
Definition: swcrsr.cxx:185
sal_Int32 w
bool IsContentProtected() const
Marks a node in the document model.
Definition: ndindex.hxx:31
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:444
bool UpDown(bool bUp, sal_uInt16 nCnt, Point const *pPt, tools::Long nUpDownX, SwRootFrame &rLayout)
Definition: swcrsr.cxx:1997
bool IsEndNode() const
Definition: node.hxx:633
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:694
bool GoInDoc(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:949
ring_container GetRingContainer()
Definition: ring.hxx:240
const sal_uInt16 coSrchRplcThreshold
Definition: swcrsr.cxx:64
virtual bool RightMargin(SwPaM *, bool bAPI=false) const =0
static bool lcl_MakeSelBkwrd(const SwNode &rSttNd, const SwNode &rEndNd, SwPaM &rPam, bool bFirst)
Definition: swcrsr.cxx:921
bool IsProtect() const
Is node in something that is protected (range, frame, table cells ...
Definition: node.cxx:426
std::pair< SwTextNode *, sal_Int32 > MapViewToModel(TextFrameIndex nIndex) const
map position in potentially merged text frame to SwPosition
Definition: txtfrm.cxx:1232
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:112
const int FIND_NO_RING
Definition: swcrsr.hxx:37
const SwPosition * Start() const
Definition: pam.hxx:212
virtual bool IsSkipOverProtectSections() const
Definition: swcrsr.cxx:164
virtual const SwContentFrame * DoSetBidiLevelLeftRight(bool &io_rbLeft, bool bVisualAllowed, bool bInsertCursor)
Definition: swcrsr.cxx:1683
EXPAND : (Start < nIndex <= End)
Definition: ndtxt.hxx:371
Find only in body - only in combination with FindRanges::InSelAll !!!
Point Center() const
Definition: swrect.hxx:338
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
const_iterator begin() const
SwPaM * GetPrev()
Definition: pam.hxx:268
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
bool GoInContentSkipHidden(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:986
void RestoreState()
Definition: swcrsr.cxx:176
virtual bool IsReadOnlyAvailable() const
Definition: swcrsr.cxx:154
const sal_uInt16 CRSR_SKIP_CELLS
Definition: swcrsr.hxx:66
const css::lang::Locale & GetLocale(const LanguageType aLang)
Definition: breakit.hxx:67
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:678
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
bool LeftRightMargin(SwRootFrame const &rLayout, bool bLeftMargin, bool bAPI)
Definition: swcrsr.cxx:2132
SwSelBoxes m_SelectedBoxes
Definition: swcrsr.hxx:261
virtual sw::mark::IMark * getAnnotationMarkFor(const SwPosition &rPosition) const =0
bool GotoTableBox(const OUString &rName)
Definition: swcrsr.cxx:2274
const SwFlowFrame * GetPrecede() const
Definition: flowfrm.hxx:172
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:458
SwTableBox & FindStartOfRowSpan(const SwTable &, sal_uInt16 nMaxStep=USHRT_MAX)
SwTableBox::FindStartOfRowSpan(..) returns the "master" cell, the cell which overlaps the given cell...
unsigned char sal_uInt8
const SwNodes & GetNodes() const
Definition: ndindex.hxx:156
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:424
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
TextFrameIndex MapModelToView(SwTextNode const *pNode, sal_Int32 nIndex) const
Definition: txtfrm.cxx:1253
sal_Int32 GetIndex() const
Definition: index.hxx:91
void SetProgressState(tools::Long nPosition, SwDocShell const *pDocShell)
Definition: mainwn.cxx:82
bool IsNoTextFrame() const
Definition: frame.hxx:1239
SwNodes & GetNodes()
Definition: doc.hxx:409
bool m_bParked
Definition: swcrsr.hxx:263
const SwPosition * End() const
Definition: pam.hxx:217
void SetCursorBidiLevel(sal_uInt8 nNewLevel)
Definition: swcrsr.hxx:212
virtual bool LeftRight(bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, bool bAllowVisual, bool bSkipHidden, bool bInsertCursor, SwRootFrame const *, bool) override
Definition: swcrsr.cxx:1673
bool IsRightToLeft() const
Definition: frame.hxx:988
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3364
SwCursor(SwCursor const &rPaM)=delete
SwTableBox & FindEndOfRowSpan(const SwTable &, sal_uInt16 nMaxStep)
SwTableBox::FindEndOfRowSpan(..) returns the last overlapped cell if there is any.
bool GoNextPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1044
bool GoPrevNextCell(bool bNext, sal_uInt16 nCnt)
Definition: swcrsr.cxx:2185
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1840
const sal_Int32 * End() const
Definition: txatbase.hxx:152
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:405
virtual ~SwTableCursor() override
Definition: swcrsr.cxx:2382
double getLength(const B2DPolygon &rCandidate)
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:727
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
void PrepareVisualMove(TextFrameIndex &nPos, sal_uInt8 &nCursorLevel, bool &bRight, bool bInsertCursor)
Prepares the cursor position for a visual cursor move (BiDi).
Definition: frmcrsr.cxx:1045
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:181
void ParkCursor()
park table cursor on the boxes' start node
Definition: swcrsr.cxx:2597
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:197
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:357
Find "one" only in body text.
virtual bool IsAtValidPos(bool bPoint=true) const
Return if cursor can be set to this position.
Definition: swcrsr.cxx:720
virtual bool IsSelOvrCheck(SwCursorSelOverFlags eFlags) override
Definition: swcrsr.cxx:197
bool IsVertical() const
Definition: frame.hxx:974
sal_Int32 m_nTableMkCnt
Definition: swcrsr.hxx:260
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:1916
void ActualizeSelection(const SwSelBoxes &rBoxes)
Definition: swcrsr.cxx:2549
bool IsTableNode() const
Definition: node.hxx:641
const SvxProtectItem & GetProtect(bool=true) const
Definition: frmatr.hxx:82
SwDoc & GetDoc() const
Definition: pam.hxx:243
bool HasMergedParas() const
Definition: rootfrm.hxx:426
static bool lcl_MakeSelFwrd(const SwNode &rSttNd, const SwNode &rEndNd, SwPaM &rPam, bool bFirst)
Definition: swcrsr.cxx:889
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:478
SectionType GetType() const
Definition: section.hxx:170
void DeleteBox(size_t nPos)
Definition: swcrsr.cxx:2522
SwSection * GetSection() const
Definition: section.cxx:669
std::pair< const_iterator, bool > insert(Value &&x)
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:158
bool IsNewModel() const
Definition: swtable.hxx:188
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2116
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:207
SwSectionFormats & GetSections()
Definition: doc.hxx:1338
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...
bool NewTableSelection()
Definition: swcrsr.cxx:2528
CharClass & GetAppCharClass()
Definition: init.cxx:703
bool IsTextNode() const
Definition: node.hxx:637
bool HasReadOnlyBoxSel() const
Definition: swcrsr.cxx:2616
void Height(tools::Long nNew)
Definition: swrect.hxx:193
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1247
virtual void SaveTableBoxContent(const SwPosition *pPos)
Definition: swcrsr.cxx:746
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1293
void MakeEndIndex(SwIndex *pIdx)
Definition: node.hxx:399
bool(* SwWhichSection)(SwPaM &, SwMoveFnCollection const &)
Definition: cshtyp.hxx:51
bool IsStartWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr) const
Definition: swcrsr.cxx:1212
sal_uInt16 nPos
bool GoStartWordWT(sal_Int16 nWordType, SwRootFrame const *pLayout=nullptr)
Definition: swcrsr.cxx:1296
void RestoreSavePos()
Restore cursor state to the one saved by SwCursorSaveState.
Definition: swcrsr.cxx:2344
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:856
size_type erase(const Value &x)
SwNodeIndex & Assign(SwNodes const &rNds, sal_uLong)
Definition: ndindex.hxx:272
SwCursor * GetPrev()
Definition: swcrsr.hxx:221
Base class of the Writer document model elements.
Definition: node.hxx:80