LibreOffice Module sw (master)  1
ndtbl1.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 <hintids.hxx>
21 #include <editeng/boxitem.hxx>
22 #include <editeng/brushitem.hxx>
23 #include <editeng/frmdiritem.hxx>
24 #include <fesh.hxx>
25 #include <fmtornt.hxx>
26 #include <fmtfsize.hxx>
27 #include <fmtrowsplt.hxx>
28 #include <tabcol.hxx>
29 #include <frmatr.hxx>
30 #include <cellfrm.hxx>
31 #include <tabfrm.hxx>
32 #include <cntfrm.hxx>
33 #include <txtfrm.hxx>
34 #include <svx/svxids.hrc>
35 #include <doc.hxx>
36 #include <IDocumentUndoRedo.hxx>
37 #include <IDocumentState.hxx>
39 #include <pam.hxx>
40 #include <swcrsr.hxx>
41 #include <viscrs.hxx>
42 #include <swtable.hxx>
43 #include <htmltbl.hxx>
44 #include <tblsel.hxx>
45 #include <swtblfmt.hxx>
46 #include <ndindex.hxx>
47 #include <undobj.hxx>
48 #include <calbck.hxx>
49 #include <UndoTable.hxx>
50 #include <o3tl/enumrange.hxx>
51 
52 using ::editeng::SvxBorderLine;
53 using namespace ::com::sun::star;
54 
55 // See swtable.cxx too
56 #define COLFUZZY 20L
57 
58 static bool IsSame( long nA, long nB ) { return std::abs(nA-nB) <= COLFUZZY; }
59 
60 namespace {
61 
62 // SwTableLine::ChgFrameFormat may delete old format which doesn't have writer listeners anymore.
63 // This may invalidate my pointers, and lead to use-after-free. For this reason, I register myself
64 // as a writer listener for the old format here, and take care to delete formats without listeners
65 // in my own dtor.
66 class SwTableFormatCmp : public SwClient
67 {
68 public:
69  SwTableFormatCmp( SwFrameFormat *pOld, SwFrameFormat *pNew, sal_Int16 nType );
70  ~SwTableFormatCmp() override;
71 
72  static SwFrameFormat* FindNewFormat(std::vector<std::unique_ptr<SwTableFormatCmp>>& rArr,
73  SwFrameFormat const* pOld, sal_Int16 nType);
74 
75 private:
76  SwFrameFormat *pOld, *pNew;
77  sal_Int16 const nType;
78 };
79 
80 }
81 
82 SwTableFormatCmp::SwTableFormatCmp( SwFrameFormat *pO, SwFrameFormat *pN, sal_Int16 nT )
83  : pOld ( pO ), pNew ( pN ), nType( nT )
84 {
85  if (pOld)
86  pOld->Add(this);
87 }
88 
89 SwTableFormatCmp::~SwTableFormatCmp()
90 {
91  if (pOld)
92  {
93  pOld->Remove(this);
94  if (!pOld->HasWriterListeners())
95  delete pOld;
96  }
97 }
98 
99 // static
100 SwFrameFormat* SwTableFormatCmp::FindNewFormat(std::vector<std::unique_ptr<SwTableFormatCmp>>& rArr,
101  SwFrameFormat const* pOld, sal_Int16 nType)
102 {
103  for (const auto& pCmp : rArr)
104  {
105  if ( pCmp->pOld == pOld && pCmp->nType == nType )
106  return pCmp->pNew;
107  }
108  return nullptr;
109 }
110 
111 static void lcl_GetStartEndCell( const SwCursor& rCursor,
112  SwLayoutFrame *&prStart, SwLayoutFrame *&prEnd )
113 {
114  OSL_ENSURE( rCursor.GetContentNode() && rCursor.GetContentNode( false ),
115  "Tab selection not at ContentNode" );
116 
117  Point aPtPos, aMkPos;
118  const SwShellCursor* pShCursor = dynamic_cast<const SwShellCursor*>(&rCursor);
119  if( pShCursor )
120  {
121  aPtPos = pShCursor->GetPtPos();
122  aMkPos = pShCursor->GetMkPos();
123  }
124 
125  // Robust:
126  SwContentNode* pPointNd = rCursor.GetContentNode();
127  SwContentNode* pMarkNd = rCursor.GetContentNode(false);
128 
129  std::pair<Point, bool> tmp(aPtPos, true);
130  SwFrame *const pPointFrame = pPointNd ? pPointNd->getLayoutFrame(pPointNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp) : nullptr;
131  tmp.first = aMkPos;
132  SwFrame *const pMarkFrame = pMarkNd ? pMarkNd->getLayoutFrame(pMarkNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp) : nullptr;
133 
134  prStart = pPointFrame ? pPointFrame->GetUpper() : nullptr;
135  prEnd = pMarkFrame ? pMarkFrame->GetUpper() : nullptr;
136 }
137 
138 static bool lcl_GetBoxSel( const SwCursor& rCursor, SwSelBoxes& rBoxes,
139  bool bAllCursor = false )
140 {
141  const SwTableCursor* pTableCursor =
142  dynamic_cast<const SwTableCursor*>(&rCursor);
143  if( pTableCursor )
144  ::GetTableSelCrs( *pTableCursor, rBoxes );
145  else
146  {
147  const SwPaM *pCurPam = &rCursor, *pSttPam = pCurPam;
148  do {
149  const SwNode* pNd = pCurPam->GetNode().FindTableBoxStartNode();
150  if( pNd )
151  {
152  SwTableBox* pBox = const_cast<SwTableBox*>(pNd->FindTableNode()->GetTable().
153  GetTableBox( pNd->GetIndex() ));
154  rBoxes.insert( pBox );
155  }
156  } while( bAllCursor &&
157  pSttPam != ( pCurPam = pCurPam->GetNext()) );
158  }
159  return !rBoxes.empty();
160 }
161 
162 static void InsertLine( std::vector<SwTableLine*>& rLineArr, SwTableLine* pLine )
163 {
164  if( rLineArr.end() == std::find( rLineArr.begin(), rLineArr.end(), pLine ) )
165  rLineArr.push_back( pLine );
166 }
167 
168 static bool lcl_IsAnLower( const SwTableLine *pLine, const SwTableLine *pAssumed )
169 {
170  const SwTableLine *pTmp = pAssumed->GetUpper() ?
171  pAssumed->GetUpper()->GetUpper() : nullptr;
172  while ( pTmp )
173  {
174  if ( pTmp == pLine )
175  return true;
176  pTmp = pTmp->GetUpper() ? pTmp->GetUpper()->GetUpper() : nullptr;
177  }
178  return false;
179 }
180 
181 namespace {
182 
183 struct LinesAndTable
184 {
185  std::vector<SwTableLine*> &m_rLines;
186  const SwTable &m_rTable;
187  bool m_bInsertLines;
188 
189  LinesAndTable(std::vector<SwTableLine*> &rL, const SwTable &rTable) :
190  m_rLines(rL), m_rTable(rTable), m_bInsertLines(true) {}
191 };
192 
193 }
194 
195 static bool FindLine_( FndLine_ & rLine, LinesAndTable* pPara );
196 
197 static bool FindBox_( FndBox_ & rBox, LinesAndTable* pPara )
198 {
199  if (!rBox.GetLines().empty())
200  {
201  pPara->m_bInsertLines = true;
202  for (auto const& rpFndLine : rBox.GetLines())
203  {
204  FindLine_(*rpFndLine, pPara);
205  }
206 
207  if (pPara->m_bInsertLines)
208  {
209  const SwTableLines &rLines = (rBox.GetBox())
210  ? rBox.GetBox()->GetTabLines()
211  : pPara->m_rTable.GetTabLines();
212  if (rBox.GetLines().size() == rLines.size())
213  {
214  for ( auto pLine : rLines )
215  ::InsertLine(pPara->m_rLines, pLine);
216  }
217  else
218  pPara->m_bInsertLines = false;
219  }
220  }
221  else if (rBox.GetBox())
222  {
223  ::InsertLine(pPara->m_rLines, rBox.GetBox()->GetUpper());
224  }
225  return true;
226 }
227 
228 bool FindLine_( FndLine_& rLine, LinesAndTable* pPara )
229 {
230  for (auto const& it : rLine.GetBoxes())
231  {
232  FindBox_(*it, pPara);
233  }
234  return true;
235 }
236 
237 static void lcl_CollectLines( std::vector<SwTableLine*> &rArr, const SwCursor& rCursor, bool bRemoveLines )
238 {
239  // Collect the selected Boxes first
240  SwSelBoxes aBoxes;
241  if( !::lcl_GetBoxSel( rCursor, aBoxes ))
242  return ;
243 
244  // Copy the selected structure
245  const SwTable &rTable = aBoxes[0]->GetSttNd()->FindTableNode()->GetTable();
246  LinesAndTable aPara( rArr, rTable );
247  FndBox_ aFndBox( nullptr, nullptr );
248  {
249  FndPara aTmpPara( aBoxes, &aFndBox );
250  ForEach_FndLineCopyCol( const_cast<SwTableLines&>(rTable.GetTabLines()), &aTmpPara );
251  }
252 
253  // Collect the Lines which only contain selected Boxes
254  ::FindBox_(aFndBox, &aPara);
255 
256  // Remove lines, that have a common superordinate row.
257  // (Not for row split)
258  if ( bRemoveLines )
259  {
260  for ( std::vector<SwTableLine*>::size_type i = 0; i < rArr.size(); ++i )
261  {
262  SwTableLine *pUpLine = rArr[i];
263  for ( std::vector<SwTableLine*>::size_type k = 0; k < rArr.size(); ++k )
264  {
265  if ( k != i && ::lcl_IsAnLower( pUpLine, rArr[k] ) )
266  {
267  rArr.erase( rArr.begin() + k );
268  if ( k <= i )
269  --i;
270  --k;
271  }
272  }
273  }
274  }
275 }
276 
277 static void lcl_ProcessRowAttr(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp,
278  SwTableLine* pLine, const SfxPoolItem& rNew)
279 {
280  SwFrameFormat *pNewFormat;
281  if ( nullptr != (pNewFormat = SwTableFormatCmp::FindNewFormat( rFormatCmp, pLine->GetFrameFormat(), 0 )))
282  pLine->ChgFrameFormat( static_cast<SwTableLineFormat*>(pNewFormat) );
283  else
284  {
285  SwFrameFormat *pOld = pLine->GetFrameFormat();
286  SwFrameFormat *pNew = pLine->ClaimFrameFormat();
287  pNew->SetFormatAttr( rNew );
288  rFormatCmp.push_back(std::make_unique<SwTableFormatCmp>(pOld, pNew, 0));
289  }
290 }
291 
292 static void lcl_ProcessBoxSize(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp,
293  SwTableBox* pBox, const SwFormatFrameSize& rNew);
294 
295 static void lcl_ProcessRowSize(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp,
296  SwTableLine* pLine, const SwFormatFrameSize& rNew)
297 {
298  lcl_ProcessRowAttr( rFormatCmp, pLine, rNew );
299  SwTableBoxes &rBoxes = pLine->GetTabBoxes();
300  for ( auto pBox : rBoxes )
301  ::lcl_ProcessBoxSize( rFormatCmp, pBox, rNew );
302 }
303 
304 static void lcl_ProcessBoxSize(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp,
305  SwTableBox* pBox, const SwFormatFrameSize& rNew)
306 {
307  SwTableLines &rLines = pBox->GetTabLines();
308  if ( !rLines.empty() )
309  {
310  SwFormatFrameSize aSz( rNew );
311  aSz.SetHeight( rNew.GetHeight() ? rNew.GetHeight() / rLines.size() : 0 );
312  for ( auto pLine : rLines )
313  ::lcl_ProcessRowSize( rFormatCmp, pLine, aSz );
314  }
315 }
316 
317 void SwDoc::SetRowSplit( const SwCursor& rCursor, const SwFormatRowSplit &rNew )
318 {
319  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
320  if( pTableNd )
321  {
322  std::vector<SwTableLine*> aRowArr; // For Lines collecting
323  ::lcl_CollectLines( aRowArr, rCursor, false );
324 
325  if( !aRowArr.empty() )
326  {
328  {
329  GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttrTable>(*pTableNd));
330  }
331 
332  std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
333  aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
334 
335  for( auto pLn : aRowArr )
336  ::lcl_ProcessRowAttr( aFormatCmp, pLn, rNew );
337 
339  }
340  }
341 }
342 
343 std::unique_ptr<SwFormatRowSplit> SwDoc::GetRowSplit( const SwCursor& rCursor )
344 {
345  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
346  if( !pTableNd )
347  return nullptr;
348 
349  std::vector<SwTableLine*> aRowArr; // For Lines collecting
350  ::lcl_CollectLines( aRowArr, rCursor, false );
351 
352  if( aRowArr.empty() )
353  return nullptr;
354 
355  SwFormatRowSplit* pSz = &const_cast<SwFormatRowSplit&>(aRowArr[0]->GetFrameFormat()->GetRowSplit());
356 
357  for ( auto pLn : aRowArr )
358  {
359  if ( pSz->GetValue() != pLn->GetFrameFormat()->GetRowSplit().GetValue() )
360  {
361  return nullptr;
362  }
363  }
364  return std::make_unique<SwFormatRowSplit>( *pSz );
365 }
366 
367 /* Class: SwDoc
368  * Methods: SetRowHeight(), GetRowHeight()
369  *
370  * The line height is calculated from the Selection.
371  * Starting with every Cell within the Selection, all Cells are iterated
372  * through in an upwards fashion.
373  *
374  * The topmost Line gets the requested value, all Lines below it get
375  * a respective value that is calculated from the relation of the old and
376  * new size of the topmost Line in the lower line's own size.
377  *
378  * All changed Lines may get an own FrameFormat.
379  * Of course we can only touch every Line once.
380  */
381 
382 void SwDoc::SetRowHeight( const SwCursor& rCursor, const SwFormatFrameSize &rNew )
383 {
384  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
385  if( pTableNd )
386  {
387  std::vector<SwTableLine*> aRowArr; // For Lines collecting
388  ::lcl_CollectLines( aRowArr, rCursor, true );
389 
390  if( !aRowArr.empty() )
391  {
393  {
394  GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttrTable>(*pTableNd));
395  }
396 
397  std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
398  aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
399  for ( auto pLn : aRowArr )
400  ::lcl_ProcessRowSize( aFormatCmp, pLn, rNew );
401 
403  }
404  }
405 }
406 
407 std::unique_ptr<SwFormatFrameSize> SwDoc::GetRowHeight( const SwCursor& rCursor )
408 {
409  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
410  if( !pTableNd )
411  return nullptr;
412 
413  std::vector<SwTableLine*> aRowArr; // For Lines collecting
414  ::lcl_CollectLines( aRowArr, rCursor, true );
415 
416  if( aRowArr.empty() )
417  return nullptr;
418 
419  SwFormatFrameSize* pSz = &const_cast<SwFormatFrameSize&>(aRowArr[0]->GetFrameFormat()->GetFrameSize());
420 
421  for ( auto pLn : aRowArr )
422  {
423  if ( *pSz != pLn->GetFrameFormat()->GetFrameSize() )
424  return nullptr;
425  }
426  return std::make_unique<SwFormatFrameSize>( *pSz );
427 }
428 
429 bool SwDoc::BalanceRowHeight( const SwCursor& rCursor, bool bTstOnly, const bool bOptimize )
430 {
431  bool bRet = false;
432  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
433  if( pTableNd )
434  {
435  std::vector<SwTableLine*> aRowArr; // For Lines collecting
436  ::lcl_CollectLines( aRowArr, rCursor, true );
437 
438  if( 1 < aRowArr.size() )
439  {
440  if( !bTstOnly )
441  {
442  long nHeight = 0;
443  sal_Int32 nTotalHeight = 0;
444  for ( auto pLn : aRowArr )
445  {
446  SwIterator<SwFrame,SwFormat> aIter( *pLn->GetFrameFormat() );
447  SwFrame* pFrame = aIter.First();
448  while ( pFrame )
449  {
450  nHeight = std::max( nHeight, pFrame->getFrameArea().Height() );
451  pFrame = aIter.Next();
452  }
453  nTotalHeight += nHeight;
454  }
455 
456  if ( bOptimize )
457  nHeight = nTotalHeight / aRowArr.size();
458 
459  SwFormatFrameSize aNew( SwFrameSize::Minimum, 0, nHeight );
460 
461  if (GetIDocumentUndoRedo().DoesUndo())
462  {
464  std::make_unique<SwUndoAttrTable>(*pTableNd));
465  }
466 
467  std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
468  aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
469  for( auto pLn : aRowArr )
470  ::lcl_ProcessRowSize( aFormatCmp, pLn, aNew );
471 
473  }
474  bRet = true;
475  }
476  }
477  return bRet;
478 }
479 
480 void SwDoc::SetRowBackground( const SwCursor& rCursor, const SvxBrushItem &rNew )
481 {
482  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
483  if( pTableNd )
484  {
485  std::vector<SwTableLine*> aRowArr; // For Lines collecting
486  ::lcl_CollectLines( aRowArr, rCursor, true );
487 
488  if( !aRowArr.empty() )
489  {
491  {
492  GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttrTable>(*pTableNd));
493  }
494 
495  std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
496  aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) );
497 
498  for( auto pLn : aRowArr )
499  ::lcl_ProcessRowAttr( aFormatCmp, pLn, rNew );
500 
502  }
503  }
504 }
505 
506 bool SwDoc::GetRowBackground( const SwCursor& rCursor, std::shared_ptr<SvxBrushItem>& rToFill )
507 {
508  bool bRet = false;
509  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
510  if( pTableNd )
511  {
512  std::vector<SwTableLine*> aRowArr; // For Lines collecting
513  ::lcl_CollectLines( aRowArr, rCursor, true );
514 
515  if( !aRowArr.empty() )
516  {
517  rToFill = aRowArr[0]->GetFrameFormat()->makeBackgroundBrushItem();
518 
519  bRet = true;
520  for ( std::vector<SwTableLine*>::size_type i = 1; i < aRowArr.size(); ++i )
521  {
522  std::shared_ptr<SvxBrushItem> aAlternative(aRowArr[i]->GetFrameFormat()->makeBackgroundBrushItem());
523 
524  if ( rToFill != aAlternative && rToFill && aAlternative && *rToFill != *aAlternative )
525  {
526  bRet = false;
527  break;
528  }
529  }
530  }
531  }
532  return bRet;
533 }
534 
535 static void InsertCell( std::vector<SwCellFrame*>& rCellArr, SwCellFrame* pCellFrame )
536 {
537  if( rCellArr.end() == std::find( rCellArr.begin(), rCellArr.end(), pCellFrame ) )
538  rCellArr.push_back( pCellFrame );
539 }
540 
541 static void lcl_CollectCells( std::vector<SwCellFrame*> &rArr, const SwRect &rUnion,
542  SwTabFrame *pTab )
543 {
544  SwLayoutFrame *pCell = pTab->FirstCell();
545  do
546  {
547  // If the Cell contains a CellFrame, we need to use it
548  // in order to get to the Cell
549  while ( !pCell->IsCellFrame() )
550  pCell = pCell->GetUpper();
551  OSL_ENSURE( pCell, "Frame is not a Cell" );
552  if ( rUnion.IsOver( pCell->getFrameArea() ) )
553  ::InsertCell( rArr, static_cast<SwCellFrame*>(pCell) );
554 
555  // Make sure the Cell is left (Areas)
556  SwLayoutFrame *pTmp = pCell;
557  do
558  { pTmp = pTmp->GetNextLayoutLeaf();
559  } while ( pCell->IsAnLower( pTmp ) );
560  pCell = pTmp;
561  } while( pCell && pTab->IsAnLower( pCell ) );
562 }
563 
564 void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet )
565 {
566  SwContentNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetContentNode();
567  SwTableNode* pTableNd = pCntNd ? pCntNd->FindTableNode() : nullptr;
568  if( !pTableNd )
569  return ;
570 
571  SwLayoutFrame *pStart, *pEnd;
572  ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
573 
574  SwSelUnions aUnions;
575  ::MakeSelUnions( aUnions, pStart, pEnd );
576 
577  if( aUnions.empty() )
578  return;
579 
580  SwTable& rTable = pTableNd->GetTable();
581  if (GetIDocumentUndoRedo().DoesUndo())
582  {
583  GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoAttrTable>(*pTableNd) );
584  }
585 
586  std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
587  aFormatCmp.reserve( 255 );
588  const SvxBoxItem* pSetBox;
589  const SvxBoxInfoItem *pSetBoxInfo;
590 
591  const SvxBorderLine* pLeft = nullptr;
592  const SvxBorderLine* pRight = nullptr;
593  const SvxBorderLine* pTop = nullptr;
594  const SvxBorderLine* pBottom = nullptr;
595  const SvxBorderLine* pHori = nullptr;
596  const SvxBorderLine* pVert = nullptr;
597  bool bHoriValid = true, bVertValid = true,
598  bTopValid = true, bBottomValid = true,
599  bLeftValid = true, bRightValid = true;
600 
601  // The Flags in the BoxInfo Item decide whether a BorderLine is valid!
602  if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER, false,
603  reinterpret_cast<const SfxPoolItem**>(&pSetBoxInfo)) )
604  {
605  pHori = pSetBoxInfo->GetHori();
606  pVert = pSetBoxInfo->GetVert();
607 
608  bHoriValid = pSetBoxInfo->IsValid(SvxBoxInfoItemValidFlags::HORI);
609  bVertValid = pSetBoxInfo->IsValid(SvxBoxInfoItemValidFlags::VERT);
610 
611  // Do we want to evaluate these?
612  bTopValid = pSetBoxInfo->IsValid(SvxBoxInfoItemValidFlags::TOP);
613  bBottomValid = pSetBoxInfo->IsValid(SvxBoxInfoItemValidFlags::BOTTOM);
614  bLeftValid = pSetBoxInfo->IsValid(SvxBoxInfoItemValidFlags::LEFT);
615  bRightValid = pSetBoxInfo->IsValid(SvxBoxInfoItemValidFlags::RIGHT);
616  }
617 
618  if( SfxItemState::SET == rSet.GetItemState( RES_BOX, false,
619  reinterpret_cast<const SfxPoolItem**>(&pSetBox)) )
620  {
621  pLeft = pSetBox->GetLeft();
622  pRight = pSetBox->GetRight();
623  pTop = pSetBox->GetTop();
624  pBottom = pSetBox->GetBottom();
625  }
626  else
627  {
628  // Not set, thus not valid values
629  bTopValid = bBottomValid = bLeftValid = bRightValid = false;
630  pSetBox = nullptr;
631  }
632 
633  bool bFirst = true;
634  for ( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
635  {
636  SwSelUnion *pUnion = &aUnions[i];
637  SwTabFrame *pTab = pUnion->GetTable();
638  const SwRect &rUnion = pUnion->GetUnion();
639  const bool bLast = (i == aUnions.size() - 1);
640 
641  std::vector<SwCellFrame*> aCellArr;
642  aCellArr.reserve( 255 );
643  ::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab );
644 
645  // All Cell Borders that match the UnionRect or extend it are
646  // Outer Borders. All others are Inner Borders.
647 
648  // New: The Outer Borders can, depending on whether it's a
649  // Start/Middle/Follow Table (for Selection via FollowTabs),
650  // also not be Outer Borders.
651  // Outer Borders are set on the left, right, at the top and at the bottom.
652  // Inner Borders are only set at the top and on the left.
653  for ( auto pCell : aCellArr )
654  {
655  const bool bVert = pTab->IsVertical();
656  const bool bRTL = pTab->IsRightToLeft();
657  bool bTopOver, bLeftOver, bRightOver, bBottomOver;
658  if ( bVert )
659  {
660  bTopOver = pCell->getFrameArea().Right() >= rUnion.Right();
661  bLeftOver = pCell->getFrameArea().Top() <= rUnion.Top();
662  bRightOver = pCell->getFrameArea().Bottom() >= rUnion.Bottom();
663  bBottomOver = pCell->getFrameArea().Left() <= rUnion.Left();
664  }
665  else
666  {
667  bTopOver = pCell->getFrameArea().Top() <= rUnion.Top();
668  bLeftOver = pCell->getFrameArea().Left() <= rUnion.Left();
669  bRightOver = pCell->getFrameArea().Right() >= rUnion.Right();
670  bBottomOver = pCell->getFrameArea().Bottom() >= rUnion.Bottom();
671  }
672 
673  if ( bRTL )
674  {
675  bool bTmp = bRightOver;
676  bRightOver = bLeftOver;
677  bLeftOver = bTmp;
678  }
679 
680  // Do not set anything by default in HeadlineRepeats
681  if ( pTab->IsFollow() &&
682  ( pTab->IsInHeadline( *pCell ) ||
683  // Same holds for follow flow rows
684  pCell->IsInFollowFlowRow() ) )
685  continue;
686 
687  SvxBoxItem aBox( pCell->GetFormat()->GetBox() );
688 
689  sal_Int16 nType = 0;
690 
691  // Top Border
692  if( bTopValid )
693  {
694  if ( bFirst && bTopOver )
695  {
696  aBox.SetLine( pTop, SvxBoxItemLine::TOP );
697  nType |= 0x0001;
698  }
699  else if ( bHoriValid )
700  {
701  aBox.SetLine( nullptr, SvxBoxItemLine::TOP );
702  nType |= 0x0002;
703  }
704  }
705 
706  // Fix fdo#62470 correct the input for RTL table
707  if (bRTL)
708  {
709  if( bLeftOver && bRightOver)
710  {
711  if ( bLeftValid )
712  {
713  aBox.SetLine( pLeft, SvxBoxItemLine::RIGHT );
714  nType |= 0x0010;
715  }
716  if ( bRightValid )
717  {
718  aBox.SetLine( pRight, SvxBoxItemLine::LEFT );
719  nType |= 0x0004;
720  }
721  }
722  else
723  {
724  if ( bLeftValid )
725  {
726  aBox.SetLine( bRightOver ? pLeft : nullptr, SvxBoxItemLine::RIGHT );
727  if (bVertValid)
728  nType |= 0x0020;
729  else
730  nType |= 0x0010;
731  }
732  if ( bLeftOver )
733  {
734  if ( bRightValid )
735  {
736  aBox.SetLine( pRight, SvxBoxItemLine::LEFT );
737  nType |= 0x0004;
738  }
739  }
740  else if ( bVertValid )
741  {
742  aBox.SetLine( pVert, SvxBoxItemLine::LEFT );
743  nType |= 0x0008;
744  }
745  }
746  }
747  else
748  {
749  // Left Border
750  if ( bLeftOver )
751  {
752  if( bLeftValid )
753  {
754  aBox.SetLine( pLeft, SvxBoxItemLine::LEFT );
755  nType |= 0x0004;
756  }
757  }
758  else if( bVertValid )
759  {
760  aBox.SetLine( pVert, SvxBoxItemLine::LEFT );
761  nType |= 0x0008;
762  }
763 
764  // Right Border
765  if( bRightValid )
766  {
767  if ( bRightOver )
768  {
769  aBox.SetLine( pRight, SvxBoxItemLine::RIGHT );
770  nType |= 0x0010;
771  }
772  else if ( bVertValid )
773  {
774  aBox.SetLine( nullptr, SvxBoxItemLine::RIGHT );
775  nType |= 0x0020;
776  }
777  }
778  }
779 
780  // Bottom Border
781  if ( bLast && bBottomOver )
782  {
783  if( bBottomValid )
784  {
785  aBox.SetLine( pBottom, SvxBoxItemLine::BOTTOM );
786  nType |= 0x0040;
787  }
788  }
789  else if( bHoriValid )
790  {
791  aBox.SetLine( pHori, SvxBoxItemLine::BOTTOM );
792  nType |= 0x0080;
793  }
794 
795  if( pSetBox )
796  {
798  aBox.SetDistance( pSetBox->GetDistance( k ), k );
799  }
800 
801  SwTableBox *pBox = const_cast<SwTableBox*>(pCell->GetTabBox());
802  SwFrameFormat *pNewFormat;
803  if ( nullptr != (pNewFormat = SwTableFormatCmp::FindNewFormat( aFormatCmp, pBox->GetFrameFormat(), nType )))
804  pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(pNewFormat) );
805  else
806  {
807  SwFrameFormat *pOld = pBox->GetFrameFormat();
808  SwFrameFormat *pNew = pBox->ClaimFrameFormat();
809  pNew->SetFormatAttr( aBox );
810  aFormatCmp.push_back(std::make_unique<SwTableFormatCmp>(pOld, pNew, nType));
811  }
812  }
813 
814  bFirst = false;
815  }
816 
817  SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
818  if( pTableLayout )
819  {
821  SwTabFrame* pTabFrame = pFrame->ImplFindTabFrame();
822 
823  pTableLayout->BordersChanged(
824  pTableLayout->GetBrowseWidthByTabFrame( *pTabFrame ) );
825  }
826  ::ClearFEShellTabCols(*this, nullptr);
828 }
829 
830 static void lcl_SetLineStyle( SvxBorderLine *pToSet,
831  const Color *pColor, const SvxBorderLine *pBorderLine)
832 {
833  if ( pBorderLine )
834  {
835  if ( !pColor )
836  {
837  Color aTmp( pToSet->GetColor() );
838  *pToSet = *pBorderLine;
839  pToSet->SetColor( aTmp );
840  }
841  else
842  *pToSet = *pBorderLine;
843  }
844  if ( pColor )
845  pToSet->SetColor( *pColor );
846 }
847 
848 void SwDoc::SetTabLineStyle( const SwCursor& rCursor,
849  const Color* pColor, bool bSetLine,
850  const SvxBorderLine* pBorderLine )
851 {
852  SwContentNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetContentNode();
853  SwTableNode* pTableNd = pCntNd ? pCntNd->FindTableNode() : nullptr;
854  if( !pTableNd )
855  return ;
856 
857  SwLayoutFrame *pStart, *pEnd;
858  ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
859 
860  SwSelUnions aUnions;
861  ::MakeSelUnions( aUnions, pStart, pEnd );
862 
863  if( !aUnions.empty() )
864  {
865  SwTable& rTable = pTableNd->GetTable();
866  if (GetIDocumentUndoRedo().DoesUndo())
867  {
868  GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttrTable>(*pTableNd));
869  }
870 
871  for( auto &rU : aUnions )
872  {
873  SwSelUnion *pUnion = &rU;
874  SwTabFrame *pTab = pUnion->GetTable();
875  std::vector<SwCellFrame*> aCellArr;
876  aCellArr.reserve( 255 );
877  ::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab );
878 
879  for ( auto pCell : aCellArr )
880  {
881  // Do not set anything by default in HeadlineRepeats
882  if ( pTab->IsFollow() && pTab->IsInHeadline( *pCell ) )
883  continue;
884 
885  const_cast<SwTableBox*>(pCell->GetTabBox())->ClaimFrameFormat();
886  SwFrameFormat *pFormat = pCell->GetFormat();
887  std::shared_ptr<SvxBoxItem> aBox(pFormat->GetBox().Clone());
888 
889  if ( !pBorderLine && bSetLine )
890  {
891  aBox.reset(::GetDfltAttr(RES_BOX)->Clone());
892  }
893  else
894  {
895  if ( aBox->GetTop() )
896  ::lcl_SetLineStyle( const_cast<SvxBorderLine*>(aBox->GetTop()),
897  pColor, pBorderLine );
898  if ( aBox->GetBottom() )
899  ::lcl_SetLineStyle( const_cast<SvxBorderLine*>(aBox->GetBottom()),
900  pColor, pBorderLine );
901  if ( aBox->GetLeft() )
902  ::lcl_SetLineStyle( const_cast<SvxBorderLine*>(aBox->GetLeft()),
903  pColor, pBorderLine );
904  if ( aBox->GetRight() )
905  ::lcl_SetLineStyle( const_cast<SvxBorderLine*>(aBox->GetRight()),
906  pColor, pBorderLine );
907  }
908  pFormat->SetFormatAttr( *aBox );
909  }
910  }
911 
912  SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
913  if( pTableLayout )
914  {
916  SwTabFrame* pTabFrame = pFrame->ImplFindTabFrame();
917 
918  pTableLayout->BordersChanged(
919  pTableLayout->GetBrowseWidthByTabFrame( *pTabFrame ) );
920  }
921  ::ClearFEShellTabCols(*this, nullptr);
923  }
924 }
925 
926 void SwDoc::GetTabBorders( const SwCursor& rCursor, SfxItemSet& rSet )
927 {
928  SwContentNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetContentNode();
929  SwTableNode* pTableNd = pCntNd ? pCntNd->FindTableNode() : nullptr;
930  if( !pTableNd )
931  return ;
932 
933  SwLayoutFrame *pStart, *pEnd;
934  ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
935 
936  SwSelUnions aUnions;
937  ::MakeSelUnions( aUnions, pStart, pEnd );
938 
939  if( !aUnions.empty() )
940  {
941  SvxBoxItem aSetBox ( rSet.Get(RES_BOX ) );
942  SvxBoxInfoItem aSetBoxInfo( rSet.Get(SID_ATTR_BORDER_INNER) );
943 
944  bool bTopSet = false,
945  bBottomSet = false,
946  bLeftSet = false,
947  bRightSet = false,
948  bHoriSet = false,
949  bVertSet = false,
950  bDistanceSet = false,
951  bRTLTab = false;
952 
953  aSetBoxInfo.ResetFlags();
954 
955  for ( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
956  {
957  SwSelUnion *pUnion = &aUnions[i];
958  const SwTabFrame *pTab = pUnion->GetTable();
959  const SwRect &rUnion = pUnion->GetUnion();
960  const bool bFirst = i == 0;
961  const bool bLast = (i == aUnions.size() - 1);
962 
963  std::vector<SwCellFrame*> aCellArr;
964  aCellArr.reserve(255);
965  ::lcl_CollectCells( aCellArr, rUnion, const_cast<SwTabFrame*>(pTab) );
966 
967  for ( auto pCell : aCellArr )
968  {
969  const bool bVert = pTab->IsVertical();
970  const bool bRTL = bRTLTab = pTab->IsRightToLeft();
971  bool bTopOver, bLeftOver, bRightOver, bBottomOver;
972  if ( bVert )
973  {
974  bTopOver = pCell->getFrameArea().Right() >= rUnion.Right();
975  bLeftOver = pCell->getFrameArea().Top() <= rUnion.Top();
976  bRightOver = pCell->getFrameArea().Bottom() >= rUnion.Bottom();
977  bBottomOver = pCell->getFrameArea().Left() <= rUnion.Left();
978  }
979  else
980  {
981  bTopOver = pCell->getFrameArea().Top() <= rUnion.Top();
982  bLeftOver = pCell->getFrameArea().Left() <= rUnion.Left();
983  bRightOver = pCell->getFrameArea().Right() >= rUnion.Right();
984  bBottomOver = pCell->getFrameArea().Bottom() >= rUnion.Bottom();
985  }
986 
987  if ( bRTL )
988  {
989  bool bTmp = bRightOver;
990  bRightOver = bLeftOver;
991  bLeftOver = bTmp;
992  }
993 
994  const SwFrameFormat *pFormat = pCell->GetFormat();
995  const SvxBoxItem &rBox = pFormat->GetBox();
996 
997  // Top Border
998  if ( bFirst && bTopOver )
999  {
1000  if (aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::TOP))
1001  {
1002  if ( !bTopSet )
1003  { bTopSet = true;
1004  aSetBox.SetLine( rBox.GetTop(), SvxBoxItemLine::TOP );
1005  }
1006  else if ((aSetBox.GetTop() && rBox.GetTop() &&
1007  (*aSetBox.GetTop() != *rBox.GetTop())) ||
1008  ((!aSetBox.GetTop()) != (!rBox.GetTop()))) // != expression is true, if one and only one of the two pointers is !0
1009  {
1010  aSetBoxInfo.SetValid(SvxBoxInfoItemValidFlags::TOP, false );
1011  aSetBox.SetLine( nullptr, SvxBoxItemLine::TOP );
1012  }
1013  }
1014  }
1015 
1016  // Left Border
1017  if ( bLeftOver )
1018  {
1019  if (aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::LEFT))
1020  {
1021  if ( !bLeftSet )
1022  { bLeftSet = true;
1023  aSetBox.SetLine( rBox.GetLeft(), SvxBoxItemLine::LEFT );
1024  }
1025  else if ((aSetBox.GetLeft() && rBox.GetLeft() &&
1026  (*aSetBox.GetLeft() != *rBox.GetLeft())) ||
1027  ((!aSetBox.GetLeft()) != (!rBox.GetLeft())))
1028  {
1029  aSetBoxInfo.SetValid(SvxBoxInfoItemValidFlags::LEFT, false );
1030  aSetBox.SetLine( nullptr, SvxBoxItemLine::LEFT );
1031  }
1032  }
1033  }
1034  else
1035  {
1036  if (aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::VERT))
1037  {
1038  if ( !bVertSet )
1039  { bVertSet = true;
1040  aSetBoxInfo.SetLine( rBox.GetLeft(), SvxBoxInfoItemLine::VERT );
1041  }
1042  else if ((aSetBoxInfo.GetVert() && rBox.GetLeft() &&
1043  (*aSetBoxInfo.GetVert() != *rBox.GetLeft())) ||
1044  ((!aSetBoxInfo.GetVert()) != (!rBox.GetLeft())))
1045  { aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::VERT, false );
1046  aSetBoxInfo.SetLine( nullptr, SvxBoxInfoItemLine::VERT );
1047  }
1048  }
1049  }
1050 
1051  // Right Border
1052  if ( aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::RIGHT) && bRightOver )
1053  {
1054  if ( !bRightSet )
1055  { bRightSet = true;
1056  aSetBox.SetLine( rBox.GetRight(), SvxBoxItemLine::RIGHT );
1057  }
1058  else if ((aSetBox.GetRight() && rBox.GetRight() &&
1059  (*aSetBox.GetRight() != *rBox.GetRight())) ||
1060  (!aSetBox.GetRight() != !rBox.GetRight()))
1061  { aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::RIGHT, false );
1062  aSetBox.SetLine( nullptr, SvxBoxItemLine::RIGHT );
1063  }
1064  }
1065 
1066  // Bottom Border
1067  if ( bLast && bBottomOver )
1068  {
1069  if ( aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::BOTTOM) )
1070  {
1071  if ( !bBottomSet )
1072  { bBottomSet = true;
1073  aSetBox.SetLine( rBox.GetBottom(), SvxBoxItemLine::BOTTOM );
1074  }
1075  else if ((aSetBox.GetBottom() && rBox.GetBottom() &&
1076  (*aSetBox.GetBottom() != *rBox.GetBottom())) ||
1077  (!aSetBox.GetBottom() != !rBox.GetBottom()))
1078  { aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, false );
1079  aSetBox.SetLine( nullptr, SvxBoxItemLine::BOTTOM );
1080  }
1081  }
1082  }
1083  // In all Lines, except for the last one, the horizontal Line
1084  // is taken from the Bottom Line.
1085  else
1086  {
1087  if (aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::HORI))
1088  {
1089  if ( !bHoriSet )
1090  { bHoriSet = true;
1091  aSetBoxInfo.SetLine( rBox.GetBottom(), SvxBoxInfoItemLine::HORI );
1092  }
1093  else if ((aSetBoxInfo.GetHori() && rBox.GetBottom() &&
1094  (*aSetBoxInfo.GetHori() != *rBox.GetBottom())) ||
1095  ((!aSetBoxInfo.GetHori()) != (!rBox.GetBottom())))
1096  {
1097  aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::HORI, false );
1098  aSetBoxInfo.SetLine( nullptr, SvxBoxInfoItemLine::HORI );
1099  }
1100  }
1101  }
1102 
1103  // Distance to text
1104  if (aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::DISTANCE))
1105  {
1106  if( !bDistanceSet ) // Set on first iteration
1107  {
1108  bDistanceSet = true;
1110  aSetBox.SetDistance( rBox.GetDistance( k ), k );
1111  }
1112  else
1113  {
1115  if( aSetBox.GetDistance( k ) !=
1116  rBox.GetDistance( k ) )
1117  {
1118  aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, false );
1119  aSetBox.SetAllDistances(0);
1120  break;
1121  }
1122  }
1123  }
1124  }
1125  }
1126 
1127  // fdo#62470 fix the reading for table format.
1128  if ( bRTLTab )
1129  {
1130  SvxBoxItem aTempBox ( rSet.Get(RES_BOX ) );
1131  SvxBoxInfoItem aTempBoxInfo( rSet.Get(SID_ATTR_BORDER_INNER) );
1132 
1133  aTempBox.SetLine( aSetBox.GetRight(), SvxBoxItemLine::RIGHT);
1134  aSetBox.SetLine( aSetBox.GetLeft(), SvxBoxItemLine::RIGHT);
1135  aSetBox.SetLine( aTempBox.GetRight(), SvxBoxItemLine::LEFT);
1136 
1137  aTempBoxInfo.SetValid( SvxBoxInfoItemValidFlags::LEFT, aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::LEFT) );
1138  aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::LEFT, aSetBoxInfo.IsValid(SvxBoxInfoItemValidFlags::RIGHT) );
1139  aSetBoxInfo.SetValid( SvxBoxInfoItemValidFlags::RIGHT, aTempBoxInfo.IsValid(SvxBoxInfoItemValidFlags::LEFT) );
1140  }
1141 
1142  rSet.Put( aSetBox );
1143  rSet.Put( aSetBoxInfo );
1144  }
1145 }
1146 
1147 void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew )
1148 {
1149  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
1150  SwSelBoxes aBoxes;
1151  if( pTableNd && ::lcl_GetBoxSel( rCursor, aBoxes, true ) )
1152  {
1153  SwTable& rTable = pTableNd->GetTable();
1154  if (GetIDocumentUndoRedo().DoesUndo())
1155  {
1156  GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoAttrTable>(*pTableNd) );
1157  }
1158 
1159  std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp;
1160  aFormatCmp.reserve(std::max<size_t>(255, aBoxes.size()));
1161  for (size_t i = 0; i < aBoxes.size(); ++i)
1162  {
1163  SwTableBox *pBox = aBoxes[i];
1164 
1165  SwFrameFormat *pNewFormat;
1166  if ( nullptr != (pNewFormat = SwTableFormatCmp::FindNewFormat( aFormatCmp, pBox->GetFrameFormat(), 0 )))
1167  pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(pNewFormat) );
1168  else
1169  {
1170  SwFrameFormat *pOld = pBox->GetFrameFormat();
1171  SwFrameFormat *pNew = pBox->ClaimFrameFormat();
1172  pNew->SetFormatAttr( rNew );
1173  aFormatCmp.push_back(std::make_unique<SwTableFormatCmp>(pOld, pNew, 0));
1174  }
1175 
1176  pBox->SetDirectFormatting(true);
1177  }
1178 
1179  SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
1180  if( pTableLayout )
1181  {
1183  SwTabFrame* pTabFrame = pFrame->ImplFindTabFrame();
1184 
1185  pTableLayout->Resize(
1186  pTableLayout->GetBrowseWidthByTabFrame( *pTabFrame ), true );
1187  }
1189  }
1190 }
1191 
1192 bool SwDoc::GetBoxAttr( const SwCursor& rCursor, std::shared_ptr<SfxPoolItem>& rToFill )
1193 {
1194  bool bRet = false;
1195  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
1196  SwSelBoxes aBoxes;
1197  if( pTableNd && lcl_GetBoxSel( rCursor, aBoxes ))
1198  {
1199  bRet = true;
1200  bool bOneFound = false;
1201  const sal_uInt16 nWhich = rToFill->Which();
1202  for (size_t i = 0; i < aBoxes.size(); ++i)
1203  {
1204  switch ( nWhich )
1205  {
1206  case RES_BACKGROUND:
1207  {
1208  std::shared_ptr<SvxBrushItem> aBack =
1209  aBoxes[i]->GetFrameFormat()->makeBackgroundBrushItem();
1210  if( !bOneFound )
1211  {
1212  rToFill.reset(aBack->Clone());
1213  bOneFound = true;
1214  }
1215  else if( rToFill != aBack )
1216  bRet = false;
1217  }
1218  break;
1219 
1220  case RES_FRAMEDIR:
1221  {
1222  const SvxFrameDirectionItem& rDir =
1223  aBoxes[i]->GetFrameFormat()->GetFrameDir();
1224  if( !bOneFound )
1225  {
1226  rToFill.reset(rDir.Clone());
1227  bOneFound = true;
1228  }
1229  else if( rToFill && *rToFill != rDir )
1230  bRet = false;
1231  }
1232  break;
1233  case RES_VERT_ORIENT:
1234  {
1235  const SwFormatVertOrient& rOrient =
1236  aBoxes[i]->GetFrameFormat()->GetVertOrient();
1237  if( !bOneFound )
1238  {
1239  rToFill.reset(rOrient.Clone());
1240  bOneFound = true;
1241  }
1242  else if( rToFill && *rToFill != rOrient )
1243  bRet = false;
1244  }
1245  break;
1246  }
1247 
1248  if ( !bRet )
1249  break;
1250  }
1251  }
1252  return bRet;
1253 }
1254 
1255 void SwDoc::SetBoxAlign( const SwCursor& rCursor, sal_uInt16 nAlign )
1256 {
1257  OSL_ENSURE( nAlign == text::VertOrientation::NONE ||
1258  nAlign == text::VertOrientation::CENTER ||
1259  nAlign == text::VertOrientation::BOTTOM, "Wrong alignment" );
1260  SwFormatVertOrient aVertOri( 0, nAlign );
1261  SetBoxAttr( rCursor, aVertOri );
1262 }
1263 
1264 sal_uInt16 SwDoc::GetBoxAlign( const SwCursor& rCursor )
1265 {
1266  sal_uInt16 nAlign = USHRT_MAX;
1267  SwTableNode* pTableNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
1268  SwSelBoxes aBoxes;
1269  if( pTableNd && ::lcl_GetBoxSel( rCursor, aBoxes ))
1270  {
1271  for (size_t i = 0; i < aBoxes.size(); ++i)
1272  {
1273  const SwFormatVertOrient &rOri =
1274  aBoxes[i]->GetFrameFormat()->GetVertOrient();
1275  if( USHRT_MAX == nAlign )
1276  nAlign = static_cast<sal_uInt16>(rOri.GetVertOrient());
1277  else if( rOri.GetVertOrient() != nAlign )
1278  {
1279  nAlign = USHRT_MAX;
1280  break;
1281  }
1282  }
1283  }
1284  return nAlign;
1285 }
1286 
1287 static sal_uInt16 lcl_CalcCellFit( const SwLayoutFrame *pCell )
1288 {
1289  SwTwips nRet = 0;
1290  const SwFrame *pFrame = pCell->Lower(); // The whole Line
1291  SwRectFnSet aRectFnSet(pCell);
1292  while ( pFrame )
1293  {
1294  const SwTwips nAdd = aRectFnSet.GetWidth(pFrame->getFrameArea()) -
1295  aRectFnSet.GetWidth(pFrame->getFramePrintArea());
1296 
1297  // pFrame does not necessarily have to be a SwTextFrame!
1298  const SwTwips nCalcFitToContent = pFrame->IsTextFrame() ?
1299  const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pFrame))->CalcFitToContent() :
1300  aRectFnSet.GetWidth(pFrame->getFramePrintArea());
1301 
1302  nRet = std::max( nRet, nCalcFitToContent + nAdd );
1303  pFrame = pFrame->GetNext();
1304  }
1305  // Surrounding border as well as left and Right Border also need to be respected
1306  nRet += aRectFnSet.GetWidth(pCell->getFrameArea()) -
1307  aRectFnSet.GetWidth(pCell->getFramePrintArea());
1308 
1309  // To compensate for the accuracy of calculation later on in SwTable::SetTabCols
1310  // we keep adding up a little.
1311  nRet += COLFUZZY;
1312  return static_cast<sal_uInt16>(std::max( long(MINLAY), nRet ));
1313 }
1314 
1315 /* The Line is within the Selection but not outlined by the TabCols.
1316  *
1317  * That means that the Line has been "split" by other Cells due to the
1318  * two-dimensional representation used. Thus, we have to distribute the cell's
1319  * default or minimum value amongst the Cell it has been split by.
1320  *
1321  * First, we collect the Columns (not the Column separators) which overlap
1322  * with the Cell. We then distribute the desired value according to the
1323  * amount of overlapping amongst the Cells.
1324  *
1325  * A Cell's default value stays the same if it already has a larger value than
1326  * the desired one. It's overwritten if it's smaller.
1327  */
1328 static void lcl_CalcSubColValues( std::vector<sal_uInt16> &rToFill, const SwTabCols &rCols,
1329  const SwLayoutFrame *pCell, const SwLayoutFrame *pTab,
1330  bool bWishValues )
1331 {
1332  const sal_uInt16 nWish = bWishValues ?
1333  ::lcl_CalcCellFit( pCell ) :
1334  MINLAY + sal_uInt16(pCell->getFrameArea().Width() - pCell->getFramePrintArea().Width());
1335 
1336  SwRectFnSet aRectFnSet(pTab);
1337 
1338  for ( size_t i = 0 ; i <= rCols.Count(); ++i )
1339  {
1340  long nColLeft = i == 0 ? rCols.GetLeft() : rCols[i-1];
1341  long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i];
1342  nColLeft += rCols.GetLeftMin();
1343  nColRight += rCols.GetLeftMin();
1344 
1345  // Adapt values to the proportions of the Table (Follows)
1346  if ( rCols.GetLeftMin() != aRectFnSet.GetLeft(pTab->getFrameArea()) )
1347  {
1348  const long nDiff = aRectFnSet.GetLeft(pTab->getFrameArea()) - rCols.GetLeftMin();
1349  nColLeft += nDiff;
1350  nColRight += nDiff;
1351  }
1352  const long nCellLeft = aRectFnSet.GetLeft(pCell->getFrameArea());
1353  const long nCellRight = aRectFnSet.GetRight(pCell->getFrameArea());
1354 
1355  // Calculate overlapping value
1356  long nWidth = 0;
1357  if ( nColLeft <= nCellLeft && nColRight >= (nCellLeft+COLFUZZY) )
1358  nWidth = nColRight - nCellLeft;
1359  else if ( nColLeft <= (nCellRight-COLFUZZY) && nColRight >= nCellRight )
1360  nWidth = nCellRight - nColLeft;
1361  else if ( nColLeft >= nCellLeft && nColRight <= nCellRight )
1362  nWidth = nColRight - nColLeft;
1363  if ( nWidth && pCell->getFrameArea().Width() )
1364  {
1365  long nTmp = nWidth * nWish / pCell->getFrameArea().Width();
1366  if ( sal_uInt16(nTmp) > rToFill[i] )
1367  rToFill[i] = sal_uInt16(nTmp);
1368  }
1369  }
1370 }
1371 
1390 static void lcl_CalcColValues( std::vector<sal_uInt16> &rToFill, const SwTabCols &rCols,
1391  const SwLayoutFrame *pStart, const SwLayoutFrame *pEnd,
1392  bool bWishValues )
1393 {
1394  SwSelUnions aUnions;
1395  ::MakeSelUnions( aUnions, pStart, pEnd,
1397 
1398  for ( auto &rU : aUnions )
1399  {
1400  SwSelUnion *pSelUnion = &rU;
1401  const SwTabFrame *pTab = pSelUnion->GetTable();
1402  const SwRect &rUnion = pSelUnion->GetUnion();
1403 
1404  SwRectFnSet aRectFnSet(pTab);
1405  bool bRTL = pTab->IsRightToLeft();
1406 
1407  const SwLayoutFrame *pCell = pTab->FirstCell();
1408  if (!pCell)
1409  continue;
1410  do
1411  {
1412  if ( pCell->IsCellFrame() && pCell->FindTabFrame() == pTab && ::IsFrameInTableSel( rUnion, pCell ) )
1413  {
1414  const long nCLeft = aRectFnSet.GetLeft(pCell->getFrameArea());
1415  const long nCRight = aRectFnSet.GetRight(pCell->getFrameArea());
1416 
1417  bool bNotInCols = true;
1418 
1419  for ( size_t i = 0; i <= rCols.Count(); ++i )
1420  {
1421  sal_uInt16 nFit = rToFill[i];
1422  long nColLeft = i == 0 ? rCols.GetLeft() : rCols[i-1];
1423  long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i];
1424 
1425  if ( bRTL )
1426  {
1427  long nTmpRight = nColRight;
1428  nColRight = rCols.GetRight() - nColLeft;
1429  nColLeft = rCols.GetRight() - nTmpRight;
1430  }
1431 
1432  nColLeft += rCols.GetLeftMin();
1433  nColRight += rCols.GetLeftMin();
1434 
1435  // Adapt values to the proportions of the Table (Follows)
1436  long nLeftA = nColLeft;
1437  long nRightA = nColRight;
1438  if ( rCols.GetLeftMin() != sal_uInt16(aRectFnSet.GetLeft(pTab->getFrameArea())) )
1439  {
1440  const long nDiff = aRectFnSet.GetLeft(pTab->getFrameArea()) - rCols.GetLeftMin();
1441  nLeftA += nDiff;
1442  nRightA += nDiff;
1443  }
1444 
1445  // We don't want to take a too close look
1446  if ( ::IsSame(nCLeft, nLeftA) && ::IsSame(nCRight, nRightA))
1447  {
1448  bNotInCols = false;
1449  if ( bWishValues )
1450  {
1451  const sal_uInt16 nWish = ::lcl_CalcCellFit( pCell );
1452  if ( nWish > nFit )
1453  nFit = nWish;
1454  }
1455  else
1456  { const sal_uInt16 nMin = MINLAY + sal_uInt16(pCell->getFrameArea().Width() -
1457  pCell->getFramePrintArea().Width());
1458  if ( !nFit || nMin < nFit )
1459  nFit = nMin;
1460  }
1461  if ( rToFill[i] < nFit )
1462  rToFill[i] = nFit;
1463  }
1464  }
1465  if ( bNotInCols )
1466  ::lcl_CalcSubColValues( rToFill, rCols, pCell, pTab, bWishValues );
1467  }
1468  do {
1469  pCell = pCell->GetNextLayoutLeaf();
1470  } while( pCell && pCell->getFrameArea().Width() == 0 );
1471  } while ( pCell && pTab->IsAnLower( pCell ) );
1472  }
1473 }
1474 
1475 void SwDoc::AdjustCellWidth( const SwCursor& rCursor,
1476  const bool bBalance,
1477  const bool bNoShrink )
1478 {
1479  // Check whether the current Cursor has it's Point/Mark in a Table
1480  SwContentNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetContentNode();
1481  SwTableNode* pTableNd = pCntNd ? pCntNd->FindTableNode() : nullptr;
1482  if( !pTableNd )
1483  return ;
1484 
1485  SwLayoutFrame *pStart, *pEnd;
1486  ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
1487 
1488  // Collect TabCols; we reset the Table with them
1489  SwFrame* pBoxFrame = pStart;
1490  while( pBoxFrame && !pBoxFrame->IsCellFrame() )
1491  pBoxFrame = pBoxFrame->GetUpper();
1492 
1493  if ( !pBoxFrame )
1494  return; // Robust
1495 
1496  SwTabCols aTabCols;
1497  GetTabCols( aTabCols, static_cast<SwCellFrame*>(pBoxFrame) );
1498 
1499  if ( ! aTabCols.Count() )
1500  return;
1501 
1502  std::vector<sal_uInt16> aWish(aTabCols.Count() + 1);
1503  std::vector<sal_uInt16> aMins(aTabCols.Count() + 1);
1504 
1505  ::lcl_CalcColValues( aWish, aTabCols, pStart, pEnd, /*bWishValues=*/true );
1506 
1507  // It's more robust if we calculate the minimum values for the whole Table
1508  const SwTabFrame *pTab = pStart->ImplFindTabFrame();
1509  pStart = const_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame const *>(pTab->FirstCell()));
1510  pEnd = const_cast<SwLayoutFrame*>(pTab->FindLastContentOrTable()->GetUpper());
1511  while( !pEnd->IsCellFrame() )
1512  pEnd = pEnd->GetUpper();
1513  ::lcl_CalcColValues( aMins, aTabCols, pStart, pEnd, /*bWishValues=*/false );
1514 
1515  sal_uInt16 nSelectedWidth = 0, nCols = 0;
1516  float fTotalWish = 0;
1517  if ( bBalance || bNoShrink )
1518  {
1519  // Find the combined size of the selected columns
1520  for ( size_t i = 0; i <= aTabCols.Count(); ++i )
1521  {
1522  if ( aWish[i] )
1523  {
1524  if ( i == 0 )
1525  nSelectedWidth += aTabCols[i] - aTabCols.GetLeft();
1526  else if ( i == aTabCols.Count() )
1527  nSelectedWidth += aTabCols.GetRight() - aTabCols[i-1];
1528  else
1529  nSelectedWidth += aTabCols[i] - aTabCols[i-1];
1530  ++nCols;
1531  }
1532  fTotalWish += aWish[i];
1533  }
1534  const sal_uInt16 nEqualWidth = nSelectedWidth / nCols;
1535  // bBalance: Distribute the width evenly
1536  for (sal_uInt16 & rn : aWish)
1537  if ( rn && bBalance )
1538  rn = nEqualWidth;
1539  }
1540 
1541  const long nOldRight = aTabCols.GetRight();
1542 
1543  // In order to make the implementation easier, but still use the available
1544  // space properly, we do this twice.
1545 
1546  // The problem: The first column is getting wider, the others get slimmer
1547  // only afterwards.
1548  // The first column's desired width would be discarded as it would cause
1549  // the Table's width to exceed the maximum width.
1550  const sal_uInt16 nEqualWidth = (aTabCols.GetRight() - aTabCols.GetLeft()) / (aTabCols.Count() + 1);
1551  const sal_Int16 nTablePadding = nSelectedWidth - fTotalWish;
1552  for ( int k = 0; k < 2; ++k )
1553  {
1554  for ( size_t i = 0; i <= aTabCols.Count(); ++i )
1555  {
1556  // bNoShrink: distribute excess space proportionately on pass 2.
1557  if ( bNoShrink && k && nTablePadding > 0 && fTotalWish > 0 )
1558  aWish[i] += round( aWish[i] / fTotalWish * nTablePadding );
1559 
1560  // First pass is primarily a shrink pass. Give all columns a chance
1561  // to grow by requesting the maximum width as "balanced".
1562  // Second pass is a first-come, first-served chance to max out.
1563  int nDiff = k ? aWish[i] : std::min(aWish[i], nEqualWidth);
1564  if ( nDiff )
1565  {
1566  int nMin = aMins[i];
1567  if ( nMin > nDiff )
1568  nDiff = nMin;
1569 
1570  if ( i == 0 )
1571  {
1572  if( aTabCols.Count() )
1573  nDiff -= aTabCols[0] - aTabCols.GetLeft();
1574  else
1575  nDiff -= aTabCols.GetRight() - aTabCols.GetLeft();
1576  }
1577  else if ( i == aTabCols.Count() )
1578  nDiff -= aTabCols.GetRight() - aTabCols[i-1];
1579  else
1580  nDiff -= aTabCols[i] - aTabCols[i-1];
1581 
1582  long nTabRight = aTabCols.GetRight() + nDiff;
1583 
1584  // If the Table would become too wide, we restrict the
1585  // adjusted amount to the allowed maximum.
1586  if ( !bBalance && nTabRight > aTabCols.GetRightMax() )
1587  {
1588  const long nTmpD = nTabRight - aTabCols.GetRightMax();
1589  nDiff -= nTmpD;
1590  nTabRight -= nTmpD;
1591  }
1592  for ( size_t i2 = i; i2 < aTabCols.Count(); ++i2 )
1593  aTabCols[i2] += nDiff;
1594  aTabCols.SetRight( nTabRight );
1595  }
1596  }
1597  }
1598 
1599  const long nNewRight = aTabCols.GetRight();
1600 
1601  SwFrameFormat *pFormat = pTableNd->GetTable().GetFrameFormat();
1602  const sal_Int16 nOriHori = pFormat->GetHoriOrient().GetHoriOrient();
1603 
1604  // We can leave the "real" work to the SwTable now
1605  SetTabCols( aTabCols, false, static_cast<SwCellFrame*>(pBoxFrame) );
1606 
1607  // Alignment might have been changed in SetTabCols; restore old value
1608  const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
1609  SwFormatHoriOrient aHori( rHori );
1610  if ( aHori.GetHoriOrient() != nOriHori )
1611  {
1612  aHori.SetHoriOrient( nOriHori );
1613  pFormat->SetFormatAttr( aHori );
1614  }
1615 
1616  // We switch to left-adjusted for automatic width
1617  // We adjust the right border for Border attributes
1618  if( !bBalance && nNewRight < nOldRight )
1619  {
1620  if( aHori.GetHoriOrient() == text::HoriOrientation::FULL )
1621  {
1622  aHori.SetHoriOrient( text::HoriOrientation::LEFT );
1623  pFormat->SetFormatAttr( aHori );
1624  }
1625  }
1626 
1628 }
1629 
1630 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:206
bool GetValue() const
Base class of the Writer layout elements.
Definition: frame.hxx:295
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
const FndLines_t & GetLines() const
Definition: tblsel.hxx:173
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
bool IsFollow() const
Definition: flowfrm.hxx:166
static void GetTabBorders(const SwCursor &rCursor, SfxItemSet &rSet)
Definition: ndtbl1.cxx:926
virtual const SwRootFrame * GetCurrentLayout() const =0
static sal_uInt16 GetBoxAlign(const SwCursor &rCursor)
Definition: ndtbl1.cxx:1264
static void lcl_SetLineStyle(SvxBorderLine *pToSet, const Color *pColor, const SvxBorderLine *pBorderLine)
Definition: ndtbl1.cxx:830
SwNodeIndex nNode
Definition: pam.hxx:37
static void GetTabCols(SwTabCols &rFill, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2478
static void lcl_ProcessRowAttr(std::vector< std::unique_ptr< SwTableFormatCmp >> &rFormatCmp, SwTableLine *pLine, const SfxPoolItem &rNew)
Definition: ndtbl1.cxx:277
SwTwips CalcFitToContent()
Simulates a formatting as if there were not right margin or Flys or other obstacles and returns the w...
Definition: txtfrm.cxx:3376
virtual void SetModified()=0
Must be called manually at changes of format.
long GetLeftMin() const
Definition: tabcol.hxx:76
#define RES_FRAMEDIR
Definition: hintids.hxx:320
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
void SetRowSplit(const SwCursor &rCursor, const SwFormatRowSplit &rNew)
Definition: ndtbl1.cxx:317
#define MINLAY
Definition: swtypes.hxx:66
const editeng::SvxBorderLine * GetVert() const
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1147
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1481
TElementType * Next()
Definition: calbck.hxx:373
sal_uInt16 GetDistance(SvxBoxItemLine nLine) const
static std::unique_ptr< SwFormatFrameSize > GetRowHeight(const SwCursor &rCursor)
Definition: ndtbl1.cxx:407
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
SwNode & GetNode() const
Definition: ndindex.hxx:119
static bool IsSame(long nA, long nB)
Definition: ndtbl1.cxx:58
long SwTwips
Definition: swtypes.hxx:49
static void lcl_ProcessRowSize(std::vector< std::unique_ptr< SwTableFormatCmp >> &rFormatCmp, SwTableLine *pLine, const SwFormatFrameSize &rNew)
Definition: ndtbl1.cxx:295
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:143
bool IsCellFrame() const
Definition: frame.hxx:1202
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
const editeng::SvxBorderLine * GetRight() const
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
Value in Var-direction gives minimum (can be exceeded but not be less).
size_type size() const
Definition: swtable.hxx:74
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
Definition: tblsel.cxx:2096
long GetRight() const
Definition: tabcol.hxx:78
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
void GetTableSelCrs(const SwCursorShell &rShell, SwSelBoxes &rBoxes)
Definition: tblsel.cxx:123
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
void ChgFrameFormat(SwTableLineFormat *pNewFormat)
Definition: swtable.cxx:1514
static bool lcl_GetBoxSel(const SwCursor &rCursor, SwSelBoxes &rBoxes, bool bAllCursor=false)
Definition: ndtbl1.cxx:138
void Top(const long nTop)
Definition: swrect.hxx:202
void AdjustCellWidth(const SwCursor &rCursor, const bool bBalance, const bool bNoShrink)
Adjusts selected cell widths in such a way, that their content does not need to be wrapped (if possib...
Definition: ndtbl1.cxx:1475
void SetHoriOrient(sal_Int16 eNew)
Definition: fmtornt.hxx:89
void SetBoxAttr(const SwCursor &rCursor, const SfxPoolItem &rNew)
Definition: ndtbl1.cxx:1147
const SwRect & getFrameArea() const
Definition: frame.hxx:175
virtual SvxFrameDirectionItem * Clone(SfxItemPool *pPool=nullptr) const override
bool IsTextFrame() const
Definition: frame.hxx:1210
void SetRowBackground(const SwCursor &rCursor, const SvxBrushItem &rNew)
Definition: ndtbl1.cxx:480
const FndBoxes_t & GetBoxes() const
Definition: tblsel.hxx:203
const SwTable & GetTable() const
Definition: node.hxx:497
const SfxPoolItem * GetDfltAttr(sal_uInt16 nWhich)
Get the default attribute from corresponding default attribute table.
Definition: hints.cxx:153
long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1355
long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1356
void Right(const long nRight)
Definition: swrect.hxx:198
size_type size() const
virtual bool DoesUndo() const =0
Is Undo enabled?
void SetRowHeight(const SwCursor &rCursor, const SwFormatFrameSize &rNew)
Definition: ndtbl1.cxx:382
SwPaM * GetNext()
Definition: pam.hxx:264
#define RES_BACKGROUND
Definition: hintids.hxx:305
void SetBoxAlign(const SwCursor &rCursor, sal_uInt16 nAlign)
Definition: ndtbl1.cxx:1255
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const editeng::SvxBorderLine * GetHori() const
const editeng::SvxBorderLine * GetTop() const
virtual void AppendUndo(std::unique_ptr< SwUndo > pUndo)=0
Add new Undo action.
SwTabFrame * ImplFindTabFrame()
Definition: findfrm.cxx:468
static void lcl_CalcSubColValues(std::vector< sal_uInt16 > &rToFill, const SwTabCols &rCols, const SwLayoutFrame *pCell, const SwLayoutFrame *pTab, bool bWishValues)
Definition: ndtbl1.cxx:1328
SwFrame * FindLastContentOrTable()
Definition: tabfrm.cxx:3338
Style of a layout element.
Definition: frmfmt.hxx:57
const editeng::SvxBorderLine * GetLeft() const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
static void lcl_GetStartEndCell(const SwCursor &rCursor, SwLayoutFrame *&prStart, SwLayoutFrame *&prEnd)
Definition: ndtbl1.cxx:111
Reference< XAnimationNode > Clone(const Reference< XAnimationNode > &xSourceNode, const SdPage *pSource, const SdPage *pTarget)
virtual SwFormatVertOrient * Clone(SfxItemPool *pPool=nullptr) const override
Definition: atrfrm.cxx:1276
static bool GetRowBackground(const SwCursor &rCursor, std::shared_ptr< SvxBrushItem > &rToFill)
Definition: ndtbl1.cxx:506
const SwPosition * GetPoint() const
Definition: pam.hxx:207
bool empty() const
Definition: swtable.hxx:73
const SwRect & GetUnion() const
Definition: tblsel.hxx:130
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:108
#define RES_VERT_ORIENT
Definition: hintids.hxx:302
void SetTabBorders(const SwCursor &rCursor, const SfxItemSet &rSet)
Definition: ndtbl1.cxx:564
static void InsertCell(std::vector< SwCellFrame * > &rCellArr, SwCellFrame *pCellFrame)
Definition: ndtbl1.cxx:535
const SwTabFrame * GetTable() const
Definition: tblsel.hxx:132
const SwFrame * Lower() const
Definition: layfrm.hxx:101
static void lcl_CalcColValues(std::vector< sal_uInt16 > &rToFill, const SwTabCols &rCols, const SwLayoutFrame *pStart, const SwLayoutFrame *pEnd, bool bWishValues)
Retrieves new values to set the TabCols.
Definition: ndtbl1.cxx:1390
int i
QPRO_FUNC_TYPE const nType
SwContentNode * GetContentNode()
Definition: node.hxx:615
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxInfoItemLine nLine)
SwDoc * GetDoc()
Definition: node.hxx:702
SwLayoutFrame * GetUpper()
Definition: frame.hxx:656
void BordersChanged(sal_uInt16 nAbsAvail)
Definition: htmltbl.cxx:1761
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:87
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:393
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:366
bool Resize(sal_uInt16 nAbsAvail, bool bRecalc=false, bool bForce=false, sal_uLong nDelay=0)
Recalculation of table widths for available width that has been passed.
Definition: htmltbl.cxx:1691
const Point & GetMkPos() const
Definition: viscrs.hxx:144
virtual SvxBoxItem * Clone(SfxItemPool *pPool=nullptr) const override
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:425
void MakeSelUnions(SwSelUnions &rUnions, const SwLayoutFrame *pStart, const SwLayoutFrame *pEnd, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:1763
static void lcl_CollectLines(std::vector< SwTableLine * > &rArr, const SwCursor &rCursor, bool bRemoveLines)
Definition: ndtbl1.cxx:237
static bool lcl_IsAnLower(const SwTableLine *pLine, const SwTableLine *pAssumed)
Definition: ndtbl1.cxx:168
bool empty() const
static bool FindLine_(FndLine_ &rLine, LinesAndTable *pPara)
Definition: ndtbl1.cxx:228
static sal_uInt16 lcl_CalcCellFit(const SwLayoutFrame *pCell)
Definition: ndtbl1.cxx:1287
static std::unique_ptr< SwFormatRowSplit > GetRowSplit(const SwCursor &rCursor)
Definition: ndtbl1.cxx:343
SwTableLines & GetTabLines()
Definition: swtable.hxx:198
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:404
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:110
SwTableLines & GetTabLines()
Definition: swtable.hxx:418
void SetTabLineStyle(const SwCursor &rCursor, const Color *pColor, bool bSetLine, const editeng::SvxBorderLine *pBorderLine)
Definition: ndtbl1.cxx:848
const SwCellFrame * FirstCell() const
Calls ContainsAny first to reach the innermost cell.
Definition: findfrm.cxx:112
bool IsValid(SvxBoxInfoItemValidFlags nValid) const
static void lcl_ProcessBoxSize(std::vector< std::unique_ptr< SwTableFormatCmp >> &rFormatCmp, SwTableBox *pBox, const SwFormatFrameSize &rNew)
Definition: ndtbl1.cxx:304
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1357
void Left(const long nLeft)
Definition: swrect.hxx:193
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
void Bottom(const long nBottom)
Definition: swrect.hxx:207
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:354
#define COLFUZZY
Definition: ndtbl1.cxx:56
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:103
void ChgFrameFormat(SwTableBoxFormat *pNewFormat, bool bNeedToReregister=true)
Definition: swtable.cxx:1741
bool IsFrameInTableSel(const SwRect &rUnion, const SwFrame *pCell)
Definition: tblsel.cxx:667
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
void SetDirectFormatting(bool bDirect)
Set that this table box contains formatting that is not set by the table style.
Definition: swtable.hxx:429
void Width(long nNew)
Definition: swrect.hxx:185
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:253
SwHTMLTableLayout * GetHTMLTableLayout()
Definition: swtable.hxx:174
std::vector< SwSelUnion > SwSelUnions
Definition: tblsel.hxx:138
const SwTableBox * GetBox() const
Definition: tblsel.hxx:175
SvxBoxItemLine
static void lcl_CollectCells(std::vector< SwCellFrame * > &rArr, const SwRect &rUnion, SwTabFrame *pTab)
Definition: ndtbl1.cxx:541
bool IsRightToLeft() const
Definition: frame.hxx:963
void ClearFEShellTabCols(SwDoc &rDoc, SwTabFrame const *const pFrame)
Definition: fetab.cxx:2084
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
bool BalanceRowHeight(const SwCursor &rCursor, bool bTstOnly, const bool bOptimize)
Adjustment of Rowheights.
Definition: ndtbl1.cxx:429
void SetHeight(long n)
const Point & GetPtPos() const
Definition: viscrs.hxx:142
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:54
void SetTabCols(const SwTabCols &rNew, bool bCurRowOnly, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2667
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1705
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:196
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:349
SwTableBox * GetUpper()
Definition: swtable.hxx:362
static bool FindBox_(FndBox_ &rBox, LinesAndTable *pPara)
Definition: ndtbl1.cxx:197
#define RES_BOX
Definition: hintids.hxx:306
static bool GetBoxAttr(const SwCursor &rCursor, std::shared_ptr< SfxPoolItem > &rToFill)
Retrieves a box attribute from the given cursor.
Definition: ndtbl1.cxx:1192
bool IsVertical() const
Definition: frame.hxx:949
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
static void InsertLine(std::vector< SwTableLine * > &rLineArr, SwTableLine *pLine)
Definition: ndtbl1.cxx:162
const SwLayoutFrame * GetNextLayoutLeaf() const
Definition: frame.hxx:996
sal_uInt16 GetBrowseWidthByTabFrame(const SwTabFrame &rTabFrame) const
Calculates available width by table-frame.
Definition: htmltbl.cxx:337
std::pair< const_iterator, bool > insert(Value &&x)
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:125
long GetHeight() const
SwTableLine * GetUpper()
Definition: swtable.hxx:421
const editeng::SvxBorderLine * GetBottom() const
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
long GetLeft() const
Definition: tabcol.hxx:77
size_t Count() const
Definition: tabcol.hxx:64
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5361
ITableControl & m_rTable
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1075
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxItemLine nLine)
SwFrame * GetNext()
Definition: frame.hxx:654
Base class of the Writer document model elements.
Definition: node.hxx:79