Update ooo320-m1
[ooovba.git] / sw / source / core / crsr / trvltbl.cxx
blob0f14a62beddda7c995ac612f073f42d53959a421
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: trvltbl.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
35 #include <vcl/svapp.hxx>
36 #include <svx/protitem.hxx>
37 #include <crsrsh.hxx>
38 #include <doc.hxx>
39 #include <cntfrm.hxx>
40 #include <editsh.hxx> //EndAllAction gibts nur an der EditShell
41 #include <pam.hxx>
42 #include <swtable.hxx>
43 #include <docary.hxx>
44 #include <frmatr.hxx>
45 #include <frmfmt.hxx>
46 #include <viscrs.hxx>
47 #include <callnk.hxx>
48 #include <tabfrm.hxx>
49 #include <ndtxt.hxx>
50 #include <shellres.hxx>
51 #include <cellatr.hxx>
52 #include <cellfrm.hxx>
53 #include <rowfrm.hxx>
56 // setze Crsr in die naechsten/vorherigen Celle
57 BOOL SwCrsrShell::GoNextCell( BOOL bAppendLine )
59 BOOL bRet = FALSE;
60 const SwTableNode* pTblNd = 0;
62 if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
64 SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
65 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
66 bRet = TRUE;
68 // Check if we have to move the cursor to a covered cell before
69 // proceeding:
70 const SwNode* pTableBoxStartNode = pCrsr->GetNode()->FindTableBoxStartNode();
71 const SwTableBox* pTableBox = 0;
73 if ( pCrsr->GetCrsrRowSpanOffset() )
75 pTableBox = pTableBoxStartNode->GetTblBox();
76 if ( pTableBox->getRowSpan() > 1 )
78 if ( !pTblNd )
79 pTblNd = IsCrsrInTbl();
80 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(),
81 (USHORT)(pTableBox->getRowSpan() + pCrsr->GetCrsrRowSpanOffset() ) );
82 pTableBoxStartNode = pTableBox->GetSttNd();
86 SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 );
88 // folgt nach dem EndNode der Cell ein weiterer StartNode, dann
89 // gibt es auch eine naechste Celle
91 if( !aCellStt.GetNode().IsStartNode() )
93 if( pCrsr->HasMark() || !bAppendLine )
94 bRet = FALSE;
95 else
97 // auf besonderen Wunsch: keine Line mehr vorhanden, dann
98 // mache doch eine neue:
99 if ( !pTableBox )
100 pTableBox = pTblNd->GetTable().GetTblBox(
101 pCrsr->GetPoint()->nNode.GetNode().
102 StartOfSectionIndex() );
104 ASSERT( pTableBox, "Box steht nicht in dieser Tabelle" );
105 SwSelBoxes aBoxes;
107 //Das Dokument veraendert sich evtl. ohne Action wuerden die Sichten
108 //nichts mitbekommen.
109 ((SwEditShell*)this)->StartAllAction();
110 bRet = pDoc->InsertRow( pTblNd->GetTable().
111 SelLineFromBox( pTableBox, aBoxes, FALSE ));
112 ((SwEditShell*)this)->EndAllAction();
115 if( bRet && 0 != ( bRet = pCrsr->GoNextCell() ))
116 UpdateCrsr(); // und den akt. Updaten
118 return bRet;
122 BOOL SwCrsrShell::GoPrevCell()
124 BOOL bRet = FALSE;
125 const SwTableNode* pTblNd;
126 if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
128 SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
129 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
130 bRet = pCrsr->GoPrevCell();
131 if( bRet )
132 UpdateCrsr(); // und den akt. Updaten
134 return bRet;
137 const SwFrm* lcl_FindMostUpperCellFrm( const SwFrm* pFrm )
139 while ( pFrm &&
140 ( !pFrm->IsCellFrm() ||
141 !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
142 pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
144 pFrm = pFrm->GetUpper();
146 return pFrm;
149 BOOL SwCrsrShell::_SelTblRowOrCol( bool bRow, bool bRowSimple )
151 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
152 SwFrm *pFrm = GetCurrFrm();
153 if( !pFrm->IsInTab() )
154 return FALSE;
156 const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
157 const SwTabFrm* pMasterTabFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
158 const SwTable* pTable = pTabFrm->GetTable();
160 SET_CURR_SHELL( this );
162 const SwTableBox* pStt = 0;
163 const SwTableBox* pEnd = 0;
165 // lasse ueber das Layout die Boxen suchen
166 SwSelBoxes aBoxes;
167 SwTblSearchType eType = bRow ? nsSwTblSearchType::TBLSEARCH_ROW : nsSwTblSearchType::TBLSEARCH_COL;
168 const bool bCheckProtected = !IsReadOnlyAvailable();
170 if( bCheckProtected )
171 eType = (SwTblSearchType)(eType | nsSwTblSearchType::TBLSEARCH_PROTECT);
173 if ( !bRowSimple )
175 GetTblSel( *this, aBoxes, eType );
177 if( !aBoxes.Count() )
178 return FALSE;
180 pStt = aBoxes[0];
181 pEnd = aBoxes[aBoxes.Count() - 1];
183 // --> FME 2004-07-30 #i32329# Enhanced table selection
184 else if ( pTable->IsNewModel() )
186 const SwShellCrsr *pCrsr = _GetCrsr();
187 SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL;
188 pTable->CreateSelection( *pCrsr, aBoxes, eSearchType, bCheckProtected );
189 if( !aBoxes.Count() )
190 return FALSE;
192 pStt = aBoxes[0];
193 pEnd = aBoxes[aBoxes.Count() - 1];
195 else
197 const SwShellCrsr *pCrsr = _GetCrsr();
198 const SwFrm* pStartFrm = pFrm;
199 const SwCntntNode *pCNd = pCrsr->GetCntntNode( FALSE );
200 const SwFrm* pEndFrm = pCNd ? pCNd->GetFrm( &pCrsr->GetMkPos() ) : 0;
202 if ( bRow )
204 pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm );
205 pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm );
208 if ( !pStartFrm || !pEndFrm )
209 return FALSE;
211 const bool bVert = pFrm->ImplFindTabFrm()->IsVertical();
213 // If we select upwards it is sufficient to set pStt and pEnd
214 // to the first resp. last box of the selection obtained from
215 // GetTblSel. However, selecting downwards requires the frames
216 // located at the corners of the selection. This does not work
217 // for column selections in vertical tables:
218 const bool bSelectUp = ( bVert && !bRow ) ||
219 *pCrsr->GetPoint() <= *pCrsr->GetMark();
220 SwCellFrms aCells;
221 GetTblSel( static_cast<const SwCellFrm*>(pStartFrm),
222 static_cast<const SwCellFrm*>(pEndFrm),
223 aBoxes, bSelectUp ? 0 : &aCells, eType );
225 if( !aBoxes.Count() || ( !bSelectUp && 4 != aCells.Count() ) )
226 return FALSE;
228 if ( bSelectUp )
230 pStt = aBoxes[0];
231 pEnd = aBoxes[aBoxes.Count() - 1];
233 else
235 pStt = aCells[ bVert ? (bRow ? 0 : 3) : (bRow ? 2 : 1) ]->GetTabBox(); // will become point of table cursor
236 pEnd = aCells[ bVert ? (bRow ? 3 : 0) : (bRow ? 1 : 2) ]->GetTabBox(); // will become mark of table cursor
239 // <--
241 // noch kein Tabellen-Cursor vorhanden, dann erzeuge einen
242 if( !pTblCrsr )
244 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
245 pCurCrsr->DeleteMark();
246 pCurCrsr->SwSelPaintRects::Hide();
249 pTblCrsr->DeleteMark();
251 // dann setze mal Anfang und Ende der Spalte
252 pTblCrsr->GetPoint()->nNode = *pEnd->GetSttNd();
253 pTblCrsr->Move( fnMoveForward, fnGoCntnt );
254 pTblCrsr->SetMark();
255 pTblCrsr->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode();
256 pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
258 // set PtPos 'close' to the reference table, otherwise we might get problems with the
259 // repeated headlines check in UpdateCrsr():
260 if ( !bRow )
261 pTblCrsr->GetPtPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
263 UpdateCrsr(); // und den akt. Updaten
264 return TRUE;
267 BOOL SwCrsrShell::SelTbl()
269 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
270 SwFrm *pFrm = GetCurrFrm();
271 if( !pFrm->IsInTab() )
272 return FALSE;
274 const SwTabFrm *pTblFrm = pFrm->ImplFindTabFrm();
275 const SwTabFrm* pMasterTabFrm = pTblFrm->IsFollow() ? pTblFrm->FindMaster( true ) : pTblFrm;
276 const SwTableNode* pTblNd = pTblFrm->GetTable()->GetTableNode();
278 SET_CURR_SHELL( this );
280 if( !pTblCrsr )
282 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
283 pCurCrsr->DeleteMark();
284 pCurCrsr->SwSelPaintRects::Hide();
287 pTblCrsr->DeleteMark();
288 pTblCrsr->GetPoint()->nNode = *pTblNd;
289 pTblCrsr->Move( fnMoveForward, fnGoCntnt );
290 pTblCrsr->SetMark();
291 // set MkPos 'close' to the master table, otherwise we might get problems with the
292 // repeated headlines check in UpdateCrsr():
293 pTblCrsr->GetMkPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
294 pTblCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
295 pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
296 UpdateCrsr(); // und den akt. Updaten
297 return TRUE;
301 BOOL SwCrsrShell::SelTblBox()
303 // if we're in a table, create a table cursor, and select the cell
304 // that the current cursor's point resides in
306 // search for start node of our table box. If not found, exit realy
307 const SwStartNode* pStartNode =
308 pCurCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
310 #ifndef PRODUCT
311 // the old code checks whether we're in a table by asking the
312 // frame. This should yield the same result as searching for the
313 // table box start node, right?
314 SwFrm *pFrm = GetCurrFrm();
315 DBG_ASSERT( !pFrm->IsInTab() == !(pStartNode != NULL),
316 "Schroedinger's table: We're in a box, and also we aren't." );
317 #endif
319 if( pStartNode == NULL )
320 return FALSE;
323 SET_CURR_SHELL( this );
325 // create a table cursor, if there isn't one already
326 if( !pTblCrsr )
328 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
329 pCurCrsr->DeleteMark();
330 pCurCrsr->SwSelPaintRects::Hide();
333 // select the complete box with our shiny new pTblCrsr
334 // 1. delete mark, and move point to first content node in box
335 // 2. set mark, and move point to last content node in box
336 // 3. exchange
338 pTblCrsr->DeleteMark();
339 *(pTblCrsr->GetPoint()) = SwPosition( *pStartNode );
340 pTblCrsr->Move( fnMoveForward, fnGoNode );
342 pTblCrsr->SetMark();
343 *(pTblCrsr->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) );
344 pTblCrsr->Move( fnMoveBackward, fnGoNode );
346 pTblCrsr->Exchange();
348 // with some luck, UpdateCrsr() will now update everything that
349 // needs updateing
350 UpdateCrsr();
352 return TRUE;
355 // return the next non-protected cell inside a table
356 // rIdx - is on a table node
357 // return:
358 // true - Idx points to content in a suitable cell
359 // false - could not find a suitable cell
360 bool lcl_FindNextCell( SwNodeIndex& rIdx, BOOL bInReadOnly )
362 // ueberpruefe geschuetzte Zellen
363 SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
365 // the resulting cell should be in that table:
366 const SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
368 if ( !pTblNd )
370 ASSERT( false, "lcl_FindNextCell not celled with table start node!" )
371 return false;
374 const SwNode* pTableEndNode = pTblNd->EndOfSectionNode();
376 SwNodes& rNds = aTmp.GetNode().GetNodes();
377 SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
379 // no content node => go to next content node
380 if( !pCNd )
381 pCNd = rNds.GoNext( &aTmp );
383 // robust
384 if ( !pCNd )
385 return false;
387 SwCntntFrm* pFrm = pCNd->GetFrm();
389 if ( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
390 (!bInReadOnly && pFrm->IsProtected() ) )
392 // we are not located inside a 'valid' cell. We have to continue searching...
394 // skip behind current section. This might be the end of the table cell
395 // or behind a inner section or or or...
396 aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
398 // loop to find a suitable cell...
399 for( ;; )
401 SwNode* pNd = &aTmp.GetNode();
403 // we break this loop if we reached the end of the table.
404 // to make this code even more robust, we also break if we are
405 // already behind the table end node:
406 if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() )
407 return false;
409 // ok, get the next content node:
410 pCNd = aTmp.GetNode().GetCntntNode();
411 if( 0 == pCNd )
412 pCNd = rNds.GoNext( &aTmp );
414 // robust:
415 if ( !pCNd )
416 return false;
418 // check if we have found a suitable table cell:
419 pFrm = pCNd->GetFrm();
421 if ( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
422 (bInReadOnly || !pFrm->IsProtected() ) )
424 // finally, we have found a suitable table cell => set index and return
425 rIdx = *pCNd;
426 return true;
429 // continue behind the current section:
430 aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
434 rIdx = *pCNd;
435 return true;
438 // comments see lcl_FindNextCell
439 bool lcl_FindPrevCell( SwNodeIndex& rIdx, BOOL bInReadOnly )
441 SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode
443 const SwNode* pTableEndNode = &rIdx.GetNode();
444 const SwTableNode* pTblNd = pTableEndNode->StartOfSectionNode()->GetTableNode();
446 if ( !pTblNd )
448 ASSERT( false, "lcl_FindPrevCell not celled with table start node!" )
449 return false;
452 SwNodes& rNds = aTmp.GetNode().GetNodes();
453 SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
455 if( !pCNd )
456 pCNd = rNds.GoPrevious( &aTmp );
458 if ( !pCNd )
459 return false;
461 SwCntntFrm* pFrm = pCNd->GetFrm();
463 if( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
464 (!bInReadOnly && pFrm->IsProtected() ))
466 // skip before current section
467 aTmp.Assign( *pCNd->StartOfSectionNode(), -1 );
468 for( ;; )
470 SwNode* pNd = &aTmp.GetNode();
472 if( pNd == pTblNd || pNd->GetIndex() < pTblNd->GetIndex() )
473 return false;
475 pCNd = aTmp.GetNode().GetCntntNode();
476 if( 0 == pCNd )
477 pCNd = rNds.GoPrevious( &aTmp );
479 if ( !pCNd )
480 return false;
482 pFrm = pCNd->GetFrm();
484 if( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
485 (bInReadOnly || !pFrm->IsProtected() ) )
487 rIdx = *pCNd;
488 return true; // Ok, nicht geschuetzt
490 aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 );
494 rIdx = *pCNd;
495 return true;
499 BOOL GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
500 BOOL bInReadOnly )
502 SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
504 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
505 if( pTblNd )
507 // #i26532#: If we are inside a table, we may not go backward
508 // to the table start node, because we would miss any tables
509 // inside this table.
510 SwTableNode* pInnerTblNd = 0;
511 SwNodeIndex aTmpIdx( aIdx );
512 while( aTmpIdx.GetIndex() &&
513 0 == ( pInnerTblNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
514 aTmpIdx--;
516 if( pInnerTblNd == pTblNd )
517 aIdx.Assign( *pTblNd, - 1 );
520 do {
521 while( aIdx.GetIndex() &&
522 0 == ( pTblNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
523 aIdx--;
525 if( pTblNd ) // gibt einen weiteren TableNode ?
527 if( fnPosTbl == fnMoveForward ) // an Anfang ?
529 aIdx = *aIdx.GetNode().StartOfSectionNode();
530 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
532 // Tabelle ueberspringen
533 aIdx.Assign( *pTblNd, -1 );
534 continue;
537 else
539 // ueberpruefe geschuetzte Zellen
540 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
542 // Tabelle ueberspringen
543 aIdx.Assign( *pTblNd, -1 );
544 continue;
548 SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
549 if ( pTxtNode )
551 rCurCrsr.GetPoint()->nNode = *pTxtNode;
552 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
553 pTxtNode->Len() :
554 0 );
556 return TRUE;
558 } while( pTblNd );
560 return FALSE;
564 BOOL GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
565 BOOL bInReadOnly )
567 SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
568 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
570 if( pTblNd )
571 aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 );
573 ULONG nLastNd = rCurCrsr.GetDoc()->GetNodes().Count() - 1;
574 do {
575 while( aIdx.GetIndex() < nLastNd &&
576 0 == ( pTblNd = aIdx.GetNode().GetTableNode()) )
577 aIdx++;
578 if( pTblNd ) // gibt einen weiteren TableNode ?
580 if( fnPosTbl == fnMoveForward ) // an Anfang ?
582 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
584 // Tabelle ueberspringen
585 aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
586 continue;
589 else
591 aIdx = *aIdx.GetNode().EndOfSectionNode();
592 // ueberpruefe geschuetzte Zellen
593 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
595 // Tabelle ueberspringen
596 aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
597 continue;
601 SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
602 if ( pTxtNode )
604 rCurCrsr.GetPoint()->nNode = *pTxtNode;
605 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
606 pTxtNode->Len() :
607 0 );
609 return TRUE;
611 } while( pTblNd );
613 return FALSE;
617 BOOL GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
618 BOOL bInReadOnly )
620 SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode();
621 if( !pTblNd )
622 return FALSE;
624 SwTxtNode* pTxtNode = 0;
625 if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle
627 SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() );
628 if( !lcl_FindPrevCell( aIdx, bInReadOnly ))
629 return FALSE;
630 pTxtNode = aIdx.GetNode().GetTxtNode();
632 else
634 SwNodeIndex aIdx( *pTblNd );
635 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
636 return FALSE;
637 pTxtNode = aIdx.GetNode().GetTxtNode();
640 if ( pTxtNode )
642 rCurCrsr.GetPoint()->nNode = *pTxtNode;
643 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
644 pTxtNode->Len() :
645 0 );
648 return TRUE;
652 BOOL SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
654 BOOL bRet = FALSE;
655 SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
657 if( pTblCrsr || !HasMark() ) // nur wenn kein Mark oder ein TblCrsr
659 SwCrsrSaveState aSaveState( *this );
660 bRet = (*fnWhichTbl)( *this, fnPosTbl, IsReadOnlyAvailable() ) &&
661 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
662 nsSwCursorSelOverFlags::SELOVER_TOGGLE );
664 return bRet;
667 BOOL SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
669 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
671 SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
672 BOOL bCheckPos, bRet;
673 ULONG nPtNd = 0;
674 xub_StrLen nPtCnt = 0;
676 if( !pTblCrsr && pCurCrsr->HasMark() ) // wenn Mark und kein TblCrsr,
678 // dann auf jedenfall in den Tabellen-Modus schalten
679 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
680 pCurCrsr->DeleteMark();
681 pCurCrsr->SwSelPaintRects::Hide();
682 pTblCrsr->SetMark();
683 pCrsr = pTblCrsr;
684 bCheckPos = FALSE;
686 else
688 bCheckPos = TRUE;
689 nPtNd = pCrsr->GetPoint()->nNode.GetIndex();
690 nPtCnt = pCrsr->GetPoint()->nContent.GetIndex();
693 bRet = pCrsr->MoveTable( fnWhichTbl, fnPosTbl );
695 if( bRet )
697 //JP 28.10.97: Bug 45028 - die "oberste" Position setzen fuer
698 // wiederholte Kopfzeilen
699 pCrsr->GetPtPos() = Point();
701 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
703 if( bCheckPos &&
704 pCrsr->GetPoint()->nNode.GetIndex() == nPtNd &&
705 pCrsr->GetPoint()->nContent.GetIndex() == nPtCnt )
706 bRet = FALSE;
708 return bRet;
712 BOOL SwCrsrShell::IsTblComplex() const
714 SwFrm *pFrm = GetCurrFrm( FALSE );
715 if ( pFrm && pFrm->IsInTab() )
716 return pFrm->FindTabFrm()->GetTable()->IsTblComplex();
717 return FALSE;
721 BOOL SwCrsrShell::IsTblComplexForChart()
723 BOOL bRet = FALSE;
725 StartAction(); // IsTblComplexForChart() may trigger table formatting
726 // we better do that inside an action
728 const SwTableNode* pTNd = pCurCrsr->GetPoint()->nNode.GetNode().FindTableNode();
729 if( pTNd )
731 // wir stehen in der Tabelle, dann teste mal, ob die Tabelle oder die
732 // Selektion ausgeglichen ist.
733 String sSel;
734 if( pTblCrsr )
735 sSel = GetBoxNms();
736 bRet = pTNd->GetTable().IsTblComplexForChart( sSel );
739 EndAction();
741 return bRet;
744 String SwCrsrShell::GetBoxNms() const
746 String sNm;
747 const SwPosition* pPos;
748 SwFrm* pFrm;
750 if( IsTableMode() )
752 SwCntntNode *pCNd = pTblCrsr->Start()->nNode.GetNode().GetCntntNode();
753 pFrm = pCNd ? pCNd->GetFrm() : 0;
754 if( !pFrm )
755 return sNm;
757 do {
758 pFrm = pFrm->GetUpper();
759 } while ( pFrm && !pFrm->IsCellFrm() );
761 ASSERT( pFrm, "kein Frame zur Box" );
762 sNm = ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
763 sNm += ':';
764 pPos = pTblCrsr->End();
766 else
768 const SwTableNode* pTblNd = IsCrsrInTbl();
769 if( !pTblNd )
770 return sNm;
771 pPos = GetCrsr()->GetPoint();
774 SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode();
775 pFrm = pCNd ? pCNd->GetFrm() : 0;
777 if( pFrm )
779 do {
780 pFrm = pFrm->GetUpper();
781 } while ( pFrm && !pFrm->IsCellFrm() );
783 if( pFrm )
784 sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
786 return sNm;
790 BOOL SwCrsrShell::GotoTable( const String& rName )
792 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
793 BOOL bRet = !pTblCrsr && pCurCrsr->GotoTable( rName );
794 if( bRet )
796 pCurCrsr->GetPtPos() = Point();
797 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
798 SwCrsrShell::READONLY ); // und den akt. Updaten
800 return bRet;
804 BOOL SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos )
806 if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() )
807 return FALSE;
809 // ueberpruefe, ob der Box Inhalt mit dem angegebenen Format der Box
810 // ueber einstimmt. Wenn nicht, setze neu
811 SwTableBox* pChkBox = 0;
812 SwStartNode* pSttNd = 0;
813 if( !pPos )
815 // gesicherte Position heraus holen.
816 if( pBoxIdx && pBoxPtr &&
817 0 != ( pSttNd = pBoxIdx->GetNode().GetStartNode() ) &&
818 SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
819 pBoxPtr == pSttNd->FindTableNode()->GetTable().
820 GetTblBox( pBoxIdx->GetIndex() ) )
821 pChkBox = pBoxPtr;
823 else if( 0 != ( pSttNd = pPos->nNode.GetNode().
824 FindSttNodeByType( SwTableBoxStartNode )) )
826 pChkBox = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
830 // Box mehr als 1 Absatz?
831 if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() )
832 pChkBox = 0;
834 // jetzt sollten wir mal die Pointer zerstoeren, bevor eine erneute
835 // Actionklammerung kommt.
836 if( !pPos && !pChkBox )
837 ClearTblBoxCntnt();
839 // liegt der Cursor nicht mehr in dem Bereich ?
840 if( pChkBox && !pPos &&
841 ( pCurCrsr->HasMark() || pCurCrsr->GetNext() != pCurCrsr ||
842 pSttNd->GetIndex() + 1 == pCurCrsr->GetPoint()->nNode.GetIndex() ))
843 pChkBox = 0;
845 //JP 12.01.99: hat sich der Inhalt der Box ueberhaupt veraendert?
846 // Ist wichtig, wenn z.B. Undo nicht den richtigen Inhalt wieder
847 // herstellen konnte.
848 if( pChkBox )
850 const SwTxtNode* pNd = GetDoc()->GetNodes()[
851 pSttNd->GetIndex() + 1 ]->GetTxtNode();
852 if( !pNd ||
853 ( pNd->GetTxt() == ViewShell::GetShellRes()->aCalc_Error &&
854 SFX_ITEM_SET == pChkBox->GetFrmFmt()->
855 GetItemState( RES_BOXATR_FORMULA )) )
856 pChkBox = 0;
859 if( pChkBox )
861 // jetzt sollten wir mal die Pointer zerstoeren, bevor ein weiterer
862 // aufruf kommt.
863 ClearTblBoxCntnt();
864 StartAction();
865 GetDoc()->ChkBoxNumFmt( *pChkBox, TRUE );
866 EndAction();
869 return 0 != pChkBox;
873 void SwCrsrShell::SaveTblBoxCntnt( const SwPosition* pPos )
875 if( IsSelTblCells() || !IsAutoUpdateCells() )
876 return ;
878 if( !pPos )
879 pPos = pCurCrsr->GetPoint();
881 SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode );
883 BOOL bCheckBox = FALSE;
884 if( pSttNd && pBoxIdx )
886 if( pSttNd == &pBoxIdx->GetNode() )
887 pSttNd = 0; // die haben wir schon
888 else
889 bCheckBox = TRUE;
891 else
892 bCheckBox = 0 != pBoxIdx;
894 if( bCheckBox )
896 // pBoxIdx Checken
897 SwPosition aPos( *pBoxIdx );
898 CheckTblBoxCntnt( &aPos );
901 if( pSttNd )
903 pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
905 if( pBoxIdx )
906 *pBoxIdx = *pSttNd;
907 else
908 pBoxIdx = new SwNodeIndex( *pSttNd );
913 void SwCrsrShell::ClearTblBoxCntnt()
915 delete pBoxIdx, pBoxIdx = 0;
916 pBoxPtr = 0;
919 BOOL SwCrsrShell::EndAllTblBoxEdit()
921 BOOL bRet = FALSE;
922 ViewShell *pSh = this;
923 do {
924 if( pSh->IsA( TYPE( SwCrsrShell ) ) )
925 bRet |= ((SwCrsrShell*)pSh)->CheckTblBoxCntnt(
926 ((SwCrsrShell*)pSh)->pCurCrsr->GetPoint() );
928 } while( this != (pSh = (ViewShell *)pSh->GetNext()) );
929 return bRet;