diff options
Diffstat (limited to 'sw/source/core/crsr/trvltbl.cxx')
-rw-r--r-- | sw/source/core/crsr/trvltbl.cxx | 931 |
1 files changed, 931 insertions, 0 deletions
diff --git a/sw/source/core/crsr/trvltbl.cxx b/sw/source/core/crsr/trvltbl.cxx new file mode 100644 index 000000000000..d9a887e61ad9 --- /dev/null +++ b/sw/source/core/crsr/trvltbl.cxx @@ -0,0 +1,931 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <hintids.hxx> + +#include <vcl/svapp.hxx> +#include <editeng/protitem.hxx> +#include <crsrsh.hxx> +#include <doc.hxx> +#include <cntfrm.hxx> +#include <editsh.hxx> //EndAllAction gibts nur an der EditShell +#include <pam.hxx> +#include <swtable.hxx> +#include <docary.hxx> +#include <frmatr.hxx> +#include <frmfmt.hxx> +#include <viscrs.hxx> +#include <callnk.hxx> +#include <tabfrm.hxx> +#include <ndtxt.hxx> +#include <shellres.hxx> +#include <cellatr.hxx> +#include <cellfrm.hxx> +#include <rowfrm.hxx> + + +// setze Crsr in die naechsten/vorherigen Celle +BOOL SwCrsrShell::GoNextCell( BOOL bAppendLine ) +{ + BOOL bRet = FALSE; + const SwTableNode* pTblNd = 0; + + if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() )) + { + SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; + SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, + bRet = TRUE; + + // Check if we have to move the cursor to a covered cell before + // proceeding: + const SwNode* pTableBoxStartNode = pCrsr->GetNode()->FindTableBoxStartNode(); + const SwTableBox* pTableBox = 0; + + if ( pCrsr->GetCrsrRowSpanOffset() ) + { + pTableBox = pTableBoxStartNode->GetTblBox(); + if ( pTableBox->getRowSpan() > 1 ) + { + if ( !pTblNd ) + pTblNd = IsCrsrInTbl(); + pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), + (USHORT)(pTableBox->getRowSpan() + pCrsr->GetCrsrRowSpanOffset() ) ); + pTableBoxStartNode = pTableBox->GetSttNd(); + } + } + + SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 ); + + // folgt nach dem EndNode der Cell ein weiterer StartNode, dann + // gibt es auch eine naechste Celle + + if( !aCellStt.GetNode().IsStartNode() ) + { + if( pCrsr->HasMark() || !bAppendLine ) + bRet = FALSE; + else + { + // auf besonderen Wunsch: keine Line mehr vorhanden, dann + // mache doch eine neue: + if ( !pTableBox ) + pTableBox = pTblNd->GetTable().GetTblBox( + pCrsr->GetPoint()->nNode.GetNode(). + StartOfSectionIndex() ); + + ASSERT( pTableBox, "Box steht nicht in dieser Tabelle" ); + SwSelBoxes aBoxes; + + //Das Dokument veraendert sich evtl. ohne Action wuerden die Sichten + //nichts mitbekommen. + ((SwEditShell*)this)->StartAllAction(); + bRet = pDoc->InsertRow( pTblNd->GetTable(). + SelLineFromBox( pTableBox, aBoxes, FALSE )); + ((SwEditShell*)this)->EndAllAction(); + } + } + if( bRet && 0 != ( bRet = pCrsr->GoNextCell() )) + UpdateCrsr(); // und den akt. Updaten + } + return bRet; +} + + +BOOL SwCrsrShell::GoPrevCell() +{ + BOOL bRet = FALSE; + const SwTableNode* pTblNd; + if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() )) + { + SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; + SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, + bRet = pCrsr->GoPrevCell(); + if( bRet ) + UpdateCrsr(); // und den akt. Updaten + } + return bRet; +} + +const SwFrm* lcl_FindMostUpperCellFrm( const SwFrm* pFrm ) +{ + while ( pFrm && + ( !pFrm->IsCellFrm() || + !pFrm->GetUpper()->GetUpper()->IsTabFrm() || + pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) ) + { + pFrm = pFrm->GetUpper(); + } + return pFrm; +} + +BOOL SwCrsrShell::_SelTblRowOrCol( bool bRow, bool bRowSimple ) +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm->IsInTab() ) + return FALSE; + + const SwTabFrm* pTabFrm = pFrm->FindTabFrm(); + const SwTabFrm* pMasterTabFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm; + const SwTable* pTable = pTabFrm->GetTable(); + + SET_CURR_SHELL( this ); + + const SwTableBox* pStt = 0; + const SwTableBox* pEnd = 0; + + // lasse ueber das Layout die Boxen suchen + SwSelBoxes aBoxes; + SwTblSearchType eType = bRow ? nsSwTblSearchType::TBLSEARCH_ROW : nsSwTblSearchType::TBLSEARCH_COL; + const bool bCheckProtected = !IsReadOnlyAvailable(); + + if( bCheckProtected ) + eType = (SwTblSearchType)(eType | nsSwTblSearchType::TBLSEARCH_PROTECT); + + if ( !bRowSimple ) + { + GetTblSel( *this, aBoxes, eType ); + + if( !aBoxes.Count() ) + return FALSE; + + pStt = aBoxes[0]; + pEnd = aBoxes[aBoxes.Count() - 1]; + } + // --> FME 2004-07-30 #i32329# Enhanced table selection + else if ( pTable->IsNewModel() ) + { + const SwShellCrsr *pCrsr = _GetCrsr(); + SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL; + pTable->CreateSelection( *pCrsr, aBoxes, eSearchType, bCheckProtected ); + if( !aBoxes.Count() ) + return FALSE; + + pStt = aBoxes[0]; + pEnd = aBoxes[aBoxes.Count() - 1]; + } + else + { + const SwShellCrsr *pCrsr = _GetCrsr(); + const SwFrm* pStartFrm = pFrm; + const SwCntntNode *pCNd = pCrsr->GetCntntNode( FALSE ); + const SwFrm* pEndFrm = pCNd ? pCNd->GetFrm( &pCrsr->GetMkPos() ) : 0; + + if ( bRow ) + { + pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm ); + pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm ); + } + + if ( !pStartFrm || !pEndFrm ) + return FALSE; + + const bool bVert = pFrm->ImplFindTabFrm()->IsVertical(); + + // If we select upwards it is sufficient to set pStt and pEnd + // to the first resp. last box of the selection obtained from + // GetTblSel. However, selecting downwards requires the frames + // located at the corners of the selection. This does not work + // for column selections in vertical tables: + const bool bSelectUp = ( bVert && !bRow ) || + *pCrsr->GetPoint() <= *pCrsr->GetMark(); + SwCellFrms aCells; + GetTblSel( static_cast<const SwCellFrm*>(pStartFrm), + static_cast<const SwCellFrm*>(pEndFrm), + aBoxes, bSelectUp ? 0 : &aCells, eType ); + + if( !aBoxes.Count() || ( !bSelectUp && 4 != aCells.Count() ) ) + return FALSE; + + if ( bSelectUp ) + { + pStt = aBoxes[0]; + pEnd = aBoxes[aBoxes.Count() - 1]; + } + else + { + pStt = aCells[ bVert ? (bRow ? 0 : 3) : (bRow ? 2 : 1) ]->GetTabBox(); // will become point of table cursor + pEnd = aCells[ bVert ? (bRow ? 3 : 0) : (bRow ? 1 : 2) ]->GetTabBox(); // will become mark of table cursor + } + } + // <-- + + // noch kein Tabellen-Cursor vorhanden, dann erzeuge einen + if( !pTblCrsr ) + { + pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); + pCurCrsr->DeleteMark(); + pCurCrsr->SwSelPaintRects::Hide(); + } + + pTblCrsr->DeleteMark(); + + // dann setze mal Anfang und Ende der Spalte + pTblCrsr->GetPoint()->nNode = *pEnd->GetSttNd(); + pTblCrsr->Move( fnMoveForward, fnGoCntnt ); + pTblCrsr->SetMark(); + pTblCrsr->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode(); + pTblCrsr->Move( fnMoveBackward, fnGoCntnt ); + + // set PtPos 'close' to the reference table, otherwise we might get problems with the + // repeated headlines check in UpdateCrsr(): + if ( !bRow ) + pTblCrsr->GetPtPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft(); + + UpdateCrsr(); // und den akt. Updaten + return TRUE; +} + +BOOL SwCrsrShell::SelTbl() +{ + // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen + SwFrm *pFrm = GetCurrFrm(); + if( !pFrm->IsInTab() ) + return FALSE; + + const SwTabFrm *pTblFrm = pFrm->ImplFindTabFrm(); + const SwTabFrm* pMasterTabFrm = pTblFrm->IsFollow() ? pTblFrm->FindMaster( true ) : pTblFrm; + const SwTableNode* pTblNd = pTblFrm->GetTable()->GetTableNode(); + + SET_CURR_SHELL( this ); + + if( !pTblCrsr ) + { + pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); + pCurCrsr->DeleteMark(); + pCurCrsr->SwSelPaintRects::Hide(); + } + + pTblCrsr->DeleteMark(); + pTblCrsr->GetPoint()->nNode = *pTblNd; + pTblCrsr->Move( fnMoveForward, fnGoCntnt ); + pTblCrsr->SetMark(); + // set MkPos 'close' to the master table, otherwise we might get problems with the + // repeated headlines check in UpdateCrsr(): + pTblCrsr->GetMkPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft(); + pTblCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode(); + pTblCrsr->Move( fnMoveBackward, fnGoCntnt ); + UpdateCrsr(); // und den akt. Updaten + return TRUE; +} + + +BOOL SwCrsrShell::SelTblBox() +{ + // 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 realy + const SwStartNode* pStartNode = + pCurCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode(); + +#ifdef DBG_UTIL + // 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? + SwFrm *pFrm = GetCurrFrm(); + DBG_ASSERT( !pFrm->IsInTab() == !(pStartNode != NULL), + "Schroedinger's table: We're in a box, and also we aren't." ); +#endif + + if( pStartNode == NULL ) + return FALSE; + + + SET_CURR_SHELL( this ); + + // create a table cursor, if there isn't one already + if( !pTblCrsr ) + { + pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); + pCurCrsr->DeleteMark(); + pCurCrsr->SwSelPaintRects::Hide(); + } + + // select the complete box with our shiny new pTblCrsr + // 1. delete mark, and move point to first content node in box + // 2. set mark, and move point to last content node in box + // 3. exchange + + pTblCrsr->DeleteMark(); + *(pTblCrsr->GetPoint()) = SwPosition( *pStartNode ); + pTblCrsr->Move( fnMoveForward, fnGoNode ); + + pTblCrsr->SetMark(); + *(pTblCrsr->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) ); + pTblCrsr->Move( fnMoveBackward, fnGoNode ); + + pTblCrsr->Exchange(); + + // with some luck, UpdateCrsr() will now update everything that + // needs updateing + UpdateCrsr(); + + return TRUE; +} + +// return the next non-protected cell inside a table +// rIdx - is on a table node +// return: +// true - Idx points to content in a suitable cell +// false - could not find a suitable cell +bool lcl_FindNextCell( SwNodeIndex& rIdx, BOOL bInReadOnly ) +{ + // ueberpruefe geschuetzte Zellen + SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode + + // the resulting cell should be in that table: + const SwTableNode* pTblNd = rIdx.GetNode().GetTableNode(); + + if ( !pTblNd ) + { + ASSERT( false, "lcl_FindNextCell not celled with table start node!" ) + return false; + } + + const SwNode* pTableEndNode = pTblNd->EndOfSectionNode(); + + SwNodes& rNds = aTmp.GetNode().GetNodes(); + SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode(); + + // no content node => go to next content node + if( !pCNd ) + pCNd = rNds.GoNext( &aTmp ); + + // robust + if ( !pCNd ) + return false; + + SwCntntFrm* pFrm = pCNd->GetFrm(); + + if ( 0 == pFrm || pCNd->FindTableNode() != pTblNd || + (!bInReadOnly && pFrm->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 a inner section or or 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() ) + return false; + + // ok, get the next content node: + pCNd = aTmp.GetNode().GetCntntNode(); + if( 0 == pCNd ) + pCNd = rNds.GoNext( &aTmp ); + + // robust: + if ( !pCNd ) + return false; + + // check if we have found a suitable table cell: + pFrm = pCNd->GetFrm(); + + if ( 0 != pFrm && pCNd->FindTableNode() == pTblNd && + (bInReadOnly || !pFrm->IsProtected() ) ) + { + // finally, we have found a suitable table cell => set index and return + rIdx = *pCNd; + return true; + } + + // continue behind the current section: + aTmp.Assign( *pCNd->EndOfSectionNode(), +1 ); + } + } + + rIdx = *pCNd; + return true; +} + +// comments see lcl_FindNextCell +bool lcl_FindPrevCell( SwNodeIndex& rIdx, BOOL bInReadOnly ) +{ + SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode + + const SwNode* pTableEndNode = &rIdx.GetNode(); + const SwTableNode* pTblNd = pTableEndNode->StartOfSectionNode()->GetTableNode(); + + if ( !pTblNd ) + { + ASSERT( false, "lcl_FindPrevCell not celled with table start node!" ) + return false; + } + + SwNodes& rNds = aTmp.GetNode().GetNodes(); + SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode(); + + if( !pCNd ) + pCNd = rNds.GoPrevious( &aTmp ); + + if ( !pCNd ) + return false; + + SwCntntFrm* pFrm = pCNd->GetFrm(); + + if( 0 == pFrm || pCNd->FindTableNode() != pTblNd || + (!bInReadOnly && pFrm->IsProtected() )) + { + // skip before current section + aTmp.Assign( *pCNd->StartOfSectionNode(), -1 ); + for( ;; ) + { + SwNode* pNd = &aTmp.GetNode(); + + if( pNd == pTblNd || pNd->GetIndex() < pTblNd->GetIndex() ) + return false; + + pCNd = aTmp.GetNode().GetCntntNode(); + if( 0 == pCNd ) + pCNd = rNds.GoPrevious( &aTmp ); + + if ( !pCNd ) + return false; + + pFrm = pCNd->GetFrm(); + + if( 0 != pFrm && pCNd->FindTableNode() == pTblNd && + (bInReadOnly || !pFrm->IsProtected() ) ) + { + rIdx = *pCNd; + return true; // Ok, nicht geschuetzt + } + aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 ); + } + } + + rIdx = *pCNd; + return true; +} + + +BOOL GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, + BOOL bInReadOnly ) +{ + SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode ); + + SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); + if( pTblNd ) + { + // #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* pInnerTblNd = 0; + SwNodeIndex aTmpIdx( aIdx ); + while( aTmpIdx.GetIndex() && + 0 == ( pInnerTblNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) ) + aTmpIdx--; + + if( pInnerTblNd == pTblNd ) + aIdx.Assign( *pTblNd, - 1 ); + } + + do { + while( aIdx.GetIndex() && + 0 == ( pTblNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) ) + aIdx--; + + if( pTblNd ) // gibt einen weiteren TableNode ? + { + if( fnPosTbl == fnMoveForward ) // an Anfang ? + { + aIdx = *aIdx.GetNode().StartOfSectionNode(); + if( !lcl_FindNextCell( aIdx, bInReadOnly )) + { + // Tabelle ueberspringen + aIdx.Assign( *pTblNd, -1 ); + continue; + } + } + else + { + // ueberpruefe geschuetzte Zellen + if( !lcl_FindNextCell( aIdx, bInReadOnly )) + { + // Tabelle ueberspringen + aIdx.Assign( *pTblNd, -1 ); + continue; + } + } + + SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode(); + if ( pTxtNode ) + { + rCurCrsr.GetPoint()->nNode = *pTxtNode; + rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? + pTxtNode->Len() : + 0 ); + } + return TRUE; + } + } while( pTblNd ); + + return FALSE; +} + + +BOOL GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, + BOOL bInReadOnly ) +{ + SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode ); + SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); + + if( pTblNd ) + aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 ); + + ULONG nLastNd = rCurCrsr.GetDoc()->GetNodes().Count() - 1; + do { + while( aIdx.GetIndex() < nLastNd && + 0 == ( pTblNd = aIdx.GetNode().GetTableNode()) ) + aIdx++; + if( pTblNd ) // gibt einen weiteren TableNode ? + { + if( fnPosTbl == fnMoveForward ) // an Anfang ? + { + if( !lcl_FindNextCell( aIdx, bInReadOnly )) + { + // Tabelle ueberspringen + aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 ); + continue; + } + } + else + { + aIdx = *aIdx.GetNode().EndOfSectionNode(); + // ueberpruefe geschuetzte Zellen + if( !lcl_FindNextCell( aIdx, bInReadOnly )) + { + // Tabelle ueberspringen + aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 ); + continue; + } + } + + SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode(); + if ( pTxtNode ) + { + rCurCrsr.GetPoint()->nNode = *pTxtNode; + rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? + pTxtNode->Len() : + 0 ); + } + return TRUE; + } + } while( pTblNd ); + + return FALSE; +} + + +BOOL GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, + BOOL bInReadOnly ) +{ + SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode(); + if( !pTblNd ) + return FALSE; + + SwTxtNode* pTxtNode = 0; + if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle + { + SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() ); + if( !lcl_FindPrevCell( aIdx, bInReadOnly )) + return FALSE; + pTxtNode = aIdx.GetNode().GetTxtNode(); + } + else + { + SwNodeIndex aIdx( *pTblNd ); + if( !lcl_FindNextCell( aIdx, bInReadOnly )) + return FALSE; + pTxtNode = aIdx.GetNode().GetTxtNode(); + } + + if ( pTxtNode ) + { + rCurCrsr.GetPoint()->nNode = *pTxtNode; + rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? + pTxtNode->Len() : + 0 ); + } + + return TRUE; +} + + +BOOL SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl ) +{ + BOOL bRet = FALSE; + SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this); + + if( pTblCrsr || !HasMark() ) // nur wenn kein Mark oder ein TblCrsr + { + SwCrsrSaveState aSaveState( *this ); + bRet = (*fnWhichTbl)( *this, fnPosTbl, IsReadOnlyAvailable() ) && + !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION | + nsSwCursorSelOverFlags::SELOVER_TOGGLE ); + } + return bRet; +} + +BOOL SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl ) +{ + SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen + + SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; + BOOL bCheckPos, bRet; + ULONG nPtNd = 0; + xub_StrLen nPtCnt = 0; + + if( !pTblCrsr && pCurCrsr->HasMark() ) // wenn Mark und kein TblCrsr, + { + // dann auf jedenfall in den Tabellen-Modus schalten + pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); + pCurCrsr->DeleteMark(); + pCurCrsr->SwSelPaintRects::Hide(); + pTblCrsr->SetMark(); + pCrsr = pTblCrsr; + bCheckPos = FALSE; + } + else + { + bCheckPos = TRUE; + nPtNd = pCrsr->GetPoint()->nNode.GetIndex(); + nPtCnt = pCrsr->GetPoint()->nContent.GetIndex(); + } + + bRet = pCrsr->MoveTable( fnWhichTbl, fnPosTbl ); + + if( bRet ) + { + //JP 28.10.97: Bug 45028 - die "oberste" Position setzen fuer + // wiederholte Kopfzeilen + pCrsr->GetPtPos() = Point(); + + UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY); + + if( bCheckPos && + pCrsr->GetPoint()->nNode.GetIndex() == nPtNd && + pCrsr->GetPoint()->nContent.GetIndex() == nPtCnt ) + bRet = FALSE; + } + return bRet; +} + + +BOOL SwCrsrShell::IsTblComplex() const +{ + SwFrm *pFrm = GetCurrFrm( FALSE ); + if ( pFrm && pFrm->IsInTab() ) + return pFrm->FindTabFrm()->GetTable()->IsTblComplex(); + return FALSE; +} + + +BOOL SwCrsrShell::IsTblComplexForChart() +{ + BOOL bRet = FALSE; + + StartAction(); // IsTblComplexForChart() may trigger table formatting + // we better do that inside an action + + const SwTableNode* pTNd = pCurCrsr->GetPoint()->nNode.GetNode().FindTableNode(); + if( pTNd ) + { + // wir stehen in der Tabelle, dann teste mal, ob die Tabelle oder die + // Selektion ausgeglichen ist. + String sSel; + if( pTblCrsr ) + sSel = GetBoxNms(); + bRet = pTNd->GetTable().IsTblComplexForChart( sSel ); + } + + EndAction(); + + return bRet; +} + +String SwCrsrShell::GetBoxNms() const +{ + String sNm; + const SwPosition* pPos; + SwFrm* pFrm; + + if( IsTableMode() ) + { + SwCntntNode *pCNd = pTblCrsr->Start()->nNode.GetNode().GetCntntNode(); + pFrm = pCNd ? pCNd->GetFrm() : 0; + if( !pFrm ) + return sNm; + + do { + pFrm = pFrm->GetUpper(); + } while ( pFrm && !pFrm->IsCellFrm() ); + + ASSERT( pFrm, "kein Frame zur Box" ); + sNm = ((SwCellFrm*)pFrm)->GetTabBox()->GetName(); + sNm += ':'; + pPos = pTblCrsr->End(); + } + else + { + const SwTableNode* pTblNd = IsCrsrInTbl(); + if( !pTblNd ) + return sNm; + pPos = GetCrsr()->GetPoint(); + } + + SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode(); + pFrm = pCNd ? pCNd->GetFrm() : 0; + + if( pFrm ) + { + do { + pFrm = pFrm->GetUpper(); + } while ( pFrm && !pFrm->IsCellFrm() ); + + if( pFrm ) + sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName(); + } + return sNm; +} + + +BOOL SwCrsrShell::GotoTable( const String& rName ) +{ + SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, + BOOL bRet = !pTblCrsr && pCurCrsr->GotoTable( rName ); + if( bRet ) + { + pCurCrsr->GetPtPos() = Point(); + UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE | + SwCrsrShell::READONLY ); // und den akt. Updaten + } + return bRet; +} + + +BOOL SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos ) +{ + if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() ) + return FALSE; + + // ueberpruefe, ob der Box Inhalt mit dem angegebenen Format der Box + // ueber einstimmt. Wenn nicht, setze neu + SwTableBox* pChkBox = 0; + SwStartNode* pSttNd = 0; + if( !pPos ) + { + // gesicherte Position heraus holen. + if( pBoxIdx && pBoxPtr && + 0 != ( pSttNd = pBoxIdx->GetNode().GetStartNode() ) && + SwTableBoxStartNode == pSttNd->GetStartNodeType() && + pBoxPtr == pSttNd->FindTableNode()->GetTable(). + GetTblBox( pBoxIdx->GetIndex() ) ) + pChkBox = pBoxPtr; + } + else if( 0 != ( pSttNd = pPos->nNode.GetNode(). + FindSttNodeByType( SwTableBoxStartNode )) ) + { + pChkBox = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() ); + } + + + // Box mehr als 1 Absatz? + if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() ) + pChkBox = 0; + + // jetzt sollten wir mal die Pointer zerstoeren, bevor eine erneute + // Actionklammerung kommt. + if( !pPos && !pChkBox ) + ClearTblBoxCntnt(); + + // liegt der Cursor nicht mehr in dem Bereich ? + if( pChkBox && !pPos && + ( pCurCrsr->HasMark() || pCurCrsr->GetNext() != pCurCrsr || + pSttNd->GetIndex() + 1 == pCurCrsr->GetPoint()->nNode.GetIndex() )) + pChkBox = 0; + + //JP 12.01.99: hat sich der Inhalt der Box ueberhaupt veraendert? + // Ist wichtig, wenn z.B. Undo nicht den richtigen Inhalt wieder + // herstellen konnte. + if( pChkBox ) + { + const SwTxtNode* pNd = GetDoc()->GetNodes()[ + pSttNd->GetIndex() + 1 ]->GetTxtNode(); + if( !pNd || + ( pNd->GetTxt() == ViewShell::GetShellRes()->aCalc_Error && + SFX_ITEM_SET == pChkBox->GetFrmFmt()-> + GetItemState( RES_BOXATR_FORMULA )) ) + pChkBox = 0; + } + + if( pChkBox ) + { + // jetzt sollten wir mal die Pointer zerstoeren, bevor ein weiterer + // aufruf kommt. + ClearTblBoxCntnt(); + StartAction(); + GetDoc()->ChkBoxNumFmt( *pChkBox, TRUE ); + EndAction(); + } + + return 0 != pChkBox; +} + + +void SwCrsrShell::SaveTblBoxCntnt( const SwPosition* pPos ) +{ + if( IsSelTblCells() || !IsAutoUpdateCells() ) + return ; + + if( !pPos ) + pPos = pCurCrsr->GetPoint(); + + SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode ); + + BOOL bCheckBox = FALSE; + if( pSttNd && pBoxIdx ) + { + if( pSttNd == &pBoxIdx->GetNode() ) + pSttNd = 0; // die haben wir schon + else + bCheckBox = TRUE; + } + else + bCheckBox = 0 != pBoxIdx; + + if( bCheckBox ) + { + // pBoxIdx Checken + SwPosition aPos( *pBoxIdx ); + CheckTblBoxCntnt( &aPos ); + } + + if( pSttNd ) + { + pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() ); + + if( pBoxIdx ) + *pBoxIdx = *pSttNd; + else + pBoxIdx = new SwNodeIndex( *pSttNd ); + } +} + + +void SwCrsrShell::ClearTblBoxCntnt() +{ + delete pBoxIdx, pBoxIdx = 0; + pBoxPtr = 0; +} + +BOOL SwCrsrShell::EndAllTblBoxEdit() +{ + BOOL bRet = FALSE; + ViewShell *pSh = this; + do { + if( pSh->IsA( TYPE( SwCrsrShell ) ) ) + bRet |= ((SwCrsrShell*)pSh)->CheckTblBoxCntnt( + ((SwCrsrShell*)pSh)->pCurCrsr->GetPoint() ); + + } while( this != (pSh = (ViewShell *)pSh->GetNext()) ); + return bRet; +} + + + + |