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