LibreOffice Module sw (master)  1
trvltbl.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 <crsrsh.hxx>
22 #include <doc.hxx>
23 #include <cntfrm.hxx>
24 #include <editsh.hxx>
25 #include <pam.hxx>
26 #include <swtable.hxx>
27 #include <frmfmt.hxx>
28 #include <viscrs.hxx>
29 #include "callnk.hxx"
30 #include <tabfrm.hxx>
31 #include <ndtxt.hxx>
32 #include <shellres.hxx>
33 #include <cellfrm.hxx>
35 #include <osl/diagnose.h>
36 #include <svx/srchdlg.hxx>
37 
39 bool SwCursorShell::GoNextCell( bool bAppendLine )
40 {
41  bool bRet = false;
42  const SwTableNode* pTableNd = nullptr;
43 
44  if( IsTableMode() || nullptr != ( pTableNd = IsCursorInTable() ))
45  {
47  SwCallLink aLk( *this ); // watch Cursor-Moves
48  bRet = true;
49 
50  // Check if we have to move the cursor to a covered cell before
51  // proceeding:
52  const SwNode* pTableBoxStartNode = pCursor->GetNode().FindTableBoxStartNode();
53  const SwTableBox* pTableBox = nullptr;
54 
55  if ( pCursor->GetCursorRowSpanOffset() )
56  {
57  pTableBox = pTableBoxStartNode->GetTableBox();
58  if (pTableBox && pTableBox->getRowSpan() > 1)
59  {
60  if ( !pTableNd )
61  pTableNd = IsCursorInTable();
62  assert (pTableNd);
63  pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
64  static_cast<sal_uInt16>(pTableBox->getRowSpan() + pCursor->GetCursorRowSpanOffset() ) );
65  pTableBoxStartNode = pTableBox->GetSttNd();
66  }
67  }
68 
69  SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 );
70 
71  // if there is another StartNode after the EndNode of a cell then
72  // there is another cell
73  if( !aCellStt.GetNode().IsStartNode() )
74  {
75  if( pCursor->HasMark() || !bAppendLine )
76  bRet = false;
77  else if (pTableNd)
78  {
79  // if there is no list anymore then create new one
80  if ( !pTableBox )
81  pTableBox = pTableNd->GetTable().GetTableBox(
82  pCursor->GetPoint()->nNode.GetNode().
83  StartOfSectionIndex() );
84 
85  OSL_ENSURE( pTableBox, "Box is not in this table" );
86  SwSelBoxes aBoxes;
87 
88  // the document might change; w/o Action views would not be notified
89  static_cast<SwEditShell*>(this)->StartAllAction();
90  bRet = mxDoc->InsertRow( SwTable::SelLineFromBox( pTableBox, aBoxes, false ));
91  static_cast<SwEditShell*>(this)->EndAllAction();
92  }
93  }
94  bRet = bRet && pCursor->GoNextCell();
95  if( bRet )
96  UpdateCursor();
97  }
98  return bRet;
99 }
100 
102 {
103  bool bRet = false;
104  if( IsTableMode() || IsCursorInTable() )
105  {
107  SwCallLink aLk( *this ); // watch Cursor-Moves
108  bRet = pCursor->GoPrevCell();
109  if( bRet )
110  UpdateCursor(); // update current cursor
111  }
112  return bRet;
113 }
114 
115 static const SwFrame* lcl_FindMostUpperCellFrame( const SwFrame* pFrame )
116 {
117  while ( pFrame &&
118  ( !pFrame->IsCellFrame() ||
119  !pFrame->GetUpper()->GetUpper()->IsTabFrame() ||
120  pFrame->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
121  {
122  pFrame = pFrame->GetUpper();
123  }
124  return pFrame;
125 }
126 
127 bool SwCursorShell::SelTableRowOrCol( bool bRow, bool bRowSimple )
128 {
129  // check if the current cursor's SPoint/Mark are in a table
130  SwFrame *pFrame = GetCurrFrame();
131  if( !pFrame->IsInTab() )
132  return false;
133 
134  const SwTabFrame* pTabFrame = pFrame->FindTabFrame();
135  const SwTabFrame* pMasterTabFrame = pTabFrame->IsFollow() ? pTabFrame->FindMaster( true ) : pTabFrame;
136  const SwTable* pTable = pTabFrame->GetTable();
137 
138  CurrShell aCurr( this );
139 
140  const SwTableBox* pStt = nullptr;
141  const SwTableBox* pEnd = nullptr;
142 
143  // search box based on layout
144  SwSelBoxes aBoxes;
146  const bool bCheckProtected = !IsReadOnlyAvailable();
147 
148  if( bCheckProtected )
149  eType = static_cast<SwTableSearchType>(eType | SwTableSearchType::Protect);
150 
151  if ( !bRowSimple )
152  {
153  GetTableSel( *this, aBoxes, eType );
154 
155  if( aBoxes.empty() )
156  return false;
157 
158  pStt = aBoxes[0];
159  pEnd = aBoxes.back();
160  }
161  // #i32329# Enhanced table selection
162  else if ( pTable->IsNewModel() )
163  {
164  const SwShellCursor *pCursor = GetCursor_();
166  pTable->CreateSelection( *pCursor, aBoxes, eSearchType, bCheckProtected );
167  if( aBoxes.empty() )
168  return false;
169 
170  pStt = aBoxes[0];
171  pEnd = aBoxes.back();
172 
173  m_eEnhancedTableSel = eSearchType;
174  }
175  else
176  {
177  const SwShellCursor *pCursor = GetCursor_();
178  const SwFrame* pStartFrame = pFrame;
179  const SwContentNode *pCNd = pCursor->GetContentNode( false );
180  std::pair<Point, bool> const tmp(pCursor->GetMkPos(), true);
181  const SwFrame* pEndFrame = pCNd
182  ? pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp)
183  : nullptr;
184 
185  if ( bRow )
186  {
187  pStartFrame = lcl_FindMostUpperCellFrame( pStartFrame );
188  pEndFrame = lcl_FindMostUpperCellFrame( pEndFrame );
189  }
190 
191  if ( !pStartFrame || !pEndFrame )
192  return false;
193 
194  const bool bVert = pFrame->ImplFindTabFrame()->IsVertical();
195 
196  // If we select upwards it is sufficient to set pStt and pEnd
197  // to the first resp. last box of the selection obtained from
198  // GetTableSel. However, selecting downwards requires the frames
199  // located at the corners of the selection. This does not work
200  // for column selections in vertical tables:
201  const bool bSelectUp = ( bVert && !bRow ) ||
202  *pCursor->GetPoint() <= *pCursor->GetMark();
203  SwCellFrames aCells;
204  GetTableSel( static_cast<const SwCellFrame*>(pStartFrame),
205  static_cast<const SwCellFrame*>(pEndFrame),
206  aBoxes, bSelectUp ? nullptr : &aCells, eType );
207 
208  if( aBoxes.empty() || ( !bSelectUp && 4 != aCells.size() ) )
209  return false;
210 
211  if ( bSelectUp )
212  {
213  pStt = aBoxes[0];
214  pEnd = aBoxes.back();
215  }
216  else
217  {
218  // will become point of table cursor
219  pStt = aCells[bVert ? 0 : (bRow ? 2 : 1)]->GetTabBox();
220  // will become mark of table cursor
221  pEnd = aCells[bVert ? 3 : (bRow ? 1 : 2)]->GetTabBox();
222  }
223  }
224 
225  // if no table cursor exists, create one
226  if( !m_pTableCursor )
227  {
230  m_pCurrentCursor->SwSelPaintRects::Hide();
231  }
232 
234 
235  // set start and end of a column
236  m_pTableCursor->GetPoint()->nNode = *pEnd->GetSttNd();
241 
242  // set PtPos 'close' to the reference table, otherwise we might get problems
243  // with the repeated headlines check in UpdateCursor():
244  if ( !bRow )
245  m_pTableCursor->GetPtPos() = pMasterTabFrame->IsVertical()
246  ? pMasterTabFrame->getFrameArea().TopRight()
247  : pMasterTabFrame->getFrameArea().TopLeft();
248 
249  UpdateCursor();
250  return true;
251 }
252 
254 {
255  // check if the current cursor's SPoint/Mark are in a table
256  SwFrame *pFrame = GetCurrFrame();
257  if( !pFrame->IsInTab() )
258  return false;
259 
260  const SwTabFrame *pTableFrame = pFrame->ImplFindTabFrame();
261  const SwTabFrame* pMasterTabFrame = pTableFrame->IsFollow() ? pTableFrame->FindMaster( true ) : pTableFrame;
262  const SwTableNode* pTableNd = pTableFrame->GetTable()->GetTableNode();
263 
264  CurrShell aCurr( this );
265 
266  if( !m_pTableCursor )
267  {
270  m_pCurrentCursor->SwSelPaintRects::Hide();
271  }
272 
274  m_pTableCursor->GetPoint()->nNode = *pTableNd;
277  // set MkPos 'close' to the master table, otherwise we might get problems
278  // with the repeated headlines check in UpdateCursor():
279  m_pTableCursor->GetMkPos() = pMasterTabFrame->IsVertical() ? pMasterTabFrame->getFrameArea().TopRight() : pMasterTabFrame->getFrameArea().TopLeft();
280  m_pTableCursor->GetPoint()->nNode = *pTableNd->EndOfSectionNode();
282  UpdateCursor();
283  return true;
284 }
285 
287 {
288  // if we're in a table, create a table cursor, and select the cell
289  // that the current cursor's point resides in
290 
291  // search for start node of our table box. If not found, exit really
292  const SwStartNode* pStartNode =
294 
295 #if OSL_DEBUG_LEVEL > 0
296  // the old code checks whether we're in a table by asking the
297  // frame. This should yield the same result as searching for the
298  // table box start node, right?
299  SwFrame *pFrame = GetCurrFrame();
300  OSL_ENSURE( !pFrame->IsInTab() == !(pStartNode != nullptr),
301  "Schroedinger's table: We're in a box, and also we aren't." );
302 #endif
303  if( pStartNode == nullptr )
304  return false;
305 
306  CurrShell aCurr( this );
307 
308  // create a table cursor, if there isn't one already
309  if( !m_pTableCursor )
310  {
313  m_pCurrentCursor->SwSelPaintRects::Hide();
314  }
315 
316  // select the complete box with our shiny new m_pTableCursor
317  // 1. delete mark, and move point to first content node in box
319  *(m_pTableCursor->GetPoint()) = SwPosition( *pStartNode );
321 
322  // 2. set mark, and move point to last content node in box
324  *(m_pTableCursor->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) );
326 
327  // 3. exchange
329 
330  // with some luck, UpdateCursor() will now update everything that
331  // needs updating
332  UpdateCursor();
333 
334  return true;
335 }
336 
337 // TODO: provide documentation
346 static bool lcl_FindNextCell( SwNodeIndex& rIdx, bool bInReadOnly )
347 {
348  // check protected cells
349  SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
350 
351  // the resulting cell should be in that table:
352  const SwTableNode* pTableNd = rIdx.GetNode().GetTableNode();
353 
354  if ( !pTableNd )
355  {
356  OSL_FAIL( "lcl_FindNextCell not celled with table start node!" );
357  return false;
358  }
359 
360  const SwNode* pTableEndNode = pTableNd->EndOfSectionNode();
361 
362  SwNodes& rNds = aTmp.GetNode().GetNodes();
363  SwContentNode* pCNd = aTmp.GetNode().GetContentNode();
364 
365  // no content node => go to next content node
366  if( !pCNd )
367  pCNd = rNds.GoNext( &aTmp );
368 
369  // robust
370  if ( !pCNd )
371  return false;
372 
374 
375  if ( nullptr == pFrame || pCNd->FindTableNode() != pTableNd ||
376  (!bInReadOnly && pFrame->IsProtected() ) )
377  {
378  // we are not located inside a 'valid' cell. We have to continue searching...
379 
380  // skip behind current section. This might be the end of the table cell
381  // or behind an inner section or...
382  aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
383 
384  // loop to find a suitable cell...
385  for( ;; )
386  {
387  SwNode* pNd = &aTmp.GetNode();
388 
389  // we break this loop if we reached the end of the table.
390  // to make this code even more robust, we also break if we are
391  // already behind the table end node:
392  if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() )
393  return false;
394 
395  // ok, get the next content node:
396  pCNd = aTmp.GetNode().GetContentNode();
397  if( nullptr == pCNd )
398  pCNd = rNds.GoNext( &aTmp );
399 
400  // robust:
401  if ( !pCNd )
402  return false;
403 
404  // check if we have found a suitable table cell:
405  pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
406 
407  if ( nullptr != pFrame && pCNd->FindTableNode() == pTableNd &&
408  (bInReadOnly || !pFrame->IsProtected() ) )
409  {
410  // finally, we have found a suitable table cell => set index and return
411  rIdx = *pCNd;
412  return true;
413  }
414 
415  // continue behind the current section:
416  aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
417  }
418  }
419  rIdx = *pCNd;
420  return true;
421 }
422 
424 static bool lcl_FindPrevCell( SwNodeIndex& rIdx, bool bInReadOnly )
425 {
426  SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode
427 
428  const SwNode* pTableEndNode = &rIdx.GetNode();
429  const SwTableNode* pTableNd = pTableEndNode->StartOfSectionNode()->GetTableNode();
430 
431  if ( !pTableNd )
432  {
433  OSL_FAIL( "lcl_FindPrevCell not celled with table start node!" );
434  return false;
435  }
436 
437  SwContentNode* pCNd = aTmp.GetNode().GetContentNode();
438 
439  if( !pCNd )
440  pCNd = SwNodes::GoPrevious( &aTmp );
441 
442  if ( !pCNd )
443  return false;
444 
446 
447  if( nullptr == pFrame || pCNd->FindTableNode() != pTableNd ||
448  (!bInReadOnly && pFrame->IsProtected() ))
449  {
450  // skip before current section
451  aTmp.Assign( *pCNd->StartOfSectionNode(), -1 );
452  for( ;; )
453  {
454  SwNode* pNd = &aTmp.GetNode();
455 
456  if( pNd == pTableNd || pNd->GetIndex() < pTableNd->GetIndex() )
457  return false;
458 
459  pCNd = aTmp.GetNode().GetContentNode();
460  if( nullptr == pCNd )
461  pCNd = SwNodes::GoPrevious( &aTmp );
462 
463  if ( !pCNd )
464  return false;
465 
466  pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
467 
468  if( nullptr != pFrame && pCNd->FindTableNode() == pTableNd &&
469  (bInReadOnly || !pFrame->IsProtected() ) )
470  {
471  rIdx = *pCNd;
472  return true; // ok, not protected
473  }
474  aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 );
475  }
476  }
477  rIdx = *pCNd;
478  return true;
479 }
480 
481 bool GotoPrevTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable,
482  bool bInReadOnly )
483 {
484  SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
485 
486  SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode );
487 
488  SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
489  if( pTableNd )
490  {
491  // #i26532#: If we are inside a table, we may not go backward to the
492  // table start node, because we would miss any tables inside this table.
493  SwTableNode* pInnerTableNd = nullptr;
494  SwNodeIndex aTmpIdx( aIdx );
495  while( aTmpIdx.GetIndex() &&
496  nullptr == ( pInnerTableNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
497  --aTmpIdx;
498 
499  if( pInnerTableNd == pTableNd )
500  aIdx.Assign( *pTableNd, - 1 );
501  }
502 
503  SwNodeIndex aOldIdx = aIdx;
504  sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1;
505  do {
506  while( aIdx.GetIndex() &&
507  nullptr == ( pTableNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
508  {
509  --aIdx;
510  if ( aIdx == aOldIdx )
511  {
512  SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
513  return false;
514  }
515  }
516 
517  if ( !aIdx.GetIndex() )
518  {
519  SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
520  aIdx = nLastNd;
521  continue;
522  }
523 
524  {
525  if( &fnPosTable == &fnMoveForward ) // at the beginning?
526  {
527  aIdx = *aIdx.GetNode().StartOfSectionNode();
528  if( !lcl_FindNextCell( aIdx, bInReadOnly ))
529  {
530  // skip table
531  aIdx.Assign( *pTableNd, -1 );
532  continue;
533  }
534  }
535  else
536  {
537  // check protected cells
538  if( !lcl_FindNextCell( aIdx, bInReadOnly ))
539  {
540  // skip table
541  aIdx.Assign( *pTableNd, -1 );
542  continue;
543  }
544  }
545 
546  SwTextNode* pTextNode = aIdx.GetNode().GetTextNode();
547  if ( pTextNode )
548  {
549  rCurrentCursor.GetPoint()->nNode = *pTextNode;
550  rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ?
551  pTextNode->Len() :
552  0 );
553  }
554  return true;
555  }
556  } while( true );
557 
558  return false;
559 }
560 
561 bool GotoNextTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable,
562  bool bInReadOnly )
563 {
564  SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
565 
566  SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode );
567  SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
568 
569  if( pTableNd )
570  aIdx.Assign( *pTableNd->EndOfSectionNode(), 1 );
571 
572  SwNodeIndex aOldIdx = aIdx;
573  sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1;
574  do {
575  while( aIdx.GetIndex() < nLastNd &&
576  nullptr == ( pTableNd = aIdx.GetNode().GetTableNode()) )
577  {
578  ++aIdx;
579  if ( aIdx == aOldIdx )
580  {
581  SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
582  return false;
583  }
584  }
585 
586  if ( aIdx.GetIndex() == nLastNd )
587  {
588  SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
589  aIdx = 0;
590  continue;
591  }
592 
593  assert( pTableNd ); // coverity, should never be nullptr
594 
595  if( &fnPosTable == &fnMoveForward ) // at the beginning?
596  {
597  if( !lcl_FindNextCell( aIdx, bInReadOnly ))
598  {
599  // skip table
600  aIdx.Assign( *pTableNd->EndOfSectionNode(), + 1 );
601  continue;
602  }
603  }
604  else
605  {
606  aIdx = *aIdx.GetNode().EndOfSectionNode();
607  // check protected cells
608  if( !lcl_FindNextCell( aIdx, bInReadOnly ))
609  {
610  // skip table
611  aIdx.Assign( *pTableNd->EndOfSectionNode(), + 1 );
612  continue;
613  }
614  }
615 
616  SwTextNode* pTextNode = aIdx.GetNode().GetTextNode();
617  if ( pTextNode )
618  {
619  rCurrentCursor.GetPoint()->nNode = *pTextNode;
620  rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ?
621  pTextNode->Len() :
622  0 );
623  }
624  return true;
625 
626  } while( true );
627 
628  // the flow is such that it is not possible to get there
629 
630  return false;
631 }
632 
633 bool GotoCurrTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable,
634  bool bInReadOnly )
635 {
636  SwTableNode* pTableNd = rCurrentCursor.GetPoint()->nNode.GetNode().FindTableNode();
637  if( !pTableNd )
638  return false;
639 
640  SwTextNode* pTextNode = nullptr;
641  if( &fnPosTable == &fnMoveBackward ) // to the end of the table
642  {
643  SwNodeIndex aIdx( *pTableNd->EndOfSectionNode() );
644  if( !lcl_FindPrevCell( aIdx, bInReadOnly ))
645  return false;
646  pTextNode = aIdx.GetNode().GetTextNode();
647  }
648  else
649  {
650  SwNodeIndex aIdx( *pTableNd );
651  if( !lcl_FindNextCell( aIdx, bInReadOnly ))
652  return false;
653  pTextNode = aIdx.GetNode().GetTextNode();
654  }
655 
656  if ( pTextNode )
657  {
658  rCurrentCursor.GetPoint()->nNode = *pTextNode;
659  rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ?
660  pTextNode->Len() :
661  0 );
662  }
663 
664  return true;
665 }
666 
667 bool SwCursor::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection const & fnPosTable )
668 {
669  bool bRet = false;
670  SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(this);
671 
672  if( pTableCursor || !HasMark() )
673  {
674  SwCursorSaveState aSaveState( *this );
675  bRet = (*fnWhichTable)( *this, fnPosTable, IsReadOnlyAvailable() ) &&
678  }
679  return bRet;
680 }
681 
682 bool SwCursorShell::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection const & fnPosTable )
683 {
684  SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
685 
687  bool bCheckPos;
688  bool bRet;
689  sal_uLong nPtNd = 0;
690  sal_Int32 nPtCnt = 0;
691 
693  {
694  // switch to table mode
697  m_pCurrentCursor->SwSelPaintRects::Hide();
699  pCursor = m_pTableCursor;
700  bCheckPos = false;
701  }
702  else
703  {
704  bCheckPos = true;
705  nPtNd = pCursor->GetPoint()->nNode.GetIndex();
706  nPtCnt = pCursor->GetPoint()->nContent.GetIndex();
707  }
708 
709  bRet = pCursor->MoveTable( fnWhichTable, fnPosTable );
710 
711  if( bRet )
712  {
713  // #i45028# - set "top" position for repeated headline rows
714  pCursor->GetPtPos() = Point();
715 
717 
718  if( bCheckPos &&
719  pCursor->GetPoint()->nNode.GetIndex() == nPtNd &&
720  pCursor->GetPoint()->nContent.GetIndex() == nPtCnt )
721  bRet = false;
722  }
723  return bRet;
724 }
725 
727 {
728  bool bRet = false;
729 
730  // Here we may trigger table formatting so we better do that inside an action
731  StartAction();
733  if( pTNd )
734  {
735  // in a table; check if table or section is balanced
736  OUString sSel;
737  if( m_pTableCursor )
738  sSel = GetBoxNms();
739  bRet = pTNd->GetTable().IsTableComplexForChart( sSel );
740  }
741  EndAction();
742 
743  return bRet;
744 }
745 
746 OUString SwCursorShell::GetBoxNms() const
747 {
748  OUString sNm;
749  const SwPosition* pPos;
750  SwFrame* pFrame;
751 
752  if( IsTableMode() )
753  {
755  pFrame = pCNd ? pCNd->getLayoutFrame( GetLayout() ) : nullptr;
756  if( !pFrame )
757  return sNm;
758 
759  do {
760  pFrame = pFrame->GetUpper();
761  } while ( pFrame && !pFrame->IsCellFrame() );
762 
763  OSL_ENSURE( pFrame, "no frame for this box" );
764 
765  if( !pFrame )
766  return sNm;
767 
768  sNm = static_cast<SwCellFrame*>(pFrame)->GetTabBox()->GetName() + ":";
769  pPos = m_pTableCursor->End();
770  }
771  else
772  {
773  const SwTableNode* pTableNd = IsCursorInTable();
774  if( !pTableNd )
775  return sNm;
776  pPos = GetCursor()->GetPoint();
777  }
778 
779  SwContentNode* pCNd = pPos->nNode.GetNode().GetContentNode();
780  pFrame = pCNd ? pCNd->getLayoutFrame( GetLayout() ) : nullptr;
781 
782  if( pFrame )
783  {
784  do {
785  pFrame = pFrame->GetUpper();
786  } while ( pFrame && !pFrame->IsCellFrame() );
787 
788  if( pFrame )
789  sNm += static_cast<SwCellFrame*>(pFrame)->GetTabBox()->GetName();
790  }
791  return sNm;
792 }
793 
794 bool SwCursorShell::GotoTable( const OUString& rName )
795 {
796  SwCallLink aLk( *this ); // watch Cursor-Moves
797  bool bRet = !m_pTableCursor && m_pCurrentCursor->GotoTable( rName );
798  if( bRet )
799  {
803  }
804  return bRet;
805 }
806 
808 {
810  return false;
811 
812  // check if box content is consistent with given box format, reset if not
813  SwTableBox* pChkBox = nullptr;
814  SwStartNode* pSttNd = nullptr;
815  if( !pPos )
816  {
817  // get stored position
818  if (nullptr != (pSttNd = m_pBoxIdx->GetNode().GetStartNode()) &&
819  SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
820  m_pBoxPtr == pSttNd->FindTableNode()->GetTable().
821  GetTableBox( m_pBoxIdx->GetIndex() ) )
822  pChkBox = m_pBoxPtr;
823  }
824  else
825  {
827  if( pSttNd)
828  pChkBox = pSttNd->FindTableNode()->GetTable().GetTableBox( pSttNd->GetIndex() );
829  }
830 
831  // box has more than one paragraph
832  if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() )
833  pChkBox = nullptr;
834 
835  // destroy pointer before next action starts
836  if( !pPos && !pChkBox )
838 
839  // cursor not anymore in this section?
840  if( pChkBox && !pPos &&
842  pSttNd->GetIndex() + 1 == m_pCurrentCursor->GetPoint()->nNode.GetIndex() ))
843  pChkBox = nullptr;
844 
845  // Did the content of a box change at all? This is important if e.g. Undo
846  // could not restore the content properly.
847  if( pChkBox )
848  {
849  const SwTextNode* pNd = GetDoc()->GetNodes()[
850  pSttNd->GetIndex() + 1 ]->GetTextNode();
851  if( !pNd ||
853  SfxItemState::SET == pChkBox->GetFrameFormat()->
854  GetItemState( RES_BOXATR_FORMULA )) )
855  pChkBox = nullptr;
856  }
857 
858  if( pChkBox )
859  {
860  // destroy pointer before next action starts
862  StartAction();
863  GetDoc()->ChkBoxNumFormat( *pChkBox, true );
864  EndAction();
865  }
866 
867  return nullptr != pChkBox;
868 }
869 
871 {
872  if( IsSelTableCells() || !IsAutoUpdateCells() )
873  return ;
874 
875  if( !pPos )
876  pPos = m_pCurrentCursor->GetPoint();
877 
879 
880  bool bCheckBox = false;
881  if( pSttNd && m_pBoxIdx )
882  {
883  if( pSttNd == &m_pBoxIdx->GetNode() )
884  pSttNd = nullptr;
885  else
886  bCheckBox = true;
887  }
888  else
889  bCheckBox = nullptr != m_pBoxIdx;
890 
891  if( bCheckBox )
892  {
893  // check m_pBoxIdx
894  SwPosition aPos( *m_pBoxIdx );
895  CheckTableBoxContent( &aPos );
896  }
897 
898  if( pSttNd )
899  {
900  m_pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTableBox( pSttNd->GetIndex() );
901 
902  if( m_pBoxIdx )
903  *m_pBoxIdx = *pSttNd;
904  else
905  m_pBoxIdx = new SwNodeIndex( *pSttNd );
906  }
907 }
908 
910 {
911  delete m_pBoxIdx;
912  m_pBoxIdx = nullptr;
913  m_pBoxPtr = nullptr;
914 }
915 
917 {
918  bool bRet = false;
919  for(SwViewShell& rSh : GetRingContainer())
920  {
921  if( auto pCursorShell = dynamic_cast<SwCursorShell *>(&rSh) )
922  bRet |= pCursorShell->CheckTableBoxContent(
923  pCursorShell->m_pCurrentCursor->GetPoint() );
924 
925  }
926  return bRet;
927 }
928 
929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwStartNode * FindSttNodeByType(SwStartNodeType eTyp)
Definition: node.cxx:764
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:686
Starts a section of nodes in the document model.
Definition: node.hxx:312
Base class of the Writer layout elements.
Definition: frame.hxx:313
SwTableBox * m_pBoxPtr
table row
Definition: crsrsh.hxx:185
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:1567
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
const Value & back() const
SwShellCursor * m_pCurrentCursor
current cursor
Definition: crsrsh.hxx:175
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:970
bool GotoTable(const OUString &rName)
Definition: trvltbl.cxx:794
bool IsFollow() const
Definition: flowfrm.hxx:166
bool IsAutoUpdateCells() const
Definition: crsrsh.hxx:805
sal_uLong Count() const
Definition: ndarr.hxx:142
Marks a position in the document model.
Definition: pam.hxx:35
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1328
void SaveTableBoxContent(const SwPosition *pPos=nullptr)
Definition: trvltbl.cxx:870
SwTableBox * GetTableBox() const
If node is in a table return the respective table box.
Definition: node.cxx:754
bool GoPrevCell(sal_uInt16 nCnt=1)
Definition: swcrsr.hxx:175
const OUString & GetText() const
Definition: ndtxt.hxx:210
virtual const SwRootFrame * GetCurrentLayout() const =0
static ShellResource * GetShellRes()
Definition: viewsh.cxx:2546
bool GotoPrevTable(SwPaM &rCurrentCursor, SwMoveFnCollection const &fnPosTable, bool bInReadOnly)
Definition: trvltbl.cxx:481
void ClearTableBoxContent()
Definition: trvltbl.cxx:909
check overlapping PaMs
Definition: crsrsh.hxx:154
const SwTable * GetTable() const
Definition: tabfrm.hxx:143
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:643
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:276
sal_uIntPtr sal_uLong
const SwPosition * GetMark() const
Definition: pam.hxx:209
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1212
virtual bool IsSelOvr(SwCursorSelOverFlags eFlags=SwCursorSelOverFlags::CheckNodeSection|SwCursorSelOverFlags::Toggle|SwCursorSelOverFlags::ChangePos)
Definition: swcrsr.cxx:224
tools::Long GetCursorRowSpanOffset() const
Definition: swcrsr.hxx:217
bool IsTableComplexForChart(const OUString &rSel) const
Definition: docchart.cxx:39
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1310
SwNode & GetNode() const
Definition: ndindex.hxx:119
OUString aCalc_Error
Definition: shellres.hxx:40
bool IsCellFrame() const
Definition: frame.hxx:1222
bool GoNextCell(bool bAppendLine=true)
set cursor into next/previous cell
Definition: trvltbl.cxx:39
bool GotoCurrTable(SwPaM &rCurrentCursor, SwMoveFnCollection const &fnPosTable, bool bInReadOnly)
Definition: trvltbl.cxx:633
sal_Int32 getRowSpan() const
Definition: swtable.cxx:75
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
std::deque< SwCellFrame * > SwCellFrames
Definition: tblsel.hxx:41
Point TopLeft() const
Definition: swrect.cxx:174
static bool lcl_FindNextCell(SwNodeIndex &rIdx, bool bInReadOnly)
get the next non-protected cell inside a table
Definition: trvltbl.cxx:346
SwTableNode * GetTableNode()
Definition: node.hxx:603
static const SwFrame * lcl_FindMostUpperCellFrame(const SwFrame *pFrame)
Definition: trvltbl.cxx:115
rtl::Reference< SwDoc > mxDoc
The document; never 0.
Definition: viewsh.hxx:171
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:178
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
bool IsInTab() const
Definition: frame.hxx:951
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
const SwTable & GetTable() const
Definition: node.hxx:501
SwDoc * GetDoc() const
Definition: viewsh.hxx:281
SwShellTableCursor * m_pTableCursor
table Cursor; only in tables when the selection lays over 2 columns
Definition: crsrsh.hxx:181
virtual bool GotoTable(const OUString &rName)
Definition: swcrsr.cxx:2248
DocumentType eType
bool GoNextCell(sal_uInt16 nCnt=1)
Definition: swcrsr.hxx:174
SwShellCursor * GetCursor_()
Definition: crsrsh.hxx:328
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
bool(* SwWhichTable)(SwPaM &, SwMoveFnCollection const &, bool bInReadOnly)
Definition: cshtyp.hxx:58
SwTabFrame * ImplFindTabFrame()
Definition: findfrm.cxx:469
const SwTableNode * IsCursorInTable() const
Definition: crsrsh.hxx:889
SwTableSearchType
Definition: tblsel.hxx:58
A helper class to save cursor state (position).
Definition: swcrsr.hxx:232
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:774
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:961
void GetTableSel(const SwCursorShell &rShell, SwSelBoxes &rBoxes, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:149
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:132
SwDoc & GetDoc()
Definition: node.hxx:212
const SwPosition * GetPoint() const
Definition: pam.hxx:207
static SwSelBoxes & SelLineFromBox(const SwTableBox *pBox, SwSelBoxes &rBoxes, bool bToTop=true)
Definition: tblcpy.cxx:1028
bool EndAllTableBoxEdit()
Definition: trvltbl.cxx:916
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
void Exchange()
Definition: pam.cxx:492
bool SelTableBox()
Definition: trvltbl.cxx:286
SwContentNode * GetContentNode()
Definition: node.hxx:619
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
SwLayoutFrame * GetUpper()
Definition: frame.hxx:676
virtual void SetMark() override
Unless this is called, the getter method of Mark will return Point.
Definition: viscrs.cxx:819
const Point & GetMkPos() const
Definition: viscrs.hxx:143
Marks a node in the document model.
Definition: ndindex.hxx:31
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:431
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:697
bool IsSelTableCells() const
Definition: crsrsh.hxx:800
ring_container GetRingContainer()
SwStartNodeType GetStartNodeType() const
Definition: node.hxx:329
bool empty() const
SwStartNode * GetStartNode()
Definition: node.hxx:595
static void SetSearchLabel(const SearchLabel &rSL)
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:111
const SwPosition * Start() const
Definition: pam.hxx:212
OUString GetBoxNms() const
Definition: trvltbl.cxx:746
void StartAction()
Definition: crsrsh.cxx:226
bool SelTable()
Definition: trvltbl.cxx:253
virtual bool IsReadOnlyAvailable() const
Definition: swcrsr.cxx:152
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:681
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
bool IsReadOnlyAvailable() const
Definition: crsrsh.hxx:474
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:445
SwNodeIndex * m_pBoxIdx
for recognizing of the changed
Definition: crsrsh.hxx:184
bool IsTabFrame() const
Definition: frame.hxx:1214
SwContentFrame * GetCurrFrame(const bool bCalcFrame=true) const
Get current frame in which the cursor is positioned.
Definition: crsrsh.cxx:2444
bool GoPrevCell()
Definition: trvltbl.cxx:101
bool MoveTable(SwWhichTable, SwMoveFnCollection const &)
Definition: trvltbl.cxx:682
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
SwShellCursor * GetNext()
Definition: viscrs.hxx:164
sal_Int32 GetIndex() const
Definition: index.hxx:91
SwNodes & GetNodes()
Definition: doc.hxx:408
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(151)
const SwPosition * End() const
Definition: pam.hxx:217
SwTableBox & FindEndOfRowSpan(const SwTable &, sal_uInt16 nMaxStep)
SwTableBox::FindEndOfRowSpan(..) returns the last overlapped cell if there is any.
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:392
const Point & GetPtPos() const
Definition: viscrs.hxx:141
bool CheckTableBoxContent(const SwPosition *pPos=nullptr)
Definition: trvltbl.cxx:807
scroll window
Definition: crsrsh.hxx:153
bool SelTableRowOrCol(bool bRow, bool bRowSimple=false)
Definition: trvltbl.cxx:127
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:197
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:357
Point TopRight() const
Definition: swrect.cxx:175
bool IsVertical() const
Definition: frame.hxx:969
bool MoveTable(SwWhichTable, SwMoveFnCollection const &)
Definition: trvltbl.cxx:667
bool IsTableComplexForChart()
Definition: trvltbl.cxx:726
bool GotoNextTable(SwPaM &rCurrentCursor, SwMoveFnCollection const &fnPosTable, bool bInReadOnly)
Definition: trvltbl.cxx:561
make visible in spite of Readonly
Definition: crsrsh.hxx:155
SwDoc & GetDoc() const
Definition: pam.hxx:243
bool IsNewModel() const
Definition: swtable.hxx:187
static bool lcl_FindPrevCell(SwNodeIndex &rIdx, bool bInReadOnly)
see lcl_FindNextCell()
Definition: trvltbl.cxx:424
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2067
SwTable::SearchType m_eEnhancedTableSel
Definition: crsrsh.hxx:202
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1293
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:845
void ChkBoxNumFormat(SwTableBox &rCurrentBox, bool bCallUpdate)
Definition: ndtbl.cxx:4040
SwNodeIndex & Assign(SwNodes const &rNds, sal_uLong)
Definition: ndindex.hxx:272
void EndAction(const bool bIdleEnd=false)
Definition: crsrsh.cxx:243
bool IsProtected() const
Is the Frame or rather the Section in which it lies protected?
Definition: trvlfrm.cxx:1628
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1095
SwTableNode * GetTableNode() const
Definition: swtable.cxx:1913
Base class of the Writer document model elements.
Definition: node.hxx:80