Line data Source code
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 <hintids.hxx>
21 : #include <editeng/protitem.hxx>
22 : #include <cntfrm.hxx>
23 : #include <pagefrm.hxx>
24 : #include <doc.hxx>
25 : #include <docary.hxx>
26 : #include <pam.hxx>
27 : #include <pamtyp.hxx>
28 : #include <txtfrm.hxx>
29 : #include <fmtcntnt.hxx>
30 : #include <frmatr.hxx>
31 : #include <swtable.hxx>
32 : #include <crsskip.hxx>
33 :
34 : // Formular view
35 : #include <flyfrm.hxx>
36 : #include <fmteiro.hxx>
37 : #include <section.hxx>
38 : #include <sectfrm.hxx>
39 : #include <ndtxt.hxx>
40 :
41 : #include <IMark.hxx>
42 : #include <hints.hxx>
43 :
44 : #include <xmloff/odffields.hxx>
45 :
46 : // for the dump "MSC-" compiler
47 13070 : inline xub_StrLen GetSttOrEnd( sal_Bool bCondition, const SwCntntNode& rNd )
48 : {
49 13070 : return bCondition ? 0 : rNd.Len();
50 : }
51 :
52 927 : SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwIndex & rCntnt )
53 927 : : nNode( rNodeIndex ), nContent( rCntnt )
54 : {
55 927 : }
56 :
57 104869 : SwPosition::SwPosition( const SwNodeIndex & rNodeIndex )
58 104869 : : nNode( rNodeIndex ), nContent( nNode.GetNode().GetCntntNode() )
59 : {
60 104869 : }
61 :
62 45125 : SwPosition::SwPosition( const SwNode& rNode )
63 45125 : : nNode( rNode ), nContent( nNode.GetNode().GetCntntNode() )
64 : {
65 45125 : }
66 :
67 2824 : SwPosition::SwPosition( SwCntntNode & rNode, const xub_StrLen nOffset )
68 2824 : : nNode( rNode ), nContent( &rNode, nOffset )
69 : {
70 2824 : }
71 :
72 :
73 120879 : SwPosition::SwPosition( const SwPosition & rPos )
74 120879 : : nNode( rPos.nNode ), nContent( rPos.nContent )
75 : {
76 120879 : }
77 :
78 40172 : SwPosition &SwPosition::operator=(const SwPosition &rPos)
79 : {
80 40172 : nNode = rPos.nNode;
81 40172 : nContent = rPos.nContent;
82 40172 : return *this;
83 : }
84 :
85 :
86 14497 : bool SwPosition::operator<(const SwPosition &rPos) const
87 : {
88 14497 : if( nNode < rPos.nNode )
89 3042 : return true;
90 11455 : if( nNode == rPos.nNode )
91 : {
92 : // note that positions with text node but no SwIndex registered are
93 : // created for text frames anchored at para (see SwXFrame::getAnchor())
94 10322 : SwIndexReg const*const pThisReg(nContent.GetIdxReg());
95 10322 : SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg());
96 10322 : if (pThisReg && pOtherReg)
97 : {
98 10275 : return (nContent < rPos.nContent);
99 : }
100 : else // by convention position with no index is smaller
101 : {
102 47 : return (pOtherReg) ? true : false;
103 : }
104 : }
105 1133 : return false;
106 : }
107 :
108 :
109 70315 : bool SwPosition::operator>(const SwPosition &rPos) const
110 : {
111 70315 : if(nNode > rPos.nNode )
112 15363 : return true;
113 54952 : if( nNode == rPos.nNode )
114 : {
115 : // note that positions with text node but no SwIndex registered are
116 : // created for text frames anchored at para (see SwXFrame::getAnchor())
117 53766 : SwIndexReg const*const pThisReg(nContent.GetIdxReg());
118 53766 : SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg());
119 53766 : if (pThisReg && pOtherReg)
120 : {
121 51217 : return (nContent > rPos.nContent);
122 : }
123 : else // by convention position with no index is smaller
124 : {
125 2549 : return (pThisReg) ? true : false;
126 : }
127 : }
128 1186 : return false;
129 : }
130 :
131 :
132 94813 : bool SwPosition::operator<=(const SwPosition &rPos) const
133 : {
134 94813 : if(nNode < rPos.nNode )
135 14664 : return true;
136 80149 : if( nNode == rPos.nNode )
137 : {
138 : // note that positions with text node but no SwIndex registered are
139 : // created for text frames anchored at para (see SwXFrame::getAnchor())
140 53263 : SwIndexReg const*const pThisReg(nContent.GetIdxReg());
141 53263 : SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg());
142 53263 : if (pThisReg && pOtherReg)
143 : {
144 51108 : return (nContent <= rPos.nContent);
145 : }
146 : else // by convention position with no index is smaller
147 : {
148 2155 : return (pThisReg) ? false : true;
149 : }
150 : }
151 26886 : return false;
152 : }
153 :
154 :
155 3995 : bool SwPosition::operator>=(const SwPosition &rPos) const
156 : {
157 3995 : if(nNode > rPos.nNode )
158 54 : return true;
159 3941 : if( nNode == rPos.nNode )
160 : {
161 : // note that positions with text node but no SwIndex registered are
162 : // created for text frames anchored at para (see SwXFrame::getAnchor())
163 3614 : SwIndexReg const*const pThisReg(nContent.GetIdxReg());
164 3614 : SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg());
165 3614 : if (pThisReg && pOtherReg)
166 : {
167 2010 : return (nContent >= rPos.nContent);
168 : }
169 : else // by convention position with no index is smaller
170 : {
171 1604 : return (pOtherReg) ? false : true;
172 : }
173 : }
174 327 : return false;
175 : }
176 :
177 :
178 3920 : bool SwPosition::operator==(const SwPosition &rPos) const
179 : {
180 3920 : return (nNode == rPos.nNode)
181 : // GetIndexReg may be null for FLY_AT_PARA frame anchor position
182 3618 : && (nContent.GetIdxReg() == rPos.nContent.GetIdxReg())
183 7538 : && (nContent == rPos.nContent);
184 : }
185 :
186 :
187 24152 : bool SwPosition::operator!=(const SwPosition &rPos) const
188 : {
189 24152 : return (nNode != rPos.nNode)
190 : // GetIndexReg may be null for FLY_AT_PARA frame anchor position
191 23881 : || (nContent.GetIdxReg() != rPos.nContent.GetIdxReg())
192 48033 : || (nContent != rPos.nContent);
193 : }
194 :
195 1 : SwDoc * SwPosition::GetDoc() const
196 : {
197 1 : return nNode.GetNode().GetDoc();
198 : }
199 :
200 :
201 : enum CHKSECTION { Chk_Both, Chk_One, Chk_None };
202 :
203 :
204 2135 : static CHKSECTION lcl_TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, const SwNode& rEndNd )
205 : {
206 2135 : sal_uLong nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex();
207 2135 : CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None;
208 2135 : if( nStt < nEndIdx && nEnd >= nEndIdx )
209 1952 : return( eSec == Chk_One ? Chk_Both : Chk_One );
210 183 : return eSec;
211 : }
212 :
213 :
214 162 : static sal_Bool lcl_ChkOneRange( CHKSECTION eSec, sal_Bool bChkSections,
215 : const SwNode& rBaseEnd, sal_uLong nStt, sal_uLong nEnd )
216 : {
217 162 : if( eSec != Chk_Both )
218 1 : return sal_False;
219 :
220 161 : if( !bChkSections )
221 0 : return sal_True;
222 :
223 : // search the surrounding section
224 161 : const SwNodes& rNds = rBaseEnd.GetNodes();
225 161 : const SwNode *pTmp, *pNd = rNds[ nStt ];
226 161 : if( !pNd->IsStartNode() )
227 158 : pNd = pNd->StartOfSectionNode();
228 :
229 161 : if( pNd == rNds[ nEnd ]->StartOfSectionNode() )
230 110 : return sal_True; // same StartNode, same section
231 :
232 : // already on a base node => error
233 51 : if( !pNd->StartOfSectionIndex() )
234 0 : return sal_False;
235 :
236 102 : while( ( pTmp = pNd->StartOfSectionNode())->EndOfSectionNode() !=
237 : &rBaseEnd )
238 0 : pNd = pTmp;
239 :
240 51 : sal_uLong nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex();
241 : return nSttIdx <= nStt && nStt <= nEndIdx &&
242 51 : nSttIdx <= nEnd && nEnd <= nEndIdx ? sal_True : sal_False;
243 : }
244 :
245 :
246 1955 : sal_Bool CheckNodesRange( const SwNodeIndex& rStt,
247 : const SwNodeIndex& rEnd, sal_Bool bChkSection )
248 : {
249 1955 : const SwNodes& rNds = rStt.GetNodes();
250 1955 : sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
251 1955 : CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() );
252 1955 : if( Chk_None != eSec ) return eSec == Chk_Both ? sal_True : sal_False;
253 :
254 162 : eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() );
255 162 : if( Chk_None != eSec )
256 : return lcl_ChkOneRange( eSec, bChkSection,
257 153 : rNds.GetEndOfAutotext(), nStt, nEnd );
258 :
259 9 : eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() );
260 9 : if( Chk_None != eSec )
261 : return lcl_ChkOneRange( eSec, bChkSection,
262 0 : rNds.GetEndOfPostIts(), nStt, nEnd );
263 :
264 9 : eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() );
265 9 : if( Chk_None != eSec )
266 : return lcl_ChkOneRange( eSec, bChkSection,
267 9 : rNds.GetEndOfInserts(), nStt, nEnd );
268 :
269 0 : eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() );
270 0 : if( Chk_None != eSec )
271 : return lcl_ChkOneRange( eSec, bChkSection,
272 0 : rNds.GetEndOfRedlines(), nStt, nEnd );
273 :
274 0 : return sal_False; // somewhere in between => error
275 : }
276 :
277 :
278 410 : sal_Bool GoNext(SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode )
279 : {
280 410 : if( pNd->IsCntntNode() )
281 402 : return ((SwCntntNode*)pNd)->GoNext( pIdx, nMode );
282 8 : return sal_False;
283 : }
284 :
285 :
286 1059 : sal_Bool GoPrevious( SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode )
287 : {
288 1059 : if( pNd->IsCntntNode() )
289 1059 : return ((SwCntntNode*)pNd)->GoPrevious( pIdx, nMode );
290 0 : return sal_False;
291 : }
292 :
293 :
294 1445 : SwCntntNode* GoNextNds( SwNodeIndex* pIdx, sal_Bool bChk )
295 : {
296 1445 : SwNodeIndex aIdx( *pIdx );
297 1445 : SwCntntNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
298 1445 : if( pNd )
299 : {
300 1823 : if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() &&
301 540 : !CheckNodesRange( *pIdx, aIdx, sal_True ) )
302 148 : pNd = 0;
303 : else
304 1135 : *pIdx = aIdx;
305 : }
306 1445 : return pNd;
307 : }
308 :
309 :
310 13334 : SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, sal_Bool bChk )
311 : {
312 13334 : SwNodeIndex aIdx( *pIdx );
313 13334 : SwCntntNode* pNd = aIdx.GetNodes().GoPrevious( &aIdx );
314 13334 : if( pNd )
315 : {
316 13341 : if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() &&
317 23 : !CheckNodesRange( *pIdx, aIdx, sal_True ) )
318 12 : pNd = 0;
319 : else
320 13306 : *pIdx = aIdx;
321 : }
322 13334 : return pNd;
323 : }
324 :
325 :
326 60247 : SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing )
327 : : Ring( pRing )
328 : , m_Bound1( rPos )
329 60247 : , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize
330 : , m_pPoint( &m_Bound1 )
331 : , m_pMark( m_pPoint )
332 120494 : , m_bIsInFrontOfLabel( false )
333 : {
334 60247 : }
335 :
336 9060 : SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing )
337 : : Ring( pRing )
338 : , m_Bound1( rMark )
339 : , m_Bound2( rPoint )
340 : , m_pPoint( &m_Bound2 )
341 : , m_pMark( &m_Bound1 )
342 9060 : , m_bIsInFrontOfLabel( false )
343 : {
344 9060 : }
345 :
346 80 : SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint,
347 : long nMarkOffset, long nPointOffset, SwPaM* pRing )
348 : : Ring( pRing )
349 : , m_Bound1( rMark )
350 : , m_Bound2( rPoint )
351 : , m_pPoint( &m_Bound2 )
352 : , m_pMark( &m_Bound1 )
353 80 : , m_bIsInFrontOfLabel( false )
354 : {
355 80 : if ( nMarkOffset )
356 : {
357 0 : m_pMark->nNode += nMarkOffset;
358 : }
359 80 : if ( nPointOffset )
360 : {
361 0 : m_pPoint->nNode += nPointOffset;
362 : }
363 :
364 80 : m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
365 80 : m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
366 80 : }
367 :
368 3136 : SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint,
369 : long nMarkOffset, long nPointOffset, SwPaM* pRing )
370 : : Ring( pRing )
371 : , m_Bound1( rMark )
372 : , m_Bound2( rPoint )
373 : , m_pPoint( &m_Bound2 )
374 : , m_pMark( &m_Bound1 )
375 3136 : , m_bIsInFrontOfLabel( false )
376 : {
377 3136 : if ( nMarkOffset )
378 : {
379 0 : m_pMark->nNode += nMarkOffset;
380 : }
381 3136 : if ( nPointOffset )
382 : {
383 0 : m_pPoint->nNode += nPointOffset;
384 : }
385 :
386 3136 : m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
387 3136 : m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
388 3136 : }
389 :
390 1398 : SwPaM::SwPaM( const SwNodeIndex& rMark , xub_StrLen nMarkCntnt,
391 : const SwNodeIndex& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
392 : : Ring( pRing )
393 : , m_Bound1( rMark )
394 : , m_Bound2( rPoint )
395 : , m_pPoint( &m_Bound2 )
396 : , m_pMark( &m_Bound1 )
397 1398 : , m_bIsInFrontOfLabel( false )
398 : {
399 1398 : m_pPoint->nContent.Assign( rPoint.GetNode().GetCntntNode(), nPointCntnt);
400 1398 : m_pMark ->nContent.Assign( rMark .GetNode().GetCntntNode(), nMarkCntnt );
401 1398 : }
402 :
403 7 : SwPaM::SwPaM( const SwNode& rMark , xub_StrLen nMarkCntnt,
404 : const SwNode& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
405 : : Ring( pRing )
406 : , m_Bound1( rMark )
407 : , m_Bound2( rPoint )
408 : , m_pPoint( &m_Bound2 )
409 : , m_pMark( &m_Bound1 )
410 7 : , m_bIsInFrontOfLabel( false )
411 : {
412 7 : m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
413 14 : nPointCntnt);
414 7 : m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetCntntNode(),
415 14 : nMarkCntnt );
416 7 : }
417 :
418 1465 : SwPaM::SwPaM( const SwNode& rNode, xub_StrLen nCntnt, SwPaM* pRing )
419 : : Ring( pRing )
420 : , m_Bound1( rNode )
421 1465 : , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize
422 : , m_pPoint( &m_Bound1 )
423 : , m_pMark( &m_Bound1 )
424 2930 : , m_bIsInFrontOfLabel( false )
425 : {
426 1465 : m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
427 2930 : nCntnt );
428 1465 : }
429 :
430 18822 : SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, xub_StrLen nCntnt, SwPaM* pRing )
431 : : Ring( pRing )
432 : , m_Bound1( rNodeIdx )
433 18822 : , m_Bound2( rNodeIdx.GetNode().GetNodes() ) // default initialize
434 : , m_pPoint( &m_Bound1 )
435 : , m_pMark( &m_Bound1 )
436 37644 : , m_bIsInFrontOfLabel( false )
437 : {
438 18822 : m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetCntntNode(), nCntnt );
439 18822 : }
440 :
441 95593 : SwPaM::~SwPaM() {}
442 :
443 : // @@@ semantic: no copy ctor.
444 9 : SwPaM::SwPaM( SwPaM &rPam )
445 : : Ring( &rPam )
446 : , m_Bound1( *(rPam.m_pPoint) )
447 : , m_Bound2( *(rPam.m_pMark) )
448 9 : , m_pPoint( &m_Bound1 ), m_pMark( rPam.HasMark() ? &m_Bound2 : m_pPoint )
449 18 : , m_bIsInFrontOfLabel( false )
450 : {
451 9 : }
452 :
453 : // @@@ semantic: no copy assignment for super class Ring.
454 0 : SwPaM &SwPaM::operator=( const SwPaM &rPam )
455 : {
456 0 : *m_pPoint = *( rPam.m_pPoint );
457 0 : if ( rPam.HasMark() )
458 : {
459 0 : SetMark();
460 0 : *m_pMark = *( rPam.m_pMark );
461 : }
462 : else
463 : {
464 0 : DeleteMark();
465 : }
466 0 : return *this;
467 : }
468 :
469 31202 : void SwPaM::SetMark()
470 : {
471 31202 : if (m_pPoint == &m_Bound1)
472 : {
473 31202 : m_pMark = &m_Bound2;
474 : }
475 : else
476 : {
477 0 : m_pMark = &m_Bound1;
478 : }
479 31202 : (*m_pMark) = (*m_pPoint);
480 31202 : }
481 :
482 : #ifdef DBG_UTIL
483 :
484 : void SwPaM::Exchange()
485 : {
486 : if (m_pPoint != m_pMark)
487 : {
488 : SwPosition *pTmp = m_pPoint;
489 : m_pPoint = m_pMark;
490 : m_pMark = pTmp;
491 : }
492 : }
493 : #endif
494 :
495 : /// movement of cursor
496 18308 : sal_Bool SwPaM::Move( SwMoveFn fnMove, SwGoInDoc fnGo )
497 : {
498 18308 : sal_Bool bRet = (*fnGo)( *this, fnMove );
499 :
500 18308 : m_bIsInFrontOfLabel = false;
501 :
502 18308 : return bRet;
503 : }
504 :
505 : /** make a new region
506 :
507 : Sets the first SwPaM onto the given SwPaM, or to the beginning or end of a
508 : document. SPoint stays at its position, GetMark will be changed respectively.
509 :
510 : @param fnMove Contains information if beginning or end of document.
511 : @param pOrigRg The given region.
512 :
513 : @return Newly created area.
514 : */
515 0 : SwPaM* SwPaM::MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg )
516 : {
517 : SwPaM* pPam;
518 0 : if( pOrigRg == 0 )
519 : {
520 0 : pPam = new SwPaM( *m_pPoint );
521 0 : pPam->SetMark(); // set beginning
522 0 : pPam->Move( fnMove, fnGoSection); // to beginning or end of a node
523 :
524 : // set SPoint onto its old position; set GetMark to the "end"
525 0 : pPam->Exchange();
526 : }
527 : else
528 : {
529 0 : pPam = new SwPaM( *(SwPaM*)pOrigRg ); // given search area
530 : // make sure that SPoint is on the "real" start position
531 : // FORWARD: SPoint always smaller than GetMark
532 : // BACKWARD: SPoint always bigger than GetMark
533 0 : if( (pPam->GetMark()->*fnMove->fnCmpOp)( *pPam->GetPoint() ) )
534 0 : pPam->Exchange();
535 : }
536 0 : return pPam;
537 : }
538 :
539 670 : SwPaM & SwPaM::Normalize(sal_Bool bPointFirst)
540 : {
541 670 : if (HasMark())
542 1040 : if ( ( bPointFirst && *m_pPoint > *m_pMark) ||
543 520 : (!bPointFirst && *m_pPoint < *m_pMark) )
544 : {
545 331 : Exchange();
546 : }
547 :
548 670 : return *this;
549 : }
550 :
551 : /// return page number at cursor (for reader and page bound frames)
552 7 : sal_uInt16 SwPaM::GetPageNum( sal_Bool bAtPoint, const Point* pLayPos )
553 : {
554 : const SwCntntFrm* pCFrm;
555 : const SwPageFrm *pPg;
556 : const SwCntntNode *pNd ;
557 7 : const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark;
558 :
559 21 : if( 0 != ( pNd = pPos->nNode.GetNode().GetCntntNode() ) &&
560 7 : 0 != ( pCFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), pLayPos, pPos, sal_False )) &&
561 7 : 0 != ( pPg = pCFrm->FindPageFrm() ))
562 7 : return pPg->GetPhyPageNum();
563 0 : return 0;
564 : }
565 :
566 : // Formular view - See also SwCrsrShell::IsCrsrReadonly()
567 0 : static const SwFrm* lcl_FindEditInReadonlyFrm( const SwFrm& rFrm )
568 : {
569 0 : const SwFrm* pRet = 0;
570 :
571 : const SwFlyFrm* pFly;
572 : const SwSectionFrm* pSectionFrm;
573 :
574 0 : if( rFrm.IsInFly() &&
575 0 : (pFly = rFrm.FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
576 0 : pFly->Lower() &&
577 0 : !pFly->Lower()->IsNoTxtFrm() )
578 : {
579 0 : pRet = pFly;
580 : }
581 0 : else if ( rFrm.IsInSct() &&
582 0 : 0 != ( pSectionFrm = rFrm.FindSctFrm() )->GetSection() &&
583 0 : pSectionFrm->GetSection()->IsEditInReadonlyFlag() )
584 : {
585 0 : pRet = pSectionFrm;
586 : }
587 :
588 0 : return pRet;
589 : }
590 :
591 : /// is in protected section or selection surrounds something protected
592 558 : sal_Bool SwPaM::HasReadonlySel( bool bFormView ) const
593 : {
594 558 : sal_Bool bRet = sal_False;
595 558 : Point aTmpPt;
596 : const SwCntntNode *pNd;
597 : const SwCntntFrm *pFrm;
598 :
599 558 : if( 0 != ( pNd = GetPoint()->nNode.GetNode().GetCntntNode() ))
600 558 : pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, GetPoint(), sal_False );
601 : else
602 0 : pFrm = 0;
603 :
604 : // Will be set if point/mark are inside edit-in-readonly environment
605 558 : const SwFrm* pSttEIRFrm = 0;
606 558 : const SwFrm* pEndEIRFrm = 0;
607 :
608 558 : if( pFrm && ( pFrm->IsProtected() ||
609 0 : ( bFormView && 0 == ( pSttEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
610 0 : bRet = sal_True;
611 558 : else if( pNd )
612 : {
613 558 : const SwSectionNode* pSNd = pNd->GetSectionNode();
614 558 : if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
615 0 : (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
616 0 : bRet = sal_True;
617 : }
618 :
619 558 : if( !bRet && HasMark() && GetPoint()->nNode != GetMark()->nNode )
620 : {
621 0 : if( 0 != ( pNd = GetMark()->nNode.GetNode().GetCntntNode() ))
622 0 : pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, GetMark(), sal_False );
623 : else
624 0 : pFrm = 0;
625 :
626 0 : if( pFrm && ( pFrm->IsProtected() ||
627 0 : ( bFormView && 0 == ( pEndEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
628 0 : bRet = sal_True;
629 0 : else if( pNd )
630 : {
631 0 : const SwSectionNode* pSNd = pNd->GetSectionNode();
632 0 : if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
633 0 : (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
634 0 : bRet = sal_True;
635 : }
636 :
637 0 : if ( !bRet && bFormView )
638 : {
639 : // Check if start and end frame are inside the _same_
640 : // edit-in-readonly-environment. Otherwise we better return 'true'
641 0 : if ( pSttEIRFrm != pEndEIRFrm )
642 0 : bRet = sal_True;
643 : }
644 :
645 : // protected section in selection
646 0 : if( !bRet )
647 : {
648 0 : sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
649 0 : nEndIdx = GetPoint()->nNode.GetIndex();
650 0 : if( nEndIdx <= nSttIdx )
651 : {
652 0 : sal_uLong nTmp = nSttIdx;
653 0 : nSttIdx = nEndIdx;
654 0 : nEndIdx = nTmp;
655 : }
656 :
657 : // If a protected section should be between nodes, then the
658 : // selection needs to contain already x nodes.
659 : // (TxtNd, SectNd, TxtNd, EndNd, TxtNd )
660 0 : if( nSttIdx + 3 < nEndIdx )
661 : {
662 0 : const SwSectionFmts& rFmts = GetDoc()->GetSections();
663 0 : for( sal_uInt16 n = rFmts.size(); n; )
664 : {
665 0 : const SwSectionFmt* pFmt = rFmts[ --n ];
666 0 : if( pFmt->GetProtect().IsCntntProtected() )
667 : {
668 0 : const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False);
669 : OSL_ENSURE( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
670 0 : sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex();
671 0 : if( nSttIdx <= nIdx && nEndIdx >= nIdx &&
672 0 : rCntnt.GetCntntIdx()->GetNode().GetNodes().IsDocNodes() )
673 : {
674 0 : bRet = sal_True;
675 0 : break;
676 : }
677 : }
678 : }
679 : }
680 : }
681 : }
682 : //FIXME FieldBk
683 : // TODO: Form Protection when Enhanced Fields are enabled
684 558 : const SwDoc *pDoc = GetDoc();
685 558 : sw::mark::IMark* pA = NULL;
686 558 : sw::mark::IMark* pB = NULL;
687 558 : bool bUnhandledMark = false;
688 558 : if ( pDoc )
689 : {
690 558 : const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( );
691 558 : pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
692 558 : pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA;
693 :
694 558 : sw::mark::IFieldmark* pFieldmark = pMarksAccess->getFieldmarkFor( *GetPoint() );
695 558 : if ( pFieldmark )
696 2 : bUnhandledMark = pFieldmark->GetFieldname( ) == ODF_UNHANDLED;
697 : }
698 :
699 558 : if (!bRet)
700 : {
701 : // Unhandled fieldmarks case shouldn't be edited manually to avoid breaking anything
702 558 : if ( ( pA == pB ) && bUnhandledMark )
703 0 : bRet = sal_True;
704 : else
705 : {
706 : // Form protection case
707 558 : bool bAtStartA = pA != NULL && pA->GetMarkStart() == *GetPoint();
708 558 : bool bAtStartB = pB != NULL && pB->GetMarkStart() == *GetMark();
709 558 : bRet = ( pA != pB ) || bAtStartA || bAtStartB;
710 558 : bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
711 558 : if ( bProtectForm )
712 0 : bRet |= ( pA == NULL || pB == NULL );
713 : }
714 : }
715 : else
716 : {
717 0 : bRet = !( pA == pB && pA != NULL );
718 : }
719 558 : return bRet;
720 : }
721 :
722 : /// This function returns the next node in direction of search. If there is no
723 : /// left or the next is out of the area, then a null-pointer is returned.
724 : /// @param rbFirst If <true> than first time request. If so than the position of
725 : /// the PaM must not be changed!
726 0 : SwCntntNode* GetNode( SwPaM & rPam, sal_Bool& rbFirst, SwMoveFn fnMove,
727 : sal_Bool bInReadOnly )
728 : {
729 0 : SwCntntNode * pNd = 0;
730 : SwCntntFrm* pFrm;
731 0 : if( ((*rPam.GetPoint()).*fnMove->fnCmpOp)( *rPam.GetMark() ) ||
732 0 : ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
733 : {
734 0 : if( rbFirst )
735 : {
736 0 : rbFirst = sal_False;
737 0 : pNd = rPam.GetCntntNode();
738 0 : if( pNd )
739 : {
740 0 : if(
741 : (
742 0 : 0 == ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout() ) ) ||
743 0 : ( !bInReadOnly && pFrm->IsProtected() ) ||
744 0 : (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow())
745 : ) ||
746 0 : ( !bInReadOnly && pNd->FindSectionNode() &&
747 0 : pNd->FindSectionNode()->GetSection().IsProtect()
748 : )
749 : )
750 : {
751 0 : pNd = 0;
752 : }
753 : }
754 : }
755 :
756 0 : if( !pNd ) // is the cursor not on a CntntNode?
757 : {
758 0 : SwPosition aPos( *rPam.GetPoint() );
759 0 : sal_Bool bSrchForward = fnMove == fnMoveForward;
760 0 : SwNodes& rNodes = aPos.nNode.GetNodes();
761 :
762 : // go to next/previous CntntNode
763 0 : while( sal_True )
764 : {
765 : pNd = bSrchForward
766 0 : ? rNodes.GoNextSection( &aPos.nNode, sal_True, !bInReadOnly )
767 0 : : rNodes.GoPrevSection( &aPos.nNode, sal_True, !bInReadOnly );
768 0 : if( pNd )
769 : {
770 0 : aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd ));
771 : // is the position still in the area
772 0 : if( (aPos.*fnMove->fnCmpOp)( *rPam.GetMark() ) )
773 : {
774 : // only in AutoTextSection can be nodes that are hidden
775 0 : if( 0 == ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout() ) ) ||
776 0 : ( !bInReadOnly && pFrm->IsProtected() ) ||
777 0 : ( pFrm->IsTxtFrm() &&
778 0 : ((SwTxtFrm*)pFrm)->IsHiddenNow() ) )
779 : {
780 0 : pNd = 0;
781 0 : continue;
782 : }
783 0 : *(SwPosition*)rPam.GetPoint() = aPos;
784 : }
785 : else
786 0 : pNd = 0; // no valid node
787 0 : break;
788 : }
789 0 : break;
790 0 : }
791 : }
792 : }
793 0 : return pNd;
794 : }
795 :
796 :
797 3296 : void GoStartDoc( SwPosition * pPos )
798 : {
799 3296 : SwNodes& rNodes = pPos->nNode.GetNodes();
800 3296 : pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
801 : // we always need to find a ContentNode!
802 3296 : SwCntntNode* pCNd = rNodes.GoNext( &pPos->nNode );
803 3296 : if( pCNd )
804 3296 : pCNd->MakeStartIndex( &pPos->nContent );
805 3296 : }
806 :
807 :
808 1989 : void GoEndDoc( SwPosition * pPos )
809 : {
810 1989 : SwNodes& rNodes = pPos->nNode.GetNodes();
811 1989 : pPos->nNode = rNodes.GetEndOfContent();
812 1989 : SwCntntNode* pCNd = GoPreviousNds( &pPos->nNode, sal_True );
813 1989 : if( pCNd )
814 1989 : pCNd->MakeEndIndex( &pPos->nContent );
815 1989 : }
816 :
817 :
818 0 : void GoStartSection( SwPosition * pPos )
819 : {
820 : // jump to section's beginning
821 0 : SwNodes& rNodes = pPos->nNode.GetNodes();
822 0 : sal_uInt16 nLevel = rNodes.GetSectionLevel( pPos->nNode );
823 0 : if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
824 0 : nLevel--;
825 0 : do { rNodes.GoStartOfSection( &pPos->nNode ); } while( nLevel-- );
826 :
827 : // already on a CntntNode
828 0 : pPos->nNode.GetNode().GetCntntNode()->MakeStartIndex( &pPos->nContent );
829 0 : }
830 :
831 : /// go to the end of the current base section
832 0 : void GoEndSection( SwPosition * pPos )
833 : {
834 : // jump to section's beginning/end
835 0 : SwNodes& rNodes = pPos->nNode.GetNodes();
836 0 : sal_uInt16 nLevel = rNodes.GetSectionLevel( pPos->nNode );
837 0 : if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
838 0 : nLevel--;
839 0 : do { rNodes.GoEndOfSection( &pPos->nNode ); } while( nLevel-- );
840 :
841 : // now on a EndNode, thus to the previous CntntNode
842 0 : if( GoPreviousNds( &pPos->nNode, sal_True ) )
843 0 : pPos->nNode.GetNode().GetCntntNode()->MakeEndIndex( &pPos->nContent );
844 0 : }
845 :
846 :
847 :
848 5285 : sal_Bool GoInDoc( SwPaM & rPam, SwMoveFn fnMove )
849 : {
850 5285 : (*fnMove->fnDoc)( rPam.GetPoint() );
851 5285 : return sal_True;
852 : }
853 :
854 :
855 0 : sal_Bool GoInSection( SwPaM & rPam, SwMoveFn fnMove )
856 : {
857 0 : (*fnMove->fnSections)( (SwPosition*)rPam.GetPoint() );
858 0 : return sal_True;
859 : }
860 :
861 :
862 12618 : sal_Bool GoInNode( SwPaM & rPam, SwMoveFn fnMove )
863 : {
864 12618 : SwCntntNode *pNd = (*fnMove->fnNds)( &rPam.GetPoint()->nNode, sal_True );
865 12618 : if( pNd )
866 12280 : rPam.GetPoint()->nContent.Assign( pNd,
867 24560 : ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
868 12618 : return 0 != pNd;
869 : }
870 :
871 :
872 1469 : sal_Bool GoInCntnt( SwPaM & rPam, SwMoveFn fnMove )
873 : {
874 2938 : if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
875 2938 : &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS ))
876 405 : return sal_True;
877 1064 : return GoInNode( rPam, fnMove );
878 : }
879 :
880 0 : sal_Bool GoInCntntCells( SwPaM & rPam, SwMoveFn fnMove )
881 : {
882 0 : if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
883 0 : &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS ))
884 0 : return sal_True;
885 0 : return GoInNode( rPam, fnMove );
886 : }
887 :
888 0 : sal_Bool GoInCntntSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
889 : {
890 0 : if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
891 0 : &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) )
892 0 : return sal_True;
893 0 : return GoInNode( rPam, fnMove );
894 : }
895 :
896 0 : sal_Bool GoInCntntCellsSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
897 : {
898 0 : if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
899 0 : &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) )
900 0 : return sal_True;
901 0 : return GoInNode( rPam, fnMove );
902 : }
903 :
904 :
905 :
906 :
907 :
908 0 : sal_Bool GoPrevPara( SwPaM & rPam, SwPosPara aPosPara )
909 : {
910 0 : if( rPam.Move( fnMoveBackward, fnGoNode ) )
911 : {
912 : // always on a CntntNode
913 0 : SwPosition& rPos = *rPam.GetPoint();
914 0 : SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
915 : rPos.nContent.Assign( pNd,
916 0 : ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
917 0 : return sal_True;
918 : }
919 0 : return sal_False;
920 : }
921 :
922 :
923 1022 : sal_Bool GoCurrPara( SwPaM & rPam, SwPosPara aPosPara )
924 : {
925 1022 : SwPosition& rPos = *rPam.GetPoint();
926 1022 : SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
927 1022 : if( pNd )
928 : {
929 1022 : xub_StrLen nOld = rPos.nContent.GetIndex(),
930 1022 : nNew = aPosPara == fnMoveForward ? 0 : pNd->Len();
931 : // if already at beginning/end then to the next/previous
932 1022 : if( nOld != nNew )
933 : {
934 1022 : rPos.nContent.Assign( pNd, nNew );
935 1022 : return sal_True;
936 : }
937 : }
938 : // move node to next/previous CntntNode
939 0 : if( ( aPosPara==fnParaStart && 0 != ( pNd =
940 0 : GoPreviousNds( &rPos.nNode, sal_True ))) ||
941 : ( aPosPara==fnParaEnd && 0 != ( pNd =
942 0 : GoNextNds( &rPos.nNode, sal_True ))) )
943 : {
944 : rPos.nContent.Assign( pNd,
945 0 : ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ));
946 0 : return sal_True;
947 : }
948 0 : return sal_False;
949 : }
950 :
951 :
952 862 : sal_Bool GoNextPara( SwPaM & rPam, SwPosPara aPosPara )
953 : {
954 862 : if( rPam.Move( fnMoveForward, fnGoNode ) )
955 : {
956 : // always on a CntntNode
957 617 : SwPosition& rPos = *rPam.GetPoint();
958 617 : SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
959 : rPos.nContent.Assign( pNd,
960 617 : ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
961 617 : return sal_True;
962 : }
963 245 : return sal_False;
964 : }
965 :
966 :
967 :
968 173 : sal_Bool GoCurrSection( SwPaM & rPam, SwMoveFn fnMove )
969 : {
970 173 : SwPosition& rPos = *rPam.GetPoint();
971 173 : SwPosition aSavePos( rPos ); // position for comparison
972 173 : SwNodes& rNds = aSavePos.nNode.GetNodes();
973 173 : (rNds.*fnMove->fnSection)( &rPos.nNode );
974 : SwCntntNode *pNd;
975 345 : if( 0 == ( pNd = rPos.nNode.GetNode().GetCntntNode()) &&
976 172 : 0 == ( pNd = (*fnMove->fnNds)( &rPos.nNode, sal_True )) )
977 : {
978 0 : rPos = aSavePos; // do not change cursor
979 0 : return sal_False;
980 : }
981 :
982 : rPos.nContent.Assign( pNd,
983 173 : ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
984 173 : return aSavePos != rPos;
985 : }
986 :
987 :
988 0 : sal_Bool GoNextSection( SwPaM & rPam, SwMoveFn fnMove )
989 : {
990 0 : SwPosition& rPos = *rPam.GetPoint();
991 0 : SwPosition aSavePos( rPos ); // position for comparison
992 0 : SwNodes& rNds = aSavePos.nNode.GetNodes();
993 0 : rNds.GoEndOfSection( &rPos.nNode );
994 :
995 : // no other CntntNode existent?
996 0 : if( !GoInCntnt( rPam, fnMoveForward ) )
997 : {
998 0 : rPos = aSavePos; // do not change cursor
999 0 : return sal_False;
1000 : }
1001 0 : (rNds.*fnMove->fnSection)( &rPos.nNode );
1002 0 : SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
1003 : rPos.nContent.Assign( pNd,
1004 0 : ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
1005 0 : return sal_True;
1006 : }
1007 :
1008 :
1009 0 : sal_Bool GoPrevSection( SwPaM & rPam, SwMoveFn fnMove )
1010 : {
1011 0 : SwPosition& rPos = *rPam.GetPoint();
1012 0 : SwPosition aSavePos( rPos ); // position for comparison
1013 0 : SwNodes& rNds = aSavePos.nNode.GetNodes();
1014 0 : rNds.GoStartOfSection( &rPos.nNode );
1015 :
1016 : // no further CntntNode existent?
1017 0 : if( !GoInCntnt( rPam, fnMoveBackward ))
1018 : {
1019 0 : rPos = aSavePos; // do not change cursor
1020 0 : return sal_False;
1021 : }
1022 0 : (rNds.*fnMove->fnSection)( &rPos.nNode );
1023 0 : SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
1024 : rPos.nContent.Assign( pNd,
1025 0 : ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ));
1026 0 : return sal_True;
1027 : }
1028 :
1029 0 : String SwPaM::GetTxt() const
1030 : {
1031 0 : String aResult;
1032 :
1033 0 : SwNodeIndex aNodeIndex = Start()->nNode;
1034 :
1035 : // The first node can be already the end node.
1036 : // A first end node must be handled, too. Therefore do-while and no
1037 : // incrementing of aNodeIndex in the first pass.
1038 0 : bool bFirst = true;
1039 0 : do
1040 : {
1041 0 : if (! bFirst)
1042 : {
1043 0 : ++aNodeIndex;
1044 : }
1045 :
1046 0 : bFirst = false;
1047 :
1048 0 : SwTxtNode * pTxtNode = aNodeIndex.GetNode().GetTxtNode();
1049 :
1050 0 : if (pTxtNode != NULL)
1051 : {
1052 0 : const String & aTmpStr = pTxtNode->GetTxt();
1053 :
1054 0 : if (aNodeIndex == Start()->nNode)
1055 : {
1056 : xub_StrLen nEnd;
1057 0 : if (End()->nNode == aNodeIndex)
1058 0 : nEnd = End()->nContent.GetIndex();
1059 : else
1060 0 : nEnd = aTmpStr.Len();
1061 :
1062 0 : aResult += aTmpStr.Copy(Start()->nContent.GetIndex(),
1063 0 : nEnd - Start()->nContent.GetIndex()) ;
1064 : }
1065 0 : else if (aNodeIndex == End()->nNode)
1066 0 : aResult += aTmpStr.Copy(0, End()->nContent.GetIndex());
1067 : else
1068 0 : aResult += aTmpStr;
1069 : }
1070 : }
1071 0 : while (aNodeIndex != End()->nNode);
1072 :
1073 0 : return aResult;
1074 : }
1075 :
1076 0 : void SwPaM::InvalidatePaM()
1077 : {
1078 0 : const SwNode *_pNd=this->GetNode();
1079 0 : const SwTxtNode *_pTxtNd=(_pNd!=NULL?_pNd->GetTxtNode():NULL);
1080 0 : if (_pTxtNd!=NULL)
1081 : {
1082 : // pretent that the PaM marks inserted text to recalc the portion...
1083 0 : SwInsTxt aHint( Start()->nContent.GetIndex(),
1084 0 : End()->nContent.GetIndex() - Start()->nContent.GetIndex() + 1 );
1085 0 : SwModify *_pModify=(SwModify*)_pTxtNd;
1086 0 : _pModify->ModifyNotification( 0, &aHint);
1087 : }
1088 0 : }
1089 :
1090 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|