| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 |
| sal_Bool SwCrsrShell::GoNextCell( sal_Bool bAppendLine ) |
| { |
| sal_Bool bRet = sal_False; |
| const SwTableNode* pTblNd = 0; |
| |
| if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() )) |
| { |
| SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; |
| SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, |
| bRet = sal_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(), |
| (sal_uInt16)(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 = sal_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, sal_False )); |
| ((SwEditShell*)this)->EndAllAction(); |
| } |
| } |
| if( bRet && 0 != ( bRet = pCrsr->GoNextCell() )) |
| UpdateCrsr(); // und den akt. Updaten |
| } |
| return bRet; |
| } |
| |
| |
| sal_Bool SwCrsrShell::GoPrevCell() |
| { |
| sal_Bool bRet = sal_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; |
| } |
| |
| sal_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 sal_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 sal_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 sal_False; |
| |
| pStt = aBoxes[0]; |
| pEnd = aBoxes[aBoxes.Count() - 1]; |
| } |
| else |
| { |
| const SwShellCrsr *pCrsr = _GetCrsr(); |
| const SwFrm* pStartFrm = pFrm; |
| const SwCntntNode *pCNd = pCrsr->GetCntntNode( sal_False ); |
| const SwFrm* pEndFrm = pCNd ? pCNd->getLayoutFrm( GetLayout(), &pCrsr->GetMkPos() ) : 0; |
| |
| if ( bRow ) |
| { |
| pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm ); |
| pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm ); |
| } |
| |
| if ( !pStartFrm || !pEndFrm ) |
| return sal_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 sal_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 sal_True; |
| } |
| |
| sal_Bool SwCrsrShell::SelTbl() |
| { |
| // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen |
| SwFrm *pFrm = GetCurrFrm(); |
| if( !pFrm->IsInTab() ) |
| return sal_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 sal_True; |
| } |
| |
| |
| sal_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 sal_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 sal_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, sal_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->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); |
| |
| 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->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); |
| |
| 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, sal_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->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); |
| |
| 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->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); |
| |
| 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; |
| } |
| |
| |
| sal_Bool GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, |
| sal_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 sal_True; |
| } |
| } while( pTblNd ); |
| |
| return sal_False; |
| } |
| |
| |
| sal_Bool GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, |
| sal_Bool bInReadOnly ) |
| { |
| SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode ); |
| SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); |
| |
| if( pTblNd ) |
| aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 ); |
| |
| sal_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 sal_True; |
| } |
| } while( pTblNd ); |
| |
| return sal_False; |
| } |
| |
| |
| sal_Bool GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, |
| sal_Bool bInReadOnly ) |
| { |
| SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| SwTxtNode* pTxtNode = 0; |
| if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle |
| { |
| SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() ); |
| if( !lcl_FindPrevCell( aIdx, bInReadOnly )) |
| return sal_False; |
| pTxtNode = aIdx.GetNode().GetTxtNode(); |
| } |
| else |
| { |
| SwNodeIndex aIdx( *pTblNd ); |
| if( !lcl_FindNextCell( aIdx, bInReadOnly )) |
| return sal_False; |
| pTxtNode = aIdx.GetNode().GetTxtNode(); |
| } |
| |
| if ( pTxtNode ) |
| { |
| rCurCrsr.GetPoint()->nNode = *pTxtNode; |
| rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? |
| pTxtNode->Len() : |
| 0 ); |
| } |
| |
| return sal_True; |
| } |
| |
| |
| sal_Bool SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl ) |
| { |
| sal_Bool bRet = sal_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; |
| } |
| |
| sal_Bool SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl ) |
| { |
| SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen |
| |
| SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; |
| sal_Bool bCheckPos, bRet; |
| sal_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 = sal_False; |
| } |
| else |
| { |
| bCheckPos = sal_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 = sal_False; |
| } |
| return bRet; |
| } |
| |
| |
| sal_Bool SwCrsrShell::IsTblComplex() const |
| { |
| SwFrm *pFrm = GetCurrFrm( sal_False ); |
| if ( pFrm && pFrm->IsInTab() ) |
| return pFrm->FindTabFrm()->GetTable()->IsTblComplex(); |
| return sal_False; |
| } |
| |
| |
| sal_Bool SwCrsrShell::IsTblComplexForChart() |
| { |
| sal_Bool bRet = sal_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->getLayoutFrm( GetLayout() ) : 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->getLayoutFrm( GetLayout() ) : 0; |
| |
| if( pFrm ) |
| { |
| do { |
| pFrm = pFrm->GetUpper(); |
| } while ( pFrm && !pFrm->IsCellFrm() ); |
| |
| if( pFrm ) |
| sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName(); |
| } |
| return sNm; |
| } |
| |
| |
| sal_Bool SwCrsrShell::GotoTable( const String& rName ) |
| { |
| SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, |
| sal_Bool bRet = !pTblCrsr && pCurCrsr->GotoTable( rName ); |
| if( bRet ) |
| { |
| pCurCrsr->GetPtPos() = Point(); |
| UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE | |
| SwCrsrShell::READONLY ); // und den akt. Updaten |
| } |
| return bRet; |
| } |
| |
| |
| sal_Bool SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos ) |
| { |
| if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() ) |
| return sal_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, sal_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 ); |
| |
| sal_Bool bCheckBox = sal_False; |
| if( pSttNd && pBoxIdx ) |
| { |
| if( pSttNd == &pBoxIdx->GetNode() ) |
| pSttNd = 0; // die haben wir schon |
| else |
| bCheckBox = sal_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; |
| } |
| |
| sal_Bool SwCrsrShell::EndAllTblBoxEdit() |
| { |
| sal_Bool bRet = sal_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; |
| } |
| |
| |
| |
| |