Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <string.h> // for strchr()
31 : : #include <hintids.hxx>
32 : :
33 : : #include <editeng/cscoitem.hxx>
34 : : #include <editeng/brkitem.hxx>
35 : : #include <linguistic/lngprops.hxx>
36 : : #include <com/sun/star/beans/XPropertySet.hpp>
37 : : #include <com/sun/star/i18n/WordType.hpp>
38 : : #include <unotools/charclass.hxx>
39 : : #include <unotools/transliterationwrapper.hxx>
40 : : #include <fmtanchr.hxx>
41 : : #include <fmtcntnt.hxx>
42 : : #include <fmtpdsc.hxx>
43 : : #include <txtftn.hxx>
44 : : #include <acorrect.hxx> // AutoCorrect
45 : : #include <IMark.hxx> // for SwBookmark
46 : : #include <cntfrm.hxx> // for Spell
47 : : #include <crsrsh.hxx>
48 : : #include <doc.hxx>
49 : : #include <UndoManager.hxx>
50 : : #include <docsh.hxx>
51 : : #include <docary.hxx>
52 : : #include <doctxm.hxx> // when moving: correct indexes
53 : : #include <ftnidx.hxx>
54 : : #include <ftninfo.hxx>
55 : : #include <mdiexp.hxx> // status bar
56 : : #include <mvsave.hxx> // structures to save when moving/deleting
57 : : #include <ndtxt.hxx>
58 : : #include <pam.hxx>
59 : : #include <redline.hxx>
60 : : #include <rootfrm.hxx> // for UpdateFtn
61 : : #include <splargs.hxx> // for Spell
62 : : #include <swtable.hxx>
63 : : #include <swundo.hxx> // for the UndoIds
64 : : #include <txtfrm.hxx>
65 : : #include <hints.hxx>
66 : : #include <UndoSplitMove.hxx>
67 : : #include <UndoRedline.hxx>
68 : : #include <UndoOverwrite.hxx>
69 : : #include <UndoInsert.hxx>
70 : : #include <UndoDelete.hxx>
71 : : #include <breakit.hxx>
72 : : #include <hhcwrp.hxx>
73 : : #include <vcl/msgbox.hxx>
74 : : #include "comcore.hrc"
75 : : #include "editsh.hxx"
76 : : #include <fldbas.hxx>
77 : : #include <fmtfld.hxx>
78 : : #include <docufld.hxx>
79 : : #include <unoflatpara.hxx>
80 : : #include <SwGrammarMarkUp.hxx>
81 : :
82 : : #include <vector>
83 : :
84 : : using ::rtl::OUString;
85 : : using namespace ::com::sun::star;
86 : : using namespace ::com::sun::star::linguistic2;
87 : : using namespace ::com::sun::star::i18n;
88 : :
89 : : #ifndef S2U
90 : : #define S2U(rString) OUString::createFromAscii(rString)
91 : : #endif
92 : :
93 : : struct _SaveRedline
94 : : {
95 : : SwRedline* pRedl;
96 : : sal_uInt32 nStt, nEnd;
97 : : xub_StrLen nSttCnt, nEndCnt;
98 : :
99 : 0 : _SaveRedline( SwRedline* pR, const SwNodeIndex& rSttIdx )
100 : 0 : : pRedl( pR )
101 : : {
102 : 0 : const SwPosition* pStt = pR->Start(),
103 [ # # ]: 0 : * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
104 : 0 : sal_uInt32 nSttIdx = rSttIdx.GetIndex();
105 : 0 : nStt = pStt->nNode.GetIndex() - nSttIdx;
106 : 0 : nSttCnt = pStt->nContent.GetIndex();
107 [ # # ]: 0 : if( pR->HasMark() )
108 : : {
109 : 0 : nEnd = pEnd->nNode.GetIndex() - nSttIdx;
110 : 0 : nEndCnt = pEnd->nContent.GetIndex();
111 : : }
112 : :
113 : 0 : pRedl->GetPoint()->nNode = 0;
114 : 0 : pRedl->GetPoint()->nContent.Assign( 0, 0 );
115 : 0 : pRedl->GetMark()->nNode = 0;
116 : 0 : pRedl->GetMark()->nContent.Assign( 0, 0 );
117 : 0 : }
118 : :
119 : 0 : _SaveRedline( SwRedline* pR, const SwPosition& rPos )
120 : 0 : : pRedl( pR )
121 : : {
122 : 0 : const SwPosition* pStt = pR->Start(),
123 [ # # ]: 0 : * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
124 : 0 : sal_uInt32 nSttIdx = rPos.nNode.GetIndex();
125 : 0 : nStt = pStt->nNode.GetIndex() - nSttIdx;
126 : 0 : nSttCnt = pStt->nContent.GetIndex();
127 [ # # ]: 0 : if( nStt == 0 )
128 : 0 : nSttCnt = nSttCnt - rPos.nContent.GetIndex();
129 [ # # ]: 0 : if( pR->HasMark() )
130 : : {
131 : 0 : nEnd = pEnd->nNode.GetIndex() - nSttIdx;
132 : 0 : nEndCnt = pEnd->nContent.GetIndex();
133 [ # # ]: 0 : if( nEnd == 0 )
134 : 0 : nEndCnt = nEndCnt - rPos.nContent.GetIndex();
135 : : }
136 : :
137 : 0 : pRedl->GetPoint()->nNode = 0;
138 : 0 : pRedl->GetPoint()->nContent.Assign( 0, 0 );
139 : 0 : pRedl->GetMark()->nNode = 0;
140 : 0 : pRedl->GetMark()->nContent.Assign( 0, 0 );
141 : 0 : }
142 : :
143 : 0 : void SetPos( sal_uInt32 nInsPos )
144 : : {
145 : 0 : pRedl->GetPoint()->nNode = nInsPos + nStt;
146 [ # # ]: 0 : pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
147 [ # # ]: 0 : if( pRedl->HasMark() )
148 : : {
149 : 0 : pRedl->GetMark()->nNode = nInsPos + nEnd;
150 [ # # ]: 0 : pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt );
151 : : }
152 : 0 : }
153 : :
154 : 0 : void SetPos( const SwPosition& aPos )
155 : : {
156 : 0 : pRedl->GetPoint()->nNode = aPos.nNode.GetIndex() + nStt;
157 [ # # ][ # # ]: 0 : pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt + ( nStt == 0 ? aPos.nContent.GetIndex() : 0 ) );
158 [ # # ]: 0 : if( pRedl->HasMark() )
159 : : {
160 : 0 : pRedl->GetMark()->nNode = aPos.nNode.GetIndex() + nEnd;
161 [ # # ][ # # ]: 0 : pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt + ( nEnd == 0 ? aPos.nContent.GetIndex() : 0 ) );
162 : : }
163 : 0 : }
164 : : };
165 : :
166 : : typedef boost::ptr_vector< _SaveRedline > _SaveRedlines;
167 : :
168 : 0 : bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
169 : : {
170 : 0 : sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
171 : : return !( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
172 [ # # ][ # # ]: 0 : (0 != pNode->GetTxtAttrForCharAt( nPos ) ) );
[ # # ]
173 : : }
174 : :
175 : 0 : void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
176 : : {
177 [ # # ]: 0 : if( !lcl_MayOverwrite( pNode, rStart ) )
178 : : {
179 : : // skip all special attributes
180 [ # # ]: 0 : do {
[ # # # # ]
181 : 0 : rIdx++;
182 : 0 : } while( (rStart = rIdx.GetIndex()) < pNode->GetTxt().Len()
183 : 0 : && !lcl_MayOverwrite(pNode, rStart) );
184 : : }
185 : 0 : }
186 : :
187 : 0 : void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx,
188 : : const SwNodeIndex* pInsertPos )
189 : : {
190 [ # # ]: 0 : SwPosition aPos( rSttIdx );
191 [ # # ]: 0 : for( size_t n = 0; n < rArr.size(); ++n )
192 : : {
193 : : // create new anchor
194 [ # # ]: 0 : _SaveFly& rSave = rArr[n];
195 : 0 : SwFrmFmt* pFmt = rSave.pFrmFmt;
196 : :
197 [ # # ]: 0 : if( rSave.bInsertPosition )
198 : : {
199 [ # # ]: 0 : if( pInsertPos != NULL )
200 [ # # ]: 0 : aPos.nNode = *pInsertPos;
201 : : else
202 [ # # ]: 0 : aPos.nNode = rSttIdx.GetIndex();
203 : : }
204 : : else
205 [ # # ]: 0 : aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
206 : :
207 [ # # ]: 0 : aPos.nContent.Assign( 0, 0 );
208 [ # # ][ # # ]: 0 : SwFmtAnchor aAnchor( pFmt->GetAnchor() );
209 [ # # ]: 0 : aAnchor.SetAnchor( &aPos );
210 [ # # ]: 0 : pFmt->GetDoc()->GetSpzFrmFmts()->push_back( pFmt );
211 [ # # ]: 0 : pFmt->SetFmtAttr( aAnchor );
212 : 0 : SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
213 [ # # ][ # # ]: 0 : if( pCNd && pCNd->getLayoutFrm( pFmt->GetDoc()->GetCurrentLayout(), 0, 0, sal_False ) )
[ # # ][ # # ]
[ # # ]
214 [ # # ]: 0 : pFmt->MakeFrms();
215 [ # # ][ # # ]: 0 : }
216 : 0 : }
217 : :
218 : 0 : void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
219 : : {
220 : 0 : SwFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
221 [ # # ]: 0 : for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
222 : : {
223 : 0 : SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>(rFmts[n]);
224 : 0 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
225 : 0 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
226 [ # # ][ # # : 0 : if (pAPos &&
# # # # #
# # # ]
227 : 0 : ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
228 : 0 : (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
229 : 0 : rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
230 : : {
231 : 0 : _SaveFly aSave( pAPos->nNode.GetIndex() - rRg.aStart.GetIndex(),
232 : 0 : pFmt, sal_False );
233 [ # # ]: 0 : rArr.push_back( aSave );
234 [ # # ]: 0 : pFmt->DelFrms();
235 [ # # ][ # # ]: 0 : rFmts.erase( rFmts.begin() + n-- );
236 : : }
237 : : }
238 : 0 : }
239 : :
240 : 0 : void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
241 : : _SaveFlyArr& rArr, bool bMoveAllFlys )
242 : : {
243 : 0 : SwFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
244 : : SwFrmFmt* pFmt;
245 : : const SwFmtAnchor* pAnchor;
246 : :
247 : 0 : const SwPosition* pPos = rPam.Start();
248 : 0 : const SwNodeIndex& rSttNdIdx = pPos->nNode;
249 : 0 : short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
250 [ # # ]: 0 : pPos->nContent.GetIndex()) ? 1 : 0;
[ # # # # ]
251 : :
252 [ # # ]: 0 : pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
253 : 0 : const SwNodeIndex& rEndNdIdx = pPos->nNode;
254 : 0 : short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
255 : 0 : pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
256 [ # # # # : 0 : ? 0 : 1;
# # ]
257 : :
258 : : const SwNodeIndex* pCntntIdx;
259 : :
260 [ # # ]: 0 : for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
261 : : {
262 : 0 : sal_Bool bInsPos = sal_False;
263 : 0 : pFmt = (SwFrmFmt*)rFmts[n];
264 : 0 : pAnchor = &pFmt->GetAnchor();
265 : 0 : const SwPosition* pAPos = pAnchor->GetCntntAnchor();
266 [ # # ][ # # : 0 : if (pAPos &&
# # # # #
# # # ]
267 : 0 : ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
268 : 0 : (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
269 : : // do not move if the InsPos is in the CntntArea of the Fly
270 : 0 : ( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
271 : 0 : !( *pCntntIdx < rInsPos &&
272 [ # # ]: 0 : rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
273 : : {
274 [ # # ][ # # ]: 0 : if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
[ # # ]
275 : : {
276 : : // Do not touch Anchor, if only a part of the EndNode
277 : : // or the whole EndNode is identical with the SttNode
278 [ # # ]: 0 : if( rSttNdIdx != pAPos->nNode )
279 : : {
280 : : // Only attach an anchor to the beginning or end
281 [ # # ]: 0 : SwPosition aPos( rSttNdIdx );
282 [ # # ]: 0 : SwFmtAnchor aAnchor( *pAnchor );
283 [ # # ]: 0 : aAnchor.SetAnchor( &aPos );
284 [ # # ][ # # ]: 0 : pFmt->SetFmtAttr( aAnchor );
[ # # ]
285 : : }
286 : : }
287 [ # # # # ]: 0 : else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
[ # # ][ # # ]
288 : 0 : && pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
289 : 0 : 0 != ( bInsPos = rInsPos == pAPos->nNode ))
290 : :
291 : : {
292 : 0 : _SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
293 : 0 : pFmt, bInsPos );
294 [ # # ]: 0 : rArr.push_back( aSave );
295 [ # # ]: 0 : pFmt->DelFrms();
296 [ # # ][ # # ]: 0 : rFmts.erase( rFmts.begin() + n-- );
297 : : }
298 : : }
299 : : }
300 : 0 : }
301 : :
302 : : // Delete and move all Flys at the paragraph, that are within the selection.
303 : : // If there is a Fly at the SPoint, it is moved onto the Mark.
304 : 921 : void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
305 : : const SwNodeIndex& rPtNdIdx )
306 : : {
307 : 921 : const sal_Bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
308 : :
309 : 921 : SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
310 : 921 : SwFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
311 [ + + ]: 1581 : for ( sal_uInt16 i = rTbl.size(); i; )
312 : : {
313 : 660 : SwFrmFmt *pFmt = rTbl[--i];
314 : 660 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
315 : 660 : SwPosition const*const pAPos = rAnch.GetCntntAnchor();
316 [ + - + + : 1965 : if (pAPos &&
+ + # # #
# ][ + + ]
[ + + + +
+ + ]
317 : 609 : ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
318 : 516 : (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
319 : : ( bDelFwrd
320 : 180 : ? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
321 : 0 : : rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
322 : : {
323 : : // Only move the Anchor??
324 [ + + ]: 9 : if( rPtNdIdx == pAPos->nNode )
325 : : {
326 [ + - ][ + - ]: 6 : SwFmtAnchor aAnch( pFmt->GetAnchor() );
327 [ + - ]: 6 : SwPosition aPos( rMkNdIdx );
328 [ + - ]: 6 : aAnch.SetAnchor( &aPos );
329 [ + - ][ + - ]: 6 : pFmt->SetFmtAttr( aAnch );
[ + - ]
330 : : }
331 : : else
332 : : {
333 : : // If the Fly is deleted, all Flys in it's content have to be deleted too.
334 : 3 : const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
335 [ - + ]: 3 : if( rCntnt.GetCntntIdx() )
336 : : {
337 : 0 : DelFlyInRange( *rCntnt.GetCntntIdx(),
338 : : SwNodeIndex( *rCntnt.GetCntntIdx()->
339 [ # # ]: 0 : GetNode().EndOfSectionNode() ));
340 : : // Position could have been moved!
341 [ # # ]: 0 : if( i > rTbl.size() )
342 : 0 : i = rTbl.size();
343 [ # # ]: 0 : else if( pFmt != rTbl[i] )
344 : 0 : i = rTbl.GetPos( pFmt );
345 : : }
346 : :
347 : 3 : pDoc->DelLayoutFmt( pFmt );
348 : :
349 : : // DelLayoutFmt can also trigger the deletion of objects.
350 [ - + ]: 3 : if( i > rTbl.size() )
351 : 0 : i = rTbl.size();
352 : : }
353 : : }
354 : : }
355 : 921 : }
356 : :
357 : 132 : bool lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
358 : : const SwNodeIndex& rInsPos,
359 : : SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
360 : : const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
361 : : {
362 : 132 : bool bUpdateFtn = sal_False;
363 : 132 : const SwNodes& rNds = rInsPos.GetNodes();
364 : 132 : const bool bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
365 [ # # ][ - + ]: 132 : rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
366 : 132 : const bool bSaveFtn = !bDelFtn &&
367 [ + - ][ + - ]: 132 : rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
368 [ - + ]: 132 : if( !rFtnArr.empty() )
369 : : {
370 : :
371 : : sal_uInt16 nPos;
372 [ # # ]: 0 : rFtnArr.SeekEntry( rSttNd, &nPos );
373 : : SwTxtFtn* pSrch;
374 : : const SwNode* pFtnNd;
375 : :
376 : : // Delete/save all that come after it
377 [ # # # # ]: 0 : while( nPos < rFtnArr.size() && ( pFtnNd =
[ # # ]
378 [ # # ][ # # ]: 0 : &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
379 : 0 : <= rEndNd.GetIndex() )
380 : : {
381 : 0 : xub_StrLen nFtnSttIdx = *pSrch->GetStart();
382 [ # # # # : 0 : if( ( pEndCnt && pSttCnt )
# # # # #
# ][ # # ]
[ # # ]
383 : 0 : ? (( &rSttNd.GetNode() == pFtnNd &&
384 : 0 : pSttCnt->GetIndex() > nFtnSttIdx) ||
385 : 0 : ( &rEndNd.GetNode() == pFtnNd &&
386 : 0 : nFtnSttIdx >= pEndCnt->GetIndex() ))
387 : 0 : : ( &rEndNd.GetNode() == pFtnNd ))
388 : : {
389 : 0 : ++nPos; // continue searching
390 : : }
391 : : else
392 : : {
393 : : // delete it
394 [ # # ]: 0 : if( bDelFtn )
395 : : {
396 : 0 : SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
397 [ # # ]: 0 : SwIndex aIdx( &rTxtNd, nFtnSttIdx );
398 [ # # ][ # # ]: 0 : rTxtNd.EraseText( aIdx, 1 );
399 : : }
400 : : else
401 : : {
402 [ # # ]: 0 : pSrch->DelFrms(0);
403 [ # # ][ # # ]: 0 : rFtnArr.erase( rFtnArr.begin() + nPos );
404 [ # # ]: 0 : if( bSaveFtn )
405 [ # # ]: 0 : rSaveArr.insert( pSrch );
406 : : }
407 : 0 : bUpdateFtn = sal_True;
408 : : }
409 : : }
410 : :
411 [ # # ]: 0 : while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
[ # # # # ]
[ # # ]
412 [ # # ]: 0 : GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
413 : : {
414 : 0 : xub_StrLen nFtnSttIdx = *pSrch->GetStart();
415 [ # # # # ]: 0 : if( !pEndCnt || !pSttCnt ||
[ # # ][ # # ]
416 : 0 : !( (( &rSttNd.GetNode() == pFtnNd &&
417 : 0 : pSttCnt->GetIndex() > nFtnSttIdx ) ||
418 : 0 : ( &rEndNd.GetNode() == pFtnNd &&
419 [ # # ]: 0 : nFtnSttIdx >= pEndCnt->GetIndex() )) ))
[ # # # # ]
420 : : {
421 [ # # ]: 0 : if( bDelFtn )
422 : : {
423 : : // delete it
424 : 0 : SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
425 [ # # ]: 0 : SwIndex aIdx( &rTxtNd, nFtnSttIdx );
426 [ # # ][ # # ]: 0 : rTxtNd.EraseText( aIdx, 1 );
427 : : }
428 : : else
429 : : {
430 [ # # ]: 0 : pSrch->DelFrms(0);
431 [ # # ][ # # ]: 0 : rFtnArr.erase( rFtnArr.begin() + nPos );
432 [ # # ]: 0 : if( bSaveFtn )
433 [ # # ]: 0 : rSaveArr.insert( pSrch );
434 : : }
435 : 0 : bUpdateFtn = sal_True;
436 : : }
437 : : }
438 : : }
439 : : // When moving from redline section into document content section, e.g.
440 : : // after loading a document with (delete-)redlines, the footnote array
441 : : // has to be adjusted... (#i70572)
442 [ + - ]: 132 : if( bSaveFtn )
443 : : {
444 [ + - ]: 132 : SwNodeIndex aIdx( rSttNd );
445 [ + + ]: 264 : while( aIdx < rEndNd ) // Check the moved section
446 : : {
447 : 132 : SwNode* pNode = &aIdx.GetNode();
448 [ + - ]: 132 : if( pNode->IsTxtNode() ) // Looking for text nodes...
449 : : {
450 : : SwpHints *pHints =
451 [ + - ]: 132 : static_cast<SwTxtNode*>(pNode)->GetpSwpHints();
452 [ # # ][ - + ]: 132 : if( pHints && pHints->HasFtn() ) //...with footnotes
[ - + ]
453 : : {
454 : 0 : bUpdateFtn = sal_True; // Heureka
455 : 0 : sal_uInt16 nCount = pHints->Count();
456 [ # # ]: 0 : for( sal_uInt16 i = 0; i < nCount; ++i )
457 : : {
458 [ # # ]: 0 : SwTxtAttr *pAttr = pHints->GetTextHint( i );
459 [ # # ][ # # ]: 0 : if ( pAttr->Which() == RES_TXTATR_FTN )
460 : : {
461 [ # # ]: 0 : rSaveArr.insert( static_cast<SwTxtFtn*>(pAttr) );
462 : : }
463 : : }
464 : : }
465 : : }
466 [ + - ]: 132 : ++aIdx;
467 [ + - ]: 132 : }
468 : : }
469 : 132 : return bUpdateFtn;
470 : : }
471 : :
472 : 0 : void lcl_SaveRedlines( const SwPaM& aPam, _SaveRedlines& rArr )
473 : : {
474 : 0 : SwDoc* pDoc = aPam.GetNode()->GetDoc();
475 : :
476 [ # # ]: 0 : const SwPosition* pStart = aPam.Start();
477 [ # # ]: 0 : const SwPosition* pEnd = aPam.End();
478 : :
479 : : // get first relevant redline
480 : : sal_uInt16 nCurrentRedline;
481 [ # # ]: 0 : pDoc->GetRedline( *pStart, &nCurrentRedline );
482 [ # # ]: 0 : if( nCurrentRedline > 0)
483 : 0 : nCurrentRedline--;
484 : :
485 : : // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
486 [ # # ]: 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
487 [ # # ]: 0 : pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
488 : :
489 : : // iterate over relevant redlines and decide for each whether it should
490 : : // be saved, or split + saved
491 [ # # ]: 0 : SwRedlineTbl& rRedlineTable = const_cast<SwRedlineTbl&>( pDoc->GetRedlineTbl() );
492 [ # # ]: 0 : for( ; nCurrentRedline < rRedlineTable.size(); nCurrentRedline++ )
493 : : {
494 [ # # ]: 0 : SwRedline* pCurrent = rRedlineTable[ nCurrentRedline ];
495 : : SwComparePosition eCompare =
496 [ # # ][ # # ]: 0 : ComparePosition( *pCurrent->Start(), *pCurrent->End(),
497 [ # # ]: 0 : *pStart, *pEnd);
498 : :
499 : : // we must save this redline if it overlaps aPam
500 : : // (we may have to split it, too)
501 [ # # ][ # # ]: 0 : if( eCompare == POS_OVERLAP_BEHIND ||
[ # # ][ # # ]
[ # # ]
502 : : eCompare == POS_OVERLAP_BEFORE ||
503 : : eCompare == POS_OUTSIDE ||
504 : : eCompare == POS_INSIDE ||
505 : : eCompare == POS_EQUAL )
506 : : {
507 [ # # ]: 0 : rRedlineTable.Remove( nCurrentRedline-- );
508 : :
509 : : // split beginning, if necessary
510 [ # # ][ # # ]: 0 : if( eCompare == POS_OVERLAP_BEFORE ||
511 : : eCompare == POS_OUTSIDE )
512 : : {
513 : :
514 [ # # ][ # # ]: 0 : SwRedline* pNewRedline = new SwRedline( *pCurrent );
515 [ # # ][ # # ]: 0 : *pNewRedline->End() = *pStart;
516 [ # # ][ # # ]: 0 : *pCurrent->Start() = *pStart;
517 [ # # ]: 0 : pDoc->AppendRedline( pNewRedline, true );
518 : : }
519 : :
520 : : // split end, if necessary
521 [ # # ][ # # ]: 0 : if( eCompare == POS_OVERLAP_BEHIND ||
522 : : eCompare == POS_OUTSIDE )
523 : : {
524 [ # # ][ # # ]: 0 : SwRedline* pNewRedline = new SwRedline( *pCurrent );
525 [ # # ][ # # ]: 0 : *pNewRedline->Start() = *pEnd;
526 [ # # ][ # # ]: 0 : *pCurrent->End() = *pEnd;
527 [ # # ]: 0 : pDoc->AppendRedline( pNewRedline, true );
528 : : }
529 : :
530 : : // save the current redline
531 [ # # ][ # # ]: 0 : _SaveRedline* pSave = new _SaveRedline( pCurrent, *pStart );
532 [ # # ]: 0 : rArr.push_back( pSave );
533 : : }
534 : : }
535 : :
536 : : // restore old redline mode
537 [ # # ]: 0 : pDoc->SetRedlineMode_intern( eOld );
538 : 0 : }
539 : :
540 : 0 : void lcl_RestoreRedlines( SwDoc* pDoc, const SwPosition& rPos, _SaveRedlines& rArr )
541 : : {
542 : 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
543 : 0 : pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
544 : :
545 [ # # ]: 0 : for( size_t n = 0; n < rArr.size(); ++n )
546 : : {
547 : 0 : rArr[ n ].SetPos( rPos );
548 : 0 : pDoc->AppendRedline( rArr[ n ].pRedl, true );
549 : : }
550 : :
551 : 0 : pDoc->SetRedlineMode_intern( eOld );
552 : 0 : }
553 : :
554 : 0 : void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
555 : : {
556 : 0 : SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
557 : : sal_uInt16 nRedlPos;
558 [ # # ][ # # ]: 0 : SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
559 [ # # ][ # # ]: 0 : aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
560 [ # # ][ # # ]: 0 : if( pDoc->GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
[ # # ][ # # ]
561 : 0 : --nRedlPos;
562 [ # # ][ # # ]: 0 : else if( nRedlPos >= pDoc->GetRedlineTbl().size() )
563 : 0 : return ;
564 : :
565 [ # # ]: 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
566 [ # # ]: 0 : pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
567 [ # # ]: 0 : SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
568 : :
569 [ # # ]: 0 : do {
570 [ # # ]: 0 : SwRedline* pTmp = rRedlTbl[ nRedlPos ];
571 : :
572 [ # # ]: 0 : const SwPosition* pRStt = pTmp->Start(),
573 : 0 : * pREnd = pTmp->GetMark() == pRStt
574 [ # # ]: 0 : ? pTmp->GetPoint() : pTmp->GetMark();
575 : :
576 [ # # ]: 0 : if( pRStt->nNode < rRg.aStart )
577 : : {
578 [ # # ][ # # ]: 0 : if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
[ # # ]
579 : : {
580 : : // Create a copy and set the end of the original to the end of the MoveArea.
581 : : // The copy is moved too.
582 [ # # ][ # # ]: 0 : SwRedline* pNewRedl = new SwRedline( *pTmp );
583 [ # # ]: 0 : SwPosition* pTmpPos = pNewRedl->Start();
584 [ # # ]: 0 : pTmpPos->nNode = rRg.aStart;
585 : : pTmpPos->nContent.Assign(
586 [ # # ][ # # ]: 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
587 : :
588 [ # # ][ # # ]: 0 : _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
589 [ # # ]: 0 : rArr.push_back( pSave );
590 : :
591 [ # # ]: 0 : pTmpPos = pTmp->End();
592 [ # # ]: 0 : pTmpPos->nNode = rRg.aEnd;
593 : : pTmpPos->nContent.Assign(
594 [ # # ][ # # ]: 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
595 : : }
596 [ # # ]: 0 : else if( pREnd->nNode == rRg.aStart )
597 : : {
598 [ # # ]: 0 : SwPosition* pTmpPos = pTmp->End();
599 [ # # ]: 0 : pTmpPos->nNode = rRg.aEnd;
600 : : pTmpPos->nContent.Assign(
601 [ # # ][ # # ]: 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
602 : : }
603 : : }
604 [ # # ]: 0 : else if( pRStt->nNode < rRg.aEnd )
605 : : {
606 [ # # ]: 0 : rRedlTbl.Remove( nRedlPos-- );
607 [ # # # # : 0 : if( pREnd->nNode < rRg.aEnd ||
# # ][ # # ]
608 : 0 : ( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
609 : : {
610 : : // move everything
611 [ # # ][ # # ]: 0 : _SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
612 [ # # ]: 0 : rArr.push_back( pSave );
613 : : }
614 : : else
615 : : {
616 : : // split
617 [ # # ][ # # ]: 0 : SwRedline* pNewRedl = new SwRedline( *pTmp );
618 [ # # ]: 0 : SwPosition* pTmpPos = pNewRedl->End();
619 [ # # ]: 0 : pTmpPos->nNode = rRg.aEnd;
620 : : pTmpPos->nContent.Assign(
621 [ # # ][ # # ]: 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
622 : :
623 [ # # ][ # # ]: 0 : _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
624 [ # # ]: 0 : rArr.push_back( pSave );
625 : :
626 [ # # ]: 0 : pTmpPos = pTmp->Start();
627 [ # # ]: 0 : pTmpPos->nNode = rRg.aEnd;
628 : : pTmpPos->nContent.Assign(
629 [ # # ][ # # ]: 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
630 [ # # ]: 0 : pDoc->AppendRedline( pTmp, true );
631 : : }
632 : : }
633 : : else
634 : 0 : break;
635 : :
636 [ # # ]: 0 : } while( ++nRedlPos < pDoc->GetRedlineTbl().size() );
637 [ # # ][ # # ]: 0 : pDoc->SetRedlineMode_intern( eOld );
[ # # ]
638 : : }
639 : :
640 : 0 : void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
641 : : {
642 : 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
643 : 0 : pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
644 : :
645 [ # # ]: 0 : for( size_t n = 0; n < rArr.size(); ++n )
646 : : {
647 : 0 : rArr[ n ].SetPos( nInsPos );
648 : 0 : pDoc->AppendRedline( rArr[ n ].pRedl, true );
649 : : }
650 : :
651 : 0 : pDoc->SetRedlineMode_intern( eOld );
652 : 0 : }
653 : :
654 : : // #i59534: Redo of insertion of multiple text nodes runs into trouble
655 : : // because of unnecessary expanded redlines
656 : : // From now on this class saves the redline positions of all redlines which ends exact at the
657 : : // insert position (node _and_ content index)
658 : 20 : _SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, xub_StrLen nCnt )
659 : 20 : : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt )
660 : : {
661 : 20 : SwNode& rNd = rInsIdx.GetNode();
662 : 20 : SwDoc* pDest = rNd.GetDoc();
663 [ - + ]: 20 : if( !pDest->GetRedlineTbl().empty() )
664 : : {
665 : : sal_uInt16 nFndPos;
666 : : const SwPosition* pEnd;
667 [ # # ][ # # ]: 0 : SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), nCnt ));
[ # # ][ # # ]
668 [ # # ]: 0 : const SwRedline* pRedl = pDest->GetRedline( aSrcPos, &nFndPos );
669 [ # # ][ # # ]: 0 : while( nFndPos--
[ # # ][ # # ]
[ # # ]
670 [ # # ][ # # ]: 0 : && *( pEnd = ( pRedl = pDest->GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos
[ # # ]
671 [ # # ][ # # ]: 0 : && *pRedl->Start() < aSrcPos )
672 : : {
673 [ # # ]: 0 : if( !pSavArr )
674 : : {
675 [ # # ][ # # ]: 0 : pSavArr = new std::vector<SwPosition*>;
676 [ # # ][ # # ]: 0 : pSavIdx = new SwNodeIndex( rInsIdx, -1 );
677 : : }
678 [ # # ]: 0 : pSavArr->push_back( (SwPosition*)pEnd );
679 [ # # ]: 0 : }
680 : : }
681 : 20 : }
682 : :
683 : 20 : _SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
684 : : {
685 [ - + ]: 20 : delete pSavArr;
686 [ - + ]: 20 : delete pSavIdx;
687 : 20 : }
688 : :
689 : 0 : void _SaveRedlEndPosForRestore::_Restore()
690 : : {
691 : 0 : (*pSavIdx)++;
692 : 0 : SwCntntNode* pNode = pSavIdx->GetNode().GetCntntNode();
693 : : // If there's no content node at the remembered position, we will not restore the old position
694 : : // This may happen if a table (or section?) will be inserted.
695 [ # # ]: 0 : if( pNode )
696 : : {
697 [ # # ][ # # ]: 0 : SwPosition aPos( *pSavIdx, SwIndex( pNode, nSavCntnt ));
[ # # ][ # # ]
698 [ # # ]: 0 : for( sal_uInt16 n = pSavArr->size(); n; )
699 [ # # ][ # # ]: 0 : *(*pSavArr)[ --n ] = aPos;
[ # # ]
700 : : }
701 : 0 : }
702 : :
703 : : // Delete a full Section of the NodeArray.
704 : : // The passed Node is located somewhere in the designated Section.
705 : 126 : void SwDoc::DeleteSection( SwNode *pNode )
706 : : {
707 : : OSL_ENSURE( pNode, "Didn't pass a Node." );
708 : 126 : SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
709 [ + + ]: 126 : : pNode->StartOfSectionNode();
710 [ + - ][ + - ]: 126 : SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
711 : :
712 : : // delete all Flys, Bookmarks, ...
713 [ + - ]: 126 : DelFlyInRange( aSttIdx, aEndIdx );
714 [ + - ]: 126 : DeleteRedline( *pSttNd, true, USHRT_MAX );
715 [ + - ]: 126 : _DelBookmarks(aSttIdx, aEndIdx);
716 : :
717 : : {
718 : : // move all Crsr/StkCrsr/UnoCrsr out of the to-be-deleted area
719 [ + - ]: 126 : SwNodeIndex aMvStt( aSttIdx, 1 );
720 [ + - ][ + - ]: 126 : CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), sal_True );
[ + - ][ + - ]
721 : : }
722 : :
723 [ + - ][ + - ]: 126 : GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
[ + - ][ + - ]
724 : 126 : }
725 : :
726 : 0 : void SwDoc::SetModified(SwPaM &rPaM)
727 : : {
728 [ # # ]: 0 : SwDataChanged aTmp( rPaM, 0 );
729 [ # # ][ # # ]: 0 : SetModified();
730 : 0 : }
731 : :
732 : : /*************************************************************************
733 : : * SwDoc::Overwrite()
734 : : ************************************************************************/
735 : 3920 : bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
736 : : {
737 : 3920 : SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
738 [ - + ]: 3920 : if( pACEWord ) // Add to AutoCorrect
739 : : {
740 [ # # ]: 0 : if( 1 == rStr.Len() )
741 [ # # ]: 0 : pACEWord->CheckChar( rPt, rStr.GetChar( 0 ) );
742 [ # # ][ # # ]: 0 : delete pACEWord, pACEWord = 0;
743 : : }
744 : :
745 : 3920 : SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
746 [ + + ]: 3920 : if(!pNode)
747 : 2018 : return sal_False;
748 : :
749 [ + - ][ + - ]: 1902 : if (GetIDocumentUndoRedo().DoesUndo())
[ - + ]
750 : : {
751 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
752 : : }
753 : :
754 : 1902 : sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
755 [ - + ]: 1902 : ? pNode->GetpSwpHints()->Count() : 0;
756 [ + - ]: 1902 : SwDataChanged aTmp( rRg, 0 );
757 : 1902 : SwIndex& rIdx = rPt.nContent;
758 : 1902 : xub_StrLen nStart = 0;
759 : :
760 : : sal_Unicode c;
761 [ + - ]: 1902 : String aStr;
762 : :
763 : 1902 : sal_Bool bOldExpFlg = pNode->IsIgnoreDontExpand();
764 : 1902 : pNode->SetIgnoreDontExpand( sal_True );
765 : :
766 [ + + ]: 11953 : for( xub_StrLen nCnt = 0; nCnt < rStr.Len(); ++nCnt )
767 : : {
768 : : // start behind the characters (to fix the attributes!)
769 : 10051 : nStart = rIdx.GetIndex();
770 [ - + ]: 10051 : if ( nStart < pNode->GetTxt().Len() )
771 : : {
772 [ # # ]: 0 : lcl_SkipAttr( pNode, rIdx, nStart );
773 : : }
774 : 10051 : c = rStr.GetChar( nCnt );
775 [ + - ][ - + ]: 10051 : if (GetIDocumentUndoRedo().DoesUndo())
[ + - ]
776 : : {
777 : 0 : bool bMerged(false);
778 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesGroupUndo())
[ # # ]
779 : : {
780 [ # # ][ # # ]: 0 : SwUndo *const pUndo = GetUndoManager().GetLastUndo();
781 : : SwUndoOverwrite *const pUndoOW(
782 [ # # ]: 0 : dynamic_cast<SwUndoOverwrite *>(pUndo) );
783 [ # # ]: 0 : if (pUndoOW)
784 : : {
785 : : // if CanGrouping() returns true it's already merged
786 [ # # ]: 0 : bMerged = pUndoOW->CanGrouping( this, rPt, c );
787 : : }
788 : : }
789 [ # # ]: 0 : if (!bMerged)
790 : : {
791 [ # # ][ # # ]: 0 : SwUndo *const pUndoOW( new SwUndoOverwrite(this, rPt, c) );
792 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndoOW);
793 : : }
794 : : }
795 : : else
796 : : {
797 : : // start behind the characters (to fix the attributes!)
798 [ - + ]: 10051 : if( nStart < pNode->GetTxt().Len() )
799 [ # # ]: 0 : rIdx++;
800 [ + - ][ + - ]: 10051 : pNode->InsertText( rtl::OUString(c), rIdx, INS_EMPTYEXPAND );
[ + - ]
801 [ - + ]: 10051 : if( nStart+1 < rIdx.GetIndex() )
802 : : {
803 [ # # ]: 0 : rIdx = nStart;
804 [ # # ]: 0 : pNode->EraseText( rIdx, 1 );
805 [ # # ]: 0 : rIdx++;
806 : : }
807 : : }
808 : : }
809 : 1902 : pNode->SetIgnoreDontExpand( bOldExpFlg );
810 : :
811 : 1902 : sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
812 [ - + ]: 1902 : ? pNode->GetpSwpHints()->Count() : 0;
813 [ - + ]: 1902 : if( nOldAttrCnt != nNewAttrCnt )
814 : : {
815 [ # # ]: 0 : SwUpdateAttr aHint( 0, 0, 0 );
816 [ # # ][ # # ]: 0 : pNode->ModifyBroadcast( 0, &aHint, TYPE( SwCrsrShell ) );
[ # # ]
817 : : }
818 : :
819 [ + - ][ + - ]: 5235 : if (!GetIDocumentUndoRedo().DoesUndo() &&
[ + - ]
[ + + + + ]
[ + + ]
820 [ + - ][ + - ]: 3333 : !IsIgnoreRedline() && !GetRedlineTbl().empty())
821 : : {
822 [ + - ]: 676 : SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
823 [ + - ][ + - ]: 676 : DeleteRedline( aPam, true, USHRT_MAX );
824 : : }
825 [ + - ][ + + ]: 1226 : else if( IsRedlineOn() )
826 : : {
827 : : // FIXME: this redline is WRONG: there is no DELETE, and the skipped
828 : : // characters are also included in aPam
829 [ + - ]: 278 : SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
830 [ + - ][ + - ]: 278 : AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
[ + - ][ + - ]
831 : : }
832 : :
833 [ + - ]: 1902 : SetModified();
834 [ + - ][ + - ]: 3920 : return sal_True;
835 : : }
836 : :
837 : 0 : bool SwDoc::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
838 : : {
839 [ # # ][ # # ]: 0 : SwNodeIndex aIdx( rPaM.Start()->nNode );
840 : 0 : sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
841 : 0 : sal_Bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
842 [ # # ]: 0 : aIdx--; // in front of the move area!
843 : :
844 [ # # ]: 0 : bool bRet = MoveRange( rPaM, rPos, eMvFlags );
845 [ # # ][ # # ]: 0 : if( bRet && !bOneNode )
846 : : {
847 [ # # ]: 0 : if( bJoinTxt )
848 [ # # ]: 0 : aIdx++;
849 : 0 : SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
850 [ # # ]: 0 : SwNodeIndex aNxtIdx( aIdx );
851 [ # # ][ # # ]: 0 : if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
[ # # ][ # # ]
852 : : {
853 : : { // Block so SwIndex into node is deleted before Join
854 : : CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex( pTxtNd,
855 [ # # ][ # # ]: 0 : pTxtNd->GetTxt().Len() ) ), 0, sal_True );
[ # # ][ # # ]
[ # # ][ # # ]
856 : : }
857 [ # # ]: 0 : pTxtNd->JoinNext();
858 [ # # ]: 0 : }
859 : : }
860 [ # # ]: 0 : return bRet;
861 : : }
862 : :
863 : : // It seems that this is mostly used by SwDoc internals; the only
864 : : // way to call this from the outside seems to be the special case in
865 : : // SwDoc::CopyRange (but I have not managed to actually hit that case).
866 : 7730 : bool SwDoc::MoveRange( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
867 : : {
868 : : // nothing moved: return
869 [ + - ][ + - ]: 7730 : const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
870 [ + - ][ + - ]: 7730 : if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
871 : 7730 : return false;
872 : :
873 : : // Save the paragraph anchored Flys, so that they can be moved.
874 [ # # ]: 0 : _SaveFlyArr aSaveFlyArr;
875 [ # # ]: 0 : _SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, 0 != ( DOC_MOVEALLFLYS & eMvFlags ) );
876 : :
877 : : // save redlines (if DOC_MOVEREDLINES is used)
878 [ # # ]: 0 : _SaveRedlines aSaveRedl;
879 [ # # ][ # # ]: 0 : if( DOC_MOVEREDLINES & eMvFlags && !GetRedlineTbl().empty() )
[ # # ][ # # ]
880 : : {
881 [ # # ]: 0 : lcl_SaveRedlines( rPaM, aSaveRedl );
882 : :
883 : : // #i17764# unfortunately, code below relies on undos being
884 : : // in a particular order, and presence of bookmarks
885 : : // will change this order. Hence, we delete bookmarks
886 : : // here without undo.
887 [ # # ][ # # ]: 0 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
888 : : _DelBookmarks(
889 : : pStt->nNode,
890 : : pEnd->nNode,
891 : : NULL,
892 : : &pStt->nContent,
893 [ # # ][ # # ]: 0 : &pEnd->nContent);
894 : : }
895 : :
896 : :
897 : 0 : int bUpdateFtn = sal_False;
898 [ # # ]: 0 : SwFtnIdxs aTmpFntIdx;
899 : :
900 : 0 : SwUndoMove * pUndoMove = 0;
901 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
902 : : {
903 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().ClearRedo();
904 [ # # ][ # # ]: 0 : pUndoMove = new SwUndoMove( rPaM, rPos );
905 : 0 : pUndoMove->SetMoveRedlines( eMvFlags == DOC_MOVEREDLINES );
906 : : }
907 : : else
908 : : {
909 : : bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
910 : 0 : GetFtnIdxs(), aTmpFntIdx,
911 [ # # ]: 0 : &pStt->nContent, &pEnd->nContent );
912 : : }
913 : :
914 : 0 : sal_Bool bSplit = sal_False;
915 [ # # ]: 0 : SwPaM aSavePam( rPos, rPos );
916 : :
917 : : // Move the SPoint to the beginning of the range
918 [ # # ]: 0 : if( rPaM.GetPoint() == pEnd )
919 : 0 : rPaM.Exchange();
920 : :
921 : : // If there is a TextNode before and after the Move, create a JoinNext in the EditShell.
922 : 0 : SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
923 [ # # ][ # # ]: 0 : sal_Bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
924 : :
925 : : // If one ore more TextNodes are moved, SwNodes::Move will do a SplitNode.
926 : : // However, this does not update the cursor. So we create a TextNode to keep
927 : : // updating the indices. After the Move the Node is optionally deleted.
928 : 0 : SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
929 [ # # # # ]: 0 : if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
[ # # ][ # # ]
[ # # ][ # # ]
930 [ # # ]: 0 : ( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam )) )
931 : : {
932 : 0 : bSplit = sal_True;
933 : 0 : xub_StrLen nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
934 : :
935 [ # # ]: 0 : std::vector<sal_uLong> aBkmkArr;
936 : 0 : _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
937 [ # # ]: 0 : aBkmkArr, SAVEFLY_SPLIT );
938 : :
939 [ # # ]: 0 : pTNd = static_cast<SwTxtNode*>(pTNd->SplitCntntNode( rPos ));
940 : :
941 [ # # ]: 0 : if( !aBkmkArr.empty() )
942 [ # # ]: 0 : _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
943 : :
944 : : // correct the PaM!
945 [ # # ]: 0 : if( rPos.nNode == rPaM.GetMark()->nNode )
946 : : {
947 [ # # ]: 0 : rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
948 [ # # ][ # # ]: 0 : rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
949 : 0 : }
950 : : }
951 : :
952 : : // Put back the Pam by one "content"; so that it's always outside of
953 : : // the manipulated range.
954 : : // If there's no content anymore, set it to the StartNode (that's
955 : : // always there).
956 [ # # ]: 0 : sal_Bool bNullCntnt = !aSavePam.Move( fnMoveBackward, fnGoCntnt );
957 [ # # ]: 0 : if( bNullCntnt )
958 : : {
959 [ # # ]: 0 : aSavePam.GetPoint()->nNode--;
960 : : }
961 : :
962 : : // Copy all Bookmarks that are within the Move range into an array,
963 : : // that saves the positon as an offset.
964 [ # # ]: 0 : ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
965 : : _DelBookmarks(
966 : : pStt->nNode,
967 : : pEnd->nNode,
968 : : &aSaveBkmks,
969 : : &pStt->nContent,
970 [ # # ]: 0 : &pEnd->nContent);
971 : :
972 : : // If there is no range anymore due to the above deletions (e.g. the
973 : : // footnotes got deleted), it's still a valid Move!
974 [ # # ][ # # ]: 0 : if( *rPaM.GetPoint() != *rPaM.GetMark() )
975 : : {
976 : : // now do the actual move
977 [ # # ][ # # ]: 0 : GetNodes().MoveRange( rPaM, rPos, GetNodes() );
[ # # ]
978 : :
979 : : // after a MoveRange() the Mark is deleted
980 [ # # ]: 0 : if ( rPaM.HasMark() ) // => no Move occurred!
981 : : {
982 [ # # ][ # # ]: 0 : delete pUndoMove;
983 : 0 : return false;
984 : : }
985 : : }
986 : : else
987 [ # # ]: 0 : rPaM.DeleteMark();
988 : :
989 : : OSL_ENSURE( *aSavePam.GetMark() == rPos ||
990 : : ( aSavePam.GetMark()->nNode.GetNode().GetCntntNode() == NULL ),
991 : : "PaM was not moved. Aren't there ContentNodes at the beginning/end?" );
992 [ # # ]: 0 : *aSavePam.GetMark() = rPos;
993 : :
994 [ # # ]: 0 : rPaM.SetMark(); // create a Sel. around the new range
995 : 0 : pTNd = aSavePam.GetNode()->GetTxtNode();
996 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
997 : : {
998 : : // correct the SavePam's Content first
999 [ # # ]: 0 : if( bNullCntnt )
1000 : : {
1001 [ # # ]: 0 : aSavePam.GetPoint()->nContent = 0;
1002 : : }
1003 : :
1004 : : // The method SwEditShell::Move() merges the TextNode after the Move,
1005 : : // where the rPaM is located.
1006 : : // If the Content was moved to the back and the SavePam's SPoint is
1007 : : // in the next Node, we have to deal with this when saving the Undo object!
1008 : 0 : SwTxtNode * pPamTxtNd = 0;
1009 : :
1010 : : // Is passed to SwUndoMove, which happens when subsequently calling Undo JoinNext.
1011 : : // If it's not possible to call Undo JoinNext here.
1012 [ # # ][ # # ]: 0 : sal_Bool bJoin = bSplit && pTNd;
1013 : : bCorrSavePam = bCorrSavePam &&
1014 : 0 : 0 != ( pPamTxtNd = rPaM.GetNode()->GetTxtNode() )
1015 [ # # ]: 0 : && pPamTxtNd->CanJoinNext()
1016 [ # # # # ]: 0 : && (*rPaM.GetPoint() <= *aSavePam.GetPoint());
[ # # ][ # # ]
[ # # ]
1017 : :
1018 : : // Do two Nodes have to be joined at the SavePam?
1019 [ # # ][ # # ]: 0 : if( bJoin && pTNd->CanJoinNext() )
[ # # ][ # # ]
1020 : : {
1021 [ # # ]: 0 : pTNd->JoinNext();
1022 : : // No temporary Index when using &&.
1023 : : // We probably only want to compare the indices.
1024 [ # # ][ # # ]: 0 : if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
[ # # ]
1025 : 0 : aSavePam.GetPoint()->nNode.GetIndex() )
1026 : : {
1027 [ # # ][ # # ]: 0 : aSavePam.GetPoint()->nContent += pPamTxtNd->Len();
1028 : : }
1029 : 0 : bJoin = sal_False;
1030 : : }
1031 [ # # ][ # # ]: 0 : else if ( !aSavePam.Move( fnMoveForward, fnGoCntnt ) )
1032 : : {
1033 [ # # ]: 0 : aSavePam.GetPoint()->nNode++;
1034 : : }
1035 : :
1036 : : // The newly inserted range is now inbetween SPoint and GetMark.
1037 : 0 : pUndoMove->SetDestRange( aSavePam, *rPaM.GetPoint(),
1038 [ # # ]: 0 : bJoin, bCorrSavePam );
1039 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo( pUndoMove );
1040 : : }
1041 : : else
1042 : : {
1043 : 0 : bool bRemove = true;
1044 : : // Do two Nodes have to be joined at the SavePam?
1045 [ # # ][ # # ]: 0 : if( bSplit && pTNd )
1046 : : {
1047 [ # # ][ # # ]: 0 : if( pTNd->CanJoinNext())
1048 : : {
1049 : : // Always join next, because <pTNd> has to stay as it is.
1050 : : // A join previous from its next would more or less delete <pTNd>
1051 [ # # ]: 0 : pTNd->JoinNext();
1052 : 0 : bRemove = false;
1053 : : }
1054 : : }
1055 [ # # ]: 0 : if( bNullCntnt )
1056 : : {
1057 [ # # ]: 0 : aSavePam.GetPoint()->nNode++;
1058 [ # # ][ # # ]: 0 : aSavePam.GetPoint()->nContent.Assign( aSavePam.GetCntntNode(), 0 );
1059 : : }
1060 [ # # ]: 0 : else if( bRemove ) // No move forward after joining with next paragraph
1061 : : {
1062 [ # # ]: 0 : aSavePam.Move( fnMoveForward, fnGoCntnt );
1063 : : }
1064 : : }
1065 : :
1066 : : // Insert the Bookmarks back into the Document.
1067 [ # # ][ # # ]: 0 : *rPaM.GetMark() = *aSavePam.Start();
1068 [ # # ][ # # ]: 0 : for(
1069 : 0 : ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
1070 : 0 : pBkmk != aSaveBkmks.end();
1071 : : ++pBkmk)
1072 : : pBkmk->SetInDoc(
1073 : : this,
1074 : 0 : rPaM.GetMark()->nNode,
1075 [ # # ]: 0 : &rPaM.GetMark()->nContent);
1076 [ # # ][ # # ]: 0 : *rPaM.GetPoint() = *aSavePam.End();
1077 : :
1078 : : // Move the Flys to the new position.
1079 [ # # ][ # # ]: 0 : _RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode, &(rPos.nNode) );
1080 : :
1081 : : // restore redlines (if DOC_MOVEREDLINES is used)
1082 [ # # ]: 0 : if( !aSaveRedl.empty() )
1083 : : {
1084 [ # # ][ # # ]: 0 : lcl_RestoreRedlines( this, *aSavePam.Start(), aSaveRedl );
1085 : : }
1086 : :
1087 [ # # ]: 0 : if( bUpdateFtn )
1088 : : {
1089 [ # # ]: 0 : if( !aTmpFntIdx.empty() )
1090 : : {
1091 [ # # ]: 0 : GetFtnIdxs().insert( aTmpFntIdx );
1092 : 0 : aTmpFntIdx.clear();
1093 : : }
1094 : :
1095 [ # # ]: 0 : GetFtnIdxs().UpdateAllFtn();
1096 : : }
1097 : :
1098 [ # # ]: 0 : SetModified();
1099 [ # # ][ # # ]: 7730 : return true;
1100 : : }
1101 : :
1102 : 132 : bool SwDoc::MoveNodeRange( SwNodeRange& rRange, SwNodeIndex& rPos,
1103 : : SwMoveFlags eMvFlags )
1104 : : {
1105 : : // Moves all Nodes to the new position.
1106 : : // Bookmarks are moved too (currently without Undo support).
1107 : :
1108 : : // If footnotes are being moved to the special section, remove them now.
1109 : : //
1110 : : // Or else delete the Frames for all footnotes that are being moved
1111 : : // and have it rebuild after the Move (footnotes can change pages).
1112 : : // Additionally we have to correct the FtnIdx array's sorting.
1113 : 132 : int bUpdateFtn = sal_False;
1114 [ + - ]: 132 : SwFtnIdxs aTmpFntIdx;
1115 : :
1116 : 132 : SwUndoMove* pUndo = 0;
1117 [ - + ][ # # ]: 132 : if ((DOC_CREATEUNDOOBJ & eMvFlags ) && GetIDocumentUndoRedo().DoesUndo())
[ # # ][ # # ]
[ - + ]
1118 : : {
1119 [ # # ][ # # ]: 0 : pUndo = new SwUndoMove( this, rRange, rPos );
1120 : : }
1121 : : else
1122 : : {
1123 : : bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
1124 [ + - ]: 132 : GetFtnIdxs(), aTmpFntIdx );
1125 : : }
1126 : :
1127 [ + - ]: 132 : _SaveRedlines aSaveRedl;
1128 [ + - ]: 132 : std::vector<SwRedline*> aSavRedlInsPosArr;
1129 [ - + ][ # # ]: 132 : if( DOC_MOVEREDLINES & eMvFlags && !GetRedlineTbl().empty() )
[ # # ][ - + ]
1130 : : {
1131 [ # # ]: 0 : lcl_SaveRedlines( rRange, aSaveRedl );
1132 : :
1133 : : // Find all RedLines that end at the InsPos.
1134 : : // These have to be moved back to the "old" position after the Move.
1135 [ # # ]: 0 : sal_uInt16 nRedlPos = GetRedlinePos( rPos.GetNode(), USHRT_MAX );
1136 [ # # ]: 0 : if( USHRT_MAX != nRedlPos )
1137 : : {
1138 : : const SwPosition *pRStt, *pREnd;
1139 [ # # ]: 0 : do {
[ # # # # ]
1140 [ # # ][ # # ]: 0 : SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
1141 [ # # ]: 0 : pRStt = pTmp->Start();
1142 [ # # ]: 0 : pREnd = pTmp->End();
1143 [ # # ][ # # ]: 0 : if( pREnd->nNode == rPos && pRStt->nNode < rPos )
[ # # ]
1144 : : {
1145 [ # # ]: 0 : aSavRedlInsPosArr.push_back( pTmp );
1146 : : }
1147 [ # # ]: 0 : } while( pRStt->nNode < rPos && ++nRedlPos < GetRedlineTbl().size());
1148 : : }
1149 : : }
1150 : :
1151 : : // Copy all Bookmarks that are within the Move range into an array
1152 : : // that stores all references to positions as an offset.
1153 : : // The final mapping happens after the Move.
1154 [ + - ]: 132 : ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
1155 [ + - ]: 132 : _DelBookmarks(rRange.aStart, rRange.aEnd, &aSaveBkmks);
1156 : :
1157 : : // Save the paragraph-bound Flys, so that they can be moved.
1158 [ + - ]: 132 : _SaveFlyArr aSaveFlyArr;
1159 [ - + ]: 132 : if( !GetSpzFrmFmts()->empty() )
1160 [ # # ]: 0 : _SaveFlyInRange( rRange, aSaveFlyArr );
1161 : :
1162 : : // Set it to before the Position, so that it cannot be moved further.
1163 [ + - ]: 132 : SwNodeIndex aIdx( rPos, -1 );
1164 : :
1165 : 132 : SwNodeIndex* pSaveInsPos = 0;
1166 [ - + ]: 132 : if( pUndo )
1167 [ # # ][ # # ]: 0 : pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
1168 : :
1169 : : // move the Nodes
1170 : 132 : sal_Bool bNoDelFrms = 0 != (DOC_NO_DELFRMS & eMvFlags);
1171 [ + - ][ + - ]: 132 : if( GetNodes()._MoveNodes( rRange, GetNodes(), rPos, !bNoDelFrms ) )
[ + - ][ + + ]
1172 : : {
1173 [ + - ]: 108 : aIdx++; // again back to old position
1174 [ - + ]: 108 : if( pSaveInsPos )
1175 [ # # ]: 0 : (*pSaveInsPos)++;
1176 : : }
1177 : : else
1178 : : {
1179 [ + - ]: 24 : aIdx = rRange.aStart;
1180 [ - + ][ # # ]: 24 : delete pUndo, pUndo = 0;
1181 : : }
1182 : :
1183 : : // move the Flys to the new position
1184 [ - + ]: 132 : if( !aSaveFlyArr.empty() )
1185 [ # # ]: 0 : _RestFlyInRange( aSaveFlyArr, aIdx, NULL );
1186 : :
1187 : : // Add the Bookmarks back to the Document
1188 [ + - ][ - + ]: 264 : for(
1189 : 132 : ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
1190 : 132 : pBkmk != aSaveBkmks.end();
1191 : : ++pBkmk)
1192 [ # # ]: 0 : pBkmk->SetInDoc(this, aIdx);
1193 : :
1194 [ - + ]: 132 : if( !aSavRedlInsPosArr.empty() )
1195 : : {
1196 : 0 : SwNode* pNewNd = &aIdx.GetNode();
1197 [ # # ]: 0 : for( sal_uInt16 n = 0; n < aSavRedlInsPosArr.size(); ++n )
1198 : : {
1199 : 0 : SwRedline* pTmp = aSavRedlInsPosArr[ n ];
1200 [ # # ][ # # ]: 0 : if( GetRedlineTbl().Contains( pTmp ) )
[ # # ]
1201 : : {
1202 [ # # ]: 0 : SwPosition* pEnd = pTmp->End();
1203 [ # # ]: 0 : pEnd->nNode = aIdx;
1204 [ # # ][ # # ]: 0 : pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
1205 : : }
1206 : : }
1207 : : }
1208 : :
1209 [ - + ]: 132 : if( !aSaveRedl.empty() )
1210 [ # # ]: 0 : lcl_RestoreRedlines( this, aIdx.GetIndex(), aSaveRedl );
1211 : :
1212 [ - + ]: 132 : if( pUndo )
1213 : : {
1214 [ # # ]: 0 : pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
1215 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1216 : : }
1217 : :
1218 [ - + ][ # # ]: 132 : delete pSaveInsPos;
1219 : :
1220 [ - + ]: 132 : if( bUpdateFtn )
1221 : : {
1222 [ # # ]: 0 : if( !aTmpFntIdx.empty() )
1223 : : {
1224 [ # # ]: 0 : GetFtnIdxs().insert( aTmpFntIdx );
1225 : 0 : aTmpFntIdx.clear();
1226 : : }
1227 : :
1228 [ # # ]: 0 : GetFtnIdxs().UpdateAllFtn();
1229 : : }
1230 : :
1231 [ + - ]: 132 : SetModified();
1232 [ + - ][ + - ]: 132 : return sal_True;
1233 : : }
1234 : :
1235 : : // Convert list of ranges of whichIds to a corresponding list of whichIds
1236 : 149 : std::vector<sal_uInt16> * lcl_RangesToVector(sal_uInt16 * pRanges)
1237 : : {
1238 [ + - ]: 149 : std::vector<sal_uInt16> * pResult = new std::vector<sal_uInt16>();
1239 : :
1240 : 149 : int i = 0;
1241 [ + + ]: 447 : while (pRanges[i] != 0)
1242 : : {
1243 : : OSL_ENSURE(pRanges[i+1] != 0, "malformed ranges");
1244 : :
1245 [ + + ]: 6109 : for (sal_uInt16 j = pRanges[i]; j < pRanges[i+1]; j++)
1246 [ + - ]: 5811 : pResult->push_back(j);
1247 : :
1248 : 298 : i += 2;
1249 : : }
1250 : :
1251 : 149 : return pResult;
1252 : : }
1253 : :
1254 : 3898 : bool lcl_StrLenOverFlow( const SwPaM& rPam )
1255 : : {
1256 : : // If we try to merge two paragraph we have to test if afterwards
1257 : : // the string doesn't exceed the allowed string length
1258 : 3898 : bool bRet = false;
1259 [ + + ]: 3898 : if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
1260 : : {
1261 : 638 : const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
1262 : 638 : const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
1263 [ + - ][ + - ]: 638 : if( (0 != pEndNd) && pStt->nNode.GetNode().IsTxtNode() )
[ + - ]
1264 : : {
1265 : 638 : sal_uInt64 nSum = pStt->nContent.GetIndex() +
1266 : 638 : pEndNd->GetTxt().Len() - pEnd->nContent.GetIndex();
1267 [ - + ]: 638 : if( nSum > STRING_LEN )
1268 : 0 : bRet = true;
1269 : : }
1270 : : }
1271 : 3898 : return bRet;
1272 : : }
1273 : :
1274 : 3283 : void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev )
1275 : : {
1276 : 3283 : rJoinTxt = sal_False;
1277 : 3283 : rJoinPrev = sal_False;
1278 [ + + ]: 3283 : if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
1279 : : {
1280 : 638 : const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
1281 : 638 : SwTxtNode *pSttNd = pStt->nNode.GetNode().GetTxtNode();
1282 [ + - ]: 638 : if( pSttNd )
1283 : : {
1284 : 638 : SwTxtNode *pEndNd = pEnd->nNode.GetNode().GetTxtNode();
1285 : 638 : rJoinTxt = 0 != pEndNd;
1286 [ + - ]: 638 : if( rJoinTxt )
1287 : : {
1288 : 638 : bool bExchange = pStt == rPam.GetPoint();
1289 [ + + ]: 854 : if( !pStt->nContent.GetIndex() &&
[ + + + + ]
1290 : 216 : pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex() )
1291 : 67 : bExchange = !bExchange;
1292 [ + + ]: 638 : if( bExchange )
1293 : 545 : rPam.Exchange();
1294 : 638 : rJoinPrev = rPam.GetPoint() == pStt;
1295 : : OSL_ENSURE( !pStt->nContent.GetIndex() &&
1296 : : pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex()
1297 : : ? rPam.GetPoint()->nNode < rPam.GetMark()->nNode
1298 : : : rPam.GetPoint()->nNode > rPam.GetMark()->nNode,
1299 : : "lcl_GetJoinFlags");
1300 : : }
1301 : : }
1302 : : }
1303 : 3283 : }
1304 : :
1305 : 638 : void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev )
1306 : : {
1307 [ + - ]: 638 : SwNodeIndex aIdx( rPam.GetPoint()->nNode );
1308 : 638 : SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
1309 [ + - ]: 638 : SwNodeIndex aOldIdx( aIdx );
1310 : 638 : SwTxtNode *pOldTxtNd = pTxtNd;
1311 : :
1312 [ + - ][ + - ]: 638 : if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
[ + - ][ + - ]
1313 : : {
1314 : 638 : SwDoc* pDoc = rPam.GetDoc();
1315 [ + + ]: 638 : if( bJoinPrev )
1316 : : {
1317 : : // We do not need to handle xmlids in this case, because
1318 : : // it is only invoked if one paragraph is completely empty
1319 : : // (see lcl_GetJoinFlags)
1320 : : {
1321 : : // If PageBreaks are deleted/set, it must not be added to the Undo history!
1322 : : // Also, deleteing the Node is not added to the Undo histroy!
1323 [ + - ][ + - ]: 67 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
1324 : :
1325 : : /* PageBreaks, PageDesc, ColumnBreaks */
1326 : : // If we need to change something about the logic to copy the PageBreaks,
1327 : : // PageDesc, etc. we also have to change SwUndoDelete.
1328 : : // There, we copy the AUTO PageBreak from the GetMarkNode!
1329 : :
1330 : : /* The GetMarkNode */
1331 [ + - ][ - + ]: 67 : if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->HasSwAttrSet() )
1332 : : {
1333 : : const SfxPoolItem* pItem;
1334 [ # # ][ # # ]: 0 : if( SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
1335 [ # # ]: 0 : RES_BREAK, sal_False, &pItem ) )
1336 [ # # ]: 0 : pTxtNd->ResetAttr( RES_BREAK );
1337 [ # # ][ # # ]: 0 : if( pTxtNd->HasSwAttrSet() &&
[ # # ][ # # ]
1338 [ # # ]: 0 : SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
1339 [ # # ]: 0 : RES_PAGEDESC, sal_False, &pItem ) )
1340 [ # # ]: 0 : pTxtNd->ResetAttr( RES_PAGEDESC );
1341 : : }
1342 : :
1343 : : /* The PointNode */
1344 [ + - ][ - + ]: 67 : if( pOldTxtNd->HasSwAttrSet() )
1345 : : {
1346 : : const SfxPoolItem* pItem;
1347 [ # # ]: 0 : SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
1348 [ # # ]: 0 : const SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
1349 [ # # ]: 0 : if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
1350 [ # # ]: 0 : sal_False, &pItem ) )
1351 [ # # ]: 0 : aSet.Put( *pItem );
1352 [ # # ]: 0 : if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
1353 [ # # ]: 0 : sal_False, &pItem ) )
1354 [ # # ]: 0 : aSet.Put( *pItem );
1355 [ # # ]: 0 : if( aSet.Count() )
1356 [ # # ][ # # ]: 0 : pTxtNd->SetAttr( aSet );
1357 : : }
1358 [ + - ]: 67 : pOldTxtNd->FmtToTxtAttr( pTxtNd );
1359 : :
1360 [ + - ]: 67 : std::vector<sal_uLong> aBkmkArr;
1361 : : ::_SaveCntntIdx( pDoc, aOldIdx.GetIndex(),
1362 [ + - ][ + - ]: 67 : pOldTxtNd->Len(), aBkmkArr );
1363 : :
1364 [ + - ][ + - ]: 67 : SwIndex aAlphaIdx(pTxtNd);
1365 [ + - ]: 67 : pOldTxtNd->CutText( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
1366 [ + - ][ + - ]: 134 : pOldTxtNd->Len() );
[ + - ][ + - ]
1367 [ + - ]: 67 : SwPosition aAlphaPos( aIdx, aAlphaIdx );
1368 [ + - ]: 67 : pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, sal_True );
1369 : :
1370 : : // move all Bookmarks/TOXMarks
1371 [ - + ]: 67 : if( !aBkmkArr.empty() )
1372 [ # # ]: 0 : ::_RestoreCntntIdx( pDoc, aBkmkArr, aIdx.GetIndex() );
1373 : :
1374 : : // If the passed PaM is not in the Crsr ring,
1375 : : // treat it seperately (e.g. when it's being called from AutoFormat)
1376 [ + - ][ - + ]: 67 : if( pOldTxtNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
1377 [ # # ]: 0 : rPam.GetBound( sal_True ) = aAlphaPos;
1378 [ + - ][ - + ]: 67 : if( pOldTxtNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
1379 [ # # ][ + - ]: 67 : rPam.GetBound( sal_False ) = aAlphaPos;
[ + - ][ + - ]
1380 : : }
1381 : : // delete the Node, at last!
1382 [ + - ][ + - ]: 67 : pDoc->GetNodes().Delete( aOldIdx, 1 );
1383 : : }
1384 : : else
1385 : : {
1386 : 571 : SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
1387 [ + + ][ + - ]: 571 : if( pTxtNd->Len() )
1388 [ + - ]: 422 : pDelNd->FmtToTxtAttr( pTxtNd );
1389 : : else
1390 : : {
1391 : : /* This case was missed:
1392 : :
1393 : : <something></something> <-- pTxtNd
1394 : : <other>ccc</other> <-- pDelNd
1395 : :
1396 : : <something> and <other> are paragraph
1397 : : attributes. The attribute <something> stayed if not
1398 : : overwritten by an attribute in "ccc". Fixed by
1399 : : first resetting all character attributes in first
1400 : : paragraph (pTxtNd).
1401 : : */
1402 : : std::vector<sal_uInt16> * pShorts =
1403 [ + - ]: 149 : lcl_RangesToVector(aCharFmtSetRange);
1404 [ + - ]: 149 : pTxtNd->ResetAttr(*pShorts);
1405 [ + - ]: 149 : delete pShorts;
1406 : :
1407 [ + - ][ + + ]: 149 : if( pDelNd->HasSwAttrSet() )
1408 : : {
1409 : : // only copy the character attributes
1410 [ + - ]: 25 : SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
1411 [ + - ][ + - ]: 25 : aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
1412 [ + - ][ + - ]: 25 : pTxtNd->SetAttr( aTmpSet );
1413 : : }
1414 : : }
1415 : :
1416 [ + - ]: 571 : pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, sal_True );
1417 : : // #i100466# adjust given <rPam>, if it does not belong to the cursors
1418 [ + - ][ - + ]: 571 : if ( pDelNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
1419 : : {
1420 [ # # ][ # # ]: 0 : rPam.GetBound( sal_True ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1421 : : }
1422 [ + - ][ - + ]: 571 : if( pDelNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
1423 : : {
1424 [ # # ][ # # ]: 0 : rPam.GetBound( sal_False ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1425 : : }
1426 [ + - ]: 571 : pTxtNd->JoinNext();
1427 : : }
1428 [ + - ][ + - ]: 638 : }
1429 : 638 : }
1430 : :
1431 : : static void
1432 : 5316 : lcl_CalcBreaks( ::std::vector<xub_StrLen> & rBreaks, SwPaM const & rPam )
1433 : : {
1434 : : SwTxtNode const * const pTxtNode(
1435 : 5316 : rPam.End()->nNode.GetNode().GetTxtNode() );
1436 [ + + ]: 5316 : if (!pTxtNode)
1437 : 1370 : return; // left-overlap only possible at end of selection...
1438 : :
1439 : 3946 : const xub_StrLen nStart(rPam.Start()->nContent.GetIndex());
1440 : 3946 : const xub_StrLen nEnd (rPam.End ()->nContent.GetIndex());
1441 [ + + ]: 3946 : if (nEnd == pTxtNode->Len())
1442 : 2930 : return; // paragraph selected until the end
1443 : :
1444 [ + + ]: 13150 : for (xub_StrLen i = nStart; i < nEnd; ++i)
1445 : : {
1446 : 7834 : const sal_Unicode c(pTxtNode->GetTxt().GetChar(i));
1447 [ + + ][ + + ]: 7834 : if ((CH_TXTATR_INWORD == c) || (CH_TXTATR_BREAKWORD == c))
1448 : : {
1449 [ + - ]: 115 : SwTxtAttr const * const pAttr( pTxtNode->GetTxtAttrForCharAt(i) );
1450 [ + - ][ + - ]: 115 : if (pAttr && pAttr->GetEnd() && (*pAttr->GetEnd() > nEnd))
[ + + ][ + - ]
[ - + ][ - + ]
1451 : : {
1452 : : OSL_ENSURE(pAttr->HasDummyChar(), "GetTxtAttrForCharAt broken?");
1453 [ # # ]: 0 : rBreaks.push_back(i);
1454 : : }
1455 : : }
1456 : : }
1457 : : }
1458 : :
1459 : 5228 : bool lcl_DoWithBreaks(SwDoc & rDoc, SwPaM & rPam,
1460 : : bool (SwDoc::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
1461 : : {
1462 [ + - ]: 5228 : ::std::vector<xub_StrLen> Breaks;
1463 : :
1464 [ + - ]: 5228 : lcl_CalcBreaks(Breaks, rPam);
1465 : :
1466 [ + - ]: 5228 : if (!Breaks.size())
1467 : : {
1468 [ + - ][ + - ]: 5228 : return (rDoc.*pFunc)(rPam, bForceJoinNext);
1469 : : }
1470 : :
1471 : : // Deletion must be split into several parts if the text node
1472 : : // contains a text attribute with end and with dummy character
1473 : : // and the selection does not contain the text attribute completely,
1474 : : // but overlaps its start (left), where the dummy character is.
1475 : :
1476 [ # # ]: 0 : SwPosition const & rSelectionEnd( *rPam.End() );
1477 : :
1478 : 0 : bool bRet( true );
1479 : : // iterate from end to start, to avoid invalidating the offsets!
1480 : 0 : ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
1481 [ # # ]: 0 : SwPaM aPam( rSelectionEnd, rSelectionEnd ); // end node!
1482 [ # # ]: 0 : SwPosition & rEnd( *aPam.End() );
1483 [ # # ]: 0 : SwPosition & rStart( *aPam.Start() );
1484 : :
1485 [ # # ][ # # ]: 0 : while (iter != Breaks.rend())
1486 : : {
1487 [ # # ][ # # ]: 0 : rStart.nContent = *iter + 1;
1488 [ # # ]: 0 : if (rEnd.nContent > rStart.nContent) // check if part is empty
1489 : : {
1490 [ # # ][ # # ]: 0 : bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
1491 : : }
1492 [ # # ][ # # ]: 0 : rEnd.nContent = *iter;
1493 [ # # ]: 0 : ++iter;
1494 : : }
1495 : :
1496 [ # # ][ # # ]: 0 : rStart = *rPam.Start(); // set to original start
1497 [ # # ]: 0 : if (rEnd.nContent > rStart.nContent) // check if part is empty
1498 : : {
1499 [ # # ][ # # ]: 0 : bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
1500 : : }
1501 : :
1502 [ # # ]: 5228 : return bRet;
1503 : : }
1504 : :
1505 : 703 : bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
1506 : : {
1507 : : OSL_ENSURE( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
1508 : :
1509 : : {
1510 : 703 : SwUndoRedlineDelete* pUndo = 0;
1511 [ + - ]: 703 : RedlineMode_t eOld = GetRedlineMode();
1512 [ + - ]: 703 : checkRedlining(eOld);
1513 [ + - ][ + - ]: 703 : if (GetIDocumentUndoRedo().DoesUndo())
[ - + ]
1514 : : {
1515 : :
1516 : : /* please don't translate -- for cultural reasons this comment is protected
1517 : : until the redline implementation is finally fixed some day */
1518 : : //JP 06.01.98: MUSS noch optimiert werden!!!
1519 : : SetRedlineMode(
1520 [ # # ]: 0 : (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
1521 : :
1522 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
1523 [ # # ][ # # ]: 0 : pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE );
1524 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1525 : : }
1526 [ + - ][ + + ]: 703 : if( *rPam.GetPoint() != *rPam.GetMark() )
1527 [ + - ][ + - ]: 6 : AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true);
[ + - ]
1528 [ + - ]: 703 : SetModified();
1529 : :
1530 [ - + ]: 703 : if( pUndo )
1531 : : {
1532 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
1533 : : // ??? why the hell is the AppendUndo not below the
1534 : : // CanGrouping, so this hideous cleanup wouldn't be necessary?
1535 : : // bah, this is redlining, probably changing this would break it...
1536 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesGroupUndo())
[ # # ]
1537 : : {
1538 [ # # ][ # # ]: 0 : SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
1539 : : SwUndoRedlineDelete *const pUndoRedlineDel(
1540 [ # # ]: 0 : dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) );
1541 [ # # ]: 0 : if (pUndoRedlineDel)
1542 : : {
1543 [ # # ]: 0 : bool const bMerged = pUndoRedlineDel->CanGrouping(*pUndo);
1544 [ # # ]: 0 : if (bMerged)
1545 : : {
1546 [ # # ][ # # ]: 0 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1547 : : SwUndo const*const pDeleted =
1548 [ # # ][ # # ]: 0 : GetUndoManager().RemoveLastUndo();
1549 : : OSL_ENSURE(pDeleted == pUndo,
1550 : : "DeleteAndJoinWithRedlineImpl: "
1551 : : "undo removed is not undo inserted?");
1552 [ # # ][ # # ]: 0 : delete pDeleted;
[ # # ]
1553 : : }
1554 : : }
1555 : : }
1556 : : //JP 06.01.98: MUSS noch optimiert werden!!!
1557 [ # # ]: 0 : SetRedlineMode( eOld );
1558 : : }
1559 : 703 : return true;
1560 : : }
1561 : : }
1562 : :
1563 : 3195 : bool SwDoc::DeleteAndJoinImpl( SwPaM & rPam,
1564 : : const bool bForceJoinNext )
1565 : : {
1566 : : sal_Bool bJoinTxt, bJoinPrev;
1567 [ + - ]: 3195 : lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
1568 : : // #i100466#
1569 [ + + ]: 3195 : if ( bForceJoinNext )
1570 : : {
1571 : 3 : bJoinPrev = sal_False;
1572 : : }
1573 : :
1574 : : {
1575 [ + - ]: 3195 : bool const bSuccess( DeleteRangeImpl( rPam ) );
1576 [ + + ]: 3195 : if (!bSuccess)
1577 : 1473 : return false;
1578 : : }
1579 : :
1580 [ + + ]: 1722 : if( bJoinTxt )
1581 : : {
1582 [ + - ]: 638 : lcl_JoinText( rPam, bJoinPrev );
1583 : : }
1584 : :
1585 : 3195 : return true;
1586 : : }
1587 : :
1588 : 4525 : bool SwDoc::DeleteRangeImpl(SwPaM & rPam, const bool)
1589 : : {
1590 : : // Move all cursors out of the deleted range, but first copy the
1591 : : // passed PaM, because it could be a cursor that would be moved!
1592 [ + - ]: 4525 : SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
1593 [ + - ]: 4525 : ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
1594 : :
1595 [ + - ]: 4525 : bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
1596 [ + + ]: 4525 : if (bSuccess)
1597 : : { // now copy position from temp copy to given PaM
1598 [ + - ]: 1731 : *rPam.GetPoint() = *aDelPam.GetPoint();
1599 : : }
1600 : :
1601 [ + - ]: 4525 : return bSuccess;
1602 : : }
1603 : :
1604 : 4525 : bool SwDoc::DeleteRangeImplImpl(SwPaM & rPam)
1605 : : {
1606 [ + - ][ + - ]: 4525 : SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
1607 : :
1608 [ + - ][ + - ]: 4525 : if( !rPam.HasMark() || *pStt >= *pEnd )
[ + + ][ + + ]
1609 : 2794 : return false;
1610 : :
1611 [ - + ]: 1731 : if( pACEWord )
1612 : : {
1613 : : // if necessary the saved Word for the exception
1614 [ # # ]: 0 : if( pACEWord->IsDeleted() || pStt->nNode != pEnd->nNode ||
[ # # # # ]
[ # # ][ # # ]
1615 : 0 : pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
1616 [ # # ]: 0 : !pACEWord->CheckDelChar( *pStt ))
1617 [ # # ][ # # ]: 0 : delete pACEWord, pACEWord = 0;
1618 : : }
1619 : :
1620 : : {
1621 : : // Delete all empty TextHints at the Mark's position
1622 : 1731 : SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
1623 : : SwpHints* pHts;
1624 [ + + ][ + - ]: 1731 : if( pTxtNd && 0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
[ + + ][ + - ]
1625 : : {
1626 : : const xub_StrLen *pEndIdx;
1627 : 432 : xub_StrLen nMkCntPos = rPam.GetMark()->nContent.GetIndex();
1628 [ + + ]: 1079 : for( sal_uInt16 n = pHts->Count(); n; )
1629 : : {
1630 [ + - ]: 647 : const SwTxtAttr* pAttr = (*pHts)[ --n ];
1631 [ + + ]: 647 : if( nMkCntPos > *pAttr->GetStart() )
1632 : 392 : break;
1633 : :
1634 [ + + ][ + - ]: 375 : if( nMkCntPos == *pAttr->GetStart() &&
[ + + + + ]
[ + + ]
1635 : : 0 != (pEndIdx = pAttr->GetEnd()) &&
1636 : 120 : *pEndIdx == *pAttr->GetStart() )
1637 [ + - ][ + - ]: 93 : pTxtNd->DestroyAttr( pHts->Cut( n ) );
1638 : : }
1639 : : }
1640 : : }
1641 : :
1642 : : // Delete fieldmarks before postits, but let's leave them alone during import.
1643 [ + - ][ + - ]: 1731 : if (GetIDocumentUndoRedo().DoesUndo() && pStt->nNode == pEnd->nNode && (pEnd->nContent.GetIndex() - pStt->nContent.GetIndex()) == 1)
[ + + ][ + + ]
[ + + ][ + + ]
1644 : : {
1645 [ + - ]: 94 : SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
1646 [ + - ]: 94 : xub_StrLen nIndex = rPam.Start()->nContent.GetIndex();
1647 : : // We may have a postit here.
1648 [ + + ]: 94 : if (pTxtNd->GetTxt().GetChar(nIndex) == CH_TXTATR_INWORD)
1649 : : {
1650 [ + - ]: 6 : SwTxtAttr* pTxtAttr = pTxtNd->GetTxtAttrForCharAt(nIndex, RES_TXTATR_FIELD);
1651 [ - + ][ # # ]: 6 : if (pTxtAttr && pTxtAttr->GetFld().GetFld()->Which() == RES_POSTITFLD)
[ - + ]
1652 : : {
1653 [ # # ]: 0 : const SwPostItField* pField = dynamic_cast<const SwPostItField*>(pTxtAttr->GetFld().GetFld());
1654 [ # # ][ # # ]: 0 : IDocumentMarkAccess::const_iterator_t ppMark = getIDocumentMarkAccess()->findMark(pField->GetName());
[ # # ]
1655 [ # # ][ # # ]: 0 : if (ppMark != getIDocumentMarkAccess()->getMarksEnd())
[ # # ][ # # ]
1656 [ # # ][ # # ]: 0 : getIDocumentMarkAccess()->deleteMark(ppMark);
1657 : : }
1658 : : }
1659 : : }
1660 : :
1661 : : {
1662 : : // Send DataChanged before deletion, so that we still know
1663 : : // which objects are in the range.
1664 : : // Afterwards they could be before/after the Position.
1665 [ + - ][ + - ]: 1731 : SwDataChanged aTmp( rPam, 0 );
1666 : : }
1667 : :
1668 : :
1669 [ + - ][ + - ]: 1731 : if (GetIDocumentUndoRedo().DoesUndo())
[ + + ]
1670 : : {
1671 [ + - ][ + - ]: 956 : GetIDocumentUndoRedo().ClearRedo();
1672 : 956 : bool bMerged(false);
1673 [ + - ][ + - ]: 956 : if (GetIDocumentUndoRedo().DoesGroupUndo())
[ + - ]
1674 : : {
1675 [ + - ][ + - ]: 956 : SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
1676 : : SwUndoDelete *const pUndoDelete(
1677 [ + + ]: 956 : dynamic_cast<SwUndoDelete *>(pLastUndo) );
1678 [ - + ]: 956 : if (pUndoDelete)
1679 : : {
1680 [ # # ]: 0 : bMerged = pUndoDelete->CanGrouping( this, rPam );
1681 : : // if CanGrouping() returns true it's already merged
1682 : : }
1683 : : }
1684 [ + - ]: 956 : if (!bMerged)
1685 : : {
1686 [ + - ][ + - ]: 956 : GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam ) );
[ + - ][ + - ]
1687 : : }
1688 : :
1689 [ + - ]: 956 : SetModified();
1690 : :
1691 : 956 : return true;
1692 : : }
1693 : :
1694 [ + - ][ + + ]: 775 : if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
[ + - ][ - + ]
[ - + ]
1695 [ # # ]: 0 : DeleteRedline( rPam, true, USHRT_MAX );
1696 : :
1697 : : // Delete and move all "Flys at the paragraph", which are within the Selection
1698 [ + - ]: 775 : DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
1699 : : _DelBookmarks(
1700 : : pStt->nNode,
1701 : : pEnd->nNode,
1702 : : NULL,
1703 : : &pStt->nContent,
1704 [ + - ]: 775 : &pEnd->nContent);
1705 : :
1706 [ + - ]: 775 : SwNodeIndex aSttIdx( pStt->nNode );
1707 : 775 : SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
1708 : :
1709 : : do { // middle checked loop!
1710 [ + - ]: 775 : if( pCNd )
1711 : : {
1712 : 775 : SwTxtNode * pStartTxtNode( pCNd->GetTxtNode() );
1713 [ + - ]: 775 : if ( pStartTxtNode )
1714 : : {
1715 : : // now move the Content to the new Node
1716 : 775 : sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
1717 : 163 : xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex()
1718 : 612 : : pCNd->Len() )
1719 [ + - ][ + + ]: 775 : - pStt->nContent.GetIndex();
1720 : :
1721 : : // Don't call again, if already empty
1722 [ + + ]: 775 : if( nLen )
1723 : : {
1724 [ + - ]: 178 : pStartTxtNode->EraseText( pStt->nContent, nLen );
1725 : :
1726 [ + - ][ + + ]: 178 : if( !pStartTxtNode->Len() )
1727 : : {
1728 : : // METADATA: remove reference if empty (consider node deleted)
1729 [ + - ]: 136 : pStartTxtNode->RemoveMetadataReference();
1730 : : }
1731 : : }
1732 : :
1733 [ + + ]: 775 : if( bOneNd ) // that's it
1734 : 163 : break;
1735 : :
1736 [ + - ]: 612 : aSttIdx++;
1737 : : }
1738 : : else
1739 : : {
1740 : : // So that there are no indices left registered when deleted,
1741 : : // we remove a SwPaM from the Content here.
1742 [ # # ]: 0 : pStt->nContent.Assign( 0, 0 );
1743 : : }
1744 : : }
1745 : :
1746 : 612 : pCNd = pEnd->nNode.GetNode().GetCntntNode();
1747 [ + - ]: 612 : if( pCNd )
1748 : : {
1749 : 612 : SwTxtNode * pEndTxtNode( pCNd->GetTxtNode() );
1750 [ + - ]: 612 : if( pEndTxtNode )
1751 : : {
1752 : : // if already empty, don't call again
1753 [ + + ]: 612 : if( pEnd->nContent.GetIndex() )
1754 : : {
1755 [ + - ][ + - ]: 3 : SwIndex aIdx( pCNd, 0 );
1756 [ + - ]: 3 : pEndTxtNode->EraseText( aIdx, pEnd->nContent.GetIndex() );
1757 : :
1758 [ + - ][ + - ]: 3 : if( !pEndTxtNode->Len() )
1759 : : {
1760 : : // METADATA: remove reference if empty (consider node deleted)
1761 [ + - ]: 3 : pEndTxtNode->RemoveMetadataReference();
1762 [ + - ]: 3 : }
1763 : : }
1764 : : }
1765 : : else
1766 : : {
1767 : : // So that there are no indices left registered when deleted,
1768 : : // we remove a SwPaM from the Content here.
1769 [ # # ]: 0 : pEnd->nContent.Assign( 0, 0 );
1770 : : }
1771 : : }
1772 : :
1773 : : // if the end is not a content node, delete it as well
1774 : 612 : sal_uInt32 nEnde = pEnd->nNode.GetIndex();
1775 [ - + ]: 612 : if( pCNd == NULL )
1776 : 0 : nEnde++;
1777 : :
1778 [ + + ]: 612 : if( aSttIdx != nEnde )
1779 : : {
1780 : : // delete the Nodes into the NodesArary
1781 [ + - ][ + - ]: 70 : GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
1782 : : }
1783 : :
1784 : : // If the Node that contained the Cursor has been deleted,
1785 : : // the Content has to be assigned to the current Content.
1786 : 612 : pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
1787 [ + - ][ + - ]: 1224 : pStt->nContent.GetIndex() );
1788 : :
1789 : : // If we deleted across Node boundaries we have to correct the PaM,
1790 : : // because they are in different Nodes now.
1791 : : // Also, the Selection is revoked.
1792 [ + - ]: 612 : *pEnd = *pStt;
1793 [ + - ]: 612 : rPam.DeleteMark();
1794 : :
1795 : : } while( sal_False );
1796 : :
1797 [ + - ][ + + ]: 775 : if( !IsIgnoreRedline() && !GetRedlineTbl().empty() )
[ + - ][ - + ]
[ - + ]
1798 [ # # ]: 0 : CompressRedlines();
1799 [ + - ]: 775 : SetModified();
1800 : :
1801 [ + - ]: 4525 : return true;
1802 : : }
1803 : :
1804 : : // #i100466# Add handling of new optional parameter <bForceJoinNext>
1805 : 3898 : bool SwDoc::DeleteAndJoin( SwPaM & rPam,
1806 : : const bool bForceJoinNext )
1807 : : {
1808 [ - + ]: 3898 : if ( lcl_StrLenOverFlow( rPam ) )
1809 : 0 : return false;
1810 : :
1811 : 3898 : return lcl_DoWithBreaks( *this, rPam, (IsRedlineOn())
1812 : : ? &SwDoc::DeleteAndJoinWithRedlineImpl
1813 : : : &SwDoc::DeleteAndJoinImpl,
1814 [ + + ]: 3898 : bForceJoinNext );
1815 : : }
1816 : :
1817 : 1330 : bool SwDoc::DeleteRange( SwPaM & rPam )
1818 : : {
1819 : 1330 : return lcl_DoWithBreaks( *this, rPam, &SwDoc::DeleteRangeImpl );
1820 : : }
1821 : :
1822 : :
1823 : 0 : void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
1824 : : xub_StrLen /*nBeginGrammarCheck*/, const ModelToViewHelper &rConversionMap )
1825 : : {
1826 [ # # ]: 0 : if( rTxtNode.IsGrammarCheckDirty() )
1827 : 0 : return;
1828 : 0 : SwGrammarMarkUp* pWrong = rTxtNode.GetGrammarCheck();
1829 : 0 : linguistic2::SingleProofreadingError* pArray = rResult.aErrors.getArray();
1830 : 0 : sal_uInt16 i, j = 0;
1831 [ # # ]: 0 : if( pWrong )
1832 : : {
1833 [ # # ]: 0 : for( i = 0; i < rResult.aErrors.getLength(); ++i )
1834 : : {
1835 : 0 : const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
1836 : 0 : xub_StrLen nStart = (xub_StrLen)rConversionMap.ConvertToModelPosition( rError.nErrorStart ).mnPos;
1837 : 0 : xub_StrLen nEnd = (xub_StrLen)rConversionMap.ConvertToModelPosition( rError.nErrorStart + rError.nErrorLength ).mnPos;
1838 [ # # ]: 0 : if( i != j )
1839 : 0 : pArray[j] = pArray[i];
1840 [ # # ]: 0 : if( pWrong->LookForEntry( nStart, nEnd ) )
1841 : 0 : ++j;
1842 : : }
1843 : : }
1844 [ # # ]: 0 : if( rResult.aErrors.getLength() > j )
1845 : 0 : rResult.aErrors.realloc( j );
1846 : : }
1847 : :
1848 : 0 : uno::Any SwDoc::Spell( SwPaM& rPaM,
1849 : : uno::Reference< XSpellChecker1 > &xSpeller,
1850 : : sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
1851 : : bool bGrammarCheck,
1852 : : SwConversionArgs *pConvArgs ) const
1853 : : {
1854 [ # # ][ # # ]: 0 : SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
1855 [ # # ]: 0 : uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
1856 : :
1857 : 0 : SwSpellArgs *pSpellArgs = 0;
1858 [ # # ]: 0 : if (pConvArgs)
1859 : : {
1860 : 0 : pConvArgs->SetStart(pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent);
1861 : 0 : pConvArgs->SetEnd( pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
1862 : : }
1863 : : else
1864 : : pSpellArgs = new SwSpellArgs( xSpeller,
1865 : 0 : pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
1866 : 0 : pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent,
1867 [ # # ][ # # ]: 0 : bGrammarCheck );
1868 : :
1869 : 0 : sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
1870 : 0 : sal_uLong nEndNd = pEndPos->nNode.GetIndex();
1871 : :
1872 : 0 : uno::Any aRet;
1873 [ # # ]: 0 : if( nCurrNd <= nEndNd )
1874 : : {
1875 : : SwCntntFrm* pCntFrm;
1876 : 0 : sal_Bool bGoOn = sal_True;
1877 [ # # ]: 0 : while( bGoOn )
1878 : : {
1879 [ # # ][ # # ]: 0 : SwNode* pNd = GetNodes()[ nCurrNd ];
1880 [ # # # # ]: 0 : switch( pNd->GetNodeType() )
1881 : : {
1882 : : case ND_TEXTNODE:
1883 [ # # ][ # # ]: 0 : if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->getLayoutFrm( GetCurrentLayout() )) )
[ # # ][ # # ]
1884 : : {
1885 : : // skip protected and hidden Cells and Flys
1886 [ # # ][ # # ]: 0 : if( pCntFrm->IsProtected() )
1887 : : {
1888 : 0 : nCurrNd = pNd->EndOfSectionIndex();
1889 : : }
1890 [ # # ][ # # ]: 0 : else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
1891 : : {
1892 [ # # ][ # # ]: 0 : if( pPageCnt && *pPageCnt && pPageSt )
[ # # ]
1893 : : {
1894 [ # # ]: 0 : sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
1895 [ # # ]: 0 : if( !*pPageSt )
1896 : : {
1897 : 0 : *pPageSt = nPageNr;
1898 [ # # ]: 0 : if( *pPageCnt < *pPageSt )
1899 : 0 : *pPageCnt = *pPageSt;
1900 : : }
1901 : : long nStat;
1902 [ # # ]: 0 : if( nPageNr >= *pPageSt )
1903 : 0 : nStat = nPageNr - *pPageSt + 1;
1904 : : else
1905 : 0 : nStat = nPageNr + *pPageCnt - *pPageSt + 1;
1906 [ # # ]: 0 : ::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
1907 : : }
1908 : : //Spell() changes the pSpellArgs in case an error is found
1909 : 0 : xub_StrLen nBeginGrammarCheck = 0;
1910 : 0 : xub_StrLen nEndGrammarCheck = 0;
1911 [ # # ][ # # ]: 0 : if( pSpellArgs && pSpellArgs->bIsGrammarCheck)
1912 : : {
1913 [ # # ][ # # ]: 0 : nBeginGrammarCheck = pSpellArgs->pStartNode == pNd ? pSpellArgs->pStartIdx->GetIndex() : 0;
1914 : : // if grammar checking starts inside of a sentence the start position has to be adjusted
1915 [ # # ]: 0 : if( nBeginGrammarCheck )
1916 : : {
1917 [ # # ][ # # ]: 0 : SwIndex aStartIndex( dynamic_cast< SwTxtNode* >( pNd ), nBeginGrammarCheck );
[ # # ]
1918 [ # # ][ # # ]: 0 : SwPosition aStart( *pNd, aStartIndex );
[ # # ]
1919 [ # # ]: 0 : SwCursor aCrsr(aStart, 0, false);
1920 [ # # ]: 0 : SwPosition aOrigPos = *aCrsr.GetPoint();
1921 [ # # ]: 0 : aCrsr.GoSentence( SwCursor::START_SENT );
1922 [ # # ][ # # ]: 0 : if( aOrigPos != *aCrsr.GetPoint() )
1923 : : {
1924 : 0 : nBeginGrammarCheck = aCrsr.GetPoint()->nContent.GetIndex();
1925 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
1926 : : }
1927 [ # # ][ # # ]: 0 : nEndGrammarCheck = pSpellArgs->pEndNode == pNd ? pSpellArgs->pEndIdx->GetIndex() : ((SwTxtNode*)pNd)->GetTxt().Len();
[ # # ]
1928 : : }
1929 : :
1930 [ # # ]: 0 : xub_StrLen nSpellErrorPosition = ((SwTxtNode*)pNd)->GetTxt().Len();
1931 [ # # ][ # # ]: 0 : if( (!pConvArgs &&
[ # # ][ # # ]
[ # # ]
1932 [ # # ][ # # ]: 0 : ((SwTxtNode*)pNd)->Spell( pSpellArgs )) ||
1933 : : ( pConvArgs &&
1934 [ # # ][ # # ]: 0 : ((SwTxtNode*)pNd)->Convert( *pConvArgs )))
1935 : : {
1936 : : // Cancel and remember position
1937 [ # # ]: 0 : pSttPos->nNode = nCurrNd;
1938 [ # # ]: 0 : pEndPos->nNode = nCurrNd;
1939 : 0 : nCurrNd = nEndNd;
1940 [ # # ]: 0 : if( pSpellArgs )
1941 : 0 : nSpellErrorPosition = pSpellArgs->pStartIdx->GetIndex() > pSpellArgs->pEndIdx->GetIndex() ?
1942 : 0 : pSpellArgs->pEndIdx->GetIndex() :
1943 [ # # ]: 0 : pSpellArgs->pStartIdx->GetIndex();
1944 : : }
1945 : :
1946 : :
1947 [ # # ][ # # ]: 0 : if( pSpellArgs && pSpellArgs->bIsGrammarCheck )
1948 : : {
1949 [ # # ]: 0 : uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( GetGCIterator() );
1950 [ # # ]: 0 : if (xGCIterator.is())
1951 : : {
1952 [ # # ][ # # ]: 0 : String aText( ((SwTxtNode*)pNd)->GetTxt().Copy( nBeginGrammarCheck, nEndGrammarCheck - nBeginGrammarCheck ) );
1953 [ # # ][ # # ]: 0 : uno::Reference< lang::XComponent > xDoc( ((SwDocShell*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY );
1954 : : // Expand the string:
1955 [ # # ][ # # ]: 0 : const ModelToViewHelper aConversionMap(*(SwTxtNode*)pNd);
1956 : 0 : rtl::OUString aExpandText = aConversionMap.getViewText();
1957 : :
1958 : : // get XFlatParagraph to use...
1959 [ # # ][ # # ]: 0 : uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *((SwTxtNode*)pNd), aExpandText, aConversionMap );
[ # # ][ # # ]
1960 : :
1961 : : // get error position of cursor in XFlatParagraph
1962 [ # # ]: 0 : linguistic2::ProofreadingResult aResult;
1963 : : sal_Int32 nGrammarErrors;
1964 [ # # ][ # # ]: 0 : do
[ # # ][ # # ]
1965 : : {
1966 [ # # ]: 0 : aConversionMap.ConvertToViewPosition( nBeginGrammarCheck );
1967 [ # # ]: 0 : aResult = xGCIterator->checkSentenceAtPosition(
1968 [ # # ][ # # ]: 0 : xDoc, xFlatPara, aExpandText, lang::Locale(), nBeginGrammarCheck, -1, -1 );
[ # # ]
1969 : :
1970 [ # # ][ # # ]: 0 : lcl_syncGrammarError( *((SwTxtNode*)pNd), aResult, nBeginGrammarCheck, aConversionMap );
1971 : :
1972 : : // get suggestions to use for the specific error position
1973 : 0 : nGrammarErrors = aResult.aErrors.getLength();
1974 : : // if grammar checking doesn't have any progress then quit
1975 [ # # ]: 0 : if( aResult.nStartOfNextSentencePosition <= nBeginGrammarCheck )
1976 : 0 : break;
1977 : : // prepare next iteration
1978 : 0 : nBeginGrammarCheck = (xub_StrLen)aResult.nStartOfNextSentencePosition;
1979 : : }
1980 : : while( nSpellErrorPosition > aResult.nBehindEndOfSentencePosition && !nGrammarErrors && aResult.nBehindEndOfSentencePosition < nEndGrammarCheck );
1981 : :
1982 [ # # ][ # # ]: 0 : if( nGrammarErrors > 0 && nSpellErrorPosition >= aResult.nBehindEndOfSentencePosition )
1983 : : {
1984 [ # # ]: 0 : aRet <<= aResult;
1985 : : //put the cursor to the current error
1986 [ # # ]: 0 : const linguistic2::SingleProofreadingError &rError = aResult.aErrors[0];
1987 : 0 : nCurrNd = pNd->GetIndex();
1988 [ # # ]: 0 : pSttPos->nNode = nCurrNd;
1989 [ # # ]: 0 : pEndPos->nNode = nCurrNd;
1990 [ # # ]: 0 : pSpellArgs->pStartNode = ((SwTxtNode*)pNd);
1991 [ # # ]: 0 : pSpellArgs->pEndNode = ((SwTxtNode*)pNd);
1992 [ # # ][ # # ]: 0 : pSpellArgs->pStartIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)aConversionMap.ConvertToModelPosition( rError.nErrorStart ).mnPos );
[ # # ][ # # ]
[ # # ]
1993 [ # # ][ # # ]: 0 : pSpellArgs->pEndIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)aConversionMap.ConvertToModelPosition( rError.nErrorStart + rError.nErrorLength ).mnPos );
[ # # ][ # # ]
[ # # ]
1994 : 0 : nCurrNd = nEndNd;
1995 [ # # ][ # # ]: 0 : }
1996 : 0 : }
1997 : : }
1998 : : }
1999 : : }
2000 : 0 : break;
2001 : : case ND_SECTIONNODE:
2002 [ # # ]: 0 : if( ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
[ # # # # ]
[ # # ]
2003 : 0 : ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
2004 : 0 : nCurrNd = pNd->EndOfSectionIndex();
2005 : 0 : break;
2006 : : case ND_ENDNODE:
2007 : : {
2008 : 0 : break;
2009 : : }
2010 : : }
2011 : :
2012 : 0 : bGoOn = nCurrNd < nEndNd;
2013 : 0 : ++nCurrNd;
2014 : : }
2015 : : }
2016 : :
2017 [ # # ]: 0 : if( !aRet.hasValue() )
2018 : : {
2019 [ # # ]: 0 : if (pConvArgs)
2020 [ # # ]: 0 : aRet <<= pConvArgs->aConvText;
2021 : : else
2022 [ # # ]: 0 : aRet <<= pSpellArgs->xSpellAlt;
2023 : : }
2024 [ # # ][ # # ]: 0 : delete pSpellArgs;
2025 : :
2026 : 0 : return aRet;
2027 : : }
2028 : :
2029 : 0 : class SwHyphArgs : public SwInterHyphInfo
2030 : : {
2031 : : const SwNode *pStart;
2032 : : const SwNode *pEnd;
2033 : : SwNode *pNode;
2034 : : sal_uInt16 *pPageCnt;
2035 : : sal_uInt16 *pPageSt;
2036 : :
2037 : : sal_uInt32 nNode;
2038 : : xub_StrLen nPamStart;
2039 : : xub_StrLen nPamLen;
2040 : :
2041 : : public:
2042 : : SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
2043 : : sal_uInt16* pPageCount, sal_uInt16* pPageStart );
2044 : : void SetPam( SwPaM *pPam ) const;
2045 : 0 : inline void SetNode( SwNode *pNew ) { pNode = pNew; }
2046 : : inline const SwNode *GetNode() const { return pNode; }
2047 : : inline void SetRange( const SwNode *pNew );
2048 : 0 : inline void NextNode() { ++nNode; }
2049 : 0 : inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
2050 : 0 : inline sal_uInt16 *GetPageSt() { return pPageSt; }
2051 : : };
2052 : :
2053 : 0 : SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
2054 : : sal_uInt16* pPageCount, sal_uInt16* pPageStart )
2055 : : : SwInterHyphInfo( rCrsrPos ), pNode(0),
2056 : 0 : pPageCnt( pPageCount ), pPageSt( pPageStart )
2057 : : {
2058 : : // The following constraints have to be met:
2059 : : // 1) there is at least one Selection
2060 : : // 2) SPoint() == Start()
2061 : : OSL_ENSURE( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
2062 : : OSL_ENSURE( *pPam->GetPoint() <= *pPam->GetMark(),
2063 : : "SwDoc::Hyphenate: New York, New York");
2064 : :
2065 : 0 : const SwPosition *pPoint = pPam->GetPoint();
2066 : 0 : nNode = pPoint->nNode.GetIndex();
2067 : :
2068 : : // Set start
2069 [ # # ]: 0 : pStart = pPoint->nNode.GetNode().GetTxtNode();
2070 : 0 : nPamStart = pPoint->nContent.GetIndex();
2071 : :
2072 : : // Set End and Length
2073 : 0 : const SwPosition *pMark = pPam->GetMark();
2074 [ # # ]: 0 : pEnd = pMark->nNode.GetNode().GetTxtNode();
2075 : 0 : nPamLen = pMark->nContent.GetIndex();
2076 [ # # ]: 0 : if( pPoint->nNode == pMark->nNode )
2077 : 0 : nPamLen = nPamLen - pPoint->nContent.GetIndex();
2078 : 0 : }
2079 : :
2080 : 0 : inline void SwHyphArgs::SetRange( const SwNode *pNew )
2081 : : {
2082 [ # # ]: 0 : nStart = pStart == pNew ? nPamStart : 0;
2083 [ # # ]: 0 : nLen = pEnd == pNew ? nPamLen : STRING_NOTFOUND;
2084 : 0 : }
2085 : :
2086 : 0 : void SwHyphArgs::SetPam( SwPaM *pPam ) const
2087 : : {
2088 [ # # ]: 0 : if( !pNode )
2089 : 0 : *pPam->GetPoint() = *pPam->GetMark();
2090 : : else
2091 : : {
2092 : 0 : pPam->GetPoint()->nNode = nNode;
2093 [ # # ]: 0 : pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
2094 : 0 : pPam->GetMark()->nNode = nNode;
2095 : 0 : pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
2096 [ # # ]: 0 : nWordStart + nWordLen );
2097 : : OSL_ENSURE( nNode == pNode->GetIndex(),
2098 : : "SwHyphArgs::SetPam: Pam disaster" );
2099 : : }
2100 : 0 : }
2101 : :
2102 : : // Returns sal_True if we can proceed.
2103 : 0 : sal_Bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
2104 : : {
2105 : : // Hyphenate returns true if there is a hyphenation point and sets pPam
2106 : 0 : SwTxtNode *pNode = rpNd->GetTxtNode();
2107 : 0 : SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
2108 [ # # ]: 0 : if( pNode )
2109 : : {
2110 : 0 : SwCntntFrm* pCntFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout() );
2111 [ # # ][ # # ]: 0 : if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
[ # # ]
2112 : : {
2113 : 0 : sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
2114 : 0 : sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
2115 [ # # ][ # # ]: 0 : if( pPageCnt && *pPageCnt && pPageSt )
[ # # ]
2116 : : {
2117 : 0 : sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
2118 [ # # ]: 0 : if( !*pPageSt )
2119 : : {
2120 : 0 : *pPageSt = nPageNr;
2121 [ # # ]: 0 : if( *pPageCnt < *pPageSt )
2122 : 0 : *pPageCnt = *pPageSt;
2123 : : }
2124 : : long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
2125 [ # # ]: 0 : : nPageNr + *pPageCnt - *pPageSt + 1;
2126 : 0 : ::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
2127 : : }
2128 : 0 : pHyphArgs->SetRange( rpNd );
2129 [ # # ]: 0 : if( pNode->Hyphenate( *pHyphArgs ) )
2130 : : {
2131 : 0 : pHyphArgs->SetNode( rpNd );
2132 : 0 : return sal_False;
2133 : : }
2134 : : }
2135 : : }
2136 : 0 : pHyphArgs->NextNode();
2137 : 0 : return sal_True;
2138 : : }
2139 : :
2140 : 0 : uno::Reference< XHyphenatedWord > SwDoc::Hyphenate(
2141 : : SwPaM *pPam, const Point &rCrsrPos,
2142 : : sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
2143 : : {
2144 : : OSL_ENSURE(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
2145 : :
2146 [ # # ][ # # ]: 0 : if( *pPam->GetPoint() > *pPam->GetMark() )
2147 : 0 : pPam->Exchange();
2148 : :
2149 [ # # ]: 0 : SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
2150 [ # # ]: 0 : SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
2151 [ # # ]: 0 : GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
2152 [ # # ]: 0 : lcl_HyphenateNode, &aHyphArg );
2153 [ # # ]: 0 : aHyphArg.SetPam( pPam );
2154 [ # # ][ # # ]: 0 : return aHyphArg.GetHyphWord(); // will be set by lcl_HyphenateNode
[ # # ]
2155 : : }
2156 : :
2157 : 88 : sal_Bool lcl_GetTokenToParaBreak( String& rStr, String& rRet, sal_Bool bRegExpRplc )
2158 : : {
2159 : 88 : sal_Bool bRet = sal_False;
2160 [ - + ]: 88 : if( bRegExpRplc )
2161 : : {
2162 : 0 : xub_StrLen nPos = 0;
2163 : 0 : rtl::OUString sPara("\\n");
2164 [ # # ][ # # ]: 0 : while( STRING_NOTFOUND != ( nPos = rStr.Search( sPara, nPos )) )
[ # # ][ # # ]
2165 : : {
2166 : : // Has this been escaped?
2167 [ # # ][ # # ]: 0 : if( nPos && '\\' == rStr.GetChar( nPos-1 ))
[ # # ]
2168 : : {
2169 [ # # ]: 0 : if( ++nPos >= rStr.Len() )
2170 : 0 : break;
2171 : : }
2172 : : else
2173 : : {
2174 [ # # ][ # # ]: 0 : rRet = rStr.Copy( 0, nPos );
[ # # ]
2175 [ # # ]: 0 : rStr.Erase( 0, nPos + sPara.getLength() );
2176 : 0 : bRet = sal_True;
2177 : 0 : break;
2178 : : }
2179 : 0 : }
2180 : : }
2181 [ + - ]: 88 : if( !bRet )
2182 : : {
2183 : 88 : rRet = rStr;
2184 : 88 : rStr.Erase();
2185 : : }
2186 : 88 : return bRet;
2187 : : }
2188 : :
2189 : 88 : bool SwDoc::ReplaceRange( SwPaM& rPam, const String& rStr,
2190 : : const bool bRegExReplace )
2191 : : {
2192 : : // unfortunately replace works slightly differently from delete,
2193 : : // so we cannot use lcl_DoWithBreaks here...
2194 : :
2195 [ + - ]: 88 : ::std::vector<xub_StrLen> Breaks;
2196 : :
2197 [ + - ]: 88 : SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2198 [ + - ]: 88 : aPam.Normalize(sal_False);
2199 [ - + ]: 88 : if (aPam.GetPoint()->nNode != aPam.GetMark()->nNode)
2200 : : {
2201 [ # # ]: 0 : aPam.Move(fnMoveBackward);
2202 : : }
2203 : : OSL_ENSURE((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?");
2204 : :
2205 [ + - ]: 88 : lcl_CalcBreaks(Breaks, aPam);
2206 : :
2207 [ - + ][ # # ]: 176 : while (!Breaks.empty() // skip over prefix of dummy chars
[ - + ]
2208 [ # # ][ - + ]: 88 : && (aPam.GetMark()->nContent.GetIndex() == *Breaks.begin()) )
[ # # ]
2209 : : {
2210 : : // skip!
2211 [ # # ]: 0 : ++aPam.GetMark()->nContent; // always in bounds if Breaks valid
2212 [ # # ]: 0 : Breaks.erase(Breaks.begin());
2213 : : }
2214 [ + - ][ + - ]: 88 : *rPam.Start() = *aPam.GetMark(); // update start of original pam w/ prefix
2215 : :
2216 [ + - ]: 88 : if (!Breaks.size())
2217 : : {
2218 : : // park aPam somewhere so it does not point to node that is deleted
2219 [ + - ]: 88 : aPam.DeleteMark();
2220 [ + - ][ + - ]: 88 : *aPam.GetPoint() = SwPosition(GetNodes().GetEndOfContent());
[ + - ][ + - ]
2221 [ + - ]: 88 : return ReplaceRangeImpl(rPam, rStr, bRegExReplace); // original pam!
2222 : : }
2223 : :
2224 : : // Deletion must be split into several parts if the text node
2225 : : // contains a text attribute with end and with dummy character
2226 : : // and the selection does not contain the text attribute completely,
2227 : : // but overlaps its start (left), where the dummy character is.
2228 : :
2229 : 0 : bool bRet( true );
2230 : : // iterate from end to start, to avoid invalidating the offsets!
2231 : 0 : ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
2232 : : OSL_ENSURE(aPam.GetPoint() == aPam.End(), "wrong!");
2233 [ # # ]: 0 : SwPosition & rEnd( *aPam.End() );
2234 [ # # ]: 0 : SwPosition & rStart( *aPam.Start() );
2235 : :
2236 : : // set end of temp pam to original end (undo Move backward above)
2237 [ # # ][ # # ]: 0 : rEnd = *rPam.End();
2238 : : // after first deletion, rEnd will point into the original text node again!
2239 : :
2240 [ # # ][ # # ]: 0 : while (iter != Breaks.rend())
2241 : : {
2242 [ # # ][ # # ]: 0 : rStart.nContent = *iter + 1;
2243 [ # # ]: 0 : if (rEnd.nContent != rStart.nContent) // check if part is empty
2244 : : {
2245 [ # # ]: 0 : bRet &= (IsRedlineOn())
2246 : : ? DeleteAndJoinWithRedlineImpl(aPam)
2247 [ # # ][ # # ]: 0 : : DeleteAndJoinImpl(aPam, false);
[ # # ]
2248 : : }
2249 [ # # ][ # # ]: 0 : rEnd.nContent = *iter;
2250 [ # # ]: 0 : ++iter;
2251 : : }
2252 : :
2253 [ # # ][ # # ]: 0 : rStart = *rPam.Start(); // set to original start
2254 : : OSL_ENSURE(rEnd.nContent > rStart.nContent, "replace part empty!");
2255 [ # # ]: 0 : if (rEnd.nContent > rStart.nContent) // check if part is empty
2256 : : {
2257 [ # # ]: 0 : bRet &= ReplaceRangeImpl(aPam, rStr, bRegExReplace);
2258 : : }
2259 : :
2260 [ # # ]: 0 : rPam = aPam; // update original pam (is this required?)
2261 : :
2262 [ + - ]: 88 : return bRet;
2263 : : }
2264 : :
2265 : : // It's possible to call Replace with a PaM that spans 2 paragraphs:
2266 : : // search with regex for "$", then replace _all_
2267 : 88 : bool SwDoc::ReplaceRangeImpl( SwPaM& rPam, const String& rStr,
2268 : : const bool bRegExReplace )
2269 : : {
2270 [ + - ][ + - ]: 88 : if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
[ - + ][ - + ]
2271 : 0 : return false;
2272 : :
2273 : : sal_Bool bJoinTxt, bJoinPrev;
2274 [ + - ]: 88 : lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
2275 : :
2276 : : {
2277 : : // Create a copy of the Cursor in order to move all Pams from
2278 : : // the other views out of the deletion range.
2279 : : // Except for itself!
2280 [ + - ]: 88 : SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
2281 [ + - ]: 88 : ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
2282 : :
2283 [ + - ]: 88 : SwPosition *pStt = (SwPosition*)aDelPam.Start(),
2284 [ + - ]: 88 : *pEnd = (SwPosition*)aDelPam.End();
2285 : : OSL_ENSURE( pStt->nNode == pEnd->nNode ||
2286 : : ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
2287 : : !pEnd->nContent.GetIndex() ),
2288 : : "invalid range: Point and Mark on different nodes" );
2289 : 88 : sal_Bool bOneNode = pStt->nNode == pEnd->nNode;
2290 : :
2291 : : // Own Undo?
2292 [ + - ]: 88 : String sRepl( rStr );
2293 : 88 : SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
2294 : 88 : xub_StrLen nStt = pStt->nContent.GetIndex(),
2295 : 88 : nEnd = bOneNode ? pEnd->nContent.GetIndex()
2296 [ + - ]: 88 : : pTxtNd->GetTxt().Len();
2297 : :
2298 [ + - ]: 88 : SwDataChanged aTmp( aDelPam, 0 );
2299 : :
2300 [ + - ][ - + ]: 88 : if( IsRedlineOn() )
2301 : : {
2302 [ # # ]: 0 : RedlineMode_t eOld = GetRedlineMode();
2303 [ # # ]: 0 : checkRedlining(eOld);
2304 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
2305 : : {
2306 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
2307 : :
2308 : : // If any Redline will change (split!) the node
2309 [ # # ][ # # ]: 0 : const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
2310 : :
2311 : : //JP 06.01.98: MUSS noch optimiert werden!!!
2312 : : SetRedlineMode(
2313 [ # # ]: 0 : (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
2314 : :
2315 [ # # ][ # # ]: 0 : *aDelPam.GetPoint() = pBkmk->GetMarkPos();
2316 [ # # ][ # # ]: 0 : if(pBkmk->IsExpanded())
2317 [ # # ][ # # ]: 0 : *aDelPam.GetMark() = pBkmk->GetOtherMarkPos();
2318 [ # # ][ # # ]: 0 : getIDocumentMarkAccess()->deleteMark(pBkmk);
2319 [ # # ]: 0 : pStt = aDelPam.Start();
2320 : 0 : pTxtNd = pStt->nNode.GetNode().GetTxtNode();
2321 : 0 : nStt = pStt->nContent.GetIndex();
2322 : : }
2323 : :
2324 [ # # ]: 0 : if( sRepl.Len() )
2325 : : {
2326 : : // Apply the first character's attributes to the ReplaceText
2327 : 0 : SfxItemSet aSet( GetAttrPool(),
2328 : : RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1,
2329 : : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
2330 [ # # ]: 0 : 0 );
2331 [ # # ]: 0 : pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
2332 : :
2333 [ # # ]: 0 : aSet.ClearItem( RES_TXTATR_REFMARK );
2334 [ # # ]: 0 : aSet.ClearItem( RES_TXTATR_TOXMARK );
2335 [ # # ]: 0 : aSet.ClearItem( RES_TXTATR_CJK_RUBY );
2336 [ # # ]: 0 : aSet.ClearItem( RES_TXTATR_INETFMT );
2337 [ # # ]: 0 : aSet.ClearItem( RES_TXTATR_META );
2338 [ # # ]: 0 : aSet.ClearItem( RES_TXTATR_METAFIELD );
2339 : :
2340 [ # # ][ # # ]: 0 : if( aDelPam.GetPoint() != aDelPam.End() )
2341 : 0 : aDelPam.Exchange();
2342 : :
2343 : : // Remember the End
2344 [ # # ]: 0 : SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
2345 : 0 : xub_StrLen nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
2346 : :
2347 : 0 : sal_Bool bFirst = sal_True;
2348 [ # # ]: 0 : String sIns;
2349 [ # # ][ # # ]: 0 : while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
2350 : : {
2351 [ # # ]: 0 : InsertString( aDelPam, sIns );
2352 [ # # ]: 0 : if( bFirst )
2353 : : {
2354 [ # # ]: 0 : SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
2355 : 0 : xub_StrLen nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
2356 : :
2357 [ # # ]: 0 : SplitNode( *aDelPam.GetPoint(), false );
2358 : :
2359 [ # # ]: 0 : aMkNd++;
2360 [ # # ]: 0 : aDelPam.GetMark()->nNode = aMkNd;
2361 : 0 : aDelPam.GetMark()->nContent.Assign(
2362 [ # # ][ # # ]: 0 : aMkNd.GetNode().GetCntntNode(), nMkCnt );
2363 [ # # ]: 0 : bFirst = sal_False;
2364 : : }
2365 : : else
2366 [ # # ]: 0 : SplitNode( *aDelPam.GetPoint(), false );
2367 : : }
2368 [ # # ]: 0 : if( sIns.Len() )
2369 : : {
2370 [ # # ]: 0 : InsertString( aDelPam, sIns );
2371 : : }
2372 : :
2373 [ # # ]: 0 : SwPaM aTmpRange( *aDelPam.GetPoint() );
2374 [ # # ]: 0 : aTmpRange.SetMark();
2375 : :
2376 [ # # ]: 0 : aPtNd++;
2377 [ # # ]: 0 : aDelPam.GetPoint()->nNode = aPtNd;
2378 : 0 : aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
2379 [ # # ][ # # ]: 0 : nPtCnt);
2380 [ # # ]: 0 : *aTmpRange.GetMark() = *aDelPam.GetPoint();
2381 : :
2382 [ # # ]: 0 : RstTxtAttrs( aTmpRange );
2383 [ # # ][ # # ]: 0 : InsertItemSet( aTmpRange, aSet, 0 );
[ # # ][ # # ]
[ # # ]
2384 : : }
2385 : :
2386 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
2387 : : {
2388 : : SwUndo *const pUndoRD =
2389 [ # # ][ # # ]: 0 : new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE );
2390 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndoRD);
2391 : : }
2392 [ # # ][ # # ]: 0 : AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDelPam ), true);
[ # # ]
2393 : :
2394 [ # # ]: 0 : *rPam.GetMark() = *aDelPam.GetMark();
2395 [ # # ][ # # ]: 0 : if (GetIDocumentUndoRedo().DoesUndo())
[ # # ]
2396 : : {
2397 [ # # ]: 0 : *aDelPam.GetPoint() = *rPam.GetPoint();
2398 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
2399 : :
2400 : : // If any Redline will change (split!) the node
2401 [ # # ][ # # ]: 0 : const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
2402 : :
2403 : 0 : SwIndex& rIdx = aDelPam.GetPoint()->nContent;
2404 [ # # ]: 0 : rIdx.Assign( 0, 0 );
2405 [ # # ]: 0 : aDelPam.GetMark()->nContent = rIdx;
2406 [ # # ]: 0 : rPam.GetPoint()->nNode = 0;
2407 [ # # ]: 0 : rPam.GetPoint()->nContent = rIdx;
2408 [ # # ]: 0 : *rPam.GetMark() = *rPam.GetPoint();
2409 : : //JP 06.01.98: MUSS noch optimiert werden!!!
2410 [ # # ]: 0 : SetRedlineMode( eOld );
2411 : :
2412 [ # # ][ # # ]: 0 : *rPam.GetPoint() = pBkmk->GetMarkPos();
2413 [ # # ][ # # ]: 0 : if(pBkmk->IsExpanded())
2414 [ # # ][ # # ]: 0 : *rPam.GetMark() = pBkmk->GetOtherMarkPos();
2415 [ # # ][ # # ]: 0 : getIDocumentMarkAccess()->deleteMark(pBkmk);
2416 : : }
2417 : 0 : bJoinTxt = sal_False;
2418 : : }
2419 : : else
2420 : : {
2421 [ + - ][ + - ]: 88 : if( !IsIgnoreRedline() && GetRedlineTbl().size() )
[ + - ][ - + ]
[ - + ]
2422 [ # # ]: 0 : DeleteRedline( aDelPam, true, USHRT_MAX );
2423 : :
2424 : 88 : SwUndoReplace* pUndoRpl = 0;
2425 [ + - ][ + - ]: 88 : bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
2426 [ + - ]: 88 : if (bDoesUndo)
2427 : : {
2428 [ + - ][ + - ]: 88 : pUndoRpl = new SwUndoReplace(aDelPam, sRepl, bRegExReplace);
[ + - ]
2429 [ + - ][ + - ]: 88 : GetIDocumentUndoRedo().AppendUndo(pUndoRpl);
2430 : : }
2431 [ + - ][ + - ]: 88 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2432 : :
2433 [ + - ]: 88 : if( aDelPam.GetPoint() != pStt )
2434 : 88 : aDelPam.Exchange();
2435 : :
2436 [ + - ]: 88 : SwNodeIndex aPtNd( pStt->nNode, -1 );
2437 : 88 : xub_StrLen nPtCnt = pStt->nContent.GetIndex();
2438 : :
2439 : : // Set the values again, if Frames or footnotes on the Text have been removed.
2440 : 88 : nStt = nPtCnt;
2441 : 88 : nEnd = bOneNode ? pEnd->nContent.GetIndex()
2442 [ + - ]: 88 : : pTxtNd->GetTxt().Len();
2443 : :
2444 : 88 : sal_Bool bFirst = sal_True;
2445 [ + - ]: 88 : String sIns;
2446 [ + - ][ - + ]: 88 : while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
2447 : : {
2448 [ # # ][ # # ]: 0 : if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
[ # # ]
2449 : : {
2450 [ # # ]: 0 : InsertString( aDelPam, sIns );
2451 : : }
2452 [ # # ][ # # ]: 0 : else if( nStt < nEnd || sIns.Len() )
[ # # ]
2453 : : {
2454 [ # # ]: 0 : pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
2455 : : }
2456 [ # # ]: 0 : SplitNode( *pStt, false);
2457 : 0 : bFirst = sal_False;
2458 : : }
2459 : :
2460 [ - + ][ # # ]: 88 : if( bFirst || sIns.Len() )
[ + - ]
2461 : : {
2462 [ + - ][ - + ]: 88 : if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
[ - + ]
2463 : : {
2464 [ # # ]: 0 : InsertString( aDelPam, sIns );
2465 : : }
2466 [ - + ][ # # ]: 88 : else if( nStt < nEnd || sIns.Len() )
[ + - ]
2467 : : {
2468 [ + - ]: 88 : pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
2469 : : }
2470 : : }
2471 : :
2472 [ + - ]: 88 : *rPam.GetMark() = *aDelPam.GetMark();
2473 : :
2474 [ + - ]: 88 : aPtNd++;
2475 [ + - ]: 88 : rPam.GetMark()->nNode = aPtNd;
2476 : 176 : rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
2477 [ + - ][ + - ]: 176 : nPtCnt );
2478 : :
2479 [ - + ][ # # ]: 88 : if (bJoinTxt && !bJoinPrev)
2480 : : {
2481 [ # # ]: 0 : rPam.Move(fnMoveBackward);
2482 : : }
2483 : :
2484 [ + - ]: 88 : if( pUndoRpl )
2485 : : {
2486 [ + - ]: 88 : pUndoRpl->SetEnd(rPam);
2487 [ + - ][ + - ]: 88 : }
[ + - ]
2488 [ + - ][ + - ]: 88 : }
[ + - ]
2489 : : }
2490 : :
2491 [ - + ]: 88 : if( bJoinTxt )
2492 [ # # ]: 0 : lcl_JoinText( rPam, bJoinPrev );
2493 : :
2494 [ + - ]: 88 : SetModified();
2495 : 88 : return true;
2496 : : }
2497 : :
2498 : : // Save the current values to add them as automatic entries to to AutoCorrect.
2499 : 0 : void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
2500 : : {
2501 [ # # ]: 0 : if( pNew != pACEWord )
2502 [ # # ]: 0 : delete pACEWord;
2503 : 0 : pACEWord = pNew;
2504 : 0 : }
2505 : :
2506 : 1645 : bool SwDoc::DelFullPara( SwPaM& rPam )
2507 : : {
2508 : 1645 : const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
2509 : 1645 : const SwNode* pNd = &rStt.nNode.GetNode();
2510 : 1645 : sal_uInt32 nSectDiff = pNd->StartOfSectionNode()->EndOfSectionIndex() -
2511 : 1645 : pNd->StartOfSectionIndex();
2512 : 1645 : sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
2513 : :
2514 [ + - - + ]: 2044 : if ( nSectDiff-2 <= nNodeDiff || IsRedlineOn() ||
[ + + ][ + + ]
2515 : : /* #i9185# Prevent getting the node after the end node (see below) */
2516 : 399 : rEnd.nNode.GetIndex() + 1 == GetNodes().Count() )
2517 : : {
2518 : 1246 : return sal_False;
2519 : : }
2520 : :
2521 : : // Move hard page brakes to the following Node.
2522 : 399 : sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
2523 : :
2524 : : /* #i9185# This whould lead to a segmentation fault if not caught above. */
2525 : 399 : sal_uLong nNextNd = rEnd.nNode.GetIndex() + 1;
2526 : 399 : SwTableNode *const pTblNd = GetNodes()[ nNextNd ]->GetTableNode();
2527 : :
2528 [ # # ][ - + ]: 399 : if( pTblNd && pNd->IsCntntNode() )
[ - + ]
2529 : : {
2530 : 0 : SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
2531 : :
2532 : : {
2533 : : const SfxPoolItem *pItem;
2534 [ # # ][ # # ]: 0 : const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
2535 [ # # ][ # # ]: 0 : if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
[ # # ]
2536 [ # # ]: 0 : sal_False, &pItem ) )
2537 : : {
2538 [ # # ]: 0 : pTableFmt->SetFmtAttr( *pItem );
2539 : 0 : bSavePageDesc = sal_True;
2540 : : }
2541 : :
2542 [ # # ][ # # ]: 0 : if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
[ # # ]
2543 [ # # ]: 0 : sal_False, &pItem ) )
2544 : : {
2545 [ # # ]: 0 : pTableFmt->SetFmtAttr( *pItem );
2546 : 0 : bSavePageBreak = sal_True;
2547 : : }
2548 : : }
2549 : : }
2550 : :
2551 : 399 : bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
2552 [ - + ]: 399 : if( bDoesUndo )
2553 : : {
2554 [ # # ]: 0 : if( !rPam.HasMark() )
2555 [ # # ]: 0 : rPam.SetMark();
2556 [ # # ]: 0 : else if( rPam.GetPoint() == &rStt )
2557 : 0 : rPam.Exchange();
2558 [ # # ]: 0 : rPam.GetPoint()->nNode++;
2559 : :
2560 : 0 : SwCntntNode *pTmpNode = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
2561 [ # # ][ # # ]: 0 : rPam.GetPoint()->nContent.Assign( pTmpNode, 0 );
2562 : 0 : bool bGoNext = (0 == pTmpNode);
2563 : 0 : pTmpNode = rPam.GetMark()->nNode.GetNode().GetCntntNode();
2564 [ # # ][ # # ]: 0 : rPam.GetMark()->nContent.Assign( pTmpNode, 0 );
2565 : :
2566 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().ClearRedo();
2567 : :
2568 [ # # ]: 0 : SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
2569 : : {
2570 [ # # ]: 0 : SwPosition aTmpPos( *aDelPam.GetPoint() );
2571 [ # # ]: 0 : if( bGoNext )
2572 : : {
2573 [ # # ][ # # ]: 0 : pTmpNode = GetNodes().GoNext( &aTmpPos.nNode );
2574 [ # # ][ # # ]: 0 : aTmpPos.nContent.Assign( pTmpNode, 0 );
2575 : : }
2576 [ # # ][ # # ]: 0 : ::PaMCorrAbs( aDelPam, aTmpPos );
2577 : : }
2578 : :
2579 [ # # ][ # # ]: 0 : SwUndoDelete* pUndo = new SwUndoDelete( aDelPam, sal_True );
2580 : :
2581 [ # # ]: 0 : *rPam.GetPoint() = *aDelPam.GetPoint();
2582 : 0 : pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
2583 [ # # ][ # # ]: 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
[ # # ]
2584 : : }
2585 : : else
2586 : : {
2587 [ + - ]: 399 : SwNodeRange aRg( rStt.nNode, rEnd.nNode );
2588 [ - + ]: 399 : if( rPam.GetPoint() != &rEnd )
2589 : 0 : rPam.Exchange();
2590 : :
2591 : : // Try to move past the End
2592 [ + - ][ + + ]: 399 : if( !rPam.Move( fnMoveForward, fnGoNode ) )
2593 : : {
2594 : : // Fair enough, at the Beginning then
2595 : 39 : rPam.Exchange();
2596 [ - + ][ + - ]: 39 : if( !rPam.Move( fnMoveBackward, fnGoNode ))
2597 : : {
2598 : : OSL_FAIL( "no more Nodes" );
2599 : 0 : return sal_False;
2600 : : }
2601 : : }
2602 : : // move bookmarks, redlines etc.
2603 [ + - ]: 399 : if (aRg.aStart == aRg.aEnd) // only first CorrAbs variant handles this
2604 : : {
2605 [ + - ]: 399 : CorrAbs( aRg.aStart, *rPam.GetPoint(), 0, sal_True );
2606 : : }
2607 : : else
2608 : : {
2609 [ # # ]: 0 : CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), sal_True );
2610 : : }
2611 : :
2612 : : // What's with Flys?
2613 : : {
2614 : : // If there are FlyFrames left, delete these too
2615 [ + + ]: 489 : for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->size(); ++n )
2616 : : {
2617 : 90 : SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
2618 [ + - ]: 90 : const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
2619 [ + - ]: 90 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
2620 [ + + + + : 324 : if (pAPos &&
+ - + + -
+ ][ - + ]
2621 : 77 : ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
2622 : 9 : (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
2623 : 148 : aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
2624 : : {
2625 [ # # ]: 0 : DelLayoutFmt( pFly );
2626 : 0 : --n;
2627 : : }
2628 : : }
2629 : : }
2630 : :
2631 : 399 : SwCntntNode *pTmpNode = rPam.GetBound( sal_True ).nNode.GetNode().GetCntntNode();
2632 [ + - ][ + - ]: 399 : rPam.GetBound( sal_True ).nContent.Assign( pTmpNode, 0 );
2633 : 399 : pTmpNode = rPam.GetBound( sal_False ).nNode.GetNode().GetCntntNode();
2634 [ + - ][ - + ]: 399 : rPam.GetBound( sal_False ).nContent.Assign( pTmpNode, 0 );
2635 [ + - ][ + - ]: 399 : GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
[ + - ][ + - ]
2636 : : }
2637 : 399 : rPam.DeleteMark();
2638 : 399 : SetModified();
2639 : :
2640 : 1645 : return sal_True;
2641 : : }
2642 : :
2643 : 0 : void SwDoc::TransliterateText(
2644 : : const SwPaM& rPaM,
2645 : : utl::TransliterationWrapper& rTrans )
2646 : : {
2647 : 0 : SwUndoTransliterate *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
2648 [ # # ]: 0 : ? new SwUndoTransliterate( rPaM, rTrans )
2649 [ # # ]: 0 : : 0;
2650 : :
2651 : 0 : const SwPosition* pStt = rPaM.Start(),
2652 : 0 : * pEnd = rPaM.End();
2653 : 0 : sal_uLong nSttNd = pStt->nNode.GetIndex(),
2654 : 0 : nEndNd = pEnd->nNode.GetIndex();
2655 : 0 : xub_StrLen nSttCnt = pStt->nContent.GetIndex(),
2656 : 0 : nEndCnt = pEnd->nContent.GetIndex();
2657 : :
2658 : 0 : SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
2659 [ # # ][ # # ]: 0 : if( pStt == pEnd && pTNd ) // no selection?
2660 : : {
2661 : : // set current word as 'area of effect'
2662 : :
2663 : 0 : Boundary aBndry;
2664 [ # # ][ # # ]: 0 : if( pBreakIt->GetBreakIter().is() )
2665 [ # # ][ # # ]: 0 : aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
2666 : 0 : pTNd->GetTxt(), nSttCnt,
2667 [ # # ][ # # ]: 0 : pBreakIt->GetLocale( pTNd->GetLang( nSttCnt ) ),
2668 : : WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
2669 [ # # ][ # # ]: 0 : sal_True );
2670 : :
2671 [ # # ][ # # ]: 0 : if( aBndry.startPos < nSttCnt && nSttCnt < aBndry.endPos )
2672 : : {
2673 : 0 : nSttCnt = (xub_StrLen)aBndry.startPos;
2674 : 0 : nEndCnt = (xub_StrLen)aBndry.endPos;
2675 : : }
2676 : : }
2677 : :
2678 [ # # ]: 0 : if( nSttNd != nEndNd ) // is more than one text node involved?
2679 : : {
2680 : : // iterate over all effected text nodes, the first and the last one
2681 : : // may be incomplete because the selection starts and/or ends there
2682 : :
2683 [ # # ]: 0 : SwNodeIndex aIdx( pStt->nNode );
2684 [ # # ]: 0 : if( nSttCnt )
2685 : : {
2686 [ # # ]: 0 : aIdx++;
2687 [ # # ]: 0 : if( pTNd )
2688 [ # # ]: 0 : pTNd->TransliterateText( rTrans, nSttCnt, pTNd->GetTxt().Len(), pUndo );
2689 : : }
2690 : :
2691 [ # # ][ # # ]: 0 : for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
2692 : : {
2693 [ # # ]: 0 : if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
2694 [ # # ]: 0 : pTNd->TransliterateText( rTrans, 0, pTNd->GetTxt().Len(), pUndo );
2695 : : }
2696 : :
2697 [ # # ][ # # ]: 0 : if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
[ # # ]
2698 [ # # ][ # # ]: 0 : pTNd->TransliterateText( rTrans, 0, nEndCnt, pUndo );
2699 : : }
2700 [ # # ][ # # ]: 0 : else if( pTNd && nSttCnt < nEndCnt )
2701 : 0 : pTNd->TransliterateText( rTrans, nSttCnt, nEndCnt, pUndo );
2702 : :
2703 [ # # ]: 0 : if( pUndo )
2704 : : {
2705 [ # # ]: 0 : if( pUndo->HasData() )
2706 : : {
2707 : 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
2708 : : }
2709 : : else
2710 [ # # ]: 0 : delete pUndo;
2711 : : }
2712 : 0 : SetModified();
2713 : 0 : }
2714 : :
2715 : : #define MAX_REDLINE_COUNT 250
2716 : :
2717 : 703 : void SwDoc::checkRedlining(RedlineMode_t& _rReadlineMode)
2718 : : {
2719 : 703 : const SwRedlineTbl& rRedlineTbl = GetRedlineTbl();
2720 : 703 : SwEditShell* pEditShell = GetEditShell();
2721 [ - + ]: 703 : Window* pParent = pEditShell ? pEditShell->GetWin() : NULL;
2722 [ - + ][ # # ]: 703 : if ( pParent && !mbReadlineChecked && rRedlineTbl.size() > MAX_REDLINE_COUNT
[ # # ][ # # ]
[ - + ]
2723 : 0 : && !((_rReadlineMode & nsRedlineMode_t::REDLINE_SHOW_DELETE) == nsRedlineMode_t::REDLINE_SHOW_DELETE) )
2724 : : {
2725 [ # # ]: 0 : WarningBox aWarning( pParent,SW_RES(MSG_DISABLE_READLINE_QUESTION));
2726 [ # # ]: 0 : sal_uInt16 nResult = aWarning.Execute();
2727 : 0 : mbReadlineChecked = sal_True;
2728 [ # # ]: 0 : if ( nResult == RET_YES )
2729 : : {
2730 : 0 : sal_Int32 nMode = (sal_Int32)_rReadlineMode;
2731 : 0 : nMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE;
2732 : 0 : _rReadlineMode = (RedlineMode_t)nMode;
2733 [ # # ]: 0 : }
2734 : : }
2735 : 703 : }
2736 : :
2737 : 16 : void SwDoc::CountWords( const SwPaM& rPaM, SwDocStat& rStat ) const
2738 : : {
2739 : : // This is a modified version of SwDoc::TransliterateText
2740 : 16 : const SwPosition* pStt = rPaM.Start();
2741 : 16 : const SwPosition* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
2742 [ + - ]: 16 : : rPaM.GetPoint();
2743 : :
2744 : 16 : const sal_uLong nSttNd = pStt->nNode.GetIndex();
2745 : 16 : const sal_uLong nEndNd = pEnd->nNode.GetIndex();
2746 : :
2747 : 16 : const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
2748 : 16 : const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
2749 : :
2750 : 16 : const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
2751 [ # # ][ - + ]: 16 : if( pStt == pEnd && pTNd ) // no region ?
2752 : : {
2753 : : // do nothing
2754 : 16 : return;
2755 : : }
2756 : :
2757 [ - + ]: 16 : if( nSttNd != nEndNd )
2758 : : {
2759 [ # # ]: 0 : SwNodeIndex aIdx( pStt->nNode );
2760 [ # # ]: 0 : if( nSttCnt )
2761 : : {
2762 [ # # ]: 0 : aIdx++;
2763 [ # # ]: 0 : if( pTNd )
2764 [ # # ]: 0 : pTNd->CountWords( rStat, nSttCnt, pTNd->GetTxt().Len() );
2765 : : }
2766 : :
2767 [ # # ][ # # ]: 0 : for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
2768 [ # # ]: 0 : if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
2769 [ # # ]: 0 : pTNd->CountWords( rStat, 0, pTNd->GetTxt().Len() );
2770 : :
2771 [ # # ][ # # ]: 0 : if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
[ # # ]
2772 [ # # ][ # # ]: 0 : pTNd->CountWords( rStat, 0, nEndCnt );
2773 : : }
2774 [ + - ][ - + ]: 16 : else if( pTNd && nSttCnt < nEndCnt )
2775 : 0 : pTNd->CountWords( rStat, nSttCnt, nEndCnt );
2776 : : }
2777 : :
2778 : 0 : void SwDoc::RemoveLeadingWhiteSpace(const SwPosition & rPos )
2779 : : {
2780 : 0 : const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
2781 [ # # ]: 0 : if ( pTNd )
2782 : : {
2783 : 0 : const String& rTxt = pTNd->GetTxt();
2784 : 0 : xub_StrLen nIdx = 0;
2785 : : sal_Unicode cCh;
2786 [ # # ][ # # ]: 0 : while( nIdx < rTxt.Len() &&
[ # # ][ # # ]
2787 : 0 : ( '\t' == ( cCh = rTxt.GetChar( nIdx ) ) ||
2788 : : ( ' ' == cCh ) ) )
2789 : 0 : ++nIdx;
2790 : :
2791 [ # # ]: 0 : if ( nIdx > 0 )
2792 : : {
2793 [ # # ]: 0 : SwPaM aPam(rPos);
2794 [ # # ]: 0 : aPam.GetPoint()->nContent = 0;
2795 [ # # ]: 0 : aPam.SetMark();
2796 [ # # ]: 0 : aPam.GetMark()->nContent = nIdx;
2797 [ # # ][ # # ]: 0 : DeleteRange( aPam );
2798 : : }
2799 : : }
2800 : 0 : }
2801 : :
2802 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|