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 <cntfrm.hxx> 31 #include <pagefrm.hxx> 32 #include <doc.hxx> 33 #include <docary.hxx> 34 #include <pam.hxx> 35 #include <pamtyp.hxx> 36 #include <txtfrm.hxx> 37 #include <section.hxx> 38 #include <fmtcntnt.hxx> 39 #include <frmatr.hxx> 40 #include <swtable.hxx> 41 #include <crsskip.hxx> 42 43 // --> FME 2004-06-29 #114856# Formular view 44 #include <flyfrm.hxx> 45 #include <fmteiro.hxx> 46 #include <section.hxx> 47 #include <sectfrm.hxx> 48 // <-- 49 #include <ndtxt.hxx> // #111827# 50 51 #include <IMark.hxx> 52 #include <hints.hxx> 53 54 // fuer den dummen ?MSC-? Compiler 55 inline xub_StrLen GetSttOrEnd( sal_Bool bCondition, const SwCntntNode& rNd ) 56 { 57 return bCondition ? 0 : rNd.Len(); 58 } 59 60 /************************************************************************* 61 |* 62 |* SwPosition 63 |* 64 |* Beschreibung PAM.DOC 65 |* Ersterstellung VB 4.3.91 66 |* Letzte Aenderung VB 4.3.91 67 |* 68 *************************************************************************/ 69 70 71 SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwIndex & rCntnt ) 72 : nNode( rNodeIndex ), nContent( rCntnt ) 73 { 74 } 75 76 SwPosition::SwPosition( const SwNodeIndex & rNodeIndex ) 77 : nNode( rNodeIndex ), nContent( nNode.GetNode().GetCntntNode() ) 78 { 79 } 80 81 SwPosition::SwPosition( const SwNode& rNode ) 82 : nNode( rNode ), nContent( nNode.GetNode().GetCntntNode() ) 83 { 84 } 85 86 SwPosition::SwPosition( SwCntntNode & rNode, const xub_StrLen nOffset ) 87 : nNode( rNode ), nContent( &rNode, nOffset ) 88 { 89 } 90 91 92 SwPosition::SwPosition( const SwPosition & rPos ) 93 : nNode( rPos.nNode ), nContent( rPos.nContent ) 94 { 95 } 96 97 SwPosition &SwPosition::operator=(const SwPosition &rPos) 98 { 99 nNode = rPos.nNode; 100 nContent = rPos.nContent; 101 return *this; 102 } 103 104 105 sal_Bool SwPosition::operator<(const SwPosition &rPos) const 106 { 107 if( nNode < rPos.nNode ) 108 return sal_True; 109 if( nNode == rPos.nNode ) 110 return ( nContent < rPos.nContent ); 111 return sal_False; 112 } 113 114 115 sal_Bool SwPosition::operator>(const SwPosition &rPos) const 116 { 117 if(nNode > rPos.nNode ) 118 return sal_True; 119 if( nNode == rPos.nNode ) 120 return ( nContent > rPos.nContent ); 121 return sal_False; 122 } 123 124 125 sal_Bool SwPosition::operator<=(const SwPosition &rPos) const 126 { 127 if(nNode < rPos.nNode ) 128 return sal_True; 129 if( nNode == rPos.nNode ) 130 return ( nContent <= rPos.nContent ); 131 return sal_False; 132 } 133 134 135 sal_Bool SwPosition::operator>=(const SwPosition &rPos) const 136 { 137 if(nNode > rPos.nNode ) 138 return sal_True; 139 if( nNode == rPos.nNode ) 140 return ( nContent >= rPos.nContent ); 141 return sal_False; 142 } 143 144 145 sal_Bool SwPosition::operator==(const SwPosition &rPos) const 146 { 147 return 148 ( ( nNode == rPos.nNode ) && ( nContent == rPos.nContent ) ? 149 sal_True: sal_False); 150 } 151 152 153 sal_Bool SwPosition::operator!=(const SwPosition &rPos) const 154 { 155 if( nNode != rPos.nNode ) 156 return sal_True; 157 return ( nContent != rPos.nContent ); 158 } 159 160 SwDoc * SwPosition::GetDoc() const 161 { 162 return nNode.GetNode().GetDoc(); 163 } 164 165 SwComparePosition ComparePosition( 166 const SwPosition& rStt1, const SwPosition& rEnd1, 167 const SwPosition& rStt2, const SwPosition& rEnd2 ) 168 { 169 SwComparePosition nRet; 170 if( rStt1 < rStt2 ) 171 { 172 if( rEnd1 > rStt2 ) 173 { 174 if( rEnd1 >= rEnd2 ) 175 nRet = POS_OUTSIDE; 176 else 177 nRet = POS_OVERLAP_BEFORE; 178 179 } 180 else if( rEnd1 == rStt2 ) 181 nRet = POS_COLLIDE_END; 182 else 183 nRet = POS_BEFORE; 184 } 185 else if( rEnd2 > rStt1 ) 186 { 187 if( rEnd2 >= rEnd1 ) 188 { 189 if( rEnd2 == rEnd1 && rStt2 == rStt1 ) 190 nRet = POS_EQUAL; 191 else 192 nRet = POS_INSIDE; 193 } 194 else 195 { 196 if (rStt1 == rStt2) 197 nRet = POS_OUTSIDE; 198 else 199 nRet = POS_OVERLAP_BEHIND; 200 } 201 } 202 else if( rEnd2 == rStt1 ) 203 nRet = POS_COLLIDE_START; 204 else 205 nRet = POS_BEHIND; 206 return nRet; 207 } 208 209 SwComparePosition ComparePosition( 210 const unsigned long nStt1, const unsigned long nEnd1, 211 const unsigned long nStt2, const unsigned long nEnd2 ) 212 { 213 SwComparePosition nRet; 214 if( nStt1 < nStt2 ) 215 { 216 if( nEnd1 > nStt2 ) 217 { 218 if( nEnd1 >= nEnd2 ) 219 nRet = POS_OUTSIDE; 220 else 221 nRet = POS_OVERLAP_BEFORE; 222 223 } 224 else if( nEnd1 == nStt2 ) 225 nRet = POS_COLLIDE_END; 226 else 227 nRet = POS_BEFORE; 228 } 229 else if( nEnd2 > nStt1 ) 230 { 231 if( nEnd2 >= nEnd1 ) 232 { 233 if( nEnd2 == nEnd1 && nStt2 == nStt1 ) 234 nRet = POS_EQUAL; 235 else 236 nRet = POS_INSIDE; 237 } 238 else 239 { 240 if (nStt1 == nStt2) 241 nRet = POS_OUTSIDE; 242 else 243 nRet = POS_OVERLAP_BEHIND; 244 } 245 } 246 else if( nEnd2 == nStt1 ) 247 nRet = POS_COLLIDE_START; 248 else 249 nRet = POS_BEHIND; 250 return nRet; 251 } 252 253 /* */ 254 255 enum CHKSECTION { Chk_Both, Chk_One, Chk_None }; 256 257 258 CHKSECTION lcl_TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, const SwNode& rEndNd ) 259 { 260 sal_uLong nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex(); 261 CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None; 262 if( nStt < nEndIdx && nEnd >= nEndIdx ) 263 return( eSec == Chk_One ? Chk_Both : Chk_One ); 264 return eSec; 265 } 266 267 268 sal_Bool lcl_ChkOneRange( CHKSECTION eSec, sal_Bool bChkSections, 269 const SwNode& rBaseEnd, sal_uLong nStt, sal_uLong nEnd ) 270 { 271 if( eSec != Chk_Both ) 272 return sal_False; 273 274 if( !bChkSections ) 275 return sal_True; 276 277 // suche die umspannende Section 278 const SwNodes& rNds = rBaseEnd.GetNodes(); 279 const SwNode *pTmp, *pNd = rNds[ nStt ]; 280 if( !pNd->IsStartNode() ) 281 pNd = pNd->StartOfSectionNode(); 282 283 if( pNd == rNds[ nEnd ]->StartOfSectionNode() ) 284 return sal_True; // der gleiche StartNode, die selbe Section 285 286 // steht schon auf einem GrundSection Node ? Fehler !!! 287 if( !pNd->StartOfSectionIndex() ) 288 return sal_False; 289 290 while( ( pTmp = pNd->StartOfSectionNode())->EndOfSectionNode() != 291 &rBaseEnd ) 292 pNd = pTmp; 293 294 sal_uLong nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex(); 295 return nSttIdx <= nStt && nStt <= nEndIdx && 296 nSttIdx <= nEnd && nEnd <= nEndIdx ? sal_True : sal_False; 297 } 298 299 300 sal_Bool CheckNodesRange( const SwNodeIndex& rStt, 301 const SwNodeIndex& rEnd, sal_Bool bChkSection ) 302 { 303 const SwNodes& rNds = rStt.GetNodes(); 304 sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex(); 305 CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() ); 306 if( Chk_None != eSec ) return eSec == Chk_Both ? sal_True : sal_False; 307 308 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() ); 309 if( Chk_None != eSec ) 310 return lcl_ChkOneRange( eSec, bChkSection, 311 rNds.GetEndOfAutotext(), nStt, nEnd ); 312 313 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() ); 314 if( Chk_None != eSec ) 315 return lcl_ChkOneRange( eSec, bChkSection, 316 rNds.GetEndOfPostIts(), nStt, nEnd ); 317 318 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() ); 319 if( Chk_None != eSec ) 320 return lcl_ChkOneRange( eSec, bChkSection, 321 rNds.GetEndOfInserts(), nStt, nEnd ); 322 323 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() ); 324 if( Chk_None != eSec ) 325 return lcl_ChkOneRange( eSec, bChkSection, 326 rNds.GetEndOfRedlines(), nStt, nEnd ); 327 328 return sal_False; // liegt irgendwo dazwischen, FEHLER 329 } 330 331 332 sal_Bool GoNext(SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode ) 333 { 334 if( pNd->IsCntntNode() ) 335 return ((SwCntntNode*)pNd)->GoNext( pIdx, nMode ); 336 return sal_False; 337 } 338 339 340 sal_Bool GoPrevious( SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode ) 341 { 342 if( pNd->IsCntntNode() ) 343 return ((SwCntntNode*)pNd)->GoPrevious( pIdx, nMode ); 344 return sal_False; 345 } 346 347 348 SwCntntNode* GoNextNds( SwNodeIndex* pIdx, sal_Bool bChk ) 349 { 350 SwNodeIndex aIdx( *pIdx ); 351 SwCntntNode* pNd = aIdx.GetNodes().GoNext( &aIdx ); 352 if( pNd ) 353 { 354 if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() && 355 !CheckNodesRange( *pIdx, aIdx, sal_True ) ) 356 pNd = 0; 357 else 358 *pIdx = aIdx; 359 } 360 return pNd; 361 } 362 363 364 SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, sal_Bool bChk ) 365 { 366 SwNodeIndex aIdx( *pIdx ); 367 SwCntntNode* pNd = aIdx.GetNodes().GoPrevious( &aIdx ); 368 if( pNd ) 369 { 370 if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() && 371 !CheckNodesRange( *pIdx, aIdx, sal_True ) ) 372 pNd = 0; 373 else 374 *pIdx = aIdx; 375 } 376 return pNd; 377 } 378 379 // ---------------------------------------------------------------------- 380 381 /************************************************************************* 382 |* 383 |* SwPointAndMark 384 |* 385 |* Beschreibung PAM.DOC 386 |* Ersterstellung VB 4.3.91 387 |* Letzte Aenderung JP 6.5.91 388 |* 389 *************************************************************************/ 390 391 SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing ) 392 : Ring( pRing ) 393 , m_Bound1( rPos ) 394 , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize 395 , m_pPoint( &m_Bound1 ) 396 , m_pMark( m_pPoint ) 397 , m_bIsInFrontOfLabel( false ) 398 { 399 } 400 401 SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing ) 402 : Ring( pRing ) 403 , m_Bound1( rMark ) 404 , m_Bound2( rPoint ) 405 , m_pPoint( &m_Bound2 ) 406 , m_pMark( &m_Bound1 ) 407 , m_bIsInFrontOfLabel( false ) 408 { 409 } 410 411 SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint, 412 long nMarkOffset, long nPointOffset, SwPaM* pRing ) 413 : Ring( pRing ) 414 , m_Bound1( rMark ) 415 , m_Bound2( rPoint ) 416 , m_pPoint( &m_Bound2 ) 417 , m_pMark( &m_Bound1 ) 418 , m_bIsInFrontOfLabel( false ) 419 { 420 if ( nMarkOffset ) 421 { 422 m_pMark->nNode += nMarkOffset; 423 } 424 if ( nPointOffset ) 425 { 426 m_pPoint->nNode += nPointOffset; 427 } 428 429 m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 ); 430 m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 ); 431 } 432 433 SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint, 434 long nMarkOffset, long nPointOffset, SwPaM* pRing ) 435 : Ring( pRing ) 436 , m_Bound1( rMark ) 437 , m_Bound2( rPoint ) 438 , m_pPoint( &m_Bound2 ) 439 , m_pMark( &m_Bound1 ) 440 , m_bIsInFrontOfLabel( false ) 441 { 442 if ( nMarkOffset ) 443 { 444 m_pMark->nNode += nMarkOffset; 445 } 446 if ( nPointOffset ) 447 { 448 m_pPoint->nNode += nPointOffset; 449 } 450 451 m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 ); 452 m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 ); 453 } 454 455 SwPaM::SwPaM( const SwNodeIndex& rMark , xub_StrLen nMarkCntnt, 456 const SwNodeIndex& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing ) 457 : Ring( pRing ) 458 , m_Bound1( rMark ) 459 , m_Bound2( rPoint ) 460 , m_pPoint( &m_Bound2 ) 461 , m_pMark( &m_Bound1 ) 462 , m_bIsInFrontOfLabel( false ) 463 { 464 m_pPoint->nContent.Assign( rPoint.GetNode().GetCntntNode(), nPointCntnt); 465 m_pMark ->nContent.Assign( rMark .GetNode().GetCntntNode(), nMarkCntnt ); 466 } 467 468 SwPaM::SwPaM( const SwNode& rMark , xub_StrLen nMarkCntnt, 469 const SwNode& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing ) 470 : Ring( pRing ) 471 , m_Bound1( rMark ) 472 , m_Bound2( rPoint ) 473 , m_pPoint( &m_Bound2 ) 474 , m_pMark( &m_Bound1 ) 475 , m_bIsInFrontOfLabel( false ) 476 { 477 m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(), 478 nPointCntnt); 479 m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetCntntNode(), 480 nMarkCntnt ); 481 } 482 483 SwPaM::SwPaM( const SwNode& rNode, xub_StrLen nCntnt, SwPaM* pRing ) 484 : Ring( pRing ) 485 , m_Bound1( rNode ) 486 , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize 487 , m_pPoint( &m_Bound1 ) 488 , m_pMark( &m_Bound1 ) 489 , m_bIsInFrontOfLabel( false ) 490 { 491 m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(), 492 nCntnt ); 493 } 494 495 SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, xub_StrLen nCntnt, SwPaM* pRing ) 496 : Ring( pRing ) 497 , m_Bound1( rNodeIdx ) 498 , m_Bound2( rNodeIdx.GetNode().GetNodes() ) // default initialize 499 , m_pPoint( &m_Bound1 ) 500 , m_pMark( &m_Bound1 ) 501 , m_bIsInFrontOfLabel( false ) 502 { 503 m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetCntntNode(), nCntnt ); 504 } 505 506 SwPaM::~SwPaM() {} 507 508 // @@@ semantic: no copy ctor. 509 SwPaM::SwPaM( SwPaM &rPam ) 510 : Ring( &rPam ) 511 , m_Bound1( *(rPam.m_pPoint) ) 512 , m_Bound2( *(rPam.m_pMark) ) 513 , m_pPoint( &m_Bound1 ), m_pMark( rPam.HasMark() ? &m_Bound2 : m_pPoint ) 514 , m_bIsInFrontOfLabel( false ) 515 { 516 } 517 518 // @@@ semantic: no copy assignment for super class Ring. 519 SwPaM &SwPaM::operator=( const SwPaM &rPam ) 520 { 521 *m_pPoint = *( rPam.m_pPoint ); 522 if ( rPam.HasMark() ) 523 { 524 SetMark(); 525 *m_pMark = *( rPam.m_pMark ); 526 } 527 else 528 { 529 DeleteMark(); 530 } 531 return *this; 532 } 533 534 void SwPaM::SetMark() 535 { 536 if (m_pPoint == &m_Bound1) 537 { 538 m_pMark = &m_Bound2; 539 } 540 else 541 { 542 m_pMark = &m_Bound1; 543 } 544 (*m_pMark) = (*m_pPoint); 545 } 546 547 #ifdef DBG_UTIL 548 549 void SwPaM::Exchange() 550 { 551 if (m_pPoint != m_pMark) 552 { 553 SwPosition *pTmp = m_pPoint; 554 m_pPoint = m_pMark; 555 m_pMark = pTmp; 556 } 557 } 558 #endif 559 560 // Bewegen des Cursors 561 562 563 sal_Bool SwPaM::Move( SwMoveFn fnMove, SwGoInDoc fnGo ) 564 { 565 sal_Bool bRet = (*fnGo)( *this, fnMove ); 566 567 m_bIsInFrontOfLabel = false; 568 569 return bRet; 570 } 571 572 573 /************************************************************************* 574 |* 575 |* void SwPaM::MakeRegion( SwMoveFn, SwPaM*, const SwPaM* ) 576 |* 577 |* Beschreibung Setzt den 1. SwPaM auf den uebergebenen SwPaM 578 |* oder setzt auf den Anfang oder Ende vom Document. 579 |* SPoint bleibt auf der Position stehen, GetMark aendert 580 |* sich entsprechend ! 581 |* 582 |* Parameter SwDirection gibt an, ob an Anfang / Ende 583 |* SwPaM * der zu setzende Bereich 584 |* const SwPaM& der enventuell vorgegeben Bereich 585 |* Return-Werte SwPaM* der entsprehend neu gesetzte Bereich 586 |* 587 |* Ersterstellung JP 26.04.91 588 |* Letzte Aenderung JP 26.04.91 589 |* 590 *************************************************************************/ 591 592 593 SwPaM* SwPaM::MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg ) 594 { 595 SwPaM* pPam; 596 if( pOrigRg == 0 ) 597 { 598 pPam = new SwPaM( *m_pPoint ); 599 pPam->SetMark(); // setze Anfang fest 600 pPam->Move( fnMove, fnGoSection); // an Anfang / Ende vom Node 601 602 // stelle SPoint wieder auf alte Position, GetMark auf das "Ende" 603 pPam->Exchange(); 604 } 605 else 606 { 607 pPam = new SwPaM( *(SwPaM*)pOrigRg ); // die Suchregion ist vorgegeben 608 // sorge dafuer, dass SPoint auf dem "echten" StartPunkt steht 609 // FORWARD --> SPoint immer kleiner als GetMark 610 // BACKWARD --> SPoint immer groesser als GetMark 611 if( (pPam->GetMark()->*fnMove->fnCmpOp)( *pPam->GetPoint() ) ) 612 pPam->Exchange(); 613 } 614 return pPam; 615 } 616 617 SwPaM & SwPaM::Normalize(sal_Bool bPointFirst) 618 { 619 if (HasMark()) 620 if ( ( bPointFirst && *m_pPoint > *m_pMark) || 621 (!bPointFirst && *m_pPoint < *m_pMark) ) 622 { 623 Exchange(); 624 } 625 626 return *this; 627 } 628 629 sal_uInt16 SwPaM::GetPageNum( sal_Bool bAtPoint, const Point* pLayPos ) 630 { 631 // return die Seitennummer am Cursor 632 // (fuer Reader + Seitengebundene Rahmen) 633 const SwCntntFrm* pCFrm; 634 const SwPageFrm *pPg; 635 const SwCntntNode *pNd ; 636 const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark; 637 638 if( 0 != ( pNd = pPos->nNode.GetNode().GetCntntNode() ) && 639 0 != ( pCFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), pLayPos, pPos, sal_False )) && 640 0 != ( pPg = pCFrm->FindPageFrm() )) 641 return pPg->GetPhyPageNum(); 642 return 0; 643 } 644 645 // --> FME 2004-06-29 #114856# Formular view 646 // See also SwCrsrShell::IsCrsrReadonly() 647 const SwFrm* lcl_FindEditInReadonlyFrm( const SwFrm& rFrm ) 648 { 649 const SwFrm* pRet = 0; 650 651 const SwFlyFrm* pFly; 652 const SwSectionFrm* pSectionFrm; 653 654 if( rFrm.IsInFly() && 655 (pFly = rFrm.FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() && 656 pFly->Lower() && 657 !pFly->Lower()->IsNoTxtFrm() ) 658 { 659 pRet = pFly; 660 } 661 else if ( rFrm.IsInSct() && 662 0 != ( pSectionFrm = rFrm.FindSctFrm() )->GetSection() && 663 pSectionFrm->GetSection()->IsEditInReadonlyFlag() ) 664 { 665 pRet = pSectionFrm; 666 } 667 668 return pRet; 669 } 670 // <-- 671 672 // steht in etwas geschuetztem oder in die Selektion umspannt 673 // etwas geschuetztes. 674 sal_Bool SwPaM::HasReadonlySel( const bool bFormView ) const 675 { 676 sal_Bool bRet = sal_False; 677 678 const SwCntntNode* pNd = GetPoint()->nNode.GetNode().GetCntntNode(); 679 const SwCntntFrm *pFrm = NULL; 680 if ( pNd != NULL ) 681 { 682 Point aTmpPt; 683 pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, GetPoint(), sal_False ); 684 } 685 686 // Will be set if point are inside edit-in-readonly environment 687 const SwFrm* pPointEditInReadonlyFrm = NULL; 688 if ( pFrm != NULL 689 && ( pFrm->IsProtected() 690 || ( bFormView 691 && 0 == ( pPointEditInReadonlyFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) ) 692 { 693 bRet = sal_True; 694 } 695 else if( pNd != NULL ) 696 { 697 const SwSectionNode* pSNd = pNd->GetSectionNode(); 698 if ( pSNd != NULL 699 && ( pSNd->GetSection().IsProtectFlag() 700 || ( bFormView 701 && !pSNd->GetSection().IsEditInReadonlyFlag()) ) ) 702 { 703 bRet = sal_True; 704 } 705 } 706 707 if ( !bRet 708 && HasMark() 709 && GetPoint()->nNode != GetMark()->nNode ) 710 { 711 pNd = GetMark()->nNode.GetNode().GetCntntNode(); 712 pFrm = NULL; 713 if ( pNd != NULL ) 714 { 715 Point aTmpPt; 716 pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, GetMark(), sal_False ); 717 } 718 719 const SwFrm* pMarkEditInReadonlyFrm = NULL; 720 if ( pFrm != NULL 721 && ( pFrm->IsProtected() 722 || ( bFormView 723 && 0 == ( pMarkEditInReadonlyFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) ) 724 { 725 bRet = sal_True; 726 } 727 else if( pNd != NULL ) 728 { 729 const SwSectionNode* pSNd = pNd->GetSectionNode(); 730 if ( pSNd != NULL 731 && ( pSNd->GetSection().IsProtectFlag() 732 || ( bFormView 733 && !pSNd->GetSection().IsEditInReadonlyFlag()) ) ) 734 { 735 bRet = sal_True; 736 } 737 } 738 739 if ( !bRet && bFormView ) 740 { 741 // Check if start and end frame are inside the _same_ 742 // edit-in-readonly-environment. Otherwise we better return 'true' 743 if ( pPointEditInReadonlyFrm != pMarkEditInReadonlyFrm ) 744 bRet = sal_True; 745 } 746 747 // check for protected section inside the selection 748 if( !bRet ) 749 { 750 sal_uLong nSttIdx = GetMark()->nNode.GetIndex(), 751 nEndIdx = GetPoint()->nNode.GetIndex(); 752 if( nEndIdx <= nSttIdx ) 753 { 754 sal_uLong nTmp = nSttIdx; 755 nSttIdx = nEndIdx; 756 nEndIdx = nTmp; 757 } 758 759 // wenn ein geschuetzter Bereich zwischen den Nodes stehen soll, 760 // muss die Selektion selbst schon x Nodes umfassen. 761 // (TxtNd, SectNd, TxtNd, EndNd, TxtNd ) 762 if( nSttIdx + 3 < nEndIdx ) 763 { 764 const SwSectionFmts& rFmts = GetDoc()->GetSections(); 765 for( sal_uInt16 n = rFmts.Count(); n; ) 766 { 767 const SwSectionFmt* pFmt = rFmts[ --n ]; 768 if( pFmt->GetProtect().IsCntntProtected() ) 769 { 770 const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False); 771 ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" ); 772 sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex(); 773 if( nSttIdx <= nIdx && nEndIdx >= nIdx && 774 rCntnt.GetCntntIdx()->GetNode().GetNodes().IsDocNodes() ) 775 { 776 bRet = sal_True; 777 break; 778 } 779 } 780 } 781 782 #ifdef CHECK_CELL_READONLY 783 //JP 22.01.99: bisher wurden Tabelle, die in der Text-Selektion standen 784 // nicht beachtet. Wollte man das haben, dann muss dieser 785 // Code freigeschaltet werden 786 787 if( !bRet ) 788 { 789 // dann noch ueber alle Tabellen 790 const SwFrmFmts& rFmts = *GetDoc()->GetTblFrmFmts(); 791 for( n = rFmts.Count(); n ; ) 792 { 793 SwFrmFmt* pFmt = (SwFrmFmt*)rFmts[ --n ]; 794 const SwTable* pTbl = SwTable::FindTable( pFmt ); 795 sal_uLong nIdx = pTbl ? pTbl->GetTabSortBoxes()[0]->GetSttIdx() 796 : 0; 797 if( nSttIdx <= nIdx && nEndIdx >= nIdx ) 798 { 799 // dann teste mal alle Boxen 800 const SwTableSortBoxes& rBoxes = pTbl->GetTabSortBoxes(); 801 802 for( sal_uInt16 i = rBoxes.Count(); i; ) 803 if( rBoxes[ --i ]->GetFrmFmt()->GetProtect(). 804 IsCntntProtected() ) 805 { 806 bRet = sal_True; 807 break; 808 } 809 810 if( bRet ) 811 break; 812 } 813 } 814 } 815 #endif 816 } 817 } 818 } 819 820 //FIXME FieldBk 821 // TODO: Form Protection when Enhanced Fields are enabled 822 if (!bRet) 823 { 824 const SwDoc *pDoc = GetDoc(); 825 sw::mark::IMark* pA = NULL; 826 sw::mark::IMark* pB = NULL; 827 if ( pDoc ) 828 { 829 const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( ); 830 pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL; 831 pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA; 832 bRet = ( pA != pB ); 833 } 834 bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM ); 835 if ( bProtectForm ) 836 bRet |= ( pA == NULL || pB == NULL ); 837 } 838 839 return bRet; 840 } 841 842 //-------------------- Suche nach Formaten( FormatNamen ) ----------------- 843 844 // die Funktion gibt in Suchrichtung den folgenden Node zurueck. 845 // Ist in der Richtung keiner mehr vorhanden oder ist dieser ausserhalb 846 // des Bereiches, wird ein 0 Pointer returnt. 847 // Das rbFirst gibt an, ob es man zu erstenmal einen Node holt. Ist das der 848 // Fall, darf die Position vom Pam nicht veraendert werden! 849 850 851 SwCntntNode* GetNode( SwPaM & rPam, sal_Bool& rbFirst, SwMoveFn fnMove, 852 sal_Bool bInReadOnly ) 853 { 854 SwCntntNode * pNd = 0; 855 SwCntntFrm* pFrm; 856 if( ((*rPam.GetPoint()).*fnMove->fnCmpOp)( *rPam.GetMark() ) || 857 ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) ) 858 { 859 if( rbFirst ) 860 { 861 rbFirst = sal_False; 862 pNd = rPam.GetCntntNode(); 863 if( pNd ) 864 { 865 if( 866 ( 867 0 == ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout() ) ) || 868 ( !bInReadOnly && pFrm->IsProtected() ) || 869 (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) 870 ) || 871 ( !bInReadOnly && pNd->FindSectionNode() && 872 pNd->FindSectionNode()->GetSection().IsProtect() 873 ) 874 ) 875 { 876 pNd = 0; 877 } 878 } 879 } 880 881 if( !pNd ) // steht Cursor auf keinem ContentNode ? 882 { 883 SwPosition aPos( *rPam.GetPoint() ); 884 sal_Bool bSrchForward = fnMove == fnMoveForward; 885 SwNodes& rNodes = aPos.nNode.GetNodes(); 886 887 // zum naechsten / vorherigen ContentNode 888 // Funktioniert noch alles, wenn die Uerbpruefung vom ueberspringen der 889 // Sektions herausgenommen wird ?? 890 // if( (*fnMove->fnNds)( rNodes, &aPos.nNode ) ) 891 while( sal_True ) 892 { 893 pNd = bSrchForward 894 ? rNodes.GoNextSection( &aPos.nNode, sal_True, !bInReadOnly ) 895 : rNodes.GoPrevSection( &aPos.nNode, sal_True, !bInReadOnly ); 896 if( pNd ) 897 { 898 aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd )); 899 // liegt Position immer noch im Bereich ? 900 if( (aPos.*fnMove->fnCmpOp)( *rPam.GetMark() ) ) 901 { 902 // nur in der AutoTextSection koennen Node stehen, die 903 // nicht angezeigt werden !! 904 if( 0 == ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout() ) ) || 905 ( !bInReadOnly && pFrm->IsProtected() ) || 906 ( pFrm->IsTxtFrm() && 907 ((SwTxtFrm*)pFrm)->IsHiddenNow() ) ) 908 909 // rNodes[ rNodes.EndOfAutotext ]->StartOfSection().GetIndex() 910 // < aPos.nNode.GetIndex() && aPos.nNode.GetIndex() 911 // < rNodes.EndOfAutotext.GetIndex() && 912 // 0 == ( pFrm = pNd->GetFrm()) && 913 // pFrm->IsProtected() ) 914 { 915 pNd = 0; 916 continue; // suche weiter 917 } 918 *(SwPosition*)rPam.GetPoint() = aPos; 919 } 920 else 921 pNd = 0; // kein gueltiger Node 922 break; 923 } 924 break; 925 } 926 } 927 } 928 return pNd; 929 } 930 931 // ---------------------------------------------------------------------- 932 933 // hier folgen die Move-Methoden ( Foward, Backward; Content, Node, Doc ) 934 935 936 void GoStartDoc( SwPosition * pPos ) 937 { 938 SwNodes& rNodes = pPos->nNode.GetNodes(); 939 pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode(); 940 // es muss immer ein ContentNode gefunden werden !! 941 SwCntntNode* pCNd = rNodes.GoNext( &pPos->nNode ); 942 if( pCNd ) 943 pCNd->MakeStartIndex( &pPos->nContent ); 944 } 945 946 947 void GoEndDoc( SwPosition * pPos ) 948 { 949 SwNodes& rNodes = pPos->nNode.GetNodes(); 950 pPos->nNode = rNodes.GetEndOfContent(); 951 SwCntntNode* pCNd = GoPreviousNds( &pPos->nNode, sal_True ); 952 if( pCNd ) 953 pCNd->MakeEndIndex( &pPos->nContent ); 954 } 955 956 957 void GoStartSection( SwPosition * pPos ) 958 { 959 // springe zum Anfang der Section 960 SwNodes& rNodes = pPos->nNode.GetNodes(); 961 sal_uInt16 nLevel = rNodes.GetSectionLevel( pPos->nNode ); 962 if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() ) 963 nLevel--; 964 do { rNodes.GoStartOfSection( &pPos->nNode ); } while( nLevel-- ); 965 966 // steht jetzt schon auf einem CntntNode 967 pPos->nNode.GetNode().GetCntntNode()->MakeStartIndex( &pPos->nContent ); 968 } 969 970 // gehe an das Ende der akt. Grund-Section 971 972 973 void GoEndSection( SwPosition * pPos ) 974 { 975 // springe zum Anfang/Ende der Section 976 SwNodes& rNodes = pPos->nNode.GetNodes(); 977 sal_uInt16 nLevel = rNodes.GetSectionLevel( pPos->nNode ); 978 if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() ) 979 nLevel--; 980 do { rNodes.GoEndOfSection( &pPos->nNode ); } while( nLevel-- ); 981 982 // steht jetzt auf einem EndNode, also zum vorherigen CntntNode 983 if( GoPreviousNds( &pPos->nNode, sal_True ) ) 984 pPos->nNode.GetNode().GetCntntNode()->MakeEndIndex( &pPos->nContent ); 985 } 986 987 988 989 sal_Bool GoInDoc( SwPaM & rPam, SwMoveFn fnMove ) 990 { 991 (*fnMove->fnDoc)( rPam.GetPoint() ); 992 return sal_True; 993 } 994 995 996 sal_Bool GoInSection( SwPaM & rPam, SwMoveFn fnMove ) 997 { 998 (*fnMove->fnSections)( (SwPosition*)rPam.GetPoint() ); 999 return sal_True; 1000 } 1001 1002 1003 sal_Bool GoInNode( SwPaM & rPam, SwMoveFn fnMove ) 1004 { 1005 SwCntntNode *pNd = (*fnMove->fnNds)( &rPam.GetPoint()->nNode, sal_True ); 1006 if( pNd ) 1007 rPam.GetPoint()->nContent.Assign( pNd, 1008 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) ); 1009 return 0 != pNd; 1010 } 1011 1012 1013 sal_Bool GoInCntnt( SwPaM & rPam, SwMoveFn fnMove ) 1014 { 1015 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(), 1016 &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS )) 1017 return sal_True; 1018 return GoInNode( rPam, fnMove ); 1019 } 1020 1021 sal_Bool GoInCntntCells( SwPaM & rPam, SwMoveFn fnMove ) 1022 { 1023 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(), 1024 &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS )) 1025 return sal_True; 1026 return GoInNode( rPam, fnMove ); 1027 } 1028 1029 sal_Bool GoInCntntSkipHidden( SwPaM & rPam, SwMoveFn fnMove ) 1030 { 1031 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(), 1032 &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) ) 1033 return sal_True; 1034 return GoInNode( rPam, fnMove ); 1035 } 1036 1037 sal_Bool GoInCntntCellsSkipHidden( SwPaM & rPam, SwMoveFn fnMove ) 1038 { 1039 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(), 1040 &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) ) 1041 return sal_True; 1042 return GoInNode( rPam, fnMove ); 1043 } 1044 1045 1046 1047 // --------- Funktionsdefinitionen fuer die SwCrsrShell -------------- 1048 1049 1050 sal_Bool GoPrevPara( SwPaM & rPam, SwPosPara aPosPara ) 1051 { 1052 if( rPam.Move( fnMoveBackward, fnGoNode ) ) 1053 { 1054 // steht immer auf einem ContentNode ! 1055 SwPosition& rPos = *rPam.GetPoint(); 1056 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode(); 1057 rPos.nContent.Assign( pNd, 1058 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) ); 1059 return sal_True; 1060 } 1061 return sal_False; 1062 } 1063 1064 1065 sal_Bool GoCurrPara( SwPaM & rPam, SwPosPara aPosPara ) 1066 { 1067 SwPosition& rPos = *rPam.GetPoint(); 1068 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode(); 1069 if( pNd ) 1070 { 1071 xub_StrLen nOld = rPos.nContent.GetIndex(), 1072 nNew = aPosPara == fnMoveForward ? 0 : pNd->Len(); 1073 // stand er schon auf dem Anfang/Ende dann zum naechsten/vorherigen 1074 if( nOld != nNew ) 1075 { 1076 rPos.nContent.Assign( pNd, nNew ); 1077 return sal_True; 1078 } 1079 } 1080 // den Node noch etwas bewegen ( auf den naechsten/vorh. CntntNode) 1081 if( ( aPosPara==fnParaStart && 0 != ( pNd = 1082 GoPreviousNds( &rPos.nNode, sal_True ))) || 1083 ( aPosPara==fnParaEnd && 0 != ( pNd = 1084 GoNextNds( &rPos.nNode, sal_True ))) ) 1085 { 1086 rPos.nContent.Assign( pNd, 1087 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd )); 1088 return sal_True; 1089 } 1090 return sal_False; 1091 } 1092 1093 1094 sal_Bool GoNextPara( SwPaM & rPam, SwPosPara aPosPara ) 1095 { 1096 if( rPam.Move( fnMoveForward, fnGoNode ) ) 1097 { 1098 // steht immer auf einem ContentNode ! 1099 SwPosition& rPos = *rPam.GetPoint(); 1100 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode(); 1101 rPos.nContent.Assign( pNd, 1102 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) ); 1103 return sal_True; 1104 } 1105 return sal_False; 1106 } 1107 1108 1109 1110 sal_Bool GoCurrSection( SwPaM & rPam, SwMoveFn fnMove ) 1111 { 1112 SwPosition& rPos = *rPam.GetPoint(); 1113 SwPosition aSavePos( rPos ); // eine Vergleichsposition 1114 SwNodes& rNds = aSavePos.nNode.GetNodes(); 1115 (rNds.*fnMove->fnSection)( &rPos.nNode ); 1116 SwCntntNode *pNd; 1117 if( 0 == ( pNd = rPos.nNode.GetNode().GetCntntNode()) && 1118 0 == ( pNd = (*fnMove->fnNds)( &rPos.nNode, sal_True )) ) 1119 { 1120 rPos = aSavePos; // Cusror nicht veraendern 1121 return sal_False; 1122 } 1123 1124 rPos.nContent.Assign( pNd, 1125 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) ); 1126 return aSavePos != rPos; 1127 } 1128 1129 1130 sal_Bool GoNextSection( SwPaM & rPam, SwMoveFn fnMove ) 1131 { 1132 SwPosition& rPos = *rPam.GetPoint(); 1133 SwPosition aSavePos( rPos ); // eine Vergleichsposition 1134 SwNodes& rNds = aSavePos.nNode.GetNodes(); 1135 rNds.GoEndOfSection( &rPos.nNode ); 1136 1137 // kein weiterer ContentNode vorhanden ? 1138 if( !GoInCntnt( rPam, fnMoveForward ) ) 1139 { 1140 rPos = aSavePos; // Cusror nicht veraendern 1141 return sal_False; 1142 } 1143 (rNds.*fnMove->fnSection)( &rPos.nNode ); 1144 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode(); 1145 rPos.nContent.Assign( pNd, 1146 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) ); 1147 return sal_True; 1148 } 1149 1150 1151 sal_Bool GoPrevSection( SwPaM & rPam, SwMoveFn fnMove ) 1152 { 1153 SwPosition& rPos = *rPam.GetPoint(); 1154 SwPosition aSavePos( rPos ); // eine Vergleichsposition 1155 SwNodes& rNds = aSavePos.nNode.GetNodes(); 1156 rNds.GoStartOfSection( &rPos.nNode ); 1157 1158 // kein weiterer ContentNode vorhanden ? 1159 if( !GoInCntnt( rPam, fnMoveBackward )) 1160 { 1161 rPos = aSavePos; // Cusror nicht veraendern 1162 return sal_False; 1163 } 1164 (rNds.*fnMove->fnSection)( &rPos.nNode ); 1165 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode(); 1166 rPos.nContent.Assign( pNd, 1167 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd )); 1168 return sal_True; 1169 } 1170 1171 // #111827# 1172 String SwPaM::GetTxt() const 1173 { 1174 String aResult; 1175 1176 SwNodeIndex aNodeIndex = Start()->nNode; 1177 1178 /* The first node can be the end node. A first end node must be 1179 handled, too. There fore do ... while and no incrementing of 1180 aNodeIndex in the first pass. 1181 */ 1182 bool bFirst = true; 1183 do 1184 { 1185 if (! bFirst) 1186 { 1187 aNodeIndex++; 1188 } 1189 1190 bFirst = false; 1191 1192 SwTxtNode * pTxtNode = aNodeIndex.GetNode().GetTxtNode(); 1193 1194 if (pTxtNode != NULL) 1195 { 1196 const String & aTmpStr = pTxtNode->GetTxt(); 1197 1198 if (aNodeIndex == Start()->nNode) 1199 { 1200 xub_StrLen nEnd; 1201 if (End()->nNode == aNodeIndex) 1202 nEnd = End()->nContent.GetIndex(); 1203 else 1204 nEnd = aTmpStr.Len(); 1205 1206 aResult += aTmpStr.Copy(Start()->nContent.GetIndex(), 1207 nEnd - Start()->nContent.GetIndex()) ; 1208 } 1209 else if (aNodeIndex == End()->nNode) 1210 aResult += aTmpStr.Copy(0, End()->nContent.GetIndex()); 1211 else 1212 aResult += aTmpStr; 1213 } 1214 } 1215 while (aNodeIndex != End()->nNode); 1216 1217 return aResult; 1218 } 1219 1220 sal_Bool SwPaM::Overlap(const SwPaM & a, const SwPaM & b) 1221 { 1222 return !(*b.End() <= *a.Start() || *a.End() <= *b.End()); 1223 } 1224 1225 void SwPaM::InvalidatePaM() 1226 { 1227 const SwNode *_pNd=this->GetNode(); 1228 const SwTxtNode *_pTxtNd=(_pNd!=NULL?_pNd->GetTxtNode():NULL); 1229 if (_pTxtNd!=NULL) 1230 { 1231 // pretent that the PaM marks inserted text to recalc the portion... 1232 SwInsTxt aHint( Start()->nContent.GetIndex(), 1233 End()->nContent.GetIndex() - Start()->nContent.GetIndex() + 1 ); 1234 SwModify *_pModify=(SwModify*)_pTxtNd; 1235 _pModify->ModifyNotification( 0, &aHint); 1236 } 1237 } 1238 1239 sal_Bool SwPaM::LessThan(const SwPaM & a, const SwPaM & b) 1240 { 1241 return (*a.Start() < *b.Start()) || (*a.Start() == *b.Start() && *a.End() < *b.End()); 1242 } 1243