/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// Check if we have to move the cursor to a covered cell before // proceeding: const SwNode* pTableBoxStartNode = pCursor->GetPointNode().FindTableBoxStartNode(); const SwTableBox* pTableBox = nullptr;
// if there is another StartNode after the EndNode of a cell then // there is another cell if( !aCellStt.GetNode().IsStartNode() )
{ if( pCursor->HasMark() || !bAppendLine )
bRet = false; elseif (pTableNd)
{ // if there is no list anymore then create new one if ( !pTableBox )
pTableBox = pTableNd->GetTable().GetTableBox(
pCursor->GetPoint()->GetNode().
StartOfSectionIndex() );
OSL_ENSURE( pTableBox, "Box is not in this table" );
SwSelBoxes aBoxes;
// the document might change; w/o Action views would not be notified static_cast<SwEditShell*>(this)->StartAllAction();
bRet = mxDoc->InsertRow( SwTable::SelLineFromBox( pTableBox, aBoxes, false )); static_cast<SwEditShell*>(this)->EndAllAction();
}
}
bRet = bRet && pCursor->GoNextCell(); if( bRet )
UpdateCursor();
} return bRet;
}
bool SwCursorShell::SelTableRowOrCol( bool bRow, bool bRowSimple )
{ // check if the current cursor's SPoint/Mark are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame || !pFrame->IsInTab() ) returnfalse;
// If we select upwards it is sufficient to set pStart and pEnd // to the first resp. last box of the selection obtained from // GetTableSel. However, selecting downwards requires the frames // located at the corners of the selection. This does not work // for column selections in vertical tables: constbool bSelectUp = ( bVert && !bRow ) ||
*pCursor->GetPoint() <= *pCursor->GetMark();
SwCellFrames aCells;
GetTableSel( static_cast<const SwCellFrame*>(pStartFrame), static_cast<const SwCellFrame*>(pEndFrame),
aBoxes, bSelectUp ? nullptr : &aCells, eType );
if ( bSelectUp )
{
pStart = aBoxes[0];
pEnd = aBoxes.back();
} else
{ // will become point of table cursor
pStart = aCells[bVert ? 0 : (bRow ? 2 : 1)]->GetTabBox(); // will become mark of table cursor
pEnd = aCells[bVert ? 3 : (bRow ? 1 : 2)]->GetTabBox();
}
}
// if no table cursor exists, create one if( !m_pTableCursor )
{
m_pTableCursor = new SwShellTableCursor( *this, *m_pCurrentCursor->GetPoint() );
m_pCurrentCursor->DeleteMark();
m_pCurrentCursor->SwSelPaintRects::Hide();
}
m_pTableCursor->DeleteMark();
// set start and end of a column
m_pTableCursor->GetPoint()->Assign( *pEnd->GetSttNd()->EndOfSectionNode() );
m_pTableCursor->Move( fnMoveBackward, GoInContent );
m_pTableCursor->SetMark();
m_pTableCursor->GetPoint()->Assign( *pStart->GetSttNd()->EndOfSectionNode() );
m_pTableCursor->Move( fnMoveBackward, GoInContent );
// set PtPos 'close' to the reference table, otherwise we might get problems // with the repeated headlines check in UpdateCursor(): if ( !bRow )
m_pTableCursor->GetPtPos() = pMasterTabFrame->IsVertical()
? pMasterTabFrame->getFrameArea().TopRight()
: pMasterTabFrame->getFrameArea().TopLeft();
UpdateCursor(); returntrue;
}
bool SwCursorShell::SelTable()
{ // check if the current cursor's SPoint/Mark are in a table
SwFrame *pFrame = GetCurrFrame(); if( !pFrame->IsInTab() ) returnfalse;
m_pTableCursor->DeleteMark();
m_pTableCursor->GetPoint()->Assign( *pTableNd );
m_pTableCursor->Move( fnMoveForward, GoInContent );
m_pTableCursor->SetMark(); // set MkPos 'close' to the master table, otherwise we might get problems // with the repeated headlines check in UpdateCursor():
m_pTableCursor->GetMkPos() = pMasterTabFrame->IsVertical() ? pMasterTabFrame->getFrameArea().TopRight() : pMasterTabFrame->getFrameArea().TopLeft();
m_pTableCursor->GetPoint()->Assign( *pTableNd->EndOfSectionNode() );
m_pTableCursor->Move( fnMoveBackward, GoInContent );
UpdateCursor(); returntrue;
}
bool SwCursorShell::SelTableBox()
{ // if we're in a table, create a table cursor, and select the cell // that the current cursor's point resides in
// search for start node of our table box. If not found, exit really const SwStartNode* pStartNode =
m_pCurrentCursor->GetPoint()->GetNode().FindTableBoxStartNode();
#if OSL_DEBUG_LEVEL > 0 // the old code checks whether we're in a table by asking the // frame. This should yield the same result as searching for the // table box start node, right?
SwFrame *pFrame = GetCurrFrame();
OSL_ENSURE( !pFrame->IsInTab() == !(pStartNode != nullptr), "Schroedinger's table: We're in a box, and also we aren't." ); #endif if( pStartNode == nullptr ) returnfalse;
CurrShell aCurr( this );
// create a table cursor, if there isn't one already if( !m_pTableCursor )
{
m_pTableCursor = new SwShellTableCursor( *this, *m_pCurrentCursor->GetPoint() );
m_pCurrentCursor->DeleteMark();
m_pCurrentCursor->SwSelPaintRects::Hide();
}
// select the complete box with our shiny new m_pTableCursor // 1. delete mark, and move point to first content node in box
m_pTableCursor->DeleteMark();
m_pTableCursor->GetPoint()->Assign( *pStartNode );
m_pTableCursor->Move( fnMoveForward, GoInNode );
// 2. set mark, and move point to last content node in box
m_pTableCursor->SetMark();
m_pTableCursor->GetPoint()->Assign( *(pStartNode->EndOfSectionNode()) );
m_pTableCursor->Move( fnMoveBackward, GoInNode );
// 3. exchange
m_pTableCursor->Exchange();
// with some luck, UpdateCursor() will now update everything that // needs updating
UpdateCursor();
returntrue;
}
// TODO: provide documentation /** get the next non-protected cell inside a table
@param[in,out] rIdx is on a table node @param bInReadOnly ???
@return <false> if no suitable cell could be found, otherwise <rIdx> points to content in a suitable cell and <true> is returned.
*/ staticbool lcl_FindNextCell( SwNodeIndex& rIdx, bool bInReadOnly )
{ // check protected cells
SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
// the resulting cell should be in that table: const SwTableNode* pTableNd = rIdx.GetNode().GetTableNode();
if ( !pTableNd )
{
OSL_FAIL( "lcl_FindNextCell not celled with table start node!" ); returnfalse;
}
if ( nullptr == pFrame || pCNd->FindTableNode() != pTableNd ||
(!bInReadOnly && pFrame->IsProtected() ) )
{ // we are not located inside a 'valid' cell. We have to continue searching...
// skip behind current section. This might be the end of the table cell // or behind an inner section or...
aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
// loop to find a suitable cell... for( ;; )
{
SwNode* pNd = &aTmp.GetNode();
// we break this loop if we reached the end of the table. // to make this code even more robust, we also break if we are // already behind the table end node: if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() ) returnfalse;
// ok, get the next content node:
pCNd = aTmp.GetNode().GetContentNode(); if( nullptr == pCNd )
pCNd = SwNodes::GoNext(&aTmp);
// robust: if ( !pCNd ) returnfalse;
// check if we have found a suitable table cell:
pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
if ( nullptr != pFrame && pCNd->FindTableNode() == pTableNd &&
(bInReadOnly || !pFrame->IsProtected() ) )
{ // finally, we have found a suitable table cell => set index and return
rIdx = *pCNd; returntrue;
}
// continue behind the current section:
aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
}
}
rIdx = *pCNd; returntrue;
}
SwTableNode* pTableNd = aIdx.GetNode().FindTableNode(); if( pTableNd )
{ // #i26532#: If we are inside a table, we may not go backward to the // table start node, because we would miss any tables inside this table.
SwTableNode* pInnerTableNd = nullptr;
SwNodeIndex aTmpIdx( aIdx ); while( aTmpIdx.GetIndex() &&
nullptr == ( pInnerTableNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
--aTmpIdx;
// Here we may trigger table formatting so we better do that inside an action
StartAction(); const SwTableNode* pTNd = m_pCurrentCursor->GetPoint()->GetNode().FindTableNode(); if( pTNd )
{ // in a table; check if table or section is balanced
OUString sSel; if( m_pTableCursor )
sSel = GetBoxNms();
bRet = pTNd->GetTable().IsTableComplexForChart( sSel );
}
EndAction();
// check if box content is consistent with given box format, reset if not
SwTableBox* pChkBox = nullptr;
SwStartNode* pSttNd = nullptr; if( !pPos )
{ // get stored position if (nullptr != (pSttNd = m_pBoxIdx->GetNode().GetStartNode()) &&
SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
m_pBoxPtr == pSttNd->FindTableNode()->GetTable().
GetTableBox( m_pBoxIdx->GetIndex() ) )
pChkBox = m_pBoxPtr;
} else
{
pSttNd = pPos->GetNode().FindStartNodeByType( SwTableBoxStartNode ); if( pSttNd)
pChkBox = pSttNd->FindTableNode()->GetTable().GetTableBox( pSttNd->GetIndex() );
}
// box has more than one paragraph if (pChkBox && pSttNd->GetIndex() + SwNodeOffset(2) != pSttNd->EndOfSectionIndex())
{
ClearTableBoxContent();
StartAction();
GetDoc()->ChkBoxNumFormat( *pChkBox, true );
EndAction();
pChkBox = nullptr;
}
// destroy pointer before next action starts if( !pPos && !pChkBox )
ClearTableBoxContent();
// cursor not anymore in this section? if( pChkBox && !pPos &&
( m_pCurrentCursor->HasMark() || m_pCurrentCursor->GetNext() != m_pCurrentCursor ||
pSttNd->GetIndex() + 1 == m_pCurrentCursor->GetPoint()->GetNodeIndex() ))
pChkBox = nullptr;
// Did the content of a box change at all? This is important if e.g. Undo // could not restore the content properly. if( pChkBox )
{ const SwTextNode* pNd = GetDoc()->GetNodes()[
pSttNd->GetIndex() + 1 ]->GetTextNode(); if( !pNd ||
( pNd->GetText() == SwViewShell::GetShellRes()->aCalc_Error &&
SfxItemState::SET == pChkBox->GetFrameFormat()->
GetItemState( RES_BOXATR_FORMULA )) )
pChkBox = nullptr;
}
if( pChkBox )
{ // destroy pointer before next action starts
ClearTableBoxContent();
StartAction();
GetDoc()->ChkBoxNumFormat( *pChkBox, true );
EndAction();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.