1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <tools/gen.hxx>
23 #include <editeng/protitem.hxx>
24 #include <officecfg/Office/Common.hxx>
25 #include <unotools/configmgr.hxx>
28 #include <pagefrm.hxx>
30 #include <IDocumentLayoutAccess.hxx>
35 #include <fmtcntnt.hxx>
38 #include <fmteiro.hxx>
39 #include <section.hxx>
40 #include <sectfrm.hxx>
45 #include <DocumentSettingManager.hxx>
47 #include <txatbase.hxx>
48 #include <osl/diagnose.h>
50 #include <xmloff/odffields.hxx>
51 #include <rtl/ustrbuf.hxx>
54 #include <textcontentcontrol.hxx>
56 // for the dump "MSC-" compiler
57 static sal_Int32
GetSttOrEnd( bool bCondition
, const SwContentNode
& rNd
)
59 return bCondition
? 0 : rNd
.Len();
62 SwPosition::SwPosition( const SwNodeIndex
& rNodeIndex
, const SwContentIndex
& rContent
)
63 : nNode( rNodeIndex
), nContent( rContent
)
65 assert((!rNodeIndex
.GetNode().GetContentNode() || rNodeIndex
.GetNode().GetContentNode() == rContent
.GetContentNode())
66 && "parameters point to different nodes");
69 SwPosition::SwPosition( const SwNode
& rNode
, const SwContentIndex
& rContent
)
70 : nNode( rNode
), nContent( rContent
)
72 assert((!rNode
.GetContentNode() || rNode
.GetContentNode() == rContent
.GetContentNode())
73 && "parameters point to different nodes");
76 SwPosition::SwPosition( const SwNodeIndex
& rNodeIndex
, const SwContentNode
* pContentNode
, sal_Int32 nContentOffset
)
77 : nNode( rNodeIndex
), nContent( pContentNode
, nContentOffset
)
79 assert((!pContentNode
|| pContentNode
== &rNodeIndex
.GetNode()) &&
80 "parameters point to different nodes");
83 SwPosition::SwPosition( const SwNode
& rNode
, const SwContentNode
* pContentNode
, sal_Int32 nContentOffset
)
84 : nNode( rNode
), nContent( pContentNode
, nContentOffset
)
86 assert((!pContentNode
|| pContentNode
== &rNode
) &&
87 "parameters point to different nodes");
90 SwPosition::SwPosition( const SwNodeIndex
& rNodeIndex
, SwNodeOffset nDiff
, const SwContentNode
* pContentNode
, sal_Int32 nContentOffset
)
91 : nNode( rNodeIndex
, nDiff
), nContent( pContentNode
, nContentOffset
)
93 assert((!pContentNode
|| pContentNode
== &rNodeIndex
.GetNode()) &&
94 "parameters point to different nodes");
97 SwPosition::SwPosition( const SwNodeIndex
& rNodeIndex
, SwNodeOffset nDiff
)
98 : nNode( rNodeIndex
, nDiff
), nContent( GetNode().GetContentNode() )
102 SwPosition::SwPosition( const SwNode
& rNode
, SwNodeOffset nDiff
)
103 : nNode( rNode
, nDiff
), nContent( GetNode().GetContentNode() )
107 SwPosition::SwPosition( SwNodes
& rNodes
, SwNodeOffset nIndex
)
108 : nNode( rNodes
, nIndex
), nContent( GetNode().GetContentNode() )
112 SwPosition::SwPosition( const SwContentNode
& rNode
, const sal_Int32 nContentOffset
)
113 : nNode( rNode
), nContent( &rNode
, nContentOffset
)
117 SwPosition::SwPosition( const SwContentIndex
& rContentIndex
, short nDiff
)
118 : nNode( *rContentIndex
.GetContentNode() ), nContent( rContentIndex
, nDiff
)
122 bool SwPosition::operator<(const SwPosition
&rPos
) const
124 // cheaper to check for == first
125 if( nNode
== rPos
.nNode
)
127 // note that positions with text node but no SwContentIndex registered are
128 // created for text frames anchored at para (see SwXFrame::getAnchor())
129 SwContentNode
const*const pThisReg(GetContentNode());
130 SwContentNode
const*const pOtherReg(rPos
.GetContentNode());
131 if (pThisReg
&& pOtherReg
)
133 return (nContent
< rPos
.nContent
);
135 else // by convention position with no index is smaller
137 return pOtherReg
!= nullptr;
140 return nNode
< rPos
.nNode
;
143 bool SwPosition::operator>(const SwPosition
&rPos
) const
145 // cheaper to check for == first
146 if( nNode
== rPos
.nNode
)
148 // note that positions with text node but no SwContentIndex registered are
149 // created for text frames anchored at para (see SwXFrame::getAnchor())
150 SwContentNode
const*const pThisReg(GetContentNode());
151 SwContentNode
const*const pOtherReg(rPos
.GetContentNode());
152 if (pThisReg
&& pOtherReg
)
154 return (nContent
> rPos
.nContent
);
156 else // by convention position with no index is smaller
158 return pThisReg
!= nullptr;
161 return nNode
> rPos
.nNode
;
164 bool SwPosition::operator<=(const SwPosition
&rPos
) const
166 // cheaper to check for == first
167 if( nNode
== rPos
.nNode
)
169 // note that positions with text node but no SwContentIndex registered are
170 // created for text frames anchored at para (see SwXFrame::getAnchor())
171 SwContentNode
const*const pThisReg(GetContentNode());
172 SwContentNode
const*const pOtherReg(rPos
.GetContentNode());
173 if (pThisReg
&& pOtherReg
)
175 return (nContent
<= rPos
.nContent
);
177 else // by convention position with no index is smaller
179 return pThisReg
== nullptr;
182 return nNode
< rPos
.nNode
;
185 bool SwPosition::operator>=(const SwPosition
&rPos
) const
187 // cheaper to check for == first
188 if( nNode
== rPos
.nNode
)
190 // note that positions with text node but no SwContentIndex registered are
191 // created for text frames anchored at para (see SwXFrame::getAnchor())
192 SwContentNode
const*const pThisReg(GetContentNode());
193 SwContentNode
const*const pOtherReg(rPos
.GetContentNode());
194 if (pThisReg
&& pOtherReg
)
196 return (nContent
>= rPos
.nContent
);
198 else // by convention position with no index is smaller
200 return pOtherReg
== nullptr;
203 return nNode
> rPos
.nNode
;
206 bool SwPosition::operator==(const SwPosition
&rPos
) const
208 return (nNode
== rPos
.nNode
)
209 && (nContent
== rPos
.nContent
);
212 bool SwPosition::operator!=(const SwPosition
&rPos
) const
214 return (nNode
!= rPos
.nNode
)
215 || (nContent
!= rPos
.nContent
);
218 SwDoc
& SwPosition::GetDoc() const
220 return GetNode().GetDoc();
223 void SwPosition::dumpAsXml(xmlTextWriterPtr pWriter
) const
225 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwPosition"));
226 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("nNode"), BAD_CAST(OString::number(sal_Int32(GetNodeIndex())).getStr()));
227 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("nContent"), BAD_CAST(OString::number(GetContentIndex()).getStr()));
228 (void)xmlTextWriterEndElement(pWriter
);
231 void SwPosition::Assign( const SwNode
& rNd
, SwNodeOffset nDelta
, sal_Int32 nContentOffset
)
233 nNode
.Assign(rNd
, nDelta
);
234 assert((nNode
.GetNode().GetContentNode() || nContentOffset
== 0) && "setting contentoffset, but node is not SwContentNode");
235 nContent
.Assign(nNode
.GetNode().GetContentNode(), nContentOffset
);
237 void SwPosition::Assign( SwNodeOffset nNodeOffset
, sal_Int32 nContentOffset
)
240 nContent
.Assign(nNode
.GetNode().GetContentNode(), nContentOffset
);
242 void SwPosition::Assign( const SwContentNode
& rNode
, sal_Int32 nContentOffset
)
245 nContent
.Assign(&rNode
, nContentOffset
);
247 void SwPosition::Assign( const SwNode
& rNd
, sal_Int32 nContentOffset
)
250 nContent
.Assign(rNd
.GetContentNode(), nContentOffset
);
252 void SwPosition::Assign( const SwNodeIndex
& rNdIdx
, sal_Int32 nContentOffset
)
255 nContent
.Assign(nNode
.GetNode().GetContentNode(), nContentOffset
);
257 void SwPosition::Adjust( SwNodeOffset nDelta
)
260 nContent
.Assign(nNode
.GetNode().GetContentNode(), 0);
262 void SwPosition::AdjustContent( sal_Int32 nDelta
)
264 assert(nNode
.GetNode().GetContentNode() && "only valid to call this if we point to an SwContentNode");
267 void SwPosition::SetContent( sal_Int32 nContentIndex
)
269 assert(nNode
.GetNode().GetContentNode() && "only valid to call this if we point to an SwContentNode");
270 nContent
= nContentIndex
;
272 void SwPosition::AssignStartIndex( const SwContentNode
& rNd
)
275 nContent
.Assign(&rNd
, 0);
277 void SwPosition::AssignEndIndex( const SwContentNode
& rNd
)
280 nContent
.Assign(&rNd
, rNd
.Len());
284 std::ostream
&operator <<(std::ostream
& s
, const SwPosition
& position
)
286 return s
<< "SwPosition (node " << position
.GetNodeIndex() << ", offset " << position
.GetContentIndex() << ")";
291 enum CHKSECTION
{ Chk_Both
, Chk_One
, Chk_None
};
295 static CHKSECTION
lcl_TstIdx( SwNodeOffset nSttIdx
, SwNodeOffset nEndIdx
, const SwNode
& rEndNd
)
297 SwNodeOffset nStt
= rEndNd
.StartOfSectionIndex(), nEnd
= rEndNd
.GetIndex();
298 CHKSECTION eSec
= nStt
< nSttIdx
&& nEnd
>= nSttIdx
? Chk_One
: Chk_None
;
299 if( nStt
< nEndIdx
&& nEnd
>= nEndIdx
)
300 return( eSec
== Chk_One
? Chk_Both
: Chk_One
);
304 static bool lcl_ChkOneRange( CHKSECTION eSec
, bool bChkSections
,
305 const SwNode
& rBaseEnd
, SwNodeOffset nStt
, SwNodeOffset nEnd
)
307 if( eSec
!= Chk_Both
)
313 // search the surrounding section
314 const SwNodes
& rNds
= rBaseEnd
.GetNodes();
315 const SwNode
*pTmp
, *pNd
= rNds
[ nStt
];
316 if( !pNd
->IsStartNode() )
317 pNd
= pNd
->StartOfSectionNode();
319 if( pNd
== rNds
[ nEnd
]->StartOfSectionNode() )
320 return true; // same StartNode, same section
322 // already on a base node => error
323 if( !pNd
->StartOfSectionIndex() )
328 pTmp
= pNd
->StartOfSectionNode();
329 if (pTmp
->EndOfSectionNode() == &rBaseEnd
)
334 SwNodeOffset nSttIdx
= pNd
->GetIndex(), nEndIdx
= pNd
->EndOfSectionIndex();
335 return nSttIdx
<= nStt
&& nStt
<= nEndIdx
&&
336 nSttIdx
<= nEnd
&& nEnd
<= nEndIdx
;
339 /** Check if the given range is inside one of the defined top-level sections.
341 * The top-level sections are Content, AutoText, PostIts, Inserts, and Redlines.
343 * @param bChkSection if true, also check that the given range is inside
344 * a single second-level section inside any of the
345 * top-level sections, except for the Content section.
347 * @return <true> if valid range
349 bool CheckNodesRange( const SwNode
& rStt
,
350 const SwNode
& rEnd
, bool bChkSection
)
352 const SwNodes
& rNds
= rStt
.GetNodes();
353 SwNodeOffset nStt
= rStt
.GetIndex(), nEnd
= rEnd
.GetIndex();
354 CHKSECTION eSec
= lcl_TstIdx( nStt
, nEnd
, rNds
.GetEndOfContent() );
355 if( Chk_None
!= eSec
)
356 return eSec
== Chk_Both
;
358 eSec
= lcl_TstIdx( nStt
, nEnd
, rNds
.GetEndOfAutotext() );
359 if( Chk_None
!= eSec
)
360 return lcl_ChkOneRange( eSec
, bChkSection
,
361 rNds
.GetEndOfAutotext(), nStt
, nEnd
);
363 eSec
= lcl_TstIdx( nStt
, nEnd
, rNds
.GetEndOfPostIts() );
364 if( Chk_None
!= eSec
)
365 return lcl_ChkOneRange( eSec
, bChkSection
,
366 rNds
.GetEndOfPostIts(), nStt
, nEnd
);
368 eSec
= lcl_TstIdx( nStt
, nEnd
, rNds
.GetEndOfInserts() );
369 if( Chk_None
!= eSec
)
370 return lcl_ChkOneRange( eSec
, bChkSection
,
371 rNds
.GetEndOfInserts(), nStt
, nEnd
);
373 eSec
= lcl_TstIdx( nStt
, nEnd
, rNds
.GetEndOfRedlines() );
374 if( Chk_None
!= eSec
)
375 return lcl_ChkOneRange( eSec
, bChkSection
,
376 rNds
.GetEndOfRedlines(), nStt
, nEnd
);
378 return false; // somewhere in between => error
381 bool GoNext(SwNode
* pNd
, SwContentIndex
* pIdx
, SwCursorSkipMode nMode
)
383 if( pNd
->IsContentNode() )
384 return static_cast<SwContentNode
*>(pNd
)->GoNext( pIdx
, nMode
);
388 bool GoPrevious( SwNode
* pNd
, SwContentIndex
* pIdx
, SwCursorSkipMode nMode
)
390 if( pNd
->IsContentNode() )
391 return static_cast<SwContentNode
*>(pNd
)->GoPrevious( pIdx
, nMode
);
395 SwContentNode
* GoNextNds( SwNodeIndex
* pIdx
, bool bChk
)
397 SwNodeIndex
aIdx( *pIdx
);
398 SwContentNode
* pNd
= aIdx
.GetNodes().GoNext( &aIdx
);
401 if( bChk
&& SwNodeOffset(1) != aIdx
.GetIndex() - pIdx
->GetIndex() &&
402 !CheckNodesRange( pIdx
->GetNode(), aIdx
.GetNode(), true ) )
410 SwContentNode
* GoPreviousNds( SwNodeIndex
* pIdx
, bool bChk
)
412 SwNodeIndex
aIdx( *pIdx
);
413 SwContentNode
* pNd
= SwNodes::GoPrevious( &aIdx
);
416 if( bChk
&& SwNodeOffset(1) != pIdx
->GetIndex() - aIdx
.GetIndex() &&
417 !CheckNodesRange( pIdx
->GetNode(), aIdx
.GetNode(), true ) )
425 SwContentNode
* GoNextPos( SwPosition
* pIdx
, bool bChk
)
427 SwNodeIndex
aIdx( pIdx
->GetNode() );
428 SwContentNode
* pNd
= aIdx
.GetNodes().GoNext( &aIdx
);
431 if( bChk
&& SwNodeOffset(1) != aIdx
.GetIndex() - pIdx
->GetNodeIndex() &&
432 !CheckNodesRange( pIdx
->GetNode(), aIdx
.GetNode(), true ) )
440 SwContentNode
* GoPreviousPos( SwPosition
* pIdx
, bool bChk
)
442 SwNodeIndex
aIdx( pIdx
->GetNode() );
443 SwContentNode
* pNd
= SwNodes::GoPrevious( &aIdx
);
446 if( bChk
&& SwNodeOffset(1) != pIdx
->GetNodeIndex() - aIdx
.GetIndex() &&
447 !CheckNodesRange( pIdx
->GetNode(), aIdx
.GetNode(), true ) )
455 SwPaM::SwPaM( const SwPosition
& rPos
, SwPaM
* pRing
)
458 , m_Bound2( rPos
.GetNode().GetNodes() ) // default initialize
459 , m_pPoint( &m_Bound1
)
460 , m_pMark( m_pPoint
)
461 , m_bIsInFrontOfLabel( false )
465 SwPaM::SwPaM( const SwPosition
& rMark
, const SwPosition
& rPoint
, SwPaM
* pRing
)
469 , m_pPoint( &m_Bound2
)
470 , m_pMark( &m_Bound1
)
471 , m_bIsInFrontOfLabel( false )
475 SwPaM::SwPaM( const SwNodeIndex
& rMark
, const SwNodeIndex
& rPoint
,
476 SwNodeOffset nMarkOffset
, SwNodeOffset nPointOffset
, SwPaM
* pRing
)
480 , m_pPoint( &m_Bound2
)
481 , m_pMark( &m_Bound1
)
482 , m_bIsInFrontOfLabel( false )
486 m_pMark
->nNode
+= nMarkOffset
;
490 m_pPoint
->nNode
+= nPointOffset
;
492 m_Bound1
.nContent
.Assign( m_Bound1
.GetNode().GetContentNode(), 0 );
493 m_Bound2
.nContent
.Assign( m_Bound2
.GetNode().GetContentNode(), 0 );
496 SwPaM::SwPaM( const SwNode
& rMark
, const SwNode
& rPoint
,
497 SwNodeOffset nMarkOffset
, SwNodeOffset nPointOffset
, SwPaM
* pRing
)
501 , m_pPoint( &m_Bound2
)
502 , m_pMark( &m_Bound1
)
503 , m_bIsInFrontOfLabel( false )
507 m_pMark
->nNode
+= nMarkOffset
;
511 m_pPoint
->nNode
+= nPointOffset
;
513 m_Bound1
.nContent
.Assign( m_Bound1
.GetNode().GetContentNode(), 0 );
514 m_Bound2
.nContent
.Assign( m_Bound2
.GetNode().GetContentNode(), 0 );
517 SwPaM::SwPaM( const SwNodeIndex
& rMark
, sal_Int32 nMarkContent
,
518 const SwNodeIndex
& rPoint
, sal_Int32 nPointContent
, SwPaM
* pRing
)
522 , m_pPoint( &m_Bound2
)
523 , m_pMark( &m_Bound1
)
524 , m_bIsInFrontOfLabel( false )
526 m_pPoint
->nContent
.Assign( rPoint
.GetNode().GetContentNode(), nPointContent
);
527 m_pMark
->nContent
.Assign( rMark
.GetNode().GetContentNode(), nMarkContent
);
530 SwPaM::SwPaM( const SwNode
& rMark
, sal_Int32 nMarkContent
,
531 const SwNode
& rPoint
, sal_Int32 nPointContent
, SwPaM
* pRing
)
535 , m_pPoint( &m_Bound2
)
536 , m_pMark( &m_Bound1
)
537 , m_bIsInFrontOfLabel( false )
539 m_pPoint
->nContent
.Assign( m_pPoint
->GetNode().GetContentNode(),
541 m_pMark
->nContent
.Assign( m_pMark
->GetNode().GetContentNode(),
545 SwPaM::SwPaM( const SwNode
& rMark
, SwNodeOffset nMarkOffset
, sal_Int32 nMarkContent
,
546 const SwNode
& rPoint
, SwNodeOffset nPointOffset
, sal_Int32 nPointContent
, SwPaM
* pRing
)
550 , m_pPoint( &m_Bound2
)
551 , m_pMark( &m_Bound1
)
552 , m_bIsInFrontOfLabel( false )
556 m_pMark
->nNode
+= nMarkOffset
;
560 m_pPoint
->nNode
+= nPointOffset
;
562 m_pPoint
->nContent
.Assign( m_pPoint
->GetNode().GetContentNode(),
564 m_pMark
->nContent
.Assign( m_pMark
->GetNode().GetContentNode(),
568 SwPaM::SwPaM( const SwNode
& rNode
, sal_Int32 nContent
, SwPaM
* pRing
)
571 , m_Bound2( m_Bound1
.GetNode().GetNodes() ) // default initialize
572 , m_pPoint( &m_Bound1
)
573 , m_pMark( &m_Bound1
)
574 , m_bIsInFrontOfLabel( false )
576 m_pPoint
->nContent
.Assign( m_pPoint
->GetNode().GetContentNode(),
580 SwPaM::SwPaM( const SwNode
& rNode
, SwNodeOffset nNdOffset
, sal_Int32 nContent
, SwPaM
* pRing
)
582 , m_Bound1( rNode
, nNdOffset
)
583 , m_Bound2( m_Bound1
.GetNode().GetNodes() ) // default initialize
584 , m_pPoint( &m_Bound1
)
585 , m_pMark( &m_Bound1
)
586 , m_bIsInFrontOfLabel( false )
588 m_pPoint
->nContent
.Assign( m_pPoint
->GetNode().GetContentNode(),
592 SwPaM::SwPaM( const SwNodeIndex
& rNodeIdx
, sal_Int32 nContent
, SwPaM
* pRing
)
594 , m_Bound1( rNodeIdx
)
595 , m_Bound2( rNodeIdx
.GetNode().GetNodes() ) // default initialize
596 , m_pPoint( &m_Bound1
)
597 , m_pMark( &m_Bound1
)
598 , m_bIsInFrontOfLabel( false )
600 m_pPoint
->nContent
.Assign( rNodeIdx
.GetNode().GetContentNode(), nContent
);
603 SwPaM::SwPaM( SwNodes
& rNodes
, SwNodeOffset nNdOffset
, SwPaM
* pRing
)
605 , m_Bound1( rNodes
, nNdOffset
)
606 , m_Bound2( rNodes
) // default initialize
607 , m_pPoint( &m_Bound1
)
608 , m_pMark( &m_Bound1
)
609 , m_bIsInFrontOfLabel( false )
615 SwPaM::SwPaM(SwPaM
const& rPam
, SwPaM
*const pRing
)
617 , m_Bound1( *(rPam
.m_pPoint
) )
618 , m_Bound2( *(rPam
.m_pMark
) )
619 , m_pPoint( &m_Bound1
), m_pMark( rPam
.HasMark() ? &m_Bound2
: m_pPoint
)
620 , m_bIsInFrontOfLabel( false )
624 // @@@ semantic: no copy assignment for super class Ring.
625 SwPaM
&SwPaM::operator=( const SwPaM
&rPam
)
630 *m_pPoint
= *( rPam
.m_pPoint
);
631 if ( rPam
.HasMark() )
634 *m_pMark
= *( rPam
.m_pMark
);
643 void SwPaM::SetMark()
645 if (m_pPoint
== &m_Bound1
)
653 (*m_pMark
) = *m_pPoint
;
656 /// movement of cursor
657 bool SwPaM::Move( SwMoveFnCollection
const & fnMove
, SwGoInDoc fnGo
)
659 const bool bRet
= (*fnGo
)( *this, fnMove
);
661 m_bIsInFrontOfLabel
= false;
667 /** make a new region
669 Sets the first SwPaM onto the given SwPaM, or to the beginning or end of a
670 document. SPoint stays at its position, GetMark will be changed respectively.
672 @param fnMove Contains information if beginning or end of document.
673 @param pOrigRg The given region.
674 @param rPam returns newly created range, in Ring with parameter pOrigRg.
676 void MakeRegion(SwMoveFnCollection
const & fnMove
,
677 const SwPaM
& rOrigRg
, std::optional
<SwPaM
>& rPam
)
679 rPam
.emplace(rOrigRg
, const_cast<SwPaM
*>(&rOrigRg
)); // given search range
680 // make sure that SPoint is on the "real" start position
681 // FORWARD: SPoint always smaller than GetMark
682 // BACKWARD: SPoint always bigger than GetMark
683 if( (rPam
->GetMark()->*fnMove
.fnCmpOp
)( *rPam
->GetPoint() ) )
689 void SwPaM::Normalize(bool bPointFirst
)
692 if ( ( bPointFirst
&& *m_pPoint
> *m_pMark
) ||
693 (!bPointFirst
&& *m_pPoint
< *m_pMark
) )
699 /// return page number at cursor (for reader and page bound frames)
700 sal_uInt16
SwPaM::GetPageNum( bool bAtPoint
, const Point
* pLayPos
)
702 const SwContentFrame
* pCFrame
;
703 const SwPageFrame
*pPg
;
704 const SwContentNode
*pNd
;
705 const SwPosition
* pPos
= bAtPoint
? m_pPoint
: m_pMark
;
707 std::pair
<Point
, bool> tmp
;
710 tmp
.first
= *pLayPos
;
713 if( nullptr != ( pNd
= pPos
->GetNode().GetContentNode() ) &&
714 nullptr != (pCFrame
= pNd
->getLayoutFrame(pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), pPos
, pLayPos
? &tmp
: nullptr)) &&
715 nullptr != ( pPg
= pCFrame
->FindPageFrame() ))
716 return pPg
->GetPhyPageNum();
720 // form view - see also SwCursorShell::IsCursorReadonly()
721 static const SwFrame
* lcl_FindEditInReadonlyFrame( const SwFrame
& rFrame
)
723 const SwFrame
* pRet
= nullptr;
725 const SwFlyFrame
* pFly
;
726 const SwSectionFrame
* pSectionFrame
;
728 if( rFrame
.IsInFly() &&
729 (pFly
= rFrame
.FindFlyFrame())->GetFormat()->GetEditInReadonly().GetValue() &&
731 !pFly
->Lower()->IsNoTextFrame() )
735 else if ( rFrame
.IsInSct() &&
736 nullptr != ( pSectionFrame
= rFrame
.FindSctFrame() )->GetSection() &&
737 pSectionFrame
->GetSection()->IsEditInReadonlyFlag() )
739 pRet
= pSectionFrame
;
745 /// is in protected section or selection surrounds something protected
746 bool SwPaM::HasReadonlySel(bool bFormView
, bool const isReplace
) const
750 const SwContentNode
* pNd
= GetPoint()->GetNode().GetContentNode();
751 const SwContentFrame
*pFrame
= nullptr;
752 if ( pNd
!= nullptr )
755 std::pair
<Point
, bool> const tmp(aTmpPt
, false);
756 pFrame
= pNd
->getLayoutFrame(
757 pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
761 // Will be set if point are inside edit-in-readonly environment
762 const SwFrame
* pPointEditInReadonlyFrame
= nullptr;
763 if ( pFrame
!= nullptr
764 && ( pFrame
->IsProtected()
766 && nullptr == ( pPointEditInReadonlyFrame
= lcl_FindEditInReadonlyFrame( *pFrame
) ) ) ) )
770 else if( pNd
!= nullptr )
772 const SwSectionNode
* pSNd
= pNd
->GetSectionNode();
774 && ( pSNd
->GetSection().IsProtectFlag()
776 && !pSNd
->GetSection().IsEditInReadonlyFlag()) ) )
782 const SwSectionNode
* pParentSectionNd
= pNd
->FindSectionNode();
783 if ( pParentSectionNd
!= nullptr
784 && ( pParentSectionNd
->GetSection().IsProtectFlag()
785 || ( bFormView
&& !pParentSectionNd
->GetSection().IsEditInReadonlyFlag()) ) )
794 && GetPoint()->nNode
!= GetMark()->nNode
)
796 pNd
= GetMark()->GetNode().GetContentNode();
798 if ( pNd
!= nullptr )
801 std::pair
<Point
, bool> const tmp(aTmpPt
, false);
802 pFrame
= pNd
->getLayoutFrame(
803 pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
807 const SwFrame
* pMarkEditInReadonlyFrame
= nullptr;
808 if ( pFrame
!= nullptr
809 && ( pFrame
->IsProtected()
811 && nullptr == ( pMarkEditInReadonlyFrame
= lcl_FindEditInReadonlyFrame( *pFrame
) ) ) ) )
815 else if( pNd
!= nullptr )
817 const SwSectionNode
* pSNd
= pNd
->GetSectionNode();
819 && ( pSNd
->GetSection().IsProtectFlag()
821 && !pSNd
->GetSection().IsEditInReadonlyFlag()) ) )
827 if ( !bRet
&& bFormView
)
829 // Check if start and end frame are inside the _same_
830 // edit-in-readonly-environment. Otherwise we better return 'true'
831 if ( pPointEditInReadonlyFrame
!= pMarkEditInReadonlyFrame
)
835 // check for protected section inside the selection
838 SwNodeOffset nSttIdx
= GetMark()->GetNodeIndex(),
839 nEndIdx
= GetPoint()->GetNodeIndex();
840 if( nEndIdx
< nSttIdx
)
841 std::swap( nSttIdx
, nEndIdx
);
843 // If a protected section should be between nodes, then the
844 // selection needs to contain already x nodes.
845 // (TextNd, SectNd, TextNd, EndNd, TextNd )
846 if( nSttIdx
+ SwNodeOffset(3) < nEndIdx
)
848 const SwSectionFormats
& rFormats
= GetDoc().GetSections();
849 for( SwSectionFormats::size_type n
= rFormats
.size(); n
; )
851 const SwSectionFormat
* pFormat
= rFormats
[ --n
];
852 if( pFormat
->GetProtect().IsContentProtected() )
854 const SwFormatContent
& rContent
= pFormat
->GetContent(false);
855 OSL_ENSURE( rContent
.GetContentIdx(), "where is the SectionNode?" );
856 SwNodeOffset nIdx
= rContent
.GetContentIdx()->GetIndex();
857 if( nSttIdx
<= nIdx
&& nEndIdx
>= nIdx
&&
858 rContent
.GetContentIdx()->GetNode().GetNodes().IsDocNodes() )
869 const SwDoc
& rDoc
= GetDoc();
870 // Legacy text/combo/checkbox: never return read-only when inside these form fields.
871 const IDocumentMarkAccess
* pMarksAccess
= rDoc
.getIDocumentMarkAccess();
872 sw::mark::IFieldmark
* pA
= GetPoint() ? pMarksAccess
->getInnerFieldmarkFor(*GetPoint()) : nullptr;
873 sw::mark::IFieldmark
* pB
= GetMark() ? pMarksAccess
->getInnerFieldmarkFor(*GetMark()) : pA
;
874 // prevent the user from accidentally deleting the field itself when modifying the text.
875 const bool bAtStartA
= (pA
!= nullptr) && (pA
->GetMarkStart() == *GetPoint());
876 const bool bAtStartB
= (pB
!= nullptr) && (pB
->GetMarkStart() == *GetMark());
878 if (!utl::ConfigManager::IsFuzzing() && officecfg::Office::Common::Filter::Microsoft::Import::ForceImportWWFieldsAsGenericFields::get())
880 ; // allow editing all fields in generic mode
884 bool bUnhandledMark
= pA
&& pA
->GetFieldname( ) == ODF_UNHANDLED
;
885 // Unhandled fieldmarks case shouldn't be edited manually to avoid breaking anything
886 if ( ( pA
== pB
) && bUnhandledMark
)
890 if ((pA
== pB
) && (bAtStartA
!= bAtStartB
))
894 // If both points are either outside or at marks edges (i.e. selection either
895 // touches fields, or fully encloses it), then don't disable editing
896 bRet
= !( ( !pA
|| bAtStartA
) && ( !pB
|| bAtStartB
) );
898 if( !bRet
&& rDoc
.GetDocumentSettingManager().get( DocumentSettingId::PROTECT_FORM
) && (pA
|| pB
) )
900 // Form protection case
901 bRet
= ( pA
== nullptr ) || ( pB
== nullptr ) || bAtStartA
|| bAtStartB
;
907 // Allow editing when the cursor/selection is fully inside of a legacy form field.
908 bRet
= !( pA
!= nullptr && !bAtStartA
&& !bAtStartB
&& pA
== pB
);
912 // Also allow editing inside content controls in general, similar to form fields.
913 // Specific types will be disabled below.
914 if (const SwEditShell
* pEditShell
= rDoc
.GetEditShell())
915 bRet
= !pEditShell
->CursorInsideContentControl();
921 // Paragraph Signatures and Classification fields are read-only.
922 if (const SwEditShell
* pEditShell
= rDoc
.GetEditShell())
923 bRet
= pEditShell
->IsCursorInParagraphMetadataField();
927 rDoc
.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS
))
929 if (rDoc
.getIDocumentMarkAccess()->isBookmarkDeleted(*this, isReplace
))
935 rDoc
.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FIELDS
))
937 SwPosition
const& rStart(*Start());
938 SwPosition
const& rEnd(*End());
939 for (SwNodeIndex
n(rStart
.GetNode()); n
<= rEnd
.GetNode(); ++n
)
941 if (SwTextNode
const*const pNode
= n
.GetNode().GetTextNode())
943 if (SwpHints
const*const pHints
= pNode
->GetpSwpHints())
945 for (size_t i
= 0; i
< pHints
->Count(); ++i
)
947 SwTextAttr
const*const pHint(pHints
->Get(i
));
948 if (n
== rStart
.GetNode() && pHint
->GetStart() < rStart
.GetContentIndex())
950 continue; // before selection
952 if (n
== rEnd
.GetNode() && rEnd
.GetContentIndex() <= pHint
->GetStart())
954 break; // after selection
956 if (pHint
->Which() == RES_TXTATR_FIELD
957 // placeholders don't work if you can't delete them
958 && pHint
->GetFormatField().GetField()->GetTyp()->Which() != SwFieldIds::JumpEdit
)
970 // See if we're inside a read-only content control.
971 const SwPosition
* pStart
= Start();
972 SwTextNode
* pTextNode
= pStart
->GetNode().GetTextNode();
975 sal_Int32 nIndex
= pStart
->GetContentIndex();
977 = pTextNode
->GetTextAttrAt(nIndex
, RES_TXTATR_CONTENTCONTROL
, ::sw::GetTextAttrMode::Parent
);
978 auto pTextContentControl
= static_txtattr_cast
<SwTextContentControl
*>(pAttr
);
979 if (pTextContentControl
)
981 const SwFormatContentControl
& rFormatContentControl
982 = pTextContentControl
->GetContentControl();
983 std::shared_ptr
<SwContentControl
> pContentControl
984 = rFormatContentControl
.GetContentControl();
985 if (pContentControl
&& !pContentControl
->GetReadWrite())
987 switch (pContentControl
->GetType())
989 case SwContentControlType::CHECKBOX
:
990 case SwContentControlType::PICTURE
:
991 case SwContentControlType::DROP_DOWN_LIST
:
1005 bool SwPaM::HasHiddenSections() const
1009 if (HasMark() && GetPoint()->nNode
!= GetMark()->nNode
)
1011 // check for hidden section inside the selection
1012 SwNodeOffset nSttIdx
= Start()->GetNodeIndex(), nEndIdx
= End()->GetNodeIndex();
1014 if (nSttIdx
+ SwNodeOffset(3) < nEndIdx
)
1016 const SwSectionFormats
& rFormats
= GetDoc().GetSections();
1017 for (SwSectionFormats::size_type n
= rFormats
.size(); n
;)
1019 const SwSectionFormat
* pFormat
= rFormats
[--n
];
1020 if (pFormat
->GetSection()->IsHidden())
1022 const SwFormatContent
& rContent
= pFormat
->GetContent(false);
1023 OSL_ENSURE(rContent
.GetContentIdx(), "where is the SectionNode?");
1024 SwNodeOffset nIdx
= rContent
.GetContentIdx()->GetIndex();
1025 if (nSttIdx
<= nIdx
&& nEndIdx
>= nIdx
1026 && rContent
.GetContentIdx()->GetNode().GetNodes().IsDocNodes())
1039 /// This function returns the next node in direction of search. If there is no
1040 /// left or the next is out of the area, then a null-pointer is returned.
1041 /// @param rbFirst If <true> then first time request. If so than the position of
1042 /// the PaM must not be changed!
1043 SwContentNode
* GetNode( SwPaM
& rPam
, bool& rbFirst
, SwMoveFnCollection
const & fnMove
,
1044 bool const bInReadOnly
, SwRootFrame
const*const i_pLayout
)
1046 SwRootFrame
const*const pLayout(i_pLayout
? i_pLayout
:
1047 rPam
.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout());
1048 SwContentNode
* pNd
= nullptr;
1049 if( ((*rPam
.GetPoint()).*fnMove
.fnCmpOp
)( *rPam
.GetMark() ) ||
1050 ( *rPam
.GetPoint() == *rPam
.GetMark() && rbFirst
) )
1055 pNd
= rPam
.GetPointContentNode();
1058 SwContentFrame
const*const pFrame(pNd
->getLayoutFrame(pLayout
));
1061 nullptr == pFrame
||
1062 ( !bInReadOnly
&& pFrame
->IsProtected() ) ||
1063 (pFrame
->IsTextFrame() && static_cast<SwTextFrame
const*>(pFrame
)->IsHiddenNow())
1065 ( !bInReadOnly
&& pNd
->FindSectionNode() &&
1066 pNd
->FindSectionNode()->GetSection().IsProtect()
1075 if( !pNd
) // is the cursor not on a ContentNode?
1077 SwPosition
aPos( *rPam
.GetPoint() );
1078 bool bSrchForward
= &fnMove
== &fnMoveForward
;
1079 SwNodes
& rNodes
= aPos
.GetNodes();
1081 // go to next/previous ContentNode
1084 if (i_pLayout
&& aPos
.GetNode().IsTextNode())
1086 auto const fal(sw::GetFirstAndLastNode(*pLayout
, aPos
.GetNode()));
1087 aPos
.Assign( bSrchForward
? *fal
.second
: *fal
.first
);
1091 ? rNodes
.GoNextSection( &aPos
, true, !bInReadOnly
)
1092 : SwNodes::GoPrevSection( &aPos
, true, !bInReadOnly
);
1096 aPos
.AssignEndIndex( *pNd
);
1097 // is the position still in the area
1098 if( (aPos
.*fnMove
.fnCmpOp
)( *rPam
.GetMark() ) )
1100 // only in AutoTextSection can be nodes that are hidden
1101 SwContentFrame
const*const pFrame(pNd
->getLayoutFrame(pLayout
));
1102 if (nullptr == pFrame
||
1103 ( !bInReadOnly
&& pFrame
->IsProtected() ) ||
1104 ( pFrame
->IsTextFrame() &&
1105 static_cast<SwTextFrame
const*>(pFrame
)->IsHiddenNow()))
1110 *rPam
.GetPoint() = aPos
;
1113 pNd
= nullptr; // no valid node
1123 void GoStartDoc( SwPosition
* pPos
)
1125 SwNodes
& rNodes
= pPos
->GetNodes();
1126 pPos
->Assign( *rNodes
.GetEndOfContent().StartOfSectionNode() );
1127 // we always need to find a ContentNode!
1128 rNodes
.GoNext( pPos
);
1131 void GoEndDoc( SwPosition
* pPos
)
1133 SwNodes
& rNodes
= pPos
->GetNodes();
1134 pPos
->Assign( rNodes
.GetEndOfContent() );
1135 SwContentNode
* pCNd
= GoPreviousPos( pPos
, true );
1137 pPos
->AssignEndIndex(*pCNd
);
1140 void GoStartSection( SwPosition
* pPos
)
1142 // jump to section's beginning
1143 SwNodes
& rNodes
= pPos
->GetNodes();
1144 sal_uInt16 nLevel
= SwNodes::GetSectionLevel( pPos
->GetNode() );
1145 if( pPos
->GetNode() < *rNodes
.GetEndOfContent().StartOfSectionNode() )
1147 do { SwNodes::GoStartOfSection( &pPos
->nNode
); } while( nLevel
-- );
1149 // already on a ContentNode
1150 pPos
->AssignStartIndex(*pPos
->GetNode().GetContentNode());
1153 void GoStartOfSection( SwPosition
* pPos
)
1155 // jump to section's beginning
1156 SwNodes::GoStartOfSection( &pPos
->nNode
);
1157 pPos
->nContent
.Assign(pPos
->GetNode().GetContentNode(), 0);
1160 /// go to the end of the current base section
1161 void GoEndSection( SwPosition
* pPos
)
1163 // jump to section's beginning/end
1164 SwNodes
& rNodes
= pPos
->GetNodes();
1165 sal_uInt16 nLevel
= SwNodes::GetSectionLevel( pPos
->GetNode() );
1166 if( pPos
->GetNode() < *rNodes
.GetEndOfContent().StartOfSectionNode() )
1168 do { SwNodes::GoEndOfSection( &pPos
->nNode
); } while( nLevel
-- );
1170 // now on an EndNode, thus to the previous ContentNode
1171 if( SwContentNode
* pCNd
= GoPreviousNds( &pPos
->nNode
, true ) )
1172 pPos
->AssignEndIndex(*pCNd
);
1175 void GoEndOfSection( SwPosition
* pPos
)
1177 SwNodes::GoEndOfSection( &pPos
->nNode
);
1178 SwContentNode
* pCNd
= pPos
->nNode
.GetNode().GetContentNode();
1179 pPos
->nContent
.Assign(pCNd
, pCNd
? pCNd
->Len() : 0);
1182 bool GoInDoc( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1184 (*fnMove
.fnDoc
)( rPam
.GetPoint() );
1188 bool GoInSection( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1190 (*fnMove
.fnSections
)( rPam
.GetPoint() );
1194 bool GoInNode( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1196 SwContentNode
*pNd
= (*fnMove
.fnPos
)( rPam
.GetPoint(), true );
1198 rPam
.GetPoint()->SetContent(
1199 ::GetSttOrEnd( &fnMove
== &fnMoveForward
, *pNd
) );
1203 bool GoInContent( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1205 if( (*fnMove
.fnNd
)( &rPam
.GetPoint()->GetNode(),
1206 &rPam
.GetPoint()->nContent
, SwCursorSkipMode::Chars
))
1208 return GoInNode( rPam
, fnMove
);
1211 bool GoInContentCells( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1213 if( (*fnMove
.fnNd
)( &rPam
.GetPoint()->GetNode(),
1214 &rPam
.GetPoint()->nContent
, SwCursorSkipMode::Cells
))
1216 return GoInNode( rPam
, fnMove
);
1219 bool GoInContentSkipHidden( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1221 if( (*fnMove
.fnNd
)( &rPam
.GetPoint()->GetNode(),
1222 &rPam
.GetPoint()->nContent
, SwCursorSkipMode::Chars
| SwCursorSkipMode::Hidden
) )
1224 return GoInNode( rPam
, fnMove
);
1227 bool GoInContentCellsSkipHidden( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1229 if( (*fnMove
.fnNd
)( &rPam
.GetPoint()->GetNode(),
1230 &rPam
.GetPoint()->nContent
, SwCursorSkipMode::Cells
| SwCursorSkipMode::Hidden
) )
1232 return GoInNode( rPam
, fnMove
);
1235 bool GoPrevPara( SwPaM
& rPam
, SwMoveFnCollection
const & aPosPara
)
1237 if( rPam
.Move( fnMoveBackward
, GoInNode
) )
1239 // always on a ContentNode
1240 SwPosition
& rPos
= *rPam
.GetPoint();
1241 SwContentNode
* pNd
= rPos
.GetNode().GetContentNode();
1242 rPos
.SetContent( ::GetSttOrEnd( &aPosPara
== &fnMoveForward
, *pNd
) );
1248 bool GoCurrPara( SwPaM
& rPam
, SwMoveFnCollection
const & aPosPara
)
1250 SwPosition
& rPos
= *rPam
.GetPoint();
1251 SwContentNode
* pNd
= rPos
.GetNode().GetContentNode();
1254 const sal_Int32 nOld
= rPos
.GetContentIndex();
1255 const sal_Int32 nNew
= &aPosPara
== &fnMoveForward
? 0 : pNd
->Len();
1256 // if already at beginning/end then to the next/previous
1259 rPos
.SetContent( nNew
);
1263 // move node to next/previous ContentNode
1264 if( ( &aPosPara
==&fnParaStart
&& nullptr != ( pNd
=
1265 GoPreviousPos( &rPos
, true ))) ||
1266 ( &aPosPara
==&fnParaEnd
&& nullptr != ( pNd
=
1267 GoNextPos( &rPos
, true ))) )
1269 rPos
.SetContent( ::GetSttOrEnd( &aPosPara
== &fnMoveForward
, *pNd
));
1275 bool GoNextPara( SwPaM
& rPam
, SwMoveFnCollection
const & aPosPara
)
1277 if( rPam
.Move( fnMoveForward
, GoInNode
) )
1279 // always on a ContentNode
1280 SwPosition
& rPos
= *rPam
.GetPoint();
1281 SwContentNode
* pNd
= rPos
.GetNode().GetContentNode();
1282 rPos
.SetContent( ::GetSttOrEnd( &aPosPara
== &fnMoveForward
, *pNd
) );
1288 bool GoCurrSection( SwPaM
& rPam
, SwMoveFnCollection
const & fnMove
)
1290 SwPosition
& rPos
= *rPam
.GetPoint();
1291 SwPosition
aSavePos( rPos
); // position for comparison
1292 (fnMove
.fnSection
)( &rPos
);
1294 if( nullptr == ( pNd
= rPos
.GetNode().GetContentNode()) &&
1295 nullptr == ( pNd
= (*fnMove
.fnPos
)( &rPos
, true )) )
1297 rPos
= aSavePos
; // do not change cursor
1301 rPos
.SetContent( ::GetSttOrEnd( &fnMove
== &fnMoveForward
, *pNd
) );
1302 return aSavePos
!= rPos
;
1305 OUString
SwPaM::GetText() const
1307 OUStringBuffer aResult
;
1309 SwNodeIndex aNodeIndex
= Start()->nNode
;
1311 // The first node can be already the end node.
1312 // Use a "forever" loop with an exit condition in the middle
1313 // of its body, in order to correctly handle all cases.
1314 bool bIsStartNode
= true;
1317 const bool bIsEndNode
= aNodeIndex
== End()->nNode
;
1318 SwTextNode
* pTextNode
= aNodeIndex
.GetNode().GetTextNode();
1320 if (pTextNode
!= nullptr)
1324 aResult
.append(CH_TXTATR_NEWLINE
); // use newline for para break
1326 const OUString
& aTmpStr
= pTextNode
->GetText();
1328 if (bIsStartNode
|| bIsEndNode
)
1330 // Handle corner cases of start/end node(s)
1331 const sal_Int32 nStart
= bIsStartNode
1332 ? Start()->GetContentIndex()
1334 const sal_Int32 nEnd
= bIsEndNode
1335 ? End()->GetContentIndex()
1336 : aTmpStr
.getLength();
1338 aResult
.append(aTmpStr
.subView(nStart
, nEnd
-nStart
));
1342 aResult
.append(aTmpStr
);
1352 bIsStartNode
= false;
1355 return aResult
.makeStringAndClear();
1358 void SwPaM::InvalidatePaM()
1360 for (SwNodeIndex
index(Start()->GetNode()); index
<= End()->GetNode(); ++index
)
1362 if (SwTextNode
*const pTextNode
= index
.GetNode().GetTextNode())
1364 // pretend that the PaM marks changed formatting to reformat...
1365 sal_Int32
const nStart(
1366 index
== Start()->nNode
? Start()->GetContentIndex() : 0);
1367 // this should work even for length of 0
1368 SwUpdateAttr
const aHint(
1370 index
== End()->nNode
1371 ? End()->GetContentIndex() - nStart
1372 : pTextNode
->Len() - nStart
,
1374 pTextNode
->TriggerNodeUpdate(sw::LegacyModifyHint(&aHint
, &aHint
));
1376 // other node types not invalidated
1380 void SwPaM::dumpAsXml(xmlTextWriterPtr pWriter
) const
1382 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwPaM"));
1384 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("point"));
1385 GetPoint()->dumpAsXml(pWriter
);
1386 (void)xmlTextWriterEndElement(pWriter
);
1390 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("mark"));
1391 GetMark()->dumpAsXml(pWriter
);
1392 (void)xmlTextWriterEndElement(pWriter
);
1395 (void)xmlTextWriterEndElement(pWriter
);
1398 std::ostream
&operator <<(std::ostream
& s
, const SwPaM
& pam
)
1401 return s
<< "SwPaM (point " << *pam
.GetPoint() << ", mark " << *pam
.GetMark() << ")";
1403 return s
<< "SwPaM (point " << *pam
.GetPoint() << ")";
1407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */