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 31 32 #include <hintids.hxx> 33 #include <editeng/protitem.hxx> 34 #include <com/sun/star/i18n/WordType.hdl> 35 #include <com/sun/star/i18n/CharType.hdl> 36 #include <unotools/charclass.hxx> 37 #include <svl/ctloptions.hxx> 38 #include <swmodule.hxx> 39 #include <fmtcntnt.hxx> 40 #include <swtblfmt.hxx> 41 #include <swcrsr.hxx> 42 #include <unocrsr.hxx> 43 #include <doc.hxx> 44 #include <IDocumentUndoRedo.hxx> 45 #include <docary.hxx> 46 #include <ndtxt.hxx> 47 #include <section.hxx> 48 #include <swtable.hxx> 49 #include <cntfrm.hxx> 50 #include <rootfrm.hxx> 51 #include <txtfrm.hxx> 52 #include <scriptinfo.hxx> 53 #include <crstate.hxx> 54 #include <docsh.hxx> 55 #include <viewsh.hxx> 56 #include <frmatr.hxx> 57 #include <breakit.hxx> 58 #include <crsskip.hxx> 59 #include <vcl/msgbox.hxx> 60 #include <mdiexp.hxx> // ...Percent() 61 #include <statstr.hrc> // ResId fuer Statusleiste 62 #include <redline.hxx> // SwRedline 63 64 65 using namespace ::com::sun::star::i18n; 66 67 68 static const sal_uInt16 coSrchRplcThreshold = 60000; 69 70 struct _PercentHdl 71 { 72 SwDocShell* pDSh; 73 sal_uLong nActPos; 74 sal_Bool bBack, bNodeIdx; 75 76 _PercentHdl( sal_uLong nStt, sal_uLong nEnd, SwDocShell* pSh ) 77 : pDSh( pSh ) 78 { 79 nActPos = nStt; 80 if( 0 != ( bBack = (nStt > nEnd )) ) 81 { 82 sal_uLong n = nStt; nStt = nEnd; nEnd = n; 83 } 84 ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, 0 ); 85 } 86 87 _PercentHdl( const SwPaM& rPam ) 88 : pDSh( (SwDocShell*)rPam.GetDoc()->GetDocShell() ) 89 { 90 sal_uLong nStt, nEnd; 91 if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode ) 92 { 93 bNodeIdx = sal_False; 94 nStt = rPam.GetMark()->nContent.GetIndex(); 95 nEnd = rPam.GetPoint()->nContent.GetIndex(); 96 } 97 else 98 { 99 bNodeIdx = sal_True; 100 nStt = rPam.GetMark()->nNode.GetIndex(); 101 nEnd = rPam.GetPoint()->nNode.GetIndex(); 102 } 103 nActPos = nStt; 104 if( 0 != ( bBack = (nStt > nEnd )) ) 105 { 106 sal_uLong n = nStt; nStt = nEnd; nEnd = n; 107 } 108 ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh ); 109 } 110 111 ~_PercentHdl() { ::EndProgress( pDSh ); } 112 113 void NextPos( sal_uLong nPos ) const 114 { ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); } 115 116 void NextPos( SwPosition& rPos ) const 117 { 118 sal_uLong nPos; 119 if( bNodeIdx ) 120 nPos = rPos.nNode.GetIndex(); 121 else 122 nPos = rPos.nContent.GetIndex(); 123 ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); 124 } 125 }; 126 127 SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing, bool bColumnSel ) 128 : SwPaM( rPos, pRing ), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ), 129 mbColumnSelection( bColumnSel ) 130 { 131 } 132 133 // @@@ semantic: no copy ctor. 134 SwCursor::SwCursor( SwCursor& rCpy ) 135 : SwPaM( rCpy ), pSavePos( 0 ), mnRowSpanOffset( rCpy.mnRowSpanOffset ), 136 nCursorBidiLevel( rCpy.nCursorBidiLevel ), mbColumnSelection( rCpy.mbColumnSelection ) 137 { 138 } 139 140 SwCursor::~SwCursor() 141 { 142 while( pSavePos ) 143 { 144 _SwCursor_SavePos* pNxt = pSavePos->pNext; 145 delete pSavePos; 146 pSavePos = pNxt; 147 } 148 } 149 150 SwCursor* SwCursor::Create( SwPaM* pRing ) const 151 { 152 return new SwCursor( *GetPoint(), pRing, false ); 153 } 154 155 bool SwCursor::IsReadOnlyAvailable() const 156 { 157 return false; 158 } 159 160 sal_Bool SwCursor::IsSkipOverHiddenSections() const 161 { 162 return sal_True; 163 } 164 165 sal_Bool SwCursor::IsSkipOverProtectSections() const 166 { 167 return !IsReadOnlyAvailable(); 168 } 169 170 171 // Sicher die aktuelle Position, damit ggfs. auf diese zurueck 172 // gefallen werden kann. Die SavePos Objekte werden als Stack verwaltet, 173 // damit das auch alles bei verschachtelten Aufrufen funktioniert. 174 // Das CreateNewSavePos ist virtual, damit abgeleitete Klassen vom Cursor 175 // gegebenenfalls eigene SaveObjecte anlegen und in den virtuellen 176 // Check-Routinen verwenden koennen. 177 178 void SwCursor::SaveState() 179 { 180 _SwCursor_SavePos* pNew = CreateNewSavePos(); 181 pNew->pNext = pSavePos; 182 pSavePos = pNew; 183 } 184 185 void SwCursor::RestoreState() 186 { 187 if( pSavePos ) // Robust 188 { 189 _SwCursor_SavePos* pDel = pSavePos; 190 pSavePos = pSavePos->pNext; 191 delete pDel; 192 } 193 } 194 195 _SwCursor_SavePos* SwCursor::CreateNewSavePos() const 196 { 197 return new _SwCursor_SavePos( *this ); 198 } 199 200 // stelle fest, ob sich der Point ausserhalb des Content-Bereichs 201 // vom Nodes-Array befindet 202 sal_Bool SwCursor::IsNoCntnt() const 203 { 204 return GetPoint()->nNode.GetIndex() < 205 GetDoc()->GetNodes().GetEndOfExtras().GetIndex(); 206 } 207 208 bool SwCursor::IsSelOvrCheck(int) 209 { 210 return false; 211 } 212 213 // extracted from IsSelOvr() 214 bool SwTableCursor::IsSelOvrCheck(int eFlags) 215 { 216 SwNodes& rNds = GetDoc()->GetNodes(); 217 // check sections of nodes array 218 if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION & eFlags) 219 && HasMark() ) 220 { 221 SwNodeIndex aOldPos( rNds, GetSavePos()->nNode ); 222 if( !CheckNodesRange( aOldPos, GetPoint()->nNode, sal_True )) 223 { 224 GetPoint()->nNode = aOldPos; 225 GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt ); 226 return true; 227 } 228 } 229 return SwCursor::IsSelOvrCheck(eFlags); 230 } 231 232 sal_Bool SwCursor::IsSelOvr( int eFlags ) 233 { 234 SwDoc* pDoc = GetDoc(); 235 SwNodes& rNds = pDoc->GetNodes(); 236 237 sal_Bool bSkipOverHiddenSections = IsSkipOverHiddenSections(); 238 sal_Bool bSkipOverProtectSections = IsSkipOverProtectSections(); 239 240 if ( IsSelOvrCheck( eFlags ) ) 241 { 242 return sal_True; 243 } 244 245 // neu: Bereiche ueberpruefen 246 // Anfang 247 if( pSavePos->nNode != GetPoint()->nNode.GetIndex() && 248 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt 249 ( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() )) 250 { 251 // teste doch mal die neuen Sections: 252 SwNodeIndex& rPtIdx = GetPoint()->nNode; 253 const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode(); 254 if( pSectNd && 255 ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) || 256 (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() ))) 257 { 258 if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) ) 259 { 260 // dann wars das schon 261 RestoreSavePos(); 262 return sal_True; 263 } 264 265 // dann setze den Cursor auf die neue Position: 266 SwNodeIndex aIdx( rPtIdx ); 267 xub_StrLen nCntntPos = pSavePos->nCntnt; 268 int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex(); 269 SwCntntNode* pCNd = bGoNxt 270 ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections) 271 : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections); 272 if( !pCNd && ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION & eFlags )) 273 { 274 bGoNxt = !bGoNxt; 275 pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections) 276 : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections); 277 } 278 279 int bIsValidPos = 0 != pCNd; 280 sal_Bool bValidNodesRange = bIsValidPos && 281 ::CheckNodesRange( rPtIdx, aIdx, sal_True ); 282 if( !bValidNodesRange ) 283 { 284 rPtIdx = pSavePos->nNode; 285 if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) ) 286 { 287 bIsValidPos = sal_False; 288 nCntntPos = 0; 289 rPtIdx = aIdx; 290 if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) ) 291 { 292 // dann auf den Anfang vom Doc 293 rPtIdx = rNds.GetEndOfExtras(); 294 pCNd = rNds.GoNext( &rPtIdx ); 295 } 296 } 297 } 298 299 // ContentIndex noch anmelden: 300 xub_StrLen nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nCntntPos; 301 GetPoint()->nContent.Assign( pCNd, nTmpPos ); 302 if( !bIsValidPos || !bValidNodesRange || 303 // sollten wir in einer Tabelle gelandet sein? 304 IsInProtectTable( sal_True ) ) 305 return sal_True; 306 } 307 308 // oder sollte eine geschuetzte Section innerhalb der Selektion liegen? 309 if( HasMark() && bSkipOverProtectSections) 310 { 311 sal_uLong nSttIdx = GetMark()->nNode.GetIndex(), 312 nEndIdx = GetPoint()->nNode.GetIndex(); 313 if( nEndIdx <= nSttIdx ) 314 { 315 sal_uLong nTmp = nSttIdx; 316 nSttIdx = nEndIdx; 317 nEndIdx = nTmp; 318 } 319 320 const SwSectionFmts& rFmts = pDoc->GetSections(); 321 for( sal_uInt16 n = 0; n < rFmts.Count(); ++n ) 322 { 323 const SwSectionFmt* pFmt = rFmts[n]; 324 const SvxProtectItem& rProtect = pFmt->GetProtect(); 325 if( rProtect.IsCntntProtected() ) 326 { 327 const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False); 328 ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" ); 329 sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex(); 330 if( nSttIdx <= nIdx && nEndIdx >= nIdx ) 331 { 332 // ist es keine gelinkte Section, dann kann sie auch 333 // nicht mitselektiert werden 334 const SwSection& rSect = *pFmt->GetSection(); 335 if( CONTENT_SECTION == rSect.GetType() ) 336 { 337 RestoreSavePos(); 338 return sal_True; 339 } 340 } 341 } 342 } 343 } 344 345 } 346 // Ende 347 // neu: Bereiche ueberpruefen 348 349 const SwNode* pNd = &GetPoint()->nNode.GetNode(); 350 if( pNd->IsCntntNode() && !dynamic_cast<SwUnoCrsr*>(this) ) 351 { 352 const SwCntntFrm* pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ); 353 if( pFrm && pFrm->IsValid() && 0 == pFrm->Frm().Height() && 354 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) ) 355 { 356 // skip to the next / prev valid paragraph with a layout 357 SwNodeIndex& rPtIdx = GetPoint()->nNode; 358 int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex(); 359 while( 0 != ( pFrm = ( bGoNxt ? pFrm->GetNextCntntFrm() 360 : pFrm->GetPrevCntntFrm() )) && 361 0 == pFrm->Frm().Height() ) 362 ; 363 364 // --> LIJIAN/FME 2007-11-27 #i72394# skip to prev /next valid paragraph 365 // with a layout in case the first search did not succeed: 366 if( !pFrm ) 367 { 368 bGoNxt = !bGoNxt; 369 pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ); 370 while ( pFrm && 0 == pFrm->Frm().Height() ) 371 { 372 pFrm = bGoNxt ? pFrm->GetNextCntntFrm() 373 : pFrm->GetPrevCntntFrm(); 374 } 375 } 376 // <-- 377 378 SwCntntNode* pCNd; 379 if( pFrm && 0 != (pCNd = (SwCntntNode*)pFrm->GetNode()) ) 380 { 381 // set this cntntNode as new position 382 rPtIdx = *pCNd; 383 pNd = pCNd; 384 385 // ContentIndex noch anmelden: 386 xub_StrLen nTmpPos = bGoNxt ? 0 : pCNd->Len(); 387 GetPoint()->nContent.Assign( pCNd, nTmpPos ); 388 389 // sollten wir in einer Tabelle gelandet sein? 390 if( IsInProtectTable( sal_True ) ) 391 pFrm = 0; 392 } 393 } 394 395 if( !pFrm ) 396 { 397 DeleteMark(); 398 RestoreSavePos(); 399 return sal_True; // ohne Frames geht gar nichts! 400 } 401 } 402 403 // darf der Cursor in geschuetzen "Nodes" stehen? 404 if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) && !IsAtValidPos() ) 405 { 406 DeleteMark(); 407 RestoreSavePos(); 408 return sal_True; 409 } 410 411 if( !HasMark() ) 412 return sal_False; 413 414 //JP 19.08.98: teste mal auf ungueltige Selektion - sprich ueber 415 // GrundSections: 416 if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, sal_True )) 417 { 418 DeleteMark(); 419 RestoreSavePos(); 420 return sal_True; // ohne Frames geht gar nichts! 421 } 422 423 const SwTableNode* pPtNd = pNd->FindTableNode(); 424 425 if( (pNd = &GetMark()->nNode.GetNode())->IsCntntNode() && 426 !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ) && !dynamic_cast<SwUnoCrsr*>(this) ) 427 { 428 DeleteMark(); 429 RestoreSavePos(); 430 return sal_True; // ohne Frames geht gar nichts! 431 } 432 433 const SwTableNode* pMrkNd = pNd->FindTableNode(); 434 435 // beide in keinem oder beide im gleichen TableNode 436 if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd ) 437 return sal_False; 438 439 // in unterschiedlichen Tabellen oder nur Mark in der Tabelle 440 if( ( pPtNd && pMrkNd ) || pMrkNd ) 441 { // dann lasse das nicht zu, alte Pos zurueck 442 RestoreSavePos(); 443 // Crsr bleibt an der alten Position 444 return sal_True; 445 } 446 447 // ACHTUNG: dieses kann nicht im TableMode geschehen !! 448 if( pPtNd ) // nur Point in Tabelle, dann gehe hinter/vor diese 449 { 450 if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) 451 { 452 sal_Bool bSelTop = GetPoint()->nNode.GetIndex() < 453 (( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags ) ? pSavePos->nNode 454 : GetMark()->nNode.GetIndex()); 455 456 do { 457 // in Schleife fuer Tabelle hinter Tabelle 458 sal_uLong nSEIdx = pPtNd->EndOfSectionIndex(); 459 sal_uLong nSttEndTbl = nSEIdx + 1; // dflt. Sel. nach unten 460 461 if( bSelTop ) // Sel. nach oben 462 nSttEndTbl = rNds[ nSEIdx ]->StartOfSectionIndex() - 1; 463 464 GetPoint()->nNode = nSttEndTbl; 465 const SwNode* pMyNd = GetNode(); 466 467 if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() && 468 pMyNd->StartOfSectionNode()->IsSectionNode() ) ) 469 { 470 // die lassen wir zu: 471 pMyNd = bSelTop 472 ? rNds.GoPrevSection( &GetPoint()->nNode,sal_True,sal_False ) 473 : rNds.GoNextSection( &GetPoint()->nNode,sal_True,sal_False ); 474 475 /* #i12312# Handle failure of Go{Prev|Next}Section */ 476 if ( 0 == pMyNd) 477 break; 478 479 if( 0 != ( pPtNd = pMyNd->FindTableNode() )) 480 continue; 481 } 482 483 if( pMyNd->IsCntntNode() && // ist es ein ContentNode ?? 484 ::CheckNodesRange( GetMark()->nNode, 485 GetPoint()->nNode, sal_True )) 486 { 487 // TABLE IN TABLE 488 const SwTableNode* pOuterTableNd = pMyNd->FindTableNode(); 489 if ( pOuterTableNd ) 490 pMyNd = pOuterTableNd; 491 else 492 { 493 SwCntntNode* pCNd = (SwCntntNode*)pMyNd; 494 xub_StrLen nTmpPos = bSelTop ? pCNd->Len() : 0; 495 GetPoint()->nContent.Assign( pCNd, nTmpPos ); 496 return sal_False; 497 } 498 } 499 if( bSelTop 500 ? ( !pMyNd->IsEndNode() || 0 == ( pPtNd = pMyNd->FindTableNode() )) 501 : 0 == ( pPtNd = pMyNd->GetTableNode() )) 502 break; 503 } while( sal_True ); 504 } 505 506 // dann verbleibe auf der alten Position 507 RestoreSavePos(); 508 return sal_True; // Crsr bleibt an der alten Position 509 } 510 return sal_False; // was bleibt noch ?? 511 } 512 513 #if defined( UNX ) 514 #define IDX (*pCellStt) 515 #else 516 #define IDX aCellStt 517 #endif 518 519 520 sal_Bool SwCursor::IsInProtectTable( sal_Bool bMove, sal_Bool bChgCrsr ) 521 { 522 SwCntntNode* pCNd = GetCntntNode(); 523 if( !pCNd ) 524 return sal_False; 525 526 // No table, no protected cell: 527 const SwTableNode* pTableNode = pCNd->FindTableNode(); 528 if ( !pTableNode ) 529 return sal_False; 530 531 // Current position == last save position? 532 if ( pSavePos->nNode == GetPoint()->nNode.GetIndex() ) 533 return sal_False; 534 535 // Check for convered cell: 536 bool bInCoveredCell = false; 537 const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode(); 538 ASSERT( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" ) 539 const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTblBox( pTmpSttNode->GetIndex() ) : 0; //Robust #151355 540 if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270 541 bInCoveredCell = true; 542 543 // Positions of covered cells are not acceptable: 544 if ( !bInCoveredCell ) 545 { 546 // Position not protected? 547 if ( !pCNd->IsProtect() ) 548 return sal_False; 549 550 // Cursor in protected cells allowed? 551 if ( IsReadOnlyAvailable() ) 552 return sal_False; 553 } 554 555 // If we reach this point, we are in a protected or covered table cell! 556 557 if( !bMove ) 558 { 559 if( bChgCrsr ) 560 // restore the last save position 561 RestoreSavePos(); 562 return sal_True; // Crsr bleibt an der alten Position 563 } 564 565 // wir stehen in einer geschuetzten TabellenZelle 566 // von Oben nach Unten Traveln ? 567 if( pSavePos->nNode < GetPoint()->nNode.GetIndex() ) 568 { 569 // suche die naechste "gueltige" Box 570 571 // folgt nach dem EndNode der Zelle ein weiterer StartNode, dann 572 // gibt es auch eine naechste Zelle 573 #if defined( UNX ) 574 SwNodeIndex* pCellStt = new SwNodeIndex( *GetNode()-> 575 FindTableBoxStartNode()->EndOfSectionNode(), 1 ); 576 #else 577 SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode()->EndOfSectionNode(), 1 ); 578 #endif 579 sal_Bool bProt = sal_True; 580 GoNextCell: 581 do { 582 if( !IDX.GetNode().IsStartNode() ) 583 break; 584 IDX++; 585 if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() )) 586 pCNd = IDX.GetNodes().GoNext( &IDX ); 587 if( 0 == ( bProt = pCNd->IsProtect() )) 588 break; 589 IDX.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 ); 590 } while( bProt ); 591 592 SetNextCrsr: 593 if( !bProt ) // eine freie Zelle gefunden 594 { 595 GetPoint()->nNode = IDX; 596 #if defined( UNX ) 597 delete pCellStt; 598 #endif 599 SwCntntNode* pTmpCNd = GetCntntNode(); 600 if( pTmpCNd ) 601 { 602 GetPoint()->nContent.Assign( pTmpCNd, 0 ); 603 return sal_False; 604 } 605 return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 606 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ); 607 } 608 // am Ende der Tabelle, also setze hinter diese 609 IDX++; // auf den naechsten Node 610 SwNode* pNd; 611 if( ( pNd = &IDX.GetNode())->IsEndNode() || HasMark()) 612 { 613 // Tabelle allein in einem FlyFrame oder SSelection, 614 // dann verbleibe auf der alten Position 615 if( bChgCrsr ) 616 RestoreSavePos(); 617 #if defined( UNX ) 618 delete pCellStt; 619 #endif 620 return sal_True; // Crsr bleibt an der alten Position 621 } 622 else if( pNd->IsTableNode() && IDX++ ) 623 goto GoNextCell; 624 625 bProt = sal_False; // Index steht jetzt auf einem ContentNode 626 goto SetNextCrsr; 627 } 628 629 // suche die vorherige "gueltige" Box 630 { 631 // liegt vor dem StartNode der Zelle ein weiterer EndNode, dann 632 // gibt es auch eine vorherige Zelle 633 #if defined( UNX ) 634 SwNodeIndex* pCellStt = new SwNodeIndex( 635 *GetNode()->FindTableBoxStartNode(), -1 ); 636 #else 637 SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode(), -1 ); 638 #endif 639 SwNode* pNd; 640 sal_Bool bProt = sal_True; 641 GoPrevCell: 642 do { 643 if( !( pNd = &IDX.GetNode())->IsEndNode() ) 644 break; 645 IDX.Assign( *pNd->StartOfSectionNode(), +1 ); 646 if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() )) 647 pCNd = pNd->GetNodes().GoNext( &IDX ); 648 if( 0 == ( bProt = pCNd->IsProtect() )) 649 break; 650 IDX.Assign( *pNd->FindTableBoxStartNode(), -1 ); 651 } while( bProt ); 652 653 SetPrevCrsr: 654 if( !bProt ) // eine freie Zelle gefunden 655 { 656 GetPoint()->nNode = IDX; 657 #if defined( UNX ) 658 delete pCellStt; 659 #endif 660 SwCntntNode* pTmpCNd = GetCntntNode(); 661 if( pTmpCNd ) 662 { 663 GetPoint()->nContent.Assign( pTmpCNd, 0 ); 664 return sal_False; 665 } 666 return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 667 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ); 668 } 669 // am Start der Tabelle, also setze vor diese 670 IDX--; // auf den naechsten Node 671 if( ( pNd = &IDX.GetNode())->IsStartNode() || HasMark() ) 672 { 673 // Tabelle allein in einem FlyFrame oder Selektion, 674 // dann verbleibe auf der alten Position 675 if( bChgCrsr ) 676 RestoreSavePos(); 677 #if defined( UNX ) 678 delete pCellStt; 679 #endif 680 return sal_True; // Crsr bleibt an der alten Position 681 } 682 else if( pNd->StartOfSectionNode()->IsTableNode() && IDX-- ) 683 goto GoPrevCell; 684 685 bProt = sal_False; // Index steht jetzt auf einem ContentNode 686 goto SetPrevCrsr; 687 } 688 } 689 690 // sal_True: an die Position kann der Cursor gesetzt werden 691 sal_Bool SwCursor::IsAtValidPos( sal_Bool bPoint ) const 692 { 693 const SwDoc* pDoc = GetDoc(); 694 const SwPosition* pPos = bPoint ? GetPoint() : GetMark(); 695 const SwNode* pNd = &pPos->nNode.GetNode(); 696 697 if( pNd->IsCntntNode() && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ) && 698 !dynamic_cast<const SwUnoCrsr*>(this) ) 699 { 700 return sal_False; 701 } 702 703 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt 704 if( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() ) 705 return sal_True; 706 707 sal_Bool bCrsrInReadOnly = IsReadOnlyAvailable(); 708 if( !bCrsrInReadOnly && pNd->IsProtect() ) 709 return sal_False; 710 711 const SwSectionNode* pSectNd = pNd->FindSectionNode(); 712 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() || 713 ( !bCrsrInReadOnly && pSectNd->GetSection().IsProtectFlag() ))) 714 return sal_False; 715 716 return sal_True; 717 } 718 719 void SwCursor::SaveTblBoxCntnt( const SwPosition* ) {} 720 721 // setze den SRange fuer das Suchen im Dokument 722 SwMoveFnCollection* SwCursor::MakeFindRange( SwDocPositions nStart, 723 SwDocPositions nEnd, SwPaM* pRange ) const 724 { 725 pRange->SetMark(); 726 FillFindPos( nStart, *pRange->GetMark() ); 727 FillFindPos( nEnd, *pRange->GetPoint() ); 728 729 // bestimme die Richtung, in der zu suchen ist 730 // ( GetPoint > GetMark -> vorwaerts, sonst rueckwaerts ) 731 return ( DOCPOS_START == nStart || DOCPOS_OTHERSTART == nStart || 732 (DOCPOS_CURR == nStart && 733 (DOCPOS_END == nEnd || DOCPOS_OTHEREND == nEnd ) )) 734 ? fnMoveForward : fnMoveBackward; 735 } 736 737 738 sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurCrsr, 739 SwMoveFn fnMove, SwCursor*& pFndRing, 740 SwPaM& aRegion, FindRanges eFndRngs, 741 sal_Bool bInReadOnly, sal_Bool& bCancel ) 742 { 743 SwDoc* pDoc = pCurCrsr->GetDoc(); 744 bool const bDoesUndo = pDoc->GetIDocumentUndoRedo().DoesUndo(); 745 int nFndRet = 0; 746 sal_uLong nFound = 0; 747 int bSrchBkwrd = fnMove == fnMoveBackward, bEnde = sal_False; 748 SwPaM *pTmpCrsr = pCurCrsr, *pSaveCrsr = pCurCrsr; 749 750 // only create progress-bar for ShellCrsr 751 bool bIsUnoCrsr = 0 != dynamic_cast<SwUnoCrsr*>(pCurCrsr); 752 _PercentHdl* pPHdl = 0; 753 sal_uInt16 nCrsrCnt = 0; 754 if( FND_IN_SEL & eFndRngs ) 755 { 756 while( pCurCrsr != ( pTmpCrsr = (SwPaM*)pTmpCrsr->GetNext() )) 757 ++nCrsrCnt; 758 if( nCrsrCnt && !bIsUnoCrsr ) 759 pPHdl = new _PercentHdl( 0, nCrsrCnt, pDoc->GetDocShell() ); 760 } 761 else 762 pSaveCrsr = (SwPaM*)pSaveCrsr->GetPrev(); 763 764 do { 765 aRegion.SetMark(); 766 // egal in welche Richtung, SPoint ist immer groesser als Mark, 767 // wenn der Suchbereich gueltig ist !! 768 SwPosition *pSttPos = aRegion.GetMark(), 769 *pEndPos = aRegion.GetPoint(); 770 *pSttPos = *pTmpCrsr->Start(); 771 *pEndPos = *pTmpCrsr->End(); 772 if( bSrchBkwrd ) 773 aRegion.Exchange(); 774 775 if( !nCrsrCnt && !pPHdl && !bIsUnoCrsr ) 776 pPHdl = new _PercentHdl( aRegion ); 777 778 // solange gefunden und nicht auf gleicher Position haengen bleibt 779 while( *pSttPos <= *pEndPos && 780 0 != ( nFndRet = rParas.Find( pCurCrsr, fnMove, 781 &aRegion, bInReadOnly )) && 782 ( !pFndRing || 783 *pFndRing->GetPoint() != *pCurCrsr->GetPoint() || 784 *pFndRing->GetMark() != *pCurCrsr->GetMark() )) 785 { 786 if( !( FIND_NO_RING & nFndRet )) 787 { 788 // Bug 24084: Ring richtig herum aufbauen -> gleiche Mimik 789 // wie beim CreateCrsr !!!! 790 791 SwCursor* pNew = pCurCrsr->Create( pFndRing ); 792 if( !pFndRing ) 793 pFndRing = pNew; 794 795 pNew->SetMark(); 796 *pNew->GetMark() = *pCurCrsr->GetMark(); 797 } 798 799 ++nFound; 800 801 if( !( eFndRngs & FND_IN_SELALL) ) 802 { 803 bEnde = sal_True; 804 break; 805 } 806 807 if ((coSrchRplcThreshold == nFound) 808 && pDoc->GetIDocumentUndoRedo().DoesUndo() 809 && rParas.IsReplaceMode()) 810 { 811 short nRet = pCurCrsr->MaxReplaceArived(); 812 if( RET_YES == nRet ) 813 { 814 pDoc->GetIDocumentUndoRedo().DelAllUndoObj(); 815 pDoc->GetIDocumentUndoRedo().DoUndo(false); 816 } 817 else 818 { 819 bEnde = sal_True; 820 if(RET_CANCEL == nRet) 821 { 822 bCancel = sal_True; 823 //unwind() ?? 824 } 825 break; 826 } 827 } 828 829 if( bSrchBkwrd ) 830 // bewege pEndPos vor den gefundenen Bereich 831 *pEndPos = *pCurCrsr->Start(); 832 else 833 // bewege pSttPos hinter den gefundenen Bereich 834 *pSttPos = *pCurCrsr->End(); 835 836 if( *pSttPos == *pEndPos ) // im Bereich, aber am Ende 837 break; // fertig 838 839 if( !nCrsrCnt && pPHdl ) 840 { 841 pPHdl->NextPos( *aRegion.GetMark() ); 842 } 843 } 844 845 if( bEnde || !( eFndRngs & ( FND_IN_SELALL | FND_IN_SEL )) ) 846 break; 847 848 pTmpCrsr = ((SwPaM*)pTmpCrsr->GetNext()); 849 if( nCrsrCnt && pPHdl ) 850 { 851 pPHdl->NextPos( ++pPHdl->nActPos ); 852 } 853 854 } while( pTmpCrsr != pSaveCrsr ); 855 856 if( nFound && !pFndRing ) // falls kein Ring aufgebaut werden soll 857 pFndRing = pCurCrsr->Create(); 858 859 delete pPHdl; 860 pDoc->GetIDocumentUndoRedo().DoUndo(bDoesUndo); 861 return nFound; 862 } 863 864 865 int lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd, 866 SwPaM& rPam, int bFirst ) 867 { 868 if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() ) 869 return sal_False; 870 871 SwNodes& rNds = rPam.GetDoc()->GetNodes(); 872 rPam.DeleteMark(); 873 SwCntntNode* pCNd; 874 if( !bFirst ) 875 { 876 rPam.GetPoint()->nNode = rSttNd; 877 pCNd = rNds.GoNext( &rPam.GetPoint()->nNode ); 878 if( !pCNd ) 879 return sal_False; 880 pCNd->MakeStartIndex( &rPam.GetPoint()->nContent ); 881 } 882 else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() || 883 rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() ) 884 return sal_False; // steht nicht in dieser Section 885 886 rPam.SetMark(); 887 rPam.GetPoint()->nNode = rEndNd; 888 pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode ); 889 if( !pCNd ) 890 return sal_False; 891 pCNd->MakeEndIndex( &rPam.GetPoint()->nContent ); 892 893 return *rPam.GetMark() < *rPam.GetPoint(); 894 } 895 896 897 int lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd, 898 SwPaM& rPam, int bFirst ) 899 { 900 if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() ) 901 return sal_False; 902 903 SwNodes& rNds = rPam.GetDoc()->GetNodes(); 904 rPam.DeleteMark(); 905 SwCntntNode* pCNd; 906 if( !bFirst ) 907 { 908 rPam.GetPoint()->nNode = rSttNd; 909 pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode ); 910 if( !pCNd ) 911 return sal_False; 912 pCNd->MakeEndIndex( &rPam.GetPoint()->nContent ); 913 } 914 else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() || 915 rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() ) 916 return sal_False; // steht nicht in dieser Section 917 918 rPam.SetMark(); 919 rPam.GetPoint()->nNode = rEndNd; 920 pCNd = rNds.GoNext( &rPam.GetPoint()->nNode ); 921 if( !pCNd ) 922 return sal_False; 923 pCNd->MakeStartIndex( &rPam.GetPoint()->nContent ); 924 925 return *rPam.GetPoint() < *rPam.GetMark(); 926 } 927 928 929 // diese Methode "sucht" fuer alle Anwendungsfaelle, denn in SwFindParas 930 // steht immer die richtigen Parameter und die entsprechende Find-Methode 931 932 sal_uLong SwCursor::FindAll( SwFindParas& rParas, 933 SwDocPositions nStart, SwDocPositions nEnde, 934 FindRanges eFndRngs, sal_Bool& bCancel ) 935 { 936 bCancel = sal_False; 937 SwCrsrSaveState aSaveState( *this ); 938 939 // Region erzeugen, ohne das diese in den Ring aufgenommen wird ! 940 SwPaM aRegion( *GetPoint() ); 941 SwMoveFn fnMove = MakeFindRange( nStart, nEnde, &aRegion ); 942 943 sal_uLong nFound = 0; 944 int bMvBkwrd = fnMove == fnMoveBackward; 945 sal_Bool bInReadOnly = IsReadOnlyAvailable(); 946 947 SwCursor* pFndRing = 0; 948 SwNodes& rNds = GetDoc()->GetNodes(); 949 950 // suche in Bereichen ? 951 if( FND_IN_SEL & eFndRngs ) 952 { 953 // String nicht im Bereich gefunden, dann erhalte alle Bereiche, 954 // der Cursor beleibt unveraendert 955 if( 0 == ( nFound = lcl_FindSelection( rParas, this, fnMove, 956 pFndRing, aRegion, eFndRngs, 957 bInReadOnly, bCancel ) )) 958 return nFound; 959 960 // der String wurde ein- bis mehrmals gefunden. Das steht alles 961 // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf 962 while( GetNext() != this ) 963 delete GetNext(); 964 965 *GetPoint() = *pFndRing->GetPoint(); 966 SetMark(); 967 *GetMark() = *pFndRing->GetMark(); 968 pFndRing->MoveRingTo( this ); 969 delete pFndRing; 970 } 971 else if( FND_IN_OTHER & eFndRngs ) 972 { 973 // Cursor als Kopie vom akt. und in den Ring aufnehmen 974 // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts 975 std::auto_ptr< SwCursor > pSav( Create( this ) ); // save the current cursor 976 977 // wenn schon ausserhalb vom Bodytext, suche von der Position, 978 // ansonsten beginne mit der 1. GrundSection 979 if( bMvBkwrd 980 ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(), 981 *rNds.GetEndOfPostIts().StartOfSectionNode(), 982 *this, rNds.GetEndOfExtras().GetIndex() >= 983 GetPoint()->nNode.GetIndex() ) 984 : lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(), 985 rNds.GetEndOfExtras(), *this, 986 rNds.GetEndOfExtras().GetIndex() >= 987 GetPoint()->nNode.GetIndex() )) 988 { 989 nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing, 990 aRegion, eFndRngs, bInReadOnly, bCancel ); 991 } 992 993 if( !nFound ) 994 { 995 // den alten wieder zurueck 996 *GetPoint() = *pSav->GetPoint(); 997 if( pSav->HasMark() ) 998 { 999 SetMark(); 1000 *GetMark() = *pSav->GetMark(); 1001 } 1002 else 1003 DeleteMark(); 1004 return 0; 1005 } 1006 pSav.release(); 1007 1008 if( !( FND_IN_SELALL & eFndRngs )) 1009 { 1010 // es sollte nur einer gesucht werden, also fuege in dazu 1011 // egal in welche Richtung, SPoint ist immer groesser als Mark, 1012 // wenn der Suchbereich gueltig ist !! 1013 *GetPoint() = *pFndRing->GetPoint(); 1014 SetMark(); 1015 *GetMark() = *pFndRing->GetMark(); 1016 } 1017 else 1018 { 1019 // es wurde ein- bis mehrmals gefunden. Das steht alles 1020 // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf 1021 while( GetNext() != this ) 1022 delete GetNext(); 1023 1024 *GetPoint() = *pFndRing->GetPoint(); 1025 SetMark(); 1026 *GetMark() = *pFndRing->GetMark(); 1027 pFndRing->MoveRingTo( this ); 1028 } 1029 delete pFndRing; 1030 } 1031 else if( FND_IN_SELALL & eFndRngs ) 1032 { 1033 ::std::auto_ptr< SwCursor> pSav( Create( this ) ); // save the current cursor 1034 1035 const SwNode* pSttNd = ( FND_IN_BODYONLY & eFndRngs ) 1036 ? rNds.GetEndOfContent().StartOfSectionNode() 1037 : rNds.GetEndOfPostIts().StartOfSectionNode(); 1038 1039 if( bMvBkwrd 1040 ? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd,*this, sal_False ) 1041 : lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, sal_False )) 1042 { 1043 nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing, 1044 aRegion, eFndRngs, bInReadOnly, bCancel ); 1045 } 1046 1047 if( !nFound ) 1048 { 1049 // den alten wieder zurueck 1050 *GetPoint() = *pSav->GetPoint(); 1051 if( pSav->HasMark() ) 1052 { 1053 SetMark(); 1054 *GetMark() = *pSav->GetMark(); 1055 } 1056 else 1057 DeleteMark(); 1058 return 0; 1059 } 1060 pSav.release(); 1061 while( GetNext() != this ) 1062 delete GetNext(); 1063 1064 *GetPoint() = *pFndRing->GetPoint(); 1065 SetMark(); 1066 *GetMark() = *pFndRing->GetMark(); 1067 pFndRing->MoveRingTo( this ); 1068 delete pFndRing; 1069 } 1070 else 1071 { 1072 // ist ein GetMark gesetzt, dann wird bei gefundenem Object 1073 // der GetMark beibehalten !! Dadurch kann ein Bereich mit der Suche 1074 // aufgespannt werden. 1075 SwPosition aMarkPos( *GetMark() ); 1076 int bMarkPos = HasMark() && !eFndRngs; 1077 1078 if( 0 != (nFound = rParas.Find( this, fnMove, 1079 &aRegion, bInReadOnly ) ? 1 : 0) 1080 && bMarkPos ) 1081 *GetMark() = aMarkPos; 1082 } 1083 1084 if( nFound && SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE ) ) 1085 nFound = 0; 1086 return nFound; 1087 } 1088 1089 1090 void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const 1091 { 1092 sal_Bool bIsStart = sal_True; 1093 SwCntntNode* pCNd = 0; 1094 SwNodes& rNds = GetDoc()->GetNodes(); 1095 1096 switch( ePos ) 1097 { 1098 case DOCPOS_START: 1099 rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode(); 1100 pCNd = rNds.GoNext( &rPos.nNode ); 1101 break; 1102 1103 case DOCPOS_END: 1104 rPos.nNode = rNds.GetEndOfContent(); 1105 pCNd = rNds.GoPrevious( &rPos.nNode ); 1106 bIsStart = sal_False; 1107 break; 1108 1109 case DOCPOS_OTHERSTART: 1110 rPos.nNode = *rNds[ sal_uLong(0) ]; 1111 pCNd = rNds.GoNext( &rPos.nNode ); 1112 break; 1113 1114 case DOCPOS_OTHEREND: 1115 rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode(); 1116 pCNd = rNds.GoPrevious( &rPos.nNode ); 1117 bIsStart = sal_False; 1118 break; 1119 1120 // case DOCPOS_CURR: 1121 default: 1122 rPos = *GetPoint(); 1123 } 1124 1125 if( pCNd ) 1126 { 1127 xub_StrLen nCPos = 0; 1128 if( !bIsStart ) 1129 nCPos = pCNd->Len(); 1130 rPos.nContent.Assign( pCNd, nCPos ); 1131 } 1132 } 1133 1134 short SwCursor::MaxReplaceArived() 1135 { 1136 return RET_YES; 1137 } 1138 1139 1140 sal_Bool SwCursor::IsStartWord( sal_Int16 nWordType ) const 1141 { 1142 return IsStartWordWT( nWordType ); 1143 } 1144 1145 sal_Bool SwCursor::IsEndWord( sal_Int16 nWordType ) const 1146 { 1147 return IsEndWordWT( nWordType ); 1148 } 1149 1150 sal_Bool SwCursor::IsInWord( sal_Int16 nWordType ) const 1151 { 1152 return IsInWordWT( nWordType ); 1153 } 1154 1155 sal_Bool SwCursor::GoStartWord() 1156 { 1157 return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES ); 1158 } 1159 1160 sal_Bool SwCursor::GoEndWord() 1161 { 1162 return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES ); 1163 } 1164 1165 sal_Bool SwCursor::GoNextWord() 1166 { 1167 return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES ); 1168 } 1169 1170 sal_Bool SwCursor::GoPrevWord() 1171 { 1172 return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES ); 1173 } 1174 1175 sal_Bool SwCursor::SelectWord( ViewShell* pViewShell, const Point* pPt ) 1176 { 1177 return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt ); 1178 } 1179 1180 sal_Bool SwCursor::IsStartWordWT( sal_Int16 nWordType ) const 1181 { 1182 sal_Bool bRet = sal_False; 1183 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1184 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1185 { 1186 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1187 bRet = pBreakIt->GetBreakIter()->isBeginWord( 1188 pTxtNd->GetTxt(), nPtPos, 1189 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos )), 1190 nWordType ); 1191 } 1192 return bRet; 1193 } 1194 1195 sal_Bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const 1196 { 1197 sal_Bool bRet = sal_False; 1198 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1199 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1200 { 1201 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1202 bRet = pBreakIt->GetBreakIter()->isEndWord( 1203 pTxtNd->GetTxt(), nPtPos, 1204 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ), 1205 nWordType ); 1206 1207 } 1208 return bRet; 1209 } 1210 1211 sal_Bool SwCursor::IsInWordWT( sal_Int16 nWordType ) const 1212 { 1213 sal_Bool bRet = sal_False; 1214 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1215 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1216 { 1217 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1218 Boundary aBoundary = pBreakIt->GetBreakIter()->getWordBoundary( 1219 pTxtNd->GetTxt(), nPtPos, 1220 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ), 1221 nWordType, 1222 sal_True ); 1223 1224 bRet = aBoundary.startPos != aBoundary.endPos && 1225 aBoundary.startPos <= nPtPos && 1226 nPtPos <= aBoundary.endPos; 1227 if(bRet) 1228 { 1229 const CharClass& rCC = GetAppCharClass(); 1230 bRet = rCC.isLetterNumeric( pTxtNd->GetTxt(), static_cast<xub_StrLen>(aBoundary.startPos) ); 1231 } 1232 } 1233 return bRet; 1234 } 1235 1236 sal_Bool SwCursor::IsStartEndSentence( bool bEnd ) const 1237 { 1238 sal_Bool bRet = bEnd ? 1239 GetCntntNode() && GetPoint()->nContent == GetCntntNode()->Len() : 1240 GetPoint()->nContent.GetIndex() == 0; 1241 1242 if( !bRet ) 1243 { 1244 SwCursor aCrsr(*GetPoint(), 0, false); 1245 SwPosition aOrigPos = *aCrsr.GetPoint(); 1246 aCrsr.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT ); 1247 bRet = aOrigPos == *aCrsr.GetPoint(); 1248 } 1249 1250 return bRet; 1251 } 1252 1253 sal_Bool SwCursor::GoStartWordWT( sal_Int16 nWordType ) 1254 { 1255 sal_Bool bRet = sal_False; 1256 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1257 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1258 { 1259 SwCrsrSaveState aSave( *this ); 1260 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1261 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary( 1262 pTxtNd->GetTxt(), nPtPos, 1263 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ), 1264 nWordType, 1265 sal_False ).startPos; 1266 1267 if( nPtPos < pTxtNd->GetTxt().Len() ) 1268 { 1269 GetPoint()->nContent = nPtPos; 1270 if( !IsSelOvr() ) 1271 bRet = sal_True; 1272 } 1273 } 1274 return bRet; 1275 } 1276 1277 sal_Bool SwCursor::GoEndWordWT( sal_Int16 nWordType ) 1278 { 1279 sal_Bool bRet = sal_False; 1280 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1281 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1282 { 1283 SwCrsrSaveState aSave( *this ); 1284 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1285 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary( 1286 pTxtNd->GetTxt(), nPtPos, 1287 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ), 1288 nWordType, 1289 sal_True ).endPos; 1290 1291 if( nPtPos <= pTxtNd->GetTxt().Len() && 1292 GetPoint()->nContent.GetIndex() != nPtPos ) 1293 { 1294 GetPoint()->nContent = nPtPos; 1295 if( !IsSelOvr() ) 1296 bRet = sal_True; 1297 } 1298 } 1299 return bRet; 1300 } 1301 1302 sal_Bool SwCursor::GoNextWordWT( sal_Int16 nWordType ) 1303 { 1304 sal_Bool bRet = sal_False; 1305 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1306 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1307 { 1308 SwCrsrSaveState aSave( *this ); 1309 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1310 1311 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextWord( 1312 pTxtNd->GetTxt(), nPtPos, 1313 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ), 1314 nWordType ).startPos; 1315 1316 if( nPtPos < pTxtNd->GetTxt().Len() ) 1317 { 1318 GetPoint()->nContent = nPtPos; 1319 if( !IsSelOvr() ) 1320 bRet = sal_True; 1321 } 1322 } 1323 return bRet; 1324 } 1325 1326 sal_Bool SwCursor::GoPrevWordWT( sal_Int16 nWordType ) 1327 { 1328 sal_Bool bRet = sal_False; 1329 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1330 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1331 { 1332 SwCrsrSaveState aSave( *this ); 1333 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1334 const xub_StrLen nPtStart = nPtPos; 1335 1336 if( nPtPos ) 1337 --nPtPos; 1338 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousWord( 1339 pTxtNd->GetTxt(), nPtStart, 1340 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ), 1341 nWordType ).startPos; 1342 1343 if( nPtPos < pTxtNd->GetTxt().Len() ) 1344 { 1345 GetPoint()->nContent = nPtPos; 1346 if( !IsSelOvr() ) 1347 bRet = sal_True; 1348 } 1349 } 1350 return bRet; 1351 } 1352 1353 sal_Bool SwCursor::SelectWordWT( ViewShell* pViewShell, sal_Int16 nWordType, const Point* pPt ) 1354 { 1355 SwCrsrSaveState aSave( *this ); 1356 1357 sal_Bool bRet = sal_False; 1358 sal_Bool bForward = sal_True; 1359 DeleteMark(); 1360 const SwRootFrm* pLayout = pViewShell->GetLayout(); 1361 if( pPt && 0 != pLayout ) 1362 { 1363 // set the cursor to the layout position 1364 Point aPt( *pPt ); 1365 pLayout->GetCrsrOfst( GetPoint(), aPt ); 1366 } //swmod 071107//swmod 071225 1367 1368 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1369 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1370 { 1371 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1372 Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary( 1373 pTxtNd->GetTxt(), nPtPos, 1374 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ), 1375 nWordType, 1376 bForward )); 1377 1378 if( aBndry.startPos != aBndry.endPos ) 1379 { 1380 GetPoint()->nContent = (xub_StrLen)aBndry.endPos; 1381 if( !IsSelOvr() ) 1382 { 1383 SetMark(); 1384 GetMark()->nContent = (xub_StrLen)aBndry.startPos; 1385 if( !IsSelOvr() ) 1386 bRet = sal_True; 1387 } 1388 } 1389 } 1390 1391 if( !bRet ) 1392 { 1393 DeleteMark(); 1394 RestoreSavePos(); 1395 } 1396 return bRet; 1397 } 1398 1399 //----------------------------------------------------------------------------- 1400 1401 static String lcl_MaskDeletedRedlines( const SwTxtNode* pTxtNd ) 1402 { 1403 String aRes; 1404 if (pTxtNd) 1405 { 1406 //mask deleted redlines 1407 String sNodeText(pTxtNd->GetTxt()); 1408 const SwDoc& rDoc = *pTxtNd->GetDoc(); 1409 const bool nShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() ); 1410 if ( nShowChg ) 1411 { 1412 sal_uInt16 nAct = rDoc.GetRedlinePos( *pTxtNd, USHRT_MAX ); 1413 for ( ; nAct < rDoc.GetRedlineTbl().Count(); nAct++ ) 1414 { 1415 const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ]; 1416 if ( pRed->Start()->nNode > pTxtNd->GetIndex() ) 1417 break; 1418 1419 if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() ) 1420 { 1421 xub_StrLen nStart, nEnd; 1422 pRed->CalcStartEnd( pTxtNd->GetIndex(), nStart, nEnd ); 1423 1424 while ( nStart < nEnd && nStart < sNodeText.Len() ) 1425 sNodeText.SetChar( nStart++, CH_TXTATR_INWORD ); 1426 } 1427 } 1428 } 1429 aRes = sNodeText; 1430 } 1431 return aRes; 1432 } 1433 1434 sal_Bool SwCursor::GoSentence( SentenceMoveType eMoveType ) 1435 { 1436 sal_Bool bRet = sal_False; 1437 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode(); 1438 if( pTxtNd && pBreakIt->GetBreakIter().is() ) 1439 { 1440 String sNodeText( lcl_MaskDeletedRedlines( pTxtNd ) ); 1441 1442 SwCrsrSaveState aSave( *this ); 1443 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex(); 1444 switch ( eMoveType ) 1445 { 1446 case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */ 1447 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence( 1448 sNodeText, 1449 nPtPos, pBreakIt->GetLocale( 1450 pTxtNd->GetLang( nPtPos ) )); 1451 break; 1452 case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */ 1453 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence( 1454 sNodeText, 1455 nPtPos, pBreakIt->GetLocale( 1456 pTxtNd->GetLang( nPtPos ) )); 1457 break; 1458 case NEXT_SENT: 1459 { 1460 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence( 1461 sNodeText, 1462 nPtPos, pBreakIt->GetLocale( 1463 pTxtNd->GetLang( nPtPos ) )); 1464 while (nPtPos != (sal_uInt16) -1 && ++nPtPos < sNodeText.Len() 1465 && sNodeText.GetChar(nPtPos)== ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ ) 1466 ; 1467 break; 1468 } 1469 case PREV_SENT: 1470 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence( 1471 sNodeText, 1472 nPtPos, pBreakIt->GetLocale( 1473 pTxtNd->GetLang( nPtPos ) )); 1474 if (nPtPos == 0) 1475 return sal_False; // the previous sentence is not in this paragraph 1476 if (nPtPos > 0) 1477 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence( 1478 sNodeText, 1479 nPtPos - 1, pBreakIt->GetLocale( 1480 pTxtNd->GetLang( nPtPos ) )); 1481 break; 1482 } 1483 1484 // it is allowed to place the PaM just behind the last 1485 // character in the text thus <= ...Len 1486 if( nPtPos <= pTxtNd->GetTxt().Len() ) 1487 { 1488 GetPoint()->nContent = nPtPos; 1489 if( !IsSelOvr() ) 1490 bRet = sal_True; 1491 } 1492 } 1493 return bRet; 1494 } 1495 1496 1497 sal_Bool SwCursor::ExpandToSentenceBorders() 1498 { 1499 sal_Bool bRes = sal_False; 1500 const SwTxtNode* pStartNd = Start()->nNode.GetNode().GetTxtNode(); 1501 const SwTxtNode* pEndNd = End()->nNode.GetNode().GetTxtNode(); 1502 if (pStartNd && pEndNd && pBreakIt->GetBreakIter().is()) 1503 { 1504 if (!HasMark()) 1505 SetMark(); 1506 1507 String sStartText( lcl_MaskDeletedRedlines( pStartNd ) ); 1508 String sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) ); 1509 1510 SwCrsrSaveState aSave( *this ); 1511 xub_StrLen nStartPos = Start()->nContent.GetIndex(); 1512 xub_StrLen nEndPos = End()->nContent.GetIndex(); 1513 1514 nStartPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence( 1515 sStartText, nStartPos, 1516 pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) ); 1517 nEndPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence( 1518 sEndText, nEndPos, 1519 pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) ); 1520 1521 // it is allowed to place the PaM just behind the last 1522 // character in the text thus <= ...Len 1523 bool bChanged = false; 1524 if (nStartPos <= pStartNd->GetTxt().Len()) 1525 { 1526 GetMark()->nContent = nStartPos; 1527 bChanged = true; 1528 } 1529 if (nEndPos <= pEndNd->GetTxt().Len()) 1530 { 1531 GetPoint()->nContent = nEndPos; 1532 bChanged = true; 1533 } 1534 if (bChanged && !IsSelOvr()) 1535 bRes = sal_True; 1536 } 1537 return bRes; 1538 } 1539 1540 1541 sal_Bool SwTableCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/, 1542 sal_Bool /*bVisualAllowed*/, sal_Bool /*bSkipHidden*/, sal_Bool /*bInsertCrsr*/ ) 1543 { 1544 return bLeft ? GoPrevCell( nCnt ) 1545 : GoNextCell( nCnt ); 1546 } 1547 1548 1549 // calculate cursor bidi level: extracted from LeftRight() 1550 const SwCntntFrm* 1551 SwCursor::DoSetBidiLevelLeftRight( 1552 sal_Bool & io_rbLeft, sal_Bool bVisualAllowed, sal_Bool bInsertCrsr) 1553 { 1554 // calculate cursor bidi level 1555 const SwCntntFrm* pSttFrm = NULL; 1556 SwNode& rNode = GetPoint()->nNode.GetNode(); 1557 1558 if( rNode.IsTxtNode() ) 1559 { 1560 const SwTxtNode& rTNd = *rNode.GetTxtNode(); 1561 SwIndex& rIdx = GetPoint()->nContent; 1562 xub_StrLen nPos = rIdx.GetIndex(); 1563 1564 const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); 1565 if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() && 1566 SvtCTLOptions::MOVEMENT_VISUAL == 1567 rCTLOptions.GetCTLCursorMovement() ) 1568 { 1569 // for visual cursor travelling (used in bidi layout) 1570 // we first have to convert the logic to a visual position 1571 Point aPt; 1572 pSttFrm = rTNd.getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1573 if( pSttFrm ) 1574 { 1575 sal_uInt8 nCrsrLevel = GetCrsrBidiLevel(); 1576 sal_Bool bForward = ! io_rbLeft; 1577 ((SwTxtFrm*)pSttFrm)->PrepareVisualMove( nPos, nCrsrLevel, 1578 bForward, bInsertCrsr ); 1579 rIdx = nPos; 1580 SetCrsrBidiLevel( nCrsrLevel ); 1581 io_rbLeft = ! bForward; 1582 } 1583 } 1584 else 1585 { 1586 const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd ); 1587 if ( pSI ) 1588 { 1589 const xub_StrLen nMoveOverPos = io_rbLeft ? 1590 ( nPos ? nPos - 1 : 0 ) : 1591 nPos; 1592 SetCrsrBidiLevel( pSI->DirType( nMoveOverPos ) ); 1593 } 1594 } 1595 } 1596 return pSttFrm; 1597 } 1598 1599 sal_Bool SwCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, 1600 sal_Bool bVisualAllowed,sal_Bool bSkipHidden, sal_Bool bInsertCrsr ) 1601 { 1602 // calculate cursor bidi level 1603 SwNode& rNode = GetPoint()->nNode.GetNode(); 1604 const SwCntntFrm* pSttFrm = // may side-effect bLeft! 1605 DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCrsr); 1606 1607 // kann der Cursor n-mal weiterverschoben werden ? 1608 SwCrsrSaveState aSave( *this ); 1609 SwMoveFn fnMove = bLeft ? fnMoveBackward : fnMoveForward; 1610 1611 SwGoInDoc fnGo; 1612 if ( bSkipHidden ) 1613 fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCellsSkipHidden : fnGoCntntSkipHidden; 1614 else 1615 fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCells : fnGoCntnt; 1616 1617 // ASSERT( not in covered cell ) 1618 1619 while( nCnt ) 1620 { 1621 SwNodeIndex aOldNodeIdx( GetPoint()->nNode ); 1622 1623 bool bSuccess = Move( fnMove, fnGo ); 1624 if ( !bSuccess ) 1625 break; 1626 1627 // If we were located inside a covered cell but our position has been 1628 // corrected, we check if the last move has moved the cursor to a different 1629 // table cell. In this case we set the cursor to the stored covered position 1630 // and redo the move: 1631 if ( mnRowSpanOffset ) 1632 { 1633 const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode(); 1634 const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : 0; 1635 const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode(); 1636 const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : 0; 1637 1638 const bool bCellChanged = pOldTabSttNode && pNewTabSttNode && 1639 pOldTabSttNode == pNewTabSttNode && 1640 pOldTabBoxSttNode && pNewTabBoxSttNode && 1641 pOldTabBoxSttNode != pNewTabBoxSttNode; 1642 1643 if ( bCellChanged ) 1644 { 1645 // Set cursor to start/end of covered cell: 1646 SwTableBox* pTableBox = pOldTabBoxSttNode->GetTblBox(); 1647 const long nRowSpan = pTableBox->getRowSpan(); 1648 if ( nRowSpan > 1 ) 1649 { 1650 pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset ) ); 1651 SwNodeIndex& rPtIdx = GetPoint()->nNode; 1652 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); 1653 rPtIdx = aNewIdx; 1654 1655 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False ); 1656 SwCntntNode* pCntntNode = GetCntntNode(); 1657 if ( pCntntNode ) 1658 { 1659 const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0; 1660 GetPoint()->nContent.Assign( pCntntNode, nTmpPos ); 1661 1662 // Redo the move: 1663 bSuccess = Move( fnMove, fnGo ); 1664 if ( !bSuccess ) 1665 break; 1666 } 1667 } 1668 1669 mnRowSpanOffset = 0; 1670 } 1671 } 1672 1673 // Check if I'm inside a covered cell. Correct cursor if necessary and 1674 // store covered cell: 1675 const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode(); 1676 if ( pTableBoxStartNode ) 1677 { 1678 const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox(); 1679 if ( pTableBox->getRowSpan() < 1 ) 1680 { 1681 // Store the row span offset: 1682 mnRowSpanOffset = pTableBox->getRowSpan(); 1683 1684 // Move cursor to non-covered cell: 1685 const SwTableNode* pTblNd = pTableBoxStartNode->FindTableNode(); 1686 pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX ); 1687 SwNodeIndex& rPtIdx = GetPoint()->nNode; 1688 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); 1689 rPtIdx = aNewIdx; 1690 1691 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False ); 1692 SwCntntNode* pCntntNode = GetCntntNode(); 1693 if ( pCntntNode ) 1694 { 1695 const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0; 1696 GetPoint()->nContent.Assign( pCntntNode, nTmpPos ); 1697 } 1698 } 1699 } 1700 1701 --nCnt; 1702 } 1703 1704 // here come some special rules for visual cursor travelling 1705 if ( pSttFrm ) 1706 { 1707 SwNode& rTmpNode = GetPoint()->nNode.GetNode(); 1708 if ( &rTmpNode != &rNode && rTmpNode.IsTxtNode() ) 1709 { 1710 Point aPt; 1711 const SwCntntFrm* pEndFrm = ((SwTxtNode&)rTmpNode).getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1712 if ( pEndFrm ) 1713 { 1714 if ( ! pEndFrm->IsRightToLeft() != ! pSttFrm->IsRightToLeft() ) 1715 { 1716 if ( ! bLeft ) 1717 pEndFrm->RightMargin( this ); 1718 else 1719 pEndFrm->LeftMargin( this ); 1720 } 1721 } 1722 } 1723 } 1724 1725 return 0 == nCnt && !IsInProtectTable( sal_True ) && 1726 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 1727 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ); 1728 } 1729 1730 // calculate cursor bidi level: extracted from UpDown() 1731 void SwCursor::DoSetBidiLevelUpDown() 1732 { 1733 SwNode& rNode = GetPoint()->nNode.GetNode(); 1734 if ( rNode.IsTxtNode() ) 1735 { 1736 const SwScriptInfo* pSI = 1737 SwScriptInfo::GetScriptInfo( (SwTxtNode&)rNode ); 1738 if ( pSI ) 1739 { 1740 SwIndex& rIdx = GetPoint()->nContent; 1741 xub_StrLen nPos = rIdx.GetIndex(); 1742 1743 if( nPos && nPos < ((SwTxtNode&)rNode).GetTxt().Len() ) 1744 { 1745 const sal_uInt8 nCurrLevel = pSI->DirType( nPos ); 1746 const sal_uInt8 nPrevLevel = pSI->DirType( nPos - 1 ); 1747 1748 if ( nCurrLevel % 2 != nPrevLevel % 2 ) 1749 { 1750 // set cursor level to the lower of the two levels 1751 SetCrsrBidiLevel( Min( nCurrLevel, nPrevLevel ) ); 1752 } 1753 else 1754 SetCrsrBidiLevel( nCurrLevel ); 1755 } 1756 } 1757 } 1758 } 1759 1760 sal_Bool SwCursor::UpDown( sal_Bool bUp, sal_uInt16 nCnt, 1761 Point* pPt, long nUpDownX ) 1762 { 1763 SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this); 1764 sal_Bool bAdjustTableCrsr = sal_False; 1765 1766 // vom Tabellen Crsr Point/Mark in der gleichen Box ?? 1767 // dann stelle den Point an den Anfang der Box 1768 if( pTblCrsr && GetNode( sal_True )->StartOfSectionNode() == 1769 GetNode( sal_False )->StartOfSectionNode() ) 1770 { 1771 if ( End() != GetPoint() ) 1772 Exchange(); 1773 bAdjustTableCrsr = sal_True; 1774 } 1775 1776 sal_Bool bRet = sal_False; 1777 Point aPt; 1778 if( pPt ) 1779 aPt = *pPt; 1780 SwCntntFrm* pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1781 1782 if( pFrm ) 1783 { 1784 SwCrsrSaveState aSave( *this ); 1785 1786 if( !pPt ) 1787 { 1788 SwRect aTmpRect; 1789 pFrm->GetCharRect( aTmpRect, *GetPoint() ); 1790 aPt = aTmpRect.Pos(); 1791 1792 nUpDownX = pFrm->IsVertical() ? 1793 aPt.Y() - pFrm->Frm().Top() : 1794 aPt.X() - pFrm->Frm().Left(); 1795 } 1796 1797 // Bei Fussnoten ist auch die Bewegung in eine andere Fussnote erlaubt. 1798 // aber keine Selection!! 1799 const sal_Bool bChkRange = pFrm->IsInFtn() && !HasMark() 1800 ? sal_False : sal_True; 1801 const SwPosition aOldPos( *GetPoint() ); 1802 sal_Bool bInReadOnly = IsReadOnlyAvailable(); 1803 1804 if ( bAdjustTableCrsr && !bUp ) 1805 { 1806 // Special case: We have a table cursor but the start box 1807 // has more than one paragraph. If we want to go down, we have to 1808 // set the point to the last frame in the table box. This is 1809 // only necessary if we do not already have a table selection 1810 const SwStartNode* pTblNd = GetNode( sal_True )->FindTableBoxStartNode(); 1811 ASSERT( pTblNd, "pTblCrsr without SwTableNode?" ) 1812 1813 if ( pTblNd ) // safety first 1814 { 1815 const SwNode* pEndNd = pTblNd->EndOfSectionNode(); 1816 GetPoint()->nNode = *pEndNd; 1817 pTblCrsr->Move( fnMoveBackward, fnGoNode ); 1818 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1819 } 1820 } 1821 1822 while( nCnt && 1823 (bUp ? pFrm->UnitUp( this, nUpDownX, bInReadOnly ) 1824 : pFrm->UnitDown( this, nUpDownX, bInReadOnly ) ) && 1825 CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange )) 1826 { 1827 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1828 --nCnt; 1829 } 1830 1831 if( !nCnt && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 1832 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) // die gesamte Anzahl durchlaufen ? 1833 { 1834 if( !pTblCrsr ) 1835 { 1836 // dann versuche den Cursor auf die Position zu setzen, 1837 // auf halber Heohe vom Char-Rectangle 1838 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1839 SwCrsrMoveState eTmpState( MV_UPDOWN ); 1840 eTmpState.bSetInReadOnly = bInReadOnly; 1841 SwRect aTmpRect; 1842 pFrm->GetCharRect( aTmpRect, *GetPoint(), &eTmpState ); 1843 if ( pFrm->IsVertical() ) 1844 { 1845 aPt.X() = aTmpRect.Center().X(); 1846 pFrm->Calc(); 1847 aPt.Y() = pFrm->Frm().Top() + nUpDownX; 1848 } 1849 else 1850 { 1851 aPt.Y() = aTmpRect.Center().Y(); 1852 pFrm->Calc(); 1853 aPt.X() = pFrm->Frm().Left() + nUpDownX; 1854 } 1855 pFrm->GetCrsrOfst( GetPoint(), aPt, &eTmpState ); 1856 } 1857 bRet = sal_True; 1858 } 1859 else 1860 *GetPoint() = aOldPos; 1861 1862 DoSetBidiLevelUpDown(); // calculate cursor bidi level 1863 } 1864 1865 return bRet; 1866 } 1867 1868 sal_Bool SwCursor::LeftRightMargin( sal_Bool bLeft, sal_Bool bAPI ) 1869 { 1870 Point aPt; 1871 SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1872 1873 // calculate cursor bidi level 1874 if ( pFrm ) 1875 SetCrsrBidiLevel( pFrm->IsRightToLeft() ? 1 : 0 ); 1876 1877 return pFrm && (bLeft ? pFrm->LeftMargin( this ) : 1878 pFrm->RightMargin( this, bAPI ) ); 1879 } 1880 1881 sal_Bool SwCursor::IsAtLeftRightMargin( sal_Bool bLeft, sal_Bool bAPI ) const 1882 { 1883 sal_Bool bRet = sal_False; 1884 Point aPt; 1885 SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() ); 1886 if( pFrm ) 1887 { 1888 SwPaM aPam( *GetPoint() ); 1889 if( !bLeft && aPam.GetPoint()->nContent.GetIndex() ) 1890 aPam.GetPoint()->nContent--; 1891 bRet = (bLeft ? pFrm->LeftMargin( &aPam ) 1892 : pFrm->RightMargin( &aPam, bAPI )) 1893 && *aPam.GetPoint() == *GetPoint(); 1894 } 1895 return bRet; 1896 } 1897 1898 sal_Bool SwCursor::SttEndDoc( sal_Bool bStt ) 1899 { 1900 SwCrsrSaveState aSave( *this ); 1901 1902 // Springe beim Selektieren nie ueber Section-Grenzen !! 1903 // kann der Cursor weiterverschoben werden ? 1904 SwMoveFn fnMove = bStt ? fnMoveBackward : fnMoveForward; 1905 sal_Bool bRet = (!HasMark() || !IsNoCntnt() ) && 1906 Move( fnMove, fnGoDoc ) && 1907 !IsInProtectTable( sal_True ) && 1908 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 1909 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS | 1910 nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION ); 1911 1912 return bRet; 1913 } 1914 1915 sal_Bool SwCursor::GoPrevNextCell( sal_Bool bNext, sal_uInt16 nCnt ) 1916 { 1917 const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode(); 1918 if( !pTblNd ) 1919 return sal_False; 1920 1921 // liegt vor dem StartNode der Cell ein weiterer EndNode, dann 1922 // gibt es auch eine vorherige Celle 1923 SwCrsrSaveState aSave( *this ); 1924 SwNodeIndex& rPtIdx = GetPoint()->nNode; 1925 1926 while( nCnt-- ) 1927 { 1928 const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode(); 1929 const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox(); 1930 1931 // Check if we have to move the cursor to a covered cell before 1932 // proceeding: 1933 if ( mnRowSpanOffset ) 1934 { 1935 if ( pTableBox->getRowSpan() > 1 ) 1936 { 1937 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset) ); 1938 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); 1939 rPtIdx = aNewIdx; 1940 pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode(); 1941 } 1942 mnRowSpanOffset = 0; 1943 } 1944 1945 const SwNode* pTmpNode = bNext ? 1946 pTableBoxStartNode->EndOfSectionNode() : 1947 pTableBoxStartNode; 1948 1949 SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 ); 1950 if( (bNext && !aCellIdx.GetNode().IsStartNode()) || 1951 (!bNext && !aCellIdx.GetNode().IsEndNode()) ) 1952 return sal_False; 1953 1954 rPtIdx = bNext ? aCellIdx : SwNodeIndex(*aCellIdx.GetNode().StartOfSectionNode()); 1955 1956 pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode(); 1957 pTableBox = pTableBoxStartNode->GetTblBox(); 1958 if ( pTableBox->getRowSpan() < 1 ) 1959 { 1960 mnRowSpanOffset = pTableBox->getRowSpan(); 1961 // move cursor to non-covered cell: 1962 pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX ); 1963 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); 1964 rPtIdx = aNewIdx; 1965 } 1966 } 1967 1968 rPtIdx++; 1969 if( !rPtIdx.GetNode().IsCntntNode() ) 1970 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_True, sal_False ); 1971 GetPoint()->nContent.Assign( GetCntntNode(), 0 ); 1972 1973 return !IsInProtectTable( sal_True ); 1974 } 1975 1976 sal_Bool SwTableCursor::GotoTable( const String& /*rName*/ ) 1977 { 1978 return sal_False; // invalid action 1979 } 1980 1981 sal_Bool SwCursor::GotoTable( const String& rName ) 1982 { 1983 sal_Bool bRet = sal_False; 1984 if ( !HasMark() ) 1985 { 1986 SwTable* pTmpTbl = SwTable::FindTable( GetDoc()->FindTblFmtByName( rName ) ); 1987 if( pTmpTbl ) 1988 { 1989 // eine Tabelle im normalen NodesArr 1990 SwCrsrSaveState aSave( *this ); 1991 GetPoint()->nNode = *pTmpTbl->GetTabSortBoxes()[ 0 ]-> 1992 GetSttNd()->FindTableNode(); 1993 Move( fnMoveForward, fnGoCntnt ); 1994 bRet = !IsSelOvr(); 1995 } 1996 } 1997 return bRet; 1998 } 1999 2000 sal_Bool SwCursor::GotoTblBox( const String& rName ) 2001 { 2002 sal_Bool bRet = sal_False; 2003 const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode(); 2004 if( pTblNd ) 2005 { 2006 // erfrage die Box, mit dem Nanen 2007 const SwTableBox* pTblBox = pTblNd->GetTable().GetTblBox( rName ); 2008 if( pTblBox && pTblBox->GetSttNd() && 2009 ( !pTblBox->GetFrmFmt()->GetProtect().IsCntntProtected() || 2010 IsReadOnlyAvailable() ) ) 2011 { 2012 SwCrsrSaveState aSave( *this ); 2013 GetPoint()->nNode = *pTblBox->GetSttNd(); 2014 Move( fnMoveForward, fnGoCntnt ); 2015 bRet = !IsSelOvr(); 2016 } 2017 } 2018 return bRet; 2019 } 2020 2021 sal_Bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara ) 2022 { 2023 //JP 28.8.2001: for optimization test something before 2024 const SwNode* pNd = &GetPoint()->nNode.GetNode(); 2025 bool bShortCut = false; 2026 if ( fnWhichPara == fnParaCurr ) 2027 { 2028 // --> FME 2005-02-21 #i41048# 2029 // If fnWhichPara == fnParaCurr, (*fnWhichPara)( *this, fnPosPara ) 2030 // can already move the cursor to a different text node. In this case 2031 // we better check if IsSelOvr(). 2032 const SwCntntNode* pCntntNd = pNd->GetCntntNode(); 2033 if ( pCntntNd ) 2034 { 2035 const xub_StrLen nSttEnd = fnPosPara == fnMoveForward ? 0 : pCntntNd->Len(); 2036 if ( GetPoint()->nContent.GetIndex() != nSttEnd ) 2037 bShortCut = true; 2038 } 2039 // <-- 2040 } 2041 else 2042 { 2043 if ( pNd->IsTxtNode() && 2044 pNd->GetNodes()[ pNd->GetIndex() + 2045 (fnWhichPara == fnParaNext ? 1 : -1 ) ]->IsTxtNode() ) 2046 bShortCut = true; 2047 } 2048 2049 if ( bShortCut ) 2050 return (*fnWhichPara)( *this, fnPosPara ); 2051 2052 // else we must use the SaveStructure, because the next/prev is not 2053 // a same node type. 2054 SwCrsrSaveState aSave( *this ); 2055 return (*fnWhichPara)( *this, fnPosPara ) && 2056 !IsInProtectTable( sal_True ) && 2057 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 2058 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ); 2059 } 2060 2061 2062 sal_Bool SwCursor::MoveSection( SwWhichSection fnWhichSect, 2063 SwPosSection fnPosSect) 2064 { 2065 SwCrsrSaveState aSave( *this ); 2066 return (*fnWhichSect)( *this, fnPosSect ) && 2067 !IsInProtectTable( sal_True ) && 2068 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | 2069 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ); 2070 } 2071 2072 /* 2073 sal_Bool MoveTable( SwWhichTable, SwPosTable ); 2074 sal_Bool MoveColumn( SwWhichColumn, SwPosColumn ); 2075 sal_Bool MoveRegion( SwWhichRegion, SwPosRegion ); 2076 */ 2077 2078 void SwCursor::RestoreSavePos() // Point auf die SavePos setzen 2079 { 2080 if( pSavePos ) 2081 { 2082 GetPoint()->nNode = pSavePos->nNode; 2083 GetPoint()->nContent.Assign( GetCntntNode(), pSavePos->nCntnt ); 2084 } 2085 } 2086 2087 2088 /* */ 2089 2090 SwTableCursor::SwTableCursor( const SwPosition &rPos, SwPaM* pRing ) 2091 : SwCursor( rPos, pRing, false ) 2092 { 2093 bParked = sal_False; 2094 bChg = sal_False; 2095 nTblPtNd = 0, nTblMkNd = 0; 2096 nTblPtCnt = 0, nTblMkCnt = 0; 2097 } 2098 2099 SwTableCursor::~SwTableCursor() {} 2100 2101 2102 sal_Bool lcl_SeekEntry( const SwSelBoxes& rTmp, const SwStartNode* pSrch, sal_uInt16& rFndPos ) 2103 { 2104 sal_uLong nIdx = pSrch->GetIndex(); 2105 2106 sal_uInt16 nO = rTmp.Count(), nM, nU = 0; 2107 if( nO > 0 ) 2108 { 2109 nO--; 2110 while( nU <= nO ) 2111 { 2112 nM = nU + ( nO - nU ) / 2; 2113 if( rTmp[ nM ]->GetSttNd() == pSrch ) 2114 { 2115 rFndPos = nM; 2116 return sal_True; 2117 } 2118 else if( rTmp[ nM ]->GetSttIdx() < nIdx ) 2119 nU = nM + 1; 2120 else if( nM == 0 ) 2121 return sal_False; 2122 else 2123 nO = nM - 1; 2124 } 2125 } 2126 return sal_False; 2127 } 2128 2129 2130 SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pAktCrsr ) 2131 { 2132 if( bChg ) // ??? 2133 { 2134 if( bParked ) 2135 { 2136 // wieder in den Inhalt schieben 2137 Exchange(); 2138 Move( fnMoveForward ); 2139 Exchange(); 2140 Move( fnMoveForward ); 2141 bParked = sal_False; 2142 } 2143 2144 bChg = sal_False; 2145 2146 // temp Kopie anlegen, damit alle Boxen, fuer die schon Cursor 2147 // existieren, entfernt werden koennen. 2148 SwSelBoxes aTmp; 2149 aTmp.Insert( &aSelBoxes ); 2150 2151 //Jetzt die Alten und die neuen abgleichen. 2152 SwNodes& rNds = pAktCrsr->GetDoc()->GetNodes(); 2153 sal_uInt16 nPos; 2154 const SwStartNode* pSttNd; 2155 SwPaM* pCur = pAktCrsr; 2156 do { 2157 sal_Bool bDel = sal_False; 2158 pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode(); 2159 if( !pCur->HasMark() || !pSttNd || 2160 pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() ) 2161 bDel = sal_True; 2162 2163 else if( lcl_SeekEntry( aTmp, pSttNd, nPos )) 2164 { 2165 SwNodeIndex aIdx( *pSttNd, 1 ); 2166 const SwNode* pNd = &aIdx.GetNode(); 2167 if( !pNd->IsCntntNode() ) 2168 pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False ); 2169 2170 SwPosition* pPos = pCur->GetMark(); 2171 if( pNd != &pPos->nNode.GetNode() ) 2172 pPos->nNode = *pNd; 2173 pPos->nContent.Assign( (SwCntntNode*)pNd, 0 ); 2174 2175 aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 ); 2176 if( !( pNd = &aIdx.GetNode())->IsCntntNode() ) 2177 pNd = rNds.GoPrevSection( &aIdx, sal_True, sal_False ); 2178 2179 pPos = pCur->GetPoint(); 2180 if( pNd != &pPos->nNode.GetNode() ) 2181 pPos->nNode = *pNd; 2182 pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() ); 2183 2184 aTmp.Remove( nPos ); 2185 } 2186 else 2187 bDel = sal_True; 2188 2189 pCur = (SwPaM*)pCur->GetNext(); 2190 if( bDel ) 2191 { 2192 SwPaM* pDel = (SwPaM*)pCur->GetPrev(); 2193 /* 2194 JP 20.07.98: der alte Code geht mit dem UNO-TableCrsr nicht 2195 if( pDel == pAktCrsr ) 2196 { 2197 if( pAktCrsr->GetNext() == pAktCrsr ) 2198 { 2199 pAktCrsr->DeleteMark(); 2200 break; // es gibt nichts mehr zu loeschen! 2201 } 2202 pAktCrsr = (SwCursor*)pDel->GetPrev(); 2203 } 2204 delete pDel; 2205 */ 2206 2207 if( pDel == pAktCrsr ) 2208 pAktCrsr->DeleteMark(); 2209 else 2210 delete pDel; 2211 } 2212 } while ( pAktCrsr != pCur ); 2213 2214 for( nPos = 0; nPos < aTmp.Count(); ++nPos ) 2215 { 2216 pSttNd = aTmp[ nPos ]->GetSttNd(); 2217 2218 SwNodeIndex aIdx( *pSttNd, 1 ); 2219 if( &aIdx.GetNodes() != &rNds ) 2220 break; 2221 const SwNode* pNd = &aIdx.GetNode(); 2222 if( !pNd->IsCntntNode() ) 2223 pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False ); 2224 2225 SwPaM* pNew; 2226 if( pAktCrsr->GetNext() == pAktCrsr && !pAktCrsr->HasMark() ) 2227 { 2228 pNew = pAktCrsr; 2229 pNew->GetPoint()->nNode = *pNd; 2230 pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 ); 2231 } 2232 else 2233 { 2234 pNew = pAktCrsr->Create( pAktCrsr ); 2235 pNew->GetPoint()->nNode = *pNd; 2236 pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 ); 2237 } 2238 pNew->SetMark(); 2239 2240 SwPosition* pPos = pNew->GetPoint(); 2241 pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 ); 2242 if( !( pNd = &pPos->nNode.GetNode())->IsCntntNode() ) 2243 pNd = rNds.GoPrevSection( &pPos->nNode, sal_True, sal_False ); 2244 2245 pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() ); 2246 } 2247 } 2248 return pAktCrsr; 2249 } 2250 2251 2252 void SwTableCursor::InsertBox( const SwTableBox& rTblBox ) 2253 { 2254 SwTableBox* pBox = (SwTableBox*)&rTblBox; 2255 aSelBoxes.Insert( pBox ); 2256 bChg = sal_True; 2257 } 2258 2259 bool SwTableCursor::NewTableSelection() 2260 { 2261 bool bRet = false; 2262 const SwNode *pStart = GetCntntNode()->FindTableBoxStartNode(); 2263 const SwNode *pEnd = GetCntntNode(sal_False)->FindTableBoxStartNode(); 2264 if( pStart && pEnd ) 2265 { 2266 const SwTableNode *pTableNode = pStart->FindTableNode(); 2267 if( pTableNode == pEnd->FindTableNode() && 2268 pTableNode->GetTable().IsNewModel() ) 2269 { 2270 bRet = true; 2271 SwSelBoxes aNew; 2272 aNew.Insert( &aSelBoxes ); 2273 pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew, 2274 SwTable::SEARCH_NONE, false ); 2275 ActualizeSelection( aNew ); 2276 } 2277 } 2278 return bRet; 2279 } 2280 2281 void SwTableCursor::ActualizeSelection( const SwSelBoxes &rNew ) 2282 { 2283 sal_uInt16 nOld = 0, nNew = 0; 2284 while ( nOld < aSelBoxes.Count() && nNew < rNew.Count() ) 2285 { 2286 const SwTableBox* pPOld = *( aSelBoxes.GetData() + nOld ); 2287 const SwTableBox* pPNew = *( rNew.GetData() + nNew ); 2288 if( pPOld == pPNew ) 2289 { // this box will stay 2290 ++nOld; 2291 ++nNew; 2292 } 2293 else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() ) 2294 DeleteBox( nOld ); // this box has to go 2295 else 2296 { 2297 InsertBox( *pPNew ); // this is a new one 2298 ++nOld; 2299 ++nNew; 2300 } 2301 } 2302 2303 while( nOld < aSelBoxes.Count() ) 2304 DeleteBox( nOld ); // some more to delete 2305 2306 for( ; nNew < rNew.Count(); ++nNew ) // some more to insert 2307 InsertBox( **( rNew.GetData() + nNew ) ); 2308 } 2309 2310 sal_Bool SwTableCursor::IsCrsrMovedUpdt() 2311 { 2312 if( !IsCrsrMoved() ) 2313 return sal_False; 2314 2315 nTblMkNd = GetMark()->nNode.GetIndex(); 2316 nTblPtNd = GetPoint()->nNode.GetIndex(); 2317 nTblMkCnt = GetMark()->nContent.GetIndex(); 2318 nTblPtCnt = GetPoint()->nContent.GetIndex(); 2319 return sal_True; 2320 } 2321 2322 2323 // Parke den Tabellen-Cursor auf dem StartNode der Boxen. 2324 void SwTableCursor::ParkCrsr() 2325 { 2326 // Index aus dem TextNode abmelden 2327 SwNode* pNd = &GetPoint()->nNode.GetNode(); 2328 if( !pNd->IsStartNode() ) 2329 pNd = pNd->StartOfSectionNode(); 2330 GetPoint()->nNode = *pNd; 2331 GetPoint()->nContent.Assign( 0, 0 ); 2332 2333 pNd = &GetMark()->nNode.GetNode(); 2334 if( !pNd->IsStartNode() ) 2335 pNd = pNd->StartOfSectionNode(); 2336 GetMark()->nNode = *pNd; 2337 GetMark()->nContent.Assign( 0, 0 ); 2338 2339 bChg = sal_True; 2340 bParked = sal_True; 2341 } 2342 2343 2344 sal_Bool SwTableCursor::HasReadOnlyBoxSel() const 2345 { 2346 sal_Bool bRet = sal_False; 2347 for( sal_uInt16 n = aSelBoxes.Count(); n; ) 2348 if( aSelBoxes[ --n ]->GetFrmFmt()->GetProtect().IsCntntProtected() ) 2349 { 2350 bRet = sal_True; 2351 break; 2352 } 2353 return bRet; 2354 } 2355 2356 2357