1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docedt.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <string.h> // fuer strchr()
35 #include <hintids.hxx>
37 #include <vcl/sound.hxx>
38 #include <svx/cscoitem.hxx>
39 #include <svx/brkitem.hxx>
40 #include <linguistic/lngprops.hxx>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/i18n/WordType.hdl>
43 #include <unotools/charclass.hxx>
44 #include <fmtanchr.hxx>
45 #include <fmtcntnt.hxx>
46 #include <fmtpdsc.hxx>
48 #include <acorrect.hxx> // Autokorrektur
49 #include <IMark.hxx> // fuer SwBookmark
50 #include <cntfrm.hxx> // fuers Spell
55 #include <doctxm.hxx> // beim Move: Verzeichnisse korrigieren
57 #include <ftninfo.hxx>
58 #include <mdiexp.hxx> // Statusanzeige
59 #include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
62 #include <redline.hxx>
63 #include <rootfrm.hxx> // fuers UpdateFtn
64 #include <splargs.hxx> // fuer Spell
65 #include <swtable.hxx>
66 #include <swundo.hxx> // fuer die UndoIds
69 #include <breakit.hxx>
71 #include <breakit.hxx>
72 #include <vcl/msgbox.hxx>
73 #include "comcore.hrc"
75 #include <unoflatpara.hxx>
76 #include <SwGrammarMarkUp.hxx>
78 using ::rtl::OUString
;
79 using namespace ::com::sun::star
;
80 using namespace ::com::sun::star::linguistic2
;
81 using namespace ::com::sun::star::i18n
;
83 //using namespace ::utl;
85 #define S2U(rString) OUString::createFromAscii(rString)
91 sal_uInt32 nStt
, nEnd
;
92 xub_StrLen nSttCnt
, nEndCnt
;
94 _SaveRedline( SwRedline
* pR
, const SwNodeIndex
& rSttIdx
)
97 const SwPosition
* pStt
= pR
->Start(),
98 * pEnd
= pR
->GetMark() == pStt
? pR
->GetPoint() : pR
->GetMark();
99 sal_uInt32 nSttIdx
= rSttIdx
.GetIndex();
100 nStt
= pStt
->nNode
.GetIndex() - nSttIdx
;
101 nSttCnt
= pStt
->nContent
.GetIndex();
104 nEnd
= pEnd
->nNode
.GetIndex() - nSttIdx
;
105 nEndCnt
= pEnd
->nContent
.GetIndex();
108 pRedl
->GetPoint()->nNode
= 0;
109 pRedl
->GetPoint()->nContent
.Assign( 0, 0 );
110 pRedl
->GetMark()->nNode
= 0;
111 pRedl
->GetMark()->nContent
.Assign( 0, 0 );
114 _SaveRedline( SwRedline
* pR
, const SwPosition
& rPos
)
117 const SwPosition
* pStt
= pR
->Start(),
118 * pEnd
= pR
->GetMark() == pStt
? pR
->GetPoint() : pR
->GetMark();
119 sal_uInt32 nSttIdx
= rPos
.nNode
.GetIndex();
120 nStt
= pStt
->nNode
.GetIndex() - nSttIdx
;
121 nSttCnt
= pStt
->nContent
.GetIndex();
123 nSttCnt
= nSttCnt
- rPos
.nContent
.GetIndex();
126 nEnd
= pEnd
->nNode
.GetIndex() - nSttIdx
;
127 nEndCnt
= pEnd
->nContent
.GetIndex();
129 nEndCnt
= nEndCnt
- rPos
.nContent
.GetIndex();
132 pRedl
->GetPoint()->nNode
= 0;
133 pRedl
->GetPoint()->nContent
.Assign( 0, 0 );
134 pRedl
->GetMark()->nNode
= 0;
135 pRedl
->GetMark()->nContent
.Assign( 0, 0 );
138 void SetPos( sal_uInt32 nInsPos
)
140 pRedl
->GetPoint()->nNode
= nInsPos
+ nStt
;
141 pRedl
->GetPoint()->nContent
.Assign( pRedl
->GetCntntNode(), nSttCnt
);
142 if( pRedl
->HasMark() )
144 pRedl
->GetMark()->nNode
= nInsPos
+ nEnd
;
145 pRedl
->GetMark()->nContent
.Assign( pRedl
->GetCntntNode(sal_False
), nEndCnt
);
149 void SetPos( const SwPosition
& aPos
)
151 pRedl
->GetPoint()->nNode
= aPos
.nNode
.GetIndex() + nStt
;
152 pRedl
->GetPoint()->nContent
.Assign( pRedl
->GetCntntNode(), nSttCnt
+ ( nStt
== 0 ? aPos
.nContent
.GetIndex() : 0 ) );
153 if( pRedl
->HasMark() )
155 pRedl
->GetMark()->nNode
= aPos
.nNode
.GetIndex() + nEnd
;
156 pRedl
->GetMark()->nContent
.Assign( pRedl
->GetCntntNode(sal_False
), nEndCnt
+ ( nEnd
== 0 ? aPos
.nContent
.GetIndex() : 0 ) );
161 SV_DECL_PTRARR_DEL( _SaveRedlines
, _SaveRedline
*, 0, 4 )
163 SV_IMPL_VARARR( _SaveFlyArr
, _SaveFly
)
164 SV_IMPL_PTRARR( _SaveRedlines
, _SaveRedline
* )
166 bool lcl_MayOverwrite( const SwTxtNode
*pNode
, const xub_StrLen nPos
)
168 sal_Unicode cChr
= pNode
->GetTxt().GetChar( nPos
);
169 return !( ( CH_TXTATR_BREAKWORD
== cChr
|| CH_TXTATR_INWORD
== cChr
) &&
170 (0 != pNode
->GetTxtAttrForCharAt( nPos
) ) );
173 void lcl_SkipAttr( const SwTxtNode
*pNode
, SwIndex
&rIdx
, xub_StrLen
&rStart
)
175 if( !lcl_MayOverwrite( pNode
, rStart
) )
177 // ueberspringe alle SonderAttribute
179 // "Beep" bei jedem ausgelassenen
180 Sound::Beep(SOUND_ERROR
);
182 } while( (rStart
= rIdx
.GetIndex()) < pNode
->GetTxt().Len()
183 && !lcl_MayOverwrite(pNode
, rStart
) );
187 // -----------------------------------------------------------------
189 void _RestFlyInRange( _SaveFlyArr
& rArr
, const SwNodeIndex
& rSttIdx
,
190 const SwNodeIndex
* pInsertPos
)
192 SwPosition
aPos( rSttIdx
);
193 for( sal_uInt16 n
= 0; n
< rArr
.Count(); ++n
)
195 // neuen Anker anlegen
196 _SaveFly
& rSave
= rArr
[n
];
197 SwFrmFmt
* pFmt
= rSave
.pFrmFmt
;
199 if( rSave
.bInsertPosition
)
201 if( pInsertPos
!= NULL
)
202 aPos
.nNode
= *pInsertPos
;
204 aPos
.nNode
= rSttIdx
.GetIndex();
207 aPos
.nNode
= rSttIdx
.GetIndex() + rSave
.nNdDiff
;
209 aPos
.nContent
.Assign( 0, 0 );
210 SwFmtAnchor
aAnchor( pFmt
->GetAnchor() );
211 aAnchor
.SetAnchor( &aPos
);
212 pFmt
->GetDoc()->GetSpzFrmFmts()->Insert(
213 pFmt
, pFmt
->GetDoc()->GetSpzFrmFmts()->Count() );
214 pFmt
->SetFmtAttr( aAnchor
);
215 SwCntntNode
* pCNd
= aPos
.nNode
.GetNode().GetCntntNode();
216 if( pCNd
&& pCNd
->GetFrm( 0, 0, sal_False
) )
221 void _SaveFlyInRange( const SwNodeRange
& rRg
, _SaveFlyArr
& rArr
)
224 const SwFmtAnchor
* pAnchor
;
225 const SwPosition
* pAPos
;
226 SwSpzFrmFmts
& rFmts
= *rRg
.aStart
.GetNode().GetDoc()->GetSpzFrmFmts();
227 for( sal_uInt16 n
= 0; n
< rFmts
.Count(); ++n
)
229 pFmt
= (SwFrmFmt
*)rFmts
[n
];
230 pAnchor
= &pFmt
->GetAnchor();
231 if( ( FLY_AT_CNTNT
== pAnchor
->GetAnchorId() ||
232 FLY_AUTO_CNTNT
== pAnchor
->GetAnchorId() ) &&
233 0 != ( pAPos
= pAnchor
->GetCntntAnchor() ) &&
234 rRg
.aStart
<= pAPos
->nNode
&& pAPos
->nNode
< rRg
.aEnd
)
236 _SaveFly
aSave( pAPos
->nNode
.GetIndex() - rRg
.aStart
.GetIndex(),
238 rArr
.Insert( aSave
, rArr
.Count());
240 rFmts
.Remove( n
--, 1 );
245 void _SaveFlyInRange( const SwPaM
& rPam
, const SwNodeIndex
& rInsPos
,
246 _SaveFlyArr
& rArr
, bool bMoveAllFlys
)
248 SwSpzFrmFmts
& rFmts
= *rPam
.GetPoint()->nNode
.GetNode().GetDoc()->GetSpzFrmFmts();
250 const SwFmtAnchor
* pAnchor
;
252 const SwPosition
* pPos
= rPam
.Start();
253 const SwNodeIndex
& rSttNdIdx
= pPos
->nNode
;
254 short nSttOff
= (!bMoveAllFlys
&& rSttNdIdx
.GetNode().IsCntntNode() &&
255 pPos
->nContent
.GetIndex()) ? 1 : 0;
257 pPos
= rPam
.GetPoint() == pPos
? rPam
.GetMark() : rPam
.GetPoint();
258 const SwNodeIndex
& rEndNdIdx
= pPos
->nNode
;
259 short nOff
= ( bMoveAllFlys
|| ( rEndNdIdx
.GetNode().IsCntntNode() &&
260 pPos
->nContent
== rEndNdIdx
.GetNode().GetCntntNode()->Len() ))
263 const SwPosition
* pAPos
;
264 const SwNodeIndex
* pCntntIdx
;
266 for( sal_uInt16 n
= 0; n
< rFmts
.Count(); ++n
)
268 sal_Bool bInsPos
= sal_False
;
269 pFmt
= (SwFrmFmt
*)rFmts
[n
];
270 pAnchor
= &pFmt
->GetAnchor();
271 if( ( FLY_AT_CNTNT
== pAnchor
->GetAnchorId() ||
272 FLY_AUTO_CNTNT
== pAnchor
->GetAnchorId() ) &&
273 0 != ( pAPos
= pAnchor
->GetCntntAnchor() ) &&
274 // nicht verschieben, wenn die InsPos im CntntBereich vom Fly ist
275 ( 0 == ( pCntntIdx
= pFmt
->GetCntnt().GetCntntIdx() ) ||
276 !( *pCntntIdx
< rInsPos
&&
277 rInsPos
< pCntntIdx
->GetNode().EndOfSectionIndex() )) )
279 if( !bMoveAllFlys
&& rEndNdIdx
== pAPos
->nNode
)
281 // wenn nur teil vom EndNode oder der EndNode und SttNode
282 // identisch sind, chaos::Anchor nicht anfassen
283 if( rSttNdIdx
!= pAPos
->nNode
)
285 // Anker nur an Anfang/Ende haengen
286 SwPosition
aPos( rSttNdIdx
);
287 SwFmtAnchor
aAnchor( *pAnchor
);
288 aAnchor
.SetAnchor( &aPos
);
289 pFmt
->SetFmtAttr( aAnchor
);
290 // ((SwFmtAnchor*)pAnchor)->SetAnchor( &aPos );
293 else if( ( rSttNdIdx
.GetIndex() + nSttOff
<= pAPos
->nNode
.GetIndex()
294 && pAPos
->nNode
.GetIndex() <= rEndNdIdx
.GetIndex() - nOff
) ||
295 0 != ( bInsPos
= rInsPos
== pAPos
->nNode
))
298 _SaveFly
aSave( pAPos
->nNode
.GetIndex() - rSttNdIdx
.GetIndex(),
300 rArr
.Insert( aSave
, rArr
.Count());
302 rFmts
.Remove( n
--, 1 );
308 // -----------------------------------------------------------------
310 // loesche und verschiebe alle "Fly's am Absatz", die in der SSelection
311 // liegen. Steht am SPoint ein Fly, wird dieser auf den Mark verschoben.
313 void DelFlyInRange( const SwNodeIndex
& rMkNdIdx
,
314 const SwNodeIndex
& rPtNdIdx
)
316 const sal_Bool bDelFwrd
= rMkNdIdx
.GetIndex() <= rPtNdIdx
.GetIndex();
318 SwDoc
* pDoc
= rMkNdIdx
.GetNode().GetDoc();
319 SwSpzFrmFmts
& rTbl
= *pDoc
->GetSpzFrmFmts();
320 const SwPosition
* pAPos
;
321 for ( sal_uInt16 i
= rTbl
.Count(); i
; )
323 SwFrmFmt
*pFmt
= rTbl
[--i
];
324 const SwFmtAnchor
&rAnch
= pFmt
->GetAnchor();
325 if( ( rAnch
.GetAnchorId() == FLY_AT_CNTNT
||
326 rAnch
.GetAnchorId() == FLY_AUTO_CNTNT
) &&
327 0 != ( pAPos
= rAnch
.GetCntntAnchor() ) &&
329 ? rMkNdIdx
< pAPos
->nNode
&& pAPos
->nNode
<= rPtNdIdx
330 : rPtNdIdx
<= pAPos
->nNode
&& pAPos
->nNode
< rMkNdIdx
))
332 // nur den Anker verschieben ??
333 if( rPtNdIdx
== pAPos
->nNode
)
335 SwFmtAnchor
aAnch( pFmt
->GetAnchor() );
336 SwPosition
aPos( rMkNdIdx
);
337 aAnch
.SetAnchor( &aPos
);
338 pFmt
->SetFmtAttr( aAnch
);
342 // wird der Fly geloescht muss auch im seinem Inhalt alle
343 // Flys geloescht werden !!
344 const SwFmtCntnt
&rCntnt
= pFmt
->GetCntnt();
345 if( rCntnt
.GetCntntIdx() )
347 DelFlyInRange( *rCntnt
.GetCntntIdx(),
348 SwNodeIndex( *rCntnt
.GetCntntIdx()->
349 GetNode().EndOfSectionNode() ));
350 // Position kann sich verschoben haben !
351 if( i
> rTbl
.Count() )
353 else if( pFmt
!= rTbl
[i
] )
354 i
= rTbl
.GetPos( pFmt
);
357 pDoc
->DelLayoutFmt( pFmt
);
359 // --> FME 2004-10-06 #117913# DelLayoutFmt can also
360 // trigger the deletion of objects.
361 if( i
> rTbl
.Count() )
370 bool lcl_SaveFtn( const SwNodeIndex
& rSttNd
, const SwNodeIndex
& rEndNd
,
371 const SwNodeIndex
& rInsPos
,
372 SwFtnIdxs
& rFtnArr
, SwFtnIdxs
& rSaveArr
,
373 const SwIndex
* pSttCnt
= 0, const SwIndex
* pEndCnt
= 0 )
375 bool bUpdateFtn
= sal_False
;
376 const SwNodes
& rNds
= rInsPos
.GetNodes();
377 const bool bDelFtn
= rInsPos
.GetIndex() < rNds
.GetEndOfAutotext().GetIndex() &&
378 rSttNd
.GetIndex() >= rNds
.GetEndOfAutotext().GetIndex();
379 const bool bSaveFtn
= !bDelFtn
&&
380 rInsPos
.GetIndex() >= rNds
.GetEndOfExtras().GetIndex();
381 if( rFtnArr
.Count() )
385 rFtnArr
.SeekEntry( rSttNd
, &nPos
);
387 const SwNode
* pFtnNd
;
389 // loesche/sicher erstmal alle, die dahinter stehen
390 while( nPos
< rFtnArr
.Count() && ( pFtnNd
=
391 &( pSrch
= rFtnArr
[ nPos
] )->GetTxtNode())->GetIndex()
392 <= rEndNd
.GetIndex() )
394 xub_StrLen nFtnSttIdx
= *pSrch
->GetStart();
395 if( ( pEndCnt
&& pSttCnt
)
396 ? (( &rSttNd
.GetNode() == pFtnNd
&&
397 pSttCnt
->GetIndex() > nFtnSttIdx
) ||
398 ( &rEndNd
.GetNode() == pFtnNd
&&
399 nFtnSttIdx
>= pEndCnt
->GetIndex() ))
400 : ( &rEndNd
.GetNode() == pFtnNd
))
402 ++nPos
; // weiter suchen
409 SwTxtNode
& rTxtNd
= (SwTxtNode
&)pSrch
->GetTxtNode();
410 SwIndex
aIdx( &rTxtNd
, nFtnSttIdx
);
411 rTxtNd
.EraseText( aIdx
, 1 );
416 rFtnArr
.Remove( nPos
);
418 rSaveArr
.Insert( pSrch
);
420 bUpdateFtn
= sal_True
;
424 while( nPos
-- && ( pFtnNd
= &( pSrch
= rFtnArr
[ nPos
] )->
425 GetTxtNode())->GetIndex() >= rSttNd
.GetIndex() )
427 xub_StrLen nFtnSttIdx
= *pSrch
->GetStart();
428 if( !pEndCnt
|| !pSttCnt
||
429 !( (( &rSttNd
.GetNode() == pFtnNd
&&
430 pSttCnt
->GetIndex() > nFtnSttIdx
) ||
431 ( &rEndNd
.GetNode() == pFtnNd
&&
432 nFtnSttIdx
>= pEndCnt
->GetIndex() )) ))
437 SwTxtNode
& rTxtNd
= (SwTxtNode
&)pSrch
->GetTxtNode();
438 SwIndex
aIdx( &rTxtNd
, nFtnSttIdx
);
439 rTxtNd
.EraseText( aIdx
, 1 );
444 rFtnArr
.Remove( nPos
);
446 rSaveArr
.Insert( pSrch
);
448 bUpdateFtn
= sal_True
;
452 // When moving from redline section into document content section, e.g.
453 // after loading a document with (delete-)redlines, the footnote array
454 // has to be adjusted... (#i70572)
457 SwNodeIndex
aIdx( rSttNd
);
458 while( aIdx
< rEndNd
) // Check the moved section
460 SwNode
* pNode
= &aIdx
.GetNode();
461 if( pNode
->IsTxtNode() ) // Looking for text nodes...
464 static_cast<SwTxtNode
*>(pNode
)->GetpSwpHints();
465 if( pHints
&& pHints
->HasFtn() ) //...with footnotes
467 bUpdateFtn
= sal_True
; // Heureka
468 USHORT nCount
= pHints
->Count();
469 for( USHORT i
= 0; i
< nCount
; ++i
)
471 SwTxtAttr
*pAttr
= pHints
->GetTextHint( i
);
472 if ( pAttr
->Which() == RES_TXTATR_FTN
)
474 rSaveArr
.Insert( static_cast<SwTxtFtn
*>(pAttr
) );
485 void lcl_SaveRedlines( const SwPaM
& aPam
, _SaveRedlines
& rArr
)
487 SwDoc
* pDoc
= aPam
.GetNode()->GetDoc();
489 const SwPosition
* pStart
= aPam
.Start();
490 const SwPosition
* pEnd
= aPam
.End();
492 // get first relevant redline
493 sal_uInt16 nCurrentRedline
;
494 pDoc
->GetRedline( *pStart
, &nCurrentRedline
);
495 if( nCurrentRedline
> 0)
498 // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
499 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
500 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
502 // iterate over relevant redlines and decide for each whether it should
503 // be saved, or split + saved
504 SwRedlineTbl
& rRedlineTable
= const_cast<SwRedlineTbl
&>( pDoc
->GetRedlineTbl() );
505 for( ; nCurrentRedline
< rRedlineTable
.Count(); nCurrentRedline
++ )
507 SwRedline
* pCurrent
= rRedlineTable
[ nCurrentRedline
];
508 SwComparePosition eCompare
=
509 ComparePosition( *pCurrent
->Start(), *pCurrent
->End(),
512 // we must save this redline if it overlaps aPam
513 // (we may have to split it, too)
514 if( eCompare
== POS_OVERLAP_BEHIND
||
515 eCompare
== POS_OVERLAP_BEFORE
||
516 eCompare
== POS_OUTSIDE
||
517 eCompare
== POS_INSIDE
||
518 eCompare
== POS_EQUAL
)
520 rRedlineTable
.Remove( nCurrentRedline
-- );
522 // split beginning, if necessary
523 if( eCompare
== POS_OVERLAP_BEFORE
||
524 eCompare
== POS_OUTSIDE
)
527 SwRedline
* pNewRedline
= new SwRedline( *pCurrent
);
528 *pNewRedline
->End() = *pStart
;
529 *pCurrent
->Start() = *pStart
;
530 pDoc
->AppendRedline( pNewRedline
, true );
533 // split end, if necessary
534 if( eCompare
== POS_OVERLAP_BEHIND
||
535 eCompare
== POS_OUTSIDE
)
537 SwRedline
* pNewRedline
= new SwRedline( *pCurrent
);
538 *pNewRedline
->Start() = *pEnd
;
539 *pCurrent
->End() = *pEnd
;
540 pDoc
->AppendRedline( pNewRedline
, true );
543 // save the current redline
544 _SaveRedline
* pSave
= new _SaveRedline( pCurrent
, *pStart
);
545 rArr
.C40_INSERT( _SaveRedline
, pSave
, rArr
.Count() );
549 // restore old redline mode
550 pDoc
->SetRedlineMode_intern( eOld
);
553 void lcl_RestoreRedlines( SwDoc
* pDoc
, const SwPosition
& rPos
, _SaveRedlines
& rArr
)
555 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
556 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
558 for( sal_uInt16 n
= 0; n
< rArr
.Count(); ++n
)
560 _SaveRedline
* pSave
= rArr
[ n
];
561 pSave
->SetPos( rPos
);
562 pDoc
->AppendRedline( pSave
->pRedl
, true );
565 pDoc
->SetRedlineMode_intern( eOld
);
569 void lcl_SaveRedlines( const SwNodeRange
& rRg
, _SaveRedlines
& rArr
)
571 SwDoc
* pDoc
= rRg
.aStart
.GetNode().GetDoc();
573 SwPosition
aSrchPos( rRg
.aStart
); aSrchPos
.nNode
--;
574 aSrchPos
.nContent
.Assign( aSrchPos
.nNode
.GetNode().GetCntntNode(), 0 );
575 if( pDoc
->GetRedline( aSrchPos
, &nRedlPos
) && nRedlPos
)
577 else if( nRedlPos
>= pDoc
->GetRedlineTbl().Count() )
580 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
581 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
582 SwRedlineTbl
& rRedlTbl
= (SwRedlineTbl
&)pDoc
->GetRedlineTbl();
585 SwRedline
* pTmp
= rRedlTbl
[ nRedlPos
];
587 const SwPosition
* pRStt
= pTmp
->Start(),
588 * pREnd
= pTmp
->GetMark() == pRStt
589 ? pTmp
->GetPoint() : pTmp
->GetMark();
591 if( pRStt
->nNode
< rRg
.aStart
)
593 if( pREnd
->nNode
> rRg
.aStart
&& pREnd
->nNode
< rRg
.aEnd
)
595 // Kopie erzeugen und Ende vom Original ans Ende des
596 // MoveBereiches setzen. Die Kopie wird mit verschoben
597 SwRedline
* pNewRedl
= new SwRedline( *pTmp
);
598 SwPosition
* pTmpPos
= pNewRedl
->Start();
599 pTmpPos
->nNode
= rRg
.aStart
;
600 pTmpPos
->nContent
.Assign(
601 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
603 _SaveRedline
* pSave
= new _SaveRedline( pNewRedl
, rRg
.aStart
);
604 // rArr.Insert( pSave, rArr.Count() );
605 rArr
.C40_INSERT( _SaveRedline
, pSave
, rArr
.Count() );
607 pTmpPos
= pTmp
->End();
608 pTmpPos
->nNode
= rRg
.aEnd
;
609 pTmpPos
->nContent
.Assign(
610 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
612 else if( pREnd
->nNode
== rRg
.aStart
)
614 SwPosition
* pTmpPos
= pTmp
->End();
615 pTmpPos
->nNode
= rRg
.aEnd
;
616 pTmpPos
->nContent
.Assign(
617 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
620 else if( pRStt
->nNode
< rRg
.aEnd
)
622 rRedlTbl
.Remove( nRedlPos
-- );
623 if( pREnd
->nNode
< rRg
.aEnd
||
624 ( pREnd
->nNode
== rRg
.aEnd
&& !pREnd
->nContent
.GetIndex()) )
626 // gesamt verschieben
627 _SaveRedline
* pSave
= new _SaveRedline( pTmp
, rRg
.aStart
);
628 // rArr.Insert( pSave, rArr.Count() );
629 rArr
.C40_INSERT( _SaveRedline
, pSave
, rArr
.Count() );
634 SwRedline
* pNewRedl
= new SwRedline( *pTmp
);
635 SwPosition
* pTmpPos
= pNewRedl
->End();
636 pTmpPos
->nNode
= rRg
.aEnd
;
637 pTmpPos
->nContent
.Assign(
638 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
640 _SaveRedline
* pSave
= new _SaveRedline( pNewRedl
, rRg
.aStart
);
641 // rArr.Insert( pSave, rArr.Count() );
642 rArr
.C40_INSERT( _SaveRedline
, pSave
, rArr
.Count() );
644 pTmpPos
= pTmp
->Start();
645 pTmpPos
->nNode
= rRg
.aEnd
;
646 pTmpPos
->nContent
.Assign(
647 pTmpPos
->nNode
.GetNode().GetCntntNode(), 0 );
648 pDoc
->AppendRedline( pTmp
, true );
654 } while( ++nRedlPos
< pDoc
->GetRedlineTbl().Count() );
655 pDoc
->SetRedlineMode_intern( eOld
);
658 void lcl_RestoreRedlines( SwDoc
* pDoc
, sal_uInt32 nInsPos
, _SaveRedlines
& rArr
)
660 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
661 pDoc
->SetRedlineMode_intern( (RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
663 for( sal_uInt16 n
= 0; n
< rArr
.Count(); ++n
)
665 _SaveRedline
* pSave
= rArr
[ n
];
666 pSave
->SetPos( nInsPos
);
667 pDoc
->AppendRedline( pSave
->pRedl
, true );
670 pDoc
->SetRedlineMode_intern( eOld
);
673 // ------------------------------------------------------------------------
674 // #i59534: Redo of insertion of multiple text nodes runs into trouble
675 // because of unnecessary expanded redlines
676 // From now on this class saves the redline positions of all redlines which ends exact at the
677 // insert position (node _and_ content index)
679 _SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex
& rInsIdx
, xub_StrLen nCnt
)
680 : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt
)
682 SwNode
& rNd
= rInsIdx
.GetNode();
683 SwDoc
* pDest
= rNd
.GetDoc();
684 if( pDest
->GetRedlineTbl().Count() )
687 const SwPosition
* pEnd
;
688 SwPosition
aSrcPos( rInsIdx
, SwIndex( rNd
.GetCntntNode(), nCnt
));
689 const SwRedline
* pRedl
= pDest
->GetRedline( aSrcPos
, &nFndPos
);
690 while( nFndPos
-- && *( pEnd
= ( pRedl
=
691 pDest
->GetRedlineTbl()[ nFndPos
] )->End() ) == aSrcPos
&& *pRedl
->Start() < aSrcPos
)
695 pSavArr
= new SvPtrarr( 2, 2 );
696 pSavIdx
= new SwNodeIndex( rInsIdx
, -1 );
698 void* p
= (void*)pEnd
;
699 pSavArr
->Insert( p
, pSavArr
->Count() );
704 _SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
713 void _SaveRedlEndPosForRestore::_Restore()
716 SwCntntNode
* pNode
= pSavIdx
->GetNode().GetCntntNode();
717 // If there's no content node at the remembered position, we will not restore the old position
718 // This may happen if a table (or section?) will be inserted.
721 SwPosition
aPos( *pSavIdx
, SwIndex( pNode
, nSavCntnt
));
722 for( sal_uInt16 n
= pSavArr
->Count(); n
; )
723 *((SwPosition
*)pSavArr
->GetObject( --n
)) = aPos
;
728 // ------------------------------------------------------------------------
730 // Loeschen einer vollstaendigen Section des NodesArray.
731 // Der uebergebene Node steht irgendwo in der gewuenschten Section
732 void SwDoc::DeleteSection( SwNode
*pNode
)
734 ASSERT( pNode
, "Kein Node uebergeben." );
735 SwStartNode
* pSttNd
= pNode
->IsStartNode() ? (SwStartNode
*)pNode
736 : pNode
->StartOfSectionNode();
737 SwNodeIndex
aSttIdx( *pSttNd
), aEndIdx( *pNode
->EndOfSectionNode() );
739 // dann loesche mal alle Fly's, text::Bookmarks, ...
740 DelFlyInRange( aSttIdx
, aEndIdx
);
741 DeleteRedline( *pSttNd
, true, USHRT_MAX
);
742 _DelBookmarks(aSttIdx
, aEndIdx
);
745 // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
746 SwNodeIndex
aMvStt( aSttIdx
, 1 );
747 CorrAbs( aMvStt
, aEndIdx
, SwPosition( aSttIdx
), sal_True
);
750 GetNodes().DelNodes( aSttIdx
, aEndIdx
.GetIndex() - aSttIdx
.GetIndex() + 1 );
754 void SwDoc::SetModified(SwPaM
&rPaM
)
756 SwDataChanged
aTmp( rPaM
, 0 );
760 /*************************************************************************
762 ************************************************************************/
764 bool SwDoc::Overwrite( const SwPaM
&rRg
, const String
&rStr
)
766 SwPosition
& rPt
= *(SwPosition
*)rRg
.GetPoint();
767 if( pACEWord
) // Aufnahme in die Autokorrektur
769 if( 1 == rStr
.Len() )
770 pACEWord
->CheckChar( rPt
, rStr
.GetChar( 0 ) );
771 delete pACEWord
, pACEWord
= 0;
774 SwTxtNode
*pNode
= rPt
.nNode
.GetNode().GetTxtNode();
781 sal_uInt16 nOldAttrCnt
= pNode
->GetpSwpHints()
782 ? pNode
->GetpSwpHints()->Count() : 0;
783 SwDataChanged
aTmp( rRg
, 0 );
784 SwIndex
& rIdx
= rPt
.nContent
;
785 xub_StrLen nStart
= 0;
787 sal_uInt16 nUndoSize
= pUndos
->Count();
792 BOOL bOldExpFlg
= pNode
->IsIgnoreDontExpand();
793 pNode
->SetIgnoreDontExpand( TRUE
);
795 for( xub_StrLen nCnt
= 0; nCnt
< rStr
.Len(); ++nCnt
)
797 // hinter das Zeichen (zum aufspannen der Attribute !!)
798 nStart
= rIdx
.GetIndex();
799 if ( nStart
< pNode
->GetTxt().Len() )
801 lcl_SkipAttr( pNode
, rIdx
, nStart
);
803 c
= rStr
.GetChar( nCnt
);
806 if( DoesGroupUndo() && nUndoSize
&&
807 UNDO_OVERWRITE
== ( pUndo
= (*pUndos
)[ nUndoSize
-1 ])->GetId() &&
808 ((SwUndoOverwrite
*)pUndo
)->CanGrouping( this, rPt
, c
))
809 ;// wenn CanGrouping() sal_True returnt, ist schon alles erledigt
812 AppendUndo( new SwUndoOverwrite( this, rPt
, c
));
813 nUndoSize
= pUndos
->Count();
818 // hinter das Zeichen (zum Aufspannen der Attribute !!)
819 if( nStart
< pNode
->GetTxt().Len() )
821 pNode
->InsertText( c
, rIdx
, INS_EMPTYEXPAND
);
822 if( nStart
+1 < rIdx
.GetIndex() )
825 pNode
->EraseText( rIdx
, 1 );
830 pNode
->SetIgnoreDontExpand( bOldExpFlg
);
832 sal_uInt16 nNewAttrCnt
= pNode
->GetpSwpHints()
833 ? pNode
->GetpSwpHints()->Count() : 0;
834 if( nOldAttrCnt
!= nNewAttrCnt
)
836 SwUpdateAttr
aHint( 0, 0, 0 );
837 SwClientIter
aIter( *pNode
);
838 SwClient
* pGTO
= aIter
.First(TYPE( SwCrsrShell
));
841 pGTO
->Modify( 0, &aHint
);
846 if( !DoesUndo() && !IsIgnoreRedline() && GetRedlineTbl().Count() )
848 SwPaM
aPam( rPt
.nNode
, nStart
, rPt
.nNode
, rPt
.nContent
.GetIndex() );
849 DeleteRedline( aPam
, true, USHRT_MAX
);
851 else if( IsRedlineOn() )
853 // FIXME: this redline is WRONG: there is no DELETE, and the skipped
854 // characters are also included in aPam
855 SwPaM
aPam( rPt
.nNode
, nStart
, rPt
.nNode
, rPt
.nContent
.GetIndex() );
856 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT
, aPam
), true);
864 bool SwDoc::MoveAndJoin( SwPaM
& rPaM
, SwPosition
& rPos
, SwMoveFlags eMvFlags
)
866 SwNodeIndex
aIdx( rPaM
.Start()->nNode
);
867 sal_Bool bJoinTxt
= aIdx
.GetNode().IsTxtNode();
868 sal_Bool bOneNode
= rPaM
.GetPoint()->nNode
== rPaM
.GetMark()->nNode
;
869 aIdx
--; // vor den Move Bereich !!
871 bool bRet
= MoveRange( rPaM
, rPos
, eMvFlags
);
872 if( bRet
&& !bOneNode
)
876 SwTxtNode
* pTxtNd
= aIdx
.GetNode().GetTxtNode();
877 SwNodeIndex
aNxtIdx( aIdx
);
878 if( pTxtNd
&& pTxtNd
->CanJoinNext( &aNxtIdx
) )
880 { // Block wegen SwIndex in den Node !!
881 CorrRel( aNxtIdx
, SwPosition( aIdx
, SwIndex( pTxtNd
,
882 pTxtNd
->GetTxt().Len() ) ), 0, sal_True
);
890 // mst: it seems that this is mostly used by SwDoc internals; the only
891 // way to call this from the outside seems to be the special case in
892 // SwDoc::CopyRange (but i have not managed to actually hit that case)
893 bool SwDoc::MoveRange( SwPaM
& rPaM
, SwPosition
& rPos
, SwMoveFlags eMvFlags
)
895 // keine Moves-Abfangen
896 const SwPosition
*pStt
= rPaM
.Start(), *pEnd
= rPaM
.End();
897 if( !rPaM
.HasMark() || *pStt
>= *pEnd
|| (*pStt
<= rPos
&& rPos
< *pEnd
))
900 // sicher die absatzgebundenen Flys, damit sie verschoben werden koennen.
901 _SaveFlyArr aSaveFlyArr
;
902 _SaveFlyInRange( rPaM
, rPos
.nNode
, aSaveFlyArr
, 0 != ( DOC_MOVEALLFLYS
& eMvFlags
) );
904 // save redlines (if DOC_MOVEREDLINES is used)
905 _SaveRedlines
aSaveRedl( 0, 4 );
906 if( DOC_MOVEREDLINES
& eMvFlags
&& GetRedlineTbl().Count() )
908 lcl_SaveRedlines( rPaM
, aSaveRedl
);
910 // #i17764# unfortunately, code below relies on undos being
911 // in a particular order, and presence of bookmarks
912 // will change this order. Hence, we delete bookmarks
913 // here without undo.
914 BOOL bDoesUndo
= DoesUndo();
926 int bUpdateFtn
= sal_False
;
927 SwFtnIdxs aTmpFntIdx
;
929 // falls Undo eingeschaltet, erzeuge das UndoMove-Objekt
930 SwUndoMove
* pUndoMove
= 0;
934 pUndoMove
= new SwUndoMove( rPaM
, rPos
);
935 pUndoMove
->SetMoveRedlines( eMvFlags
== DOC_MOVEREDLINES
);
939 bUpdateFtn
= lcl_SaveFtn( pStt
->nNode
, pEnd
->nNode
, rPos
.nNode
,
940 GetFtnIdxs(), aTmpFntIdx
,
941 &pStt
->nContent
, &pEnd
->nContent
);
944 sal_Bool bSplit
= sal_False
;
945 SwPaM
aSavePam( rPos
, rPos
);
947 // stelle den SPoint an den Anfang vom Bereich (Definition)
948 if( rPaM
.GetPoint() == pEnd
)
951 // in der EditShell wird nach dem Move ein JoinNext erzeugt, wenn
952 // vor und nach dem Move ein Text-Node steht.
953 SwTxtNode
* pSrcNd
= rPaM
.GetPoint()->nNode
.GetNode().GetTxtNode();
954 sal_Bool bCorrSavePam
= pSrcNd
&& pStt
->nNode
!= pEnd
->nNode
;
956 // werden ein oder mehr TextNodes bewegt, so wird
957 // im SwNodes::Move ein SplitNode erzeugt. Dieser Updated aber nicht
958 // den Cursor. Um das zu verhindern, wird hier ein TextNode angelegt,
959 // um die Updaterei der Indizies zu erhalten. Nach dem Move wird
960 // evt. der Node geloescht.
962 SwTxtNode
* pTNd
= rPos
.nNode
.GetNode().GetTxtNode();
963 if( pTNd
&& rPaM
.GetPoint()->nNode
!= rPaM
.GetMark()->nNode
&&
964 ( rPos
.nContent
.GetIndex() || ( pTNd
->Len() && bCorrSavePam
)) )
967 xub_StrLen nMkCntnt
= rPaM
.GetMark()->nContent
.GetIndex();
969 SvULongs
aBkmkArr( 15, 15 );
970 _SaveCntntIdx( this, rPos
.nNode
.GetIndex(), rPos
.nContent
.GetIndex(),
971 aBkmkArr
, SAVEFLY_SPLIT
);
973 pTNd
= static_cast<SwTxtNode
*>(pTNd
->SplitCntntNode( rPos
));
975 if( aBkmkArr
.Count() )
976 _RestoreCntntIdx( this, aBkmkArr
, rPos
.nNode
.GetIndex()-1, 0, sal_True
);
978 // jetzt noch den Pam berichtigen !!
979 if( rPos
.nNode
== rPaM
.GetMark()->nNode
)
981 rPaM
.GetMark()->nNode
= rPos
.nNode
.GetIndex()-1;
982 rPaM
.GetMark()->nContent
.Assign( pTNd
, nMkCntnt
);
986 // setze den Pam um einen "Inhalt" zurueck; dadurch steht er immer
987 // ausserhalb des manipulierten Bereiches. Falls kein Inhalt mehr vor-
988 // handen, dann auf den StartNode (es ist immer einer vorhanden !!!)
989 sal_Bool bNullCntnt
= !aSavePam
.Move( fnMoveBackward
, fnGoCntnt
);
992 aSavePam
.GetPoint()->nNode
--;
995 // kopiere alle Bookmarks, die im Move Bereich stehen in ein
996 // Array, das alle Angaben auf die Position als Offset speichert.
997 // Die neue Zuordung erfolgt nach dem Moven.
998 ::std::vector
< ::sw::mark::SaveBookmark
> aSaveBkmks
;
1006 // falls durch die vorherigen Loeschungen (z.B. der Fussnoten) kein
1007 // Bereich mehr existiert, ist das immernoch ein gueltiger Move!
1008 if( *rPaM
.GetPoint() != *rPaM
.GetMark() )
1010 // now do the actual move
1011 GetNodes().MoveRange( rPaM
, rPos
, GetNodes() );
1013 // after a MoveRange() the Mark is deleted
1014 if ( rPaM
.HasMark() ) // => no Move occurred!
1023 ASSERT( *aSavePam
.GetMark() == rPos
||
1024 ( aSavePam
.GetMark()->nNode
.GetNode().GetCntntNode() == NULL
),
1025 "PaM wurde nicht verschoben, am Anfang/Ende keine ContentNodes?" );
1026 *aSavePam
.GetMark() = rPos
;
1028 rPaM
.SetMark(); // um den neuen Bereich eine Sel. aufspannen
1029 pTNd
= aSavePam
.GetNode()->GetTxtNode();
1032 // korrigiere erstmal den Content vom SavePam
1035 aSavePam
.GetPoint()->nContent
= 0;
1038 // die Methode SwEditShell::Move() fuegt nach dem Move den Text-Node
1039 // zusammen, in dem der rPaM steht. Wurde der Inhalt nach hinten
1040 // geschoben und liegt der SPoint vom SavePam im naechsten Node, so
1041 // muss beim Speichern vom Undo-Object das beachtet werden !!
1042 SwTxtNode
* pPamTxtNd
= 0;
1044 // wird ans SwUndoMove weitergegeben, das dann beim Undo JoinNext
1045 // aufruft. (falls es hier nicht moeglich ist).
1046 sal_Bool bJoin
= bSplit
&& pTNd
;
1047 bCorrSavePam
= bCorrSavePam
&&
1048 0 != ( pPamTxtNd
= rPaM
.GetNode()->GetTxtNode() )
1049 && pPamTxtNd
->CanJoinNext()
1050 && (*rPaM
.GetPoint() <= *aSavePam
.GetPoint());
1052 // muessen am SavePam 2 Nodes zusammengefasst werden ??
1053 if( bJoin
&& pTNd
->CanJoinNext() )
1056 // kein temp. sdbcx::Index bei &&
1057 // es sollten wohl nur die Indexwerte verglichen werden.
1058 if( bCorrSavePam
&& rPaM
.GetPoint()->nNode
.GetIndex()+1 ==
1059 aSavePam
.GetPoint()->nNode
.GetIndex() )
1061 aSavePam
.GetPoint()->nContent
+= pPamTxtNd
->Len();
1065 // else if( !bCorrSavePam && !pSavePam->Move( fnMoveForward, fnGoCntnt ))
1066 else if ( !aSavePam
.Move( fnMoveForward
, fnGoCntnt
) )
1068 aSavePam
.GetPoint()->nNode
++;
1071 // zwischen SPoint und GetMark steht jetzt der neu eingefuegte Bereich
1072 pUndoMove
->SetDestRange( aSavePam
, *rPaM
.GetPoint(),
1073 bJoin
, bCorrSavePam
);
1074 AppendUndo( pUndoMove
);
1078 bool bRemove
= true;
1079 // muessen am SavePam 2 Nodes zusammengefasst werden ??
1080 if( bSplit
&& pTNd
)
1082 if( pTNd
->CanJoinNext())
1084 // --> OD 2009-08-20 #i100466#
1085 // Always join next, because <pTNd> has to stay as it is.
1086 // A join previous from its next would more or less delete <pTNd>
1094 aSavePam
.GetPoint()->nNode
++;
1095 aSavePam
.GetPoint()->nContent
.Assign( aSavePam
.GetCntntNode(), 0 );
1097 else if( bRemove
) // No move forward after joining with next paragraph
1099 aSavePam
.Move( fnMoveForward
, fnGoCntnt
);
1103 // setze jetzt wieder die text::Bookmarks in das Dokument
1104 *rPaM
.GetMark() = *aSavePam
.Start();
1106 ::std::vector
< ::sw::mark::SaveBookmark
>::iterator pBkmk
= aSaveBkmks
.begin();
1107 pBkmk
!= aSaveBkmks
.end();
1111 rPaM
.GetMark()->nNode
,
1112 &rPaM
.GetMark()->nContent
);
1113 *rPaM
.GetPoint() = *aSavePam
.End();
1115 // verschiebe die Flys an die neue Position
1116 _RestFlyInRange( aSaveFlyArr
, rPaM
.Start()->nNode
, &(rPos
.nNode
) );
1118 // restore redlines (if DOC_MOVEREDLINES is used)
1119 if( aSaveRedl
.Count() )
1121 lcl_RestoreRedlines( this, *aSavePam
.Start(), aSaveRedl
);
1126 if( aTmpFntIdx
.Count() )
1128 GetFtnIdxs().Insert( &aTmpFntIdx
);
1129 aTmpFntIdx
.Remove( sal_uInt16( 0 ), aTmpFntIdx
.Count() );
1132 GetFtnIdxs().UpdateAllFtn();
1139 bool SwDoc::MoveNodeRange( SwNodeRange
& rRange
, SwNodeIndex
& rPos
,
1140 SwMoveFlags eMvFlags
)
1142 // bewegt alle Nodes an die neue Position. Dabei werden die
1143 // text::Bookmarks mit verschoben !! (zur Zeit ohne Undo)
1145 // falls durchs Move Fussnoten in den Sonderbereich kommen sollten,
1146 // dann entferne sie jetzt.
1148 // ansonsten bei allen Fussnoten, die verschoben werden, die Frames
1149 // loeschen und nach dem Move wieder aufbauen lassen (Fussnoten koennen
1150 // die Seite wechseln). Zusaetzlich muss natuerlich die Sortierung
1151 // der FtnIdx-Array wieder korrigiert werden.
1153 int bUpdateFtn
= sal_False
;
1154 SwFtnIdxs aTmpFntIdx
;
1156 SwUndoMove
* pUndo
= 0;
1157 if( (DOC_CREATEUNDOOBJ
& eMvFlags
) && DoesUndo() )
1158 pUndo
= new SwUndoMove( this, rRange
, rPos
);
1160 bUpdateFtn
= lcl_SaveFtn( rRange
.aStart
, rRange
.aEnd
, rPos
,
1161 GetFtnIdxs(), aTmpFntIdx
);
1163 _SaveRedlines
aSaveRedl( 0, 4 );
1164 SvPtrarr
aSavRedlInsPosArr( 0, 4 );
1165 if( DOC_MOVEREDLINES
& eMvFlags
&& GetRedlineTbl().Count() )
1167 lcl_SaveRedlines( rRange
, aSaveRedl
);
1169 // suche alle Redlines, die an der InsPos aufhoeren. Diese muessen
1170 // nach dem Move wieder an die "alte" Position verschoben werden
1171 sal_uInt16 nRedlPos
= GetRedlinePos( rPos
.GetNode(), USHRT_MAX
);
1172 if( USHRT_MAX
!= nRedlPos
)
1174 const SwPosition
*pRStt
, *pREnd
;
1176 SwRedline
* pTmp
= GetRedlineTbl()[ nRedlPos
];
1177 pRStt
= pTmp
->Start();
1178 pREnd
= pTmp
->End();
1179 if( pREnd
->nNode
== rPos
&& pRStt
->nNode
< rPos
)
1182 aSavRedlInsPosArr
.Insert( p
, aSavRedlInsPosArr
.Count() );
1184 } while( pRStt
->nNode
< rPos
&& ++nRedlPos
< GetRedlineTbl().Count());
1188 // kopiere alle Bookmarks, die im Move Bereich stehen in ein
1189 // Array, das alle Angaben auf die Position als Offset speichert.
1190 // Die neue Zuordung erfolgt nach dem Moven.
1191 ::std::vector
< ::sw::mark::SaveBookmark
> aSaveBkmks
;
1192 _DelBookmarks(rRange
.aStart
, rRange
.aEnd
, &aSaveBkmks
);
1194 // sicher die absatzgebundenen Flys, damit verschoben werden koennen.
1195 _SaveFlyArr aSaveFlyArr
;
1196 if( GetSpzFrmFmts()->Count() )
1197 _SaveFlyInRange( rRange
, aSaveFlyArr
);
1199 // vor die Position setzen, damit er nicht weitergeschoben wird
1200 SwNodeIndex
aIdx( rPos
, -1 );
1202 SwNodeIndex
* pSaveInsPos
= 0;
1204 pSaveInsPos
= new SwNodeIndex( rRange
.aStart
, -1 );
1206 // verschiebe die Nodes
1207 BOOL bNoDelFrms
= 0 != (DOC_NO_DELFRMS
& eMvFlags
);
1208 if( GetNodes()._MoveNodes( rRange
, GetNodes(), rPos
, !bNoDelFrms
) )
1210 aIdx
++; // wieder auf alte Position
1216 aIdx
= rRange
.aStart
;
1217 delete pUndo
, pUndo
= 0;
1220 // verschiebe die Flys an die neue Position
1221 if( aSaveFlyArr
.Count() )
1222 _RestFlyInRange( aSaveFlyArr
, aIdx
, NULL
);
1224 // setze jetzt wieder die text::Bookmarks in das Dokument
1226 ::std::vector
< ::sw::mark::SaveBookmark
>::iterator pBkmk
= aSaveBkmks
.begin();
1227 pBkmk
!= aSaveBkmks
.end();
1229 pBkmk
->SetInDoc(this, aIdx
);
1231 if( aSavRedlInsPosArr
.Count() )
1233 SwNode
* pNewNd
= &aIdx
.GetNode();
1234 for( sal_uInt16 n
= 0; n
< aSavRedlInsPosArr
.Count(); ++n
)
1236 SwRedline
* pTmp
= (SwRedline
*)aSavRedlInsPosArr
[ n
];
1237 if( USHRT_MAX
!= GetRedlineTbl().GetPos( pTmp
) )
1239 SwPosition
* pEnd
= pTmp
->End();
1241 pEnd
->nContent
.Assign( pNewNd
->GetCntntNode(), 0 );
1246 if( aSaveRedl
.Count() )
1247 lcl_RestoreRedlines( this, aIdx
.GetIndex(), aSaveRedl
);
1252 pUndo
->SetDestRange( aIdx
, rPos
, *pSaveInsPos
);
1253 AppendUndo( pUndo
);
1261 if( aTmpFntIdx
.Count() )
1263 GetFtnIdxs().Insert( &aTmpFntIdx
);
1264 aTmpFntIdx
.Remove( sal_uInt16( 0 ), aTmpFntIdx
.Count() );
1267 GetFtnIdxs().UpdateAllFtn();
1274 /* #107318# Convert list of ranges of whichIds to a corresponding list
1276 SvUShorts
* lcl_RangesToUShorts(USHORT
* pRanges
)
1278 SvUShorts
* pResult
= new SvUShorts();
1281 while (pRanges
[i
] != 0)
1283 ASSERT(pRanges
[i
+1] != 0, "malformed ranges");
1285 for (USHORT j
= pRanges
[i
]; j
< pRanges
[i
+1]; j
++)
1286 pResult
->Insert(j
, pResult
->Count());
1294 bool lcl_StrLenOverFlow( const SwPaM
& rPam
)
1296 // If we try to merge two paragraph we have to test if afterwards
1297 // the string doesn't exceed the allowed string length
1299 if( rPam
.GetPoint()->nNode
!= rPam
.GetMark()->nNode
)
1301 const SwPosition
* pStt
= rPam
.Start(), *pEnd
= rPam
.End();
1302 const SwTxtNode
* pEndNd
= pEnd
->nNode
.GetNode().GetTxtNode();
1303 if( (0 != pEndNd
) && pStt
->nNode
.GetNode().IsTxtNode() )
1305 sal_uInt64 nSum
= pStt
->nContent
.GetIndex() +
1306 pEndNd
->GetTxt().Len() - pEnd
->nContent
.GetIndex();
1307 if( nSum
> STRING_LEN
)
1314 void lcl_GetJoinFlags( SwPaM
& rPam
, sal_Bool
& rJoinTxt
, sal_Bool
& rJoinPrev
)
1316 rJoinTxt
= sal_False
;
1317 rJoinPrev
= sal_False
;
1318 if( rPam
.GetPoint()->nNode
!= rPam
.GetMark()->nNode
)
1320 const SwPosition
* pStt
= rPam
.Start(), *pEnd
= rPam
.End();
1321 SwTxtNode
*pSttNd
= pStt
->nNode
.GetNode().GetTxtNode();
1324 SwTxtNode
*pEndNd
= pEnd
->nNode
.GetNode().GetTxtNode();
1325 rJoinTxt
= 0 != pEndNd
;
1328 bool bExchange
= pStt
== rPam
.GetPoint();
1329 if( !pStt
->nContent
.GetIndex() &&
1330 pEndNd
->GetTxt().Len() != pEnd
->nContent
.GetIndex() )
1331 bExchange
= !bExchange
;
1334 rJoinPrev
= rPam
.GetPoint() == pStt
;
1335 ASSERT( !pStt
->nContent
.GetIndex() &&
1336 pEndNd
->GetTxt().Len() != pEnd
->nContent
.GetIndex()
1337 ? rPam
.GetPoint()->nNode
< rPam
.GetMark()->nNode
1338 : rPam
.GetPoint()->nNode
> rPam
.GetMark()->nNode
,
1339 "lcl_GetJoinFlags");
1345 void lcl_JoinText( SwPaM
& rPam
, sal_Bool bJoinPrev
)
1347 SwNodeIndex
aIdx( rPam
.GetPoint()->nNode
);
1348 SwTxtNode
*pTxtNd
= aIdx
.GetNode().GetTxtNode();
1349 SwNodeIndex
aOldIdx( aIdx
);
1350 SwTxtNode
*pOldTxtNd
= pTxtNd
;
1352 if( pTxtNd
&& pTxtNd
->CanJoinNext( &aIdx
) )
1354 SwDoc
* pDoc
= rPam
.GetDoc();
1357 // N.B.: we do not need to handle xmlids in this case, because
1358 // it is only invoked if one paragraph is completely empty
1359 // (see lcl_GetJoinFlags)
1361 // falls PageBreaks geloescht / gesetzt werden, darf das
1362 // nicht in die Undo-History aufgenommen werden !!
1363 // (das loeschen vom Node geht auch am Undo vorbei !!!)
1364 sal_Bool bDoUndo
= pDoc
->DoesUndo();
1365 pDoc
->DoUndo( sal_False
);
1367 /* PageBreaks, PageDesc, ColumnBreaks */
1368 // Sollte an der Logik zum Kopieren der PageBreak's ...
1369 // etwas geaendert werden, muss es auch im SwUndoDelete
1370 // geandert werden. Dort wird sich das AUTO-PageBreak
1371 // aus dem GetMarkNode kopiert.!!!
1373 /* Der GetMarkNode */
1374 if( ( pTxtNd
= aIdx
.GetNode().GetTxtNode())->HasSwAttrSet() )
1376 const SfxPoolItem
* pItem
;
1377 if( SFX_ITEM_SET
== pTxtNd
->GetpSwAttrSet()->GetItemState(
1378 RES_BREAK
, sal_False
, &pItem
) )
1379 pTxtNd
->ResetAttr( RES_BREAK
);
1380 if( pTxtNd
->HasSwAttrSet() &&
1381 SFX_ITEM_SET
== pTxtNd
->GetpSwAttrSet()->GetItemState(
1382 RES_PAGEDESC
, sal_False
, &pItem
) )
1383 pTxtNd
->ResetAttr( RES_PAGEDESC
);
1387 if( pOldTxtNd
->HasSwAttrSet() )
1389 const SfxPoolItem
* pItem
;
1390 SfxItemSet
aSet( pDoc
->GetAttrPool(), aBreakSetRange
);
1391 const SfxItemSet
* pSet
= pOldTxtNd
->GetpSwAttrSet();
1392 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
,
1393 sal_False
, &pItem
) )
1395 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_PAGEDESC
,
1396 sal_False
, &pItem
) )
1399 pTxtNd
->SetAttr( aSet
);
1401 pOldTxtNd
->FmtToTxtAttr( pTxtNd
);
1403 SvULongs
aBkmkArr( 15, 15 );
1404 ::_SaveCntntIdx( pDoc
, aOldIdx
.GetIndex(),
1405 pOldTxtNd
->Len(), aBkmkArr
);
1407 SwIndex
aAlphaIdx(pTxtNd
);
1408 pOldTxtNd
->CutText( pTxtNd
, aAlphaIdx
, SwIndex(pOldTxtNd
),
1410 SwPosition
aAlphaPos( aIdx
, aAlphaIdx
);
1411 pDoc
->CorrRel( rPam
.GetPoint()->nNode
, aAlphaPos
, 0, sal_True
);
1413 // verschiebe noch alle Bookmarks/TOXMarks
1414 if( aBkmkArr
.Count() )
1415 ::_RestoreCntntIdx( pDoc
, aBkmkArr
, aIdx
.GetIndex() );
1417 pDoc
->DoUndo( bDoUndo
);
1419 // falls der uebergebene PaM nicht im Crsr-Ring steht,
1420 // gesondert behandeln (z.B. Aufruf aus dem Auto-Format)
1421 if( pOldTxtNd
== rPam
.GetBound( sal_True
).nContent
.GetIdxReg() )
1422 rPam
.GetBound( sal_True
) = aAlphaPos
;
1423 if( pOldTxtNd
== rPam
.GetBound( sal_False
).nContent
.GetIdxReg() )
1424 rPam
.GetBound( sal_False
) = aAlphaPos
;
1426 // jetzt nur noch den Node loeschen
1427 pDoc
->GetNodes().Delete( aOldIdx
, 1 );
1431 SwTxtNode
* pDelNd
= aIdx
.GetNode().GetTxtNode();
1433 pDelNd
->FmtToTxtAttr( pTxtNd
);
1436 /* #107318# This case was missed:
1438 <something></something> <-- pTxtNd
1439 <other>ccc</other> <-- pDelNd
1441 <something> and <other> are paragraph
1442 attributes. The attribute <something> stayed if not
1443 overwritten by an attribute in "ccc". Fixed by
1444 first resetting all character attributes in first
1447 SvUShorts
* pShorts
=
1448 lcl_RangesToUShorts(aCharFmtSetRange
);
1449 pTxtNd
->ResetAttr(*pShorts
);
1452 if( pDelNd
->HasSwAttrSet() )
1454 // nur die Zeichenattribute kopieren
1455 SfxItemSet
aTmpSet( pDoc
->GetAttrPool(), aCharFmtSetRange
);
1456 aTmpSet
.Put( *pDelNd
->GetpSwAttrSet() );
1457 pTxtNd
->SetAttr( aTmpSet
);
1461 pDoc
->CorrRel( aIdx
, *rPam
.GetPoint(), 0, sal_True
);
1462 // --> OD 2009-08-20 #i100466#
1463 // adjust given <rPam>, if it does not belong to the cursors
1464 if ( pDelNd
== rPam
.GetBound( sal_True
).nContent
.GetIdxReg() )
1466 rPam
.GetBound( sal_True
) = SwPosition( SwNodeIndex( *pTxtNd
), SwIndex( pTxtNd
) );
1468 if( pDelNd
== rPam
.GetBound( sal_False
).nContent
.GetIdxReg() )
1470 rPam
.GetBound( sal_False
) = SwPosition( SwNodeIndex( *pTxtNd
), SwIndex( pTxtNd
) );
1479 lcl_CalcBreaks( ::std::vector
<xub_StrLen
> & rBreaks
, SwPaM
const & rPam
)
1481 SwTxtNode
const * const pTxtNode(
1482 rPam
.End()->nNode
.GetNode().GetTxtNode() );
1484 return; // left-overlap only possible at end of selection...
1486 const xub_StrLen
nStart(rPam
.Start()->nContent
.GetIndex());
1487 const xub_StrLen
nEnd (rPam
.End ()->nContent
.GetIndex());
1488 if (nEnd
== pTxtNode
->Len())
1489 return; // paragraph selected until the end
1491 for (xub_StrLen i
= nStart
; i
< nEnd
; ++i
)
1493 const sal_Unicode
c(pTxtNode
->GetTxt().GetChar(i
));
1494 if ((CH_TXTATR_INWORD
== c
) || (CH_TXTATR_BREAKWORD
== c
))
1496 SwTxtAttr
const * const pAttr( pTxtNode
->GetTxtAttrForCharAt(i
) );
1497 if (pAttr
&& pAttr
->GetEnd() && (*pAttr
->GetEnd() > nEnd
))
1499 ASSERT(pAttr
->HasDummyChar(), "GetTxtAttrForCharAt broken?");
1500 rBreaks
.push_back(i
);
1506 bool lcl_DoWithBreaks(SwDoc
& rDoc
, SwPaM
& rPam
,
1507 bool (SwDoc::*pFunc
)(SwPaM
&, bool), const bool bForceJoinNext
= false)
1509 ::std::vector
<xub_StrLen
> Breaks
;
1511 lcl_CalcBreaks(Breaks
, rPam
);
1515 return (rDoc
.*pFunc
)(rPam
, bForceJoinNext
);
1518 // N.B.: deletion must be split into several parts if the text node
1519 // contains a text attribute with end and with dummy character
1520 // and the selection does not contain the text attribute completely,
1521 // but overlaps its start (left), where the dummy character is.
1523 SwPosition
const & rSelectionEnd( *rPam
.End() );
1526 // iterate from end to start, to avoid invalidating the offsets!
1527 ::std::vector
<xub_StrLen
>::reverse_iterator
iter( Breaks
.rbegin() );
1528 SwPaM
aPam( rSelectionEnd
, rSelectionEnd
); // end node!
1529 SwPosition
& rEnd( *aPam
.End() );
1530 SwPosition
& rStart( *aPam
.Start() );
1532 while (iter
!= Breaks
.rend())
1534 rStart
.nContent
= *iter
+ 1;
1535 if (rEnd
.nContent
> rStart
.nContent
) // check if part is empty
1537 bRet
&= (rDoc
.*pFunc
)(aPam
, bForceJoinNext
);
1539 rEnd
.nContent
= *iter
;
1543 rStart
= *rPam
.Start(); // set to original start
1544 if (rEnd
.nContent
> rStart
.nContent
) // check if part is empty
1546 bRet
&= (rDoc
.*pFunc
)(aPam
, bForceJoinNext
);
1553 bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM
& rPam
, const bool )
1555 ASSERT( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
1558 sal_uInt16 nUndoSize
= 0;
1559 SwUndoRedlineDelete
* pUndo
= 0;
1560 RedlineMode_t eOld
= GetRedlineMode();
1561 checkRedlining(eOld
);
1566 //JP 06.01.98: MUSS noch optimiert werden!!!
1568 (RedlineMode_t
)(nsRedlineMode_t::REDLINE_ON
| nsRedlineMode_t::REDLINE_SHOW_INSERT
| nsRedlineMode_t::REDLINE_SHOW_DELETE
));
1570 nUndoSize
= pUndos
->Count();
1571 StartUndo(UNDO_EMPTY
, NULL
);
1572 AppendUndo( pUndo
= new SwUndoRedlineDelete( rPam
, UNDO_DELETE
));
1574 if( *rPam
.GetPoint() != *rPam
.GetMark() )
1575 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE
, rPam
), true);
1580 EndUndo(UNDO_EMPTY
, NULL
);
1582 if( nUndoSize
&& DoesGroupUndo() &&
1583 nUndoSize
+ 1 == pUndos
->Count() &&
1584 UNDO_REDLINE
== ( pPrevUndo
= (*pUndos
)[ nUndoSize
-1 ])->GetId() &&
1585 UNDO_DELETE
== ((SwUndoRedline
*)pPrevUndo
)->GetUserId() &&
1586 ((SwUndoRedlineDelete
*)pPrevUndo
)->CanGrouping( *pUndo
))
1588 DoUndo( sal_False
);
1589 pUndos
->DeleteAndDestroy( nUndoSize
, 1 );
1590 --nUndoPos
, --nUndoCnt
;
1593 //JP 06.01.98: MUSS noch optimiert werden!!!
1594 SetRedlineMode( eOld
);
1600 bool SwDoc::DeleteAndJoinImpl( SwPaM
& rPam
,
1601 const bool bForceJoinNext
)
1603 sal_Bool bJoinTxt
, bJoinPrev
;
1604 lcl_GetJoinFlags( rPam
, bJoinTxt
, bJoinPrev
);
1605 // --> OD 2009-08-20 #i100466#
1606 if ( bForceJoinNext
)
1608 bJoinPrev
= sal_False
;
1612 // dann eine Kopie vom Cursor erzeugen um alle Pams aus den
1613 // anderen Sichten aus dem Loeschbereich zu verschieben
1614 // ABER NICHT SICH SELBST !!
1615 SwPaM
aDelPam( *rPam
.GetMark(), *rPam
.GetPoint() );
1616 ::PaMCorrAbs( aDelPam
, *aDelPam
.GetPoint() );
1618 const bool bSuccess( DeleteRangeImpl( aDelPam
) );
1622 *rPam
.GetPoint() = *aDelPam
.GetPoint();
1627 lcl_JoinText( rPam
, bJoinPrev
);
1633 bool SwDoc::DeleteRangeImpl( SwPaM
& rPam
, const bool )
1635 SwPosition
*pStt
= (SwPosition
*)rPam
.Start(), *pEnd
= (SwPosition
*)rPam
.End();
1637 if( !rPam
.HasMark() || *pStt
>= *pEnd
)
1642 // ggfs. das gesicherte Word fuer die Ausnahme
1643 if( pACEWord
->IsDeleted() || pStt
->nNode
!= pEnd
->nNode
||
1644 pStt
->nContent
.GetIndex() + 1 != pEnd
->nContent
.GetIndex() ||
1645 !pACEWord
->CheckDelChar( *pStt
))
1646 delete pACEWord
, pACEWord
= 0;
1650 // loesche alle leeren TextHints an der Mark-Position
1651 SwTxtNode
* pTxtNd
= rPam
.GetMark()->nNode
.GetNode().GetTxtNode();
1653 if( pTxtNd
&& 0 != ( pHts
= pTxtNd
->GetpSwpHints()) && pHts
->Count() )
1655 const xub_StrLen
*pEndIdx
;
1656 xub_StrLen nMkCntPos
= rPam
.GetMark()->nContent
.GetIndex();
1657 for( sal_uInt16 n
= pHts
->Count(); n
; )
1659 const SwTxtAttr
* pAttr
= (*pHts
)[ --n
];
1660 if( nMkCntPos
> *pAttr
->GetStart() )
1663 if( nMkCntPos
== *pAttr
->GetStart() &&
1664 0 != (pEndIdx
= pAttr
->GetEnd()) &&
1665 *pEndIdx
== *pAttr
->GetStart() )
1666 pTxtNd
->DestroyAttr( pHts
->Cut( n
) );
1672 // Bug 26675: DataChanged vorm loeschen verschicken, dann bekommt
1673 // man noch mit, welche Objecte sich im Bereich befinden.
1674 // Danach koennen sie vor/hinter der Position befinden.
1675 SwDataChanged
aTmp( rPam
, 0 );
1682 sal_uInt16 nUndoSize
= pUndos
->Count();
1684 if( DoesGroupUndo() && nUndoSize
-- &&
1685 UNDO_DELETE
== ( pUndo
= (*pUndos
)[ nUndoSize
])->GetId() &&
1686 ((SwUndoDelete
*)pUndo
)->CanGrouping( this, rPam
))
1687 ;// wenn CanGrouping() sal_True returnt, ist schon alles erledigt
1689 AppendUndo( new SwUndoDelete( rPam
) );
1696 if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
1697 DeleteRedline( rPam
, true, USHRT_MAX
);
1699 // loesche und verschiebe erstmal alle "Fly's am Absatz", die in der
1701 DelFlyInRange(rPam
.GetMark()->nNode
, rPam
.GetPoint()->nNode
);
1709 SwNodeIndex
aSttIdx( pStt
->nNode
);
1710 SwCntntNode
* pCNd
= aSttIdx
.GetNode().GetCntntNode();
1712 do { // middle checked loop!
1715 SwTxtNode
* pStartTxtNode( pCNd
->GetTxtNode() );
1716 if ( pStartTxtNode
)
1718 // verschiebe jetzt noch den Inhalt in den neuen Node
1719 sal_Bool bOneNd
= pStt
->nNode
== pEnd
->nNode
;
1720 xub_StrLen nLen
= ( bOneNd
? pEnd
->nContent
.GetIndex()
1722 - pStt
->nContent
.GetIndex();
1724 // falls schon leer, dann nicht noch aufrufen
1727 pStartTxtNode
->EraseText( pStt
->nContent
, nLen
);
1729 if( !pStartTxtNode
->Len() )
1731 // METADATA: remove reference if empty (consider node deleted)
1732 pStartTxtNode
->RemoveMetadataReference();
1736 if( bOneNd
) // das wars schon
1743 // damit beim loeschen keine Indizies mehr angemeldet sind,
1744 // wird hier der SwPaM aus dem Content entfernt !!
1745 pStt
->nContent
.Assign( 0, 0 );
1749 pCNd
= pEnd
->nNode
.GetNode().GetCntntNode();
1752 SwTxtNode
* pEndTxtNode( pCNd
->GetTxtNode() );
1755 // falls schon leer, dann nicht noch aufrufen
1756 if( pEnd
->nContent
.GetIndex() )
1758 SwIndex
aIdx( pCNd
, 0 );
1759 pEndTxtNode
->EraseText( aIdx
, pEnd
->nContent
.GetIndex() );
1761 if( !pEndTxtNode
->Len() )
1763 // METADATA: remove reference if empty (consider node deleted)
1764 pEndTxtNode
->RemoveMetadataReference();
1770 // damit beim Loeschen keine Indizies mehr angemeldet sind,
1771 // wird hier der SwPaM aus dem Content entfernt !!
1772 pEnd
->nContent
.Assign( 0, 0 );
1776 // if the end is not a content node, delete it as well
1777 sal_uInt32 nEnde
= pEnd
->nNode
.GetIndex();
1781 if( aSttIdx
!= nEnde
)
1783 // loesche jetzt die Nodes in das NodesArary
1784 GetNodes().Delete( aSttIdx
, nEnde
- aSttIdx
.GetIndex() );
1787 // falls der Node geloescht wurde, in dem der Cursor stand, so
1788 // muss der Content im akt. Content angemeldet werden !!!
1789 pStt
->nContent
.Assign( pStt
->nNode
.GetNode().GetCntntNode(),
1790 pStt
->nContent
.GetIndex() );
1792 // der PaM wird korrigiert, denn falls ueber Nodegrenzen geloescht
1793 // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
1794 // wird aufgehoben !
1798 } while( sal_False
);
1800 if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
1807 // OD 2009-08-20 #i100466#
1808 // Add handling of new optional parameter <bForceJoinNext>
1809 bool SwDoc::DeleteAndJoin( SwPaM
& rPam
,
1810 const bool bForceJoinNext
)
1812 if ( lcl_StrLenOverFlow( rPam
) )
1815 return lcl_DoWithBreaks( *this, rPam
, (IsRedlineOn())
1816 ? &SwDoc::DeleteAndJoinWithRedlineImpl
1817 : &SwDoc::DeleteAndJoinImpl
,
1821 bool SwDoc::DeleteRange( SwPaM
& rPam
)
1823 return lcl_DoWithBreaks( *this, rPam
, &SwDoc::DeleteRangeImpl
);
1827 void lcl_syncGrammarError( SwTxtNode
&rTxtNode
, linguistic2::ProofreadingResult
& rResult
,
1828 xub_StrLen
/*nBeginGrammarCheck*/, const ModelToViewHelper::ConversionMap
* pConversionMap
)
1830 if( rTxtNode
.IsGrammarCheckDirty() )
1832 SwGrammarMarkUp
* pWrong
= rTxtNode
.GetGrammarCheck();
1833 linguistic2::SingleProofreadingError
* pArray
= rResult
.aErrors
.getArray();
1837 for( i
= 0; i
< rResult
.aErrors
.getLength(); ++i
)
1839 const linguistic2::SingleProofreadingError
&rError
= rResult
.aErrors
[i
];
1840 xub_StrLen nStart
= (xub_StrLen
)ModelToViewHelper::ConvertToModelPosition( pConversionMap
, rError
.nErrorStart
).mnPos
;
1841 xub_StrLen nEnd
= (xub_StrLen
)ModelToViewHelper::ConvertToModelPosition( pConversionMap
, rError
.nErrorStart
+ rError
.nErrorLength
).mnPos
;
1843 pArray
[j
] = pArray
[i
];
1844 if( pWrong
->LookForEntry( nStart
, nEnd
) )
1848 if( rResult
.aErrors
.getLength() > j
)
1849 rResult
.aErrors
.realloc( j
);
1853 uno::Any
SwDoc::Spell( SwPaM
& rPaM
,
1854 uno::Reference
< XSpellChecker1
> &xSpeller
,
1855 sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
,
1857 SwConversionArgs
*pConvArgs
) const
1859 SwPosition
* pSttPos
= rPaM
.Start(), *pEndPos
= rPaM
.End();
1860 uno::Reference
< beans::XPropertySet
> xProp( ::GetLinguPropertySet() );
1862 SwSpellArgs
*pSpellArgs
= 0;
1863 //SwConversionArgs *pConvArgs = 0;
1866 pConvArgs
->SetStart(pSttPos
->nNode
.GetNode().GetTxtNode(), pSttPos
->nContent
);
1867 pConvArgs
->SetEnd( pEndPos
->nNode
.GetNode().GetTxtNode(), pEndPos
->nContent
);
1870 pSpellArgs
= new SwSpellArgs( xSpeller
,
1871 pSttPos
->nNode
.GetNode().GetTxtNode(), pSttPos
->nContent
,
1872 pEndPos
->nNode
.GetNode().GetTxtNode(), pEndPos
->nContent
,
1875 ULONG nCurrNd
= pSttPos
->nNode
.GetIndex();
1876 ULONG nEndNd
= pEndPos
->nNode
.GetIndex();
1879 if( nCurrNd
<= nEndNd
)
1881 SwCntntFrm
* pCntFrm
;
1882 sal_Bool bGoOn
= sal_True
;
1885 SwNode
* pNd
= GetNodes()[ nCurrNd
];
1886 switch( pNd
->GetNodeType() )
1889 if( 0 != ( pCntFrm
= ((SwTxtNode
*)pNd
)->GetFrm()) )
1891 // geschutze Cellen/Flys ueberspringen, ausgeblendete
1893 if( pCntFrm
->IsProtected() )
1895 nCurrNd
= pNd
->EndOfSectionIndex();
1897 else if( !((SwTxtFrm
*)pCntFrm
)->IsHiddenNow() )
1899 if( pPageCnt
&& *pPageCnt
&& pPageSt
)
1901 sal_uInt16 nPageNr
= pCntFrm
->GetPhyPageNum();
1905 if( *pPageCnt
< *pPageSt
)
1906 *pPageCnt
= *pPageSt
;
1909 if( nPageNr
>= *pPageSt
)
1910 nStat
= nPageNr
- *pPageSt
+ 1;
1912 nStat
= nPageNr
+ *pPageCnt
- *pPageSt
+ 1;
1913 ::SetProgressState( nStat
, (SwDocShell
*)GetDocShell() );
1915 //Spell() changes the pSpellArgs in case an error is found
1916 xub_StrLen nBeginGrammarCheck
= 0;
1917 xub_StrLen nEndGrammarCheck
= 0;
1918 if( pSpellArgs
&& pSpellArgs
->bIsGrammarCheck
)
1920 nBeginGrammarCheck
= pSpellArgs
->pStartNode
== pNd
? pSpellArgs
->pStartIdx
->GetIndex() : 0;
1921 // if grammar checking starts inside of a sentence the start position has to be adjusted
1922 if( nBeginGrammarCheck
)
1924 SwIndex
aStartIndex( dynamic_cast< SwTxtNode
* >( pNd
), nBeginGrammarCheck
);
1925 SwPosition
aStart( *pNd
, aStartIndex
);
1926 SwCursor
aCrsr(aStart
, 0, false);
1927 SwPosition aOrigPos
= *aCrsr
.GetPoint();
1928 aCrsr
.GoSentence( SwCursor::START_SENT
);
1929 if( aOrigPos
!= *aCrsr
.GetPoint() )
1931 nBeginGrammarCheck
= aCrsr
.GetPoint()->nContent
.GetIndex();
1934 nEndGrammarCheck
= pSpellArgs
->pEndNode
== pNd
? pSpellArgs
->pEndIdx
->GetIndex() : ((SwTxtNode
*)pNd
)->GetTxt().Len();
1937 xub_StrLen nSpellErrorPosition
= ((SwTxtNode
*)pNd
)->GetTxt().Len();
1939 ((SwTxtNode
*)pNd
)->Spell( pSpellArgs
)) ||
1941 ((SwTxtNode
*)pNd
)->Convert( *pConvArgs
)))
1943 // Abbrechen und Position merken
1944 pSttPos
->nNode
= nCurrNd
;
1945 pEndPos
->nNode
= nCurrNd
;
1948 nSpellErrorPosition
= pSpellArgs
->pStartIdx
->GetIndex() > pSpellArgs
->pEndIdx
->GetIndex() ?
1949 pSpellArgs
->pEndIdx
->GetIndex() :
1950 pSpellArgs
->pStartIdx
->GetIndex();
1954 if( pSpellArgs
&& pSpellArgs
->bIsGrammarCheck
)
1956 uno::Reference
< linguistic2::XProofreadingIterator
> xGCIterator( GetGCIterator() );
1957 if (xGCIterator
.is())
1959 String
aText( ((SwTxtNode
*)pNd
)->GetTxt().Copy( nBeginGrammarCheck
, nEndGrammarCheck
- nBeginGrammarCheck
) );
1960 uno::Reference
< lang::XComponent
> xDoc( ((SwDocShell
*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY
);
1961 // Expand the string:
1962 rtl::OUString aExpandText
;
1963 const ModelToViewHelper::ConversionMap
* pConversionMap
=
1964 ((SwTxtNode
*)pNd
)->BuildConversionMap( aExpandText
);
1965 // get XFlatParagraph to use...
1966 uno::Reference
< text::XFlatParagraph
> xFlatPara
= new SwXFlatParagraph( *((SwTxtNode
*)pNd
), aExpandText
, pConversionMap
);
1968 // get error position of cursor in XFlatParagraph
1969 sal_Int32 nGrammarErrorPosInText
;
1970 linguistic2::ProofreadingResult aResult
;
1971 sal_Int32 nGrammarErrors
;
1974 nGrammarErrorPosInText
= ModelToViewHelper::ConvertToViewPosition( pConversionMap
, nBeginGrammarCheck
);
1975 aResult
= xGCIterator
->checkSentenceAtPosition(
1976 xDoc
, xFlatPara
, aExpandText
, lang::Locale(), nBeginGrammarCheck
, -1, -1 );
1978 lcl_syncGrammarError( *((SwTxtNode
*)pNd
), aResult
, nBeginGrammarCheck
, pConversionMap
);
1980 // get suggestions to use for the specific error position
1981 nGrammarErrors
= aResult
.aErrors
.getLength();
1982 // if grammar checking doesn't have any progress then quit
1983 if( aResult
.nStartOfNextSentencePosition
<= nBeginGrammarCheck
)
1985 // prepare next iteration
1986 nBeginGrammarCheck
= (xub_StrLen
)aResult
.nStartOfNextSentencePosition
;
1988 while( nSpellErrorPosition
> aResult
.nBehindEndOfSentencePosition
&& !nGrammarErrors
&& aResult
.nBehindEndOfSentencePosition
< nEndGrammarCheck
);
1990 if( nGrammarErrors
> 0 && nSpellErrorPosition
>= aResult
.nBehindEndOfSentencePosition
)
1993 //put the cursor to the current error
1994 const linguistic2::SingleProofreadingError
&rError
= aResult
.aErrors
[0];
1995 nCurrNd
= pNd
->GetIndex();
1996 pSttPos
->nNode
= nCurrNd
;
1997 pEndPos
->nNode
= nCurrNd
;
1998 pSpellArgs
->pStartNode
= ((SwTxtNode
*)pNd
);
1999 pSpellArgs
->pEndNode
= ((SwTxtNode
*)pNd
);
2000 pSpellArgs
->pStartIdx
->Assign(((SwTxtNode
*)pNd
), (xub_StrLen
)ModelToViewHelper::ConvertToModelPosition( pConversionMap
, rError
.nErrorStart
).mnPos
);
2001 pSpellArgs
->pEndIdx
->Assign(((SwTxtNode
*)pNd
), (xub_StrLen
)ModelToViewHelper::ConvertToModelPosition( pConversionMap
, rError
.nErrorStart
+ rError
.nErrorLength
).mnPos
);
2009 case ND_SECTIONNODE
:
2010 if( ( ((SwSectionNode
*)pNd
)->GetSection().IsProtect() ||
2011 ((SwSectionNode
*)pNd
)->GetSection().IsHidden() ) )
2012 nCurrNd
= pNd
->EndOfSectionIndex();
2020 bGoOn
= nCurrNd
< nEndNd
;
2025 if( !aRet
.hasValue() )
2028 aRet
<<= pConvArgs
->aConvText
;
2030 aRet
<<= pSpellArgs
->xSpellAlt
;
2037 class SwHyphArgs
: public SwInterHyphInfo
2039 const SwNode
*pStart
;
2042 sal_uInt16
*pPageCnt
;
2043 sal_uInt16
*pPageSt
;
2046 xub_StrLen nPamStart
;
2050 SwHyphArgs( const SwPaM
*pPam
, const Point
&rPoint
,
2051 sal_uInt16
* pPageCount
, sal_uInt16
* pPageStart
);
2052 void SetPam( SwPaM
*pPam
) const;
2053 inline void SetNode( SwNode
*pNew
) { pNode
= pNew
; }
2054 inline const SwNode
*GetNode() const { return pNode
; }
2055 inline void SetRange( const SwNode
*pNew
);
2056 inline void NextNode() { ++nNode
; }
2057 inline sal_uInt16
*GetPageCnt() { return pPageCnt
; }
2058 inline sal_uInt16
*GetPageSt() { return pPageSt
; }
2061 SwHyphArgs::SwHyphArgs( const SwPaM
*pPam
, const Point
&rCrsrPos
,
2062 sal_uInt16
* pPageCount
, sal_uInt16
* pPageStart
)
2063 : SwInterHyphInfo( rCrsrPos
), pNode(0),
2064 pPageCnt( pPageCount
), pPageSt( pPageStart
)
2066 // Folgende Bedingungen muessen eingehalten werden:
2067 // 1) es gibt mindestens eine Selektion
2068 // 2) SPoint() == Start()
2069 ASSERT( pPam
->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
2070 ASSERT( *pPam
->GetPoint() <= *pPam
->GetMark(),
2071 "SwDoc::Hyphenate: New York, New York");
2073 const SwPosition
*pPoint
= pPam
->GetPoint();
2074 nNode
= pPoint
->nNode
.GetIndex();
2077 pStart
= pPoint
->nNode
.GetNode().GetTxtNode();
2078 nPamStart
= pPoint
->nContent
.GetIndex();
2080 // Ende und Laenge einstellen.
2081 const SwPosition
*pMark
= pPam
->GetMark();
2082 pEnd
= pMark
->nNode
.GetNode().GetTxtNode();
2083 nPamLen
= pMark
->nContent
.GetIndex();
2084 if( pPoint
->nNode
== pMark
->nNode
)
2085 nPamLen
= nPamLen
- pPoint
->nContent
.GetIndex();
2088 inline void SwHyphArgs::SetRange( const SwNode
*pNew
)
2090 nStart
= pStart
== pNew
? nPamStart
: 0;
2091 nLen
= pEnd
== pNew
? nPamLen
: STRING_NOTFOUND
;
2094 void SwHyphArgs::SetPam( SwPaM
*pPam
) const
2097 *pPam
->GetPoint() = *pPam
->GetMark();
2100 pPam
->GetPoint()->nNode
= nNode
;
2101 pPam
->GetPoint()->nContent
.Assign( pNode
->GetCntntNode(), nWordStart
);
2102 pPam
->GetMark()->nNode
= nNode
;
2103 pPam
->GetMark()->nContent
.Assign( pNode
->GetCntntNode(),
2104 nWordStart
+ nWordLen
);
2105 ASSERT( nNode
== pNode
->GetIndex(),
2106 "SwHyphArgs::SetPam: Pam desaster" );
2110 // liefert sal_True zurueck, wenn es weitergehen soll.
2111 sal_Bool
lcl_HyphenateNode( const SwNodePtr
& rpNd
, void* pArgs
)
2113 // Hyphenate liefert sal_True zurueck, wenn eine Trennstelle anliegt
2114 // und stellt pPam ein.
2115 SwTxtNode
*pNode
= rpNd
->GetTxtNode();
2116 SwHyphArgs
*pHyphArgs
= (SwHyphArgs
*)pArgs
;
2119 SwCntntFrm
* pCntFrm
= pNode
->GetFrm();
2120 if( pCntFrm
&& !((SwTxtFrm
*)pCntFrm
)->IsHiddenNow() )
2122 sal_uInt16
*pPageSt
= pHyphArgs
->GetPageSt();
2123 sal_uInt16
*pPageCnt
= pHyphArgs
->GetPageCnt();
2124 if( pPageCnt
&& *pPageCnt
&& pPageSt
)
2126 sal_uInt16 nPageNr
= pCntFrm
->GetPhyPageNum();
2130 if( *pPageCnt
< *pPageSt
)
2131 *pPageCnt
= *pPageSt
;
2133 long nStat
= nPageNr
>= *pPageSt
? nPageNr
- *pPageSt
+ 1
2134 : nPageNr
+ *pPageCnt
- *pPageSt
+ 1;
2135 ::SetProgressState( nStat
, (SwDocShell
*)pNode
->GetDoc()->GetDocShell() );
2137 pHyphArgs
->SetRange( rpNd
);
2138 if( pNode
->Hyphenate( *pHyphArgs
) )
2140 pHyphArgs
->SetNode( rpNd
);
2145 pHyphArgs
->NextNode();
2149 uno::Reference
< XHyphenatedWord
> SwDoc::Hyphenate(
2150 SwPaM
*pPam
, const Point
&rCrsrPos
,
2151 sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
)
2153 ASSERT(this == pPam
->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
2155 if( *pPam
->GetPoint() > *pPam
->GetMark() )
2158 SwHyphArgs
aHyphArg( pPam
, rCrsrPos
, pPageCnt
, pPageSt
);
2159 SwNodeIndex
aTmpIdx( pPam
->GetMark()->nNode
, 1 );
2160 GetNodes().ForEach( pPam
->GetPoint()->nNode
, aTmpIdx
,
2161 lcl_HyphenateNode
, &aHyphArg
);
2162 aHyphArg
.SetPam( pPam
);
2163 return aHyphArg
.GetHyphWord(); // will be set by lcl_HyphenateNode
2167 sal_Bool
lcl_GetTokenToParaBreak( String
& rStr
, String
& rRet
, sal_Bool bRegExpRplc
)
2169 sal_Bool bRet
= sal_False
;
2172 xub_StrLen nPos
= 0;
2173 String
sPara( String::CreateFromAscii(
2174 RTL_CONSTASCII_STRINGPARAM( "\\n" )));
2175 while( STRING_NOTFOUND
!= ( nPos
= rStr
.Search( sPara
, nPos
)) )
2177 // wurde das escaped?
2178 if( nPos
&& '\\' == rStr
.GetChar( nPos
-1 ))
2180 if( ++nPos
>= rStr
.Len() )
2185 rRet
= rStr
.Copy( 0, nPos
);
2186 rStr
.Erase( 0, nPos
+ sPara
.Len() );
2200 bool SwDoc::ReplaceRange( SwPaM
& rPam
, const String
& rStr
,
2201 const bool bRegExReplace
)
2203 // unfortunately replace works slightly differently from delete,
2204 // so we cannot use lcl_DoWithBreaks here...
2206 ::std::vector
<xub_StrLen
> Breaks
;
2208 SwPaM
aPam( *rPam
.GetMark(), *rPam
.GetPoint() );
2209 aPam
.Normalize(FALSE
);
2210 if (aPam
.GetPoint()->nNode
!= aPam
.GetMark()->nNode
)
2212 aPam
.Move(fnMoveBackward
);
2214 ASSERT((aPam
.GetPoint()->nNode
== aPam
.GetMark()->nNode
), "invalid pam?");
2216 lcl_CalcBreaks(Breaks
, aPam
);
2218 while (!Breaks
.empty() // skip over prefix of dummy chars
2219 && (aPam
.GetMark()->nContent
.GetIndex() == *Breaks
.begin()) )
2222 ++aPam
.GetMark()->nContent
; // always in bounds if Breaks valid
2223 Breaks
.erase(Breaks
.begin());
2225 *rPam
.Start() = *aPam
.GetMark(); // update start of original pam w/ prefix
2229 return ReplaceRangeImpl(rPam
, rStr
, bRegExReplace
); // original pam!
2232 // N.B.: deletion must be split into several parts if the text node
2233 // contains a text attribute with end and with dummy character
2234 // and the selection does not contain the text attribute completely,
2235 // but overlaps its start (left), where the dummy character is.
2238 // iterate from end to start, to avoid invalidating the offsets!
2239 ::std::vector
<xub_StrLen
>::reverse_iterator
iter( Breaks
.rbegin() );
2240 ASSERT(aPam
.GetPoint() == aPam
.End(), "wrong!");
2241 SwPosition
& rEnd( *aPam
.End() );
2242 SwPosition
& rStart( *aPam
.Start() );
2244 // set end of temp pam to original end (undo Move backward above)
2246 // after first deletion, rEnd will point into the original text node again!
2248 while (iter
!= Breaks
.rend())
2250 rStart
.nContent
= *iter
+ 1;
2251 if (rEnd
.nContent
!= rStart
.nContent
) // check if part is empty
2253 bRet
&= (IsRedlineOn())
2254 ? DeleteAndJoinWithRedlineImpl(aPam
)
2255 : DeleteAndJoinImpl(aPam
, false);
2257 rEnd
.nContent
= *iter
;
2261 rStart
= *rPam
.Start(); // set to original start
2262 ASSERT(rEnd
.nContent
> rStart
.nContent
, "replace part empty!");
2263 if (rEnd
.nContent
> rStart
.nContent
) // check if part is empty
2265 bRet
&= ReplaceRangeImpl(aPam
, rStr
, bRegExReplace
);
2268 rPam
= aPam
; // update original pam (is this required?)
2273 // N.B.: it is possible to call Replace with a PaM that spans 2 paragraphs:
2274 // search with regex for "$", then replace _all_
2275 bool SwDoc::ReplaceRangeImpl( SwPaM
& rPam
, const String
& rStr
,
2276 const bool bRegExReplace
)
2278 if( !rPam
.HasMark() || *rPam
.GetPoint() == *rPam
.GetMark() )
2281 sal_Bool bJoinTxt
, bJoinPrev
;
2282 lcl_GetJoinFlags( rPam
, bJoinTxt
, bJoinPrev
);
2285 // dann eine Kopie vom Cursor erzeugen um alle Pams aus den
2286 // anderen Sichten aus dem Loeschbereich zu verschieben
2287 // ABER NICHT SICH SELBST !!
2288 SwPaM
aDelPam( *rPam
.GetMark(), *rPam
.GetPoint() );
2289 ::PaMCorrAbs( aDelPam
, *aDelPam
.GetPoint() );
2291 SwPosition
*pStt
= (SwPosition
*)aDelPam
.Start(),
2292 *pEnd
= (SwPosition
*)aDelPam
.End();
2293 ASSERT( pStt
->nNode
== pEnd
->nNode
||
2294 ( pStt
->nNode
.GetIndex() + 1 == pEnd
->nNode
.GetIndex() &&
2295 !pEnd
->nContent
.GetIndex() ),
2296 "invalid range: Point and Mark on different nodes" );
2297 sal_Bool bOneNode
= pStt
->nNode
== pEnd
->nNode
;
2299 // eigenes Undo ????
2300 String
sRepl( rStr
);
2301 SwTxtNode
* pTxtNd
= pStt
->nNode
.GetNode().GetTxtNode();
2302 xub_StrLen nStt
= pStt
->nContent
.GetIndex(),
2303 nEnd
= bOneNode
? pEnd
->nContent
.GetIndex()
2304 : pTxtNd
->GetTxt().Len();
2306 SwDataChanged
aTmp( aDelPam
, 0 );
2310 RedlineMode_t eOld
= GetRedlineMode();
2311 checkRedlining(eOld
);
2314 StartUndo(UNDO_EMPTY
, NULL
);
2316 // Bug 68584 - if any Redline will change (split!) the node
2317 const ::sw::mark::IMark
* pBkmk
= getIDocumentMarkAccess()->makeMark( aDelPam
, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK
);
2319 //JP 06.01.98: MUSS noch optimiert werden!!!
2321 (RedlineMode_t
)(nsRedlineMode_t::REDLINE_ON
| nsRedlineMode_t::REDLINE_SHOW_INSERT
| nsRedlineMode_t::REDLINE_SHOW_DELETE
));
2323 *aDelPam
.GetPoint() = pBkmk
->GetMarkPos();
2324 if(pBkmk
->IsExpanded())
2325 *aDelPam
.GetMark() = pBkmk
->GetOtherMarkPos();
2326 getIDocumentMarkAccess()->deleteMark(pBkmk
);
2327 pStt
= aDelPam
.Start();
2328 pTxtNd
= pStt
->nNode
.GetNode().GetTxtNode();
2329 nStt
= pStt
->nContent
.GetIndex();
2334 // Attribute des 1. Zeichens ueber den ReplaceText setzen
2335 SfxItemSet
aSet( GetAttrPool(),
2336 RES_CHRATR_BEGIN
, RES_TXTATR_WITHEND_END
- 1,
2337 RES_UNKNOWNATR_BEGIN
, RES_UNKNOWNATR_END
-1,
2339 pTxtNd
->GetAttr( aSet
, nStt
+1, nStt
+1 );
2341 aSet
.ClearItem( RES_TXTATR_REFMARK
);
2342 aSet
.ClearItem( RES_TXTATR_TOXMARK
);
2343 aSet
.ClearItem( RES_TXTATR_CJK_RUBY
);
2344 aSet
.ClearItem( RES_TXTATR_INETFMT
);
2345 aSet
.ClearItem( RES_TXTATR_META
);
2346 aSet
.ClearItem( RES_TXTATR_METAFIELD
);
2348 if( aDelPam
.GetPoint() != aDelPam
.End() )
2352 SwNodeIndex
aPtNd( aDelPam
.GetPoint()->nNode
, -1 );
2353 xub_StrLen nPtCnt
= aDelPam
.GetPoint()->nContent
.GetIndex();
2355 sal_Bool bFirst
= sal_True
;
2357 while ( lcl_GetTokenToParaBreak( sRepl
, sIns
, bRegExReplace
) )
2359 InsertString( aDelPam
, sIns
);
2362 SwNodeIndex
aMkNd( aDelPam
.GetMark()->nNode
, -1 );
2363 xub_StrLen nMkCnt
= aDelPam
.GetMark()->nContent
.GetIndex();
2365 SplitNode( *aDelPam
.GetPoint(), false );
2368 aDelPam
.GetMark()->nNode
= aMkNd
;
2369 aDelPam
.GetMark()->nContent
.Assign(
2370 aMkNd
.GetNode().GetCntntNode(), nMkCnt
);
2374 SplitNode( *aDelPam
.GetPoint(), false );
2378 InsertString( aDelPam
, sIns
);
2381 SwPaM
aTmpRange( *aDelPam
.GetPoint() );
2382 aTmpRange
.SetMark();
2385 aDelPam
.GetPoint()->nNode
= aPtNd
;
2386 aDelPam
.GetPoint()->nContent
.Assign( aPtNd
.GetNode().GetCntntNode(),
2388 *aTmpRange
.GetMark() = *aDelPam
.GetPoint();
2390 RstTxtAttrs( aTmpRange
);
2391 InsertItemSet( aTmpRange
, aSet
, 0 );
2395 AppendUndo( new SwUndoRedlineDelete( aDelPam
, UNDO_REPLACE
));
2396 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE
, aDelPam
), true);
2398 *rPam
.GetMark() = *aDelPam
.GetMark();
2401 *aDelPam
.GetPoint() = *rPam
.GetPoint();
2402 EndUndo(UNDO_EMPTY
, NULL
);
2404 // Bug 68584 - if any Redline will change (split!) the node
2405 const ::sw::mark::IMark
* pBkmk
= getIDocumentMarkAccess()->makeMark( aDelPam
, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK
);
2407 SwIndex
& rIdx
= aDelPam
.GetPoint()->nContent
;
2408 rIdx
.Assign( 0, 0 );
2409 aDelPam
.GetMark()->nContent
= rIdx
;
2410 rPam
.GetPoint()->nNode
= 0;
2411 rPam
.GetPoint()->nContent
= rIdx
;
2412 *rPam
.GetMark() = *rPam
.GetPoint();
2413 //JP 06.01.98: MUSS noch optimiert werden!!!
2414 SetRedlineMode( eOld
);
2416 *rPam
.GetPoint() = pBkmk
->GetMarkPos();
2417 if(pBkmk
->IsExpanded())
2418 *rPam
.GetMark() = pBkmk
->GetOtherMarkPos();
2419 getIDocumentMarkAccess()->deleteMark(pBkmk
);
2421 bJoinTxt
= sal_False
;
2425 if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
2426 DeleteRedline( aDelPam
, true, USHRT_MAX
);
2428 SwUndoReplace
* pUndoRpl
= 0;
2434 if( !pUndos
->Count() ||
2435 UNDO_REPLACE
!= ( pU
= (*pUndos
)[ pUndos
->Count()-1 ])->GetId() ||
2436 ( pUndoRpl
= (SwUndoReplace
*)pU
)->IsFull() )
2438 pUndoRpl
= new SwUndoReplace();
2439 AppendUndo( pUndoRpl
);
2441 pUndoRpl
->AddEntry( aDelPam
, sRepl
, bRegExReplace
);
2442 DoUndo( sal_False
);
2445 if( aDelPam
.GetPoint() != pStt
)
2448 SwNodeIndex
aPtNd( pStt
->nNode
, -1 );
2449 xub_StrLen nPtCnt
= pStt
->nContent
.GetIndex();
2451 // die Werte nochmal setzen, falls schohn Rahmen oder Fussnoten
2452 // auf dem Text entfernt wurden!
2454 nEnd
= bOneNode
? pEnd
->nContent
.GetIndex()
2455 : pTxtNd
->GetTxt().Len();
2457 sal_Bool bFirst
= sal_True
;
2459 while ( lcl_GetTokenToParaBreak( sRepl
, sIns
, bRegExReplace
) )
2461 if( !bFirst
|| nStt
== pTxtNd
->GetTxt().Len() )
2463 InsertString( aDelPam
, sIns
);
2465 else if( nStt
< nEnd
|| sIns
.Len() )
2467 pTxtNd
->ReplaceText( pStt
->nContent
, nEnd
- nStt
, sIns
);
2469 SplitNode( *pStt
, false);
2473 if( bFirst
|| sIns
.Len() )
2475 if( !bFirst
|| nStt
== pTxtNd
->GetTxt().Len() )
2477 InsertString( aDelPam
, sIns
);
2479 else if( nStt
< nEnd
|| sIns
.Len() )
2481 pTxtNd
->ReplaceText( pStt
->nContent
, nEnd
- nStt
, sIns
);
2485 *rPam
.GetMark() = *aDelPam
.GetMark();
2488 rPam
.GetMark()->nNode
= aPtNd
;
2489 rPam
.GetMark()->nContent
.Assign( aPtNd
.GetNode().GetCntntNode(),
2492 rPam
.Move( fnMoveBackward
);
2496 pUndoRpl
->SetEntryEnd( rPam
);
2503 lcl_JoinText( rPam
, bJoinPrev
);
2509 // speicher die akt. Werte fuer die automatische Aufnahme von Ausnahmen
2510 // in die Autokorrektur
2511 void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord
* pNew
)
2513 if( pACEWord
&& pNew
!= pACEWord
)
2518 bool SwDoc::DelFullPara( SwPaM
& rPam
)
2520 const SwPosition
&rStt
= *rPam
.Start(), &rEnd
= *rPam
.End();
2521 const SwNode
* pNd
= &rStt
.nNode
.GetNode();
2522 sal_uInt32 nSectDiff
= pNd
->StartOfSectionNode()->EndOfSectionIndex() -
2523 pNd
->StartOfSectionIndex();
2524 sal_uInt32 nNodeDiff
= rEnd
.nNode
.GetIndex() - rStt
.nNode
.GetIndex();
2526 if ( nSectDiff
-2 <= nNodeDiff
|| IsRedlineOn() ||
2527 /* #i9185# Prevent getting the node after the end node (see below) */
2528 rEnd
.nNode
.GetIndex() + 1 == aNodes
.Count() )
2531 // harte SeitenUmbrueche am nachfolgenden Node verschieben
2532 sal_Bool bSavePageBreak
= sal_False
, bSavePageDesc
= sal_False
;
2534 /* #i9185# This whould lead to a segmentation fault if not catched
2536 ULONG nNextNd
= rEnd
.nNode
.GetIndex() + 1;
2537 SwTableNode
* pTblNd
= aNodes
[ nNextNd
]->GetTableNode();
2539 if( pTblNd
&& pNd
->IsCntntNode() )
2541 SwFrmFmt
* pTableFmt
= pTblNd
->GetTable().GetFrmFmt();
2542 //JP 24.08.98: will man wirklich den PageDesc/Break vom
2543 // nachfolgen Absatz ueberbuegeln?
2544 // const SwAttrSet& rAttrSet = pTableFmt->GetAttrSet();
2545 // if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
2546 // SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
2548 const SfxPoolItem
*pItem
;
2549 const SfxItemSet
* pSet
= ((SwCntntNode
*)pNd
)->GetpSwAttrSet();
2550 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState( RES_PAGEDESC
,
2551 sal_False
, &pItem
) )
2553 pTableFmt
->SetFmtAttr( *pItem
);
2554 bSavePageDesc
= sal_True
;
2557 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
,
2558 sal_False
, &pItem
) )
2560 pTableFmt
->SetFmtAttr( *pItem
);
2561 bSavePageBreak
= sal_True
;
2566 sal_Bool bDoesUndo
= DoesUndo();
2569 if( !rPam
.HasMark() )
2571 else if( rPam
.GetPoint() == &rStt
)
2573 rPam
.GetPoint()->nNode
++;
2575 SwCntntNode
*pTmpNode
= rPam
.GetPoint()->nNode
.GetNode().GetCntntNode();
2576 rPam
.GetPoint()->nContent
.Assign( pTmpNode
, 0 );
2577 bool bGoNext
= (0 == pTmpNode
);
2578 pTmpNode
= rPam
.GetMark()->nNode
.GetNode().GetCntntNode();
2579 rPam
.GetMark()->nContent
.Assign( pTmpNode
, 0 );
2583 SwPaM
aDelPam( *rPam
.GetMark(), *rPam
.GetPoint() );
2585 SwPosition
aTmpPos( *aDelPam
.GetPoint() );
2588 pTmpNode
= GetNodes().GoNext( &aTmpPos
.nNode
);
2589 aTmpPos
.nContent
.Assign( pTmpNode
, 0 );
2591 ::PaMCorrAbs( aDelPam
, aTmpPos
);
2594 SwUndoDelete
* pUndo
= new SwUndoDelete( aDelPam
, sal_True
);
2596 *rPam
.GetPoint() = *aDelPam
.GetPoint();
2597 pUndo
->SetPgBrkFlags( bSavePageBreak
, bSavePageDesc
);
2598 AppendUndo( pUndo
);
2602 SwNodeRange
aRg( rStt
.nNode
, rEnd
.nNode
);
2603 if( rPam
.GetPoint() != &rEnd
)
2606 // versuche hinters Ende zu verschieben
2607 if( !rPam
.Move( fnMoveForward
, fnGoNode
) )
2609 // na gut, dann an den Anfang
2611 if( !rPam
.Move( fnMoveBackward
, fnGoNode
))
2613 ASSERT( sal_False
, "kein Node mehr vorhanden" );
2617 // text::Bookmarks usw. verschieben
2618 CorrAbs( aRg
.aStart
, aRg
.aEnd
, *rPam
.GetPoint(), sal_True
);
2620 // was ist mit Fly's ??
2622 // stehen noch FlyFrames rum, loesche auch diese
2623 const SwPosition
* pAPos
;
2624 for( sal_uInt16 n
= 0; n
< GetSpzFrmFmts()->Count(); ++n
)
2626 SwFrmFmt
* pFly
= (*GetSpzFrmFmts())[n
];
2627 const SwFmtAnchor
* pAnchor
= &pFly
->GetAnchor();
2628 if( ( FLY_AT_CNTNT
== pAnchor
->GetAnchorId() ||
2629 FLY_AUTO_CNTNT
== pAnchor
->GetAnchorId() ) &&
2630 0 != ( pAPos
= pAnchor
->GetCntntAnchor() ) &&
2631 aRg
.aStart
<= pAPos
->nNode
&& pAPos
->nNode
<= aRg
.aEnd
)
2633 DelLayoutFmt( pFly
);
2639 SwCntntNode
*pTmpNode
= rPam
.GetBound( TRUE
).nNode
.GetNode().GetCntntNode();
2640 rPam
.GetBound( TRUE
).nContent
.Assign( pTmpNode
, 0 );
2641 pTmpNode
= rPam
.GetBound( FALSE
).nNode
.GetNode().GetCntntNode();
2642 rPam
.GetBound( FALSE
).nContent
.Assign( pTmpNode
, 0 );
2643 GetNodes().Delete( aRg
.aStart
, nNodeDiff
+1 );
2652 void SwDoc::TransliterateText( const SwPaM
& rPaM
,
2653 utl::TransliterationWrapper
& rTrans
)
2655 SwUndoTransliterate
* pUndo
;
2657 pUndo
= new SwUndoTransliterate( rPaM
, rTrans
);
2661 const SwPosition
* pStt
= rPaM
.Start(),
2662 * pEnd
= pStt
== rPaM
.GetPoint() ? rPaM
.GetMark()
2664 ULONG nSttNd
= pStt
->nNode
.GetIndex(), nEndNd
= pEnd
->nNode
.GetIndex();
2665 xub_StrLen nSttCnt
= pStt
->nContent
.GetIndex(),
2666 nEndCnt
= pEnd
->nContent
.GetIndex();
2668 SwTxtNode
* pTNd
= pStt
->nNode
.GetNode().GetTxtNode();
2669 if( pStt
== pEnd
&& pTNd
) // no region ?
2672 if( pBreakIt
->GetBreakIter().is() )
2673 aBndry
= pBreakIt
->GetBreakIter()->getWordBoundary(
2674 pTNd
->GetTxt(), nSttCnt
,
2675 pBreakIt
->GetLocale( pTNd
->GetLang( nSttCnt
) ),
2676 WordType::ANY_WORD
/*ANYWORD_IGNOREWHITESPACES*/,
2679 if( aBndry
.startPos
< nSttCnt
&& nSttCnt
< aBndry
.endPos
)
2681 nSttCnt
= (xub_StrLen
)aBndry
.startPos
;
2682 nEndCnt
= (xub_StrLen
)aBndry
.endPos
;
2686 if( nSttNd
!= nEndNd
)
2688 SwNodeIndex
aIdx( pStt
->nNode
);
2693 pTNd
->TransliterateText( rTrans
, nSttCnt
,
2694 pTNd
->GetTxt().Len(), pUndo
);
2697 for( ; aIdx
.GetIndex() < nEndNd
; aIdx
++ )
2698 if( 0 != ( pTNd
= aIdx
.GetNode().GetTxtNode() ))
2699 pTNd
->TransliterateText( rTrans
, 0, pTNd
->GetTxt().Len(),
2702 if( nEndCnt
&& 0 != ( pTNd
= pEnd
->nNode
.GetNode().GetTxtNode() ))
2703 pTNd
->TransliterateText( rTrans
, 0, nEndCnt
, pUndo
);
2705 else if( pTNd
&& nSttCnt
< nEndCnt
)
2706 pTNd
->TransliterateText( rTrans
, nSttCnt
, nEndCnt
, pUndo
);
2710 if( pUndo
->HasData() )
2713 AppendUndo( pUndo
);
2720 #define MAX_REDLINE_COUNT 250
2721 // -----------------------------------------------------------------------------
2722 void SwDoc::checkRedlining(RedlineMode_t
& _rReadlineMode
)
2724 const SwRedlineTbl
& rRedlineTbl
= GetRedlineTbl();
2725 SwEditShell
* pEditShell
= GetEditShell();
2726 Window
* pParent
= pEditShell
? pEditShell
->GetWin() : NULL
;
2727 if ( pParent
&& !mbReadlineChecked
&& rRedlineTbl
.Count() > MAX_REDLINE_COUNT
2728 && !((_rReadlineMode
& nsRedlineMode_t::REDLINE_SHOW_DELETE
) == nsRedlineMode_t::REDLINE_SHOW_DELETE
) )
2730 WarningBox
aWarning( pParent
,SW_RES(MSG_DISABLE_READLINE_QUESTION
));
2731 USHORT nResult
= aWarning
.Execute();
2732 mbReadlineChecked
= sal_True
;
2733 if ( nResult
== RET_YES
)
2735 sal_Int32 nMode
= (sal_Int32
)_rReadlineMode
;
2736 nMode
|= nsRedlineMode_t::REDLINE_SHOW_INSERT
| nsRedlineMode_t::REDLINE_SHOW_DELETE
;
2737 _rReadlineMode
= (RedlineMode_t
)nMode
;
2741 // -----------------------------------------------------------------------------
2743 void SwDoc::CountWords( const SwPaM
& rPaM
, SwDocStat
& rStat
) const
2745 // This is a modified version of SwDoc::TransliterateText
2746 const SwPosition
* pStt
= rPaM
.Start();
2747 const SwPosition
* pEnd
= pStt
== rPaM
.GetPoint() ? rPaM
.GetMark()
2750 const ULONG nSttNd
= pStt
->nNode
.GetIndex();
2751 const ULONG nEndNd
= pEnd
->nNode
.GetIndex();
2753 const xub_StrLen nSttCnt
= pStt
->nContent
.GetIndex();
2754 const xub_StrLen nEndCnt
= pEnd
->nContent
.GetIndex();
2756 const SwTxtNode
* pTNd
= pStt
->nNode
.GetNode().GetTxtNode();
2757 if( pStt
== pEnd
&& pTNd
) // no region ?
2763 if( nSttNd
!= nEndNd
)
2765 SwNodeIndex
aIdx( pStt
->nNode
);
2770 pTNd
->CountWords( rStat
, nSttCnt
, pTNd
->GetTxt().Len() );
2773 for( ; aIdx
.GetIndex() < nEndNd
; aIdx
++ )
2774 if( 0 != ( pTNd
= aIdx
.GetNode().GetTxtNode() ))
2775 pTNd
->CountWords( rStat
, 0, pTNd
->GetTxt().Len() );
2777 if( nEndCnt
&& 0 != ( pTNd
= pEnd
->nNode
.GetNode().GetTxtNode() ))
2778 pTNd
->CountWords( rStat
, 0, nEndCnt
);
2780 else if( pTNd
&& nSttCnt
< nEndCnt
)
2781 pTNd
->CountWords( rStat
, nSttCnt
, nEndCnt
);
2784 void SwDoc::RemoveLeadingWhiteSpace(const SwPosition
& rPos
)
2786 const SwTxtNode
* pTNd
= rPos
.nNode
.GetNode().GetTxtNode();
2789 const String
& rTxt
= pTNd
->GetTxt();
2790 xub_StrLen nIdx
= 0;
2792 while( nIdx
< rTxt
.Len() &&
2793 ( '\t' == ( cCh
= rTxt
.GetChar( nIdx
) ) ||
2800 aPam
.GetPoint()->nContent
= 0;
2802 aPam
.GetMark()->nContent
= nIdx
;
2803 DeleteRange( aPam
);