update dev300-m58
[ooovba.git] / sw / source / core / crsr / pam.cxx
blobc5a7344761152b6a00d24f09cd0d70fe56690d75
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pam.cxx,v $
10 * $Revision: 1.23.12.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svx/protitem.hxx>
37 #include <cntfrm.hxx>
38 #include <pagefrm.hxx>
39 #include <doc.hxx>
40 #include <docary.hxx>
41 #include <pam.hxx>
42 #include <pamtyp.hxx>
43 #include <txtfrm.hxx>
44 #include <section.hxx>
45 #include <fmtcntnt.hxx>
46 #include <frmatr.hxx>
47 #include <swtable.hxx>
48 #include <crsskip.hxx>
50 // --> FME 2004-06-29 #114856# Formular view
51 #include <flyfrm.hxx>
52 #include <fmteiro.hxx>
53 #include <section.hxx>
54 #include <sectfrm.hxx>
55 // <--
56 #include <ndtxt.hxx> // #111827#
58 #include <IMark.hxx>
59 #include <hints.hxx>
61 // fuer den dummen ?MSC-? Compiler
62 inline xub_StrLen GetSttOrEnd( BOOL bCondition, const SwCntntNode& rNd )
64 return bCondition ? 0 : rNd.Len();
67 /*************************************************************************
69 |* SwPosition
71 |* Beschreibung PAM.DOC
72 |* Ersterstellung VB 4.3.91
73 |* Letzte Aenderung VB 4.3.91
75 *************************************************************************/
78 SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwIndex & rCntnt )
79 : nNode( rNodeIndex ), nContent( rCntnt )
83 SwPosition::SwPosition( const SwNodeIndex & rNodeIndex )
84 : nNode( rNodeIndex ), nContent( nNode.GetNode().GetCntntNode() )
88 SwPosition::SwPosition( const SwNode& rNode )
89 : nNode( rNode ), nContent( nNode.GetNode().GetCntntNode() )
93 SwPosition::SwPosition( SwCntntNode & rNode, const xub_StrLen nOffset )
94 : nNode( rNode ), nContent( &rNode, nOffset )
99 SwPosition::SwPosition( const SwPosition & rPos )
100 : nNode( rPos.nNode ), nContent( rPos.nContent )
104 SwPosition &SwPosition::operator=(const SwPosition &rPos)
106 nNode = rPos.nNode;
107 nContent = rPos.nContent;
108 return *this;
112 BOOL SwPosition::operator<(const SwPosition &rPos) const
114 if( nNode < rPos.nNode )
115 return TRUE;
116 if( nNode == rPos.nNode )
117 return ( nContent < rPos.nContent );
118 return FALSE;
122 BOOL SwPosition::operator>(const SwPosition &rPos) const
124 if(nNode > rPos.nNode )
125 return TRUE;
126 if( nNode == rPos.nNode )
127 return ( nContent > rPos.nContent );
128 return FALSE;
132 BOOL SwPosition::operator<=(const SwPosition &rPos) const
134 if(nNode < rPos.nNode )
135 return TRUE;
136 if( nNode == rPos.nNode )
137 return ( nContent <= rPos.nContent );
138 return FALSE;
142 BOOL SwPosition::operator>=(const SwPosition &rPos) const
144 if(nNode > rPos.nNode )
145 return TRUE;
146 if( nNode == rPos.nNode )
147 return ( nContent >= rPos.nContent );
148 return FALSE;
152 BOOL SwPosition::operator==(const SwPosition &rPos) const
154 return
155 ( ( nNode == rPos.nNode ) && ( nContent == rPos.nContent ) ?
156 TRUE: FALSE);
160 BOOL SwPosition::operator!=(const SwPosition &rPos) const
162 if( nNode != rPos.nNode )
163 return TRUE;
164 return ( nContent != rPos.nContent );
167 SwDoc * SwPosition::GetDoc() const
169 return nNode.GetNode().GetDoc();
172 SwComparePosition ComparePosition(
173 const SwPosition& rStt1, const SwPosition& rEnd1,
174 const SwPosition& rStt2, const SwPosition& rEnd2 )
176 SwComparePosition nRet;
177 if( rStt1 < rStt2 )
179 if( rEnd1 > rStt2 )
181 if( rEnd1 >= rEnd2 )
182 nRet = POS_OUTSIDE;
183 else
184 nRet = POS_OVERLAP_BEFORE;
187 else if( rEnd1 == rStt2 )
188 nRet = POS_COLLIDE_END;
189 else
190 nRet = POS_BEFORE;
192 else if( rEnd2 > rStt1 )
194 if( rEnd2 >= rEnd1 )
196 if( rEnd2 == rEnd1 && rStt2 == rStt1 )
197 nRet = POS_EQUAL;
198 else
199 nRet = POS_INSIDE;
201 else
202 nRet = POS_OVERLAP_BEHIND;
204 else if( rEnd2 == rStt1 )
205 nRet = POS_COLLIDE_START;
206 else
207 nRet = POS_BEHIND;
208 return nRet;
211 SwComparePosition ComparePosition(
212 const unsigned long nStt1, const unsigned long nEnd1,
213 const unsigned long nStt2, const unsigned long nEnd2 )
215 SwComparePosition nRet;
216 if( nStt1 < nStt2 )
218 if( nEnd1 > nStt2 )
220 if( nEnd1 >= nEnd2 )
221 nRet = POS_OUTSIDE;
222 else
223 nRet = POS_OVERLAP_BEFORE;
226 else if( nEnd1 == nStt2 )
227 nRet = POS_COLLIDE_END;
228 else
229 nRet = POS_BEFORE;
231 else if( nEnd2 > nStt1 )
233 if( nEnd2 >= nEnd1 )
235 if( nEnd2 == nEnd1 && nStt2 == nStt1 )
236 nRet = POS_EQUAL;
237 else
238 nRet = POS_INSIDE;
240 else
241 nRet = POS_OVERLAP_BEHIND;
243 else if( nEnd2 == nStt1 )
244 nRet = POS_COLLIDE_START;
245 else
246 nRet = POS_BEHIND;
247 return nRet;
250 /* \f */
252 enum CHKSECTION { Chk_Both, Chk_One, Chk_None };
255 CHKSECTION lcl_TstIdx( ULONG nSttIdx, ULONG nEndIdx, const SwNode& rEndNd )
257 ULONG nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex();
258 CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None;
259 if( nStt < nEndIdx && nEnd >= nEndIdx )
260 return( eSec == Chk_One ? Chk_Both : Chk_One );
261 return eSec;
265 BOOL lcl_ChkOneRange( CHKSECTION eSec, BOOL bChkSections,
266 const SwNode& rBaseEnd, ULONG nStt, ULONG nEnd )
268 if( eSec != Chk_Both )
269 return FALSE;
271 if( !bChkSections )
272 return TRUE;
274 // suche die umspannende Section
275 const SwNodes& rNds = rBaseEnd.GetNodes();
276 const SwNode *pTmp, *pNd = rNds[ nStt ];
277 if( !pNd->IsStartNode() )
278 pNd = pNd->StartOfSectionNode();
280 if( pNd == rNds[ nEnd ]->StartOfSectionNode() )
281 return TRUE; // der gleiche StartNode, die selbe Section
283 // steht schon auf einem GrundSection Node ? Fehler !!!
284 if( !pNd->StartOfSectionIndex() )
285 return FALSE;
287 while( ( pTmp = pNd->StartOfSectionNode())->EndOfSectionNode() !=
288 &rBaseEnd )
289 pNd = pTmp;
291 ULONG nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex();
292 return nSttIdx <= nStt && nStt <= nEndIdx &&
293 nSttIdx <= nEnd && nEnd <= nEndIdx ? TRUE : FALSE;
297 BOOL CheckNodesRange( const SwNodeIndex& rStt,
298 const SwNodeIndex& rEnd, BOOL bChkSection )
300 const SwNodes& rNds = rStt.GetNodes();
301 ULONG nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
302 CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() );
303 if( Chk_None != eSec ) return eSec == Chk_Both ? TRUE : FALSE;
305 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() );
306 if( Chk_None != eSec )
307 return lcl_ChkOneRange( eSec, bChkSection,
308 rNds.GetEndOfAutotext(), nStt, nEnd );
310 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() );
311 if( Chk_None != eSec )
312 return lcl_ChkOneRange( eSec, bChkSection,
313 rNds.GetEndOfPostIts(), nStt, nEnd );
315 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() );
316 if( Chk_None != eSec )
317 return lcl_ChkOneRange( eSec, bChkSection,
318 rNds.GetEndOfInserts(), nStt, nEnd );
320 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() );
321 if( Chk_None != eSec )
322 return lcl_ChkOneRange( eSec, bChkSection,
323 rNds.GetEndOfRedlines(), nStt, nEnd );
325 return FALSE; // liegt irgendwo dazwischen, FEHLER
329 BOOL GoNext(SwNode* pNd, SwIndex * pIdx, USHORT nMode )
331 if( pNd->IsCntntNode() )
332 return ((SwCntntNode*)pNd)->GoNext( pIdx, nMode );
333 return FALSE;
337 BOOL GoPrevious( SwNode* pNd, SwIndex * pIdx, USHORT nMode )
339 if( pNd->IsCntntNode() )
340 return ((SwCntntNode*)pNd)->GoPrevious( pIdx, nMode );
341 return FALSE;
345 SwCntntNode* GoNextNds( SwNodeIndex* pIdx, BOOL bChk )
347 SwNodeIndex aIdx( *pIdx );
348 SwCntntNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
349 if( pNd )
351 if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() &&
352 !CheckNodesRange( *pIdx, aIdx, TRUE ) )
353 pNd = 0;
354 else
355 *pIdx = aIdx;
357 return pNd;
361 SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, BOOL bChk )
363 SwNodeIndex aIdx( *pIdx );
364 SwCntntNode* pNd = aIdx.GetNodes().GoPrevious( &aIdx );
365 if( pNd )
367 if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() &&
368 !CheckNodesRange( *pIdx, aIdx, TRUE ) )
369 pNd = 0;
370 else
371 *pIdx = aIdx;
373 return pNd;
376 // ----------------------------------------------------------------------
378 /*************************************************************************
380 |* SwPointAndMark
382 |* Beschreibung PAM.DOC
383 |* Ersterstellung VB 4.3.91
384 |* Letzte Aenderung JP 6.5.91
386 *************************************************************************/
388 SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing )
389 : Ring( pRing )
390 , m_Bound1( rPos )
391 , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize
392 , m_pPoint( &m_Bound1 )
393 , m_pMark( m_pPoint )
394 , m_bIsInFrontOfLabel( false )
398 SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing )
399 : Ring( pRing )
400 , m_Bound1( rMark )
401 , m_Bound2( rPoint )
402 , m_pPoint( &m_Bound2 )
403 , m_pMark( &m_Bound1 )
404 , m_bIsInFrontOfLabel( false )
408 SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint,
409 long nMarkOffset, long nPointOffset, SwPaM* pRing )
410 : Ring( pRing )
411 , m_Bound1( rMark )
412 , m_Bound2( rPoint )
413 , m_pPoint( &m_Bound2 )
414 , m_pMark( &m_Bound1 )
415 , m_bIsInFrontOfLabel( false )
417 if ( nMarkOffset )
419 m_pMark->nNode += nMarkOffset;
421 if ( nPointOffset )
423 m_pPoint->nNode += nPointOffset;
426 m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
427 m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
430 SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint,
431 long nMarkOffset, long nPointOffset, SwPaM* pRing )
432 : Ring( pRing )
433 , m_Bound1( rMark )
434 , m_Bound2( rPoint )
435 , m_pPoint( &m_Bound2 )
436 , m_pMark( &m_Bound1 )
437 , m_bIsInFrontOfLabel( false )
439 if ( nMarkOffset )
441 m_pMark->nNode += nMarkOffset;
443 if ( nPointOffset )
445 m_pPoint->nNode += nPointOffset;
448 m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
449 m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
452 SwPaM::SwPaM( const SwNodeIndex& rMark , xub_StrLen nMarkCntnt,
453 const SwNodeIndex& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
454 : Ring( pRing )
455 , m_Bound1( rMark )
456 , m_Bound2( rPoint )
457 , m_pPoint( &m_Bound2 )
458 , m_pMark( &m_Bound1 )
459 , m_bIsInFrontOfLabel( false )
461 m_pPoint->nContent.Assign( rPoint.GetNode().GetCntntNode(), nPointCntnt);
462 m_pMark ->nContent.Assign( rMark .GetNode().GetCntntNode(), nMarkCntnt );
465 SwPaM::SwPaM( const SwNode& rMark , xub_StrLen nMarkCntnt,
466 const SwNode& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
467 : Ring( pRing )
468 , m_Bound1( rMark )
469 , m_Bound2( rPoint )
470 , m_pPoint( &m_Bound2 )
471 , m_pMark( &m_Bound1 )
472 , m_bIsInFrontOfLabel( false )
474 m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
475 nPointCntnt);
476 m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetCntntNode(),
477 nMarkCntnt );
480 SwPaM::SwPaM( const SwNode& rNode, xub_StrLen nCntnt, SwPaM* pRing )
481 : Ring( pRing )
482 , m_Bound1( rNode )
483 , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize
484 , m_pPoint( &m_Bound1 )
485 , m_pMark( &m_Bound1 )
486 , m_bIsInFrontOfLabel( false )
488 m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
489 nCntnt );
492 SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, xub_StrLen nCntnt, SwPaM* pRing )
493 : Ring( pRing )
494 , m_Bound1( rNodeIdx )
495 , m_Bound2( rNodeIdx.GetNode().GetNodes() ) // default initialize
496 , m_pPoint( &m_Bound1 )
497 , m_pMark( &m_Bound1 )
498 , m_bIsInFrontOfLabel( false )
500 m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetCntntNode(), nCntnt );
503 SwPaM::~SwPaM() {}
505 // @@@ semantic: no copy ctor.
506 SwPaM::SwPaM( SwPaM &rPam )
507 : Ring( &rPam )
508 , m_Bound1( *(rPam.m_pPoint) )
509 , m_Bound2( *(rPam.m_pMark) )
510 , m_pPoint( &m_Bound1 ), m_pMark( rPam.HasMark() ? &m_Bound2 : m_pPoint )
511 , m_bIsInFrontOfLabel( false )
515 // @@@ semantic: no copy assignment for super class Ring.
516 SwPaM &SwPaM::operator=( const SwPaM &rPam )
518 *m_pPoint = *( rPam.m_pPoint );
519 if ( rPam.HasMark() )
521 SetMark();
522 *m_pMark = *( rPam.m_pMark );
524 else
526 DeleteMark();
528 return *this;
531 void SwPaM::SetMark()
533 if (m_pPoint == &m_Bound1)
535 m_pMark = &m_Bound2;
537 else
539 m_pMark = &m_Bound1;
541 (*m_pMark) = (*m_pPoint);
544 #ifndef PRODUCT
546 void SwPaM::Exchange()
548 if (m_pPoint != m_pMark)
550 SwPosition *pTmp = m_pPoint;
551 m_pPoint = m_pMark;
552 m_pMark = pTmp;
555 #endif
557 // Bewegen des Cursors
560 BOOL SwPaM::Move( SwMoveFn fnMove, SwGoInDoc fnGo )
562 BOOL bRet = (*fnGo)( *this, fnMove );
564 m_bIsInFrontOfLabel = false;
566 return bRet;
570 /*************************************************************************
572 |* void SwPaM::MakeRegion( SwMoveFn, SwPaM*, const SwPaM* )
574 |* Beschreibung Setzt den 1. SwPaM auf den uebergebenen SwPaM
575 |* oder setzt auf den Anfang oder Ende vom Document.
576 |* SPoint bleibt auf der Position stehen, GetMark aendert
577 |* sich entsprechend !
579 |* Parameter SwDirection gibt an, ob an Anfang / Ende
580 |* SwPaM * der zu setzende Bereich
581 |* const SwPaM& der enventuell vorgegeben Bereich
582 |* Return-Werte SwPaM* der entsprehend neu gesetzte Bereich
584 |* Ersterstellung JP 26.04.91
585 |* Letzte Aenderung JP 26.04.91
587 *************************************************************************/
590 SwPaM* SwPaM::MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg )
592 SwPaM* pPam;
593 if( pOrigRg == 0 )
595 pPam = new SwPaM( *m_pPoint );
596 pPam->SetMark(); // setze Anfang fest
597 pPam->Move( fnMove, fnGoSection); // an Anfang / Ende vom Node
599 // stelle SPoint wieder auf alte Position, GetMark auf das "Ende"
600 pPam->Exchange();
602 else
604 pPam = new SwPaM( *(SwPaM*)pOrigRg ); // die Suchregion ist vorgegeben
605 // sorge dafuer, dass SPoint auf dem "echten" StartPunkt steht
606 // FORWARD --> SPoint immer kleiner als GetMark
607 // BACKWARD --> SPoint immer groesser als GetMark
608 if( (pPam->GetMark()->*fnMove->fnCmpOp)( *pPam->GetPoint() ) )
609 pPam->Exchange();
611 return pPam;
614 SwPaM & SwPaM::Normalize(BOOL bPointFirst)
616 if (HasMark())
617 if ( ( bPointFirst && *m_pPoint > *m_pMark) ||
618 (!bPointFirst && *m_pPoint < *m_pMark) )
620 Exchange();
623 return *this;
626 USHORT SwPaM::GetPageNum( BOOL bAtPoint, const Point* pLayPos )
628 // return die Seitennummer am Cursor
629 // (fuer Reader + Seitengebundene Rahmen)
630 const SwCntntFrm* pCFrm;
631 const SwPageFrm *pPg;
632 const SwCntntNode *pNd ;
633 const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark;
635 if( 0 != ( pNd = pPos->nNode.GetNode().GetCntntNode() ) &&
636 0 != ( pCFrm = pNd->GetFrm( pLayPos, pPos, FALSE )) &&
637 0 != ( pPg = pCFrm->FindPageFrm() ))
638 return pPg->GetPhyPageNum();
639 return 0;
642 // --> FME 2004-06-29 #114856# Formular view
643 // See also SwCrsrShell::IsCrsrReadonly()
644 const SwFrm* lcl_FindEditInReadonlyFrm( const SwFrm& rFrm )
646 const SwFrm* pRet = 0;
648 const SwFlyFrm* pFly;
649 const SwSectionFrm* pSectionFrm;
651 if( rFrm.IsInFly() &&
652 (pFly = rFrm.FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
653 pFly->Lower() &&
654 !pFly->Lower()->IsNoTxtFrm() )
656 pRet = pFly;
658 else if ( rFrm.IsInSct() &&
659 0 != ( pSectionFrm = rFrm.FindSctFrm() )->GetSection() &&
660 pSectionFrm->GetSection()->IsEditInReadonlyFlag() )
662 pRet = pSectionFrm;
665 return pRet;
667 // <--
669 // steht in etwas geschuetztem oder in die Selektion umspannt
670 // etwas geschuetztes.
671 BOOL SwPaM::HasReadonlySel( bool bFormView ) const
673 BOOL bRet = FALSE;
674 Point aTmpPt;
675 const SwCntntNode *pNd;
676 const SwCntntFrm *pFrm;
678 if( 0 != ( pNd = GetPoint()->nNode.GetNode().GetCntntNode() ))
679 pFrm = pNd->GetFrm( &aTmpPt, GetPoint(), FALSE );
680 else
681 pFrm = 0;
683 // --> FME 2004-06-29 #114856# Formular view
684 // Will be set if point/mark are inside edit-in-readonly environment
685 const SwFrm* pSttEIRFrm = 0;
686 const SwFrm* pEndEIRFrm = 0;
688 if( pFrm && ( pFrm->IsProtected() ||
689 // --> FME 2004-06-29 #114856# Formular view
690 ( bFormView &&
691 0 == ( pSttEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
692 // <--
693 bRet = TRUE;
694 else if( pNd )
696 const SwSectionNode* pSNd = pNd->GetSectionNode();
697 if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
698 // --> FME 2004-06-29 #114856# Formular view
699 (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
700 // <--
701 bRet = TRUE;
704 if( !bRet && HasMark() && GetPoint()->nNode != GetMark()->nNode )
706 if( 0 != ( pNd = GetMark()->nNode.GetNode().GetCntntNode() ))
707 pFrm = pNd->GetFrm( &aTmpPt, GetMark(), FALSE );
708 else
709 pFrm = 0;
711 if( pFrm && ( pFrm->IsProtected() ||
712 // --> FME 2004-06-29 #114856# Formular view
713 ( bFormView &&
714 0 == ( pEndEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
715 // <--
716 bRet = TRUE;
717 else if( pNd )
719 const SwSectionNode* pSNd = pNd->GetSectionNode();
720 if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
721 // --> FME 2004-06-29 #114856# Formular view
722 (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
723 // <--
724 bRet = TRUE;
727 // --> FME 2004-06-29 #114856# Formular view
728 if ( !bRet && bFormView )
730 // Check if start and end frame are inside the _same_
731 // edit-in-readonly-environment. Otherwise we better return 'true'
732 if ( pSttEIRFrm != pEndEIRFrm )
733 bRet = TRUE;
735 // <--
737 // oder sollte eine geschuetzte Section innerhalb der
738 // Selektion liegen?
739 if( !bRet )
741 ULONG nSttIdx = GetMark()->nNode.GetIndex(),
742 nEndIdx = GetPoint()->nNode.GetIndex();
743 if( nEndIdx <= nSttIdx )
745 ULONG nTmp = nSttIdx;
746 nSttIdx = nEndIdx;
747 nEndIdx = nTmp;
750 // wenn ein geschuetzter Bereich zwischen den Nodes stehen soll,
751 // muss die Selektion selbst schon x Nodes umfassen.
752 // (TxtNd, SectNd, TxtNd, EndNd, TxtNd )
753 if( nSttIdx + 3 < nEndIdx )
755 const SwSectionFmts& rFmts = GetDoc()->GetSections();
756 for( USHORT n = rFmts.Count(); n; )
758 const SwSectionFmt* pFmt = rFmts[ --n ];
759 if( pFmt->GetProtect().IsCntntProtected() )
761 const SwFmtCntnt& rCntnt = pFmt->GetCntnt(FALSE);
762 ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
763 ULONG nIdx = rCntnt.GetCntntIdx()->GetIndex();
764 if( nSttIdx <= nIdx && nEndIdx >= nIdx &&
765 rCntnt.GetCntntIdx()->GetNode().GetNodes().IsDocNodes() )
767 /* // ist es keine gelinkte Section, dann kann sie auch
768 // nicht mitselektiert werden
769 const SwSection& rSect = *pFmt->GetSection();
770 if( CONTENT_SECTION == rSect.GetType() )
772 RestoreSavePos();
773 return TRUE;
776 bRet = TRUE;
777 break;
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
787 if( !bRet )
789 // dann noch ueber alle Tabellen
790 const SwFrmFmts& rFmts = *GetDoc()->GetTblFrmFmts();
791 for( n = rFmts.Count(); n ; )
793 SwFrmFmt* pFmt = (SwFrmFmt*)rFmts[ --n ];
794 const SwTable* pTbl = SwTable::FindTable( pFmt );
795 ULONG nIdx = pTbl ? pTbl->GetTabSortBoxes()[0]->GetSttIdx()
796 : 0;
797 if( nSttIdx <= nIdx && nEndIdx >= nIdx )
799 // dann teste mal alle Boxen
800 const SwTableSortBoxes& rBoxes = pTbl->GetTabSortBoxes();
802 for( USHORT i = rBoxes.Count(); i; )
803 if( rBoxes[ --i ]->GetFrmFmt()->GetProtect().
804 IsCntntProtected() )
806 bRet = TRUE;
807 break;
810 if( bRet )
811 break;
815 #endif
819 //FIXME FieldBk
820 // TODO: Form Protection when Enhanced Fields are enabled
821 if (!bRet) {
822 const SwDoc *pDoc = GetDoc();
823 sw::mark::IMark* pA = NULL;
824 sw::mark::IMark* pB = NULL;
825 if ( pDoc )
827 const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( );
828 pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
829 pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA;
830 bRet = ( pA != pB );
832 bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
833 if ( bProtectForm )
834 bRet |= ( pA == NULL || pB == NULL );
836 return bRet;
839 //-------------------- Suche nach Formaten( FormatNamen ) -----------------
841 // die Funktion gibt in Suchrichtung den folgenden Node zurueck.
842 // Ist in der Richtung keiner mehr vorhanden oder ist dieser ausserhalb
843 // des Bereiches, wird ein 0 Pointer returnt.
844 // Das rbFirst gibt an, ob es man zu erstenmal einen Node holt. Ist das der
845 // Fall, darf die Position vom Pam nicht veraendert werden!
848 SwCntntNode* GetNode( SwPaM & rPam, BOOL& rbFirst, SwMoveFn fnMove,
849 BOOL bInReadOnly )
851 SwCntntNode * pNd = 0;
852 SwCntntFrm* pFrm;
853 if( ((*rPam.GetPoint()).*fnMove->fnCmpOp)( *rPam.GetMark() ) ||
854 ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
856 if( rbFirst )
858 rbFirst = FALSE;
859 pNd = rPam.GetCntntNode();
860 if( pNd )
862 if(
864 0 == ( pFrm = pNd->GetFrm()) ||
865 ( !bInReadOnly && pFrm->IsProtected() ) ||
866 (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow())
867 ) ||
868 ( !bInReadOnly && pNd->FindSectionNode() &&
869 pNd->FindSectionNode()->GetSection().IsProtect()
873 pNd = 0;
878 if( !pNd ) // steht Cursor auf keinem ContentNode ?
880 SwPosition aPos( *rPam.GetPoint() );
881 BOOL bSrchForward = fnMove == fnMoveForward;
882 SwNodes& rNodes = aPos.nNode.GetNodes();
884 // zum naechsten / vorherigen ContentNode
885 // Funktioniert noch alles, wenn die Uerbpruefung vom ueberspringen der
886 // Sektions herausgenommen wird ??
887 // if( (*fnMove->fnNds)( rNodes, &aPos.nNode ) )
888 while( TRUE )
890 pNd = bSrchForward
891 ? rNodes.GoNextSection( &aPos.nNode, TRUE, !bInReadOnly )
892 : rNodes.GoPrevSection( &aPos.nNode, TRUE, !bInReadOnly );
893 if( pNd )
895 aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd ));
896 // liegt Position immer noch im Bereich ?
897 if( (aPos.*fnMove->fnCmpOp)( *rPam.GetMark() ) )
899 // nur in der AutoTextSection koennen Node stehen, die
900 // nicht angezeigt werden !!
901 if( 0 == ( pFrm = pNd->GetFrm()) ||
902 ( !bInReadOnly && pFrm->IsProtected() ) ||
903 ( pFrm->IsTxtFrm() &&
904 ((SwTxtFrm*)pFrm)->IsHiddenNow() ) )
906 // rNodes[ rNodes.EndOfAutotext ]->StartOfSection().GetIndex()
907 // < aPos.nNode.GetIndex() && aPos.nNode.GetIndex()
908 // < rNodes.EndOfAutotext.GetIndex() &&
909 // 0 == ( pFrm = pNd->GetFrm()) &&
910 // pFrm->IsProtected() )
912 pNd = 0;
913 continue; // suche weiter
915 *(SwPosition*)rPam.GetPoint() = aPos;
917 else
918 pNd = 0; // kein gueltiger Node
919 break;
921 break;
925 return pNd;
928 // ----------------------------------------------------------------------
930 // hier folgen die Move-Methoden ( Foward, Backward; Content, Node, Doc )
933 void GoStartDoc( SwPosition * pPos )
935 SwNodes& rNodes = pPos->nNode.GetNodes();
936 pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
937 // es muss immer ein ContentNode gefunden werden !!
938 SwCntntNode* pCNd = rNodes.GoNext( &pPos->nNode );
939 if( pCNd )
940 pCNd->MakeStartIndex( &pPos->nContent );
944 void GoEndDoc( SwPosition * pPos )
946 SwNodes& rNodes = pPos->nNode.GetNodes();
947 pPos->nNode = rNodes.GetEndOfContent();
948 SwCntntNode* pCNd = GoPreviousNds( &pPos->nNode, TRUE );
949 if( pCNd )
950 pCNd->MakeEndIndex( &pPos->nContent );
954 void GoStartSection( SwPosition * pPos )
956 // springe zum Anfang der Section
957 SwNodes& rNodes = pPos->nNode.GetNodes();
958 USHORT nLevel = rNodes.GetSectionLevel( pPos->nNode );
959 if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
960 nLevel--;
961 do { rNodes.GoStartOfSection( &pPos->nNode ); } while( nLevel-- );
963 // steht jetzt schon auf einem CntntNode
964 pPos->nNode.GetNode().GetCntntNode()->MakeStartIndex( &pPos->nContent );
967 // gehe an das Ende der akt. Grund-Section
970 void GoEndSection( SwPosition * pPos )
972 // springe zum Anfang/Ende der Section
973 SwNodes& rNodes = pPos->nNode.GetNodes();
974 USHORT nLevel = rNodes.GetSectionLevel( pPos->nNode );
975 if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
976 nLevel--;
977 do { rNodes.GoEndOfSection( &pPos->nNode ); } while( nLevel-- );
979 // steht jetzt auf einem EndNode, also zum vorherigen CntntNode
980 if( GoPreviousNds( &pPos->nNode, TRUE ) )
981 pPos->nNode.GetNode().GetCntntNode()->MakeEndIndex( &pPos->nContent );
986 BOOL GoInDoc( SwPaM & rPam, SwMoveFn fnMove )
988 (*fnMove->fnDoc)( rPam.GetPoint() );
989 return TRUE;
993 BOOL GoInSection( SwPaM & rPam, SwMoveFn fnMove )
995 (*fnMove->fnSections)( (SwPosition*)rPam.GetPoint() );
996 return TRUE;
1000 BOOL GoInNode( SwPaM & rPam, SwMoveFn fnMove )
1002 SwCntntNode *pNd = (*fnMove->fnNds)( &rPam.GetPoint()->nNode, TRUE );
1003 if( pNd )
1004 rPam.GetPoint()->nContent.Assign( pNd,
1005 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1006 return 0 != pNd;
1010 BOOL GoInCntnt( SwPaM & rPam, SwMoveFn fnMove )
1012 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1013 &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS ))
1014 return TRUE;
1015 return GoInNode( rPam, fnMove );
1018 BOOL GoInCntntCells( SwPaM & rPam, SwMoveFn fnMove )
1020 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1021 &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS ))
1022 return TRUE;
1023 return GoInNode( rPam, fnMove );
1026 BOOL GoInCntntSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
1028 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1029 &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) )
1030 return TRUE;
1031 return GoInNode( rPam, fnMove );
1034 BOOL GoInCntntCellsSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
1036 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1037 &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) )
1038 return TRUE;
1039 return GoInNode( rPam, fnMove );
1044 // --------- Funktionsdefinitionen fuer die SwCrsrShell --------------
1047 BOOL GoPrevPara( SwPaM & rPam, SwPosPara aPosPara )
1049 if( rPam.Move( fnMoveBackward, fnGoNode ) )
1051 // steht immer auf einem ContentNode !
1052 SwPosition& rPos = *rPam.GetPoint();
1053 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
1054 rPos.nContent.Assign( pNd,
1055 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
1056 return TRUE;
1058 return FALSE;
1062 BOOL GoCurrPara( SwPaM & rPam, SwPosPara aPosPara )
1064 SwPosition& rPos = *rPam.GetPoint();
1065 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
1066 if( pNd )
1068 xub_StrLen nOld = rPos.nContent.GetIndex(),
1069 nNew = aPosPara == fnMoveForward ? 0 : pNd->Len();
1070 // stand er schon auf dem Anfang/Ende dann zum naechsten/vorherigen
1071 if( nOld != nNew )
1073 rPos.nContent.Assign( pNd, nNew );
1074 return TRUE;
1077 // den Node noch etwas bewegen ( auf den naechsten/vorh. CntntNode)
1078 if( ( aPosPara==fnParaStart && 0 != ( pNd =
1079 GoPreviousNds( &rPos.nNode, TRUE ))) ||
1080 ( aPosPara==fnParaEnd && 0 != ( pNd =
1081 GoNextNds( &rPos.nNode, TRUE ))) )
1083 rPos.nContent.Assign( pNd,
1084 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ));
1085 return TRUE;
1087 return FALSE;
1091 BOOL GoNextPara( SwPaM & rPam, SwPosPara aPosPara )
1093 if( rPam.Move( fnMoveForward, fnGoNode ) )
1095 // steht immer auf einem ContentNode !
1096 SwPosition& rPos = *rPam.GetPoint();
1097 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
1098 rPos.nContent.Assign( pNd,
1099 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
1100 return TRUE;
1102 return FALSE;
1107 BOOL GoCurrSection( SwPaM & rPam, SwMoveFn fnMove )
1109 SwPosition& rPos = *rPam.GetPoint();
1110 SwPosition aSavePos( rPos ); // eine Vergleichsposition
1111 SwNodes& rNds = aSavePos.nNode.GetNodes();
1112 (rNds.*fnMove->fnSection)( &rPos.nNode );
1113 SwCntntNode *pNd;
1114 if( 0 == ( pNd = rPos.nNode.GetNode().GetCntntNode()) &&
1115 0 == ( pNd = (*fnMove->fnNds)( &rPos.nNode, TRUE )) )
1117 rPos = aSavePos; // Cusror nicht veraendern
1118 return FALSE;
1121 rPos.nContent.Assign( pNd,
1122 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1123 return aSavePos != rPos;
1127 BOOL GoNextSection( SwPaM & rPam, SwMoveFn fnMove )
1129 SwPosition& rPos = *rPam.GetPoint();
1130 SwPosition aSavePos( rPos ); // eine Vergleichsposition
1131 SwNodes& rNds = aSavePos.nNode.GetNodes();
1132 rNds.GoEndOfSection( &rPos.nNode );
1134 // kein weiterer ContentNode vorhanden ?
1135 if( !GoInCntnt( rPam, fnMoveForward ) )
1137 rPos = aSavePos; // Cusror nicht veraendern
1138 return FALSE;
1140 (rNds.*fnMove->fnSection)( &rPos.nNode );
1141 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
1142 rPos.nContent.Assign( pNd,
1143 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1144 return TRUE;
1148 BOOL GoPrevSection( SwPaM & rPam, SwMoveFn fnMove )
1150 SwPosition& rPos = *rPam.GetPoint();
1151 SwPosition aSavePos( rPos ); // eine Vergleichsposition
1152 SwNodes& rNds = aSavePos.nNode.GetNodes();
1153 rNds.GoStartOfSection( &rPos.nNode );
1155 // kein weiterer ContentNode vorhanden ?
1156 if( !GoInCntnt( rPam, fnMoveBackward ))
1158 rPos = aSavePos; // Cusror nicht veraendern
1159 return FALSE;
1161 (rNds.*fnMove->fnSection)( &rPos.nNode );
1162 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
1163 rPos.nContent.Assign( pNd,
1164 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ));
1165 return TRUE;
1168 // #111827#
1169 String SwPaM::GetTxt() const
1171 String aResult;
1173 SwNodeIndex aNodeIndex = Start()->nNode;
1175 /* The first node can be the end node. A first end node must be
1176 handled, too. There fore do ... while and no incrementing of
1177 aNodeIndex in the first pass.
1179 bool bFirst = true;
1182 if (! bFirst)
1184 aNodeIndex++;
1187 bFirst = false;
1189 SwTxtNode * pTxtNode = aNodeIndex.GetNode().GetTxtNode();
1191 if (pTxtNode != NULL)
1193 const String & aTmpStr = pTxtNode->GetTxt();
1195 if (aNodeIndex == Start()->nNode)
1197 xub_StrLen nEnd;
1198 if (End()->nNode == aNodeIndex)
1199 nEnd = End()->nContent.GetIndex();
1200 else
1201 nEnd = aTmpStr.Len();
1203 aResult += aTmpStr.Copy(Start()->nContent.GetIndex(),
1204 nEnd - Start()->nContent.GetIndex()) ;
1206 else if (aNodeIndex == End()->nNode)
1207 aResult += aTmpStr.Copy(0, End()->nContent.GetIndex());
1208 else
1209 aResult += aTmpStr;
1212 while (aNodeIndex != End()->nNode);
1214 return aResult;
1217 BOOL SwPaM::Overlap(const SwPaM & a, const SwPaM & b)
1219 return !(*b.End() <= *a.Start() || *a.End() <= *b.End());
1222 void SwPaM::Invalidate()
1224 const SwNode *_pNd=this->GetNode();
1225 const SwTxtNode *_pTxtNd=(_pNd!=NULL?_pNd->GetTxtNode():NULL);
1226 if (_pTxtNd!=NULL) {
1227 //pretent we've added a char to force layout to recalc the portion...
1228 SwInsChr aHint(_pTxtNd->GetIndex());
1229 SwModify *_pModify=(SwModify*)_pTxtNd;
1230 _pModify->Modify( 0, &aHint);
1234 BOOL SwPaM::LessThan(const SwPaM & a, const SwPaM & b)
1236 return (*a.Start() < *b.Start()) || (*a.Start() == *b.Start() && *a.End() < *b.End());