1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ndcopy.cxx,v $
10 * $Revision: 1.34.74.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #define _ZFORLIST_DECLARE_TABLE
36 #include <hintids.hxx>
39 #include <svx/brkitem.hxx>
40 #include <fmtpdsc.hxx>
41 #include <fmtanchr.hxx>
42 #include <fmtcntnt.hxx>
47 #include <swtable.hxx>
52 #include <cellatr.hxx>
53 #include <swtblfmt.hxx>
54 #include <swddetbl.hxx>
56 #include <fmtcnct.hxx>
57 #include <redline.hxx>
59 #include <pagedesc.hxx>
60 #include <poolfmt.hxx>
61 #include <SwNodeNum.hxx>
63 #define CHECK_TABLE(t)
66 #define CHECK_TABLE(t) (t).CheckConsistency();
68 #define CHECK_TABLE(t)
75 The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
76 array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
77 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.
78 The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
80 rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
81 of "non-copy" nodes between rPam.Start() and rLastIdx.
82 nNewIdx is the new position of interest.
85 static void lcl_NonCopyCount( const SwPaM
& rPam
, SwNodeIndex
& rLastIdx
, const ULONG nNewIdx
, ULONG
& rDelCount
)
87 ULONG nStart
= rPam
.Start()->nNode
.GetIndex();
88 ULONG nEnd
= rPam
.End()->nNode
.GetIndex();
89 if( rLastIdx
.GetIndex() < nNewIdx
) // Moving forward?
91 do // count "non-copy" nodes
93 SwNode
& rNode
= rLastIdx
.GetNode();
94 if( ( rNode
.IsSectionNode() && rNode
.EndOfSectionIndex() >= nEnd
)
95 || ( rNode
.IsEndNode() && rNode
.StartOfSectionNode()->GetIndex() < nStart
) )
99 while( rLastIdx
.GetIndex() < nNewIdx
);
101 else if( rDelCount
) // optimization: if there are no "non-copy" nodes until now,
102 // no move backward needed
104 while( rLastIdx
.GetIndex() > nNewIdx
)
106 SwNode
& rNode
= rLastIdx
.GetNode();
107 if( ( rNode
.IsSectionNode() && rNode
.EndOfSectionIndex() >= nEnd
)
108 || ( rNode
.IsEndNode() && rNode
.StartOfSectionNode()->GetIndex() < nStart
) )
115 static void lcl_SetCpyPos( const SwPosition
& rOrigPos
,
116 const SwPosition
& rOrigStt
,
117 const SwPosition
& rCpyStt
,
121 ULONG nNdOff
= rOrigPos
.nNode
.GetIndex();
122 nNdOff
-= rOrigStt
.nNode
.GetIndex();
124 xub_StrLen nCntntPos
= rOrigPos
.nContent
.GetIndex();
126 // --> OD, AMA 2008-07-07 #b6713815#
127 // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
128 rChgPos
.nNode
= nNdOff
+ rCpyStt
.nNode
.GetIndex();
132 // dann nur den Content anpassen
133 if( nCntntPos
> rOrigStt
.nContent
.GetIndex() )
134 nCntntPos
= nCntntPos
- rOrigStt
.nContent
.GetIndex();
137 nCntntPos
= nCntntPos
+ rCpyStt
.nContent
.GetIndex();
139 rChgPos
.nContent
.Assign( rChgPos
.nNode
.GetNode().GetCntntNode(), nCntntPos
);
142 // TODO: use SaveBookmark (from _DelBookmarks)
143 static void lcl_CopyBookmarks(const SwPaM
& rPam
, SwPaM
& rCpyPam
)
145 const SwDoc
* pSrcDoc
= rPam
.GetDoc();
146 SwDoc
* pDestDoc
= rCpyPam
.GetDoc();
147 const IDocumentMarkAccess
* const pSrcMarkAccess
= pSrcDoc
->getIDocumentMarkAccess();
148 bool bDoesUndo
= pDestDoc
->DoesUndo();
149 pDestDoc
->DoUndo(false);
151 const SwPosition
&rStt
= *rPam
.Start(), &rEnd
= *rPam
.End();
152 SwPosition
* pCpyStt
= rCpyPam
.Start();
154 typedef ::std::vector
< const ::sw::mark::IMark
* > mark_vector_t
;
155 mark_vector_t vMarksToCopy
;
156 for(IDocumentMarkAccess::const_iterator_t ppMark
= pSrcMarkAccess
->getMarksBegin();
157 ppMark
!= pSrcMarkAccess
->getMarksEnd();
160 const ::sw::mark::IMark
* const pMark
= ppMark
->get();
161 const SwPosition
& rMarkStart
= pMark
->GetMarkStart();
162 const SwPosition
& rMarkEnd
= pMark
->GetMarkEnd();
163 // only include marks that are in the range and not touching
164 // both start and end
165 bool bIsNotOnBoundary
= pMark
->IsExpanded()
166 ? (rMarkStart
!= rStt
|| rMarkEnd
!= rEnd
) // rMarkStart != rMarkEnd
167 : (rMarkStart
!= rStt
&& rMarkEnd
!= rEnd
); // rMarkStart == rMarkEnd
168 if(rMarkStart
>= rStt
&& rMarkEnd
<= rEnd
&& bIsNotOnBoundary
)
170 vMarksToCopy
.push_back(pMark
);
173 // We have to count the "non-copied" nodes..
174 SwNodeIndex
aCorrIdx(rStt
.nNode
);
176 for(mark_vector_t::const_iterator ppMark
= vMarksToCopy
.begin();
177 ppMark
!= vMarksToCopy
.end();
180 const ::sw::mark::IMark
* const pMark
= *ppMark
;
181 SwPaM
aTmpPam(*pCpyStt
);
182 lcl_NonCopyCount(rPam
, aCorrIdx
, pMark
->GetMarkPos().nNode
.GetIndex(), nDelCount
);
183 lcl_SetCpyPos( pMark
->GetMarkPos(), rStt
, *pCpyStt
, *aTmpPam
.GetPoint(), nDelCount
);
184 if(pMark
->IsExpanded())
187 lcl_NonCopyCount(rPam
, aCorrIdx
, pMark
->GetOtherMarkPos().nNode
.GetIndex(), nDelCount
);
188 lcl_SetCpyPos(pMark
->GetOtherMarkPos(), rStt
, *pCpyStt
, *aTmpPam
.GetMark(), nDelCount
);
191 ::sw::mark::IMark
* const pNewMark
= pDestDoc
->getIDocumentMarkAccess()->makeMark(
194 IDocumentMarkAccess::GetType(*pMark
));
195 // Explicitly try to get exactly the same name as in the source
196 // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
197 pDestDoc
->getIDocumentMarkAccess()->renameMark(pNewMark
, pMark
->GetName());
198 ::sw::mark::IBookmark
* const pNewBookmark
=
199 dynamic_cast< ::sw::mark::IBookmark
* const >(pNewMark
);
200 if(pNewBookmark
) /* copying additional attributes for bookmarks */
202 const ::sw::mark::IBookmark
* const pOldBookmark
= dynamic_cast< const ::sw::mark::IBookmark
* >(pMark
);
203 pNewBookmark
->SetKeyCode(pOldBookmark
->GetKeyCode());
204 pNewBookmark
->SetShortName(pOldBookmark
->GetShortName());
206 ::sfx2::Metadatable
const*const pMetadatable(
207 dynamic_cast< ::sfx2::Metadatable
const* >(pMark
));
208 ::sfx2::Metadatable
*const pNewMetadatable(
209 dynamic_cast< ::sfx2::Metadatable
* >(pNewMark
));
210 if (pMetadatable
&& pNewMetadatable
)
212 pNewMetadatable
->RegisterAsCopyOf(*pMetadatable
);
215 pDestDoc
->DoUndo(bDoesUndo
);
219 // Struktur fuer das Mappen von alten und neuen Frame-Formaten an den
220 // Boxen und Lines einer Tabelle
224 const SwFrmFmt
*pOld
, *pNew
;
225 _MapTblFrmFmt( const SwFrmFmt
*pOldFmt
, const SwFrmFmt
*pNewFmt
)
226 : pOld( pOldFmt
), pNew( pNewFmt
)
230 SV_DECL_VARARR( _MapTblFrmFmts
, _MapTblFrmFmt
, 0, 10 )
231 SV_IMPL_VARARR( _MapTblFrmFmts
, _MapTblFrmFmt
);
233 SwCntntNode
* SwTxtNode::MakeCopy( SwDoc
* pDoc
, const SwNodeIndex
& rIdx
) const
235 // the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
236 // node with the collection and hard attributes. Normally ist the same
237 // node, but if insert a glossary without formatting, then the Attrnode
238 // is the prev node of the destionation position in dest. document.
239 SwTxtNode
* pCpyTxtNd
= (SwTxtNode
*)this;
240 SwTxtNode
* pCpyAttrNd
= pCpyTxtNd
;
242 // kopiere die Formate in das andere Dokument:
243 SwTxtFmtColl
* pColl
= 0;
244 if( pDoc
->IsInsOnlyTextGlossary() )
246 SwNodeIndex
aIdx( rIdx
, -1 );
247 if( aIdx
.GetNode().IsTxtNode() )
249 pCpyAttrNd
= aIdx
.GetNode().GetTxtNode();
250 pColl
= &pCpyAttrNd
->GetTxtColl()->GetNextTxtFmtColl();
254 pColl
= pDoc
->CopyTxtColl( *GetTxtColl() );
256 SwTxtNode
* pTxtNd
= pDoc
->GetNodes().MakeTxtNode( rIdx
, pColl
);
258 // METADATA: register copy
259 pTxtNd
->RegisterAsCopyOf(*pCpyTxtNd
);
261 // kopiere Attribute/Text
262 if( !pCpyAttrNd
->HasSwAttrSet() )
263 // wurde ein AttrSet fuer die Numerierung angelegt, so loesche diesen!
264 pCpyAttrNd
->ResetAllAttr();
266 // if Copy-Textnode unequal to Copy-Attrnode, then copy first
267 // the attributes into the new Node.
268 if( pCpyAttrNd
!= pCpyTxtNd
)
270 pCpyAttrNd
->CopyAttr( pTxtNd
, 0, 0 );
271 if( pCpyAttrNd
->HasSwAttrSet() )
273 SwAttrSet
aSet( *pCpyAttrNd
->GetpSwAttrSet() );
274 aSet
.ClearItem( RES_PAGEDESC
);
275 aSet
.ClearItem( RES_BREAK
);
276 aSet
.CopyToModify( *pTxtNd
);
280 // ??? reicht das ??? was ist mit PostIts/Feldern/FeldTypen ???
281 // --> OD 2008-11-18 #i96213# - force copy of all attributes
282 pCpyTxtNd
->CopyText( pTxtNd
, SwIndex( pCpyTxtNd
),
283 pCpyTxtNd
->GetTxt().Len(), true );
287 if( RES_CONDTXTFMTCOLL
== pColl
->Which() )
288 pTxtNd
->ChkCondColl();
295 BOOL
lcl_SrchNew( const _MapTblFrmFmt
& rMap
, void * pPara
)
297 if( rMap
.pOld
!= *(const SwFrmFmt
**)pPara
)
299 *((const SwFrmFmt
**)pPara
) = rMap
.pNew
;
300 return FALSE
; // abbrechen, Pointer gefunden
308 _MapTblFrmFmts
& rMapArr
;
309 SwTableLine
* pInsLine
;
312 const SwTable
*pOldTable
;
314 _CopyTable( SwDoc
* pDc
, _MapTblFrmFmts
& rArr
, ULONG nOldStt
,
315 SwTableNode
& rTblNd
, const SwTable
* pOldTbl
)
316 : pDoc(pDc
), nOldTblSttIdx(nOldStt
), rMapArr(rArr
),
317 pInsLine(0), pInsBox(0), pTblNd(&rTblNd
), pOldTable( pOldTbl
)
321 BOOL
lcl_CopyTblBox( const SwTableBox
*& rpBox
, void* pPara
);
323 BOOL
lcl_CopyTblLine( const SwTableLine
*& rpLine
, void* pPara
);
325 BOOL
lcl_CopyTblBox( const SwTableBox
*& rpBox
, void* pPara
)
327 _CopyTable
* pCT
= (_CopyTable
*)pPara
;
329 SwTableBoxFmt
* pBoxFmt
= (SwTableBoxFmt
*)rpBox
->GetFrmFmt();
330 pCT
->rMapArr
.ForEach( lcl_SrchNew
, &pBoxFmt
);
331 if( pBoxFmt
== rpBox
->GetFrmFmt() ) // ein neues anlegen ??
333 const SfxPoolItem
* pItem
;
334 if( SFX_ITEM_SET
== pBoxFmt
->GetItemState( RES_BOXATR_FORMULA
, FALSE
,
335 &pItem
) && ((SwTblBoxFormula
*)pItem
)->IsIntrnlName() )
337 ((SwTblBoxFormula
*)pItem
)->PtrToBoxNm( pCT
->pOldTable
);
340 pBoxFmt
= pCT
->pDoc
->MakeTableBoxFmt();
341 pBoxFmt
->CopyAttrs( *rpBox
->GetFrmFmt() );
343 if( rpBox
->GetSttIdx() )
345 SvNumberFormatter
* pN
= pCT
->pDoc
->GetNumberFormatter( FALSE
);
346 if( pN
&& pN
->HasMergeFmtTbl() && SFX_ITEM_SET
== pBoxFmt
->
347 GetItemState( RES_BOXATR_FORMAT
, FALSE
, &pItem
) )
349 ULONG nOldIdx
= ((SwTblBoxNumFormat
*)pItem
)->GetValue();
350 ULONG nNewIdx
= pN
->GetMergeFmtIndex( nOldIdx
);
351 if( nNewIdx
!= nOldIdx
)
352 pBoxFmt
->SetFmtAttr( SwTblBoxNumFormat( nNewIdx
));
357 pCT
->rMapArr
.Insert( _MapTblFrmFmt( rpBox
->GetFrmFmt(), pBoxFmt
),
358 pCT
->rMapArr
.Count() );
361 USHORT nLines
= rpBox
->GetTabLines().Count();
364 pNewBox
= new SwTableBox( pBoxFmt
, nLines
, pCT
->pInsLine
);
367 SwNodeIndex
aNewIdx( *pCT
->pTblNd
,
368 rpBox
->GetSttIdx() - pCT
->nOldTblSttIdx
);
369 ASSERT( aNewIdx
.GetNode().IsStartNode(), "Index nicht auf einem StartNode" );
370 pNewBox
= new SwTableBox( pBoxFmt
, aNewIdx
, pCT
->pInsLine
);
371 pNewBox
->setRowSpan( rpBox
->getRowSpan() );
374 pCT
->pInsLine
->GetTabBoxes().C40_INSERT( SwTableBox
, pNewBox
,
375 pCT
->pInsLine
->GetTabBoxes().Count() );
379 _CopyTable
aPara( *pCT
);
380 aPara
.pInsBox
= pNewBox
;
381 ((SwTableBox
*)rpBox
)->GetTabLines().ForEach( &lcl_CopyTblLine
, &aPara
);
383 else if( pNewBox
->IsInHeadline( &pCT
->pTblNd
->GetTable() ))
384 // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
385 pNewBox
->GetSttNd()->CheckSectionCondColl();
389 BOOL
lcl_CopyTblLine( const SwTableLine
*& rpLine
, void* pPara
)
391 _CopyTable
* pCT
= (_CopyTable
*)pPara
;
392 SwTableLineFmt
* pLineFmt
= (SwTableLineFmt
*)rpLine
->GetFrmFmt();
393 pCT
->rMapArr
.ForEach( lcl_SrchNew
, &pLineFmt
);
394 if( pLineFmt
== rpLine
->GetFrmFmt() ) // ein neues anlegen ??
396 pLineFmt
= pCT
->pDoc
->MakeTableLineFmt();
397 pLineFmt
->CopyAttrs( *rpLine
->GetFrmFmt() );
398 pCT
->rMapArr
.Insert( _MapTblFrmFmt( rpLine
->GetFrmFmt(), pLineFmt
),
399 pCT
->rMapArr
.Count());
401 SwTableLine
* pNewLine
= new SwTableLine( pLineFmt
,
402 rpLine
->GetTabBoxes().Count(), pCT
->pInsBox
);
403 // die neue Zeile in die Tabelle eintragen
406 pCT
->pInsBox
->GetTabLines().C40_INSERT( SwTableLine
, pNewLine
,
407 pCT
->pInsBox
->GetTabLines().Count() );
411 pCT
->pTblNd
->GetTable().GetTabLines().C40_INSERT( SwTableLine
, pNewLine
,
412 pCT
->pTblNd
->GetTable().GetTabLines().Count() );
414 pCT
->pInsLine
= pNewLine
;
415 ((SwTableLine
*)rpLine
)->GetTabBoxes().ForEach( &lcl_CopyTblBox
, pCT
);
419 SwTableNode
* SwTableNode::MakeCopy( SwDoc
* pDoc
, const SwNodeIndex
& rIdx
) const
421 // in welchen Array steht ich denn Nodes, UndoNodes ??
422 SwNodes
& rNds
= (SwNodes
&)GetNodes();
425 // nicht in Fussnoten kopieren !!
428 SwCntntNode* pCNd = pDoc->GetNodes()[ rIdx ]->GetCntntNode();
430 if( (pCNd && 0 != ( pFrm = pCNd->GetFrm()))
432 : rIdx < pDoc->GetNodes().EndOfInserts &&
433 pDoc->GetNodes()[pDoc->GetNodes().EndOfInserts]->StartOfSection()
436 if( rIdx
< pDoc
->GetNodes().GetEndOfInserts().GetIndex() &&
437 rIdx
>= pDoc
->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
441 // das TableFrmFmt kopieren
442 String
sTblName( GetTable().GetFrmFmt()->GetName() );
443 if( !pDoc
->IsCopyIsMove() )
445 const SwFrmFmts
& rTblFmts
= *pDoc
->GetTblFrmFmts();
446 for( USHORT n
= rTblFmts
.Count(); n
; )
447 if( rTblFmts
[ --n
]->GetName() == sTblName
)
449 sTblName
= pDoc
->GetUniqueTblName();
454 SwFrmFmt
* pTblFmt
= pDoc
->MakeTblFrmFmt( sTblName
, pDoc
->GetDfltFrmFmt() );
455 pTblFmt
->CopyAttrs( *GetTable().GetFrmFmt() );
456 SwTableNode
* pTblNd
= new SwTableNode( rIdx
);
457 SwEndNode
* pEndNd
= new SwEndNode( rIdx
, *pTblNd
);
458 SwNodeIndex
aInsPos( *pEndNd
);
460 SwTable
& rTbl
= (SwTable
&)pTblNd
->GetTable();
461 pTblFmt
->Add( &rTbl
); // das Frame-Format setzen
463 rTbl
.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
464 rTbl
.SetTblChgMode( GetTable().GetTblChgMode() );
465 rTbl
.SetTableModel( GetTable().IsNewModel() );
467 SwDDEFieldType
* pDDEType
= 0;
468 if( IS_TYPE( SwDDETable
, &GetTable() ))
470 // es wird eine DDE-Tabelle kopiert
471 // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
472 pDDEType
= ((SwDDETable
&)GetTable()).GetDDEFldType();
473 if( pDDEType
->IsDeleted() )
474 pDoc
->InsDeletedFldType( *pDDEType
);
476 pDDEType
= (SwDDEFieldType
*)pDoc
->InsertFldType( *pDDEType
);
477 ASSERT( pDDEType
, "unbekannter FieldType" );
479 // tauschen am Node den Tabellen-Pointer aus
480 SwDDETable
* pNewTable
= new SwDDETable( pTblNd
->GetTable(), pDDEType
);
481 pTblNd
->SetNewTable( pNewTable
, FALSE
);
483 // dann kopiere erstmal den Inhalt der Tabelle, die Zuordnung der
484 // Boxen/Lines und das anlegen der Frames erfolgt spaeter
485 SwNodeRange
aRg( *this, +1, *EndOfSectionNode() ); // (wo stehe in denn nun ??)
487 // If there is a table in this table, the table format for the outer table
488 // does not seem to be used, because the table does not have any contents yet
489 // (see IsUsed). Therefore the inner table gets the same name as the outer table.
490 // We have to make sure that the table node of the SwTable is accessible, even
491 // without any content in aSortCntBoxes. #i26629#
492 pTblNd
->GetTable().SetTableNode( pTblNd
);
493 rNds
._Copy( aRg
, aInsPos
, FALSE
);
494 pTblNd
->GetTable().SetTableNode( 0 );
496 // Sonderbehandlung fuer eine einzelne Box
497 if( 1 == GetTable().GetTabSortBoxes().Count() )
499 aRg
.aStart
.Assign( *pTblNd
, 1 );
500 aRg
.aEnd
.Assign( *pTblNd
->EndOfSectionNode() );
501 pDoc
->GetNodes().SectionDown( &aRg
, SwTableBoxStartNode
);
504 // loesche alle Frames vom kopierten Bereich, diese werden beim
505 // erzeugen des TableFrames angelegt !
508 _MapTblFrmFmts aMapArr
;
509 _CopyTable
aPara( pDoc
, aMapArr
, GetIndex(), *pTblNd
, &GetTable() );
511 ((SwTable
&)GetTable()).GetTabLines().ForEach( &lcl_CopyTblLine
, &aPara
);
514 pDDEType
->IncRefCnt();
516 CHECK_TABLE( GetTable() );
520 void SwTxtNode::CopyCollFmt( SwTxtNode
& rDestNd
)
522 // kopiere die Formate in das andere Dokument:
524 // Sonderbehandlung fuer PageBreak/PageDesc/ColBrk
525 SwDoc
* pDestDoc
= rDestNd
.GetDoc();
526 SwAttrSet
aPgBrkSet( pDestDoc
->GetAttrPool(), aBreakSetRange
);
527 const SwAttrSet
* pSet
;
529 if( 0 != ( pSet
= rDestNd
.GetpSwAttrSet() ) )
531 // Sonderbehandlung fuer unsere Break-Attribute
532 const SfxPoolItem
* pAttr
;
533 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
, FALSE
, &pAttr
) )
534 aPgBrkSet
.Put( *pAttr
);
536 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_PAGEDESC
, FALSE
, &pAttr
) )
537 aPgBrkSet
.Put( *pAttr
);
540 rDestNd
.ChgFmtColl( pDestDoc
->CopyTxtColl( *GetTxtColl() ));
541 if( 0 != ( pSet
= GetpSwAttrSet() ) )
542 pSet
->CopyToModify( rDestNd
);
544 if( aPgBrkSet
.Count() )
545 rDestNd
.SetAttr( aPgBrkSet
);
549 // ----- Copy-Methode vom SwDoc ------
551 // verhinder das Kopieren in Fly's, die im Bereich verankert sind.
552 BOOL
lcl_ChkFlyFly( SwDoc
* pDoc
, ULONG nSttNd
, ULONG nEndNd
,
555 const SwFrmFmt
* pFmt
;
556 const SwFmtAnchor
* pAnchor
;
557 const SwPosition
* pAPos
;
558 const SwSpzFrmFmts
& rFrmFmtTbl
= *pDoc
->GetSpzFrmFmts();
560 for( USHORT n
= 0; n
< rFrmFmtTbl
.Count(); ++n
)
562 pFmt
= rFrmFmtTbl
[n
];
563 pAnchor
= &pFmt
->GetAnchor();
564 if( 0 != ( pAPos
= pAnchor
->GetCntntAnchor()) &&
565 ( FLY_IN_CNTNT
== pAnchor
->GetAnchorId() ||
566 FLY_AUTO_CNTNT
== pAnchor
->GetAnchorId() ||
567 FLY_AT_FLY
== pAnchor
->GetAnchorId() ||
568 FLY_AT_CNTNT
== pAnchor
->GetAnchorId() ) &&
569 nSttNd
<= pAPos
->nNode
.GetIndex() &&
570 pAPos
->nNode
.GetIndex() < nEndNd
)
572 const SwFmtCntnt
& rCntnt
= pFmt
->GetCntnt();
574 if( !rCntnt
.GetCntntIdx() ||
575 0 == ( pSNd
= rCntnt
.GetCntntIdx()->GetNode().GetStartNode() ))
578 if( pSNd
->GetIndex() < nInsNd
&&
579 nInsNd
< pSNd
->EndOfSectionIndex() )
580 return TRUE
; // nicht kopieren !!
582 if( lcl_ChkFlyFly( pDoc
, pSNd
->GetIndex(),
583 pSNd
->EndOfSectionIndex(), nInsNd
) )
584 return TRUE
; // nicht kopieren !!
591 void lcl_DeleteRedlines( const SwPaM
& rPam
, SwPaM
& rCpyPam
)
593 const SwDoc
* pSrcDoc
= rPam
.GetDoc();
594 const SwRedlineTbl
& rTbl
= pSrcDoc
->GetRedlineTbl();
597 SwDoc
* pDestDoc
= rCpyPam
.GetDoc();
598 SwPosition
* pCpyStt
= rCpyPam
.Start(), *pCpyEnd
= rCpyPam
.End();
600 const SwPosition
*pStt
= rPam
.Start(), *pEnd
= rPam
.End();
601 // We have to count the "non-copied" nodes
603 SwNodeIndex
aCorrIdx( pStt
->nNode
);
606 pSrcDoc
->GetRedline( *pStt
, &n
);
607 for( ; n
< rTbl
.Count(); ++n
)
609 const SwRedline
* pRedl
= rTbl
[ n
];
610 if( nsRedlineType_t::REDLINE_DELETE
== pRedl
->GetType() && pRedl
->IsVisible() )
612 const SwPosition
*pRStt
= pRedl
->Start(), *pREnd
= pRedl
->End();
614 SwComparePosition eCmpPos
= ComparePosition( *pStt
, *pEnd
, *pRStt
, *pREnd
);
617 case POS_COLLIDE_END
:
618 case POS_BEFORE
: // Pos1 liegt vor Pos2
621 case POS_COLLIDE_START
:
622 case POS_BEHIND
: // Pos1 liegt hinter Pos2
628 pDelPam
= new SwPaM( *pCpyStt
, pDelPam
);
631 lcl_NonCopyCount( rPam
, aCorrIdx
, pRStt
->nNode
.GetIndex(), nDelCount
);
632 lcl_SetCpyPos( *pRStt
, *pStt
, *pCpyStt
,
633 *pDelPam
->GetPoint(), nDelCount
);
638 *pDelPam
->GetPoint() = *pCpyEnd
;
641 lcl_NonCopyCount( rPam
, aCorrIdx
, pREnd
->nNode
.GetIndex(), nDelCount
);
642 lcl_SetCpyPos( *pREnd
, *pStt
, *pCpyStt
,
643 *pDelPam
->GetPoint(), nDelCount
);
652 RedlineMode_t eOld
= pDestDoc
->GetRedlineMode();
653 pDestDoc
->SetRedlineMode_intern( (RedlineMode_t
)(eOld
| nsRedlineMode_t::REDLINE_IGNORE
));
655 BOOL bDoesUndo
= pDestDoc
->DoesUndo();
656 pDestDoc
->DoUndo( FALSE
);
659 pDestDoc
->DeleteAndJoin( *(SwPaM
*)pDelPam
->GetNext() );
660 if( pDelPam
->GetNext() == pDelPam
)
662 delete pDelPam
->GetNext();
666 pDestDoc
->DoUndo( bDoesUndo
);
667 pDestDoc
->SetRedlineMode_intern( eOld
);
672 void lcl_DeleteRedlines( const SwNodeRange
& rRg
, SwNodeRange
& rCpyRg
)
674 SwDoc
* pSrcDoc
= rRg
.aStart
.GetNode().GetDoc();
675 if( pSrcDoc
->GetRedlineTbl().Count() )
677 SwPaM
aRgTmp( rRg
.aStart
, rRg
.aEnd
);
678 SwPaM
aCpyTmp( rCpyRg
.aStart
, rCpyRg
.aEnd
);
679 lcl_DeleteRedlines( aRgTmp
, aCpyTmp
);
683 // Kopieren eines Bereiches im oder in ein anderes Dokument !
686 SwDoc::CopyRange( SwPaM
& rPam
, SwPosition
& rPos
, const bool bCopyAll
) const
688 const SwPosition
*pStt
= rPam
.Start(), *pEnd
= rPam
.End();
690 SwDoc
* pDoc
= rPos
.nNode
.GetNode().GetDoc();
691 bool bColumnSel
= pDoc
->IsClipBoard() && pDoc
->IsColumnSelection();
693 // kein Copy abfangen.
694 if( !rPam
.HasMark() || ( *pStt
>= *pEnd
&& !bColumnSel
) )
697 // verhinder das Kopieren in Fly's, die im Bereich verankert sind.
700 // Start-/EndNode noch korrigieren
701 ULONG nStt
= pStt
->nNode
.GetIndex(),
702 nEnd
= pEnd
->nNode
.GetIndex(),
703 nDiff
= nEnd
- nStt
+1;
704 SwNode
* pNd
= GetNodes()[ nStt
];
705 if( pNd
->IsCntntNode() && pStt
->nContent
.GetIndex() )
707 if( (pNd
= GetNodes()[ nEnd
])->IsCntntNode() &&
708 ((SwCntntNode
*)pNd
)->Len() != pEnd
->nContent
.GetIndex() )
711 lcl_ChkFlyFly( pDoc
, nStt
, nEnd
, rPos
.nNode
.GetIndex() ) )
717 SwPaM
* pRedlineRange
= 0;
718 if( pDoc
->IsRedlineOn() ||
719 (!pDoc
->IsIgnoreRedline() && pDoc
->GetRedlineTbl().Count() ) )
720 pRedlineRange
= new SwPaM( rPos
);
722 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
728 bRet
= CopyImpl( rPam
, rPos
, true, bCopyAll
, pRedlineRange
);
730 // Copy in sich selbst (ueber mehrere Nodes wird hier gesondert
731 // behandelt; in einem TextNode wird normal behandelt)
732 else if( ! ( *pStt
<= rPos
&& rPos
< *pEnd
&&
733 ( pStt
->nNode
!= pEnd
->nNode
||
734 !pStt
->nNode
.GetNode().IsTxtNode() )) )
736 bRet
= CopyImpl( rPam
, rPos
, true, bCopyAll
, pRedlineRange
);
740 ASSERT( this == pDoc
, " falscher Copy-Zweig!" );
741 ASSERT(false, "mst: i thought this could be dead code;"
742 "please tell me what you did to get here!");
743 pDoc
->SetRedlineMode_intern((RedlineMode_t
)(eOld
| nsRedlineMode_t::REDLINE_IGNORE
));
745 BOOL bDoUndo
= pDoc
->DoesUndo();
746 pDoc
->DoUndo( FALSE
); // Auf jedenfall Undo abschalten
747 // dann kopiere den Bereich im unteren DokumentBereich,
748 // (mit Start/End-Nodes geklammert) und verschiebe diese
749 // dann an die gewuenschte Stelle.
751 SwUndoCpyDoc
* pUndo
= 0;
752 SwPaM
aPam( rPos
); // UndoBereich sichern
756 pUndo
= new SwUndoCpyDoc( aPam
);
759 SwStartNode
* pSttNd
= pDoc
->GetNodes().MakeEmptySection(
760 SwNodeIndex( GetNodes().GetEndOfAutotext() ));
761 aPam
.GetPoint()->nNode
= *pSttNd
->EndOfSectionNode();
762 // copy without Frames
763 pDoc
->CopyImpl( rPam
, *aPam
.GetPoint(), false, bCopyAll
, 0 );
765 aPam
.GetPoint()->nNode
= pDoc
->GetNodes().GetEndOfAutotext();
767 SwCntntNode
* pNode
= pDoc
->GetNodes().GoPrevious( &aPam
.GetMark()->nNode
);
768 pNode
->MakeEndIndex( &aPam
.GetMark()->nContent
);
770 aPam
.GetPoint()->nNode
= *aPam
.GetNode()->StartOfSectionNode();
771 pNode
= pDoc
->GetNodes().GoNext( &aPam
.GetPoint()->nNode
);
772 pNode
->MakeStartIndex( &aPam
.GetPoint()->nContent
);
773 // move to desired position
774 pDoc
->MoveRange( aPam
, rPos
, DOC_MOVEDEFAULT
);
776 pNode
= aPam
.GetCntntNode();
777 *aPam
.GetPoint() = rPos
; // Cursor umsetzen fuers Undo !
778 aPam
.SetMark(); // auch den Mark umsetzen !!
779 aPam
.DeleteMark(); // aber keinen Bereich makieren !!
780 pDoc
->DeleteSection( pNode
); // Bereich wieder loeschen
782 // falls Undo eingeschaltet ist, so speicher den eingefuegten Bereich
783 pDoc
->DoUndo( bDoUndo
);
786 pUndo
->SetInsertRange( aPam
);
787 pDoc
->AppendUndo( pUndo
);
792 pRedlineRange
->SetMark();
793 *pRedlineRange
->GetPoint() = *aPam
.GetPoint();
794 *pRedlineRange
->GetMark() = *aPam
.GetMark();
801 pDoc
->SetRedlineMode_intern( eOld
);
804 if( pDoc
->IsRedlineOn() )
805 pDoc
->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT
, *pRedlineRange
), true);
807 pDoc
->SplitRedline( *pRedlineRange
);
808 delete pRedlineRange
;
814 // Kopieren eines Bereiches im oder in ein anderes Dokument !
815 // Die Position darf nicht im Bereich liegen !!
817 bool lcl_MarksWholeNode(const SwPaM
& rPam
)
819 bool bResult
= false;
820 const SwPosition
* pStt
= rPam
.Start();
821 const SwPosition
* pEnd
= rPam
.End();
823 if (NULL
!= pStt
&& NULL
!= pEnd
)
825 const SwTxtNode
* pSttNd
= pStt
->nNode
.GetNode().GetTxtNode();
826 const SwTxtNode
* pEndNd
= pEnd
->nNode
.GetNode().GetTxtNode();
828 if (NULL
!= pSttNd
&& NULL
!= pEndNd
&&
829 pStt
->nContent
.GetIndex() == 0 &&
830 pEnd
->nContent
.GetIndex() == pEndNd
->Len())
839 // --> OD 2009-08-25 #i86492#
840 bool lcl_ContainsOnlyParagraphsInList( const SwPaM
& rPam
)
844 const SwTxtNode
* pTxtNd
= rPam
.Start()->nNode
.GetNode().GetTxtNode();
845 const SwTxtNode
* pEndTxtNd
= rPam
.End()->nNode
.GetNode().GetTxtNode();
846 if ( pTxtNd
&& pTxtNd
->IsInList() &&
847 pEndTxtNd
&& pEndTxtNd
->IsInList() )
850 SwNodeIndex
aIdx(rPam
.Start()->nNode
);
855 pTxtNd
= aIdx
.GetNode().GetTxtNode();
857 if ( !pTxtNd
|| !pTxtNd
->IsInList() )
862 } while ( pTxtNd
&& pTxtNd
!= pEndTxtNd
);
870 bool SwDoc::CopyImpl( SwPaM
& rPam
, SwPosition
& rPos
,
871 const bool bMakeNewFrms
, const bool bCopyAll
,
872 SwPaM
*const pCpyRange
) const
874 SwDoc
* pDoc
= rPos
.nNode
.GetNode().GetDoc();
875 const bool bColumnSel
= pDoc
->IsClipBoard() && pDoc
->IsColumnSelection();
877 SwPosition
* pStt
= rPam
.Start();
878 SwPosition
* pEnd
= rPam
.End();
880 // kein Copy abfangen.
881 if( !rPam
.HasMark() || ( *pStt
>= *pEnd
&& !bColumnSel
) ||
882 //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
883 //JP 15.11.2001: don't test inclusive the end, ever exclusive
884 ( pDoc
== this && *pStt
<= rPos
&& rPos
< *pEnd
))
889 const bool bEndEqualIns
= pDoc
== this && rPos
== *pEnd
;
891 // falls Undo eingeschaltet, erzeuge das UndoCopy-Objekt
892 SwUndoCpyDoc
* pUndo
= 0;
893 SwPaM
aCpyPam( rPos
);
895 SwTblNumFmtMerge
aTNFM( *this, *pDoc
);
897 if( pDoc
->DoesUndo() )
900 pUndo
= new SwUndoCpyDoc( aCpyPam
);
901 pDoc
->AppendUndo( pUndo
);
904 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
905 pDoc
->SetRedlineMode_intern((RedlineMode_t
)(eOld
| nsRedlineMode_t::REDLINE_IGNORE
));
908 // bewege den Pam von der Insert-Position ein zurueck, dadurch wird
909 // die Position nicht "verschoben"
911 BOOL bCanMoveBack
= aCpyPam
.Move( fnMoveBackward
, fnGoCntnt
);
913 aCpyPam
.GetPoint()->nNode
--;
915 SwNodeRange
aRg( pStt
->nNode
, pEnd
->nNode
);
916 SwNodeIndex
aInsPos( rPos
.nNode
);
917 const bool bOneNode
= pStt
->nNode
== pEnd
->nNode
;
918 SwTxtNode
* pSttTxtNd
= pStt
->nNode
.GetNode().GetTxtNode();
919 SwTxtNode
* pEndTxtNd
= pEnd
->nNode
.GetNode().GetTxtNode();
920 SwTxtNode
* pDestTxtNd
= aInsPos
.GetNode().GetTxtNode();
921 bool bCopyCollFmt
= !pDoc
->IsInsOnlyTextGlossary() &&
922 ( ( pDestTxtNd
&& !pDestTxtNd
->GetTxt().Len() ) ||
923 ( !bOneNode
&& !rPos
.nContent
.GetIndex() ) );
924 bool bCopyBookmarks
= true;
925 BOOL bStartIsTxtNode
= 0 != pSttTxtNd
;
927 // --> OD 2009-08-25 #i86492#
928 // Correct the search for a previous list:
929 // First search for non-outline numbering list. Then search for non-outline
931 // Keep also the <ListId> value for possible propagation.
932 String aListIdToPropagate
;
933 const SwNumRule
* pNumRuleToPropagate
=
934 pDoc
->SearchNumRule( rPos
, false, true, false, 0, aListIdToPropagate
, true );
935 if ( !pNumRuleToPropagate
)
937 pNumRuleToPropagate
=
938 pDoc
->SearchNumRule( rPos
, false, false, false, 0, aListIdToPropagate
, true );
941 // --> OD 2009-08-25 #i86492#
942 // Do not propagate previous found list, if
943 // - destination is an empty paragraph which is not in a list and
944 // - source contains at least one paragraph which is not in a list
945 if ( pNumRuleToPropagate
&&
946 pDestTxtNd
&& !pDestTxtNd
->GetTxt().Len() && !pDestTxtNd
->IsInList() &&
947 !lcl_ContainsOnlyParagraphsInList( rPam
) )
949 pNumRuleToPropagate
= 0;
953 // Block, damit aus diesem gesprungen werden kann !!
957 // den Anfang nicht komplett kopieren ?
958 if( !bCopyCollFmt
|| bColumnSel
|| pStt
->nContent
.GetIndex() )
960 SwIndex
aDestIdx( rPos
.nContent
);
961 BOOL bCopyOk
= FALSE
;
964 if( pStt
->nContent
.GetIndex() || bOneNode
)
965 pDestTxtNd
= pDoc
->GetNodes().MakeTxtNode( aInsPos
,
966 pDoc
->GetTxtCollFromPool(RES_POOLCOLL_STANDARD
));
969 pDestTxtNd
= static_cast<SwTxtNode
*>(pSttTxtNd
->MakeCopy( pDoc
, aInsPos
));
972 aDestIdx
.Assign( pDestTxtNd
, 0 );
975 else if( !bOneNode
|| bColumnSel
)
977 xub_StrLen nCntntEnd
= pEnd
->nContent
.GetIndex();
978 BOOL bDoesUndo
= pDoc
->DoesUndo();
979 pDoc
->DoUndo( FALSE
);
980 pDoc
->SplitNode( rPos
, false );
981 pDoc
->DoUndo( bDoesUndo
);
983 if( bCanMoveBack
&& rPos
== *aCpyPam
.GetPoint() )
985 // nach dem SplitNode, den CpyPam wieder richtig aufspannen
986 aCpyPam
.Move( fnMoveBackward
, fnGoCntnt
);
987 aCpyPam
.Move( fnMoveBackward
, fnGoCntnt
);
990 pDestTxtNd
= pDoc
->GetNodes()[ aInsPos
.GetIndex()-1 ]->GetTxtNode();
991 aDestIdx
.Assign( pDestTxtNd
, pDestTxtNd
->GetTxt().Len() );
993 // korrigiere den Bereich wieder !!
996 BOOL bChg
= pEnd
!= rPam
.GetPoint();
999 rPam
.Move( fnMoveBackward
, fnGoCntnt
);
1003 aRg
.aEnd
= pEnd
->nNode
;
1004 pEndTxtNd
= pEnd
->nNode
.GetNode().GetTxtNode();
1006 else if( rPos
== *pEnd
) // Wurde das Ende auch verschoben
1009 pEnd
->nContent
.Assign( pDestTxtNd
, nCntntEnd
);
1010 aRg
.aEnd
= pEnd
->nNode
;
1011 pEndTxtNd
= pEnd
->nNode
.GetNode().GetTxtNode();
1015 /* #107213#: Safe numrule item at destination. */
1016 // --> OD 2009-08-25 #i86492#
1017 // Safe also <ListId> item of destination.
1018 int aNumRuleState
= SFX_ITEM_UNKNOWN
;
1019 SwNumRuleItem aNumRuleItem
;
1020 int aListIdState
= SFX_ITEM_UNKNOWN
;
1021 SfxStringItem
aListIdItem( RES_PARATR_LIST_ID
, String() );
1023 const SfxItemSet
* pAttrSet
= pDestTxtNd
->GetpSwAttrSet();
1024 if (pAttrSet
!= NULL
)
1026 const SfxPoolItem
* pItem
= NULL
;
1027 aNumRuleState
= pAttrSet
->GetItemState(RES_PARATR_NUMRULE
, FALSE
, &pItem
);
1028 if (SFX_ITEM_SET
== aNumRuleState
)
1029 aNumRuleItem
= *((SwNumRuleItem
*) pItem
);
1032 pAttrSet
->GetItemState(RES_PARATR_LIST_ID
, FALSE
, &pItem
);
1033 if (SFX_ITEM_SET
== aListIdState
)
1035 aListIdItem
.SetValue( static_cast<const SfxStringItem
*>(pItem
)->GetValue() );
1044 const xub_StrLen nCpyLen
= ( (bOneNode
)
1045 ? pEnd
->nContent
.GetIndex()
1046 : pSttTxtNd
->GetTxt().Len() )
1047 - pStt
->nContent
.GetIndex();
1048 pSttTxtNd
->CopyText( pDestTxtNd
, aDestIdx
,
1049 pStt
->nContent
, nCpyLen
);
1051 pEnd
->nContent
-= nCpyLen
;
1058 pSttTxtNd
->CopyCollFmt( *pDestTxtNd
);
1060 /* #107213# If only a part of one paragraph is copied
1061 restore the numrule at the destination. */
1062 // --> OD 2009-08-25 #i86492#
1063 // restore also <ListId> item
1064 if ( !lcl_MarksWholeNode(rPam
) )
1066 if (SFX_ITEM_SET
== aNumRuleState
)
1068 pDestTxtNd
->SetAttr(aNumRuleItem
);
1072 pDestTxtNd
->ResetAttr(RES_PARATR_NUMRULE
);
1074 if (SFX_ITEM_SET
== aListIdState
)
1076 pDestTxtNd
->SetAttr(aListIdItem
);
1080 pDestTxtNd
->ResetAttr(RES_PARATR_LIST_ID
);
1091 else if( pDestTxtNd
)
1093 // Problems with insertion of table selections into "normal" text solved.
1094 // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
1095 // the undo operation will try to merge this node after removing the table.
1096 // If we didn't split a textnode, the PaM should start at the inserted table node
1097 if( rPos
.nContent
.GetIndex() == pDestTxtNd
->Len() )
1098 { // Insertion at the last position of a textnode (empty or not)
1099 aInsPos
++; // The table will be inserted behind the text node
1101 else if( rPos
.nContent
.GetIndex() )
1102 { // Insertion in the middle of a text node, it has to be split
1103 // (and joined from undo)
1104 bStartIsTxtNode
= TRUE
;
1105 // splitte den TextNode, bei dem Eingefuegt wird.
1107 xub_StrLen nCntntEnd
= pEnd
->nContent
.GetIndex();
1108 BOOL bDoesUndo
= pDoc
->DoesUndo();
1109 pDoc
->DoUndo( FALSE
);
1110 pDoc
->SplitNode( rPos
, false );
1111 pDoc
->DoUndo( bDoesUndo
);
1113 if( bCanMoveBack
&& rPos
== *aCpyPam
.GetPoint() )
1115 // nach dem SplitNode, den CpyPam wieder richtig aufspannen
1116 aCpyPam
.Move( fnMoveBackward
, fnGoCntnt
);
1117 aCpyPam
.Move( fnMoveBackward
, fnGoCntnt
);
1120 // korrigiere den Bereich wieder !!
1123 else if( rPos
== *pEnd
) // Wurde das Ende auch verschoben
1126 rPos
.nContent
.Assign( rPos
.nNode
.GetNode().GetCntntNode(),
1132 else if( bCanMoveBack
)
1133 { //Insertion at the first position of a text node. It will not be splitted, the table
1134 // will be inserted before the text node.
1135 // See below, before the SetInsertRange funciton of the undo object will be called,
1136 // the CpyPam would be moved to the next content position. This has to be avoided
1137 // We want to be moved to the table node itself thus we have to set bCanMoveBack
1138 // and to manipulate aCpyPam.
1139 bCanMoveBack
= false;
1140 aCpyPam
.GetPoint()->nNode
--;
1144 pDestTxtNd
= aInsPos
.GetNode().GetTxtNode();
1147 SwIndex
aDestIdx( rPos
.nContent
);
1150 pDestTxtNd
= pDoc
->GetNodes().MakeTxtNode( aInsPos
,
1151 pDoc
->GetTxtCollFromPool(RES_POOLCOLL_STANDARD
));
1152 aDestIdx
.Assign( pDestTxtNd
, 0 );
1155 // #112756# #98130# if we have to insert an extra text node
1156 // at the destination, this node will be our new destination
1157 // (text) node, and thus we set bStartisTxtNode to true. This
1158 // will ensure that this node will be deleted during Undo
1160 DBG_ASSERT( !bStartIsTxtNode
, "Oops, undo may be instable now." );
1161 bStartIsTxtNode
= TRUE
;
1164 /* #107213# Save numrule at destination */
1165 // --> OD 2009-08-25 #i86492#
1166 // Safe also <ListId> item of destination.
1167 int aNumRuleState
= SFX_ITEM_UNKNOWN
;
1168 SwNumRuleItem aNumRuleItem
;
1169 int aListIdState
= SFX_ITEM_UNKNOWN
;
1170 SfxStringItem
aListIdItem( RES_PARATR_LIST_ID
, String() );
1172 const SfxItemSet
* pAttrSet
= pDestTxtNd
->GetpSwAttrSet();
1173 if (pAttrSet
!= NULL
)
1175 const SfxPoolItem
* pItem
= NULL
;
1178 pAttrSet
->GetItemState(RES_PARATR_NUMRULE
, FALSE
, &pItem
);
1179 if (SFX_ITEM_SET
== aNumRuleState
)
1180 aNumRuleItem
= *((SwNumRuleItem
*) pItem
);
1183 pAttrSet
->GetItemState(RES_PARATR_LIST_ID
, FALSE
, &pItem
);
1184 if (SFX_ITEM_SET
== aListIdState
)
1185 aListIdItem
.SetValue( static_cast<const SfxStringItem
*>(pItem
)->GetValue() );
1191 const bool bEmptyDestNd
= 0 == pDestTxtNd
->GetTxt().Len();
1192 pEndTxtNd
->CopyText( pDestTxtNd
, aDestIdx
, SwIndex( pEndTxtNd
),
1193 pEnd
->nContent
.GetIndex() );
1195 // auch alle FormatVorlagen kopieren
1196 if( bCopyCollFmt
&& ( bOneNode
|| bEmptyDestNd
))
1198 pEndTxtNd
->CopyCollFmt( *pDestTxtNd
);
1202 /* #107213# If only a part of one paragraph is copied
1203 restore the numrule at the destination. */
1204 // --> OD 2009-08-25 #i86492#
1205 // restore also <ListId> item
1206 if ( !lcl_MarksWholeNode(rPam
) )
1208 if (SFX_ITEM_SET
== aNumRuleState
)
1210 pDestTxtNd
->SetAttr(aNumRuleItem
);
1214 pDestTxtNd
->ResetAttr(RES_PARATR_NUMRULE
);
1216 if (SFX_ITEM_SET
== aListIdState
)
1218 pDestTxtNd
->SetAttr(aListIdItem
);
1222 pDestTxtNd
->ResetAttr(RES_PARATR_LIST_ID
);
1229 if( bCopyAll
|| aRg
.aStart
!= aRg
.aEnd
)
1231 SfxItemSet
aBrkSet( pDoc
->GetAttrPool(), aBreakSetRange
);
1232 if( pSttTxtNd
&& bCopyCollFmt
&& pDestTxtNd
->HasSwAttrSet() )
1234 aBrkSet
.Put( *pDestTxtNd
->GetpSwAttrSet() );
1235 if( SFX_ITEM_SET
== aBrkSet
.GetItemState( RES_BREAK
, FALSE
) )
1236 pDestTxtNd
->ResetAttr( RES_BREAK
);
1237 if( SFX_ITEM_SET
== aBrkSet
.GetItemState( RES_PAGEDESC
, FALSE
) )
1238 pDestTxtNd
->ResetAttr( RES_PAGEDESC
);
1241 if( aInsPos
== pEnd
->nNode
)
1243 SwNodeIndex
aSaveIdx( aInsPos
, -1 );
1244 CopyWithFlyInFly( aRg
, 0,aInsPos
, bMakeNewFrms
, FALSE
);
1246 pEnd
->nNode
= aSaveIdx
;
1247 pEnd
->nContent
.Assign( aSaveIdx
.GetNode().GetTxtNode(), 0 );
1250 CopyWithFlyInFly( aRg
, pEnd
->nContent
.GetIndex(), aInsPos
, bMakeNewFrms
, FALSE
);
1252 bCopyBookmarks
= false;
1254 // harte Umbrueche wieder in den ersten Node setzen
1255 if( aBrkSet
.Count() && 0 != ( pDestTxtNd
= pDoc
->GetNodes()[
1256 aCpyPam
.GetPoint()->nNode
.GetIndex()+1 ]->GetTxtNode() ) )
1258 pDestTxtNd
->SetAttr( aBrkSet
);
1263 // Position ummelden ( falls verschoben / im anderen Node )
1264 rPos
.nContent
.Assign( rPos
.nNode
.GetNode().GetCntntNode(),
1265 rPos
.nContent
.GetIndex() );
1267 if( rPos
.nNode
!= aInsPos
)
1269 aCpyPam
.GetMark()->nNode
= aInsPos
;
1270 aCpyPam
.GetMark()->nContent
.Assign( aCpyPam
.GetCntntNode(FALSE
), 0 );
1271 rPos
= *aCpyPam
.GetMark();
1274 *aCpyPam
.GetMark() = rPos
;
1276 aCpyPam
.Move( fnMoveForward
, bCanMoveBack
? fnGoCntnt
: fnGoNode
);
1279 // dann kopiere noch alle Bookmarks
1280 if( bCopyBookmarks
&& getIDocumentMarkAccess()->getMarksCount() )
1281 lcl_CopyBookmarks( rPam
, aCpyPam
);
1283 if( nsRedlineMode_t::REDLINE_DELETE_REDLINES
& eOld
)
1284 lcl_DeleteRedlines( rPam
, aCpyPam
);
1286 // falls Undo eingeschaltet ist, so speicher den eingefuegten Bereich
1287 if( pDoc
->DoesUndo() )
1288 pUndo
->SetInsertRange( aCpyPam
, TRUE
, bStartIsTxtNode
);
1292 pCpyRange
->SetMark();
1293 *pCpyRange
->GetPoint() = *aCpyPam
.GetPoint();
1294 *pCpyRange
->GetMark() = *aCpyPam
.GetMark();
1297 if ( pNumRuleToPropagate
)
1299 // --> OD 2009-08-25 #i86492#
1300 // use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
1301 // pDoc->ReplaceNumRule(aCpyPam, *pNumRuleToPropagate);
1302 pDoc
->SetNumRule( aCpyPam
, *pNumRuleToPropagate
, false,
1303 aListIdToPropagate
, sal_True
, true );
1306 pDoc
->SetRedlineMode_intern( eOld
);
1307 pDoc
->SetModified();
1313 // ----- Copy-Methode vom SwDoc - "kopiere Fly's in Fly's" ------
1315 void SwDoc::CopyWithFlyInFly( const SwNodeRange
& rRg
, const xub_StrLen nEndContentIndex
,
1316 const SwNodeIndex
& rInsPos
, BOOL bMakeNewFrms
,
1317 BOOL bDelRedlines
, BOOL bCopyFlyAtFly
) const
1319 SwDoc
* pDest
= rInsPos
.GetNode().GetDoc();
1321 _SaveRedlEndPosForRestore
aRedlRest( rInsPos
, 0 );
1323 SwNodeIndex
aSavePos( rInsPos
, -1 );
1324 BOOL bEndIsEqualEndPos
= rInsPos
== rRg
.aEnd
;
1325 GetNodes()._CopyNodes( rRg
, rInsPos
, bMakeNewFrms
, TRUE
);
1327 if( bEndIsEqualEndPos
)
1328 ((SwNodeIndex
&)rRg
.aEnd
) = aSavePos
;
1330 aRedlRest
.Restore();
1334 //JP 17.06.99: Bug 66973 - check count only if the selection is in
1335 // the same (or no) section. Becaus not full selected
1336 // section are not copied.
1337 const SwSectionNode
* pSSectNd
= rRg
.aStart
.GetNode().FindSectionNode();
1338 SwNodeIndex
aTmpI( rRg
.aEnd
, -1 );
1339 const SwSectionNode
* pESectNd
= aTmpI
.GetNode().FindSectionNode();
1340 if( pSSectNd
== pESectNd
&&
1341 !rRg
.aStart
.GetNode().IsSectionNode() &&
1342 !aTmpI
.GetNode().IsEndNode() )
1344 ASSERT( rInsPos
.GetIndex() - aSavePos
.GetIndex() ==
1345 rRg
.aEnd
.GetIndex() - rRg
.aStart
.GetIndex(),
1346 "Es wurden zu wenig Nodes kopiert!" )
1352 BOOL bUndo
= pDest
->DoesUndo();
1353 pDest
->DoUndo( FALSE
);
1354 CopyFlyInFlyImpl( rRg
, nEndContentIndex
, aSavePos
, bCopyFlyAtFly
);
1355 pDest
->DoUndo( bUndo
);
1357 SwNodeRange
aCpyRange( aSavePos
, rInsPos
);
1359 // dann kopiere noch alle Bookmarks
1360 if( getIDocumentMarkAccess()->getMarksCount() )
1362 SwPaM
aRgTmp( rRg
.aStart
, rRg
.aEnd
);
1363 SwPaM
aCpyTmp( aCpyRange
.aStart
, aCpyRange
.aEnd
);
1365 lcl_CopyBookmarks( aRgTmp
, aCpyTmp
);
1368 if( bDelRedlines
&& ( nsRedlineMode_t::REDLINE_DELETE_REDLINES
& pDest
->GetRedlineMode() ))
1369 lcl_DeleteRedlines( rRg
, aCpyRange
);
1371 pDest
->GetNodes()._DelDummyNodes( aCpyRange
);
1374 void lcl_ChainFmts( SwFlyFrmFmt
*pSrc
, SwFlyFrmFmt
*pDest
)
1376 SwFmtChain
aSrc( pSrc
->GetChain() );
1377 if ( !aSrc
.GetNext() )
1379 aSrc
.SetNext( pDest
);
1380 pSrc
->SetFmtAttr( aSrc
);
1382 SwFmtChain
aDest( pDest
->GetChain() );
1383 if ( !aDest
.GetPrev() )
1385 aDest
.SetPrev( pSrc
);
1386 pDest
->SetFmtAttr( aDest
);
1390 void SwDoc::CopyFlyInFlyImpl( const SwNodeRange
& rRg
,
1391 const xub_StrLen nEndContentIndex
, const SwNodeIndex
& rStartIdx
,
1392 const bool bCopyFlyAtFly
) const
1394 // Bug 22727: suche erst mal alle Flys zusammen, sortiere sie entsprechend
1395 // ihrer Ordnungsnummer und kopiere sie erst dann. Damit wird
1396 // die Ordnungsnummer (wird nur im DrawModel verwaltet)
1398 SwDoc
*const pDest
= rStartIdx
.GetNode().GetDoc();
1400 USHORT nArrLen
= GetSpzFrmFmts()->Count();
1403 for( n
= 0; n
< nArrLen
; ++n
)
1405 const SwFrmFmt
* pFmt
= (*GetSpzFrmFmts())[n
];
1406 const SwFmtAnchor
* pAnchor
= &pFmt
->GetAnchor();
1407 const SwPosition
* pAPos
;
1408 bool bAtCntnt
= pAnchor
->GetAnchorId() == FLY_AT_CNTNT
;
1410 pAnchor
->GetAnchorId() == FLY_AT_FLY
||
1411 pAnchor
->GetAnchorId() == FLY_AUTO_CNTNT
) &&
1412 0 != ( pAPos
= pAnchor
->GetCntntAnchor()) &&
1413 (( bCopyFlyAtFly
&& FLY_AT_FLY
== pAnchor
->GetAnchorId() )
1414 ? rRg
.aStart
<= pAPos
->nNode
.GetIndex() + 1
1416 ? rRg
.aStart
< pAPos
->nNode
1417 : rRg
.aStart
<= pAPos
->nNode
)) &&
1418 pAPos
->nNode
<= rRg
.aEnd
)
1420 //frames at the last source node are not always copied:
1421 //- if the node is empty and is the last node of the document or a table cell
1422 // or a text frame then tey have to be copied
1423 //- if the content index in this node is > 0 then paragph and frame bound objects are copied
1424 //- to-character bound objects are copied if their index is <= nEndContentIndex
1426 if( pAPos
->nNode
< rRg
.aEnd
)
1430 bool bEmptyNode
= false;
1431 bool bLastNode
= false;
1432 // is the node empty?
1433 const SwNodes
& rNodes
= pAPos
->nNode
.GetNodes();
1434 SwTxtNode
* pTxtNode
;
1435 if( 0 != ( pTxtNode
= pAPos
->nNode
.GetNode().GetTxtNode() ))
1437 bEmptyNode
= !pTxtNode
->GetTxt().Len();
1440 //last node information is only necessary to know for the last TextNode
1441 SwNodeIndex
aTmp( pAPos
->nNode
);
1442 ++aTmp
;//goto next node
1443 while( rNodes
[aTmp
]->IsEndNode() )
1445 if( aTmp
== rNodes
.GetEndOfContent().GetIndex() )
1454 bAdd
= bLastNode
&& bEmptyNode
;
1458 bAdd
= nEndContentIndex
> 0;
1460 bAdd
= pAPos
->nContent
<= nEndContentIndex
;
1464 aArr
.Insert( _ZSortFly( pFmt
, pAnchor
, nArrLen
+ aArr
.Count() ));
1468 //Alle kopierten (also die neu erzeugten) Rahmen in ein weiteres Array
1469 //stopfen. Dort sizten sie passend zu den Originalen, damit hinterher
1470 //die Chains entsprechend aufgebaut werden koennen.
1471 SvPtrarr
aNewArr( 10, 10 );
1473 for( n
= 0; n
< aArr
.Count(); ++n
)
1475 const _ZSortFly
& rZSortFly
= aArr
[ n
];
1477 // --> OD 2006-01-04 #i59964#
1478 // correct determination of new anchor position
1479 SwFmtAnchor
aAnchor( *rZSortFly
.GetAnchor() );
1480 SwPosition
* pNewPos
= (SwPosition
*)aAnchor
.GetCntntAnchor();
1481 // for at-paragraph and at-character anchored objects the new anchor
1482 // position can *not* be determined by the difference of the current
1483 // anchor position to the start of the copied range, because not
1484 // complete selected sections in the copied range aren't copied - see
1485 // method <SwNodes::_CopyNodes(..)>.
1486 // Thus, the new anchor position in the destination document is found
1487 // by counting the text nodes.
1488 if ( aAnchor
.GetAnchorId() == FLY_AT_CNTNT
||
1489 aAnchor
.GetAnchorId() == FLY_AUTO_CNTNT
)
1491 // First, determine number of anchor text node in the copied range.
1492 // Note: The anchor text node *have* to be inside the copied range.
1493 ULONG
nAnchorTxtNdNumInRange( 0L );
1494 bool bAnchorTxtNdFound( false );
1495 SwNodeIndex
aIdx( rRg
.aStart
);
1496 while ( !bAnchorTxtNdFound
&& aIdx
<= rRg
.aEnd
)
1498 if ( aIdx
.GetNode().IsTxtNode() )
1500 ++nAnchorTxtNdNumInRange
;
1501 bAnchorTxtNdFound
= aAnchor
.GetCntntAnchor()->nNode
== aIdx
;
1506 if ( !bAnchorTxtNdFound
)
1508 // This case can *not* happen, but to be robust take the first
1509 // text node in the destination document.
1511 "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
1512 nAnchorTxtNdNumInRange
= 1;
1514 // Second, search corresponding text node in destination document
1515 // by counting forward from start insert position <rStartIdx> the
1516 // determined number of text nodes.
1518 SwNodeIndex
aAnchorNdIdx( rStartIdx
);
1519 const SwNode
& aEndOfContentNd
=
1520 aIdx
.GetNode().GetNodes().GetEndOfContent();
1521 while ( nAnchorTxtNdNumInRange
> 0 &&
1522 &(aIdx
.GetNode()) != &aEndOfContentNd
)
1524 if ( aIdx
.GetNode().IsTxtNode() )
1526 --nAnchorTxtNdNumInRange
;
1527 aAnchorNdIdx
= aIdx
;
1532 if ( !aAnchorNdIdx
.GetNode().IsTxtNode() )
1534 // This case can *not* happen, but to be robust take the first
1535 // text node in the destination document.
1537 "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
1538 aAnchorNdIdx
= rStartIdx
;
1539 while ( !aAnchorNdIdx
.GetNode().IsTxtNode() )
1544 // apply found anchor text node as new anchor position
1545 pNewPos
->nNode
= aAnchorNdIdx
;
1549 long nOffset
= pNewPos
->nNode
.GetIndex() - rRg
.aStart
.GetIndex();
1550 SwNodeIndex
aIdx( rStartIdx
, nOffset
);
1551 pNewPos
->nNode
= aIdx
;
1554 // die am Zeichen Flys wieder ans das vorgegebene Zeichen setzen
1555 if ( FLY_AUTO_CNTNT
== aAnchor
.GetAnchorId() &&
1556 pNewPos
->nNode
.GetNode().IsTxtNode() )
1558 pNewPos
->nContent
.Assign( (SwTxtNode
*)&pNewPos
->nNode
.GetNode(),
1559 pNewPos
->nContent
.GetIndex() );
1563 pNewPos
->nContent
.Assign( 0, 0 );
1566 // ueberpruefe Rekursion: Inhalt in "seinen eigenen" Frame
1567 // kopieren. Dann nicht kopieren
1568 BOOL bMakeCpy
= TRUE
;
1571 const SwFmtCntnt
& rCntnt
= rZSortFly
.GetFmt()->GetCntnt();
1572 const SwStartNode
* pSNd
;
1573 if( rCntnt
.GetCntntIdx() &&
1574 0 != ( pSNd
= rCntnt
.GetCntntIdx()->GetNode().GetStartNode() ) &&
1575 pSNd
->GetIndex() < rStartIdx
.GetIndex() &&
1576 rStartIdx
.GetIndex() < pSNd
->EndOfSectionIndex() )
1579 aArr
.Remove( n
, 1 );
1584 // Format kopieren und den neuen Anker setzen
1586 aNewArr
.Insert( pDest
->CopyLayoutFmt( *rZSortFly
.GetFmt(),
1587 aAnchor
, false, true ), aNewArr
.Count() );
1590 //Alle chains, die im Original vorhanden sind, soweit wie moeglich wieder
1592 ASSERT( aArr
.Count() == aNewArr
.Count(), "Missing new Flys" );
1593 if ( aArr
.Count() == aNewArr
.Count() )
1595 for ( n
= 0; n
< aArr
.Count(); ++n
)
1597 const SwFrmFmt
*pFmt
= aArr
[n
].GetFmt();
1598 const SwFmtChain
&rChain
= pFmt
->GetChain();
1599 int nCnt
= 0 != rChain
.GetPrev();
1600 nCnt
+= rChain
.GetNext() ? 1: 0;
1601 for ( USHORT k
= 0; nCnt
&& k
< aArr
.Count(); ++k
)
1603 const _ZSortFly
&rTmp
= aArr
[k
];
1604 const SwFrmFmt
*pTmp
= rTmp
.GetFmt();
1605 if ( rChain
.GetPrev() == pTmp
)
1607 ::lcl_ChainFmts( (SwFlyFrmFmt
*)aNewArr
[k
],
1608 (SwFlyFrmFmt
*)aNewArr
[n
] );
1611 else if ( rChain
.GetNext() == pTmp
)
1613 ::lcl_ChainFmts( (SwFlyFrmFmt
*)aNewArr
[n
],
1614 (SwFlyFrmFmt
*)aNewArr
[k
] );