Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx
Warning:line 1727, column 13
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name tblsel.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx
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 <editeng/boxitem.hxx>
21#include <editeng/protitem.hxx>
22
23#include <hintids.hxx>
24#include <fmtanchr.hxx>
25#include <fmtfsize.hxx>
26#include <frmatr.hxx>
27#include <tblsel.hxx>
28#include <crsrsh.hxx>
29#include <doc.hxx>
30#include <IDocumentUndoRedo.hxx>
31#include <IDocumentLayoutAccess.hxx>
32#include <docary.hxx>
33#include <pam.hxx>
34#include <ndtxt.hxx>
35#include <swtable.hxx>
36#include <cntfrm.hxx>
37#include <tabfrm.hxx>
38#include <rowfrm.hxx>
39#include <cellfrm.hxx>
40#include <rootfrm.hxx>
41#include <viscrs.hxx>
42#include <swtblfmt.hxx>
43#include <UndoTable.hxx>
44#include <sectfrm.hxx>
45#include <frmtool.hxx>
46#include <calbck.hxx>
47#include <frameformats.hxx>
48#include <deque>
49#include <memory>
50
51// see also swtable.cxx
52#define COLFUZZY20L 20L
53
54// macros, determining how table boxes are merged:
55// - 1. remove empty lines, all boxes separated with blanks,
56// all lines separated with ParaBreak
57// - 2. remove all empty lines and remove all empty boxes at beginning and end,
58// all boxes separated with Blank,
59// all lines separated with ParaBreak
60// - 3. remove all empty boxes, all boxes separated with blanks,
61// all lines separated with ParaBreak
62
63#undef DEL_ONLY_EMPTY_LINES
64#undef DEL_EMPTY_BOXES_AT_START_AND_END
65
66namespace {
67
68struct CmpLPt
69{
70 Point aPos;
71 const SwTableBox* pSelBox;
72 bool bVert;
73
74 CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical );
75
76 bool operator<( const CmpLPt& rCmp ) const
77 {
78 if ( bVert )
79 return X() > rCmp.X() || ( X() == rCmp.X() && Y() < rCmp.Y() );
80 else
81 return Y() < rCmp.Y() || ( Y() == rCmp.Y() && X() < rCmp.X() );
82 }
83
84 long X() const { return aPos.X(); }
85 long Y() const { return aPos.Y(); }
86};
87
88}
89
90typedef o3tl::sorted_vector<CmpLPt> MergePos;
91
92namespace {
93
94struct Sort_CellFrame
95{
96 const SwCellFrame* pFrame;
97
98 explicit Sort_CellFrame( const SwCellFrame& rCFrame )
99 : pFrame( &rCFrame ) {}
100};
101
102}
103
104static const SwLayoutFrame *lcl_FindCellFrame( const SwLayoutFrame *pLay )
105{
106 while ( pLay && !pLay->IsCellFrame() )
107 pLay = pLay->GetUpper();
108 return pLay;
109}
110
111static const SwLayoutFrame *lcl_FindNextCellFrame( const SwLayoutFrame *pLay )
112{
113 // ensure we leave the cell (sections)
114 const SwLayoutFrame *pTmp = pLay;
115 do {
116 pTmp = pTmp->GetNextLayoutLeaf();
117 } while( pLay->IsAnLower( pTmp ) );
118
119 while( pTmp && !pTmp->IsCellFrame() )
120 pTmp = pTmp->GetUpper();
121 return pTmp;
122}
123
124void GetTableSelCrs( const SwCursorShell &rShell, SwSelBoxes& rBoxes )
125{
126 rBoxes.clear();
127 if( rShell.IsTableMode() && const_cast<SwCursorShell&>(rShell).UpdateTableSelBoxes())
128 {
129 rBoxes.insert(rShell.GetTableCursor()->GetSelectedBoxes());
130 }
131}
132
133void GetTableSelCrs( const SwTableCursor& rTableCursor, SwSelBoxes& rBoxes )
134{
135 rBoxes.clear();
136
137 if (rTableCursor.IsChgd() || !rTableCursor.GetSelectedBoxesCount())
138 {
139 SwTableCursor* pTCursor = const_cast<SwTableCursor*>(&rTableCursor);
140 pTCursor->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()->MakeTableCursors( *pTCursor );
141 }
142
143 if (rTableCursor.GetSelectedBoxesCount())
144 {
145 rBoxes.insert(rTableCursor.GetSelectedBoxes());
146 }
147}
148
149void GetTableSel( const SwCursorShell& rShell, SwSelBoxes& rBoxes,
150 const SwTableSearchType eSearchType )
151{
152 // get start and end cell
153 if ( !rShell.IsTableMode() )
154 rShell.GetCursor();
155
156 GetTableSel( *rShell.getShellCursor(false), rBoxes, eSearchType );
157}
158
159void GetTableSel( const SwCursor& rCursor, SwSelBoxes& rBoxes,
160 const SwTableSearchType eSearchType )
161{
162 // get start and end cell
163 OSL_ENSURE( rCursor.GetContentNode() && rCursor.GetContentNode( false ),do { if (true && (!(rCursor.GetContentNode() &&
rCursor.GetContentNode( false )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "164" ": "), "%s", "Tabselection not on Cnt."); } } while
(false)
164 "Tabselection not on Cnt." )do { if (true && (!(rCursor.GetContentNode() &&
rCursor.GetContentNode( false )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "164" ": "), "%s", "Tabselection not on Cnt."); } } while
(false)
;
165
166 // Row-selection:
167 // Check for complex tables. If Yes, search selected boxes via
168 // the layout. Otherwise via the table structure (for macros !!)
169 const SwContentNode* pContentNd = rCursor.GetNode().GetContentNode();
170 const SwTableNode* pTableNd = pContentNd ? pContentNd->FindTableNode() : nullptr;
171 if( pTableNd && pTableNd->GetTable().IsNewModel() )
172 {
173 SwTable::SearchType eSearch;
174 switch( SwTableSearchType::Col & eSearchType )
175 {
176 case SwTableSearchType::Row: eSearch = SwTable::SEARCH_ROW; break;
177 case SwTableSearchType::Col: eSearch = SwTable::SEARCH_COL; break;
178 default: eSearch = SwTable::SEARCH_NONE; break;
179 }
180 const bool bChkP( SwTableSearchType::Protect & eSearchType );
181 pTableNd->GetTable().CreateSelection( rCursor, rBoxes, eSearch, bChkP );
182 return;
183 }
184 if( SwTableSearchType::Row == ((~SwTableSearchType::Protect ) & eSearchType ) &&
185 pTableNd && !pTableNd->GetTable().IsTableComplex() )
186 {
187 const SwTable& rTable = pTableNd->GetTable();
188 const SwTableLines& rLines = rTable.GetTabLines();
189
190 const SwNode& rMarkNode = rCursor.GetNode( false );
191 const sal_uLong nMarkSectionStart = rMarkNode.StartOfSectionIndex();
192 const SwTableBox* pMarkBox = rTable.GetTableBox( nMarkSectionStart );
193
194 OSL_ENSURE( pMarkBox, "Point in table, mark outside?" )do { if (true && (!(pMarkBox))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "194" ": "), "%s", "Point in table, mark outside?"); } }
while (false)
;
195
196 const SwTableLine* pLine = pMarkBox ? pMarkBox->GetUpper() : nullptr;
197 sal_uInt16 nSttPos = rLines.GetPos( pLine );
198 OSL_ENSURE( USHRT_MAX != nSttPos, "Where is my row in the table?" )do { if (true && (!((32767 *2 +1) != nSttPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "198" ": "), "%s", "Where is my row in the table?"); } }
while (false)
;
199 pLine = rTable.GetTableBox( rCursor.GetNode().StartOfSectionIndex() )->GetUpper();
200 sal_uInt16 nEndPos = rLines.GetPos( pLine );
201 OSL_ENSURE( USHRT_MAX != nEndPos, "Where is my row in the table?" )do { if (true && (!((32767 *2 +1) != nEndPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "201" ": "), "%s", "Where is my row in the table?"); } }
while (false)
;
202 // pb: #i20193# if tableintable then nSttPos == nEndPos == USHRT_MAX
203 if ( nSttPos != USHRT_MAX(32767 *2 +1) && nEndPos != USHRT_MAX(32767 *2 +1) )
204 {
205 if( nEndPos < nSttPos ) // exchange
206 {
207 sal_uInt16 nTmp = nSttPos; nSttPos = nEndPos; nEndPos = nTmp;
208 }
209
210 bool bChkProtected( SwTableSearchType::Protect & eSearchType );
211 for( ; nSttPos <= nEndPos; ++nSttPos )
212 {
213 pLine = rLines[ nSttPos ];
214 for( auto n = pLine->GetTabBoxes().size(); n ; )
215 {
216 SwTableBox* pBox = pLine->GetTabBoxes()[ --n ];
217 // check for cell protection??
218 if( !bChkProtected ||
219 !pBox->GetFrameFormat()->GetProtect().IsContentProtected() )
220 rBoxes.insert( pBox );
221 }
222 }
223 }
224 }
225 else
226 {
227 Point aPtPos, aMkPos;
228 const SwShellCursor* pShCursor = dynamic_cast<const SwShellCursor*>(&rCursor);
229 if( pShCursor )
230 {
231 aPtPos = pShCursor->GetPtPos();
232 aMkPos = pShCursor->GetMkPos();
233 }
234 const SwContentNode *pCntNd = rCursor.GetContentNode();
235 std::pair<Point, bool> tmp(aPtPos, true);
236 const SwLayoutFrame *pStart = pCntNd ?
237 pCntNd->getLayoutFrame(pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp)->GetUpper() : nullptr;
238 pCntNd = rCursor.GetContentNode(false);
239 tmp.first = aMkPos;
240 const SwLayoutFrame *pEnd = pCntNd ?
241 pCntNd->getLayoutFrame(pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp)->GetUpper() : nullptr;
242 if( pStart && pEnd )
243 GetTableSel( pStart, pEnd, rBoxes, nullptr, eSearchType );
244 }
245}
246
247void GetTableSel( const SwLayoutFrame* pStart, const SwLayoutFrame* pEnd,
248 SwSelBoxes& rBoxes, SwCellFrames* pCells,
249 const SwTableSearchType eSearchType )
250{
251 const SwTabFrame* pStartTab = pStart->FindTabFrame();
252 if ( !pStartTab )
253 {
254 OSL_FAIL( "GetTableSel without start table" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "254" ": "), "%s", "GetTableSel without start table"); }
} while (false)
;
255 return;
256 }
257
258 bool bChkProtected( SwTableSearchType::Protect & eSearchType );
259
260 // #i55421# Reduced value 10
261 int nLoopMax = 10;
262
263 do {
264 bool bTableIsValid = true;
265
266 // First, compute tables and rectangles
267 SwSelUnions aUnions;
268 ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
269
270 Point aCurrentTopLeft( LONG_MAX9223372036854775807L, LONG_MAX9223372036854775807L );
271 Point aCurrentTopRight( 0, LONG_MAX9223372036854775807L );
272 Point aCurrentBottomLeft( LONG_MAX9223372036854775807L, 0 );
273 Point aCurrentBottomRight( 0, 0 );
274 const SwCellFrame* pCurrentTopLeftFrame = nullptr;
275 const SwCellFrame* pCurrentTopRightFrame = nullptr;
276 const SwCellFrame* pCurrentBottomLeftFrame = nullptr;
277 const SwCellFrame* pCurrentBottomRightFrame = nullptr;
278
279 // Now find boxes for each entry and emit
280 for (size_t i = 0; i < aUnions.size() && bTableIsValid; ++i)
281 {
282 SwSelUnion *pUnion = &aUnions[i];
283 const SwTabFrame *pTable = pUnion->GetTable();
284
285 if( !pTable->isFrameAreaDefinitionValid() && nLoopMax )
286 {
287 bTableIsValid = false;
288 break;
289 }
290
291 // Skip any repeated headlines in the follow:
292 const SwLayoutFrame* pRow = pTable->IsFollow() ?
293 pTable->GetFirstNonHeadlineRow() :
294 static_cast<const SwLayoutFrame*>(pTable->Lower());
295
296 while( pRow && bTableIsValid )
297 {
298 if( !pRow->isFrameAreaDefinitionValid() && nLoopMax )
299 {
300 bTableIsValid = false;
301 break;
302 }
303
304 if ( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
305 {
306 const SwLayoutFrame *pCell = pRow->FirstCell();
307
308 while (pCell && pRow->IsAnLower(pCell))
309 {
310 if( !pCell->isFrameAreaDefinitionValid() && nLoopMax )
311 {
312 bTableIsValid = false;
313 break;
314 }
315
316 OSL_ENSURE( pCell->IsCellFrame(), "Frame without Cell" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "316" ": "), "%s", "Frame without Cell"); } } while (false
)
;
317 if( ::IsFrameInTableSel( pUnion->GetUnion(), pCell ) )
318 {
319 SwTableBox* pBox = const_cast<SwTableBox*>(
320 static_cast<const SwCellFrame*>(pCell)->GetTabBox());
321 // check for cell protection??
322 if( !bChkProtected ||
323 !pBox->GetFrameFormat()->GetProtect().IsContentProtected() )
324 rBoxes.insert( pBox );
325
326 if ( pCells )
327 {
328 const Point aTopLeft( pCell->getFrameArea().TopLeft() );
329 const Point aTopRight( pCell->getFrameArea().TopRight() );
330 const Point aBottomLeft( pCell->getFrameArea().BottomLeft() );
331 const Point aBottomRight( pCell->getFrameArea().BottomRight() );
332
333 if ( aTopLeft.getY() < aCurrentTopLeft.getY() ||
334 ( aTopLeft.getY() == aCurrentTopLeft.getY() &&
335 aTopLeft.getX() < aCurrentTopLeft.getX() ) )
336 {
337 aCurrentTopLeft = aTopLeft;
338 pCurrentTopLeftFrame = static_cast<const SwCellFrame*>( pCell );
339 }
340
341 if ( aTopRight.getY() < aCurrentTopRight.getY() ||
342 ( aTopRight.getY() == aCurrentTopRight.getY() &&
343 aTopRight.getX() > aCurrentTopRight.getX() ) )
344 {
345 aCurrentTopRight = aTopRight;
346 pCurrentTopRightFrame = static_cast<const SwCellFrame*>( pCell );
347 }
348
349 if ( aBottomLeft.getY() > aCurrentBottomLeft.getY() ||
350 ( aBottomLeft.getY() == aCurrentBottomLeft.getY() &&
351 aBottomLeft.getX() < aCurrentBottomLeft.getX() ) )
352 {
353 aCurrentBottomLeft = aBottomLeft;
354 pCurrentBottomLeftFrame = static_cast<const SwCellFrame*>( pCell );
355 }
356
357 if ( aBottomRight.getY() > aCurrentBottomRight.getY() ||
358 ( aBottomRight.getY() == aCurrentBottomRight.getY() &&
359 aBottomRight.getX() > aCurrentBottomRight.getX() ) )
360 {
361 aCurrentBottomRight = aBottomRight;
362 pCurrentBottomRightFrame = static_cast<const SwCellFrame*>( pCell );
363 }
364
365 }
366 }
367 if ( pCell->GetNext() )
368 {
369 pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
370 if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
371 pCell = pCell->FirstCell();
372 }
373 else
374 pCell = ::lcl_FindNextCellFrame( pCell );
375 }
376 }
377 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
378 }
379 }
380
381 if ( pCells )
382 {
383 pCells->clear();
384 pCells->push_back( const_cast< SwCellFrame* >(pCurrentTopLeftFrame) );
385 pCells->push_back( const_cast< SwCellFrame* >(pCurrentTopRightFrame) );
386 pCells->push_back( const_cast< SwCellFrame* >(pCurrentBottomLeftFrame) );
387 pCells->push_back( const_cast< SwCellFrame* >(pCurrentBottomRightFrame) );
388 }
389
390 if( bTableIsValid )
391 break;
392
393 SwDeletionChecker aDelCheck( pStart );
394
395 // otherwise quickly "calculate" the table layout and start over
396 SwTabFrame *pTable = aUnions.front().GetTable();
397 while( pTable )
398 {
399 if( pTable->isFrameAreaDefinitionValid() )
400 {
401 pTable->InvalidatePos();
402 }
403
404 pTable->SetONECalcLowers();
405 pTable->Calc(pTable->getRootFrame()->GetCurrShell()->GetOut());
406 pTable->SetCompletePaint();
407
408 pTable = pTable->GetFollow();
409 if( nullptr == pTable )
410 break;
411 }
412
413 // --> Make code robust, check if pStart has
414 // been deleted due to the formatting of the table:
415 if ( aDelCheck.HasBeenDeleted() )
416 {
417 OSL_FAIL( "Current box has been deleted during GetTableSel()" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "417" ": "), "%s", "Current box has been deleted during GetTableSel()"
); } } while (false)
;
418 break;
419 }
420
421 rBoxes.clear();
422 --nLoopMax;
423
424 } while( true );
425 OSL_ENSURE( nLoopMax, "Table layout is still invalid!" )do { if (true && (!(nLoopMax))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "425" ": "), "%s", "Table layout is still invalid!"); } }
while (false)
;
426}
427
428bool ChkChartSel( const SwNode& rSttNd, const SwNode& rEndNd )
429{
430 const SwTableNode* pTNd = rSttNd.FindTableNode();
431 if( !pTNd )
432 return false;
433
434 Point aNullPos;
435 SwNodeIndex aIdx( rSttNd );
436 const SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
437 if( !pCNd )
438 pCNd = aIdx.GetNodes().GoNextSection( &aIdx, false, false );
439
440 // if table is invisible, return
441 // (layout needed for forming table selection further down, so we can't
442 // continue with invisible tables)
443 // #i22135# - Also the content of the table could be
444 // invisible - e.g. in a hidden section
445 // Robust: check, if content was found (e.g. empty table cells)
446 if ( !pCNd || pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) == nullptr )
447 return false;
448
449 std::pair<Point, bool> tmp(aNullPos, true);
450 const SwLayoutFrame *const pStart = pCNd->getLayoutFrame(
451 pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
452 nullptr, &tmp)->GetUpper();
453 OSL_ENSURE( pStart, "without frame nothing works" )do { if (true && (!(pStart))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "453" ": "), "%s", "without frame nothing works"); } } while
(false)
;
454
455 aIdx = rEndNd;
456 pCNd = aIdx.GetNode().GetContentNode();
457 if( !pCNd )
458 pCNd = aIdx.GetNodes().GoNextSection( &aIdx, false, false );
459
460 // #i22135# - Robust: check, if content was found and if it's visible
461 if ( !pCNd || pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) == nullptr )
462 {
463 return false;
464 }
465
466 const SwLayoutFrame *const pEnd = pCNd->getLayoutFrame(
467 pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
468 nullptr, &tmp)->GetUpper();
469 OSL_ENSURE( pEnd, "without frame nothing works" )do { if (true && (!(pEnd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "469" ": "), "%s", "without frame nothing works"); } } while
(false)
;
470
471 bool bValidChartSel;
472 // #i55421# Reduced value 10
473 int nLoopMax = 10; //JP 28.06.99: max 100 loops - Bug 67292
474
475 do {
476 bool bTableIsValid = true;
477 bValidChartSel = true;
478
479 sal_uInt16 nRowCells = USHRT_MAX(32767 *2 +1);
480
481 // First, compute tables and rectangles
482 SwSelUnions aUnions;
483 ::MakeSelUnions( aUnions, pStart, pEnd, SwTableSearchType::NoUnionCorrect );
484
485 // find boxes for each entry and emit
486 for( auto & rSelUnion : aUnions )
487 {
488 if (!bTableIsValid || !bValidChartSel)
489 break;
490
491 SwSelUnion *pUnion = &rSelUnion;
492 const SwTabFrame *pTable = pUnion->GetTable();
493
494 SwRectFnSet aRectFnSet(pTable);
495 bool bRTL = pTable->IsRightToLeft();
496
497 if( !pTable->isFrameAreaDefinitionValid() && nLoopMax )
498 {
499 bTableIsValid = false;
500 break;
501 }
502
503 std::deque< Sort_CellFrame > aCellFrames;
504
505 // Skip any repeated headlines in the follow:
506 const SwLayoutFrame* pRow = pTable->IsFollow() ?
507 pTable->GetFirstNonHeadlineRow() :
508 static_cast<const SwLayoutFrame*>(pTable->Lower());
509
510 while( pRow && bTableIsValid && bValidChartSel )
511 {
512 if( !pRow->isFrameAreaDefinitionValid() && nLoopMax )
513 {
514 bTableIsValid = false;
515 break;
516 }
517
518 if( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
519 {
520 const SwLayoutFrame *pCell = pRow->FirstCell();
521
522 while (pCell && pRow->IsAnLower(pCell))
523 {
524 if( !pCell->isFrameAreaDefinitionValid() && nLoopMax )
525 {
526 bTableIsValid = false;
527 break;
528 }
529
530 OSL_ENSURE( pCell->IsCellFrame(), "Frame without Cell" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "530" ": "), "%s", "Frame without Cell"); } } while (false
)
;
531 const SwRect& rUnion = pUnion->GetUnion(),
532 & rFrameRect = pCell->getFrameArea();
533
534 const long nUnionRight = rUnion.Right();
535 const long nUnionBottom = rUnion.Bottom();
536 const long nFrameRight = rFrameRect.Right();
537 const long nFrameBottom = rFrameRect.Bottom();
538
539 // ignore if FrameRect is outside the union
540
541 const long nXFuzzy = aRectFnSet.IsVert() ? 0 : 20;
542 const long nYFuzzy = aRectFnSet.IsVert() ? 20 : 0;
543
544 if( !( rUnion.Top() + nYFuzzy > nFrameBottom ||
545 nUnionBottom < rFrameRect.Top() + nYFuzzy ||
546 rUnion.Left() + nXFuzzy > nFrameRight ||
547 nUnionRight < rFrameRect.Left() + nXFuzzy ))
548 {
549 // ok, rUnion is _not_ completely outside of rFrameRect
550
551 // if not completely inside the union, then
552 // for Chart it is an invalid selection
553 if( rUnion.Left() <= rFrameRect.Left() + nXFuzzy &&
554 rFrameRect.Left() <= nUnionRight &&
555 rUnion.Left() <= nFrameRight &&
556 nFrameRight <= nUnionRight + nXFuzzy &&
557 rUnion.Top() <= rFrameRect.Top() + nYFuzzy &&
558 rFrameRect.Top() <= nUnionBottom &&
559 rUnion.Top() <= nFrameBottom &&
560 nFrameBottom <= nUnionBottom+ nYFuzzy )
561
562 aCellFrames.emplace_back( *static_cast<const SwCellFrame*>(pCell) );
563 else
564 {
565 bValidChartSel = false;
566 break;
567 }
568 }
569 if ( pCell->GetNext() )
570 {
571 pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
572 if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
573 pCell = pCell->FirstCell();
574 }
575 else
576 pCell = ::lcl_FindNextCellFrame( pCell );
577 }
578 }
579 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
580 }
581
582 if( !bValidChartSel )
583 break;
584
585 // all cells of the (part) table together. Now check if
586 // they're all adjacent
587 size_t n;
588 sal_uInt16 nCellCnt = 0;
589 long nYPos = LONG_MAX9223372036854775807L;
590 long nXPos = 0;
591 long nHeight = 0;
592
593 for( n = 0 ; n < aCellFrames.size(); ++n )
594 {
595 const Sort_CellFrame& rCF = aCellFrames[ n ];
596 if( aRectFnSet.GetTop(rCF.pFrame->getFrameArea()) != nYPos )
597 {
598 // new row
599 if( n )
600 {
601 if( USHRT_MAX(32767 *2 +1) == nRowCells ) // 1. row change
602 nRowCells = nCellCnt;
603 else if( nRowCells != nCellCnt )
604 {
605 bValidChartSel = false;
606 break;
607 }
608 }
609 nCellCnt = 1;
610 nYPos = aRectFnSet.GetTop(rCF.pFrame->getFrameArea());
611 nHeight = aRectFnSet.GetHeight(rCF.pFrame->getFrameArea());
612
613 nXPos = bRTL ?
614 aRectFnSet.GetLeft(rCF.pFrame->getFrameArea()) :
615 aRectFnSet.GetRight(rCF.pFrame->getFrameArea());
616 }
617 else if( nXPos == ( bRTL ?
618 aRectFnSet.GetRight(rCF.pFrame->getFrameArea()) :
619 aRectFnSet.GetLeft(rCF.pFrame->getFrameArea()) ) &&
620 nHeight == aRectFnSet.GetHeight(rCF.pFrame->getFrameArea()) )
621 {
622 nXPos += ( bRTL ? -1 : 1 ) *
623 aRectFnSet.GetWidth(rCF.pFrame->getFrameArea());
624 ++nCellCnt;
625 }
626 else
627 {
628 bValidChartSel = false;
629 break;
630 }
631 }
632 if( bValidChartSel )
633 {
634 if( USHRT_MAX(32767 *2 +1) == nRowCells )
635 nRowCells = nCellCnt;
636 else if( nRowCells != nCellCnt )
637 bValidChartSel = false;
638 }
639 }
640
641 if( bTableIsValid )
642 break;
643
644 // otherwise quickly "calculate" table layout and start over
645 SwTabFrame *pTable = aUnions.front().GetTable();
646
647 for( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
648 {
649 if( pTable->isFrameAreaDefinitionValid() )
650 {
651 pTable->InvalidatePos();
652 }
653
654 pTable->SetONECalcLowers();
655 pTable->Calc(pTable->getRootFrame()->GetCurrShell()->GetOut());
656 pTable->SetCompletePaint();
657
658 pTable = pTable->GetFollow();
659 if( nullptr == pTable )
660 break;
661 }
662 --nLoopMax;
663 } while( true );
664
665 OSL_ENSURE( nLoopMax, "table layout is still invalid!" )do { if (true && (!(nLoopMax))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "665" ": "), "%s", "table layout is still invalid!"); } }
while (false)
;
666
667 return bValidChartSel;
668}
669
670bool IsFrameInTableSel( const SwRect& rUnion, const SwFrame* pCell )
671{
672 OSL_ENSURE( pCell->IsCellFrame(), "Frame without Gazelle" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "672" ": "), "%s", "Frame without Gazelle"); } } while (
false)
;
673
674 if( pCell->FindTabFrame()->IsVertical() )
675 return rUnion.Right() >= pCell->getFrameArea().Right() &&
676 rUnion.Left() <= pCell->getFrameArea().Left() &&
677 (( rUnion.Top() <= pCell->getFrameArea().Top()+20 &&
678 rUnion.Bottom() > pCell->getFrameArea().Top() ) ||
679 ( rUnion.Top() >= pCell->getFrameArea().Top() &&
680 rUnion.Bottom() < pCell->getFrameArea().Bottom() ));
681
682 return
683 rUnion.Top() <= pCell->getFrameArea().Top() &&
684 rUnion.Bottom() >= pCell->getFrameArea().Bottom() &&
685
686 (( rUnion.Left() <= pCell->getFrameArea().Left()+20 &&
687 rUnion.Right() > pCell->getFrameArea().Left() ) ||
688
689 ( rUnion.Left() >= pCell->getFrameArea().Left() &&
690 rUnion.Right() < pCell->getFrameArea().Right() ));
691}
692
693bool GetAutoSumSel( const SwCursorShell& rShell, SwCellFrames& rBoxes )
694{
695 SwShellCursor* pCursor = rShell.m_pCurrentCursor;
696 if ( rShell.IsTableMode() )
697 pCursor = rShell.m_pTableCursor;
698
699 std::pair<Point, bool> tmp(pCursor->GetPtPos(), true);
700 const SwLayoutFrame *const pStart = pCursor->GetContentNode()->getLayoutFrame(
701 rShell.GetLayout(), nullptr, &tmp)->GetUpper();
702 tmp.first = pCursor->GetMkPos();
703 const SwLayoutFrame *const pEnd = pCursor->GetContentNode(false)->getLayoutFrame(
704 rShell.GetLayout(), nullptr, &tmp)->GetUpper();
705
706 const SwLayoutFrame* pSttCell = pStart;
707 while( pSttCell && !pSttCell->IsCellFrame() )
708 pSttCell = pSttCell->GetUpper();
709
710 // First, compute tables and rectangles
711 SwSelUnions aUnions;
712
713 // by default, first test above and then to the left
714 ::MakeSelUnions( aUnions, pStart, pEnd, SwTableSearchType::Col );
715
716 bool bTstRow = true, bFound = false;
717
718 // 1. check if box above contains value/formula
719 for( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
720 {
721 SwSelUnion *pUnion = &aUnions[i];
722 const SwTabFrame *pTable = pUnion->GetTable();
723
724 // Skip any repeated headlines in the follow:
725 const SwLayoutFrame* pRow = pTable->IsFollow() ?
726 pTable->GetFirstNonHeadlineRow() :
727 static_cast<const SwLayoutFrame*>(pTable->Lower());
728
729 while( pRow )
730 {
731 if( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
732 {
733 const SwCellFrame* pUpperCell = nullptr;
734 const SwLayoutFrame *pCell = pRow->FirstCell();
735
736 while( pCell && pRow->IsAnLower( pCell ) )
737 {
738 if( pCell == pSttCell )
739 {
740 sal_uInt16 nWhichId = 0;
741 for( size_t n = rBoxes.size(); n; )
742 {
743 nWhichId = rBoxes[ --n ]->GetTabBox()->IsFormulaOrValueBox();
744 if( USHRT_MAX(32767 *2 +1) != nWhichId )
745 break;
746 }
747
748 // all boxes together, do not check the
749 // row, if a formula or value was found
750 bTstRow = 0 == nWhichId || USHRT_MAX(32767 *2 +1) == nWhichId;
751 bFound = true;
752 break;
753 }
754
755 OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "755" ": "), "%s", "Frame without cell"); } } while (false
)
;
756 if( ::IsFrameInTableSel( pUnion->GetUnion(), pCell ) )
757 pUpperCell = static_cast<const SwCellFrame*>(pCell);
758
759 if( pCell->GetNext() )
760 {
761 pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
762 if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
763 pCell = pCell->FirstCell();
764 }
765 else
766 pCell = ::lcl_FindNextCellFrame( pCell );
767 }
768
769 if( pUpperCell )
770 rBoxes.push_back( const_cast< SwCellFrame* >(pUpperCell) );
771 }
772 if( bFound )
773 {
774 i = aUnions.size();
775 break;
776 }
777 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
778 }
779 }
780
781 // 2. check if box on left contains value/formula
782 if( bTstRow )
783 {
784 bFound = false;
785
786 rBoxes.clear();
787 aUnions.clear();
788 ::MakeSelUnions( aUnions, pStart, pEnd, SwTableSearchType::Row );
789
790 for( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
791 {
792 SwSelUnion *pUnion = &aUnions[i];
793 const SwTabFrame *pTable = pUnion->GetTable();
794
795 // Skip any repeated headlines in the follow:
796 const SwLayoutFrame* pRow = pTable->IsFollow() ?
797 pTable->GetFirstNonHeadlineRow() :
798 static_cast<const SwLayoutFrame*>(pTable->Lower());
799
800 while( pRow )
801 {
802 if( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
803 {
804 const SwLayoutFrame *pCell = pRow->FirstCell();
805
806 while( pCell && pRow->IsAnLower( pCell ) )
807 {
808 if( pCell == pSttCell )
809 {
810 sal_uInt16 nWhichId = 0;
811 for( size_t n = rBoxes.size(); n; )
812 {
813 nWhichId = rBoxes[ --n ]
814 ->GetTabBox()->IsFormulaOrValueBox();
815 if( USHRT_MAX(32767 *2 +1) != nWhichId )
816 break;
817 }
818
819 // all boxes together, do not check the
820 // row if a formula or value was found
821 bFound = 0 != nWhichId && USHRT_MAX(32767 *2 +1) != nWhichId;
822 bTstRow = false;
823 break;
824 }
825
826 OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "826" ": "), "%s", "Frame without cell"); } } while (false
)
;
827 if( ::IsFrameInTableSel( pUnion->GetUnion(), pCell ) )
828 {
829 SwCellFrame* pC = const_cast<SwCellFrame*>(static_cast<const SwCellFrame*>(pCell));
830 rBoxes.push_back( pC );
831 }
832 if( pCell->GetNext() )
833 {
834 pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
835 if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
836 pCell = pCell->FirstCell();
837 }
838 else
839 pCell = ::lcl_FindNextCellFrame( pCell );
840 }
841 }
842 if( !bTstRow )
843 {
844 i = aUnions.size();
845 break;
846 }
847
848 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
849 }
850 }
851 }
852
853 return bFound;
854}
855
856bool HasProtectedCells( const SwSelBoxes& rBoxes )
857{
858 bool bRet = false;
859 for (size_t n = 0; n < rBoxes.size(); ++n)
860 {
861 if( rBoxes[ n ]->GetFrameFormat()->GetProtect().IsContentProtected() )
862 {
863 bRet = true;
864 break;
865 }
866 }
867 return bRet;
868}
869
870CmpLPt::CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical )
871 : aPos( rPt ), pSelBox( pBox ), bVert( bVertical )
872{}
873
874static void lcl_InsTableBox( SwTableNode* pTableNd, SwDoc* pDoc, SwTableBox* pBox,
875 sal_uInt16 nInsPos, sal_uInt16 nCnt = 1 )
876{
877 OSL_ENSURE( pBox->GetSttNd(), "Box without Start-Node" )do { if (true && (!(pBox->GetSttNd()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "877" ": "), "%s", "Box without Start-Node"); } } while (
false)
;
878 SwContentNode* pCNd = pDoc->GetNodes()[ pBox->GetSttIdx() + 1 ]
879 ->GetContentNode();
880 if( pCNd && pCNd->IsTextNode() )
881 pDoc->GetNodes().InsBoxen( pTableNd, pBox->GetUpper(),
882 static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat()),
883 static_cast<SwTextNode*>(pCNd)->GetTextColl(),
884 pCNd->GetpSwAttrSet(),
885 nInsPos, nCnt );
886 else
887 pDoc->GetNodes().InsBoxen( pTableNd, pBox->GetUpper(),
888 static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat()),
889 pDoc->GetDfltTextFormatColl(), nullptr,
890 nInsPos, nCnt );
891}
892
893bool IsEmptyBox( const SwTableBox& rBox, SwPaM& rPam )
894{
895 rPam.GetPoint()->nNode = *rBox.GetSttNd()->EndOfSectionNode();
896 rPam.Move( fnMoveBackward, GoInContent );
897 rPam.SetMark();
898 rPam.GetPoint()->nNode = *rBox.GetSttNd();
899 rPam.Move( fnMoveForward, GoInContent );
900 bool bRet = *rPam.GetMark() == *rPam.GetPoint()
901 && ( rBox.GetSttNd()->GetIndex() + 1 == rPam.GetPoint()->nNode.GetIndex() );
902
903 if( bRet )
904 {
905 // now check for paragraph bound flies
906 const SwFrameFormats& rFormats = *rPam.GetDoc().GetSpzFrameFormats();
907 sal_uLong nSttIdx = rPam.GetPoint()->nNode.GetIndex(),
908 nEndIdx = rBox.GetSttNd()->EndOfSectionIndex(),
909 nIdx;
910
911 for( auto pFormat : rFormats )
912 {
913 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
914 const SwPosition* pAPos = rAnchor.GetContentAnchor();
915 if (pAPos &&
916 ((RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) ||
917 (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
918 nSttIdx <= ( nIdx = pAPos->nNode.GetIndex() ) &&
919 nIdx < nEndIdx )
920 {
921 bRet = false;
922 break;
923 }
924 }
925 }
926 return bRet;
927}
928
929void GetMergeSel( const SwPaM& rPam, SwSelBoxes& rBoxes,
930 SwTableBox** ppMergeBox, SwUndoTableMerge* pUndo )
931{
932 rBoxes.clear();
933
934 OSL_ENSURE( rPam.GetContentNode() && rPam.GetContentNode( false ),do { if (true && (!(rPam.GetContentNode() && rPam
.GetContentNode( false )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "935" ": "), "%s", "Tabselection not on Cnt."); } } while
(false)
935 "Tabselection not on Cnt." )do { if (true && (!(rPam.GetContentNode() && rPam
.GetContentNode( false )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "935" ": "), "%s", "Tabselection not on Cnt."); } } while
(false)
;
936
937//JP 24.09.96: Merge with repeating TableHeadLines does not work properly.
938// Why not use point 0,0? Then it is assured the first
939// headline is contained.
940 Point aPt( 0, 0 );
941
942 const SwContentNode* pCntNd = rPam.GetContentNode();
943 std::pair<Point, bool> const tmp(aPt, true);
944 const SwLayoutFrame *const pStart = pCntNd->getLayoutFrame(
945 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
946 nullptr, &tmp)->GetUpper();
947 pCntNd = rPam.GetContentNode(false);
948 const SwLayoutFrame *const pEnd = pCntNd->getLayoutFrame(
949 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
950 nullptr, &tmp)->GetUpper();
951
952 // First, compute tables and rectangles
953 SwSelUnions aUnions;
954 ::MakeSelUnions( aUnions, pStart, pEnd );
955 if( aUnions.empty() )
956 return;
957
958 const SwTable *pTable = aUnions.front().GetTable()->GetTable();
959 SwDoc* pDoc = const_cast<SwDoc*>(pStart->GetFormat()->GetDoc());
960 SwTableNode* pTableNd = const_cast<SwTableNode*>(pTable->GetTabSortBoxes()[ 0 ]->
961 GetSttNd()->FindTableNode());
962
963 MergePos aPosArr; // Sort-Array with the frame positions
964 long nWidth;
965 SwTableBox* pLastBox = nullptr;
966
967 SwRectFnSet aRectFnSet(pStart->GetUpper());
968
969 for ( auto & rSelUnion : aUnions )
970 {
971 const SwTabFrame *pTabFrame = rSelUnion.GetTable();
972
973 SwRect &rUnion = rSelUnion.GetUnion();
974
975 // Skip any repeated headlines in the follow:
976 const SwLayoutFrame* pRow = pTabFrame->IsFollow() ?
977 pTabFrame->GetFirstNonHeadlineRow() :
978 static_cast<const SwLayoutFrame*>(pTabFrame->Lower());
979
980 while ( pRow )
981 {
982 if ( pRow->getFrameArea().IsOver( rUnion ) )
983 {
984 const SwLayoutFrame *pCell = pRow->FirstCell();
985
986 while ( pCell && pRow->IsAnLower( pCell ) )
987 {
988 OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "988" ": "), "%s", "Frame without cell"); } } while (false
)
;
989 // overlap in full width?
990 if( rUnion.Top() <= pCell->getFrameArea().Top() &&
991 rUnion.Bottom() >= pCell->getFrameArea().Bottom() )
992 {
993 SwTableBox* pBox = const_cast<SwTableBox*>(static_cast<const SwCellFrame*>(pCell)->GetTabBox());
994
995 // only overlap to the right?
996 if( ( rUnion.Left() - COLFUZZY20L ) <= pCell->getFrameArea().Left() &&
997 ( rUnion.Right() - COLFUZZY20L ) > pCell->getFrameArea().Left() )
998 {
999 if( ( rUnion.Right() + COLFUZZY20L ) < pCell->getFrameArea().Right() )
1000 {
1001 sal_uInt16 nInsPos = pBox->GetUpper()->GetBoxPos( pBox )+1;
1002 lcl_InsTableBox( pTableNd, pDoc, pBox, nInsPos );
1003 pBox->ClaimFrameFormat();
1004 SwFormatFrameSize aNew(
1005 pBox->GetFrameFormat()->GetFrameSize() );
1006 nWidth = rUnion.Right() - pCell->getFrameArea().Left();
1007 nWidth = nWidth * aNew.GetWidth() /
1008 pCell->getFrameArea().Width();
1009 long nTmpWidth = aNew.GetWidth() - nWidth;
1010 aNew.SetWidth( nWidth );
1011 pBox->GetFrameFormat()->SetFormatAttr( aNew );
1012 // this box is selected
1013 pLastBox = pBox;
1014 rBoxes.insert( pBox );
1015 aPosArr.insert(
1016 CmpLPt( aRectFnSet.GetPos(pCell->getFrameArea()),
1017 pBox, aRectFnSet.IsVert() ) );
1018
1019 pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
1020 aNew.SetWidth( nTmpWidth );
1021 pBox->ClaimFrameFormat();
1022 pBox->GetFrameFormat()->SetFormatAttr( aNew );
1023
1024 if( pUndo )
1025 pUndo->AddNewBox( pBox->GetSttIdx() );
1026 }
1027 else
1028 {
1029 // this box is selected
1030 pLastBox = pBox;
1031 rBoxes.insert( pBox );
1032 aPosArr.insert(
1033 CmpLPt( aRectFnSet.GetPos(pCell->getFrameArea()),
1034 pBox, aRectFnSet.IsVert() ) );
1035 }
1036 }
1037 // overlapping on left- or right-side
1038 else if( ( rUnion.Left() - COLFUZZY20L ) >= pCell->getFrameArea().Left() &&
1039 ( rUnion.Right() + COLFUZZY20L ) < pCell->getFrameArea().Right() )
1040 {
1041 sal_uInt16 nInsPos = pBox->GetUpper()->GetBoxPos( pBox )+1;
1042 lcl_InsTableBox( pTableNd, pDoc, pBox, nInsPos, 2 );
1043 pBox->ClaimFrameFormat();
1044 SwFormatFrameSize aNew(
1045 pBox->GetFrameFormat()->GetFrameSize() );
1046 long nLeft = rUnion.Left() - pCell->getFrameArea().Left();
1047 nLeft = nLeft * aNew.GetWidth() /
1048 pCell->getFrameArea().Width();
1049 long nRight = pCell->getFrameArea().Right() - rUnion.Right();
1050 nRight = nRight * aNew.GetWidth() /
1051 pCell->getFrameArea().Width();
1052 nWidth = aNew.GetWidth() - nLeft - nRight;
1053
1054 aNew.SetWidth( nLeft );
1055 pBox->GetFrameFormat()->SetFormatAttr( aNew );
1056
1057 {
1058 const SfxPoolItem* pItem;
1059 if( SfxItemState::SET == pBox->GetFrameFormat()->GetAttrSet()
1060 .GetItemState( RES_BOX, false, &pItem ))
1061 {
1062 SvxBoxItem aBox( *static_cast<const SvxBoxItem*>(pItem) );
1063 aBox.SetLine( nullptr, SvxBoxItemLine::RIGHT );
1064 pBox->GetFrameFormat()->SetFormatAttr( aBox );
1065 }
1066 }
1067
1068 pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
1069 aNew.SetWidth( nWidth );
1070 pBox->ClaimFrameFormat();
1071 pBox->GetFrameFormat()->SetFormatAttr( aNew );
1072
1073 if( pUndo )
1074 pUndo->AddNewBox( pBox->GetSttIdx() );
1075
1076 // this box is selected
1077 pLastBox = pBox;
1078 rBoxes.insert( pBox );
1079 aPosArr.insert(
1080 CmpLPt( aRectFnSet.GetPos(pCell->getFrameArea()),
1081 pBox, aRectFnSet.IsVert() ) );
1082
1083 pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos+1 ];
1084 aNew.SetWidth( nRight );
1085 pBox->ClaimFrameFormat();
1086 pBox->GetFrameFormat()->SetFormatAttr( aNew );
1087
1088 if( pUndo )
1089 pUndo->AddNewBox( pBox->GetSttIdx() );
1090 }
1091 // is right side of box part of the selected area?
1092 else if( ( pCell->getFrameArea().Right() - COLFUZZY20L ) < rUnion.Right() &&
1093 ( pCell->getFrameArea().Right() - COLFUZZY20L ) > rUnion.Left() &&
1094 ( pCell->getFrameArea().Left() + COLFUZZY20L ) < rUnion.Left() )
1095 {
1096 // then we should insert a new box and adjust the widths
1097 sal_uInt16 nInsPos = pBox->GetUpper()->GetBoxPos( pBox )+1;
1098 lcl_InsTableBox( pTableNd, pDoc, pBox, nInsPos );
1099
1100 SwFormatFrameSize aNew(pBox->GetFrameFormat()->GetFrameSize() );
1101 long nLeft = rUnion.Left() - pCell->getFrameArea().Left(),
1102 nRight = pCell->getFrameArea().Right() - rUnion.Left();
1103
1104 nLeft = nLeft * aNew.GetWidth() /
1105 pCell->getFrameArea().Width();
1106 nRight = nRight * aNew.GetWidth() /
1107 pCell->getFrameArea().Width();
1108
1109 aNew.SetWidth( nLeft );
1110 pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
1111
1112 // this box is selected
1113 pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
1114 aNew.SetWidth( nRight );
1115 pBox->ClaimFrameFormat();
1116 pBox->GetFrameFormat()->SetFormatAttr( aNew );
1117
1118 pLastBox = pBox;
1119 rBoxes.insert( pBox );
1120 aPosArr.insert( CmpLPt( Point( rUnion.Left(),
1121 pCell->getFrameArea().Top()), pBox, aRectFnSet.IsVert() ));
1122
1123 if( pUndo )
1124 pUndo->AddNewBox( pBox->GetSttIdx() );
1125 }
1126 }
1127 if ( pCell->GetNext() )
1128 {
1129 pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
1130 // --> Check if table cell is not empty
1131 if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
1132 pCell = pCell->FirstCell();
1133 }
1134 else
1135 pCell = ::lcl_FindNextCellFrame( pCell );
1136 }
1137 }
1138 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
1139 }
1140 }
1141
1142 // no SSelection / no boxes found
1143 if( 1 >= rBoxes.size() )
1144 return;
1145
1146 // now search all horizontally adjacent boxes and connect
1147 // their contents with blanks. All vertically adjacent will be tied
1148 // together as paragraphs
1149
1150 // 1. Solution: map array and all on same Y-level
1151 // are separated with blanks
1152 // all others are separated with paragraphs
1153 bool bCalcWidth = true;
1154 const SwTableBox* pFirstBox = aPosArr[ 0 ].pSelBox;
1155
1156 // JP 27.03.98: Optimise - if boxes on one row are empty,
1157 // then do not insert blanks or carriage returns
1158 //Block to assure SwPaM, SwPosition are deleted from stack
1159 {
1160 SwPaM aPam( pDoc->GetNodes() );
1161
1162#if defined( DEL_ONLY_EMPTY_LINES )
1163 nWidth = pFirstBox->GetFrameFormat()->GetFrameSize().GetWidth();
1164 bool bEmptyLine = sal_True((sal_Bool)1);
1165 sal_uInt16 n, nSttPos = 0;
1166
1167 for( n = 0; n < aPosArr.Count(); ++n )
1168 {
1169 const CmpLPt& rPt = aPosArr[ n ];
1170 if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // same Y level?
1171 {
1172 if( bEmptyLine && !IsEmptyBox( *rPt.pSelBox, aPam ))
1173 bEmptyLine = sal_False((sal_Bool)0);
1174 if( bCalcWidth )
1175 nWidth += rPt.pSelBox->GetFrameFormat()->GetFrameSize().GetWidth();
1176 }
1177 else
1178 {
1179 if( bCalcWidth && n )
1180 bCalcWidth = false; // one line is ready
1181
1182 if( bEmptyLine && nSttPos < n )
1183 {
1184 // now complete line is empty and should not
1185 // be filled with blanks and be inserted as paragraph
1186 if( pUndo )
1187 for( sal_uInt16 i = nSttPos; i < n; ++i )
1188 pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1189
1190 aPosArr.Remove( nSttPos, n - nSttPos );
1191 n = nSttPos;
1192 }
1193 else
1194 nSttPos = n;
1195
1196 bEmptyLine = IsEmptyBox( *aPosArr[n].pSelBox, aPam );
1197 }
1198 }
1199 if( bEmptyLine && nSttPos < n )
1200 {
1201 if( pUndo )
1202 for( sal_uInt16 i = nSttPos; i < n; ++i )
1203 pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1204 aPosArr.Remove( nSttPos, n - nSttPos );
1205 }
1206#elif defined( DEL_EMPTY_BOXES_AT_START_AND_END )
1207
1208 nWidth = pFirstBox->GetFrameFormat()->GetFrameSize().GetWidth();
1209 sal_uInt16 n, nSttPos = 0, nSEndPos = 0, nESttPos = 0;
1210
1211 for( n = 0; n < aPosArr.Count(); ++n )
1212 {
1213 const CmpLPt& rPt = aPosArr[ n ];
1214 if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // same Y level?
1215 {
1216 bool bEmptyBox = IsEmptyBox( *rPt.pSelBox, aPam );
1217 if( bEmptyBox )
1218 {
1219 if( nSEndPos == n ) // beginning is empty
1220 nESttPos = ++nSEndPos;
1221 }
1222 else // end could be empty
1223 nESttPos = n+1;
1224
1225 if( bCalcWidth )
1226 nWidth += rPt.pSelBox->GetFrameFormat()->GetFrameSize().GetWidth();
1227 }
1228 else
1229 {
1230 if( bCalcWidth && n )
1231 bCalcWidth = false; // one line ready
1232
1233 // first those at the beginning
1234 if( nSttPos < nSEndPos )
1235 {
1236 // now the beginning of the line is empty and should
1237 // not be filled with blanks
1238 if( pUndo )
1239 for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
1240 pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1241
1242 sal_uInt16 nCnt = nSEndPos - nSttPos;
1243 aPosArr.Remove( nSttPos, nCnt );
1244 nESttPos -= nCnt;
1245 n -= nCnt;
1246 }
1247
1248 if( nESttPos < n )
1249 {
1250 // now the beginning of the line is empty and should
1251 // not be filled with blanks
1252 if( pUndo )
1253 for( sal_uInt16 i = nESttPos; i < n; ++i )
1254 pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1255
1256 sal_uInt16 nCnt = n - nESttPos;
1257 aPosArr.Remove( nESttPos, nCnt );
1258 n -= nCnt;
1259 }
1260
1261 nSttPos = nSEndPos = nESttPos = n;
1262 if( IsEmptyBox( *aPosArr[n].pSelBox, aPam ))
1263 ++nSEndPos;
1264 else
1265 ++nESttPos;
1266 }
1267 }
1268
1269 // first those at the beginning
1270 if( nSttPos < nSEndPos )
1271 {
1272 // now the beginning of the line is empty and should
1273 // not be filled with blanks
1274 if( pUndo )
1275 for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
1276 pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1277
1278 sal_uInt16 nCnt = nSEndPos - nSttPos;
1279 aPosArr.Remove( nSttPos, nCnt );
1280 nESttPos -= nCnt;
1281 n -= nCnt;
1282 }
1283 if( nESttPos < n )
1284 {
1285 // now the beginning of the line is empty and should
1286 // not be filled with blanks
1287 if( pUndo )
1288 for( sal_uInt16 i = nESttPos; i < n; ++i )
1289 pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1290
1291 sal_uInt16 nCnt = n - nESttPos;
1292 aPosArr.Remove( nESttPos, nCnt );
1293 }
1294#else
1295// DEL_ALL_EMPTY_BOXES
1296
1297 nWidth = 0;
1298 long nY = !aPosArr.empty() ?
1299 ( aRectFnSet.IsVert() ?
1300 aPosArr[ 0 ].X() :
1301 aPosArr[ 0 ].Y() ) :
1302 0;
1303
1304 for( MergePos::size_type n = 0; n < aPosArr.size(); ++n )
1305 {
1306 const CmpLPt& rPt = aPosArr[ n ];
1307 if( bCalcWidth )
1308 {
1309 if( nY == ( aRectFnSet.IsVert() ? rPt.X() : rPt.Y() ) ) // same Y level?
1310 nWidth += rPt.pSelBox->GetFrameFormat()->GetFrameSize().GetWidth();
1311 else
1312 bCalcWidth = false; // one line ready
1313 }
1314
1315 if( IsEmptyBox( *rPt.pSelBox, aPam ) )
1316 {
1317 if( pUndo )
1318 pUndo->SaveCollection( *rPt.pSelBox );
1319
1320 aPosArr.erase( aPosArr.begin() + n );
1321 --n;
1322 }
1323 }
1324#endif
1325 }
1326
1327 // first create new box
1328 {
1329 SwTableBox* pTmpBox = rBoxes[0];
1330 SwTableLine* pInsLine = pTmpBox->GetUpper();
1331 sal_uInt16 nInsPos = pInsLine->GetBoxPos( pTmpBox );
1332
1333 lcl_InsTableBox( pTableNd, pDoc, pTmpBox, nInsPos );
1334 (*ppMergeBox) = pInsLine->GetTabBoxes()[ nInsPos ];
1335 pInsLine->GetTabBoxes().erase( pInsLine->GetTabBoxes().begin() + nInsPos ); // remove again
1336 (*ppMergeBox)->SetUpper( nullptr );
1337 (*ppMergeBox)->ClaimFrameFormat();
1338
1339 // define the border: the upper/left side of the first box,
1340 // the lower/right side of the last box:
1341 if( pLastBox && pFirstBox )
1342 {
1343 SvxBoxItem aBox( pFirstBox->GetFrameFormat()->GetBox() );
1344 const SvxBoxItem& rBox = pLastBox->GetFrameFormat()->GetBox();
1345 aBox.SetLine( rBox.GetRight(), SvxBoxItemLine::RIGHT );
1346 aBox.SetLine( rBox.GetBottom(), SvxBoxItemLine::BOTTOM );
1347 if( aBox.GetLeft() || aBox.GetTop() ||
1348 aBox.GetRight() || aBox.GetBottom() )
1349 (*ppMergeBox)->GetFrameFormat()->SetFormatAttr( aBox );
1350 }
1351 }
1352
1353 //Block to delete SwPaM, SwPosition from stack
1354 if( !aPosArr.empty() )
1355 {
1356 SwPosition aInsPos( *(*ppMergeBox)->GetSttNd() );
1357 SwNodeIndex& rInsPosNd = aInsPos.nNode;
1358
1359 SwPaM aPam( aInsPos );
1360
1361 for( const auto &rPt : aPosArr )
1362 {
1363 aPam.GetPoint()->nNode.Assign( *rPt.pSelBox->GetSttNd()->
1364 EndOfSectionNode(), -1 );
1365 SwContentNode* pCNd = aPam.GetContentNode();
1366 aPam.GetPoint()->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
1367
1368 SwNodeIndex aSttNdIdx( *rPt.pSelBox->GetSttNd(), 1 );
1369 // one node should be kept in the box (otherwise the
1370 // section would be deleted during a move)
1371 bool const bUndo(pDoc->GetIDocumentUndoRedo().DoesUndo());
1372 if( pUndo )
1373 {
1374 pDoc->GetIDocumentUndoRedo().DoUndo(false);
1375 }
1376 pDoc->getIDocumentContentOperations().AppendTextNode( *aPam.GetPoint() );
1377 if( pUndo )
1378 {
1379 pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
1380 }
1381 SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
1382 ++rInsPosNd;
1383 if( pUndo )
1384 pUndo->MoveBoxContent( *pDoc, aRg, rInsPosNd );
1385 else
1386 {
1387 pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, rInsPosNd,
1388 SwMoveFlags::DEFAULT );
1389 }
1390 // where is now aInsPos ??
1391
1392 if( bCalcWidth )
1393 bCalcWidth = false; // one line is ready
1394
1395 // skip the first TextNode
1396 rInsPosNd.Assign( pDoc->GetNodes(),
1397 rInsPosNd.GetNode().EndOfSectionIndex() - 2 );
1398 SwTextNode* pTextNd = rInsPosNd.GetNode().GetTextNode();
1399 if( pTextNd )
1400 aInsPos.nContent.Assign(pTextNd, pTextNd->GetText().getLength());
1401 }
1402
1403 // the MergeBox should contain the complete text
1404 // now erase the initial TextNode
1405 OSL_ENSURE( (*ppMergeBox)->GetSttIdx()+2 <do { if (true && (!((*ppMergeBox)->GetSttIdx()+2 <
(*ppMergeBox)->GetSttNd()->EndOfSectionIndex()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1407" ": "), "%s", "empty box"); } } while (false)
1406 (*ppMergeBox)->GetSttNd()->EndOfSectionIndex(),do { if (true && (!((*ppMergeBox)->GetSttIdx()+2 <
(*ppMergeBox)->GetSttNd()->EndOfSectionIndex()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1407" ": "), "%s", "empty box"); } } while (false)
1407 "empty box" )do { if (true && (!((*ppMergeBox)->GetSttIdx()+2 <
(*ppMergeBox)->GetSttNd()->EndOfSectionIndex()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1407" ": "), "%s", "empty box"); } } while (false)
;
1408 SwNodeIndex aIdx( *(*ppMergeBox)->GetSttNd()->EndOfSectionNode(), -1 );
1409 pDoc->GetNodes().Delete( aIdx );
1410 }
1411
1412 // set width of the box
1413 (*ppMergeBox)->GetFrameFormat()->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth, 0 ));
1414 if( pUndo )
1415 pUndo->AddNewBox( (*ppMergeBox)->GetSttIdx() );
1416}
1417
1418static bool lcl_CheckCol(FndBox_ const&, bool* pPara);
1419
1420static bool lcl_CheckRow( const FndLine_& rFndLine, bool* pPara )
1421{
1422 for (auto const& it : rFndLine.GetBoxes())
1423 {
1424 lcl_CheckCol(*it, pPara);
1425 }
1426 return *pPara;
1427}
1428
1429static bool lcl_CheckCol( FndBox_ const& rFndBox, bool* pPara )
1430{
1431 if (!rFndBox.GetBox()->GetSttNd())
1432 {
1433 if (rFndBox.GetLines().size() !=
1434 rFndBox.GetBox()->GetTabLines().size())
1435 {
1436 *pPara = false;
1437 }
1438 else
1439 {
1440 for (auto const& rpFndLine : rFndBox.GetLines())
1441 {
1442 lcl_CheckRow( *rpFndLine, pPara );
1443 }
1444 }
1445 }
1446 // is box protected ??
1447 else if (rFndBox.GetBox()->GetFrameFormat()->GetProtect().IsContentProtected())
1448 *pPara = false;
1449 return *pPara;
1450}
1451
1452TableMergeErr CheckMergeSel( const SwPaM& rPam )
1453{
1454 SwSelBoxes aBoxes;
1455//JP 24.09.96: Merge with repeating TableHeadLines does not work properly.
1456// Why not use point 0,0? Then it is assured the first
1457// headline is contained.
1458
1459 Point aPt;
1460 const SwContentNode* pCntNd = rPam.GetContentNode();
1461 std::pair<Point, bool> tmp(aPt, true);
1462 const SwLayoutFrame *const pStart = pCntNd->getLayoutFrame(
1463 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
1464 nullptr, &tmp)->GetUpper();
1465 pCntNd = rPam.GetContentNode(false);
1466 const SwLayoutFrame *const pEnd = pCntNd->getLayoutFrame(
1467 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
1468 nullptr, &tmp)->GetUpper();
1469 GetTableSel( pStart, pEnd, aBoxes, nullptr );
1470 return CheckMergeSel( aBoxes );
1471}
1472
1473TableMergeErr CheckMergeSel( const SwSelBoxes& rBoxes )
1474{
1475 TableMergeErr eRet = TableMergeErr::NoSelection;
1476 if( !rBoxes.empty() )
1477 {
1478 eRet = TableMergeErr::Ok;
1479
1480 FndBox_ aFndBox( nullptr, nullptr );
1481 FndPara aPara( rBoxes, &aFndBox );
1482 const SwTableNode* pTableNd = aPara.rBoxes[0]->GetSttNd()->FindTableNode();
1483 ForEach_FndLineCopyCol( const_cast<SwTableLines&>(pTableNd->GetTable().GetTabLines()), &aPara );
1484 if( !aFndBox.GetLines().empty() )
1485 {
1486 bool bMergeSelOk = true;
1487 FndBox_* pFndBox = &aFndBox;
1488 FndLine_* pFndLine = nullptr;
1489 while( pFndBox && 1 == pFndBox->GetLines().size() )
1490 {
1491 pFndLine = pFndBox->GetLines().front().get();
1492 if( 1 == pFndLine->GetBoxes().size() )
1493 pFndBox = pFndLine->GetBoxes().front().get();
1494 else
1495 pFndBox = nullptr;
1496 }
1497 if( pFndBox )
1498 {
1499 for (auto const& it : pFndBox->GetLines())
1500 {
1501 lcl_CheckRow(*it, &bMergeSelOk);
1502 }
1503 }
1504 else if( pFndLine )
1505 {
1506 for (auto const& it : pFndLine->GetBoxes())
1507 {
1508 lcl_CheckCol(*it, &bMergeSelOk);
1509 }
1510 }
1511 if( !bMergeSelOk )
1512 eRet = TableMergeErr::TooComplex;
1513 }
1514 else
1515 eRet = TableMergeErr::NoSelection;
1516 }
1517 return eRet;
1518}
1519
1520static SwTwips lcl_CalcWish( const SwLayoutFrame *pCell, long nWish,
1521 const long nAct )
1522{
1523 const SwLayoutFrame *pTmp = pCell;
1524 if ( !nWish )
1525 nWish = 1;
1526
1527 const bool bRTL = pCell->IsRightToLeft();
1528 SwTwips nRet = bRTL ?
1529 nAct - pCell->getFrameArea().Width() :
1530 0;
1531
1532 while ( pTmp )
1533 {
1534 while ( pTmp->GetPrev() )
1535 {
1536 pTmp = static_cast<const SwLayoutFrame*>(pTmp->GetPrev());
1537 sal_Int64 nTmp = pTmp->GetFormat()->GetFrameSize().GetWidth();
1538 // multiply in 64-bit to avoid overflow here!
1539 nRet += ( bRTL ? -1 : 1 ) * nTmp * nAct / nWish;
1540 }
1541 pTmp = pTmp->GetUpper()->GetUpper();
1542 if ( pTmp && !pTmp->IsCellFrame() )
1543 pTmp = nullptr;
1544 }
1545 return nRet;
1546}
1547
1548static void lcl_FindStartEndRow( const SwLayoutFrame *&rpStart,
1549 const SwLayoutFrame *&rpEnd,
1550 const bool bChkProtected )
1551{
1552 // Put Start at beginning of a row.
1553 // Put End at the end of its row.
1554 rpStart = static_cast<const SwLayoutFrame*>(rpStart->GetUpper()->Lower());
1555 while ( rpEnd->GetNext() )
1556 rpEnd = static_cast<const SwLayoutFrame*>(rpEnd->GetNext());
1557
1558 std::deque<const SwLayoutFrame *> aSttArr, aEndArr;
1559 const SwLayoutFrame *pTmp;
1560 for( pTmp = rpStart; (SwFrameType::Cell|SwFrameType::Row) & pTmp->GetType();
1561 pTmp = pTmp->GetUpper() )
1562 {
1563 aSttArr.push_front( pTmp );
1564 }
1565 for( pTmp = rpEnd; (SwFrameType::Cell|SwFrameType::Row) & pTmp->GetType();
1566 pTmp = pTmp->GetUpper() )
1567 {
1568 aEndArr.push_front( pTmp );
1569 }
1570
1571 for( std::deque<const SwLayoutFrame *>::size_type n = 0; n < aEndArr.size() && n < aSttArr.size(); ++n )
1572 if( aSttArr[ n ] != aEndArr[ n ] )
1573 {
1574 // first unequal line or box - all odds are
1575 if( n & 1 ) // 1, 3, 5, ... are boxes
1576 {
1577 rpStart = aSttArr[ n ];
1578 rpEnd = aEndArr[ n ];
1579 }
1580 else // 0, 2, 4, ... are lines
1581 {
1582 // check if start & end line are the first & last Line of the
1583 // box. If not return these cells.
1584 // Else the whole line with all Boxes has to be deleted.
1585 rpStart = aSttArr[ n+1 ];
1586 rpEnd = aEndArr[ n+1 ];
1587 if( n )
1588 {
1589 const SwCellFrame* pCellFrame = static_cast<const SwCellFrame*>(aSttArr[ n-1 ]);
1590 const SwTableLines& rLns = pCellFrame->
1591 GetTabBox()->GetTabLines();
1592 if( rLns[ 0 ] == static_cast<const SwRowFrame*>(aSttArr[ n ])->GetTabLine() &&
1593 rLns[ rLns.size() - 1 ] ==
1594 static_cast<const SwRowFrame*>(aEndArr[ n ])->GetTabLine() )
1595 {
1596 rpStart = rpEnd = pCellFrame;
1597 while ( rpStart->GetPrev() )
1598 rpStart = static_cast<const SwLayoutFrame*>(rpStart->GetPrev());
1599 while ( rpEnd->GetNext() )
1600 rpEnd = static_cast<const SwLayoutFrame*>(rpEnd->GetNext());
1601 }
1602 }
1603 }
1604 break;
1605 }
1606
1607 if( !bChkProtected ) // protected cell ?
1608 return;
1609
1610 // Beginning and end should not be in protected cells
1611 while ( rpStart->GetFormat()->GetProtect().IsContentProtected() )
1612 rpStart = static_cast<const SwLayoutFrame*>(rpStart->GetNext());
1613 while ( rpEnd->GetFormat()->GetProtect().IsContentProtected() )
1614 rpEnd = static_cast<const SwLayoutFrame*>(rpEnd->GetPrev());
1615}
1616
1617static void lcl_FindStartEndCol( const SwLayoutFrame *&rpStart,
1618 const SwLayoutFrame *&rpEnd,
1619 const bool bChkProtected )
1620{
1621 // Beginning and end vertical till the border of the table;
1622 // Consider the whole table, including master and follows.
1623 // In order to start we need the mother-tableFrame
1624 if( !rpStart )
1
Assuming 'rpStart' is non-null
2
Taking false branch
1625 return;
1626 const SwTabFrame *pOrg = rpStart->FindTabFrame();
1627 const SwTabFrame *pTab = pOrg;
1628
1629 SwRectFnSet aRectFnSet(pTab);
1630
1631 bool bRTL = pTab->IsRightToLeft();
1632 const long nTmpWish = pOrg->GetFormat()->GetFrameSize().GetWidth();
1633 const long nWish = ( nTmpWish > 0 ) ? nTmpWish : 1;
3
Assuming 'nTmpWish' is <= 0
4
'?' condition is false
1634
1635 while ( pTab->IsFollow() )
5
Loop condition is false. Execution continues on line 1642
1636 {
1637 const SwFrame *pTmp = pTab->FindPrev();
1638 OSL_ENSURE( pTmp->IsTabFrame(), "Predecessor of Follow is not Master." )do { if (true && (!(pTmp->IsTabFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1638" ": "), "%s", "Predecessor of Follow is not Master."
); } } while (false)
;
1639 pTab = static_cast<const SwTabFrame*>(pTmp);
1640 }
1641
1642 SwTwips nSX = 0;
1643 SwTwips nSX2 = 0;
1644
1645 if ( pTab->GetTable()->IsNewModel() )
6
Assuming the condition is false
7
Taking false branch
1646 {
1647 nSX = aRectFnSet.GetLeft(rpStart->getFrameArea());
1648 nSX2 = aRectFnSet.GetRight(rpStart->getFrameArea());
1649 }
1650 else
1651 {
1652 const SwTwips nPrtWidth = aRectFnSet.GetWidth(pTab->getFramePrintArea());
1653 nSX = ::lcl_CalcWish( rpStart, nWish, nPrtWidth ) + aRectFnSet.GetPrtLeft(*pTab);
1654 nSX2 = nSX + (rpStart->GetFormat()->GetFrameSize().GetWidth() * nPrtWidth / nWish);
1655 }
1656
1657 const SwLayoutFrame *pTmp = pTab->FirstCell();
1658
1659 while ( pTmp &&
8
Assuming 'pTmp' is null
1660 (!pTmp->IsCellFrame() ||
1661 ( ( ! bRTL && aRectFnSet.GetLeft(pTmp->getFrameArea()) < nSX &&
1662 aRectFnSet.GetRight(pTmp->getFrameArea())< nSX2 ) ||
1663 ( bRTL && aRectFnSet.GetLeft(pTmp->getFrameArea()) > nSX &&
1664 aRectFnSet.GetRight(pTmp->getFrameArea())> nSX2 ) ) ) )
1665 pTmp = pTmp->GetNextLayoutLeaf();
1666
1667 if ( pTmp
8.1
'pTmp' is null
)
9
Taking false branch
1668 rpStart = pTmp;
1669
1670 pTab = pOrg;
1671
1672 const SwTabFrame* pLastValidTab = pTab;
1673 while ( pTab->GetFollow() )
10
Loop condition is false. Execution continues on line 1690
1674 {
1675
1676 // Check if pTab->GetFollow() is a valid follow table:
1677 // Only follow tables with at least on non-FollowFlowLine
1678 // should be considered.
1679
1680 if ( pTab->HasFollowFlowLine() )
1681 {
1682 pTab = pTab->GetFollow();
1683 const SwFrame* pTmpRow = pTab->GetFirstNonHeadlineRow();
1684 if ( pTmpRow && pTmpRow->GetNext() )
1685 pLastValidTab = pTab;
1686 }
1687 else
1688 pLastValidTab = pTab = pTab->GetFollow();
1689 }
1690 pTab = pLastValidTab;
1691
1692 SwTwips nEX = 0;
1693
1694 if ( pTab->GetTable()->IsNewModel() )
11
Assuming the condition is false
12
Taking false branch
1695 {
1696 nEX = aRectFnSet.GetLeft(rpEnd->getFrameArea());
1697 }
1698 else
1699 {
1700 const SwTwips nPrtWidth = aRectFnSet.GetWidth(pTab->getFramePrintArea());
1701 nEX = ::lcl_CalcWish( rpEnd, nWish, nPrtWidth ) + aRectFnSet.GetPrtLeft(*pTab);
1702 }
1703
1704 SwFrame const*const pLastContent = pTab->FindLastContentOrTable();
1705 rpEnd = pLastContent ? pLastContent->GetUpper() : nullptr;
13
Assuming 'pLastContent' is non-null
14
'?' condition is true
1706 // --> Made code robust. If pTab does not have a lower,
1707 // we would crash here.
1708 if ( !pLastContent
14.1
'pLastContent' is non-null
) return;
15
Taking false branch
1709
1710 while( !rpEnd->IsCellFrame() )
16
Loop condition is false. Execution continues on line 1713
1711 rpEnd = rpEnd->GetUpper();
1712
1713 while ( ( bRTL && aRectFnSet.GetLeft(rpEnd->getFrameArea()) < nEX ) ||
17
Assuming 'bRTL' is false
19
Loop condition is false. Execution continues on line 1722
1714 ( ! bRTL
17.1
'bRTL' is false
&& aRectFnSet.GetLeft(rpEnd->getFrameArea()) > nEX ) )
18
Assuming the condition is false
1715 {
1716 const SwLayoutFrame* pTmpLeaf = rpEnd->GetPrevLayoutLeaf();
1717 if( !pTmpLeaf || !pTab->IsAnLower( pTmpLeaf ) )
1718 break;
1719 rpEnd = pTmpLeaf;
1720 }
1721
1722 if( !bChkProtected ) // check for protected cell ?
20
Assuming 'bChkProtected' is true
21
Taking false branch
1723 return;
1724
1725 // Beginning and end should not be in protected cells.
1726 // If necessary we should search backwards again
1727 while ( rpStart->GetFormat()->GetProtect().IsContentProtected() )
22
Loop condition is true. Entering loop body
28
Called C++ object pointer is null
1728 {
1729 const SwLayoutFrame *pTmpLeaf = rpStart->GetNextLayoutLeaf();
23
'pTmpLeaf' initialized here
1730 while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) > nEX ) // first skip line
24
Assuming 'pTmpLeaf' is null
1731 pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
1732 while ( pTmpLeaf
24.1
'pTmpLeaf' is null
&& aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) < nSX &&
1733 aRectFnSet.GetRight(pTmpLeaf->getFrameArea())< nSX2 )
1734 pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
1735 const SwTabFrame *pTmpTab = rpStart->FindTabFrame();
1736 if ( !pTmpTab->IsAnLower( pTmpLeaf ) )
25
Assuming the condition is false
26
Taking false branch
1737 {
1738 pTmpTab = pTmpTab->GetFollow();
1739 rpStart = pTmpTab->FirstCell();
1740 while ( rpStart &&
1741 aRectFnSet.GetLeft(rpStart->getFrameArea()) < nSX &&
1742 aRectFnSet.GetRight(rpStart->getFrameArea())< nSX2 )
1743 rpStart = rpStart->GetNextLayoutLeaf();
1744 }
1745 else
1746 rpStart = pTmpLeaf;
27
Storing null pointer value
1747 }
1748 while ( rpEnd->GetFormat()->GetProtect().IsContentProtected() )
1749 {
1750 const SwLayoutFrame *pTmpLeaf = rpEnd->GetPrevLayoutLeaf();
1751 while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) < nEX ) // skip the line for now
1752 pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
1753 while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) > nEX )
1754 pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
1755 const SwTabFrame *pTmpTab = rpEnd->FindTabFrame();
1756 if ( !pTmpLeaf || !pTmpTab->IsAnLower( pTmpLeaf ) )
1757 {
1758 pTmpTab = static_cast<const SwTabFrame*>(pTmpTab->FindPrev());
1759 OSL_ENSURE( pTmpTab->IsTabFrame(), "Predecessor of Follow not Master.")do { if (true && (!(pTmpTab->IsTabFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1759" ": "), "%s", "Predecessor of Follow not Master.")
; } } while (false)
;
1760 rpEnd = pTmpTab->FindLastContentOrTable()->GetUpper();
1761 while( !rpEnd->IsCellFrame() )
1762 rpEnd = rpEnd->GetUpper();
1763 while ( aRectFnSet.GetLeft(rpEnd->getFrameArea()) > nEX )
1764 rpEnd = rpEnd->GetPrevLayoutLeaf();
1765 }
1766 else
1767 rpEnd = pTmpLeaf;
1768 }
1769}
1770
1771void MakeSelUnions( SwSelUnions& rUnions, const SwLayoutFrame *pStart,
1772 const SwLayoutFrame *pEnd, const SwTableSearchType eSearchType )
1773{
1774 while ( pStart && !pStart->IsCellFrame() )
1775 pStart = pStart->GetUpper();
1776 while ( pEnd && !pEnd->IsCellFrame() )
1777 pEnd = pEnd->GetUpper();
1778
1779 if ( !pStart || !pEnd )
1780 {
1781 OSL_FAIL( "MakeSelUnions with pStart or pEnd not in CellFrame" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1781" ": "), "%s", "MakeSelUnions with pStart or pEnd not in CellFrame"
); } } while (false)
;
1782 return;
1783 }
1784
1785 const SwTabFrame *pTable = pStart->FindTabFrame();
1786 const SwTabFrame *pEndTable = pEnd->FindTabFrame();
1787 if( !pTable || !pEndTable )
1788 return;
1789 bool bExchange = false;
1790
1791 if ( pTable != pEndTable )
1792 {
1793 if ( !pTable->IsAnFollow( pEndTable ) )
1794 {
1795 OSL_ENSURE( pEndTable->IsAnFollow( pTable ), "Tabchain in knots." )do { if (true && (!(pEndTable->IsAnFollow( pTable )
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1795" ": "), "%s", "Tabchain in knots."); } } while (false
)
;
1796 bExchange = true;
1797 }
1798 }
1799 else
1800 {
1801 SwRectFnSet aRectFnSet(pTable);
1802 long nSttTop = aRectFnSet.GetTop(pStart->getFrameArea());
1803 long nEndTop = aRectFnSet.GetTop(pEnd->getFrameArea());
1804 if( nSttTop == nEndTop )
1805 {
1806 if( aRectFnSet.GetLeft(pStart->getFrameArea()) >
1807 aRectFnSet.GetLeft(pEnd->getFrameArea()) )
1808 bExchange = true;
1809 }
1810 else if( aRectFnSet.IsVert() == ( nSttTop < nEndTop ) )
1811 bExchange = true;
1812 }
1813 if ( bExchange )
1814 {
1815 const SwLayoutFrame *pTmp = pStart;
1816 pStart = pEnd;
1817 pEnd = pTmp;
1818 // do no resort pTable and pEndTable, set new below
1819 // MA: 28. Dec. 93 Bug: 5190
1820 }
1821
1822 // Beginning and end now nicely sorted, if required we
1823 // should move them
1824 if( SwTableSearchType::Row == ((~SwTableSearchType::Protect ) & eSearchType ) )
1825 ::lcl_FindStartEndRow( pStart, pEnd, bool(SwTableSearchType::Protect & eSearchType) );
1826 else if( SwTableSearchType::Col == ((~SwTableSearchType::Protect ) & eSearchType ) )
1827 ::lcl_FindStartEndCol( pStart, pEnd, bool(SwTableSearchType::Protect & eSearchType) );
1828
1829 if ( !pEnd || !pStart ) return; // Made code robust.
1830
1831 // retrieve again, as they have been moved
1832 pTable = pStart->FindTabFrame();
1833 pEndTable = pEnd->FindTabFrame();
1834
1835 const long nStSz = pStart->GetFormat()->GetFrameSize().GetWidth();
1836 const long nEdSz = pEnd->GetFormat()->GetFrameSize().GetWidth();
1837 const long nWish = std::max( 1L, pTable->GetFormat()->GetFrameSize().GetWidth() );
1838 while ( pTable )
1839 {
1840 SwRectFnSet aRectFnSet(pTable);
1841 const long nOfst = aRectFnSet.GetPrtLeft(*pTable);
1842 const long nPrtWidth = aRectFnSet.GetWidth(pTable->getFramePrintArea());
1843 long nSt1 = ::lcl_CalcWish( pStart, nWish, nPrtWidth ) + nOfst;
1844 long nEd1 = ::lcl_CalcWish( pEnd, nWish, nPrtWidth ) + nOfst;
1845
1846 if ( nSt1 <= nEd1 )
1847 nEd1 += static_cast<long>((nEdSz * nPrtWidth) / nWish) - 1;
1848 else
1849 nSt1 += static_cast<long>((nStSz * nPrtWidth) / nWish) - 1;
1850
1851 long nSt2;
1852 long nEd2;
1853 if( pTable->IsAnLower( pStart ) )
1854 nSt2 = aRectFnSet.GetTop(pStart->getFrameArea());
1855 else
1856 nSt2 = aRectFnSet.GetTop(pTable->getFrameArea());
1857 if( pTable->IsAnLower( pEnd ) )
1858 nEd2 = aRectFnSet.GetBottom(pEnd->getFrameArea());
1859 else
1860 nEd2 = aRectFnSet.GetBottom(pTable->getFrameArea());
1861 Point aSt, aEd;
1862 if( nSt1 > nEd1 )
1863 {
1864 long nTmp = nSt1;
1865 nSt1 = nEd1;
1866 nEd1 = nTmp;
1867 }
1868 if( nSt2 > nEd2 )
1869 {
1870 long nTmp = nSt2;
1871 nSt2 = nEd2;
1872 nEd2 = nTmp;
1873 }
1874 if( aRectFnSet.IsVert() )
1875 {
1876 aSt = Point( nSt2, nSt1 );
1877 aEd = Point( nEd2, nEd1 );
1878 }
1879 else
1880 {
1881 aSt = Point( nSt1, nSt2 );
1882 aEd = Point( nEd1, nEd2 );
1883 }
1884
1885 const Point aDiff( aEd - aSt );
1886 SwRect aUnion( aSt, Size( aDiff.X(), aDiff.Y() ) );
1887 aUnion.Justify();
1888
1889 if( !(SwTableSearchType::NoUnionCorrect & eSearchType ))
1890 {
1891 // Unfortunately the union contains rounding errors now, therefore
1892 // erroneous results could occur during split/merge.
1893 // To prevent these we will determine the first and last row
1894 // within the union and use their values for a new union
1895 const SwLayoutFrame* pRow = pTable->IsFollow() ?
1896 pTable->GetFirstNonHeadlineRow() :
1897 static_cast<const SwLayoutFrame*>(pTable->Lower());
1898
1899 while ( pRow && !pRow->getFrameArea().IsOver( aUnion ) )
1900 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
1901
1902 // #i31976#
1903 // A follow flow row may contain empty cells. These are not
1904 // considered by FirstCell(). Therefore we have to find
1905 // the first cell manually:
1906 const SwFrame* pTmpCell = nullptr;
1907 if ( pTable->IsFollow() && pRow && pRow->IsInFollowFlowRow() )
1908 {
1909 const SwFrame* pTmpRow = pRow;
1910 while ( pTmpRow && pTmpRow->IsRowFrame() )
1911 {
1912 pTmpCell = static_cast<const SwRowFrame*>(pTmpRow)->Lower();
1913 pTmpRow = static_cast<const SwCellFrame*>(pTmpCell)->Lower();
1914 }
1915 OSL_ENSURE( !pTmpCell || pTmpCell->IsCellFrame(), "Lower of rowframe != cellframe?!" )do { if (true && (!(!pTmpCell || pTmpCell->IsCellFrame
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "1915" ": "), "%s", "Lower of rowframe != cellframe?!");
} } while (false)
;
1916 }
1917
1918 const SwLayoutFrame* pFirst = pTmpCell ?
1919 static_cast<const SwLayoutFrame*>(pTmpCell) :
1920 pRow ?
1921 pRow->FirstCell() :
1922 nullptr;
1923
1924 while ( pFirst && !::IsFrameInTableSel( aUnion, pFirst ) )
1925 {
1926 if ( pFirst->GetNext() )
1927 {
1928 pFirst = static_cast<const SwLayoutFrame*>(pFirst->GetNext());
1929 if ( pFirst->Lower() && pFirst->Lower()->IsRowFrame() )
1930 pFirst = pFirst->FirstCell();
1931 }
1932 else
1933 pFirst = ::lcl_FindNextCellFrame( pFirst );
1934 }
1935 const SwLayoutFrame* pLast = nullptr;
1936 SwFrame const*const pLastContent = pTable->FindLastContentOrTable();
1937 if ( pLastContent )
1938 pLast = ::lcl_FindCellFrame( pLastContent->GetUpper() );
1939
1940 while ( pLast && !::IsFrameInTableSel( aUnion, pLast ) )
1941 pLast = ::lcl_FindCellFrame( pLast->GetPrevLayoutLeaf() );
1942
1943 if ( pFirst && pLast ) //Robust
1944 {
1945 aUnion = pFirst->getFrameArea();
1946 aUnion.Union( pLast->getFrameArea() );
1947 }
1948 else
1949 aUnion.Width( 0 );
1950 }
1951
1952 if( aRectFnSet.GetWidth(aUnion) )
1953 {
1954 rUnions.emplace_back(aUnion, const_cast<SwTabFrame*>(pTable));
1955 }
1956
1957 pTable = pTable->GetFollow();
1958 if ( pTable != pEndTable && pEndTable->IsAnFollow( pTable ) )
1959 pTable = nullptr;
1960 }
1961}
1962
1963bool CheckSplitCells( const SwCursorShell& rShell, sal_uInt16 nDiv,
1964 const SwTableSearchType eSearchType )
1965{
1966 if( !rShell.IsTableMode() )
1967 rShell.GetCursor();
1968
1969 return CheckSplitCells( *rShell.getShellCursor(false), nDiv, eSearchType );
1970}
1971
1972bool CheckSplitCells( const SwCursor& rCursor, sal_uInt16 nDiv,
1973 const SwTableSearchType eSearchType )
1974{
1975 if( 1 >= nDiv )
1976 return false;
1977
1978 sal_uInt16 nMinValue = nDiv * MINLAY23;
1979
1980 // Get start and end cell
1981 Point aPtPos, aMkPos;
1982 const SwShellCursor* pShCursor = dynamic_cast<const SwShellCursor*>(&rCursor);
1983 if( pShCursor )
1984 {
1985 aPtPos = pShCursor->GetPtPos();
1986 aMkPos = pShCursor->GetMkPos();
1987 }
1988
1989 const SwContentNode* pCntNd = rCursor.GetContentNode();
1990 std::pair<Point, bool> tmp(aPtPos, true);
1991 const SwLayoutFrame *const pStart = pCntNd->getLayoutFrame(
1992 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
1993 nullptr, &tmp)->GetUpper();
1994 pCntNd = rCursor.GetContentNode(false);
1995 tmp.first = aMkPos;
1996 const SwLayoutFrame *const pEnd = pCntNd->getLayoutFrame(
1997 pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
1998 nullptr, &tmp)->GetUpper();
1999
2000 SwRectFnSet aRectFnSet(pStart->GetUpper());
2001
2002 // First, compute tables and rectangles
2003 SwSelUnions aUnions;
2004
2005 ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
2006
2007 // now search boxes for each entry and emit
2008 for ( const auto& rSelUnion : aUnions )
2009 {
2010 const SwTabFrame *pTable = rSelUnion.GetTable();
2011
2012 // Skip any repeated headlines in the follow:
2013 const SwLayoutFrame* pRow = pTable->IsFollow() ?
2014 pTable->GetFirstNonHeadlineRow() :
2015 static_cast<const SwLayoutFrame*>(pTable->Lower());
2016
2017 while ( pRow )
2018 {
2019 if ( pRow->getFrameArea().IsOver( rSelUnion.GetUnion() ) )
2020 {
2021 const SwLayoutFrame *pCell = pRow->FirstCell();
2022
2023 while ( pCell && pRow->IsAnLower( pCell ) )
2024 {
2025 OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" )do { if (true && (!(pCell->IsCellFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2025" ": "), "%s", "Frame without cell"); } } while (false
)
;
2026 if( ::IsFrameInTableSel( rSelUnion.GetUnion(), pCell ) )
2027 {
2028 if( aRectFnSet.GetWidth(pCell->getFrameArea()) < nMinValue )
2029 return false;
2030 }
2031
2032 if ( pCell->GetNext() )
2033 {
2034 pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
2035 if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
2036 pCell = pCell->FirstCell();
2037 }
2038 else
2039 pCell = ::lcl_FindNextCellFrame( pCell );
2040 }
2041 }
2042 pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
2043 }
2044 }
2045 return true;
2046}
2047
2048// These Classes copy the current table selections (rBoxes),
2049// into a new structure, retaining the table structure
2050// new: SS for targeted erasing/restoring of the layout
2051
2052static void lcl_InsertRow( SwTableLine const &rLine, SwLayoutFrame *pUpper, SwFrame *pSibling )
2053{
2054 SwRowFrame *pRow = new SwRowFrame( rLine, pUpper );
2055 if ( pUpper->IsTabFrame() && static_cast<SwTabFrame*>(pUpper)->IsFollow() )
2056 {
2057 SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pUpper);
2058 pTabFrame->FindMaster()->InvalidatePos(); //can absorb the line
2059
2060 if ( pSibling && pTabFrame->IsInHeadline( *pSibling ) )
2061 {
2062 // Skip any repeated headlines in the follow:
2063 pSibling = pTabFrame->GetFirstNonHeadlineRow();
2064 }
2065 }
2066 pRow->Paste( pUpper, pSibling );
2067 pRow->RegistFlys();
2068}
2069
2070static void FndBoxCopyCol( SwTableBox* pBox, FndPara* pFndPara )
2071{
2072 std::unique_ptr<FndBox_> pFndBox(new FndBox_( pBox, pFndPara->pFndLine ));
2073 if( !pBox->GetTabLines().empty() )
2074 {
2075 FndPara aPara( *pFndPara, pFndBox.get() );
2076 ForEach_FndLineCopyCol( pFndBox->GetBox()->GetTabLines(), &aPara );
2077 if( pFndBox->GetLines().empty() )
2078 {
2079 return;
2080 }
2081 }
2082 else
2083 {
2084 if( pFndPara->rBoxes.find( pBox ) == pFndPara->rBoxes.end())
2085 {
2086 return;
2087 }
2088 }
2089 pFndPara->pFndLine->GetBoxes().push_back( std::move(pFndBox) );
2090}
2091
2092static void FndLineCopyCol( SwTableLine* pLine, FndPara* pFndPara )
2093{
2094 std::unique_ptr<FndLine_> pFndLine(new FndLine_(pLine, pFndPara->pFndBox));
2095 FndPara aPara(*pFndPara, pFndLine.get());
2096 for( auto& rpBox : pFndLine->GetLine()->GetTabBoxes() )
2097 FndBoxCopyCol(rpBox, &aPara );
2098 if( !pFndLine->GetBoxes().empty() )
2099 {
2100 pFndPara->pFndBox->GetLines().push_back( std::move(pFndLine) );
2101 }
2102}
2103
2104void ForEach_FndLineCopyCol(SwTableLines& rLines, FndPara* pFndPara )
2105{
2106 for( SwTableLines::iterator it = rLines.begin(); it != rLines.end(); ++it )
2107 FndLineCopyCol( *it, pFndPara );
2108}
2109
2110void FndBox_::SetTableLines( const SwSelBoxes &rBoxes, const SwTable &rTable )
2111{
2112 // Set pointers to lines before and after the area to process.
2113 // If the first/last lines are contained in the area, then the pointers
2114 // are 0. We first search for the positions of the first/last affected
2115 // lines in array of the SwTable. In order to use 0 for 'no line'
2116 // we adjust the positions by 1.
2117
2118 sal_uInt16 nStPos = USHRT_MAX(32767 *2 +1);
2119 sal_uInt16 nEndPos= 0;
2120
2121 for (size_t i = 0; i < rBoxes.size(); ++i)
2122 {
2123 SwTableLine *pLine = rBoxes[i]->GetUpper();
2124 while ( pLine->GetUpper() )
2125 pLine = pLine->GetUpper()->GetUpper();
2126 const sal_uInt16 nPos = rTable.GetTabLines().GetPos(
2127 const_cast<const SwTableLine*&>(pLine) ) + 1;
2128
2129 OSL_ENSURE( nPos != USHRT_MAX, "TableLine not found." )do { if (true && (!(nPos != (32767 *2 +1)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2129" ": "), "%s", "TableLine not found."); } } while (
false)
;
2130
2131 if( nStPos > nPos )
2132 nStPos = nPos;
2133
2134 if( nEndPos < nPos )
2135 nEndPos = nPos;
2136 }
2137 if (USHRT_MAX(32767 *2 +1) != nStPos && nStPos > 1)
2138 m_pLineBefore = rTable.GetTabLines()[nStPos - 2];
2139 if ( nEndPos < rTable.GetTabLines().size() )
2140 m_pLineBehind = rTable.GetTabLines()[nEndPos];
2141}
2142
2143void FndBox_::SetTableLines( const SwTable &rTable )
2144{
2145 // Set pointers to lines before and after the area to process.
2146 // If the first/last lines are contained in the area, then the pointers
2147 // are 0. The positions of the first/last affected lines in the array
2148 // of the SwTable are in FndBox. In order to use 0 for 'no line'
2149 // we adjust the positions by 1.
2150
2151 if( GetLines().empty() )
2152 return;
2153
2154 SwTableLine* pTmpLine = GetLines().front()->GetLine();
2155 sal_uInt16 nPos = rTable.GetTabLines().GetPos( pTmpLine );
2156 OSL_ENSURE( USHRT_MAX != nPos, "Line is not in table" )do { if (true && (!((32767 *2 +1) != nPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2156" ": "), "%s", "Line is not in table"); } } while (
false)
;
2157 if( nPos )
2158 m_pLineBefore = rTable.GetTabLines()[ nPos - 1 ];
2159
2160 pTmpLine = GetLines().back()->GetLine();
2161 nPos = rTable.GetTabLines().GetPos( pTmpLine );
2162 OSL_ENSURE( USHRT_MAX != nPos, "Line is not in the table" )do { if (true && (!((32767 *2 +1) != nPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2162" ": "), "%s", "Line is not in the table"); } } while
(false)
;
2163 if( ++nPos < rTable.GetTabLines().size() )
2164 m_pLineBehind = rTable.GetTabLines()[nPos];
2165}
2166
2167inline void UnsetFollow( SwFlowFrame *pTab )
2168{
2169 pTab->m_pPrecede = nullptr;
2170}
2171
2172void FndBox_::DelFrames( SwTable &rTable )
2173{
2174 // All lines between pLineBefore and pLineBehind should be cut
2175 // from the layout and erased.
2176 // If this creates empty Follows we should destroy these.
2177 // If a master is destroyed, the follow should become master.
2178 // Always a TabFrame should remain.
2179
2180 sal_uInt16 nStPos = 0;
2181 sal_uInt16 nEndPos= rTable.GetTabLines().size() - 1;
2182 if( rTable.IsNewModel() && m_pLineBefore )
2183 rTable.CheckRowSpan( m_pLineBefore, true );
2184 if ( m_pLineBefore )
2185 {
2186 nStPos = rTable.GetTabLines().GetPos(
2187 const_cast<const SwTableLine*&>(m_pLineBefore) );
2188 OSL_ENSURE( nStPos != USHRT_MAX, "The fox stole the line!" )do { if (true && (!(nStPos != (32767 *2 +1)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2188" ": "), "%s", "The fox stole the line!"); } } while
(false)
;
2189 ++nStPos;
2190 }
2191 if( rTable.IsNewModel() && m_pLineBehind )
2192 rTable.CheckRowSpan( m_pLineBehind, false );
2193 if ( m_pLineBehind )
2194 {
2195 nEndPos = rTable.GetTabLines().GetPos(
2196 const_cast<const SwTableLine*&>(m_pLineBehind) );
2197 OSL_ENSURE( nEndPos != USHRT_MAX, "The fox stole the line!" )do { if (true && (!(nEndPos != (32767 *2 +1)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2197" ": "), "%s", "The fox stole the line!"); } } while
(false)
;
2198 if (nEndPos != 0)
2199 --nEndPos;
2200 }
2201
2202 for ( sal_uInt16 i = nStPos; i <= nEndPos; ++i)
2203 {
2204 SwFrameFormat *pFormat = rTable.GetTabLines()[i]->GetFrameFormat();
2205 SwIterator<SwRowFrame,SwFormat> aIter( *pFormat );
2206 for ( SwRowFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
2207 {
2208 if ( pFrame->GetTabLine() == rTable.GetTabLines()[i] )
2209 {
2210 bool bDel = true;
2211 SwTabFrame *pUp = !pFrame->GetPrev() && !pFrame->GetNext() ?
2212 static_cast<SwTabFrame*>(pFrame->GetUpper()) : nullptr;
2213 if ( !pUp )
2214 {
2215 const sal_uInt16 nRepeat =
2216 static_cast<SwTabFrame*>(pFrame->GetUpper())->GetTable()->GetRowsToRepeat();
2217 if ( nRepeat > 0 &&
2218 static_cast<SwTabFrame*>(pFrame->GetUpper())->IsFollow() )
2219 {
2220 if ( !pFrame->GetNext() )
2221 {
2222 SwRowFrame* pFirstNonHeadline =
2223 static_cast<SwTabFrame*>(pFrame->GetUpper())->GetFirstNonHeadlineRow();
2224 if ( pFirstNonHeadline == pFrame )
2225 {
2226 pUp = static_cast<SwTabFrame*>(pFrame->GetUpper());
2227 }
2228 }
2229 }
2230 }
2231 if ( pUp )
2232 {
2233 SwTabFrame *pFollow = pUp->GetFollow();
2234 SwTabFrame *pPrev = pUp->IsFollow() ? pUp : nullptr;
2235 if ( pPrev )
2236 {
2237 SwFrame *pTmp = pPrev->FindPrev();
2238 OSL_ENSURE( pTmp->IsTabFrame(),do { if (true && (!(pTmp->IsTabFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2239" ": "), "%s", "Predecessor of Follow is no Master."
); } } while (false)
2239 "Predecessor of Follow is no Master.")do { if (true && (!(pTmp->IsTabFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2239" ": "), "%s", "Predecessor of Follow is no Master."
); } } while (false)
;
2240 pPrev = static_cast<SwTabFrame*>(pTmp);
2241 }
2242 if ( pPrev )
2243 {
2244 pPrev->SetFollow( pFollow );
2245 // #i60340# Do not transfer the
2246 // flag from pUp to pPrev. pUp may still have the
2247 // flag set although there is not more follow flow
2248 // line associated with pUp.
2249 pPrev->SetFollowFlowLine( false );
2250 }
2251 else if ( pFollow )
2252 ::UnsetFollow( pFollow );
2253
2254 // A TableFrame should always remain!
2255 if ( pPrev || pFollow )
2256 {
2257 // OD 26.08.2003 #i18103# - if table is in a section,
2258 // lock the section, to avoid its delete.
2259 {
2260 SwSectionFrame* pSctFrame = pUp->FindSctFrame();
2261 bool bOldSectLock = false;
2262 if ( pSctFrame )
2263 {
2264 bOldSectLock = pSctFrame->IsColLocked();
2265 pSctFrame->ColLock();
2266 }
2267 pUp->Cut();
2268 if ( pSctFrame && !bOldSectLock )
2269 {
2270 pSctFrame->ColUnlock();
2271 }
2272 }
2273 SwFrame::DestroyFrame(pUp);
2274 bDel = false; // Row goes to /dev/null.
2275 }
2276 }
2277 if ( bDel )
2278 {
2279 SwFrame* pTabFrame = pFrame->GetUpper();
2280 if ( pTabFrame->IsTabFrame() &&
2281 !pFrame->GetNext() &&
2282 static_cast<SwTabFrame*>(pTabFrame)->GetFollow() )
2283 {
2284 // We do not delete the follow flow line,
2285 // this will be done automatically in the
2286 // next turn.
2287 static_cast<SwTabFrame*>(pTabFrame)->SetFollowFlowLine( false );
2288 }
2289 pFrame->Cut();
2290 SwFrame::DestroyFrame(pFrame);
2291 }
2292 }
2293 }
2294 }
2295}
2296
2297static bool lcl_IsLineOfTableFrame( const SwTabFrame& rTable, const SwFrame& rChk )
2298{
2299 const SwTabFrame* pTableFrame = rChk.FindTabFrame();
2300 if( pTableFrame->IsFollow() )
2301 pTableFrame = pTableFrame->FindMaster( true );
2302 return &rTable == pTableFrame;
2303}
2304
2305static void lcl_UpdateRepeatedHeadlines( SwTabFrame& rTabFrame, bool bCalcLowers )
2306{
2307 OSL_ENSURE( rTabFrame.IsFollow(), "lcl_UpdateRepeatedHeadlines called for non-follow tab" )do { if (true && (!(rTabFrame.IsFollow()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2307" ": "), "%s", "lcl_UpdateRepeatedHeadlines called for non-follow tab"
); } } while (false)
;
2308
2309 // Delete remaining headlines:
2310 SwRowFrame* pLower = nullptr;
2311 while ( nullptr != ( pLower = static_cast<SwRowFrame*>(rTabFrame.Lower()) ) && pLower->IsRepeatedHeadline() )
2312 {
2313 pLower->Cut();
2314 SwFrame::DestroyFrame(pLower);
2315 }
2316
2317 // Insert fresh set of headlines:
2318 pLower = static_cast<SwRowFrame*>(rTabFrame.Lower());
2319 SwTable& rTable = *rTabFrame.GetTable();
2320 const sal_uInt16 nRepeat = rTable.GetRowsToRepeat();
2321 for ( sal_uInt16 nIdx = 0; nIdx < nRepeat; ++nIdx )
2322 {
2323 SwRowFrame* pHeadline = new SwRowFrame( *rTable.GetTabLines()[ nIdx ], &rTabFrame );
2324 pHeadline->SetRepeatedHeadline( true );
2325 pHeadline->Paste( &rTabFrame, pLower );
2326 pHeadline->RegistFlys();
2327 }
2328
2329 if ( bCalcLowers )
2330 rTabFrame.SetCalcLowers();
2331}
2332
2333void FndBox_::MakeFrames( SwTable &rTable )
2334{
2335 // All lines between pLineBefore and pLineBehind should be re-generated in layout.
2336 // And this for all instances of a table (for example in header/footer).
2337 sal_uInt16 nStPos = 0;
2338 sal_uInt16 nEndPos= rTable.GetTabLines().size() - 1;
2339 if ( m_pLineBefore )
2340 {
2341 nStPos = rTable.GetTabLines().GetPos(
2342 const_cast<const SwTableLine*&>(m_pLineBefore) );
2343 OSL_ENSURE( nStPos != USHRT_MAX, "Fox stole the line!" )do { if (true && (!(nStPos != (32767 *2 +1)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2343" ": "), "%s", "Fox stole the line!"); } } while (false
)
;
2344 ++nStPos;
2345
2346 }
2347 if ( m_pLineBehind )
2348 {
2349 nEndPos = rTable.GetTabLines().GetPos(
2350 const_cast<const SwTableLine*&>(m_pLineBehind) );
2351 OSL_ENSURE( nEndPos != USHRT_MAX, "Fox stole the line!" )do { if (true && (!(nEndPos != (32767 *2 +1)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2351" ": "), "%s", "Fox stole the line!"); } } while (false
)
;
2352 --nEndPos;
2353 }
2354 // now big insert operation for all tables.
2355 SwIterator<SwTabFrame,SwFormat> aTabIter( *rTable.GetFrameFormat() );
2356 for ( SwTabFrame *pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
2357 {
2358 if ( !pTable->IsFollow() )
2359 {
2360 SwRowFrame *pSibling = nullptr;
2361 SwFrame *pUpperFrame = nullptr;
2362 int i;
2363 for ( i = rTable.GetTabLines().size()-1;
2364 i >= 0 && !pSibling; --i )
2365 {
2366 SwTableLine *pLine = m_pLineBehind ? m_pLineBehind :
2367 rTable.GetTabLines()[static_cast<sal_uInt16>(i)];
2368 SwIterator<SwRowFrame,SwFormat> aIter( *pLine->GetFrameFormat() );
2369 pSibling = aIter.First();
2370 while ( pSibling && (
2371 pSibling->GetTabLine() != pLine ||
2372 !lcl_IsLineOfTableFrame( *pTable, *pSibling ) ||
2373 pSibling->IsRepeatedHeadline() ||
2374 // #i53647# If !pLineBehind,
2375 // IsInSplitTableRow() should be checked.
2376 ( m_pLineBehind && pSibling->IsInFollowFlowRow() ) ||
2377 (!m_pLineBehind && pSibling->IsInSplitTableRow() ) ) )
2378 {
2379 pSibling = aIter.Next();
2380 }
2381 }
2382 if ( pSibling )
2383 {
2384 pUpperFrame = pSibling->GetUpper();
2385 if ( !m_pLineBehind )
2386 pSibling = nullptr;
2387 }
2388 else
2389// ???? or is this the last Follow of the table ????
2390 pUpperFrame = pTable;
2391
2392 for ( sal_uInt16 j = nStPos; j <= nEndPos; ++j )
2393 ::lcl_InsertRow( *rTable.GetTabLines()[j],
2394 static_cast<SwLayoutFrame*>(pUpperFrame), pSibling );
2395 if ( pUpperFrame->IsTabFrame() )
2396 static_cast<SwTabFrame*>(pUpperFrame)->SetCalcLowers();
2397 }
2398 else if ( rTable.GetRowsToRepeat() > 0 )
2399 {
2400 // Insert new headlines:
2401 lcl_UpdateRepeatedHeadlines( *pTable, true );
2402 }
2403 }
2404}
2405
2406void FndBox_::MakeNewFrames( SwTable &rTable, const sal_uInt16 nNumber,
2407 const bool bBehind )
2408{
2409 // Create Frames for newly inserted lines
2410 // bBehind == true: before pLineBehind
2411 // == false: after pLineBefore
2412 const sal_uInt16 nBfPos = m_pLineBefore ?
2413 rTable.GetTabLines().GetPos( const_cast<const SwTableLine*&>(m_pLineBefore) ) :
2414 USHRT_MAX(32767 *2 +1);
2415 const sal_uInt16 nBhPos = m_pLineBehind ?
2416 rTable.GetTabLines().GetPos( const_cast<const SwTableLine*&>(m_pLineBehind) ) :
2417 USHRT_MAX(32767 *2 +1);
2418
2419 //nNumber: how often did we insert
2420 //nCnt: how many were inserted nNumber times
2421
2422 const sal_uInt16 nCnt =
2423 ((nBhPos != USHRT_MAX(32767 *2 +1) ? nBhPos : rTable.GetTabLines().size()) -
2424 (nBfPos != USHRT_MAX(32767 *2 +1) ? nBfPos + 1 : 0)) / (nNumber + 1);
2425
2426 // search the Master-TabFrame
2427 SwIterator<SwTabFrame,SwFormat> aTabIter( *rTable.GetFrameFormat() );
2428 SwTabFrame *pTable;
2429 for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
2430 {
2431 if( !pTable->IsFollow() )
2432 {
2433 SwRowFrame* pSibling = nullptr;
2434 SwLayoutFrame *pUpperFrame = nullptr;
2435 if ( bBehind )
2436 {
2437 if ( m_pLineBehind )
2438 {
2439 SwIterator<SwRowFrame,SwFormat> aIter( *m_pLineBehind->GetFrameFormat() );
2440 pSibling = aIter.First();
2441 while ( pSibling && (
2442 // only consider row frames associated with pLineBehind:
2443 pSibling->GetTabLine() != m_pLineBehind ||
2444 // only consider row frames that are in pTables Master-Follow chain:
2445 !lcl_IsLineOfTableFrame( *pTable, *pSibling ) ||
2446 // only consider row frames that are not repeated headlines:
2447 pSibling->IsRepeatedHeadline() ||
2448 // only consider row frames that are not follow flow rows
2449 pSibling->IsInFollowFlowRow() ) )
2450 {
2451 pSibling = aIter.Next();
2452 }
2453 }
2454 if ( pSibling )
2455 pUpperFrame = pSibling->GetUpper();
2456 else
2457 {
2458 while( pTable->GetFollow() )
2459 pTable = pTable->GetFollow();
2460 pUpperFrame = pTable;
2461 }
2462 const sal_uInt16 nMax = nBhPos != USHRT_MAX(32767 *2 +1) ?
2463 nBhPos : rTable.GetTabLines().size();
2464
2465 sal_uInt16 i = nBfPos != USHRT_MAX(32767 *2 +1) ? nBfPos + 1 + nCnt : nCnt;
2466
2467 for ( ; i < nMax; ++i )
2468 ::lcl_InsertRow( *rTable.GetTabLines()[i], pUpperFrame, pSibling );
2469 if ( pUpperFrame->IsTabFrame() )
2470 static_cast<SwTabFrame*>(pUpperFrame)->SetCalcLowers();
2471 }
2472 else // insert before
2473 {
2474 sal_uInt16 i;
2475
2476 // We are looking for the frame that is behind the row frame
2477 // that should be inserted.
2478 for ( i = 0; !pSibling; ++i )
2479 {
2480 SwTableLine* pLine = m_pLineBefore ? m_pLineBefore : rTable.GetTabLines()[i];
2481
2482 SwIterator<SwRowFrame,SwFormat> aIter( *pLine->GetFrameFormat() );
2483 pSibling = aIter.First();
2484
2485 while ( pSibling && (
2486 // only consider row frames associated with pLineBefore:
2487 pSibling->GetTabLine() != pLine ||
2488 // only consider row frames that are in pTables Master-Follow chain:
2489 !lcl_IsLineOfTableFrame( *pTable, *pSibling ) ||
2490 // only consider row frames that are not repeated headlines:
2491 pSibling->IsRepeatedHeadline() ||
2492 // 1. case: pLineBefore == 0:
2493 // only consider row frames that are not follow flow rows
2494 // 2. case: pLineBefore != 0:
2495 // only consider row frames that are not split table rows
2496 // #i37476# If !pLineBefore,
2497 // check IsInFollowFlowRow instead of IsInSplitTableRow.
2498 ( ( !m_pLineBefore && pSibling->IsInFollowFlowRow() ) ||
2499 ( m_pLineBefore && pSibling->IsInSplitTableRow() ) ) ) )
2500 {
2501 pSibling = aIter.Next();
2502 }
2503 }
2504
2505 pUpperFrame = pSibling->GetUpper();
2506 if ( m_pLineBefore )
2507 pSibling = static_cast<SwRowFrame*>( pSibling->GetNext() );
2508
2509 sal_uInt16 nMax = nBhPos != USHRT_MAX(32767 *2 +1) ?
2510 nBhPos - nCnt :
2511 rTable.GetTabLines().size() - nCnt;
2512
2513 i = nBfPos != USHRT_MAX(32767 *2 +1) ? nBfPos + 1 : 0;
2514 for ( ; i < nMax; ++i )
2515 ::lcl_InsertRow( *rTable.GetTabLines()[i],
2516 pUpperFrame, pSibling );
2517 if ( pUpperFrame->IsTabFrame() )
2518 static_cast<SwTabFrame*>(pUpperFrame)->SetCalcLowers();
2519 }
2520 }
2521 }
2522
2523 // If necessary headlines should be processed. In order to
2524 // not to fragment good code, we iterate once more.
2525 const sal_uInt16 nRowsToRepeat = rTable.GetRowsToRepeat();
2526 if ( !(nRowsToRepeat > 0 &&
2527 ( ( !bBehind && ( nBfPos == USHRT_MAX(32767 *2 +1) || nBfPos + 1 < nRowsToRepeat ) ) ||
2528 ( bBehind && ( ( nBfPos == USHRT_MAX(32767 *2 +1) && nRowsToRepeat > 1 ) || nBfPos + 2 < nRowsToRepeat ) ) )) )
2529 return;
2530
2531 for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
2532 {
2533 if ( pTable->Lower() )
2534 {
2535 if ( pTable->IsFollow() )
2536 {
2537 lcl_UpdateRepeatedHeadlines( *pTable, true );
2538 }
2539
2540 OSL_ENSURE( static_cast<SwRowFrame*>(pTable->Lower())->GetTabLine() ==do { if (true && (!(static_cast<SwRowFrame*>(pTable
->Lower())->GetTabLine() == rTable.GetTabLines()[0]))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2541" ": "), "%s", "MakeNewFrames: Table corruption!");
} } while (false)
2541 rTable.GetTabLines()[0], "MakeNewFrames: Table corruption!" )do { if (true && (!(static_cast<SwRowFrame*>(pTable
->Lower())->GetTabLine() == rTable.GetTabLines()[0]))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2541" ": "), "%s", "MakeNewFrames: Table corruption!");
} } while (false)
;
2542 }
2543 }
2544}
2545
2546bool FndBox_::AreLinesToRestore( const SwTable &rTable ) const
2547{
2548 // Should we call MakeFrames here?
2549
2550 if ( !m_pLineBefore && !m_pLineBehind && !rTable.GetTabLines().empty() )
2551 return true;
2552
2553 sal_uInt16 nBfPos;
2554 if(m_pLineBefore)
2555 {
2556 const SwTableLine* rLBefore = const_cast<const SwTableLine*>(m_pLineBefore);
2557 nBfPos = rTable.GetTabLines().GetPos( rLBefore );
2558 }
2559 else
2560 nBfPos = USHRT_MAX(32767 *2 +1);
2561
2562 sal_uInt16 nBhPos;
2563 if(m_pLineBehind)
2564 {
2565 const SwTableLine* rLBehind = const_cast<const SwTableLine*>(m_pLineBehind);
2566 nBhPos = rTable.GetTabLines().GetPos( rLBehind );
2567 }
2568 else
2569 nBhPos = USHRT_MAX(32767 *2 +1);
2570
2571 if ( nBfPos == nBhPos ) // Should never occur.
2572 {
2573 OSL_FAIL( "Table, erase but not on any area !?!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx"
":" "2573" ": "), "%s", "Table, erase but not on any area !?!"
); } } while (false)
;
2574 return false;
2575 }
2576
2577 if ( rTable.GetRowsToRepeat() > 0 )
2578 {
2579 // oops: should the repeated headline have been deleted??
2580 SwIterator<SwTabFrame,SwFormat> aIter( *rTable.GetFrameFormat() );
2581 for( SwTabFrame* pTable = aIter.First(); pTable; pTable = aIter.Next() )
2582 {
2583 if( pTable->IsFollow() )
2584 {
2585 // Insert new headlines:
2586 lcl_UpdateRepeatedHeadlines( *pTable, false );
2587 }
2588 }
2589 }
2590
2591 // Some adjacent lines at the beginning of the table have been deleted:
2592 if ( nBfPos == USHRT_MAX(32767 *2 +1) && nBhPos == 0 )
2593 return false;
2594
2595 // Some adjacent lines at the end of the table have been deleted:
2596 if ( nBhPos == USHRT_MAX(32767 *2 +1) && nBfPos == (rTable.GetTabLines().size() - 1) )
2597 return false;
2598
2599 // Some adjacent lines in the middle of the table have been deleted:
2600 if ( nBfPos != USHRT_MAX(32767 *2 +1) && nBhPos != USHRT_MAX(32767 *2 +1) && (nBfPos + 1) == nBhPos )
2601 return false;
2602
2603 // The structure of the deleted lines is more complex due to split lines.
2604 // A call of MakeFrames() is necessary.
2605 return true;
2606}
2607
2608/* vim:set shiftwidth=4 softtabstop=4 expandtab: */