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