xref: /AOO41X/main/sw/source/core/crsr/pam.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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