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