File: | home/maarten/src/libreoffice/core/sw/source/core/frmedt/tblsel.cxx |
Warning: | line 1727, column 13 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
66 | namespace { | |||
67 | ||||
68 | struct 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 | ||||
90 | typedef o3tl::sorted_vector<CmpLPt> MergePos; | |||
91 | ||||
92 | namespace { | |||
93 | ||||
94 | struct Sort_CellFrame | |||
95 | { | |||
96 | const SwCellFrame* pFrame; | |||
97 | ||||
98 | explicit Sort_CellFrame( const SwCellFrame& rCFrame ) | |||
99 | : pFrame( &rCFrame ) {} | |||
100 | }; | |||
101 | ||||
102 | } | |||
103 | ||||
104 | static const SwLayoutFrame *lcl_FindCellFrame( const SwLayoutFrame *pLay ) | |||
105 | { | |||
106 | while ( pLay && !pLay->IsCellFrame() ) | |||
107 | pLay = pLay->GetUpper(); | |||
108 | return pLay; | |||
109 | } | |||
110 | ||||
111 | static 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 | ||||
124 | void 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 | ||||
133 | void 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 | ||||
149 | void 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 | ||||
159 | void 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 | ||||
247 | void 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 | ||||
428 | bool 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 | ||||
670 | bool 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 | ||||
693 | bool 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 | ||||
856 | bool 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 | ||||
870 | CmpLPt::CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical ) | |||
871 | : aPos( rPt ), pSelBox( pBox ), bVert( bVertical ) | |||
872 | {} | |||
873 | ||||
874 | static 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 | ||||
893 | bool 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 | ||||
929 | void 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 | ||||
1418 | static bool lcl_CheckCol(FndBox_ const&, bool* pPara); | |||
1419 | ||||
1420 | static 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 | ||||
1429 | static 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 | ||||
1452 | TableMergeErr 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 | ||||
1473 | TableMergeErr 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 | ||||
1520 | static 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 | ||||
1548 | static 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 | ||||
1617 | static 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 ) | |||
| ||||
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; | |||
1634 | ||||
1635 | while ( pTab->IsFollow() ) | |||
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() ) | |||
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 && | |||
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
| |||
1668 | rpStart = pTmp; | |||
1669 | ||||
1670 | pTab = pOrg; | |||
1671 | ||||
1672 | const SwTabFrame* pLastValidTab = pTab; | |||
1673 | while ( pTab->GetFollow() ) | |||
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() ) | |||
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; | |||
1706 | // --> Made code robust. If pTab does not have a lower, | |||
1707 | // we would crash here. | |||
1708 | if ( !pLastContent
| |||
1709 | ||||
1710 | while( !rpEnd->IsCellFrame() ) | |||
1711 | rpEnd = rpEnd->GetUpper(); | |||
1712 | ||||
1713 | while ( ( bRTL && aRectFnSet.GetLeft(rpEnd->getFrameArea()) < nEX ) || | |||
1714 | ( ! bRTL
| |||
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 ? | |||
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() ) | |||
| ||||
1728 | { | |||
1729 | const SwLayoutFrame *pTmpLeaf = rpStart->GetNextLayoutLeaf(); | |||
1730 | while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) > nEX ) // first skip line | |||
1731 | pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf(); | |||
1732 | while ( pTmpLeaf
| |||
1733 | aRectFnSet.GetRight(pTmpLeaf->getFrameArea())< nSX2 ) | |||
1734 | pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf(); | |||
1735 | const SwTabFrame *pTmpTab = rpStart->FindTabFrame(); | |||
1736 | if ( !pTmpTab->IsAnLower( pTmpLeaf ) ) | |||
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; | |||
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 | ||||
1771 | void 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 | ||||
1963 | bool 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 | ||||
1972 | bool 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 | ||||
2052 | static 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 | ||||
2070 | static 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 | ||||
2092 | static 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 | ||||
2104 | void ForEach_FndLineCopyCol(SwTableLines& rLines, FndPara* pFndPara ) | |||
2105 | { | |||
2106 | for( SwTableLines::iterator it = rLines.begin(); it != rLines.end(); ++it ) | |||
2107 | FndLineCopyCol( *it, pFndPara ); | |||
2108 | } | |||
2109 | ||||
2110 | void 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 | ||||
2143 | void 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 | ||||
2167 | inline void UnsetFollow( SwFlowFrame *pTab ) | |||
2168 | { | |||
2169 | pTab->m_pPrecede = nullptr; | |||
2170 | } | |||
2171 | ||||
2172 | void 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 | ||||
2297 | static 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 | ||||
2305 | static 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 | ||||
2333 | void 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 | ||||
2406 | void 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 | ||||
2546 | bool 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: */ |