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