LibreOffice Module sw (master) 1
tblrwcl.cxx
Go to the documentation of this file.
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 <memory>
21#include <com/sun/star/text/HoriOrientation.hpp>
22#include <osl/diagnose.h>
23#include <svl/numformat.hxx>
24#include <hintids.hxx>
25
26#include <editeng/lrspitem.hxx>
27#include <editeng/boxitem.hxx>
28#include <tools/fract.hxx>
29#include <fmtfsize.hxx>
30#include <fmtornt.hxx>
31#include <doc.hxx>
38#include <docsh.hxx>
39#include <fesh.hxx>
40#include <tabfrm.hxx>
41#include <frmatr.hxx>
42#include <frmtool.hxx>
43#include <pam.hxx>
44#include <swtable.hxx>
45#include <tblsel.hxx>
46#include <fldbas.hxx>
47#include <rowfrm.hxx>
48#include <ddefld.hxx>
49#include <hints.hxx>
50#include <UndoTable.hxx>
51#include <cellatr.hxx>
52#include <mvsave.hxx>
53#include <swtblfmt.hxx>
54#include <swddetbl.hxx>
55#include <poolfmt.hxx>
56#include <tblrwcl.hxx>
57#include <unochart.hxx>
58#include <o3tl/numeric.hxx>
59#include <calbck.hxx>
60#include <docary.hxx>
61
62using namespace com::sun::star;
63using namespace com::sun::star::uno;
64
65#define COLFUZZY 20
66#define ROWFUZZY 10
67
68#ifdef DBG_UTIL
69#define CHECK_TABLE(t) (t).CheckConsistency();
70#else
71#define CHECK_TABLE(t)
72#endif
73
74namespace {
75
76// In order to set the Frame Formats for the Boxes, it's enough to look
77// up the current one in the array. If it's already there return the new one.
78struct CpyTabFrame
79{
80 SwFrameFormat* pFrameFormat;
81 SwTableBoxFormat *pNewFrameFormat;
82
83 explicit CpyTabFrame(SwFrameFormat* pCurrentFrameFormat) : pNewFrameFormat( nullptr )
84 { pFrameFormat = pCurrentFrameFormat; }
85
86 bool operator==( const CpyTabFrame& rCpyTabFrame ) const
87 { return pFrameFormat == rCpyTabFrame.pFrameFormat; }
88 bool operator<( const CpyTabFrame& rCpyTabFrame ) const
89 { return pFrameFormat < rCpyTabFrame.pFrameFormat; }
90};
91
92struct CR_SetBoxWidth
93{
94 SwShareBoxFormats aShareFormats;
95 SwTableNode* pTableNd;
96 SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
97 TableChgMode nMode;
98 bool bBigger, bLeft;
99
100 CR_SetBoxWidth( TableChgWidthHeightType eType, SwTwips nDif, SwTwips nSid,
101 SwTwips nMax, SwTableNode* pTNd )
102 : pTableNd( pTNd ),
103 nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 )
104 {
108 nMode = pTableNd->GetTable().GetTableChgMode();
109 }
110 CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
111 : pTableNd( rCpy.pTableNd ),
112 nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
113 nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
114 nMode( rCpy.nMode ),
115 bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft )
116 {
117 }
118
119 void LoopClear()
120 {
121 nLowerDiff = 0;
122 }
123};
124
125}
126
127static bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
128 SwTwips nDist, bool bCheck );
129static bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
130 SwTwips nDist, bool bCheck );
131
132typedef bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, bool );
133
134#ifdef DBG_UTIL
135
136#define CHECKBOXWIDTH \
137 { \
138 SwTwips nSize = GetFrameFormat()->GetFrameSize().GetWidth(); \
139 for (size_t nTmp = 0; nTmp < m_aLines.size(); ++nTmp) \
140 ::CheckBoxWidth( *m_aLines[ nTmp ], nSize ); \
141 }
142
143#define CHECKTABLELAYOUT \
144 { \
145 for ( size_t i = 0; i < GetTabLines().size(); ++i ) \
146 { \
147 SwFrameFormat* pFormat = GetTabLines()[i]->GetFrameFormat(); \
148 SwIterator<SwRowFrame,SwFormat> aIter( *pFormat ); \
149 for (SwRowFrame* pFrame=aIter.First(); pFrame; pFrame=aIter.Next())\
150 { \
151 if ( pFrame->GetTabLine() == GetTabLines()[i] ) \
152 { \
153 OSL_ENSURE( pFrame->GetUpper()->IsTabFrame(), \
154 "Table layout does not match table structure" ); \
155 } \
156 } \
157 } \
158 }
159
160#else
161
162#define CHECKBOXWIDTH
163#define CHECKTABLELAYOUT
164
165#endif // DBG_UTIL
166
167namespace {
168
169struct CR_SetLineHeight
170{
171 SwTableNode* pTableNd;
172 SwTwips nMaxSpace, nMaxHeight;
173 TableChgMode nMode;
174 bool bBigger;
175
176 CR_SetLineHeight( TableChgWidthHeightType eType, SwTableNode* pTNd )
177 : pTableNd( pTNd ),
178 nMaxSpace( 0 ), nMaxHeight( 0 )
179 {
181 nMode = pTableNd->GetTable().GetTableChgMode();
182 }
183 CR_SetLineHeight( const CR_SetLineHeight& rCpy )
184 : pTableNd( rCpy.pTableNd ),
185 nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
186 nMode( rCpy.nMode ),
187 bBigger( rCpy.bBigger )
188 {}
189};
190
191}
192
193static bool lcl_SetSelLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
194 SwTwips nDist, bool bCheck );
195static bool lcl_SetOtherLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
196 SwTwips nDist, bool bCheck );
197
198typedef bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, bool );
199
201
202namespace {
203
204struct CpyPara
205{
206 std::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths;
207 SwDoc& rDoc;
208 SwTableNode* pTableNd;
209 CpyTabFrames& rTabFrameArr;
210 SwTableLine* pInsLine;
211 SwTableBox* pInsBox;
212 sal_uLong nOldSize, nNewSize; // in order to correct the size attributes
213 sal_uLong nMinLeft, nMaxRight;
214 sal_uInt16 nCpyCnt, nInsPos;
215 sal_uInt16 nLnIdx, nBoxIdx;
216 sal_uInt8 nDelBorderFlag;
217 bool bCpyContent;
218
219 CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, CpyTabFrames& rFrameArr )
220 : rDoc( pNd->GetDoc() ), pTableNd( pNd ), rTabFrameArr(rFrameArr),
221 pInsLine(nullptr), pInsBox(nullptr), nOldSize(0), nNewSize(0),
222 nMinLeft(ULONG_MAX), nMaxRight(0),
223 nCpyCnt(nCopies), nInsPos(0),
224 nLnIdx(0), nBoxIdx(0),
225 nDelBorderFlag(0), bCpyContent( true )
226 {}
227 CpyPara( const CpyPara& rPara, SwTableLine* pLine )
228 : pWidths( rPara.pWidths ), rDoc(rPara.rDoc), pTableNd(rPara.pTableNd),
229 rTabFrameArr(rPara.rTabFrameArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
230 nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
231 nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
232 nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
233 nDelBorderFlag( rPara.nDelBorderFlag ), bCpyContent( rPara.bCpyContent )
234 {}
235 CpyPara( const CpyPara& rPara, SwTableBox* pBox )
236 : pWidths( rPara.pWidths ), rDoc(rPara.rDoc), pTableNd(rPara.pTableNd),
237 rTabFrameArr(rPara.rTabFrameArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
238 nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
239 nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
240 nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
241 nDelBorderFlag( rPara.nDelBorderFlag ), bCpyContent( rPara.bCpyContent )
242 {}
243};
244
245}
246
247static SwTableLine* lcl_CopyRow(FndLine_ & rFndLine, CpyPara *const pCpyPara);
248
249static void lcl_CopyCol( FndBox_ & rFndBox, CpyPara *const pCpyPara)
250{
251 // Look up the Frame Format in the Frame Format Array
252 SwTableBox* pBox = rFndBox.GetBox();
253 CpyTabFrame aFindFrame(pBox->GetFrameFormat());
254
255 if( pCpyPara->nCpyCnt )
256 {
257 sal_uInt16 nFndPos;
258 CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.lower_bound( aFindFrame );
259 nFndPos = itFind - pCpyPara->rTabFrameArr.begin();
260 if( itFind == pCpyPara->rTabFrameArr.end() || !(*itFind == aFindFrame) )
261 {
262 // For nested copying, also save the new Format as an old one.
263 SwTableBoxFormat* pNewFormat = static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat());
264
265 // Find the selected Boxes in the Line:
266 FndLine_ const* pCmpLine = nullptr;
267 SwFormatFrameSize aFrameSz( pNewFormat->GetFrameSize() );
268
269 bool bDiffCount = false;
270 if( !pBox->GetTabLines().empty() )
271 {
272 pCmpLine = rFndBox.GetLines().front().get();
273 if ( pCmpLine->GetBoxes().size() != pCmpLine->GetLine()->GetTabBoxes().size() )
274 bDiffCount = true;
275 }
276
277 if( bDiffCount )
278 {
279 // The first Line should be enough
280 FndBoxes_t const& rFndBoxes = pCmpLine->GetBoxes();
281 tools::Long nSz = 0;
282 for( auto n = rFndBoxes.size(); n; )
283 {
284 nSz += rFndBoxes[--n]->GetBox()->
285 GetFrameFormat()->GetFrameSize().GetWidth();
286 }
287 aFrameSz.SetWidth( aFrameSz.GetWidth() -
288 nSz / ( pCpyPara->nCpyCnt + 1 ) );
289 pNewFormat->SetFormatAttr( aFrameSz );
290 aFrameSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
291
292 // Create a new Format for the new Box, specifying its size.
293 aFindFrame.pNewFrameFormat = reinterpret_cast<SwTableBoxFormat*>(pNewFormat->GetDoc()->
294 MakeTableLineFormat());
295 *aFindFrame.pNewFrameFormat = *pNewFormat;
296 aFindFrame.pNewFrameFormat->SetFormatAttr( aFrameSz );
297 }
298 else
299 {
300 aFrameSz.SetWidth( aFrameSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
301 pNewFormat->SetFormatAttr( aFrameSz );
302
303 aFindFrame.pNewFrameFormat = pNewFormat;
304 pCpyPara->rTabFrameArr.insert( aFindFrame );
305 aFindFrame.pFrameFormat = pNewFormat;
306 pCpyPara->rTabFrameArr.insert( aFindFrame );
307 }
308 }
309 else
310 {
311 aFindFrame = pCpyPara->rTabFrameArr[ nFndPos ];
312 pBox->ChgFrameFormat( aFindFrame.pNewFrameFormat );
313 }
314 }
315 else
316 {
317 CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.find( aFindFrame );
318 if( pCpyPara->nDelBorderFlag &&
319 itFind != pCpyPara->rTabFrameArr.end() )
320 aFindFrame = *itFind;
321 else
322 aFindFrame.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
323 }
324
325 if (!rFndBox.GetLines().empty())
326 {
327 pBox = new SwTableBox( aFindFrame.pNewFrameFormat,
328 rFndBox.GetLines().size(), pCpyPara->pInsLine );
329 pCpyPara->pInsLine->GetTabBoxes().insert( pCpyPara->pInsLine->GetTabBoxes().begin() + pCpyPara->nInsPos++, pBox );
330 CpyPara aPara( *pCpyPara, pBox );
331 aPara.nDelBorderFlag &= 7;
332
333 for (auto const& pFndLine : rFndBox.GetLines())
334 {
335 lcl_CopyRow(*pFndLine, &aPara);
336 }
337 }
338 else
339 {
340 ::InsTableBox( pCpyPara->rDoc, pCpyPara->pTableNd, pCpyPara->pInsLine,
341 aFindFrame.pNewFrameFormat, pBox, pCpyPara->nInsPos++ );
342
343 const FndBoxes_t& rFndBxs = rFndBox.GetUpper()->GetBoxes();
344 if( 8 > pCpyPara->nDelBorderFlag
345 ? pCpyPara->nDelBorderFlag != 0
346 : &rFndBox == rFndBxs[rFndBxs.size() - 1].get())
347 {
348 const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
349 if( 8 > pCpyPara->nDelBorderFlag
350 ? rBoxItem.GetTop()
351 : rBoxItem.GetRight() )
352 {
353 aFindFrame.pFrameFormat = pBox->GetFrameFormat();
354
355 SvxBoxItem aNew( rBoxItem );
356 if( 8 > pCpyPara->nDelBorderFlag )
357 aNew.SetLine( nullptr, SvxBoxItemLine::TOP );
358 else
359 aNew.SetLine( nullptr, SvxBoxItemLine::RIGHT );
360
361 if( 1 == pCpyPara->nDelBorderFlag ||
362 8 == pCpyPara->nDelBorderFlag )
363 {
364 // For all Boxes that delete TopBorderLine, we copy after that
365 pBox = pCpyPara->pInsLine->GetTabBoxes()[
366 pCpyPara->nInsPos - 1 ];
367 }
368
369 aFindFrame.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
370
371 // Else we copy before that and the first Line keeps the TopLine
372 // and we remove it at the original
373 pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
374
375 if( !pCpyPara->nCpyCnt )
376 pCpyPara->rTabFrameArr.insert( aFindFrame );
377 }
378 }
379 }
380}
381
382static SwTableLine* lcl_CopyRow(FndLine_& rFndLine, CpyPara *const pCpyPara)
383{
384 SwTableLine* pNewLine = new SwTableLine(
385 static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()),
386 rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
387 if( pCpyPara->pInsBox )
388 {
389 SwTableLines& rLines = pCpyPara->pInsBox->GetTabLines();
390 rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
391 }
392 else
393 {
394 SwTableLines& rLines = pCpyPara->pTableNd->GetTable().GetTabLines();
395 rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
396 }
397
398 CpyPara aPara( *pCpyPara, pNewLine );
399 for (auto const& it : rFndLine.GetBoxes())
400 {
401 lcl_CopyCol(*it, &aPara);
402 }
403
404 pCpyPara->nDelBorderFlag &= 0xf8;
405
406 return pNewLine;
407}
408
409static void lcl_InsCol( FndLine_* pFndLn, CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
410 bool bBehind )
411{
412 // Bug 29124: Not only copy in the BaseLines. If possible, we go down as far as possible
413 FndBox_* pFBox;
414 if( 1 == pFndLn->GetBoxes().size() &&
415 !( pFBox = pFndLn->GetBoxes()[0].get() )->GetBox()->GetSttNd() )
416 {
417 // A Box with multiple Lines, so insert into these Lines
418 for (auto &rpLine : pFBox->GetLines())
419 {
420 lcl_InsCol( rpLine.get(), rCpyPara, nCpyCnt, bBehind );
421 }
422 }
423 else
424 {
425 rCpyPara.pInsLine = pFndLn->GetLine();
426 SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
427 pFndLn->GetBoxes().size()-1 : 0 ]->GetBox();
428 rCpyPara.nInsPos = pFndLn->GetLine()->GetBoxPos( pBox );
429 if( bBehind )
430 ++rCpyPara.nInsPos;
431
432 for( sal_uInt16 n = 0; n < nCpyCnt; ++n )
433 {
434 if( n + 1 == nCpyCnt && bBehind )
435 rCpyPara.nDelBorderFlag = 9;
436 else
437 rCpyPara.nDelBorderFlag = 8;
438 for (auto const& it : pFndLn->GetBoxes())
439 {
440 lcl_CopyCol(*it, &rCpyPara);
441 }
442 }
443 }
444}
445
447{
449 for( SwRowFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
450 if( pFrame->GetTabLine() == &rLine )
451 return pFrame;
452 return nullptr;
453}
454
455bool SwTable::InsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
456{
457 OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid Box List" );
458 SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
459 if( !pTableNd )
460 return false;
461
462 bool bRes = true;
463 if( IsNewModel() )
464 bRes = NewInsertCol( rDoc, rBoxes, nCnt, bBehind );
465 else
466 {
467 // Find all Boxes/Lines
468 FndBox_ aFndBox( nullptr, nullptr );
469 {
470 FndPara aPara( rBoxes, &aFndBox );
472 }
473 if( aFndBox.GetLines().empty() )
474 return false;
475
476 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
477
478 // Find Lines for the layout update
479 aFndBox.SetTableLines( *this );
480 aFndBox.DelFrames( *this );
481
482 // TL_CHART2: nothing to be done since chart2 currently does not want to
483 // get notified about new rows/cols.
484
485 CpyTabFrames aTabFrameArr;
486 CpyPara aCpyPara( pTableNd, nCnt, aTabFrameArr );
487
488 for (auto & rpLine : aFndBox.GetLines())
489 {
490 lcl_InsCol( rpLine.get(), aCpyPara, nCnt, bBehind );
491 }
492
493 // clean up this Line's structure once again, generally all of them
494 GCLines();
495
496 // Update Layout
497 aFndBox.MakeFrames( *this );
498
501 bRes = true;
502 }
503
505 if (pPCD && nCnt)
506 pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
508
510
511 return bRes;
512}
513
514bool SwTable::InsertRow_( SwDoc* pDoc, const SwSelBoxes& rBoxes,
515 sal_uInt16 nCnt, bool bBehind )
516{
517 OSL_ENSURE( pDoc && !rBoxes.empty() && nCnt, "No valid Box List" );
518 SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
519 if( !pTableNd )
520 return false;
521
522 // Find all Boxes/Lines
523 FndBox_ aFndBox( nullptr, nullptr );
524 {
525 FndPara aPara( rBoxes, &aFndBox );
527 }
528 if( aFndBox.GetLines().empty() )
529 return false;
530
531 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
532
533 FndBox_* pFndBox = &aFndBox;
534 {
535 FndLine_* pFndLine;
536 while( 1 == pFndBox->GetLines().size() )
537 {
538 pFndLine = pFndBox->GetLines()[0].get();
539 if( 1 != pFndLine->GetBoxes().size() )
540 break;
541 // Don't go down too far! One Line with Box needs to remain!
542 FndBox_ *const pTmpBox = pFndLine->GetBoxes().front().get();
543 if( !pTmpBox->GetLines().empty() )
544 pFndBox = pTmpBox;
545 else
546 break;
547 }
548 }
549
550 // Find Lines for the layout update
551 const bool bLayout = !IsNewModel() &&
553
554 if ( bLayout )
555 {
556 aFndBox.SetTableLines( *this );
557 if( pFndBox != &aFndBox )
558 aFndBox.DelFrames( *this );
559 // TL_CHART2: nothing to be done since chart2 currently does not want to
560 // get notified about new rows/cols.
561 }
562
563 CpyTabFrames aTabFrameArr;
564 CpyPara aCpyPara( pTableNd, 0, aTabFrameArr );
565
566 SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
567 pFndBox->GetLines().size()-1 : 0 ]->GetLine();
568 if( &aFndBox == pFndBox )
569 aCpyPara.nInsPos = GetTabLines().GetPos( pLine );
570 else
571 {
572 aCpyPara.pInsBox = pFndBox->GetBox();
573 aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().GetPos( pLine );
574 }
575
576 if( bBehind )
577 {
578 ++aCpyPara.nInsPos;
579 aCpyPara.nDelBorderFlag = 1;
580 }
581 else
582 aCpyPara.nDelBorderFlag = 2;
583
584 for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
585 {
586 if( bBehind )
587 aCpyPara.nDelBorderFlag = 1;
588 for (auto & rpFndLine : pFndBox->GetLines())
589 {
590 SwTableLine* pNewTableLine = lcl_CopyRow( *rpFndLine, &aCpyPara );
591
592 // tracked insertion of empty table line
594 {
595 SvxPrintItem aSetTracking(RES_PRINT, false);
596 SwPosition aPos(*pNewTableLine->GetTabBoxes()[0]->GetSttNd());
597 SwCursor aCursor( aPos, nullptr );
598 SwPaM aPaM(*pNewTableLine->GetTabBoxes()[0]->GetSttNd(), SwNodeOffset(1));
600 OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
601 pDoc->SetRowNotTracked( aCursor, aSetTracking, /*bAll=*/false, /*bIns=*/true );
602 }
603 }
604 }
605
606 // clean up this Line's structure once again, generally all of them
607 if( !pDoc->IsInReading() )
608 GCLines();
609
610 // Update Layout
611 if ( bLayout )
612 {
613 if( pFndBox != &aFndBox )
614 aFndBox.MakeFrames( *this );
615 else
616 aFndBox.MakeNewFrames( *this, nCnt, bBehind );
617 }
618
621
623 if (pPCD && nCnt)
624 pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
625 pDoc->UpdateCharts( GetFrameFormat()->GetName() );
626
628
629 return true;
630}
631
632static void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const tools::Long nOffset,
633 bool bFirst, SwShareBoxFormats& rShareFormats );
634
635static void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const tools::Long nOffset,
636 bool bFirst, SwShareBoxFormats& rShareFormats )
637{
638 for ( auto pLine : rLines )
639 ::lcl_LastBoxSetWidth( pLine->GetTabBoxes(), nOffset, bFirst, rShareFormats );
640}
641
642static void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const tools::Long nOffset,
643 bool bFirst, SwShareBoxFormats& rShareFormats )
644{
645 SwTableBox& rBox = *(bFirst ? rBoxes.front() : rBoxes.back());
646 if( !rBox.GetSttNd() )
647 ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
648 bFirst, rShareFormats );
649
650 // Adapt the Box
651 const SwFrameFormat *pBoxFormat = rBox.GetFrameFormat();
652 SwFormatFrameSize aNew( pBoxFormat->GetFrameSize() );
653 aNew.SetWidth( aNew.GetWidth() + nOffset );
654 SwFrameFormat *pFormat = rShareFormats.GetFormat( *pBoxFormat, aNew );
655 if( pFormat )
656 rBox.ChgFrameFormat( static_cast<SwTableBoxFormat*>(pFormat) );
657 else
658 {
659 pFormat = rBox.ClaimFrameFormat();
660
661 pFormat->LockModify();
662 pFormat->SetFormatAttr( aNew );
663 pFormat->UnlockModify();
664
665 rShareFormats.AddFormat( *pBoxFormat, *pFormat );
666 }
667}
668
669void DeleteBox_( SwTable& rTable, SwTableBox* pBox, SwUndo* pUndo,
670 bool bCalcNewSize, const bool bCorrBorder,
671 SwShareBoxFormats* pShareFormats )
672{
673 do {
674 SwTwips nBoxSz = bCalcNewSize ?
675 pBox->GetFrameFormat()->GetFrameSize().GetWidth() : 0;
676 SwTableLine* pLine = pBox->GetUpper();
677 SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
678 sal_uInt16 nDelPos = pLine->GetBoxPos( pBox );
679 SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
680
681 // Special treatment for the border:
682 if( bCorrBorder && 1 < rTableBoxes.size() )
683 {
684 const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
685
686 if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
687 {
688 bool bChgd = false;
689
690 // JP 02.04.97: 1st part for Bug 36271
691 // First the left/right edges
692 if( nDelPos + 1 < o3tl::narrowing<sal_uInt16>(rTableBoxes.size()) )
693 {
694 SwTableBox* pNxtBox = rTableBoxes[ nDelPos + 1 ];
695 const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrameFormat()->GetBox();
696
697 SwTableBox* pPrvBox = nDelPos ? rTableBoxes[ nDelPos - 1 ] : nullptr;
698
699 if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
700 ( !pPrvBox || !pPrvBox->GetFrameFormat()->GetBox().GetRight()) )
701 {
702 SvxBoxItem aTmp( rNxtBoxItem );
704 : rBoxItem.GetRight(),
705 SvxBoxItemLine::LEFT );
706 if( pShareFormats )
707 pShareFormats->SetAttr( *pNxtBox, aTmp );
708 else
709 pNxtBox->ClaimFrameFormat()->SetFormatAttr( aTmp );
710 bChgd = true;
711 }
712 }
713 if( !bChgd && nDelPos )
714 {
715 SwTableBox* pPrvBox = rTableBoxes[ nDelPos - 1 ];
716 const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrameFormat()->GetBox();
717
718 SwTableBox* pNxtBox = nDelPos + 1 < o3tl::narrowing<sal_uInt16>(rTableBoxes.size())
719 ? rTableBoxes[ nDelPos + 1 ] : nullptr;
720
721 if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
722 ( !pNxtBox || !pNxtBox->GetFrameFormat()->GetBox().GetLeft()) )
723 {
724 SvxBoxItem aTmp( rPrvBoxItem );
726 : rBoxItem.GetRight(),
727 SvxBoxItemLine::RIGHT );
728 if( pShareFormats )
729 pShareFormats->SetAttr( *pPrvBox, aTmp );
730 else
731 pPrvBox->ClaimFrameFormat()->SetFormatAttr( aTmp );
732 }
733 }
734 }
735 }
736
737 // Delete the Box first, then the Nodes!
738 SwStartNode* pSttNd = const_cast<SwStartNode*>(pBox->GetSttNd());
739 if( pShareFormats )
740 pShareFormats->RemoveFormat( *rTableBoxes[ nDelPos ]->GetFrameFormat() );
741
742 // Before deleting the 'Table Box' from memory - delete any redlines attached to it
743 rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableCellRedline( rTable.GetFrameFormat()->GetDoc(), *(rTableBoxes[nDelPos]), true, RedlineType::Any );
744 delete rTableBoxes[nDelPos];
745 rTableBoxes.erase( rTableBoxes.begin() + nDelPos );
746
747 if( pSttNd )
748 {
749 // Has the UndoObject been prepared to save the Section?
750 if( pUndo && pUndo->IsDelBox() )
751 static_cast<SwUndoTableNdsChg*>(pUndo)->SaveSection( pSttNd );
752 else
754 }
755
756 // Also delete the Line?
757 if( !rTableBoxes.empty() )
758 {
759 // Then adapt the Frame-SSize
760 bool bLastBox = nDelPos == rTableBoxes.size();
761 if( bLastBox )
762 --nDelPos;
763 pBox = rTableBoxes[nDelPos];
764 if( bCalcNewSize )
765 {
767 aNew.SetWidth( aNew.GetWidth() + nBoxSz );
768 if( pShareFormats )
769 pShareFormats->SetSize( *pBox, aNew );
770 else
771 pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
772
773 if( !pBox->GetSttNd() )
774 {
775 // We need to this recursively in all Lines in all Cells!
776 SwShareBoxFormats aShareFormats;
777 ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
778 !bLastBox,
779 pShareFormats ? *pShareFormats
780 : aShareFormats );
781 }
782 }
783 break; // Stop deleting
784 }
785 // Delete the Line from the Table/Box
786 if( !pUpperBox )
787 {
788 // Also delete the Line from the Table
789 nDelPos = rTable.GetTabLines().GetPos( pLine );
790 if( pShareFormats )
791 pShareFormats->RemoveFormat( *rTable.GetTabLines()[ nDelPos ]->GetFrameFormat() );
792
793 SwTableLine* pTabLineToDelete = rTable.GetTabLines()[ nDelPos ];
794 // Before deleting the 'Table Line' from memory - delete any redlines attached to it
795 rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableRowRedline( rTable.GetFrameFormat()->GetDoc(), *pTabLineToDelete, true, RedlineType::Any );
796 delete pTabLineToDelete;
797 rTable.GetTabLines().erase( rTable.GetTabLines().begin() + nDelPos );
798 break; // we cannot delete more
799 }
800
801 // finally also delete the Line
802 pBox = pUpperBox;
803 nDelPos = pBox->GetTabLines().GetPos( pLine );
804 if( pShareFormats )
805 pShareFormats->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrameFormat() );
806
807 SwTableLine* pTabLineToDelete = pBox->GetTabLines()[ nDelPos ];
808 // Before deleting the 'Table Line' from memory - delete any redlines attached to it
809 rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableRowRedline( rTable.GetFrameFormat()->GetDoc(), *pTabLineToDelete, true, RedlineType::Any );
810 delete pTabLineToDelete;
811 pBox->GetTabLines().erase( pBox->GetTabLines().begin() + nDelPos );
812 } while( pBox->GetTabLines().empty() );
813}
814
815static SwTableBox*
817 SwTwips nBoxStt, SwTwips nBoxWidth,
818 sal_uInt16 nLinePos, bool bNxt,
819 SwSelBoxes* pAllDelBoxes, size_t *const pCurPos)
820{
821 SwTableBox* pFndBox = nullptr;
822 do {
823 if( bNxt )
824 ++nLinePos;
825 else
826 --nLinePos;
827 SwTableLine* pLine = rTableLns[ nLinePos ];
828 SwTwips nFndBoxWidth = 0;
829 SwTwips nFndWidth = nBoxStt + nBoxWidth;
830
831 pFndBox = pLine->GetTabBoxes()[ 0 ];
832 for( auto pBox : pLine->GetTabBoxes() )
833 {
834 if ( nFndWidth <= 0 )
835 {
836 break;
837 }
838 pFndBox = pBox;
839 nFndBoxWidth = pFndBox->GetFrameFormat()->GetFrameSize().GetWidth();
840 nFndWidth -= nFndBoxWidth;
841 }
842
843 // Find the first ContentBox
844 while( !pFndBox->GetSttNd() )
845 {
846 const SwTableLines& rLowLns = pFndBox->GetTabLines();
847 if( bNxt )
848 pFndBox = rLowLns.front()->GetTabBoxes().front();
849 else
850 pFndBox = rLowLns.back()->GetTabBoxes().front();
851 }
852
853 if( std::abs( nFndWidth ) > COLFUZZY ||
854 std::abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
855 pFndBox = nullptr;
856 else if( pAllDelBoxes )
857 {
858 // If the predecessor will also be deleted, there's nothing to do
859 SwSelBoxes::const_iterator aFndIt = pAllDelBoxes->find( pFndBox);
860 if( aFndIt == pAllDelBoxes->end() )
861 break;
862 size_t const nFndPos = aFndIt - pAllDelBoxes->begin() ;
863
864 // else, we keep on searching.
865 // We do not need to recheck the Box, however
866 pFndBox = nullptr;
867 if( nFndPos <= *pCurPos )
868 --*pCurPos;
869 pAllDelBoxes->erase( pAllDelBoxes->begin() + nFndPos );
870 }
871 } while( bNxt ? ( nLinePos + 1 < o3tl::narrowing<sal_uInt16>(rTableLns.size()) ) : nLinePos != 0 );
872 return pFndBox;
873}
874
875static void
877 SwShareBoxFormats& rShareFormats,
878 SwSelBoxes* pAllDelBoxes = nullptr,
879 size_t *const pCurPos = nullptr )
880{
881//JP 16.04.97: 2. part for Bug 36271
882 const SwTableLine* pLine = rBox.GetUpper();
883 const SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
884 const SwTableBox* pUpperBox = &rBox;
885 sal_uInt16 nDelPos = pLine->GetBoxPos( pUpperBox );
886 pUpperBox = rBox.GetUpper()->GetUpper();
887 const SvxBoxItem& rBoxItem = rBox.GetFrameFormat()->GetBox();
888
889 // then the top/bottom edges
890 if( !rBoxItem.GetTop() && !rBoxItem.GetBottom() )
891 return;
892
893 bool bChgd = false;
894 const SwTableLines* pTableLns;
895 if( pUpperBox )
896 pTableLns = &pUpperBox->GetTabLines();
897 else
898 pTableLns = &rTable.GetTabLines();
899
900 sal_uInt16 nLnPos = pTableLns->GetPos( pLine );
901
902 // Calculate the attribute position of the top-be-deleted Box and then
903 // search in the top/bottom Line of the respective counterparts.
904 SwTwips nBoxStt = 0;
905 for( sal_uInt16 n = 0; n < nDelPos; ++n )
906 nBoxStt += rTableBoxes[ n ]->GetFrameFormat()->GetFrameSize().GetWidth();
907 SwTwips nBoxWidth = rBox.GetFrameFormat()->GetFrameSize().GetWidth();
908
909 SwTableBox *pPrvBox = nullptr, *pNxtBox = nullptr;
910 if( nLnPos ) // Predecessor?
911 pPrvBox = ::lcl_FndNxtPrvDelBox( *pTableLns, nBoxStt, nBoxWidth,
912 nLnPos, false, pAllDelBoxes, pCurPos );
913
914 if( nLnPos + 1 < o3tl::narrowing<sal_uInt16>(pTableLns->size()) ) // Successor?
915 pNxtBox = ::lcl_FndNxtPrvDelBox( *pTableLns, nBoxStt, nBoxWidth,
916 nLnPos, true, pAllDelBoxes, pCurPos );
917
918 if( pNxtBox && pNxtBox->GetSttNd() )
919 {
920 const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrameFormat()->GetBox();
921 if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
922 !pPrvBox->GetFrameFormat()->GetBox().GetBottom()) )
923 {
924 SvxBoxItem aTmp( rNxtBoxItem );
927 SvxBoxItemLine::TOP );
928 rShareFormats.SetAttr( *pNxtBox, aTmp );
929 bChgd = true;
930 }
931 }
932 if( !(!bChgd && pPrvBox && pPrvBox->GetSttNd()) )
933 return;
934
935 const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrameFormat()->GetBox();
936 if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
937 !pNxtBox->GetFrameFormat()->GetBox().GetTop()) )
938 {
939 SvxBoxItem aTmp( rPrvBoxItem );
942 SvxBoxItemLine::BOTTOM );
943 rShareFormats.SetAttr( *pPrvBox, aTmp );
944 }
945
946}
947
949 SwDoc* pDoc
950 ,
951 const SwSelBoxes& rBoxes,
952 const SwSelBoxes* pMerged, SwUndo* pUndo,
953 const bool bDelMakeFrames, const bool bCorrBorder )
954{
955 OSL_ENSURE( pDoc, "No doc?" );
956 SwTableNode* pTableNd = nullptr;
957 if( !rBoxes.empty() )
958 {
959 pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
960 if( !pTableNd )
961 return false;
962 }
963
964 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
965
966 // Find Lines for the Layout update
967 FndBox_ aFndBox( nullptr, nullptr );
968 if ( bDelMakeFrames )
969 {
970 if( pMerged && !pMerged->empty() )
971 aFndBox.SetTableLines( *pMerged, *this );
972 else if( !rBoxes.empty() )
973 aFndBox.SetTableLines( rBoxes, *this );
974 aFndBox.DelFrames( *this );
975 }
976
977 SwShareBoxFormats aShareFormats;
978
979 // First switch the Border, then delete
980 if( bCorrBorder )
981 {
982 SwSelBoxes aBoxes( rBoxes );
983 for (size_t n = 0; n < aBoxes.size(); ++n)
984 {
985 ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFormats,
986 &aBoxes, &n );
987 }
988 }
989
990 PrepareDelBoxes( rBoxes );
991
993 // Delete boxes from last to first
994 for (size_t n = 0; n < rBoxes.size(); ++n)
995 {
996 size_t const nIdx = rBoxes.size() - 1 - n;
997
998 // First adapt the data-sequence for chart if necessary
999 // (needed to move the implementation cursor properly to its new
1000 // position which can't be done properly if the cell is already gone)
1001 if (pPCD && pTableNd)
1002 pPCD->DeleteBox( &pTableNd->GetTable(), *rBoxes[nIdx] );
1003
1004 // ... then delete the boxes
1005 DeleteBox_( *this, rBoxes[nIdx], pUndo, true, bCorrBorder, &aShareFormats );
1006 }
1007
1008 // then clean up the structure of all Lines
1009 GCLines();
1010
1011 if( bDelMakeFrames && aFndBox.AreLinesToRestore( *this ) )
1012 aFndBox.MakeFrames( *this );
1013
1014 // TL_CHART2: now inform chart that sth has changed
1015 pDoc->UpdateCharts( GetFrameFormat()->GetName() );
1016
1018 CHECK_TABLE( *this );
1019
1020 return true;
1021}
1022
1023bool SwTable::OldSplitRow( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
1024 bool bSameHeight )
1025{
1026 OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid values" );
1027 SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1028 if( !pTableNd )
1029 return false;
1030
1031 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1032 // the table too complex to be handled with chart.
1033 // Thus we tell the charts to use their own data provider and forget about this table
1035
1036 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
1037
1038 // If the rows should get the same (min) height, we first have
1039 // to store the old row heights before deleting the frames
1040 std::unique_ptr<tools::Long[]> pRowHeights;
1041 if ( bSameHeight )
1042 {
1043 pRowHeights.reset(new tools::Long[ rBoxes.size() ]);
1044 for (size_t n = 0; n < rBoxes.size(); ++n)
1045 {
1046 SwTableBox* pSelBox = rBoxes[n];
1047 const SwRowFrame* pRow = GetRowFrame( *pSelBox->GetUpper() );
1048 OSL_ENSURE( pRow, "Where is the SwTableLine's Frame?" );
1049 SwRectFnSet aRectFnSet(pRow);
1050 pRowHeights[ n ] = aRectFnSet.GetHeight(pRow->getFrameArea());
1051 }
1052 }
1053
1054 // Find Lines for the Layout update
1055 FndBox_ aFndBox( nullptr, nullptr );
1056 aFndBox.SetTableLines( rBoxes, *this );
1057 aFndBox.DelFrames( *this );
1058
1059 for (size_t n = 0; n < rBoxes.size(); ++n)
1060 {
1061 SwTableBox* pSelBox = rBoxes[n];
1062 OSL_ENSURE( pSelBox, "Box is not within the Table" );
1063
1064 // Insert nCnt new Lines into the Box
1065 SwTableLine* pInsLine = pSelBox->GetUpper();
1066 SwTableBoxFormat* pFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat());
1067
1068 // Respect the Line's height, reset if needed
1069 SwFormatFrameSize aFSz( pInsLine->GetFrameFormat()->GetFrameSize() );
1070 if ( bSameHeight && SwFrameSize::Variable == aFSz.GetHeightSizeType() )
1072
1073 bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
1074 if ( bChgLineSz )
1075 aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
1076 (nCnt + 1) );
1077
1078 SwTableBox* pNewBox = new SwTableBox( pFrameFormat, nCnt, pInsLine );
1079 sal_uInt16 nBoxPos = pInsLine->GetBoxPos( pSelBox );
1080 pInsLine->GetTabBoxes()[nBoxPos] = pNewBox; // overwrite old one
1081
1082 // Delete background/border attribute
1083 SwTableBox* pLastBox = pSelBox; // To distribute the TextNodes!
1084 // If Areas are contained in the Box, it stays as is
1085 // !! If this is changed we need to adapt the Undo, too !!!
1086 bool bMoveNodes = true;
1087 {
1088 SwNodeOffset nSttNd = pLastBox->GetSttIdx() + 1,
1089 nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
1090 while( nSttNd < nEndNd )
1091 if( !rDoc.GetNodes()[ nSttNd++ ]->IsTextNode() )
1092 {
1093 bMoveNodes = false;
1094 break;
1095 }
1096 }
1097
1098 SwTableBoxFormat* pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat());
1099 bool bChkBorder = nullptr != pCpyBoxFrameFormat->GetBox().GetTop();
1100 if( bChkBorder )
1101 pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->ClaimFrameFormat());
1102
1103 for( sal_uInt16 i = 0; i <= nCnt; ++i )
1104 {
1105 // Create a new Line in the new Box
1106 SwTableLine* pNewLine = new SwTableLine(
1107 static_cast<SwTableLineFormat*>(pInsLine->GetFrameFormat()), 1, pNewBox );
1108 if( bChgLineSz )
1109 {
1110 pNewLine->ClaimFrameFormat()->SetFormatAttr( aFSz );
1111 }
1112
1113 pNewBox->GetTabLines().insert( pNewBox->GetTabLines().begin() + i, pNewLine );
1114 // then a new Box in the Line
1115 if( !i ) // hang up the original Box
1116 {
1117 pSelBox->SetUpper( pNewLine );
1118 pNewLine->GetTabBoxes().insert( pNewLine->GetTabBoxes().begin(), pSelBox );
1119 }
1120 else
1121 {
1122 ::InsTableBox( rDoc, pTableNd, pNewLine, pCpyBoxFrameFormat,
1123 pLastBox, 0 );
1124
1125 if( bChkBorder )
1126 {
1127 pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pNewLine->GetTabBoxes()[ 0 ]->ClaimFrameFormat());
1128 SvxBoxItem aTmp( pCpyBoxFrameFormat->GetBox() );
1129 aTmp.SetLine( nullptr, SvxBoxItemLine::TOP );
1130 pCpyBoxFrameFormat->SetFormatAttr( aTmp );
1131 bChkBorder = false;
1132 }
1133
1134 if( bMoveNodes )
1135 {
1136 const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
1137 if( pLastBox->GetSttIdx()+SwNodeOffset(2) != pEndNd->GetIndex() )
1138 {
1139 // Move TextNodes
1140 SwNodeRange aRg( *pLastBox->GetSttNd(), SwNodeOffset(+2), *pEndNd );
1141 pLastBox = pNewLine->GetTabBoxes()[0]; // reset
1142 SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
1143 rDoc.GetNodes().MoveNodes(aRg, rDoc.GetNodes(), aInsPos.GetNode(), false);
1144 rDoc.GetNodes().Delete( aInsPos ); // delete the empty one
1145 }
1146 }
1147 }
1148 }
1149 // In Boxes with Lines, we can only have Size/Fillorder
1150 pFrameFormat = static_cast<SwTableBoxFormat*>(pNewBox->ClaimFrameFormat());
1151 pFrameFormat->ResetFormatAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1152 pFrameFormat->ResetFormatAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
1153 }
1154
1155 pRowHeights.reset();
1156
1157 GCLines();
1158
1159 aFndBox.MakeFrames( *this );
1160
1163 return true;
1164}
1165
1166bool SwTable::SplitCol(SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt)
1167{
1168 OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid values" );
1169 SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1170 if( !pTableNd )
1171 return false;
1172
1173 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1174 // the table too complex to be handled with chart.
1175 // Thus we tell the charts to use their own data provider and forget about this table
1177
1178 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
1179 SwSelBoxes aSelBoxes(rBoxes);
1180 ExpandSelection( aSelBoxes );
1181
1182 // Find Lines for the Layout update
1183 FndBox_ aFndBox( nullptr, nullptr );
1184 aFndBox.SetTableLines( aSelBoxes, *this );
1185 aFndBox.DelFrames( *this );
1186
1187 CpyTabFrames aFrameArr;
1188 std::vector<SwTableBoxFormat*> aLastBoxArr;
1189 for (size_t n = 0; n < aSelBoxes.size(); ++n)
1190 {
1191 SwTableBox* pSelBox = aSelBoxes[n];
1192 OSL_ENSURE( pSelBox, "Box is not in the table" );
1193
1194 // We don't want to split small table cells into very very small cells
1195 if( pSelBox->GetFrameFormat()->GetFrameSize().GetWidth()/( nCnt + 1 ) < 10 )
1196 continue;
1197
1198 // Then split the nCnt Box up into nCnt Boxes
1199 SwTableLine* pInsLine = pSelBox->GetUpper();
1200 sal_uInt16 nBoxPos = pInsLine->GetBoxPos( pSelBox );
1201
1202 // Find the Frame Format in the Frame Format Array
1203 SwTableBoxFormat* pLastBoxFormat;
1204 CpyTabFrame aFindFrame( static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat()) );
1205 CpyTabFrames::const_iterator itFind = aFrameArr.lower_bound( aFindFrame );
1206 const size_t nFndPos = itFind - aFrameArr.begin();
1207 if( itFind == aFrameArr.end() || !(*itFind == aFindFrame) )
1208 {
1209 // Change the FrameFormat
1210 aFindFrame.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->ClaimFrameFormat());
1211 SwTwips nBoxSz = aFindFrame.pNewFrameFormat->GetFrameSize().GetWidth();
1212 SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
1213 aFindFrame.pNewFrameFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable,
1214 nNewBoxSz, 0 ) );
1215 aFrameArr.insert( aFindFrame );
1216
1217 pLastBoxFormat = aFindFrame.pNewFrameFormat;
1218 if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
1219 {
1220 // We have a remainder, so we need to define an own Format
1221 // for the last Box.
1222 pLastBoxFormat = new SwTableBoxFormat( *aFindFrame.pNewFrameFormat );
1224 nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
1225 }
1226 aLastBoxArr.insert( aLastBoxArr.begin() + nFndPos, pLastBoxFormat );
1227 }
1228 else
1229 {
1230 aFindFrame = aFrameArr[ nFndPos ];
1231 pSelBox->ChgFrameFormat( aFindFrame.pNewFrameFormat );
1232 pLastBoxFormat = aLastBoxArr[ nFndPos ];
1233 }
1234
1235 // Insert the Boxes at the Position
1236 for( sal_uInt16 i = 1; i < nCnt; ++i )
1237 ::InsTableBox( rDoc, pTableNd, pInsLine, aFindFrame.pNewFrameFormat,
1238 pSelBox, nBoxPos + i ); // insert after
1239
1240 ::InsTableBox( rDoc, pTableNd, pInsLine, pLastBoxFormat,
1241 pSelBox, nBoxPos + nCnt ); // insert after
1242
1243 // Special treatment for the Border:
1244 const SvxBoxItem& aSelBoxItem = aFindFrame.pNewFrameFormat->GetBox();
1245 if( aSelBoxItem.GetRight() )
1246 {
1247 pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrameFormat();
1248
1249 SvxBoxItem aTmp( aSelBoxItem );
1250 aTmp.SetLine( nullptr, SvxBoxItemLine::RIGHT );
1251 aFindFrame.pNewFrameFormat->SetFormatAttr( aTmp );
1252
1253 // Remove the Format from the "cache"
1254 for( auto i = aFrameArr.size(); i; )
1255 {
1256 const CpyTabFrame& rCTF = aFrameArr[ --i ];
1257 if( rCTF.pNewFrameFormat == aFindFrame.pNewFrameFormat ||
1258 rCTF.pFrameFormat == aFindFrame.pNewFrameFormat )
1259 {
1260 aFrameArr.erase( aFrameArr.begin() + i );
1261 aLastBoxArr.erase( aLastBoxArr.begin() + i );
1262 }
1263 }
1264 }
1265 }
1266
1267 // Update Layout
1268 aFndBox.MakeFrames( *this );
1269
1272 return true;
1273}
1274
1275/*
1276 * >> MERGE <<
1277 * Algorithm:
1278 * If we only have one Line in the FndBox_, take this Line and test
1279 * the Box count:
1280 * If we have more than one Box, we merge on Box level, meaning
1281 * the new Box will be as wide as the old ones.
1282 * All Lines that are above/under the Area, are inserted into
1283 * the Box as Line + Box.
1284 * All Lines that come before/after the Area, are inserted into
1285 * the Boxes Left/Right.
1286 *
1287 * >> MERGE <<
1288 */
1289static void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd,
1290 SwTableLines& rLines,
1291 SwTableBox* pInsBox,
1292 sal_uInt16 nPos = USHRT_MAX )
1293{
1294 for( sal_uInt16 n = nStt; n < nEnd; ++n )
1295 rLines[n]->SetUpper( pInsBox );
1296 if( USHRT_MAX == nPos )
1297 nPos = pInsBox->GetTabLines().size();
1298 pInsBox->GetTabLines().insert( pInsBox->GetTabLines().begin() + nPos,
1299 rLines.begin() + nStt, rLines.begin() + nEnd );
1300 rLines.erase( rLines.begin() + nStt, rLines.begin() + nEnd );
1301}
1302
1303static void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd,
1304 SwTableBoxes& rBoxes,
1305 SwTableLine* pInsLine )
1306{
1307 for( sal_uInt16 n = nStt; n < nEnd; ++n )
1308 rBoxes[n]->SetUpper( pInsLine );
1309 sal_uInt16 nPos = pInsLine->GetTabBoxes().size();
1310 pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + nPos,
1311 rBoxes.begin() + nStt, rBoxes.begin() + nEnd );
1312 rBoxes.erase( rBoxes.begin() + nStt, rBoxes.begin() + nEnd );
1313}
1314
1315static void lcl_CalcWidth( SwTableBox* pBox )
1316{
1317 // Assertion: Every Line in the Box is as large
1318 SwFrameFormat* pFormat = pBox->ClaimFrameFormat();
1319 OSL_ENSURE( pBox->GetTabLines().size(), "Box does not have any Lines" );
1320
1321 SwTableLine* pLine = pBox->GetTabLines()[0];
1322 OSL_ENSURE( pLine, "Box is not within a Line" );
1323
1324 tools::Long nWidth = 0;
1325 for( auto pTabBox : pLine->GetTabBoxes() )
1326 nWidth += pTabBox->GetFrameFormat()->GetFrameSize().GetWidth();
1327
1328 pFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth, 0 ));
1329
1330 // Boxes with Lines can only have Size/Fillorder
1333}
1334
1335namespace {
1336
1337struct InsULPara
1338{
1339 SwTableNode* pTableNd;
1340 SwTableLine* pInsLine;
1341 SwTableBox* pInsBox;
1342 bool bUL_LR : 1; // Upper-Lower(true) or Left-Right(false) ?
1343 bool bUL : 1; // Upper-Left(true) or Lower-Right(false) ?
1344
1345 SwTableBox* pLeftBox;
1346
1347 InsULPara( SwTableNode* pTNd,
1348 SwTableBox* pLeft,
1349 SwTableLine* pLine )
1350 : pTableNd( pTNd ), pInsLine( pLine ), pInsBox( nullptr ),
1351 pLeftBox( pLeft )
1352 { bUL_LR = true; bUL = true; }
1353
1354 void SetLeft( SwTableBox* pBox )
1355 { bUL_LR = false; bUL = true; if( pBox ) pInsBox = pBox; }
1356 void SetRight( SwTableBox* pBox )
1357 { bUL_LR = false; bUL = false; if( pBox ) pInsBox = pBox; }
1358 void SetLower( SwTableLine* pLine )
1359 { bUL_LR = true; bUL = false; if( pLine ) pInsLine = pLine; }
1360};
1361
1362}
1363
1364static void lcl_Merge_MoveLine(FndLine_ & rFndLine, InsULPara *const pULPara);
1365
1366static void lcl_Merge_MoveBox(FndBox_ & rFndBox, InsULPara *const pULPara)
1367{
1368 SwTableBoxes* pBoxes;
1369
1370 sal_uInt16 nStt = 0, nEnd = rFndBox.GetLines().size();
1371 sal_uInt16 nInsPos = USHRT_MAX;
1372 if( !pULPara->bUL_LR ) // Left/Right
1373 {
1374 sal_uInt16 nPos;
1375 SwTableBox* pFndTableBox = rFndBox.GetBox();
1376 pBoxes = &pFndTableBox->GetUpper()->GetTabBoxes();
1377 if( pULPara->bUL ) // Left ?
1378 {
1379 // if there are Boxes before it, move them
1380 nPos = pFndTableBox->GetUpper()->GetBoxPos( pFndTableBox );
1381 if( 0 != nPos )
1382 lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
1383 }
1384 else // Right
1385 {
1386 // if there are Boxes behind it, move them
1387 nPos = pFndTableBox->GetUpper()->GetBoxPos( pFndTableBox );
1388 if( nPos +1 < o3tl::narrowing<sal_uInt16>(pBoxes->size()) )
1389 {
1390 nInsPos = pULPara->pInsLine->GetTabBoxes().size();
1391 lcl_CpyBoxes( nPos+1, pBoxes->size(),
1392 *pBoxes, pULPara->pInsLine );
1393 }
1394 }
1395 }
1396 // Upper/Lower and still deeper?
1397 else if (!rFndBox.GetLines().empty())
1398 {
1399 // Only search the Line from which we need to move
1400 nStt = pULPara->bUL ? 0 : rFndBox.GetLines().size()-1;
1401 nEnd = nStt+1;
1402 }
1403
1404 pBoxes = &pULPara->pInsLine->GetTabBoxes();
1405
1406 // Is there still a level to step down to?
1407 if (rFndBox.GetBox()->GetTabLines().empty())
1408 return;
1409
1410 SwTableBox* pBox = new SwTableBox(
1411 static_cast<SwTableBoxFormat*>(rFndBox.GetBox()->GetFrameFormat()),
1412 0, pULPara->pInsLine );
1413 InsULPara aPara( *pULPara );
1414 aPara.pInsBox = pBox;
1415 for (FndLines_t::iterator it = rFndBox.GetLines().begin() + nStt;
1416 it != rFndBox.GetLines().begin() + nEnd; ++it )
1417 {
1418 lcl_Merge_MoveLine(**it, &aPara);
1419 }
1420 if( !pBox->GetTabLines().empty() )
1421 {
1422 if( USHRT_MAX == nInsPos )
1423 nInsPos = pBoxes->size();
1424 pBoxes->insert( pBoxes->begin() + nInsPos, pBox );
1425 lcl_CalcWidth( pBox ); // calculate the Box's width
1426 }
1427 else
1428 delete pBox;
1429}
1430
1431static void lcl_Merge_MoveLine(FndLine_& rFndLine, InsULPara *const pULPara)
1432{
1433 SwTableLines* pLines;
1434
1435 sal_uInt16 nStt = 0, nEnd = rFndLine.GetBoxes().size();
1436 sal_uInt16 nInsPos = USHRT_MAX;
1437 if( pULPara->bUL_LR ) // UpperLower ?
1438 {
1439 sal_uInt16 nPos;
1440 SwTableLine* pFndLn = rFndLine.GetLine();
1441 pLines = pFndLn->GetUpper() ?
1442 &pFndLn->GetUpper()->GetTabLines() :
1443 &pULPara->pTableNd->GetTable().GetTabLines();
1444
1445 SwTableBox* pLBx = rFndLine.GetBoxes().front()->GetBox();
1446 SwTableBox* pRBx = rFndLine.GetBoxes().back()->GetBox();
1447 sal_uInt16 nLeft = pFndLn->GetBoxPos( pLBx );
1448 sal_uInt16 nRight = pFndLn->GetBoxPos( pRBx );
1449
1450 if( !nLeft || nRight == pFndLn->GetTabBoxes().size() )
1451 {
1452 if( pULPara->bUL ) // Upper ?
1453 {
1454 // If there are Lines before it, move them
1455 nPos = pLines->GetPos( pFndLn );
1456 if( 0 != nPos )
1457 lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
1458 }
1459 else
1460 // If there are Lines after it, move them
1461 if( (nPos = pLines->GetPos( pFndLn )) + 1 < o3tl::narrowing<sal_uInt16>(pLines->size()) )
1462 {
1463 nInsPos = pULPara->pInsBox->GetTabLines().size();
1464 lcl_CpyLines( nPos+1, pLines->size(), *pLines,
1465 pULPara->pInsBox );
1466 }
1467 }
1468 else
1469 {
1470 // There are still Boxes on the left side, so put the Left-
1471 // and Merge-Box into one Box and Line, insert before/after
1472 // a Line with a Box, into which the upper/lower Lines are
1473 // inserted
1474 SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
1475 SwTableBox* pLMBox = new SwTableBox(
1476 static_cast<SwTableBoxFormat*>(pULPara->pLeftBox->GetFrameFormat()), 0, pInsLine );
1477 SwTableLine* pLMLn = new SwTableLine(
1478 static_cast<SwTableLineFormat*>(pInsLine->GetFrameFormat()), 2, pLMBox );
1480
1481 pLMBox->GetTabLines().insert( pLMBox->GetTabLines().begin(), pLMLn );
1482
1483 lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
1484
1485 pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin(), pLMBox );
1486
1487 if( pULPara->bUL ) // Upper ?
1488 {
1489 // If there are Lines before it, move them
1490 nPos = pLines->GetPos( pFndLn );
1491 if( 0 != nPos )
1492 lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
1493 }
1494 else
1495 // If there are Lines after it, move them
1496 if( (nPos = pLines->GetPos( pFndLn )) + 1 < o3tl::narrowing<sal_uInt16>(pLines->size()) )
1497 lcl_CpyLines( nPos+1, pLines->size(), *pLines,
1498 pLMBox );
1499 lcl_CalcWidth( pLMBox ); // calculate the Box's width
1500 }
1501 }
1502 // Left/Right
1503 else
1504 {
1505 // Find only the Line from which we need to move
1506 nStt = pULPara->bUL ? 0 : rFndLine.GetBoxes().size()-1;
1507 nEnd = nStt+1;
1508 }
1509 pLines = &pULPara->pInsBox->GetTabLines();
1510
1511 SwTableLine* pNewLine = new SwTableLine(
1512 static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()), 0, pULPara->pInsBox );
1513 InsULPara aPara( *pULPara ); // copying
1514 aPara.pInsLine = pNewLine;
1515 FndBoxes_t & rLineBoxes = rFndLine.GetBoxes();
1516 for (FndBoxes_t::iterator it = rLineBoxes.begin() + nStt;
1517 it != rLineBoxes.begin() + nEnd; ++it)
1518 {
1519 lcl_Merge_MoveBox(**it, &aPara);
1520 }
1521
1522 if( !pNewLine->GetTabBoxes().empty() )
1523 {
1524 if( USHRT_MAX == nInsPos )
1525 nInsPos = pLines->size();
1526 pLines->insert( pLines->begin() + nInsPos, pNewLine );
1527 }
1528 else
1529 delete pNewLine;
1530}
1531
1532static void lcl_BoxSetHeadCondColl( const SwTableBox* pBox );
1533
1534bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
1535 SwTableBox* pMergeBox, SwUndoTableMerge* pUndo )
1536{
1537 OSL_ENSURE( !rBoxes.empty() && pMergeBox, "no valid values" );
1538 SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1539 if( !pTableNd )
1540 return false;
1541
1542 // Find all Boxes/Lines
1543 FndBox_ aFndBox( nullptr, nullptr );
1544 {
1545 FndPara aPara( rBoxes, &aFndBox );
1547 }
1548 if( aFndBox.GetLines().empty() )
1549 return false;
1550
1551 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1552 // the table too complex to be handled with chart.
1553 // Thus we tell the charts to use their own data provider and forget about this table
1555
1556 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
1557
1558 if( pUndo )
1559 pUndo->SetSelBoxes( rBoxes );
1560
1561 // Find Lines for the Layout update
1562 aFndBox.SetTableLines( *this );
1563 aFndBox.DelFrames( *this );
1564
1565 FndBox_* pFndBox = &aFndBox;
1566 while( 1 == pFndBox->GetLines().size() &&
1567 1 == pFndBox->GetLines().front()->GetBoxes().size() )
1568 {
1569 pFndBox = pFndBox->GetLines().front()->GetBoxes().front().get();
1570 }
1571
1572 SwTableLine* pInsLine = new SwTableLine(
1573 static_cast<SwTableLineFormat*>(pFndBox->GetLines().front()->GetLine()->GetFrameFormat()), 0,
1574 !pFndBox->GetUpper() ? nullptr : pFndBox->GetBox() );
1576
1577 // Add the new Line
1578 SwTableLines* pLines = pFndBox->GetUpper() ?
1579 &pFndBox->GetBox()->GetTabLines() : &GetTabLines();
1580
1581 SwTableLine* pNewLine = pFndBox->GetLines().front()->GetLine();
1582 sal_uInt16 nInsPos = pLines->GetPos( pNewLine );
1583 pLines->insert( pLines->begin() + nInsPos, pInsLine );
1584
1585 SwTableBox* pLeftBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pMergeBox->GetFrameFormat()), 0, pInsLine );
1586 SwTableBox* pRightBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pMergeBox->GetFrameFormat()), 0, pInsLine );
1587 pMergeBox->SetUpper( pInsLine );
1588 pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin(), pLeftBox );
1589 pLeftBox->ClaimFrameFormat();
1590 pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + 1, pMergeBox);
1591 pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + 2, pRightBox );
1592 pRightBox->ClaimFrameFormat();
1593
1594 // This contains all Lines that are above the selected Area,
1595 // thus they form a Upper/Lower Line
1596 InsULPara aPara( pTableNd, pLeftBox, pInsLine );
1597
1598 // Move the overlapping upper/lower Lines of the selected Area
1599 for (auto & it : pFndBox->GetLines().front()->GetBoxes())
1600 {
1601 lcl_Merge_MoveBox(*it, &aPara);
1602 }
1603 aPara.SetLower( pInsLine );
1604 const auto nEnd = pFndBox->GetLines().size()-1;
1605 for (auto & it : pFndBox->GetLines()[nEnd]->GetBoxes())
1606 {
1607 lcl_Merge_MoveBox(*it, &aPara);
1608 }
1609
1610 // Move the Boxes extending into the selected Area from left/right
1611 aPara.SetLeft( pLeftBox );
1612 for (auto & rpFndLine : pFndBox->GetLines())
1613 {
1614 lcl_Merge_MoveLine( *rpFndLine, &aPara );
1615 }
1616
1617 aPara.SetRight( pRightBox );
1618 for (auto & rpFndLine : pFndBox->GetLines())
1619 {
1620 lcl_Merge_MoveLine( *rpFndLine, &aPara );
1621 }
1622
1623 if( pLeftBox->GetTabLines().empty() )
1624 DeleteBox_( *this, pLeftBox, nullptr, false, false );
1625 else
1626 {
1627 lcl_CalcWidth( pLeftBox ); // calculate the Box's width
1628 if( pUndo && pLeftBox->GetSttNd() )
1629 pUndo->AddNewBox( pLeftBox->GetSttIdx() );
1630 }
1631 if( pRightBox->GetTabLines().empty() )
1632 DeleteBox_( *this, pRightBox, nullptr, false, false );
1633 else
1634 {
1635 lcl_CalcWidth( pRightBox ); // calculate the Box's width
1636 if( pUndo && pRightBox->GetSttNd() )
1637 pUndo->AddNewBox( pRightBox->GetSttIdx() );
1638 }
1639
1640 DeleteSel( pDoc, rBoxes, nullptr, nullptr, false, false );
1641
1642 // Clean up this Line's structure once again, generally all of them
1643 GCLines();
1644
1645 for( const auto& rpBox : GetTabLines()[0]->GetTabBoxes() )
1647
1648 aFndBox.MakeFrames( *this );
1649
1652
1653 return true;
1654}
1655
1656static void lcl_CheckRowSpan( SwTable &rTable )
1657{
1658 const tools::Long nLineCount = static_cast<tools::Long>(rTable.GetTabLines().size());
1659 tools::Long nMaxSpan = nLineCount;
1660 tools::Long nMinSpan = 1;
1661 while( nMaxSpan )
1662 {
1663 SwTableLine* pLine = rTable.GetTabLines()[ nLineCount - nMaxSpan ];
1664 for( auto pBox : pLine->GetTabBoxes() )
1665 {
1666 sal_Int32 nRowSpan = pBox->getRowSpan();
1667 if( nRowSpan > nMaxSpan )
1668 pBox->setRowSpan( nMaxSpan );
1669 else if( nRowSpan < nMinSpan )
1670 pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
1671 }
1672 --nMaxSpan;
1673 nMinSpan = -nMaxSpan;
1674 }
1675}
1676
1677static sal_uInt16 lcl_GetBoxOffset( const FndBox_& rBox )
1678{
1679 // Find the first Box
1680 const FndBox_* pFirstBox = &rBox;
1681 while (!pFirstBox->GetLines().empty())
1682 {
1683 pFirstBox = pFirstBox->GetLines().front()->GetBoxes().front().get();
1684 }
1685
1686 sal_uInt16 nRet = 0;
1687 // Calculate the position relative to above via the Lines
1688 const SwTableBox* pBox = pFirstBox->GetBox();
1689 do {
1690 const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
1691 for( auto pCmp : rBoxes )
1692 {
1693 if (pBox==pCmp)
1694 break;
1695 nRet = nRet + o3tl::narrowing<sal_uInt16>(pCmp->GetFrameFormat()->GetFrameSize().GetWidth());
1696 }
1697 pBox = pBox->GetUpper()->GetUpper();
1698 } while( pBox );
1699 return nRet;
1700}
1701
1702static sal_uInt16 lcl_GetLineWidth( const FndLine_& rLine )
1703{
1704 sal_uInt16 nRet = 0;
1705 for( auto n = rLine.GetBoxes().size(); n; )
1706 {
1707 nRet = nRet + o3tl::narrowing<sal_uInt16>(rLine.GetBoxes()[--n]->GetBox()
1708 ->GetFrameFormat()->GetFrameSize().GetWidth());
1709 }
1710 return nRet;
1711}
1712
1713static void lcl_CalcNewWidths(const FndLines_t& rFndLines, CpyPara& rPara)
1714{
1715 rPara.pWidths.reset();
1716 const size_t nLineCount = rFndLines.size();
1717 if( nLineCount )
1718 {
1719 rPara.pWidths = std::make_shared< std::vector< std::vector< sal_uLong > > >
1720 ( nLineCount );
1721 // First we collect information about the left/right borders of all
1722 // selected cells
1723 for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1724 {
1725 std::vector< sal_uLong > &rWidth = (*rPara.pWidths)[ nLine ];
1726 const FndLine_ *pFndLine = rFndLines[ nLine ].get();
1727 if( pFndLine && !pFndLine->GetBoxes().empty() )
1728 {
1729 const SwTableLine *pLine = pFndLine->GetLine();
1730 if( pLine && !pLine->GetTabBoxes().empty() )
1731 {
1732 size_t nBoxCount = pLine->GetTabBoxes().size();
1733 sal_uLong nPos = 0;
1734 // The first selected box...
1735 const SwTableBox *const pSel =
1736 pFndLine->GetBoxes().front()->GetBox();
1737 size_t nBox = 0;
1738 // Sum up the width of all boxes before the first selected box
1739 while( nBox < nBoxCount )
1740 {
1741 SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
1742 if( pBox != pSel )
1743 nPos += pBox->GetFrameFormat()->GetFrameSize().GetWidth();
1744 else
1745 break;
1746 }
1747 // nPos is now the left border of the first selected box
1748 if( rPara.nMinLeft > nPos )
1749 rPara.nMinLeft = nPos;
1750 nBoxCount = pFndLine->GetBoxes().size();
1751 rWidth = std::vector< sal_uLong >( nBoxCount+2 );
1752 rWidth[ 0 ] = nPos;
1753 // Add now the widths of all selected boxes and store
1754 // the positions in the vector
1755 for( nBox = 0; nBox < nBoxCount; )
1756 {
1757 nPos += pFndLine->GetBoxes()[nBox]
1758 ->GetBox()->GetFrameFormat()->GetFrameSize().GetWidth();
1759 rWidth[ ++nBox ] = nPos;
1760 }
1761 // nPos: The right border of the last selected box
1762 if( rPara.nMaxRight < nPos )
1763 rPara.nMaxRight = nPos;
1764 if( nPos <= rWidth[ 0 ] )
1765 rWidth.clear();
1766 }
1767 }
1768 }
1769 }
1770 // Second step: calculate the new widths for the copied cells
1771 sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft;
1772 if( !nSelSize )
1773 return;
1774
1775 for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1776 {
1777 std::vector< sal_uLong > &rWidth = (*rPara.pWidths)[ nLine ];
1778 const size_t nCount = rWidth.size();
1779 if( nCount > 2 )
1780 {
1781 rWidth[ nCount - 1 ] = rPara.nMaxRight;
1782 sal_uLong nLastPos = 0;
1783 for( size_t nBox = 0; nBox < nCount; ++nBox )
1784 {
1785 sal_uInt64 nNextPos = rWidth[ nBox ];
1786 nNextPos -= rPara.nMinLeft;
1787 nNextPos *= rPara.nNewSize;
1788 nNextPos /= nSelSize;
1789 rWidth[ nBox ] = static_cast<sal_uLong>(nNextPos - nLastPos);
1790 nLastPos = static_cast<sal_uLong>(nNextPos);
1791 }
1792 }
1793 }
1794}
1795
1796static void
1797lcl_CopyLineToDoc(FndLine_ const& rpFndLn, CpyPara *const pCpyPara);
1798
1799static void lcl_CopyBoxToDoc(FndBox_ const& rFndBox, CpyPara *const pCpyPara)
1800{
1801 // Calculation of new size
1802 sal_uLong nRealSize;
1803 sal_uLong nDummy1 = 0;
1804 sal_uLong nDummy2 = 0;
1805 if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1806 {
1807 if( pCpyPara->nBoxIdx == 1 )
1808 nDummy1 = (*pCpyPara->pWidths)[pCpyPara->nLnIdx][0];
1809 nRealSize = (*pCpyPara->pWidths)[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
1810 if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths)[pCpyPara->nLnIdx].size()-1 )
1811 nDummy2 = (*pCpyPara->pWidths)[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
1812 }
1813 else
1814 {
1815 nRealSize = pCpyPara->nNewSize;
1816 nRealSize *= rFndBox.GetBox()->GetFrameFormat()->GetFrameSize().GetWidth();
1817 if (pCpyPara->nOldSize == 0)
1818 throw o3tl::divide_by_zero();
1819 nRealSize /= pCpyPara->nOldSize;
1820 }
1821
1822 sal_uLong nSize;
1823 bool bDummy = nDummy1 > 0;
1824 if( bDummy )
1825 nSize = nDummy1;
1826 else
1827 {
1828 nSize = nRealSize;
1829 nRealSize = 0;
1830 }
1831 do
1832 {
1833 // Find the Frame Format in the list of all Frame Formats
1834 CpyTabFrame aFindFrame(static_cast<SwTableBoxFormat*>(rFndBox.GetBox()->GetFrameFormat()));
1835
1836 std::shared_ptr<SwFormatFrameSize> aFrameSz(std::make_shared<SwFormatFrameSize>());
1837 CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.lower_bound( aFindFrame );
1838 const CpyTabFrames::size_type nFndPos = itFind - pCpyPara->rTabFrameArr.begin();
1839
1840 // It *is* sometimes cool to have multiple tests/if's and assignments
1841 // in a single statement, and it is technically possible. But it is definitely
1842 // not simply readable - where from my POV reading code is done 1000 times
1843 // more often than writing it. Thus I dismantled the expression in smaller
1844 // chunks to keep it handy/understandable/changeable (hopefully without error)
1845 // The original for reference:
1846 // if( itFind == pCpyPara->rTabFrameArr.end() || !(*itFind == aFindFrame) ||
1847 // ( aFrameSz = ( aFindFrame = pCpyPara->rTabFrameArr[ nFndPos ]).pNewFrameFormat->
1848 // GetFrameSize()).GetWidth() != static_cast<SwTwips>(nSize) )
1849
1850 bool DoCopyIt(itFind == pCpyPara->rTabFrameArr.end());
1851
1852 if(!DoCopyIt)
1853 {
1854 DoCopyIt = !(*itFind == aFindFrame);
1855 }
1856
1857 if(!DoCopyIt)
1858 {
1859 aFindFrame = pCpyPara->rTabFrameArr[ nFndPos ];
1860 aFrameSz.reset(aFindFrame.pNewFrameFormat->GetFrameSize().Clone());
1861 DoCopyIt = aFrameSz->GetWidth() != static_cast<SwTwips>(nSize);
1862 }
1863
1864 if(DoCopyIt)
1865 {
1866 // It doesn't exist yet, so copy it
1867 aFindFrame.pNewFrameFormat = pCpyPara->rDoc.MakeTableBoxFormat();
1868 aFindFrame.pNewFrameFormat->CopyAttrs( *rFndBox.GetBox()->GetFrameFormat() );
1869 if( !pCpyPara->bCpyContent )
1870 aFindFrame.pNewFrameFormat->ResetFormatAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1871 aFrameSz->SetWidth( nSize );
1872 aFindFrame.pNewFrameFormat->SetFormatAttr( *aFrameSz );
1873 pCpyPara->rTabFrameArr.insert( aFindFrame );
1874 }
1875
1876 SwTableBox* pBox;
1877 if (!rFndBox.GetLines().empty())
1878 {
1879 pBox = new SwTableBox( aFindFrame.pNewFrameFormat,
1880 rFndBox.GetLines().size(), pCpyPara->pInsLine );
1881 pCpyPara->pInsLine->GetTabBoxes().insert( pCpyPara->pInsLine->GetTabBoxes().begin() + pCpyPara->nInsPos++, pBox );
1882 CpyPara aPara( *pCpyPara, pBox );
1883 aPara.nNewSize = nSize; // get the size
1884 for (auto const& rpFndLine : rFndBox.GetLines())
1885 {
1886 lcl_CopyLineToDoc( *rpFndLine, &aPara );
1887 }
1888 }
1889 else
1890 {
1891 // Create an empty Box
1892 pCpyPara->rDoc.GetNodes().InsBoxen( pCpyPara->pTableNd, pCpyPara->pInsLine,
1893 aFindFrame.pNewFrameFormat,
1894 pCpyPara->rDoc.GetDfltTextFormatColl(),
1895 nullptr, pCpyPara->nInsPos );
1896 pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
1897 if( bDummy )
1898 pBox->setDummyFlag( true );
1899 else if( pCpyPara->bCpyContent )
1900 {
1901 // Copy the content into this empty Box
1902 pBox->setRowSpan(rFndBox.GetBox()->getRowSpan());
1903
1904 // We can also copy formulas and values, if we copy the content
1905 {
1906 SfxItemSetFixed<RES_BOXATR_FORMAT, RES_BOXATR_VALUE> aBoxAttrSet( pCpyPara->rDoc.GetAttrPool() );
1907 aBoxAttrSet.Put(rFndBox.GetBox()->GetFrameFormat()->GetAttrSet());
1908 if( aBoxAttrSet.Count() )
1909 {
1910 const SwTableBoxNumFormat* pItem;
1911 SvNumberFormatter* pN = pCpyPara->rDoc.GetNumberFormatter( false );
1912 if( pN && pN->HasMergeFormatTable() && (pItem = aBoxAttrSet.
1913 GetItemIfSet( RES_BOXATR_FORMAT, false )) )
1914 {
1915 sal_uLong nOldIdx = pItem->GetValue();
1916 sal_uLong nNewIdx = pN->GetMergeFormatIndex( nOldIdx );
1917 if( nNewIdx != nOldIdx )
1918 aBoxAttrSet.Put( SwTableBoxNumFormat( nNewIdx ));
1919 }
1920 pBox->ClaimFrameFormat()->SetFormatAttr( aBoxAttrSet );
1921 }
1922 }
1923 SwDoc* pFromDoc = rFndBox.GetBox()->GetFrameFormat()->GetDoc();
1924 SwNodeRange aCpyRg( *rFndBox.GetBox()->GetSttNd(), SwNodeOffset(1),
1925 *rFndBox.GetBox()->GetSttNd()->EndOfSectionNode() );
1926 SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
1927
1928 pFromDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly(aCpyRg, aInsIdx.GetNode(), nullptr, false);
1929 // Delete the initial TextNode
1930 pCpyPara->rDoc.GetNodes().Delete( aInsIdx );
1931 }
1932 ++pCpyPara->nInsPos;
1933 }
1934 if( nRealSize )
1935 {
1936 bDummy = false;
1937 nSize = nRealSize;
1938 nRealSize = 0;
1939 }
1940 else
1941 {
1942 bDummy = true;
1943 nSize = nDummy2;
1944 nDummy2 = 0;
1945 }
1946 }
1947 while( nSize );
1948}
1949
1950static void
1951lcl_CopyLineToDoc(const FndLine_& rFndLine, CpyPara *const pCpyPara)
1952{
1953 // Find the Frame Format in the list of all Frame Formats
1954 CpyTabFrame aFindFrame( rFndLine.GetLine()->GetFrameFormat() );
1955 CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.find( aFindFrame );
1956 if( itFind == pCpyPara->rTabFrameArr.end() )
1957 {
1958 // It doesn't exist yet, so copy it
1959 aFindFrame.pNewFrameFormat = reinterpret_cast<SwTableBoxFormat*>(pCpyPara->rDoc.MakeTableLineFormat());
1960 aFindFrame.pNewFrameFormat->CopyAttrs( *rFndLine.GetLine()->GetFrameFormat() );
1961 pCpyPara->rTabFrameArr.insert( aFindFrame );
1962 }
1963 else
1964 aFindFrame = *itFind;
1965
1966 SwTableLine* pNewLine = new SwTableLine( reinterpret_cast<SwTableLineFormat*>(aFindFrame.pNewFrameFormat),
1967 rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
1968 if( pCpyPara->pInsBox )
1969 {
1970 SwTableLines& rLines = pCpyPara->pInsBox->GetTabLines();
1971 rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
1972 }
1973 else
1974 {
1975 SwTableLines& rLines = pCpyPara->pTableNd->GetTable().GetTabLines();
1976 rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine);
1977 }
1978
1979 CpyPara aPara( *pCpyPara, pNewLine );
1980
1981 if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1982 {
1983 aPara.nOldSize = 0; // will not be used
1984 aPara.nBoxIdx = 1;
1985 }
1986 else if( rFndLine.GetBoxes().size() ==
1987 rFndLine.GetLine()->GetTabBoxes().size() )
1988 {
1989 // Get the Parent's size
1990 const SwFrameFormat* pFormat;
1991
1992 if( rFndLine.GetLine()->GetUpper() )
1993 pFormat = rFndLine.GetLine()->GetUpper()->GetFrameFormat();
1994 else
1995 pFormat = pCpyPara->pTableNd->GetTable().GetFrameFormat();
1996 aPara.nOldSize = pFormat->GetFrameSize().GetWidth();
1997 }
1998 else
1999 // Calculate it
2000 for (auto &rpBox : rFndLine.GetBoxes())
2001 {
2002 aPara.nOldSize += rpBox->GetBox()->GetFrameFormat()->GetFrameSize().GetWidth();
2003 }
2004
2005 const FndBoxes_t& rBoxes = rFndLine.GetBoxes();
2006 for (auto const& it : rBoxes)
2007 {
2008 lcl_CopyBoxToDoc(*it, &aPara);
2009 }
2010 if( pCpyPara->pTableNd->GetTable().IsNewModel() )
2011 ++pCpyPara->nLnIdx;
2012}
2013
2015{
2016 // Find all Boxes/Lines
2017 SwSelBoxes aSelBoxes;
2018 SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
2019 pBox = GetTableBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
2020 SelLineFromBox( pBox, aSelBoxes );
2021
2022 FndBox_ aFndBox( nullptr, nullptr );
2023 {
2024 FndPara aPara( aSelBoxes, &aFndBox );
2026 }
2027 if( aFndBox.GetLines().empty() )
2028 return;
2029
2030 {
2031 // Convert Table formulas to their relative representation
2032 SwTableFormulaUpdate aMsgHint( this );
2033 aMsgHint.m_eFlags = TBL_RELBOXNAME;
2035 }
2036
2037 CpyTabFrames aCpyFormat;
2038 CpyPara aPara( &rTableNd, 1, aCpyFormat );
2039 aPara.nNewSize = aPara.nOldSize = rTableNd.GetTable().GetFrameFormat()->GetFrameSize().GetWidth();
2040 // Copy
2041 if( IsNewModel() )
2042 lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2043 for (const auto & rpFndLine : aFndBox.GetLines())
2044 {
2045 lcl_CopyLineToDoc( *rpFndLine, &aPara );
2046 }
2047 if( rTableNd.GetTable().IsNewModel() )
2048 { // The copied line must not contain any row span attributes > 1
2049 SwTableLine* pLine = rTableNd.GetTable().GetTabLines()[0];
2050 OSL_ENSURE( !pLine->GetTabBoxes().empty(), "Empty Table Line" );
2051 for( auto pTableBox : pLine->GetTabBoxes() )
2052 {
2053 OSL_ENSURE( pTableBox, "Missing Table Box" );
2054 pTableBox->setRowSpan( 1 );
2055 }
2056 }
2057}
2058
2059bool SwTable::MakeCopy( SwDoc& rInsDoc, const SwPosition& rPos,
2060 const SwSelBoxes& rSelBoxes,
2061 bool bCpyName, const OUString& rStyleName ) const
2062{
2063 // Find all Boxes/Lines
2064 FndBox_ aFndBox( nullptr, nullptr );
2065 {
2066 FndPara aPara( rSelBoxes, &aFndBox );
2067 ForEach_FndLineCopyCol( const_cast<SwTableLines&>(GetTabLines()), &aPara );
2068 }
2069 if( aFndBox.GetLines().empty() )
2070 return false;
2071
2072 // First copy the PoolTemplates for the Table, so that the Tables are
2073 // actually copied and have valid values.
2074 SwDoc* pSrcDoc = GetFrameFormat()->GetDoc();
2075 if( pSrcDoc != &rInsDoc )
2076 {
2079 }
2080
2081 SwTable* pNewTable = const_cast<SwTable*>(rInsDoc.InsertTable(
2083 rPos, 1, 1, GetFrameFormat()->GetHoriOrient().GetHoriOrient(),
2084 nullptr, nullptr, false, IsNewModel() ));
2085 if( !pNewTable )
2086 return false;
2087
2088 SwNodeIndex aIdx( rPos.GetNode(), -1 );
2089 SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
2090 ++aIdx;
2091 OSL_ENSURE( pTableNd, "Where is the TableNode now?" );
2092
2093 pTableNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
2094
2095 pNewTable->SetTableStyleName(pTableNd->GetTable().GetTableStyleName());
2096
2097 pTableNd->GetTable().SetTableStyleName(rStyleName);
2098 if( auto pSwDDETable = dynamic_cast<const SwDDETable*>(this) )
2099 {
2100 // A DDE-Table is being copied
2101 // Does the new Document actually have it's FieldType?
2103 *pSwDDETable->GetDDEFieldType() );
2104 OSL_ENSURE( pFieldType, "unknown FieldType" );
2105
2106 // Change the Table Pointer at the Node
2107 pNewTable = new SwDDETable( *pNewTable,
2108 static_cast<SwDDEFieldType*>(pFieldType) );
2109 pTableNd->SetNewTable( std::unique_ptr<SwTable>(pNewTable), false );
2110 }
2111
2112 pNewTable->GetFrameFormat()->CopyAttrs( *GetFrameFormat() );
2113 pNewTable->SetTableChgMode( GetTableChgMode() );
2114
2115 // Destroy the already created Frames
2116 pTableNd->DelFrames();
2117
2118 {
2119 // Convert the Table formulas to their relative representation
2120 SwTableFormulaUpdate aMsgHint( this );
2121 aMsgHint.m_eFlags = TBL_RELBOXNAME;
2122 pSrcDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2123 }
2124
2125 SwTableNumFormatMerge aTNFM(*pSrcDoc, rInsDoc);
2126
2127 // Also copy Names or enforce a new unique one
2128 if( bCpyName )
2129 pNewTable->GetFrameFormat()->SetFormatName( GetFrameFormat()->GetName() );
2130
2131 CpyTabFrames aCpyFormat;
2132 CpyPara aPara( pTableNd, 1, aCpyFormat );
2133 aPara.nNewSize = aPara.nOldSize = GetFrameFormat()->GetFrameSize().GetWidth();
2134
2135 if( IsNewModel() )
2136 lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2137 // Copy
2138 for (const auto & rpFndLine : aFndBox.GetLines())
2139 {
2140 lcl_CopyLineToDoc( *rpFndLine, &aPara );
2141 }
2142
2143 // Set the "right" margin above/below
2144 {
2145 FndLine_* pFndLn = aFndBox.GetLines().front().get();
2146 SwTableLine* pLn = pFndLn->GetLine();
2147 const SwTableLine* pTmp = pLn;
2148 sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp );
2149 if( USHRT_MAX != nLnPos && nLnPos )
2150 {
2151 // There is a Line before it
2153
2154 pLn = GetTabLines()[ nLnPos - 1 ];
2155 for( const auto& rpBox : pLn->GetTabBoxes() )
2156 sw_Box_CollectBox( rpBox, &aLnPara );
2157
2158 if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2159 lcl_GetLineWidth( *pFndLn )) )
2160 {
2161 aLnPara.SetValues( true );
2162 pLn = pNewTable->GetTabLines()[ 0 ];
2163 for( const auto& rpBox : pLn->GetTabBoxes() )
2164 sw_BoxSetSplitBoxFormats(rpBox, &aLnPara );
2165 }
2166 }
2167
2168 pFndLn = aFndBox.GetLines().back().get();
2169 pLn = pFndLn->GetLine();
2170 pTmp = pLn;
2171 nLnPos = GetTabLines().GetPos( pTmp );
2172 if( nLnPos < GetTabLines().size() - 1 )
2173 {
2174 // There is a Line following it
2176
2177 pLn = GetTabLines()[ nLnPos + 1 ];
2178 for( const auto& rpBox : pLn->GetTabBoxes() )
2179 sw_Box_CollectBox( rpBox, &aLnPara );
2180
2181 if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2182 lcl_GetLineWidth( *pFndLn )) )
2183 {
2184 aLnPara.SetValues( false );
2185 pLn = pNewTable->GetTabLines().back();
2186 for( const auto& rpBox : pLn->GetTabBoxes() )
2187 sw_BoxSetSplitBoxFormats(rpBox, &aLnPara );
2188 }
2189 }
2190 }
2191
2192 // We need to delete the initial Box
2193 DeleteBox_( *pNewTable, pNewTable->GetTabLines().back()->GetTabBoxes()[0],
2194 nullptr, false, false );
2195
2196 if( pNewTable->IsNewModel() )
2197 lcl_CheckRowSpan( *pNewTable );
2198 // Clean up
2199 pNewTable->GCLines();
2200
2201 pTableNd->MakeOwnFrames(); // re-generate the Frames
2202
2204
2205 return true;
2206}
2207
2208// Find the next Box with content from this Line
2210 const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2211{
2212 const SwTableLine* pLine = this; // for M800
2213 SwTableBox* pBox;
2214 sal_uInt16 nFndPos;
2215 if( !GetTabBoxes().empty() && pSrchBox )
2216 {
2217 nFndPos = GetBoxPos( pSrchBox );
2218 if( USHRT_MAX != nFndPos &&
2219 nFndPos + 1 != o3tl::narrowing<sal_uInt16>(GetTabBoxes().size()) )
2220 {
2221 pBox = GetTabBoxes()[ nFndPos + 1 ];
2222 while( !pBox->GetTabLines().empty() )
2223 pBox = pBox->GetTabLines().front()->GetTabBoxes()[0];
2224 return pBox;
2225 }
2226 }
2227
2228 if( GetUpper() )
2229 {
2230 nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2231 OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
2232 // Is there another Line?
2233 if( nFndPos+1 >= o3tl::narrowing<sal_uInt16>(GetUpper()->GetTabLines().size()) )
2234 return GetUpper()->GetUpper()->FindNextBox( rTable, GetUpper(), bOvrTableLns );
2235 pLine = GetUpper()->GetTabLines()[nFndPos+1];
2236 }
2237 else if( bOvrTableLns ) // Over a Table's the "BaseLines"??
2238 {
2239 // Search for the next Line in the Table
2240 nFndPos = rTable.GetTabLines().GetPos( pLine );
2241 if( nFndPos + 1 >= o3tl::narrowing<sal_uInt16>(rTable.GetTabLines().size()) )
2242 return nullptr; // there are no more Boxes
2243
2244 pLine = rTable.GetTabLines()[ nFndPos+1 ];
2245 }
2246 else
2247 return nullptr;
2248
2249 if( !pLine->GetTabBoxes().empty() )
2250 {
2251 pBox = pLine->GetTabBoxes().front();
2252 while( !pBox->GetTabLines().empty() )
2253 pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
2254 return pBox;
2255 }
2256 return pLine->FindNextBox( rTable, nullptr, bOvrTableLns );
2257}
2258
2259// Find the previous Box from this Line
2261 const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2262{
2263 const SwTableLine* pLine = this; // for M800
2264 SwTableBox* pBox;
2265 sal_uInt16 nFndPos;
2266 if( !GetTabBoxes().empty() && pSrchBox )
2267 {
2268 nFndPos = GetBoxPos( pSrchBox );
2269 if( USHRT_MAX != nFndPos && nFndPos )
2270 {
2271 pBox = GetTabBoxes()[ nFndPos - 1 ];
2272 while( !pBox->GetTabLines().empty() )
2273 {
2274 pLine = pBox->GetTabLines().back();
2275 pBox = pLine->GetTabBoxes().back();
2276 }
2277 return pBox;
2278 }
2279 }
2280
2281 if( GetUpper() )
2282 {
2283 nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2284 OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
2285 // Is there another Line?
2286 if( !nFndPos )
2287 return GetUpper()->GetUpper()->FindPreviousBox( rTable, GetUpper(), bOvrTableLns );
2288 pLine = GetUpper()->GetTabLines()[nFndPos-1];
2289 }
2290 else if( bOvrTableLns ) // Over a Table's the "BaseLines"??
2291 {
2292 // Search for the next Line in the Table
2293 nFndPos = rTable.GetTabLines().GetPos( pLine );
2294 if( !nFndPos )
2295 return nullptr; // there are no more Boxes
2296
2297 pLine = rTable.GetTabLines()[ nFndPos-1 ];
2298 }
2299 else
2300 return nullptr;
2301
2302 if( !pLine->GetTabBoxes().empty() )
2303 {
2304 pBox = pLine->GetTabBoxes().back();
2305 while( !pBox->GetTabLines().empty() )
2306 {
2307 pLine = pBox->GetTabLines().back();
2308 pBox = pLine->GetTabBoxes().back();
2309 }
2310 return pBox;
2311 }
2312 return pLine->FindPreviousBox( rTable, nullptr, bOvrTableLns );
2313}
2314
2315// Find the next Box with content from this Line
2317 const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2318{
2319 if( !pSrchBox && GetTabLines().empty() )
2320 return const_cast<SwTableBox*>(this);
2321 return GetUpper()->FindNextBox( rTable, pSrchBox ? pSrchBox : this,
2322 bOvrTableLns );
2323
2324}
2325
2326// Find the next Box with content from this Line
2328 const SwTableBox* pSrchBox ) const
2329{
2330 if( !pSrchBox && GetTabLines().empty() )
2331 return const_cast<SwTableBox*>(this);
2332 return GetUpper()->FindPreviousBox( rTable, pSrchBox ? pSrchBox : this );
2333}
2334
2335static void lcl_BoxSetHeadCondColl( const SwTableBox* pBox )
2336{
2337 // We need to adapt the paragraphs with conditional templates in the HeadLine
2338 const SwStartNode* pSttNd = pBox->GetSttNd();
2339 if( pSttNd )
2340 pSttNd->CheckSectionCondColl();
2341 else
2342 for( const SwTableLine* pLine : pBox->GetTabLines() )
2343 sw_LineSetHeadCondColl( pLine );
2344}
2345
2347{
2348 for( const SwTableBox* pBox : pLine->GetTabBoxes() )
2350}
2351
2352static SwTwips lcl_GetDistance( SwTableBox* pBox, bool bLeft )
2353{
2354 bool bFirst = true;
2355 SwTwips nRet = 0;
2356 SwTableLine* pLine;
2357 while( pBox )
2358 {
2359 pLine = pBox->GetUpper();
2360 if( !pLine )
2361 break;
2362 sal_uInt16 nStt = 0, nPos = pLine->GetBoxPos( pBox );
2363
2364 if( bFirst && !bLeft )
2365 ++nPos;
2366 bFirst = false;
2367
2368 while( nStt < nPos )
2369 nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrameFormat()
2370 ->GetFrameSize().GetWidth();
2371 pBox = pLine->GetUpper();
2372 }
2373 return nRet;
2374}
2375
2376static bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2377 SwTwips nDist, bool bCheck )
2378{
2379 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2380 for( auto pBox : rBoxes )
2381 {
2382 SwFrameFormat* pFormat = pBox->GetFrameFormat();
2383 const SwFormatFrameSize& rSz = pFormat->GetFrameSize();
2384 SwTwips nWidth = rSz.GetWidth();
2385 bool bGreaterBox = false;
2386
2387 if( bCheck )
2388 {
2389 for( auto pLn : pBox->GetTabLines() )
2390 if( !::lcl_SetSelBoxWidth( pLn, rParam, nDist, true ))
2391 return false;
2392
2393 // Collect all "ContentBoxes"
2394 bGreaterBox = (TableChgMode::FixedWidthChangeAbs != rParam.nMode)
2395 && ((nDist + (rParam.bLeft ? 0 : nWidth)) >= rParam.nSide);
2396 if (bGreaterBox
2397 || (!rParam.bBigger
2398 && (std::abs(nDist + ((rParam.nMode != TableChgMode::FixedWidthChangeAbs && rParam.bLeft) ? 0 : nWidth) - rParam.nSide) < COLFUZZY)))
2399 {
2400 SwTwips nLowerDiff;
2401 if( bGreaterBox && TableChgMode::FixedWidthChangeProp == rParam.nMode )
2402 {
2403 // The "other Boxes" have been adapted, so change by this value
2404 nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2405 nLowerDiff *= rParam.nDiff;
2406 nLowerDiff /= rParam.nMaxSize;
2407 nLowerDiff = rParam.nDiff - nLowerDiff;
2408 }
2409 else
2410 nLowerDiff = rParam.nDiff;
2411
2412 if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
2413 return false;
2414 }
2415 }
2416 else
2417 {
2418 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2419 for( auto pLn : pBox->GetTabLines() )
2420 {
2421 rParam.nLowerDiff = 0;
2422 lcl_SetSelBoxWidth( pLn, rParam, nDist, false );
2423
2424 if( nLowerDiff < rParam.nLowerDiff )
2425 nLowerDiff = rParam.nLowerDiff;
2426 }
2427 rParam.nLowerDiff = nOldLower;
2428
2429 if( nLowerDiff ||
2430 (bGreaterBox = !nOldLower && TableChgMode::FixedWidthChangeAbs != rParam.nMode &&
2431 ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide) ||
2432 ( std::abs( nDist + ( (rParam.nMode != TableChgMode::FixedWidthChangeAbs && rParam.bLeft) ? 0 : nWidth )
2433 - rParam.nSide ) < COLFUZZY ))
2434 {
2435 // This column contains the Cursor - so decrease/increase
2436 SwFormatFrameSize aNew( rSz );
2437
2438 if( !nLowerDiff )
2439 {
2440 if( bGreaterBox && TableChgMode::FixedWidthChangeProp == rParam.nMode )
2441 {
2442 // The "other Boxes" have been adapted, so change by this value
2443 nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2444 nLowerDiff *= rParam.nDiff;
2445 nLowerDiff /= rParam.nMaxSize;
2446 nLowerDiff = rParam.nDiff - nLowerDiff;
2447 }
2448 else
2449 nLowerDiff = rParam.nDiff;
2450 }
2451
2452 rParam.nLowerDiff += nLowerDiff;
2453
2454 if( rParam.bBigger )
2455 aNew.SetWidth( nWidth + nLowerDiff );
2456 else
2457 aNew.SetWidth( nWidth - nLowerDiff );
2458 rParam.aShareFormats.SetSize( *pBox, aNew );
2459 break;
2460 }
2461 }
2462
2463 if( rParam.bLeft && rParam.nMode != TableChgMode::FixedWidthChangeAbs && nDist >= rParam.nSide )
2464 break;
2465
2466 nDist += nWidth;
2467
2468 // If it gets bigger, then that's it
2469 if( ( TableChgMode::FixedWidthChangeAbs == rParam.nMode || !rParam.bLeft ) &&
2470 nDist >= rParam.nSide )
2471 break;
2472 }
2473 return true;
2474}
2475
2476static bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2477 SwTwips nDist, bool bCheck )
2478{
2479 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2480 for( auto pBox : rBoxes )
2481 {
2482 SwFrameFormat* pFormat = pBox->GetFrameFormat();
2483 const SwFormatFrameSize& rSz = pFormat->GetFrameSize();
2484 SwTwips nWidth = rSz.GetWidth();
2485
2486 if( bCheck )
2487 {
2488 for( auto pLn : pBox->GetTabLines() )
2489 if( !::lcl_SetOtherBoxWidth( pLn, rParam, nDist, true ))
2490 return false;
2491
2492 if( rParam.bBigger && ( TableChgMode::FixedWidthChangeAbs == rParam.nMode
2493 ? std::abs( nDist - rParam.nSide ) < COLFUZZY
2494 : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2495 : nDist >= rParam.nSide - COLFUZZY )) )
2496 {
2497 SwTwips nDiff;
2498 if( TableChgMode::FixedWidthChangeProp == rParam.nMode ) // Table fixed, proportional
2499 {
2500 // calculate relative
2501 nDiff = nWidth;
2502 nDiff *= rParam.nDiff;
2503 nDiff /= rParam.nMaxSize;
2504 }
2505 else
2506 nDiff = rParam.nDiff;
2507
2508 if( nWidth < nDiff || nWidth - nDiff < MINLAY )
2509 return false;
2510 }
2511 }
2512 else
2513 {
2514 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2515 for( auto pLn : pBox->GetTabLines() )
2516 {
2517 rParam.nLowerDiff = 0;
2518 lcl_SetOtherBoxWidth( pLn, rParam, nDist, false );
2519
2520 if( nLowerDiff < rParam.nLowerDiff )
2521 nLowerDiff = rParam.nLowerDiff;
2522 }
2523 rParam.nLowerDiff = nOldLower;
2524
2525 if( nLowerDiff ||
2526 ( TableChgMode::FixedWidthChangeAbs == rParam.nMode
2527 ? std::abs( nDist - rParam.nSide ) < COLFUZZY
2528 : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2529 : nDist >= rParam.nSide - COLFUZZY)
2530 ) )
2531 {
2532 SwFormatFrameSize aNew( rSz );
2533
2534 if( !nLowerDiff )
2535 {
2536 if( TableChgMode::FixedWidthChangeProp == rParam.nMode ) // Table fixed, proportional
2537 {
2538 // calculate relative
2539 nLowerDiff = nWidth;
2540 nLowerDiff *= rParam.nDiff;
2541 nLowerDiff /= rParam.nMaxSize;
2542 }
2543 else
2544 nLowerDiff = rParam.nDiff;
2545 }
2546
2547 rParam.nLowerDiff += nLowerDiff;
2548
2549 if( rParam.bBigger )
2550 aNew.SetWidth( nWidth - nLowerDiff );
2551 else
2552 aNew.SetWidth( nWidth + nLowerDiff );
2553
2554 rParam.aShareFormats.SetSize( *pBox, aNew );
2555 }
2556 }
2557
2558 nDist += nWidth;
2559 if( ( TableChgMode::FixedWidthChangeAbs == rParam.nMode || rParam.bLeft ) &&
2560 nDist > rParam.nSide )
2561 break;
2562 }
2563 return true;
2564}
2565
2566static void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
2567{
2568 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2569 for( auto pBox : rBoxes )
2570 {
2572 SwTwips nWidth = aSz.GetWidth();
2573 nWidth *= rParam.nDiff;
2574 nWidth /= rParam.nMaxSize;
2575 aSz.SetWidth( nWidth );
2576 rParam.aShareFormats.SetSize( *pBox, aSz );
2577
2578 for( auto pLn : pBox->GetTabLines() )
2579 ::lcl_AjustLines( pLn, rParam );
2580 }
2581}
2582
2583#ifdef DBG_UTIL
2584void CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
2585{
2586 const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
2587
2588 SwTwips nCurrentSize = 0;
2589 // See if the tables have a correct width
2590 for (const SwTableBox* pBox : rBoxes)
2591 {
2592 const SwTwips nBoxW = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
2593 nCurrentSize += nBoxW;
2594
2595 for( auto pLn : pBox->GetTabLines() )
2596 CheckBoxWidth( *pLn, nBoxW );
2597 }
2598
2599 if (sal::static_int_cast< tools::ULong >(std::abs(nCurrentSize - nSize)) >
2600 (COLFUZZY * rBoxes.size()))
2601 {
2602 OSL_FAIL( "Line's Boxes are too small or too large" );
2603 }
2604}
2605#endif
2606
2608 SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr<SwUndo>* ppUndo )
2609{
2610 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
2611
2613 const SvxLRSpaceItem& rLR = GetFrameFormat()->GetLRSpace();
2614
2615 bool bBigger,
2616 bRet = false,
2619
2620 // Get the current Box's edge
2621 // Only needed for manipulating the width
2622 const SwTwips nDist = ::lcl_GetDistance( &rCurrentBox, bLeft );
2623 SwTwips nDistStt = 0;
2624 CR_SetBoxWidth aParam( eType, nRelDiff, nDist,
2625 bLeft ? nDist : rSz.GetWidth() - nDist,
2626 const_cast<SwTableNode*>(rCurrentBox.GetSttNd()->FindTableNode()) );
2627 bBigger = aParam.bBigger;
2628
2629 FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
2630 fnSelBox = lcl_SetSelBoxWidth;
2631 fnOtherBox = lcl_SetOtherBoxWidth;
2632
2633 switch( extractPosition(eType) )
2634 {
2638 {
2639 // First test if we have room at all
2640 bool bChgLRSpace = true;
2641 if( bBigger )
2642 {
2643 if( GetFrameFormat()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) &&
2644 !rSz.GetWidthPercent() )
2645 {
2646 // silence -Wsign-compare on Android with the static cast
2647 bRet = rSz.GetWidth() < static_cast<unsigned short>(USHRT_MAX) - nRelDiff;
2648 bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
2649 : rLR.GetRight() >= nAbsDiff;
2650 }
2651 else
2652 bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
2653 : rLR.GetRight() >= nAbsDiff;
2654
2655 if( !bRet )
2656 {
2657 // Then call itself recursively; only with another mode (proportional)
2660
2661 bRet = SetColWidth( rCurrentBox, eType, nAbsDiff, nRelDiff,
2662 ppUndo );
2663 m_eTableChgMode = eOld;
2664 return bRet;
2665 }
2666 }
2667 else
2668 {
2669 bRet = true;
2670 for( auto const & n: m_aLines )
2671 {
2672 aParam.LoopClear();
2673 if( !(*fnSelBox)( n, aParam, nDistStt, true ))
2674 {
2675 bRet = false;
2676 break;
2677 }
2678 }
2679 }
2680
2681 if( bRet )
2682 {
2683 if( ppUndo )
2684 ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
2685
2686 tools::Long nFrameWidth = LONG_MAX;
2687 LockModify();
2688 SwFormatFrameSize aSz( rSz );
2689 SvxLRSpaceItem aLR( rLR );
2690 if( bBigger )
2691 {
2692 // If the Table does not have any room to grow, we need to create some!
2693 // silence -Wsign-compare on Android with the static cast
2694 if( aSz.GetWidth() + nRelDiff > static_cast<unsigned short>(USHRT_MAX) )
2695 {
2696 // Break down to USHRT_MAX / 2
2697 CR_SetBoxWidth aTmpPara( TableChgWidthHeightType::ColLeft, aSz.GetWidth() / 2,
2698 0, aSz.GetWidth(), aParam.pTableNd );
2699 for( size_t nLn = 0; nLn < m_aLines.size(); ++nLn )
2700 ::lcl_AjustLines( m_aLines[ nLn ], aTmpPara );
2701 aSz.SetWidth( aSz.GetWidth() / 2 );
2702 aParam.nDiff = nRelDiff /= 2;
2703 aParam.nSide /= 2;
2704 aParam.nMaxSize /= 2;
2705 }
2706
2707 if( bLeft )
2708 aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) );
2709 else
2710 aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) );
2711 }
2712 else if( bLeft )
2713 aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) );
2714 else
2715 aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) );
2716
2717 if( bChgLRSpace )
2718 GetFrameFormat()->SetFormatAttr( aLR );
2720 if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
2721 (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
2722 (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
2723 {
2724 SwFormatHoriOrient aHOri( rHOri );
2726 GetFrameFormat()->SetFormatAttr( aHOri );
2727
2728 // If the Table happens to contain relative values (USHORT_MAX),
2729 // we need to convert them to absolute ones now.
2730 // Bug 61494
2731 if( GetFrameFormat()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) &&
2732 !rSz.GetWidthPercent() )
2733 {
2735 if( pTabFrame &&
2736 pTabFrame->getFramePrintArea().Width() != rSz.GetWidth() )
2737 {
2738 nFrameWidth = pTabFrame->getFramePrintArea().Width();
2739 if( bBigger )
2740 nFrameWidth += nAbsDiff;
2741 else
2742 nFrameWidth -= nAbsDiff;
2743 }
2744 }
2745 }
2746
2747 if( bBigger )
2748 aSz.SetWidth( aSz.GetWidth() + nRelDiff );
2749 else
2750 aSz.SetWidth( aSz.GetWidth() - nRelDiff );
2751
2752 if( rSz.GetWidthPercent() )
2753 aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) /
2754 ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
2755
2756 GetFrameFormat()->SetFormatAttr( aSz );
2757
2758 UnlockModify();
2759
2760 for( sal_uInt16 n = m_aLines.size(); n; )
2761 {
2762 --n;
2763 aParam.LoopClear();
2764 (*fnSelBox)( m_aLines[ n ], aParam, nDistStt, false );
2765 }
2766
2767 // If the Table happens to contain relative values (USHORT_MAX),
2768 // we need to convert them to absolute ones now.
2769 // Bug 61494
2770 if( LONG_MAX != nFrameWidth )
2771 {
2772 SwFormatFrameSize aAbsSz( aSz );
2773 aAbsSz.SetWidth( nFrameWidth );
2774 GetFrameFormat()->SetFormatAttr( aAbsSz );
2775 }
2776 }
2777 }
2778 else if( bLeft ? nDist != 0 : std::abs( rSz.GetWidth() - nDist ) > COLFUZZY )
2779 {
2780 bRet = true;
2782 aParam.bBigger = !bBigger;
2783
2784 // First test if we have room at all
2785 if( aParam.bBigger )
2786 {
2787 for( auto const & n: m_aLines )
2788 {
2789 aParam.LoopClear();
2790 if( !(*fnOtherBox)( n, aParam, 0, true ))
2791 {
2792 bRet = false;
2793 break;
2794 }
2795 }
2796 }
2797 else
2798 {
2799 for( auto const & n: m_aLines )
2800 {
2801 aParam.LoopClear();
2802 if( !(*fnSelBox)( n, aParam, nDistStt, true ))
2803 {
2804 bRet = false;
2805 break;
2806 }
2807 }
2808 }
2809
2810 // If true, set it
2811 if( bRet )
2812 {
2813 CR_SetBoxWidth aParam1( aParam );
2814 if( ppUndo )
2815 ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
2816
2818 {
2819 for( sal_uInt16 n = m_aLines.size(); n; )
2820 {
2821 --n;
2822 aParam.LoopClear();
2823 aParam1.LoopClear();
2824 (*fnSelBox)( m_aLines[ n ], aParam, nDistStt, false );
2825 (*fnOtherBox)( m_aLines[ n ], aParam1, nDistStt, false );
2826 }
2827 }
2828 else
2829 {
2830 for( sal_uInt16 n = m_aLines.size(); n; )
2831 {
2832 --n;
2833 aParam.LoopClear();
2834 aParam1.LoopClear();
2835 (*fnOtherBox)( m_aLines[ n ], aParam1, nDistStt, false );
2836 (*fnSelBox)( m_aLines[ n ], aParam, nDistStt, false );
2837 }
2838 }
2839 }
2840 }
2841 break;
2842
2846 {
2847 // Then call itself recursively; only with another mode (proportional)
2850
2851 bRet = SetColWidth( rCurrentBox, eType, nAbsDiff, nRelDiff,
2852 ppUndo );
2853 m_eTableChgMode = eOld;
2854 return bRet;
2855 }
2856 else if( bLeft ? nDist != 0 : (rSz.GetWidth() - nDist) > COLFUZZY )
2857 {
2859 aParam.bBigger = !bBigger;
2860
2861 // First, see if there is enough room at all
2862 SwTableBox* pBox = &rCurrentBox;
2863 SwTableLine* pLine = rCurrentBox.GetUpper();
2864 while( pLine->GetUpper() )
2865 {
2866 const SwTableBoxes::size_type nPos = pLine->GetBoxPos( pBox );
2867 if( bLeft ? nPos != 0 : nPos + 1 != pLine->GetTabBoxes().size() )
2868 break;
2869
2870 pBox = pLine->GetUpper();
2871 pLine = pBox->GetUpper();
2872 }
2873
2874 if( pLine->GetUpper() )
2875 {
2876 // We need to correct the distance once again!
2877 aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), true );
2878
2879 if( bLeft )
2880 aParam.nMaxSize = aParam.nSide;
2881 else
2882 aParam.nMaxSize = pLine->GetUpper()->GetFrameFormat()->
2883 GetFrameSize().GetWidth() - aParam.nSide;
2884 }
2885
2886 // First, see if there is enough room at all
2887 FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
2888 bRet = (*fnTmp)( pLine, aParam, nDistStt, true );
2889
2890 // If true, set it
2891 if( bRet )
2892 {
2893 CR_SetBoxWidth aParam1( aParam );
2894 if( ppUndo )
2895 ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
2896
2898 {
2899 (*fnSelBox)( pLine, aParam, nDistStt, false );
2900 (*fnOtherBox)( pLine, aParam1, nDistStt, false );
2901 }
2902 else
2903 {
2904 (*fnOtherBox)( pLine, aParam1, nDistStt, false );
2905 (*fnSelBox)( pLine, aParam, nDistStt, false );
2906 }
2907 }
2908 }
2909 break;
2910 default: break;
2911 }
2912
2913#if defined DBG_UTIL
2914 if( bRet )
2915 {
2918 }
2919#endif
2920
2921 return bRet;
2922}
2923
2924static void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
2925 bool bMinSize )
2926{
2927 SwLayoutFrame* pLineFrame = GetRowFrame( rLine );
2928 OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine?" );
2929
2930 SwFrameFormat* pFormat = rLine.ClaimFrameFormat();
2931
2932 SwTwips nMyNewH, nMyOldH = pLineFrame->getFrameArea().Height();
2933 if( !nOldHeight ) // the BaseLine and absolute
2934 nMyNewH = nMyOldH + nNewHeight;
2935 else
2936 {
2937 // Calculate as exactly as possible
2938 Fraction aTmp( nMyOldH );
2939 aTmp *= Fraction( nNewHeight, nOldHeight );
2940 aTmp += Fraction( 1, 2 ); // round up if needed
2941 nMyNewH = tools::Long(aTmp);
2942 }
2943
2945 if( !bMinSize &&
2946 ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrame ) + ROWFUZZY ))
2947 eSize = SwFrameSize::Fixed;
2948
2949 pFormat->SetFormatAttr( SwFormatFrameSize( eSize, 0, nMyNewH ) );
2950
2951 // First adapt all internal ones
2952 for( auto pBox : rLine.GetTabBoxes() )
2953 {
2954 for( auto pLine : pBox->GetTabLines() )
2955 SetLineHeight( *pLine, nMyOldH, nMyNewH, bMinSize );
2956 }
2957}
2958
2959static bool lcl_SetSelLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
2960 SwTwips nDist, bool bCheck )
2961{
2962 bool bRet = true;
2963 if( !bCheck )
2964 {
2965 // Set line height
2966 SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
2967 rParam.bBigger );
2968 }
2969 else if( !rParam.bBigger )
2970 {
2971 // Calculate the new relative size by means of the old one
2972 SwLayoutFrame* pLineFrame = GetRowFrame( *pLine );
2973 OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine?" );
2974 SwTwips nRstHeight = CalcRowRstHeight( pLineFrame );
2975 if( (nRstHeight + ROWFUZZY) < nDist )
2976 bRet = false;
2977 }
2978 return bRet;
2979}
2980
2981static bool lcl_SetOtherLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
2982 SwTwips nDist, bool bCheck )
2983{
2984 bool bRet = true;
2985 if( bCheck )
2986 {
2987 if( rParam.bBigger )
2988 {
2989 // Calculate the new relative size by means of the old one
2990 SwLayoutFrame* pLineFrame = GetRowFrame( *pLine );
2991 OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine?" );
2992
2993 if( TableChgMode::FixedWidthChangeProp == rParam.nMode )
2994 {
2995 nDist *= pLineFrame->getFrameArea().Height();
2996 nDist /= rParam.nMaxHeight;
2997 }
2998 bRet = nDist <= CalcRowRstHeight( pLineFrame );
2999 }
3000 }
3001 else
3002 {
3003 // Set line height
3004 // pLine is the following/preceding, thus adjust it
3005 if( TableChgMode::FixedWidthChangeProp == rParam.nMode )
3006 {
3007 SwLayoutFrame* pLineFrame = GetRowFrame( *pLine );
3008 OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine??" );
3009
3010 // Calculate the new relative size by means of the old one
3011 // If the selected Box get bigger, adjust via the max space else
3012 // via the max height.
3013 if( (true) )
3014 {
3015 nDist *= pLineFrame->getFrameArea().Height();
3016 nDist /= rParam.nMaxHeight;
3017 }
3018 else
3019 {
3020 // Calculate the new relative size by means of the old one
3021 nDist *= CalcRowRstHeight( pLineFrame );
3022 nDist /= rParam.nMaxSpace;
3023 }
3024 }
3025 SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
3026 !rParam.bBigger );
3027 }
3028 return bRet;
3029}
3030
3032 SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr<SwUndo>* ppUndo )
3033{
3034 SwTableLine* pLine = rCurrentBox.GetUpper();
3035
3036 SwTableLine* pBaseLine = pLine;
3037 while( pBaseLine->GetUpper() )
3038 pBaseLine = pBaseLine->GetUpper()->GetUpper();
3039
3040 bool bBigger,
3041 bRet = false,
3043 sal_uInt16 nBaseLinePos = GetTabLines().GetPos( pBaseLine );
3044
3045 CR_SetLineHeight aParam( eType,
3046 const_cast<SwTableNode*>(rCurrentBox.GetSttNd()->FindTableNode()) );
3047 bBigger = aParam.bBigger;
3048
3049 SwTableLines* pLines = &m_aLines;
3050
3051 // How do we get to the height?
3052 switch( extractPosition(eType) )
3053 {
3056 if( pLine == pBaseLine )
3057 break; // it doesn't work then!
3058
3059 // Is a nested Line (Box!)
3060 pLines = &pLine->GetUpper()->GetTabLines();
3061 nBaseLinePos = pLines->GetPos( pLine );
3062 [[fallthrough]];
3063
3065 {
3067 {
3068 // First test if we have room at all
3069 if( bBigger )
3070 bRet = true;
3071 else
3072 bRet = lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3073 nAbsDiff, true );
3074
3075 if( bRet )
3076 {
3077 if( ppUndo )
3078 ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
3079
3080 lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3081 nAbsDiff, false );
3082 }
3083 }
3084 else
3085 {
3086 bRet = true;
3089 if( bTop )
3090 {
3091 nStt = 0;
3092 nEnd = nBaseLinePos;
3093 }
3094 else
3095 {
3096 nStt = nBaseLinePos + 1;
3097 nEnd = pLines->size();
3098 }
3099
3100 // Get the current Lines' height
3102 {
3103 for( auto n = nStt; n < nEnd; ++n )
3104 {
3105 SwLayoutFrame* pLineFrame = GetRowFrame( *(*pLines)[ n ] );
3106 OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine??" );
3107 aParam.nMaxSpace += CalcRowRstHeight( pLineFrame );
3108 aParam.nMaxHeight += pLineFrame->getFrameArea().Height();
3109 }
3110 if( bBigger && aParam.nMaxSpace < nAbsDiff )
3111 bRet = false;
3112 }
3113 else
3114 {
3115 if( bTop ? nEnd != 0 : nStt < nEnd )
3116 {
3117 if( bTop )
3118 nStt = nEnd - 1;
3119 else
3120 nEnd = nStt + 1;
3121 }
3122 else
3123 bRet = false;
3124 }
3125
3126 if( bRet )
3127 {
3128 if( bBigger )
3129 {
3130 for( auto n = nStt; n < nEnd; ++n )
3131 {
3132 if( !lcl_SetOtherLineHeight( (*pLines)[ n ], aParam,
3133 nAbsDiff, true ))
3134 {
3135 bRet = false;
3136 break;
3137 }
3138 }
3139 }
3140 else
3141 bRet = lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3142 nAbsDiff, true );
3143 }
3144
3145 if( bRet )
3146 {
3147 // Adjust
3148 if( ppUndo )
3149 ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
3150
3151 CR_SetLineHeight aParam1( aParam );
3152
3153 if( bTop )
3154 {
3155 lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3156 nAbsDiff, false );
3157 for( auto n = nStt; n < nEnd; ++n )
3158 lcl_SetOtherLineHeight( (*pLines)[ n ], aParam1,
3159 nAbsDiff, false );
3160 }
3161 else
3162 {
3163 for( auto n = nStt; n < nEnd; ++n )
3164 lcl_SetOtherLineHeight( (*pLines)[ n ], aParam1,
3165 nAbsDiff, false );
3166 lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3167 nAbsDiff, false );
3168 }
3169 }
3170 else
3171 {
3172 // Then call itself recursively; only with another mode (proportional)
3175
3176 bRet = SetRowHeight( rCurrentBox, eType, nAbsDiff,
3177 nRelDiff, ppUndo );
3178
3179 m_eTableChgMode = eOld;
3180 }
3181 }
3182 }
3183 break;
3184 default: break;
3185 }
3186
3188
3189 return bRet;
3190}
3191
3193{
3194 SwFrameFormat *pRet = nullptr, *pTmp;
3195 for( auto n = m_aNewFormats.size(); n; )
3196 if( ( pTmp = m_aNewFormats[ --n ])->GetFrameSize().GetWidth()
3197 == nWidth )
3198 {
3199 pRet = pTmp;
3200 break;
3201 }
3202 return pRet;
3203}
3204
3206{
3207 const SfxPoolItem* pItem;
3208 sal_uInt16 nWhich = rItem.Which();
3209 SwFrameFormat *pRet = nullptr, *pTmp;
3210 const SfxPoolItem& rFrameSz = m_pOldFormat->GetFormatAttr( RES_FRM_SIZE, false );
3211 for( auto n = m_aNewFormats.size(); n; )
3212 if( SfxItemState::SET == ( pTmp = m_aNewFormats[ --n ])->
3213 GetItemState( nWhich, false, &pItem ) && *pItem == rItem &&
3214 pTmp->GetFormatAttr( RES_FRM_SIZE, false ) == rFrameSz )
3215 {
3216 pRet = pTmp;
3217 break;
3218 }
3219 return pRet;
3220}
3221
3223{
3224 m_aNewFormats.push_back( &rNew );
3225}
3226
3228{
3229 // returns true, if we can delete
3230 if( m_pOldFormat == &rFormat )
3231 return true;
3232
3233 std::vector<SwFrameFormat*>::iterator it = std::find( m_aNewFormats.begin(), m_aNewFormats.end(), &rFormat );
3234 if( m_aNewFormats.end() != it )
3235 m_aNewFormats.erase( it );
3236 return m_aNewFormats.empty();
3237}
3238
3240{
3241}
3242
3244{
3245 sal_uInt16 nPos;
3246 return Seek_Entry( rFormat, &nPos )
3247 ? m_ShareArr[ nPos ].GetFormat(nWidth)
3248 : nullptr;
3249}
3251 const SfxPoolItem& rItem ) const
3252{
3253 sal_uInt16 nPos;
3254 return Seek_Entry( rFormat, &nPos )
3255 ? m_ShareArr[ nPos ].GetFormat(rItem)
3256 : nullptr;
3257}
3258
3260{
3261 sal_uInt16 nPos;
3262 if( !Seek_Entry( rOld, &nPos ))
3263 {
3264 SwShareBoxFormat aEntry(rOld);
3265 aEntry.AddFormat( rNew );
3266 m_ShareArr.insert(m_ShareArr.begin() + nPos, aEntry);
3267 }
3268 else
3269 m_ShareArr[ nPos ].AddFormat(rNew);
3270}
3271
3273 SwFrameFormat& rFormat )
3274{
3275 SwClient aCl;
3276 SwFrameFormat* pOld = nullptr;
3277 if( pBox )
3278 {
3279 pOld = pBox->GetFrameFormat();
3280 pOld->Add( &aCl );
3281 pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(&rFormat) );
3282 }
3283 else if( pLn )
3284 {
3285 pOld = pLn->GetFrameFormat();
3286 pOld->Add( &aCl );
3287 pLn->ChgFrameFormat( static_cast<SwTableLineFormat*>(&rFormat) );
3288 }
3289 if( pOld && pOld->HasOnlyOneListener() )
3290 {
3291 RemoveFormat( *pOld );
3292 delete pOld;
3293 }
3294}
3295
3297{
3298 SwFrameFormat *pBoxFormat = rBox.GetFrameFormat(),
3299 *pRet = GetFormat( *pBoxFormat, rSz.GetWidth() );
3300 if( pRet )
3301 ChangeFrameFormat( &rBox, nullptr, *pRet );
3302 else
3303 {
3304 pRet = rBox.ClaimFrameFormat();
3305 pRet->SetFormatAttr( rSz );
3306 AddFormat( *pBoxFormat, *pRet );
3307 }
3308}
3309
3311{
3312 SwFrameFormat *pBoxFormat = rBox.GetFrameFormat(),
3313 *pRet = GetFormat( *pBoxFormat, rItem );
3314 if( pRet )
3315 ChangeFrameFormat( &rBox, nullptr, *pRet );
3316 else
3317 {
3318 pRet = rBox.ClaimFrameFormat();
3319 pRet->SetFormatAttr( rItem );
3320 AddFormat( *pBoxFormat, *pRet );
3321 }
3322}
3323
3325{
3326 SwFrameFormat *pLineFormat = rLine.GetFrameFormat(),
3327 *pRet = GetFormat( *pLineFormat, rItem );
3328 if( pRet )
3329 ChangeFrameFormat( nullptr, &rLine, *pRet );
3330 else
3331 {
3332 pRet = rLine.ClaimFrameFormat();
3333 pRet->SetFormatAttr( rItem );
3334 AddFormat( *pLineFormat, *pRet );
3335 }
3336}
3337
3339{
3340 for (auto i = m_ShareArr.size(); i; )
3341 {
3342 if (m_ShareArr[ --i ].RemoveFormat(rFormat))
3343 {
3344 m_ShareArr.erase( m_ShareArr.begin() + i );
3345 }
3346 }
3347}
3348
3349bool SwShareBoxFormats::Seek_Entry( const SwFrameFormat& rFormat, sal_uInt16* pPos ) const
3350{
3351 sal_uIntPtr nIdx = reinterpret_cast<sal_uIntPtr>(&rFormat);
3352 auto nO = m_ShareArr.size();
3353 decltype(nO) nU = 0;
3354 if( nO > 0 )
3355 {
3356 nO--;
3357 while( nU <= nO )
3358 {
3359 const auto nM = nU + ( nO - nU ) / 2;
3360 sal_uIntPtr nFormat = reinterpret_cast<sal_uIntPtr>(&m_ShareArr[ nM ].GetOldFormat());
3361 if( nFormat == nIdx )
3362 {
3363 if( pPos )
3364 *pPos = nM;
3365 return true;
3366 }
3367 else if( nFormat < nIdx )
3368 nU = nM + 1;
3369 else if( nM == 0 )
3370 {
3371 if( pPos )
3372 *pPos = nU;
3373 return false;
3374 }
3375 else
3376 nO = nM - 1;
3377 }
3378 }
3379 if( pPos )
3380 *pPos = nU;
3381 return false;
3382}
3383
3384/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt32 GetValue() const
void SetTableLines(const SwSelBoxes &rBoxes, const SwTable &rTable)
Definition: tblsel.cxx:2096
const FndLine_ * GetUpper() const
Definition: tblsel.hxx:176
const FndLines_t & GetLines() const
Definition: tblsel.hxx:172
void MakeNewFrames(SwTable &rTable, const sal_uInt16 nNumber, const bool bBehind)
Definition: tblsel.cxx:2401
void MakeFrames(SwTable &rTable)
Definition: tblsel.cxx:2319
bool AreLinesToRestore(const SwTable &rTable) const
Definition: tblsel.cxx:2541
void DelFrames(SwTable &rTable)
Definition: tblsel.cxx:2158
const SwTableBox * GetBox() const
Definition: tblsel.hxx:174
const FndBoxes_t & GetBoxes() const
Definition: tblsel.hxx:202
const SwTableLine * GetLine() const
Definition: tblsel.hxx:204
virtual SwChartDataProvider * GetChartDataProvider(bool bCreate=false) const =0
returns or creates the data-provider for chart
virtual void CreateChartInternalDataProviders(const SwTable *pTable)=0
calls createInternalDataProvider for all charts using the specified table
virtual void DeleteSection(SwNode *pNode)=0
Delete section containing the node.
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
virtual SwFieldType * InsertFieldType(const SwFieldType &)=0
virtual void UpdateTableFields(SfxPoolItem *pHt)=0
virtual const SwExtraRedlineTable & GetExtraRedlineTable() const =0
static bool IsRedlineOn(const RedlineFlags eM)
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
sal_uInt16 Count() const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_uInt16 Which() const
sal_uInt32 GetMergeFormatIndex(sal_uInt32 nOldFmt) const
bool HasMergeFormatTable() const
const editeng::SvxBorderLine * GetTop() const
const editeng::SvxBorderLine * GetRight() const
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxItemLine nLine)
const editeng::SvxBorderLine * GetLeft() const
const editeng::SvxBorderLine * GetBottom() const
void SetRight(const tools::Long nR, const sal_uInt16 nProp=100)
tools::Long GetRight() const
tools::Long GetLeft() const
void SetLeft(const tools::Long nL, const sal_uInt16 nProp=100)
tools::Long GetHeight() const
tools::Long GetWidth() const
void SetHeight(tools::Long n)
void SetWidth(tools::Long n)
void AddRowCols(const SwTable &rTable, const SwSelBoxes &rBoxes, sal_uInt16 nLines, bool bBehind)
SwChartDataProvider::AddRowCols tries to notify charts of added columns or rows and extends the value...
Definition: unochart.cxx:1558
void DeleteBox(const SwTable *pTable, const SwTableBox &rBox)
Definition: unochart.cxx:1457
Class for SplitTable Collects the uppermost or lowermost Lines of a Box from a Line in an array.
Definition: tblrwcl.hxx:61
bool Resize(sal_uInt16 nOffset, sal_uInt16 nWidth)
Definition: ndtbl.cxx:2957
void SetValues(bool bFlag)
Definition: tblrwcl.hxx:96
SwFEShell * GetFEShell()
For Core - it knows the DocShell but not the WrtShell!
Definition: docsh.cxx:1225
Definition: doc.hxx:194
bool IsInReading() const
Definition: doc.hxx:962
SwTextFormatColl * CopyTextColl(const SwTextFormatColl &rColl)
copy TextNodes
Definition: docfmt.cxx:1173
void UpdateCharts(const OUString &rName) const
Definition: docchart.cxx:141
IDocumentChartDataProviderAccess const & getIDocumentChartDataProviderAccess() const
Definition: doc.cxx:233
const SwTable * InsertTable(const SwInsertTableOptions &rInsTableOpts, const SwPosition &rPos, sal_uInt16 nRows, sal_uInt16 nCols, sal_Int16 eAdjust, const SwTableAutoFormat *pTAFormat=nullptr, const std::vector< sal_uInt16 > *pColArr=nullptr, bool bCalledFromShell=false, bool bNewModel=true)
Insert new table at position.
Definition: ndtbl.cxx:337
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:321
SwNodes & GetNodes()
Definition: doc.hxx:417
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:363
void SetRowNotTracked(const SwCursor &rCursor, const SvxPrintItem &rNotTracked, bool bAll=false, bool bIns=false)
rNotTracked = false means that the row was deleted or inserted with its tracked cell content bAll: de...
Definition: ndtbl1.cxx:581
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:341
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:432
::sw::DocumentContentOperationsManager const & GetDocumentContentOperationsManager() const
Definition: doc.cxx:331
SwDocShell * GetDocShell()
Definition: doc.hxx:1359
bool DeleteTableRowRedline(SwDoc *pDoc, const SwTableLine &rTableLine, bool bSaveInUndo, RedlineType nRedlineTypeToDelete)
Definition: docredln.cxx:190
bool DeleteTableCellRedline(SwDoc *pDoc, const SwTableBox &rTableBox, bool bSaveInUndo, RedlineType nRedlineTypeToDelete)
Definition: docredln.cxx:234
bool UpdateTableStyleFormatting(SwTableNode *pTableNode=nullptr, bool bResetDirect=false, OUString const *pStyleName=nullptr)
Update the direct formatting according to the current table style.
Definition: fetab.cxx:1318
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:242
void SetWidthPercent(sal_uInt8 n)
Definition: fmtfsize.hxx:95
void SetHeightSizeType(SwFrameSize eSize)
Definition: fmtfsize.hxx:81
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
SwFrameSize GetHeightSizeType() const
Definition: fmtfsize.hxx:80
Defines the horizontal position of a fly frame.
Definition: fmtornt.hxx:73
void SetHoriOrient(sal_Int16 eNew)
Definition: fmtornt.hxx:96
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:94
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:618
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
void CopyAttrs(const SwFormat &)
Copy attributes even among documents.
Definition: format.cxx:171
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:115
const SfxPoolItem & GetFormatAttr(sal_uInt16 nWhich, bool bInParents=true) const
If bInParents is FALSE, search only in this format for attribute.
Definition: format.cxx:366
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:447
const SwRect & getFrameArea() const
Definition: frame.hxx:179
const SwRect & getFramePrintArea() const
Definition: frame.hxx:180
Style of a layout element.
Definition: frmfmt.hxx:62
virtual void SetFormatName(const OUString &rNewName, bool bBroadcast=false) override
Definition: atrfrm.cxx:2593
TElementType * Next()
Definition: calbck.hxx:373
TElementType * First()
Definition: calbck.hxx:365
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame.
Definition: layfrm.hxx:36
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:136
Base class of the Writer document model elements.
Definition: node.hxx:98
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwDoc & GetDoc()
Definition: node.hxx:233
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:726
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:731
bool MoveNodes(const SwNodeRange &, SwNodes &rNodes, SwNode &rPos, bool bNewFrames=true)
move the node pointer
Definition: nodes.cxx:399
void Delete(const SwNodeIndex &rPos, SwNodeOffset nNodes=SwNodeOffset(1))
Definition: nodes.cxx:1065
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1381
void Height(tools::Long nNew)
Definition: swrect.hxx:193
void Width(tools::Long nNew)
Definition: swrect.hxx:189
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:29
SwFrameFormat * GetFormat(tools::Long nWidth) const
Definition: tblrwcl.cxx:3192
const SwFrameFormat * m_pOldFormat
Definition: tblrwcl.hxx:154
bool RemoveFormat(const SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3227
void AddFormat(SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3222
std::vector< SwFrameFormat * > m_aNewFormats
Definition: tblrwcl.hxx:155
std::vector< SwShareBoxFormat > m_ShareArr
Definition: tblrwcl.hxx:173
SwFrameFormat * GetFormat(const SwFrameFormat &rFormat, tools::Long nWidth) const
Definition: tblrwcl.cxx:3243
void RemoveFormat(const SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3338
void ChangeFrameFormat(SwTableBox *pBox, SwTableLine *pLn, SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3272
bool Seek_Entry(const SwFrameFormat &rFormat, sal_uInt16 *pPos) const
Definition: tblrwcl.cxx:3349
void SetAttr(SwTableBox &rBox, const SfxPoolItem &rItem)
Definition: tblrwcl.cxx:3310
void SetSize(SwTableBox &rBox, const SwFormatFrameSize &rSz)
Definition: tblrwcl.cxx:3296
void AddFormat(const SwFrameFormat &rOld, SwFrameFormat &rNew)
Definition: tblrwcl.cxx:3259
Starts a section of nodes in the document model.
Definition: node.hxx:348
void CheckSectionCondColl() const
Call ChkCondcoll to all ContentNodes of section.
Definition: node.cxx:995
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:47
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:426
SwTableLine * GetUpper()
Definition: swtable.hxx:460
void SetUpper(SwTableLine *pNew)
Definition: swtable.hxx:462
sal_Int32 getRowSpan() const
Definition: swtable.hxx:523
SwNodeOffset GetSttIdx() const
Definition: swtable.cxx:2065
void setRowSpan(sal_Int32 nNewRowSpan)
Definition: swtable.cxx:77
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:464
SwTableLines & GetTabLines()
Definition: swtable.hxx:457
void setDummyFlag(bool bDummy)
Definition: swtable.cxx:87
SwTableBox * FindPreviousBox(const SwTable &, const SwTableBox *) const
Definition: tblrwcl.cxx:2327
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:478
void ChgFrameFormat(SwTableBoxFormat *pNewFormat, bool bNeedToReregister=true)
Definition: swtable.cxx:1953
SwTableBox * FindNextBox(const SwTable &, const SwTableBox *, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2316
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1917
TableFormulaUpdateFlags m_eFlags
Definition: hints.hxx:286
SwTableLine is one table row in the document model.
Definition: swtable.hxx:364
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:386
void ChgFrameFormat(SwTableLineFormat *pNewFormat)
Definition: swtable.cxx:1511
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1478
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:374
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:376
SwTableBox * FindPreviousBox(const SwTable &, const SwTableBox *=nullptr, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2260
SwTableBox * FindNextBox(const SwTable &, const SwTableBox *=nullptr, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2209
SwTableBox * GetUpper()
Definition: swtable.hxx:382
size_type size() const
Definition: swtable.hxx:76
SwTableLine * back() const
Definition: swtable.hxx:82
iterator erase(iterator aIt)
Definition: swtable.hxx:84
SwTableLine * front() const
Definition: swtable.hxx:81
iterator insert(iterator aIt, SwTableLine *pLine)
Definition: swtable.hxx:86
std::vector< SwTableLine * >::size_type size_type
Definition: swtable.hxx:68
iterator begin()
Definition: swtable.hxx:77
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:98
bool empty() const
Definition: swtable.hxx:75
void SetNewTable(std::unique_ptr< SwTable >, bool bNewFrames=true)
Definition: ndtbl.cxx:2467
const SwTable & GetTable() const
Definition: node.hxx:542
void MakeOwnFrames(SwPosition *pIdxBehind=nullptr)
Creates the frms for the table node (i.e.
Definition: ndtbl.cxx:2375
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2422
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
void SetHTMLTableLayout(std::shared_ptr< SwHTMLTableLayout > const &r)
Definition: swtable.cxx:2157
void PrepareDelBoxes(const SwSelBoxes &rBoxes)
SwTable::PrepareDelBoxes(..) adjusts the row span attributes for an upcoming deletion of table cells ...
void LockModify()
Definition: swtable.hxx:187
const OUString & GetTableStyleName() const
Return the table style name of this table.
Definition: swtable.hxx:194
bool SplitCol(SwDoc &rDoc, const SwSelBoxes &rBoxes, sal_uInt16 nCnt)
Definition: tblrwcl.cxx:1166
void SetRowsToRepeat(sal_uInt16 nNumOfRows)
Definition: swtable.hxx:200
SwTableLines & GetTabLines()
Definition: swtable.hxx:204
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:207
void GCLines()
Definition: gctable.cxx:452
bool DeleteSel(SwDoc *, const SwSelBoxes &rBoxes, const SwSelBoxes *pMerged, SwUndo *pUndo, const bool bDelMakeFrames, const bool bCorrBorder)
Definition: tblrwcl.cxx:948
SwTableLines m_aLines
Definition: swtable.hxx:116
void SetTableStyleName(const OUString &rName)
Set the new table style name for this table.
Definition: swtable.hxx:197
bool InsertCol(SwDoc &, const SwSelBoxes &rBoxes, sal_uInt16 nCnt, bool bBehind)
Definition: tblrwcl.cxx:455
TableChgMode m_eTableChgMode
Definition: swtable.hxx:129
bool OldSplitRow(SwDoc &, const SwSelBoxes &, sal_uInt16, bool)
Definition: tblrwcl.cxx:1023
bool SetRowHeight(SwTableBox &rCurrentBox, TableChgWidthHeightType eType, SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr< SwUndo > *ppUndo)
Definition: tblrwcl.cxx:3031
void SetTableChgMode(TableChgMode eMode)
Definition: swtable.hxx:337
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1340
bool OldMerge(SwDoc *, const SwSelBoxes &, SwTableBox *, SwUndoTableMerge *)
Definition: tblrwcl.cxx:1534
bool NewInsertCol(SwDoc &, const SwSelBoxes &rBoxes, sal_uInt16 nCnt, bool)
SwTable::NewInsertCol(..) insert new column(s) into a table.
Definition: swnewtable.cxx:653
void CopyHeadlineIntoTable(SwTableNode &rTableNd)
Definition: tblrwcl.cxx:2014
void UnlockModify()
Definition: swtable.hxx:188
void ExpandSelection(SwSelBoxes &rBoxes) const
SwTable::ExpandSelection(..) adds all boxes to the box selections which are overlapped by it.
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:199
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:265
bool SetColWidth(SwTableBox &rCurrentBox, TableChgWidthHeightType eType, SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr< SwUndo > *ppUndo)
Definition: tblrwcl.cxx:2607
bool IsNewModel() const
Definition: swtable.hxx:191
static SwSelBoxes & SelLineFromBox(const SwTableBox *pBox, SwSelBoxes &rBoxes, bool bToTop=true)
Definition: tblcpy.cxx:1028
bool InsertRow_(SwDoc *, const SwSelBoxes &, sal_uInt16 nCnt, bool bBehind)
Definition: tblrwcl.cxx:514
TableChgMode GetTableChgMode() const
Definition: swtable.hxx:336
bool MakeCopy(SwDoc &, const SwPosition &, const SwSelBoxes &, bool bCpyName=false, const OUString &rStyleName="") const
Definition: tblrwcl.cxx:2059
void SetSelBoxes(const SwSelBoxes &rBoxes)
Definition: untbl.cxx:2015
void AddNewBox(SwNodeOffset nSttNdIdx)
Definition: UndoTable.hxx:241
void SaveSection(SwStartNode *pSttNd)
Definition: untbl.cxx:1632
bool IsDelBox() const
Definition: undobj.cxx:172
const_iterator begin() const
std::vector< Value >::const_iterator const_iterator
const_iterator find(const Value &x) const
size_type erase(const Value &x)
bool empty() const
const_iterator end() const
size_type size() const
std::vector< Value >::size_type size_type
std::pair< const_iterator, bool > insert(Value &&x)
const_iterator lower_bound(const Value &x) const
void CopyWithFlyInFly(const SwNodeRange &rRg, SwNode &rInsPos, const std::pair< const SwPaM &, const SwPosition & > *pCopiedPaM=nullptr, bool bMakeNewFrames=true, bool bDelRedlines=true, bool bCopyFlyAtFly=false, SwCopyFlags flags=SwCopyFlags::Default) const
note: rRg/rInsPos exclude a partially selected start text node; pCopiedPaM includes a partially selec...
int nCount
virtual OUString GetName() const override
DocumentType eType
SwFrameSize
Definition: fmtfsize.hxx:36
@ Fixed
Frame cannot be moved in Var-direction.
@ Variable
Frame is variable in Var-direction.
@ Minimum
Value in Var-direction gives minimum (can be exceeded but not be less).
SwTwips CalcRowRstHeight(SwLayoutFrame *pRow)
Definition: frmtool.cxx:3713
constexpr sal_uInt16 RES_FRMATR_END(133)
constexpr sal_uInt16 RES_BOXATR_END(153)
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(152)
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
constexpr sal_uInt16 RES_BOXATR_BEGIN(RES_GRFATR_END)
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(151)
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
constexpr TypedWhichId< SvxPrintItem > RES_PRINT(98)
constexpr TypedWhichId< SvxLRSpaceItem > RES_LR_SPACE(91)
#define CH_TXT_TRACKED_DUMMY_CHAR
Definition: hintids.hxx:187
@ TBL_RELBOXNAME
Definition: hints.hxx:272
sal_Int64 n
sal_uInt16 nPos
const long LONG_MAX
size
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
long Long
void sw_Box_CollectBox(const SwTableBox *pBox, SwCollectTableLineBoxes *pSplPara)
Definition: ndtbl.cxx:3008
void sw_BoxSetSplitBoxFormats(SwTableBox *pBox, SwCollectTableLineBoxes *pSplPara)
Definition: ndtbl.cxx:3026
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
@ RES_POOLCOLL_TABLE
Subgroup table.
Definition: poolfmt.hxx:341
@ RES_POOLCOLL_TABLE_HDLN
Table of Contents - heading.
Definition: poolfmt.hxx:342
sal_uIntPtr sal_uLong
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:105
#define MINLAY
Definition: swtypes.hxx:62
tools::Long SwTwips
Definition: swtypes.hxx:51
SvxBoxItem & rBoxItem
TableChgMode
Definition: tblenum.hxx:48
constexpr TableChgWidthHeightType extractPosition(TableChgWidthHeightType e)
Definition: tblenum.hxx:43
TableChgWidthHeightType
Definition: tblenum.hxx:27
static void lcl_Merge_MoveLine(FndLine_ &rFndLine, InsULPara *const pULPara)
Definition: tblrwcl.cxx:1431
static bool lcl_SetSelBoxWidth(SwTableLine *pLine, CR_SetBoxWidth &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2376
static SwTwips lcl_GetDistance(SwTableBox *pBox, bool bLeft)
Definition: tblrwcl.cxx:2352
void DeleteBox_(SwTable &rTable, SwTableBox *pBox, SwUndo *pUndo, bool bCalcNewSize, const bool bCorrBorder, SwShareBoxFormats *pShareFormats)
Definition: tblrwcl.cxx:669
static void lcl_AjustLines(SwTableLine *pLine, CR_SetBoxWidth &rParam)
Definition: tblrwcl.cxx:2566
void CheckBoxWidth(const SwTableLine &rLine, SwTwips nSize)
Definition: tblrwcl.cxx:2584
static void lcl_BoxSetHeadCondColl(const SwTableBox *pBox)
Definition: tblrwcl.cxx:2335
bool(* FN_lcl_SetLineHeight)(SwTableLine *, CR_SetLineHeight &, SwTwips, bool)
Definition: tblrwcl.cxx:198
static void lcl_Merge_MoveBox(FndBox_ &rFndBox, InsULPara *const pULPara)
Definition: tblrwcl.cxx:1366
static void lcl_CopyLineToDoc(FndLine_ const &rpFndLn, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:1951
static void lcl_CpyLines(sal_uInt16 nStt, sal_uInt16 nEnd, SwTableLines &rLines, SwTableBox *pInsBox, sal_uInt16 nPos=USHRT_MAX)
Definition: tblrwcl.cxx:1289
void sw_LineSetHeadCondColl(const SwTableLine *pLine)
Definition: tblrwcl.cxx:2346
static void lcl_CalcWidth(SwTableBox *pBox)
Definition: tblrwcl.cxx:1315
static void lcl_CopyCol(FndBox_ &rFndBox, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:249
static bool lcl_SetOtherBoxWidth(SwTableLine *pLine, CR_SetBoxWidth &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2476
#define COLFUZZY
Definition: tblrwcl.cxx:65
#define CHECKTABLELAYOUT
Definition: tblrwcl.cxx:143
static SwRowFrame * GetRowFrame(SwTableLine &rLine)
Definition: tblrwcl.cxx:446
bool(* FN_lcl_SetBoxWidth)(SwTableLine *, CR_SetBoxWidth &, SwTwips, bool)
Definition: tblrwcl.cxx:132
static void lcl_CheckRowSpan(SwTable &rTable)
Definition: tblrwcl.cxx:1656
#define ROWFUZZY
Definition: tblrwcl.cxx:66
static void lcl_InsCol(FndLine_ *pFndLn, CpyPara &rCpyPara, sal_uInt16 nCpyCnt, bool bBehind)
Definition: tblrwcl.cxx:409
static bool lcl_SetSelLineHeight(SwTableLine *pLine, const CR_SetLineHeight &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2959
static void lcl_CalcNewWidths(const FndLines_t &rFndLines, CpyPara &rPara)
Definition: tblrwcl.cxx:1713
static bool lcl_SetOtherLineHeight(SwTableLine *pLine, const CR_SetLineHeight &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2981
static SwTableLine * lcl_CopyRow(FndLine_ &rFndLine, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:382
static void lcl_CpyBoxes(sal_uInt16 nStt, sal_uInt16 nEnd, SwTableBoxes &rBoxes, SwTableLine *pInsLine)
Definition: tblrwcl.cxx:1303
#define CHECK_TABLE(t)
Definition: tblrwcl.cxx:69
static SwTableBox * lcl_FndNxtPrvDelBox(const SwTableLines &rTableLns, SwTwips nBoxStt, SwTwips nBoxWidth, sal_uInt16 nLinePos, bool bNxt, SwSelBoxes *pAllDelBoxes, size_t *const pCurPos)
Definition: tblrwcl.cxx:816
static sal_uInt16 lcl_GetBoxOffset(const FndBox_ &rBox)
Definition: tblrwcl.cxx:1677
static void lcl_SaveUpperLowerBorder(SwTable &rTable, const SwTableBox &rBox, SwShareBoxFormats &rShareFormats, SwSelBoxes *pAllDelBoxes=nullptr, size_t *const pCurPos=nullptr)
Definition: tblrwcl.cxx:876
static void lcl_CopyBoxToDoc(FndBox_ const &rFndBox, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:1799
static sal_uInt16 lcl_GetLineWidth(const FndLine_ &rLine)
Definition: tblrwcl.cxx:1702
static void lcl_LastBoxSetWidth(SwTableBoxes &rBoxes, const tools::Long nOffset, bool bFirst, SwShareBoxFormats &rShareFormats)
Definition: tblrwcl.cxx:642
o3tl::sorted_vector< CpyTabFrame > CpyTabFrames
Definition: tblrwcl.cxx:200
static void SetLineHeight(SwTableLine &rLine, SwTwips nOldHeight, SwTwips nNewHeight, bool bMinSize)
Definition: tblrwcl.cxx:2924
static void lcl_LastBoxSetWidthLine(SwTableLines &rLines, const tools::Long nOffset, bool bFirst, SwShareBoxFormats &rShareFormats)
Definition: tblrwcl.cxx:635
#define CHECKBOXWIDTH
Definition: tblrwcl.cxx:136
void InsTableBox(SwDoc &rDoc, SwTableNode *pTableNd, SwTableLine *pLine, SwTableBoxFormat *pBoxFrameFormat, SwTableBox *pBox, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Definition: swtable.cxx:127
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
This creates a structure mirroring the SwTable structure that contains all rows and non-leaf boxes (a...
Definition: tblsel.cxx:2090
std::vector< std::unique_ptr< FndLine_ > > FndLines_t
Definition: tblsel.hxx:155
std::vector< std::unique_ptr< FndBox_ > > FndBoxes_t
Definition: tblsel.hxx:152
unsigned char sal_uInt8
bool operator<(const wwFont &r1, const wwFont &r2)
Definition: wrtw8sty.cxx:841
bool operator==(const XclFontData &rLeft, const XclFontData &rRight)