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: tblcpy.cxx,v $
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 #include <hintids.hxx>
37 #define _ZFORLIST_DECLARE_TABLE
38 #include <svtools/zforlist.hxx>
43 #include <swtable.hxx>
48 #include <poolfmt.hxx>
49 #include <cellatr.hxx>
52 #include <fmtanchr.hxx>
54 #include <redline.hxx>
55 #include <fmtfsize.hxx>
58 BOOL
_FndCntntLine( const SwTableLine
*& rpLine
, void* pPara
);
59 BOOL
_FndCntntBox( const SwTableBox
*& rpBox
, void* pPara
);
60 void lcl_CpyBox( const SwTable
& rCpyTbl
, const SwTableBox
* pCpyBox
,
61 SwTable
& rDstTbl
, SwTableBox
* pDstBox
,
62 BOOL bDelCntnt
, SwUndoTblCpyTbl
* pUndo
);
64 // The following type will be used by table copy functions to describe
65 // the structure of tables (or parts of tables).
66 // It's for new table model only.
78 typedef std::vector
< BoxSpanInfo
> BoxStructure
;
79 typedef std::vector
< BoxStructure
> LineStructure
;
80 typedef std::list
< ULONG
> ColumnStructure
;
88 typedef std::list
< SubBox
> SubLine
;
89 typedef std::list
< SubLine
> SubTable
;
94 LineStructure maLines
;
95 ColumnStructure maCols
;
98 void addLine( USHORT
&rLine
, const SwTableBoxes
&, const SwSelBoxes
*,
100 void addBox( USHORT nLine
, const SwSelBoxes
*, SwTableBox
*pBox
,
101 ULONG
&rnB
, USHORT
&rnC
, ColumnStructure::iterator
& rpCl
,
102 BoxStructure::iterator
& rpSel
, bool &rbSel
, bool bCover
);
103 void incColSpan( USHORT nLine
, USHORT nCol
);
104 TableStructure( const SwTable
& rTable
);
105 TableStructure( const SwTable
& rTable
, _FndBox
&rFndBox
,
106 const SwSelBoxes
& rSelBoxes
,
107 LineStructure::size_type nMinSize
);
108 LineStructure::size_type
getLineCount() const
109 { return maLines
.size(); }
110 void moreLines( const SwTable
& rTable
);
111 void assignBoxes( const TableStructure
&rSource
);
112 void copyBoxes( const SwTable
& rSource
, SwTable
& rDstTbl
,
113 SwUndoTblCpyTbl
* pUndo
) const;
116 SubTable::iterator
insertSubLine( SubTable
& rSubTable
, SwTableLine
& rLine
,
117 SubTable::iterator pStartLn
);
119 SubTable::iterator
insertSubBox( SubTable
& rSubTable
, SwTableBox
& rBox
,
120 SubTable::iterator pStartLn
, SubTable::iterator pEndLn
)
122 if( rBox
.GetTabLines().Count() )
124 SubTable::difference_type nSize
= std::distance( pStartLn
, pEndLn
);
125 if( nSize
< rBox
.GetTabLines().Count() )
128 SubLine::iterator pBox
= pStartLn
->begin();
129 SubLine::iterator pEnd
= pStartLn
->end();
130 while( pBox
!= pEnd
)
133 aSub
.mpBox
= pBox
->mpBox
;
134 aSub
.mbCovered
= true;
135 aSubLine
.push_back( aSub
);
140 rSubTable
.insert( pEndLn
, aSubLine
);
141 } while( ++nSize
< rBox
.GetTabLines().Count() );
143 for( USHORT nLine
= 0; nLine
< rBox
.GetTabLines().Count(); ++nLine
)
144 pStartLn
= insertSubLine( rSubTable
, *rBox
.GetTabLines()[nLine
],
146 ASSERT( pStartLn
== pEndLn
, "Sub line confusion" );
152 aSub
.mbCovered
= false;
153 while( pStartLn
!= pEndLn
)
155 pStartLn
->push_back( aSub
);
156 aSub
.mbCovered
= true;
163 SubTable::iterator
insertSubLine( SubTable
& rSubTable
, SwTableLine
& rLine
,
164 SubTable::iterator pStartLn
)
166 SubTable::iterator pMax
= pStartLn
;
168 SubTable::difference_type nMax
= 1;
169 for( USHORT nBox
= 0; nBox
< rLine
.GetTabBoxes().Count(); ++nBox
)
171 SubTable::iterator pTmp
= insertSubBox( rSubTable
,
172 *rLine
.GetTabBoxes()[nBox
], pStartLn
, pMax
);
173 SubTable::difference_type nTmp
= std::distance( pStartLn
, pTmp
);
183 TableStructure::TableStructure( const SwTable
& rTable
) :
184 maLines( rTable
.GetTabLines().Count() ), mnStartCol(USHRT_MAX
),
187 maCols
.push_front(0);
188 const SwTableLines
&rLines
= rTable
.GetTabLines();
190 for( USHORT nLine
= 0; nLine
< rLines
.Count(); ++nLine
)
191 addLine( nCnt
, rLines
[nLine
]->GetTabBoxes(), 0, rTable
.IsNewModel() );
194 TableStructure::TableStructure( const SwTable
& rTable
,
195 _FndBox
&rFndBox
, const SwSelBoxes
& rSelBoxes
,
196 LineStructure::size_type nMinSize
)
197 : mnStartCol(USHRT_MAX
), mnAddLine(0)
199 if( rFndBox
.GetLines().Count() )
201 bool bNoSelection
= rSelBoxes
.Count() < 2;
202 _FndLines
&rFndLines
= rFndBox
.GetLines();
203 maCols
.push_front(0);
204 const SwTableLine
* pLine
= rFndLines
[0]->GetLine();
205 USHORT nStartLn
= rTable
.GetTabLines().C40_GETPOS( SwTableLine
, pLine
);
206 USHORT nEndLn
= nStartLn
;
207 if( rFndLines
.Count() > 1 )
209 pLine
= rFndLines
[ rFndLines
.Count()-1 ]->GetLine();
210 nEndLn
= rTable
.GetTabLines().C40_GETPOS( SwTableLine
, pLine
);
212 if( nStartLn
< USHRT_MAX
&& nEndLn
< USHRT_MAX
)
214 const SwTableLines
&rLines
= rTable
.GetTabLines();
216 (USHORT
)nMinSize
> nEndLn
- nStartLn
+ 1 )
218 USHORT nNewEndLn
= nStartLn
+ (USHORT
)nMinSize
- 1;
219 if( nNewEndLn
>= rLines
.Count() )
221 mnAddLine
= nNewEndLn
- rLines
.Count() + 1;
222 nNewEndLn
= rLines
.Count() - 1;
224 while( nEndLn
< nNewEndLn
)
226 SwTableLine
*pLine2
= rLines
[ ++nEndLn
];
227 SwTableBox
*pTmpBox
= pLine2
->GetTabBoxes()[0];
228 _FndLine
*pInsLine
= new _FndLine( pLine2
, &rFndBox
);
229 _FndBox
*pFndBox
= new _FndBox( pTmpBox
, pInsLine
);
230 pInsLine
->GetBoxes().C40_INSERT( _FndBox
, pFndBox
, 0 );
231 rFndLines
.C40_INSERT( _FndLine
, pInsLine
, rFndLines
.Count() );
234 maLines
.resize( nEndLn
- nStartLn
+ 1 );
235 const SwSelBoxes
* pSelBoxes
= &rSelBoxes
;
237 for( USHORT nLine
= nStartLn
; nLine
<= nEndLn
; ++nLine
)
239 addLine( nCnt
, rLines
[nLine
]->GetTabBoxes(),
240 pSelBoxes
, rTable
.IsNewModel() );
245 if( bNoSelection
&& mnStartCol
< USHRT_MAX
)
247 BoxStructure::iterator pC
= maLines
[0].begin();
248 BoxStructure::iterator pEnd
= maLines
[0].end();
249 USHORT nIdx
= mnStartCol
;
251 while( nIdx
&& pC
!= pEnd
)
253 mnStartCol
= mnStartCol
+ pC
->mnColSpan
;
259 mnStartCol
= USHRT_MAX
;
263 void TableStructure::addLine( USHORT
&rLine
, const SwTableBoxes
& rBoxes
,
264 const SwSelBoxes
* pSelBoxes
, bool bNewModel
)
266 bool bComplex
= false;
268 for( USHORT nBox
= 0; !bComplex
&& nBox
< rBoxes
.Count(); ++nBox
)
269 bComplex
= rBoxes
[nBox
]->GetTabLines().Count() > 0;
274 aSubTable
.push_back( aSubLine
);
275 SubTable::iterator pStartLn
= aSubTable
.begin();
276 SubTable::iterator pEndLn
= aSubTable
.end();
277 for( USHORT nBox
= 0; nBox
< rBoxes
.Count(); ++nBox
)
278 insertSubBox( aSubTable
, *rBoxes
[nBox
], pStartLn
, pEndLn
);
279 SubTable::size_type nSize
= aSubTable
.size();
282 maLines
.resize( maLines
.size() + nSize
- 1 );
283 while( pStartLn
!= pEndLn
)
285 bool bSelected
= false;
288 maLines
[rLine
].reserve( pStartLn
->size() );
289 BoxStructure::iterator pSel
= maLines
[rLine
].end();
290 ColumnStructure::iterator pCol
= maCols
.begin();
291 SubLine::iterator pBox
= pStartLn
->begin();
292 SubLine::iterator pEnd
= pStartLn
->end();
293 while( pBox
!= pEnd
)
295 addBox( rLine
, pSelBoxes
, pBox
->mpBox
, nBorder
, nCol
,
296 pCol
, pSel
, bSelected
, pBox
->mbCovered
);
306 bool bSelected
= false;
309 maLines
[rLine
].reserve( rBoxes
.Count() );
310 ColumnStructure::iterator pCol
= maCols
.begin();
311 BoxStructure::iterator pSel
= maLines
[rLine
].end();
312 for( USHORT nBox
= 0; nBox
< rBoxes
.Count(); ++nBox
)
313 addBox( rLine
, pSelBoxes
, rBoxes
[nBox
], nBorder
, nCol
,
314 pCol
, pSel
, bSelected
, false );
319 void TableStructure::addBox( USHORT nLine
, const SwSelBoxes
* pSelBoxes
,
320 SwTableBox
*pBox
, ULONG
&rnBorder
, USHORT
&rnCol
,
321 ColumnStructure::iterator
& rpCol
, BoxStructure::iterator
& rpSel
,
322 bool &rbSelected
, bool bCovered
)
326 USHRT_MAX
!= pSelBoxes
->GetPos( pBox
) )
328 aInfo
.mbSelected
= true;
329 if( mnStartCol
== USHRT_MAX
)
331 mnStartCol
= (USHORT
)maLines
[nLine
].size();
332 if( pSelBoxes
->Count() < 2 )
335 aInfo
.mbSelected
= false;
340 aInfo
.mbSelected
= false;
341 rnBorder
+= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
342 USHORT nLeftCol
= rnCol
;
343 while( rpCol
!= maCols
.end() && *rpCol
< rnBorder
)
348 if( rpCol
== maCols
.end() || *rpCol
> rnBorder
)
350 maCols
.insert( rpCol
, rnBorder
);
352 incColSpan( nLine
, rnCol
);
354 aInfo
.mnColSpan
= rnCol
- nLeftCol
;
356 aInfo
.mpBox
= bCovered
? 0 : pBox
;
357 maLines
[nLine
].push_back( aInfo
);
358 if( aInfo
.mbSelected
)
362 while( rpSel
!= maLines
[nLine
].end() )
364 rpSel
->mbSelected
= true;
370 rpSel
= maLines
[nLine
].end();
377 void TableStructure::moreLines( const SwTable
& rTable
)
381 const SwTableLines
&rLines
= rTable
.GetTabLines();
382 USHORT nLineCount
= rLines
.Count();
383 if( nLineCount
< mnAddLine
)
384 mnAddLine
= nLineCount
;
385 USHORT nLine
= (USHORT
)maLines
.size();
386 maLines
.resize( nLine
+ mnAddLine
);
389 SwTableLine
*pLine
= rLines
[ nLineCount
- mnAddLine
];
390 addLine( nLine
, pLine
->GetTabBoxes(), 0, rTable
.IsNewModel() );
396 void TableStructure::incColSpan( USHORT nLineMax
, USHORT nNewCol
)
398 for( USHORT nLine
= 0; nLine
< nLineMax
; ++nLine
)
400 BoxStructure::iterator pInfo
= maLines
[nLine
].begin();
401 BoxStructure::iterator pEnd
= maLines
[nLine
].end();
402 long nCol
= pInfo
->mnColSpan
;
403 while( nNewCol
> nCol
&& ++pInfo
!= pEnd
)
404 nCol
+= pInfo
->mnColSpan
;
406 ++(pInfo
->mnColSpan
);
410 void TableStructure::assignBoxes( const TableStructure
&rSource
)
412 LineStructure::const_iterator pFirstLine
= rSource
.maLines
.begin();
413 LineStructure::const_iterator pLastLine
= rSource
.maLines
.end();
414 if( pFirstLine
== pLastLine
)
416 LineStructure::const_iterator pCurrLine
= pFirstLine
;
417 LineStructure::size_type nLineCount
= maLines
.size();
418 USHORT nFirstStartCol
= 0;
420 BoxStructure::const_iterator pFirstBox
= pFirstLine
->begin();
421 if( pFirstBox
!= pFirstLine
->end() && pFirstBox
->mpBox
&&
422 pFirstBox
->mpBox
->getDummyFlag() )
423 nFirstStartCol
= pFirstBox
->mnColSpan
;
425 for( LineStructure::size_type nLine
= 0; nLine
< nLineCount
; ++nLine
)
427 BoxStructure::const_iterator pFirstBox
= pCurrLine
->begin();
428 BoxStructure::const_iterator pLastBox
= pCurrLine
->end();
429 USHORT nCurrStartCol
= mnStartCol
;
430 if( pFirstBox
!= pLastBox
)
432 BoxStructure::const_iterator pTmpBox
= pLastBox
;
434 if( pTmpBox
->mpBox
&& pTmpBox
->mpBox
->getDummyFlag() )
436 if( pFirstBox
!= pLastBox
&& pFirstBox
->mpBox
&&
437 pFirstBox
->mpBox
->getDummyFlag() )
439 if( nCurrStartCol
< USHRT_MAX
)
441 if( pFirstBox
->mnColSpan
> nFirstStartCol
)
442 nCurrStartCol
= pFirstBox
->mnColSpan
- nFirstStartCol
448 if( pFirstBox
!= pLastBox
)
450 BoxStructure::const_iterator pCurrBox
= pFirstBox
;
451 BoxStructure
&rBox
= maLines
[nLine
];
452 BoxStructure::size_type nBoxCount
= rBox
.size();
454 for( BoxStructure::size_type nBox
= 0; nBox
< nBoxCount
; ++nBox
)
456 BoxSpanInfo
& rInfo
= rBox
[nBox
];
457 nCol
= nCol
+ rInfo
.mnColSpan
;
458 if( rInfo
.mbSelected
|| nCol
> nCurrStartCol
)
460 rInfo
.mpCopy
= pCurrBox
->mpBox
;
461 if( rInfo
.mbSelected
&& rInfo
.mpCopy
->getDummyFlag() )
464 if( pCurrBox
== pLastBox
)
466 pCurrBox
= pFirstBox
;
467 if( pCurrBox
->mpBox
->getDummyFlag() )
470 rInfo
.mpCopy
= pCurrBox
->mpBox
;
473 if( pCurrBox
== pLastBox
)
475 if( rInfo
.mbSelected
)
476 pCurrBox
= pFirstBox
;
479 rInfo
.mbSelected
= rInfo
.mpCopy
== 0;
483 rInfo
.mbSelected
= rInfo
.mpCopy
== 0;
488 if( pCurrLine
== pLastLine
)
489 pCurrLine
= pFirstLine
;
493 void TableStructure::copyBoxes( const SwTable
& rSource
, SwTable
& rDstTbl
,
494 SwUndoTblCpyTbl
* pUndo
) const
496 LineStructure::size_type nLineCount
= maLines
.size();
497 for( LineStructure::size_type nLine
= 0; nLine
< nLineCount
; ++nLine
)
499 const BoxStructure
&rBox
= maLines
[nLine
];
500 BoxStructure::size_type nBoxCount
= rBox
.size();
501 for( BoxStructure::size_type nBox
= 0; nBox
< nBoxCount
; ++nBox
)
503 const BoxSpanInfo
& rInfo
= rBox
[nBox
];
504 if( ( rInfo
.mpCopy
&& !rInfo
.mpCopy
->getDummyFlag() )
505 || rInfo
.mbSelected
)
507 SwTableBox
*pBox
= rInfo
.mpBox
;
508 if( pBox
&& pBox
->getRowSpan() > 0 )
509 lcl_CpyBox( rSource
, rInfo
.mpCopy
, rDstTbl
, pBox
,
511 /* Idea: If target cell is a covered cell, append content
513 BOOL bReplace = TRUE;
514 if( pBox->getRowSpan() < 0 )
516 if( rInfo.mpCopy->getRowSpan() < 0 )
518 pBox = &pBox->FindStartOfRowSpan( rDstTbl );
521 lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
530 // ---------------------------------------------------------------
532 // kopiere die Tabelle in diese.
533 // Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
534 // wird dabei geloescht.
535 // Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
536 // Box einer "GrundLine".
537 // Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
541 void lcl_CpyBox( const SwTable
& rCpyTbl
, const SwTableBox
* pCpyBox
,
542 SwTable
& rDstTbl
, SwTableBox
* pDstBox
,
543 BOOL bDelCntnt
, SwUndoTblCpyTbl
* pUndo
)
545 ASSERT( ( !pCpyBox
|| pCpyBox
->GetSttNd() ) && pDstBox
->GetSttNd(),
546 "Keine inhaltstragende Box" );
548 SwDoc
* pCpyDoc
= rCpyTbl
.GetFrmFmt()->GetDoc();
549 SwDoc
* pDoc
= rDstTbl
.GetFrmFmt()->GetDoc();
551 // kopiere erst den neuen und loeschen dann den alten Inhalt
552 // (keine leeren Section erzeugen; werden sonst geloescht!)
553 std::auto_ptr
< SwNodeRange
> pRg( pCpyBox
?
554 new SwNodeRange ( *pCpyBox
->GetSttNd(), 1,
555 *pCpyBox
->GetSttNd()->EndOfSectionNode() ) : 0 );
557 SwNodeIndex
aInsIdx( *pDstBox
->GetSttNd(), bDelCntnt
? 1 :
558 pDstBox
->GetSttNd()->EndOfSectionIndex() -
559 pDstBox
->GetSttIdx() );
562 pUndo
->AddBoxBefore( *pDstBox
, bDelCntnt
);
564 BOOL bUndo
= pDoc
->DoesUndo();
565 bool bUndoRedline
= pUndo
&& pDoc
->IsRedlineOn();
566 pDoc
->DoUndo( FALSE
);
568 SwNodeIndex
aSavePos( aInsIdx
, -1 );
570 pCpyDoc
->CopyWithFlyInFly( *pRg
, 0, aInsIdx
, FALSE
);
572 pDoc
->GetNodes().MakeTxtNode( aInsIdx
, (SwTxtFmtColl
*)pDoc
->GetDfltTxtFmtColl() );
575 SwTableLine
* pLine
= pDstBox
->GetUpper();
576 while( pLine
->GetUpper() )
577 pLine
= pLine
->GetUpper()->GetUpper();
579 BOOL bReplaceColl
= TRUE
;
580 if( bDelCntnt
&& !bUndoRedline
)
582 // zuerst die Fly loeschen, dann die entsprechenden Nodes
583 SwNodeIndex
aEndNdIdx( *aInsIdx
.GetNode().EndOfSectionNode() );
585 // Bookmarks usw. verschieben
587 SwPosition
aMvPos( aInsIdx
);
588 SwCntntNode
* pCNd
= pDoc
->GetNodes().GoPrevious( &aMvPos
.nNode
);
589 aMvPos
.nContent
.Assign( pCNd
, pCNd
->Len() );
590 pDoc
->CorrAbs( aInsIdx
, aEndNdIdx
, aMvPos
, /*TRUE*/FALSE
);
593 // stehen noch FlyFrames rum, loesche auch diese
594 const SwPosition
* pAPos
;
595 for( USHORT n
= 0; n
< pDoc
->GetSpzFrmFmts()->Count(); ++n
)
597 SwFrmFmt
* pFly
= (*pDoc
->GetSpzFrmFmts())[n
];
598 const SwFmtAnchor
* pAnchor
= &pFly
->GetAnchor();
599 if( ( FLY_AT_CNTNT
== pAnchor
->GetAnchorId() ||
600 FLY_AUTO_CNTNT
== pAnchor
->GetAnchorId() ) &&
601 0 != ( pAPos
= pAnchor
->GetCntntAnchor() ) &&
602 aInsIdx
<= pAPos
->nNode
&& pAPos
->nNode
<= aEndNdIdx
)
604 pDoc
->DelLayoutFmt( pFly
);
608 // ist DestBox eine Headline-Box und hat Tabellen-Vorlage gesetzt,
609 // dann NICHT die TabellenHeadline-Vorlage automatisch setzen
610 if( 1 < rDstTbl
.GetTabLines().Count() &&
611 pLine
== rDstTbl
.GetTabLines()[0] )
613 SwCntntNode
* pCNd
= aInsIdx
.GetNode().GetCntntNode();
616 SwNodeIndex
aTmp( aInsIdx
);
617 pCNd
= pDoc
->GetNodes().GoNext( &aTmp
);
621 /*RES_POOLCOLL_TABLE == */
622 RES_POOLCOLL_TABLE_HDLN
!=
623 pCNd
->GetFmtColl()->GetPoolFmtId() )
624 bReplaceColl
= FALSE
;
627 pDoc
->GetNodes().Delete( aInsIdx
, aEndNdIdx
.GetIndex() - aInsIdx
.GetIndex() );
630 //b6341295: Table copy redlining will be managed by AddBoxAfter()
632 pUndo
->AddBoxAfter( *pDstBox
, aInsIdx
, bDelCntnt
);
635 SwTxtNode
* pTxtNd
= pDoc
->GetNodes()[ aSavePos
]->GetTxtNode();
638 USHORT nPoolId
= pTxtNd
->GetTxtColl()->GetPoolFmtId();
640 (( 1 < rDstTbl
.GetTabLines().Count() &&
641 pLine
== rDstTbl
.GetTabLines()[0] )
642 // gilt noch die Tabellen-Inhalt ??
643 ? RES_POOLCOLL_TABLE
== nPoolId
644 : RES_POOLCOLL_TABLE_HDLN
== nPoolId
) )
646 SwTxtFmtColl
* pColl
= pDoc
->GetTxtCollFromPool(
647 static_cast<sal_uInt16
>(
648 RES_POOLCOLL_TABLE
== nPoolId
649 ? RES_POOLCOLL_TABLE_HDLN
650 : RES_POOLCOLL_TABLE
) );
651 if( pColl
) // Vorlage umsetzen
653 SwPaM
aPam( aSavePos
);
655 aPam
.Move( fnMoveForward
, fnGoSection
);
656 pDoc
->SetTxtFmtColl( aPam
, pColl
);
660 // loesche die akt. Formel/Format/Value Werte
661 if( SFX_ITEM_SET
== pDstBox
->GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT
) ||
662 SFX_ITEM_SET
== pDstBox
->GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA
) ||
663 SFX_ITEM_SET
== pDstBox
->GetFrmFmt()->GetItemState( RES_BOXATR_VALUE
) )
665 pDstBox
->ClaimFrmFmt()->ResetFmtAttr( RES_BOXATR_FORMAT
,
669 // kopiere die TabellenBoxAttribute - Formel/Format/Value
672 SfxItemSet
aBoxAttrSet( pCpyDoc
->GetAttrPool(), RES_BOXATR_FORMAT
,
674 aBoxAttrSet
.Put( pCpyBox
->GetFrmFmt()->GetAttrSet() );
675 if( aBoxAttrSet
.Count() )
677 const SfxPoolItem
* pItem
;
678 SvNumberFormatter
* pN
= pDoc
->GetNumberFormatter( FALSE
);
679 if( pN
&& pN
->HasMergeFmtTbl() && SFX_ITEM_SET
== aBoxAttrSet
.
680 GetItemState( RES_BOXATR_FORMAT
, FALSE
, &pItem
) )
682 ULONG nOldIdx
= ((SwTblBoxNumFormat
*)pItem
)->GetValue();
683 ULONG nNewIdx
= pN
->GetMergeFmtIndex( nOldIdx
);
684 if( nNewIdx
!= nOldIdx
)
685 aBoxAttrSet
.Put( SwTblBoxNumFormat( nNewIdx
));
687 pDstBox
->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet
);
692 pDoc
->DoUndo( bUndo
);
695 BOOL
SwTable::InsNewTable( const SwTable
& rCpyTbl
, const SwSelBoxes
& rSelBoxes
,
696 SwUndoTblCpyTbl
* pUndo
)
698 SwDoc
* pDoc
= GetFrmFmt()->GetDoc();
699 SwDoc
* pCpyDoc
= rCpyTbl
.GetFrmFmt()->GetDoc();
701 SwTblNumFmtMerge
aTNFM( *pCpyDoc
, *pDoc
);
703 // analyse source structure
704 TableStructure
aCopyStruct( rCpyTbl
);
706 // analyse target structure (from start box) and selected substructure
707 _FndBox
aFndBox( 0, 0 );
708 { // get all boxes/lines
709 _FndPara
aPara( rSelBoxes
, &aFndBox
);
710 GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
712 TableStructure
aTarget( *this, aFndBox
, rSelBoxes
, aCopyStruct
.getLineCount() );
715 if( aTarget
.mnAddLine
&& IsNewModel() )
718 aBoxes
.Insert( GetTabLines()[ GetTabLines().Count()-1 ]->GetTabBoxes()[0] );
720 pUndo
->InsertRow( *this, aBoxes
, aTarget
.mnAddLine
);
722 InsertRow( pDoc
, aBoxes
, aTarget
.mnAddLine
, TRUE
);
724 aTarget
.moreLines( *this );
728 // find mapping, if needed extend target table and/or selection
729 aTarget
.assignBoxes( aCopyStruct
);
732 // Change table formulas into relative representation
733 SwTableFmlUpdate
aMsgHnt( &rCpyTbl
);
734 aMsgHnt
.eFlags
= TBL_RELBOXNAME
;
735 pCpyDoc
->UpdateTblFlds( &aMsgHnt
);
739 aFndBox
.SetTableLines( *this );
741 aFndBox
.ClearLineBehind();
742 aFndBox
.DelFrms( *this );
745 aTarget
.copyBoxes( rCpyTbl
, *this, pUndo
);
747 // adjust row span attributes accordingly
750 aFndBox
.MakeFrms( *this );
755 // ---------------------------------------------------------------
757 // kopiere die Tabelle in diese.
758 // Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
759 // wird dabei geloescht.
760 // Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
761 // Box einer "GrundLine".
762 // Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
766 BOOL
SwTable::InsTable( const SwTable
& rCpyTbl
, const SwNodeIndex
& rSttBox
,
767 SwUndoTblCpyTbl
* pUndo
)
769 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
771 SwDoc
* pDoc
= GetFrmFmt()->GetDoc();
773 SwTableNode
* pTblNd
= pDoc
->IsIdxInTbl( rSttBox
);
775 // suche erstmal die Box, in die kopiert werden soll:
776 SwTableBox
* pMyBox
= (SwTableBox
*)GetTblBox(
777 rSttBox
.GetNode().FindTableBoxStartNode()->GetIndex() );
779 ASSERT( pMyBox
, "Index steht nicht in dieser Tabelle in einer Box" );
781 // loesche erstmal die Frames der Tabelle
782 _FndBox
aFndBox( 0, 0 );
783 aFndBox
.DelFrms( pTblNd
->GetTable() );
785 SwDoc
* pCpyDoc
= rCpyTbl
.GetFrmFmt()->GetDoc();
788 // Tabellen-Formeln in die relative Darstellung umwandeln
789 SwTableFmlUpdate
aMsgHnt( &rCpyTbl
);
790 aMsgHnt
.eFlags
= TBL_RELBOXNAME
;
791 pCpyDoc
->UpdateTblFlds( &aMsgHnt
);
794 SwTblNumFmtMerge
aTNFM( *pCpyDoc
, *pDoc
);
796 BOOL bDelCntnt
= TRUE
;
797 const SwTableBox
* pTmp
;
799 for( USHORT nLines
= 0; nLines
< rCpyTbl
.GetTabLines().Count(); ++nLines
)
801 // hole die erste Box von der Copy-Line
802 const SwTableBox
* pCpyBox
= rCpyTbl
.GetTabLines()[nLines
]
804 while( pCpyBox
->GetTabLines().Count() )
805 pCpyBox
= pCpyBox
->GetTabLines()[0]->GetTabBoxes()[0];
808 // kopiere erst den neuen und loeschen dann den alten Inhalt
809 // (keine leeren Section erzeugen, werden sonst geloescht!)
810 lcl_CpyBox( rCpyTbl
, pCpyBox
, *this, pMyBox
, bDelCntnt
, pUndo
);
812 if( 0 == (pTmp
= pCpyBox
->FindNextBox( rCpyTbl
, pCpyBox
, FALSE
)))
813 break; // es folgt keine weitere Box mehr
816 if( 0 == ( pTmp
= pMyBox
->FindNextBox( *this, pMyBox
, FALSE
)))
817 bDelCntnt
= FALSE
; // kein Platz mehr ??
819 pMyBox
= (SwTableBox
*)pTmp
;
823 // suche die oberste Line
824 SwTableLine
* pNxtLine
= pMyBox
->GetUpper();
825 while( pNxtLine
->GetUpper() )
826 pNxtLine
= pNxtLine
->GetUpper()->GetUpper();
827 USHORT nPos
= GetTabLines().C40_GETPOS( SwTableLine
, pNxtLine
);
828 // gibt es eine naechste ??
829 if( nPos
+ 1 >= GetTabLines().Count() )
830 bDelCntnt
= FALSE
; // es gibt keine, alles in die letzte Box
833 // suche die naechste "Inhaltstragende Box"
834 pNxtLine
= GetTabLines()[ nPos
+1 ];
835 pMyBox
= pNxtLine
->GetTabBoxes()[0];
836 while( pMyBox
->GetTabLines().Count() )
837 pMyBox
= pMyBox
->GetTabLines()[0]->GetTabBoxes()[0];
842 aFndBox
.MakeFrms( pTblNd
->GetTable() ); // erzeuge die Frames neu
847 BOOL
SwTable::InsTable( const SwTable
& rCpyTbl
, const SwSelBoxes
& rSelBoxes
,
848 SwUndoTblCpyTbl
* pUndo
)
850 ASSERT( rSelBoxes
.Count(), "Missing selection" )
852 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
854 if( IsNewModel() || rCpyTbl
.IsNewModel() )
855 return InsNewTable( rCpyTbl
, rSelBoxes
, pUndo
);
857 ASSERT( !rCpyTbl
.IsTblComplex(), "Table too complex" )
859 SwDoc
* pDoc
= GetFrmFmt()->GetDoc();
860 SwDoc
* pCpyDoc
= rCpyTbl
.GetFrmFmt()->GetDoc();
862 SwTblNumFmtMerge
aTNFM( *pCpyDoc
, *pDoc
);
864 SwTableBox
*pTmpBox
, *pSttBox
= (SwTableBox
*)rSelBoxes
[0];
867 _FndLine
*pFLine
, *pInsFLine
= 0;
868 _FndBox
aFndBox( 0, 0 );
869 // suche alle Boxen / Lines
871 _FndPara
aPara( rSelBoxes
, &aFndBox
);
872 ((SwTableLines
&)GetTabLines()).ForEach( &_FndLineCopyCol
, &aPara
);
875 // JP 06.09.96: Sonderfall - eine Box in der Tabelle -> in alle
876 // selektierten Boxen kopieren!
877 if( 1 != rCpyTbl
.GetTabSortBoxes().Count() )
879 SwTableLine
* pSttLine
= pSttBox
->GetUpper();
880 USHORT nSttBox
= pSttLine
->GetTabBoxes().C40_GETPOS( SwTableBox
, pSttBox
);
881 USHORT nSttLine
= GetTabLines().C40_GETPOS( SwTableLine
, pSttLine
);
884 USHORT nFndCnt
= aFndBox
.GetLines().Count();
888 // teste ob genug Platz fuer die einzelnen Lines und Boxen ist:
890 pFLine
= aFndBox
.GetLines()[ 0 ];
891 pSttLine
= pFLine
->GetLine();
892 nSttLine
= GetTabLines().C40_GETPOS( SwTableLine
, pSttLine
);
893 // sind ueberhaupt soviele Zeilen vorhanden
896 // in der Tabelle noch genug Platz ??
897 if( (GetTabLines().Count() - nSttLine
) <
898 rCpyTbl
.GetTabLines().Count() )
900 // sollte nicht mehr soviele Lines vorhanden sein, dann
901 // teste, ob man durch einfuegen neuer zum Ziel kommt. Aber
902 // nur wenn die SSelection eine Box umfasst !!
903 if( 1 < rSelBoxes
.Count() )
906 USHORT nNewLns
= rCpyTbl
.GetTabLines().Count() -
907 (GetTabLines().Count() - nSttLine
);
909 // Dann teste mal ob die Anzahl der Boxen fuer die Lines reicht
910 SwTableLine
* pLastLn
= GetTabLines()[ GetTabLines().Count()-1 ];
912 pSttBox
= pFLine
->GetBoxes()[0]->GetBox();
913 nSttBox
= pFLine
->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox
, pSttBox
);
914 for( USHORT n
= rCpyTbl
.GetTabLines().Count() - nNewLns
;
915 n
< rCpyTbl
.GetTabLines().Count(); ++n
)
917 SwTableLine
* pCpyLn
= rCpyTbl
.GetTabLines()[ n
];
919 if( pLastLn
->GetTabBoxes().Count() < nSttBox
||
920 ( pLastLn
->GetTabBoxes().Count() - nSttBox
) <
921 pCpyLn
->GetTabBoxes().Count() )
924 // Test auf Verschachtelungen
925 for( nBx
= 0; nBx
< pCpyLn
->GetTabBoxes().Count(); ++nBx
)
926 if( !( pTmpBox
= pLastLn
->GetTabBoxes()[ nSttBox
+ nBx
])
930 // es ist also Platz fuer das zu kopierende vorhanden, also
931 // fuege entsprechend neue Zeilen ein.
932 SwTableBox
* pInsBox
= pLastLn
->GetTabBoxes()[ nSttBox
];
933 ASSERT( pInsBox
&& pInsBox
->GetSttNd(),
934 "kein CntntBox oder steht nicht in dieser Tabelle" );
938 ? !pUndo
->InsertRow( *this, SelLineFromBox( pInsBox
,
939 aBoxes
, TRUE
), nNewLns
)
940 : !InsertRow( pDoc
, SelLineFromBox( pInsBox
,
941 aBoxes
, TRUE
), nNewLns
, TRUE
) )
945 nTstLns
= rCpyTbl
.GetTabLines().Count(); // soviele Kopieren
947 else if( 0 == (nFndCnt
% rCpyTbl
.GetTabLines().Count()) )
950 return FALSE
; // kein Platz fuer die Zeilen
952 for( nLn
= 0; nLn
< nTstLns
; ++nLn
)
954 // Zeilen sind genug vorhanden, dann ueberpruefe die Boxen
956 pFLine
= aFndBox
.GetLines()[ nLn
% nFndCnt
];
957 SwTableLine
* pLine
= pFLine
->GetLine();
958 pSttBox
= pFLine
->GetBoxes()[0]->GetBox();
959 nSttBox
= pLine
->GetTabBoxes().C40_GETPOS( SwTableBox
, pSttBox
);
962 // es sind im ClipBoard mehr Zeilen als selectiert wurden
963 pInsFLine
= new _FndLine( GetTabLines()[ nSttLine
+ nLn
],
965 pLine
= pInsFLine
->GetLine();
967 SwTableLine
* pCpyLn
= rCpyTbl
.GetTabLines()[ nLn
%
968 rCpyTbl
.GetTabLines().Count() ];
970 // zu wenig Zeilen selektiert ?
973 // eine neue Zeile wird in die FndBox eingefuegt,
974 if( pLine
->GetTabBoxes().Count() < nSttBox
||
975 ( pLine
->GetTabBoxes().Count() - nSttBox
) <
976 pFLine
->GetBoxes().Count() )
979 // Test auf Verschachtelungen
980 for( nBx
= 0; nBx
< pFLine
->GetBoxes().Count(); ++nBx
)
982 if( !( pTmpBox
= pLine
->GetTabBoxes()[ nSttBox
+ nBx
])
985 // wenn Ok, fuege die Box in die FndLine zu
986 pFndBox
= new _FndBox( pTmpBox
, pInsFLine
);
987 pInsFLine
->GetBoxes().C40_INSERT( _FndBox
, pFndBox
, nBx
);
989 aFndBox
.GetLines().C40_INSERT( _FndLine
, pInsFLine
, nLn
);
991 else if( pFLine
->GetBoxes().Count() == 1 )
993 if( pLine
->GetTabBoxes().Count() < nSttBox
||
994 ( pLine
->GetTabBoxes().Count() - nSttBox
) <
995 pCpyLn
->GetTabBoxes().Count() )
998 // Test auf Verschachtelungen
999 for( nBx
= 0; nBx
< pCpyLn
->GetTabBoxes().Count(); ++nBx
)
1001 if( !( pTmpBox
= pLine
->GetTabBoxes()[ nSttBox
+ nBx
])
1004 // wenn Ok, fuege die Box in die FndLine zu
1005 if( nBx
== pFLine
->GetBoxes().Count() )
1007 pFndBox
= new _FndBox( pTmpBox
, pFLine
);
1008 pFLine
->GetBoxes().C40_INSERT( _FndBox
, pFndBox
, nBx
);
1014 // ueberpruefe die selektierten Boxen mit denen im Clipboard
1016 if( 0 != ( pFLine
->GetBoxes().Count() %
1017 pCpyLn
->GetTabBoxes().Count() ))
1020 // Test auf Verschachtelungen
1021 for( nBx
= 0; nBx
< pFLine
->GetBoxes().Count(); ++nBx
)
1022 if( !pFLine
->GetBoxes()[ nBx
]->GetBox()->GetSttNd() )
1027 if( !aFndBox
.GetLines().Count() )
1032 // Tabellen-Formeln in die relative Darstellung umwandeln
1033 SwTableFmlUpdate
aMsgHnt( &rCpyTbl
);
1034 aMsgHnt
.eFlags
= TBL_RELBOXNAME
;
1035 pCpyDoc
->UpdateTblFlds( &aMsgHnt
);
1038 // loesche die Frames
1039 aFndBox
.SetTableLines( *this );
1040 aFndBox
.DelFrms( *this );
1042 if( 1 == rCpyTbl
.GetTabSortBoxes().Count() )
1044 SwTableBox
*pTmpBx
= rCpyTbl
.GetTabSortBoxes()[0];
1045 for( USHORT n
= 0; n
< rSelBoxes
.Count(); ++n
)
1046 lcl_CpyBox( rCpyTbl
, pTmpBx
, *this,
1047 (SwTableBox
*)rSelBoxes
[n
], TRUE
, pUndo
);
1050 for( nLn
= 0; nLn
< aFndBox
.GetLines().Count(); ++nLn
)
1052 pFLine
= aFndBox
.GetLines()[ nLn
];
1053 SwTableLine
* pCpyLn
= rCpyTbl
.GetTabLines()[
1054 nLn
% rCpyTbl
.GetTabLines().Count() ];
1055 for( nBx
= 0; nBx
< pFLine
->GetBoxes().Count(); ++nBx
)
1057 // Kopiere in pMyBox die pCpyBox
1058 lcl_CpyBox( rCpyTbl
, pCpyLn
->GetTabBoxes()[
1059 nBx
% pCpyLn
->GetTabBoxes().Count() ],
1060 *this, pFLine
->GetBoxes()[ nBx
]->GetBox(), TRUE
, pUndo
);
1064 aFndBox
.MakeFrms( *this );
1070 BOOL
_FndCntntBox( const SwTableBox
*& rpBox
, void* pPara
)
1072 SwTableBox
* pBox
= (SwTableBox
*)rpBox
;
1073 if( rpBox
->GetTabLines().Count() )
1074 pBox
->GetTabLines().ForEach( &_FndCntntLine
, pPara
);
1076 ((SwSelBoxes
*)pPara
)->Insert( pBox
);
1081 BOOL
_FndCntntLine( const SwTableLine
*& rpLine
, void* pPara
)
1083 ((SwTableLine
*)rpLine
)->GetTabBoxes().ForEach( &_FndCntntBox
, pPara
);
1088 // suche alle Inhaltstragenden-Boxen dieser Box
1089 SwSelBoxes
& SwTable::SelLineFromBox( const SwTableBox
* pBox
,
1090 SwSelBoxes
& rBoxes
, BOOL bToTop
) const
1092 SwTableLine
* pLine
= (SwTableLine
*)pBox
->GetUpper();
1094 while( pLine
->GetUpper() )
1095 pLine
= pLine
->GetUpper()->GetUpper();
1097 // alle alten loeschen
1098 rBoxes
.Remove( USHORT(0), rBoxes
.Count() );
1099 pLine
->GetTabBoxes().ForEach( &_FndCntntBox
, &rBoxes
);