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