Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 : #include <DocumentContentOperationsManager.hxx>
20 : #include <doc.hxx>
21 : #include <IDocumentUndoRedo.hxx>
22 : #include <IDocumentMarkAccess.hxx>
23 : #include <DocumentRedlineManager.hxx>
24 : #include <IDocumentState.hxx>
25 : #include <IDocumentLayoutAccess.hxx>
26 : #include <IDocumentStylePoolAccess.hxx>
27 : #include <UndoManager.hxx>
28 : #include <docary.hxx>
29 : #include <textboxhelper.hxx>
30 : #include <dcontact.hxx>
31 : #include <grfatr.hxx>
32 : #include <numrule.hxx>
33 : #include <charfmt.hxx>
34 : #include <ndgrf.hxx>
35 : #include <ndnotxt.hxx>
36 : #include <ndole.hxx>
37 : #include <fmtcol.hxx>
38 : #include <breakit.hxx>
39 : #include <frmfmt.hxx>
40 : #include <fmtanchr.hxx>
41 : #include <fmtcntnt.hxx>
42 : #include <fmtinfmt.hxx>
43 : #include <fmtpdsc.hxx>
44 : #include <fmtcnct.hxx>
45 : #include <SwStyleNameMapper.hxx>
46 : #include <redline.hxx>
47 : #include <unocrsr.hxx>
48 : #include <mvsave.hxx>
49 : #include <ndtxt.hxx>
50 : #include <poolfmt.hxx>
51 : #include <paratr.hxx>
52 : #include <txatbase.hxx>
53 : #include <UndoRedline.hxx>
54 : #include <undobj.hxx>
55 : #include <UndoDelete.hxx>
56 : #include <UndoSplitMove.hxx>
57 : #include <UndoOverwrite.hxx>
58 : #include <UndoInsert.hxx>
59 : #include <UndoAttribute.hxx>
60 : #include <rolbck.hxx>
61 : #include <acorrect.hxx>
62 : #include <ftnidx.hxx>
63 : #include <txtftn.hxx>
64 : #include <hints.hxx>
65 : #include <crsrsh.hxx>
66 : #include <fmtflcnt.hxx>
67 : #include <docedt.hxx>
68 : #include <unotools/charclass.hxx>
69 : #include <sfx2/Metadatable.hxx>
70 : #include <svl/stritem.hxx>
71 : #include <svl/itemiter.hxx>
72 : #include <svx/svdobj.hxx>
73 : #include <svx/svdouno.hxx>
74 : #include <editeng/formatbreakitem.hxx>
75 : #include <com/sun/star/i18n/Boundary.hpp>
76 :
77 : using namespace ::com::sun::star::i18n;
78 :
79 : namespace
80 : {
81 : // Copy method from SwDoc
82 : // Prevent copying in Flys that are anchored in the area
83 432 : static bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
84 : sal_uLong nInsNd )
85 : {
86 432 : const SwFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
87 :
88 5186 : for( size_t n = 0; n < rFrmFmtTbl.size(); ++n )
89 : {
90 4754 : SwFrmFmt const*const pFmt = rFrmFmtTbl[n];
91 4754 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
92 4754 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
93 9246 : if (pAPos &&
94 7150 : ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
95 5146 : (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
96 4976 : (FLY_AT_FLY == pAnchor->GetAnchorId()) ||
97 6980 : (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
98 12404 : nSttNd <= pAPos->nNode.GetIndex() &&
99 3158 : pAPos->nNode.GetIndex() < nEndNd )
100 : {
101 90 : const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
102 : SwStartNode* pSNd;
103 154 : if( !rCntnt.GetCntntIdx() ||
104 64 : 0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
105 26 : continue;
106 :
107 128 : if( pSNd->GetIndex() < nInsNd &&
108 64 : nInsNd < pSNd->EndOfSectionIndex() )
109 : // Do not copy !
110 0 : return true;
111 :
112 64 : if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
113 64 : pSNd->EndOfSectionIndex(), nInsNd ) )
114 : // Do not copy !
115 0 : return true;
116 : }
117 : }
118 :
119 432 : return false;
120 : }
121 :
122 : /*
123 : The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
124 : array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
125 : every node (at least at the moment: 2/08/2006 ), section start and end nodes will not be copied if the corresponding end/start node is outside the copied pam.
126 : The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
127 : index inside the pam.
128 : rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
129 : of "non-copy" nodes between rPam.Start() and rLastIdx.
130 : nNewIdx is the new position of interest.
131 : */
132 :
133 798 : static void lcl_NonCopyCount( const SwPaM& rPam, SwNodeIndex& rLastIdx, const sal_uLong nNewIdx, sal_uLong& rDelCount )
134 : {
135 798 : sal_uLong nStart = rPam.Start()->nNode.GetIndex();
136 798 : sal_uLong nEnd = rPam.End()->nNode.GetIndex();
137 798 : if( rLastIdx.GetIndex() < nNewIdx ) // Moving forward?
138 : {
139 1572 : do // count "non-copy" nodes
140 : {
141 1572 : SwNode& rNode = rLastIdx.GetNode();
142 3168 : if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
143 3144 : || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
144 0 : ++rDelCount;
145 1572 : ++rLastIdx;
146 : }
147 1572 : while( rLastIdx.GetIndex() < nNewIdx );
148 : }
149 318 : else if( rDelCount ) // optimization: if there are no "non-copy" nodes until now,
150 : // no move backward needed
151 : {
152 0 : while( rLastIdx.GetIndex() > nNewIdx )
153 : {
154 0 : SwNode& rNode = rLastIdx.GetNode();
155 0 : if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
156 0 : || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
157 0 : --rDelCount;
158 0 : rLastIdx--;
159 : }
160 : }
161 798 : }
162 :
163 798 : static void lcl_SetCpyPos( const SwPosition& rOrigPos,
164 : const SwPosition& rOrigStt,
165 : const SwPosition& rCpyStt,
166 : SwPosition& rChgPos,
167 : sal_uLong nDelCount )
168 : {
169 798 : sal_uLong nNdOff = rOrigPos.nNode.GetIndex();
170 798 : nNdOff -= rOrigStt.nNode.GetIndex();
171 798 : nNdOff -= nDelCount;
172 798 : sal_Int32 nCntntPos = rOrigPos.nContent.GetIndex();
173 :
174 : // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
175 798 : rChgPos.nNode = nNdOff + rCpyStt.nNode.GetIndex();
176 798 : if( !nNdOff )
177 : {
178 : // dann nur den Content anpassen
179 40 : if( nCntntPos > rOrigStt.nContent.GetIndex() )
180 20 : nCntntPos -= rOrigStt.nContent.GetIndex();
181 : else
182 20 : nCntntPos = 0;
183 40 : nCntntPos += rCpyStt.nContent.GetIndex();
184 : }
185 798 : rChgPos.nContent.Assign( rChgPos.nNode.GetNode().GetCntntNode(), nCntntPos );
186 798 : }
187 :
188 : // TODO: use SaveBookmark (from _DelBookmarks)
189 872 : static void lcl_CopyBookmarks(
190 : const SwPaM& rPam,
191 : SwPaM& rCpyPam )
192 : {
193 872 : const SwDoc* pSrcDoc = rPam.GetDoc();
194 872 : SwDoc* pDestDoc = rCpyPam.GetDoc();
195 872 : const IDocumentMarkAccess* const pSrcMarkAccess = pSrcDoc->getIDocumentMarkAccess();
196 872 : ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
197 :
198 872 : const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
199 872 : SwPosition* pCpyStt = rCpyPam.Start();
200 :
201 : typedef ::std::vector< const ::sw::mark::IMark* > mark_vector_t;
202 1744 : mark_vector_t vMarksToCopy;
203 56268 : for ( IDocumentMarkAccess::const_iterator_t ppMark = pSrcMarkAccess->getAllMarksBegin();
204 37512 : ppMark != pSrcMarkAccess->getAllMarksEnd();
205 : ++ppMark )
206 : {
207 17884 : const ::sw::mark::IMark* const pMark = ppMark->get();
208 :
209 17884 : const SwPosition& rMarkStart = pMark->GetMarkStart();
210 17884 : const SwPosition& rMarkEnd = pMark->GetMarkEnd();
211 : // only include marks that are in the range and not touching both start and end
212 : // - not for annotation marks.
213 : const bool bIsNotOnBoundary =
214 17884 : pMark->IsExpanded()
215 6998 : ? (rMarkStart != rStt || rMarkEnd != rEnd) // rMarkStart != rMarkEnd
216 24882 : : (rMarkStart != rStt && rMarkEnd != rEnd); // rMarkStart == rMarkEnd
217 52182 : if ( rMarkStart >= rStt && rMarkEnd <= rEnd
218 19606 : && ( bIsNotOnBoundary
219 206 : || IDocumentMarkAccess::GetType( *pMark ) == IDocumentMarkAccess::ANNOTATIONMARK ) )
220 : {
221 758 : vMarksToCopy.push_back(pMark);
222 : }
223 : }
224 : // We have to count the "non-copied" nodes..
225 1744 : SwNodeIndex aCorrIdx(rStt.nNode);
226 872 : sal_uLong nDelCount = 0;
227 4890 : for(mark_vector_t::const_iterator ppMark = vMarksToCopy.begin();
228 3260 : ppMark != vMarksToCopy.end();
229 : ++ppMark)
230 : {
231 758 : const ::sw::mark::IMark* const pMark = *ppMark;
232 758 : SwPaM aTmpPam(*pCpyStt);
233 758 : lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetMarkPos().nNode.GetIndex(), nDelCount);
234 758 : lcl_SetCpyPos( pMark->GetMarkPos(), rStt, *pCpyStt, *aTmpPam.GetPoint(), nDelCount);
235 758 : if(pMark->IsExpanded())
236 : {
237 40 : aTmpPam.SetMark();
238 40 : lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetOtherMarkPos().nNode.GetIndex(), nDelCount);
239 40 : lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount);
240 : }
241 :
242 758 : ::sw::mark::IMark* const pNewMark = pDestDoc->getIDocumentMarkAccess()->makeMark(
243 : aTmpPam,
244 758 : pMark->GetName(),
245 1516 : IDocumentMarkAccess::GetType(*pMark));
246 : // Explicitly try to get exactly the same name as in the source
247 : // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
248 758 : pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
249 :
250 : // copying additional attributes for bookmarks or fieldmarks
251 : ::sw::mark::IBookmark* const pNewBookmark =
252 758 : dynamic_cast< ::sw::mark::IBookmark* const >(pNewMark);
253 : const ::sw::mark::IBookmark* const pOldBookmark =
254 758 : dynamic_cast< const ::sw::mark::IBookmark* >(pMark);
255 758 : if (pNewBookmark && pOldBookmark)
256 : {
257 58 : pNewBookmark->SetKeyCode(pOldBookmark->GetKeyCode());
258 58 : pNewBookmark->SetShortName(pOldBookmark->GetShortName());
259 : }
260 : ::sw::mark::IFieldmark* const pNewFieldmark =
261 758 : dynamic_cast< ::sw::mark::IFieldmark* const >(pNewMark);
262 : const ::sw::mark::IFieldmark* const pOldFieldmark =
263 758 : dynamic_cast< const ::sw::mark::IFieldmark* >(pMark);
264 758 : if (pNewFieldmark && pOldFieldmark)
265 : {
266 4 : pNewFieldmark->SetFieldname(pOldFieldmark->GetFieldname());
267 4 : pNewFieldmark->SetFieldHelptext(pOldFieldmark->GetFieldHelptext());
268 4 : ::sw::mark::IFieldmark::parameter_map_t* pNewParams = pNewFieldmark->GetParameters();
269 4 : const ::sw::mark::IFieldmark::parameter_map_t* pOldParams = pOldFieldmark->GetParameters();
270 4 : ::sw::mark::IFieldmark::parameter_map_t::const_iterator pIt = pOldParams->begin();
271 4 : for (; pIt != pOldParams->end(); ++pIt )
272 : {
273 0 : pNewParams->insert( *pIt );
274 : }
275 : }
276 :
277 : ::sfx2::Metadatable const*const pMetadatable(
278 758 : dynamic_cast< ::sfx2::Metadatable const* >(pMark));
279 : ::sfx2::Metadatable *const pNewMetadatable(
280 758 : dynamic_cast< ::sfx2::Metadatable * >(pNewMark));
281 758 : if (pMetadatable && pNewMetadatable)
282 : {
283 58 : pNewMetadatable->RegisterAsCopyOf(*pMetadatable);
284 : }
285 1630 : }
286 872 : }
287 :
288 4 : static void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
289 : {
290 4 : const SwDoc* pSrcDoc = rPam.GetDoc();
291 4 : const SwRedlineTbl& rTbl = pSrcDoc->getIDocumentRedlineAccess().GetRedlineTbl();
292 4 : if( !rTbl.empty() )
293 : {
294 0 : SwDoc* pDestDoc = rCpyPam.GetDoc();
295 0 : SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
296 0 : SwPaM* pDelPam = 0;
297 0 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
298 : // We have to count the "non-copied" nodes
299 0 : sal_uLong nDelCount = 0;
300 0 : SwNodeIndex aCorrIdx( pStt->nNode );
301 :
302 0 : sal_uInt16 n = 0;
303 0 : pSrcDoc->getIDocumentRedlineAccess().GetRedline( *pStt, &n );
304 0 : for( ; n < rTbl.size(); ++n )
305 : {
306 0 : const SwRangeRedline* pRedl = rTbl[ n ];
307 0 : if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
308 : {
309 0 : const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
310 :
311 0 : SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
312 0 : switch( eCmpPos )
313 : {
314 : case POS_COLLIDE_END:
315 : case POS_BEFORE:
316 : // Pos1 is before Pos2
317 0 : break;
318 :
319 : case POS_COLLIDE_START:
320 : case POS_BEHIND:
321 : // Pos1 is after Pos2
322 0 : n = rTbl.size();
323 0 : break;
324 :
325 : default:
326 : {
327 0 : pDelPam = new SwPaM( *pCpyStt, pDelPam );
328 0 : if( *pStt < *pRStt )
329 : {
330 0 : lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
331 : lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
332 0 : *pDelPam->GetPoint(), nDelCount );
333 : }
334 0 : pDelPam->SetMark();
335 :
336 0 : if( *pEnd < *pREnd )
337 0 : *pDelPam->GetPoint() = *pCpyEnd;
338 : else
339 : {
340 0 : lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
341 : lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
342 0 : *pDelPam->GetPoint(), nDelCount );
343 : }
344 : }
345 : }
346 : }
347 : }
348 :
349 0 : if( pDelPam )
350 : {
351 0 : RedlineMode_t eOld = pDestDoc->getIDocumentRedlineAccess().GetRedlineMode();
352 0 : pDestDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
353 :
354 0 : ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
355 :
356 : do {
357 0 : pDestDoc->getIDocumentContentOperations().DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
358 0 : if( pDelPam->GetNext() == pDelPam )
359 0 : break;
360 0 : delete pDelPam->GetNext();
361 : } while( true );
362 0 : delete pDelPam;
363 :
364 0 : pDestDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
365 0 : }
366 : }
367 4 : }
368 :
369 2 : static void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
370 : {
371 2 : SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
372 2 : if( !pSrcDoc->getIDocumentRedlineAccess().GetRedlineTbl().empty() )
373 : {
374 0 : SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
375 0 : SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
376 0 : lcl_DeleteRedlines( aRgTmp, aCpyTmp );
377 : }
378 2 : }
379 :
380 0 : static void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
381 : {
382 0 : SwFmtChain aSrc( pSrc->GetChain() );
383 0 : if ( !aSrc.GetNext() )
384 : {
385 0 : aSrc.SetNext( pDest );
386 0 : pSrc->SetFmtAttr( aSrc );
387 : }
388 0 : SwFmtChain aDest( pDest->GetChain() );
389 0 : if ( !aDest.GetPrev() )
390 : {
391 0 : aDest.SetPrev( pSrc );
392 0 : pDest->SetFmtAttr( aDest );
393 0 : }
394 0 : }
395 :
396 : // #i86492#
397 4 : static bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
398 : {
399 4 : bool bRet = false;
400 :
401 4 : const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
402 4 : const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
403 8 : if ( pTxtNd && pTxtNd->IsInList() &&
404 6 : pEndTxtNd && pEndTxtNd->IsInList() )
405 : {
406 2 : bRet = true;
407 2 : SwNodeIndex aIdx(rPam.Start()->nNode);
408 :
409 0 : do
410 : {
411 2 : ++aIdx;
412 2 : pTxtNd = aIdx.GetNode().GetTxtNode();
413 :
414 2 : if ( !pTxtNd || !pTxtNd->IsInList() )
415 : {
416 2 : bRet = false;
417 2 : break;
418 : }
419 0 : } while ( pTxtNd && pTxtNd != pEndTxtNd );
420 : }
421 :
422 4 : return bRet;
423 : }
424 :
425 158 : static bool lcl_MarksWholeNode(const SwPaM & rPam)
426 : {
427 158 : bool bResult = false;
428 158 : const SwPosition* pStt = rPam.Start();
429 158 : const SwPosition* pEnd = rPam.End();
430 :
431 158 : if (NULL != pStt && NULL != pEnd)
432 : {
433 158 : const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
434 158 : const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
435 :
436 474 : if (NULL != pSttNd && NULL != pEndNd &&
437 470 : pStt->nContent.GetIndex() == 0 &&
438 154 : pEnd->nContent.GetIndex() == pEndNd->Len())
439 : {
440 154 : bResult = true;
441 : }
442 : }
443 :
444 158 : return bResult;
445 : }
446 : }
447 :
448 : //local functions originally from sw/source/core/doc/docedt.cxx
449 : namespace
450 : {
451 : static void
452 10591 : lcl_CalcBreaks( ::std::vector<sal_Int32> & rBreaks, SwPaM const & rPam )
453 : {
454 : SwTxtNode const * const pTxtNode(
455 10591 : rPam.End()->nNode.GetNode().GetTxtNode() );
456 10591 : if (!pTxtNode)
457 558 : return; // left-overlap only possible at end of selection...
458 :
459 10033 : const sal_Int32 nStart(rPam.Start()->nContent.GetIndex());
460 10033 : const sal_Int32 nEnd (rPam.End ()->nContent.GetIndex());
461 10033 : if (nEnd == pTxtNode->Len())
462 8873 : return; // paragraph selected until the end
463 :
464 9308 : for (sal_Int32 i = nStart; i < nEnd; ++i)
465 : {
466 8148 : const sal_Unicode c(pTxtNode->GetTxt()[i]);
467 8148 : if ((CH_TXTATR_INWORD == c) || (CH_TXTATR_BREAKWORD == c))
468 : {
469 152 : SwTxtAttr const * const pAttr( pTxtNode->GetTxtAttrForCharAt(i) );
470 152 : if (pAttr && pAttr->End() && (*pAttr->End() > nEnd))
471 : {
472 : OSL_ENSURE(pAttr->HasDummyChar(), "GetTxtAttrForCharAt broken?");
473 0 : rBreaks.push_back(i);
474 : }
475 : }
476 : }
477 : }
478 :
479 10499 : static bool lcl_DoWithBreaks(::sw::DocumentContentOperationsManager & rDocumentContentOperations, SwPaM & rPam,
480 : bool (::sw::DocumentContentOperationsManager::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
481 : {
482 10499 : ::std::vector<sal_Int32> Breaks;
483 :
484 10499 : lcl_CalcBreaks(Breaks, rPam);
485 :
486 10499 : if (!Breaks.size())
487 : {
488 10499 : return (rDocumentContentOperations.*pFunc)(rPam, bForceJoinNext);
489 : }
490 :
491 : // Deletion must be split into several parts if the text node
492 : // contains a text attribute with end and with dummy character
493 : // and the selection does not contain the text attribute completely,
494 : // but overlaps its start (left), where the dummy character is.
495 :
496 0 : SwPosition const & rSelectionEnd( *rPam.End() );
497 :
498 0 : bool bRet( true );
499 : // iterate from end to start, to avoid invalidating the offsets!
500 0 : ::std::vector<sal_Int32>::reverse_iterator iter( Breaks.rbegin() );
501 0 : SwPaM aPam( rSelectionEnd, rSelectionEnd ); // end node!
502 0 : SwPosition & rEnd( *aPam.End() );
503 0 : SwPosition & rStart( *aPam.Start() );
504 :
505 0 : while (iter != Breaks.rend())
506 : {
507 0 : rStart.nContent = *iter + 1;
508 0 : if (rEnd.nContent > rStart.nContent) // check if part is empty
509 : {
510 0 : bRet &= (rDocumentContentOperations.*pFunc)(aPam, bForceJoinNext);
511 : }
512 0 : rEnd.nContent = *iter;
513 0 : ++iter;
514 : }
515 :
516 0 : rStart = *rPam.Start(); // set to original start
517 0 : if (rEnd.nContent > rStart.nContent) // check if part is empty
518 : {
519 0 : bRet &= (rDocumentContentOperations.*pFunc)(aPam, bForceJoinNext);
520 : }
521 :
522 10499 : return bRet;
523 : }
524 :
525 9629 : static bool lcl_StrLenOverflow( const SwPaM& rPam )
526 : {
527 : // If we try to merge two paragraphs we have to test if afterwards
528 : // the string doesn't exceed the allowed string length
529 9629 : if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
530 : {
531 5022 : const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
532 5022 : const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
533 5022 : if( (0 != pEndNd) && pStt->nNode.GetNode().IsTxtNode() )
534 : {
535 10036 : const sal_uInt64 nSum = pStt->nContent.GetIndex() +
536 10036 : pEndNd->GetTxt().getLength() - pEnd->nContent.GetIndex();
537 5018 : return nSum > static_cast<sal_uInt64>(SAL_MAX_INT32);
538 : }
539 : }
540 4611 : return false;
541 : }
542 :
543 : struct _SaveRedline
544 : {
545 : SwRangeRedline* pRedl;
546 : sal_uInt32 nStt, nEnd;
547 : sal_Int32 nSttCnt;
548 : sal_Int32 nEndCnt;
549 :
550 0 : _SaveRedline( SwRangeRedline* pR, const SwNodeIndex& rSttIdx )
551 : : pRedl(pR)
552 : , nEnd(0)
553 0 : , nEndCnt(0)
554 : {
555 0 : const SwPosition* pStt = pR->Start(),
556 0 : * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
557 0 : sal_uInt32 nSttIdx = rSttIdx.GetIndex();
558 0 : nStt = pStt->nNode.GetIndex() - nSttIdx;
559 0 : nSttCnt = pStt->nContent.GetIndex();
560 0 : if( pR->HasMark() )
561 : {
562 0 : nEnd = pEnd->nNode.GetIndex() - nSttIdx;
563 0 : nEndCnt = pEnd->nContent.GetIndex();
564 : }
565 :
566 0 : pRedl->GetPoint()->nNode = 0;
567 0 : pRedl->GetPoint()->nContent.Assign( 0, 0 );
568 0 : pRedl->GetMark()->nNode = 0;
569 0 : pRedl->GetMark()->nContent.Assign( 0, 0 );
570 0 : }
571 :
572 0 : _SaveRedline( SwRangeRedline* pR, const SwPosition& rPos )
573 : : pRedl(pR)
574 : , nEnd(0)
575 0 : , nEndCnt(0)
576 : {
577 0 : const SwPosition* pStt = pR->Start(),
578 0 : * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
579 0 : sal_uInt32 nSttIdx = rPos.nNode.GetIndex();
580 0 : nStt = pStt->nNode.GetIndex() - nSttIdx;
581 0 : nSttCnt = pStt->nContent.GetIndex();
582 0 : if( nStt == 0 )
583 0 : nSttCnt = nSttCnt - rPos.nContent.GetIndex();
584 0 : if( pR->HasMark() )
585 : {
586 0 : nEnd = pEnd->nNode.GetIndex() - nSttIdx;
587 0 : nEndCnt = pEnd->nContent.GetIndex();
588 0 : if( nEnd == 0 )
589 0 : nEndCnt = nEndCnt - rPos.nContent.GetIndex();
590 : }
591 :
592 0 : pRedl->GetPoint()->nNode = 0;
593 0 : pRedl->GetPoint()->nContent.Assign( 0, 0 );
594 0 : pRedl->GetMark()->nNode = 0;
595 0 : pRedl->GetMark()->nContent.Assign( 0, 0 );
596 0 : }
597 :
598 0 : void SetPos( sal_uInt32 nInsPos )
599 : {
600 0 : pRedl->GetPoint()->nNode = nInsPos + nStt;
601 0 : pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
602 0 : if( pRedl->HasMark() )
603 : {
604 0 : pRedl->GetMark()->nNode = nInsPos + nEnd;
605 0 : pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(false), nEndCnt );
606 : }
607 0 : }
608 :
609 0 : void SetPos( const SwPosition& aPos )
610 : {
611 0 : pRedl->GetPoint()->nNode = aPos.nNode.GetIndex() + nStt;
612 0 : pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt + ( nStt == 0 ? aPos.nContent.GetIndex() : 0 ) );
613 0 : if( pRedl->HasMark() )
614 : {
615 0 : pRedl->GetMark()->nNode = aPos.nNode.GetIndex() + nEnd;
616 0 : pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(false), nEndCnt + ( nEnd == 0 ? aPos.nContent.GetIndex() : 0 ) );
617 : }
618 0 : }
619 : };
620 :
621 : typedef boost::ptr_vector< _SaveRedline > _SaveRedlines;
622 :
623 0 : static void lcl_SaveRedlines( const SwPaM& aPam, _SaveRedlines& rArr )
624 : {
625 0 : SwDoc* pDoc = aPam.GetNode().GetDoc();
626 :
627 0 : const SwPosition* pStart = aPam.Start();
628 0 : const SwPosition* pEnd = aPam.End();
629 :
630 : // get first relevant redline
631 : sal_uInt16 nCurrentRedline;
632 0 : pDoc->getIDocumentRedlineAccess().GetRedline( *pStart, &nCurrentRedline );
633 0 : if( nCurrentRedline > 0)
634 0 : nCurrentRedline--;
635 :
636 : // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
637 0 : RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode();
638 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
639 :
640 : // iterate over relevant redlines and decide for each whether it should
641 : // be saved, or split + saved
642 0 : SwRedlineTbl& rRedlineTable = const_cast<SwRedlineTbl&>( pDoc->getIDocumentRedlineAccess().GetRedlineTbl() );
643 0 : for( ; nCurrentRedline < rRedlineTable.size(); nCurrentRedline++ )
644 : {
645 0 : SwRangeRedline* pCurrent = rRedlineTable[ nCurrentRedline ];
646 : SwComparePosition eCompare =
647 0 : ComparePosition( *pCurrent->Start(), *pCurrent->End(),
648 0 : *pStart, *pEnd);
649 :
650 : // we must save this redline if it overlaps aPam
651 : // (we may have to split it, too)
652 0 : if( eCompare == POS_OVERLAP_BEHIND ||
653 0 : eCompare == POS_OVERLAP_BEFORE ||
654 0 : eCompare == POS_OUTSIDE ||
655 0 : eCompare == POS_INSIDE ||
656 : eCompare == POS_EQUAL )
657 : {
658 0 : rRedlineTable.Remove( nCurrentRedline-- );
659 :
660 : // split beginning, if necessary
661 0 : if( eCompare == POS_OVERLAP_BEFORE ||
662 : eCompare == POS_OUTSIDE )
663 : {
664 0 : SwRangeRedline* pNewRedline = new SwRangeRedline( *pCurrent );
665 0 : *pNewRedline->End() = *pStart;
666 0 : *pCurrent->Start() = *pStart;
667 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( pNewRedline, true );
668 : }
669 :
670 : // split end, if necessary
671 0 : if( eCompare == POS_OVERLAP_BEHIND ||
672 : eCompare == POS_OUTSIDE )
673 : {
674 0 : SwRangeRedline* pNewRedline = new SwRangeRedline( *pCurrent );
675 0 : *pNewRedline->Start() = *pEnd;
676 0 : *pCurrent->End() = *pEnd;
677 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( pNewRedline, true );
678 : }
679 :
680 : // save the current redline
681 0 : _SaveRedline* pSave = new _SaveRedline( pCurrent, *pStart );
682 0 : rArr.push_back( pSave );
683 : }
684 : }
685 :
686 : // restore old redline mode
687 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
688 0 : }
689 :
690 0 : static void lcl_RestoreRedlines( SwDoc* pDoc, const SwPosition& rPos, _SaveRedlines& rArr )
691 : {
692 0 : RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode();
693 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
694 :
695 0 : for( size_t n = 0; n < rArr.size(); ++n )
696 : {
697 0 : rArr[ n ].SetPos( rPos );
698 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( rArr[ n ].pRedl, true );
699 : }
700 :
701 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
702 0 : }
703 :
704 0 : static void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
705 : {
706 0 : SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
707 : sal_uInt16 nRedlPos;
708 0 : SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
709 0 : aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
710 0 : if( pDoc->getIDocumentRedlineAccess().GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
711 0 : --nRedlPos;
712 0 : else if( nRedlPos >= pDoc->getIDocumentRedlineAccess().GetRedlineTbl().size() )
713 0 : return ;
714 :
715 0 : RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode();
716 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
717 0 : SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->getIDocumentRedlineAccess().GetRedlineTbl();
718 :
719 0 : do {
720 0 : SwRangeRedline* pTmp = rRedlTbl[ nRedlPos ];
721 :
722 0 : const SwPosition* pRStt = pTmp->Start(),
723 0 : * pREnd = pTmp->GetMark() == pRStt
724 0 : ? pTmp->GetPoint() : pTmp->GetMark();
725 :
726 0 : if( pRStt->nNode < rRg.aStart )
727 : {
728 0 : if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
729 : {
730 : // Create a copy and set the end of the original to the end of the MoveArea.
731 : // The copy is moved too.
732 0 : SwRangeRedline* pNewRedl = new SwRangeRedline( *pTmp );
733 0 : SwPosition* pTmpPos = pNewRedl->Start();
734 0 : pTmpPos->nNode = rRg.aStart;
735 : pTmpPos->nContent.Assign(
736 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
737 :
738 0 : _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
739 0 : rArr.push_back( pSave );
740 :
741 0 : pTmpPos = pTmp->End();
742 0 : pTmpPos->nNode = rRg.aEnd;
743 : pTmpPos->nContent.Assign(
744 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
745 : }
746 0 : else if( pREnd->nNode == rRg.aStart )
747 : {
748 0 : SwPosition* pTmpPos = pTmp->End();
749 0 : pTmpPos->nNode = rRg.aEnd;
750 : pTmpPos->nContent.Assign(
751 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
752 : }
753 : }
754 0 : else if( pRStt->nNode < rRg.aEnd )
755 : {
756 0 : rRedlTbl.Remove( nRedlPos-- );
757 0 : if( pREnd->nNode < rRg.aEnd ||
758 0 : ( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
759 : {
760 : // move everything
761 0 : _SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
762 0 : rArr.push_back( pSave );
763 : }
764 : else
765 : {
766 : // split
767 0 : SwRangeRedline* pNewRedl = new SwRangeRedline( *pTmp );
768 0 : SwPosition* pTmpPos = pNewRedl->End();
769 0 : pTmpPos->nNode = rRg.aEnd;
770 : pTmpPos->nContent.Assign(
771 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
772 :
773 0 : _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
774 0 : rArr.push_back( pSave );
775 :
776 0 : pTmpPos = pTmp->Start();
777 0 : pTmpPos->nNode = rRg.aEnd;
778 : pTmpPos->nContent.Assign(
779 0 : pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
780 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( pTmp, true );
781 : }
782 : }
783 : else
784 0 : break;
785 :
786 0 : } while( ++nRedlPos < pDoc->getIDocumentRedlineAccess().GetRedlineTbl().size() );
787 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
788 : }
789 :
790 0 : static void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
791 : {
792 0 : RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode();
793 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
794 :
795 0 : for( size_t n = 0; n < rArr.size(); ++n )
796 : {
797 0 : rArr[ n ].SetPos( nInsPos );
798 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( rArr[ n ].pRedl, true );
799 : }
800 :
801 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
802 0 : }
803 :
804 144 : static bool lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
805 : const SwNodeIndex& rInsPos,
806 : SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
807 : const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
808 : {
809 144 : bool bUpdateFtn = false;
810 144 : const SwNodes& rNds = rInsPos.GetNodes();
811 144 : const bool bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
812 144 : rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
813 288 : const bool bSaveFtn = !bDelFtn &&
814 288 : rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
815 144 : if( !rFtnArr.empty() )
816 : {
817 :
818 0 : size_t nPos = 0;
819 0 : rFtnArr.SeekEntry( rSttNd, &nPos );
820 : SwTxtFtn* pSrch;
821 : const SwNode* pFtnNd;
822 :
823 : // Delete/save all that come after it
824 0 : while( nPos < rFtnArr.size() && ( pFtnNd =
825 0 : &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
826 0 : <= rEndNd.GetIndex() )
827 : {
828 0 : const sal_Int32 nFtnSttIdx = pSrch->GetStart();
829 0 : if( ( pEndCnt && pSttCnt )
830 0 : ? (( &rSttNd.GetNode() == pFtnNd &&
831 0 : pSttCnt->GetIndex() > nFtnSttIdx) ||
832 0 : ( &rEndNd.GetNode() == pFtnNd &&
833 0 : nFtnSttIdx >= pEndCnt->GetIndex() ))
834 0 : : ( &rEndNd.GetNode() == pFtnNd ))
835 : {
836 0 : ++nPos; // continue searching
837 : }
838 : else
839 : {
840 : // delete it
841 0 : if( bDelFtn )
842 : {
843 0 : SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
844 0 : SwIndex aIdx( &rTxtNd, nFtnSttIdx );
845 0 : rTxtNd.EraseText( aIdx, 1 );
846 : }
847 : else
848 : {
849 0 : pSrch->DelFrms(0);
850 0 : rFtnArr.erase( rFtnArr.begin() + nPos );
851 0 : if( bSaveFtn )
852 0 : rSaveArr.insert( pSrch );
853 : }
854 0 : bUpdateFtn = true;
855 : }
856 : }
857 :
858 0 : while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
859 0 : GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
860 : {
861 0 : const sal_Int32 nFtnSttIdx = pSrch->GetStart();
862 0 : if( !pEndCnt || !pSttCnt ||
863 0 : !( (( &rSttNd.GetNode() == pFtnNd &&
864 0 : pSttCnt->GetIndex() > nFtnSttIdx ) ||
865 0 : ( &rEndNd.GetNode() == pFtnNd &&
866 0 : nFtnSttIdx >= pEndCnt->GetIndex() )) ))
867 : {
868 0 : if( bDelFtn )
869 : {
870 : // delete it
871 0 : SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
872 0 : SwIndex aIdx( &rTxtNd, nFtnSttIdx );
873 0 : rTxtNd.EraseText( aIdx, 1 );
874 : }
875 : else
876 : {
877 0 : pSrch->DelFrms(0);
878 0 : rFtnArr.erase( rFtnArr.begin() + nPos );
879 0 : if( bSaveFtn )
880 0 : rSaveArr.insert( pSrch );
881 : }
882 0 : bUpdateFtn = true;
883 : }
884 : }
885 : }
886 : // When moving from redline section into document content section, e.g.
887 : // after loading a document with (delete-)redlines, the footnote array
888 : // has to be adjusted... (#i70572)
889 144 : if( bSaveFtn )
890 : {
891 144 : SwNodeIndex aIdx( rSttNd );
892 426 : while( aIdx < rEndNd ) // Check the moved section
893 : {
894 138 : SwNode* pNode = &aIdx.GetNode();
895 138 : if( pNode->IsTxtNode() ) // Looking for text nodes...
896 : {
897 : SwpHints *pHints =
898 138 : static_cast<SwTxtNode*>(pNode)->GetpSwpHints();
899 138 : if( pHints && pHints->HasFtn() ) //...with footnotes
900 : {
901 0 : bUpdateFtn = true; // Heureka
902 0 : const size_t nCount = pHints->Count();
903 0 : for( size_t i = 0; i < nCount; ++i )
904 : {
905 0 : SwTxtAttr *pAttr = pHints->GetTextHint( i );
906 0 : if ( pAttr->Which() == RES_TXTATR_FTN )
907 : {
908 0 : rSaveArr.insert( static_cast<SwTxtFtn*>(pAttr) );
909 : }
910 : }
911 : }
912 : }
913 138 : ++aIdx;
914 144 : }
915 : }
916 144 : return bUpdateFtn;
917 : }
918 :
919 0 : static bool lcl_MayOverwrite( const SwTxtNode *pNode, const sal_Int32 nPos )
920 : {
921 0 : sal_Unicode const cChr = pNode->GetTxt()[nPos];
922 0 : switch (cChr)
923 : {
924 : case CH_TXTATR_BREAKWORD:
925 : case CH_TXTATR_INWORD:
926 0 : return !pNode->GetTxtAttrForCharAt(nPos);// how could there be none?
927 : case CH_TXT_ATR_FIELDSTART:
928 : case CH_TXT_ATR_FIELDEND:
929 : case CH_TXT_ATR_FORMELEMENT:
930 0 : return false;
931 : default:
932 0 : return true;
933 : }
934 : }
935 :
936 0 : static void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, sal_Int32 &rStart )
937 : {
938 0 : if( !lcl_MayOverwrite( pNode, rStart ) )
939 : {
940 : // skip all special attributes
941 0 : do {
942 0 : ++rIdx;
943 0 : rStart = rIdx.GetIndex();
944 0 : } while (rStart < pNode->GetTxt().getLength()
945 0 : && !lcl_MayOverwrite(pNode, rStart) );
946 : }
947 0 : }
948 :
949 92 : static bool lcl_GetTokenToParaBreak( OUString& rStr, OUString& rRet, bool bRegExpRplc )
950 : {
951 92 : if( bRegExpRplc )
952 : {
953 0 : sal_Int32 nPos = 0;
954 0 : const OUString sPara("\\n");
955 : for (;;)
956 : {
957 0 : nPos = rStr.indexOf( sPara, nPos );
958 0 : if (nPos<0)
959 : {
960 0 : break;
961 : }
962 : // Has this been escaped?
963 0 : if( nPos && '\\' == rStr[nPos-1])
964 : {
965 0 : ++nPos;
966 0 : if( nPos >= rStr.getLength() )
967 : {
968 0 : break;
969 : }
970 : }
971 : else
972 : {
973 0 : rRet = rStr.copy( 0, nPos );
974 0 : rStr = rStr.copy( nPos + sPara.getLength() );
975 0 : return true;
976 : }
977 0 : }
978 : }
979 92 : rRet = rStr;
980 92 : rStr = OUString();
981 92 : return false;
982 : }
983 : }
984 :
985 : namespace //local functions originally from docfmt.cxx
986 : {
987 : #define DELETECHARSETS if ( bDelete ) { delete pCharSet; delete pOtherSet; }
988 :
989 : /// Insert Hints according to content types;
990 : // Is used in SwDoc::Insert(..., SwFmtHint &rHt)
991 :
992 244696 : static bool lcl_InsAttr(
993 : SwDoc *const pDoc,
994 : const SwPaM &rRg,
995 : const SfxItemSet& rChgSet,
996 : const SetAttrMode nFlags,
997 : SwUndoAttr *const pUndo,
998 : const bool bExpandCharToPara=false)
999 : {
1000 : // Divide the Sets (for selections in Nodes)
1001 244696 : const SfxItemSet* pCharSet = 0;
1002 244696 : const SfxItemSet* pOtherSet = 0;
1003 244696 : bool bDelete = false;
1004 244696 : bool bCharAttr = false;
1005 244696 : bool bOtherAttr = false;
1006 :
1007 : // Check, if we can work with rChgSet or if we have to create additional SfxItemSets
1008 244696 : if ( 1 == rChgSet.Count() )
1009 : {
1010 117922 : SfxItemIter aIter( rChgSet );
1011 117922 : const SfxPoolItem* pItem = aIter.FirstItem();
1012 117922 : if (!IsInvalidItem(pItem))
1013 : {
1014 117922 : const sal_uInt16 nWhich = pItem->Which();
1015 :
1016 297468 : if ( isCHRATR(nWhich) ||
1017 52622 : (RES_TXTATR_CHARFMT == nWhich) ||
1018 49846 : (RES_TXTATR_INETFMT == nWhich) ||
1019 161084 : (RES_TXTATR_AUTOFMT == nWhich) ||
1020 : (RES_TXTATR_UNKNOWN_CONTAINER == nWhich) )
1021 : {
1022 74806 : pCharSet = &rChgSet;
1023 74806 : bCharAttr = true;
1024 : }
1025 :
1026 235844 : if ( isPARATR(nWhich)
1027 97742 : || isPARATR_LIST(nWhich)
1028 97742 : || isFRMATR(nWhich)
1029 77984 : || isGRFATR(nWhich)
1030 77984 : || isUNKNOWNATR(nWhich)
1031 195906 : || isDrawingLayerAttribute(nWhich) ) //UUUU
1032 : {
1033 39938 : pOtherSet = &rChgSet;
1034 39938 : bOtherAttr = true;
1035 : }
1036 117922 : }
1037 : }
1038 :
1039 : // Build new itemset if either
1040 : // - rChgSet.Count() > 1 or
1041 : // - The attribute in rChgSet does not belong to one of the above categories
1042 244696 : if ( !bCharAttr && !bOtherAttr )
1043 : {
1044 129952 : SfxItemSet* pTmpCharItemSet = new SfxItemSet( pDoc->GetAttrPool(),
1045 : RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1046 : RES_TXTATR_AUTOFMT, RES_TXTATR_AUTOFMT,
1047 : RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1048 : RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1049 : RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
1050 129952 : 0 );
1051 :
1052 129952 : SfxItemSet* pTmpOtherItemSet = new SfxItemSet( pDoc->GetAttrPool(),
1053 : RES_PARATR_BEGIN, RES_PARATR_END-1,
1054 : RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
1055 : RES_FRMATR_BEGIN, RES_FRMATR_END-1,
1056 : RES_GRFATR_BEGIN, RES_GRFATR_END-1,
1057 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1058 :
1059 : //UUUU FillAttribute support
1060 : XATTR_FILL_FIRST, XATTR_FILL_LAST,
1061 :
1062 129952 : 0 );
1063 :
1064 129952 : pTmpCharItemSet->Put( rChgSet );
1065 129952 : pTmpOtherItemSet->Put( rChgSet );
1066 :
1067 129952 : pCharSet = pTmpCharItemSet;
1068 129952 : pOtherSet = pTmpOtherItemSet;
1069 :
1070 129952 : bDelete = true;
1071 : }
1072 :
1073 244696 : SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
1074 244696 : bool bRet = false;
1075 244696 : const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
1076 244696 : SwCntntNode* pNode = pStt->nNode.GetNode().GetCntntNode();
1077 :
1078 244696 : if( pNode && pNode->IsTxtNode() )
1079 : {
1080 : // #i27615#
1081 244696 : if (rRg.IsInFrontOfLabel())
1082 : {
1083 0 : SwTxtNode * pTxtNd = pNode->GetTxtNode();
1084 0 : SwNumRule * pNumRule = pTxtNd->GetNumRule();
1085 :
1086 0 : if ( !pNumRule )
1087 : {
1088 : OSL_FAIL( "<InsAttr(..)> - PaM in front of label, but text node has no numbering rule set. This is a serious defect, please inform OD." );
1089 0 : DELETECHARSETS
1090 0 : return false;
1091 : }
1092 :
1093 0 : int nLevel = pTxtNd->GetActualListLevel();
1094 :
1095 0 : if (nLevel < 0)
1096 0 : nLevel = 0;
1097 :
1098 0 : if (nLevel >= MAXLEVEL)
1099 0 : nLevel = MAXLEVEL - 1;
1100 :
1101 0 : SwNumFmt aNumFmt = pNumRule->Get(static_cast<sal_uInt16>(nLevel));
1102 : SwCharFmt * pCharFmt =
1103 0 : pDoc->FindCharFmtByName(aNumFmt.GetCharFmtName());
1104 :
1105 0 : if (pCharFmt)
1106 : {
1107 0 : if (pHistory)
1108 0 : pHistory->Add(pCharFmt->GetAttrSet(), *pCharFmt);
1109 :
1110 0 : if ( pCharSet )
1111 0 : pCharFmt->SetFmtAttr(*pCharSet);
1112 : }
1113 :
1114 0 : DELETECHARSETS
1115 0 : return true;
1116 : }
1117 :
1118 244696 : const SwIndex& rSt = pStt->nContent;
1119 :
1120 : // Attributes without an end do not have a range
1121 244696 : if ( !bCharAttr && !bOtherAttr )
1122 : {
1123 129952 : SfxItemSet aTxtSet( pDoc->GetAttrPool(),
1124 129952 : RES_TXTATR_NOEND_BEGIN, RES_TXTATR_NOEND_END-1 );
1125 129952 : aTxtSet.Put( rChgSet );
1126 129952 : if( aTxtSet.Count() )
1127 : {
1128 2238 : SwRegHistory history( pNode, *pNode, pHistory );
1129 : bRet = history.InsertItems(
1130 2238 : aTxtSet, rSt.GetIndex(), rSt.GetIndex(), nFlags ) || bRet;
1131 :
1132 2248 : if (bRet && (pDoc->getIDocumentRedlineAccess().IsRedlineOn() || (!pDoc->getIDocumentRedlineAccess().IsIgnoreRedline()
1133 2238 : && !pDoc->getIDocumentRedlineAccess().GetRedlineTbl().empty())))
1134 : {
1135 10 : SwPaM aPam( pStt->nNode, pStt->nContent.GetIndex()-1,
1136 20 : pStt->nNode, pStt->nContent.GetIndex() );
1137 :
1138 10 : if( pUndo )
1139 0 : pUndo->SaveRedlineData( aPam, true );
1140 :
1141 10 : if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
1142 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
1143 : else
1144 10 : pDoc->getIDocumentRedlineAccess().SplitRedline( aPam );
1145 2238 : }
1146 129952 : }
1147 : }
1148 :
1149 : // TextAttributes with an end never expand their range
1150 244696 : if ( !bCharAttr && !bOtherAttr )
1151 : {
1152 : // CharFmt and URL attributes are treated separately!
1153 : // TEST_TEMP ToDo: AutoFmt!
1154 129952 : SfxItemSet aTxtSet( pDoc->GetAttrPool(),
1155 : RES_TXTATR_REFMARK, RES_TXTATR_TOXMARK,
1156 : RES_TXTATR_META, RES_TXTATR_METAFIELD,
1157 : RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
1158 : RES_TXTATR_INPUTFIELD, RES_TXTATR_INPUTFIELD,
1159 129952 : 0 );
1160 :
1161 129952 : aTxtSet.Put( rChgSet );
1162 129952 : if( aTxtSet.Count() )
1163 : {
1164 940 : const sal_Int32 nInsCnt = rSt.GetIndex();
1165 940 : const sal_Int32 nEnd = pStt->nNode == pEnd->nNode
1166 940 : ? pEnd->nContent.GetIndex()
1167 1880 : : pNode->Len();
1168 940 : SwRegHistory history( pNode, *pNode, pHistory );
1169 940 : bRet = history.InsertItems( aTxtSet, nInsCnt, nEnd, nFlags )
1170 940 : || bRet;
1171 :
1172 940 : if (bRet && (pDoc->getIDocumentRedlineAccess().IsRedlineOn() || (!pDoc->getIDocumentRedlineAccess().IsIgnoreRedline()
1173 936 : && !pDoc->getIDocumentRedlineAccess().GetRedlineTbl().empty())))
1174 : {
1175 : // Was text content inserted? (RefMark/TOXMarks without an end)
1176 0 : bool bTxtIns = nInsCnt != rSt.GetIndex();
1177 : // Was content inserted or set over the selection?
1178 : SwPaM aPam( pStt->nNode, bTxtIns ? nInsCnt + 1 : nEnd,
1179 0 : pStt->nNode, nInsCnt );
1180 0 : if( pUndo )
1181 0 : pUndo->SaveRedlineData( aPam, bTxtIns );
1182 :
1183 0 : if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
1184 0 : pDoc->getIDocumentRedlineAccess().AppendRedline(
1185 : new SwRangeRedline(
1186 0 : bTxtIns ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_FORMAT, aPam ),
1187 0 : true);
1188 0 : else if( bTxtIns )
1189 0 : pDoc->getIDocumentRedlineAccess().SplitRedline( aPam );
1190 940 : }
1191 129952 : }
1192 : }
1193 : }
1194 :
1195 : // We always have to set the auto flag for PageDescs that are set at the Node!
1196 244696 : if( pOtherSet && pOtherSet->Count() )
1197 : {
1198 : SwTableNode* pTblNd;
1199 : const SwFmtPageDesc* pDesc;
1200 78546 : if( SfxItemState::SET == pOtherSet->GetItemState( RES_PAGEDESC,
1201 78546 : false, (const SfxPoolItem**)&pDesc ))
1202 : {
1203 4426 : if( pNode )
1204 : {
1205 : // Set auto flag. Only in the template it's without auto!
1206 4426 : SwFmtPageDesc aNew( *pDesc );
1207 :
1208 : // Tables now also know line breaks
1209 4646 : if( 0 == (nFlags & nsSetAttrMode::SETATTR_APICALL) &&
1210 220 : 0 != ( pTblNd = pNode->FindTableNode() ) )
1211 : {
1212 0 : SwTableNode* pCurTblNd = pTblNd;
1213 0 : while ( 0 != ( pCurTblNd = pCurTblNd->StartOfSectionNode()->FindTableNode() ) )
1214 0 : pTblNd = pCurTblNd;
1215 :
1216 : // set the table format
1217 0 : SwFrmFmt* pFmt = pTblNd->GetTable().GetFrmFmt();
1218 0 : SwRegHistory aRegH( pFmt, *pTblNd, pHistory );
1219 0 : pFmt->SetFmtAttr( aNew );
1220 0 : bRet = true;
1221 : }
1222 : else
1223 : {
1224 4426 : SwRegHistory aRegH( pNode, *pNode, pHistory );
1225 4426 : bRet = pNode->SetAttr( aNew ) || bRet;
1226 4426 : }
1227 : }
1228 :
1229 : // bOtherAttr = true means that pOtherSet == rChgSet. In this case
1230 : // we know, that there is only one attribute in pOtherSet. We cannot
1231 : // perform the following operations, instead we return:
1232 4426 : if ( bOtherAttr )
1233 8852 : return bRet;
1234 :
1235 0 : const_cast<SfxItemSet*>(pOtherSet)->ClearItem( RES_PAGEDESC );
1236 0 : if( !pOtherSet->Count() )
1237 : {
1238 0 : DELETECHARSETS
1239 0 : return bRet;
1240 : }
1241 : }
1242 :
1243 : // Tables now also know line breaks
1244 : const SvxFmtBreakItem* pBreak;
1245 155656 : if( pNode && 0 == (nFlags & nsSetAttrMode::SETATTR_APICALL) &&
1246 84894 : 0 != (pTblNd = pNode->FindTableNode() ) &&
1247 : SfxItemState::SET == pOtherSet->GetItemState( RES_BREAK,
1248 3358 : false, (const SfxPoolItem**)&pBreak ) )
1249 : {
1250 0 : SwTableNode* pCurTblNd = pTblNd;
1251 0 : while ( 0 != ( pCurTblNd = pCurTblNd->StartOfSectionNode()->FindTableNode() ) )
1252 0 : pTblNd = pCurTblNd;
1253 :
1254 : // set the table format
1255 0 : SwFrmFmt* pFmt = pTblNd->GetTable().GetFrmFmt();
1256 0 : SwRegHistory aRegH( pFmt, *pTblNd, pHistory );
1257 0 : pFmt->SetFmtAttr( *pBreak );
1258 0 : bRet = true;
1259 :
1260 : // bOtherAttr = true means that pOtherSet == rChgSet. In this case
1261 : // we know, that there is only one attribute in pOtherSet. We cannot
1262 : // perform the following operations, instead we return:
1263 0 : if ( bOtherAttr )
1264 0 : return bRet;
1265 :
1266 0 : const_cast<SfxItemSet*>(pOtherSet)->ClearItem( RES_BREAK );
1267 0 : if( !pOtherSet->Count() )
1268 : {
1269 0 : DELETECHARSETS
1270 0 : return bRet;
1271 0 : }
1272 : }
1273 :
1274 : {
1275 : // If we have a PoolNumRule, create it if needed
1276 : const SwNumRuleItem* pRule;
1277 74120 : sal_uInt16 nPoolId=0;
1278 74120 : if( SfxItemState::SET == pOtherSet->GetItemState( RES_PARATR_NUMRULE,
1279 77316 : false, (const SfxPoolItem**)&pRule ) &&
1280 74626 : !pDoc->FindNumRulePtr( pRule->GetValue() ) &&
1281 506 : USHRT_MAX != (nPoolId = SwStyleNameMapper::GetPoolIdFromUIName ( pRule->GetValue(),
1282 : nsSwGetPoolIdFromName::GET_POOLID_NUMRULE )) )
1283 0 : pDoc->getIDocumentStylePoolAccess().GetNumRuleFromPool( nPoolId );
1284 : }
1285 : }
1286 :
1287 240270 : if( !rRg.HasMark() ) // no range
1288 : {
1289 86940 : if( !pNode )
1290 : {
1291 0 : DELETECHARSETS
1292 0 : return bRet;
1293 : }
1294 :
1295 86940 : if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
1296 : {
1297 52998 : SwTxtNode* pTxtNd = static_cast<SwTxtNode*>(pNode);
1298 52998 : const SwIndex& rSt = pStt->nContent;
1299 52998 : sal_Int32 nMkPos, nPtPos = rSt.GetIndex();
1300 52998 : const OUString& rStr = pTxtNd->GetTxt();
1301 :
1302 : // Special case: if the Crsr is located within a URL attribute, we take over it's area
1303 : SwTxtAttr const*const pURLAttr(
1304 52998 : pTxtNd->GetTxtAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
1305 52998 : if (pURLAttr && !pURLAttr->GetINetFmt().GetValue().isEmpty())
1306 : {
1307 22 : nMkPos = pURLAttr->GetStart();
1308 22 : nPtPos = *pURLAttr->End();
1309 : }
1310 : else
1311 : {
1312 52976 : Boundary aBndry;
1313 52976 : if( g_pBreakIt->GetBreakIter().is() )
1314 105952 : aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary(
1315 52976 : pTxtNd->GetTxt(), nPtPos,
1316 52976 : g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1317 : WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
1318 105952 : sal_True );
1319 :
1320 52976 : if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
1321 : {
1322 0 : nMkPos = aBndry.startPos;
1323 0 : nPtPos = aBndry.endPos;
1324 : }
1325 : else
1326 52976 : nPtPos = nMkPos = rSt.GetIndex();
1327 : }
1328 :
1329 : // Remove the overriding attributes from the SwpHintsArray,
1330 : // if the selection spans across the whole paragraph.
1331 : // These attributes are inserted as FormatAttributes and
1332 : // never override the TextAttributes!
1333 158994 : if( !(nFlags & nsSetAttrMode::SETATTR_DONTREPLACE ) &&
1334 91110 : pTxtNd->HasHints() && !nMkPos && nPtPos == rStr.getLength())
1335 : {
1336 22 : SwIndex aSt( pTxtNd );
1337 22 : if( pHistory )
1338 : {
1339 : // Save all attributes for the Undo.
1340 22 : SwRegHistory aRHst( *pTxtNd, pHistory );
1341 22 : pTxtNd->GetpSwpHints()->Register( &aRHst );
1342 22 : pTxtNd->RstTxtAttr( aSt, nPtPos, 0, pCharSet );
1343 22 : if( pTxtNd->GetpSwpHints() )
1344 22 : pTxtNd->GetpSwpHints()->DeRegister();
1345 : }
1346 : else
1347 0 : pTxtNd->RstTxtAttr( aSt, nPtPos, 0, pCharSet );
1348 : }
1349 :
1350 : // the SwRegHistory inserts the attribute into the TxtNode!
1351 52998 : SwRegHistory history( pNode, *pNode, pHistory );
1352 52998 : bRet = history.InsertItems( *pCharSet, nMkPos, nPtPos, nFlags )
1353 52998 : || bRet;
1354 :
1355 52998 : if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
1356 : {
1357 0 : SwPaM aPam( *pNode, nMkPos, *pNode, nPtPos );
1358 :
1359 0 : if( pUndo )
1360 0 : pUndo->SaveRedlineData( aPam, false );
1361 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_FORMAT, aPam ), true);
1362 52998 : }
1363 : }
1364 86940 : if( pOtherSet && pOtherSet->Count() )
1365 : {
1366 44998 : SwRegHistory aRegH( pNode, *pNode, pHistory );
1367 :
1368 : //UUUU Need to check for unique item for DrawingLayer items of type NameOrIndex
1369 : // and evtl. correct that item to ensure unique names for that type. This call may
1370 : // modify/correct entries inside of the given SfxItemSet
1371 89996 : SfxItemSet aTempLocalCopy(*pOtherSet);
1372 :
1373 44998 : pDoc->CheckForUniqueItemForLineFillNameOrIndex(aTempLocalCopy);
1374 89996 : bRet = pNode->SetAttr(aTempLocalCopy) || bRet;
1375 : }
1376 :
1377 86940 : DELETECHARSETS
1378 86940 : return bRet;
1379 : }
1380 :
1381 153330 : if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() && pCharSet && pCharSet->Count() )
1382 : {
1383 0 : if( pUndo )
1384 0 : pUndo->SaveRedlineData( rRg, false );
1385 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_FORMAT, rRg ), true);
1386 : }
1387 :
1388 : /* now if range */
1389 153330 : sal_uLong nNodes = 0;
1390 :
1391 153330 : SwNodeIndex aSt( pDoc->GetNodes() );
1392 306660 : SwNodeIndex aEnd( pDoc->GetNodes() );
1393 306660 : SwIndex aCntEnd( pEnd->nContent );
1394 :
1395 153330 : if( pNode )
1396 : {
1397 153330 : const sal_Int32 nLen = pNode->Len();
1398 153330 : if( pStt->nNode != pEnd->nNode )
1399 12060 : aCntEnd.Assign( pNode, nLen );
1400 :
1401 153330 : if( pStt->nContent.GetIndex() != 0 || aCntEnd.GetIndex() != nLen )
1402 : {
1403 : // the SwRegHistory inserts the attribute into the TxtNode!
1404 71860 : if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
1405 : {
1406 70794 : SwRegHistory history( pNode, *pNode, pHistory );
1407 : bRet = history.InsertItems(*pCharSet,
1408 70794 : pStt->nContent.GetIndex(), aCntEnd.GetIndex(), nFlags)
1409 70794 : || bRet;
1410 : }
1411 :
1412 71860 : if( pOtherSet && pOtherSet->Count() )
1413 : {
1414 1490 : SwRegHistory aRegH( pNode, *pNode, pHistory );
1415 1490 : bRet = pNode->SetAttr( *pOtherSet ) || bRet;
1416 : }
1417 :
1418 : // Only selection in a Node.
1419 71860 : if( pStt->nNode == pEnd->nNode )
1420 : {
1421 : //The data parameter flag: bExpandCharToPara, comes from the data member of SwDoc,
1422 : //Which is set in SW MS word Binary filter WW8ImplRreader. With this flag on, means that
1423 : //current setting attribute set is a character range properties set and comes from a MS word
1424 : //binary file, And the setting range include a paragraph end position (0X0D);
1425 : //More specifications, as such property inside the character range properties set recorded in
1426 : //MS word binary file are dealed and inserted into data model (SwDoc) one by one, so we
1427 : //only dealing the scenario that the char properties set with 1 item inside;
1428 :
1429 65942 : if (bExpandCharToPara && pCharSet && pCharSet->Count() ==1 )
1430 : {
1431 966 : SwTxtNode* pCurrentNd = pStt->nNode.GetNode().GetTxtNode();
1432 :
1433 966 : if (pCurrentNd)
1434 : {
1435 966 : pCurrentNd->TryCharSetExpandToNum(*pCharSet);
1436 :
1437 : }
1438 : }
1439 65942 : DELETECHARSETS
1440 65942 : return bRet;
1441 : }
1442 5918 : ++nNodes;
1443 5918 : aSt.Assign( pStt->nNode.GetNode(), +1 );
1444 : }
1445 : else
1446 81470 : aSt = pStt->nNode;
1447 87388 : aCntEnd = pEnd->nContent; // aEnd was changed!
1448 : }
1449 : else
1450 0 : aSt.Assign( pStt->nNode.GetNode(), +1 );
1451 :
1452 : // aSt points to the first full Node now
1453 :
1454 : /*
1455 : * The selection spans more than one Node.
1456 : */
1457 87388 : if( pStt->nNode < pEnd->nNode )
1458 : {
1459 12060 : pNode = pEnd->nNode.GetNode().GetCntntNode();
1460 12060 : if(pNode)
1461 : {
1462 12060 : if( aCntEnd.GetIndex() != pNode->Len() )
1463 : {
1464 : // the SwRegHistory inserts the attribute into the TxtNode!
1465 6120 : if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
1466 : {
1467 6074 : SwRegHistory history( pNode, *pNode, pHistory );
1468 : (void)history.InsertItems(*pCharSet,
1469 6074 : 0, aCntEnd.GetIndex(), nFlags);
1470 : }
1471 :
1472 6120 : if( pOtherSet && pOtherSet->Count() )
1473 : {
1474 46 : SwRegHistory aRegH( pNode, *pNode, pHistory );
1475 46 : pNode->SetAttr( *pOtherSet );
1476 : }
1477 :
1478 6120 : ++nNodes;
1479 6120 : aEnd = pEnd->nNode;
1480 : }
1481 : else
1482 5940 : aEnd.Assign( pEnd->nNode.GetNode(), +1 );
1483 : }
1484 : else
1485 0 : aEnd = pEnd->nNode;
1486 : }
1487 : else
1488 75328 : aEnd.Assign( pEnd->nNode.GetNode(), +1 );
1489 :
1490 : // aEnd points BEHIND the last full node now
1491 :
1492 : /* Edit the fully selected Nodes. */
1493 : // Reset all attributes from the set!
1494 87388 : if( pCharSet && pCharSet->Count() && !( nsSetAttrMode::SETATTR_DONTREPLACE & nFlags ) )
1495 : {
1496 52788 : ::sw::DocumentContentOperationsManager::ParaRstFmt aPara( pStt, pEnd, pHistory, 0, pCharSet );
1497 52788 : pDoc->GetNodes().ForEach( aSt, aEnd, ::sw::DocumentContentOperationsManager::lcl_RstTxtAttr, &aPara );
1498 : }
1499 :
1500 151360 : bool bCreateSwpHints = pCharSet && (
1501 118012 : SfxItemState::SET == pCharSet->GetItemState( RES_TXTATR_CHARFMT, false ) ||
1502 145420 : SfxItemState::SET == pCharSet->GetItemState( RES_TXTATR_INETFMT, false ) );
1503 :
1504 193764 : for(; aSt < aEnd; ++aSt )
1505 : {
1506 106376 : pNode = aSt.GetNode().GetCntntNode();
1507 106376 : if( !pNode )
1508 12872 : continue;
1509 :
1510 93504 : SwTxtNode* pTNd = pNode->GetTxtNode();
1511 93504 : if( pHistory )
1512 : {
1513 14114 : SwRegHistory aRegH( pNode, *pNode, pHistory );
1514 : SwpHints *pSwpHints;
1515 :
1516 14114 : if( pTNd && pCharSet && pCharSet->Count() )
1517 : {
1518 : pSwpHints = bCreateSwpHints ? &pTNd->GetOrCreateSwpHints()
1519 5740 : : pTNd->GetpSwpHints();
1520 5740 : if( pSwpHints )
1521 986 : pSwpHints->Register( &aRegH );
1522 :
1523 5740 : pTNd->SetAttr(*pCharSet, 0, pTNd->GetTxt().getLength(), nFlags);
1524 5740 : if( pSwpHints )
1525 986 : pSwpHints->DeRegister();
1526 : }
1527 14114 : if( pOtherSet && pOtherSet->Count() )
1528 4118 : pNode->SetAttr( *pOtherSet );
1529 : }
1530 : else
1531 : {
1532 79390 : if( pTNd && pCharSet && pCharSet->Count() )
1533 52134 : pTNd->SetAttr(*pCharSet, 0, pTNd->GetTxt().getLength(), nFlags);
1534 79390 : if( pOtherSet && pOtherSet->Count() )
1535 24600 : pNode->SetAttr( *pOtherSet );
1536 : }
1537 93504 : ++nNodes;
1538 : }
1539 :
1540 : //The data parameter flag: bExpandCharToPara, comes from the data member of SwDoc,
1541 : //Which is set in SW MS word Binary filter WW8ImplRreader. With this flag on, means that
1542 : //current setting attribute set is a character range properties set and comes from a MS word
1543 : //binary file, And the setting range include a paragraph end position (0X0D);
1544 : //More specifications, as such property inside the character range properties set recorded in
1545 : //MS word binary file are dealed and inserted into data model (SwDoc) one by one, so we
1546 : //only dealing the scenario that the char properties set with 1 item inside;
1547 87388 : if (bExpandCharToPara && pCharSet && pCharSet->Count() ==1)
1548 : {
1549 3990 : SwPosition aStartPos (*rRg.Start());
1550 7980 : SwPosition aEndPos (*rRg.End());
1551 :
1552 3990 : if (aEndPos.nNode.GetNode().GetTxtNode() && aEndPos.nContent != aEndPos.nNode.GetNode().GetTxtNode()->Len())
1553 1228 : aEndPos.nNode--;
1554 :
1555 3990 : sal_uLong nStart = aStartPos.nNode.GetIndex();
1556 3990 : sal_uLong nEnd = aEndPos.nNode.GetIndex();
1557 13894 : for(; nStart <= nEnd; ++nStart)
1558 : {
1559 9904 : SwNode* pNd = pDoc->GetNodes()[ nStart ];
1560 9904 : if (!pNd || !pNd->IsTxtNode())
1561 340 : continue;
1562 9564 : SwTxtNode *pCurrentNd = (SwTxtNode*)pNd;
1563 9564 : pCurrentNd->TryCharSetExpandToNum(*pCharSet);
1564 3990 : }
1565 : }
1566 :
1567 87388 : DELETECHARSETS
1568 240718 : return (nNodes != 0) || bRet;
1569 : }
1570 : }
1571 :
1572 : namespace sw
1573 : {
1574 :
1575 5052 : DocumentContentOperationsManager::DocumentContentOperationsManager( SwDoc& i_rSwdoc ) : m_rSwdoc( i_rSwdoc )
1576 : {
1577 5052 : }
1578 :
1579 : // Copy an area into this document or into another document
1580 : bool
1581 406 : DocumentContentOperationsManager::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
1582 : {
1583 406 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
1584 :
1585 406 : SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
1586 406 : bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
1587 :
1588 : // Catch if there's no copy to do
1589 406 : if( !rPam.HasMark() || ( *pStt > *pEnd && !bColumnSel ) )
1590 0 : return false;
1591 :
1592 : // Prevent copying in Flys that are anchored in the area
1593 406 : if( pDoc == &m_rSwdoc )
1594 : {
1595 : // Correct the Start-/EndNode
1596 370 : sal_uLong nStt = pStt->nNode.GetIndex(),
1597 370 : nEnd = pEnd->nNode.GetIndex(),
1598 370 : nDiff = nEnd - nStt +1;
1599 370 : SwNode* pNd = m_rSwdoc.GetNodes()[ nStt ];
1600 370 : if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
1601 2 : ++nStt, --nDiff;
1602 740 : if( (pNd = m_rSwdoc.GetNodes()[ nEnd ])->IsCntntNode() &&
1603 370 : ((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
1604 0 : --nEnd, --nDiff;
1605 738 : if( nDiff &&
1606 368 : lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
1607 : {
1608 0 : return false;
1609 : }
1610 : }
1611 :
1612 406 : SwPaM* pRedlineRange = 0;
1613 822 : if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() ||
1614 810 : (!pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() && !pDoc->getIDocumentRedlineAccess().GetRedlineTbl().empty() ) )
1615 10 : pRedlineRange = new SwPaM( rPos );
1616 :
1617 406 : RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode();
1618 :
1619 406 : bool bRet = false;
1620 :
1621 406 : if( pDoc != &m_rSwdoc )
1622 : { // ordinary copy
1623 36 : bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
1624 : }
1625 964 : else if( ! ( *pStt <= rPos && rPos < *pEnd &&
1626 0 : ( pStt->nNode != pEnd->nNode ||
1627 740 : !pStt->nNode.GetNode().IsTxtNode() )) )
1628 : {
1629 : // Copy to a position outside of the area, or copy a single TextNode
1630 : // Do an ordinary copy
1631 370 : bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
1632 : }
1633 : else
1634 : {
1635 : // Copy the area in itself
1636 : // Special case for handling an area with several nodes,
1637 : // or a single node that is not a TextNode
1638 : OSL_ENSURE( &m_rSwdoc == pDoc, " invalid copy branch!" );
1639 : OSL_FAIL("mst: i thought this could be dead code;"
1640 : "please tell me what you did to get here!");
1641 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
1642 :
1643 : // Then copy the area to the underlying document area
1644 : // (with start/end nodes clamped) and move them to
1645 : // the desired position.
1646 :
1647 0 : SwUndoCpyDoc* pUndo = 0;
1648 : // Save the Undo area
1649 0 : SwPaM aPam( rPos );
1650 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1651 : {
1652 0 : pDoc->GetIDocumentUndoRedo().ClearRedo();
1653 0 : pUndo = new SwUndoCpyDoc( aPam );
1654 : }
1655 :
1656 : {
1657 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
1658 0 : SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
1659 0 : SwNodeIndex( m_rSwdoc.GetNodes().GetEndOfAutotext() ));
1660 0 : aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
1661 : // copy without Frames
1662 0 : pDoc->GetDocumentContentOperationsManager().CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
1663 :
1664 0 : aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
1665 0 : aPam.SetMark();
1666 : SwCntntNode* pNode =
1667 0 : pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
1668 0 : pNode->MakeEndIndex( &aPam.GetMark()->nContent );
1669 :
1670 0 : aPam.GetPoint()->nNode = *aPam.GetNode().StartOfSectionNode();
1671 0 : pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
1672 0 : pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
1673 : // move to desired position
1674 0 : pDoc->getIDocumentContentOperations().MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
1675 :
1676 0 : pNode = aPam.GetCntntNode();
1677 0 : *aPam.GetPoint() = rPos; // Move the cursor for Undo
1678 0 : aPam.SetMark(); // also move the Mark
1679 0 : aPam.DeleteMark(); // But don't mark any area
1680 0 : pDoc->getIDocumentContentOperations().DeleteSection( pNode ); // Delete the area again
1681 : }
1682 :
1683 : // if Undo is enabled, store the insertion range
1684 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1685 : {
1686 0 : pUndo->SetInsertRange( aPam );
1687 0 : pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
1688 : }
1689 :
1690 0 : if( pRedlineRange )
1691 : {
1692 0 : pRedlineRange->SetMark();
1693 0 : *pRedlineRange->GetPoint() = *aPam.GetPoint();
1694 0 : *pRedlineRange->GetMark() = *aPam.GetMark();
1695 : }
1696 :
1697 0 : pDoc->getIDocumentState().SetModified();
1698 0 : bRet = true;
1699 : }
1700 :
1701 406 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
1702 406 : if( pRedlineRange )
1703 : {
1704 10 : if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
1705 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
1706 : else
1707 10 : pDoc->getIDocumentRedlineAccess().SplitRedline( *pRedlineRange );
1708 10 : delete pRedlineRange;
1709 : }
1710 :
1711 406 : return bRet;
1712 : }
1713 :
1714 : /// Delete a full Section of the NodeArray.
1715 : /// The passed Node is located somewhere in the designated Section.
1716 6986 : void DocumentContentOperationsManager::DeleteSection( SwNode *pNode )
1717 : {
1718 : assert(pNode && "Didn't pass a Node.");
1719 :
1720 6986 : SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
1721 6986 : : pNode->StartOfSectionNode();
1722 13972 : SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
1723 :
1724 : // delete all Flys, Bookmarks, ...
1725 6986 : DelFlyInRange( aSttIdx, aEndIdx );
1726 6986 : m_rSwdoc.getIDocumentRedlineAccess().DeleteRedline( *pSttNd, true, USHRT_MAX );
1727 6986 : _DelBookmarks(aSttIdx, aEndIdx);
1728 :
1729 : {
1730 : // move all Crsr/StkCrsr/UnoCrsr out of the to-be-deleted area
1731 6986 : SwNodeIndex aMvStt( aSttIdx, 1 );
1732 6986 : m_rSwdoc.CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), true );
1733 : }
1734 :
1735 13972 : m_rSwdoc.GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
1736 6986 : }
1737 :
1738 870 : bool DocumentContentOperationsManager::DeleteRange( SwPaM & rPam )
1739 : {
1740 870 : return lcl_DoWithBreaks( *this, rPam, &DocumentContentOperationsManager::DeleteRangeImpl );
1741 : }
1742 :
1743 5955 : bool DocumentContentOperationsManager::DelFullPara( SwPaM& rPam )
1744 : {
1745 5955 : const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
1746 5955 : const SwNode* pNd = &rStt.nNode.GetNode();
1747 5955 : sal_uInt32 nSectDiff = pNd->StartOfSectionNode()->EndOfSectionIndex() -
1748 5955 : pNd->StartOfSectionIndex();
1749 5955 : sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
1750 :
1751 11019 : if ( nSectDiff-2 <= nNodeDiff || m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() ||
1752 : /* #i9185# Prevent getting the node after the end node (see below) */
1753 5064 : rEnd.nNode.GetIndex() + 1 == m_rSwdoc.GetNodes().Count() )
1754 : {
1755 891 : return false;
1756 : }
1757 :
1758 : // Move hard page brakes to the following Node.
1759 5064 : bool bSavePageBreak = false, bSavePageDesc = false;
1760 :
1761 : /* #i9185# This whould lead to a segmentation fault if not caught above. */
1762 5064 : sal_uLong nNextNd = rEnd.nNode.GetIndex() + 1;
1763 5064 : SwTableNode *const pTblNd = m_rSwdoc.GetNodes()[ nNextNd ]->GetTableNode();
1764 :
1765 5064 : if( pTblNd && pNd->IsCntntNode() )
1766 : {
1767 386 : SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
1768 :
1769 : {
1770 : const SfxPoolItem *pItem;
1771 386 : const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
1772 708 : if( pSet && SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC,
1773 322 : false, &pItem ) )
1774 : {
1775 304 : pTableFmt->SetFmtAttr( *pItem );
1776 304 : bSavePageDesc = true;
1777 : }
1778 :
1779 708 : if( pSet && SfxItemState::SET == pSet->GetItemState( RES_BREAK,
1780 322 : false, &pItem ) )
1781 : {
1782 0 : pTableFmt->SetFmtAttr( *pItem );
1783 0 : bSavePageBreak = true;
1784 : }
1785 : }
1786 : }
1787 :
1788 5064 : bool const bDoesUndo = m_rSwdoc.GetIDocumentUndoRedo().DoesUndo();
1789 5064 : if( bDoesUndo )
1790 : {
1791 438 : if( !rPam.HasMark() )
1792 438 : rPam.SetMark();
1793 0 : else if( rPam.GetPoint() == &rStt )
1794 0 : rPam.Exchange();
1795 438 : rPam.GetPoint()->nNode++;
1796 :
1797 438 : SwCntntNode *pTmpNode = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
1798 438 : rPam.GetPoint()->nContent.Assign( pTmpNode, 0 );
1799 438 : bool bGoNext = (0 == pTmpNode);
1800 438 : pTmpNode = rPam.GetMark()->nNode.GetNode().GetCntntNode();
1801 438 : rPam.GetMark()->nContent.Assign( pTmpNode, 0 );
1802 :
1803 438 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo();
1804 :
1805 438 : SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
1806 : {
1807 438 : SwPosition aTmpPos( *aDelPam.GetPoint() );
1808 438 : if( bGoNext )
1809 : {
1810 438 : pTmpNode = m_rSwdoc.GetNodes().GoNext( &aTmpPos.nNode );
1811 438 : aTmpPos.nContent.Assign( pTmpNode, 0 );
1812 : }
1813 438 : ::PaMCorrAbs( aDelPam, aTmpPos );
1814 : }
1815 :
1816 438 : SwUndoDelete* pUndo = new SwUndoDelete( aDelPam, true );
1817 :
1818 438 : *rPam.GetPoint() = *aDelPam.GetPoint();
1819 438 : pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
1820 438 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
1821 : }
1822 : else
1823 : {
1824 4626 : SwNodeRange aRg( rStt.nNode, rEnd.nNode );
1825 4626 : if( rPam.GetPoint() != &rEnd )
1826 0 : rPam.Exchange();
1827 :
1828 : // Try to move past the End
1829 4626 : if( !rPam.Move( fnMoveForward, fnGoNode ) )
1830 : {
1831 : // Fair enough, at the Beginning then
1832 3278 : rPam.Exchange();
1833 3278 : if( !rPam.Move( fnMoveBackward, fnGoNode ))
1834 : {
1835 : OSL_FAIL( "no more Nodes" );
1836 0 : return false;
1837 : }
1838 : }
1839 : // move bookmarks, redlines etc.
1840 4626 : if (aRg.aStart == aRg.aEnd) // only first CorrAbs variant handles this
1841 : {
1842 4626 : m_rSwdoc.CorrAbs( aRg.aStart, *rPam.GetPoint(), 0, true );
1843 : }
1844 : else
1845 : {
1846 0 : m_rSwdoc.CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), true );
1847 : }
1848 :
1849 : // What's with Flys?
1850 : {
1851 : // If there are FlyFrames left, delete these too
1852 17990 : for( size_t n = 0; n < m_rSwdoc.GetSpzFrmFmts()->size(); ++n )
1853 : {
1854 13364 : SwFrmFmt* pFly = (*m_rSwdoc.GetSpzFrmFmts())[n];
1855 13364 : const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
1856 13364 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
1857 26562 : if (pAPos &&
1858 17080 : ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
1859 14474 : (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
1860 31144 : aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
1861 : {
1862 12 : m_rSwdoc.getIDocumentLayoutAccess().DelLayoutFmt( pFly );
1863 12 : --n;
1864 : }
1865 : }
1866 : }
1867 :
1868 4626 : SwCntntNode *pTmpNode = rPam.GetBound( true ).nNode.GetNode().GetCntntNode();
1869 4626 : rPam.GetBound( true ).nContent.Assign( pTmpNode, 0 );
1870 4626 : pTmpNode = rPam.GetBound( false ).nNode.GetNode().GetCntntNode();
1871 4626 : rPam.GetBound( false ).nContent.Assign( pTmpNode, 0 );
1872 4626 : m_rSwdoc.GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
1873 : }
1874 5064 : rPam.DeleteMark();
1875 5064 : m_rSwdoc.getIDocumentState().SetModified();
1876 :
1877 5064 : return true;
1878 : }
1879 :
1880 : // #i100466# Add handling of new optional parameter <bForceJoinNext>
1881 9629 : bool DocumentContentOperationsManager::DeleteAndJoin( SwPaM & rPam,
1882 : const bool bForceJoinNext )
1883 : {
1884 9629 : if ( lcl_StrLenOverflow( rPam ) )
1885 0 : return false;
1886 :
1887 9629 : return lcl_DoWithBreaks( *this, rPam, (m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn())
1888 : ? &DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl
1889 : : &DocumentContentOperationsManager::DeleteAndJoinImpl,
1890 19258 : bForceJoinNext );
1891 : }
1892 :
1893 : // It seems that this is mostly used by SwDoc internals; the only
1894 : // way to call this from the outside seems to be the special case in
1895 : // SwDoc::CopyRange (but I have not managed to actually hit that case).
1896 5226 : bool DocumentContentOperationsManager::MoveRange( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
1897 : {
1898 : // nothing moved: return
1899 5226 : const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
1900 5226 : if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
1901 5214 : return false;
1902 :
1903 : // Save the paragraph anchored Flys, so that they can be moved.
1904 12 : _SaveFlyArr aSaveFlyArr;
1905 12 : _SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, 0 != ( DOC_MOVEALLFLYS & eMvFlags ) );
1906 :
1907 : // save redlines (if DOC_MOVEREDLINES is used)
1908 24 : _SaveRedlines aSaveRedl;
1909 12 : if( DOC_MOVEREDLINES & eMvFlags && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() )
1910 : {
1911 0 : lcl_SaveRedlines( rPaM, aSaveRedl );
1912 :
1913 : // #i17764# unfortunately, code below relies on undos being
1914 : // in a particular order, and presence of bookmarks
1915 : // will change this order. Hence, we delete bookmarks
1916 : // here without undo.
1917 0 : ::sw::UndoGuard const undoGuard(m_rSwdoc.GetIDocumentUndoRedo());
1918 : _DelBookmarks(
1919 : pStt->nNode,
1920 : pEnd->nNode,
1921 : NULL,
1922 : &pStt->nContent,
1923 0 : &pEnd->nContent);
1924 : }
1925 :
1926 12 : bool bUpdateFtn = false;
1927 24 : SwFtnIdxs aTmpFntIdx;
1928 :
1929 12 : SwUndoMove * pUndoMove = 0;
1930 12 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
1931 : {
1932 0 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo();
1933 0 : pUndoMove = new SwUndoMove( rPaM, rPos );
1934 0 : pUndoMove->SetMoveRedlines( eMvFlags == DOC_MOVEREDLINES );
1935 : }
1936 : else
1937 : {
1938 : bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
1939 12 : m_rSwdoc.GetFtnIdxs(), aTmpFntIdx,
1940 24 : &pStt->nContent, &pEnd->nContent );
1941 : }
1942 :
1943 12 : bool bSplit = false;
1944 24 : SwPaM aSavePam( rPos, rPos );
1945 :
1946 : // Move the SPoint to the beginning of the range
1947 12 : if( rPaM.GetPoint() == pEnd )
1948 12 : rPaM.Exchange();
1949 :
1950 : // If there is a TextNode before and after the Move, create a JoinNext in the EditShell.
1951 12 : SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
1952 12 : bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
1953 :
1954 : // If one ore more TextNodes are moved, SwNodes::Move will do a SplitNode.
1955 : // However, this does not update the cursor. So we create a TextNode to keep
1956 : // updating the indices. After the Move the Node is optionally deleted.
1957 12 : SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
1958 24 : if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
1959 6 : ( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam )) )
1960 : {
1961 6 : bSplit = true;
1962 6 : const sal_Int32 nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
1963 :
1964 6 : const boost::shared_ptr<sw::mark::CntntIdxStore> pCntntStore(sw::mark::CntntIdxStore::Create());
1965 6 : pCntntStore->Save( &m_rSwdoc, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(), true );
1966 :
1967 6 : pTNd = static_cast<SwTxtNode*>(pTNd->SplitCntntNode( rPos ));
1968 :
1969 6 : if( !pCntntStore->Empty() )
1970 2 : pCntntStore->Restore( &m_rSwdoc, rPos.nNode.GetIndex()-1, 0, true );
1971 :
1972 : // correct the PaM!
1973 6 : if( rPos.nNode == rPaM.GetMark()->nNode )
1974 : {
1975 0 : rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
1976 0 : rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
1977 6 : }
1978 : }
1979 :
1980 : // Put back the Pam by one "content"; so that it's always outside of
1981 : // the manipulated range.
1982 : // If there's no content anymore, set it to the StartNode (that's
1983 : // always there).
1984 12 : const bool bNullCntnt = !aSavePam.Move( fnMoveBackward, fnGoCntnt );
1985 12 : if( bNullCntnt )
1986 : {
1987 2 : aSavePam.GetPoint()->nNode--;
1988 : }
1989 :
1990 : // Copy all Bookmarks that are within the Move range into an array,
1991 : // that saves the position as an offset.
1992 24 : ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
1993 : _DelBookmarks(
1994 : pStt->nNode,
1995 : pEnd->nNode,
1996 : &aSaveBkmks,
1997 : &pStt->nContent,
1998 12 : &pEnd->nContent);
1999 :
2000 : // If there is no range anymore due to the above deletions (e.g. the
2001 : // footnotes got deleted), it's still a valid Move!
2002 12 : if( *rPaM.GetPoint() != *rPaM.GetMark() )
2003 : {
2004 : // now do the actual move
2005 12 : m_rSwdoc.GetNodes().MoveRange( rPaM, rPos, m_rSwdoc.GetNodes() );
2006 :
2007 : // after a MoveRange() the Mark is deleted
2008 12 : if ( rPaM.HasMark() ) // => no Move occurred!
2009 : {
2010 0 : delete pUndoMove;
2011 0 : return false;
2012 : }
2013 : }
2014 : else
2015 0 : rPaM.DeleteMark();
2016 :
2017 : OSL_ENSURE( *aSavePam.GetMark() == rPos ||
2018 : ( aSavePam.GetMark()->nNode.GetNode().GetCntntNode() == NULL ),
2019 : "PaM was not moved. Aren't there ContentNodes at the beginning/end?" );
2020 12 : *aSavePam.GetMark() = rPos;
2021 :
2022 12 : rPaM.SetMark(); // create a Sel. around the new range
2023 12 : pTNd = aSavePam.GetNode().GetTxtNode();
2024 12 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2025 : {
2026 : // correct the SavePam's Content first
2027 0 : if( bNullCntnt )
2028 : {
2029 0 : aSavePam.GetPoint()->nContent = 0;
2030 : }
2031 :
2032 : // The method SwEditShell::Move() merges the TextNode after the Move,
2033 : // where the rPaM is located.
2034 : // If the Content was moved to the back and the SavePam's SPoint is
2035 : // in the next Node, we have to deal with this when saving the Undo object!
2036 0 : SwTxtNode * pPamTxtNd = 0;
2037 :
2038 : // Is passed to SwUndoMove, which happens when subsequently calling Undo JoinNext.
2039 : // If it's not possible to call Undo JoinNext here.
2040 0 : bool bJoin = bSplit && pTNd;
2041 0 : bCorrSavePam = bCorrSavePam &&
2042 0 : 0 != ( pPamTxtNd = rPaM.GetNode().GetTxtNode() )
2043 0 : && pPamTxtNd->CanJoinNext()
2044 0 : && (*rPaM.GetPoint() <= *aSavePam.GetPoint());
2045 :
2046 : // Do two Nodes have to be joined at the SavePam?
2047 0 : if( bJoin && pTNd->CanJoinNext() )
2048 : {
2049 0 : pTNd->JoinNext();
2050 : // No temporary Index when using &&.
2051 : // We probably only want to compare the indices.
2052 0 : if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
2053 0 : aSavePam.GetPoint()->nNode.GetIndex() )
2054 : {
2055 0 : aSavePam.GetPoint()->nContent += pPamTxtNd->Len();
2056 : }
2057 0 : bJoin = false;
2058 : }
2059 0 : else if ( !aSavePam.Move( fnMoveForward, fnGoCntnt ) )
2060 : {
2061 0 : aSavePam.GetPoint()->nNode++;
2062 : }
2063 :
2064 : // The newly inserted range is now inbetween SPoint and GetMark.
2065 0 : pUndoMove->SetDestRange( aSavePam, *rPaM.GetPoint(),
2066 0 : bJoin, bCorrSavePam );
2067 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( pUndoMove );
2068 : }
2069 : else
2070 : {
2071 12 : bool bRemove = true;
2072 : // Do two Nodes have to be joined at the SavePam?
2073 12 : if( bSplit && pTNd )
2074 : {
2075 6 : if( pTNd->CanJoinNext())
2076 : {
2077 : // Always join next, because <pTNd> has to stay as it is.
2078 : // A join previous from its next would more or less delete <pTNd>
2079 6 : pTNd->JoinNext();
2080 6 : bRemove = false;
2081 : }
2082 : }
2083 12 : if( bNullCntnt )
2084 : {
2085 2 : aSavePam.GetPoint()->nNode++;
2086 2 : aSavePam.GetPoint()->nContent.Assign( aSavePam.GetCntntNode(), 0 );
2087 : }
2088 10 : else if( bRemove ) // No move forward after joining with next paragraph
2089 : {
2090 4 : aSavePam.Move( fnMoveForward, fnGoCntnt );
2091 : }
2092 : }
2093 :
2094 : // Insert the Bookmarks back into the Document.
2095 12 : *rPaM.GetMark() = *aSavePam.Start();
2096 36 : for(
2097 12 : ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
2098 24 : pBkmk != aSaveBkmks.end();
2099 : ++pBkmk)
2100 : pBkmk->SetInDoc(
2101 : &m_rSwdoc,
2102 0 : rPaM.GetMark()->nNode,
2103 0 : &rPaM.GetMark()->nContent);
2104 12 : *rPaM.GetPoint() = *aSavePam.End();
2105 :
2106 : // Move the Flys to the new position.
2107 12 : _RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode, &(rPos.nNode) );
2108 :
2109 : // restore redlines (if DOC_MOVEREDLINES is used)
2110 12 : if( !aSaveRedl.empty() )
2111 : {
2112 0 : lcl_RestoreRedlines( &m_rSwdoc, *aSavePam.Start(), aSaveRedl );
2113 : }
2114 :
2115 12 : if( bUpdateFtn )
2116 : {
2117 0 : if( !aTmpFntIdx.empty() )
2118 : {
2119 0 : m_rSwdoc.GetFtnIdxs().insert( aTmpFntIdx );
2120 0 : aTmpFntIdx.clear();
2121 : }
2122 :
2123 0 : m_rSwdoc.GetFtnIdxs().UpdateAllFtn();
2124 : }
2125 :
2126 12 : m_rSwdoc.getIDocumentState().SetModified();
2127 24 : return true;
2128 : }
2129 :
2130 132 : bool DocumentContentOperationsManager::MoveNodeRange( SwNodeRange& rRange, SwNodeIndex& rPos,
2131 : SwMoveFlags eMvFlags )
2132 : {
2133 : // Moves all Nodes to the new position.
2134 : // Bookmarks are moved too (currently without Undo support).
2135 :
2136 : // If footnotes are being moved to the special section, remove them now.
2137 :
2138 : // Or else delete the Frames for all footnotes that are being moved
2139 : // and have it rebuild after the Move (footnotes can change pages).
2140 : // Additionally we have to correct the FtnIdx array's sorting.
2141 132 : bool bUpdateFtn = false;
2142 132 : SwFtnIdxs aTmpFntIdx;
2143 :
2144 132 : SwUndoMove* pUndo = 0;
2145 132 : if ((DOC_CREATEUNDOOBJ & eMvFlags ) && m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2146 : {
2147 0 : pUndo = new SwUndoMove( &m_rSwdoc, rRange, rPos );
2148 : }
2149 : else
2150 : {
2151 : bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
2152 132 : m_rSwdoc.GetFtnIdxs(), aTmpFntIdx );
2153 : }
2154 :
2155 264 : _SaveRedlines aSaveRedl;
2156 264 : std::vector<SwRangeRedline*> aSavRedlInsPosArr;
2157 132 : if( DOC_MOVEREDLINES & eMvFlags && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() )
2158 : {
2159 0 : lcl_SaveRedlines( rRange, aSaveRedl );
2160 :
2161 : // Find all RedLines that end at the InsPos.
2162 : // These have to be moved back to the "old" position after the Move.
2163 0 : sal_uInt16 nRedlPos = m_rSwdoc.getIDocumentRedlineAccess().GetRedlinePos( rPos.GetNode(), USHRT_MAX );
2164 0 : if( USHRT_MAX != nRedlPos )
2165 : {
2166 : const SwPosition *pRStt, *pREnd;
2167 0 : do {
2168 0 : SwRangeRedline* pTmp = m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl()[ nRedlPos ];
2169 0 : pRStt = pTmp->Start();
2170 0 : pREnd = pTmp->End();
2171 0 : if( pREnd->nNode == rPos && pRStt->nNode < rPos )
2172 : {
2173 0 : aSavRedlInsPosArr.push_back( pTmp );
2174 : }
2175 0 : } while( pRStt->nNode < rPos && ++nRedlPos < m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().size());
2176 : }
2177 : }
2178 :
2179 : // Copy all Bookmarks that are within the Move range into an array
2180 : // that stores all references to positions as an offset.
2181 : // The final mapping happens after the Move.
2182 264 : ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
2183 132 : _DelBookmarks(rRange.aStart, rRange.aEnd, &aSaveBkmks);
2184 :
2185 : // Save the paragraph-bound Flys, so that they can be moved.
2186 264 : _SaveFlyArr aSaveFlyArr;
2187 132 : if( !m_rSwdoc.GetSpzFrmFmts()->empty() )
2188 0 : _SaveFlyInRange( rRange, aSaveFlyArr );
2189 :
2190 : // Set it to before the Position, so that it cannot be moved further.
2191 264 : SwNodeIndex aIdx( rPos, -1 );
2192 :
2193 132 : SwNodeIndex* pSaveInsPos = 0;
2194 132 : if( pUndo )
2195 0 : pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
2196 :
2197 : // move the Nodes
2198 132 : bool bNoDelFrms = 0 != (DOC_NO_DELFRMS & eMvFlags);
2199 132 : if( m_rSwdoc.GetNodes()._MoveNodes( rRange, m_rSwdoc.GetNodes(), rPos, !bNoDelFrms ) )
2200 : {
2201 108 : ++aIdx; // again back to old position
2202 108 : if( pSaveInsPos )
2203 0 : ++(*pSaveInsPos);
2204 : }
2205 : else
2206 : {
2207 24 : aIdx = rRange.aStart;
2208 24 : delete pUndo, pUndo = 0;
2209 : }
2210 :
2211 : // move the Flys to the new position
2212 132 : if( !aSaveFlyArr.empty() )
2213 0 : _RestFlyInRange( aSaveFlyArr, aIdx, NULL );
2214 :
2215 : // Add the Bookmarks back to the Document
2216 396 : for(
2217 132 : ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
2218 264 : pBkmk != aSaveBkmks.end();
2219 : ++pBkmk)
2220 0 : pBkmk->SetInDoc(&m_rSwdoc, aIdx);
2221 :
2222 132 : if( !aSavRedlInsPosArr.empty() )
2223 : {
2224 0 : SwNode* pNewNd = &aIdx.GetNode();
2225 0 : for( size_t n = 0; n < aSavRedlInsPosArr.size(); ++n )
2226 : {
2227 0 : SwRangeRedline* pTmp = aSavRedlInsPosArr[ n ];
2228 0 : if( m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().Contains( pTmp ) )
2229 : {
2230 0 : SwPosition* pEnd = pTmp->End();
2231 0 : pEnd->nNode = aIdx;
2232 0 : pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
2233 : }
2234 : }
2235 : }
2236 :
2237 132 : if( !aSaveRedl.empty() )
2238 0 : lcl_RestoreRedlines( &m_rSwdoc, aIdx.GetIndex(), aSaveRedl );
2239 :
2240 132 : if( pUndo )
2241 : {
2242 0 : pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
2243 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
2244 : }
2245 :
2246 132 : delete pSaveInsPos;
2247 :
2248 132 : if( bUpdateFtn )
2249 : {
2250 0 : if( !aTmpFntIdx.empty() )
2251 : {
2252 0 : m_rSwdoc.GetFtnIdxs().insert( aTmpFntIdx );
2253 0 : aTmpFntIdx.clear();
2254 : }
2255 :
2256 0 : m_rSwdoc.GetFtnIdxs().UpdateAllFtn();
2257 : }
2258 :
2259 132 : m_rSwdoc.getIDocumentState().SetModified();
2260 264 : return true;
2261 : }
2262 :
2263 0 : bool DocumentContentOperationsManager::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
2264 : {
2265 0 : SwNodeIndex aIdx( rPaM.Start()->nNode );
2266 0 : bool bJoinTxt = aIdx.GetNode().IsTxtNode();
2267 0 : bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
2268 0 : aIdx--; // in front of the move area!
2269 :
2270 0 : bool bRet = MoveRange( rPaM, rPos, eMvFlags );
2271 0 : if( bRet && !bOneNode )
2272 : {
2273 0 : if( bJoinTxt )
2274 0 : ++aIdx;
2275 0 : SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
2276 0 : SwNodeIndex aNxtIdx( aIdx );
2277 0 : if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
2278 : {
2279 : { // Block so SwIndex into node is deleted before Join
2280 : m_rSwdoc.CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex(pTxtNd,
2281 0 : pTxtNd->GetTxt().getLength()) ), 0, true );
2282 : }
2283 0 : pTxtNd->JoinNext();
2284 0 : }
2285 : }
2286 0 : return bRet;
2287 : }
2288 :
2289 2624 : bool DocumentContentOperationsManager::Overwrite( const SwPaM &rRg, const OUString &rStr )
2290 : {
2291 2624 : SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
2292 2624 : if( m_rSwdoc.GetAutoCorrExceptWord() ) // Add to AutoCorrect
2293 : {
2294 0 : if( 1 == rStr.getLength() )
2295 0 : m_rSwdoc.GetAutoCorrExceptWord()->CheckChar( rPt, rStr[ 0 ] );
2296 0 : m_rSwdoc.DeleteAutoCorrExceptWord();
2297 : }
2298 :
2299 2624 : SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
2300 2624 : if (!pNode || rStr.getLength() > pNode->GetSpaceLeft()) // worst case: no erase
2301 : {
2302 904 : return false;
2303 : }
2304 :
2305 1720 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2306 : {
2307 0 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
2308 : }
2309 :
2310 1720 : const size_t nOldAttrCnt = pNode->GetpSwpHints()
2311 1720 : ? pNode->GetpSwpHints()->Count() : 0;
2312 1720 : SwDataChanged aTmp( rRg );
2313 1720 : SwIndex& rIdx = rPt.nContent;
2314 1720 : sal_Int32 nStart = 0;
2315 :
2316 1720 : bool bOldExpFlg = pNode->IsIgnoreDontExpand();
2317 1720 : pNode->SetIgnoreDontExpand( true );
2318 :
2319 10749 : for( sal_Int32 nCnt = 0; nCnt < rStr.getLength(); ++nCnt )
2320 : {
2321 : // start behind the characters (to fix the attributes!)
2322 9029 : nStart = rIdx.GetIndex();
2323 9029 : if (nStart < pNode->GetTxt().getLength())
2324 : {
2325 0 : lcl_SkipAttr( pNode, rIdx, nStart );
2326 : }
2327 9029 : sal_Unicode c = rStr[ nCnt ];
2328 9029 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2329 : {
2330 0 : bool bMerged(false);
2331 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesGroupUndo())
2332 : {
2333 0 : SwUndo *const pUndo = m_rSwdoc.GetUndoManager().GetLastUndo();
2334 : SwUndoOverwrite *const pUndoOW(
2335 0 : dynamic_cast<SwUndoOverwrite *>(pUndo) );
2336 0 : if (pUndoOW)
2337 : {
2338 : // if CanGrouping() returns true it's already merged
2339 0 : bMerged = pUndoOW->CanGrouping( &m_rSwdoc, rPt, c );
2340 : }
2341 : }
2342 0 : if (!bMerged)
2343 : {
2344 0 : SwUndo *const pUndoOW( new SwUndoOverwrite(&m_rSwdoc, rPt, c) );
2345 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndoOW);
2346 : }
2347 : }
2348 : else
2349 : {
2350 : // start behind the characters (to fix the attributes!)
2351 9029 : if (nStart < pNode->GetTxt().getLength())
2352 0 : ++rIdx;
2353 9029 : pNode->InsertText( OUString(c), rIdx, INS_EMPTYEXPAND );
2354 9029 : if( nStart+1 < rIdx.GetIndex() )
2355 : {
2356 0 : rIdx = nStart;
2357 0 : pNode->EraseText( rIdx, 1 );
2358 0 : ++rIdx;
2359 : }
2360 : }
2361 : }
2362 1720 : pNode->SetIgnoreDontExpand( bOldExpFlg );
2363 :
2364 1720 : const size_t nNewAttrCnt = pNode->GetpSwpHints()
2365 1720 : ? pNode->GetpSwpHints()->Count() : 0;
2366 1720 : if( nOldAttrCnt != nNewAttrCnt )
2367 : {
2368 : SwUpdateAttr aHint(
2369 : 0,
2370 : 0,
2371 0 : 0);
2372 :
2373 0 : pNode->ModifyBroadcast( 0, &aHint, TYPE( SwCrsrShell ) );
2374 : }
2375 :
2376 5160 : if (!m_rSwdoc.GetIDocumentUndoRedo().DoesUndo() &&
2377 3010 : !m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty())
2378 : {
2379 600 : SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
2380 600 : m_rSwdoc.getIDocumentRedlineAccess().DeleteRedline( aPam, true, USHRT_MAX );
2381 : }
2382 1120 : else if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() )
2383 : {
2384 : // FIXME: this redline is WRONG: there is no DELETE, and the skipped
2385 : // characters are also included in aPam
2386 250 : SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
2387 250 : m_rSwdoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
2388 : }
2389 :
2390 1720 : m_rSwdoc.getIDocumentState().SetModified();
2391 1720 : return true;
2392 : }
2393 :
2394 219348 : bool DocumentContentOperationsManager::InsertString( const SwPaM &rRg, const OUString &rStr,
2395 : const enum InsertFlags nInsertMode )
2396 : {
2397 : // fetching DoesUndo is surprisingly expensive
2398 219348 : bool bDoesUndo = m_rSwdoc.GetIDocumentUndoRedo().DoesUndo();
2399 219348 : if (bDoesUndo)
2400 16506 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called!
2401 :
2402 219348 : const SwPosition& rPos = *rRg.GetPoint();
2403 :
2404 219348 : if( m_rSwdoc.GetAutoCorrExceptWord() ) // add to auto correction
2405 : {
2406 0 : if( 1 == rStr.getLength() && m_rSwdoc.GetAutoCorrExceptWord()->IsDeleted() )
2407 : {
2408 0 : m_rSwdoc.GetAutoCorrExceptWord()->CheckChar( rPos, rStr[ 0 ] );
2409 : }
2410 0 : m_rSwdoc.DeleteAutoCorrExceptWord();
2411 : }
2412 :
2413 219348 : SwTxtNode *const pNode = rPos.nNode.GetNode().GetTxtNode();
2414 219348 : if(!pNode)
2415 1846 : return false;
2416 :
2417 217502 : SwDataChanged aTmp( rRg );
2418 :
2419 217502 : if (!bDoesUndo || !m_rSwdoc.GetIDocumentUndoRedo().DoesGroupUndo())
2420 : {
2421 217302 : OUString const ins(pNode->InsertText(rStr, rPos.nContent, nInsertMode));
2422 217302 : if (bDoesUndo)
2423 : {
2424 : SwUndoInsert * const pUndo( new SwUndoInsert(rPos.nNode,
2425 16306 : rPos.nContent.GetIndex(), ins.getLength(), nInsertMode));
2426 16306 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
2427 217302 : }
2428 : }
2429 : else
2430 : { // if Undo and grouping is enabled, everything changes!
2431 200 : SwUndoInsert * pUndo = NULL;
2432 :
2433 : // don't group the start if hints at the start should be expanded
2434 200 : if (!(nInsertMode & IDocumentContentOperations::INS_FORCEHINTEXPAND))
2435 : {
2436 198 : SwUndo *const pLastUndo = m_rSwdoc.GetUndoManager().GetLastUndo();
2437 : SwUndoInsert *const pUndoInsert(
2438 198 : dynamic_cast<SwUndoInsert *>(pLastUndo) );
2439 198 : if (pUndoInsert && pUndoInsert->CanGrouping(rPos))
2440 : {
2441 94 : pUndo = pUndoInsert;
2442 : }
2443 : }
2444 :
2445 200 : CharClass const& rCC = GetAppCharClass();
2446 200 : sal_Int32 nInsPos = rPos.nContent.GetIndex();
2447 :
2448 200 : if (!pUndo)
2449 : {
2450 : pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 0, nInsertMode,
2451 106 : !rCC.isLetterNumeric( rStr, 0 ) );
2452 106 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( pUndo );
2453 : }
2454 :
2455 200 : OUString const ins(pNode->InsertText(rStr, rPos.nContent, nInsertMode));
2456 :
2457 816 : for (sal_Int32 i = 0; i < ins.getLength(); ++i)
2458 : {
2459 616 : nInsPos++;
2460 : // if CanGrouping() returns true, everything has already been done
2461 616 : if (!pUndo->CanGrouping(ins[i]))
2462 : {
2463 : pUndo = new SwUndoInsert(rPos.nNode, nInsPos, 1, nInsertMode,
2464 74 : !rCC.isLetterNumeric(ins, i));
2465 74 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( pUndo );
2466 : }
2467 200 : }
2468 : }
2469 :
2470 : // To-Do - add 'SwExtraRedlineTbl' also ?
2471 217502 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() || (!m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() ))
2472 : {
2473 : SwPaM aPam( rPos.nNode, aTmp.GetCntnt(),
2474 3476 : rPos.nNode, rPos.nContent.GetIndex());
2475 3476 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() )
2476 : {
2477 1854 : m_rSwdoc.getIDocumentRedlineAccess().AppendRedline(
2478 1854 : new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
2479 : }
2480 : else
2481 : {
2482 1622 : m_rSwdoc.getIDocumentRedlineAccess().SplitRedline( aPam );
2483 3476 : }
2484 : }
2485 :
2486 217502 : m_rSwdoc.getIDocumentState().SetModified();
2487 217502 : return true;
2488 : }
2489 :
2490 12 : void DocumentContentOperationsManager::TransliterateText(
2491 : const SwPaM& rPaM,
2492 : utl::TransliterationWrapper& rTrans )
2493 : {
2494 12 : SwUndoTransliterate *const pUndo = (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2495 0 : ? new SwUndoTransliterate( rPaM, rTrans )
2496 12 : : 0;
2497 :
2498 12 : const SwPosition* pStt = rPaM.Start(),
2499 12 : * pEnd = rPaM.End();
2500 12 : sal_uLong nSttNd = pStt->nNode.GetIndex(),
2501 12 : nEndNd = pEnd->nNode.GetIndex();
2502 12 : sal_Int32 nSttCnt = pStt->nContent.GetIndex();
2503 12 : sal_Int32 nEndCnt = pEnd->nContent.GetIndex();
2504 :
2505 12 : SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
2506 12 : if( pStt == pEnd && pTNd ) // no selection?
2507 : {
2508 : // set current word as 'area of effect'
2509 :
2510 0 : Boundary aBndry;
2511 0 : if( g_pBreakIt->GetBreakIter().is() )
2512 0 : aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary(
2513 0 : pTNd->GetTxt(), nSttCnt,
2514 0 : g_pBreakIt->GetLocale( pTNd->GetLang( nSttCnt ) ),
2515 : WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
2516 0 : sal_True );
2517 :
2518 0 : if( aBndry.startPos < nSttCnt && nSttCnt < aBndry.endPos )
2519 : {
2520 0 : nSttCnt = aBndry.startPos;
2521 0 : nEndCnt = aBndry.endPos;
2522 : }
2523 : }
2524 :
2525 12 : if( nSttNd != nEndNd ) // is more than one text node involved?
2526 : {
2527 : // iterate over all effected text nodes, the first and the last one
2528 : // may be incomplete because the selection starts and/or ends there
2529 :
2530 0 : SwNodeIndex aIdx( pStt->nNode );
2531 0 : if( nSttCnt )
2532 : {
2533 0 : ++aIdx;
2534 0 : if( pTNd )
2535 : pTNd->TransliterateText(
2536 0 : rTrans, nSttCnt, pTNd->GetTxt().getLength(), pUndo);
2537 : }
2538 :
2539 0 : for( ; aIdx.GetIndex() < nEndNd; ++aIdx )
2540 : {
2541 0 : pTNd = aIdx.GetNode().GetTxtNode();
2542 0 : if (pTNd)
2543 : {
2544 : pTNd->TransliterateText(
2545 0 : rTrans, 0, pTNd->GetTxt().getLength(), pUndo);
2546 : }
2547 : }
2548 :
2549 0 : if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
2550 0 : pTNd->TransliterateText( rTrans, 0, nEndCnt, pUndo );
2551 : }
2552 12 : else if( pTNd && nSttCnt < nEndCnt )
2553 12 : pTNd->TransliterateText( rTrans, nSttCnt, nEndCnt, pUndo );
2554 :
2555 12 : if( pUndo )
2556 : {
2557 0 : if( pUndo->HasData() )
2558 : {
2559 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
2560 : }
2561 : else
2562 0 : delete pUndo;
2563 : }
2564 12 : m_rSwdoc.getIDocumentState().SetModified();
2565 12 : }
2566 :
2567 506 : SwFlyFrmFmt* DocumentContentOperationsManager::Insert( const SwPaM &rRg,
2568 : const OUString& rGrfName,
2569 : const OUString& rFltName,
2570 : const Graphic* pGraphic,
2571 : const SfxItemSet* pFlyAttrSet,
2572 : const SfxItemSet* pGrfAttrSet,
2573 : SwFrmFmt* pFrmFmt )
2574 : {
2575 506 : if( !pFrmFmt )
2576 506 : pFrmFmt = m_rSwdoc.getIDocumentStylePoolAccess().GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
2577 506 : SwGrfNode* pSwGrfNode = m_rSwdoc.GetNodes().MakeGrfNode(
2578 506 : SwNodeIndex( m_rSwdoc.GetNodes().GetEndOfAutotext() ),
2579 : rGrfName, rFltName, pGraphic,
2580 1518 : m_rSwdoc.GetDfltGrfFmtColl() );
2581 506 : SwFlyFrmFmt* pSwFlyFrmFmt = _InsNoTxtNode( *rRg.GetPoint(), pSwGrfNode,
2582 506 : pFlyAttrSet, pGrfAttrSet, pFrmFmt );
2583 506 : return pSwFlyFrmFmt;
2584 : }
2585 :
2586 292 : SwFlyFrmFmt* DocumentContentOperationsManager::Insert( const SwPaM &rRg, const GraphicObject& rGrfObj,
2587 : const SfxItemSet* pFlyAttrSet,
2588 : const SfxItemSet* pGrfAttrSet,
2589 : SwFrmFmt* pFrmFmt )
2590 : {
2591 292 : if( !pFrmFmt )
2592 0 : pFrmFmt = m_rSwdoc.getIDocumentStylePoolAccess().GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
2593 292 : SwGrfNode* pSwGrfNode = m_rSwdoc.GetNodes().MakeGrfNode(
2594 292 : SwNodeIndex( m_rSwdoc.GetNodes().GetEndOfAutotext() ),
2595 876 : rGrfObj, m_rSwdoc.GetDfltGrfFmtColl() );
2596 292 : SwFlyFrmFmt* pSwFlyFrmFmt = _InsNoTxtNode( *rRg.GetPoint(), pSwGrfNode,
2597 292 : pFlyAttrSet, pGrfAttrSet, pFrmFmt );
2598 292 : return pSwFlyFrmFmt;
2599 : }
2600 :
2601 730 : SwFlyFrmFmt* DocumentContentOperationsManager::Insert(const SwPaM &rRg, const svt::EmbeddedObjectRef& xObj,
2602 : const SfxItemSet* pFlyAttrSet,
2603 : const SfxItemSet* pGrfAttrSet,
2604 : SwFrmFmt* pFrmFmt )
2605 : {
2606 730 : if( !pFrmFmt )
2607 : {
2608 730 : sal_uInt16 nId = RES_POOLFRM_OLE;
2609 730 : SvGlobalName aClassName( xObj->getClassID() );
2610 730 : if (SotExchange::IsMath(aClassName))
2611 534 : nId = RES_POOLFRM_FORMEL;
2612 :
2613 730 : pFrmFmt = m_rSwdoc.getIDocumentStylePoolAccess().GetFrmFmtFromPool( nId );
2614 : }
2615 1460 : return _InsNoTxtNode( *rRg.GetPoint(), m_rSwdoc.GetNodes().MakeOLENode(
2616 730 : SwNodeIndex( m_rSwdoc.GetNodes().GetEndOfAutotext() ),
2617 : xObj,
2618 2920 : m_rSwdoc.GetDfltGrfFmtColl() ),
2619 : pFlyAttrSet, pGrfAttrSet,
2620 1460 : pFrmFmt );
2621 : }
2622 :
2623 148 : SwFlyFrmFmt* DocumentContentOperationsManager::InsertOLE(const SwPaM &rRg, const OUString& rObjName,
2624 : sal_Int64 nAspect,
2625 : const SfxItemSet* pFlyAttrSet,
2626 : const SfxItemSet* pGrfAttrSet,
2627 : SwFrmFmt* pFrmFmt )
2628 : {
2629 148 : if( !pFrmFmt )
2630 148 : pFrmFmt = m_rSwdoc.getIDocumentStylePoolAccess().GetFrmFmtFromPool( RES_POOLFRM_OLE );
2631 :
2632 148 : return _InsNoTxtNode( *rRg.GetPoint(),
2633 148 : m_rSwdoc.GetNodes().MakeOLENode(
2634 148 : SwNodeIndex( m_rSwdoc.GetNodes().GetEndOfAutotext() ),
2635 : rObjName,
2636 : nAspect,
2637 : m_rSwdoc.GetDfltGrfFmtColl(),
2638 592 : 0 ),
2639 : pFlyAttrSet, pGrfAttrSet,
2640 296 : pFrmFmt );
2641 : }
2642 :
2643 12 : void DocumentContentOperationsManager::ReRead( SwPaM& rPam, const OUString& rGrfName,
2644 : const OUString& rFltName, const Graphic* pGraphic,
2645 : const GraphicObject* pGrafObj )
2646 : {
2647 : SwGrfNode *pGrfNd;
2648 24 : if( ( !rPam.HasMark()
2649 0 : || rPam.GetPoint()->nNode.GetIndex() == rPam.GetMark()->nNode.GetIndex() )
2650 24 : && 0 != ( pGrfNd = rPam.GetPoint()->nNode.GetNode().GetGrfNode() ) )
2651 : {
2652 12 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2653 : {
2654 12 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(new SwUndoReRead(rPam, *pGrfNd));
2655 : }
2656 :
2657 : // Because we don't know if we can mirror the graphic, the mirror attribute is always reset
2658 24 : if( RES_MIRROR_GRAPH_DONT != pGrfNd->GetSwAttrSet().
2659 12 : GetMirrorGrf().GetValue() )
2660 2 : pGrfNd->SetAttr( SwMirrorGrf() );
2661 :
2662 12 : pGrfNd->ReRead( rGrfName, rFltName, pGraphic, pGrafObj, true );
2663 12 : m_rSwdoc.getIDocumentState().SetModified();
2664 : }
2665 12 : }
2666 :
2667 : // Insert drawing object, which has to be already inserted in the DrawModel
2668 4020 : SwDrawFrmFmt* DocumentContentOperationsManager::InsertDrawObj(
2669 : const SwPaM &rRg,
2670 : SdrObject& rDrawObj,
2671 : const SfxItemSet& rFlyAttrSet )
2672 : {
2673 4020 : SwDrawFrmFmt* pFmt = m_rSwdoc.MakeDrawFrmFmt( OUString(), m_rSwdoc.GetDfltFrmFmt() );
2674 :
2675 4020 : const SwFmtAnchor* pAnchor = 0;
2676 4020 : rFlyAttrSet.GetItemState( RES_ANCHOR, false, (const SfxPoolItem**) &pAnchor );
2677 4020 : pFmt->SetFmtAttr( rFlyAttrSet );
2678 :
2679 : // Didn't set the Anchor yet?
2680 : // DrawObjecte must never end up in the Header/Footer!
2681 4020 : RndStdIds eAnchorId = pAnchor != NULL ? pAnchor->GetAnchorId() : pFmt->GetAnchor().GetAnchorId();
2682 4020 : const bool bIsAtCntnt = (FLY_AT_PAGE != eAnchorId);
2683 :
2684 4020 : const SwNodeIndex* pChkIdx = 0;
2685 4020 : if ( pAnchor == NULL )
2686 : {
2687 0 : pChkIdx = &rRg.GetPoint()->nNode;
2688 : }
2689 4020 : else if ( bIsAtCntnt )
2690 : {
2691 : pChkIdx =
2692 776 : pAnchor->GetCntntAnchor() ? &pAnchor->GetCntntAnchor()->nNode : &rRg.GetPoint()->nNode;
2693 : }
2694 :
2695 : // allow drawing objects in header/footer, but control objects aren't allowed in header/footer.
2696 4020 : if( pChkIdx != NULL
2697 776 : && ::CheckControlLayer( &rDrawObj )
2698 4550 : && m_rSwdoc.IsInHeaderFooter( *pChkIdx ) )
2699 : {
2700 : // apply at-page anchor format
2701 0 : eAnchorId = FLY_AT_PAGE;
2702 0 : pFmt->SetFmtAttr( SwFmtAnchor( eAnchorId ) );
2703 : }
2704 8040 : else if( pAnchor == NULL
2705 4196 : || ( bIsAtCntnt
2706 776 : && pAnchor->GetCntntAnchor() == NULL ) )
2707 : {
2708 : // apply anchor format
2709 176 : SwFmtAnchor aAnch( pAnchor != NULL ? *pAnchor : pFmt->GetAnchor() );
2710 176 : eAnchorId = aAnch.GetAnchorId();
2711 176 : if ( eAnchorId == FLY_AT_FLY )
2712 : {
2713 18 : SwPosition aPos( *rRg.GetNode().FindFlyStartNode() );
2714 18 : aAnch.SetAnchor( &aPos );
2715 : }
2716 : else
2717 : {
2718 158 : aAnch.SetAnchor( rRg.GetPoint() );
2719 158 : if ( eAnchorId == FLY_AT_PAGE )
2720 : {
2721 0 : eAnchorId = rDrawObj.ISA( SdrUnoObj ) ? FLY_AS_CHAR : FLY_AT_PARA;
2722 0 : aAnch.SetType( eAnchorId );
2723 : }
2724 : }
2725 176 : pFmt->SetFmtAttr( aAnch );
2726 : }
2727 :
2728 : // insert text attribute for as-character anchored drawing object
2729 4020 : if ( eAnchorId == FLY_AS_CHAR )
2730 : {
2731 566 : bool bAnchorAtPageAsFallback = true;
2732 566 : const SwFmtAnchor& rDrawObjAnchorFmt = pFmt->GetAnchor();
2733 566 : if ( rDrawObjAnchorFmt.GetCntntAnchor() != NULL )
2734 : {
2735 : SwTxtNode* pAnchorTxtNode =
2736 566 : rDrawObjAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
2737 566 : if ( pAnchorTxtNode != NULL )
2738 : {
2739 566 : const sal_Int32 nStt = rDrawObjAnchorFmt.GetCntntAnchor()->nContent.GetIndex();
2740 566 : SwFmtFlyCnt aFmt( pFmt );
2741 566 : pAnchorTxtNode->InsertItem( aFmt, nStt, nStt );
2742 566 : bAnchorAtPageAsFallback = false;
2743 : }
2744 : }
2745 :
2746 566 : if ( bAnchorAtPageAsFallback )
2747 : {
2748 : OSL_ENSURE( false, "DocumentContentOperationsManager::InsertDrawObj(..) - missing content anchor for as-character anchored drawing object --> anchor at-page" );
2749 0 : pFmt->SetFmtAttr( SwFmtAnchor( FLY_AT_PAGE ) );
2750 : }
2751 : }
2752 :
2753 4020 : SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
2754 :
2755 : // Create Frames if necessary
2756 4020 : if( m_rSwdoc.getIDocumentLayoutAccess().GetCurrentViewShell() )
2757 : {
2758 : // create layout representation
2759 502 : pFmt->MakeFrms();
2760 : // #i42319# - follow-up of #i35635#
2761 : // move object to visible layer
2762 : // #i79391#
2763 502 : if ( pContact->GetAnchorFrm() )
2764 : {
2765 502 : pContact->MoveObjToVisibleLayer( &rDrawObj );
2766 : }
2767 : }
2768 :
2769 4020 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2770 : {
2771 502 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoInsLayFmt(pFmt, 0, 0) );
2772 : }
2773 :
2774 4020 : m_rSwdoc.getIDocumentState().SetModified();
2775 4020 : return pFmt;
2776 : }
2777 :
2778 1238 : bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart )
2779 : {
2780 1238 : SwCntntNode *pNode = rPos.nNode.GetNode().GetCntntNode();
2781 1238 : if(0 == pNode)
2782 0 : return false;
2783 :
2784 : {
2785 : // BUG 26675: Send DataChanged before deleting, so that we notice which objects are in scope.
2786 : // After that they can be before/after the position.
2787 1238 : SwDataChanged aTmp( &m_rSwdoc, rPos );
2788 : }
2789 :
2790 1238 : SwUndoSplitNode* pUndo = 0;
2791 1238 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2792 : {
2793 664 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo();
2794 : // insert the Undo object (currently only for TextNode)
2795 664 : if( pNode->IsTxtNode() )
2796 : {
2797 664 : pUndo = new SwUndoSplitNode( &m_rSwdoc, rPos, bChkTableStart );
2798 664 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
2799 : }
2800 : }
2801 :
2802 : // Update the rsid of the old and the new node unless
2803 : // the old node is split at the beginning or at the end
2804 1238 : SwTxtNode *pTxtNode = rPos.nNode.GetNode().GetTxtNode();
2805 1238 : const sal_Int32 nPos = rPos.nContent.GetIndex();
2806 1238 : if( pTxtNode && nPos && nPos != pTxtNode->Len() )
2807 : {
2808 84 : m_rSwdoc.UpdateParRsid( pTxtNode );
2809 : }
2810 :
2811 : //JP 28.01.97: Special case for SplitNode at table start:
2812 : // If it is at the beginning of a Doc/Fly/Footer/... or right at after a table
2813 : // then insert a paragraph before it.
2814 1238 : if( bChkTableStart && !rPos.nContent.GetIndex() && pNode->IsTxtNode() )
2815 : {
2816 12 : sal_uLong nPrevPos = rPos.nNode.GetIndex() - 1;
2817 : const SwTableNode* pTblNd;
2818 12 : const SwNode* pNd = m_rSwdoc.GetNodes()[ nPrevPos ];
2819 30 : if( pNd->IsStartNode() &&
2820 6 : SwTableBoxStartNode == ((SwStartNode*)pNd)->GetStartNodeType() &&
2821 12 : 0 != ( pTblNd = m_rSwdoc.GetNodes()[ --nPrevPos ]->GetTableNode() ) &&
2822 0 : ((( pNd = m_rSwdoc.GetNodes()[ --nPrevPos ])->IsStartNode() &&
2823 0 : SwTableBoxStartNode != ((SwStartNode*)pNd)->GetStartNodeType() )
2824 0 : || ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
2825 0 : || pNd->IsCntntNode() ))
2826 : {
2827 0 : if( pNd->IsCntntNode() )
2828 : {
2829 : //JP 30.04.99 Bug 65660:
2830 : // There are no page breaks outside of the normal body area,
2831 : // so this is not a valid condition to insert a paragraph.
2832 0 : if( nPrevPos < m_rSwdoc.GetNodes().GetEndOfExtras().GetIndex() )
2833 0 : pNd = 0;
2834 : else
2835 : {
2836 : // Only if the table has page breaks!
2837 0 : const SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
2838 0 : if( SfxItemState::SET != pFrmFmt->GetItemState(RES_PAGEDESC, false) &&
2839 0 : SfxItemState::SET != pFrmFmt->GetItemState( RES_BREAK, false ) )
2840 0 : pNd = 0;
2841 : }
2842 : }
2843 :
2844 0 : if( pNd )
2845 : {
2846 0 : SwTxtNode* pTxtNd = m_rSwdoc.GetNodes().MakeTxtNode(
2847 : SwNodeIndex( *pTblNd ),
2848 0 : m_rSwdoc.getIDocumentStylePoolAccess().GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
2849 0 : if( pTxtNd )
2850 : {
2851 0 : ((SwPosition&)rPos).nNode = pTblNd->GetIndex()-1;
2852 0 : ((SwPosition&)rPos).nContent.Assign( pTxtNd, 0 );
2853 :
2854 : // only add page breaks/styles to the body area
2855 0 : if( nPrevPos > m_rSwdoc.GetNodes().GetEndOfExtras().GetIndex() )
2856 : {
2857 0 : SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
2858 : const SfxPoolItem *pItem;
2859 0 : if( SfxItemState::SET == pFrmFmt->GetItemState( RES_PAGEDESC,
2860 0 : false, &pItem ) )
2861 : {
2862 0 : pTxtNd->SetAttr( *pItem );
2863 0 : pFrmFmt->ResetFmtAttr( RES_PAGEDESC );
2864 : }
2865 0 : if( SfxItemState::SET == pFrmFmt->GetItemState( RES_BREAK,
2866 0 : false, &pItem ) )
2867 : {
2868 0 : pTxtNd->SetAttr( *pItem );
2869 0 : pFrmFmt->ResetFmtAttr( RES_BREAK );
2870 : }
2871 : }
2872 :
2873 0 : if( pUndo )
2874 0 : pUndo->SetTblFlag();
2875 0 : m_rSwdoc.getIDocumentState().SetModified();
2876 0 : return true;
2877 : }
2878 : }
2879 : }
2880 : }
2881 :
2882 1238 : const boost::shared_ptr<sw::mark::CntntIdxStore> pCntntStore(sw::mark::CntntIdxStore::Create());
2883 1238 : pCntntStore->Save( &m_rSwdoc, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(), true );
2884 : // FIXME: only SwTxtNode has a valid implementation of SplitCntntNode!
2885 : OSL_ENSURE(pNode->IsTxtNode(), "splitting non-text node?");
2886 1238 : pNode = pNode->SplitCntntNode( rPos );
2887 1238 : if (pNode)
2888 : {
2889 : // move all bookmarks, TOXMarks, FlyAtCnt
2890 1238 : if( !pCntntStore->Empty() )
2891 66 : pCntntStore->Restore( &m_rSwdoc, rPos.nNode.GetIndex()-1, 0, true );
2892 :
2893 : // To-Do - add 'SwExtraRedlineTbl' also ?
2894 1238 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() || (!m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() ))
2895 : {
2896 0 : SwPaM aPam( rPos );
2897 0 : aPam.SetMark();
2898 0 : aPam.Move( fnMoveBackward );
2899 0 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() )
2900 0 : m_rSwdoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
2901 : else
2902 0 : m_rSwdoc.getIDocumentRedlineAccess().SplitRedline( aPam );
2903 : }
2904 : }
2905 :
2906 1238 : m_rSwdoc.getIDocumentState().SetModified();
2907 1238 : return true;
2908 : }
2909 :
2910 61880 : bool DocumentContentOperationsManager::AppendTxtNode( SwPosition& rPos )
2911 : {
2912 : // create new node before EndOfContent
2913 61880 : SwTxtNode * pCurNode = rPos.nNode.GetNode().GetTxtNode();
2914 61880 : if( !pCurNode )
2915 : {
2916 : // so then one can be created!
2917 264 : SwNodeIndex aIdx( rPos.nNode, 1 );
2918 264 : pCurNode = m_rSwdoc.GetNodes().MakeTxtNode( aIdx,
2919 528 : m_rSwdoc.getIDocumentStylePoolAccess().GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
2920 : }
2921 : else
2922 61616 : pCurNode = (SwTxtNode*)pCurNode->AppendNode( rPos );
2923 :
2924 61880 : rPos.nNode++;
2925 61880 : rPos.nContent.Assign( pCurNode, 0 );
2926 :
2927 61880 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2928 : {
2929 3760 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoInsert( rPos.nNode ) );
2930 : }
2931 :
2932 : // To-Do - add 'SwExtraRedlineTbl' also ?
2933 61880 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() || (!m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() ))
2934 : {
2935 776 : SwPaM aPam( rPos );
2936 776 : aPam.SetMark();
2937 776 : aPam.Move( fnMoveBackward );
2938 776 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() )
2939 26 : m_rSwdoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
2940 : else
2941 750 : m_rSwdoc.getIDocumentRedlineAccess().SplitRedline( aPam );
2942 : }
2943 :
2944 61880 : m_rSwdoc.getIDocumentState().SetModified();
2945 61880 : return true;
2946 : }
2947 :
2948 92 : bool DocumentContentOperationsManager::ReplaceRange( SwPaM& rPam, const OUString& rStr,
2949 : const bool bRegExReplace )
2950 : {
2951 : // unfortunately replace works slightly differently from delete,
2952 : // so we cannot use lcl_DoWithBreaks here...
2953 :
2954 92 : ::std::vector<sal_Int32> Breaks;
2955 :
2956 184 : SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2957 92 : aPam.Normalize(false);
2958 92 : if (aPam.GetPoint()->nNode != aPam.GetMark()->nNode)
2959 : {
2960 0 : aPam.Move(fnMoveBackward);
2961 : }
2962 : OSL_ENSURE((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?");
2963 :
2964 92 : lcl_CalcBreaks(Breaks, aPam);
2965 :
2966 460 : while (!Breaks.empty() // skip over prefix of dummy chars
2967 276 : && (aPam.GetMark()->nContent.GetIndex() == *Breaks.begin()) )
2968 : {
2969 : // skip!
2970 0 : ++aPam.GetMark()->nContent; // always in bounds if Breaks valid
2971 0 : Breaks.erase(Breaks.begin());
2972 : }
2973 92 : *rPam.Start() = *aPam.GetMark(); // update start of original pam w/ prefix
2974 :
2975 92 : if (!Breaks.size())
2976 : {
2977 : // park aPam somewhere so it does not point to node that is deleted
2978 92 : aPam.DeleteMark();
2979 92 : *aPam.GetPoint() = SwPosition(m_rSwdoc.GetNodes().GetEndOfContent());
2980 92 : return ReplaceRangeImpl(rPam, rStr, bRegExReplace); // original pam!
2981 : }
2982 :
2983 : // Deletion must be split into several parts if the text node
2984 : // contains a text attribute with end and with dummy character
2985 : // and the selection does not contain the text attribute completely,
2986 : // but overlaps its start (left), where the dummy character is.
2987 :
2988 0 : bool bRet( true );
2989 : // iterate from end to start, to avoid invalidating the offsets!
2990 0 : ::std::vector<sal_Int32>::reverse_iterator iter( Breaks.rbegin() );
2991 : OSL_ENSURE(aPam.GetPoint() == aPam.End(), "wrong!");
2992 0 : SwPosition & rEnd( *aPam.End() );
2993 0 : SwPosition & rStart( *aPam.Start() );
2994 :
2995 : // set end of temp pam to original end (undo Move backward above)
2996 0 : rEnd = *rPam.End();
2997 : // after first deletion, rEnd will point into the original text node again!
2998 :
2999 0 : while (iter != Breaks.rend())
3000 : {
3001 0 : rStart.nContent = *iter + 1;
3002 0 : if (rEnd.nContent != rStart.nContent) // check if part is empty
3003 : {
3004 0 : bRet &= (m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn())
3005 : ? DeleteAndJoinWithRedlineImpl(aPam)
3006 0 : : DeleteAndJoinImpl(aPam, false);
3007 : }
3008 0 : rEnd.nContent = *iter;
3009 0 : ++iter;
3010 : }
3011 :
3012 0 : rStart = *rPam.Start(); // set to original start
3013 : OSL_ENSURE(rEnd.nContent > rStart.nContent, "replace part empty!");
3014 0 : if (rEnd.nContent > rStart.nContent) // check if part is empty
3015 : {
3016 0 : bRet &= ReplaceRangeImpl(aPam, rStr, bRegExReplace);
3017 : }
3018 :
3019 0 : rPam = aPam; // update original pam (is this required?)
3020 :
3021 92 : return bRet;
3022 : }
3023 :
3024 : ///Add a para for the char attribute exp...
3025 45456 : bool DocumentContentOperationsManager::InsertPoolItem(
3026 : const SwPaM &rRg,
3027 : const SfxPoolItem &rHt,
3028 : const SetAttrMode nFlags,
3029 : const bool bExpandCharToPara)
3030 : {
3031 45456 : SwDataChanged aTmp( rRg );
3032 45456 : SwUndoAttr* pUndoAttr = 0;
3033 45456 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3034 : {
3035 582 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo();
3036 582 : pUndoAttr = new SwUndoAttr( rRg, rHt, nFlags );
3037 : }
3038 :
3039 90912 : SfxItemSet aSet( m_rSwdoc.GetAttrPool(), rHt.Which(), rHt.Which() );
3040 45456 : aSet.Put( rHt );
3041 45456 : const bool bRet = lcl_InsAttr( &m_rSwdoc, rRg, aSet, nFlags, pUndoAttr, bExpandCharToPara );
3042 :
3043 45456 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3044 : {
3045 582 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( pUndoAttr );
3046 : }
3047 :
3048 45456 : if( bRet )
3049 : {
3050 45412 : m_rSwdoc.getIDocumentState().SetModified();
3051 : }
3052 90912 : return bRet;
3053 : }
3054 :
3055 199240 : bool DocumentContentOperationsManager::InsertItemSet ( const SwPaM &rRg, const SfxItemSet &rSet,
3056 : const SetAttrMode nFlags )
3057 : {
3058 199240 : SwDataChanged aTmp( rRg );
3059 199240 : SwUndoAttr* pUndoAttr = 0;
3060 199240 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3061 : {
3062 17960 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo();
3063 17960 : pUndoAttr = new SwUndoAttr( rRg, rSet, nFlags );
3064 : }
3065 :
3066 199240 : bool bRet = lcl_InsAttr( &m_rSwdoc, rRg, rSet, nFlags, pUndoAttr );
3067 :
3068 199240 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3069 : {
3070 17960 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( pUndoAttr );
3071 : }
3072 :
3073 199240 : if( bRet )
3074 178624 : m_rSwdoc.getIDocumentState().SetModified();
3075 199240 : return bRet;
3076 : }
3077 :
3078 0 : void DocumentContentOperationsManager::RemoveLeadingWhiteSpace(const SwPosition & rPos )
3079 : {
3080 0 : const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
3081 0 : if ( pTNd )
3082 : {
3083 0 : const OUString& rTxt = pTNd->GetTxt();
3084 0 : sal_Int32 nIdx = 0;
3085 0 : while (nIdx < rTxt.getLength())
3086 : {
3087 0 : sal_Unicode const cCh = rTxt[nIdx];
3088 0 : if (('\t' != cCh) && (' ' != cCh))
3089 : {
3090 0 : break;
3091 : }
3092 0 : ++nIdx;
3093 : }
3094 :
3095 0 : if ( nIdx > 0 )
3096 : {
3097 0 : SwPaM aPam(rPos);
3098 0 : aPam.GetPoint()->nContent = 0;
3099 0 : aPam.SetMark();
3100 0 : aPam.GetMark()->nContent = nIdx;
3101 0 : DeleteRange( aPam );
3102 : }
3103 : }
3104 0 : }
3105 :
3106 : // Copy method from SwDoc - "copy Flys in Flys"
3107 954 : void DocumentContentOperationsManager::CopyWithFlyInFly(
3108 : const SwNodeRange& rRg,
3109 : const sal_Int32 nEndContentIndex,
3110 : const SwNodeIndex& rInsPos,
3111 : const SwPaM* pCopiedPaM,
3112 : const bool bMakeNewFrms,
3113 : const bool bDelRedlines,
3114 : const bool bCopyFlyAtFly,
3115 : const bool bMergedFirstNode ) const
3116 : {
3117 954 : SwDoc* pDest = rInsPos.GetNode().GetDoc();
3118 :
3119 954 : _SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
3120 :
3121 1908 : SwNodeIndex aSavePos( rInsPos, -1 );
3122 954 : bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
3123 1908 : SwNodeRange aRg( rRg );
3124 954 : if ( bMergedFirstNode )
3125 10 : aRg.aStart++;
3126 954 : if ( aRg.aStart <= aRg.aEnd )
3127 954 : m_rSwdoc.GetNodes()._CopyNodes( aRg, rInsPos, bMakeNewFrms, true );
3128 954 : if ( !bMergedFirstNode )
3129 944 : ++aSavePos;
3130 954 : if ( bEndIsEqualEndPos )
3131 0 : ((SwNodeIndex&)rRg.aEnd) = aSavePos;
3132 :
3133 954 : aRedlRest.Restore();
3134 : #if OSL_DEBUG_LEVEL > 0
3135 : {
3136 : //JP 17.06.99: Bug 66973 - check count only if the selection is in
3137 : // the same section or there's no section, because sections that are
3138 : // not fully selected are not copied.
3139 : const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
3140 : SwNodeIndex aTmpI( rRg.aEnd, -1 );
3141 : const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
3142 : if( pSSectNd == pESectNd &&
3143 : !rRg.aStart.GetNode().IsSectionNode() &&
3144 : !aTmpI.GetNode().IsEndNode() )
3145 : {
3146 : // If the range starts with a SwStartNode, it isn't copied
3147 : sal_uInt16 offset = (aRg.aStart.GetNode().GetNodeType() != ND_STARTNODE) ? 1 : 0;
3148 : OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
3149 : aRg.aEnd.GetIndex() - aRg.aStart.GetIndex() - 1 + offset,
3150 : "An insufficient number of nodes were copied!" );
3151 : }
3152 : }
3153 : #endif
3154 :
3155 : {
3156 954 : ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
3157 954 : CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly, bMergedFirstNode );
3158 : }
3159 :
3160 1908 : SwNodeRange aCpyRange( aSavePos, rInsPos );
3161 :
3162 : // Also copy all bookmarks
3163 954 : if( m_rSwdoc.getIDocumentMarkAccess()->getAllMarksCount() )
3164 : {
3165 736 : SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
3166 1472 : SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
3167 :
3168 : lcl_CopyBookmarks(
3169 : pCopiedPaM != NULL ? *pCopiedPaM : aRgTmp,
3170 1472 : aCpyTmp );
3171 : }
3172 :
3173 954 : if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->getIDocumentRedlineAccess().GetRedlineMode() ))
3174 2 : lcl_DeleteRedlines( rRg, aCpyRange );
3175 :
3176 1908 : pDest->GetNodes()._DelDummyNodes( aCpyRange );
3177 954 : }
3178 :
3179 7368 : void DocumentContentOperationsManager::CopyFlyInFlyImpl(
3180 : const SwNodeRange& rRg,
3181 : const sal_Int32 nEndContentIndex,
3182 : const SwNodeIndex& rStartIdx,
3183 : const bool bCopyFlyAtFly,
3184 : const bool bMergedFirstNode ) const
3185 : {
3186 : // First collect all Flys, sort them according to their ordering number,
3187 : // and then only copy them. This maintains the ordering numbers (which are only
3188 : // managed in the DrawModel).
3189 7368 : SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
3190 7368 : ::std::set< _ZSortFly > aSet;
3191 7368 : const size_t nArrLen = m_rSwdoc.GetSpzFrmFmts()->size();
3192 :
3193 14736 : SwTextBoxHelper::SavedLink aOldTextBoxes;
3194 7368 : SwTextBoxHelper::saveLinks(*m_rSwdoc.GetSpzFrmFmts(), aOldTextBoxes);
3195 14736 : SwTextBoxHelper::SavedContent aOldContent;
3196 :
3197 31332 : for ( size_t n = 0; n < nArrLen; ++n )
3198 : {
3199 23964 : SwFrmFmt* pFmt = (*m_rSwdoc.GetSpzFrmFmts())[n];
3200 23964 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
3201 23964 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
3202 23964 : bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
3203 47586 : if ( pAPos &&
3204 8686 : ( bAtCntnt ||
3205 17372 : (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
3206 25892 : (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
3207 5762 : (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
3208 0 : ? rRg.aStart <= pAPos->nNode.GetIndex() + 1
3209 17206 : : ( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineMove()
3210 1286 : ? rRg.aStart < pAPos->nNode
3211 88364 : : rRg.aStart <= pAPos->nNode )) &&
3212 14068 : pAPos->nNode <= rRg.aEnd )
3213 : {
3214 : //frames at the last source node are not always copied:
3215 : //- if the node is empty and is the last node of the document or a table cell
3216 : // or a text frame then tey have to be copied
3217 : //- if the content index in this node is > 0 then paragph and frame bound objects are copied
3218 : //- to-character bound objects are copied if their index is <= nEndContentIndex
3219 840 : bool bAdd = false;
3220 840 : if( pAPos->nNode < rRg.aEnd )
3221 840 : bAdd = true;
3222 840 : if (!bAdd && !m_rSwdoc.getIDocumentRedlineAccess().IsRedlineMove()) // fdo#40599: not for redline move
3223 : {
3224 0 : bool bEmptyNode = false;
3225 0 : bool bLastNode = false;
3226 : // is the node empty?
3227 0 : const SwNodes& rNodes = pAPos->nNode.GetNodes();
3228 : SwTxtNode* pTxtNode;
3229 0 : if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
3230 : {
3231 0 : bEmptyNode = pTxtNode->GetTxt().isEmpty();
3232 0 : if( bEmptyNode )
3233 : {
3234 : //last node information is only necessary to know for the last TextNode
3235 0 : SwNodeIndex aTmp( pAPos->nNode );
3236 0 : ++aTmp;//goto next node
3237 0 : while (aTmp.GetNode().IsEndNode())
3238 : {
3239 0 : if( aTmp == rNodes.GetEndOfContent().GetIndex() )
3240 : {
3241 0 : bLastNode = true;
3242 0 : break;
3243 : }
3244 0 : ++aTmp;
3245 0 : }
3246 : }
3247 : }
3248 0 : bAdd = bLastNode && bEmptyNode;
3249 0 : if( !bAdd )
3250 : {
3251 0 : if( bAtCntnt )
3252 0 : bAdd = nEndContentIndex > 0;
3253 : else
3254 0 : bAdd = pAPos->nContent <= nEndContentIndex;
3255 : }
3256 : }
3257 840 : if( bAdd )
3258 : {
3259 : // Make sure draw formats don't refer to content, so that such
3260 : // content can be removed without problems.
3261 840 : SwTextBoxHelper::resetLink(pFmt, aOldContent);
3262 840 : aSet.insert( _ZSortFly( pFmt, pAnchor, nArrLen + aSet.size() ));
3263 : }
3264 : }
3265 : }
3266 :
3267 : // Store all copied (and also the newly created) frames in another array.
3268 : // They are stored as matching the originals, so that we will be later
3269 : // able to build the chains accordingly.
3270 14736 : ::std::vector< SwFrmFmt* > aVecSwFrmFmt;
3271 7368 : ::std::set< _ZSortFly >::const_iterator it=aSet.begin();
3272 :
3273 15576 : while (it != aSet.end())
3274 : {
3275 : // #i59964#
3276 : // correct determination of new anchor position
3277 840 : SwFmtAnchor aAnchor( *(*it).GetAnchor() );
3278 840 : SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
3279 : // for at-paragraph and at-character anchored objects the new anchor
3280 : // position can *not* be determined by the difference of the current
3281 : // anchor position to the start of the copied range, because not
3282 : // complete selected sections in the copied range aren't copied - see
3283 : // method <SwNodes::_CopyNodes(..)>.
3284 : // Thus, the new anchor position in the destination document is found
3285 : // by counting the text nodes.
3286 1110 : if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
3287 270 : (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
3288 : {
3289 : // First, determine number of anchor text node in the copied range.
3290 : // Note: The anchor text node *have* to be inside the copied range.
3291 840 : sal_uLong nAnchorTxtNdNumInRange( 0L );
3292 840 : bool bAnchorTxtNdFound( false );
3293 840 : SwNodeIndex aIdx( rRg.aStart );
3294 4006 : while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
3295 : {
3296 2326 : if ( aIdx.GetNode().IsTxtNode() )
3297 : {
3298 1078 : ++nAnchorTxtNdNumInRange;
3299 1078 : bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
3300 : }
3301 :
3302 2326 : ++aIdx;
3303 : }
3304 840 : if ( bMergedFirstNode )
3305 0 : nAnchorTxtNdNumInRange--;
3306 :
3307 840 : if ( !bAnchorTxtNdFound )
3308 : {
3309 : // This case can *not* happen, but to be robust take the first
3310 : // text node in the destination document.
3311 : OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
3312 0 : nAnchorTxtNdNumInRange = 1;
3313 : }
3314 : // Second, search corresponding text node in destination document
3315 : // by counting forward from start insert position <rStartIdx> the
3316 : // determined number of text nodes.
3317 840 : aIdx = rStartIdx;
3318 1680 : SwNodeIndex aAnchorNdIdx( rStartIdx );
3319 : const SwNode& aEndOfContentNd =
3320 840 : aIdx.GetNode().GetNodes().GetEndOfContent();
3321 6220 : while ( nAnchorTxtNdNumInRange > 0 &&
3322 2270 : &(aIdx.GetNode()) != &aEndOfContentNd )
3323 : {
3324 2270 : if ( aIdx.GetNode().IsTxtNode() )
3325 : {
3326 1078 : --nAnchorTxtNdNumInRange;
3327 1078 : aAnchorNdIdx = aIdx;
3328 : }
3329 :
3330 2270 : ++aIdx;
3331 : }
3332 840 : if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
3333 : {
3334 : // This case can *not* happen, but to be robust take the first
3335 : // text node in the destination document.
3336 : OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
3337 0 : aAnchorNdIdx = rStartIdx;
3338 0 : while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
3339 : {
3340 0 : ++aAnchorNdIdx;
3341 : }
3342 : }
3343 : // apply found anchor text node as new anchor position
3344 1680 : pNewPos->nNode = aAnchorNdIdx;
3345 : }
3346 : else
3347 : {
3348 0 : long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
3349 0 : SwNodeIndex aIdx( rStartIdx, nOffset );
3350 0 : pNewPos->nNode = aIdx;
3351 : }
3352 : // Set the character bound Flys back at the original character
3353 1110 : if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
3354 270 : pNewPos->nNode.GetNode().IsTxtNode() )
3355 : {
3356 270 : pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
3357 540 : pNewPos->nContent.GetIndex() );
3358 : }
3359 : else
3360 : {
3361 570 : pNewPos->nContent.Assign( 0, 0 );
3362 : }
3363 :
3364 : // Check recursion: copy content in its own frame, then don't copy it.
3365 840 : bool bMakeCpy = true;
3366 840 : if( pDest == &m_rSwdoc )
3367 : {
3368 784 : const SwFmtCntnt& rCntnt = (*it).GetFmt()->GetCntnt();
3369 : const SwStartNode* pSNd;
3370 1994 : if( rCntnt.GetCntntIdx() &&
3371 852 : 0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
3372 1636 : pSNd->GetIndex() < rStartIdx.GetIndex() &&
3373 426 : rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
3374 : {
3375 0 : bMakeCpy = false;
3376 0 : aSet.erase (it++);
3377 0 : continue;
3378 : }
3379 : }
3380 :
3381 : // Copy the format and set the new anchor
3382 840 : if( bMakeCpy )
3383 1680 : aVecSwFrmFmt.push_back( pDest->getIDocumentLayoutAccess().CopyLayoutFmt( *(*it).GetFmt(),
3384 1680 : aAnchor, false, true ) );
3385 840 : ++it;
3386 840 : }
3387 :
3388 : // Rebuild as much as possible of all chains that are available in the original,
3389 : OSL_ENSURE( aSet.size() == aVecSwFrmFmt.size(), "Missing new Flys" );
3390 7368 : if ( aSet.size() == aVecSwFrmFmt.size() )
3391 : {
3392 7368 : size_t n = 0;
3393 8208 : for (::std::set< _ZSortFly >::const_iterator nIt=aSet.begin() ; nIt != aSet.end(); ++nIt, ++n )
3394 : {
3395 840 : const SwFrmFmt *pFmtN = (*nIt).GetFmt();
3396 840 : const SwFmtChain &rChain = pFmtN->GetChain();
3397 840 : int nCnt = int(0 != rChain.GetPrev());
3398 840 : nCnt += rChain.GetNext() ? 1: 0;
3399 840 : size_t k = 0;
3400 3972 : for (::std::set< _ZSortFly >::const_iterator kIt=aSet.begin() ; kIt != aSet.end(); ++kIt, ++k )
3401 : {
3402 3132 : const SwFrmFmt *pFmtK = (*kIt).GetFmt();
3403 3132 : if ( rChain.GetPrev() == pFmtK )
3404 : {
3405 0 : ::lcl_ChainFmts( static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]),
3406 0 : static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]) );
3407 0 : --nCnt;
3408 : }
3409 3132 : else if ( rChain.GetNext() == pFmtK )
3410 : {
3411 0 : ::lcl_ChainFmts( static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]),
3412 0 : static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]) );
3413 0 : --nCnt;
3414 : }
3415 : }
3416 : }
3417 :
3418 : // Re-create content property of draw formats, knowing how old shapes
3419 : // were paired with old fly formats (aOldTextBoxes) and that aSet is
3420 : // parallel with aVecSwFrmFmt.
3421 7368 : SwTextBoxHelper::restoreLinks(aSet, aVecSwFrmFmt, aOldTextBoxes, aOldContent);
3422 7368 : }
3423 7368 : }
3424 :
3425 : /*
3426 : * Reset the text's hard formatting
3427 : */
3428 : /** @params pArgs contains the document's ChrFmtTable
3429 : * Is need for selections at the beginning/end and with no SSelection.
3430 : */
3431 120280 : bool DocumentContentOperationsManager::lcl_RstTxtAttr( const SwNodePtr& rpNd, void* pArgs )
3432 : {
3433 120280 : ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
3434 120280 : SwTxtNode * pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
3435 120280 : if( pTxtNode && pTxtNode->GetpSwpHints() )
3436 : {
3437 12426 : SwIndex aSt( pTxtNode, 0 );
3438 12426 : sal_Int32 nEnd = pTxtNode->Len();
3439 :
3440 24650 : if( &pPara->pSttNd->nNode.GetNode() == pTxtNode &&
3441 12224 : pPara->pSttNd->nContent.GetIndex() )
3442 988 : aSt = pPara->pSttNd->nContent.GetIndex();
3443 :
3444 12426 : if( &pPara->pEndNd->nNode.GetNode() == rpNd )
3445 10154 : nEnd = pPara->pEndNd->nContent.GetIndex();
3446 :
3447 12426 : if( pPara->pHistory )
3448 : {
3449 : // Save all attributes for the Undo.
3450 986 : SwRegHistory aRHst( *pTxtNode, pPara->pHistory );
3451 986 : pTxtNode->GetpSwpHints()->Register( &aRHst );
3452 986 : pTxtNode->RstTxtAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich,
3453 1972 : pPara->pDelSet, pPara->bInclRefToxMark );
3454 986 : if( pTxtNode->GetpSwpHints() )
3455 982 : pTxtNode->GetpSwpHints()->DeRegister();
3456 : }
3457 : else
3458 11440 : pTxtNode->RstTxtAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich,
3459 22880 : pPara->pDelSet, pPara->bInclRefToxMark );
3460 : }
3461 120280 : return true;
3462 : }
3463 :
3464 10090 : DocumentContentOperationsManager::~DocumentContentOperationsManager()
3465 : {
3466 10090 : }
3467 : //Private methods
3468 :
3469 455 : bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
3470 : {
3471 : OSL_ENSURE( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
3472 :
3473 : {
3474 455 : SwUndoRedlineDelete* pUndo = 0;
3475 455 : RedlineMode_t eOld = m_rSwdoc.getIDocumentRedlineAccess().GetRedlineMode();
3476 455 : m_rSwdoc.GetDocumentRedlineManager().checkRedlining( eOld );
3477 455 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3478 : {
3479 :
3480 : /* please don't translate -- for cultural reasons this comment is protected
3481 : until the redline implementation is finally fixed some day */
3482 : //JP 06.01.98: MUSS noch optimiert werden!!!
3483 0 : m_rSwdoc.getIDocumentRedlineAccess().SetRedlineMode(
3484 0 : (RedlineMode_t) ( nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ) );
3485 :
3486 0 : m_rSwdoc.GetIDocumentUndoRedo().StartUndo( UNDO_DELETE, NULL );
3487 0 : pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE );
3488 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( pUndo );
3489 : }
3490 :
3491 455 : if ( *rPam.GetPoint() != *rPam.GetMark() )
3492 34 : m_rSwdoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true );
3493 455 : m_rSwdoc.getIDocumentState().SetModified();
3494 :
3495 455 : if ( pUndo )
3496 : {
3497 0 : m_rSwdoc.GetIDocumentUndoRedo().EndUndo( UNDO_EMPTY, NULL );
3498 : // ??? why the hell is the AppendUndo not below the
3499 : // CanGrouping, so this hideous cleanup wouldn't be necessary?
3500 : // bah, this is redlining, probably changing this would break it...
3501 0 : if ( m_rSwdoc.GetIDocumentUndoRedo().DoesGroupUndo() )
3502 : {
3503 0 : SwUndo * const pLastUndo( m_rSwdoc.GetUndoManager().GetLastUndo() );
3504 0 : SwUndoRedlineDelete * const pUndoRedlineDel( dynamic_cast< SwUndoRedlineDelete* >( pLastUndo ) );
3505 0 : if ( pUndoRedlineDel )
3506 : {
3507 0 : bool const bMerged = pUndoRedlineDel->CanGrouping( *pUndo );
3508 0 : if ( bMerged )
3509 : {
3510 0 : ::sw::UndoGuard const undoGuard( m_rSwdoc.GetIDocumentUndoRedo() );
3511 0 : SwUndo const* const pDeleted = m_rSwdoc.GetUndoManager().RemoveLastUndo();
3512 : OSL_ENSURE( pDeleted == pUndo, "DeleteAndJoinWithRedlineImpl: "
3513 : "undo removed is not undo inserted?" );
3514 0 : delete pDeleted;
3515 : }
3516 : }
3517 : }
3518 : //JP 06.01.98: MUSS noch optimiert werden!!!
3519 0 : m_rSwdoc.getIDocumentRedlineAccess().SetRedlineMode( eOld );
3520 : }
3521 455 : return true;
3522 : }
3523 : }
3524 :
3525 9174 : bool DocumentContentOperationsManager::DeleteAndJoinImpl( SwPaM & rPam,
3526 : const bool bForceJoinNext )
3527 : {
3528 : bool bJoinTxt, bJoinPrev;
3529 9174 : ::sw_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
3530 : // #i100466#
3531 9174 : if ( bForceJoinNext )
3532 : {
3533 2 : bJoinPrev = false;
3534 : }
3535 :
3536 : {
3537 9174 : bool const bSuccess( DeleteRangeImpl( rPam ) );
3538 9174 : if (!bSuccess)
3539 1446 : return false;
3540 : }
3541 :
3542 7728 : if( bJoinTxt )
3543 : {
3544 5018 : ::sw_JoinText( rPam, bJoinPrev );
3545 : }
3546 :
3547 7728 : return true;
3548 : }
3549 :
3550 10044 : bool DocumentContentOperationsManager::DeleteRangeImpl(SwPaM & rPam, const bool)
3551 : {
3552 : // Move all cursors out of the deleted range, but first copy the
3553 : // passed PaM, because it could be a cursor that would be moved!
3554 10044 : SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
3555 10044 : ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
3556 :
3557 10044 : bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
3558 10044 : if (bSuccess)
3559 : { // now copy position from temp copy to given PaM
3560 7736 : *rPam.GetPoint() = *aDelPam.GetPoint();
3561 : }
3562 :
3563 10044 : return bSuccess;
3564 : }
3565 :
3566 10044 : bool DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam)
3567 : {
3568 10044 : SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
3569 :
3570 10044 : if( !rPam.HasMark() || *pStt >= *pEnd )
3571 2308 : return false;
3572 :
3573 7736 : if( m_rSwdoc.GetAutoCorrExceptWord() )
3574 : {
3575 : // if necessary the saved Word for the exception
3576 0 : if( m_rSwdoc.GetAutoCorrExceptWord()->IsDeleted() || pStt->nNode != pEnd->nNode ||
3577 0 : pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
3578 0 : !m_rSwdoc.GetAutoCorrExceptWord()->CheckDelChar( *pStt ))
3579 0 : { m_rSwdoc.DeleteAutoCorrExceptWord(); }
3580 : }
3581 :
3582 : {
3583 : // Delete all empty TextHints at the Mark's position
3584 7736 : SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
3585 : SwpHints* pHts;
3586 7736 : if( pTxtNd && 0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
3587 : {
3588 : const sal_Int32 *pEndIdx;
3589 3308 : const sal_Int32 nMkCntPos = rPam.GetMark()->nContent.GetIndex();
3590 8108 : for( size_t n = pHts->Count(); n; )
3591 : {
3592 4622 : const SwTxtAttr* pAttr = (*pHts)[ --n ];
3593 4622 : if( nMkCntPos > pAttr->GetStart() )
3594 3130 : break;
3595 :
3596 4350 : if( nMkCntPos == pAttr->GetStart() &&
3597 2678 : 0 != (pEndIdx = pAttr->End()) &&
3598 1186 : *pEndIdx == pAttr->GetStart() )
3599 1078 : pTxtNd->DestroyAttr( pHts->Cut( n ) );
3600 : }
3601 : }
3602 : }
3603 :
3604 : {
3605 : // Send DataChanged before deletion, so that we still know
3606 : // which objects are in the range.
3607 : // Afterwards they could be before/after the Position.
3608 7736 : SwDataChanged aTmp( rPam );
3609 : }
3610 :
3611 7736 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3612 : {
3613 1050 : m_rSwdoc.GetIDocumentUndoRedo().ClearRedo();
3614 1050 : bool bMerged(false);
3615 1050 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesGroupUndo())
3616 : {
3617 1050 : SwUndo *const pLastUndo( m_rSwdoc.GetUndoManager().GetLastUndo() );
3618 : SwUndoDelete *const pUndoDelete(
3619 1050 : dynamic_cast<SwUndoDelete *>(pLastUndo) );
3620 1050 : if (pUndoDelete)
3621 : {
3622 16 : bMerged = pUndoDelete->CanGrouping( &m_rSwdoc, rPam );
3623 : // if CanGrouping() returns true it's already merged
3624 : }
3625 : }
3626 1050 : if (!bMerged)
3627 : {
3628 1050 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam ) );
3629 : }
3630 :
3631 1050 : m_rSwdoc.getIDocumentState().SetModified();
3632 :
3633 1050 : return true;
3634 : }
3635 :
3636 6686 : if( !m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() )
3637 120 : m_rSwdoc.getIDocumentRedlineAccess().DeleteRedline( rPam, true, USHRT_MAX );
3638 :
3639 : // Delete and move all "Flys at the paragraph", which are within the Selection
3640 6686 : DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
3641 : _DelBookmarks(
3642 : pStt->nNode,
3643 : pEnd->nNode,
3644 : NULL,
3645 : &pStt->nContent,
3646 6686 : &pEnd->nContent);
3647 :
3648 6686 : SwNodeIndex aSttIdx( pStt->nNode );
3649 6686 : SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
3650 :
3651 : do { // middle checked loop!
3652 6686 : if( pCNd )
3653 : {
3654 6686 : SwTxtNode * pStartTxtNode( pCNd->GetTxtNode() );
3655 6686 : if ( pStartTxtNode )
3656 : {
3657 : // now move the Content to the new Node
3658 6686 : bool bOneNd = pStt->nNode == pEnd->nNode;
3659 1712 : const sal_Int32 nLen = ( bOneNd ? pEnd->nContent.GetIndex()
3660 4974 : : pCNd->Len() )
3661 13372 : - pStt->nContent.GetIndex();
3662 :
3663 : // Don't call again, if already empty
3664 6686 : if( nLen )
3665 : {
3666 1850 : pStartTxtNode->EraseText( pStt->nContent, nLen );
3667 :
3668 1850 : if( !pStartTxtNode->Len() )
3669 : {
3670 : // METADATA: remove reference if empty (consider node deleted)
3671 476 : pStartTxtNode->RemoveMetadataReference();
3672 : }
3673 : }
3674 :
3675 6686 : if( bOneNd ) // that's it
3676 1712 : break;
3677 :
3678 4974 : ++aSttIdx;
3679 : }
3680 : else
3681 : {
3682 : // So that there are no indices left registered when deleted,
3683 : // we remove a SwPaM from the Content here.
3684 0 : pStt->nContent.Assign( 0, 0 );
3685 : }
3686 : }
3687 :
3688 4974 : pCNd = pEnd->nNode.GetNode().GetCntntNode();
3689 4974 : if( pCNd )
3690 : {
3691 4974 : SwTxtNode * pEndTxtNode( pCNd->GetTxtNode() );
3692 4974 : if( pEndTxtNode )
3693 : {
3694 : // if already empty, don't call again
3695 4974 : if( pEnd->nContent.GetIndex() )
3696 : {
3697 14 : SwIndex aIdx( pCNd, 0 );
3698 14 : pEndTxtNode->EraseText( aIdx, pEnd->nContent.GetIndex() );
3699 :
3700 14 : if( !pEndTxtNode->Len() )
3701 : {
3702 : // METADATA: remove reference if empty (consider node deleted)
3703 12 : pEndTxtNode->RemoveMetadataReference();
3704 14 : }
3705 : }
3706 : }
3707 : else
3708 : {
3709 : // So that there are no indices left registered when deleted,
3710 : // we remove a SwPaM from the Content here.
3711 0 : pEnd->nContent.Assign( 0, 0 );
3712 : }
3713 : }
3714 :
3715 : // if the end is not a content node, delete it as well
3716 4974 : sal_uInt32 nEnde = pEnd->nNode.GetIndex();
3717 4974 : if( pCNd == NULL )
3718 0 : nEnde++;
3719 :
3720 4974 : if( aSttIdx != nEnde )
3721 : {
3722 : // delete the Nodes into the NodesArary
3723 300 : m_rSwdoc.GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
3724 : }
3725 :
3726 : // If the Node that contained the Cursor has been deleted,
3727 : // the Content has to be assigned to the current Content.
3728 4974 : pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
3729 9948 : pStt->nContent.GetIndex() );
3730 :
3731 : // If we deleted across Node boundaries we have to correct the PaM,
3732 : // because they are in different Nodes now.
3733 : // Also, the Selection is revoked.
3734 4974 : *pEnd = *pStt;
3735 4974 : rPam.DeleteMark();
3736 :
3737 : } while( false );
3738 :
3739 6686 : if( !m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().empty() )
3740 120 : m_rSwdoc.getIDocumentRedlineAccess().CompressRedlines();
3741 6686 : m_rSwdoc.getIDocumentState().SetModified();
3742 :
3743 6686 : return true;
3744 : }
3745 :
3746 : // It's possible to call Replace with a PaM that spans 2 paragraphs:
3747 : // search with regex for "$", then replace _all_
3748 92 : bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUString& rStr,
3749 : const bool bRegExReplace )
3750 : {
3751 92 : if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
3752 0 : return false;
3753 :
3754 : bool bJoinTxt, bJoinPrev;
3755 92 : ::sw_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
3756 :
3757 : {
3758 : // Create a copy of the Cursor in order to move all Pams from
3759 : // the other views out of the deletion range.
3760 : // Except for itself!
3761 92 : SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
3762 92 : ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
3763 :
3764 92 : SwPosition *pStt = (SwPosition*)aDelPam.Start(),
3765 92 : *pEnd = (SwPosition*)aDelPam.End();
3766 : OSL_ENSURE( pStt->nNode == pEnd->nNode ||
3767 : ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
3768 : !pEnd->nContent.GetIndex() ),
3769 : "invalid range: Point and Mark on different nodes" );
3770 92 : bool bOneNode = pStt->nNode == pEnd->nNode;
3771 :
3772 : // Own Undo?
3773 184 : OUString sRepl( rStr );
3774 92 : SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
3775 92 : sal_Int32 nStt = pStt->nContent.GetIndex();
3776 92 : sal_Int32 nEnd = bOneNode ? pEnd->nContent.GetIndex()
3777 184 : : pTxtNd->GetTxt().getLength();
3778 :
3779 184 : SwDataChanged aTmp( aDelPam );
3780 :
3781 92 : if( m_rSwdoc.getIDocumentRedlineAccess().IsRedlineOn() )
3782 : {
3783 0 : RedlineMode_t eOld = m_rSwdoc.getIDocumentRedlineAccess().GetRedlineMode();
3784 0 : m_rSwdoc.GetDocumentRedlineManager().checkRedlining(eOld);
3785 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3786 : {
3787 0 : m_rSwdoc.GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
3788 :
3789 : // If any Redline will change (split!) the node
3790 0 : const ::sw::mark::IMark* pBkmk = m_rSwdoc.getIDocumentMarkAccess()->makeMark( aDelPam, OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
3791 :
3792 : //JP 06.01.98: MUSS noch optimiert werden!!!
3793 0 : m_rSwdoc.getIDocumentRedlineAccess().SetRedlineMode(
3794 0 : (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
3795 :
3796 0 : *aDelPam.GetPoint() = pBkmk->GetMarkPos();
3797 0 : if(pBkmk->IsExpanded())
3798 0 : *aDelPam.GetMark() = pBkmk->GetOtherMarkPos();
3799 0 : m_rSwdoc.getIDocumentMarkAccess()->deleteMark(pBkmk);
3800 0 : pStt = aDelPam.Start();
3801 0 : pTxtNd = pStt->nNode.GetNode().GetTxtNode();
3802 0 : nStt = pStt->nContent.GetIndex();
3803 : }
3804 :
3805 0 : if( !sRepl.isEmpty() )
3806 : {
3807 : // Apply the first character's attributes to the ReplaceText
3808 0 : SfxItemSet aSet( m_rSwdoc.GetAttrPool(),
3809 : RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1,
3810 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
3811 0 : 0 );
3812 0 : pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
3813 :
3814 0 : aSet.ClearItem( RES_TXTATR_REFMARK );
3815 0 : aSet.ClearItem( RES_TXTATR_TOXMARK );
3816 0 : aSet.ClearItem( RES_TXTATR_CJK_RUBY );
3817 0 : aSet.ClearItem( RES_TXTATR_INETFMT );
3818 0 : aSet.ClearItem( RES_TXTATR_META );
3819 0 : aSet.ClearItem( RES_TXTATR_METAFIELD );
3820 :
3821 0 : if( aDelPam.GetPoint() != aDelPam.End() )
3822 0 : aDelPam.Exchange();
3823 :
3824 : // Remember the End
3825 0 : SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
3826 0 : const sal_Int32 nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
3827 :
3828 0 : bool bFirst = true;
3829 0 : OUString sIns;
3830 0 : while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
3831 : {
3832 0 : InsertString( aDelPam, sIns );
3833 0 : if( bFirst )
3834 : {
3835 0 : SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
3836 0 : const sal_Int32 nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
3837 :
3838 0 : SplitNode( *aDelPam.GetPoint(), false );
3839 :
3840 0 : ++aMkNd;
3841 0 : aDelPam.GetMark()->nNode = aMkNd;
3842 0 : aDelPam.GetMark()->nContent.Assign(
3843 0 : aMkNd.GetNode().GetCntntNode(), nMkCnt );
3844 0 : bFirst = false;
3845 : }
3846 : else
3847 0 : SplitNode( *aDelPam.GetPoint(), false );
3848 : }
3849 0 : if( !sIns.isEmpty() )
3850 : {
3851 0 : InsertString( aDelPam, sIns );
3852 : }
3853 :
3854 0 : SwPaM aTmpRange( *aDelPam.GetPoint() );
3855 0 : aTmpRange.SetMark();
3856 :
3857 0 : ++aPtNd;
3858 0 : aDelPam.GetPoint()->nNode = aPtNd;
3859 0 : aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
3860 0 : nPtCnt);
3861 0 : *aTmpRange.GetMark() = *aDelPam.GetPoint();
3862 :
3863 0 : m_rSwdoc.RstTxtAttrs( aTmpRange );
3864 0 : InsertItemSet( aTmpRange, aSet, 0 );
3865 : }
3866 :
3867 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3868 : {
3869 : SwUndo *const pUndoRD =
3870 0 : new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE );
3871 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndoRD);
3872 : }
3873 0 : m_rSwdoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, aDelPam ), true);
3874 :
3875 0 : *rPam.GetMark() = *aDelPam.GetMark();
3876 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
3877 : {
3878 0 : *aDelPam.GetPoint() = *rPam.GetPoint();
3879 0 : m_rSwdoc.GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
3880 :
3881 : // If any Redline will change (split!) the node
3882 0 : const ::sw::mark::IMark* pBkmk = m_rSwdoc.getIDocumentMarkAccess()->makeMark( aDelPam, OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
3883 :
3884 0 : SwIndex& rIdx = aDelPam.GetPoint()->nContent;
3885 0 : rIdx.Assign( 0, 0 );
3886 0 : aDelPam.GetMark()->nContent = rIdx;
3887 0 : rPam.GetPoint()->nNode = 0;
3888 0 : rPam.GetPoint()->nContent = rIdx;
3889 0 : *rPam.GetMark() = *rPam.GetPoint();
3890 : //JP 06.01.98: MUSS noch optimiert werden!!!
3891 0 : m_rSwdoc.getIDocumentRedlineAccess().SetRedlineMode( eOld );
3892 :
3893 0 : *rPam.GetPoint() = pBkmk->GetMarkPos();
3894 0 : if(pBkmk->IsExpanded())
3895 0 : *rPam.GetMark() = pBkmk->GetOtherMarkPos();
3896 0 : m_rSwdoc.getIDocumentMarkAccess()->deleteMark(pBkmk);
3897 : }
3898 0 : bJoinTxt = false;
3899 : }
3900 : else
3901 : {
3902 92 : if( !m_rSwdoc.getIDocumentRedlineAccess().IsIgnoreRedline() && m_rSwdoc.getIDocumentRedlineAccess().GetRedlineTbl().size() )
3903 0 : m_rSwdoc.getIDocumentRedlineAccess().DeleteRedline( aDelPam, true, USHRT_MAX );
3904 :
3905 92 : SwUndoReplace* pUndoRpl = 0;
3906 92 : bool const bDoesUndo = m_rSwdoc.GetIDocumentUndoRedo().DoesUndo();
3907 92 : if (bDoesUndo)
3908 : {
3909 92 : pUndoRpl = new SwUndoReplace(aDelPam, sRepl, bRegExReplace);
3910 92 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndoRpl);
3911 : }
3912 92 : ::sw::UndoGuard const undoGuard(m_rSwdoc.GetIDocumentUndoRedo());
3913 :
3914 92 : if( aDelPam.GetPoint() != pStt )
3915 90 : aDelPam.Exchange();
3916 :
3917 184 : SwNodeIndex aPtNd( pStt->nNode, -1 );
3918 92 : const sal_Int32 nPtCnt = pStt->nContent.GetIndex();
3919 :
3920 : // Set the values again, if Frames or footnotes on the Text have been removed.
3921 92 : nStt = nPtCnt;
3922 92 : nEnd = bOneNode ? pEnd->nContent.GetIndex()
3923 184 : : pTxtNd->GetTxt().getLength();
3924 :
3925 92 : bool bFirst = true;
3926 184 : OUString sIns;
3927 184 : while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
3928 : {
3929 0 : if (!bFirst || nStt == pTxtNd->GetTxt().getLength())
3930 : {
3931 0 : InsertString( aDelPam, sIns );
3932 : }
3933 0 : else if( nStt < nEnd || !sIns.isEmpty() )
3934 : {
3935 0 : pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
3936 : }
3937 0 : SplitNode( *pStt, false);
3938 0 : bFirst = false;
3939 : }
3940 :
3941 92 : if( bFirst || !sIns.isEmpty() )
3942 : {
3943 92 : if (!bFirst || nStt == pTxtNd->GetTxt().getLength())
3944 : {
3945 0 : InsertString( aDelPam, sIns );
3946 : }
3947 92 : else if( nStt < nEnd || !sIns.isEmpty() )
3948 : {
3949 92 : pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
3950 : }
3951 : }
3952 :
3953 92 : *rPam.GetPoint() = *aDelPam.GetMark();
3954 92 : ++aPtNd;
3955 92 : rPam.GetMark()->nNode = aPtNd;
3956 184 : rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
3957 184 : nPtCnt );
3958 :
3959 92 : if (bJoinTxt)
3960 : {
3961 : assert(rPam.GetPoint() == rPam.End());
3962 : // move so that SetEnd remembers position after sw_JoinText
3963 0 : rPam.Move(fnMoveBackward);
3964 : }
3965 92 : else if (aDelPam.GetPoint() == pStt) // backward selection?
3966 : {
3967 : assert(*rPam.GetMark() <= *rPam.GetPoint());
3968 92 : rPam.Exchange(); // swap so that rPam is backwards
3969 : }
3970 :
3971 92 : if( pUndoRpl )
3972 : {
3973 92 : pUndoRpl->SetEnd(rPam);
3974 92 : }
3975 92 : }
3976 : }
3977 :
3978 92 : if( bJoinTxt )
3979 0 : ::sw_JoinText( rPam, bJoinPrev );
3980 :
3981 92 : m_rSwdoc.getIDocumentState().SetModified();
3982 92 : return true;
3983 : }
3984 :
3985 1676 : SwFlyFrmFmt* DocumentContentOperationsManager::_InsNoTxtNode( const SwPosition& rPos, SwNoTxtNode* pNode,
3986 : const SfxItemSet* pFlyAttrSet,
3987 : const SfxItemSet* pGrfAttrSet,
3988 : SwFrmFmt* pFrmFmt)
3989 : {
3990 1676 : SwFlyFrmFmt *pFmt = 0;
3991 1676 : if( pNode )
3992 : {
3993 : pFmt = m_rSwdoc._MakeFlySection( rPos, *pNode, FLY_AT_PARA,
3994 1676 : pFlyAttrSet, pFrmFmt );
3995 1676 : if( pGrfAttrSet )
3996 818 : pNode->SetAttr( *pGrfAttrSet );
3997 : }
3998 1676 : return pFmt;
3999 : }
4000 :
4001 : #define NUMRULE_STATE \
4002 : SfxItemState aNumRuleState = SfxItemState::UNKNOWN; \
4003 : SwNumRuleItem aNumRuleItem; \
4004 : SfxItemState aListIdState = SfxItemState::UNKNOWN; \
4005 : SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() ); \
4006 :
4007 : #define PUSH_NUMRULE_STATE \
4008 : lcl_PushNumruleState( aNumRuleState, aNumRuleItem, aListIdState, aListIdItem, pDestTxtNd );
4009 :
4010 : #define POP_NUMRULE_STATE \
4011 : lcl_PopNumruleState( aNumRuleState, aNumRuleItem, aListIdState, aListIdItem, pDestTxtNd, rPam );
4012 :
4013 396 : static void lcl_PushNumruleState( SfxItemState &aNumRuleState, SwNumRuleItem &aNumRuleItem,
4014 : SfxItemState &aListIdState, SfxStringItem &aListIdItem,
4015 : const SwTxtNode *pDestTxtNd )
4016 : {
4017 : // Safe numrule item at destination.
4018 : // #i86492# - Safe also <ListId> item of destination.
4019 396 : const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
4020 396 : if (pAttrSet != NULL)
4021 : {
4022 0 : const SfxPoolItem * pItem = NULL;
4023 0 : aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
4024 0 : if (SfxItemState::SET == aNumRuleState)
4025 0 : aNumRuleItem = *((SwNumRuleItem *) pItem);
4026 :
4027 : aListIdState =
4028 0 : pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
4029 0 : if (SfxItemState::SET == aListIdState)
4030 : {
4031 0 : aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
4032 : }
4033 : }
4034 396 : }
4035 :
4036 158 : static void lcl_PopNumruleState( SfxItemState aNumRuleState, const SwNumRuleItem &aNumRuleItem,
4037 : SfxItemState aListIdState, const SfxStringItem &aListIdItem,
4038 : SwTxtNode *pDestTxtNd, const SwPaM& rPam )
4039 : {
4040 : /* If only a part of one paragraph is copied
4041 : restore the numrule at the destination. */
4042 : // #i86492# - restore also <ListId> item
4043 158 : if ( !lcl_MarksWholeNode(rPam) )
4044 : {
4045 4 : if (SfxItemState::SET == aNumRuleState)
4046 : {
4047 0 : pDestTxtNd->SetAttr(aNumRuleItem);
4048 : }
4049 : else
4050 : {
4051 4 : pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
4052 : }
4053 4 : if (SfxItemState::SET == aListIdState)
4054 : {
4055 0 : pDestTxtNd->SetAttr(aListIdItem);
4056 : }
4057 : else
4058 : {
4059 4 : pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
4060 : }
4061 : }
4062 158 : }
4063 :
4064 406 : bool DocumentContentOperationsManager::CopyImpl( SwPaM& rPam, SwPosition& rPos,
4065 : const bool bMakeNewFrms, const bool bCopyAll,
4066 : SwPaM *const pCpyRange ) const
4067 : {
4068 406 : SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
4069 406 : const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
4070 :
4071 406 : SwPosition* pStt = rPam.Start();
4072 406 : SwPosition* pEnd = rPam.End();
4073 :
4074 : // Catch when there's no copy to do.
4075 812 : if( !rPam.HasMark() || ( *pStt > *pEnd && !bColumnSel ) ||
4076 : //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
4077 : //JP 15.11.2001: don't test inclusive the end, ever exclusive
4078 776 : ( pDoc == &m_rSwdoc && *pStt <= rPos && rPos < *pEnd ))
4079 : {
4080 0 : return false;
4081 : }
4082 :
4083 406 : const bool bEndEqualIns = pDoc == &m_rSwdoc && rPos == *pEnd;
4084 :
4085 : // If Undo is enabled, create the UndoCopy object
4086 406 : SwUndoCpyDoc* pUndo = 0;
4087 : // lcl_DeleteRedlines may delete the start or end node of the cursor when
4088 : // removing the redlines so use cursor that is corrected by PaMCorrAbs
4089 406 : ::boost::scoped_ptr<SwUnoCrsr> const pCopyPam(pDoc->CreateUnoCrsr(rPos));
4090 :
4091 812 : SwTblNumFmtMerge aTNFM( m_rSwdoc, *pDoc );
4092 :
4093 406 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
4094 : {
4095 18 : pUndo = new SwUndoCpyDoc(*pCopyPam);
4096 18 : pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
4097 : }
4098 :
4099 406 : RedlineMode_t eOld = pDoc->getIDocumentRedlineAccess().GetRedlineMode();
4100 406 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
4101 :
4102 : // Move the PaM one node back from the insert position, so that
4103 : // the position doesn't get moved
4104 406 : pCopyPam->SetMark();
4105 406 : bool bCanMoveBack = pCopyPam->Move(fnMoveBackward, fnGoCntnt);
4106 : // If the position was shifted from more than one node, an end node has been skipped
4107 406 : bool bAfterTable = false;
4108 406 : if ((rPos.nNode.GetIndex() - pCopyPam->GetPoint()->nNode.GetIndex()) > 1)
4109 : {
4110 : // First go back to the original place
4111 0 : pCopyPam->GetPoint()->nNode = rPos.nNode;
4112 0 : pCopyPam->GetPoint()->nContent = rPos.nContent;
4113 :
4114 0 : bCanMoveBack = false;
4115 0 : bAfterTable = true;
4116 : }
4117 406 : if( !bCanMoveBack )
4118 384 : pCopyPam->GetPoint()->nNode--;
4119 :
4120 812 : SwNodeRange aRg( pStt->nNode, pEnd->nNode );
4121 812 : SwNodeIndex aInsPos( rPos.nNode );
4122 406 : const bool bOneNode = pStt->nNode == pEnd->nNode;
4123 406 : SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
4124 406 : SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
4125 406 : SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
4126 802 : bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
4127 400 : ( (pDestTxtNd && !pDestTxtNd->GetTxt().getLength()) ||
4128 450 : ( !bOneNode && !rPos.nContent.GetIndex() ) );
4129 406 : bool bCopyBookmarks = true;
4130 406 : bool bStartIsTxtNode = 0 != pSttTxtNd;
4131 :
4132 : // #i104585# copy outline num rule to clipboard (for ASCII filter)
4133 406 : if (pDoc->IsClipBoard() && m_rSwdoc.GetOutlineNumRule())
4134 : {
4135 4 : pDoc->SetOutlineNumRule(*m_rSwdoc.GetOutlineNumRule());
4136 : }
4137 :
4138 : // #i86492#
4139 : // Correct the search for a previous list:
4140 : // First search for non-outline numbering list. Then search for non-outline
4141 : // bullet list.
4142 : // Keep also the <ListId> value for possible propagation.
4143 812 : OUString aListIdToPropagate;
4144 : const SwNumRule* pNumRuleToPropagate =
4145 406 : pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
4146 406 : if ( !pNumRuleToPropagate )
4147 : {
4148 : pNumRuleToPropagate =
4149 406 : pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
4150 : }
4151 : // #i86492#
4152 : // Do not propagate previous found list, if
4153 : // - destination is an empty paragraph which is not in a list and
4154 : // - source contains at least one paragraph which is not in a list
4155 410 : if ( pNumRuleToPropagate &&
4156 8 : pDestTxtNd && !pDestTxtNd->GetTxt().getLength() &&
4157 414 : !pDestTxtNd->IsInList() &&
4158 4 : !lcl_ContainsOnlyParagraphsInList( rPam ) )
4159 : {
4160 4 : pNumRuleToPropagate = 0;
4161 : }
4162 :
4163 406 : bool bHandledStartNode = false;
4164 :
4165 : // This do/while block is only there so that we can break out of it!
4166 : do {
4167 406 : if( pSttTxtNd )
4168 : {
4169 : // Don't copy the beginning completely?
4170 384 : if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
4171 : {
4172 14 : bHandledStartNode = true;
4173 :
4174 14 : SwIndex aDestIdx( rPos.nContent );
4175 14 : bool bCopyOk = false;
4176 14 : if( !pDestTxtNd )
4177 : {
4178 0 : if( pStt->nContent.GetIndex() || bOneNode )
4179 0 : pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
4180 0 : pDoc->getIDocumentStylePoolAccess().GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
4181 : else
4182 : {
4183 0 : pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
4184 0 : bCopyOk = true;
4185 : }
4186 0 : aDestIdx.Assign( pDestTxtNd, 0 );
4187 0 : bCopyCollFmt = true;
4188 : }
4189 14 : else if( !bOneNode || bColumnSel )
4190 : {
4191 10 : const sal_Int32 nCntntEnd = pEnd->nContent.GetIndex();
4192 : {
4193 10 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
4194 10 : pDoc->getIDocumentContentOperations().SplitNode( rPos, false );
4195 : }
4196 :
4197 10 : if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
4198 : {
4199 : // after the SplitNode, span the CpyPam correctly again
4200 2 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
4201 2 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
4202 : }
4203 :
4204 10 : pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
4205 : aDestIdx.Assign(
4206 10 : pDestTxtNd, pDestTxtNd->GetTxt().getLength());
4207 :
4208 : // Correct the area again
4209 10 : if( bEndEqualIns )
4210 : {
4211 0 : bool bChg = pEnd != rPam.GetPoint();
4212 0 : if( bChg )
4213 0 : rPam.Exchange();
4214 0 : rPam.Move( fnMoveBackward, fnGoCntnt );
4215 0 : if( bChg )
4216 0 : rPam.Exchange();
4217 :
4218 0 : aRg.aEnd = pEnd->nNode;
4219 0 : pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
4220 : }
4221 10 : else if( rPos == *pEnd )
4222 : {
4223 : // The end was also moved
4224 0 : pEnd->nNode--;
4225 0 : pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
4226 0 : aRg.aEnd = pEnd->nNode;
4227 0 : pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
4228 : }
4229 : }
4230 :
4231 28 : NUMRULE_STATE
4232 14 : if( bCopyCollFmt && bOneNode )
4233 : {
4234 4 : PUSH_NUMRULE_STATE
4235 : }
4236 :
4237 14 : if( !bCopyOk )
4238 : {
4239 : const sal_Int32 nCpyLen = ( (bOneNode)
4240 4 : ? pEnd->nContent.GetIndex()
4241 10 : : pSttTxtNd->GetTxt().getLength())
4242 28 : - pStt->nContent.GetIndex();
4243 : pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
4244 14 : pStt->nContent, nCpyLen );
4245 14 : if( bEndEqualIns )
4246 0 : pEnd->nContent -= nCpyLen;
4247 : }
4248 :
4249 14 : if( bCopyCollFmt && bOneNode )
4250 : {
4251 4 : pSttTxtNd->CopyCollFmt( *pDestTxtNd );
4252 4 : POP_NUMRULE_STATE
4253 14 : }
4254 : }
4255 : }
4256 22 : else if( pDestTxtNd )
4257 : {
4258 : // Problems with insertion of table selections into "normal" text solved.
4259 : // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
4260 : // the undo operation will try to merge this node after removing the table.
4261 : // If we didn't split a textnode, the PaM should start at the inserted table node
4262 2 : if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
4263 : { // Insertion at the last position of a textnode (empty or not)
4264 2 : ++aInsPos; // The table will be inserted behind the text node
4265 : }
4266 0 : else if( rPos.nContent.GetIndex() )
4267 : { // Insertion in the middle of a text node, it has to be split
4268 : // (and joined from undo)
4269 0 : bStartIsTxtNode = true;
4270 :
4271 0 : const sal_Int32 nCntntEnd = pEnd->nContent.GetIndex();
4272 : {
4273 0 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
4274 0 : pDoc->getIDocumentContentOperations().SplitNode( rPos, false );
4275 : }
4276 :
4277 0 : if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
4278 : {
4279 : // after the SplitNode, span the CpyPam correctly again
4280 0 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
4281 0 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
4282 : }
4283 :
4284 : // Correct the area again
4285 0 : if( bEndEqualIns )
4286 0 : aRg.aEnd--;
4287 : // The end would also be moved
4288 0 : else if( rPos == *pEnd )
4289 : {
4290 0 : rPos.nNode-=2;
4291 0 : rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
4292 0 : nCntntEnd );
4293 0 : rPos.nNode++;
4294 0 : aRg.aEnd--;
4295 : }
4296 : }
4297 0 : else if( bCanMoveBack )
4298 : { //Insertion at the first position of a text node. It will not be splitted, the table
4299 : // will be inserted before the text node.
4300 : // See below, before the SetInsertRange funciton of the undo object will be called,
4301 : // the CpyPam would be moved to the next content position. This has to be avoided
4302 : // We want to be moved to the table node itself thus we have to set bCanMoveBack
4303 : // and to manipulate pCopyPam.
4304 0 : bCanMoveBack = false;
4305 0 : pCopyPam->GetPoint()->nNode--;
4306 : }
4307 : }
4308 :
4309 406 : pDestTxtNd = aInsPos.GetNode().GetTxtNode();
4310 406 : if( pEndTxtNd && (!bOneNode || !bHandledStartNode) )
4311 : {
4312 402 : SwIndex aDestIdx( rPos.nContent );
4313 402 : if( !pDestTxtNd )
4314 : {
4315 22 : pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
4316 44 : pDoc->getIDocumentStylePoolAccess().GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
4317 22 : aDestIdx.Assign( pDestTxtNd, 0 );
4318 22 : aInsPos--;
4319 :
4320 : // if we have to insert an extra text node
4321 : // at the destination, this node will be our new destination
4322 : // (text) node, and thus we set bStartisTxtNode to true. This
4323 : // will ensure that this node will be deleted during Undo
4324 : // using JoinNext.
4325 : OSL_ENSURE( !bStartIsTxtNode, "Oops, undo may be instable now." );
4326 22 : bStartIsTxtNode = true;
4327 : }
4328 :
4329 402 : const bool bEmptyDestNd = pDestTxtNd->GetTxt().isEmpty();
4330 :
4331 804 : NUMRULE_STATE
4332 402 : if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
4333 : {
4334 392 : PUSH_NUMRULE_STATE
4335 : }
4336 :
4337 402 : pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
4338 804 : pEnd->nContent.GetIndex() );
4339 :
4340 : // Also copy all format templates
4341 402 : if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
4342 : {
4343 392 : pEndTxtNd->CopyCollFmt( *pDestTxtNd );
4344 392 : if ( bOneNode )
4345 : {
4346 154 : POP_NUMRULE_STATE
4347 : }
4348 402 : }
4349 : }
4350 :
4351 406 : if( bCopyAll || aRg.aStart != aRg.aEnd )
4352 : {
4353 248 : SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
4354 248 : if( !bOneNode && pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
4355 : {
4356 150 : aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
4357 150 : if( SfxItemState::SET == aBrkSet.GetItemState( RES_BREAK, false ) )
4358 0 : pDestTxtNd->ResetAttr( RES_BREAK );
4359 150 : if( SfxItemState::SET == aBrkSet.GetItemState( RES_PAGEDESC, false ) )
4360 0 : pDestTxtNd->ResetAttr( RES_PAGEDESC );
4361 : }
4362 :
4363 248 : if( aInsPos == pEnd->nNode )
4364 : {
4365 0 : SwNodeIndex aSaveIdx( aInsPos, -1 );
4366 : CopyWithFlyInFly( aRg, 0, aInsPos, &rPam, bMakeNewFrms,
4367 0 : false, false, bHandledStartNode );
4368 0 : ++aSaveIdx;
4369 0 : pEnd->nNode = aSaveIdx;
4370 0 : pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
4371 : }
4372 : else
4373 : CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &rPam,
4374 248 : bMakeNewFrms, false, false, bHandledStartNode );
4375 :
4376 248 : bCopyBookmarks = false;
4377 :
4378 : // Put the breaks back into the first node
4379 248 : if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
4380 0 : pCopyPam->GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode()))
4381 : {
4382 0 : pDestTxtNd->SetAttr( aBrkSet );
4383 248 : }
4384 : }
4385 : } while( false );
4386 :
4387 : // Adjust position (in case it was moved / in another node)
4388 406 : rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
4389 812 : rPos.nContent.GetIndex() );
4390 :
4391 406 : if( rPos.nNode != aInsPos )
4392 : {
4393 22 : pCopyPam->GetMark()->nNode = aInsPos;
4394 22 : pCopyPam->GetMark()->nContent.Assign(pCopyPam->GetCntntNode(false), 0);
4395 22 : rPos = *pCopyPam->GetMark();
4396 : }
4397 : else
4398 384 : *pCopyPam->GetMark() = rPos;
4399 :
4400 406 : if ( !bAfterTable )
4401 406 : pCopyPam->Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
4402 : else
4403 : {
4404 : // Reset the offset to 0 as it was before the insertion
4405 0 : pCopyPam->GetPoint()->nContent -= pCopyPam->GetPoint()->nContent;
4406 :
4407 0 : pCopyPam->GetPoint()->nNode++;
4408 : // If the next node is a start node, then step back: the start node
4409 : // has been copied and needs to be in the selection for the undo
4410 0 : if (pCopyPam->GetPoint()->nNode.GetNode().IsStartNode())
4411 0 : pCopyPam->GetPoint()->nNode--;
4412 :
4413 : }
4414 406 : pCopyPam->Exchange();
4415 :
4416 : // Also copy all bookmarks
4417 406 : if( bCopyBookmarks && m_rSwdoc.getIDocumentMarkAccess()->getAllMarksCount() )
4418 136 : lcl_CopyBookmarks( rPam, *pCopyPam );
4419 :
4420 406 : if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
4421 : {
4422 : assert(*pCopyPam->GetPoint() == rPos);
4423 : // the Node rPos points to may be deleted so unregister ...
4424 4 : rPos.nContent = SwIndex(0);
4425 4 : lcl_DeleteRedlines(rPam, *pCopyPam);
4426 4 : rPos = *pCopyPam->GetPoint(); // ... and restore.
4427 : }
4428 :
4429 : // If Undo is enabled, store the inserted area
4430 406 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
4431 : {
4432 18 : pUndo->SetInsertRange( *pCopyPam, true, bStartIsTxtNode );
4433 : }
4434 :
4435 406 : if( pCpyRange )
4436 : {
4437 10 : pCpyRange->SetMark();
4438 10 : *pCpyRange->GetPoint() = *pCopyPam->GetPoint();
4439 10 : *pCpyRange->GetMark() = *pCopyPam->GetMark();
4440 : }
4441 :
4442 406 : if ( pNumRuleToPropagate != NULL )
4443 : {
4444 : // #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
4445 0 : pDoc->SetNumRule( *pCopyPam, *pNumRuleToPropagate, false,
4446 0 : aListIdToPropagate, true, true );
4447 : }
4448 :
4449 406 : pDoc->getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
4450 406 : pDoc->getIDocumentState().SetModified();
4451 :
4452 812 : return true;
4453 : }
4454 :
4455 :
4456 270 : }
4457 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|