1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
26 #include <swtable.hxx>
32 #include <shellres.hxx>
33 #include <cellfrm.hxx>
34 #include <IDocumentLayoutAccess.hxx>
35 #include <osl/diagnose.h>
36 #include <svx/srchdlg.hxx>
38 /// set cursor into next/previous cell
39 bool SwCursorShell::GoNextCell( bool bAppendLine
)
42 const SwTableNode
* pTableNd
= nullptr;
44 if( IsTableMode() || nullptr != ( pTableNd
= IsCursorInTable() ))
46 SwCursor
* pCursor
= m_pTableCursor
? m_pTableCursor
: m_pCurrentCursor
;
47 SwCallLink
aLk( *this ); // watch Cursor-Moves
50 // Check if we have to move the cursor to a covered cell before
52 const SwNode
* pTableBoxStartNode
= pCursor
->GetPointNode().FindTableBoxStartNode();
53 const SwTableBox
* pTableBox
= nullptr;
55 if ( pCursor
->GetCursorRowSpanOffset() )
57 pTableBox
= pTableBoxStartNode
->GetTableBox();
58 if (pTableBox
&& pTableBox
->getRowSpan() > 1)
61 pTableNd
= IsCursorInTable();
63 pTableBox
= & pTableBox
->FindEndOfRowSpan( pTableNd
->GetTable(),
64 o3tl::narrowing
<sal_uInt16
>(pTableBox
->getRowSpan() + pCursor
->GetCursorRowSpanOffset() ) );
65 pTableBoxStartNode
= pTableBox
->GetSttNd();
69 SwNodeIndex
aCellStt( *pTableBoxStartNode
->EndOfSectionNode(), 1 );
71 // if there is another StartNode after the EndNode of a cell then
72 // there is another cell
73 if( !aCellStt
.GetNode().IsStartNode() )
75 if( pCursor
->HasMark() || !bAppendLine
)
79 // if there is no list anymore then create new one
81 pTableBox
= pTableNd
->GetTable().GetTableBox(
82 pCursor
->GetPoint()->GetNode().
83 StartOfSectionIndex() );
85 OSL_ENSURE( pTableBox
, "Box is not in this table" );
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();
94 bRet
= bRet
&& pCursor
->GoNextCell();
101 bool SwCursorShell::GoPrevCell()
104 if( IsTableMode() || IsCursorInTable() )
106 SwCursor
* pCursor
= m_pTableCursor
? m_pTableCursor
: m_pCurrentCursor
;
107 SwCallLink
aLk( *this ); // watch Cursor-Moves
108 bRet
= pCursor
->GoPrevCell();
110 UpdateCursor(); // update current cursor
115 static const SwFrame
* lcl_FindMostUpperCellFrame( const SwFrame
* pFrame
)
118 ( !pFrame
->IsCellFrame() ||
119 !pFrame
->GetUpper()->GetUpper()->IsTabFrame() ||
120 pFrame
->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
122 pFrame
= pFrame
->GetUpper();
127 bool SwCursorShell::SelTableRowOrCol( bool bRow
, bool bRowSimple
)
129 // check if the current cursor's SPoint/Mark are in a table
130 SwFrame
*pFrame
= GetCurrFrame();
131 if( !pFrame
|| !pFrame
->IsInTab() )
134 const SwTabFrame
* pTabFrame
= pFrame
->FindTabFrame();
135 const SwTabFrame
* pMasterTabFrame
= pTabFrame
->IsFollow() ? pTabFrame
->FindMaster( true ) : pTabFrame
;
136 const SwTable
* pTable
= pTabFrame
->GetTable();
138 CurrShell
aCurr( this );
140 const SwTableBox
* pStt
= nullptr;
141 const SwTableBox
* pEnd
= nullptr;
143 // search box based on layout
145 SwTableSearchType eType
= bRow
? SwTableSearchType::Row
: SwTableSearchType::Col
;
146 const bool bCheckProtected
= !IsReadOnlyAvailable();
148 if( bCheckProtected
)
149 eType
= static_cast<SwTableSearchType
>(eType
| SwTableSearchType::Protect
);
153 GetTableSel( *this, aBoxes
, eType
);
159 pEnd
= aBoxes
.back();
161 // #i32329# Enhanced table selection
162 else if ( pTable
->IsNewModel() )
164 const SwShellCursor
*pCursor
= GetCursor_();
165 SwTable::SearchType eSearchType
= bRow
? SwTable::SEARCH_ROW
: SwTable::SEARCH_COL
;
166 pTable
->CreateSelection( *pCursor
, aBoxes
, eSearchType
, bCheckProtected
);
171 pEnd
= aBoxes
.back();
173 m_eEnhancedTableSel
= eSearchType
;
177 const SwShellCursor
*pCursor
= GetCursor_();
178 const SwFrame
* pStartFrame
= pFrame
;
179 const SwContentNode
*pCNd
= pCursor
->GetMarkContentNode();
180 std::pair
<Point
, bool> const tmp(pCursor
->GetMkPos(), true);
181 const SwFrame
* pEndFrame
= pCNd
182 ? pCNd
->getLayoutFrame(GetLayout(), nullptr, &tmp
)
187 pStartFrame
= lcl_FindMostUpperCellFrame( pStartFrame
);
188 pEndFrame
= lcl_FindMostUpperCellFrame( pEndFrame
);
191 if ( !pStartFrame
|| !pEndFrame
)
194 const bool bVert
= pFrame
->ImplFindTabFrame()->IsVertical();
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();
204 GetTableSel( static_cast<const SwCellFrame
*>(pStartFrame
),
205 static_cast<const SwCellFrame
*>(pEndFrame
),
206 aBoxes
, bSelectUp
? nullptr : &aCells
, eType
);
208 if( aBoxes
.empty() || ( !bSelectUp
&& 4 != aCells
.size() ) )
214 pEnd
= aBoxes
.back();
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();
225 // if no table cursor exists, create one
226 if( !m_pTableCursor
)
228 m_pTableCursor
= new SwShellTableCursor( *this, *m_pCurrentCursor
->GetPoint() );
229 m_pCurrentCursor
->DeleteMark();
230 m_pCurrentCursor
->SwSelPaintRects::Hide();
233 m_pTableCursor
->DeleteMark();
235 // set start and end of a column
236 m_pTableCursor
->GetPoint()->Assign( *pEnd
->GetSttNd()->EndOfSectionNode() );
237 m_pTableCursor
->Move( fnMoveBackward
, GoInContent
);
238 m_pTableCursor
->SetMark();
239 m_pTableCursor
->GetPoint()->Assign( *pStt
->GetSttNd()->EndOfSectionNode() );
240 m_pTableCursor
->Move( fnMoveBackward
, GoInContent
);
242 // set PtPos 'close' to the reference table, otherwise we might get problems
243 // with the repeated headlines check in UpdateCursor():
245 m_pTableCursor
->GetPtPos() = pMasterTabFrame
->IsVertical()
246 ? pMasterTabFrame
->getFrameArea().TopRight()
247 : pMasterTabFrame
->getFrameArea().TopLeft();
253 bool SwCursorShell::SelTable()
255 // check if the current cursor's SPoint/Mark are in a table
256 SwFrame
*pFrame
= GetCurrFrame();
257 if( !pFrame
->IsInTab() )
260 const SwTabFrame
*pTableFrame
= pFrame
->ImplFindTabFrame();
261 const SwTabFrame
* pMasterTabFrame
= pTableFrame
->IsFollow() ? pTableFrame
->FindMaster( true ) : pTableFrame
;
262 const SwTableNode
* pTableNd
= pTableFrame
->GetTable()->GetTableNode();
264 CurrShell
aCurr( this );
266 if( !m_pTableCursor
)
268 m_pTableCursor
= new SwShellTableCursor( *this, *m_pCurrentCursor
->GetPoint() );
269 m_pCurrentCursor
->DeleteMark();
270 m_pCurrentCursor
->SwSelPaintRects::Hide();
273 m_pTableCursor
->DeleteMark();
274 m_pTableCursor
->GetPoint()->Assign( *pTableNd
);
275 m_pTableCursor
->Move( fnMoveForward
, GoInContent
);
276 m_pTableCursor
->SetMark();
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()->Assign( *pTableNd
->EndOfSectionNode() );
281 m_pTableCursor
->Move( fnMoveBackward
, GoInContent
);
286 bool SwCursorShell::SelTableBox()
288 // if we're in a table, create a table cursor, and select the cell
289 // that the current cursor's point resides in
291 // search for start node of our table box. If not found, exit really
292 const SwStartNode
* pStartNode
=
293 m_pCurrentCursor
->GetPoint()->GetNode().FindTableBoxStartNode();
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." );
303 if( pStartNode
== nullptr )
306 CurrShell
aCurr( this );
308 // create a table cursor, if there isn't one already
309 if( !m_pTableCursor
)
311 m_pTableCursor
= new SwShellTableCursor( *this, *m_pCurrentCursor
->GetPoint() );
312 m_pCurrentCursor
->DeleteMark();
313 m_pCurrentCursor
->SwSelPaintRects::Hide();
316 // select the complete box with our shiny new m_pTableCursor
317 // 1. delete mark, and move point to first content node in box
318 m_pTableCursor
->DeleteMark();
319 m_pTableCursor
->GetPoint()->Assign( *pStartNode
);
320 m_pTableCursor
->Move( fnMoveForward
, GoInNode
);
322 // 2. set mark, and move point to last content node in box
323 m_pTableCursor
->SetMark();
324 m_pTableCursor
->GetPoint()->Assign( *(pStartNode
->EndOfSectionNode()) );
325 m_pTableCursor
->Move( fnMoveBackward
, GoInNode
);
328 m_pTableCursor
->Exchange();
330 // with some luck, UpdateCursor() will now update everything that
337 // TODO: provide documentation
338 /** get the next non-protected cell inside a table
340 @param[in,out] rIdx is on a table node
341 @param bInReadOnly ???
343 @return <false> if no suitable cell could be found, otherwise <rIdx> points
344 to content in a suitable cell and <true> is returned.
346 static bool lcl_FindNextCell( SwNodeIndex
& rIdx
, bool bInReadOnly
)
348 // check protected cells
349 SwNodeIndex
aTmp( rIdx
, 2 ); // TableNode + StartNode
351 // the resulting cell should be in that table:
352 const SwTableNode
* pTableNd
= rIdx
.GetNode().GetTableNode();
356 OSL_FAIL( "lcl_FindNextCell not celled with table start node!" );
360 const SwNode
* pTableEndNode
= pTableNd
->EndOfSectionNode();
362 SwNodes
& rNds
= aTmp
.GetNode().GetNodes();
363 SwContentNode
* pCNd
= aTmp
.GetNode().GetContentNode();
365 // no content node => go to next content node
367 pCNd
= rNds
.GoNext( &aTmp
);
373 SwContentFrame
* pFrame
= pCNd
->getLayoutFrame( pCNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
375 if ( nullptr == pFrame
|| pCNd
->FindTableNode() != pTableNd
||
376 (!bInReadOnly
&& pFrame
->IsProtected() ) )
378 // we are not located inside a 'valid' cell. We have to continue searching...
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 );
384 // loop to find a suitable cell...
387 SwNode
* pNd
= &aTmp
.GetNode();
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() )
395 // ok, get the next content node:
396 pCNd
= aTmp
.GetNode().GetContentNode();
397 if( nullptr == pCNd
)
398 pCNd
= rNds
.GoNext( &aTmp
);
404 // check if we have found a suitable table cell:
405 pFrame
= pCNd
->getLayoutFrame( pCNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
407 if ( nullptr != pFrame
&& pCNd
->FindTableNode() == pTableNd
&&
408 (bInReadOnly
|| !pFrame
->IsProtected() ) )
410 // finally, we have found a suitable table cell => set index and return
415 // continue behind the current section:
416 aTmp
.Assign( *pCNd
->EndOfSectionNode(), +1 );
423 /// see lcl_FindNextCell()
424 static bool lcl_FindPrevCell( SwNodeIndex
& rIdx
, bool bInReadOnly
)
426 SwNodeIndex
aTmp( rIdx
, -2 ); // TableNode + EndNode
428 const SwNode
* pTableEndNode
= &rIdx
.GetNode();
429 const SwTableNode
* pTableNd
= pTableEndNode
->StartOfSectionNode()->GetTableNode();
433 OSL_FAIL( "lcl_FindPrevCell not celled with table start node!" );
437 SwContentNode
* pCNd
= aTmp
.GetNode().GetContentNode();
440 pCNd
= SwNodes::GoPrevious( &aTmp
);
445 SwContentFrame
* pFrame
= pCNd
->getLayoutFrame( pCNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
447 if( nullptr == pFrame
|| pCNd
->FindTableNode() != pTableNd
||
448 (!bInReadOnly
&& pFrame
->IsProtected() ))
450 // skip before current section
451 aTmp
.Assign( *pCNd
->StartOfSectionNode(), -1 );
454 SwNode
* pNd
= &aTmp
.GetNode();
456 if( pNd
== pTableNd
|| pNd
->GetIndex() < pTableNd
->GetIndex() )
459 pCNd
= aTmp
.GetNode().GetContentNode();
460 if( nullptr == pCNd
)
461 pCNd
= SwNodes::GoPrevious( &aTmp
);
466 pFrame
= pCNd
->getLayoutFrame( pCNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
468 if( nullptr != pFrame
&& pCNd
->FindTableNode() == pTableNd
&&
469 (bInReadOnly
|| !pFrame
->IsProtected() ) )
472 return true; // ok, not protected
474 aTmp
.Assign( *pCNd
->StartOfSectionNode(), -1 );
481 bool GotoPrevTable( SwPaM
& rCurrentCursor
, SwMoveFnCollection
const & fnPosTable
,
484 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty
);
486 SwNodeIndex
aIdx( rCurrentCursor
.GetPoint()->GetNode() );
488 SwTableNode
* pTableNd
= aIdx
.GetNode().FindTableNode();
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()) )
499 if( pInnerTableNd
== pTableNd
)
500 aIdx
.Assign( *pTableNd
, -1 );
503 SwNodeIndex aOldIdx
= aIdx
;
504 SwNodeOffset
nLastNd(rCurrentCursor
.GetDoc().GetNodes().Count() - 1);
506 while( aIdx
.GetIndex() &&
507 nullptr == ( pTableNd
= aIdx
.GetNode().StartOfSectionNode()->GetTableNode()) )
510 if ( aIdx
== aOldIdx
)
512 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound
);
517 if ( !aIdx
.GetIndex() )
519 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped
);
525 if( &fnPosTable
== &fnMoveForward
) // at the beginning?
527 aIdx
= *aIdx
.GetNode().StartOfSectionNode();
528 if( !lcl_FindNextCell( aIdx
, bInReadOnly
))
531 aIdx
.Assign( *pTableNd
, -1 );
537 // check protected cells
538 if( !lcl_FindNextCell( aIdx
, bInReadOnly
))
541 aIdx
.Assign( *pTableNd
, -1 );
546 SwTextNode
* pTextNode
= aIdx
.GetNode().GetTextNode();
549 rCurrentCursor
.GetPoint()->Assign(*pTextNode
, &fnPosTable
== &fnMoveBackward
?
560 bool GotoNextTable( SwPaM
& rCurrentCursor
, SwMoveFnCollection
const & fnPosTable
,
563 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty
);
565 SwNodeIndex
aIdx( rCurrentCursor
.GetPoint()->GetNode() );
566 SwTableNode
* pTableNd
= aIdx
.GetNode().FindTableNode();
569 aIdx
.Assign( *pTableNd
->EndOfSectionNode(), 1 );
571 SwNodeIndex aOldIdx
= aIdx
;
572 SwNodeOffset
nLastNd(rCurrentCursor
.GetDoc().GetNodes().Count() - 1);
574 while( aIdx
.GetIndex() < nLastNd
&&
575 nullptr == ( pTableNd
= aIdx
.GetNode().GetTableNode()) )
578 if ( aIdx
== aOldIdx
)
580 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound
);
585 if ( aIdx
.GetIndex() == nLastNd
)
587 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped
);
588 aIdx
= SwNodeOffset(0);
592 assert( pTableNd
); // coverity, should never be nullptr
594 if( &fnPosTable
== &fnMoveForward
) // at the beginning?
596 if( !lcl_FindNextCell( aIdx
, bInReadOnly
))
599 aIdx
.Assign( *pTableNd
->EndOfSectionNode(), + 1 );
605 aIdx
= *aIdx
.GetNode().EndOfSectionNode();
606 // check protected cells
607 if( !lcl_FindNextCell( aIdx
, bInReadOnly
))
610 aIdx
.Assign( *pTableNd
->EndOfSectionNode(), + 1 );
615 SwTextNode
* pTextNode
= aIdx
.GetNode().GetTextNode();
618 rCurrentCursor
.GetPoint()->Assign(*pTextNode
, &fnPosTable
== &fnMoveBackward
?
626 // the flow is such that it is not possible to get there
631 bool GotoCurrTable( SwPaM
& rCurrentCursor
, SwMoveFnCollection
const & fnPosTable
,
634 SwTableNode
* pTableNd
= rCurrentCursor
.GetPoint()->GetNode().FindTableNode();
638 SwTextNode
* pTextNode
= nullptr;
639 if( &fnPosTable
== &fnMoveBackward
) // to the end of the table
641 SwNodeIndex
aIdx( *pTableNd
->EndOfSectionNode() );
642 if( !lcl_FindPrevCell( aIdx
, bInReadOnly
))
644 pTextNode
= aIdx
.GetNode().GetTextNode();
648 SwNodeIndex
aIdx( *pTableNd
);
649 if( !lcl_FindNextCell( aIdx
, bInReadOnly
))
651 pTextNode
= aIdx
.GetNode().GetTextNode();
656 rCurrentCursor
.GetPoint()->Assign(*pTextNode
, &fnPosTable
== &fnMoveBackward
?
664 bool SwCursor::MoveTable( SwWhichTable fnWhichTable
, SwMoveFnCollection
const & fnPosTable
)
667 SwTableCursor
* pTableCursor
= dynamic_cast<SwTableCursor
*>(this);
669 if( pTableCursor
|| !HasMark() )
671 SwCursorSaveState
aSaveState( *this );
672 bRet
= (*fnWhichTable
)( *this, fnPosTable
, IsReadOnlyAvailable() ) &&
673 !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection
|
674 SwCursorSelOverFlags::Toggle
);
679 bool SwCursorShell::MoveTable( SwWhichTable fnWhichTable
, SwMoveFnCollection
const & fnPosTable
)
681 SwCallLink
aLk( *this ); // watch Cursor-Moves; call Link if needed
683 SwShellCursor
* pCursor
= m_pTableCursor
? m_pTableCursor
: m_pCurrentCursor
;
686 SwNodeOffset
nPtNd(0);
687 sal_Int32 nPtCnt
= 0;
689 if ( !m_pTableCursor
&& m_pCurrentCursor
->HasMark() )
691 // switch to table mode
692 m_pTableCursor
= new SwShellTableCursor( *this, *m_pCurrentCursor
->GetPoint() );
693 m_pCurrentCursor
->DeleteMark();
694 m_pCurrentCursor
->SwSelPaintRects::Hide();
695 m_pTableCursor
->SetMark();
696 pCursor
= m_pTableCursor
;
702 nPtNd
= pCursor
->GetPoint()->GetNodeIndex();
703 nPtCnt
= pCursor
->GetPoint()->GetContentIndex();
706 bRet
= pCursor
->MoveTable( fnWhichTable
, fnPosTable
);
710 // #i45028# - set "top" position for repeated headline rows
711 pCursor
->GetPtPos() = Point();
713 UpdateCursor(SwCursorShell::SCROLLWIN
|SwCursorShell::CHKRANGE
|SwCursorShell::READONLY
);
716 pCursor
->GetPoint()->GetNodeIndex() == nPtNd
&&
717 pCursor
->GetPoint()->GetContentIndex() == nPtCnt
)
723 bool SwCursorShell::IsTableComplexForChart()
727 // Here we may trigger table formatting so we better do that inside an action
729 const SwTableNode
* pTNd
= m_pCurrentCursor
->GetPoint()->GetNode().FindTableNode();
732 // in a table; check if table or section is balanced
736 bRet
= pTNd
->GetTable().IsTableComplexForChart( sSel
);
743 OUString
SwCursorShell::GetBoxNms() const
746 const SwPosition
* pPos
;
751 SwContentNode
*pCNd
= m_pTableCursor
->Start()->GetNode().GetContentNode();
752 pFrame
= pCNd
? pCNd
->getLayoutFrame( GetLayout() ) : nullptr;
757 pFrame
= pFrame
->GetUpper();
758 } while ( pFrame
&& !pFrame
->IsCellFrame() );
760 OSL_ENSURE( pFrame
, "no frame for this box" );
765 sNm
= static_cast<SwCellFrame
*>(pFrame
)->GetTabBox()->GetName() + ":";
766 pPos
= m_pTableCursor
->End();
770 const SwTableNode
* pTableNd
= IsCursorInTable();
773 pPos
= GetCursor()->GetPoint();
776 SwContentNode
* pCNd
= pPos
->GetNode().GetContentNode();
777 pFrame
= pCNd
? pCNd
->getLayoutFrame( GetLayout() ) : nullptr;
782 pFrame
= pFrame
->GetUpper();
783 } while ( pFrame
&& !pFrame
->IsCellFrame() );
786 sNm
+= static_cast<SwCellFrame
*>(pFrame
)->GetTabBox()->GetName();
791 bool SwCursorShell::GotoTable( const OUString
& rName
)
793 SwCallLink
aLk( *this ); // watch Cursor-Moves
794 bool bRet
= !m_pTableCursor
&& m_pCurrentCursor
->GotoTable( rName
);
797 m_pCurrentCursor
->GetPtPos() = Point();
798 UpdateCursor( SwCursorShell::SCROLLWIN
| SwCursorShell::CHKRANGE
|
799 SwCursorShell::READONLY
);
804 bool SwCursorShell::CheckTableBoxContent( const SwPosition
* pPos
)
806 if( !m_pBoxIdx
|| !m_pBoxPtr
|| IsSelTableCells() || !IsAutoUpdateCells() )
809 // check if box content is consistent with given box format, reset if not
810 SwTableBox
* pChkBox
= nullptr;
811 SwStartNode
* pSttNd
= nullptr;
814 // get stored position
815 if (nullptr != (pSttNd
= m_pBoxIdx
->GetNode().GetStartNode()) &&
816 SwTableBoxStartNode
== pSttNd
->GetStartNodeType() &&
817 m_pBoxPtr
== pSttNd
->FindTableNode()->GetTable().
818 GetTableBox( m_pBoxIdx
->GetIndex() ) )
823 pSttNd
= pPos
->GetNode().FindSttNodeByType( SwTableBoxStartNode
);
825 pChkBox
= pSttNd
->FindTableNode()->GetTable().GetTableBox( pSttNd
->GetIndex() );
828 // box has more than one paragraph
829 if( pChkBox
&& pSttNd
->GetIndex() + SwNodeOffset(2) != pSttNd
->EndOfSectionIndex() )
832 // destroy pointer before next action starts
833 if( !pPos
&& !pChkBox
)
834 ClearTableBoxContent();
836 // cursor not anymore in this section?
837 if( pChkBox
&& !pPos
&&
838 ( m_pCurrentCursor
->HasMark() || m_pCurrentCursor
->GetNext() != m_pCurrentCursor
||
839 pSttNd
->GetIndex() + 1 == m_pCurrentCursor
->GetPoint()->GetNodeIndex() ))
842 // Did the content of a box change at all? This is important if e.g. Undo
843 // could not restore the content properly.
846 const SwTextNode
* pNd
= GetDoc()->GetNodes()[
847 pSttNd
->GetIndex() + 1 ]->GetTextNode();
849 ( pNd
->GetText() == SwViewShell::GetShellRes()->aCalc_Error
&&
850 SfxItemState::SET
== pChkBox
->GetFrameFormat()->
851 GetItemState( RES_BOXATR_FORMULA
)) )
857 // destroy pointer before next action starts
858 ClearTableBoxContent();
860 GetDoc()->ChkBoxNumFormat( *pChkBox
, true );
864 return nullptr != pChkBox
;
867 void SwCursorShell::SaveTableBoxContent( const SwPosition
* pPos
)
869 if( IsSelTableCells() || !IsAutoUpdateCells() )
873 pPos
= m_pCurrentCursor
->GetPoint();
875 SwStartNode
* pSttNd
= pPos
->GetNode().FindSttNodeByType( SwTableBoxStartNode
);
877 bool bCheckBox
= false;
878 if( pSttNd
&& m_pBoxIdx
)
880 if( pSttNd
== &m_pBoxIdx
->GetNode() )
886 bCheckBox
= nullptr != m_pBoxIdx
;
891 SwPosition
aPos( *m_pBoxIdx
);
892 CheckTableBoxContent( &aPos
);
897 m_pBoxPtr
= pSttNd
->FindTableNode()->GetTable().GetTableBox( pSttNd
->GetIndex() );
900 *m_pBoxIdx
= *pSttNd
;
902 m_pBoxIdx
= new SwNodeIndex( *pSttNd
);
906 void SwCursorShell::ClearTableBoxContent()
913 bool SwCursorShell::EndAllTableBoxEdit()
916 for(SwViewShell
& rSh
: GetRingContainer())
918 if( auto pCursorShell
= dynamic_cast<SwCursorShell
*>(&rSh
) )
919 bRet
|= pCursorShell
->CheckTableBoxContent(
920 pCursorShell
->m_pCurrentCursor
->GetPoint() );
926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */