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