Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <hintids.hxx>
21 :
22 : #include <svl/zforlist.hxx>
23 : #include <frmfmt.hxx>
24 : #include <doc.hxx>
25 : #include <IDocumentUndoRedo.hxx>
26 : #include <DocumentContentOperationsManager.hxx>
27 : #include <IDocumentRedlineAccess.hxx>
28 : #include <IDocumentFieldsAccess.hxx>
29 : #include <IDocumentLayoutAccess.hxx>
30 : #include <IDocumentStylePoolAccess.hxx>
31 : #include <cntfrm.hxx>
32 : #include <pam.hxx>
33 : #include <swtable.hxx>
34 : #include <ndtxt.hxx>
35 : #include <fldbas.hxx>
36 : #include <tblsel.hxx>
37 : #include <tabfrm.hxx>
38 : #include <poolfmt.hxx>
39 : #include <cellatr.hxx>
40 : #include <mvsave.hxx>
41 : #include <docary.hxx>
42 : #include <fmtanchr.hxx>
43 : #include <hints.hxx>
44 : #include <UndoTable.hxx>
45 : #include <redline.hxx>
46 : #include <fmtfsize.hxx>
47 : #include <list>
48 : #include <boost/scoped_ptr.hpp>
49 :
50 : static void lcl_CpyBox( const SwTable& rCpyTable, const SwTableBox* pCpyBox,
51 : SwTable& rDstTable, SwTableBox* pDstBox,
52 : bool bDelContent, SwUndoTableCpyTable* pUndo );
53 :
54 : // The following type will be used by table copy functions to describe
55 : // the structure of tables (or parts of tables).
56 : // It's for new table model only.
57 :
58 : namespace
59 : {
60 : struct BoxSpanInfo
61 : {
62 : SwTableBox* mpBox;
63 : SwTableBox* mpCopy;
64 : sal_uInt16 mnColSpan;
65 : bool mbSelected;
66 : };
67 :
68 : typedef std::vector< BoxSpanInfo > BoxStructure;
69 : typedef std::vector< BoxStructure > LineStructure;
70 : typedef std::list< sal_uLong > ColumnStructure;
71 :
72 : struct SubBox
73 : {
74 : SwTableBox *mpBox;
75 : bool mbCovered;
76 : };
77 :
78 : typedef std::list< SubBox > SubLine;
79 : typedef std::list< SubLine > SubTable;
80 :
81 0 : class TableStructure
82 : {
83 : public:
84 : LineStructure maLines;
85 : ColumnStructure maCols;
86 : sal_uInt16 mnStartCol;
87 : sal_uInt16 mnAddLine;
88 : void addLine( sal_uInt16 &rLine, const SwTableBoxes&, const SwSelBoxes*,
89 : bool bNewModel );
90 : void addBox( sal_uInt16 nLine, const SwSelBoxes*, SwTableBox *pBox,
91 : sal_uLong &rnB, sal_uInt16 &rnC, ColumnStructure::iterator& rpCl,
92 : BoxStructure::iterator& rpSel, bool &rbSel, bool bCover );
93 : void incColSpan( sal_uInt16 nLine, sal_uInt16 nCol );
94 : explicit TableStructure( const SwTable& rTable );
95 : TableStructure( const SwTable& rTable, _FndBox &rFndBox,
96 : const SwSelBoxes& rSelBoxes,
97 : LineStructure::size_type nMinSize );
98 0 : LineStructure::size_type getLineCount() const
99 0 : { return maLines.size(); }
100 : void moreLines( const SwTable& rTable );
101 : void assignBoxes( const TableStructure &rSource );
102 : void copyBoxes( const SwTable& rSource, SwTable& rDstTable,
103 : SwUndoTableCpyTable* pUndo ) const;
104 : };
105 :
106 : SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
107 : SubTable::iterator pStartLn );
108 :
109 0 : SubTable::iterator insertSubBox( SubTable& rSubTable, SwTableBox& rBox,
110 : SubTable::iterator pStartLn, SubTable::iterator pEndLn )
111 : {
112 0 : if( !rBox.GetTabLines().empty() )
113 : {
114 0 : SubTable::size_type nSize = static_cast<SubTable::size_type>(std::distance( pStartLn, pEndLn ));
115 0 : if( nSize < rBox.GetTabLines().size() )
116 : {
117 0 : SubLine aSubLine;
118 0 : SubLine::iterator pBox = pStartLn->begin();
119 0 : SubLine::iterator pEnd = pStartLn->end();
120 0 : while( pBox != pEnd )
121 : {
122 : SubBox aSub;
123 0 : aSub.mpBox = pBox->mpBox;
124 0 : aSub.mbCovered = true;
125 0 : aSubLine.push_back( aSub );
126 0 : ++pBox;
127 : }
128 0 : do
129 : {
130 0 : rSubTable.insert( pEndLn, aSubLine );
131 0 : } while( ++nSize < rBox.GetTabLines().size() );
132 : }
133 0 : for( auto pLine : rBox.GetTabLines() )
134 0 : pStartLn = insertSubLine( rSubTable, *pLine, pStartLn );
135 : OSL_ENSURE( pStartLn == pEndLn, "Sub line confusion" );
136 : }
137 : else
138 : {
139 : SubBox aSub;
140 0 : aSub.mpBox = &rBox;
141 0 : aSub.mbCovered = false;
142 0 : while( pStartLn != pEndLn )
143 : {
144 0 : pStartLn->push_back( aSub );
145 0 : aSub.mbCovered = true;
146 0 : ++pStartLn;
147 : }
148 : }
149 0 : return pStartLn;
150 : }
151 :
152 0 : SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
153 : SubTable::iterator pStartLn )
154 : {
155 0 : SubTable::iterator pMax = pStartLn;
156 0 : ++pMax;
157 0 : SubTable::difference_type nMax = 1;
158 0 : for( auto pBox : rLine.GetTabBoxes() )
159 : {
160 0 : SubTable::iterator pTmp = insertSubBox( rSubTable, *pBox, pStartLn, pMax );
161 0 : SubTable::difference_type nTmp = std::distance( pStartLn, pTmp );
162 0 : if( nTmp > nMax )
163 : {
164 0 : pMax = pTmp;
165 0 : nMax = nTmp;
166 : }
167 : }
168 0 : return pMax;
169 : }
170 :
171 0 : TableStructure::TableStructure( const SwTable& rTable ) :
172 0 : maLines( rTable.GetTabLines().size() ), mnStartCol(USHRT_MAX),
173 0 : mnAddLine(0)
174 : {
175 0 : maCols.push_front(0);
176 0 : sal_uInt16 nCnt = 0;
177 0 : for( auto pLine : rTable.GetTabLines() )
178 0 : addLine( nCnt, pLine->GetTabBoxes(), 0, rTable.IsNewModel() );
179 0 : }
180 :
181 0 : TableStructure::TableStructure( const SwTable& rTable,
182 : _FndBox &rFndBox, const SwSelBoxes& rSelBoxes,
183 : LineStructure::size_type nMinSize )
184 0 : : mnStartCol(USHRT_MAX), mnAddLine(0)
185 : {
186 0 : if( !rFndBox.GetLines().empty() )
187 : {
188 0 : bool bNoSelection = rSelBoxes.size() < 2;
189 0 : _FndLines &rFndLines = rFndBox.GetLines();
190 0 : maCols.push_front(0);
191 0 : const SwTableLine* pLine = rFndLines.front().GetLine();
192 0 : const sal_uInt16 nStartLn = rTable.GetTabLines().GetPos( pLine );
193 0 : sal_uInt16 nEndLn = nStartLn;
194 0 : if( rFndLines.size() > 1 )
195 : {
196 0 : pLine = rFndLines.back().GetLine();
197 0 : nEndLn = rTable.GetTabLines().GetPos( pLine );
198 : }
199 0 : if( nStartLn < USHRT_MAX && nEndLn < USHRT_MAX )
200 : {
201 0 : const SwTableLines &rLines = rTable.GetTabLines();
202 0 : if( bNoSelection &&
203 0 : nMinSize > static_cast<LineStructure::size_type>(nEndLn - nStartLn + 1) )
204 : {
205 0 : LineStructure::size_type nNewEndLn = nStartLn + nMinSize - 1;
206 0 : if( nNewEndLn >= rLines.size() )
207 : {
208 0 : mnAddLine = nNewEndLn - rLines.size() + 1;
209 0 : nNewEndLn = rLines.size() - 1;
210 : }
211 0 : while( nEndLn < nNewEndLn )
212 : {
213 0 : SwTableLine *pLine2 = rLines[ ++nEndLn ];
214 0 : SwTableBox *pTmpBox = pLine2->GetTabBoxes()[0];
215 0 : _FndLine *pInsLine = new _FndLine( pLine2, &rFndBox );
216 0 : _FndBox *pFndBox = new _FndBox( pTmpBox, pInsLine );
217 0 : pInsLine->GetBoxes().insert(pInsLine->GetBoxes().begin(), pFndBox);
218 0 : rFndLines.push_back( pInsLine );
219 : }
220 : }
221 0 : maLines.resize( nEndLn - nStartLn + 1 );
222 0 : const SwSelBoxes* pSelBoxes = &rSelBoxes;
223 0 : sal_uInt16 nCnt = 0;
224 0 : for( sal_uInt16 nLine = nStartLn; nLine <= nEndLn; ++nLine )
225 : {
226 0 : addLine( nCnt, rLines[nLine]->GetTabBoxes(),
227 0 : pSelBoxes, rTable.IsNewModel() );
228 0 : if( bNoSelection )
229 0 : pSelBoxes = 0;
230 : }
231 : }
232 0 : if( bNoSelection && mnStartCol < USHRT_MAX )
233 : {
234 0 : BoxStructure::iterator pC = maLines[0].begin();
235 0 : BoxStructure::iterator pEnd = maLines[0].end();
236 0 : sal_uInt16 nIdx = mnStartCol;
237 0 : mnStartCol = 0;
238 0 : while( nIdx && pC != pEnd )
239 : {
240 0 : mnStartCol += pC->mnColSpan;
241 0 : --nIdx;
242 0 : ++pC;
243 0 : }
244 : }
245 : else
246 0 : mnStartCol = USHRT_MAX;
247 : }
248 0 : }
249 :
250 0 : void TableStructure::addLine( sal_uInt16 &rLine, const SwTableBoxes& rBoxes,
251 : const SwSelBoxes* pSelBoxes, bool bNewModel )
252 : {
253 0 : bool bComplex = false;
254 0 : if( !bNewModel )
255 0 : for( SwTableBoxes::size_type nBox = 0; !bComplex && nBox < rBoxes.size(); ++nBox )
256 0 : bComplex = !rBoxes[nBox]->GetTabLines().empty();
257 0 : if( bComplex )
258 : {
259 0 : SubTable aSubTable;
260 0 : SubLine aSubLine;
261 0 : aSubTable.push_back( aSubLine );
262 0 : SubTable::iterator pStartLn = aSubTable.begin();
263 0 : SubTable::iterator pEndLn = aSubTable.end();
264 0 : for( auto pBox : rBoxes )
265 0 : insertSubBox( aSubTable, *pBox, pStartLn, pEndLn );
266 0 : SubTable::size_type nSize = aSubTable.size();
267 0 : if( nSize )
268 : {
269 0 : maLines.resize( maLines.size() + nSize - 1 );
270 0 : while( pStartLn != pEndLn )
271 : {
272 0 : bool bSelected = false;
273 0 : sal_uLong nBorder = 0;
274 0 : sal_uInt16 nCol = 0;
275 0 : maLines[rLine].reserve( pStartLn->size() );
276 0 : BoxStructure::iterator pSel = maLines[rLine].end();
277 0 : ColumnStructure::iterator pCol = maCols.begin();
278 0 : SubLine::iterator pBox = pStartLn->begin();
279 0 : SubLine::iterator pEnd = pStartLn->end();
280 0 : while( pBox != pEnd )
281 : {
282 0 : addBox( rLine, pSelBoxes, pBox->mpBox, nBorder, nCol,
283 0 : pCol, pSel, bSelected, pBox->mbCovered );
284 0 : ++pBox;
285 : }
286 0 : ++rLine;
287 0 : ++pStartLn;
288 : }
289 0 : }
290 : }
291 : else
292 : {
293 0 : bool bSelected = false;
294 0 : sal_uLong nBorder = 0;
295 0 : sal_uInt16 nCol = 0;
296 0 : maLines[rLine].reserve( rBoxes.size() );
297 0 : ColumnStructure::iterator pCol = maCols.begin();
298 0 : BoxStructure::iterator pSel = maLines[rLine].end();
299 0 : for( auto pBox : rBoxes )
300 : addBox( rLine, pSelBoxes, pBox, nBorder, nCol,
301 0 : pCol, pSel, bSelected, false );
302 0 : ++rLine;
303 : }
304 0 : }
305 :
306 0 : void TableStructure::addBox( sal_uInt16 nLine, const SwSelBoxes* pSelBoxes,
307 : SwTableBox *pBox, sal_uLong &rnBorder, sal_uInt16 &rnCol,
308 : ColumnStructure::iterator& rpCol, BoxStructure::iterator& rpSel,
309 : bool &rbSelected, bool bCovered )
310 : {
311 : BoxSpanInfo aInfo;
312 0 : if( pSelBoxes &&
313 0 : pSelBoxes->end() != pSelBoxes->find( pBox ) )
314 : {
315 0 : aInfo.mbSelected = true;
316 0 : if( mnStartCol == USHRT_MAX )
317 : {
318 0 : mnStartCol = (sal_uInt16)maLines[nLine].size();
319 0 : if( pSelBoxes->size() < 2 )
320 : {
321 0 : pSelBoxes = 0;
322 0 : aInfo.mbSelected = false;
323 : }
324 : }
325 : }
326 : else
327 0 : aInfo.mbSelected = false;
328 0 : rnBorder += pBox->GetFrameFormat()->GetFrmSize().GetWidth();
329 0 : const sal_uInt16 nLeftCol = rnCol;
330 0 : while( rpCol != maCols.end() && *rpCol < rnBorder )
331 : {
332 0 : ++rnCol;
333 0 : ++rpCol;
334 : }
335 0 : if( rpCol == maCols.end() || *rpCol > rnBorder )
336 : {
337 0 : maCols.insert( rpCol, rnBorder );
338 0 : --rpCol;
339 0 : incColSpan( nLine, rnCol );
340 : }
341 0 : aInfo.mnColSpan = rnCol - nLeftCol;
342 0 : aInfo.mpCopy = 0;
343 0 : aInfo.mpBox = bCovered ? 0 : pBox;
344 0 : maLines[nLine].push_back( aInfo );
345 0 : if( aInfo.mbSelected )
346 : {
347 0 : if( rbSelected )
348 : {
349 0 : while( rpSel != maLines[nLine].end() )
350 : {
351 0 : rpSel->mbSelected = true;
352 0 : ++rpSel;
353 : }
354 : }
355 : else
356 : {
357 0 : rpSel = maLines[nLine].end();
358 0 : rbSelected = true;
359 : }
360 0 : --rpSel;
361 : }
362 0 : }
363 :
364 0 : void TableStructure::moreLines( const SwTable& rTable )
365 : {
366 0 : if( mnAddLine )
367 : {
368 0 : const SwTableLines &rLines = rTable.GetTabLines();
369 0 : const sal_uInt16 nLineCount = rLines.size();
370 0 : if( nLineCount < mnAddLine )
371 0 : mnAddLine = nLineCount;
372 0 : sal_uInt16 nLine = (sal_uInt16)maLines.size();
373 0 : maLines.resize( nLine + mnAddLine );
374 0 : while( mnAddLine )
375 : {
376 0 : SwTableLine *pLine = rLines[ nLineCount - mnAddLine ];
377 0 : addLine( nLine, pLine->GetTabBoxes(), 0, rTable.IsNewModel() );
378 0 : --mnAddLine;
379 : }
380 : }
381 0 : }
382 :
383 0 : void TableStructure::incColSpan( sal_uInt16 nLineMax, sal_uInt16 nNewCol )
384 : {
385 0 : for( sal_uInt16 nLine = 0; nLine < nLineMax; ++nLine )
386 : {
387 0 : BoxStructure::iterator pInfo = maLines[nLine].begin();
388 0 : BoxStructure::iterator pEnd = maLines[nLine].end();
389 0 : long nCol = pInfo->mnColSpan;
390 0 : while( nNewCol > nCol && ++pInfo != pEnd )
391 0 : nCol += pInfo->mnColSpan;
392 0 : if( pInfo != pEnd )
393 0 : ++(pInfo->mnColSpan);
394 : }
395 0 : }
396 :
397 0 : void TableStructure::assignBoxes( const TableStructure &rSource )
398 : {
399 0 : LineStructure::const_iterator pFirstLine = rSource.maLines.begin();
400 0 : LineStructure::const_iterator pLastLine = rSource.maLines.end();
401 0 : if( pFirstLine == pLastLine )
402 0 : return;
403 0 : LineStructure::const_iterator pCurrLine = pFirstLine;
404 0 : LineStructure::size_type nLineCount = maLines.size();
405 0 : sal_uInt16 nFirstStartCol = 0;
406 : {
407 0 : BoxStructure::const_iterator pFirstBox = pFirstLine->begin();
408 0 : if( pFirstBox != pFirstLine->end() && pFirstBox->mpBox &&
409 0 : pFirstBox->mpBox->getDummyFlag() )
410 0 : nFirstStartCol = pFirstBox->mnColSpan;
411 : }
412 0 : for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
413 : {
414 0 : BoxStructure::const_iterator pFirstBox = pCurrLine->begin();
415 0 : BoxStructure::const_iterator pLastBox = pCurrLine->end();
416 0 : sal_uInt16 nCurrStartCol = mnStartCol;
417 0 : if( pFirstBox != pLastBox )
418 : {
419 0 : BoxStructure::const_iterator pTmpBox = pLastBox;
420 0 : --pTmpBox;
421 0 : if( pTmpBox->mpBox && pTmpBox->mpBox->getDummyFlag() )
422 0 : --pLastBox;
423 0 : if( pFirstBox != pLastBox && pFirstBox->mpBox &&
424 0 : pFirstBox->mpBox->getDummyFlag() )
425 : {
426 0 : if( nCurrStartCol < USHRT_MAX )
427 : {
428 0 : if( pFirstBox->mnColSpan > nFirstStartCol )
429 0 : nCurrStartCol += pFirstBox->mnColSpan - nFirstStartCol;
430 : }
431 0 : ++pFirstBox;
432 : }
433 : }
434 0 : if( pFirstBox != pLastBox )
435 : {
436 0 : BoxStructure::const_iterator pCurrBox = pFirstBox;
437 0 : BoxStructure &rBox = maLines[nLine];
438 0 : BoxStructure::size_type nBoxCount = rBox.size();
439 0 : sal_uInt16 nCol = 0;
440 0 : for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
441 : {
442 0 : BoxSpanInfo& rInfo = rBox[nBox];
443 0 : nCol += rInfo.mnColSpan;
444 0 : if( rInfo.mbSelected || nCol > nCurrStartCol )
445 : {
446 0 : rInfo.mpCopy = pCurrBox->mpBox;
447 0 : if( rInfo.mbSelected && rInfo.mpCopy->getDummyFlag() )
448 : {
449 0 : ++pCurrBox;
450 0 : if( pCurrBox == pLastBox )
451 : {
452 0 : pCurrBox = pFirstBox;
453 0 : if( pCurrBox->mpBox->getDummyFlag() )
454 0 : ++pCurrBox;
455 : }
456 0 : rInfo.mpCopy = pCurrBox->mpBox;
457 : }
458 0 : ++pCurrBox;
459 0 : if( pCurrBox == pLastBox )
460 : {
461 0 : if( rInfo.mbSelected )
462 0 : pCurrBox = pFirstBox;
463 : else
464 : {
465 0 : rInfo.mbSelected = rInfo.mpCopy == 0;
466 0 : break;
467 : }
468 : }
469 0 : rInfo.mbSelected = rInfo.mpCopy == 0;
470 : }
471 : }
472 : }
473 0 : ++pCurrLine;
474 0 : if( pCurrLine == pLastLine )
475 0 : pCurrLine = pFirstLine;
476 : }
477 : }
478 :
479 0 : void TableStructure::copyBoxes( const SwTable& rSource, SwTable& rDstTable,
480 : SwUndoTableCpyTable* pUndo ) const
481 : {
482 0 : LineStructure::size_type nLineCount = maLines.size();
483 0 : for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
484 : {
485 0 : const BoxStructure &rBox = maLines[nLine];
486 0 : BoxStructure::size_type nBoxCount = rBox.size();
487 0 : for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
488 : {
489 0 : const BoxSpanInfo& rInfo = rBox[nBox];
490 0 : if( ( rInfo.mpCopy && !rInfo.mpCopy->getDummyFlag() )
491 0 : || rInfo.mbSelected )
492 : {
493 0 : SwTableBox *pBox = rInfo.mpBox;
494 0 : if( pBox && pBox->getRowSpan() > 0 )
495 : lcl_CpyBox( rSource, rInfo.mpCopy, rDstTable, pBox,
496 0 : true, pUndo );
497 : }
498 : }
499 : }
500 0 : }
501 : }
502 :
503 : /** Copy Table into this Box.
504 : Copy all Boxes of a Line into the corresponding Boxes. The old content
505 : is deleted by doing this.
506 : If no Box is left the remaining content goes to the Box of a "BaseLine".
507 : If there's no Line anymore, put it also into the last Box of a "BaseLine". */
508 0 : static void lcl_CpyBox( const SwTable& rCpyTable, const SwTableBox* pCpyBox,
509 : SwTable& rDstTable, SwTableBox* pDstBox,
510 : bool bDelContent, SwUndoTableCpyTable* pUndo )
511 : {
512 : OSL_ENSURE( ( !pCpyBox || pCpyBox->GetSttNd() ) && pDstBox->GetSttNd(),
513 : "No content in this Box" );
514 :
515 0 : SwDoc* pCpyDoc = rCpyTable.GetFrameFormat()->GetDoc();
516 0 : SwDoc* pDoc = rDstTable.GetFrameFormat()->GetDoc();
517 :
518 : // First copy the new content and then delete the old one.
519 : // Do not create empty Sections, otherwise they will be deleted!
520 : boost::scoped_ptr< SwNodeRange > pRg( pCpyBox ?
521 0 : new SwNodeRange ( *pCpyBox->GetSttNd(), 1,
522 0 : *pCpyBox->GetSttNd()->EndOfSectionNode() ) : 0 );
523 :
524 0 : SwNodeIndex aInsIdx( *pDstBox->GetSttNd(), bDelContent ? 1 :
525 0 : pDstBox->GetSttNd()->EndOfSectionIndex() -
526 0 : pDstBox->GetSttIdx() );
527 :
528 0 : if( pUndo )
529 0 : pUndo->AddBoxBefore( *pDstBox, bDelContent );
530 :
531 0 : bool bUndoRedline = pUndo && pDoc->getIDocumentRedlineAccess().IsRedlineOn();
532 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
533 :
534 0 : SwNodeIndex aSavePos( aInsIdx, -1 );
535 0 : if( pRg.get() )
536 0 : pCpyDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly( *pRg, 0, aInsIdx, NULL, false );
537 : else
538 0 : pDoc->GetNodes().MakeTextNode( aInsIdx, pDoc->GetDfltTextFormatColl() );
539 0 : ++aSavePos;
540 :
541 0 : SwTableLine* pLine = pDstBox->GetUpper();
542 0 : while( pLine->GetUpper() )
543 0 : pLine = pLine->GetUpper()->GetUpper();
544 :
545 0 : bool bReplaceColl = true;
546 0 : if( bDelContent && !bUndoRedline )
547 : {
548 : // Delete the Fly first, then the corresponding Nodes
549 0 : SwNodeIndex aEndNdIdx( *aInsIdx.GetNode().EndOfSectionNode() );
550 :
551 : // Move Bookmarks
552 : {
553 0 : SwPosition aMvPos( aInsIdx );
554 0 : SwContentNode* pCNd = SwNodes::GoPrevious( &aMvPos.nNode );
555 0 : aMvPos.nContent.Assign( pCNd, pCNd->Len() );
556 0 : SwDoc::CorrAbs( aInsIdx, aEndNdIdx, aMvPos, false );
557 : }
558 :
559 : // If we still have FlyFrames hanging around, delete them too
560 0 : for( const auto pFly : *pDoc->GetSpzFrameFormats() )
561 : {
562 0 : SwFormatAnchor const*const pAnchor = &pFly->GetAnchor();
563 0 : SwPosition const*const pAPos = pAnchor->GetContentAnchor();
564 0 : if (pAPos &&
565 0 : ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
566 0 : (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
567 0 : aInsIdx <= pAPos->nNode && pAPos->nNode <= aEndNdIdx )
568 : {
569 0 : pDoc->getIDocumentLayoutAccess().DelLayoutFormat( pFly );
570 : }
571 : }
572 :
573 : // If DestBox is a Headline Box and has Table style set, then
574 : // DO NOT automatically set the TableHeadline style!
575 0 : if( 1 < rDstTable.GetTabLines().size() &&
576 0 : pLine == rDstTable.GetTabLines().front() )
577 : {
578 0 : SwContentNode* pCNd = aInsIdx.GetNode().GetContentNode();
579 0 : if( !pCNd )
580 : {
581 0 : SwNodeIndex aTmp( aInsIdx );
582 0 : pCNd = pDoc->GetNodes().GoNext( &aTmp );
583 : }
584 :
585 0 : if( pCNd &&
586 : RES_POOLCOLL_TABLE_HDLN !=
587 0 : pCNd->GetFormatColl()->GetPoolFormatId() )
588 0 : bReplaceColl = false;
589 : }
590 :
591 0 : pDoc->GetNodes().Delete( aInsIdx, aEndNdIdx.GetIndex() - aInsIdx.GetIndex() );
592 : }
593 :
594 : //b6341295: Table copy redlining will be managed by AddBoxAfter()
595 0 : if( pUndo )
596 0 : pUndo->AddBoxAfter( *pDstBox, aInsIdx, bDelContent );
597 :
598 : // heading
599 0 : SwTextNode *const pTextNd = aSavePos.GetNode().GetTextNode();
600 0 : if( pTextNd )
601 : {
602 0 : const sal_uInt16 nPoolId = pTextNd->GetTextColl()->GetPoolFormatId();
603 0 : if( bReplaceColl &&
604 0 : (( 1 < rDstTable.GetTabLines().size() &&
605 0 : pLine == rDstTable.GetTabLines().front() )
606 : // Is the Table's content sill valid?
607 : ? RES_POOLCOLL_TABLE == nPoolId
608 : : RES_POOLCOLL_TABLE_HDLN == nPoolId ) )
609 : {
610 0 : SwTextFormatColl* pColl = pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(
611 : static_cast<sal_uInt16>(
612 : RES_POOLCOLL_TABLE == nPoolId
613 : ? RES_POOLCOLL_TABLE_HDLN
614 0 : : RES_POOLCOLL_TABLE ) );
615 0 : if( pColl ) // Apply style
616 : {
617 0 : SwPaM aPam( aSavePos );
618 0 : aPam.SetMark();
619 0 : aPam.Move( fnMoveForward, fnGoSection );
620 0 : pDoc->SetTextFormatColl( aPam, pColl );
621 : }
622 : }
623 :
624 : // Delete the current Formula/Format/Value values
625 0 : if( SfxItemState::SET == pDstBox->GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT ) ||
626 0 : SfxItemState::SET == pDstBox->GetFrameFormat()->GetItemState( RES_BOXATR_FORMULA ) ||
627 0 : SfxItemState::SET == pDstBox->GetFrameFormat()->GetItemState( RES_BOXATR_VALUE ) )
628 : {
629 0 : pDstBox->ClaimFrameFormat()->ResetFormatAttr( RES_BOXATR_FORMAT,
630 0 : RES_BOXATR_VALUE );
631 : }
632 :
633 : // Copy the TableBoxAttributes - Formula/Format/Value
634 0 : if( pCpyBox )
635 : {
636 0 : SfxItemSet aBoxAttrSet( pCpyDoc->GetAttrPool(), RES_BOXATR_FORMAT,
637 0 : RES_BOXATR_VALUE );
638 0 : aBoxAttrSet.Put( pCpyBox->GetFrameFormat()->GetAttrSet() );
639 0 : if( aBoxAttrSet.Count() )
640 : {
641 : const SfxPoolItem* pItem;
642 0 : SvNumberFormatter* pN = pDoc->GetNumberFormatter( false );
643 0 : if( pN && pN->HasMergeFormatTable() && SfxItemState::SET == aBoxAttrSet.
644 0 : GetItemState( RES_BOXATR_FORMAT, false, &pItem ) )
645 : {
646 0 : sal_uLong nOldIdx = static_cast<const SwTableBoxNumFormat*>(pItem)->GetValue();
647 0 : sal_uLong nNewIdx = pN->GetMergeFormatIndex( nOldIdx );
648 0 : if( nNewIdx != nOldIdx )
649 0 : aBoxAttrSet.Put( SwTableBoxNumFormat( nNewIdx ));
650 : }
651 0 : pDstBox->ClaimFrameFormat()->SetFormatAttr( aBoxAttrSet );
652 0 : }
653 : }
654 0 : }
655 0 : }
656 :
657 0 : bool SwTable::InsNewTable( const SwTable& rCpyTable, const SwSelBoxes& rSelBoxes,
658 : SwUndoTableCpyTable* pUndo )
659 : {
660 0 : SwDoc* pDoc = GetFrameFormat()->GetDoc();
661 0 : SwDoc* pCpyDoc = rCpyTable.GetFrameFormat()->GetDoc();
662 :
663 0 : SwTableNumFormatMerge aTNFM( *pCpyDoc, *pDoc );
664 :
665 : // Analyze source structure
666 0 : TableStructure aCopyStruct( rCpyTable );
667 :
668 : // Analyze target structure (from start box) and selected substructure
669 0 : _FndBox aFndBox( 0, 0 );
670 : { // get all boxes/lines
671 0 : _FndPara aPara( rSelBoxes, &aFndBox );
672 0 : ForEach_FndLineCopyCol( GetTabLines(), &aPara );
673 : }
674 0 : TableStructure aTarget( *this, aFndBox, rSelBoxes, aCopyStruct.getLineCount() );
675 :
676 0 : bool bClear = false;
677 0 : if( aTarget.mnAddLine && IsNewModel() )
678 : {
679 0 : SwSelBoxes aBoxes;
680 0 : aBoxes.insert( GetTabLines().back()->GetTabBoxes().front() );
681 0 : if( pUndo )
682 0 : pUndo->InsertRow( *this, aBoxes, aTarget.mnAddLine );
683 : else
684 0 : InsertRow( pDoc, aBoxes, aTarget.mnAddLine, true );
685 :
686 0 : aTarget.moreLines( *this );
687 0 : bClear = true;
688 : }
689 :
690 : // Find mapping, if needed extend target table and/or selection
691 0 : aTarget.assignBoxes( aCopyStruct );
692 :
693 : {
694 : // Change table formulas into relative representation
695 0 : SwTableFormulaUpdate aMsgHint( &rCpyTable );
696 0 : aMsgHint.eFlags = TBL_RELBOXNAME;
697 0 : pCpyDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
698 : }
699 :
700 : // delete frames
701 0 : aFndBox.SetTableLines( *this );
702 0 : if( bClear )
703 0 : aFndBox.ClearLineBehind();
704 0 : aFndBox.DelFrms( *this );
705 :
706 : // copy boxes
707 0 : aTarget.copyBoxes( rCpyTable, *this, pUndo );
708 :
709 : // adjust row span attributes accordingly
710 :
711 : // make frames
712 0 : aFndBox.MakeFrms( *this );
713 :
714 0 : return true;
715 : }
716 :
717 : /** Copy Table into this Box.
718 : Copy all Boxes of a Line into the corresponding Boxes. The old content is
719 : deleted by doing this.
720 : If no Box is left the remaining content goes to the Box of a "BaseLine".
721 : If there's no Line anymore, put it also into the last Box of a "BaseLine". */
722 0 : bool SwTable::InsTable( const SwTable& rCpyTable, const SwNodeIndex& rSttBox,
723 : SwUndoTableCpyTable* pUndo )
724 : {
725 0 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
726 :
727 0 : SwDoc* pDoc = GetFrameFormat()->GetDoc();
728 :
729 0 : SwTableNode* pTableNd = pDoc->IsIdxInTable( rSttBox );
730 :
731 : // Find the Box, to which should be copied:
732 : SwTableBox* pMyBox = GetTableBox(
733 0 : rSttBox.GetNode().FindTableBoxStartNode()->GetIndex() );
734 :
735 : OSL_ENSURE( pMyBox, "Index is not in a Box in this Table" );
736 :
737 : // First delete the Table's Frames
738 0 : _FndBox aFndBox( 0, 0 );
739 0 : aFndBox.DelFrms( pTableNd->GetTable() );
740 :
741 0 : SwDoc* pCpyDoc = rCpyTable.GetFrameFormat()->GetDoc();
742 :
743 : {
744 : // Convert Table formulas to their relative representation
745 0 : SwTableFormulaUpdate aMsgHint( &rCpyTable );
746 0 : aMsgHint.eFlags = TBL_RELBOXNAME;
747 0 : pCpyDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
748 : }
749 :
750 0 : SwTableNumFormatMerge aTNFM( *pCpyDoc, *pDoc );
751 :
752 0 : bool bDelContent = true;
753 : const SwTableBox* pTmp;
754 :
755 0 : for( auto pLine : rCpyTable.GetTabLines() )
756 : {
757 : // Get the first from the CopyLine
758 0 : const SwTableBox* pCpyBox = pLine->GetTabBoxes().front();
759 0 : while( !pCpyBox->GetTabLines().empty() )
760 0 : pCpyBox = pCpyBox->GetTabLines().front()->GetTabBoxes().front();
761 :
762 : do {
763 : // First copy the new content and then delete the old one.
764 : // Do not create empty Sections, otherwise they will be deleted!
765 0 : lcl_CpyBox( rCpyTable, pCpyBox, *this, pMyBox, bDelContent, pUndo );
766 :
767 0 : if( 0 == (pTmp = pCpyBox->FindNextBox( rCpyTable, pCpyBox, false )))
768 0 : break; // no more Boxes
769 0 : pCpyBox = pTmp;
770 :
771 0 : if( 0 == ( pTmp = pMyBox->FindNextBox( *this, pMyBox, false )))
772 0 : bDelContent = false; // No space left?
773 : else
774 0 : pMyBox = const_cast<SwTableBox*>(pTmp);
775 :
776 : } while( true );
777 :
778 : // Find the topmost Line
779 0 : SwTableLine* pNxtLine = pMyBox->GetUpper();
780 0 : while( pNxtLine->GetUpper() )
781 0 : pNxtLine = pNxtLine->GetUpper()->GetUpper();
782 0 : const SwTableLines::size_type nPos = GetTabLines().GetPos( pNxtLine ) + 1;
783 : // Is there a next?
784 0 : if( nPos >= GetTabLines().size() )
785 0 : bDelContent = false; // there is none, all goes into the last Box
786 : else
787 : {
788 : // Find the next Box with content
789 0 : pNxtLine = GetTabLines()[ nPos ];
790 0 : pMyBox = pNxtLine->GetTabBoxes().front();
791 0 : while( !pMyBox->GetTabLines().empty() )
792 0 : pMyBox = pMyBox->GetTabLines().front()->GetTabBoxes().front();
793 0 : bDelContent = true;
794 : }
795 0 : }
796 :
797 0 : aFndBox.MakeFrms( pTableNd->GetTable() ); // Create the Frames anew
798 0 : return true;
799 : }
800 :
801 0 : bool SwTable::InsTable( const SwTable& rCpyTable, const SwSelBoxes& rSelBoxes,
802 : SwUndoTableCpyTable* pUndo )
803 : {
804 : OSL_ENSURE( !rSelBoxes.empty(), "Missing selection" );
805 :
806 0 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
807 :
808 0 : if( IsNewModel() || rCpyTable.IsNewModel() )
809 0 : return InsNewTable( rCpyTable, rSelBoxes, pUndo );
810 :
811 : OSL_ENSURE( !rCpyTable.IsTableComplex(), "Table too complex" );
812 :
813 0 : SwDoc* pDoc = GetFrameFormat()->GetDoc();
814 0 : SwDoc* pCpyDoc = rCpyTable.GetFrameFormat()->GetDoc();
815 :
816 0 : SwTableNumFormatMerge aTNFM( *pCpyDoc, *pDoc );
817 :
818 0 : SwTableBox *pSttBox = rSelBoxes[0];
819 :
820 0 : _FndLine *pFLine, *pInsFLine = 0;
821 0 : _FndBox aFndBox( 0, 0 );
822 : // Find all Boxes/Lines
823 : {
824 0 : _FndPara aPara( rSelBoxes, &aFndBox );
825 0 : ForEach_FndLineCopyCol( GetTabLines(), &aPara );
826 : }
827 :
828 : // Special case: If a Box is located in a Table, copy it to all selected
829 : // Boxes!
830 0 : if( 1 != rCpyTable.GetTabSortBoxes().size() )
831 : {
832 : _FndBox* pFndBox;
833 :
834 0 : const _FndLines::size_type nFndCnt = aFndBox.GetLines().size();
835 0 : if( !nFndCnt )
836 0 : return false;
837 :
838 : // Check if we have enough space for all Lines and Boxes
839 0 : SwTableLines::size_type nTstLns = 0;
840 0 : pFLine = &aFndBox.GetLines().front();
841 0 : sal_uInt16 nSttLine = GetTabLines().GetPos( pFLine->GetLine() );
842 : // Do we have as many rows, actually?
843 0 : if( 1 == nFndCnt )
844 : {
845 : // Is there still enough space in the Table?
846 0 : if( (GetTabLines().size() - nSttLine ) <
847 0 : rCpyTable.GetTabLines().size() )
848 : {
849 : // If we don't have enough Lines, then see if we can insert
850 : // new ones to reach our goal. But only if the SSelection
851 : // contains a Box!
852 0 : if( 1 < rSelBoxes.size() )
853 0 : return false;
854 :
855 0 : const sal_uInt16 nNewLns = rCpyTable.GetTabLines().size() -
856 0 : (GetTabLines().size() - nSttLine );
857 :
858 : // See if the Box count is high enough for the Lines
859 0 : SwTableLine* pLastLn = GetTabLines().back();
860 :
861 0 : pSttBox = pFLine->GetBoxes()[0].GetBox();
862 0 : const SwTableBoxes::size_type nSttBox = pFLine->GetLine()->GetTabBoxes().GetPos( pSttBox );
863 0 : for( SwTableLines::size_type n = rCpyTable.GetTabLines().size() - nNewLns;
864 0 : n < rCpyTable.GetTabLines().size(); ++n )
865 : {
866 0 : SwTableLine* pCpyLn = rCpyTable.GetTabLines()[ n ];
867 :
868 0 : if( pLastLn->GetTabBoxes().size() < nSttBox ||
869 0 : ( pLastLn->GetTabBoxes().size() - nSttBox ) <
870 0 : pCpyLn->GetTabBoxes().size() )
871 0 : return false;
872 :
873 : // Test for nesting
874 0 : for( SwTableBoxes::size_type nBx = 0; nBx < pCpyLn->GetTabBoxes().size(); ++nBx )
875 0 : if( !pLastLn->GetTabBoxes()[ nSttBox + nBx ]->GetSttNd() )
876 0 : return false;
877 : }
878 : // We have enough space for the to-be-copied, so insert new
879 : // rows accordingly.
880 0 : SwTableBox* pInsBox = pLastLn->GetTabBoxes()[ nSttBox ];
881 : OSL_ENSURE( pInsBox && pInsBox->GetSttNd(),
882 : "no ContentBox or it's not in this Table" );
883 0 : SwSelBoxes aBoxes;
884 :
885 0 : if( pUndo
886 : ? !pUndo->InsertRow( *this, SelLineFromBox( pInsBox,
887 0 : aBoxes, true ), nNewLns )
888 : : !InsertRow( pDoc, SelLineFromBox( pInsBox,
889 0 : aBoxes, true ), nNewLns, true ) )
890 0 : return false;
891 : }
892 :
893 0 : nTstLns = rCpyTable.GetTabLines().size(); // copy this many
894 : }
895 0 : else if( 0 == (nFndCnt % rCpyTable.GetTabLines().size()) )
896 0 : nTstLns = nFndCnt;
897 : else
898 0 : return false; // not enough space for the rows
899 :
900 0 : for( SwTableLines::size_type nLn = 0; nLn < nTstLns; ++nLn )
901 : {
902 : // We have enough rows, so check the Boxes per row
903 0 : pFLine = &aFndBox.GetLines()[ nLn % nFndCnt ];
904 0 : SwTableLine* pLine = pFLine->GetLine();
905 0 : pSttBox = pFLine->GetBoxes()[0].GetBox();
906 0 : const SwTableBoxes::size_type nSttBox = pLine->GetTabBoxes().GetPos( pSttBox );
907 0 : if( nLn >= nFndCnt )
908 : {
909 : // We have more rows in the ClipBoard than we have selected
910 0 : pInsFLine = new _FndLine( GetTabLines()[ nSttLine + nLn ],
911 0 : &aFndBox );
912 0 : pLine = pInsFLine->GetLine();
913 : }
914 0 : SwTableLine* pCpyLn = rCpyTable.GetTabLines()[ nLn %
915 0 : rCpyTable.GetTabLines().size() ];
916 :
917 : // Selected too few rows?
918 0 : if( pInsFLine )
919 : {
920 : // We insert a new row into the FndBox
921 0 : if( pLine->GetTabBoxes().size() < nSttBox ||
922 0 : pLine->GetTabBoxes().size() - nSttBox < pFLine->GetBoxes().size() )
923 : {
924 0 : delete pInsFLine;
925 0 : return false;
926 : }
927 :
928 : // Test for nesting
929 0 : for( _FndBoxes::size_type nBx = 0; nBx < pFLine->GetBoxes().size(); ++nBx )
930 : {
931 0 : SwTableBox *pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ];
932 0 : if( !pTmpBox->GetSttNd() )
933 : {
934 0 : delete pInsFLine;
935 0 : return false;
936 : }
937 : // if Ok, insert the Box into the FndLine
938 0 : pFndBox = new _FndBox( pTmpBox, pInsFLine );
939 0 : pInsFLine->GetBoxes().insert( pInsFLine->GetBoxes().begin() + nBx, pFndBox );
940 : }
941 0 : aFndBox.GetLines().insert( aFndBox.GetLines().begin() + nLn, pInsFLine );
942 : }
943 0 : else if( pFLine->GetBoxes().size() == 1 )
944 : {
945 0 : if( pLine->GetTabBoxes().size() < nSttBox ||
946 0 : ( pLine->GetTabBoxes().size() - nSttBox ) <
947 0 : pCpyLn->GetTabBoxes().size() )
948 0 : return false;
949 :
950 : // Test for nesting
951 0 : for( SwTableBoxes::size_type nBx = 0; nBx < pCpyLn->GetTabBoxes().size(); ++nBx )
952 : {
953 0 : SwTableBox *pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ];
954 0 : if( !pTmpBox->GetSttNd() )
955 0 : return false;
956 : // if Ok, insert the Box into the FndLine
957 0 : if( nBx == pFLine->GetBoxes().size() )
958 : {
959 0 : pFndBox = new _FndBox( pTmpBox, pFLine );
960 0 : pFLine->GetBoxes().insert( pFLine->GetBoxes().begin() + nBx, pFndBox );
961 : }
962 : }
963 : }
964 : else
965 : {
966 : // Match the selected Boxes with the ones in the Clipboard
967 : // (n times)
968 0 : if( 0 != ( pFLine->GetBoxes().size() %
969 0 : pCpyLn->GetTabBoxes().size() ))
970 0 : return false;
971 :
972 : // Test for nesting
973 0 : for( auto &rBox : pFLine->GetBoxes() )
974 0 : if (!rBox.GetBox()->GetSttNd())
975 0 : return false;
976 : }
977 : }
978 :
979 0 : if( aFndBox.GetLines().empty() )
980 0 : return false;
981 : }
982 :
983 : {
984 : // Convert Table formulas to their relative representation
985 0 : SwTableFormulaUpdate aMsgHint( &rCpyTable );
986 0 : aMsgHint.eFlags = TBL_RELBOXNAME;
987 0 : pCpyDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
988 : }
989 :
990 : // Delete the Frames
991 0 : aFndBox.SetTableLines( *this );
992 : //Not dispose accessible table
993 0 : aFndBox.DelFrms( *this,false );
994 :
995 0 : if( 1 == rCpyTable.GetTabSortBoxes().size() )
996 : {
997 0 : SwTableBox *pTmpBx = rCpyTable.GetTabSortBoxes()[0];
998 0 : for (size_t n = 0; n < rSelBoxes.size(); ++n)
999 : {
1000 : lcl_CpyBox( rCpyTable, pTmpBx, *this,
1001 0 : rSelBoxes[n], true, pUndo );
1002 : }
1003 : }
1004 : else
1005 0 : for( _FndLines::size_type nLn = 0; nLn < aFndBox.GetLines().size(); ++nLn )
1006 : {
1007 0 : pFLine = &aFndBox.GetLines()[ nLn ];
1008 0 : SwTableLine* pCpyLn = rCpyTable.GetTabLines()[
1009 0 : nLn % rCpyTable.GetTabLines().size() ];
1010 0 : for( _FndBoxes::size_type nBx = 0; nBx < pFLine->GetBoxes().size(); ++nBx )
1011 : {
1012 : // Copy the pCpyBox into pMyBox
1013 0 : lcl_CpyBox( rCpyTable, pCpyLn->GetTabBoxes()[
1014 0 : nBx % pCpyLn->GetTabBoxes().size() ],
1015 0 : *this, pFLine->GetBoxes()[nBx].GetBox(), true, pUndo );
1016 : }
1017 : }
1018 :
1019 0 : aFndBox.MakeFrms( *this );
1020 0 : return true;
1021 : }
1022 :
1023 : static void _FndContentLine( const SwTableLine* pLine, SwSelBoxes* pPara );
1024 :
1025 0 : static void _FndContentBox( const SwTableBox* pBox, SwSelBoxes* pPara )
1026 : {
1027 0 : if( !pBox->GetTabLines().empty() )
1028 : {
1029 0 : for( const SwTableLine* pLine : pBox->GetTabLines() )
1030 0 : _FndContentLine( pLine, pPara );
1031 : }
1032 : else
1033 0 : pPara->insert( const_cast<SwTableBox*>(pBox) );
1034 0 : }
1035 :
1036 0 : static void _FndContentLine( const SwTableLine* pLine, SwSelBoxes* pPara )
1037 : {
1038 0 : for( const SwTableBox* pBox : pLine->GetTabBoxes() )
1039 0 : _FndContentBox(pBox, pPara );
1040 0 : }
1041 :
1042 : // Find all Boxes with content in this Box
1043 0 : SwSelBoxes& SwTable::SelLineFromBox( const SwTableBox* pBox,
1044 : SwSelBoxes& rBoxes, bool bToTop )
1045 : {
1046 0 : SwTableLine* pLine = const_cast<SwTableLine*>(pBox->GetUpper());
1047 0 : if( bToTop )
1048 0 : while( pLine->GetUpper() )
1049 0 : pLine = pLine->GetUpper()->GetUpper();
1050 :
1051 : // Delete all old ones
1052 0 : rBoxes.clear();
1053 0 : for( SwTableBoxes::iterator it = pLine->GetTabBoxes().begin();
1054 0 : it != pLine->GetTabBoxes().end(); ++it)
1055 0 : _FndContentBox(*it, &rBoxes );
1056 0 : return rBoxes;
1057 177 : }
1058 :
1059 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|