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