LibreOffice Module sw (master) 1
pam.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <tools/gen.hxx>
23#include <editeng/protitem.hxx>
24#include <officecfg/Office/Common.hxx>
26
27#include <cntfrm.hxx>
28#include <pagefrm.hxx>
29#include <doc.hxx>
31#include <docary.hxx>
32#include <pam.hxx>
33#include <pamtyp.hxx>
34#include <txtfrm.hxx>
35#include <fmtcntnt.hxx>
36#include <frmatr.hxx>
37#include <flyfrm.hxx>
38#include <fmteiro.hxx>
39#include <section.hxx>
40#include <sectfrm.hxx>
41#include <ndtxt.hxx>
42#include <swcrsr.hxx>
43
44#include <IMark.hxx>
46#include <hints.hxx>
47#include <txatbase.hxx>
48#include <osl/diagnose.h>
49#include <utility>
50#include <xmloff/odffields.hxx>
51#include <rtl/ustrbuf.hxx>
52
53#include <editsh.hxx>
55
56// for the dump "MSC-" compiler
57static sal_Int32 GetSttOrEnd( bool bCondition, const SwContentNode& rNd )
58{
59 return bCondition ? 0 : rNd.Len();
60}
61
62SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwContentIndex & rContent )
63 : nNode( rNodeIndex ), nContent( rContent )
64{
65 assert((!rNodeIndex.GetNode().GetContentNode() || rNodeIndex.GetNode().GetContentNode() == rContent.GetContentNode())
66 && "parameters point to different nodes");
67}
68
69SwPosition::SwPosition( const SwNode & rNode, const SwContentIndex & rContent )
70 : nNode( rNode ), nContent( rContent )
71{
72 assert((!rNode.GetContentNode() || rNode.GetContentNode() == rContent.GetContentNode())
73 && "parameters point to different nodes");
74}
75
76SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwContentNode* pContentNode, sal_Int32 nContentOffset )
77 : nNode( rNodeIndex ), nContent( pContentNode, nContentOffset )
78{
79 assert((!pContentNode || pContentNode == &rNodeIndex.GetNode()) &&
80 "parameters point to different nodes");
81}
82
83SwPosition::SwPosition( const SwNode & rNode, const SwContentNode* pContentNode, sal_Int32 nContentOffset )
84 : nNode( rNode ), nContent( pContentNode, nContentOffset )
85{
86 assert((!pContentNode || pContentNode == &rNode) &&
87 "parameters point to different nodes");
88}
89
90SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, SwNodeOffset nDiff, const SwContentNode* pContentNode, sal_Int32 nContentOffset )
91 : nNode( rNodeIndex, nDiff ), nContent( pContentNode, nContentOffset )
92{
93 assert((!pContentNode || pContentNode == &rNodeIndex.GetNode()) &&
94 "parameters point to different nodes");
95}
96
98 : nNode( rNodeIndex, nDiff ), nContent( GetNode().GetContentNode() )
99{
100}
101
103 : nNode( rNode, nDiff ), nContent( GetNode().GetContentNode() )
104{
105}
106
108 : nNode( rNodes, nIndex ), nContent( GetNode().GetContentNode() )
109{
110}
111
112SwPosition::SwPosition( const SwContentNode & rNode, const sal_Int32 nContentOffset )
113 : nNode( rNode ), nContent( &rNode, nContentOffset )
114{
115}
116
117SwPosition::SwPosition( const SwContentIndex & rContentIndex, short nDiff )
118 : nNode( *rContentIndex.GetContentNode() ), nContent( rContentIndex, nDiff )
119{
120}
121
122bool SwPosition::operator<(const SwPosition &rPos) const
123{
124 // cheaper to check for == first
125 if( nNode == rPos.nNode )
126 {
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)
132 {
133 return (nContent < rPos.nContent);
134 }
135 else // by convention position with no index is smaller
136 {
137 return pOtherReg != nullptr;
138 }
139 }
140 return nNode < rPos.nNode;
141}
142
143bool SwPosition::operator>(const SwPosition &rPos) const
144{
145 // cheaper to check for == first
146 if( nNode == rPos.nNode )
147 {
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)
153 {
154 return (nContent > rPos.nContent);
155 }
156 else // by convention position with no index is smaller
157 {
158 return pThisReg != nullptr;
159 }
160 }
161 return nNode > rPos.nNode;
162}
163
164bool SwPosition::operator<=(const SwPosition &rPos) const
165{
166 // cheaper to check for == first
167 if( nNode == rPos.nNode )
168 {
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)
174 {
175 return (nContent <= rPos.nContent);
176 }
177 else // by convention position with no index is smaller
178 {
179 return pThisReg == nullptr;
180 }
181 }
182 return nNode < rPos.nNode;
183}
184
185bool SwPosition::operator>=(const SwPosition &rPos) const
186{
187 // cheaper to check for == first
188 if( nNode == rPos.nNode )
189 {
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)
195 {
196 return (nContent >= rPos.nContent);
197 }
198 else // by convention position with no index is smaller
199 {
200 return pOtherReg == nullptr;
201 }
202 }
203 return nNode > rPos.nNode;
204}
205
206bool SwPosition::operator==(const SwPosition &rPos) const
207{
208 return (nNode == rPos.nNode)
209 && (nContent == rPos.nContent);
210}
211
212bool SwPosition::operator!=(const SwPosition &rPos) const
213{
214 return (nNode != rPos.nNode)
215 || (nContent != rPos.nContent);
216}
217
219{
220 return GetNode().GetDoc();
221}
222
224{
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);
229}
230
231void SwPosition::Assign( const SwNode& rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset )
232{
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);
236}
237void SwPosition::Assign( SwNodeOffset nNodeOffset, sal_Int32 nContentOffset )
238{
239 nNode = nNodeOffset;
240 nContent.Assign(nNode.GetNode().GetContentNode(), nContentOffset);
241}
242void SwPosition::Assign( const SwContentNode& rNode, sal_Int32 nContentOffset )
243{
244 nNode = rNode;
245 nContent.Assign(&rNode, nContentOffset);
246}
247void SwPosition::Assign( const SwNode& rNd, sal_Int32 nContentOffset )
248{
249 nNode.Assign(rNd);
250 nContent.Assign(rNd.GetContentNode(), nContentOffset);
251}
252void SwPosition::Assign( const SwNodeIndex& rNdIdx, sal_Int32 nContentOffset )
253{
254 nNode = rNdIdx;
255 nContent.Assign(nNode.GetNode().GetContentNode(), nContentOffset);
256}
258{
259 nNode += nDelta;
261}
262void SwPosition::AdjustContent( sal_Int32 nDelta )
263{
264 assert(nNode.GetNode().GetContentNode() && "only valid to call this if we point to an SwContentNode");
265 nContent += nDelta;
266}
267void SwPosition::SetContent( sal_Int32 nContentIndex )
268{
269 assert(nNode.GetNode().GetContentNode() && "only valid to call this if we point to an SwContentNode");
270 nContent = nContentIndex;
271}
273{
274 nNode = rNd;
275 nContent.Assign(&rNd, 0);
276}
278{
279 nNode = rNd;
280 nContent.Assign(&rNd, rNd.Len());
281}
282
283
284std::ostream &operator <<(std::ostream& s, const SwPosition& position)
285{
286 return s << "SwPosition (node " << position.GetNodeIndex() << ", offset " << position.GetContentIndex() << ")";
287}
288
289namespace {
290
291enum CHKSECTION { Chk_Both, Chk_One, Chk_None };
292
293}
294
295static CHKSECTION lcl_TstIdx( SwNodeOffset nSttIdx, SwNodeOffset nEndIdx, const SwNode& rEndNd )
296{
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 );
301 return eSec;
302}
303
304static bool lcl_ChkOneRange( CHKSECTION eSec, bool bChkSections,
305 const SwNode& rBaseEnd, SwNodeOffset nStt, SwNodeOffset nEnd )
306{
307 if( eSec != Chk_Both )
308 return false;
309
310 if( !bChkSections )
311 return true;
312
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();
318
319 if( pNd == rNds[ nEnd ]->StartOfSectionNode() )
320 return true; // same StartNode, same section
321
322 // already on a base node => error
323 if( !pNd->StartOfSectionIndex() )
324 return false;
325
326 for (;;)
327 {
328 pTmp = pNd->StartOfSectionNode();
329 if (pTmp->EndOfSectionNode() == &rBaseEnd )
330 break;
331 pNd = pTmp;
332 }
333
334 SwNodeOffset nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex();
335 return nSttIdx <= nStt && nStt <= nEndIdx &&
336 nSttIdx <= nEnd && nEnd <= nEndIdx;
337}
338
349bool CheckNodesRange( const SwNode& rStt,
350 const SwNode& rEnd, bool bChkSection )
351{
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;
357
358 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() );
359 if( Chk_None != eSec )
360 return lcl_ChkOneRange( eSec, bChkSection,
361 rNds.GetEndOfAutotext(), nStt, nEnd );
362
363 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() );
364 if( Chk_None != eSec )
365 return lcl_ChkOneRange( eSec, bChkSection,
366 rNds.GetEndOfPostIts(), nStt, nEnd );
367
368 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() );
369 if( Chk_None != eSec )
370 return lcl_ChkOneRange( eSec, bChkSection,
371 rNds.GetEndOfInserts(), nStt, nEnd );
372
373 eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() );
374 if( Chk_None != eSec )
375 return lcl_ChkOneRange( eSec, bChkSection,
376 rNds.GetEndOfRedlines(), nStt, nEnd );
377
378 return false; // somewhere in between => error
379}
380
382{
383 if( pNd->IsContentNode() )
384 return static_cast<SwContentNode*>(pNd)->GoNext( pIdx, nMode );
385 return false;
386}
387
389{
390 if( pNd->IsContentNode() )
391 return static_cast<SwContentNode*>(pNd)->GoPrevious( pIdx, nMode );
392 return false;
393}
394
396{
397 SwNodeIndex aIdx( *pIdx );
398 SwContentNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
399 if( pNd )
400 {
401 if( bChk && SwNodeOffset(1) != aIdx.GetIndex() - pIdx->GetIndex() &&
402 !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) )
403 pNd = nullptr;
404 else
405 *pIdx = aIdx;
406 }
407 return pNd;
408}
409
411{
412 SwNodeIndex aIdx( *pIdx );
413 SwContentNode* pNd = SwNodes::GoPrevious( &aIdx );
414 if( pNd )
415 {
416 if( bChk && SwNodeOffset(1) != pIdx->GetIndex() - aIdx.GetIndex() &&
417 !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) )
418 pNd = nullptr;
419 else
420 *pIdx = aIdx;
421 }
422 return pNd;
423}
424
426{
427 SwNodeIndex aIdx( pIdx->GetNode() );
428 SwContentNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
429 if( pNd )
430 {
431 if( bChk && SwNodeOffset(1) != aIdx.GetIndex() - pIdx->GetNodeIndex() &&
432 !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) )
433 pNd = nullptr;
434 else
435 pIdx->Assign(aIdx);
436 }
437 return pNd;
438}
439
441{
442 SwNodeIndex aIdx( pIdx->GetNode() );
443 SwContentNode* pNd = SwNodes::GoPrevious( &aIdx );
444 if( pNd )
445 {
446 if( bChk && SwNodeOffset(1) != pIdx->GetNodeIndex() - aIdx.GetIndex() &&
447 !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) )
448 pNd = nullptr;
449 else
450 pIdx->Assign(aIdx);
451 }
452 return pNd;
453}
454
455SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing )
456 : Ring( pRing )
457 , m_Bound1( rPos )
458 , m_Bound2( rPos.GetNode().GetNodes() ) // default initialize
459 , m_pPoint( &m_Bound1 )
460 , m_pMark( m_pPoint )
461 , m_bIsInFrontOfLabel( false )
462{
463}
464
465SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing )
466 : Ring( pRing )
467 , m_Bound1( rMark )
468 , m_Bound2( rPoint )
469 , m_pPoint( &m_Bound2 )
470 , m_pMark( &m_Bound1 )
471 , m_bIsInFrontOfLabel( false )
472{
473}
474
475SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint,
476 SwNodeOffset nMarkOffset, SwNodeOffset nPointOffset, 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 )
483{
484 if ( nMarkOffset )
485 {
486 m_pMark->nNode += nMarkOffset;
487 }
488 if ( nPointOffset )
489 {
490 m_pPoint->nNode += nPointOffset;
491 }
494}
495
496SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint,
497 SwNodeOffset nMarkOffset, SwNodeOffset nPointOffset, SwPaM* pRing )
498 : Ring( pRing )
499 , m_Bound1( rMark )
500 , m_Bound2( rPoint )
501 , m_pPoint( &m_Bound2 )
502 , m_pMark( &m_Bound1 )
503 , m_bIsInFrontOfLabel( false )
504{
505 if ( nMarkOffset )
506 {
507 m_pMark->nNode += nMarkOffset;
508 }
509 if ( nPointOffset )
510 {
511 m_pPoint->nNode += nPointOffset;
512 }
515}
516
517SwPaM::SwPaM( const SwNodeIndex& rMark, sal_Int32 nMarkContent,
518 const SwNodeIndex& rPoint, sal_Int32 nPointContent, SwPaM* pRing )
519 : Ring( pRing )
520 , m_Bound1( rMark )
521 , m_Bound2( rPoint )
522 , m_pPoint( &m_Bound2 )
523 , m_pMark( &m_Bound1 )
524 , m_bIsInFrontOfLabel( false )
525{
526 m_pPoint->nContent.Assign( rPoint.GetNode().GetContentNode(), nPointContent);
527 m_pMark ->nContent.Assign( rMark .GetNode().GetContentNode(), nMarkContent );
528}
529
530SwPaM::SwPaM( const SwNode& rMark, sal_Int32 nMarkContent,
531 const SwNode& rPoint, sal_Int32 nPointContent, SwPaM* pRing )
532 : Ring( pRing )
533 , m_Bound1( rMark )
534 , m_Bound2( rPoint )
535 , m_pPoint( &m_Bound2 )
536 , m_pMark( &m_Bound1 )
537 , m_bIsInFrontOfLabel( false )
538{
540 nPointContent);
542 nMarkContent );
543}
544
545SwPaM::SwPaM( const SwNode& rMark, SwNodeOffset nMarkOffset, sal_Int32 nMarkContent,
546 const SwNode& rPoint, SwNodeOffset nPointOffset, sal_Int32 nPointContent, SwPaM* pRing )
547 : Ring( pRing )
548 , m_Bound1( rMark )
549 , m_Bound2( rPoint )
550 , m_pPoint( &m_Bound2 )
551 , m_pMark( &m_Bound1 )
552 , m_bIsInFrontOfLabel( false )
553{
554 if ( nMarkOffset )
555 {
556 m_pMark->nNode += nMarkOffset;
557 }
558 if ( nPointOffset )
559 {
560 m_pPoint->nNode += nPointOffset;
561 }
563 nPointContent);
565 nMarkContent );
566}
567
568SwPaM::SwPaM( const SwNode& rNode, sal_Int32 nContent, SwPaM* pRing )
569 : Ring( pRing )
570 , m_Bound1( rNode )
571 , m_Bound2( m_Bound1.GetNode().GetNodes() ) // default initialize
572 , m_pPoint( &m_Bound1 )
573 , m_pMark( &m_Bound1 )
574 , m_bIsInFrontOfLabel( false )
575{
577 nContent );
578}
579
580SwPaM::SwPaM( const SwNode& rNode, SwNodeOffset nNdOffset, sal_Int32 nContent, SwPaM* pRing )
581 : Ring( 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 )
587{
589 nContent );
590}
591
592SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, sal_Int32 nContent, SwPaM* pRing )
593 : Ring( 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 )
599{
600 m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetContentNode(), nContent );
601}
602
603SwPaM::SwPaM( SwNodes& rNodes, SwNodeOffset nNdOffset, SwPaM* pRing )
604 : Ring( 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 )
610{
611}
612
614
615SwPaM::SwPaM(SwPaM const& rPam, SwPaM *const pRing)
616 : Ring(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 )
621{
622}
623
624// @@@ semantic: no copy assignment for super class Ring.
626{
627 if(this == &rPam)
628 return *this;
629
630 *m_pPoint = *( rPam.m_pPoint );
631 if ( rPam.HasMark() )
632 {
633 SetMark();
634 *m_pMark = *( rPam.m_pMark );
635 }
636 else
637 {
638 DeleteMark();
639 }
640 return *this;
641}
642
644{
645 if (m_pPoint == &m_Bound1)
646 {
647 m_pMark = &m_Bound2;
648 }
649 else
650 {
651 m_pMark = &m_Bound1;
652 }
653 (*m_pMark) = *m_pPoint;
654}
655
657bool SwPaM::Move( SwMoveFnCollection const & fnMove, SwGoInDoc fnGo )
658{
659 const bool bRet = (*fnGo)( *this, fnMove );
660
661 m_bIsInFrontOfLabel = false;
662 return bRet;
663}
664
665namespace sw {
666
676void MakeRegion(SwMoveFnCollection const & fnMove,
677 const SwPaM & rOrigRg, std::optional<SwPaM>& rPam)
678{
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() ) )
684 rPam->Exchange();
685}
686
687} // namespace sw
688
689void SwPaM::Normalize(bool bPointFirst)
690{
691 if (HasMark())
692 if ( ( bPointFirst && *m_pPoint > *m_pMark) ||
693 (!bPointFirst && *m_pPoint < *m_pMark) )
694 {
695 Exchange();
696 }
697}
698
700sal_uInt16 SwPaM::GetPageNum( bool bAtPoint, const Point* pLayPos )
701{
702 const SwContentFrame* pCFrame;
703 const SwPageFrame *pPg;
704 const SwContentNode *pNd ;
705 const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark;
706
707 std::pair<Point, bool> tmp;
708 if (pLayPos)
709 {
710 tmp.first = *pLayPos;
711 tmp.second = false;
712 }
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();
717 return 0;
718}
719
720// form view - see also SwCursorShell::IsCursorReadonly()
721static const SwFrame* lcl_FindEditInReadonlyFrame( const SwFrame& rFrame )
722{
723 const SwFrame* pRet = nullptr;
724
725 const SwFlyFrame* pFly;
726 const SwSectionFrame* pSectionFrame;
727
728 if( rFrame.IsInFly() &&
729 (pFly = rFrame.FindFlyFrame())->GetFormat()->GetEditInReadonly().GetValue() &&
730 pFly->Lower() &&
731 !pFly->Lower()->IsNoTextFrame() )
732 {
733 pRet = pFly;
734 }
735 else if ( rFrame.IsInSct() &&
736 nullptr != ( pSectionFrame = rFrame.FindSctFrame() )->GetSection() &&
737 pSectionFrame->GetSection()->IsEditInReadonlyFlag() )
738 {
739 pRet = pSectionFrame;
740 }
741
742 return pRet;
743}
744
746bool SwPaM::HasReadonlySel(bool bFormView, bool const isReplace) const
747{
748 bool bRet = false;
749
750 const SwContentNode* pNd = GetPoint()->GetNode().GetContentNode();
751 const SwContentFrame *pFrame = nullptr;
752 if ( pNd != nullptr )
753 {
754 Point aTmpPt;
755 std::pair<Point, bool> const tmp(aTmpPt, false);
756 pFrame = pNd->getLayoutFrame(
758 GetPoint(), &tmp);
759 }
760
761 // Will be set if point are inside edit-in-readonly environment
762 const SwFrame* pPointEditInReadonlyFrame = nullptr;
763 if ( pFrame != nullptr
764 && ( pFrame->IsProtected()
765 || ( bFormView
766 && nullptr == ( pPointEditInReadonlyFrame = lcl_FindEditInReadonlyFrame( *pFrame ) ) ) ) )
767 {
768 bRet = true;
769 }
770 else if( pNd != nullptr )
771 {
772 const SwSectionNode* pSNd = pNd->GetSectionNode();
773 if ( pSNd != nullptr
774 && ( pSNd->GetSection().IsProtectFlag()
775 || ( bFormView
776 && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
777 {
778 bRet = true;
779 }
780 else
781 {
782 const SwSectionNode* pParentSectionNd = pNd->FindSectionNode();
783 if ( pParentSectionNd != nullptr
784 && ( pParentSectionNd->GetSection().IsProtectFlag()
785 || ( bFormView && !pParentSectionNd->GetSection().IsEditInReadonlyFlag()) ) )
786 {
787 bRet = true;
788 }
789 }
790 }
791
792 if ( !bRet
793 && HasMark()
794 && GetPoint()->nNode != GetMark()->nNode )
795 {
796 pNd = GetMark()->GetNode().GetContentNode();
797 pFrame = nullptr;
798 if ( pNd != nullptr )
799 {
800 Point aTmpPt;
801 std::pair<Point, bool> const tmp(aTmpPt, false);
802 pFrame = pNd->getLayoutFrame(
804 GetMark(), &tmp);
805 }
806
807 const SwFrame* pMarkEditInReadonlyFrame = nullptr;
808 if ( pFrame != nullptr
809 && ( pFrame->IsProtected()
810 || ( bFormView
811 && nullptr == ( pMarkEditInReadonlyFrame = lcl_FindEditInReadonlyFrame( *pFrame ) ) ) ) )
812 {
813 bRet = true;
814 }
815 else if( pNd != nullptr )
816 {
817 const SwSectionNode* pSNd = pNd->GetSectionNode();
818 if ( pSNd != nullptr
819 && ( pSNd->GetSection().IsProtectFlag()
820 || ( bFormView
821 && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
822 {
823 bRet = true;
824 }
825 }
826
827 if ( !bRet && bFormView )
828 {
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 )
832 bRet = true;
833 }
834
835 // check for protected section inside the selection
836 if( !bRet )
837 {
838 SwNodeOffset nSttIdx = GetMark()->GetNodeIndex(),
839 nEndIdx = GetPoint()->GetNodeIndex();
840 if( nEndIdx < nSttIdx )
841 std::swap( nSttIdx, nEndIdx );
842
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 )
847 {
848 const SwSectionFormats& rFormats = GetDoc().GetSections();
849 for( SwSectionFormats::size_type n = rFormats.size(); n; )
850 {
851 const SwSectionFormat* pFormat = rFormats[ --n ];
852 if( pFormat->GetProtect().IsContentProtected() )
853 {
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() )
859 {
860 bRet = true;
861 break;
862 }
863 }
864 }
865 }
866 }
867 }
868
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());
877
879 {
880 ; // allow editing all fields in generic mode
881 }
882 else if (!bRet)
883 {
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 )
887 bRet = true;
888 else
889 {
890 if ((pA == pB) && (bAtStartA != bAtStartB))
891 bRet = true;
892 else if (pA != pB)
893 {
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 ) );
897 }
898 if( !bRet && rDoc.GetDocumentSettingManager().get( DocumentSettingId::PROTECT_FORM ) && (pA || pB) )
899 {
900 // Form protection case
901 bRet = ( pA == nullptr ) || ( pB == nullptr ) || bAtStartA || bAtStartB;
902 }
903 }
904 }
905 else
906 {
907 // Allow editing when the cursor/selection is fully inside of a legacy form field.
908 bRet = !( pA != nullptr && !bAtStartA && !bAtStartB && pA == pB );
909
910 if (bRet)
911 {
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();
916 }
917 }
918
919 if (!bRet)
920 {
921 // Paragraph Signatures and Classification fields are read-only.
922 if (const SwEditShell* pEditShell = rDoc.GetEditShell())
923 bRet = pEditShell->IsCursorInParagraphMetadataField();
924 }
925
926 if (!bRet &&
928 {
929 if (rDoc.getIDocumentMarkAccess()->isBookmarkDeleted(*this, isReplace))
930 {
931 return true;
932 }
933 }
934 if (!bRet &&
936 {
937 SwPosition const& rStart(*Start());
938 SwPosition const& rEnd(*End());
939 for (SwNodeIndex n(rStart.GetNode()); n <= rEnd.GetNode(); ++n)
940 {
941 if (SwTextNode const*const pNode = n.GetNode().GetTextNode())
942 {
943 if (SwpHints const*const pHints = pNode->GetpSwpHints())
944 {
945 for (size_t i = 0; i < pHints->Count(); ++i)
946 {
947 SwTextAttr const*const pHint(pHints->Get(i));
948 if (n == rStart.GetNode() && pHint->GetStart() < rStart.GetContentIndex())
949 {
950 continue; // before selection
951 }
952 if (n == rEnd.GetNode() && rEnd.GetContentIndex() <= pHint->GetStart())
953 {
954 break; // after selection
955 }
956 if (pHint->Which() == RES_TXTATR_FIELD
957 // placeholders don't work if you can't delete them
959 {
960 return true;
961 }
962 }
963 }
964 }
965 }
966 }
967
968 if (!bRet)
969 {
970 // See if we're inside a read-only content control.
971 const SwPosition* pStart = Start();
972 SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
973 if (pTextNode)
974 {
975 sal_Int32 nIndex = pStart->GetContentIndex();
976 SwTextAttr* pAttr
978 auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
979 if (pTextContentControl)
980 {
981 const SwFormatContentControl& rFormatContentControl
982 = pTextContentControl->GetContentControl();
983 std::shared_ptr<SwContentControl> pContentControl
984 = rFormatContentControl.GetContentControl();
985 if (pContentControl && !pContentControl->GetReadWrite())
986 {
987 switch (pContentControl->GetType())
988 {
992 bRet = true;
993 break;
994 default:
995 break;
996 }
997 }
998 }
999 }
1000 }
1001
1002 return bRet;
1003}
1004
1006{
1007 bool bRet = false;
1008
1009 if (HasMark() && GetPoint()->nNode != GetMark()->nNode)
1010 {
1011 // check for hidden section inside the selection
1012 SwNodeOffset nSttIdx = Start()->GetNodeIndex(), nEndIdx = End()->GetNodeIndex();
1013
1014 if (nSttIdx + SwNodeOffset(3) < nEndIdx)
1015 {
1016 const SwSectionFormats& rFormats = GetDoc().GetSections();
1017 for (SwSectionFormats::size_type n = rFormats.size(); n;)
1018 {
1019 const SwSectionFormat* pFormat = rFormats[--n];
1020 if (pFormat->GetSection()->IsHidden())
1021 {
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())
1027 {
1028 bRet = true;
1029 break;
1030 }
1031 }
1032 }
1033 }
1034 }
1035
1036 return bRet;
1037}
1038
1043SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & fnMove,
1044 bool const bInReadOnly, SwRootFrame const*const i_pLayout)
1045{
1046 SwRootFrame const*const pLayout(i_pLayout ? i_pLayout :
1048 SwContentNode * pNd = nullptr;
1049 if( ((*rPam.GetPoint()).*fnMove.fnCmpOp)( *rPam.GetMark() ) ||
1050 ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
1051 {
1052 if( rbFirst )
1053 {
1054 rbFirst = false;
1055 pNd = rPam.GetPointContentNode();
1056 if( pNd )
1057 {
1058 SwContentFrame const*const pFrame(pNd->getLayoutFrame(pLayout));
1059 if(
1060 (
1061 nullptr == pFrame ||
1062 ( !bInReadOnly && pFrame->IsProtected() ) ||
1063 (pFrame->IsTextFrame() && static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())
1064 ) ||
1065 ( !bInReadOnly && pNd->FindSectionNode() &&
1067 )
1068 )
1069 {
1070 pNd = nullptr;
1071 }
1072 }
1073 }
1074
1075 if( !pNd ) // is the cursor not on a ContentNode?
1076 {
1077 SwPosition aPos( *rPam.GetPoint() );
1078 bool bSrchForward = &fnMove == &fnMoveForward;
1079 SwNodes& rNodes = aPos.GetNodes();
1080
1081 // go to next/previous ContentNode
1082 while( true )
1083 {
1084 if (i_pLayout && aPos.GetNode().IsTextNode())
1085 {
1086 auto const fal(sw::GetFirstAndLastNode(*pLayout, aPos.GetNode()));
1087 aPos.Assign( bSrchForward ? *fal.second : *fal.first );
1088 }
1089
1090 pNd = bSrchForward
1091 ? rNodes.GoNextSection( &aPos, true, !bInReadOnly )
1092 : SwNodes::GoPrevSection( &aPos, true, !bInReadOnly );
1093 if( pNd )
1094 {
1095 if (!bSrchForward)
1096 aPos.AssignEndIndex( *pNd );
1097 // is the position still in the area
1098 if( (aPos.*fnMove.fnCmpOp)( *rPam.GetMark() ) )
1099 {
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()))
1106 {
1107 pNd = nullptr;
1108 continue;
1109 }
1110 *rPam.GetPoint() = aPos;
1111 }
1112 else
1113 pNd = nullptr; // no valid node
1114 break;
1115 }
1116 break;
1117 }
1118 }
1119 }
1120 return pNd;
1121}
1122
1124{
1125 SwNodes& rNodes = pPos->GetNodes();
1126 pPos->Assign( *rNodes.GetEndOfContent().StartOfSectionNode() );
1127 // we always need to find a ContentNode!
1128 rNodes.GoNext( pPos );
1129}
1130
1131void GoEndDoc( SwPosition * pPos )
1132{
1133 SwNodes& rNodes = pPos->GetNodes();
1134 pPos->Assign( rNodes.GetEndOfContent() );
1135 SwContentNode* pCNd = GoPreviousPos( pPos, true );
1136 if( pCNd )
1137 pPos->AssignEndIndex(*pCNd);
1138}
1139
1141{
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() )
1146 nLevel--;
1147 do { SwNodes::GoStartOfSection( &pPos->nNode ); } while( nLevel-- );
1148
1149 // already on a ContentNode
1150 pPos->AssignStartIndex(*pPos->GetNode().GetContentNode());
1151}
1152
1154{
1155 // jump to section's beginning
1157 pPos->nContent.Assign(pPos->GetNode().GetContentNode(), 0);
1158}
1159
1162{
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() )
1167 nLevel--;
1168 do { SwNodes::GoEndOfSection( &pPos->nNode ); } while( nLevel-- );
1169
1170 // now on an EndNode, thus to the previous ContentNode
1171 if( SwContentNode* pCNd = GoPreviousNds( &pPos->nNode, true ) )
1172 pPos->AssignEndIndex(*pCNd);
1173}
1174
1176{
1178 SwContentNode* pCNd = pPos->nNode.GetNode().GetContentNode();
1179 pPos->nContent.Assign(pCNd, pCNd ? pCNd->Len() : 0);
1180}
1181
1182bool GoInDoc( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1183{
1184 (*fnMove.fnDoc)( rPam.GetPoint() );
1185 return true;
1186}
1187
1188bool GoInSection( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1189{
1190 (*fnMove.fnSections)( rPam.GetPoint() );
1191 return true;
1192}
1193
1194bool GoInNode( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1195{
1196 SwContentNode *pNd = (*fnMove.fnPos)( rPam.GetPoint(), true );
1197 if( pNd )
1198 rPam.GetPoint()->SetContent(
1199 ::GetSttOrEnd( &fnMove == &fnMoveForward, *pNd ) );
1200 return pNd;
1201}
1202
1203bool GoInContent( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1204{
1205 if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(),
1207 return true;
1208 return GoInNode( rPam, fnMove );
1209}
1210
1211bool GoInContentCells( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1212{
1213 if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(),
1215 return true;
1216 return GoInNode( rPam, fnMove );
1217}
1218
1219bool GoInContentSkipHidden( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1220{
1221 if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(),
1223 return true;
1224 return GoInNode( rPam, fnMove );
1225}
1226
1228{
1229 if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(),
1231 return true;
1232 return GoInNode( rPam, fnMove );
1233}
1234
1235bool GoPrevPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara )
1236{
1237 if( rPam.Move( fnMoveBackward, GoInNode ) )
1238 {
1239 // always on a ContentNode
1240 SwPosition& rPos = *rPam.GetPoint();
1241 SwContentNode * pNd = rPos.GetNode().GetContentNode();
1242 rPos.SetContent( ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ) );
1243 return true;
1244 }
1245 return false;
1246}
1247
1248bool GoCurrPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara )
1249{
1250 SwPosition& rPos = *rPam.GetPoint();
1251 SwContentNode * pNd = rPos.GetNode().GetContentNode();
1252 if( pNd )
1253 {
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
1257 if( nOld != nNew )
1258 {
1259 rPos.SetContent( nNew );
1260 return true;
1261 }
1262 }
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 ))) )
1268 {
1269 rPos.SetContent( ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ));
1270 return true;
1271 }
1272 return false;
1273}
1274
1275bool GoNextPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara )
1276{
1277 if( rPam.Move( fnMoveForward, GoInNode ) )
1278 {
1279 // always on a ContentNode
1280 SwPosition& rPos = *rPam.GetPoint();
1281 SwContentNode * pNd = rPos.GetNode().GetContentNode();
1282 rPos.SetContent( ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ) );
1283 return true;
1284 }
1285 return false;
1286}
1287
1288bool GoCurrSection( SwPaM & rPam, SwMoveFnCollection const & fnMove )
1289{
1290 SwPosition& rPos = *rPam.GetPoint();
1291 SwPosition aSavePos( rPos ); // position for comparison
1292 (fnMove.fnSection)( &rPos );
1293 SwContentNode *pNd;
1294 if( nullptr == ( pNd = rPos.GetNode().GetContentNode()) &&
1295 nullptr == ( pNd = (*fnMove.fnPos)( &rPos, true )) )
1296 {
1297 rPos = aSavePos; // do not change cursor
1298 return false;
1299 }
1300
1301 rPos.SetContent( ::GetSttOrEnd( &fnMove == &fnMoveForward, *pNd ) );
1302 return aSavePos != rPos;
1303}
1304
1305OUString SwPaM::GetText() const
1306{
1307 OUStringBuffer aResult;
1308
1309 SwNodeIndex aNodeIndex = Start()->nNode;
1310
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;
1315 for (;;)
1316 {
1317 const bool bIsEndNode = aNodeIndex == End()->nNode;
1318 SwTextNode * pTextNode = aNodeIndex.GetNode().GetTextNode();
1319
1320 if (pTextNode != nullptr)
1321 {
1322 if (!bIsStartNode)
1323 {
1324 aResult.append(CH_TXTATR_NEWLINE); // use newline for para break
1325 }
1326 const OUString& aTmpStr = pTextNode->GetText();
1327
1328 if (bIsStartNode || bIsEndNode)
1329 {
1330 // Handle corner cases of start/end node(s)
1331 const sal_Int32 nStart = bIsStartNode
1332 ? Start()->GetContentIndex()
1333 : 0;
1334 const sal_Int32 nEnd = bIsEndNode
1335 ? End()->GetContentIndex()
1336 : aTmpStr.getLength();
1337
1338 aResult.append(aTmpStr.subView(nStart, nEnd-nStart));
1339 }
1340 else
1341 {
1342 aResult.append(aTmpStr);
1343 }
1344 }
1345
1346 if (bIsEndNode)
1347 {
1348 break;
1349 }
1350
1351 ++aNodeIndex;
1352 bIsStartNode = false;
1353 }
1354
1355 return aResult.makeStringAndClear();
1356}
1357
1359{
1360 for (SwNodeIndex index(Start()->GetNode()); index <= End()->GetNode(); ++index)
1361 {
1362 if (SwTextNode *const pTextNode = index.GetNode().GetTextNode())
1363 {
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(
1369 nStart,
1370 index == End()->nNode
1371 ? End()->GetContentIndex() - nStart
1372 : pTextNode->Len() - nStart,
1373 0);
1374 pTextNode->TriggerNodeUpdate(sw::LegacyModifyHint(&aHint, &aHint));
1375 }
1376 // other node types not invalidated
1377 }
1378}
1379
1381{
1382 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwPaM"));
1383
1384 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("point"));
1385 GetPoint()->dumpAsXml(pWriter);
1386 (void)xmlTextWriterEndElement(pWriter);
1387
1388 if (HasMark())
1389 {
1390 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("mark"));
1391 GetMark()->dumpAsXml(pWriter);
1392 (void)xmlTextWriterEndElement(pWriter);
1393 }
1394
1395 (void)xmlTextWriterEndElement(pWriter);
1396}
1397
1398std::ostream &operator <<(std::ostream& s, const SwPaM& pam)
1399{
1400 if( pam.HasMark())
1401 return s << "SwPaM (point " << *pam.GetPoint() << ", mark " << *pam.GetMark() << ")";
1402 else
1403 return s << "SwPaM (point " << *pam.GetPoint() << ")";
1404}
1405
1406
1407/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual const SwRootFrame * GetCurrentLayout() const =0
Provides access to the marks of a document.
virtual sw::mark::IFieldmark * getInnerFieldmarkFor(const SwPosition &pos) const =0
virtual bool isBookmarkDeleted(SwPaM const &rPaM, bool isReplace) const =0
check if the selection would delete a BOOKMARK
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
bool IsContentProtected() const
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:59
Marks a character position inside a document model content node (SwContentNode)
const SwContentNode * GetContentNode() const
SwContentIndex & Assign(const SwContentNode *, sal_Int32)
Definition: index.cxx:206
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1223
virtual sal_Int32 Len() const
Definition: node.cxx:1256
Definition: doc.hxx:197
SwSectionFormats & GetSections()
Definition: doc.hxx:1356
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:330
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:419
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:190
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1890
::sw::DocumentSettingManager & GetDocumentSettingManager()
Definition: doc.cxx:200
SwFieldIds Which() const
Definition: fldbas.hxx:276
SwFieldType * GetTyp() const
Definition: fldbas.hxx:402
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
SfxPoolItem subclass that wraps an SwContentControl.
const std::shared_ptr< SwContentControl > & GetContentControl() const
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:32
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
const SwField * GetField() const
Definition: fmtfld.hxx:131
const SvxProtectItem & GetProtect(bool=true) const
Definition: frmatr.hxx:106
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsTextFrame() const
Definition: frame.hxx:1240
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1117
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1121
bool IsProtected() const
Is the Frame or rather the Section in which it lies protected?
Definition: trvlfrm.cxx:1639
bool IsInFly() const
Definition: frame.hxx:967
bool IsNoTextFrame() const
Definition: frame.hxx:1244
SwPageFrame * FindPageFrame()
Definition: frame.hxx:686
bool IsInSct() const
Definition: frame.hxx:973
const SwFrame * Lower() const
Definition: layfrm.hxx:101
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNodes & GetNodes() const
Definition: ndindex.hxx:119
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
SwNodeIndex & Assign(SwNodes const &rNds, SwNodeOffset nIdx)
Definition: ndindex.hxx:114
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwSectionNode * GetSectionNode()
Definition: node.hxx:658
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:706
bool IsContentNode() const
Definition: node.hxx:188
SwDoc & GetDoc()
Definition: node.hxx:233
bool IsStartNode() const
Definition: node.hxx:187
SwNodeOffset StartOfSectionIndex() const
Definition: node.hxx:687
bool IsTextNode() const
Definition: node.hxx:190
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:968
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwContentNode * GetContentNode()
Definition: node.hxx:666
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:695
static sal_uInt16 GetSectionLevel(const SwNode &rIndex)
get section level at the given position
Definition: nodes.cxx:1267
static void GoEndOfSection(SwNodeIndex *)
Definition: nodes.cxx:1293
SwNode & GetEndOfAutotext() const
Section for all Flys/Header/Footers.
Definition: ndarr.hxx:158
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
bool IsDocNodes() const
Is the NodesArray the regular one of Doc? (and not the UndoNds, ...) Implementation in doc....
Definition: nodes.cxx:2555
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1333
static void GoStartOfSection(SwNodeIndex *)
Definition: nodes.cxx:1275
SwNode & GetEndOfRedlines() const
Section for all Redlines.
Definition: ndarr.hxx:160
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
SwContentNode * GoNextSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true) const
Go to next content-node that is not protected or hidden (Both set FALSE ==> GoNext/GoPrevious!...
Definition: nodes.cxx:1948
SwNode & GetEndOfInserts() const
Section for all footnotes.
Definition: ndarr.hxx:156
SwNode & GetEndOfPostIts() const
A still empty section.
Definition: ndarr.hxx:154
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:2064
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
SwPaM & operator=(const SwPaM &)
@@ semantic: no copy assignment for super class Ring.
Definition: pam.cxx:625
SwPosition m_Bound1
Definition: pam.hxx:189
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: pam.cxx:1380
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
void Exchange()
Definition: pam.hxx:242
SwPosition * m_pMark
points at either m_Bound1 or m_Bound2
Definition: pam.hxx:192
virtual ~SwPaM() override
Definition: pam.cxx:613
void Normalize(bool bPointFirst=true)
Normalizes PaM, i.e.
Definition: pam.cxx:689
SwPosition * m_pPoint
points at either m_Bound1 or m_Bound2
Definition: pam.hxx:191
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:279
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * End() const
Definition: pam.hxx:263
SwPaM(SwPaM const &rPaM)=delete
SwDoc & GetDoc() const
Definition: pam.hxx:291
SwPosition m_Bound2
Definition: pam.hxx:190
sal_uInt16 GetPageNum(bool bAtPoint=true, const Point *pLayPos=nullptr)
Get number of page which contains cursor.
Definition: pam.cxx:700
OUString GetText() const
Definition: pam.cxx:1305
bool m_bIsInFrontOfLabel
Definition: pam.hxx:193
void DeleteMark()
Definition: pam.hxx:232
bool HasReadonlySel(bool bFormView, bool isReplace) const
Is in something protected (readonly) or selection contains something protected.
Definition: pam.cxx:746
const SwPosition * GetPoint() const
Definition: pam.hxx:253
bool HasHiddenSections() const
Is there hidden sections in the selected area.
Definition: pam.cxx:1005
const SwPosition * Start() const
Definition: pam.hxx:258
void InvalidatePaM()
Definition: pam.cxx:1358
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
A page of the document layout.
Definition: pagefrm.hxx:60
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:209
The root element of a Writer document layout.
Definition: rootfrm.hxx:85
SwSection * GetSection() const
Definition: section.cxx:646
Array of Undo-history.
Definition: docary.hxx:193
SwSection * GetSection()
Definition: sectfrm.hxx:97
A section node represents the start of a section on the UI, i.e.
Definition: node.hxx:575
const SwSection & GetSection() const
Definition: node.hxx:590
bool IsProtectFlag() const
Definition: section.hxx:191
bool IsHidden() const
Definition: section.hxx:181
bool IsProtect() const
Definition: section.cxx:334
bool IsEditInReadonlyFlag() const
Definition: section.hxx:192
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
sal_uInt16 Which() const
Definition: txatbase.hxx:116
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1447
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
SwTextAttr * GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, ::sw::GetTextAttrMode const eMode=::sw::GetTextAttrMode::Default) const
get the innermost text attribute covering position nIndex.
Definition: ndtxt.cxx:1804
const OUString & GetText() const
Definition: ndtxt.hxx:244
std::vector< SwSectionFormat * >::size_type size_type
Definition: docary.hxx:67
size_t size() const
Definition: docary.hxx:88
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
virtual bool get(DocumentSettingId id) const override
Return the specified document setting.
static bool IsFuzzing()
struct _xmlTextWriter * xmlTextWriterPtr
static SwContentNode * GetContentNode(SwDoc &rDoc, SwPosition &rPos, bool bNext)
Definition: fltshell.cxx:54
constexpr TypedWhichId< SwFormatContentControl > RES_TXTATR_CONTENTCONTROL(56)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
#define CH_TXTATR_NEWLINE
Definition: hintids.hxx:177
sal_Int32 nIndex
sal_Int64 n
def position(n=-1)
int i
index
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Dialog to specify the properties of date form field.
void MakeRegion(SwMoveFnCollection const &fnMove, const SwPaM &rOrigRg, std::optional< SwPaM > &rPam)
make a new region
Definition: pam.cxx:676
std::pair< SwTextNode *, SwTextNode * > GetFirstAndLastNode(SwRootFrame const &rLayout, SwNode const &rPos)
Definition: txtfrm.cxx:354
@ Parent
EXPAND : (Start < nIndex <= End)
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
constexpr OUStringLiteral ODF_UNHANDLED
void GoEndOfSection(SwPosition *pPos)
Definition: pam.cxx:1175
bool GoCurrPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1248
SwContentNode * GoNextNds(SwNodeIndex *pIdx, bool bChk)
Definition: pam.cxx:395
bool GoInContentSkipHidden(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1219
bool GoPrevPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1235
SwContentNode * GoPreviousPos(SwPosition *pIdx, bool bChk)
Definition: pam.cxx:440
void GoStartSection(SwPosition *pPos)
Definition: pam.cxx:1140
bool GoInContentCells(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1211
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1194
std::ostream & operator<<(std::ostream &s, const SwPosition &position)
Definition: pam.cxx:284
void GoStartDoc(SwPosition *pPos)
Definition: pam.cxx:1123
bool GoNext(SwNode *pNd, SwContentIndex *pIdx, SwCursorSkipMode nMode)
Definition: pam.cxx:381
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:1043
bool GoInDoc(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1182
void GoStartOfSection(SwPosition *pPos)
Definition: pam.cxx:1153
bool GoInContentCellsSkipHidden(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1227
static CHKSECTION lcl_TstIdx(SwNodeOffset nSttIdx, SwNodeOffset nEndIdx, const SwNode &rEndNd)
Definition: pam.cxx:295
bool CheckNodesRange(const SwNode &rStt, const SwNode &rEnd, bool bChkSection)
Check if the given range is inside one of the defined top-level sections.
Definition: pam.cxx:349
static const SwFrame * lcl_FindEditInReadonlyFrame(const SwFrame &rFrame)
Definition: pam.cxx:721
SwContentNode * GoPreviousNds(SwNodeIndex *pIdx, bool bChk)
Definition: pam.cxx:410
bool GoPrevious(SwNode *pNd, SwContentIndex *pIdx, SwCursorSkipMode nMode)
Definition: pam.cxx:388
void GoEndDoc(SwPosition *pPos)
Definition: pam.cxx:1131
bool GoNextPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1275
bool GoInSection(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1188
void GoEndSection(SwPosition *pPos)
go to the end of the current base section
Definition: pam.cxx:1161
static bool lcl_ChkOneRange(CHKSECTION eSec, bool bChkSections, const SwNode &rBaseEnd, SwNodeOffset nStt, SwNodeOffset nEnd)
Definition: pam.cxx:304
static sal_Int32 GetSttOrEnd(bool bCondition, const SwContentNode &rNd)
Definition: pam.cxx:57
SwContentNode * GoNextPos(SwPosition *pIdx, bool bChk)
Definition: pam.cxx:425
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1203
bool GoCurrSection(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1288
auto(*)(SwPaM &rPam, SwMoveFnCollection const &fnMove) -> bool SwGoInDoc
Definition: pam.hxx:172
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:48
SwMoveFnCollection const & fnParaEnd
Definition: paminit.cxx:49
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:60
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
MvSection fnSection
Definition: pamtyp.hxx:86
GoSection fnSections
Definition: pamtyp.hxx:82
Marks a position in the document model.
Definition: pam.hxx:38
void Adjust(SwNodeOffset nDelta)
Adjust node position, and resets content position to zero.
Definition: pam.cxx:257
SwNode & GetNode() const
Definition: pam.hxx:81
bool operator<(const SwPosition &) const
Definition: pam.cxx:122
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
void AssignEndIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the end of rNd.
Definition: pam.cxx:277
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:267
SwNodeIndex nNode
Definition: pam.hxx:39
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: pam.cxx:223
bool operator>(const SwPosition &) const
Definition: pam.cxx:143
bool operator>=(const SwPosition &) const
Definition: pam.cxx:185
const SwContentNode * GetContentNode() const
Definition: pam.hxx:84
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
bool operator<=(const SwPosition &) const
Definition: pam.cxx:164
const SwNodes & GetNodes() const
Definition: pam.hxx:79
void AssignStartIndex(const SwContentNode &rNd)
Set nNode to rNd, and nContent to the beginning of rNd.
Definition: pam.cxx:272
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
SwPosition(const SwNodeIndex &rNode, const SwContentIndex &rContent)
Definition: pam.cxx:62
bool operator==(const SwPosition &) const
Definition: pam.cxx:206
void AdjustContent(sal_Int32 nDelta)
Adjust content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:262
SwDoc & GetDoc() const
Returns the document this position is in.
Definition: pam.cxx:218
bool operator!=(const SwPosition &) const
Definition: pam.cxx:212
SwContentIndex nContent
Definition: pam.hxx:40
SwCursorSkipMode
Definition: swcrsr.hxx:65