xref: /trunk/main/sw/source/core/doc/tblcpy.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <hintids.hxx>
33 
34 #define _ZFORLIST_DECLARE_TABLE
35 #include <svl/zforlist.hxx>
36 #include <frmfmt.hxx>
37 #include <doc.hxx>
38 #include <IDocumentUndoRedo.hxx>
39 #include <cntfrm.hxx>
40 #include <pam.hxx>
41 #include <swtable.hxx>
42 #include <ndtxt.hxx>
43 #include <fldbas.hxx>
44 #include <tblsel.hxx>
45 #include <tabfrm.hxx>
46 #include <poolfmt.hxx>
47 #include <cellatr.hxx>
48 #include <mvsave.hxx>
49 #include <docary.hxx>
50 #include <fmtanchr.hxx>
51 #include <hints.hxx>
52 #include <UndoTable.hxx>
53 #include <redline.hxx>
54 #include <fmtfsize.hxx>
55 #include <list>
56 
57 sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara );
58 sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara );
59 void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
60                     SwTable& rDstTbl, SwTableBox* pDstBox,
61                     sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo );
62 
63 // The following type will be used by table copy functions to describe
64 // the structure of tables (or parts of tables).
65 // It's for new table model only.
66 
67 namespace
68 {
69     struct BoxSpanInfo
70     {
71         SwTableBox* mpBox;
72         SwTableBox* mpCopy;
73         sal_uInt16 mnColSpan;
74         bool mbSelected;
75     };
76 
77     typedef std::vector< BoxSpanInfo > BoxStructure;
78     typedef std::vector< BoxStructure > LineStructure;
79     typedef std::list< sal_uLong > ColumnStructure;
80 
81     struct SubBox
82     {
83         SwTableBox *mpBox;
84         bool mbCovered;
85     };
86 
87     typedef std::list< SubBox > SubLine;
88     typedef std::list< SubLine > SubTable;
89 
90     class TableStructure
91     {
92     public:
93         LineStructure maLines;
94         ColumnStructure maCols;
95         sal_uInt16 mnStartCol;
96         sal_uInt16 mnAddLine;
97         void addLine( sal_uInt16 &rLine, const SwTableBoxes&, const SwSelBoxes*,
98                       bool bNewModel );
99         void addBox( sal_uInt16 nLine, const SwSelBoxes*, SwTableBox *pBox,
100                      sal_uLong &rnB, sal_uInt16 &rnC, ColumnStructure::iterator& rpCl,
101                      BoxStructure::iterator& rpSel, bool &rbSel, bool bCover );
102         void incColSpan( sal_uInt16 nLine, sal_uInt16 nCol );
103         TableStructure( const SwTable& rTable );
104         TableStructure( const SwTable& rTable, _FndBox &rFndBox,
105                         const SwSelBoxes& rSelBoxes,
106                         LineStructure::size_type nMinSize );
107         LineStructure::size_type getLineCount() const
108             { return maLines.size(); }
109         void moreLines( const SwTable& rTable );
110         void assignBoxes( const TableStructure &rSource );
111         void copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
112                         SwUndoTblCpyTbl* pUndo ) const;
113     };
114 
115     SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
116         SubTable::iterator pStartLn );
117 
118     SubTable::iterator insertSubBox( SubTable& rSubTable, SwTableBox& rBox,
119         SubTable::iterator pStartLn, SubTable::iterator pEndLn )
120     {
121         if( rBox.GetTabLines().Count() )
122         {
123             SubTable::difference_type nSize = std::distance( pStartLn, pEndLn );
124             if( nSize < rBox.GetTabLines().Count() )
125             {
126                 SubLine aSubLine;
127                 SubLine::iterator pBox = pStartLn->begin();
128                 SubLine::iterator pEnd = pStartLn->end();
129                 while( pBox != pEnd )
130                 {
131                     SubBox aSub;
132                     aSub.mpBox = pBox->mpBox;
133                     aSub.mbCovered = true;
134                     aSubLine.push_back( aSub );
135                     ++pBox;
136                 }
137                 do
138                 {
139                     rSubTable.insert( pEndLn, aSubLine );
140                 } while( ++nSize < rBox.GetTabLines().Count() );
141             }
142             for( sal_uInt16 nLine = 0; nLine < rBox.GetTabLines().Count(); ++nLine )
143                 pStartLn = insertSubLine( rSubTable, *rBox.GetTabLines()[nLine],
144                            pStartLn );
145             ASSERT( pStartLn == pEndLn, "Sub line confusion" );
146         }
147         else
148         {
149             SubBox aSub;
150             aSub.mpBox = &rBox;
151             aSub.mbCovered = false;
152             while( pStartLn != pEndLn )
153             {
154                 pStartLn->push_back( aSub );
155                 aSub.mbCovered = true;
156                 ++pStartLn;
157             }
158         }
159         return pStartLn;
160     }
161 
162     SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
163         SubTable::iterator pStartLn )
164     {
165         SubTable::iterator pMax = pStartLn;
166         ++pMax;
167         SubTable::difference_type nMax = 1;
168         for( sal_uInt16 nBox = 0; nBox < rLine.GetTabBoxes().Count(); ++nBox )
169         {
170             SubTable::iterator pTmp = insertSubBox( rSubTable,
171                 *rLine.GetTabBoxes()[nBox], pStartLn, pMax );
172             SubTable::difference_type nTmp = std::distance( pStartLn, pTmp );
173             if( nTmp > nMax )
174             {
175                 pMax = pTmp;
176                 nMax = nTmp;
177             }
178         }
179         return pMax;
180     }
181 
182     TableStructure::TableStructure( const SwTable& rTable ) :
183         maLines( rTable.GetTabLines().Count() ), mnStartCol(USHRT_MAX),
184         mnAddLine(0)
185     {
186         maCols.push_front(0);
187         const SwTableLines &rLines = rTable.GetTabLines();
188         sal_uInt16 nCnt = 0;
189         for( sal_uInt16 nLine = 0; nLine < rLines.Count(); ++nLine )
190             addLine( nCnt, rLines[nLine]->GetTabBoxes(), 0, rTable.IsNewModel() );
191     }
192 
193     TableStructure::TableStructure( const SwTable& rTable,
194         _FndBox &rFndBox, const SwSelBoxes& rSelBoxes,
195         LineStructure::size_type nMinSize )
196         : mnStartCol(USHRT_MAX), mnAddLine(0)
197     {
198         if( rFndBox.GetLines().Count() )
199         {
200             bool bNoSelection = rSelBoxes.Count() < 2;
201             _FndLines &rFndLines = rFndBox.GetLines();
202             maCols.push_front(0);
203             const SwTableLine* pLine = rFndLines[0]->GetLine();
204             sal_uInt16 nStartLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
205             sal_uInt16 nEndLn = nStartLn;
206             if( rFndLines.Count() > 1 )
207             {
208                 pLine = rFndLines[ rFndLines.Count()-1 ]->GetLine();
209                 nEndLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
210             }
211             if( nStartLn < USHRT_MAX && nEndLn < USHRT_MAX )
212             {
213                 const SwTableLines &rLines = rTable.GetTabLines();
214                 if( bNoSelection &&
215                     (sal_uInt16)nMinSize > nEndLn - nStartLn + 1 )
216                 {
217                     sal_uInt16 nNewEndLn = nStartLn + (sal_uInt16)nMinSize - 1;
218                     if( nNewEndLn >= rLines.Count() )
219                     {
220                         mnAddLine = nNewEndLn - rLines.Count() + 1;
221                         nNewEndLn = rLines.Count() - 1;
222                     }
223                     while( nEndLn < nNewEndLn )
224                     {
225                         SwTableLine *pLine2 = rLines[ ++nEndLn ];
226                         SwTableBox *pTmpBox = pLine2->GetTabBoxes()[0];
227                         _FndLine *pInsLine = new _FndLine( pLine2, &rFndBox );
228                         _FndBox *pFndBox = new _FndBox( pTmpBox, pInsLine );
229                         pInsLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, 0 );
230                         rFndLines.C40_INSERT( _FndLine, pInsLine, rFndLines.Count() );
231                     }
232                 }
233                 maLines.resize( nEndLn - nStartLn + 1 );
234                 const SwSelBoxes* pSelBoxes = &rSelBoxes;
235                 sal_uInt16 nCnt = 0;
236                 for( sal_uInt16 nLine = nStartLn; nLine <= nEndLn; ++nLine )
237                 {
238                     addLine( nCnt, rLines[nLine]->GetTabBoxes(),
239                              pSelBoxes, rTable.IsNewModel() );
240                     if( bNoSelection )
241                         pSelBoxes = 0;
242                 }
243             }
244             if( bNoSelection && mnStartCol < USHRT_MAX )
245             {
246                 BoxStructure::iterator pC = maLines[0].begin();
247                 BoxStructure::iterator pEnd = maLines[0].end();
248                 sal_uInt16 nIdx = mnStartCol;
249                 mnStartCol = 0;
250                 while( nIdx && pC != pEnd )
251                 {
252                     mnStartCol = mnStartCol + pC->mnColSpan;
253                     --nIdx;
254                     ++pC;
255                 }
256             }
257             else
258                 mnStartCol = USHRT_MAX;
259         }
260     }
261 
262     void TableStructure::addLine( sal_uInt16 &rLine, const SwTableBoxes& rBoxes,
263         const SwSelBoxes* pSelBoxes, bool bNewModel )
264     {
265         bool bComplex = false;
266         if( !bNewModel )
267             for( sal_uInt16 nBox = 0; !bComplex && nBox < rBoxes.Count(); ++nBox )
268                 bComplex = rBoxes[nBox]->GetTabLines().Count() > 0;
269         if( bComplex )
270         {
271             SubTable aSubTable;
272             SubLine aSubLine;
273             aSubTable.push_back( aSubLine );
274             SubTable::iterator pStartLn = aSubTable.begin();
275             SubTable::iterator pEndLn = aSubTable.end();
276             for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
277                 insertSubBox( aSubTable, *rBoxes[nBox], pStartLn, pEndLn );
278             SubTable::size_type nSize = aSubTable.size();
279             if( nSize )
280             {
281                 maLines.resize( maLines.size() + nSize - 1 );
282                 while( pStartLn != pEndLn )
283                 {
284                     bool bSelected = false;
285                     sal_uLong nBorder = 0;
286                     sal_uInt16 nCol = 0;
287                     maLines[rLine].reserve( pStartLn->size() );
288                     BoxStructure::iterator pSel = maLines[rLine].end();
289                     ColumnStructure::iterator pCol = maCols.begin();
290                     SubLine::iterator pBox = pStartLn->begin();
291                     SubLine::iterator pEnd = pStartLn->end();
292                     while( pBox != pEnd )
293                     {
294                         addBox( rLine, pSelBoxes, pBox->mpBox, nBorder, nCol,
295                             pCol, pSel, bSelected, pBox->mbCovered );
296                         ++pBox;
297                     }
298                     ++rLine;
299                     ++pStartLn;
300                 }
301             }
302         }
303         else
304         {
305             bool bSelected = false;
306             sal_uLong nBorder = 0;
307             sal_uInt16 nCol = 0;
308             maLines[rLine].reserve( rBoxes.Count() );
309             ColumnStructure::iterator pCol = maCols.begin();
310             BoxStructure::iterator pSel = maLines[rLine].end();
311             for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
312                 addBox( rLine, pSelBoxes, rBoxes[nBox], nBorder, nCol,
313                         pCol, pSel, bSelected, false );
314             ++rLine;
315         }
316     }
317 
318     void TableStructure::addBox( sal_uInt16 nLine, const SwSelBoxes* pSelBoxes,
319         SwTableBox *pBox, sal_uLong &rnBorder, sal_uInt16 &rnCol,
320         ColumnStructure::iterator& rpCol, BoxStructure::iterator& rpSel,
321         bool &rbSelected, bool bCovered )
322     {
323         BoxSpanInfo aInfo;
324         if( pSelBoxes &&
325             USHRT_MAX != pSelBoxes->GetPos( pBox ) )
326         {
327             aInfo.mbSelected = true;
328             if( mnStartCol == USHRT_MAX )
329             {
330                 mnStartCol = (sal_uInt16)maLines[nLine].size();
331                 if( pSelBoxes->Count() < 2 )
332                 {
333                     pSelBoxes = 0;
334                     aInfo.mbSelected = false;
335                 }
336             }
337         }
338         else
339             aInfo.mbSelected = false;
340         rnBorder += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
341         sal_uInt16 nLeftCol = rnCol;
342         while( rpCol != maCols.end() && *rpCol < rnBorder )
343         {
344             ++rnCol;
345             ++rpCol;
346         }
347         if( rpCol == maCols.end() || *rpCol > rnBorder )
348         {
349             maCols.insert( rpCol, rnBorder );
350             --rpCol;
351             incColSpan( nLine, rnCol );
352         }
353         aInfo.mnColSpan = rnCol - nLeftCol;
354         aInfo.mpCopy = 0;
355         aInfo.mpBox = bCovered ? 0 : pBox;
356         maLines[nLine].push_back( aInfo );
357         if( aInfo.mbSelected )
358         {
359             if( rbSelected )
360             {
361                 while( rpSel != maLines[nLine].end() )
362                 {
363                     rpSel->mbSelected = true;
364                     ++rpSel;
365                 }
366             }
367             else
368             {
369                 rpSel = maLines[nLine].end();
370                 rbSelected = true;
371             }
372             --rpSel;
373         }
374     }
375 
376     void TableStructure::moreLines( const SwTable& rTable )
377     {
378         if( mnAddLine )
379         {
380             const SwTableLines &rLines = rTable.GetTabLines();
381             sal_uInt16 nLineCount = rLines.Count();
382             if( nLineCount < mnAddLine )
383                 mnAddLine = nLineCount;
384             sal_uInt16 nLine = (sal_uInt16)maLines.size();
385             maLines.resize( nLine + mnAddLine );
386             while( mnAddLine )
387             {
388                 SwTableLine *pLine = rLines[ nLineCount - mnAddLine ];
389                 addLine( nLine, pLine->GetTabBoxes(), 0, rTable.IsNewModel() );
390                 --mnAddLine;
391             }
392         }
393     }
394 
395     void TableStructure::incColSpan( sal_uInt16 nLineMax, sal_uInt16 nNewCol )
396     {
397         for( sal_uInt16 nLine = 0; nLine < nLineMax; ++nLine )
398         {
399             BoxStructure::iterator pInfo = maLines[nLine].begin();
400             BoxStructure::iterator pEnd = maLines[nLine].end();
401             long nCol = pInfo->mnColSpan;
402             while( nNewCol > nCol && ++pInfo != pEnd )
403                 nCol += pInfo->mnColSpan;
404             if( pInfo != pEnd )
405                 ++(pInfo->mnColSpan);
406         }
407     }
408 
409     void TableStructure::assignBoxes( const TableStructure &rSource )
410     {
411         LineStructure::const_iterator pFirstLine = rSource.maLines.begin();
412         LineStructure::const_iterator pLastLine = rSource.maLines.end();
413         if( pFirstLine == pLastLine )
414             return;
415         LineStructure::const_iterator pCurrLine = pFirstLine;
416         LineStructure::size_type nLineCount = maLines.size();
417         sal_uInt16 nFirstStartCol = 0;
418         {
419             BoxStructure::const_iterator pFirstBox = pFirstLine->begin();
420             if( pFirstBox != pFirstLine->end() && pFirstBox->mpBox &&
421                 pFirstBox->mpBox->getDummyFlag() )
422                 nFirstStartCol = pFirstBox->mnColSpan;
423         }
424         for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
425         {
426             BoxStructure::const_iterator pFirstBox = pCurrLine->begin();
427             BoxStructure::const_iterator pLastBox = pCurrLine->end();
428             sal_uInt16 nCurrStartCol = mnStartCol;
429             if( pFirstBox != pLastBox )
430             {
431                 BoxStructure::const_iterator pTmpBox = pLastBox;
432                 --pTmpBox;
433                 if( pTmpBox->mpBox && pTmpBox->mpBox->getDummyFlag() )
434                     --pLastBox;
435                 if( pFirstBox != pLastBox && pFirstBox->mpBox &&
436                     pFirstBox->mpBox->getDummyFlag() )
437                 {
438                     if( nCurrStartCol < USHRT_MAX )
439                     {
440                         if( pFirstBox->mnColSpan > nFirstStartCol )
441                             nCurrStartCol = pFirstBox->mnColSpan - nFirstStartCol
442                                             + nCurrStartCol;
443                     }
444                     ++pFirstBox;
445                 }
446             }
447             if( pFirstBox != pLastBox )
448             {
449                 BoxStructure::const_iterator pCurrBox = pFirstBox;
450                 BoxStructure &rBox = maLines[nLine];
451                 BoxStructure::size_type nBoxCount = rBox.size();
452                 sal_uInt16 nCol = 0;
453                 for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
454                 {
455                     BoxSpanInfo& rInfo = rBox[nBox];
456                     nCol = nCol + rInfo.mnColSpan;
457                     if( rInfo.mbSelected || nCol > nCurrStartCol )
458                     {
459                         rInfo.mpCopy = pCurrBox->mpBox;
460                         if( rInfo.mbSelected && rInfo.mpCopy->getDummyFlag() )
461                         {
462                             ++pCurrBox;
463                             if( pCurrBox == pLastBox )
464                             {
465                                 pCurrBox = pFirstBox;
466                                 if( pCurrBox->mpBox->getDummyFlag() )
467                                     ++pCurrBox;
468                             }
469                             rInfo.mpCopy = pCurrBox->mpBox;
470                         }
471                         ++pCurrBox;
472                         if( pCurrBox == pLastBox )
473                         {
474                             if( rInfo.mbSelected )
475                                 pCurrBox = pFirstBox;
476                             else
477                             {
478                                 rInfo.mbSelected = rInfo.mpCopy == 0;
479                                 break;
480                             }
481                         }
482                         rInfo.mbSelected = rInfo.mpCopy == 0;
483                     }
484                 }
485             }
486             ++pCurrLine;
487             if( pCurrLine == pLastLine )
488                 pCurrLine = pFirstLine;
489         }
490     }
491 
492     void TableStructure::copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
493                                     SwUndoTblCpyTbl* pUndo ) const
494     {
495         LineStructure::size_type nLineCount = maLines.size();
496         for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
497         {
498             const BoxStructure &rBox = maLines[nLine];
499             BoxStructure::size_type nBoxCount = rBox.size();
500             for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
501             {
502                 const BoxSpanInfo& rInfo = rBox[nBox];
503                 if( ( rInfo.mpCopy && !rInfo.mpCopy->getDummyFlag() )
504                     || rInfo.mbSelected )
505                 {
506                     SwTableBox *pBox = rInfo.mpBox;
507                     if( pBox && pBox->getRowSpan() > 0 )
508                         lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
509                                     sal_True, pUndo );
510                     /* Idea: If target cell is a covered cell, append content
511                              to master cell.
512                     sal_Bool bReplace = sal_True;
513                     if( pBox->getRowSpan() < 0 )
514                     {
515                         if( rInfo.mpCopy->getRowSpan() < 0 )
516                             continue;
517                         pBox = &pBox->FindStartOfRowSpan( rDstTbl );
518                         bReplace = sal_False;
519                     }
520                     lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
521                                 bReplace, pUndo );
522                     */
523                 }
524             }
525         }
526     }
527 }
528 
529 // ---------------------------------------------------------------
530 
531 // kopiere die Tabelle in diese.
532 //  Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
533 //  wird dabei geloescht.
534 //  Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
535 //  Box einer "GrundLine".
536 //  Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
537 //  einer "GrundLine"
538 
539 
540 void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
541                     SwTable& rDstTbl, SwTableBox* pDstBox,
542                     sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo )
543 {
544     ASSERT( ( !pCpyBox || pCpyBox->GetSttNd() ) && pDstBox->GetSttNd(),
545             "Keine inhaltstragende Box" );
546 
547     SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
548     SwDoc* pDoc = rDstTbl.GetFrmFmt()->GetDoc();
549 
550     // kopiere erst den neuen und loeschen dann den alten Inhalt
551     // (keine leeren Section erzeugen; werden sonst geloescht!)
552     std::auto_ptr< SwNodeRange > pRg( pCpyBox ?
553         new SwNodeRange ( *pCpyBox->GetSttNd(), 1,
554         *pCpyBox->GetSttNd()->EndOfSectionNode() ) : 0 );
555 
556     SwNodeIndex aInsIdx( *pDstBox->GetSttNd(), bDelCntnt ? 1 :
557                         pDstBox->GetSttNd()->EndOfSectionIndex() -
558                         pDstBox->GetSttIdx() );
559 
560     if( pUndo )
561         pUndo->AddBoxBefore( *pDstBox, bDelCntnt );
562 
563     bool bUndoRedline = pUndo && pDoc->IsRedlineOn();
564     ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
565 
566     SwNodeIndex aSavePos( aInsIdx, -1 );
567     if( pRg.get() )
568         pCpyDoc->CopyWithFlyInFly( *pRg, 0, aInsIdx, sal_False );
569     else
570         pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
571     aSavePos++;
572 
573     SwTableLine* pLine = pDstBox->GetUpper();
574     while( pLine->GetUpper() )
575         pLine = pLine->GetUpper()->GetUpper();
576 
577     sal_Bool bReplaceColl = sal_True;
578     if( bDelCntnt && !bUndoRedline )
579     {
580         // zuerst die Fly loeschen, dann die entsprechenden Nodes
581         SwNodeIndex aEndNdIdx( *aInsIdx.GetNode().EndOfSectionNode() );
582 
583             // Bookmarks usw. verschieben
584         {
585             SwPosition aMvPos( aInsIdx );
586             SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious( &aMvPos.nNode );
587             aMvPos.nContent.Assign( pCNd, pCNd->Len() );
588             pDoc->CorrAbs( aInsIdx, aEndNdIdx, aMvPos, /*sal_True*/sal_False );
589         }
590 
591         // stehen noch FlyFrames rum, loesche auch diese
592         for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n )
593         {
594             SwFrmFmt *const pFly = (*pDoc->GetSpzFrmFmts())[n];
595             SwFmtAnchor const*const pAnchor = &pFly->GetAnchor();
596             SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
597             if (pAPos &&
598                 ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
599                  (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
600                 aInsIdx <= pAPos->nNode && pAPos->nNode <= aEndNdIdx )
601             {
602                 pDoc->DelLayoutFmt( pFly );
603             }
604         }
605 
606         // ist DestBox eine Headline-Box und hat Tabellen-Vorlage gesetzt,
607         // dann NICHT die TabellenHeadline-Vorlage automatisch setzen
608         if( 1 < rDstTbl.GetTabLines().Count() &&
609             pLine == rDstTbl.GetTabLines()[0] )
610         {
611             SwCntntNode* pCNd = aInsIdx.GetNode().GetCntntNode();
612             if( !pCNd )
613             {
614                 SwNodeIndex aTmp( aInsIdx );
615                 pCNd = pDoc->GetNodes().GoNext( &aTmp );
616             }
617 
618             if( pCNd &&
619                 /*RES_POOLCOLL_TABLE == */
620                 RES_POOLCOLL_TABLE_HDLN !=
621                     pCNd->GetFmtColl()->GetPoolFmtId() )
622                 bReplaceColl = sal_False;
623         }
624 
625         pDoc->GetNodes().Delete( aInsIdx, aEndNdIdx.GetIndex() - aInsIdx.GetIndex() );
626     }
627 
628     //b6341295: Table copy redlining will be managed by AddBoxAfter()
629     if( pUndo )
630         pUndo->AddBoxAfter( *pDstBox, aInsIdx, bDelCntnt );
631 
632     // heading
633     SwTxtNode *const pTxtNd = aSavePos.GetNode().GetTxtNode();
634     if( pTxtNd )
635     {
636         sal_uInt16 nPoolId = pTxtNd->GetTxtColl()->GetPoolFmtId();
637         if( bReplaceColl &&
638             (( 1 < rDstTbl.GetTabLines().Count() &&
639                 pLine == rDstTbl.GetTabLines()[0] )
640                 // gilt noch die Tabellen-Inhalt ??
641                 ? RES_POOLCOLL_TABLE == nPoolId
642                 : RES_POOLCOLL_TABLE_HDLN == nPoolId ) )
643         {
644             SwTxtFmtColl* pColl = pDoc->GetTxtCollFromPool(
645                 static_cast<sal_uInt16>(
646                                     RES_POOLCOLL_TABLE == nPoolId
647                                         ? RES_POOLCOLL_TABLE_HDLN
648                                         : RES_POOLCOLL_TABLE ) );
649             if( pColl )         // Vorlage umsetzen
650             {
651                 SwPaM aPam( aSavePos );
652                 aPam.SetMark();
653                 aPam.Move( fnMoveForward, fnGoSection );
654                 pDoc->SetTxtFmtColl( aPam, pColl );
655             }
656         }
657 
658         // loesche die akt. Formel/Format/Value Werte
659         if( SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT ) ||
660             SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA ) ||
661             SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_VALUE ) )
662         {
663             pDstBox->ClaimFrmFmt()->ResetFmtAttr( RES_BOXATR_FORMAT,
664                                                  RES_BOXATR_VALUE );
665         }
666 
667         // kopiere die TabellenBoxAttribute - Formel/Format/Value
668         if( pCpyBox )
669         {
670             SfxItemSet aBoxAttrSet( pCpyDoc->GetAttrPool(), RES_BOXATR_FORMAT,
671                                                             RES_BOXATR_VALUE );
672             aBoxAttrSet.Put( pCpyBox->GetFrmFmt()->GetAttrSet() );
673             if( aBoxAttrSet.Count() )
674             {
675                 const SfxPoolItem* pItem;
676                 SvNumberFormatter* pN = pDoc->GetNumberFormatter( sal_False );
677                 if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
678                     GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
679                 {
680                     sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
681                     sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
682                     if( nNewIdx != nOldIdx )
683                         aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
684                 }
685                 pDstBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
686             }
687         }
688     }
689 }
690 
691 sal_Bool SwTable::InsNewTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
692                         SwUndoTblCpyTbl* pUndo )
693 {
694     SwDoc* pDoc = GetFrmFmt()->GetDoc();
695     SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
696 
697     SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
698 
699     // analyse source structure
700     TableStructure aCopyStruct( rCpyTbl );
701 
702     // analyse target structure (from start box) and selected substructure
703     _FndBox aFndBox( 0, 0 );
704     {   // get all boxes/lines
705         _FndPara aPara( rSelBoxes, &aFndBox );
706         GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
707     }
708     TableStructure aTarget( *this, aFndBox, rSelBoxes, aCopyStruct.getLineCount() );
709 
710     bool bClear = false;
711     if( aTarget.mnAddLine && IsNewModel() )
712     {
713         SwSelBoxes aBoxes;
714         aBoxes.Insert( GetTabLines()[ GetTabLines().Count()-1 ]->GetTabBoxes()[0] );
715         if( pUndo )
716             pUndo->InsertRow( *this, aBoxes, aTarget.mnAddLine );
717         else
718             InsertRow( pDoc, aBoxes, aTarget.mnAddLine, sal_True );
719 
720         aTarget.moreLines( *this );
721         bClear = true;
722     }
723 
724     // find mapping, if needed extend target table and/or selection
725     aTarget.assignBoxes( aCopyStruct );
726 
727     {
728         // Change table formulas into relative representation
729         SwTableFmlUpdate aMsgHnt( &rCpyTbl );
730         aMsgHnt.eFlags = TBL_RELBOXNAME;
731         pCpyDoc->UpdateTblFlds( &aMsgHnt );
732     }
733 
734     // delete frames
735     aFndBox.SetTableLines( *this );
736     if( bClear )
737         aFndBox.ClearLineBehind();
738     aFndBox.DelFrms( *this );
739 
740     // copy boxes
741     aTarget.copyBoxes( rCpyTbl, *this, pUndo );
742 
743     // adjust row span attributes accordingly
744 
745     // make frames
746     aFndBox.MakeFrms( *this );
747 
748     return sal_True;
749 }
750 
751 // ---------------------------------------------------------------
752 
753 // kopiere die Tabelle in diese.
754 //  Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
755 //  wird dabei geloescht.
756 //  Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
757 //  Box einer "GrundLine".
758 //  Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
759 //  einer "GrundLine"
760 
761 
762 sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwNodeIndex& rSttBox,
763                         SwUndoTblCpyTbl* pUndo )
764 {
765     SetHTMLTableLayout( 0 );    // MIB 9.7.97: HTML-Layout loeschen
766 
767     SwDoc* pDoc = GetFrmFmt()->GetDoc();
768 
769     SwTableNode* pTblNd = pDoc->IsIdxInTbl( rSttBox );
770 
771     // suche erstmal die Box, in die kopiert werden soll:
772     SwTableBox* pMyBox = (SwTableBox*)GetTblBox(
773             rSttBox.GetNode().FindTableBoxStartNode()->GetIndex() );
774 
775     ASSERT( pMyBox, "Index steht nicht in dieser Tabelle in einer Box" );
776 
777     // loesche erstmal die Frames der Tabelle
778     _FndBox aFndBox( 0, 0 );
779     aFndBox.DelFrms( pTblNd->GetTable() );
780 
781     SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
782 
783     {
784         // Tabellen-Formeln in die relative Darstellung umwandeln
785         SwTableFmlUpdate aMsgHnt( &rCpyTbl );
786         aMsgHnt.eFlags = TBL_RELBOXNAME;
787         pCpyDoc->UpdateTblFlds( &aMsgHnt );
788     }
789 
790     SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
791 
792     sal_Bool bDelCntnt = sal_True;
793     const SwTableBox* pTmp;
794 
795     for( sal_uInt16 nLines = 0; nLines < rCpyTbl.GetTabLines().Count(); ++nLines )
796     {
797         // hole die erste Box von der Copy-Line
798         const SwTableBox* pCpyBox = rCpyTbl.GetTabLines()[nLines]
799                                     ->GetTabBoxes()[0];
800         while( pCpyBox->GetTabLines().Count() )
801             pCpyBox = pCpyBox->GetTabLines()[0]->GetTabBoxes()[0];
802 
803         do {
804             // kopiere erst den neuen und loeschen dann den alten Inhalt
805             // (keine leeren Section erzeugen, werden sonst geloescht!)
806             lcl_CpyBox( rCpyTbl, pCpyBox, *this, pMyBox, bDelCntnt, pUndo );
807 
808             if( 0 == (pTmp = pCpyBox->FindNextBox( rCpyTbl, pCpyBox, sal_False )))
809                 break;      // es folgt keine weitere Box mehr
810             pCpyBox = pTmp;
811 
812             if( 0 == ( pTmp = pMyBox->FindNextBox( *this, pMyBox, sal_False )))
813                 bDelCntnt = sal_False;  // kein Platz mehr ??
814             else
815                 pMyBox = (SwTableBox*)pTmp;
816 
817         } while( sal_True );
818 
819         // suche die oberste Line
820         SwTableLine* pNxtLine = pMyBox->GetUpper();
821         while( pNxtLine->GetUpper() )
822             pNxtLine = pNxtLine->GetUpper()->GetUpper();
823         sal_uInt16 nPos = GetTabLines().C40_GETPOS( SwTableLine, pNxtLine );
824         // gibt es eine naechste ??
825         if( nPos + 1 >= GetTabLines().Count() )
826             bDelCntnt = sal_False;      // es gibt keine, alles in die letzte Box
827         else
828         {
829             // suche die naechste "Inhaltstragende Box"
830             pNxtLine = GetTabLines()[ nPos+1 ];
831             pMyBox = pNxtLine->GetTabBoxes()[0];
832             while( pMyBox->GetTabLines().Count() )
833                 pMyBox = pMyBox->GetTabLines()[0]->GetTabBoxes()[0];
834             bDelCntnt = sal_True;
835         }
836     }
837 
838     aFndBox.MakeFrms( pTblNd->GetTable() );     // erzeuge die Frames neu
839     return sal_True;
840 }
841 
842 
843 sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
844                         SwUndoTblCpyTbl* pUndo )
845 {
846     ASSERT( rSelBoxes.Count(), "Missing selection" )
847 
848     SetHTMLTableLayout( 0 );    // MIB 9.7.97: HTML-Layout loeschen
849 
850     if( IsNewModel() || rCpyTbl.IsNewModel() )
851         return InsNewTable( rCpyTbl, rSelBoxes, pUndo );
852 
853     ASSERT( !rCpyTbl.IsTblComplex(), "Table too complex" )
854 
855             SwDoc* pDoc = GetFrmFmt()->GetDoc();
856     SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
857 
858     SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
859 
860     SwTableBox *pTmpBox, *pSttBox = (SwTableBox*)rSelBoxes[0];
861 
862     sal_uInt16 nLn, nBx;
863     _FndLine *pFLine, *pInsFLine = 0;
864     _FndBox aFndBox( 0, 0 );
865     // suche alle Boxen / Lines
866     {
867         _FndPara aPara( rSelBoxes, &aFndBox );
868         ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
869     }
870 
871     // JP 06.09.96: Sonderfall - eine Box in der Tabelle -> in alle
872     //              selektierten Boxen kopieren!
873     if( 1 != rCpyTbl.GetTabSortBoxes().Count() )
874     {
875         SwTableLine* pSttLine = pSttBox->GetUpper();
876         sal_uInt16 nSttBox = pSttLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
877         sal_uInt16 nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
878         _FndBox* pFndBox;
879 
880         sal_uInt16 nFndCnt = aFndBox.GetLines().Count();
881         if( !nFndCnt )
882             return sal_False;
883 
884         // teste ob genug Platz fuer die einzelnen Lines und Boxen ist:
885         sal_uInt16 nTstLns = 0;
886         pFLine = aFndBox.GetLines()[ 0 ];
887         pSttLine = pFLine->GetLine();
888         nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
889         // sind ueberhaupt soviele Zeilen vorhanden
890         if( 1 == nFndCnt )
891         {
892             // in der Tabelle noch genug Platz ??
893             if( (GetTabLines().Count() - nSttLine ) <
894                 rCpyTbl.GetTabLines().Count() )
895             {
896                 // sollte nicht mehr soviele Lines vorhanden sein, dann
897                 // teste, ob man durch einfuegen neuer zum Ziel kommt. Aber
898                 // nur wenn die SSelection eine Box umfasst !!
899                 if( 1 < rSelBoxes.Count() )
900                     return sal_False;
901 
902                 sal_uInt16 nNewLns = rCpyTbl.GetTabLines().Count() -
903                                 (GetTabLines().Count() - nSttLine );
904 
905                 // Dann teste mal ob die Anzahl der Boxen fuer die Lines reicht
906                 SwTableLine* pLastLn = GetTabLines()[ GetTabLines().Count()-1 ];
907 
908                 pSttBox = pFLine->GetBoxes()[0]->GetBox();
909                 nSttBox = pFLine->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
910                 for( sal_uInt16 n = rCpyTbl.GetTabLines().Count() - nNewLns;
911                         n < rCpyTbl.GetTabLines().Count(); ++n )
912                 {
913                     SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ n ];
914 
915                     if( pLastLn->GetTabBoxes().Count() < nSttBox ||
916                         ( pLastLn->GetTabBoxes().Count() - nSttBox ) <
917                             pCpyLn->GetTabBoxes().Count() )
918                         return sal_False;
919 
920                     // Test auf Verschachtelungen
921                     for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
922                         if( !( pTmpBox = pLastLn->GetTabBoxes()[ nSttBox + nBx ])
923                                     ->GetSttNd() )
924                             return sal_False;
925                 }
926                 // es ist also Platz fuer das zu kopierende vorhanden, also
927                 // fuege entsprechend neue Zeilen ein.
928                 SwTableBox* pInsBox = pLastLn->GetTabBoxes()[ nSttBox ];
929                 ASSERT( pInsBox && pInsBox->GetSttNd(),
930                     "kein CntntBox oder steht nicht in dieser Tabelle" );
931                 SwSelBoxes aBoxes;
932 
933                 if( pUndo
934                     ? !pUndo->InsertRow( *this, SelLineFromBox( pInsBox,
935                                 aBoxes, sal_True ), nNewLns )
936                     : !InsertRow( pDoc, SelLineFromBox( pInsBox,
937                                 aBoxes, sal_True ), nNewLns, sal_True ) )
938                     return sal_False;
939             }
940 
941             nTstLns = rCpyTbl.GetTabLines().Count();        // soviele Kopieren
942         }
943         else if( 0 == (nFndCnt % rCpyTbl.GetTabLines().Count()) )
944             nTstLns = nFndCnt;
945         else
946             return sal_False;       // kein Platz fuer die Zeilen
947 
948         for( nLn = 0; nLn < nTstLns; ++nLn )
949         {
950             // Zeilen sind genug vorhanden, dann ueberpruefe die Boxen
951             // je Zeile
952             pFLine = aFndBox.GetLines()[ nLn % nFndCnt ];
953             SwTableLine* pLine = pFLine->GetLine();
954             pSttBox = pFLine->GetBoxes()[0]->GetBox();
955             nSttBox = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
956             if( nLn >= nFndCnt )
957             {
958                 // es sind im ClipBoard mehr Zeilen als selectiert wurden
959                 pInsFLine = new _FndLine( GetTabLines()[ nSttLine + nLn ],
960                                         &aFndBox );
961                 pLine = pInsFLine->GetLine();
962             }
963             SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ nLn %
964                                         rCpyTbl.GetTabLines().Count() ];
965 
966             // zu wenig Zeilen selektiert ?
967             if( pInsFLine )
968             {
969                 // eine neue Zeile wird in die FndBox eingefuegt,
970                 if( pLine->GetTabBoxes().Count() < nSttBox ||
971                     ( pLine->GetTabBoxes().Count() - nSttBox ) <
972                     pFLine->GetBoxes().Count() )
973                     return sal_False;
974 
975                 // Test auf Verschachtelungen
976                 for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
977                 {
978                     if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
979                         ->GetSttNd() )
980                         return sal_False;
981                     // wenn Ok, fuege die Box in die FndLine zu
982                     pFndBox = new _FndBox( pTmpBox, pInsFLine );
983                     pInsFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
984                 }
985                 aFndBox.GetLines().C40_INSERT( _FndLine, pInsFLine, nLn );
986             }
987             else if( pFLine->GetBoxes().Count() == 1 )
988             {
989                 if( pLine->GetTabBoxes().Count() < nSttBox  ||
990                     ( pLine->GetTabBoxes().Count() - nSttBox ) <
991                     pCpyLn->GetTabBoxes().Count() )
992                     return sal_False;
993 
994                 // Test auf Verschachtelungen
995                 for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
996                 {
997                     if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
998                         ->GetSttNd() )
999                         return sal_False;
1000                     // wenn Ok, fuege die Box in die FndLine zu
1001                     if( nBx == pFLine->GetBoxes().Count() )
1002                     {
1003                         pFndBox = new _FndBox( pTmpBox, pFLine );
1004                         pFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
1005                     }
1006                 }
1007             }
1008             else
1009             {
1010                 // ueberpruefe die selektierten Boxen mit denen im Clipboard
1011                 // (n-Fach)
1012                 if( 0 != ( pFLine->GetBoxes().Count() %
1013                             pCpyLn->GetTabBoxes().Count() ))
1014                     return sal_False;
1015 
1016                 // Test auf Verschachtelungen
1017                 for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
1018                     if( !pFLine->GetBoxes()[ nBx ]->GetBox()->GetSttNd() )
1019                         return sal_False;
1020             }
1021         }
1022 
1023         if( !aFndBox.GetLines().Count() )
1024             return sal_False;
1025     }
1026 
1027     {
1028         // Tabellen-Formeln in die relative Darstellung umwandeln
1029         SwTableFmlUpdate aMsgHnt( &rCpyTbl );
1030         aMsgHnt.eFlags = TBL_RELBOXNAME;
1031         pCpyDoc->UpdateTblFlds( &aMsgHnt );
1032     }
1033 
1034     // loesche die Frames
1035     aFndBox.SetTableLines( *this );
1036     aFndBox.DelFrms( *this );
1037 
1038     if( 1 == rCpyTbl.GetTabSortBoxes().Count() )
1039     {
1040         SwTableBox *pTmpBx = rCpyTbl.GetTabSortBoxes()[0];
1041         for( sal_uInt16 n = 0; n < rSelBoxes.Count(); ++n )
1042             lcl_CpyBox( rCpyTbl, pTmpBx, *this,
1043                         (SwTableBox*)rSelBoxes[n], sal_True, pUndo );
1044     }
1045     else
1046         for( nLn = 0; nLn < aFndBox.GetLines().Count(); ++nLn )
1047         {
1048             pFLine = aFndBox.GetLines()[ nLn ];
1049             SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[
1050                                 nLn % rCpyTbl.GetTabLines().Count() ];
1051             for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
1052             {
1053                 // Kopiere in pMyBox die pCpyBox
1054                 lcl_CpyBox( rCpyTbl, pCpyLn->GetTabBoxes()[
1055                             nBx % pCpyLn->GetTabBoxes().Count() ],
1056                     *this, pFLine->GetBoxes()[ nBx ]->GetBox(), sal_True, pUndo );
1057             }
1058         }
1059 
1060     aFndBox.MakeFrms( *this );
1061     return sal_True;
1062 }
1063 
1064 
1065 
1066 sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara )
1067 {
1068     SwTableBox* pBox = (SwTableBox*)rpBox;
1069     if( rpBox->GetTabLines().Count() )
1070         pBox->GetTabLines().ForEach( &_FndCntntLine, pPara );
1071     else
1072         ((SwSelBoxes*)pPara)->Insert( pBox );
1073     return sal_True;
1074 }
1075 
1076 
1077 sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara )
1078 {
1079     ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &_FndCntntBox, pPara );
1080     return sal_True;
1081 }
1082 
1083 
1084 // suche alle Inhaltstragenden-Boxen dieser Box
1085 SwSelBoxes& SwTable::SelLineFromBox( const SwTableBox* pBox,
1086                                     SwSelBoxes& rBoxes, sal_Bool bToTop ) const
1087 {
1088     SwTableLine* pLine = (SwTableLine*)pBox->GetUpper();
1089     if( bToTop )
1090         while( pLine->GetUpper() )
1091             pLine = pLine->GetUpper()->GetUpper();
1092 
1093     // alle alten loeschen
1094     rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
1095     pLine->GetTabBoxes().ForEach( &_FndCntntBox, &rBoxes );
1096     return rBoxes;
1097 }
1098 
1099 
1100