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