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 .
21 #include <fmtanchr.hxx>
22 #include <fmtcntnt.hxx>
24 #include <acorrect.hxx> // AutoCorrect
25 #include <UndoManager.hxx>
28 #include <doctxm.hxx> // when moving: correct indexes
30 #include <mdiexp.hxx> // status bar
31 #include <mvsave.hxx> // structures to save when moving/deleting
32 #include <redline.hxx>
33 #include <rootfrm.hxx> // for UpdateFtn
34 #include <splargs.hxx> // for Spell
36 #include <UndoSplitMove.hxx>
37 #include <UndoRedline.hxx>
38 #include <UndoOverwrite.hxx>
39 #include <UndoInsert.hxx>
40 #include <UndoDelete.hxx>
41 #include <breakit.hxx>
42 #include <vcl/msgbox.hxx>
43 #include "comcore.hrc"
46 #include <docufld.hxx>
47 #include <unoflatpara.hxx>
48 #include <SwGrammarMarkUp.hxx>
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::linguistic2
;
54 using namespace ::com::sun::star::i18n
;
59 sal_uInt32 nStt
, nEnd
;
60 xub_StrLen nSttCnt
, nEndCnt
;
62 _SaveRedline( SwRedline
* pR
, const SwNodeIndex
& rSttIdx
)
65 const SwPosition
* pStt
= pR
->Start(),
66 * pEnd
= pR
->GetMark() == pStt
? pR
->GetPoint() : pR
->GetMark();
67 sal_uInt32 nSttIdx
= rSttIdx
.GetIndex();
68 nStt
= pStt
->nNode
.GetIndex() - nSttIdx
;
69 nSttCnt
= pStt
->nContent
.GetIndex();
72 nEnd
= pEnd
->nNode
.GetIndex() - nSttIdx
;
73 nEndCnt
= pEnd
->nContent
.GetIndex();
76 pRedl
->GetPoint()->nNode
= 0;
77 pRedl
->GetPoint()->nContent
.Assign( 0, 0 );
78 pRedl
->GetMark()->nNode
= 0;
79 pRedl
->GetMark()->nContent
.Assign( 0, 0 );
82 _SaveRedline( SwRedline
* pR
, const SwPosition
& rPos
)
85 const SwPosition
* pStt
= pR
->Start(),
86 * pEnd
= pR
->GetMark() == pStt
? pR
->GetPoint() : pR
->GetMark();
87 sal_uInt32 nSttIdx
= rPos
.nNode
.GetIndex();
88 nStt
= pStt
->nNode
.GetIndex() - nSttIdx
;
89 nSttCnt
= pStt
->nContent
.GetIndex();
91 nSttCnt
= nSttCnt
- rPos
.nContent
.GetIndex();
94 nEnd
= pEnd
->nNode
.GetIndex() - nSttIdx
;
95 nEndCnt
= pEnd
->nContent
.GetIndex();
97 nEndCnt
= nEndCnt
- rPos
.nContent
.GetIndex();
100 pRedl
->GetPoint()->nNode
= 0;
101 pRedl
->GetPoint()->nContent
.Assign( 0, 0 );
102 pRedl
->GetMark()->nNode
= 0;
103 pRedl
->GetMark()->nContent
.Assign( 0, 0 );
106 void SetPos( sal_uInt32 nInsPos
)
108 pRedl
->GetPoint()->nNode
= nInsPos
+ nStt
;
109 pRedl
->GetPoint()->nContent
.Assign( pRedl
->GetCntntNode(), nSttCnt
);
110 if( pRedl
->HasMark() )
112 pRedl
->GetMark()->nNode
= nInsPos
+ nEnd
;
113 pRedl
->GetMark()->nContent
.Assign( pRedl
->GetCntntNode(sal_False
), nEndCnt
);
117 void SetPos( const SwPosition
& aPos
)
119 pRedl
->GetPoint()->nNode
= aPos
.nNode
.GetIndex() + nStt
;
120 pRedl
->GetPoint()->nContent
.Assign( pRedl
->GetCntntNode(), nSttCnt
+ ( nStt
== 0 ? aPos
.nContent
.GetIndex() : 0 ) );
121 if( pRedl
->HasMark() )
123 pRedl
->GetMark()->nNode
= aPos
.nNode
.GetIndex() + nEnd
;
124 pRedl
->GetMark()->nContent
.Assign( pRedl
->GetCntntNode(sal_False
), nEndCnt
+ ( nEnd
== 0 ? aPos
.nContent
.GetIndex() : 0 ) );
129 typedef boost::ptr_vector
< _SaveRedline
> _SaveRedlines
;
131 static bool lcl_MayOverwrite( const SwTxtNode
*pNode
, const xub_StrLen nPos
)
133 sal_Unicode
const cChr
= pNode
->GetTxt()[nPos
];
136 case CH_TXTATR_BREAKWORD
:
137 case CH_TXTATR_INWORD
:
138 return !pNode
->GetTxtAttrForCharAt(nPos
);// how could there be none?
139 case CH_TXT_ATR_FIELDSTART
:
140 case CH_TXT_ATR_FIELDEND
:
141 case CH_TXT_ATR_FORMELEMENT
:
148 static void lcl_SkipAttr( const SwTxtNode
*pNode
, SwIndex
&rIdx
, xub_StrLen
&rStart
)
150 if( !lcl_MayOverwrite( pNode
, rStart
) )
152 // skip all special attributes
155 rStart
= rIdx
.GetIndex();
156 } while (rStart
< pNode
->GetTxt().getLength()
157 && !lcl_MayOverwrite(pNode
, rStart
) );
161 void _RestFlyInRange( _SaveFlyArr
& rArr
, const SwNodeIndex
& rSttIdx
,
162 const SwNodeIndex
* pInsertPos
)
164 SwPosition
aPos( rSttIdx
);
165 for( size_t n
= 0; n
< rArr
.size(); ++n
)
168 _SaveFly
& rSave
= rArr
[n
];
169 SwFrmFmt
* pFmt
= rSave
.pFrmFmt
;
171 if( rSave
.bInsertPosition
)
173 if( pInsertPos
!= NULL
)
174 aPos
.nNode
= *pInsertPos
;
176 aPos
.nNode
= rSttIdx
.GetIndex();
179 aPos
.nNode
= rSttIdx
.GetIndex() + rSave
.nNdDiff
;
181 aPos
.nContent
.Assign( 0, 0 );
182 SwFmtAnchor
aAnchor( pFmt
->GetAnchor() );
183 aAnchor
.SetAnchor( &aPos
);
184 pFmt
->GetDoc()->GetSpzFrmFmts()->push_back( pFmt
);
185 pFmt
->SetFmtAttr( aAnchor
);
186 SwCntntNode
* pCNd
= aPos
.nNode
.GetNode().GetCntntNode();
187 if( pCNd
&& pCNd
->getLayoutFrm( pFmt
->GetDoc()->GetCurrentLayout(), 0, 0, sal_False
) )
192 void _SaveFlyInRange( const SwNodeRange
& rRg
, _SaveFlyArr
& rArr
)
194 SwFrmFmts
& rFmts
= *rRg
.aStart
.GetNode().GetDoc()->GetSpzFrmFmts();
195 for( sal_uInt16 n
= 0; n
< rFmts
.size(); ++n
)
197 SwFrmFmt
*const pFmt
= static_cast<SwFrmFmt
*>(rFmts
[n
]);
198 SwFmtAnchor
const*const pAnchor
= &pFmt
->GetAnchor();
199 SwPosition
const*const pAPos
= pAnchor
->GetCntntAnchor();
201 ((FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
202 (FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
203 rRg
.aStart
<= pAPos
->nNode
&& pAPos
->nNode
< rRg
.aEnd
)
205 _SaveFly
aSave( pAPos
->nNode
.GetIndex() - rRg
.aStart
.GetIndex(),
207 rArr
.push_back( aSave
);
209 rFmts
.erase( rFmts
.begin() + n
-- );
214 void _SaveFlyInRange( const SwPaM
& rPam
, const SwNodeIndex
& rInsPos
,
215 _SaveFlyArr
& rArr
, bool bMoveAllFlys
)
217 SwFrmFmts
& rFmts
= *rPam
.GetPoint()->nNode
.GetNode().GetDoc()->GetSpzFrmFmts();
219 const SwFmtAnchor
* pAnchor
;
221 const SwPosition
* pPos
= rPam
.Start();
222 const SwNodeIndex
& rSttNdIdx
= pPos
->nNode
;
223 short nSttOff
= (!bMoveAllFlys
&& rSttNdIdx
.GetNode().IsCntntNode() &&
224 pPos
->nContent
.GetIndex()) ? 1 : 0;
226 pPos
= rPam
.GetPoint() == pPos
? rPam
.GetMark() : rPam
.GetPoint();
227 const SwNodeIndex
& rEndNdIdx
= pPos
->nNode
;
228 short nOff
= ( bMoveAllFlys
|| ( rEndNdIdx
.GetNode().IsCntntNode() &&
229 pPos
->nContent
== rEndNdIdx
.GetNode().GetCntntNode()->Len() ))
232 const SwNodeIndex
* pCntntIdx
;
234 for( sal_uInt16 n
= 0; n
< rFmts
.size(); ++n
)
236 bool bInsPos
= false;
237 pFmt
= (SwFrmFmt
*)rFmts
[n
];
238 pAnchor
= &pFmt
->GetAnchor();
239 const SwPosition
* pAPos
= pAnchor
->GetCntntAnchor();
241 ((FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
242 (FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
243 // do not move if the InsPos is in the CntntArea of the Fly
244 ( 0 == ( pCntntIdx
= pFmt
->GetCntnt().GetCntntIdx() ) ||
245 !( *pCntntIdx
< rInsPos
&&
246 rInsPos
< pCntntIdx
->GetNode().EndOfSectionIndex() )) )
248 if( !bMoveAllFlys
&& rEndNdIdx
== pAPos
->nNode
)
250 // Do not touch Anchor, if only a part of the EndNode
251 // or the whole EndNode is identical with the SttNode
252 if( rSttNdIdx
!= pAPos
->nNode
)
254 // Only attach an anchor to the beginning or end
255 SwPosition
aPos( rSttNdIdx
);
256 SwFmtAnchor
aAnchor( *pAnchor
);
257 aAnchor
.SetAnchor( &aPos
);
258 pFmt
->SetFmtAttr( aAnchor
);
261 else if( ( rSttNdIdx
.GetIndex() + nSttOff
<= pAPos
->nNode
.GetIndex()
262 && pAPos
->nNode
.GetIndex() <= rEndNdIdx
.GetIndex() - nOff
) ||
263 0 != ( bInsPos
= rInsPos
== pAPos
->nNode
))
266 _SaveFly
aSave( pAPos
->nNode
.GetIndex() - rSttNdIdx
.GetIndex(),
268 rArr
.push_back( aSave
);
270 rFmts
.erase( rFmts
.begin() + n
-- );
276 /// Delete and move all Flys at the paragraph, that are within the selection.
277 /// If there is a Fly at the SPoint, it is moved onto the Mark.
278 void DelFlyInRange( const SwNodeIndex
& rMkNdIdx
,
279 const SwNodeIndex
& rPtNdIdx
)
281 const bool bDelFwrd
= rMkNdIdx
.GetIndex() <= rPtNdIdx
.GetIndex();
283 SwDoc
* pDoc
= rMkNdIdx
.GetNode().GetDoc();
284 SwFrmFmts
& rTbl
= *pDoc
->GetSpzFrmFmts();
285 for ( sal_uInt16 i
= rTbl
.size(); i
; )
287 SwFrmFmt
*pFmt
= rTbl
[--i
];
288 const SwFmtAnchor
&rAnch
= pFmt
->GetAnchor();
289 SwPosition
const*const pAPos
= rAnch
.GetCntntAnchor();
291 ((rAnch
.GetAnchorId() == FLY_AT_PARA
) ||
292 (rAnch
.GetAnchorId() == FLY_AT_CHAR
)) &&
294 ? rMkNdIdx
< pAPos
->nNode
&& pAPos
->nNode
<= rPtNdIdx
295 : rPtNdIdx
<= pAPos
->nNode
&& pAPos
->nNode
< rMkNdIdx
))
297 // Only move the Anchor??
298 if( rPtNdIdx
== pAPos
->nNode
)
300 SwFmtAnchor
aAnch( pFmt
->GetAnchor() );
301 SwPosition
aPos( rMkNdIdx
);
302 aAnch
.SetAnchor( &aPos
);
303 pFmt
->SetFmtAttr( aAnch
);
307 // If the Fly is deleted, all Flys in it's content have to be deleted too.
308 const SwFmtCntnt
&rCntnt
= pFmt
->GetCntnt();
309 if( rCntnt
.GetCntntIdx() )
311 DelFlyInRange( *rCntnt
.GetCntntIdx(),
312 SwNodeIndex( *rCntnt
.GetCntntIdx()->
313 GetNode().EndOfSectionNode() ));
314 // Position could have been moved!
315 if( i
> rTbl
.size() )
317 else if( pFmt
!= rTbl
[i
] )
318 i
= rTbl
.GetPos( pFmt
);
321 pDoc
->DelLayoutFmt( pFmt
);
323 // DelLayoutFmt can also trigger the deletion of objects.
324 if( i
> rTbl
.size() )
331 static bool lcl_SaveFtn( const SwNodeIndex
& rSttNd
, const SwNodeIndex
& rEndNd
,
332 const SwNodeIndex
& rInsPos
,
333 SwFtnIdxs
& rFtnArr
, SwFtnIdxs
& rSaveArr
,
334 const SwIndex
* pSttCnt
= 0, const SwIndex
* pEndCnt
= 0 )
336 bool bUpdateFtn
= sal_False
;
337 const SwNodes
& rNds
= rInsPos
.GetNodes();
338 const bool bDelFtn
= rInsPos
.GetIndex() < rNds
.GetEndOfAutotext().GetIndex() &&
339 rSttNd
.GetIndex() >= rNds
.GetEndOfAutotext().GetIndex();
340 const bool bSaveFtn
= !bDelFtn
&&
341 rInsPos
.GetIndex() >= rNds
.GetEndOfExtras().GetIndex();
342 if( !rFtnArr
.empty() )
346 rFtnArr
.SeekEntry( rSttNd
, &nPos
);
348 const SwNode
* pFtnNd
;
350 // Delete/save all that come after it
351 while( nPos
< rFtnArr
.size() && ( pFtnNd
=
352 &( pSrch
= rFtnArr
[ nPos
] )->GetTxtNode())->GetIndex()
353 <= rEndNd
.GetIndex() )
355 xub_StrLen nFtnSttIdx
= *pSrch
->GetStart();
356 if( ( pEndCnt
&& pSttCnt
)
357 ? (( &rSttNd
.GetNode() == pFtnNd
&&
358 pSttCnt
->GetIndex() > nFtnSttIdx
) ||
359 ( &rEndNd
.GetNode() == pFtnNd
&&
360 nFtnSttIdx
>= pEndCnt
->GetIndex() ))
361 : ( &rEndNd
.GetNode() == pFtnNd
))
363 ++nPos
; // continue searching
370 SwTxtNode
& rTxtNd
= (SwTxtNode
&)pSrch
->GetTxtNode();
371 SwIndex
aIdx( &rTxtNd
, nFtnSttIdx
);
372 rTxtNd
.EraseText( aIdx
, 1 );
377 rFtnArr
.erase( rFtnArr
.begin() + nPos
);
379 rSaveArr
.insert( pSrch
);
381 bUpdateFtn
= sal_True
;
385 while( nPos
-- && ( pFtnNd
= &( pSrch
= rFtnArr
[ nPos
] )->
386 GetTxtNode())->GetIndex() >= rSttNd
.GetIndex() )
388 xub_StrLen nFtnSttIdx
= *pSrch
->GetStart();
389 if( !pEndCnt
|| !pSttCnt
||
390 !( (( &rSttNd
.GetNode() == pFtnNd
&&
391 pSttCnt
->GetIndex() > nFtnSttIdx
) ||
392 ( &rEndNd
.GetNode() == pFtnNd
&&
393 nFtnSttIdx
>= pEndCnt
->GetIndex() )) ))
398 SwTxtNode
& rTxtNd
= (SwTxtNode
&)pSrch
->GetTxtNode();
399 SwIndex
aIdx( &rTxtNd
, nFtnSttIdx
);
400 rTxtNd
.EraseText( aIdx
, 1 );
405 rFtnArr
.erase( rFtnArr
.begin() + nPos
);
407 rSaveArr
.insert( pSrch
);
409 bUpdateFtn
= sal_True
;
413 // When moving from redline section into document content section, e.g.
414 // after loading a document with (delete-)redlines, the footnote array
415 // has to be adjusted... (#i70572)
418 SwNodeIndex
aIdx( rSttNd
);
419 while( aIdx
< rEndNd
) // Check the moved section
421 SwNode
* pNode
= &aIdx
.GetNode();
422 if( pNode
->IsTxtNode() ) // Looking for text nodes...
425 static_cast<SwTxtNode
*>(pNode
)->GetpSwpHints();
426 if( pHints
&& pHints
->HasFtn() ) //...with footnotes
428 bUpdateFtn
= sal_True
; // Heureka
429 sal_uInt16 nCount
= pHints
->Count();
430 for( sal_uInt16 i
= 0; i
< nCount
; ++i
)
432 SwTxtAttr
*pAttr
= pHints
->GetTextHint( i
);
433 if ( pAttr
->Which() == RES_TXTATR_FTN
)
435 rSaveArr
.insert( static_cast<SwTxtFtn
*>(pAttr
) );
446 static void lcl_SaveRedlines( const SwPaM
& aPam
, _SaveRedlines
& rArr
)
448 SwDoc
* pDoc
= aPam
.GetNode()->GetDoc();
450 const SwPosition
* pStart
= aPam
.Start();
451 const SwPosition
* pEnd
= aPam
.End();
453 // get first relevant redline
454 sal_uInt16 nCurrentRedline
;
455 pDoc
->GetRedline( *pStart
, &nCurrentRedline
);
456 if( nCurrentRedline
> 0)
459 // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
460 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
461 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
463 // iterate over relevant redlines and decide for each whether it should
464 // be saved, or split + saved
465 SwRedlineTbl
& rRedlineTable
= const_cast<SwRedlineTbl
&>( pDoc
->GetRedlineTbl() );
466 for( ; nCurrentRedline
< rRedlineTable
.size(); nCurrentRedline
++ )
468 SwRedline
* pCurrent
= rRedlineTable
[ nCurrentRedline
];
469 SwComparePosition eCompare
=
470 ComparePosition( *pCurrent
->Start(), *pCurrent
->End(),
473 // we must save this redline if it overlaps aPam
474 // (we may have to split it, too)
475 if( eCompare
== POS_OVERLAP_BEHIND
||
476 eCompare
== POS_OVERLAP_BEFORE
||
477 eCompare
== POS_OUTSIDE
||
478 eCompare
== POS_INSIDE
||
479 eCompare
== POS_EQUAL
)
481 rRedlineTable
.Remove( nCurrentRedline
-- );
483 // split beginning, if necessary
484 if( eCompare
== POS_OVERLAP_BEFORE
||
485 eCompare
== POS_OUTSIDE
)
488 SwRedline
* pNewRedline
= new SwRedline( *pCurrent
);
489 *pNewRedline
->End() = *pStart
;
490 *pCurrent
->Start() = *pStart
;
491 pDoc
->AppendRedline( pNewRedline
, true );
494 // split end, if necessary
495 if( eCompare
== POS_OVERLAP_BEHIND
||
496 eCompare
== POS_OUTSIDE
)
498 SwRedline
* pNewRedline
= new SwRedline( *pCurrent
);
499 *pNewRedline
->Start() = *pEnd
;
500 *pCurrent
->End() = *pEnd
;
501 pDoc
->AppendRedline( pNewRedline
, true );
504 // save the current redline
505 _SaveRedline
* pSave
= new _SaveRedline( pCurrent
, *pStart
);
506 rArr
.push_back( pSave
);
510 // restore old redline mode
511 pDoc
->SetRedlineMode_intern( eOld
);
514 static void lcl_RestoreRedlines( SwDoc
* pDoc
, const SwPosition
& rPos
, _SaveRedlines
& rArr
)
516 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
517 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
519 for( size_t n
= 0; n
< rArr
.size(); ++n
)
521 rArr
[ n
].SetPos( rPos
);
522 pDoc
->AppendRedline( rArr
[ n
].pRedl
, true );
525 pDoc
->SetRedlineMode_intern( eOld
);
528 static void lcl_SaveRedlines( const SwNodeRange
& rRg
, _SaveRedlines
& rArr
)
530 SwDoc
* pDoc
= rRg
.aStart
.GetNode().GetDoc();
532 SwPosition
aSrchPos( rRg
.aStart
); aSrchPos
.nNode
--;
533 aSrchPos
.nContent
.Assign( aSrchPos
.nNode
.GetNode().GetCntntNode(), 0 );
534 if( pDoc
->GetRedline( aSrchPos
, &nRedlPos
) && nRedlPos
)
536 else if( nRedlPos
>= pDoc
->GetRedlineTbl().size() )
539 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
540 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
541 SwRedlineTbl
& rRedlTbl
= (SwRedlineTbl
&)pDoc
->GetRedlineTbl();
544 SwRedline
* pTmp
= rRedlTbl
[ nRedlPos
];
546 const SwPosition
* pRStt
= pTmp
->Start(),
547 * pREnd
= pTmp
->GetMark() == pRStt
548 ? pTmp
->GetPoint() : pTmp
->GetMark();
550 if( pRStt
->nNode
< rRg
.aStart
)
552 if( pREnd
->nNode
> rRg
.aStart
&& pREnd
->nNode
< rRg
.aEnd
)
554 // Create a copy and set the end of the original to the end of the MoveArea.
555 // The copy is moved too.
556 SwRedline
* pNewRedl
= new SwRedline( *pTmp
);
557 SwPosition
* pTmpPos
= pNewRedl
->Start();
558 pTmpPos
->nNode
= rRg
.aStart
;
559 pTmpPos
->nContent
.Assign(
560 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
562 _SaveRedline
* pSave
= new _SaveRedline( pNewRedl
, rRg
.aStart
);
563 rArr
.push_back( pSave
);
565 pTmpPos
= pTmp
->End();
566 pTmpPos
->nNode
= rRg
.aEnd
;
567 pTmpPos
->nContent
.Assign(
568 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
570 else if( pREnd
->nNode
== rRg
.aStart
)
572 SwPosition
* pTmpPos
= pTmp
->End();
573 pTmpPos
->nNode
= rRg
.aEnd
;
574 pTmpPos
->nContent
.Assign(
575 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
578 else if( pRStt
->nNode
< rRg
.aEnd
)
580 rRedlTbl
.Remove( nRedlPos
-- );
581 if( pREnd
->nNode
< rRg
.aEnd
||
582 ( pREnd
->nNode
== rRg
.aEnd
&& !pREnd
->nContent
.GetIndex()) )
585 _SaveRedline
* pSave
= new _SaveRedline( pTmp
, rRg
.aStart
);
586 rArr
.push_back( pSave
);
591 SwRedline
* pNewRedl
= new SwRedline( *pTmp
);
592 SwPosition
* pTmpPos
= pNewRedl
->End();
593 pTmpPos
->nNode
= rRg
.aEnd
;
594 pTmpPos
->nContent
.Assign(
595 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
597 _SaveRedline
* pSave
= new _SaveRedline( pNewRedl
, rRg
.aStart
);
598 rArr
.push_back( pSave
);
600 pTmpPos
= pTmp
->Start();
601 pTmpPos
->nNode
= rRg
.aEnd
;
602 pTmpPos
->nContent
.Assign(
603 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
604 pDoc
->AppendRedline( pTmp
, true );
610 } while( ++nRedlPos
< pDoc
->GetRedlineTbl().size() );
611 pDoc
->SetRedlineMode_intern( eOld
);
614 static void lcl_RestoreRedlines( SwDoc
* pDoc
, sal_uInt32 nInsPos
, _SaveRedlines
& rArr
)
616 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
617 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
619 for( size_t n
= 0; n
< rArr
.size(); ++n
)
621 rArr
[ n
].SetPos( nInsPos
);
622 pDoc
->AppendRedline( rArr
[ n
].pRedl
, true );
625 pDoc
->SetRedlineMode_intern( eOld
);
628 // #i59534: Redo of insertion of multiple text nodes runs into trouble
629 // because of unnecessary expanded redlines
630 // From now on this class saves the redline positions of all redlines which ends exact at the
631 // insert position (node _and_ content index)
632 _SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex
& rInsIdx
, xub_StrLen nCnt
)
633 : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt
)
635 SwNode
& rNd
= rInsIdx
.GetNode();
636 SwDoc
* pDest
= rNd
.GetDoc();
637 if( !pDest
->GetRedlineTbl().empty() )
640 const SwPosition
* pEnd
;
641 SwPosition
aSrcPos( rInsIdx
, SwIndex( rNd
.GetCntntNode(), nCnt
));
642 const SwRedline
* pRedl
= pDest
->GetRedline( aSrcPos
, &nFndPos
);
644 && *( pEnd
= ( pRedl
= pDest
->GetRedlineTbl()[ nFndPos
] )->End() ) == aSrcPos
645 && *pRedl
->Start() < aSrcPos
)
649 pSavArr
= new std::vector
<SwPosition
*>;
650 pSavIdx
= new SwNodeIndex( rInsIdx
, -1 );
652 pSavArr
->push_back( (SwPosition
*)pEnd
);
657 _SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
663 void _SaveRedlEndPosForRestore::_Restore()
666 SwCntntNode
* pNode
= pSavIdx
->GetNode().GetCntntNode();
667 // If there's no content node at the remembered position, we will not restore the old position
668 // This may happen if a table (or section?) will be inserted.
671 SwPosition
aPos( *pSavIdx
, SwIndex( pNode
, nSavCntnt
));
672 for( sal_uInt16 n
= pSavArr
->size(); n
; )
673 *(*pSavArr
)[ --n
] = aPos
;
677 /// Delete a full Section of the NodeArray.
678 /// The passed Node is located somewhere in the designated Section.
679 void SwDoc::DeleteSection( SwNode
*pNode
)
681 OSL_ENSURE( pNode
, "Didn't pass a Node." );
682 SwStartNode
* pSttNd
= pNode
->IsStartNode() ? (SwStartNode
*)pNode
683 : pNode
->StartOfSectionNode();
684 SwNodeIndex
aSttIdx( *pSttNd
), aEndIdx( *pNode
->EndOfSectionNode() );
686 // delete all Flys, Bookmarks, ...
687 DelFlyInRange( aSttIdx
, aEndIdx
);
688 DeleteRedline( *pSttNd
, true, USHRT_MAX
);
689 _DelBookmarks(aSttIdx
, aEndIdx
);
692 // move all Crsr/StkCrsr/UnoCrsr out of the to-be-deleted area
693 SwNodeIndex
aMvStt( aSttIdx
, 1 );
694 CorrAbs( aMvStt
, aEndIdx
, SwPosition( aSttIdx
), sal_True
);
697 GetNodes().DelNodes( aSttIdx
, aEndIdx
.GetIndex() - aSttIdx
.GetIndex() + 1 );
700 void SwDoc::SetModified(SwPaM
&rPaM
)
702 SwDataChanged
aTmp( rPaM
);
706 bool SwDoc::Overwrite( const SwPaM
&rRg
, const String
&rStr
)
708 SwPosition
& rPt
= *(SwPosition
*)rRg
.GetPoint();
709 if( mpACEWord
) // Add to AutoCorrect
711 if( 1 == rStr
.Len() )
712 mpACEWord
->CheckChar( rPt
, rStr
.GetChar( 0 ) );
713 delete mpACEWord
, mpACEWord
= 0;
716 SwTxtNode
*pNode
= rPt
.nNode
.GetNode().GetTxtNode();
717 if (!pNode
|| ( static_cast<size_t>(rStr
.Len()) // worst case: no erase
718 + static_cast<size_t>(pNode
->GetTxt().getLength()) > TXTNODE_MAX
))
723 if (GetIDocumentUndoRedo().DoesUndo())
725 GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
728 sal_uInt16 nOldAttrCnt
= pNode
->GetpSwpHints()
729 ? pNode
->GetpSwpHints()->Count() : 0;
730 SwDataChanged
aTmp( rRg
);
731 SwIndex
& rIdx
= rPt
.nContent
;
732 xub_StrLen nStart
= 0;
734 bool bOldExpFlg
= pNode
->IsIgnoreDontExpand();
735 pNode
->SetIgnoreDontExpand( true );
737 for( xub_StrLen nCnt
= 0; nCnt
< rStr
.Len(); ++nCnt
)
739 // start behind the characters (to fix the attributes!)
740 nStart
= rIdx
.GetIndex();
741 if (nStart
< pNode
->GetTxt().getLength())
743 lcl_SkipAttr( pNode
, rIdx
, nStart
);
745 sal_Unicode c
= rStr
.GetChar( nCnt
);
746 if (GetIDocumentUndoRedo().DoesUndo())
749 if (GetIDocumentUndoRedo().DoesGroupUndo())
751 SwUndo
*const pUndo
= GetUndoManager().GetLastUndo();
752 SwUndoOverwrite
*const pUndoOW(
753 dynamic_cast<SwUndoOverwrite
*>(pUndo
) );
756 // if CanGrouping() returns true it's already merged
757 bMerged
= pUndoOW
->CanGrouping( this, rPt
, c
);
762 SwUndo
*const pUndoOW( new SwUndoOverwrite(this, rPt
, c
) );
763 GetIDocumentUndoRedo().AppendUndo(pUndoOW
);
768 // start behind the characters (to fix the attributes!)
769 if (nStart
< pNode
->GetTxt().getLength())
771 pNode
->InsertText( OUString(c
), rIdx
, INS_EMPTYEXPAND
);
772 if( nStart
+1 < rIdx
.GetIndex() )
775 pNode
->EraseText( rIdx
, 1 );
780 pNode
->SetIgnoreDontExpand( bOldExpFlg
);
782 sal_uInt16 nNewAttrCnt
= pNode
->GetpSwpHints()
783 ? pNode
->GetpSwpHints()->Count() : 0;
784 if( nOldAttrCnt
!= nNewAttrCnt
)
786 SwUpdateAttr
aHint( 0, 0, 0 );
787 pNode
->ModifyBroadcast( 0, &aHint
, TYPE( SwCrsrShell
) );
790 if (!GetIDocumentUndoRedo().DoesUndo() &&
791 !IsIgnoreRedline() && !GetRedlineTbl().empty())
793 SwPaM
aPam( rPt
.nNode
, nStart
, rPt
.nNode
, rPt
.nContent
.GetIndex() );
794 DeleteRedline( aPam
, true, USHRT_MAX
);
796 else if( IsRedlineOn() )
798 // FIXME: this redline is WRONG: there is no DELETE, and the skipped
799 // characters are also included in aPam
800 SwPaM
aPam( rPt
.nNode
, nStart
, rPt
.nNode
, rPt
.nContent
.GetIndex() );
801 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT
, aPam
), true);
808 bool SwDoc::MoveAndJoin( SwPaM
& rPaM
, SwPosition
& rPos
, SwMoveFlags eMvFlags
)
810 SwNodeIndex
aIdx( rPaM
.Start()->nNode
);
811 sal_Bool bJoinTxt
= aIdx
.GetNode().IsTxtNode();
812 sal_Bool bOneNode
= rPaM
.GetPoint()->nNode
== rPaM
.GetMark()->nNode
;
813 aIdx
--; // in front of the move area!
815 bool bRet
= MoveRange( rPaM
, rPos
, eMvFlags
);
816 if( bRet
&& !bOneNode
)
820 SwTxtNode
* pTxtNd
= aIdx
.GetNode().GetTxtNode();
821 SwNodeIndex
aNxtIdx( aIdx
);
822 if( pTxtNd
&& pTxtNd
->CanJoinNext( &aNxtIdx
) )
824 { // Block so SwIndex into node is deleted before Join
825 CorrRel( aNxtIdx
, SwPosition( aIdx
, SwIndex(pTxtNd
,
826 pTxtNd
->GetTxt().getLength()) ), 0, sal_True
);
834 // It seems that this is mostly used by SwDoc internals; the only
835 // way to call this from the outside seems to be the special case in
836 // SwDoc::CopyRange (but I have not managed to actually hit that case).
837 bool SwDoc::MoveRange( SwPaM
& rPaM
, SwPosition
& rPos
, SwMoveFlags eMvFlags
)
839 // nothing moved: return
840 const SwPosition
*pStt
= rPaM
.Start(), *pEnd
= rPaM
.End();
841 if( !rPaM
.HasMark() || *pStt
>= *pEnd
|| (*pStt
<= rPos
&& rPos
< *pEnd
))
844 // Save the paragraph anchored Flys, so that they can be moved.
845 _SaveFlyArr aSaveFlyArr
;
846 _SaveFlyInRange( rPaM
, rPos
.nNode
, aSaveFlyArr
, 0 != ( DOC_MOVEALLFLYS
& eMvFlags
) );
848 // save redlines (if DOC_MOVEREDLINES is used)
849 _SaveRedlines aSaveRedl
;
850 if( DOC_MOVEREDLINES
& eMvFlags
&& !GetRedlineTbl().empty() )
852 lcl_SaveRedlines( rPaM
, aSaveRedl
);
854 // #i17764# unfortunately, code below relies on undos being
855 // in a particular order, and presence of bookmarks
856 // will change this order. Hence, we delete bookmarks
857 // here without undo.
858 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
868 int bUpdateFtn
= sal_False
;
869 SwFtnIdxs aTmpFntIdx
;
871 SwUndoMove
* pUndoMove
= 0;
872 if (GetIDocumentUndoRedo().DoesUndo())
874 GetIDocumentUndoRedo().ClearRedo();
875 pUndoMove
= new SwUndoMove( rPaM
, rPos
);
876 pUndoMove
->SetMoveRedlines( eMvFlags
== DOC_MOVEREDLINES
);
880 bUpdateFtn
= lcl_SaveFtn( pStt
->nNode
, pEnd
->nNode
, rPos
.nNode
,
881 GetFtnIdxs(), aTmpFntIdx
,
882 &pStt
->nContent
, &pEnd
->nContent
);
885 sal_Bool bSplit
= sal_False
;
886 SwPaM
aSavePam( rPos
, rPos
);
888 // Move the SPoint to the beginning of the range
889 if( rPaM
.GetPoint() == pEnd
)
892 // If there is a TextNode before and after the Move, create a JoinNext in the EditShell.
893 SwTxtNode
* pSrcNd
= rPaM
.GetPoint()->nNode
.GetNode().GetTxtNode();
894 sal_Bool bCorrSavePam
= pSrcNd
&& pStt
->nNode
!= pEnd
->nNode
;
896 // If one ore more TextNodes are moved, SwNodes::Move will do a SplitNode.
897 // However, this does not update the cursor. So we create a TextNode to keep
898 // updating the indices. After the Move the Node is optionally deleted.
899 SwTxtNode
* pTNd
= rPos
.nNode
.GetNode().GetTxtNode();
900 if( pTNd
&& rPaM
.GetPoint()->nNode
!= rPaM
.GetMark()->nNode
&&
901 ( rPos
.nContent
.GetIndex() || ( pTNd
->Len() && bCorrSavePam
)) )
904 xub_StrLen nMkCntnt
= rPaM
.GetMark()->nContent
.GetIndex();
906 std::vector
<sal_uLong
> aBkmkArr
;
907 _SaveCntntIdx( this, rPos
.nNode
.GetIndex(), rPos
.nContent
.GetIndex(),
908 aBkmkArr
, SAVEFLY_SPLIT
);
910 pTNd
= static_cast<SwTxtNode
*>(pTNd
->SplitCntntNode( rPos
));
912 if( !aBkmkArr
.empty() )
913 _RestoreCntntIdx( this, aBkmkArr
, rPos
.nNode
.GetIndex()-1, 0, true );
916 if( rPos
.nNode
== rPaM
.GetMark()->nNode
)
918 rPaM
.GetMark()->nNode
= rPos
.nNode
.GetIndex()-1;
919 rPaM
.GetMark()->nContent
.Assign( pTNd
, nMkCntnt
);
923 // Put back the Pam by one "content"; so that it's always outside of
924 // the manipulated range.
925 // If there's no content anymore, set it to the StartNode (that's
927 sal_Bool bNullCntnt
= !aSavePam
.Move( fnMoveBackward
, fnGoCntnt
);
930 aSavePam
.GetPoint()->nNode
--;
933 // Copy all Bookmarks that are within the Move range into an array,
934 // that saves the positon as an offset.
935 ::std::vector
< ::sw::mark::SaveBookmark
> aSaveBkmks
;
943 // If there is no range anymore due to the above deletions (e.g. the
944 // footnotes got deleted), it's still a valid Move!
945 if( *rPaM
.GetPoint() != *rPaM
.GetMark() )
947 // now do the actual move
948 GetNodes().MoveRange( rPaM
, rPos
, GetNodes() );
950 // after a MoveRange() the Mark is deleted
951 if ( rPaM
.HasMark() ) // => no Move occurred!
960 OSL_ENSURE( *aSavePam
.GetMark() == rPos
||
961 ( aSavePam
.GetMark()->nNode
.GetNode().GetCntntNode() == NULL
),
962 "PaM was not moved. Aren't there ContentNodes at the beginning/end?" );
963 *aSavePam
.GetMark() = rPos
;
965 rPaM
.SetMark(); // create a Sel. around the new range
966 pTNd
= aSavePam
.GetNode()->GetTxtNode();
967 if (GetIDocumentUndoRedo().DoesUndo())
969 // correct the SavePam's Content first
972 aSavePam
.GetPoint()->nContent
= 0;
975 // The method SwEditShell::Move() merges the TextNode after the Move,
976 // where the rPaM is located.
977 // If the Content was moved to the back and the SavePam's SPoint is
978 // in the next Node, we have to deal with this when saving the Undo object!
979 SwTxtNode
* pPamTxtNd
= 0;
981 // Is passed to SwUndoMove, which happens when subsequently calling Undo JoinNext.
982 // If it's not possible to call Undo JoinNext here.
983 sal_Bool bJoin
= bSplit
&& pTNd
;
984 bCorrSavePam
= bCorrSavePam
&&
985 0 != ( pPamTxtNd
= rPaM
.GetNode()->GetTxtNode() )
986 && pPamTxtNd
->CanJoinNext()
987 && (*rPaM
.GetPoint() <= *aSavePam
.GetPoint());
989 // Do two Nodes have to be joined at the SavePam?
990 if( bJoin
&& pTNd
->CanJoinNext() )
993 // No temporary Index when using &&.
994 // We probably only want to compare the indices.
995 if( bCorrSavePam
&& rPaM
.GetPoint()->nNode
.GetIndex()+1 ==
996 aSavePam
.GetPoint()->nNode
.GetIndex() )
998 aSavePam
.GetPoint()->nContent
+= pPamTxtNd
->Len();
1002 else if ( !aSavePam
.Move( fnMoveForward
, fnGoCntnt
) )
1004 aSavePam
.GetPoint()->nNode
++;
1007 // The newly inserted range is now inbetween SPoint and GetMark.
1008 pUndoMove
->SetDestRange( aSavePam
, *rPaM
.GetPoint(),
1009 bJoin
, bCorrSavePam
);
1010 GetIDocumentUndoRedo().AppendUndo( pUndoMove
);
1014 bool bRemove
= true;
1015 // Do two Nodes have to be joined at the SavePam?
1016 if( bSplit
&& pTNd
)
1018 if( pTNd
->CanJoinNext())
1020 // Always join next, because <pTNd> has to stay as it is.
1021 // A join previous from its next would more or less delete <pTNd>
1028 aSavePam
.GetPoint()->nNode
++;
1029 aSavePam
.GetPoint()->nContent
.Assign( aSavePam
.GetCntntNode(), 0 );
1031 else if( bRemove
) // No move forward after joining with next paragraph
1033 aSavePam
.Move( fnMoveForward
, fnGoCntnt
);
1037 // Insert the Bookmarks back into the Document.
1038 *rPaM
.GetMark() = *aSavePam
.Start();
1040 ::std::vector
< ::sw::mark::SaveBookmark
>::iterator pBkmk
= aSaveBkmks
.begin();
1041 pBkmk
!= aSaveBkmks
.end();
1045 rPaM
.GetMark()->nNode
,
1046 &rPaM
.GetMark()->nContent
);
1047 *rPaM
.GetPoint() = *aSavePam
.End();
1049 // Move the Flys to the new position.
1050 _RestFlyInRange( aSaveFlyArr
, rPaM
.Start()->nNode
, &(rPos
.nNode
) );
1052 // restore redlines (if DOC_MOVEREDLINES is used)
1053 if( !aSaveRedl
.empty() )
1055 lcl_RestoreRedlines( this, *aSavePam
.Start(), aSaveRedl
);
1060 if( !aTmpFntIdx
.empty() )
1062 GetFtnIdxs().insert( aTmpFntIdx
);
1066 GetFtnIdxs().UpdateAllFtn();
1073 bool SwDoc::MoveNodeRange( SwNodeRange
& rRange
, SwNodeIndex
& rPos
,
1074 SwMoveFlags eMvFlags
)
1076 // Moves all Nodes to the new position.
1077 // Bookmarks are moved too (currently without Undo support).
1079 // If footnotes are being moved to the special section, remove them now.
1081 // Or else delete the Frames for all footnotes that are being moved
1082 // and have it rebuild after the Move (footnotes can change pages).
1083 // Additionally we have to correct the FtnIdx array's sorting.
1084 int bUpdateFtn
= sal_False
;
1085 SwFtnIdxs aTmpFntIdx
;
1087 SwUndoMove
* pUndo
= 0;
1088 if ((DOC_CREATEUNDOOBJ
& eMvFlags
) && GetIDocumentUndoRedo().DoesUndo())
1090 pUndo
= new SwUndoMove( this, rRange
, rPos
);
1094 bUpdateFtn
= lcl_SaveFtn( rRange
.aStart
, rRange
.aEnd
, rPos
,
1095 GetFtnIdxs(), aTmpFntIdx
);
1098 _SaveRedlines aSaveRedl
;
1099 std::vector
<SwRedline
*> aSavRedlInsPosArr
;
1100 if( DOC_MOVEREDLINES
& eMvFlags
&& !GetRedlineTbl().empty() )
1102 lcl_SaveRedlines( rRange
, aSaveRedl
);
1104 // Find all RedLines that end at the InsPos.
1105 // These have to be moved back to the "old" position after the Move.
1106 sal_uInt16 nRedlPos
= GetRedlinePos( rPos
.GetNode(), USHRT_MAX
);
1107 if( USHRT_MAX
!= nRedlPos
)
1109 const SwPosition
*pRStt
, *pREnd
;
1111 SwRedline
* pTmp
= GetRedlineTbl()[ nRedlPos
];
1112 pRStt
= pTmp
->Start();
1113 pREnd
= pTmp
->End();
1114 if( pREnd
->nNode
== rPos
&& pRStt
->nNode
< rPos
)
1116 aSavRedlInsPosArr
.push_back( pTmp
);
1118 } while( pRStt
->nNode
< rPos
&& ++nRedlPos
< GetRedlineTbl().size());
1122 // Copy all Bookmarks that are within the Move range into an array
1123 // that stores all references to positions as an offset.
1124 // The final mapping happens after the Move.
1125 ::std::vector
< ::sw::mark::SaveBookmark
> aSaveBkmks
;
1126 _DelBookmarks(rRange
.aStart
, rRange
.aEnd
, &aSaveBkmks
);
1128 // Save the paragraph-bound Flys, so that they can be moved.
1129 _SaveFlyArr aSaveFlyArr
;
1130 if( !GetSpzFrmFmts()->empty() )
1131 _SaveFlyInRange( rRange
, aSaveFlyArr
);
1133 // Set it to before the Position, so that it cannot be moved further.
1134 SwNodeIndex
aIdx( rPos
, -1 );
1136 SwNodeIndex
* pSaveInsPos
= 0;
1138 pSaveInsPos
= new SwNodeIndex( rRange
.aStart
, -1 );
1141 sal_Bool bNoDelFrms
= 0 != (DOC_NO_DELFRMS
& eMvFlags
);
1142 if( GetNodes()._MoveNodes( rRange
, GetNodes(), rPos
, !bNoDelFrms
) )
1144 ++aIdx
; // again back to old position
1150 aIdx
= rRange
.aStart
;
1151 delete pUndo
, pUndo
= 0;
1154 // move the Flys to the new position
1155 if( !aSaveFlyArr
.empty() )
1156 _RestFlyInRange( aSaveFlyArr
, aIdx
, NULL
);
1158 // Add the Bookmarks back to the Document
1160 ::std::vector
< ::sw::mark::SaveBookmark
>::iterator pBkmk
= aSaveBkmks
.begin();
1161 pBkmk
!= aSaveBkmks
.end();
1163 pBkmk
->SetInDoc(this, aIdx
);
1165 if( !aSavRedlInsPosArr
.empty() )
1167 SwNode
* pNewNd
= &aIdx
.GetNode();
1168 for( sal_uInt16 n
= 0; n
< aSavRedlInsPosArr
.size(); ++n
)
1170 SwRedline
* pTmp
= aSavRedlInsPosArr
[ n
];
1171 if( GetRedlineTbl().Contains( pTmp
) )
1173 SwPosition
* pEnd
= pTmp
->End();
1175 pEnd
->nContent
.Assign( pNewNd
->GetCntntNode(), 0 );
1180 if( !aSaveRedl
.empty() )
1181 lcl_RestoreRedlines( this, aIdx
.GetIndex(), aSaveRedl
);
1185 pUndo
->SetDestRange( aIdx
, rPos
, *pSaveInsPos
);
1186 GetIDocumentUndoRedo().AppendUndo(pUndo
);
1193 if( !aTmpFntIdx
.empty() )
1195 GetFtnIdxs().insert( aTmpFntIdx
);
1199 GetFtnIdxs().UpdateAllFtn();
1206 /// Convert list of ranges of whichIds to a corresponding list of whichIds
1207 static std::vector
<sal_uInt16
> * lcl_RangesToVector(sal_uInt16
* pRanges
)
1209 std::vector
<sal_uInt16
> * pResult
= new std::vector
<sal_uInt16
>();
1212 while (pRanges
[i
] != 0)
1214 OSL_ENSURE(pRanges
[i
+1] != 0, "malformed ranges");
1216 for (sal_uInt16 j
= pRanges
[i
]; j
< pRanges
[i
+1]; j
++)
1217 pResult
->push_back(j
);
1225 static bool lcl_StrLenOverFlow( const SwPaM
& rPam
)
1227 // If we try to merge two paragraph we have to test if afterwards
1228 // the string doesn't exceed the allowed string length
1230 if( rPam
.GetPoint()->nNode
!= rPam
.GetMark()->nNode
)
1232 const SwPosition
* pStt
= rPam
.Start(), *pEnd
= rPam
.End();
1233 const SwTxtNode
* pEndNd
= pEnd
->nNode
.GetNode().GetTxtNode();
1234 if( (0 != pEndNd
) && pStt
->nNode
.GetNode().IsTxtNode() )
1236 sal_uInt64 nSum
= pStt
->nContent
.GetIndex() +
1237 pEndNd
->GetTxt().getLength() - pEnd
->nContent
.GetIndex();
1238 if( nSum
> STRING_LEN
)
1245 void sw_GetJoinFlags( SwPaM
& rPam
, sal_Bool
& rJoinTxt
, sal_Bool
& rJoinPrev
)
1247 rJoinTxt
= sal_False
;
1248 rJoinPrev
= sal_False
;
1249 if( rPam
.GetPoint()->nNode
!= rPam
.GetMark()->nNode
)
1251 const SwPosition
* pStt
= rPam
.Start(), *pEnd
= rPam
.End();
1252 SwTxtNode
*pSttNd
= pStt
->nNode
.GetNode().GetTxtNode();
1255 SwTxtNode
*pEndNd
= pEnd
->nNode
.GetNode().GetTxtNode();
1256 rJoinTxt
= 0 != pEndNd
;
1259 bool bExchange
= pStt
== rPam
.GetPoint();
1260 if( !pStt
->nContent
.GetIndex() &&
1261 pEndNd
->GetTxt().getLength() != pEnd
->nContent
.GetIndex())
1262 bExchange
= !bExchange
;
1265 rJoinPrev
= rPam
.GetPoint() == pStt
;
1266 OSL_ENSURE( !pStt
->nContent
.GetIndex() &&
1267 pEndNd
->GetTxt().getLength() != pEnd
->nContent
.GetIndex()
1268 ? rPam
.GetPoint()->nNode
< rPam
.GetMark()->nNode
1269 : rPam
.GetPoint()->nNode
> rPam
.GetMark()->nNode
,
1276 void sw_JoinText( SwPaM
& rPam
, sal_Bool bJoinPrev
)
1278 SwNodeIndex
aIdx( rPam
.GetPoint()->nNode
);
1279 SwTxtNode
*pTxtNd
= aIdx
.GetNode().GetTxtNode();
1280 SwNodeIndex
aOldIdx( aIdx
);
1281 SwTxtNode
*pOldTxtNd
= pTxtNd
;
1283 if( pTxtNd
&& pTxtNd
->CanJoinNext( &aIdx
) )
1285 SwDoc
* pDoc
= rPam
.GetDoc();
1288 // We do not need to handle xmlids in this case, because
1289 // it is only invoked if one paragraph is completely empty
1290 // (see sw_GetJoinFlags)
1292 // If PageBreaks are deleted/set, it must not be added to the Undo history!
1293 // Also, deleteing the Node is not added to the Undo histroy!
1294 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
1296 /* PageBreaks, PageDesc, ColumnBreaks */
1297 // If we need to change something about the logic to copy the PageBreaks,
1298 // PageDesc, etc. we also have to change SwUndoDelete.
1299 // There, we copy the AUTO PageBreak from the GetMarkNode!
1301 /* The GetMarkNode */
1302 if( ( pTxtNd
= aIdx
.GetNode().GetTxtNode())->HasSwAttrSet() )
1304 const SfxPoolItem
* pItem
;
1305 if( SFX_ITEM_SET
== pTxtNd
->GetpSwAttrSet()->GetItemState(
1306 RES_BREAK
, sal_False
, &pItem
) )
1307 pTxtNd
->ResetAttr( RES_BREAK
);
1308 if( pTxtNd
->HasSwAttrSet() &&
1309 SFX_ITEM_SET
== pTxtNd
->GetpSwAttrSet()->GetItemState(
1310 RES_PAGEDESC
, sal_False
, &pItem
) )
1311 pTxtNd
->ResetAttr( RES_PAGEDESC
);
1315 if( pOldTxtNd
->HasSwAttrSet() )
1317 const SfxPoolItem
* pItem
;
1318 SfxItemSet
aSet( pDoc
->GetAttrPool(), aBreakSetRange
);
1319 const SfxItemSet
* pSet
= pOldTxtNd
->GetpSwAttrSet();
1320 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
,
1321 sal_False
, &pItem
) )
1323 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_PAGEDESC
,
1324 sal_False
, &pItem
) )
1327 pTxtNd
->SetAttr( aSet
);
1329 pOldTxtNd
->FmtToTxtAttr( pTxtNd
);
1331 std::vector
<sal_uLong
> aBkmkArr
;
1332 ::_SaveCntntIdx( pDoc
, aOldIdx
.GetIndex(),
1333 pOldTxtNd
->Len(), aBkmkArr
);
1335 SwIndex
aAlphaIdx(pTxtNd
);
1336 pOldTxtNd
->CutText( pTxtNd
, aAlphaIdx
, SwIndex(pOldTxtNd
),
1338 SwPosition
aAlphaPos( aIdx
, aAlphaIdx
);
1339 pDoc
->CorrRel( rPam
.GetPoint()->nNode
, aAlphaPos
, 0, sal_True
);
1341 // move all Bookmarks/TOXMarks
1342 if( !aBkmkArr
.empty() )
1343 ::_RestoreCntntIdx( pDoc
, aBkmkArr
, aIdx
.GetIndex() );
1345 // If the passed PaM is not in the Crsr ring,
1346 // treat it separately (e.g. when it's being called from AutoFormat)
1347 if( pOldTxtNd
== rPam
.GetBound( sal_True
).nContent
.GetIdxReg() )
1348 rPam
.GetBound( sal_True
) = aAlphaPos
;
1349 if( pOldTxtNd
== rPam
.GetBound( sal_False
).nContent
.GetIdxReg() )
1350 rPam
.GetBound( sal_False
) = aAlphaPos
;
1352 // delete the Node, at last!
1353 pDoc
->GetNodes().Delete( aOldIdx
, 1 );
1357 SwTxtNode
* pDelNd
= aIdx
.GetNode().GetTxtNode();
1359 pDelNd
->FmtToTxtAttr( pTxtNd
);
1362 /* This case was missed:
1364 <something></something> <-- pTxtNd
1365 <other>ccc</other> <-- pDelNd
1367 <something> and <other> are paragraph
1368 attributes. The attribute <something> stayed if not
1369 overwritten by an attribute in "ccc". Fixed by
1370 first resetting all character attributes in first
1373 std::vector
<sal_uInt16
> * pShorts
=
1374 lcl_RangesToVector(aCharFmtSetRange
);
1375 pTxtNd
->ResetAttr(*pShorts
);
1378 if( pDelNd
->HasSwAttrSet() )
1380 // only copy the character attributes
1381 SfxItemSet
aTmpSet( pDoc
->GetAttrPool(), aCharFmtSetRange
);
1382 aTmpSet
.Put( *pDelNd
->GetpSwAttrSet() );
1383 pTxtNd
->SetAttr( aTmpSet
);
1387 pDoc
->CorrRel( aIdx
, *rPam
.GetPoint(), 0, sal_True
);
1388 // #i100466# adjust given <rPam>, if it does not belong to the cursors
1389 if ( pDelNd
== rPam
.GetBound( sal_True
).nContent
.GetIdxReg() )
1391 rPam
.GetBound( sal_True
) = SwPosition( SwNodeIndex( *pTxtNd
), SwIndex( pTxtNd
) );
1393 if( pDelNd
== rPam
.GetBound( sal_False
).nContent
.GetIdxReg() )
1395 rPam
.GetBound( sal_False
) = SwPosition( SwNodeIndex( *pTxtNd
), SwIndex( pTxtNd
) );
1403 lcl_CalcBreaks( ::std::vector
<xub_StrLen
> & rBreaks
, SwPaM
const & rPam
)
1405 SwTxtNode
const * const pTxtNode(
1406 rPam
.End()->nNode
.GetNode().GetTxtNode() );
1408 return; // left-overlap only possible at end of selection...
1410 const xub_StrLen
nStart(rPam
.Start()->nContent
.GetIndex());
1411 const xub_StrLen
nEnd (rPam
.End ()->nContent
.GetIndex());
1412 if (nEnd
== pTxtNode
->Len())
1413 return; // paragraph selected until the end
1415 for (xub_StrLen i
= nStart
; i
< nEnd
; ++i
)
1417 const sal_Unicode
c(pTxtNode
->GetTxt()[i
]);
1418 if ((CH_TXTATR_INWORD
== c
) || (CH_TXTATR_BREAKWORD
== c
))
1420 SwTxtAttr
const * const pAttr( pTxtNode
->GetTxtAttrForCharAt(i
) );
1421 if (pAttr
&& pAttr
->GetEnd() && (*pAttr
->GetEnd() > nEnd
))
1423 OSL_ENSURE(pAttr
->HasDummyChar(), "GetTxtAttrForCharAt broken?");
1424 rBreaks
.push_back(i
);
1430 static bool lcl_DoWithBreaks(SwDoc
& rDoc
, SwPaM
& rPam
,
1431 bool (SwDoc::*pFunc
)(SwPaM
&, bool), const bool bForceJoinNext
= false)
1433 ::std::vector
<xub_StrLen
> Breaks
;
1435 lcl_CalcBreaks(Breaks
, rPam
);
1439 return (rDoc
.*pFunc
)(rPam
, bForceJoinNext
);
1442 // Deletion must be split into several parts if the text node
1443 // contains a text attribute with end and with dummy character
1444 // and the selection does not contain the text attribute completely,
1445 // but overlaps its start (left), where the dummy character is.
1447 SwPosition
const & rSelectionEnd( *rPam
.End() );
1450 // iterate from end to start, to avoid invalidating the offsets!
1451 ::std::vector
<xub_StrLen
>::reverse_iterator
iter( Breaks
.rbegin() );
1452 SwPaM
aPam( rSelectionEnd
, rSelectionEnd
); // end node!
1453 SwPosition
& rEnd( *aPam
.End() );
1454 SwPosition
& rStart( *aPam
.Start() );
1456 while (iter
!= Breaks
.rend())
1458 rStart
.nContent
= *iter
+ 1;
1459 if (rEnd
.nContent
> rStart
.nContent
) // check if part is empty
1461 bRet
&= (rDoc
.*pFunc
)(aPam
, bForceJoinNext
);
1463 rEnd
.nContent
= *iter
;
1467 rStart
= *rPam
.Start(); // set to original start
1468 if (rEnd
.nContent
> rStart
.nContent
) // check if part is empty
1470 bRet
&= (rDoc
.*pFunc
)(aPam
, bForceJoinNext
);
1476 bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM
& rPam
, const bool )
1478 OSL_ENSURE( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
1481 SwUndoRedlineDelete
* pUndo
= 0;
1482 RedlineMode_t eOld
= GetRedlineMode();
1483 checkRedlining(eOld
);
1484 if (GetIDocumentUndoRedo().DoesUndo())
1487 /* please don't translate -- for cultural reasons this comment is protected
1488 until the redline implementation is finally fixed some day */
1489 //JP 06.01.98: MUSS noch optimiert werden!!!
1491 (RedlineMode_t
)(nsRedlineMode_t::REDLINE_ON
| nsRedlineMode_t::REDLINE_SHOW_INSERT
| nsRedlineMode_t::REDLINE_SHOW_DELETE
));
1493 GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY
, NULL
);
1494 pUndo
= new SwUndoRedlineDelete( rPam
, UNDO_DELETE
);
1495 GetIDocumentUndoRedo().AppendUndo(pUndo
);
1497 if( *rPam
.GetPoint() != *rPam
.GetMark() )
1498 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE
, rPam
), true);
1503 GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY
, NULL
);
1504 // ??? why the hell is the AppendUndo not below the
1505 // CanGrouping, so this hideous cleanup wouldn't be necessary?
1506 // bah, this is redlining, probably changing this would break it...
1507 if (GetIDocumentUndoRedo().DoesGroupUndo())
1509 SwUndo
*const pLastUndo( GetUndoManager().GetLastUndo() );
1510 SwUndoRedlineDelete
*const pUndoRedlineDel(
1511 dynamic_cast<SwUndoRedlineDelete
*>(pLastUndo
) );
1512 if (pUndoRedlineDel
)
1514 bool const bMerged
= pUndoRedlineDel
->CanGrouping(*pUndo
);
1517 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
1518 SwUndo
const*const pDeleted
=
1519 GetUndoManager().RemoveLastUndo();
1520 OSL_ENSURE(pDeleted
== pUndo
,
1521 "DeleteAndJoinWithRedlineImpl: "
1522 "undo removed is not undo inserted?");
1527 //JP 06.01.98: MUSS noch optimiert werden!!!
1528 SetRedlineMode( eOld
);
1534 bool SwDoc::DeleteAndJoinImpl( SwPaM
& rPam
,
1535 const bool bForceJoinNext
)
1537 sal_Bool bJoinTxt
, bJoinPrev
;
1538 sw_GetJoinFlags( rPam
, bJoinTxt
, bJoinPrev
);
1540 if ( bForceJoinNext
)
1542 bJoinPrev
= sal_False
;
1546 bool const bSuccess( DeleteRangeImpl( rPam
) );
1553 sw_JoinText( rPam
, bJoinPrev
);
1559 bool SwDoc::DeleteRangeImpl(SwPaM
& rPam
, const bool)
1561 // Move all cursors out of the deleted range, but first copy the
1562 // passed PaM, because it could be a cursor that would be moved!
1563 SwPaM
aDelPam( *rPam
.GetMark(), *rPam
.GetPoint() );
1564 ::PaMCorrAbs( aDelPam
, *aDelPam
.GetPoint() );
1566 bool const bSuccess( DeleteRangeImplImpl( aDelPam
) );
1568 { // now copy position from temp copy to given PaM
1569 *rPam
.GetPoint() = *aDelPam
.GetPoint();
1575 bool SwDoc::DeleteRangeImplImpl(SwPaM
& rPam
)
1577 SwPosition
*pStt
= (SwPosition
*)rPam
.Start(), *pEnd
= (SwPosition
*)rPam
.End();
1579 if( !rPam
.HasMark() || *pStt
>= *pEnd
)
1584 // if necessary the saved Word for the exception
1585 if( mpACEWord
->IsDeleted() || pStt
->nNode
!= pEnd
->nNode
||
1586 pStt
->nContent
.GetIndex() + 1 != pEnd
->nContent
.GetIndex() ||
1587 !mpACEWord
->CheckDelChar( *pStt
))
1588 delete mpACEWord
, mpACEWord
= 0;
1592 // Delete all empty TextHints at the Mark's position
1593 SwTxtNode
* pTxtNd
= rPam
.GetMark()->nNode
.GetNode().GetTxtNode();
1595 if( pTxtNd
&& 0 != ( pHts
= pTxtNd
->GetpSwpHints()) && pHts
->Count() )
1597 const xub_StrLen
*pEndIdx
;
1598 xub_StrLen nMkCntPos
= rPam
.GetMark()->nContent
.GetIndex();
1599 for( sal_uInt16 n
= pHts
->Count(); n
; )
1601 const SwTxtAttr
* pAttr
= (*pHts
)[ --n
];
1602 if( nMkCntPos
> *pAttr
->GetStart() )
1605 if( nMkCntPos
== *pAttr
->GetStart() &&
1606 0 != (pEndIdx
= pAttr
->GetEnd()) &&
1607 *pEndIdx
== *pAttr
->GetStart() )
1608 pTxtNd
->DestroyAttr( pHts
->Cut( n
) );
1613 // Delete fieldmarks before postits, but let's leave them alone during import.
1614 if (GetIDocumentUndoRedo().DoesUndo() && pStt
->nNode
== pEnd
->nNode
&& (pEnd
->nContent
.GetIndex() - pStt
->nContent
.GetIndex()) == 1)
1616 SwTxtNode
* pTxtNd
= rPam
.Start()->nNode
.GetNode().GetTxtNode();
1617 xub_StrLen nIndex
= rPam
.Start()->nContent
.GetIndex();
1618 // We may have a postit here.
1619 if (pTxtNd
->GetTxt()[nIndex
] == CH_TXTATR_INWORD
)
1621 SwTxtAttr
* pTxtAttr
= pTxtNd
->GetTxtAttrForCharAt(nIndex
, RES_TXTATR_FIELD
);
1622 if (pTxtAttr
&& pTxtAttr
->GetFld().GetFld()->Which() == RES_POSTITFLD
)
1624 const SwPostItField
* pField
= dynamic_cast<const SwPostItField
*>(pTxtAttr
->GetFld().GetFld());
1625 IDocumentMarkAccess::const_iterator_t ppMark
= getIDocumentMarkAccess()->findMark(pField
->GetName());
1626 if (ppMark
!= getIDocumentMarkAccess()->getMarksEnd())
1627 getIDocumentMarkAccess()->deleteMark(ppMark
);
1633 // Send DataChanged before deletion, so that we still know
1634 // which objects are in the range.
1635 // Afterwards they could be before/after the Position.
1636 SwDataChanged
aTmp( rPam
);
1640 if (GetIDocumentUndoRedo().DoesUndo())
1642 GetIDocumentUndoRedo().ClearRedo();
1643 bool bMerged(false);
1644 if (GetIDocumentUndoRedo().DoesGroupUndo())
1646 SwUndo
*const pLastUndo( GetUndoManager().GetLastUndo() );
1647 SwUndoDelete
*const pUndoDelete(
1648 dynamic_cast<SwUndoDelete
*>(pLastUndo
) );
1651 bMerged
= pUndoDelete
->CanGrouping( this, rPam
);
1652 // if CanGrouping() returns true it's already merged
1657 GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam
) );
1665 if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
1666 DeleteRedline( rPam
, true, USHRT_MAX
);
1668 // Delete and move all "Flys at the paragraph", which are within the Selection
1669 DelFlyInRange(rPam
.GetMark()->nNode
, rPam
.GetPoint()->nNode
);
1677 SwNodeIndex
aSttIdx( pStt
->nNode
);
1678 SwCntntNode
* pCNd
= aSttIdx
.GetNode().GetCntntNode();
1680 do { // middle checked loop!
1683 SwTxtNode
* pStartTxtNode( pCNd
->GetTxtNode() );
1684 if ( pStartTxtNode
)
1686 // now move the Content to the new Node
1687 sal_Bool bOneNd
= pStt
->nNode
== pEnd
->nNode
;
1688 xub_StrLen nLen
= ( bOneNd
? pEnd
->nContent
.GetIndex()
1690 - pStt
->nContent
.GetIndex();
1692 // Don't call again, if already empty
1695 pStartTxtNode
->EraseText( pStt
->nContent
, nLen
);
1697 if( !pStartTxtNode
->Len() )
1699 // METADATA: remove reference if empty (consider node deleted)
1700 pStartTxtNode
->RemoveMetadataReference();
1704 if( bOneNd
) // that's it
1711 // So that there are no indices left registered when deleted,
1712 // we remove a SwPaM from the Content here.
1713 pStt
->nContent
.Assign( 0, 0 );
1717 pCNd
= pEnd
->nNode
.GetNode().GetCntntNode();
1720 SwTxtNode
* pEndTxtNode( pCNd
->GetTxtNode() );
1723 // if already empty, don't call again
1724 if( pEnd
->nContent
.GetIndex() )
1726 SwIndex
aIdx( pCNd
, 0 );
1727 pEndTxtNode
->EraseText( aIdx
, pEnd
->nContent
.GetIndex() );
1729 if( !pEndTxtNode
->Len() )
1731 // METADATA: remove reference if empty (consider node deleted)
1732 pEndTxtNode
->RemoveMetadataReference();
1738 // So that there are no indices left registered when deleted,
1739 // we remove a SwPaM from the Content here.
1740 pEnd
->nContent
.Assign( 0, 0 );
1744 // if the end is not a content node, delete it as well
1745 sal_uInt32 nEnde
= pEnd
->nNode
.GetIndex();
1749 if( aSttIdx
!= nEnde
)
1751 // delete the Nodes into the NodesArary
1752 GetNodes().Delete( aSttIdx
, nEnde
- aSttIdx
.GetIndex() );
1755 // If the Node that contained the Cursor has been deleted,
1756 // the Content has to be assigned to the current Content.
1757 pStt
->nContent
.Assign( pStt
->nNode
.GetNode().GetCntntNode(),
1758 pStt
->nContent
.GetIndex() );
1760 // If we deleted across Node boundaries we have to correct the PaM,
1761 // because they are in different Nodes now.
1762 // Also, the Selection is revoked.
1768 if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
1775 // #i100466# Add handling of new optional parameter <bForceJoinNext>
1776 bool SwDoc::DeleteAndJoin( SwPaM
& rPam
,
1777 const bool bForceJoinNext
)
1779 if ( lcl_StrLenOverFlow( rPam
) )
1782 return lcl_DoWithBreaks( *this, rPam
, (IsRedlineOn())
1783 ? &SwDoc::DeleteAndJoinWithRedlineImpl
1784 : &SwDoc::DeleteAndJoinImpl
,
1788 bool SwDoc::DeleteRange( SwPaM
& rPam
)
1790 return lcl_DoWithBreaks( *this, rPam
, &SwDoc::DeleteRangeImpl
);
1794 static void lcl_syncGrammarError( SwTxtNode
&rTxtNode
, linguistic2::ProofreadingResult
& rResult
,
1795 xub_StrLen
/*nBeginGrammarCheck*/, const ModelToViewHelper
&rConversionMap
)
1797 if( rTxtNode
.IsGrammarCheckDirty() )
1799 SwGrammarMarkUp
* pWrong
= rTxtNode
.GetGrammarCheck();
1800 linguistic2::SingleProofreadingError
* pArray
= rResult
.aErrors
.getArray();
1801 sal_uInt16 i
, j
= 0;
1804 for( i
= 0; i
< rResult
.aErrors
.getLength(); ++i
)
1806 const linguistic2::SingleProofreadingError
&rError
= rResult
.aErrors
[i
];
1807 xub_StrLen nStart
= (xub_StrLen
)rConversionMap
.ConvertToModelPosition( rError
.nErrorStart
).mnPos
;
1808 xub_StrLen nEnd
= (xub_StrLen
)rConversionMap
.ConvertToModelPosition( rError
.nErrorStart
+ rError
.nErrorLength
).mnPos
;
1810 pArray
[j
] = pArray
[i
];
1811 if( pWrong
->LookForEntry( nStart
, nEnd
) )
1815 if( rResult
.aErrors
.getLength() > j
)
1816 rResult
.aErrors
.realloc( j
);
1819 uno::Any
SwDoc::Spell( SwPaM
& rPaM
,
1820 uno::Reference
< XSpellChecker1
> &xSpeller
,
1821 sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
,
1823 SwConversionArgs
*pConvArgs
) const
1825 SwPosition
* pSttPos
= rPaM
.Start(), *pEndPos
= rPaM
.End();
1827 SwSpellArgs
*pSpellArgs
= 0;
1830 pConvArgs
->SetStart(pSttPos
->nNode
.GetNode().GetTxtNode(), pSttPos
->nContent
);
1831 pConvArgs
->SetEnd( pEndPos
->nNode
.GetNode().GetTxtNode(), pEndPos
->nContent
);
1834 pSpellArgs
= new SwSpellArgs( xSpeller
,
1835 pSttPos
->nNode
.GetNode().GetTxtNode(), pSttPos
->nContent
,
1836 pEndPos
->nNode
.GetNode().GetTxtNode(), pEndPos
->nContent
,
1839 sal_uLong nCurrNd
= pSttPos
->nNode
.GetIndex();
1840 sal_uLong nEndNd
= pEndPos
->nNode
.GetIndex();
1843 if( nCurrNd
<= nEndNd
)
1845 SwCntntFrm
* pCntFrm
;
1849 SwNode
* pNd
= GetNodes()[ nCurrNd
];
1850 switch( pNd
->GetNodeType() )
1853 if( 0 != ( pCntFrm
= ((SwTxtNode
*)pNd
)->getLayoutFrm( GetCurrentLayout() )) )
1855 // skip protected and hidden Cells and Flys
1856 if( pCntFrm
->IsProtected() )
1858 nCurrNd
= pNd
->EndOfSectionIndex();
1860 else if( !((SwTxtFrm
*)pCntFrm
)->IsHiddenNow() )
1862 if( pPageCnt
&& *pPageCnt
&& pPageSt
)
1864 sal_uInt16 nPageNr
= pCntFrm
->GetPhyPageNum();
1868 if( *pPageCnt
< *pPageSt
)
1869 *pPageCnt
= *pPageSt
;
1872 if( nPageNr
>= *pPageSt
)
1873 nStat
= nPageNr
- *pPageSt
+ 1;
1875 nStat
= nPageNr
+ *pPageCnt
- *pPageSt
+ 1;
1876 ::SetProgressState( nStat
, (SwDocShell
*)GetDocShell() );
1878 //Spell() changes the pSpellArgs in case an error is found
1879 xub_StrLen nBeginGrammarCheck
= 0;
1880 xub_StrLen nEndGrammarCheck
= 0;
1881 if( pSpellArgs
&& pSpellArgs
->bIsGrammarCheck
)
1883 nBeginGrammarCheck
= pSpellArgs
->pStartNode
== pNd
? pSpellArgs
->pStartIdx
->GetIndex() : 0;
1884 // if grammar checking starts inside of a sentence the start position has to be adjusted
1885 if( nBeginGrammarCheck
)
1887 SwIndex
aStartIndex( dynamic_cast< SwTxtNode
* >( pNd
), nBeginGrammarCheck
);
1888 SwPosition
aStart( *pNd
, aStartIndex
);
1889 SwCursor
aCrsr(aStart
, 0, false);
1890 SwPosition aOrigPos
= *aCrsr
.GetPoint();
1891 aCrsr
.GoSentence( SwCursor::START_SENT
);
1892 if( aOrigPos
!= *aCrsr
.GetPoint() )
1894 nBeginGrammarCheck
= aCrsr
.GetPoint()->nContent
.GetIndex();
1897 nEndGrammarCheck
= (pSpellArgs
->pEndNode
== pNd
)
1898 ? pSpellArgs
->pEndIdx
->GetIndex()
1899 : static_cast<SwTxtNode
const*>(pNd
)
1900 ->GetTxt().getLength();
1903 xub_StrLen nSpellErrorPosition
=
1904 static_cast<SwTxtNode
const*>(pNd
)->GetTxt().getLength();
1906 ((SwTxtNode
*)pNd
)->Spell( pSpellArgs
)) ||
1908 ((SwTxtNode
*)pNd
)->Convert( *pConvArgs
)))
1910 // Cancel and remember position
1911 pSttPos
->nNode
= nCurrNd
;
1912 pEndPos
->nNode
= nCurrNd
;
1915 nSpellErrorPosition
= pSpellArgs
->pStartIdx
->GetIndex() > pSpellArgs
->pEndIdx
->GetIndex() ?
1916 pSpellArgs
->pEndIdx
->GetIndex() :
1917 pSpellArgs
->pStartIdx
->GetIndex();
1921 if( pSpellArgs
&& pSpellArgs
->bIsGrammarCheck
)
1923 uno::Reference
< linguistic2::XProofreadingIterator
> xGCIterator( GetGCIterator() );
1924 if (xGCIterator
.is())
1926 uno::Reference
< lang::XComponent
> xDoc( ((SwDocShell
*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY
);
1927 // Expand the string:
1928 const ModelToViewHelper
aConversionMap(*(SwTxtNode
*)pNd
);
1929 OUString aExpandText
= aConversionMap
.getViewText();
1931 // get XFlatParagraph to use...
1932 uno::Reference
< text::XFlatParagraph
> xFlatPara
= new SwXFlatParagraph( *((SwTxtNode
*)pNd
), aExpandText
, aConversionMap
);
1934 // get error position of cursor in XFlatParagraph
1935 linguistic2::ProofreadingResult aResult
;
1936 sal_Int32 nGrammarErrors
;
1939 aConversionMap
.ConvertToViewPosition( nBeginGrammarCheck
);
1940 aResult
= xGCIterator
->checkSentenceAtPosition(
1941 xDoc
, xFlatPara
, aExpandText
, lang::Locale(), nBeginGrammarCheck
, -1, -1 );
1943 lcl_syncGrammarError( *((SwTxtNode
*)pNd
), aResult
, nBeginGrammarCheck
, aConversionMap
);
1945 // get suggestions to use for the specific error position
1946 nGrammarErrors
= aResult
.aErrors
.getLength();
1947 // if grammar checking doesn't have any progress then quit
1948 if( aResult
.nStartOfNextSentencePosition
<= nBeginGrammarCheck
)
1950 // prepare next iteration
1951 nBeginGrammarCheck
= (xub_StrLen
)aResult
.nStartOfNextSentencePosition
;
1953 while( nSpellErrorPosition
> aResult
.nBehindEndOfSentencePosition
&& !nGrammarErrors
&& aResult
.nBehindEndOfSentencePosition
< nEndGrammarCheck
);
1955 if( nGrammarErrors
> 0 && nSpellErrorPosition
>= aResult
.nBehindEndOfSentencePosition
)
1958 //put the cursor to the current error
1959 const linguistic2::SingleProofreadingError
&rError
= aResult
.aErrors
[0];
1960 nCurrNd
= pNd
->GetIndex();
1961 pSttPos
->nNode
= nCurrNd
;
1962 pEndPos
->nNode
= nCurrNd
;
1963 pSpellArgs
->pStartNode
= ((SwTxtNode
*)pNd
);
1964 pSpellArgs
->pEndNode
= ((SwTxtNode
*)pNd
);
1965 pSpellArgs
->pStartIdx
->Assign(((SwTxtNode
*)pNd
), (xub_StrLen
)aConversionMap
.ConvertToModelPosition( rError
.nErrorStart
).mnPos
);
1966 pSpellArgs
->pEndIdx
->Assign(((SwTxtNode
*)pNd
), (xub_StrLen
)aConversionMap
.ConvertToModelPosition( rError
.nErrorStart
+ rError
.nErrorLength
).mnPos
);
1974 case ND_SECTIONNODE
:
1975 if( ( ((SwSectionNode
*)pNd
)->GetSection().IsProtect() ||
1976 ((SwSectionNode
*)pNd
)->GetSection().IsHidden() ) )
1977 nCurrNd
= pNd
->EndOfSectionIndex();
1985 bGoOn
= nCurrNd
< nEndNd
;
1990 if( !aRet
.hasValue() )
1993 aRet
<<= pConvArgs
->aConvText
;
1995 aRet
<<= pSpellArgs
->xSpellAlt
;
2002 class SwHyphArgs
: public SwInterHyphInfo
2004 const SwNode
*pStart
;
2007 sal_uInt16
*pPageCnt
;
2008 sal_uInt16
*pPageSt
;
2011 xub_StrLen nPamStart
;
2015 SwHyphArgs( const SwPaM
*pPam
, const Point
&rPoint
,
2016 sal_uInt16
* pPageCount
, sal_uInt16
* pPageStart
);
2017 void SetPam( SwPaM
*pPam
) const;
2018 inline void SetNode( SwNode
*pNew
) { pNode
= pNew
; }
2019 inline const SwNode
*GetNode() const { return pNode
; }
2020 inline void SetRange( const SwNode
*pNew
);
2021 inline void NextNode() { ++nNode
; }
2022 inline sal_uInt16
*GetPageCnt() { return pPageCnt
; }
2023 inline sal_uInt16
*GetPageSt() { return pPageSt
; }
2026 SwHyphArgs::SwHyphArgs( const SwPaM
*pPam
, const Point
&rCrsrPos
,
2027 sal_uInt16
* pPageCount
, sal_uInt16
* pPageStart
)
2028 : SwInterHyphInfo( rCrsrPos
), pNode(0),
2029 pPageCnt( pPageCount
), pPageSt( pPageStart
)
2031 // The following constraints have to be met:
2032 // 1) there is at least one Selection
2033 // 2) SPoint() == Start()
2034 OSL_ENSURE( pPam
->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
2035 OSL_ENSURE( *pPam
->GetPoint() <= *pPam
->GetMark(),
2036 "SwDoc::Hyphenate: New York, New York");
2038 const SwPosition
*pPoint
= pPam
->GetPoint();
2039 nNode
= pPoint
->nNode
.GetIndex();
2042 pStart
= pPoint
->nNode
.GetNode().GetTxtNode();
2043 nPamStart
= pPoint
->nContent
.GetIndex();
2045 // Set End and Length
2046 const SwPosition
*pMark
= pPam
->GetMark();
2047 pEnd
= pMark
->nNode
.GetNode().GetTxtNode();
2048 nPamLen
= pMark
->nContent
.GetIndex();
2049 if( pPoint
->nNode
== pMark
->nNode
)
2050 nPamLen
= nPamLen
- pPoint
->nContent
.GetIndex();
2053 inline void SwHyphArgs::SetRange( const SwNode
*pNew
)
2055 nStart
= pStart
== pNew
? nPamStart
: 0;
2056 nLen
= pEnd
== pNew
? nPamLen
: STRING_NOTFOUND
;
2059 void SwHyphArgs::SetPam( SwPaM
*pPam
) const
2062 *pPam
->GetPoint() = *pPam
->GetMark();
2065 pPam
->GetPoint()->nNode
= nNode
;
2066 pPam
->GetPoint()->nContent
.Assign( pNode
->GetCntntNode(), nWordStart
);
2067 pPam
->GetMark()->nNode
= nNode
;
2068 pPam
->GetMark()->nContent
.Assign( pNode
->GetCntntNode(),
2069 nWordStart
+ nWordLen
);
2070 OSL_ENSURE( nNode
== pNode
->GetIndex(),
2071 "SwHyphArgs::SetPam: Pam disaster" );
2075 // Returns sal_True if we can proceed.
2076 static bool lcl_HyphenateNode( const SwNodePtr
& rpNd
, void* pArgs
)
2078 // Hyphenate returns true if there is a hyphenation point and sets pPam
2079 SwTxtNode
*pNode
= rpNd
->GetTxtNode();
2080 SwHyphArgs
*pHyphArgs
= (SwHyphArgs
*)pArgs
;
2083 SwCntntFrm
* pCntFrm
= pNode
->getLayoutFrm( pNode
->GetDoc()->GetCurrentLayout() );
2084 if( pCntFrm
&& !((SwTxtFrm
*)pCntFrm
)->IsHiddenNow() )
2086 sal_uInt16
*pPageSt
= pHyphArgs
->GetPageSt();
2087 sal_uInt16
*pPageCnt
= pHyphArgs
->GetPageCnt();
2088 if( pPageCnt
&& *pPageCnt
&& pPageSt
)
2090 sal_uInt16 nPageNr
= pCntFrm
->GetPhyPageNum();
2094 if( *pPageCnt
< *pPageSt
)
2095 *pPageCnt
= *pPageSt
;
2097 long nStat
= nPageNr
>= *pPageSt
? nPageNr
- *pPageSt
+ 1
2098 : nPageNr
+ *pPageCnt
- *pPageSt
+ 1;
2099 ::SetProgressState( nStat
, (SwDocShell
*)pNode
->GetDoc()->GetDocShell() );
2101 pHyphArgs
->SetRange( rpNd
);
2102 if( pNode
->Hyphenate( *pHyphArgs
) )
2104 pHyphArgs
->SetNode( rpNd
);
2109 pHyphArgs
->NextNode();
2113 uno::Reference
< XHyphenatedWord
> SwDoc::Hyphenate(
2114 SwPaM
*pPam
, const Point
&rCrsrPos
,
2115 sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
)
2117 OSL_ENSURE(this == pPam
->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
2119 if( *pPam
->GetPoint() > *pPam
->GetMark() )
2122 SwHyphArgs
aHyphArg( pPam
, rCrsrPos
, pPageCnt
, pPageSt
);
2123 SwNodeIndex
aTmpIdx( pPam
->GetMark()->nNode
, 1 );
2124 GetNodes().ForEach( pPam
->GetPoint()->nNode
, aTmpIdx
,
2125 lcl_HyphenateNode
, &aHyphArg
);
2126 aHyphArg
.SetPam( pPam
);
2127 return aHyphArg
.GetHyphWord(); // will be set by lcl_HyphenateNode
2130 static bool lcl_GetTokenToParaBreak( String
& rStr
, String
& rRet
, bool bRegExpRplc
)
2135 xub_StrLen nPos
= 0;
2136 OUString
sPara("\\n");
2137 while( STRING_NOTFOUND
!= ( nPos
= rStr
.Search( sPara
, nPos
)) )
2139 // Has this been escaped?
2140 if( nPos
&& '\\' == rStr
.GetChar( nPos
-1 ))
2142 if( ++nPos
>= rStr
.Len() )
2147 rRet
= rStr
.Copy( 0, nPos
);
2148 rStr
.Erase( 0, nPos
+ sPara
.getLength() );
2162 bool SwDoc::ReplaceRange( SwPaM
& rPam
, const String
& rStr
,
2163 const bool bRegExReplace
)
2165 // unfortunately replace works slightly differently from delete,
2166 // so we cannot use lcl_DoWithBreaks here...
2168 ::std::vector
<xub_StrLen
> Breaks
;
2170 SwPaM
aPam( *rPam
.GetMark(), *rPam
.GetPoint() );
2171 aPam
.Normalize(sal_False
);
2172 if (aPam
.GetPoint()->nNode
!= aPam
.GetMark()->nNode
)
2174 aPam
.Move(fnMoveBackward
);
2176 OSL_ENSURE((aPam
.GetPoint()->nNode
== aPam
.GetMark()->nNode
), "invalid pam?");
2178 lcl_CalcBreaks(Breaks
, aPam
);
2180 while (!Breaks
.empty() // skip over prefix of dummy chars
2181 && (aPam
.GetMark()->nContent
.GetIndex() == *Breaks
.begin()) )
2184 ++aPam
.GetMark()->nContent
; // always in bounds if Breaks valid
2185 Breaks
.erase(Breaks
.begin());
2187 *rPam
.Start() = *aPam
.GetMark(); // update start of original pam w/ prefix
2191 // park aPam somewhere so it does not point to node that is deleted
2193 *aPam
.GetPoint() = SwPosition(GetNodes().GetEndOfContent());
2194 return ReplaceRangeImpl(rPam
, rStr
, bRegExReplace
); // original pam!
2197 // Deletion must be split into several parts if the text node
2198 // contains a text attribute with end and with dummy character
2199 // and the selection does not contain the text attribute completely,
2200 // but overlaps its start (left), where the dummy character is.
2203 // iterate from end to start, to avoid invalidating the offsets!
2204 ::std::vector
<xub_StrLen
>::reverse_iterator
iter( Breaks
.rbegin() );
2205 OSL_ENSURE(aPam
.GetPoint() == aPam
.End(), "wrong!");
2206 SwPosition
& rEnd( *aPam
.End() );
2207 SwPosition
& rStart( *aPam
.Start() );
2209 // set end of temp pam to original end (undo Move backward above)
2211 // after first deletion, rEnd will point into the original text node again!
2213 while (iter
!= Breaks
.rend())
2215 rStart
.nContent
= *iter
+ 1;
2216 if (rEnd
.nContent
!= rStart
.nContent
) // check if part is empty
2218 bRet
&= (IsRedlineOn())
2219 ? DeleteAndJoinWithRedlineImpl(aPam
)
2220 : DeleteAndJoinImpl(aPam
, false);
2222 rEnd
.nContent
= *iter
;
2226 rStart
= *rPam
.Start(); // set to original start
2227 OSL_ENSURE(rEnd
.nContent
> rStart
.nContent
, "replace part empty!");
2228 if (rEnd
.nContent
> rStart
.nContent
) // check if part is empty
2230 bRet
&= ReplaceRangeImpl(aPam
, rStr
, bRegExReplace
);
2233 rPam
= aPam
; // update original pam (is this required?)
2238 // It's possible to call Replace with a PaM that spans 2 paragraphs:
2239 // search with regex for "$", then replace _all_
2240 bool SwDoc::ReplaceRangeImpl( SwPaM
& rPam
, const String
& rStr
,
2241 const bool bRegExReplace
)
2243 if( !rPam
.HasMark() || *rPam
.GetPoint() == *rPam
.GetMark() )
2246 sal_Bool bJoinTxt
, bJoinPrev
;
2247 sw_GetJoinFlags( rPam
, bJoinTxt
, bJoinPrev
);
2250 // Create a copy of the Cursor in order to move all Pams from
2251 // the other views out of the deletion range.
2252 // Except for itself!
2253 SwPaM
aDelPam( *rPam
.GetMark(), *rPam
.GetPoint() );
2254 ::PaMCorrAbs( aDelPam
, *aDelPam
.GetPoint() );
2256 SwPosition
*pStt
= (SwPosition
*)aDelPam
.Start(),
2257 *pEnd
= (SwPosition
*)aDelPam
.End();
2258 OSL_ENSURE( pStt
->nNode
== pEnd
->nNode
||
2259 ( pStt
->nNode
.GetIndex() + 1 == pEnd
->nNode
.GetIndex() &&
2260 !pEnd
->nContent
.GetIndex() ),
2261 "invalid range: Point and Mark on different nodes" );
2262 sal_Bool bOneNode
= pStt
->nNode
== pEnd
->nNode
;
2265 String
sRepl( rStr
);
2266 SwTxtNode
* pTxtNd
= pStt
->nNode
.GetNode().GetTxtNode();
2267 xub_StrLen nStt
= pStt
->nContent
.GetIndex(),
2268 nEnd
= bOneNode
? pEnd
->nContent
.GetIndex()
2269 : pTxtNd
->GetTxt().getLength();
2271 SwDataChanged
aTmp( aDelPam
);
2275 RedlineMode_t eOld
= GetRedlineMode();
2276 checkRedlining(eOld
);
2277 if (GetIDocumentUndoRedo().DoesUndo())
2279 GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY
, NULL
);
2281 // If any Redline will change (split!) the node
2282 const ::sw::mark::IMark
* pBkmk
= getIDocumentMarkAccess()->makeMark( aDelPam
, OUString(), IDocumentMarkAccess::UNO_BOOKMARK
);
2284 //JP 06.01.98: MUSS noch optimiert werden!!!
2286 (RedlineMode_t
)(nsRedlineMode_t::REDLINE_ON
| nsRedlineMode_t::REDLINE_SHOW_INSERT
| nsRedlineMode_t::REDLINE_SHOW_DELETE
));
2288 *aDelPam
.GetPoint() = pBkmk
->GetMarkPos();
2289 if(pBkmk
->IsExpanded())
2290 *aDelPam
.GetMark() = pBkmk
->GetOtherMarkPos();
2291 getIDocumentMarkAccess()->deleteMark(pBkmk
);
2292 pStt
= aDelPam
.Start();
2293 pTxtNd
= pStt
->nNode
.GetNode().GetTxtNode();
2294 nStt
= pStt
->nContent
.GetIndex();
2299 // Apply the first character's attributes to the ReplaceText
2300 SfxItemSet
aSet( GetAttrPool(),
2301 RES_CHRATR_BEGIN
, RES_TXTATR_WITHEND_END
- 1,
2302 RES_UNKNOWNATR_BEGIN
, RES_UNKNOWNATR_END
-1,
2304 pTxtNd
->GetAttr( aSet
, nStt
+1, nStt
+1 );
2306 aSet
.ClearItem( RES_TXTATR_REFMARK
);
2307 aSet
.ClearItem( RES_TXTATR_TOXMARK
);
2308 aSet
.ClearItem( RES_TXTATR_CJK_RUBY
);
2309 aSet
.ClearItem( RES_TXTATR_INETFMT
);
2310 aSet
.ClearItem( RES_TXTATR_META
);
2311 aSet
.ClearItem( RES_TXTATR_METAFIELD
);
2313 if( aDelPam
.GetPoint() != aDelPam
.End() )
2317 SwNodeIndex
aPtNd( aDelPam
.GetPoint()->nNode
, -1 );
2318 xub_StrLen nPtCnt
= aDelPam
.GetPoint()->nContent
.GetIndex();
2322 while ( lcl_GetTokenToParaBreak( sRepl
, sIns
, bRegExReplace
) )
2324 InsertString( aDelPam
, sIns
);
2327 SwNodeIndex
aMkNd( aDelPam
.GetMark()->nNode
, -1 );
2328 xub_StrLen nMkCnt
= aDelPam
.GetMark()->nContent
.GetIndex();
2330 SplitNode( *aDelPam
.GetPoint(), false );
2333 aDelPam
.GetMark()->nNode
= aMkNd
;
2334 aDelPam
.GetMark()->nContent
.Assign(
2335 aMkNd
.GetNode().GetCntntNode(), nMkCnt
);
2339 SplitNode( *aDelPam
.GetPoint(), false );
2343 InsertString( aDelPam
, sIns
);
2346 SwPaM
aTmpRange( *aDelPam
.GetPoint() );
2347 aTmpRange
.SetMark();
2350 aDelPam
.GetPoint()->nNode
= aPtNd
;
2351 aDelPam
.GetPoint()->nContent
.Assign( aPtNd
.GetNode().GetCntntNode(),
2353 *aTmpRange
.GetMark() = *aDelPam
.GetPoint();
2355 RstTxtAttrs( aTmpRange
);
2356 InsertItemSet( aTmpRange
, aSet
, 0 );
2359 if (GetIDocumentUndoRedo().DoesUndo())
2361 SwUndo
*const pUndoRD
=
2362 new SwUndoRedlineDelete( aDelPam
, UNDO_REPLACE
);
2363 GetIDocumentUndoRedo().AppendUndo(pUndoRD
);
2365 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE
, aDelPam
), true);
2367 *rPam
.GetMark() = *aDelPam
.GetMark();
2368 if (GetIDocumentUndoRedo().DoesUndo())
2370 *aDelPam
.GetPoint() = *rPam
.GetPoint();
2371 GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY
, NULL
);
2373 // If any Redline will change (split!) the node
2374 const ::sw::mark::IMark
* pBkmk
= getIDocumentMarkAccess()->makeMark( aDelPam
, OUString(), IDocumentMarkAccess::UNO_BOOKMARK
);
2376 SwIndex
& rIdx
= aDelPam
.GetPoint()->nContent
;
2377 rIdx
.Assign( 0, 0 );
2378 aDelPam
.GetMark()->nContent
= rIdx
;
2379 rPam
.GetPoint()->nNode
= 0;
2380 rPam
.GetPoint()->nContent
= rIdx
;
2381 *rPam
.GetMark() = *rPam
.GetPoint();
2382 //JP 06.01.98: MUSS noch optimiert werden!!!
2383 SetRedlineMode( eOld
);
2385 *rPam
.GetPoint() = pBkmk
->GetMarkPos();
2386 if(pBkmk
->IsExpanded())
2387 *rPam
.GetMark() = pBkmk
->GetOtherMarkPos();
2388 getIDocumentMarkAccess()->deleteMark(pBkmk
);
2390 bJoinTxt
= sal_False
;
2394 if( !IsIgnoreRedline() && GetRedlineTbl().size() )
2395 DeleteRedline( aDelPam
, true, USHRT_MAX
);
2397 SwUndoReplace
* pUndoRpl
= 0;
2398 bool const bDoesUndo
= GetIDocumentUndoRedo().DoesUndo();
2401 pUndoRpl
= new SwUndoReplace(aDelPam
, sRepl
, bRegExReplace
);
2402 GetIDocumentUndoRedo().AppendUndo(pUndoRpl
);
2404 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
2406 if( aDelPam
.GetPoint() != pStt
)
2409 SwNodeIndex
aPtNd( pStt
->nNode
, -1 );
2410 xub_StrLen nPtCnt
= pStt
->nContent
.GetIndex();
2412 // Set the values again, if Frames or footnotes on the Text have been removed.
2414 nEnd
= bOneNode
? pEnd
->nContent
.GetIndex()
2415 : pTxtNd
->GetTxt().getLength();
2419 while ( lcl_GetTokenToParaBreak( sRepl
, sIns
, bRegExReplace
) )
2421 if (!bFirst
|| nStt
== pTxtNd
->GetTxt().getLength())
2423 InsertString( aDelPam
, sIns
);
2425 else if( nStt
< nEnd
|| sIns
.Len() )
2427 pTxtNd
->ReplaceText( pStt
->nContent
, nEnd
- nStt
, sIns
);
2429 SplitNode( *pStt
, false);
2433 if( bFirst
|| sIns
.Len() )
2435 if (!bFirst
|| nStt
== pTxtNd
->GetTxt().getLength())
2437 InsertString( aDelPam
, sIns
);
2439 else if( nStt
< nEnd
|| sIns
.Len() )
2441 pTxtNd
->ReplaceText( pStt
->nContent
, nEnd
- nStt
, sIns
);
2445 *rPam
.GetPoint() = *aDelPam
.GetMark();
2447 rPam
.GetMark()->nNode
= aPtNd
;
2448 rPam
.GetMark()->nContent
.Assign( aPtNd
.GetNode().GetCntntNode(),
2453 assert(rPam
.GetPoint() == rPam
.End());
2454 // move so that SetEnd remembers position after sw_JoinText
2455 rPam
.Move(fnMoveBackward
);
2457 else if (aDelPam
.GetPoint() == pStt
) // backward selection?
2459 assert(*rPam
.GetMark() <= *rPam
.GetPoint());
2460 rPam
.Exchange(); // swap so that rPam is backwards
2465 pUndoRpl
->SetEnd(rPam
);
2471 sw_JoinText( rPam
, bJoinPrev
);
2477 // Save the current values to add them as automatic entries to to AutoCorrect.
2478 void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord
* pNew
)
2480 if( pNew
!= mpACEWord
)
2485 bool SwDoc::DelFullPara( SwPaM
& rPam
)
2487 const SwPosition
&rStt
= *rPam
.Start(), &rEnd
= *rPam
.End();
2488 const SwNode
* pNd
= &rStt
.nNode
.GetNode();
2489 sal_uInt32 nSectDiff
= pNd
->StartOfSectionNode()->EndOfSectionIndex() -
2490 pNd
->StartOfSectionIndex();
2491 sal_uInt32 nNodeDiff
= rEnd
.nNode
.GetIndex() - rStt
.nNode
.GetIndex();
2493 if ( nSectDiff
-2 <= nNodeDiff
|| IsRedlineOn() ||
2494 /* #i9185# Prevent getting the node after the end node (see below) */
2495 rEnd
.nNode
.GetIndex() + 1 == GetNodes().Count() )
2500 // Move hard page brakes to the following Node.
2501 sal_Bool bSavePageBreak
= sal_False
, bSavePageDesc
= sal_False
;
2503 /* #i9185# This whould lead to a segmentation fault if not caught above. */
2504 sal_uLong nNextNd
= rEnd
.nNode
.GetIndex() + 1;
2505 SwTableNode
*const pTblNd
= GetNodes()[ nNextNd
]->GetTableNode();
2507 if( pTblNd
&& pNd
->IsCntntNode() )
2509 SwFrmFmt
* pTableFmt
= pTblNd
->GetTable().GetFrmFmt();
2512 const SfxPoolItem
*pItem
;
2513 const SfxItemSet
* pSet
= ((SwCntntNode
*)pNd
)->GetpSwAttrSet();
2514 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState( RES_PAGEDESC
,
2515 sal_False
, &pItem
) )
2517 pTableFmt
->SetFmtAttr( *pItem
);
2518 bSavePageDesc
= sal_True
;
2521 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
,
2522 sal_False
, &pItem
) )
2524 pTableFmt
->SetFmtAttr( *pItem
);
2525 bSavePageBreak
= sal_True
;
2530 bool const bDoesUndo
= GetIDocumentUndoRedo().DoesUndo();
2533 if( !rPam
.HasMark() )
2535 else if( rPam
.GetPoint() == &rStt
)
2537 rPam
.GetPoint()->nNode
++;
2539 SwCntntNode
*pTmpNode
= rPam
.GetPoint()->nNode
.GetNode().GetCntntNode();
2540 rPam
.GetPoint()->nContent
.Assign( pTmpNode
, 0 );
2541 bool bGoNext
= (0 == pTmpNode
);
2542 pTmpNode
= rPam
.GetMark()->nNode
.GetNode().GetCntntNode();
2543 rPam
.GetMark()->nContent
.Assign( pTmpNode
, 0 );
2545 GetIDocumentUndoRedo().ClearRedo();
2547 SwPaM
aDelPam( *rPam
.GetMark(), *rPam
.GetPoint() );
2549 SwPosition
aTmpPos( *aDelPam
.GetPoint() );
2552 pTmpNode
= GetNodes().GoNext( &aTmpPos
.nNode
);
2553 aTmpPos
.nContent
.Assign( pTmpNode
, 0 );
2555 ::PaMCorrAbs( aDelPam
, aTmpPos
);
2558 SwUndoDelete
* pUndo
= new SwUndoDelete( aDelPam
, sal_True
);
2560 *rPam
.GetPoint() = *aDelPam
.GetPoint();
2561 pUndo
->SetPgBrkFlags( bSavePageBreak
, bSavePageDesc
);
2562 GetIDocumentUndoRedo().AppendUndo(pUndo
);
2566 SwNodeRange
aRg( rStt
.nNode
, rEnd
.nNode
);
2567 if( rPam
.GetPoint() != &rEnd
)
2570 // Try to move past the End
2571 if( !rPam
.Move( fnMoveForward
, fnGoNode
) )
2573 // Fair enough, at the Beginning then
2575 if( !rPam
.Move( fnMoveBackward
, fnGoNode
))
2577 OSL_FAIL( "no more Nodes" );
2581 // move bookmarks, redlines etc.
2582 if (aRg
.aStart
== aRg
.aEnd
) // only first CorrAbs variant handles this
2584 CorrAbs( aRg
.aStart
, *rPam
.GetPoint(), 0, sal_True
);
2588 CorrAbs( aRg
.aStart
, aRg
.aEnd
, *rPam
.GetPoint(), sal_True
);
2591 // What's with Flys?
2593 // If there are FlyFrames left, delete these too
2594 for( sal_uInt16 n
= 0; n
< GetSpzFrmFmts()->size(); ++n
)
2596 SwFrmFmt
* pFly
= (*GetSpzFrmFmts())[n
];
2597 const SwFmtAnchor
* pAnchor
= &pFly
->GetAnchor();
2598 SwPosition
const*const pAPos
= pAnchor
->GetCntntAnchor();
2600 ((FLY_AT_PARA
== pAnchor
->GetAnchorId()) ||
2601 (FLY_AT_CHAR
== pAnchor
->GetAnchorId())) &&
2602 aRg
.aStart
<= pAPos
->nNode
&& pAPos
->nNode
<= aRg
.aEnd
)
2604 DelLayoutFmt( pFly
);
2610 SwCntntNode
*pTmpNode
= rPam
.GetBound( sal_True
).nNode
.GetNode().GetCntntNode();
2611 rPam
.GetBound( sal_True
).nContent
.Assign( pTmpNode
, 0 );
2612 pTmpNode
= rPam
.GetBound( sal_False
).nNode
.GetNode().GetCntntNode();
2613 rPam
.GetBound( sal_False
).nContent
.Assign( pTmpNode
, 0 );
2614 GetNodes().Delete( aRg
.aStart
, nNodeDiff
+1 );
2622 void SwDoc::TransliterateText(
2624 utl::TransliterationWrapper
& rTrans
)
2626 SwUndoTransliterate
*const pUndo
= (GetIDocumentUndoRedo().DoesUndo())
2627 ? new SwUndoTransliterate( rPaM
, rTrans
)
2630 const SwPosition
* pStt
= rPaM
.Start(),
2631 * pEnd
= rPaM
.End();
2632 sal_uLong nSttNd
= pStt
->nNode
.GetIndex(),
2633 nEndNd
= pEnd
->nNode
.GetIndex();
2634 xub_StrLen nSttCnt
= pStt
->nContent
.GetIndex(),
2635 nEndCnt
= pEnd
->nContent
.GetIndex();
2637 SwTxtNode
* pTNd
= pStt
->nNode
.GetNode().GetTxtNode();
2638 if( pStt
== pEnd
&& pTNd
) // no selection?
2640 // set current word as 'area of effect'
2643 if( g_pBreakIt
->GetBreakIter().is() )
2644 aBndry
= g_pBreakIt
->GetBreakIter()->getWordBoundary(
2645 pTNd
->GetTxt(), nSttCnt
,
2646 g_pBreakIt
->GetLocale( pTNd
->GetLang( nSttCnt
) ),
2647 WordType::ANY_WORD
/*ANYWORD_IGNOREWHITESPACES*/,
2650 if( aBndry
.startPos
< nSttCnt
&& nSttCnt
< aBndry
.endPos
)
2652 nSttCnt
= (xub_StrLen
)aBndry
.startPos
;
2653 nEndCnt
= (xub_StrLen
)aBndry
.endPos
;
2657 if( nSttNd
!= nEndNd
) // is more than one text node involved?
2659 // iterate over all effected text nodes, the first and the last one
2660 // may be incomplete because the selection starts and/or ends there
2662 SwNodeIndex
aIdx( pStt
->nNode
);
2667 pTNd
->TransliterateText(
2668 rTrans
, nSttCnt
, pTNd
->GetTxt().getLength(), pUndo
);
2671 for( ; aIdx
.GetIndex() < nEndNd
; ++aIdx
)
2673 pTNd
= aIdx
.GetNode().GetTxtNode();
2676 pTNd
->TransliterateText(
2677 rTrans
, 0, pTNd
->GetTxt().getLength(), pUndo
);
2681 if( nEndCnt
&& 0 != ( pTNd
= pEnd
->nNode
.GetNode().GetTxtNode() ))
2682 pTNd
->TransliterateText( rTrans
, 0, nEndCnt
, pUndo
);
2684 else if( pTNd
&& nSttCnt
< nEndCnt
)
2685 pTNd
->TransliterateText( rTrans
, nSttCnt
, nEndCnt
, pUndo
);
2689 if( pUndo
->HasData() )
2691 GetIDocumentUndoRedo().AppendUndo(pUndo
);
2699 #define MAX_REDLINE_COUNT 250
2701 void SwDoc::checkRedlining(RedlineMode_t
& _rReadlineMode
)
2703 const SwRedlineTbl
& rRedlineTbl
= GetRedlineTbl();
2704 SwEditShell
* pEditShell
= GetEditShell();
2705 Window
* pParent
= pEditShell
? pEditShell
->GetWin() : NULL
;
2706 if ( pParent
&& !mbReadlineChecked
&& rRedlineTbl
.size() > MAX_REDLINE_COUNT
2707 && !((_rReadlineMode
& nsRedlineMode_t::REDLINE_SHOW_DELETE
) == nsRedlineMode_t::REDLINE_SHOW_DELETE
) )
2709 WarningBox
aWarning( pParent
,SW_RES(MSG_DISABLE_READLINE_QUESTION
));
2710 sal_uInt16 nResult
= aWarning
.Execute();
2711 mbReadlineChecked
= sal_True
;
2712 if ( nResult
== RET_YES
)
2714 sal_Int32 nMode
= (sal_Int32
)_rReadlineMode
;
2715 nMode
|= nsRedlineMode_t::REDLINE_SHOW_INSERT
| nsRedlineMode_t::REDLINE_SHOW_DELETE
;
2716 _rReadlineMode
= (RedlineMode_t
)nMode
;
2721 void SwDoc::CountWords( const SwPaM
& rPaM
, SwDocStat
& rStat
) const
2723 // This is a modified version of SwDoc::TransliterateText
2724 const SwPosition
* pStt
= rPaM
.Start();
2725 const SwPosition
* pEnd
= pStt
== rPaM
.GetPoint() ? rPaM
.GetMark()
2728 const sal_uLong nSttNd
= pStt
->nNode
.GetIndex();
2729 const sal_uLong nEndNd
= pEnd
->nNode
.GetIndex();
2731 const xub_StrLen nSttCnt
= pStt
->nContent
.GetIndex();
2732 const xub_StrLen nEndCnt
= pEnd
->nContent
.GetIndex();
2734 const SwTxtNode
* pTNd
= pStt
->nNode
.GetNode().GetTxtNode();
2735 if( pStt
== pEnd
&& pTNd
) // no region ?
2741 if( nSttNd
!= nEndNd
)
2743 SwNodeIndex
aIdx( pStt
->nNode
);
2748 pTNd
->CountWords( rStat
, nSttCnt
, pTNd
->GetTxt().getLength() );
2751 for( ; aIdx
.GetIndex() < nEndNd
; ++aIdx
)
2752 if( 0 != ( pTNd
= aIdx
.GetNode().GetTxtNode() ))
2753 pTNd
->CountWords( rStat
, 0, pTNd
->GetTxt().getLength() );
2755 if( nEndCnt
&& 0 != ( pTNd
= pEnd
->nNode
.GetNode().GetTxtNode() ))
2756 pTNd
->CountWords( rStat
, 0, nEndCnt
);
2758 else if( pTNd
&& nSttCnt
< nEndCnt
)
2759 pTNd
->CountWords( rStat
, nSttCnt
, nEndCnt
);
2762 void SwDoc::RemoveLeadingWhiteSpace(const SwPosition
& rPos
)
2764 const SwTxtNode
* pTNd
= rPos
.nNode
.GetNode().GetTxtNode();
2767 const OUString
& rTxt
= pTNd
->GetTxt();
2768 xub_StrLen nIdx
= 0;
2769 while (nIdx
< rTxt
.getLength())
2771 sal_Unicode
const cCh
= rTxt
[nIdx
];
2772 if (('\t' != cCh
) && (' ' != cCh
))
2782 aPam
.GetPoint()->nContent
= 0;
2784 aPam
.GetMark()->nContent
= nIdx
;
2785 DeleteRange( aPam
);
2790 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */