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