merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / crsr / pam.cxx
blob74b8212c5c16e874a612b0219494a42c587770dc
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
203 if (rStt1 == rStt2)
204 nRet = POS_OUTSIDE;
205 else
206 nRet = POS_OVERLAP_BEHIND;
209 else if( rEnd2 == rStt1 )
210 nRet = POS_COLLIDE_START;
211 else
212 nRet = POS_BEHIND;
213 return nRet;
216 SwComparePosition ComparePosition(
217 const unsigned long nStt1, const unsigned long nEnd1,
218 const unsigned long nStt2, const unsigned long nEnd2 )
220 SwComparePosition nRet;
221 if( nStt1 < nStt2 )
223 if( nEnd1 > nStt2 )
225 if( nEnd1 >= nEnd2 )
226 nRet = POS_OUTSIDE;
227 else
228 nRet = POS_OVERLAP_BEFORE;
231 else if( nEnd1 == nStt2 )
232 nRet = POS_COLLIDE_END;
233 else
234 nRet = POS_BEFORE;
236 else if( nEnd2 > nStt1 )
238 if( nEnd2 >= nEnd1 )
240 if( nEnd2 == nEnd1 && nStt2 == nStt1 )
241 nRet = POS_EQUAL;
242 else
243 nRet = POS_INSIDE;
245 else
247 if (nStt1 == nStt2)
248 nRet = POS_OUTSIDE;
249 else
250 nRet = POS_OVERLAP_BEHIND;
253 else if( nEnd2 == nStt1 )
254 nRet = POS_COLLIDE_START;
255 else
256 nRet = POS_BEHIND;
257 return nRet;
260 /* \f */
262 enum CHKSECTION { Chk_Both, Chk_One, Chk_None };
265 CHKSECTION lcl_TstIdx( ULONG nSttIdx, ULONG nEndIdx, const SwNode& rEndNd )
267 ULONG nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex();
268 CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None;
269 if( nStt < nEndIdx && nEnd >= nEndIdx )
270 return( eSec == Chk_One ? Chk_Both : Chk_One );
271 return eSec;
275 BOOL lcl_ChkOneRange( CHKSECTION eSec, BOOL bChkSections,
276 const SwNode& rBaseEnd, ULONG nStt, ULONG nEnd )
278 if( eSec != Chk_Both )
279 return FALSE;
281 if( !bChkSections )
282 return TRUE;
284 // suche die umspannende Section
285 const SwNodes& rNds = rBaseEnd.GetNodes();
286 const SwNode *pTmp, *pNd = rNds[ nStt ];
287 if( !pNd->IsStartNode() )
288 pNd = pNd->StartOfSectionNode();
290 if( pNd == rNds[ nEnd ]->StartOfSectionNode() )
291 return TRUE; // der gleiche StartNode, die selbe Section
293 // steht schon auf einem GrundSection Node ? Fehler !!!
294 if( !pNd->StartOfSectionIndex() )
295 return FALSE;
297 while( ( pTmp = pNd->StartOfSectionNode())->EndOfSectionNode() !=
298 &rBaseEnd )
299 pNd = pTmp;
301 ULONG nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex();
302 return nSttIdx <= nStt && nStt <= nEndIdx &&
303 nSttIdx <= nEnd && nEnd <= nEndIdx ? TRUE : FALSE;
307 BOOL CheckNodesRange( const SwNodeIndex& rStt,
308 const SwNodeIndex& rEnd, BOOL bChkSection )
310 const SwNodes& rNds = rStt.GetNodes();
311 ULONG nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
312 CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() );
313 if( Chk_None != eSec ) return eSec == Chk_Both ? TRUE : FALSE;
315 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() );
316 if( Chk_None != eSec )
317 return lcl_ChkOneRange( eSec, bChkSection,
318 rNds.GetEndOfAutotext(), nStt, nEnd );
320 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() );
321 if( Chk_None != eSec )
322 return lcl_ChkOneRange( eSec, bChkSection,
323 rNds.GetEndOfPostIts(), nStt, nEnd );
325 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() );
326 if( Chk_None != eSec )
327 return lcl_ChkOneRange( eSec, bChkSection,
328 rNds.GetEndOfInserts(), nStt, nEnd );
330 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() );
331 if( Chk_None != eSec )
332 return lcl_ChkOneRange( eSec, bChkSection,
333 rNds.GetEndOfRedlines(), nStt, nEnd );
335 return FALSE; // liegt irgendwo dazwischen, FEHLER
339 BOOL GoNext(SwNode* pNd, SwIndex * pIdx, USHORT nMode )
341 if( pNd->IsCntntNode() )
342 return ((SwCntntNode*)pNd)->GoNext( pIdx, nMode );
343 return FALSE;
347 BOOL GoPrevious( SwNode* pNd, SwIndex * pIdx, USHORT nMode )
349 if( pNd->IsCntntNode() )
350 return ((SwCntntNode*)pNd)->GoPrevious( pIdx, nMode );
351 return FALSE;
355 SwCntntNode* GoNextNds( SwNodeIndex* pIdx, BOOL bChk )
357 SwNodeIndex aIdx( *pIdx );
358 SwCntntNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
359 if( pNd )
361 if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() &&
362 !CheckNodesRange( *pIdx, aIdx, TRUE ) )
363 pNd = 0;
364 else
365 *pIdx = aIdx;
367 return pNd;
371 SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, BOOL bChk )
373 SwNodeIndex aIdx( *pIdx );
374 SwCntntNode* pNd = aIdx.GetNodes().GoPrevious( &aIdx );
375 if( pNd )
377 if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() &&
378 !CheckNodesRange( *pIdx, aIdx, TRUE ) )
379 pNd = 0;
380 else
381 *pIdx = aIdx;
383 return pNd;
386 // ----------------------------------------------------------------------
388 /*************************************************************************
390 |* SwPointAndMark
392 |* Beschreibung PAM.DOC
393 |* Ersterstellung VB 4.3.91
394 |* Letzte Aenderung JP 6.5.91
396 *************************************************************************/
398 SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing )
399 : Ring( pRing )
400 , m_Bound1( rPos )
401 , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize
402 , m_pPoint( &m_Bound1 )
403 , m_pMark( m_pPoint )
404 , m_bIsInFrontOfLabel( false )
408 SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing )
409 : Ring( pRing )
410 , m_Bound1( rMark )
411 , m_Bound2( rPoint )
412 , m_pPoint( &m_Bound2 )
413 , m_pMark( &m_Bound1 )
414 , m_bIsInFrontOfLabel( false )
418 SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint,
419 long nMarkOffset, long nPointOffset, SwPaM* pRing )
420 : Ring( pRing )
421 , m_Bound1( rMark )
422 , m_Bound2( rPoint )
423 , m_pPoint( &m_Bound2 )
424 , m_pMark( &m_Bound1 )
425 , m_bIsInFrontOfLabel( false )
427 if ( nMarkOffset )
429 m_pMark->nNode += nMarkOffset;
431 if ( nPointOffset )
433 m_pPoint->nNode += nPointOffset;
436 m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
437 m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
440 SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint,
441 long nMarkOffset, long nPointOffset, SwPaM* pRing )
442 : Ring( pRing )
443 , m_Bound1( rMark )
444 , m_Bound2( rPoint )
445 , m_pPoint( &m_Bound2 )
446 , m_pMark( &m_Bound1 )
447 , m_bIsInFrontOfLabel( false )
449 if ( nMarkOffset )
451 m_pMark->nNode += nMarkOffset;
453 if ( nPointOffset )
455 m_pPoint->nNode += nPointOffset;
458 m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
459 m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
462 SwPaM::SwPaM( const SwNodeIndex& rMark , xub_StrLen nMarkCntnt,
463 const SwNodeIndex& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
464 : Ring( pRing )
465 , m_Bound1( rMark )
466 , m_Bound2( rPoint )
467 , m_pPoint( &m_Bound2 )
468 , m_pMark( &m_Bound1 )
469 , m_bIsInFrontOfLabel( false )
471 m_pPoint->nContent.Assign( rPoint.GetNode().GetCntntNode(), nPointCntnt);
472 m_pMark ->nContent.Assign( rMark .GetNode().GetCntntNode(), nMarkCntnt );
475 SwPaM::SwPaM( const SwNode& rMark , xub_StrLen nMarkCntnt,
476 const SwNode& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
477 : Ring( pRing )
478 , m_Bound1( rMark )
479 , m_Bound2( rPoint )
480 , m_pPoint( &m_Bound2 )
481 , m_pMark( &m_Bound1 )
482 , m_bIsInFrontOfLabel( false )
484 m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
485 nPointCntnt);
486 m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetCntntNode(),
487 nMarkCntnt );
490 SwPaM::SwPaM( const SwNode& rNode, xub_StrLen nCntnt, SwPaM* pRing )
491 : Ring( pRing )
492 , m_Bound1( rNode )
493 , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize
494 , m_pPoint( &m_Bound1 )
495 , m_pMark( &m_Bound1 )
496 , m_bIsInFrontOfLabel( false )
498 m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
499 nCntnt );
502 SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, xub_StrLen nCntnt, SwPaM* pRing )
503 : Ring( pRing )
504 , m_Bound1( rNodeIdx )
505 , m_Bound2( rNodeIdx.GetNode().GetNodes() ) // default initialize
506 , m_pPoint( &m_Bound1 )
507 , m_pMark( &m_Bound1 )
508 , m_bIsInFrontOfLabel( false )
510 m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetCntntNode(), nCntnt );
513 SwPaM::~SwPaM() {}
515 // @@@ semantic: no copy ctor.
516 SwPaM::SwPaM( SwPaM &rPam )
517 : Ring( &rPam )
518 , m_Bound1( *(rPam.m_pPoint) )
519 , m_Bound2( *(rPam.m_pMark) )
520 , m_pPoint( &m_Bound1 ), m_pMark( rPam.HasMark() ? &m_Bound2 : m_pPoint )
521 , m_bIsInFrontOfLabel( false )
525 // @@@ semantic: no copy assignment for super class Ring.
526 SwPaM &SwPaM::operator=( const SwPaM &rPam )
528 *m_pPoint = *( rPam.m_pPoint );
529 if ( rPam.HasMark() )
531 SetMark();
532 *m_pMark = *( rPam.m_pMark );
534 else
536 DeleteMark();
538 return *this;
541 void SwPaM::SetMark()
543 if (m_pPoint == &m_Bound1)
545 m_pMark = &m_Bound2;
547 else
549 m_pMark = &m_Bound1;
551 (*m_pMark) = (*m_pPoint);
554 #ifndef PRODUCT
556 void SwPaM::Exchange()
558 if (m_pPoint != m_pMark)
560 SwPosition *pTmp = m_pPoint;
561 m_pPoint = m_pMark;
562 m_pMark = pTmp;
565 #endif
567 // Bewegen des Cursors
570 BOOL SwPaM::Move( SwMoveFn fnMove, SwGoInDoc fnGo )
572 BOOL bRet = (*fnGo)( *this, fnMove );
574 m_bIsInFrontOfLabel = false;
576 return bRet;
580 /*************************************************************************
582 |* void SwPaM::MakeRegion( SwMoveFn, SwPaM*, const SwPaM* )
584 |* Beschreibung Setzt den 1. SwPaM auf den uebergebenen SwPaM
585 |* oder setzt auf den Anfang oder Ende vom Document.
586 |* SPoint bleibt auf der Position stehen, GetMark aendert
587 |* sich entsprechend !
589 |* Parameter SwDirection gibt an, ob an Anfang / Ende
590 |* SwPaM * der zu setzende Bereich
591 |* const SwPaM& der enventuell vorgegeben Bereich
592 |* Return-Werte SwPaM* der entsprehend neu gesetzte Bereich
594 |* Ersterstellung JP 26.04.91
595 |* Letzte Aenderung JP 26.04.91
597 *************************************************************************/
600 SwPaM* SwPaM::MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg )
602 SwPaM* pPam;
603 if( pOrigRg == 0 )
605 pPam = new SwPaM( *m_pPoint );
606 pPam->SetMark(); // setze Anfang fest
607 pPam->Move( fnMove, fnGoSection); // an Anfang / Ende vom Node
609 // stelle SPoint wieder auf alte Position, GetMark auf das "Ende"
610 pPam->Exchange();
612 else
614 pPam = new SwPaM( *(SwPaM*)pOrigRg ); // die Suchregion ist vorgegeben
615 // sorge dafuer, dass SPoint auf dem "echten" StartPunkt steht
616 // FORWARD --> SPoint immer kleiner als GetMark
617 // BACKWARD --> SPoint immer groesser als GetMark
618 if( (pPam->GetMark()->*fnMove->fnCmpOp)( *pPam->GetPoint() ) )
619 pPam->Exchange();
621 return pPam;
624 SwPaM & SwPaM::Normalize(BOOL bPointFirst)
626 if (HasMark())
627 if ( ( bPointFirst && *m_pPoint > *m_pMark) ||
628 (!bPointFirst && *m_pPoint < *m_pMark) )
630 Exchange();
633 return *this;
636 USHORT SwPaM::GetPageNum( BOOL bAtPoint, const Point* pLayPos )
638 // return die Seitennummer am Cursor
639 // (fuer Reader + Seitengebundene Rahmen)
640 const SwCntntFrm* pCFrm;
641 const SwPageFrm *pPg;
642 const SwCntntNode *pNd ;
643 const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark;
645 if( 0 != ( pNd = pPos->nNode.GetNode().GetCntntNode() ) &&
646 0 != ( pCFrm = pNd->GetFrm( pLayPos, pPos, FALSE )) &&
647 0 != ( pPg = pCFrm->FindPageFrm() ))
648 return pPg->GetPhyPageNum();
649 return 0;
652 // --> FME 2004-06-29 #114856# Formular view
653 // See also SwCrsrShell::IsCrsrReadonly()
654 const SwFrm* lcl_FindEditInReadonlyFrm( const SwFrm& rFrm )
656 const SwFrm* pRet = 0;
658 const SwFlyFrm* pFly;
659 const SwSectionFrm* pSectionFrm;
661 if( rFrm.IsInFly() &&
662 (pFly = rFrm.FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
663 pFly->Lower() &&
664 !pFly->Lower()->IsNoTxtFrm() )
666 pRet = pFly;
668 else if ( rFrm.IsInSct() &&
669 0 != ( pSectionFrm = rFrm.FindSctFrm() )->GetSection() &&
670 pSectionFrm->GetSection()->IsEditInReadonlyFlag() )
672 pRet = pSectionFrm;
675 return pRet;
677 // <--
679 // steht in etwas geschuetztem oder in die Selektion umspannt
680 // etwas geschuetztes.
681 BOOL SwPaM::HasReadonlySel( bool bFormView ) const
683 BOOL bRet = FALSE;
684 Point aTmpPt;
685 const SwCntntNode *pNd;
686 const SwCntntFrm *pFrm;
688 if( 0 != ( pNd = GetPoint()->nNode.GetNode().GetCntntNode() ))
689 pFrm = pNd->GetFrm( &aTmpPt, GetPoint(), FALSE );
690 else
691 pFrm = 0;
693 // --> FME 2004-06-29 #114856# Formular view
694 // Will be set if point/mark are inside edit-in-readonly environment
695 const SwFrm* pSttEIRFrm = 0;
696 const SwFrm* pEndEIRFrm = 0;
698 if( pFrm && ( pFrm->IsProtected() ||
699 // --> FME 2004-06-29 #114856# Formular view
700 ( bFormView &&
701 0 == ( pSttEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
702 // <--
703 bRet = TRUE;
704 else if( pNd )
706 const SwSectionNode* pSNd = pNd->GetSectionNode();
707 if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
708 // --> FME 2004-06-29 #114856# Formular view
709 (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
710 // <--
711 bRet = TRUE;
714 if( !bRet && HasMark() && GetPoint()->nNode != GetMark()->nNode )
716 if( 0 != ( pNd = GetMark()->nNode.GetNode().GetCntntNode() ))
717 pFrm = pNd->GetFrm( &aTmpPt, GetMark(), FALSE );
718 else
719 pFrm = 0;
721 if( pFrm && ( pFrm->IsProtected() ||
722 // --> FME 2004-06-29 #114856# Formular view
723 ( bFormView &&
724 0 == ( pEndEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
725 // <--
726 bRet = TRUE;
727 else if( pNd )
729 const SwSectionNode* pSNd = pNd->GetSectionNode();
730 if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
731 // --> FME 2004-06-29 #114856# Formular view
732 (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
733 // <--
734 bRet = TRUE;
737 // --> FME 2004-06-29 #114856# Formular view
738 if ( !bRet && bFormView )
740 // Check if start and end frame are inside the _same_
741 // edit-in-readonly-environment. Otherwise we better return 'true'
742 if ( pSttEIRFrm != pEndEIRFrm )
743 bRet = TRUE;
745 // <--
747 // oder sollte eine geschuetzte Section innerhalb der
748 // Selektion liegen?
749 if( !bRet )
751 ULONG nSttIdx = GetMark()->nNode.GetIndex(),
752 nEndIdx = GetPoint()->nNode.GetIndex();
753 if( nEndIdx <= nSttIdx )
755 ULONG nTmp = nSttIdx;
756 nSttIdx = nEndIdx;
757 nEndIdx = nTmp;
760 // wenn ein geschuetzter Bereich zwischen den Nodes stehen soll,
761 // muss die Selektion selbst schon x Nodes umfassen.
762 // (TxtNd, SectNd, TxtNd, EndNd, TxtNd )
763 if( nSttIdx + 3 < nEndIdx )
765 const SwSectionFmts& rFmts = GetDoc()->GetSections();
766 for( USHORT n = rFmts.Count(); n; )
768 const SwSectionFmt* pFmt = rFmts[ --n ];
769 if( pFmt->GetProtect().IsCntntProtected() )
771 const SwFmtCntnt& rCntnt = pFmt->GetCntnt(FALSE);
772 ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
773 ULONG nIdx = rCntnt.GetCntntIdx()->GetIndex();
774 if( nSttIdx <= nIdx && nEndIdx >= nIdx &&
775 rCntnt.GetCntntIdx()->GetNode().GetNodes().IsDocNodes() )
777 /* // ist es keine gelinkte Section, dann kann sie auch
778 // nicht mitselektiert werden
779 const SwSection& rSect = *pFmt->GetSection();
780 if( CONTENT_SECTION == rSect.GetType() )
782 RestoreSavePos();
783 return TRUE;
786 bRet = TRUE;
787 break;
792 #ifdef CHECK_CELL_READONLY
793 //JP 22.01.99: bisher wurden Tabelle, die in der Text-Selektion standen
794 // nicht beachtet. Wollte man das haben, dann muss dieser
795 // Code freigeschaltet werden
797 if( !bRet )
799 // dann noch ueber alle Tabellen
800 const SwFrmFmts& rFmts = *GetDoc()->GetTblFrmFmts();
801 for( n = rFmts.Count(); n ; )
803 SwFrmFmt* pFmt = (SwFrmFmt*)rFmts[ --n ];
804 const SwTable* pTbl = SwTable::FindTable( pFmt );
805 ULONG nIdx = pTbl ? pTbl->GetTabSortBoxes()[0]->GetSttIdx()
806 : 0;
807 if( nSttIdx <= nIdx && nEndIdx >= nIdx )
809 // dann teste mal alle Boxen
810 const SwTableSortBoxes& rBoxes = pTbl->GetTabSortBoxes();
812 for( USHORT i = rBoxes.Count(); i; )
813 if( rBoxes[ --i ]->GetFrmFmt()->GetProtect().
814 IsCntntProtected() )
816 bRet = TRUE;
817 break;
820 if( bRet )
821 break;
825 #endif
829 //FIXME FieldBk
830 // TODO: Form Protection when Enhanced Fields are enabled
831 if (!bRet) {
832 const SwDoc *pDoc = GetDoc();
833 sw::mark::IMark* pA = NULL;
834 sw::mark::IMark* pB = NULL;
835 if ( pDoc )
837 const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( );
838 pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
839 pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA;
840 bRet = ( pA != pB );
842 bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
843 if ( bProtectForm )
844 bRet |= ( pA == NULL || pB == NULL );
846 return bRet;
849 //-------------------- Suche nach Formaten( FormatNamen ) -----------------
851 // die Funktion gibt in Suchrichtung den folgenden Node zurueck.
852 // Ist in der Richtung keiner mehr vorhanden oder ist dieser ausserhalb
853 // des Bereiches, wird ein 0 Pointer returnt.
854 // Das rbFirst gibt an, ob es man zu erstenmal einen Node holt. Ist das der
855 // Fall, darf die Position vom Pam nicht veraendert werden!
858 SwCntntNode* GetNode( SwPaM & rPam, BOOL& rbFirst, SwMoveFn fnMove,
859 BOOL bInReadOnly )
861 SwCntntNode * pNd = 0;
862 SwCntntFrm* pFrm;
863 if( ((*rPam.GetPoint()).*fnMove->fnCmpOp)( *rPam.GetMark() ) ||
864 ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
866 if( rbFirst )
868 rbFirst = FALSE;
869 pNd = rPam.GetCntntNode();
870 if( pNd )
872 if(
874 0 == ( pFrm = pNd->GetFrm()) ||
875 ( !bInReadOnly && pFrm->IsProtected() ) ||
876 (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow())
877 ) ||
878 ( !bInReadOnly && pNd->FindSectionNode() &&
879 pNd->FindSectionNode()->GetSection().IsProtect()
883 pNd = 0;
888 if( !pNd ) // steht Cursor auf keinem ContentNode ?
890 SwPosition aPos( *rPam.GetPoint() );
891 BOOL bSrchForward = fnMove == fnMoveForward;
892 SwNodes& rNodes = aPos.nNode.GetNodes();
894 // zum naechsten / vorherigen ContentNode
895 // Funktioniert noch alles, wenn die Uerbpruefung vom ueberspringen der
896 // Sektions herausgenommen wird ??
897 // if( (*fnMove->fnNds)( rNodes, &aPos.nNode ) )
898 while( TRUE )
900 pNd = bSrchForward
901 ? rNodes.GoNextSection( &aPos.nNode, TRUE, !bInReadOnly )
902 : rNodes.GoPrevSection( &aPos.nNode, TRUE, !bInReadOnly );
903 if( pNd )
905 aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd ));
906 // liegt Position immer noch im Bereich ?
907 if( (aPos.*fnMove->fnCmpOp)( *rPam.GetMark() ) )
909 // nur in der AutoTextSection koennen Node stehen, die
910 // nicht angezeigt werden !!
911 if( 0 == ( pFrm = pNd->GetFrm()) ||
912 ( !bInReadOnly && pFrm->IsProtected() ) ||
913 ( pFrm->IsTxtFrm() &&
914 ((SwTxtFrm*)pFrm)->IsHiddenNow() ) )
916 // rNodes[ rNodes.EndOfAutotext ]->StartOfSection().GetIndex()
917 // < aPos.nNode.GetIndex() && aPos.nNode.GetIndex()
918 // < rNodes.EndOfAutotext.GetIndex() &&
919 // 0 == ( pFrm = pNd->GetFrm()) &&
920 // pFrm->IsProtected() )
922 pNd = 0;
923 continue; // suche weiter
925 *(SwPosition*)rPam.GetPoint() = aPos;
927 else
928 pNd = 0; // kein gueltiger Node
929 break;
931 break;
935 return pNd;
938 // ----------------------------------------------------------------------
940 // hier folgen die Move-Methoden ( Foward, Backward; Content, Node, Doc )
943 void GoStartDoc( SwPosition * pPos )
945 SwNodes& rNodes = pPos->nNode.GetNodes();
946 pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
947 // es muss immer ein ContentNode gefunden werden !!
948 SwCntntNode* pCNd = rNodes.GoNext( &pPos->nNode );
949 if( pCNd )
950 pCNd->MakeStartIndex( &pPos->nContent );
954 void GoEndDoc( SwPosition * pPos )
956 SwNodes& rNodes = pPos->nNode.GetNodes();
957 pPos->nNode = rNodes.GetEndOfContent();
958 SwCntntNode* pCNd = GoPreviousNds( &pPos->nNode, TRUE );
959 if( pCNd )
960 pCNd->MakeEndIndex( &pPos->nContent );
964 void GoStartSection( SwPosition * pPos )
966 // springe zum Anfang der Section
967 SwNodes& rNodes = pPos->nNode.GetNodes();
968 USHORT nLevel = rNodes.GetSectionLevel( pPos->nNode );
969 if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
970 nLevel--;
971 do { rNodes.GoStartOfSection( &pPos->nNode ); } while( nLevel-- );
973 // steht jetzt schon auf einem CntntNode
974 pPos->nNode.GetNode().GetCntntNode()->MakeStartIndex( &pPos->nContent );
977 // gehe an das Ende der akt. Grund-Section
980 void GoEndSection( SwPosition * pPos )
982 // springe zum Anfang/Ende der Section
983 SwNodes& rNodes = pPos->nNode.GetNodes();
984 USHORT nLevel = rNodes.GetSectionLevel( pPos->nNode );
985 if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
986 nLevel--;
987 do { rNodes.GoEndOfSection( &pPos->nNode ); } while( nLevel-- );
989 // steht jetzt auf einem EndNode, also zum vorherigen CntntNode
990 if( GoPreviousNds( &pPos->nNode, TRUE ) )
991 pPos->nNode.GetNode().GetCntntNode()->MakeEndIndex( &pPos->nContent );
996 BOOL GoInDoc( SwPaM & rPam, SwMoveFn fnMove )
998 (*fnMove->fnDoc)( rPam.GetPoint() );
999 return TRUE;
1003 BOOL GoInSection( SwPaM & rPam, SwMoveFn fnMove )
1005 (*fnMove->fnSections)( (SwPosition*)rPam.GetPoint() );
1006 return TRUE;
1010 BOOL GoInNode( SwPaM & rPam, SwMoveFn fnMove )
1012 SwCntntNode *pNd = (*fnMove->fnNds)( &rPam.GetPoint()->nNode, TRUE );
1013 if( pNd )
1014 rPam.GetPoint()->nContent.Assign( pNd,
1015 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1016 return 0 != pNd;
1020 BOOL GoInCntnt( SwPaM & rPam, SwMoveFn fnMove )
1022 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1023 &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS ))
1024 return TRUE;
1025 return GoInNode( rPam, fnMove );
1028 BOOL GoInCntntCells( SwPaM & rPam, SwMoveFn fnMove )
1030 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1031 &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS ))
1032 return TRUE;
1033 return GoInNode( rPam, fnMove );
1036 BOOL GoInCntntSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
1038 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1039 &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) )
1040 return TRUE;
1041 return GoInNode( rPam, fnMove );
1044 BOOL GoInCntntCellsSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
1046 if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
1047 &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) )
1048 return TRUE;
1049 return GoInNode( rPam, fnMove );
1054 // --------- Funktionsdefinitionen fuer die SwCrsrShell --------------
1057 BOOL GoPrevPara( SwPaM & rPam, SwPosPara aPosPara )
1059 if( rPam.Move( fnMoveBackward, fnGoNode ) )
1061 // steht immer auf einem ContentNode !
1062 SwPosition& rPos = *rPam.GetPoint();
1063 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
1064 rPos.nContent.Assign( pNd,
1065 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
1066 return TRUE;
1068 return FALSE;
1072 BOOL GoCurrPara( SwPaM & rPam, SwPosPara aPosPara )
1074 SwPosition& rPos = *rPam.GetPoint();
1075 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
1076 if( pNd )
1078 xub_StrLen nOld = rPos.nContent.GetIndex(),
1079 nNew = aPosPara == fnMoveForward ? 0 : pNd->Len();
1080 // stand er schon auf dem Anfang/Ende dann zum naechsten/vorherigen
1081 if( nOld != nNew )
1083 rPos.nContent.Assign( pNd, nNew );
1084 return TRUE;
1087 // den Node noch etwas bewegen ( auf den naechsten/vorh. CntntNode)
1088 if( ( aPosPara==fnParaStart && 0 != ( pNd =
1089 GoPreviousNds( &rPos.nNode, TRUE ))) ||
1090 ( aPosPara==fnParaEnd && 0 != ( pNd =
1091 GoNextNds( &rPos.nNode, TRUE ))) )
1093 rPos.nContent.Assign( pNd,
1094 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ));
1095 return TRUE;
1097 return FALSE;
1101 BOOL GoNextPara( SwPaM & rPam, SwPosPara aPosPara )
1103 if( rPam.Move( fnMoveForward, fnGoNode ) )
1105 // steht immer auf einem ContentNode !
1106 SwPosition& rPos = *rPam.GetPoint();
1107 SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
1108 rPos.nContent.Assign( pNd,
1109 ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
1110 return TRUE;
1112 return FALSE;
1117 BOOL GoCurrSection( SwPaM & rPam, SwMoveFn fnMove )
1119 SwPosition& rPos = *rPam.GetPoint();
1120 SwPosition aSavePos( rPos ); // eine Vergleichsposition
1121 SwNodes& rNds = aSavePos.nNode.GetNodes();
1122 (rNds.*fnMove->fnSection)( &rPos.nNode );
1123 SwCntntNode *pNd;
1124 if( 0 == ( pNd = rPos.nNode.GetNode().GetCntntNode()) &&
1125 0 == ( pNd = (*fnMove->fnNds)( &rPos.nNode, TRUE )) )
1127 rPos = aSavePos; // Cusror nicht veraendern
1128 return FALSE;
1131 rPos.nContent.Assign( pNd,
1132 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1133 return aSavePos != rPos;
1137 BOOL GoNextSection( SwPaM & rPam, SwMoveFn fnMove )
1139 SwPosition& rPos = *rPam.GetPoint();
1140 SwPosition aSavePos( rPos ); // eine Vergleichsposition
1141 SwNodes& rNds = aSavePos.nNode.GetNodes();
1142 rNds.GoEndOfSection( &rPos.nNode );
1144 // kein weiterer ContentNode vorhanden ?
1145 if( !GoInCntnt( rPam, fnMoveForward ) )
1147 rPos = aSavePos; // Cusror nicht veraendern
1148 return FALSE;
1150 (rNds.*fnMove->fnSection)( &rPos.nNode );
1151 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
1152 rPos.nContent.Assign( pNd,
1153 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1154 return TRUE;
1158 BOOL GoPrevSection( SwPaM & rPam, SwMoveFn fnMove )
1160 SwPosition& rPos = *rPam.GetPoint();
1161 SwPosition aSavePos( rPos ); // eine Vergleichsposition
1162 SwNodes& rNds = aSavePos.nNode.GetNodes();
1163 rNds.GoStartOfSection( &rPos.nNode );
1165 // kein weiterer ContentNode vorhanden ?
1166 if( !GoInCntnt( rPam, fnMoveBackward ))
1168 rPos = aSavePos; // Cusror nicht veraendern
1169 return FALSE;
1171 (rNds.*fnMove->fnSection)( &rPos.nNode );
1172 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
1173 rPos.nContent.Assign( pNd,
1174 ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ));
1175 return TRUE;
1178 // #111827#
1179 String SwPaM::GetTxt() const
1181 String aResult;
1183 SwNodeIndex aNodeIndex = Start()->nNode;
1185 /* The first node can be the end node. A first end node must be
1186 handled, too. There fore do ... while and no incrementing of
1187 aNodeIndex in the first pass.
1189 bool bFirst = true;
1192 if (! bFirst)
1194 aNodeIndex++;
1197 bFirst = false;
1199 SwTxtNode * pTxtNode = aNodeIndex.GetNode().GetTxtNode();
1201 if (pTxtNode != NULL)
1203 const String & aTmpStr = pTxtNode->GetTxt();
1205 if (aNodeIndex == Start()->nNode)
1207 xub_StrLen nEnd;
1208 if (End()->nNode == aNodeIndex)
1209 nEnd = End()->nContent.GetIndex();
1210 else
1211 nEnd = aTmpStr.Len();
1213 aResult += aTmpStr.Copy(Start()->nContent.GetIndex(),
1214 nEnd - Start()->nContent.GetIndex()) ;
1216 else if (aNodeIndex == End()->nNode)
1217 aResult += aTmpStr.Copy(0, End()->nContent.GetIndex());
1218 else
1219 aResult += aTmpStr;
1222 while (aNodeIndex != End()->nNode);
1224 return aResult;
1227 BOOL SwPaM::Overlap(const SwPaM & a, const SwPaM & b)
1229 return !(*b.End() <= *a.Start() || *a.End() <= *b.End());
1232 void SwPaM::Invalidate()
1234 const SwNode *_pNd=this->GetNode();
1235 const SwTxtNode *_pTxtNd=(_pNd!=NULL?_pNd->GetTxtNode():NULL);
1236 if (_pTxtNd!=NULL) {
1237 //pretent we've added a char to force layout to recalc the portion...
1238 SwInsChr aHint(_pTxtNd->GetIndex());
1239 SwModify *_pModify=(SwModify*)_pTxtNd;
1240 _pModify->Modify( 0, &aHint);
1244 BOOL SwPaM::LessThan(const SwPaM & a, const SwPaM & b)
1246 return (*a.Start() < *b.Start()) || (*a.Start() == *b.Start() && *a.End() < *b.End());