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 :
20 : #include <editeng/formatbreakitem.hxx>
21 :
22 : #include <hintids.hxx>
23 : #include <fmtpdsc.hxx>
24 : #include <fmtanchr.hxx>
25 : #include <fmtcntnt.hxx>
26 : #include <doc.hxx>
27 : #include <IDocumentUndoRedo.hxx>
28 : #include <pam.hxx>
29 : #include <ndtxt.hxx>
30 : #include <fldbas.hxx>
31 : #include <swtable.hxx>
32 : #include <ddefld.hxx>
33 : #include <unocrsr.hxx>
34 : #include <undobj.hxx>
35 : #include <IMark.hxx>
36 : #include <mvsave.hxx>
37 : #include <cellatr.hxx>
38 : #include <swtblfmt.hxx>
39 : #include <swddetbl.hxx>
40 : #include <docary.hxx>
41 : #include <fmtcnct.hxx>
42 : #include <redline.hxx>
43 : #include <paratr.hxx>
44 : #include <pagedesc.hxx>
45 : #include <poolfmt.hxx>
46 : #include <SwNodeNum.hxx>
47 : #include <set>
48 : #include <vector>
49 : #include <boost/foreach.hpp>
50 :
51 : #ifdef DBG_UTIL
52 : #define CHECK_TABLE(t) (t).CheckConsistency();
53 : #else
54 : #define CHECK_TABLE(t)
55 : #endif
56 :
57 : namespace
58 : {
59 : /*
60 : The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
61 : array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
62 : 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.
63 : The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
64 : index inside the pam.
65 : rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
66 : of "non-copy" nodes between rPam.Start() and rLastIdx.
67 : nNewIdx is the new position of interest.
68 : */
69 :
70 0 : static void lcl_NonCopyCount( const SwPaM& rPam, SwNodeIndex& rLastIdx, const sal_uLong nNewIdx, sal_uLong& rDelCount )
71 : {
72 0 : sal_uLong nStart = rPam.Start()->nNode.GetIndex();
73 0 : sal_uLong nEnd = rPam.End()->nNode.GetIndex();
74 0 : if( rLastIdx.GetIndex() < nNewIdx ) // Moving forward?
75 : {
76 0 : do // count "non-copy" nodes
77 : {
78 0 : SwNode& rNode = rLastIdx.GetNode();
79 0 : if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
80 0 : || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
81 0 : ++rDelCount;
82 0 : ++rLastIdx;
83 : }
84 0 : while( rLastIdx.GetIndex() < nNewIdx );
85 : }
86 0 : else if( rDelCount ) // optimization: if there are no "non-copy" nodes until now,
87 : // no move backward needed
88 : {
89 0 : while( rLastIdx.GetIndex() > nNewIdx )
90 : {
91 0 : SwNode& rNode = rLastIdx.GetNode();
92 0 : if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
93 0 : || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
94 0 : --rDelCount;
95 0 : rLastIdx--;
96 : }
97 : }
98 0 : }
99 :
100 0 : static void lcl_SetCpyPos( const SwPosition& rOrigPos,
101 : const SwPosition& rOrigStt,
102 : const SwPosition& rCpyStt,
103 : SwPosition& rChgPos,
104 : sal_uLong nDelCount )
105 : {
106 0 : sal_uLong nNdOff = rOrigPos.nNode.GetIndex();
107 0 : nNdOff -= rOrigStt.nNode.GetIndex();
108 0 : nNdOff -= nDelCount;
109 0 : sal_Int32 nCntntPos = rOrigPos.nContent.GetIndex();
110 :
111 : // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
112 0 : rChgPos.nNode = nNdOff + rCpyStt.nNode.GetIndex();
113 0 : if( !nNdOff )
114 : {
115 : // dann nur den Content anpassen
116 0 : if( nCntntPos > rOrigStt.nContent.GetIndex() )
117 0 : nCntntPos -= rOrigStt.nContent.GetIndex();
118 : else
119 0 : nCntntPos = 0;
120 0 : nCntntPos += rCpyStt.nContent.GetIndex();
121 : }
122 0 : rChgPos.nContent.Assign( rChgPos.nNode.GetNode().GetCntntNode(), nCntntPos );
123 0 : }
124 :
125 : // TODO: use SaveBookmark (from _DelBookmarks)
126 0 : static void lcl_CopyBookmarks(
127 : const SwPaM& rPam,
128 : SwPaM& rCpyPam )
129 : {
130 0 : const SwDoc* pSrcDoc = rPam.GetDoc();
131 0 : SwDoc* pDestDoc = rCpyPam.GetDoc();
132 0 : const IDocumentMarkAccess* const pSrcMarkAccess = pSrcDoc->getIDocumentMarkAccess();
133 0 : ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
134 :
135 0 : const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
136 0 : SwPosition* pCpyStt = rCpyPam.Start();
137 :
138 : typedef ::std::vector< const ::sw::mark::IMark* > mark_vector_t;
139 0 : mark_vector_t vMarksToCopy;
140 0 : for ( IDocumentMarkAccess::const_iterator_t ppMark = pSrcMarkAccess->getAllMarksBegin();
141 0 : ppMark != pSrcMarkAccess->getAllMarksEnd();
142 : ++ppMark )
143 : {
144 0 : const ::sw::mark::IMark* const pMark = ppMark->get();
145 :
146 0 : const SwPosition& rMarkStart = pMark->GetMarkStart();
147 0 : const SwPosition& rMarkEnd = pMark->GetMarkEnd();
148 : // only include marks that are in the range and not touching both start and end
149 : // - not for annotation marks.
150 : const bool bIsNotOnBoundary =
151 0 : pMark->IsExpanded()
152 0 : ? (rMarkStart != rStt || rMarkEnd != rEnd) // rMarkStart != rMarkEnd
153 0 : : (rMarkStart != rStt && rMarkEnd != rEnd); // rMarkStart == rMarkEnd
154 0 : if ( rMarkStart >= rStt && rMarkEnd <= rEnd
155 0 : && ( bIsNotOnBoundary
156 0 : || IDocumentMarkAccess::GetType( *pMark ) == IDocumentMarkAccess::ANNOTATIONMARK ) )
157 : {
158 0 : vMarksToCopy.push_back(pMark);
159 : }
160 : }
161 : // We have to count the "non-copied" nodes..
162 0 : SwNodeIndex aCorrIdx(rStt.nNode);
163 0 : sal_uLong nDelCount = 0;
164 0 : for(mark_vector_t::const_iterator ppMark = vMarksToCopy.begin();
165 0 : ppMark != vMarksToCopy.end();
166 : ++ppMark)
167 : {
168 0 : const ::sw::mark::IMark* const pMark = *ppMark;
169 0 : SwPaM aTmpPam(*pCpyStt);
170 0 : lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetMarkPos().nNode.GetIndex(), nDelCount);
171 0 : lcl_SetCpyPos( pMark->GetMarkPos(), rStt, *pCpyStt, *aTmpPam.GetPoint(), nDelCount);
172 0 : if(pMark->IsExpanded())
173 : {
174 0 : aTmpPam.SetMark();
175 0 : lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetOtherMarkPos().nNode.GetIndex(), nDelCount);
176 0 : lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount);
177 : }
178 :
179 0 : ::sw::mark::IMark* const pNewMark = pDestDoc->getIDocumentMarkAccess()->makeMark(
180 : aTmpPam,
181 0 : pMark->GetName(),
182 0 : IDocumentMarkAccess::GetType(*pMark));
183 : // Explicitly try to get exactly the same name as in the source
184 : // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
185 0 : pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
186 :
187 : // copying additional attributes for bookmarks or fieldmarks
188 : ::sw::mark::IBookmark* const pNewBookmark =
189 0 : dynamic_cast< ::sw::mark::IBookmark* const >(pNewMark);
190 0 : if(pNewBookmark)
191 : {
192 0 : const ::sw::mark::IBookmark* const pOldBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(pMark);
193 0 : pNewBookmark->SetKeyCode(pOldBookmark->GetKeyCode());
194 0 : pNewBookmark->SetShortName(pOldBookmark->GetShortName());
195 : }
196 : ::sw::mark::IFieldmark* const pNewFieldmark =
197 0 : dynamic_cast< ::sw::mark::IFieldmark* const >(pNewMark);
198 0 : if(pNewFieldmark)
199 : {
200 0 : const ::sw::mark::IFieldmark* const pOldFieldmark = dynamic_cast< const ::sw::mark::IFieldmark* >(pMark);
201 0 : pNewFieldmark->SetFieldname(pOldFieldmark->GetFieldname());
202 0 : pNewFieldmark->SetFieldHelptext(pOldFieldmark->GetFieldHelptext());
203 0 : ::sw::mark::IFieldmark::parameter_map_t* pNewParams = pNewFieldmark->GetParameters();
204 0 : const ::sw::mark::IFieldmark::parameter_map_t* pOldParams = pOldFieldmark->GetParameters();
205 0 : ::sw::mark::IFieldmark::parameter_map_t::const_iterator pIt = pOldParams->begin();
206 0 : for (; pIt != pOldParams->end(); ++pIt )
207 : {
208 0 : pNewParams->insert( *pIt );
209 : }
210 : }
211 :
212 : ::sfx2::Metadatable const*const pMetadatable(
213 0 : dynamic_cast< ::sfx2::Metadatable const* >(pMark));
214 : ::sfx2::Metadatable *const pNewMetadatable(
215 0 : dynamic_cast< ::sfx2::Metadatable * >(pNewMark));
216 0 : if (pMetadatable && pNewMetadatable)
217 : {
218 0 : pNewMetadatable->RegisterAsCopyOf(*pMetadatable);
219 : }
220 0 : }
221 0 : }
222 : }
223 :
224 : // Structure for the mapping from old and new frame formats to the
225 : // boxes and lines of a table
226 : struct _MapTblFrmFmt
227 : {
228 : const SwFrmFmt *pOld, *pNew;
229 0 : _MapTblFrmFmt( const SwFrmFmt *pOldFmt, const SwFrmFmt*pNewFmt )
230 0 : : pOld( pOldFmt ), pNew( pNewFmt )
231 0 : {}
232 : };
233 :
234 : typedef std::vector<_MapTblFrmFmt> _MapTblFrmFmts;
235 :
236 0 : SwCntntNode* SwTxtNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
237 : {
238 : // the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
239 : // node with the collection and hard attributes. Normally is the same
240 : // node, but if insert a glossary without formatting, then the Attrnode
241 : // is the prev node of the destionation position in dest. document.
242 0 : SwTxtNode* pCpyTxtNd = (SwTxtNode*)this;
243 0 : SwTxtNode* pCpyAttrNd = pCpyTxtNd;
244 :
245 : // Copy the formats to the other document
246 0 : SwTxtFmtColl* pColl = 0;
247 0 : if( pDoc->IsInsOnlyTextGlossary() )
248 : {
249 0 : SwNodeIndex aIdx( rIdx, -1 );
250 0 : if( aIdx.GetNode().IsTxtNode() )
251 : {
252 0 : pCpyAttrNd = aIdx.GetNode().GetTxtNode();
253 0 : pColl = &pCpyAttrNd->GetTxtColl()->GetNextTxtFmtColl();
254 0 : }
255 : }
256 0 : if( !pColl )
257 0 : pColl = pDoc->CopyTxtColl( *GetTxtColl() );
258 :
259 0 : SwTxtNode* pTxtNd = pDoc->GetNodes().MakeTxtNode( rIdx, pColl );
260 :
261 : // METADATA: register copy
262 0 : pTxtNd->RegisterAsCopyOf(*pCpyTxtNd);
263 :
264 : // Copy Attribute/Text
265 0 : if( !pCpyAttrNd->HasSwAttrSet() )
266 : // An AttrSet was added for numbering, so delete it
267 0 : pTxtNd->ResetAllAttr();
268 :
269 : // if Copy-Textnode unequal to Copy-Attrnode, then copy first
270 : // the attributes into the new Node.
271 0 : if( pCpyAttrNd != pCpyTxtNd )
272 : {
273 0 : pCpyAttrNd->CopyAttr( pTxtNd, 0, 0 );
274 0 : if( pCpyAttrNd->HasSwAttrSet() )
275 : {
276 0 : SwAttrSet aSet( *pCpyAttrNd->GetpSwAttrSet() );
277 0 : aSet.ClearItem( RES_PAGEDESC );
278 0 : aSet.ClearItem( RES_BREAK );
279 0 : aSet.CopyToModify( *pTxtNd );
280 : }
281 : }
282 :
283 : // Is that enough? What about PostIts/Fields/FieldTypes?
284 : // #i96213# - force copy of all attributes
285 0 : pCpyTxtNd->CopyText( pTxtNd, SwIndex( pCpyTxtNd ),
286 0 : pCpyTxtNd->GetTxt().getLength(), true );
287 :
288 0 : if( RES_CONDTXTFMTCOLL == pColl->Which() )
289 0 : pTxtNd->ChkCondColl();
290 :
291 0 : return pTxtNd;
292 : }
293 :
294 0 : static bool lcl_SrchNew( const _MapTblFrmFmt& rMap, const SwFrmFmt** pPara )
295 : {
296 0 : if( rMap.pOld != *pPara )
297 0 : return true;
298 0 : *pPara = rMap.pNew;
299 0 : return false;
300 : }
301 :
302 : struct _CopyTable
303 : {
304 : SwDoc* pDoc;
305 : sal_uLong nOldTblSttIdx;
306 : _MapTblFrmFmts& rMapArr;
307 : SwTableLine* pInsLine;
308 : SwTableBox* pInsBox;
309 : SwTableNode *pTblNd;
310 : const SwTable *pOldTable;
311 :
312 0 : _CopyTable( SwDoc* pDc, _MapTblFrmFmts& rArr, sal_uLong nOldStt,
313 : SwTableNode& rTblNd, const SwTable* pOldTbl )
314 : : pDoc(pDc), nOldTblSttIdx(nOldStt), rMapArr(rArr),
315 0 : pInsLine(0), pInsBox(0), pTblNd(&rTblNd), pOldTable( pOldTbl )
316 0 : {}
317 : };
318 :
319 : static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT );
320 :
321 0 : static void lcl_CopyTblBox( SwTableBox* pBox, _CopyTable* pCT )
322 : {
323 0 : SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
324 0 : for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
325 0 : if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pBoxFmt ) )
326 0 : break;
327 0 : if( pBoxFmt == pBox->GetFrmFmt() ) // Create a new one?
328 : {
329 : const SfxPoolItem* pItem;
330 0 : if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMULA, sal_False,
331 0 : &pItem ) && ((SwTblBoxFormula*)pItem)->IsIntrnlName() )
332 : {
333 0 : ((SwTblBoxFormula*)pItem)->PtrToBoxNm( pCT->pOldTable );
334 : }
335 :
336 0 : pBoxFmt = pCT->pDoc->MakeTableBoxFmt();
337 0 : pBoxFmt->CopyAttrs( *pBox->GetFrmFmt() );
338 :
339 0 : if( pBox->GetSttIdx() )
340 : {
341 0 : SvNumberFormatter* pN = pCT->pDoc->GetNumberFormatter( sal_False );
342 0 : if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == pBoxFmt->
343 0 : GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
344 : {
345 0 : sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
346 0 : sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
347 0 : if( nNewIdx != nOldIdx )
348 0 : pBoxFmt->SetFmtAttr( SwTblBoxNumFormat( nNewIdx ));
349 :
350 : }
351 : }
352 :
353 0 : pCT->rMapArr.push_back( _MapTblFrmFmt( pBox->GetFrmFmt(), pBoxFmt ) );
354 : }
355 :
356 0 : sal_uInt16 nLines = pBox->GetTabLines().size();
357 : SwTableBox* pNewBox;
358 0 : if( nLines )
359 0 : pNewBox = new SwTableBox( pBoxFmt, nLines, pCT->pInsLine );
360 : else
361 : {
362 : SwNodeIndex aNewIdx( *pCT->pTblNd,
363 0 : pBox->GetSttIdx() - pCT->nOldTblSttIdx );
364 : OSL_ENSURE( aNewIdx.GetNode().IsStartNode(), "Index is not on the start node" );
365 0 : pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
366 0 : pNewBox->setRowSpan( pBox->getRowSpan() );
367 : }
368 :
369 0 : pCT->pInsLine->GetTabBoxes().push_back( pNewBox );
370 :
371 0 : if( nLines )
372 : {
373 0 : _CopyTable aPara( *pCT );
374 0 : aPara.pInsBox = pNewBox;
375 0 : BOOST_FOREACH( const SwTableLine* pLine, pBox->GetTabLines() )
376 0 : lcl_CopyTblLine( pLine, &aPara );
377 : }
378 0 : else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
379 : // In the headline, the paragraphs must match conditional styles
380 0 : pNewBox->GetSttNd()->CheckSectionCondColl();
381 0 : }
382 :
383 0 : static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT )
384 : {
385 0 : SwTableLineFmt* pLineFmt = (SwTableLineFmt*)pLine->GetFrmFmt();
386 0 : for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
387 0 : if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pLineFmt ) )
388 0 : break;
389 0 : if( pLineFmt == pLine->GetFrmFmt() ) // Create a new one?
390 : {
391 0 : pLineFmt = pCT->pDoc->MakeTableLineFmt();
392 0 : pLineFmt->CopyAttrs( *pLine->GetFrmFmt() );
393 0 : pCT->rMapArr.push_back( _MapTblFrmFmt( pLine->GetFrmFmt(), pLineFmt ) );
394 : }
395 : SwTableLine* pNewLine = new SwTableLine( pLineFmt,
396 0 : pLine->GetTabBoxes().size(), pCT->pInsBox );
397 : // Insert the new row into the table
398 0 : if( pCT->pInsBox )
399 : {
400 0 : pCT->pInsBox->GetTabLines().push_back( pNewLine );
401 : }
402 : else
403 : {
404 0 : pCT->pTblNd->GetTable().GetTabLines().push_back( pNewLine );
405 : }
406 0 : pCT->pInsLine = pNewLine;
407 0 : for( SwTableBoxes::iterator it = ((SwTableLine*)pLine)->GetTabBoxes().begin();
408 0 : it != ((SwTableLine*)pLine)->GetTabBoxes().end(); ++it)
409 0 : lcl_CopyTblBox(*it, pCT );
410 0 : }
411 :
412 0 : SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
413 : {
414 : // In which array are we? Nodes? UndoNodes?
415 0 : SwNodes& rNds = (SwNodes&)GetNodes();
416 :
417 : {
418 0 : if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
419 0 : rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
420 0 : return 0;
421 : }
422 :
423 : // Copy the TableFrmFmt
424 0 : OUString sTblName( GetTable().GetFrmFmt()->GetName() );
425 0 : if( !pDoc->IsCopyIsMove() )
426 : {
427 0 : const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
428 0 : for( sal_uInt16 n = rTblFmts.size(); n; )
429 0 : if( rTblFmts[ --n ]->GetName() == sTblName )
430 : {
431 0 : sTblName = pDoc->GetUniqueTblName();
432 0 : break;
433 : }
434 : }
435 :
436 0 : SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
437 0 : pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
438 0 : SwTableNode* pTblNd = new SwTableNode( rIdx );
439 0 : SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
440 0 : SwNodeIndex aInsPos( *pEndNd );
441 :
442 0 : SwTable& rTbl = (SwTable&)pTblNd->GetTable();
443 0 : rTbl.RegisterToFormat( *pTblFmt );
444 :
445 0 : rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
446 0 : rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
447 0 : rTbl.SetTableModel( GetTable().IsNewModel() );
448 :
449 0 : SwDDEFieldType* pDDEType = 0;
450 0 : if( IS_TYPE( SwDDETable, &GetTable() ))
451 : {
452 : // We're copying a DDE table
453 : // Is the field type available in the new document?
454 0 : pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
455 0 : if( pDDEType->IsDeleted() )
456 0 : pDoc->InsDeletedFldType( *pDDEType );
457 : else
458 0 : pDDEType = (SwDDEFieldType*)pDoc->InsertFldType( *pDDEType );
459 : OSL_ENSURE( pDDEType, "unknown FieldType" );
460 :
461 : // Swap the table pointers in the node
462 0 : SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
463 0 : pTblNd->SetNewTable( pNewTable, sal_False );
464 : }
465 : // First copy the content of the tables, we will later assign the
466 : // boxes/lines and create the frames
467 0 : SwNodeRange aRg( *this, +1, *EndOfSectionNode() );
468 :
469 : // If there is a table in this table, the table format for the outer table
470 : // does not seem to be used, because the table does not have any contents yet
471 : // (see IsUsed). Therefore the inner table gets the same name as the outer table.
472 : // We have to make sure that the table node of the SwTable is accessible, even
473 : // without any content in m_TabSortContentBoxes. #i26629#
474 0 : pTblNd->GetTable().SetTableNode( pTblNd );
475 0 : rNds._Copy( aRg, aInsPos, sal_False );
476 0 : pTblNd->GetTable().SetTableNode( 0 );
477 :
478 : // Special case for a single box
479 0 : if( 1 == GetTable().GetTabSortBoxes().size() )
480 : {
481 0 : aRg.aStart.Assign( *pTblNd, 1 );
482 0 : aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
483 0 : pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
484 : }
485 :
486 : // Delete all frames from the copied area, they will be created
487 : // during the generation of the table frame
488 0 : pTblNd->DelFrms();
489 :
490 0 : _MapTblFrmFmts aMapArr;
491 0 : _CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
492 :
493 0 : BOOST_FOREACH(const SwTableLine* pLine, GetTable().GetTabLines() )
494 0 : lcl_CopyTblLine( pLine, &aPara );
495 :
496 0 : if( pDDEType )
497 0 : pDDEType->IncRefCnt();
498 :
499 : CHECK_TABLE( GetTable() );
500 0 : return pTblNd;
501 : }
502 :
503 0 : void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
504 : {
505 : // Copy the formats into the other document:
506 : // Special case for PageBreak/PageDesc/ColBrk
507 0 : SwDoc* pDestDoc = rDestNd.GetDoc();
508 0 : SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
509 : const SwAttrSet* pSet;
510 :
511 0 : if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
512 : {
513 : // Special cases for Break-Attributes
514 : const SfxPoolItem* pAttr;
515 0 : if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, false, &pAttr ) )
516 0 : aPgBrkSet.Put( *pAttr );
517 :
518 0 : if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, false, &pAttr ) )
519 0 : aPgBrkSet.Put( *pAttr );
520 : }
521 :
522 0 : rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
523 0 : if( 0 != ( pSet = GetpSwAttrSet() ) )
524 0 : pSet->CopyToModify( rDestNd );
525 :
526 0 : if( aPgBrkSet.Count() )
527 0 : rDestNd.SetAttr( aPgBrkSet );
528 0 : }
529 :
530 : // Copy method from SwDoc
531 : // Prevent copying in Flys that are anchored in the area
532 0 : static sal_Bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
533 : sal_uLong nInsNd )
534 : {
535 0 : const SwFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
536 :
537 0 : for( sal_uInt16 n = 0; n < rFrmFmtTbl.size(); ++n )
538 : {
539 0 : SwFrmFmt const*const pFmt = rFrmFmtTbl[n];
540 0 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
541 0 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
542 0 : if (pAPos &&
543 0 : ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
544 0 : (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
545 0 : (FLY_AT_FLY == pAnchor->GetAnchorId()) ||
546 0 : (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
547 0 : nSttNd <= pAPos->nNode.GetIndex() &&
548 0 : pAPos->nNode.GetIndex() < nEndNd )
549 : {
550 0 : const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
551 : SwStartNode* pSNd;
552 0 : if( !rCntnt.GetCntntIdx() ||
553 0 : 0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
554 0 : continue;
555 :
556 0 : if( pSNd->GetIndex() < nInsNd &&
557 0 : nInsNd < pSNd->EndOfSectionIndex() )
558 : // Do not copy !
559 0 : return sal_True;
560 :
561 0 : if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
562 0 : pSNd->EndOfSectionIndex(), nInsNd ) )
563 : // Do not copy !
564 0 : return sal_True;
565 : }
566 : }
567 :
568 0 : return sal_False;
569 : }
570 :
571 0 : static void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
572 : {
573 0 : const SwDoc* pSrcDoc = rPam.GetDoc();
574 0 : const SwRedlineTbl& rTbl = pSrcDoc->GetRedlineTbl();
575 0 : if( !rTbl.empty() )
576 : {
577 0 : SwDoc* pDestDoc = rCpyPam.GetDoc();
578 0 : SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
579 0 : SwPaM* pDelPam = 0;
580 0 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
581 : // We have to count the "non-copied" nodes
582 0 : sal_uLong nDelCount = 0;
583 0 : SwNodeIndex aCorrIdx( pStt->nNode );
584 :
585 0 : sal_uInt16 n = 0;
586 0 : pSrcDoc->GetRedline( *pStt, &n );
587 0 : for( ; n < rTbl.size(); ++n )
588 : {
589 0 : const SwRangeRedline* pRedl = rTbl[ n ];
590 0 : if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
591 : {
592 0 : const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
593 :
594 0 : SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
595 0 : switch( eCmpPos )
596 : {
597 : case POS_COLLIDE_END:
598 : case POS_BEFORE:
599 : // Pos1 is before Pos2
600 0 : break;
601 :
602 : case POS_COLLIDE_START:
603 : case POS_BEHIND:
604 : // Pos1 is after Pos2
605 0 : n = rTbl.size();
606 0 : break;
607 :
608 : default:
609 : {
610 0 : pDelPam = new SwPaM( *pCpyStt, pDelPam );
611 0 : if( *pStt < *pRStt )
612 : {
613 0 : lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
614 : lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
615 0 : *pDelPam->GetPoint(), nDelCount );
616 : }
617 0 : pDelPam->SetMark();
618 :
619 0 : if( *pEnd < *pREnd )
620 0 : *pDelPam->GetPoint() = *pCpyEnd;
621 : else
622 : {
623 0 : lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
624 : lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
625 0 : *pDelPam->GetPoint(), nDelCount );
626 : }
627 : }
628 : }
629 : }
630 : }
631 :
632 0 : if( pDelPam )
633 : {
634 0 : RedlineMode_t eOld = pDestDoc->GetRedlineMode();
635 0 : pDestDoc->SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
636 :
637 0 : ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
638 :
639 : do {
640 0 : pDestDoc->DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
641 0 : if( pDelPam->GetNext() == pDelPam )
642 0 : break;
643 0 : delete pDelPam->GetNext();
644 : } while( true );
645 0 : delete pDelPam;
646 :
647 0 : pDestDoc->SetRedlineMode_intern( eOld );
648 0 : }
649 : }
650 0 : }
651 :
652 0 : static void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
653 : {
654 0 : SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
655 0 : if( !pSrcDoc->GetRedlineTbl().empty() )
656 : {
657 0 : SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
658 0 : SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
659 0 : lcl_DeleteRedlines( aRgTmp, aCpyTmp );
660 : }
661 0 : }
662 :
663 : // Copy an area into this document or into another document
664 : bool
665 0 : SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
666 : {
667 0 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
668 :
669 0 : SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
670 0 : bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
671 :
672 : // Catch if there's no copy to do
673 0 : if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
674 0 : return false;
675 :
676 : // Prevent copying in Flys that are anchored in the area
677 0 : if( pDoc == this )
678 : {
679 : // Correct the Start-/EndNode
680 0 : sal_uLong nStt = pStt->nNode.GetIndex(),
681 0 : nEnd = pEnd->nNode.GetIndex(),
682 0 : nDiff = nEnd - nStt +1;
683 0 : SwNode* pNd = GetNodes()[ nStt ];
684 0 : if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
685 0 : ++nStt, --nDiff;
686 0 : if( (pNd = GetNodes()[ nEnd ])->IsCntntNode() &&
687 0 : ((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
688 0 : --nEnd, --nDiff;
689 0 : if( nDiff &&
690 0 : lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
691 : {
692 0 : return false;
693 : }
694 : }
695 :
696 0 : SwPaM* pRedlineRange = 0;
697 0 : if( pDoc->IsRedlineOn() ||
698 0 : (!pDoc->IsIgnoreRedline() && !pDoc->GetRedlineTbl().empty() ) )
699 0 : pRedlineRange = new SwPaM( rPos );
700 :
701 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
702 :
703 0 : bool bRet = false;
704 :
705 0 : if( pDoc != this )
706 : { // ordinary copy
707 0 : bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
708 : }
709 0 : else if( ! ( *pStt <= rPos && rPos < *pEnd &&
710 0 : ( pStt->nNode != pEnd->nNode ||
711 0 : !pStt->nNode.GetNode().IsTxtNode() )) )
712 : {
713 : // Copy to a position outside of the area, or copy a single TextNode
714 : // Do an ordinary copy
715 0 : bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
716 : }
717 : else
718 : {
719 : // Copy the area in itself
720 : // Special case for handling an area with several nodes,
721 : // or a single node that is not a TextNode
722 : OSL_ENSURE( this == pDoc, " invalid copy branch!" );
723 : OSL_FAIL("mst: i thought this could be dead code;"
724 : "please tell me what you did to get here!");
725 0 : pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
726 :
727 : // Then copy the area to the underlying document area
728 : // (with start/end nodes clamped) and move them to
729 : // the desired position.
730 :
731 0 : SwUndoCpyDoc* pUndo = 0;
732 : // Save the Undo area
733 0 : SwPaM aPam( rPos );
734 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
735 : {
736 0 : pDoc->GetIDocumentUndoRedo().ClearRedo();
737 0 : pUndo = new SwUndoCpyDoc( aPam );
738 : }
739 :
740 : {
741 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
742 0 : SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
743 0 : SwNodeIndex( GetNodes().GetEndOfAutotext() ));
744 0 : aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
745 : // copy without Frames
746 0 : pDoc->CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
747 :
748 0 : aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
749 0 : aPam.SetMark();
750 : SwCntntNode* pNode =
751 0 : pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
752 0 : pNode->MakeEndIndex( &aPam.GetMark()->nContent );
753 :
754 0 : aPam.GetPoint()->nNode = *aPam.GetNode()->StartOfSectionNode();
755 0 : pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
756 0 : pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
757 : // move to desired position
758 0 : pDoc->MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
759 :
760 0 : pNode = aPam.GetCntntNode();
761 0 : *aPam.GetPoint() = rPos; // Move the cursor for Undo
762 0 : aPam.SetMark(); // also move the Mark
763 0 : aPam.DeleteMark(); // But don't mark any area
764 0 : pDoc->DeleteSection( pNode ); // Delete the area again
765 : }
766 :
767 : // if Undo is enabled, store the insertion range
768 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
769 : {
770 0 : pUndo->SetInsertRange( aPam );
771 0 : pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
772 : }
773 :
774 0 : if( pRedlineRange )
775 : {
776 0 : pRedlineRange->SetMark();
777 0 : *pRedlineRange->GetPoint() = *aPam.GetPoint();
778 0 : *pRedlineRange->GetMark() = *aPam.GetMark();
779 : }
780 :
781 0 : pDoc->SetModified();
782 0 : bRet = true;
783 : }
784 :
785 0 : pDoc->SetRedlineMode_intern( eOld );
786 0 : if( pRedlineRange )
787 : {
788 0 : if( pDoc->IsRedlineOn() )
789 0 : pDoc->AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
790 : else
791 0 : pDoc->SplitRedline( *pRedlineRange );
792 0 : delete pRedlineRange;
793 : }
794 :
795 0 : return bRet;
796 : }
797 :
798 0 : static bool lcl_MarksWholeNode(const SwPaM & rPam)
799 : {
800 0 : bool bResult = false;
801 0 : const SwPosition* pStt = rPam.Start();
802 0 : const SwPosition* pEnd = rPam.End();
803 :
804 0 : if (NULL != pStt && NULL != pEnd)
805 : {
806 0 : const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
807 0 : const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
808 :
809 0 : if (NULL != pSttNd && NULL != pEndNd &&
810 0 : pStt->nContent.GetIndex() == 0 &&
811 0 : pEnd->nContent.GetIndex() == pEndNd->Len())
812 : {
813 0 : bResult = true;
814 : }
815 : }
816 :
817 0 : return bResult;
818 : }
819 :
820 : // #i86492#
821 0 : static bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
822 : {
823 0 : bool bRet = false;
824 :
825 0 : const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
826 0 : const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
827 0 : if ( pTxtNd && pTxtNd->IsInList() &&
828 0 : pEndTxtNd && pEndTxtNd->IsInList() )
829 : {
830 0 : bRet = true;
831 0 : SwNodeIndex aIdx(rPam.Start()->nNode);
832 :
833 0 : do
834 : {
835 0 : ++aIdx;
836 0 : pTxtNd = aIdx.GetNode().GetTxtNode();
837 :
838 0 : if ( !pTxtNd || !pTxtNd->IsInList() )
839 : {
840 0 : bRet = false;
841 0 : break;
842 : }
843 0 : } while ( pTxtNd && pTxtNd != pEndTxtNd );
844 : }
845 :
846 0 : return bRet;
847 : }
848 :
849 0 : bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
850 : const bool bMakeNewFrms, const bool bCopyAll,
851 : SwPaM *const pCpyRange ) const
852 : {
853 0 : SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
854 0 : const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
855 :
856 0 : SwPosition* pStt = rPam.Start();
857 0 : SwPosition* pEnd = rPam.End();
858 :
859 : // Catch when there's no copy to do.
860 0 : if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
861 : //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
862 : //JP 15.11.2001: don't test inclusive the end, ever exclusive
863 0 : ( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
864 : {
865 0 : return false;
866 : }
867 :
868 0 : const bool bEndEqualIns = pDoc == this && rPos == *pEnd;
869 :
870 : // If Undo is enabled, create the UndoCopy object
871 0 : SwUndoCpyDoc* pUndo = 0;
872 : // lcl_DeleteRedlines may delete the start or end node of the cursor when
873 : // removing the redlines so use cursor that is corrected by PaMCorrAbs
874 0 : ::boost::scoped_ptr<SwUnoCrsr> const pCopyPam(pDoc->CreateUnoCrsr(rPos));
875 :
876 0 : SwTblNumFmtMerge aTNFM( *this, *pDoc );
877 :
878 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
879 : {
880 0 : pUndo = new SwUndoCpyDoc(*pCopyPam);
881 0 : pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
882 : }
883 :
884 0 : RedlineMode_t eOld = pDoc->GetRedlineMode();
885 0 : pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
886 :
887 : // Move the PaM one node back from the insert position, so that
888 : // the position doesn't get moved
889 0 : pCopyPam->SetMark();
890 0 : bool bCanMoveBack = pCopyPam->Move(fnMoveBackward, fnGoCntnt);
891 : // If the position was shifted from more than one node, an end node has been skipped
892 0 : bool bAfterTable = false;
893 0 : if ((rPos.nNode.GetIndex() - pCopyPam->GetPoint()->nNode.GetIndex()) > 1)
894 : {
895 : // First go back to the original place
896 0 : pCopyPam->GetPoint()->nNode = rPos.nNode;
897 0 : pCopyPam->GetPoint()->nContent = rPos.nContent;
898 :
899 0 : bCanMoveBack = false;
900 0 : bAfterTable = true;
901 : }
902 0 : if( !bCanMoveBack )
903 0 : pCopyPam->GetPoint()->nNode--;
904 :
905 0 : SwNodeRange aRg( pStt->nNode, pEnd->nNode );
906 0 : SwNodeIndex aInsPos( rPos.nNode );
907 0 : const bool bOneNode = pStt->nNode == pEnd->nNode;
908 0 : SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
909 0 : SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
910 0 : SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
911 0 : bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
912 0 : ( (pDestTxtNd && !pDestTxtNd->GetTxt().getLength()) ||
913 0 : ( !bOneNode && !rPos.nContent.GetIndex() ) );
914 0 : bool bCopyBookmarks = true;
915 0 : bool bStartIsTxtNode = 0 != pSttTxtNd;
916 :
917 : // #i104585# copy outline num rule to clipboard (for ASCII filter)
918 0 : if (pDoc->IsClipBoard() && GetOutlineNumRule())
919 : {
920 0 : pDoc->SetOutlineNumRule(*GetOutlineNumRule());
921 : }
922 :
923 : // #i86492#
924 : // Correct the search for a previous list:
925 : // First search for non-outline numbering list. Then search for non-outline
926 : // bullet list.
927 : // Keep also the <ListId> value for possible propagation.
928 0 : OUString aListIdToPropagate;
929 : const SwNumRule* pNumRuleToPropagate =
930 0 : pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
931 0 : if ( !pNumRuleToPropagate )
932 : {
933 : pNumRuleToPropagate =
934 0 : pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
935 : }
936 : // #i86492#
937 : // Do not propagate previous found list, if
938 : // - destination is an empty paragraph which is not in a list and
939 : // - source contains at least one paragraph which is not in a list
940 0 : if ( pNumRuleToPropagate &&
941 0 : pDestTxtNd && !pDestTxtNd->GetTxt().getLength() &&
942 0 : !pDestTxtNd->IsInList() &&
943 0 : !lcl_ContainsOnlyParagraphsInList( rPam ) )
944 : {
945 0 : pNumRuleToPropagate = 0;
946 : }
947 :
948 : // This do/while block is only there so that we can break out of it!
949 : do {
950 0 : if( pSttTxtNd )
951 : {
952 : // Don't copy the beginning completely?
953 0 : if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
954 : {
955 0 : SwIndex aDestIdx( rPos.nContent );
956 0 : bool bCopyOk = false;
957 0 : if( !pDestTxtNd )
958 : {
959 0 : if( pStt->nContent.GetIndex() || bOneNode )
960 0 : pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
961 0 : pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
962 : else
963 : {
964 0 : pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
965 0 : bCopyOk = true;
966 : }
967 0 : aDestIdx.Assign( pDestTxtNd, 0 );
968 0 : bCopyCollFmt = true;
969 : }
970 0 : else if( !bOneNode || bColumnSel )
971 : {
972 0 : const sal_Int32 nCntntEnd = pEnd->nContent.GetIndex();
973 : {
974 0 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
975 0 : pDoc->SplitNode( rPos, false );
976 : }
977 :
978 0 : if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
979 : {
980 : // after the SplitNode, span the CpyPam correctly again
981 0 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
982 0 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
983 : }
984 :
985 0 : pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
986 : aDestIdx.Assign(
987 0 : pDestTxtNd, pDestTxtNd->GetTxt().getLength());
988 :
989 : // Correct the area again
990 0 : if( bEndEqualIns )
991 : {
992 0 : bool bChg = pEnd != rPam.GetPoint();
993 0 : if( bChg )
994 0 : rPam.Exchange();
995 0 : rPam.Move( fnMoveBackward, fnGoCntnt );
996 0 : if( bChg )
997 0 : rPam.Exchange();
998 :
999 0 : aRg.aEnd = pEnd->nNode;
1000 0 : pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1001 : }
1002 0 : else if( rPos == *pEnd )
1003 : {
1004 : // The end was also moved
1005 0 : pEnd->nNode--;
1006 0 : pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
1007 0 : aRg.aEnd = pEnd->nNode;
1008 0 : pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1009 : }
1010 : }
1011 :
1012 : // Safe numrule item at destination.
1013 : // #i86492# - Safe also <ListId> item of destination.
1014 0 : int aNumRuleState = SFX_ITEM_UNKNOWN;
1015 0 : SwNumRuleItem aNumRuleItem;
1016 0 : int aListIdState = SFX_ITEM_UNKNOWN;
1017 0 : SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() );
1018 : {
1019 0 : const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
1020 0 : if (pAttrSet != NULL)
1021 : {
1022 0 : const SfxPoolItem * pItem = NULL;
1023 0 : aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
1024 0 : if (SFX_ITEM_SET == aNumRuleState)
1025 0 : aNumRuleItem = *((SwNumRuleItem *) pItem);
1026 :
1027 : aListIdState =
1028 0 : pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
1029 0 : if (SFX_ITEM_SET == aListIdState)
1030 : {
1031 0 : aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1032 : }
1033 : }
1034 : }
1035 :
1036 0 : if( !bCopyOk )
1037 : {
1038 : const sal_Int32 nCpyLen = ( (bOneNode)
1039 0 : ? pEnd->nContent.GetIndex()
1040 0 : : pSttTxtNd->GetTxt().getLength())
1041 0 : - pStt->nContent.GetIndex();
1042 : pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
1043 0 : pStt->nContent, nCpyLen );
1044 0 : if( bEndEqualIns )
1045 0 : pEnd->nContent -= nCpyLen;
1046 : }
1047 :
1048 0 : if( bOneNode )
1049 : {
1050 0 : if( bCopyCollFmt )
1051 : {
1052 0 : pSttTxtNd->CopyCollFmt( *pDestTxtNd );
1053 :
1054 : /* If only a part of one paragraph is copied
1055 : restore the numrule at the destination. */
1056 : // #i86492# - restore also <ListId> item
1057 0 : if ( !lcl_MarksWholeNode(rPam) )
1058 : {
1059 0 : if (SFX_ITEM_SET == aNumRuleState)
1060 : {
1061 0 : pDestTxtNd->SetAttr(aNumRuleItem);
1062 : }
1063 : else
1064 : {
1065 0 : pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1066 : }
1067 0 : if (SFX_ITEM_SET == aListIdState)
1068 : {
1069 0 : pDestTxtNd->SetAttr(aListIdItem);
1070 : }
1071 : else
1072 : {
1073 0 : pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1074 : }
1075 : }
1076 : }
1077 :
1078 0 : break;
1079 : }
1080 :
1081 0 : aRg.aStart++;
1082 : }
1083 : }
1084 0 : else if( pDestTxtNd )
1085 : {
1086 : // Problems with insertion of table selections into "normal" text solved.
1087 : // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
1088 : // the undo operation will try to merge this node after removing the table.
1089 : // If we didn't split a textnode, the PaM should start at the inserted table node
1090 0 : if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
1091 : { // Insertion at the last position of a textnode (empty or not)
1092 0 : ++aInsPos; // The table will be inserted behind the text node
1093 : }
1094 0 : else if( rPos.nContent.GetIndex() )
1095 : { // Insertion in the middle of a text node, it has to be split
1096 : // (and joined from undo)
1097 0 : bStartIsTxtNode = true;
1098 :
1099 0 : const sal_Int32 nCntntEnd = pEnd->nContent.GetIndex();
1100 : {
1101 0 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
1102 0 : pDoc->SplitNode( rPos, false );
1103 : }
1104 :
1105 0 : if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
1106 : {
1107 : // after the SplitNode, span the CpyPam correctly again
1108 0 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
1109 0 : pCopyPam->Move( fnMoveBackward, fnGoCntnt );
1110 : }
1111 :
1112 : // Correct the area again
1113 0 : if( bEndEqualIns )
1114 0 : aRg.aEnd--;
1115 : // The end would also be moved
1116 0 : else if( rPos == *pEnd )
1117 : {
1118 0 : rPos.nNode-=2;
1119 0 : rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1120 0 : nCntntEnd );
1121 0 : rPos.nNode++;
1122 0 : aRg.aEnd--;
1123 : }
1124 : }
1125 0 : else if( bCanMoveBack )
1126 : { //Insertion at the first position of a text node. It will not be splitted, the table
1127 : // will be inserted before the text node.
1128 : // See below, before the SetInsertRange funciton of the undo object will be called,
1129 : // the CpyPam would be moved to the next content position. This has to be avoided
1130 : // We want to be moved to the table node itself thus we have to set bCanMoveBack
1131 : // and to manipulate pCopyPam.
1132 0 : bCanMoveBack = false;
1133 0 : pCopyPam->GetPoint()->nNode--;
1134 : }
1135 : }
1136 :
1137 0 : pDestTxtNd = aInsPos.GetNode().GetTxtNode();
1138 0 : if( pEndTxtNd )
1139 : {
1140 0 : SwIndex aDestIdx( rPos.nContent );
1141 0 : if( !pDestTxtNd )
1142 : {
1143 0 : pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
1144 0 : pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
1145 0 : aDestIdx.Assign( pDestTxtNd, 0 );
1146 0 : aInsPos--;
1147 :
1148 : // if we have to insert an extra text node
1149 : // at the destination, this node will be our new destination
1150 : // (text) node, and thus we set bStartisTxtNode to true. This
1151 : // will ensure that this node will be deleted during Undo
1152 : // using JoinNext.
1153 : OSL_ENSURE( !bStartIsTxtNode, "Oops, undo may be instable now." );
1154 0 : bStartIsTxtNode = true;
1155 : }
1156 :
1157 : // Save numrule at destination
1158 : // #i86492# - Safe also <ListId> item of destination.
1159 0 : int aNumRuleState = SFX_ITEM_UNKNOWN;
1160 0 : SwNumRuleItem aNumRuleItem;
1161 0 : int aListIdState = SFX_ITEM_UNKNOWN;
1162 0 : SfxStringItem aListIdItem( RES_PARATR_LIST_ID, OUString() );
1163 : {
1164 0 : const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
1165 0 : if (pAttrSet != NULL)
1166 : {
1167 0 : const SfxPoolItem * pItem = NULL;
1168 :
1169 : aNumRuleState =
1170 0 : pAttrSet->GetItemState(RES_PARATR_NUMRULE, false, &pItem);
1171 0 : if (SFX_ITEM_SET == aNumRuleState)
1172 0 : aNumRuleItem = *((SwNumRuleItem *) pItem);
1173 :
1174 : aListIdState =
1175 0 : pAttrSet->GetItemState(RES_PARATR_LIST_ID, false, &pItem);
1176 0 : if (SFX_ITEM_SET == aListIdState)
1177 0 : aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1178 : }
1179 : }
1180 :
1181 0 : const bool bEmptyDestNd = pDestTxtNd->GetTxt().isEmpty();
1182 0 : pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
1183 0 : pEnd->nContent.GetIndex() );
1184 :
1185 : // Also copy all format templates
1186 0 : if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
1187 : {
1188 0 : pEndTxtNd->CopyCollFmt( *pDestTxtNd );
1189 :
1190 0 : if ( bOneNode )
1191 : {
1192 : /* If only a part of one paragraph is copied
1193 : restore the numrule at the destination. */
1194 : // #i86492# - restore also <ListId> item
1195 0 : if ( !lcl_MarksWholeNode(rPam) )
1196 : {
1197 0 : if (SFX_ITEM_SET == aNumRuleState)
1198 : {
1199 0 : pDestTxtNd->SetAttr(aNumRuleItem);
1200 : }
1201 : else
1202 : {
1203 0 : pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1204 : }
1205 0 : if (SFX_ITEM_SET == aListIdState)
1206 : {
1207 0 : pDestTxtNd->SetAttr(aListIdItem);
1208 : }
1209 : else
1210 : {
1211 0 : pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1212 : }
1213 : }
1214 : }
1215 0 : }
1216 : }
1217 :
1218 0 : if( bCopyAll || aRg.aStart != aRg.aEnd )
1219 : {
1220 0 : SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
1221 0 : if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
1222 : {
1223 0 : aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
1224 0 : if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, false ) )
1225 0 : pDestTxtNd->ResetAttr( RES_BREAK );
1226 0 : if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_PAGEDESC, false ) )
1227 0 : pDestTxtNd->ResetAttr( RES_PAGEDESC );
1228 : }
1229 :
1230 0 : if( aInsPos == pEnd->nNode )
1231 : {
1232 0 : SwNodeIndex aSaveIdx( aInsPos, -1 );
1233 0 : CopyWithFlyInFly( aRg, 0,aInsPos, &rPam, bMakeNewFrms, sal_False );
1234 0 : ++aSaveIdx;
1235 0 : pEnd->nNode = aSaveIdx;
1236 0 : pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
1237 : }
1238 : else
1239 0 : CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &rPam, bMakeNewFrms, sal_False );
1240 :
1241 0 : bCopyBookmarks = false;
1242 :
1243 : // Put the breaks back into the first node
1244 0 : if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
1245 0 : pCopyPam->GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode()))
1246 : {
1247 0 : pDestTxtNd->SetAttr( aBrkSet );
1248 0 : }
1249 : }
1250 : } while( false );
1251 :
1252 : // Adjust position (in case it was moved / in another node)
1253 0 : rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1254 0 : rPos.nContent.GetIndex() );
1255 :
1256 0 : if( rPos.nNode != aInsPos )
1257 : {
1258 0 : pCopyPam->GetMark()->nNode = aInsPos;
1259 0 : pCopyPam->GetMark()->nContent.Assign(pCopyPam->GetCntntNode(false), 0);
1260 0 : rPos = *pCopyPam->GetMark();
1261 : }
1262 : else
1263 0 : *pCopyPam->GetMark() = rPos;
1264 :
1265 0 : if ( !bAfterTable )
1266 0 : pCopyPam->Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
1267 : else
1268 : {
1269 : // Reset the offset to 0 as it was before the insertion
1270 0 : pCopyPam->GetPoint()->nContent -= pCopyPam->GetPoint()->nContent;
1271 :
1272 0 : pCopyPam->GetPoint()->nNode++;
1273 : // If the next node is a start node, then step back: the start node
1274 : // has been copied and needs to be in the selection for the undo
1275 0 : if (pCopyPam->GetPoint()->nNode.GetNode().IsStartNode())
1276 0 : pCopyPam->GetPoint()->nNode--;
1277 :
1278 : }
1279 0 : pCopyPam->Exchange();
1280 :
1281 : // Also copy all bookmarks
1282 0 : if( bCopyBookmarks && getIDocumentMarkAccess()->getAllMarksCount() )
1283 0 : lcl_CopyBookmarks( rPam, *pCopyPam );
1284 :
1285 0 : if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
1286 : {
1287 : assert(*pCopyPam->GetPoint() == rPos);
1288 : // the Node rPos points to may be deleted so unregister ...
1289 0 : rPos.nContent = SwIndex(0);
1290 0 : lcl_DeleteRedlines(rPam, *pCopyPam);
1291 0 : rPos = *pCopyPam->GetPoint(); // ... and restore.
1292 : }
1293 :
1294 : // If Undo is enabled, store the inserted area
1295 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1296 : {
1297 0 : pUndo->SetInsertRange( *pCopyPam, true, bStartIsTxtNode );
1298 : }
1299 :
1300 0 : if( pCpyRange )
1301 : {
1302 0 : pCpyRange->SetMark();
1303 0 : *pCpyRange->GetPoint() = *pCopyPam->GetPoint();
1304 0 : *pCpyRange->GetMark() = *pCopyPam->GetMark();
1305 : }
1306 :
1307 0 : if ( pNumRuleToPropagate != NULL )
1308 : {
1309 : // #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
1310 0 : pDoc->SetNumRule( *pCopyPam, *pNumRuleToPropagate, false,
1311 0 : aListIdToPropagate, true, true );
1312 : }
1313 :
1314 0 : pDoc->SetRedlineMode_intern( eOld );
1315 0 : pDoc->SetModified();
1316 :
1317 0 : return true;
1318 : }
1319 :
1320 : // Copy method from SwDoc - "copy Flys in Flys"
1321 0 : void SwDoc::CopyWithFlyInFly(
1322 : const SwNodeRange& rRg,
1323 : const sal_Int32 nEndContentIndex,
1324 : const SwNodeIndex& rInsPos,
1325 : const SwPaM* pCopiedPaM,
1326 : const sal_Bool bMakeNewFrms,
1327 : const sal_Bool bDelRedlines,
1328 : const sal_Bool bCopyFlyAtFly ) const
1329 : {
1330 0 : SwDoc* pDest = rInsPos.GetNode().GetDoc();
1331 :
1332 0 : _SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
1333 :
1334 0 : SwNodeIndex aSavePos( rInsPos, -1 );
1335 0 : bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
1336 0 : GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
1337 0 : ++aSavePos;
1338 0 : if( bEndIsEqualEndPos )
1339 0 : ((SwNodeIndex&)rRg.aEnd) = aSavePos;
1340 :
1341 0 : aRedlRest.Restore();
1342 :
1343 : #if OSL_DEBUG_LEVEL > 0
1344 : {
1345 : //JP 17.06.99: Bug 66973 - check count only if the selection is in
1346 : // the same section or there's no section, because sections that are
1347 : // not fully selected are not copied.
1348 : const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
1349 : SwNodeIndex aTmpI( rRg.aEnd, -1 );
1350 : const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
1351 : if( pSSectNd == pESectNd &&
1352 : !rRg.aStart.GetNode().IsSectionNode() &&
1353 : !aTmpI.GetNode().IsEndNode() )
1354 : {
1355 : OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
1356 : rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
1357 : "An insufficient number of nodes were copied!" );
1358 : }
1359 : }
1360 : #endif
1361 :
1362 : {
1363 0 : ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
1364 0 : CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
1365 : }
1366 :
1367 0 : SwNodeRange aCpyRange( aSavePos, rInsPos );
1368 :
1369 : // Also copy all bookmarks
1370 0 : if( getIDocumentMarkAccess()->getAllMarksCount() )
1371 : {
1372 0 : SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
1373 0 : SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
1374 :
1375 : lcl_CopyBookmarks(
1376 : pCopiedPaM != NULL ? *pCopiedPaM : aRgTmp,
1377 0 : aCpyTmp );
1378 : }
1379 :
1380 0 : if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
1381 0 : lcl_DeleteRedlines( rRg, aCpyRange );
1382 :
1383 0 : pDest->GetNodes()._DelDummyNodes( aCpyRange );
1384 0 : }
1385 :
1386 0 : static void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
1387 : {
1388 0 : SwFmtChain aSrc( pSrc->GetChain() );
1389 0 : if ( !aSrc.GetNext() )
1390 : {
1391 0 : aSrc.SetNext( pDest );
1392 0 : pSrc->SetFmtAttr( aSrc );
1393 : }
1394 0 : SwFmtChain aDest( pDest->GetChain() );
1395 0 : if ( !aDest.GetPrev() )
1396 : {
1397 0 : aDest.SetPrev( pSrc );
1398 0 : pDest->SetFmtAttr( aDest );
1399 0 : }
1400 0 : }
1401 :
1402 0 : void SwDoc::CopyFlyInFlyImpl(
1403 : const SwNodeRange& rRg,
1404 : const sal_Int32 nEndContentIndex,
1405 : const SwNodeIndex& rStartIdx,
1406 : const bool bCopyFlyAtFly ) const
1407 : {
1408 : // First collect all Flys, sort them according to their ordering number,
1409 : // and then only copy them. This maintains the ordering numbers (which are only
1410 : // managed in the DrawModel).
1411 0 : SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
1412 0 : ::std::set< _ZSortFly > aSet;
1413 0 : sal_uInt16 nArrLen = GetSpzFrmFmts()->size();
1414 :
1415 0 : for ( sal_uInt16 n = 0; n < nArrLen; ++n )
1416 : {
1417 0 : SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
1418 0 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
1419 0 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
1420 0 : bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
1421 0 : if ( pAPos &&
1422 0 : ( bAtCntnt ||
1423 0 : (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
1424 0 : (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
1425 0 : (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
1426 0 : ? rRg.aStart <= pAPos->nNode.GetIndex() + 1
1427 0 : : ( IsRedlineMove()
1428 0 : ? rRg.aStart < pAPos->nNode
1429 0 : : rRg.aStart <= pAPos->nNode )) &&
1430 0 : pAPos->nNode <= rRg.aEnd )
1431 : {
1432 : //frames at the last source node are not always copied:
1433 : //- if the node is empty and is the last node of the document or a table cell
1434 : // or a text frame then tey have to be copied
1435 : //- if the content index in this node is > 0 then paragph and frame bound objects are copied
1436 : //- to-character bound objects are copied if their index is <= nEndContentIndex
1437 0 : bool bAdd = false;
1438 0 : if( pAPos->nNode < rRg.aEnd )
1439 0 : bAdd = true;
1440 0 : if (!bAdd && !IsRedlineMove()) // fdo#40599: not for redline move
1441 : {
1442 0 : bool bEmptyNode = false;
1443 0 : bool bLastNode = false;
1444 : // is the node empty?
1445 0 : const SwNodes& rNodes = pAPos->nNode.GetNodes();
1446 : SwTxtNode* pTxtNode;
1447 0 : if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
1448 : {
1449 0 : bEmptyNode = pTxtNode->GetTxt().isEmpty();
1450 0 : if( bEmptyNode )
1451 : {
1452 : //last node information is only necessary to know for the last TextNode
1453 0 : SwNodeIndex aTmp( pAPos->nNode );
1454 0 : ++aTmp;//goto next node
1455 0 : while (aTmp.GetNode().IsEndNode())
1456 : {
1457 0 : if( aTmp == rNodes.GetEndOfContent().GetIndex() )
1458 : {
1459 0 : bLastNode = true;
1460 0 : break;
1461 : }
1462 0 : ++aTmp;
1463 0 : }
1464 : }
1465 : }
1466 0 : bAdd = bLastNode && bEmptyNode;
1467 0 : if( !bAdd )
1468 : {
1469 0 : if( bAtCntnt )
1470 0 : bAdd = nEndContentIndex > 0;
1471 : else
1472 0 : bAdd = pAPos->nContent <= nEndContentIndex;
1473 : }
1474 : }
1475 0 : if( bAdd )
1476 0 : aSet.insert( _ZSortFly( pFmt, pAnchor, nArrLen + aSet.size() ));
1477 : }
1478 : }
1479 :
1480 : // Store all copied (and also the newly created) frames in another array.
1481 : // They are stored as matching the originals, so that we will be later
1482 : // able to build the chains accordingly.
1483 0 : ::std::vector< SwFrmFmt* > aVecSwFrmFmt;
1484 0 : ::std::set< _ZSortFly >::const_iterator it=aSet.begin();
1485 :
1486 0 : while (it != aSet.end())
1487 : {
1488 : // #i59964#
1489 : // correct determination of new anchor position
1490 0 : SwFmtAnchor aAnchor( *(*it).GetAnchor() );
1491 0 : SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
1492 : // for at-paragraph and at-character anchored objects the new anchor
1493 : // position can *not* be determined by the difference of the current
1494 : // anchor position to the start of the copied range, because not
1495 : // complete selected sections in the copied range aren't copied - see
1496 : // method <SwNodes::_CopyNodes(..)>.
1497 : // Thus, the new anchor position in the destination document is found
1498 : // by counting the text nodes.
1499 0 : if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
1500 0 : (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
1501 : {
1502 : // First, determine number of anchor text node in the copied range.
1503 : // Note: The anchor text node *have* to be inside the copied range.
1504 0 : sal_uLong nAnchorTxtNdNumInRange( 0L );
1505 0 : bool bAnchorTxtNdFound( false );
1506 0 : SwNodeIndex aIdx( rRg.aStart );
1507 0 : while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
1508 : {
1509 0 : if ( aIdx.GetNode().IsTxtNode() )
1510 : {
1511 0 : ++nAnchorTxtNdNumInRange;
1512 0 : bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
1513 : }
1514 :
1515 0 : ++aIdx;
1516 : }
1517 0 : if ( !bAnchorTxtNdFound )
1518 : {
1519 : // This case can *not* happen, but to be robust take the first
1520 : // text node in the destination document.
1521 : OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
1522 0 : nAnchorTxtNdNumInRange = 1;
1523 : }
1524 : // Second, search corresponding text node in destination document
1525 : // by counting forward from start insert position <rStartIdx> the
1526 : // determined number of text nodes.
1527 0 : aIdx = rStartIdx;
1528 0 : SwNodeIndex aAnchorNdIdx( rStartIdx );
1529 : const SwNode& aEndOfContentNd =
1530 0 : aIdx.GetNode().GetNodes().GetEndOfContent();
1531 0 : while ( nAnchorTxtNdNumInRange > 0 &&
1532 0 : &(aIdx.GetNode()) != &aEndOfContentNd )
1533 : {
1534 0 : if ( aIdx.GetNode().IsTxtNode() )
1535 : {
1536 0 : --nAnchorTxtNdNumInRange;
1537 0 : aAnchorNdIdx = aIdx;
1538 : }
1539 :
1540 0 : ++aIdx;
1541 : }
1542 0 : if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1543 : {
1544 : // This case can *not* happen, but to be robust take the first
1545 : // text node in the destination document.
1546 : OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
1547 0 : aAnchorNdIdx = rStartIdx;
1548 0 : while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1549 : {
1550 0 : ++aAnchorNdIdx;
1551 : }
1552 : }
1553 : // apply found anchor text node as new anchor position
1554 0 : pNewPos->nNode = aAnchorNdIdx;
1555 : }
1556 : else
1557 : {
1558 0 : long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
1559 0 : SwNodeIndex aIdx( rStartIdx, nOffset );
1560 0 : pNewPos->nNode = aIdx;
1561 : }
1562 : // Set the character bound Flys back at the original character
1563 0 : if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
1564 0 : pNewPos->nNode.GetNode().IsTxtNode() )
1565 : {
1566 0 : pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
1567 0 : pNewPos->nContent.GetIndex() );
1568 : }
1569 : else
1570 : {
1571 0 : pNewPos->nContent.Assign( 0, 0 );
1572 : }
1573 :
1574 : // Check recursion: copy content in its own frame, then don't copy it.
1575 0 : bool bMakeCpy = true;
1576 0 : if( pDest == this )
1577 : {
1578 0 : const SwFmtCntnt& rCntnt = (*it).GetFmt()->GetCntnt();
1579 : const SwStartNode* pSNd;
1580 0 : if( rCntnt.GetCntntIdx() &&
1581 0 : 0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
1582 0 : pSNd->GetIndex() < rStartIdx.GetIndex() &&
1583 0 : rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
1584 : {
1585 0 : bMakeCpy = false;
1586 0 : aSet.erase (it++);
1587 0 : continue;
1588 : }
1589 : }
1590 :
1591 : // Copy the format and set the new anchor
1592 0 : if( bMakeCpy )
1593 0 : aVecSwFrmFmt.push_back( pDest->CopyLayoutFmt( *(*it).GetFmt(),
1594 0 : aAnchor, false, true ) );
1595 0 : ++it;
1596 0 : }
1597 :
1598 : // Rebuild as much as possible of all chains that are available in the original,
1599 : OSL_ENSURE( aSet.size() == aVecSwFrmFmt.size(), "Missing new Flys" );
1600 0 : if ( aSet.size() == aVecSwFrmFmt.size() )
1601 : {
1602 0 : size_t n = 0;
1603 0 : for (::std::set< _ZSortFly >::const_iterator nIt=aSet.begin() ; nIt != aSet.end(); ++nIt, ++n )
1604 : {
1605 0 : const SwFrmFmt *pFmtN = (*nIt).GetFmt();
1606 0 : const SwFmtChain &rChain = pFmtN->GetChain();
1607 0 : int nCnt = int(0 != rChain.GetPrev());
1608 0 : nCnt += rChain.GetNext() ? 1: 0;
1609 0 : size_t k = 0;
1610 0 : for (::std::set< _ZSortFly >::const_iterator kIt=aSet.begin() ; kIt != aSet.end(); ++kIt, ++k )
1611 : {
1612 0 : const SwFrmFmt *pFmtK = (*kIt).GetFmt();
1613 0 : if ( rChain.GetPrev() == pFmtK )
1614 : {
1615 0 : ::lcl_ChainFmts( static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]),
1616 0 : static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]) );
1617 0 : --nCnt;
1618 : }
1619 0 : else if ( rChain.GetNext() == pFmtK )
1620 : {
1621 0 : ::lcl_ChainFmts( static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]),
1622 0 : static_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]) );
1623 0 : --nCnt;
1624 : }
1625 : }
1626 : }
1627 0 : }
1628 0 : }
1629 :
1630 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|