1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 #include <hintids.hxx> 31 32 #include <vcl/svapp.hxx> 33 #include <editeng/protitem.hxx> 34 #include <crsrsh.hxx> 35 #include <doc.hxx> 36 #include <cntfrm.hxx> 37 #include <editsh.hxx> //EndAllAction gibts nur an der EditShell 38 #include <pam.hxx> 39 #include <swtable.hxx> 40 #include <docary.hxx> 41 #include <frmatr.hxx> 42 #include <frmfmt.hxx> 43 #include <viscrs.hxx> 44 #include <callnk.hxx> 45 #include <tabfrm.hxx> 46 #include <ndtxt.hxx> 47 #include <shellres.hxx> 48 #include <cellatr.hxx> 49 #include <cellfrm.hxx> 50 #include <rowfrm.hxx> 51 52 53 // setze Crsr in die naechsten/vorherigen Celle 54 sal_Bool SwCrsrShell::GoNextCell( sal_Bool bAppendLine ) 55 { 56 sal_Bool bRet = sal_False; 57 const SwTableNode* pTblNd = 0; 58 59 if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() )) 60 { 61 SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 62 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 63 bRet = sal_True; 64 65 // Check if we have to move the cursor to a covered cell before 66 // proceeding: 67 const SwNode* pTableBoxStartNode = pCrsr->GetNode()->FindTableBoxStartNode(); 68 const SwTableBox* pTableBox = 0; 69 70 if ( pCrsr->GetCrsrRowSpanOffset() ) 71 { 72 pTableBox = pTableBoxStartNode->GetTblBox(); 73 if ( pTableBox->getRowSpan() > 1 ) 74 { 75 if ( !pTblNd ) 76 pTblNd = IsCrsrInTbl(); 77 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), 78 (sal_uInt16)(pTableBox->getRowSpan() + pCrsr->GetCrsrRowSpanOffset() ) ); 79 pTableBoxStartNode = pTableBox->GetSttNd(); 80 } 81 } 82 83 SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 ); 84 85 // folgt nach dem EndNode der Cell ein weiterer StartNode, dann 86 // gibt es auch eine naechste Celle 87 88 if( !aCellStt.GetNode().IsStartNode() ) 89 { 90 if( pCrsr->HasMark() || !bAppendLine ) 91 bRet = sal_False; 92 else 93 { 94 // auf besonderen Wunsch: keine Line mehr vorhanden, dann 95 // mache doch eine neue: 96 if ( !pTableBox ) 97 pTableBox = pTblNd->GetTable().GetTblBox( 98 pCrsr->GetPoint()->nNode.GetNode(). 99 StartOfSectionIndex() ); 100 101 ASSERT( pTableBox, "Box steht nicht in dieser Tabelle" ); 102 SwSelBoxes aBoxes; 103 104 //Das Dokument veraendert sich evtl. ohne Action wuerden die Sichten 105 //nichts mitbekommen. 106 ((SwEditShell*)this)->StartAllAction(); 107 bRet = pDoc->InsertRow( pTblNd->GetTable(). 108 SelLineFromBox( pTableBox, aBoxes, sal_False )); 109 ((SwEditShell*)this)->EndAllAction(); 110 } 111 } 112 if( bRet && 0 != ( bRet = pCrsr->GoNextCell() )) 113 UpdateCrsr(); // und den akt. Updaten 114 } 115 return bRet; 116 } 117 118 119 sal_Bool SwCrsrShell::GoPrevCell() 120 { 121 sal_Bool bRet = sal_False; 122 const SwTableNode* pTblNd; 123 if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() )) 124 { 125 SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 126 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 127 bRet = pCrsr->GoPrevCell(); 128 if( bRet ) 129 UpdateCrsr(); // und den akt. Updaten 130 } 131 return bRet; 132 } 133 134 const SwFrm* lcl_FindMostUpperCellFrm( const SwFrm* pFrm ) 135 { 136 while ( pFrm && 137 ( !pFrm->IsCellFrm() || 138 !pFrm->GetUpper()->GetUpper()->IsTabFrm() || 139 pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) ) 140 { 141 pFrm = pFrm->GetUpper(); 142 } 143 return pFrm; 144 } 145 146 sal_Bool SwCrsrShell::_SelTblRowOrCol( bool bRow, bool bRowSimple ) 147 { 148 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen 149 SwFrm *pFrm = GetCurrFrm(); 150 if( !pFrm->IsInTab() ) 151 return sal_False; 152 153 const SwTabFrm* pTabFrm = pFrm->FindTabFrm(); 154 const SwTabFrm* pMasterTabFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm; 155 const SwTable* pTable = pTabFrm->GetTable(); 156 157 SET_CURR_SHELL( this ); 158 159 const SwTableBox* pStt = 0; 160 const SwTableBox* pEnd = 0; 161 162 // lasse ueber das Layout die Boxen suchen 163 SwSelBoxes aBoxes; 164 SwTblSearchType eType = bRow ? nsSwTblSearchType::TBLSEARCH_ROW : nsSwTblSearchType::TBLSEARCH_COL; 165 const bool bCheckProtected = !IsReadOnlyAvailable(); 166 167 if( bCheckProtected ) 168 eType = (SwTblSearchType)(eType | nsSwTblSearchType::TBLSEARCH_PROTECT); 169 170 if ( !bRowSimple ) 171 { 172 GetTblSel( *this, aBoxes, eType ); 173 174 if( !aBoxes.Count() ) 175 return sal_False; 176 177 pStt = aBoxes[0]; 178 pEnd = aBoxes[aBoxes.Count() - 1]; 179 } 180 // --> FME 2004-07-30 #i32329# Enhanced table selection 181 else if ( pTable->IsNewModel() ) 182 { 183 const SwShellCrsr *pCrsr = _GetCrsr(); 184 SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL; 185 pTable->CreateSelection( *pCrsr, aBoxes, eSearchType, bCheckProtected ); 186 if( !aBoxes.Count() ) 187 return sal_False; 188 189 pStt = aBoxes[0]; 190 pEnd = aBoxes[aBoxes.Count() - 1]; 191 } 192 else 193 { 194 const SwShellCrsr *pCrsr = _GetCrsr(); 195 const SwFrm* pStartFrm = pFrm; 196 const SwCntntNode *pCNd = pCrsr->GetCntntNode( sal_False ); 197 const SwFrm* pEndFrm = pCNd ? pCNd->getLayoutFrm( GetLayout(), &pCrsr->GetMkPos() ) : 0; 198 199 if ( bRow ) 200 { 201 pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm ); 202 pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm ); 203 } 204 205 if ( !pStartFrm || !pEndFrm ) 206 return sal_False; 207 208 const bool bVert = pFrm->ImplFindTabFrm()->IsVertical(); 209 210 // If we select upwards it is sufficient to set pStt and pEnd 211 // to the first resp. last box of the selection obtained from 212 // GetTblSel. However, selecting downwards requires the frames 213 // located at the corners of the selection. This does not work 214 // for column selections in vertical tables: 215 const bool bSelectUp = ( bVert && !bRow ) || 216 *pCrsr->GetPoint() <= *pCrsr->GetMark(); 217 SwCellFrms aCells; 218 GetTblSel( static_cast<const SwCellFrm*>(pStartFrm), 219 static_cast<const SwCellFrm*>(pEndFrm), 220 aBoxes, bSelectUp ? 0 : &aCells, eType ); 221 222 if( !aBoxes.Count() || ( !bSelectUp && 4 != aCells.Count() ) ) 223 return sal_False; 224 225 if ( bSelectUp ) 226 { 227 pStt = aBoxes[0]; 228 pEnd = aBoxes[aBoxes.Count() - 1]; 229 } 230 else 231 { 232 pStt = aCells[ bVert ? (bRow ? 0 : 3) : (bRow ? 2 : 1) ]->GetTabBox(); // will become point of table cursor 233 pEnd = aCells[ bVert ? (bRow ? 3 : 0) : (bRow ? 1 : 2) ]->GetTabBox(); // will become mark of table cursor 234 } 235 } 236 // <-- 237 238 // noch kein Tabellen-Cursor vorhanden, dann erzeuge einen 239 if( !pTblCrsr ) 240 { 241 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); 242 pCurCrsr->DeleteMark(); 243 pCurCrsr->SwSelPaintRects::Hide(); 244 } 245 246 pTblCrsr->DeleteMark(); 247 248 // dann setze mal Anfang und Ende der Spalte 249 pTblCrsr->GetPoint()->nNode = *pEnd->GetSttNd(); 250 pTblCrsr->Move( fnMoveForward, fnGoCntnt ); 251 pTblCrsr->SetMark(); 252 pTblCrsr->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode(); 253 pTblCrsr->Move( fnMoveBackward, fnGoCntnt ); 254 255 // set PtPos 'close' to the reference table, otherwise we might get problems with the 256 // repeated headlines check in UpdateCrsr(): 257 if ( !bRow ) 258 pTblCrsr->GetPtPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft(); 259 260 UpdateCrsr(); // und den akt. Updaten 261 return sal_True; 262 } 263 264 sal_Bool SwCrsrShell::SelTbl() 265 { 266 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen 267 SwFrm *pFrm = GetCurrFrm(); 268 if( !pFrm->IsInTab() ) 269 return sal_False; 270 271 const SwTabFrm *pTblFrm = pFrm->ImplFindTabFrm(); 272 const SwTabFrm* pMasterTabFrm = pTblFrm->IsFollow() ? pTblFrm->FindMaster( true ) : pTblFrm; 273 const SwTableNode* pTblNd = pTblFrm->GetTable()->GetTableNode(); 274 275 SET_CURR_SHELL( this ); 276 277 if( !pTblCrsr ) 278 { 279 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); 280 pCurCrsr->DeleteMark(); 281 pCurCrsr->SwSelPaintRects::Hide(); 282 } 283 284 pTblCrsr->DeleteMark(); 285 pTblCrsr->GetPoint()->nNode = *pTblNd; 286 pTblCrsr->Move( fnMoveForward, fnGoCntnt ); 287 pTblCrsr->SetMark(); 288 // set MkPos 'close' to the master table, otherwise we might get problems with the 289 // repeated headlines check in UpdateCrsr(): 290 pTblCrsr->GetMkPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft(); 291 pTblCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode(); 292 pTblCrsr->Move( fnMoveBackward, fnGoCntnt ); 293 UpdateCrsr(); // und den akt. Updaten 294 return sal_True; 295 } 296 297 298 sal_Bool SwCrsrShell::SelTblBox() 299 { 300 // if we're in a table, create a table cursor, and select the cell 301 // that the current cursor's point resides in 302 303 // search for start node of our table box. If not found, exit realy 304 const SwStartNode* pStartNode = 305 pCurCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode(); 306 307 #ifdef DBG_UTIL 308 // the old code checks whether we're in a table by asking the 309 // frame. This should yield the same result as searching for the 310 // table box start node, right? 311 SwFrm *pFrm = GetCurrFrm(); 312 DBG_ASSERT( !pFrm->IsInTab() == !(pStartNode != NULL), 313 "Schroedinger's table: We're in a box, and also we aren't." ); 314 #endif 315 316 if( pStartNode == NULL ) 317 return sal_False; 318 319 320 SET_CURR_SHELL( this ); 321 322 // create a table cursor, if there isn't one already 323 if( !pTblCrsr ) 324 { 325 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); 326 pCurCrsr->DeleteMark(); 327 pCurCrsr->SwSelPaintRects::Hide(); 328 } 329 330 // select the complete box with our shiny new pTblCrsr 331 // 1. delete mark, and move point to first content node in box 332 // 2. set mark, and move point to last content node in box 333 // 3. exchange 334 335 pTblCrsr->DeleteMark(); 336 *(pTblCrsr->GetPoint()) = SwPosition( *pStartNode ); 337 pTblCrsr->Move( fnMoveForward, fnGoNode ); 338 339 pTblCrsr->SetMark(); 340 *(pTblCrsr->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) ); 341 pTblCrsr->Move( fnMoveBackward, fnGoNode ); 342 343 pTblCrsr->Exchange(); 344 345 // with some luck, UpdateCrsr() will now update everything that 346 // needs updateing 347 UpdateCrsr(); 348 349 return sal_True; 350 } 351 352 // return the next non-protected cell inside a table 353 // rIdx - is on a table node 354 // return: 355 // true - Idx points to content in a suitable cell 356 // false - could not find a suitable cell 357 bool lcl_FindNextCell( SwNodeIndex& rIdx, sal_Bool bInReadOnly ) 358 { 359 // ueberpruefe geschuetzte Zellen 360 SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode 361 362 // the resulting cell should be in that table: 363 const SwTableNode* pTblNd = rIdx.GetNode().GetTableNode(); 364 365 if ( !pTblNd ) 366 { 367 ASSERT( false, "lcl_FindNextCell not celled with table start node!" ) 368 return false; 369 } 370 371 const SwNode* pTableEndNode = pTblNd->EndOfSectionNode(); 372 373 SwNodes& rNds = aTmp.GetNode().GetNodes(); 374 SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode(); 375 376 // no content node => go to next content node 377 if( !pCNd ) 378 pCNd = rNds.GoNext( &aTmp ); 379 380 // robust 381 if ( !pCNd ) 382 return false; 383 384 SwCntntFrm* pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); 385 386 if ( 0 == pFrm || pCNd->FindTableNode() != pTblNd || 387 (!bInReadOnly && pFrm->IsProtected() ) ) 388 { 389 // we are not located inside a 'valid' cell. We have to continue searching... 390 391 // skip behind current section. This might be the end of the table cell 392 // or behind a inner section or or or... 393 aTmp.Assign( *pCNd->EndOfSectionNode(), 1 ); 394 395 // loop to find a suitable cell... 396 for( ;; ) 397 { 398 SwNode* pNd = &aTmp.GetNode(); 399 400 // we break this loop if we reached the end of the table. 401 // to make this code even more robust, we also break if we are 402 // already behind the table end node: 403 if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() ) 404 return false; 405 406 // ok, get the next content node: 407 pCNd = aTmp.GetNode().GetCntntNode(); 408 if( 0 == pCNd ) 409 pCNd = rNds.GoNext( &aTmp ); 410 411 // robust: 412 if ( !pCNd ) 413 return false; 414 415 // check if we have found a suitable table cell: 416 pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); 417 418 if ( 0 != pFrm && pCNd->FindTableNode() == pTblNd && 419 (bInReadOnly || !pFrm->IsProtected() ) ) 420 { 421 // finally, we have found a suitable table cell => set index and return 422 rIdx = *pCNd; 423 return true; 424 } 425 426 // continue behind the current section: 427 aTmp.Assign( *pCNd->EndOfSectionNode(), +1 ); 428 } 429 } 430 431 rIdx = *pCNd; 432 return true; 433 } 434 435 // comments see lcl_FindNextCell 436 bool lcl_FindPrevCell( SwNodeIndex& rIdx, sal_Bool bInReadOnly ) 437 { 438 SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode 439 440 const SwNode* pTableEndNode = &rIdx.GetNode(); 441 const SwTableNode* pTblNd = pTableEndNode->StartOfSectionNode()->GetTableNode(); 442 443 if ( !pTblNd ) 444 { 445 ASSERT( false, "lcl_FindPrevCell not celled with table start node!" ) 446 return false; 447 } 448 449 SwNodes& rNds = aTmp.GetNode().GetNodes(); 450 SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode(); 451 452 if( !pCNd ) 453 pCNd = rNds.GoPrevious( &aTmp ); 454 455 if ( !pCNd ) 456 return false; 457 458 SwCntntFrm* pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); 459 460 if( 0 == pFrm || pCNd->FindTableNode() != pTblNd || 461 (!bInReadOnly && pFrm->IsProtected() )) 462 { 463 // skip before current section 464 aTmp.Assign( *pCNd->StartOfSectionNode(), -1 ); 465 for( ;; ) 466 { 467 SwNode* pNd = &aTmp.GetNode(); 468 469 if( pNd == pTblNd || pNd->GetIndex() < pTblNd->GetIndex() ) 470 return false; 471 472 pCNd = aTmp.GetNode().GetCntntNode(); 473 if( 0 == pCNd ) 474 pCNd = rNds.GoPrevious( &aTmp ); 475 476 if ( !pCNd ) 477 return false; 478 479 pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ); 480 481 if( 0 != pFrm && pCNd->FindTableNode() == pTblNd && 482 (bInReadOnly || !pFrm->IsProtected() ) ) 483 { 484 rIdx = *pCNd; 485 return true; // Ok, nicht geschuetzt 486 } 487 aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 ); 488 } 489 } 490 491 rIdx = *pCNd; 492 return true; 493 } 494 495 496 sal_Bool GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, 497 sal_Bool bInReadOnly ) 498 { 499 SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode ); 500 501 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); 502 if( pTblNd ) 503 { 504 // #i26532#: If we are inside a table, we may not go backward 505 // to the table start node, because we would miss any tables 506 // inside this table. 507 SwTableNode* pInnerTblNd = 0; 508 SwNodeIndex aTmpIdx( aIdx ); 509 while( aTmpIdx.GetIndex() && 510 0 == ( pInnerTblNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) ) 511 aTmpIdx--; 512 513 if( pInnerTblNd == pTblNd ) 514 aIdx.Assign( *pTblNd, - 1 ); 515 } 516 517 do { 518 while( aIdx.GetIndex() && 519 0 == ( pTblNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) ) 520 aIdx--; 521 522 if( pTblNd ) // gibt einen weiteren TableNode ? 523 { 524 if( fnPosTbl == fnMoveForward ) // an Anfang ? 525 { 526 aIdx = *aIdx.GetNode().StartOfSectionNode(); 527 if( !lcl_FindNextCell( aIdx, bInReadOnly )) 528 { 529 // Tabelle ueberspringen 530 aIdx.Assign( *pTblNd, -1 ); 531 continue; 532 } 533 } 534 else 535 { 536 // ueberpruefe geschuetzte Zellen 537 if( !lcl_FindNextCell( aIdx, bInReadOnly )) 538 { 539 // Tabelle ueberspringen 540 aIdx.Assign( *pTblNd, -1 ); 541 continue; 542 } 543 } 544 545 SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode(); 546 if ( pTxtNode ) 547 { 548 rCurCrsr.GetPoint()->nNode = *pTxtNode; 549 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? 550 pTxtNode->Len() : 551 0 ); 552 } 553 return sal_True; 554 } 555 } while( pTblNd ); 556 557 return sal_False; 558 } 559 560 561 sal_Bool GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, 562 sal_Bool bInReadOnly ) 563 { 564 SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode ); 565 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); 566 567 if( pTblNd ) 568 aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 ); 569 570 sal_uLong nLastNd = rCurCrsr.GetDoc()->GetNodes().Count() - 1; 571 do { 572 while( aIdx.GetIndex() < nLastNd && 573 0 == ( pTblNd = aIdx.GetNode().GetTableNode()) ) 574 aIdx++; 575 if( pTblNd ) // gibt einen weiteren TableNode ? 576 { 577 if( fnPosTbl == fnMoveForward ) // an Anfang ? 578 { 579 if( !lcl_FindNextCell( aIdx, bInReadOnly )) 580 { 581 // Tabelle ueberspringen 582 aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 ); 583 continue; 584 } 585 } 586 else 587 { 588 aIdx = *aIdx.GetNode().EndOfSectionNode(); 589 // ueberpruefe geschuetzte Zellen 590 if( !lcl_FindNextCell( aIdx, bInReadOnly )) 591 { 592 // Tabelle ueberspringen 593 aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 ); 594 continue; 595 } 596 } 597 598 SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode(); 599 if ( pTxtNode ) 600 { 601 rCurCrsr.GetPoint()->nNode = *pTxtNode; 602 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? 603 pTxtNode->Len() : 604 0 ); 605 } 606 return sal_True; 607 } 608 } while( pTblNd ); 609 610 return sal_False; 611 } 612 613 614 sal_Bool GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl, 615 sal_Bool bInReadOnly ) 616 { 617 SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode(); 618 if( !pTblNd ) 619 return sal_False; 620 621 SwTxtNode* pTxtNode = 0; 622 if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle 623 { 624 SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() ); 625 if( !lcl_FindPrevCell( aIdx, bInReadOnly )) 626 return sal_False; 627 pTxtNode = aIdx.GetNode().GetTxtNode(); 628 } 629 else 630 { 631 SwNodeIndex aIdx( *pTblNd ); 632 if( !lcl_FindNextCell( aIdx, bInReadOnly )) 633 return sal_False; 634 pTxtNode = aIdx.GetNode().GetTxtNode(); 635 } 636 637 if ( pTxtNode ) 638 { 639 rCurCrsr.GetPoint()->nNode = *pTxtNode; 640 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ? 641 pTxtNode->Len() : 642 0 ); 643 } 644 645 return sal_True; 646 } 647 648 649 sal_Bool SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl ) 650 { 651 sal_Bool bRet = sal_False; 652 SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this); 653 654 if( pTblCrsr || !HasMark() ) // nur wenn kein Mark oder ein TblCrsr 655 { 656 SwCrsrSaveState aSaveState( *this ); 657 bRet = (*fnWhichTbl)( *this, fnPosTbl, IsReadOnlyAvailable() ) && 658 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION | 659 nsSwCursorSelOverFlags::SELOVER_TOGGLE ); 660 } 661 return bRet; 662 } 663 664 sal_Bool SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl ) 665 { 666 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen 667 668 SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr; 669 sal_Bool bCheckPos, bRet; 670 sal_uLong nPtNd = 0; 671 xub_StrLen nPtCnt = 0; 672 673 if( !pTblCrsr && pCurCrsr->HasMark() ) // wenn Mark und kein TblCrsr, 674 { 675 // dann auf jedenfall in den Tabellen-Modus schalten 676 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() ); 677 pCurCrsr->DeleteMark(); 678 pCurCrsr->SwSelPaintRects::Hide(); 679 pTblCrsr->SetMark(); 680 pCrsr = pTblCrsr; 681 bCheckPos = sal_False; 682 } 683 else 684 { 685 bCheckPos = sal_True; 686 nPtNd = pCrsr->GetPoint()->nNode.GetIndex(); 687 nPtCnt = pCrsr->GetPoint()->nContent.GetIndex(); 688 } 689 690 bRet = pCrsr->MoveTable( fnWhichTbl, fnPosTbl ); 691 692 if( bRet ) 693 { 694 //JP 28.10.97: Bug 45028 - die "oberste" Position setzen fuer 695 // wiederholte Kopfzeilen 696 pCrsr->GetPtPos() = Point(); 697 698 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY); 699 700 if( bCheckPos && 701 pCrsr->GetPoint()->nNode.GetIndex() == nPtNd && 702 pCrsr->GetPoint()->nContent.GetIndex() == nPtCnt ) 703 bRet = sal_False; 704 } 705 return bRet; 706 } 707 708 709 sal_Bool SwCrsrShell::IsTblComplex() const 710 { 711 SwFrm *pFrm = GetCurrFrm( sal_False ); 712 if ( pFrm && pFrm->IsInTab() ) 713 return pFrm->FindTabFrm()->GetTable()->IsTblComplex(); 714 return sal_False; 715 } 716 717 718 sal_Bool SwCrsrShell::IsTblComplexForChart() 719 { 720 sal_Bool bRet = sal_False; 721 722 StartAction(); // IsTblComplexForChart() may trigger table formatting 723 // we better do that inside an action 724 725 const SwTableNode* pTNd = pCurCrsr->GetPoint()->nNode.GetNode().FindTableNode(); 726 if( pTNd ) 727 { 728 // wir stehen in der Tabelle, dann teste mal, ob die Tabelle oder die 729 // Selektion ausgeglichen ist. 730 String sSel; 731 if( pTblCrsr ) 732 sSel = GetBoxNms(); 733 bRet = pTNd->GetTable().IsTblComplexForChart( sSel ); 734 } 735 736 EndAction(); 737 738 return bRet; 739 } 740 741 String SwCrsrShell::GetBoxNms() const 742 { 743 String sNm; 744 const SwPosition* pPos; 745 SwFrm* pFrm; 746 747 if( IsTableMode() ) 748 { 749 SwCntntNode *pCNd = pTblCrsr->Start()->nNode.GetNode().GetCntntNode(); 750 pFrm = pCNd ? pCNd->getLayoutFrm( GetLayout() ) : 0; 751 if( !pFrm ) 752 return sNm; 753 754 do { 755 pFrm = pFrm->GetUpper(); 756 } while ( pFrm && !pFrm->IsCellFrm() ); 757 758 ASSERT( pFrm, "kein Frame zur Box" ); 759 sNm = ((SwCellFrm*)pFrm)->GetTabBox()->GetName(); 760 sNm += ':'; 761 pPos = pTblCrsr->End(); 762 } 763 else 764 { 765 const SwTableNode* pTblNd = IsCrsrInTbl(); 766 if( !pTblNd ) 767 return sNm; 768 pPos = GetCrsr()->GetPoint(); 769 } 770 771 SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode(); 772 pFrm = pCNd ? pCNd->getLayoutFrm( GetLayout() ) : 0; 773 774 if( pFrm ) 775 { 776 do { 777 pFrm = pFrm->GetUpper(); 778 } while ( pFrm && !pFrm->IsCellFrm() ); 779 780 if( pFrm ) 781 sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName(); 782 } 783 return sNm; 784 } 785 786 787 sal_Bool SwCrsrShell::GotoTable( const String& rName ) 788 { 789 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, 790 sal_Bool bRet = !pTblCrsr && pCurCrsr->GotoTable( rName ); 791 if( bRet ) 792 { 793 pCurCrsr->GetPtPos() = Point(); 794 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE | 795 SwCrsrShell::READONLY ); // und den akt. Updaten 796 } 797 return bRet; 798 } 799 800 801 sal_Bool SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos ) 802 { 803 if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() ) 804 return sal_False; 805 806 // ueberpruefe, ob der Box Inhalt mit dem angegebenen Format der Box 807 // ueber einstimmt. Wenn nicht, setze neu 808 SwTableBox* pChkBox = 0; 809 SwStartNode* pSttNd = 0; 810 if( !pPos ) 811 { 812 // gesicherte Position heraus holen. 813 if( pBoxIdx && pBoxPtr && 814 0 != ( pSttNd = pBoxIdx->GetNode().GetStartNode() ) && 815 SwTableBoxStartNode == pSttNd->GetStartNodeType() && 816 pBoxPtr == pSttNd->FindTableNode()->GetTable(). 817 GetTblBox( pBoxIdx->GetIndex() ) ) 818 pChkBox = pBoxPtr; 819 } 820 else if( 0 != ( pSttNd = pPos->nNode.GetNode(). 821 FindSttNodeByType( SwTableBoxStartNode )) ) 822 { 823 pChkBox = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() ); 824 } 825 826 827 // Box mehr als 1 Absatz? 828 if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() ) 829 pChkBox = 0; 830 831 // jetzt sollten wir mal die Pointer zerstoeren, bevor eine erneute 832 // Actionklammerung kommt. 833 if( !pPos && !pChkBox ) 834 ClearTblBoxCntnt(); 835 836 // liegt der Cursor nicht mehr in dem Bereich ? 837 if( pChkBox && !pPos && 838 ( pCurCrsr->HasMark() || pCurCrsr->GetNext() != pCurCrsr || 839 pSttNd->GetIndex() + 1 == pCurCrsr->GetPoint()->nNode.GetIndex() )) 840 pChkBox = 0; 841 842 //JP 12.01.99: hat sich der Inhalt der Box ueberhaupt veraendert? 843 // Ist wichtig, wenn z.B. Undo nicht den richtigen Inhalt wieder 844 // herstellen konnte. 845 if( pChkBox ) 846 { 847 const SwTxtNode* pNd = GetDoc()->GetNodes()[ 848 pSttNd->GetIndex() + 1 ]->GetTxtNode(); 849 if( !pNd || 850 ( pNd->GetTxt() == ViewShell::GetShellRes()->aCalc_Error && 851 SFX_ITEM_SET == pChkBox->GetFrmFmt()-> 852 GetItemState( RES_BOXATR_FORMULA )) ) 853 pChkBox = 0; 854 } 855 856 if( pChkBox ) 857 { 858 // jetzt sollten wir mal die Pointer zerstoeren, bevor ein weiterer 859 // aufruf kommt. 860 ClearTblBoxCntnt(); 861 StartAction(); 862 GetDoc()->ChkBoxNumFmt( *pChkBox, sal_True ); 863 EndAction(); 864 } 865 866 return 0 != pChkBox; 867 } 868 869 870 void SwCrsrShell::SaveTblBoxCntnt( const SwPosition* pPos ) 871 { 872 if( IsSelTblCells() || !IsAutoUpdateCells() ) 873 return ; 874 875 if( !pPos ) 876 pPos = pCurCrsr->GetPoint(); 877 878 SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode ); 879 880 sal_Bool bCheckBox = sal_False; 881 if( pSttNd && pBoxIdx ) 882 { 883 if( pSttNd == &pBoxIdx->GetNode() ) 884 pSttNd = 0; // die haben wir schon 885 else 886 bCheckBox = sal_True; 887 } 888 else 889 bCheckBox = 0 != pBoxIdx; 890 891 if( bCheckBox ) 892 { 893 // pBoxIdx Checken 894 SwPosition aPos( *pBoxIdx ); 895 CheckTblBoxCntnt( &aPos ); 896 } 897 898 if( pSttNd ) 899 { 900 pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() ); 901 902 if( pBoxIdx ) 903 *pBoxIdx = *pSttNd; 904 else 905 pBoxIdx = new SwNodeIndex( *pSttNd ); 906 } 907 } 908 909 910 void SwCrsrShell::ClearTblBoxCntnt() 911 { 912 delete pBoxIdx, pBoxIdx = 0; 913 pBoxPtr = 0; 914 } 915 916 sal_Bool SwCrsrShell::EndAllTblBoxEdit() 917 { 918 sal_Bool bRet = sal_False; 919 ViewShell *pSh = this; 920 do { 921 if( pSh->IsA( TYPE( SwCrsrShell ) ) ) 922 bRet |= ((SwCrsrShell*)pSh)->CheckTblBoxCntnt( 923 ((SwCrsrShell*)pSh)->pCurCrsr->GetPoint() ); 924 925 } while( this != (pSh = (ViewShell *)pSh->GetNext()) ); 926 return bRet; 927 } 928 929 930 931 932