Line data Source code
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 <com/sun/star/text/HoriOrientation.hpp>
21 : #include <com/sun/star/chart2/XChartDocument.hpp>
22 : #include <hintids.hxx>
23 :
24 : #include <editeng/brushitem.hxx>
25 : #include <editeng/lrspitem.hxx>
26 : #include <editeng/protitem.hxx>
27 : #include <editeng/boxitem.hxx>
28 : #include <tools/fract.hxx>
29 : #include <fmtfsize.hxx>
30 : #include <fmtornt.hxx>
31 : #include <doc.hxx>
32 : #include <IDocumentSettingAccess.hxx>
33 : #include <IDocumentChartDataProviderAccess.hxx>
34 : #include <DocumentContentOperationsManager.hxx>
35 : #include <IDocumentRedlineAccess.hxx>
36 : #include <IDocumentStylePoolAccess.hxx>
37 : #include <IDocumentFieldsAccess.hxx>
38 : #include <cntfrm.hxx>
39 : #include <tabfrm.hxx>
40 : #include <frmtool.hxx>
41 : #include <pam.hxx>
42 : #include <swtable.hxx>
43 : #include <ndtxt.hxx>
44 : #include <tblsel.hxx>
45 : #include <fldbas.hxx>
46 : #include <swundo.hxx>
47 : #include <rowfrm.hxx>
48 : #include <ddefld.hxx>
49 : #include <hints.hxx>
50 : #include <UndoTable.hxx>
51 : #include <cellatr.hxx>
52 : #include <mvsave.hxx>
53 : #include <swtblfmt.hxx>
54 : #include <swddetbl.hxx>
55 : #include <poolfmt.hxx>
56 : #include <tblrwcl.hxx>
57 : #include <unochart.hxx>
58 : #include <o3tl/numeric.hxx>
59 : #include <boost/shared_ptr.hpp>
60 : #include <boost/scoped_ptr.hpp>
61 : #include <calbck.hxx>
62 : #include <docary.hxx>
63 :
64 : using namespace com::sun::star;
65 : using namespace com::sun::star::uno;
66 :
67 : #define COLFUZZY 20
68 : #define ROWFUZZY 10
69 :
70 : using namespace ::com::sun::star;
71 :
72 : #ifdef DBG_UTIL
73 : #define CHECK_TABLE(t) (t).CheckConsistency();
74 : #else
75 : #define CHECK_TABLE(t)
76 : #endif
77 :
78 : typedef std::map<SwTableLine*, sal_uInt16> SwTableLineWidthMap_t;
79 :
80 : // In order to set the Frame Formats for the Boxes, it's enough to look
81 : // up the current one in the array. If it's already there return the new one.
82 : struct _CpyTabFrm
83 : {
84 : union {
85 : SwTableBoxFormat *pFrameFormat; // for CopyCol
86 : SwTwips nSize; // for DelCol
87 : } Value;
88 : SwTableBoxFormat *pNewFrameFormat;
89 :
90 9 : explicit _CpyTabFrm( SwTableBoxFormat* pAktFrameFormat ) : pNewFrameFormat( 0 )
91 9 : { Value.pFrameFormat = pAktFrameFormat; }
92 :
93 : _CpyTabFrm& operator=( const _CpyTabFrm& );
94 :
95 0 : bool operator==( const _CpyTabFrm& rCpyTabFrm ) const
96 0 : { return (sal_uLong)Value.nSize == (sal_uLong)rCpyTabFrm.Value.nSize; }
97 6 : bool operator<( const _CpyTabFrm& rCpyTabFrm ) const
98 6 : { return (sal_uLong)Value.nSize < (sal_uLong)rCpyTabFrm.Value.nSize; }
99 : };
100 :
101 0 : struct CR_SetBoxWidth
102 : {
103 : SwSelBoxes m_Boxes;
104 : SwTableLineWidthMap_t m_LineWidthMap;
105 : SwShareBoxFormats aShareFormats;
106 : SwTableNode* pTableNd;
107 : SwUndoTableNdsChg* pUndo;
108 : SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
109 : TableChgMode nMode;
110 : sal_uInt16 nTableWidth, nRemainWidth, nBoxWidth;
111 : bool bBigger, bLeft, bSplittBox, bAnyBoxFnd;
112 :
113 0 : CR_SetBoxWidth( sal_uInt16 eType, SwTwips nDif, SwTwips nSid, SwTwips nTableW,
114 : SwTwips nMax, SwTableNode* pTNd )
115 : : pTableNd( pTNd ), pUndo( 0 ),
116 : nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ),
117 : nTableWidth( (sal_uInt16)nTableW ), nRemainWidth( 0 ), nBoxWidth( 0 ),
118 0 : bSplittBox( false ), bAnyBoxFnd( false )
119 : {
120 0 : bLeft = nsTableChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
121 0 : nsTableChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff );
122 0 : bBigger = 0 != (eType & nsTableChgWidthHeightType::WH_FLAG_BIGGER );
123 0 : nMode = pTableNd->GetTable().GetTableChgMode();
124 0 : }
125 0 : CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
126 : : m_LineWidthMap(rCpy.m_LineWidthMap)
127 : ,
128 : pTableNd( rCpy.pTableNd ),
129 : pUndo( rCpy.pUndo ),
130 : nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
131 : nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
132 : nMode( rCpy.nMode ), nTableWidth( rCpy.nTableWidth ),
133 : nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( rCpy.nBoxWidth ),
134 : bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ),
135 0 : bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
136 : {
137 0 : }
138 :
139 0 : SwUndoTableNdsChg* CreateUndo( SwUndoId eUndoType )
140 : {
141 0 : return pUndo = new SwUndoTableNdsChg( eUndoType, m_Boxes, *pTableNd );
142 : }
143 :
144 0 : void LoopClear()
145 : {
146 0 : nLowerDiff = 0; nRemainWidth = 0;
147 0 : }
148 : };
149 :
150 : static bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
151 : SwTwips nDist, bool bCheck );
152 : static bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
153 : SwTwips nDist, bool bCheck );
154 : static bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
155 : SwTwips nDist, bool bCheck );
156 : static bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
157 : SwTwips nDist, bool bCheck );
158 : static bool lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
159 : SwTwips nDist, bool bCheck );
160 : static bool lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
161 : SwTwips nDist, bool bCheck );
162 :
163 : typedef bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, bool );
164 :
165 : #ifdef DBG_UTIL
166 :
167 : #define CHECKBOXWIDTH \
168 : { \
169 : SwTwips nSize = GetFrameFormat()->GetFrmSize().GetWidth(); \
170 : for (size_t nTmp = 0; nTmp < aLines.size(); ++nTmp) \
171 : ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \
172 : }
173 :
174 : #define CHECKTABLELAYOUT \
175 : { \
176 : for ( size_t i = 0; i < GetTabLines().size(); ++i ) \
177 : { \
178 : SwFrameFormat* pFormat = GetTabLines()[i]->GetFrameFormat(); \
179 : SwIterator<SwRowFrm,SwFormat> aIter( *pFormat ); \
180 : for (SwRowFrm* pFrm=aIter.First(); pFrm; pFrm=aIter.Next())\
181 : { \
182 : if ( pFrm->GetTabLine() == GetTabLines()[i] ) \
183 : { \
184 : OSL_ENSURE( pFrm->GetUpper()->IsTabFrm(), \
185 : "Table layout does not match table structure" ); \
186 : } \
187 : } \
188 : } \
189 : }
190 :
191 : #else
192 :
193 : #define CHECKBOXWIDTH
194 : #define CHECKTABLELAYOUT
195 :
196 : #endif // DBG_UTIL
197 :
198 0 : struct CR_SetLineHeight
199 : {
200 : SwSelBoxes m_Boxes;
201 : SwShareBoxFormats aShareFormats;
202 : SwTableNode* pTableNd;
203 : SwUndoTableNdsChg* pUndo;
204 : SwTwips nMaxSpace, nMaxHeight;
205 : TableChgMode nMode;
206 : sal_uInt16 nLines;
207 : bool bBigger, bTop, bSplittBox, bAnyBoxFnd;
208 :
209 0 : CR_SetLineHeight( sal_uInt16 eType, SwTableNode* pTNd )
210 : : pTableNd( pTNd ), pUndo( 0 ),
211 : nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ),
212 0 : bSplittBox( false ), bAnyBoxFnd( false )
213 : {
214 0 : bTop = nsTableChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTableChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff );
215 0 : bBigger = 0 != (eType & nsTableChgWidthHeightType::WH_FLAG_BIGGER );
216 0 : if( eType & nsTableChgWidthHeightType::WH_FLAG_INSDEL )
217 0 : bBigger = !bBigger;
218 0 : nMode = pTableNd->GetTable().GetTableChgMode();
219 0 : }
220 0 : CR_SetLineHeight( const CR_SetLineHeight& rCpy )
221 : : pTableNd( rCpy.pTableNd ), pUndo( rCpy.pUndo ),
222 : nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
223 : nMode( rCpy.nMode ), nLines( rCpy.nLines ),
224 : bBigger( rCpy.bBigger ), bTop( rCpy.bTop ),
225 0 : bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
226 0 : {}
227 :
228 0 : SwUndoTableNdsChg* CreateUndo( SwUndoId nUndoType )
229 : {
230 0 : return pUndo = new SwUndoTableNdsChg( nUndoType, m_Boxes, *pTableNd );
231 : }
232 : };
233 :
234 : static bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
235 : SwTwips nDist, bool bCheck );
236 : static bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
237 : SwTwips nDist, bool bCheck );
238 : static bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
239 : SwTwips nDist, bool bCheck );
240 :
241 : typedef bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, bool );
242 :
243 0 : _CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm )
244 : {
245 0 : pNewFrameFormat = rCpyTabFrm.pNewFrameFormat;
246 0 : Value = rCpyTabFrm.Value;
247 0 : return *this;
248 : }
249 :
250 : typedef o3tl::sorted_vector<_CpyTabFrm> _CpyTabFrms;
251 :
252 8 : struct _CpyPara
253 : {
254 : boost::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths;
255 : SwDoc* pDoc;
256 : SwTableNode* pTableNd;
257 : _CpyTabFrms& rTabFrmArr;
258 : SwTableLine* pInsLine;
259 : SwTableBox* pInsBox;
260 : sal_uLong nOldSize, nNewSize; // in order to correct the size attributes
261 : sal_uLong nMinLeft, nMaxRight;
262 : sal_uInt16 nCpyCnt, nInsPos;
263 : sal_uInt16 nLnIdx, nBoxIdx;
264 : sal_uInt8 nDelBorderFlag;
265 : bool bCpyContent;
266 :
267 4 : _CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, _CpyTabFrms& rFrmArr,
268 : bool bCopyContent = true )
269 4 : : pDoc( pNd->GetDoc() ), pTableNd( pNd ), rTabFrmArr(rFrmArr),
270 : pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0),
271 : nMinLeft(ULONG_MAX), nMaxRight(0),
272 : nCpyCnt(nCopies), nInsPos(0),
273 : nLnIdx(0), nBoxIdx(0),
274 8 : nDelBorderFlag(0), bCpyContent( bCopyContent )
275 4 : {}
276 4 : _CpyPara( const _CpyPara& rPara, SwTableLine* pLine )
277 : : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTableNd(rPara.pTableNd),
278 : rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
279 : nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
280 : nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
281 : nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
282 4 : nDelBorderFlag( rPara.nDelBorderFlag ), bCpyContent( rPara.bCpyContent )
283 4 : {}
284 0 : _CpyPara( const _CpyPara& rPara, SwTableBox* pBox )
285 : : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTableNd(rPara.pTableNd),
286 : rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
287 : nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
288 : nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
289 : nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
290 0 : nDelBorderFlag( rPara.nDelBorderFlag ), bCpyContent( rPara.bCpyContent )
291 0 : {}
292 : };
293 :
294 : static void lcl_CopyRow(_FndLine & rFndLine, _CpyPara *const pCpyPara);
295 :
296 7 : static void lcl_CopyCol( _FndBox & rFndBox, _CpyPara *const pCpyPara)
297 : {
298 : // Look up the Frame Format in the Frame Format Array
299 7 : SwTableBox* pBox = rFndBox.GetBox();
300 7 : _CpyTabFrm aFindFrm( static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat()) );
301 :
302 : sal_uInt16 nFndPos;
303 7 : if( pCpyPara->nCpyCnt )
304 : {
305 0 : _CpyTabFrms::const_iterator itFind = pCpyPara->rTabFrmArr.lower_bound( aFindFrm );
306 0 : nFndPos = itFind - pCpyPara->rTabFrmArr.begin();
307 0 : if( itFind == pCpyPara->rTabFrmArr.end() || !(*itFind == aFindFrm) )
308 : {
309 : // For nested copying, also save the new Format as an old one.
310 0 : SwTableBoxFormat* pNewFormat = static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat());
311 :
312 : // Find the selected Boxes in the Line:
313 0 : _FndLine const* pCmpLine = NULL;
314 0 : SwFormatFrmSize aFrmSz( pNewFormat->GetFrmSize() );
315 :
316 0 : bool bDiffCount = false;
317 0 : if( pBox->GetTabLines().size() )
318 : {
319 0 : pCmpLine = &rFndBox.GetLines().front();
320 0 : if ( pCmpLine->GetBoxes().size() != pCmpLine->GetLine()->GetTabBoxes().size() )
321 0 : bDiffCount = true;
322 : }
323 :
324 0 : if( bDiffCount )
325 : {
326 : // The first Line should be enough
327 0 : _FndBoxes const& rFndBoxes = pCmpLine->GetBoxes();
328 0 : long nSz = 0;
329 0 : for( auto n = rFndBoxes.size(); n; )
330 : {
331 0 : nSz += rFndBoxes[--n].GetBox()->
332 0 : GetFrameFormat()->GetFrmSize().GetWidth();
333 : }
334 0 : aFrmSz.SetWidth( aFrmSz.GetWidth() -
335 0 : nSz / ( pCpyPara->nCpyCnt + 1 ) );
336 0 : pNewFormat->SetFormatAttr( aFrmSz );
337 0 : aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
338 :
339 : // Create a new Format for the new Box, specifying its size.
340 : aFindFrm.pNewFrameFormat = reinterpret_cast<SwTableBoxFormat*>(pNewFormat->GetDoc()->
341 0 : MakeTableLineFormat());
342 0 : *aFindFrm.pNewFrameFormat = *pNewFormat;
343 0 : aFindFrm.pNewFrameFormat->SetFormatAttr( aFrmSz );
344 : }
345 : else
346 : {
347 0 : aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
348 0 : pNewFormat->SetFormatAttr( aFrmSz );
349 :
350 0 : aFindFrm.pNewFrameFormat = pNewFormat;
351 0 : pCpyPara->rTabFrmArr.insert( aFindFrm );
352 0 : aFindFrm.Value.pFrameFormat = pNewFormat;
353 0 : pCpyPara->rTabFrmArr.insert( aFindFrm );
354 0 : }
355 : }
356 : else
357 : {
358 0 : aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
359 0 : pBox->ChgFrameFormat( aFindFrm.pNewFrameFormat );
360 : }
361 : }
362 : else
363 : {
364 7 : _CpyTabFrms::const_iterator itFind = pCpyPara->rTabFrmArr.find( aFindFrm );
365 28 : if( pCpyPara->nDelBorderFlag &&
366 28 : itFind != pCpyPara->rTabFrmArr.end() )
367 0 : aFindFrm = *itFind;
368 : else
369 7 : aFindFrm.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
370 : }
371 :
372 7 : if (!rFndBox.GetLines().empty())
373 : {
374 : pBox = new SwTableBox( aFindFrm.pNewFrameFormat,
375 0 : rFndBox.GetLines().size(), pCpyPara->pInsLine );
376 0 : pCpyPara->pInsLine->GetTabBoxes().insert( pCpyPara->pInsLine->GetTabBoxes().begin() + pCpyPara->nInsPos++, pBox );
377 0 : _CpyPara aPara( *pCpyPara, pBox );
378 0 : aPara.nDelBorderFlag &= 7;
379 :
380 0 : for( _FndLine & rFndLine : rFndBox.GetLines() )
381 0 : lcl_CopyRow( rFndLine, &aPara );
382 : }
383 : else
384 : {
385 : ::_InsTableBox( pCpyPara->pDoc, pCpyPara->pTableNd, pCpyPara->pInsLine,
386 7 : aFindFrm.pNewFrameFormat, pBox, pCpyPara->nInsPos++ );
387 :
388 7 : const _FndBoxes& rFndBxs = rFndBox.GetUpper()->GetBoxes();
389 14 : if( 8 > pCpyPara->nDelBorderFlag
390 7 : ? pCpyPara->nDelBorderFlag != 0
391 0 : : &rFndBox == &rFndBxs[rFndBxs.size() - 1] )
392 : {
393 7 : const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
394 14 : if( 8 > pCpyPara->nDelBorderFlag
395 7 : ? rBoxItem.GetTop()
396 14 : : rBoxItem.GetRight() )
397 : {
398 7 : aFindFrm.Value.pFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
399 :
400 7 : SvxBoxItem aNew( rBoxItem );
401 7 : if( 8 > pCpyPara->nDelBorderFlag )
402 7 : aNew.SetLine( 0, SvxBoxItemLine::TOP );
403 : else
404 0 : aNew.SetLine( 0, SvxBoxItemLine::RIGHT );
405 :
406 9 : if( 1 == pCpyPara->nDelBorderFlag ||
407 2 : 8 == pCpyPara->nDelBorderFlag )
408 : {
409 : // For all Boxes that delete TopBorderLine, we copy after that
410 5 : pBox = pCpyPara->pInsLine->GetTabBoxes()[
411 10 : pCpyPara->nInsPos - 1 ];
412 : }
413 :
414 7 : aFindFrm.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
415 :
416 : // Else we copy before that and the first Line keeps the TopLine
417 : // and we remove it at the original
418 7 : pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
419 :
420 7 : if( !pCpyPara->nCpyCnt )
421 7 : pCpyPara->rTabFrmArr.insert( aFindFrm );
422 : }
423 : }
424 : }
425 7 : }
426 :
427 4 : static void lcl_CopyRow(_FndLine& rFndLine, _CpyPara *const pCpyPara)
428 : {
429 : SwTableLine* pNewLine = new SwTableLine(
430 4 : static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()),
431 4 : rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
432 4 : if( pCpyPara->pInsBox )
433 : {
434 0 : SwTableLines& rLines = pCpyPara->pInsBox->GetTabLines();
435 0 : rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
436 : }
437 : else
438 : {
439 4 : SwTableLines& rLines = pCpyPara->pTableNd->GetTable().GetTabLines();
440 4 : rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
441 : }
442 :
443 4 : _CpyPara aPara( *pCpyPara, pNewLine );
444 33 : for (_FndBoxes::iterator it = rFndLine.GetBoxes().begin();
445 22 : it != rFndLine.GetBoxes().end(); ++it)
446 : {
447 7 : lcl_CopyCol(*it, &aPara);
448 : }
449 :
450 4 : pCpyPara->nDelBorderFlag &= 0xf8;
451 4 : }
452 :
453 0 : static void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
454 : bool bBehind )
455 : {
456 : // Bug 29124: Not only copy in the BaseLines. If possible, we go down as far as possible
457 : _FndBox* pFBox;
458 0 : if( 1 == pFndLn->GetBoxes().size() &&
459 0 : !( pFBox = &pFndLn->GetBoxes()[0] )->GetBox()->GetSttNd() )
460 : {
461 : // A Box with multiple Lines, so insert into these Lines
462 0 : for( auto &rLine : pFBox->GetLines() )
463 0 : lcl_InsCol( &rLine, rCpyPara, nCpyCnt, bBehind );
464 : }
465 : else
466 : {
467 0 : rCpyPara.pInsLine = pFndLn->GetLine();
468 0 : SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
469 0 : pFndLn->GetBoxes().size()-1 : 0 ].GetBox();
470 0 : rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().GetPos( pBox );
471 0 : if( bBehind )
472 0 : ++rCpyPara.nInsPos;
473 :
474 0 : for( sal_uInt16 n = 0; n < nCpyCnt; ++n )
475 : {
476 0 : if( n + 1 == nCpyCnt && bBehind )
477 0 : rCpyPara.nDelBorderFlag = 9;
478 : else
479 0 : rCpyPara.nDelBorderFlag = 8;
480 0 : for (_FndBoxes::iterator it = pFndLn->GetBoxes().begin();
481 0 : it != pFndLn->GetBoxes().end(); ++it)
482 : {
483 0 : lcl_CopyCol(*it, &rCpyPara);
484 : }
485 : }
486 : }
487 0 : }
488 :
489 0 : SwRowFrm* GetRowFrm( SwTableLine& rLine )
490 : {
491 0 : SwIterator<SwRowFrm,SwFormat> aIter( *rLine.GetFrameFormat() );
492 0 : for( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
493 0 : if( pFrm->GetTabLine() == &rLine )
494 0 : return pFrm;
495 0 : return 0;
496 : }
497 :
498 0 : bool SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
499 : {
500 : OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid Box List" );
501 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
502 0 : if( !pTableNd )
503 0 : return false;
504 :
505 0 : bool bRes = true;
506 0 : if( IsNewModel() )
507 0 : bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind );
508 : else
509 : {
510 : // Find all Boxes/Lines
511 0 : _FndBox aFndBox( 0, 0 );
512 : {
513 0 : _FndPara aPara( rBoxes, &aFndBox );
514 0 : ForEach_FndLineCopyCol( GetTabLines(), &aPara );
515 : }
516 0 : if( aFndBox.GetLines().empty() )
517 0 : return false;
518 :
519 0 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
520 :
521 : // Find Lines for the layout update
522 0 : aFndBox.SetTableLines( *this );
523 0 : aFndBox.DelFrms( *this );
524 :
525 : // TL_CHART2: nothing to be done since chart2 currently does not want to
526 : // get notified about new rows/cols.
527 :
528 0 : _CpyTabFrms aTabFrmArr;
529 0 : _CpyPara aCpyPara( pTableNd, nCnt, aTabFrmArr );
530 :
531 0 : for( auto &rLine : aFndBox.GetLines() )
532 0 : lcl_InsCol( &rLine, aCpyPara, nCnt, bBehind );
533 :
534 : // clean up this Line's structure once again, generally all of them
535 0 : GCLines();
536 :
537 : // Update Layout
538 0 : aFndBox.MakeFrms( *this );
539 :
540 : CHECKBOXWIDTH;
541 : CHECKTABLELAYOUT;
542 0 : bRes = true;
543 : }
544 :
545 0 : SwChartDataProvider *pPCD = pDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider();
546 0 : if (pPCD && nCnt)
547 0 : pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
548 0 : pDoc->UpdateCharts( GetFrameFormat()->GetName() );
549 :
550 0 : return bRes;
551 : }
552 :
553 4 : bool SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
554 : sal_uInt16 nCnt, bool bBehind )
555 : {
556 : OSL_ENSURE( pDoc && !rBoxes.empty() && nCnt, "No valid Box List" );
557 4 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
558 4 : if( !pTableNd )
559 0 : return false;
560 :
561 : // Find all Boxes/Lines
562 4 : _FndBox aFndBox( 0, 0 );
563 : {
564 4 : _FndPara aPara( rBoxes, &aFndBox );
565 4 : ForEach_FndLineCopyCol( GetTabLines(), &aPara );
566 : }
567 4 : if( aFndBox.GetLines().empty() )
568 0 : return false;
569 :
570 4 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
571 :
572 4 : _FndBox* pFndBox = &aFndBox;
573 : {
574 : _FndLine* pFndLine;
575 16 : while( 1 == pFndBox->GetLines().size() &&
576 8 : 1 == ( pFndLine = &pFndBox->GetLines()[ 0 ])->GetBoxes().size() )
577 : {
578 : // Don't go down too far! One Line with Box needs to remain!
579 1 : _FndBox* pTmpBox = &pFndLine->GetBoxes().front();
580 1 : if( !pTmpBox->GetLines().empty() )
581 0 : pFndBox = pTmpBox;
582 : else
583 1 : break;
584 : }
585 : }
586 :
587 : // Find Lines for the layout update
588 4 : const bool bLayout = !IsNewModel() &&
589 4 : nullptr != SwIterator<SwTabFrm,SwFormat>( *GetFrameFormat() ).First();
590 :
591 4 : if ( bLayout )
592 : {
593 0 : aFndBox.SetTableLines( *this );
594 0 : if( pFndBox != &aFndBox )
595 0 : aFndBox.DelFrms( *this );
596 : // TL_CHART2: nothing to be done since chart2 currently does not want to
597 : // get notified about new rows/cols.
598 : }
599 :
600 8 : _CpyTabFrms aTabFrmArr;
601 8 : _CpyPara aCpyPara( pTableNd, 0, aTabFrmArr );
602 :
603 4 : SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
604 8 : pFndBox->GetLines().size()-1 : 0 ].GetLine();
605 4 : if( &aFndBox == pFndBox )
606 4 : aCpyPara.nInsPos = GetTabLines().GetPos( pLine );
607 : else
608 : {
609 0 : aCpyPara.pInsBox = pFndBox->GetBox();
610 0 : aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().GetPos( pLine );
611 : }
612 :
613 4 : if( bBehind )
614 : {
615 3 : ++aCpyPara.nInsPos;
616 3 : aCpyPara.nDelBorderFlag = 1;
617 : }
618 : else
619 1 : aCpyPara.nDelBorderFlag = 2;
620 :
621 8 : for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
622 : {
623 4 : if( bBehind )
624 3 : aCpyPara.nDelBorderFlag = 1;
625 8 : for( _FndLine& rFndLine : pFndBox->GetLines() )
626 4 : lcl_CopyRow( rFndLine, &aCpyPara );
627 : }
628 :
629 : // clean up this Line's structure once again, generally all of them
630 4 : if( !pDoc->IsInReading() )
631 4 : GCLines();
632 :
633 : // Update Layout
634 4 : if ( bLayout )
635 : {
636 0 : if( pFndBox != &aFndBox )
637 0 : aFndBox.MakeFrms( *this );
638 : else
639 0 : aFndBox.MakeNewFrms( *this, nCnt, bBehind );
640 : }
641 :
642 : CHECKBOXWIDTH;
643 : CHECKTABLELAYOUT;
644 :
645 4 : SwChartDataProvider *pPCD = pDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider();
646 4 : if (pPCD && nCnt)
647 0 : pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
648 4 : pDoc->UpdateCharts( GetFrameFormat()->GetName() );
649 :
650 8 : return true;
651 : }
652 :
653 : static void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
654 : bool bFirst, SwShareBoxFormats& rShareFormats );
655 :
656 0 : static void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset,
657 : bool bFirst, SwShareBoxFormats& rShareFormats )
658 : {
659 0 : for ( auto pLine : rLines )
660 0 : ::lcl_LastBoxSetWidth( pLine->GetTabBoxes(), nOffset, bFirst, rShareFormats );
661 0 : }
662 :
663 0 : static void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
664 : bool bFirst, SwShareBoxFormats& rShareFormats )
665 : {
666 0 : SwTableBox& rBox = *(bFirst ? rBoxes.front() : rBoxes.back());
667 0 : if( !rBox.GetSttNd() )
668 0 : ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
669 0 : bFirst, rShareFormats );
670 :
671 : // Adapt the Box
672 0 : const SwFrameFormat *pBoxFormat = rBox.GetFrameFormat();
673 0 : SwFormatFrmSize aNew( pBoxFormat->GetFrmSize() );
674 0 : aNew.SetWidth( aNew.GetWidth() + nOffset );
675 0 : SwFrameFormat *pFormat = rShareFormats.GetFormat( *pBoxFormat, aNew );
676 0 : if( pFormat )
677 0 : rBox.ChgFrameFormat( static_cast<SwTableBoxFormat*>(pFormat) );
678 : else
679 : {
680 0 : pFormat = rBox.ClaimFrameFormat();
681 :
682 0 : pFormat->LockModify();
683 0 : pFormat->SetFormatAttr( aNew );
684 0 : pFormat->UnlockModify();
685 :
686 0 : rShareFormats.AddFormat( *pBoxFormat, *pFormat );
687 0 : }
688 0 : }
689 :
690 7 : void _DeleteBox( SwTable& rTable, SwTableBox* pBox, SwUndo* pUndo,
691 : bool bCalcNewSize, const bool bCorrBorder,
692 : SwShareBoxFormats* pShareFormats )
693 : {
694 0 : do {
695 : SwTwips nBoxSz = bCalcNewSize ?
696 7 : pBox->GetFrameFormat()->GetFrmSize().GetWidth() : 0;
697 7 : SwTableLine* pLine = pBox->GetUpper();
698 7 : SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
699 7 : sal_uInt16 nDelPos = rTableBoxes.GetPos( pBox );
700 7 : SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
701 :
702 : // Special treatment for the border:
703 7 : if( bCorrBorder && 1 < rTableBoxes.size() )
704 : {
705 5 : const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
706 :
707 5 : if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
708 : {
709 4 : bool bChgd = false;
710 :
711 : // JP 02.04.97: 1st part for Bug 36271
712 : // First the left/right edges
713 4 : if( nDelPos + 1 < (sal_uInt16)rTableBoxes.size() )
714 : {
715 0 : SwTableBox* pNxtBox = rTableBoxes[ nDelPos + 1 ];
716 0 : const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrameFormat()->GetBox();
717 :
718 0 : SwTableBox* pPrvBox = nDelPos ? rTableBoxes[ nDelPos - 1 ] : 0;
719 :
720 0 : if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
721 0 : ( !pPrvBox || !pPrvBox->GetFrameFormat()->GetBox().GetRight()) )
722 : {
723 0 : SvxBoxItem aTmp( rNxtBoxItem );
724 0 : aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
725 : : rBoxItem.GetRight(),
726 0 : SvxBoxItemLine::LEFT );
727 0 : if( pShareFormats )
728 0 : pShareFormats->SetAttr( *pNxtBox, aTmp );
729 : else
730 0 : pNxtBox->ClaimFrameFormat()->SetFormatAttr( aTmp );
731 0 : bChgd = true;
732 : }
733 : }
734 4 : if( !bChgd && nDelPos )
735 : {
736 4 : SwTableBox* pPrvBox = rTableBoxes[ nDelPos - 1 ];
737 4 : const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrameFormat()->GetBox();
738 :
739 4 : SwTableBox* pNxtBox = nDelPos + 1 < (sal_uInt16)rTableBoxes.size()
740 4 : ? rTableBoxes[ nDelPos + 1 ] : 0;
741 :
742 5 : if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
743 0 : ( !pNxtBox || !pNxtBox->GetFrameFormat()->GetBox().GetLeft()) )
744 : {
745 1 : SvxBoxItem aTmp( rPrvBoxItem );
746 1 : aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
747 : : rBoxItem.GetRight(),
748 1 : SvxBoxItemLine::RIGHT );
749 1 : if( pShareFormats )
750 1 : pShareFormats->SetAttr( *pPrvBox, aTmp );
751 : else
752 0 : pPrvBox->ClaimFrameFormat()->SetFormatAttr( aTmp );
753 : }
754 : }
755 : }
756 : }
757 :
758 : // Delete the Box first, then the Nodes!
759 7 : SwStartNode* pSttNd = const_cast<SwStartNode*>(pBox->GetSttNd());
760 7 : if( pShareFormats )
761 7 : pShareFormats->RemoveFormat( *rTableBoxes[ nDelPos ]->GetFrameFormat() );
762 :
763 : // Before deleting the 'Table Box' from memory - delete any redlines attached to it
764 7 : if ( rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().HasExtraRedlineTable() )
765 7 : rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableCellRedline( rTable.GetFrameFormat()->GetDoc(), *(rTableBoxes[nDelPos]), true, USHRT_MAX );
766 7 : delete rTableBoxes[nDelPos];
767 7 : rTableBoxes.erase( rTableBoxes.begin() + nDelPos );
768 :
769 7 : if( pSttNd )
770 : {
771 : // Has the UndoObject been prepared to save the Section?
772 7 : if( pUndo && pUndo->IsDelBox() )
773 2 : static_cast<SwUndoTableNdsChg*>(pUndo)->SaveSection( pSttNd );
774 : else
775 5 : pSttNd->GetDoc()->getIDocumentContentOperations().DeleteSection( pSttNd );
776 : }
777 :
778 : // Also delete the Line?
779 7 : if( !rTableBoxes.empty() )
780 : {
781 : // Then adapt the Frame-SSize
782 5 : bool bLastBox = nDelPos == rTableBoxes.size();
783 5 : if( bLastBox )
784 4 : --nDelPos;
785 5 : pBox = rTableBoxes[nDelPos];
786 5 : if( bCalcNewSize )
787 : {
788 5 : SwFormatFrmSize aNew( pBox->GetFrameFormat()->GetFrmSize() );
789 5 : aNew.SetWidth( aNew.GetWidth() + nBoxSz );
790 5 : if( pShareFormats )
791 5 : pShareFormats->SetSize( *pBox, aNew );
792 : else
793 0 : pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
794 :
795 5 : if( !pBox->GetSttNd() )
796 : {
797 : // We need to this recursively in all Lines in all Cells!
798 0 : SwShareBoxFormats aShareFormats;
799 0 : ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
800 0 : !bLastBox,
801 : pShareFormats ? *pShareFormats
802 0 : : aShareFormats );
803 5 : }
804 : }
805 5 : break; // Stop deleting
806 : }
807 : // Delete the Line from the Table/Box
808 2 : if( !pUpperBox )
809 : {
810 : // Also delete the Line from the Table
811 2 : nDelPos = rTable.GetTabLines().GetPos( pLine );
812 2 : if( pShareFormats )
813 2 : pShareFormats->RemoveFormat( *rTable.GetTabLines()[ nDelPos ]->GetFrameFormat() );
814 :
815 2 : SwTableLine* pTabLineToDelete = rTable.GetTabLines()[ nDelPos ];
816 : // Before deleting the 'Table Line' from memory - delete any redlines attached to it
817 2 : if ( rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().HasExtraRedlineTable() )
818 2 : rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableRowRedline( rTable.GetFrameFormat()->GetDoc(), *pTabLineToDelete, true, USHRT_MAX );
819 2 : delete pTabLineToDelete;
820 2 : rTable.GetTabLines().erase( rTable.GetTabLines().begin() + nDelPos );
821 2 : break; // we cannot delete more
822 : }
823 :
824 : // finally also delete the Line
825 0 : pBox = pUpperBox;
826 0 : nDelPos = pBox->GetTabLines().GetPos( pLine );
827 0 : if( pShareFormats )
828 0 : pShareFormats->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrameFormat() );
829 :
830 0 : SwTableLine* pTabLineToDelete = pBox->GetTabLines()[ nDelPos ];
831 : // Before deleting the 'Table Line' from memory - delete any redlines attached to it
832 0 : if ( rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().HasExtraRedlineTable() )
833 0 : rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableRowRedline( rTable.GetFrameFormat()->GetDoc(), *pTabLineToDelete, true, USHRT_MAX );
834 0 : delete pTabLineToDelete;
835 0 : pBox->GetTabLines().erase( pBox->GetTabLines().begin() + nDelPos );
836 0 : } while( pBox->GetTabLines().empty() );
837 7 : }
838 :
839 : static SwTableBox*
840 6 : lcl_FndNxtPrvDelBox( const SwTableLines& rTableLns,
841 : SwTwips nBoxStt, SwTwips nBoxWidth,
842 : sal_uInt16 nLinePos, bool bNxt,
843 : SwSelBoxes* pAllDelBoxes, size_t *const pCurPos)
844 : {
845 6 : SwTableBox* pFndBox = 0;
846 5 : do {
847 6 : if( bNxt )
848 4 : ++nLinePos;
849 : else
850 2 : --nLinePos;
851 6 : SwTableLine* pLine = rTableLns[ nLinePos ];
852 6 : SwTwips nFndBoxWidth = 0;
853 6 : SwTwips nFndWidth = nBoxStt + nBoxWidth;
854 :
855 6 : pFndBox = pLine->GetTabBoxes()[ 0 ];
856 14 : for( auto pBox : pLine->GetTabBoxes() )
857 : {
858 12 : if ( nFndWidth <= 0 )
859 : {
860 4 : break;
861 : }
862 8 : pFndBox = pBox;
863 8 : nFndBoxWidth = pFndBox->GetFrameFormat()->GetFrmSize().GetWidth();
864 8 : nFndWidth -= nFndBoxWidth;
865 : }
866 :
867 : // Find the first ContentBox
868 12 : while( !pFndBox->GetSttNd() )
869 : {
870 0 : const SwTableLines& rLowLns = pFndBox->GetTabLines();
871 0 : if( bNxt )
872 0 : pFndBox = rLowLns.front()->GetTabBoxes().front();
873 : else
874 0 : pFndBox = rLowLns.back()->GetTabBoxes().front();
875 : }
876 :
877 12 : if( std::abs( nFndWidth ) > COLFUZZY ||
878 6 : std::abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
879 3 : pFndBox = 0;
880 3 : else if( pAllDelBoxes )
881 : {
882 : // If the predecessor will also be deleted, there's nothing to do
883 3 : SwSelBoxes::const_iterator aFndIt = pAllDelBoxes->find( pFndBox);
884 3 : if( aFndIt == pAllDelBoxes->end() )
885 3 : break;
886 0 : size_t const nFndPos = aFndIt - pAllDelBoxes->begin() ;
887 :
888 : // else, we keep on searching.
889 : // We do not need to recheck the Box, however
890 0 : pFndBox = 0;
891 0 : if( nFndPos <= *pCurPos )
892 0 : --*pCurPos;
893 0 : pAllDelBoxes->erase( pAllDelBoxes->begin() + nFndPos );
894 : }
895 2 : } while( bNxt ? ( nLinePos + 1 < (sal_uInt16)rTableLns.size() ) : nLinePos != 0 );
896 6 : return pFndBox;
897 : }
898 :
899 : static void
900 7 : lcl_SaveUpperLowerBorder( SwTable& rTable, const SwTableBox& rBox,
901 : SwShareBoxFormats& rShareFormats,
902 : SwSelBoxes* pAllDelBoxes = 0,
903 : size_t *const pCurPos = 0 )
904 : {
905 : //JP 16.04.97: 2. part for Bug 36271
906 7 : const SwTableLine* pLine = rBox.GetUpper();
907 7 : const SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
908 7 : const SwTableBox* pUpperBox = &rBox;
909 7 : sal_uInt16 nDelPos = rTableBoxes.GetPos( pUpperBox );
910 7 : pUpperBox = rBox.GetUpper()->GetUpper();
911 7 : const SvxBoxItem& rBoxItem = rBox.GetFrameFormat()->GetBox();
912 :
913 : // then the top/bottom edges
914 7 : if( rBoxItem.GetTop() || rBoxItem.GetBottom() )
915 : {
916 6 : bool bChgd = false;
917 : const SwTableLines* pTableLns;
918 6 : if( pUpperBox )
919 0 : pTableLns = &pUpperBox->GetTabLines();
920 : else
921 6 : pTableLns = &rTable.GetTabLines();
922 :
923 6 : sal_uInt16 nLnPos = pTableLns->GetPos( pLine );
924 :
925 : // Calculate the attribute position of the top-be-deleted Box and then
926 : // search in the top/bottom Line of the respective counterparts.
927 6 : SwTwips nBoxStt = 0;
928 10 : for( sal_uInt16 n = 0; n < nDelPos; ++n )
929 4 : nBoxStt += rTableBoxes[ n ]->GetFrameFormat()->GetFrmSize().GetWidth();
930 6 : SwTwips nBoxWidth = rBox.GetFrameFormat()->GetFrmSize().GetWidth();
931 :
932 6 : SwTableBox *pPrvBox = 0, *pNxtBox = 0;
933 6 : if( nLnPos ) // Predecessor?
934 : pPrvBox = ::lcl_FndNxtPrvDelBox( *pTableLns, nBoxStt, nBoxWidth,
935 2 : nLnPos, false, pAllDelBoxes, pCurPos );
936 :
937 6 : if( nLnPos + 1 < (sal_uInt16)pTableLns->size() ) // Successor?
938 : pNxtBox = ::lcl_FndNxtPrvDelBox( *pTableLns, nBoxStt, nBoxWidth,
939 4 : nLnPos, true, pAllDelBoxes, pCurPos );
940 :
941 6 : if( pNxtBox && pNxtBox->GetSttNd() )
942 : {
943 2 : const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrameFormat()->GetBox();
944 2 : if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
945 0 : !pPrvBox->GetFrameFormat()->GetBox().GetBottom()) )
946 : {
947 2 : SvxBoxItem aTmp( rNxtBoxItem );
948 2 : aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
949 : : rBoxItem.GetBottom(),
950 2 : SvxBoxItemLine::TOP );
951 2 : rShareFormats.SetAttr( *pNxtBox, aTmp );
952 2 : bChgd = true;
953 : }
954 : }
955 6 : if( !bChgd && pPrvBox && pPrvBox->GetSttNd() )
956 : {
957 1 : const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrameFormat()->GetBox();
958 1 : if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
959 0 : !pNxtBox->GetFrameFormat()->GetBox().GetTop()) )
960 : {
961 0 : SvxBoxItem aTmp( rPrvBoxItem );
962 0 : aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
963 : : rBoxItem.GetBottom(),
964 0 : SvxBoxItemLine::BOTTOM );
965 0 : rShareFormats.SetAttr( *pPrvBox, aTmp );
966 : }
967 : }
968 : }
969 7 : }
970 :
971 4 : bool SwTable::DeleteSel(
972 : SwDoc* pDoc
973 : ,
974 : const SwSelBoxes& rBoxes,
975 : const SwSelBoxes* pMerged, SwUndo* pUndo,
976 : const bool bDelMakeFrms, const bool bCorrBorder )
977 : {
978 : OSL_ENSURE( pDoc, "No doc?" );
979 4 : SwTableNode* pTableNd = 0;
980 4 : if( !rBoxes.empty() )
981 : {
982 4 : pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
983 4 : if( !pTableNd )
984 0 : return false;
985 : }
986 :
987 4 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
988 :
989 : // Find Lines for the Layout update
990 4 : _FndBox aFndBox( 0, 0 );
991 4 : if ( bDelMakeFrms )
992 : {
993 4 : if( pMerged && !pMerged->empty() )
994 3 : aFndBox.SetTableLines( *pMerged, *this );
995 1 : else if( !rBoxes.empty() )
996 1 : aFndBox.SetTableLines( rBoxes, *this );
997 4 : aFndBox.DelFrms( *this );
998 : }
999 :
1000 8 : SwShareBoxFormats aShareFormats;
1001 :
1002 : // First switch the Border, then delete
1003 4 : if( bCorrBorder )
1004 : {
1005 4 : SwSelBoxes aBoxes( rBoxes );
1006 11 : for (size_t n = 0; n < aBoxes.size(); ++n)
1007 : {
1008 7 : ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFormats,
1009 7 : &aBoxes, &n );
1010 4 : }
1011 : }
1012 :
1013 4 : PrepareDelBoxes( rBoxes );
1014 :
1015 4 : SwChartDataProvider *pPCD = pDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider();
1016 : // Delete boxes from last to first
1017 11 : for (size_t n = 0; n < rBoxes.size(); ++n)
1018 : {
1019 7 : size_t const nIdx = rBoxes.size() - 1 - n;
1020 :
1021 : // First adapt the data-sequence for chart if necessary
1022 : // (needed to move the implementation cursor properly to it's new
1023 : // position which can't be done properly if the cell is already gone)
1024 7 : if (pPCD && pTableNd)
1025 0 : pPCD->DeleteBox( &pTableNd->GetTable(), *rBoxes[nIdx] );
1026 :
1027 : // ... then delete the boxes
1028 7 : _DeleteBox( *this, rBoxes[nIdx], pUndo, true, bCorrBorder, &aShareFormats );
1029 : }
1030 :
1031 : // then clean up the structure of all Lines
1032 4 : GCLines();
1033 :
1034 4 : if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) )
1035 3 : aFndBox.MakeFrms( *this );
1036 :
1037 : // TL_CHART2: now inform chart that sth has changed
1038 4 : pDoc->UpdateCharts( GetFrameFormat()->GetName() );
1039 :
1040 : CHECKTABLELAYOUT;
1041 : CHECK_TABLE( *this );
1042 :
1043 8 : return true;
1044 : }
1045 :
1046 0 : bool SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
1047 : bool bSameHeight )
1048 : {
1049 : OSL_ENSURE( pDoc && !rBoxes.empty() && nCnt, "No valid values" );
1050 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1051 0 : if( !pTableNd )
1052 0 : return false;
1053 :
1054 : // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1055 : // the table too complex to be handled with chart.
1056 : // Thus we tell the charts to use their own data provider and forget about this table
1057 0 : pDoc->getIDocumentChartDataProviderAccess().CreateChartInternalDataProviders( this );
1058 :
1059 0 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
1060 :
1061 : // If the rows should get the same (min) height, we first have
1062 : // to store the old row heights before deleting the frames
1063 0 : long* pRowHeights = 0;
1064 0 : if ( bSameHeight )
1065 : {
1066 0 : pRowHeights = new long[ rBoxes.size() ];
1067 0 : for (size_t n = 0; n < rBoxes.size(); ++n)
1068 : {
1069 0 : SwTableBox* pSelBox = rBoxes[n];
1070 0 : const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() );
1071 : OSL_ENSURE( pRow, "Where is the SwTableLine's Frame?" );
1072 0 : SWRECTFN( pRow )
1073 0 : pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)();
1074 : }
1075 : }
1076 :
1077 : // Find Lines for the Layout update
1078 0 : _FndBox aFndBox( 0, 0 );
1079 0 : aFndBox.SetTableLines( rBoxes, *this );
1080 0 : aFndBox.DelFrms( *this );
1081 :
1082 0 : for (size_t n = 0; n < rBoxes.size(); ++n)
1083 : {
1084 0 : SwTableBox* pSelBox = rBoxes[n];
1085 : OSL_ENSURE( pSelBox, "Box is not within the Table" );
1086 :
1087 : // Insert nCnt new Lines into the Box
1088 0 : SwTableLine* pInsLine = pSelBox->GetUpper();
1089 0 : SwTableBoxFormat* pFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat());
1090 :
1091 : // Respect the Line's height, reset if needed
1092 0 : SwFormatFrmSize aFSz( pInsLine->GetFrameFormat()->GetFrmSize() );
1093 0 : if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() )
1094 0 : aFSz.SetHeightSizeType( ATT_MIN_SIZE );
1095 :
1096 0 : bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
1097 0 : if ( bChgLineSz )
1098 0 : aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
1099 0 : (nCnt + 1) );
1100 :
1101 0 : SwTableBox* pNewBox = new SwTableBox( pFrameFormat, nCnt, pInsLine );
1102 0 : sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().GetPos( pSelBox );
1103 0 : pInsLine->GetTabBoxes()[nBoxPos] = pNewBox; // overwrite old one
1104 :
1105 : // Delete background/border attribute
1106 0 : SwTableBox* pLastBox = pSelBox; // To distribute the TextNodes!
1107 : // If Areas are contained in the Box, it stays as is
1108 : // !! If this is changed we need to adapt the Undo, too !!!
1109 0 : bool bMoveNodes = true;
1110 : {
1111 0 : sal_uLong nSttNd = pLastBox->GetSttIdx() + 1,
1112 0 : nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
1113 0 : while( nSttNd < nEndNd )
1114 0 : if( !pDoc->GetNodes()[ nSttNd++ ]->IsTextNode() )
1115 : {
1116 0 : bMoveNodes = false;
1117 0 : break;
1118 : }
1119 : }
1120 :
1121 0 : SwTableBoxFormat* pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat());
1122 0 : bool bChkBorder = 0 != pCpyBoxFrameFormat->GetBox().GetTop();
1123 0 : if( bChkBorder )
1124 0 : pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->ClaimFrameFormat());
1125 :
1126 0 : for( sal_uInt16 i = 0; i <= nCnt; ++i )
1127 : {
1128 : // Create a new Line in the new Box
1129 : SwTableLine* pNewLine = new SwTableLine(
1130 0 : static_cast<SwTableLineFormat*>(pInsLine->GetFrameFormat()), 1, pNewBox );
1131 0 : if( bChgLineSz )
1132 : {
1133 0 : pNewLine->ClaimFrameFormat()->SetFormatAttr( aFSz );
1134 : }
1135 :
1136 0 : pNewBox->GetTabLines().insert( pNewBox->GetTabLines().begin() + i, pNewLine );
1137 : // then a new Box in the Line
1138 0 : if( !i ) // hang up the original Box
1139 : {
1140 0 : pSelBox->SetUpper( pNewLine );
1141 0 : pNewLine->GetTabBoxes().insert( pNewLine->GetTabBoxes().begin(), pSelBox );
1142 : }
1143 : else
1144 : {
1145 : ::_InsTableBox( pDoc, pTableNd, pNewLine, pCpyBoxFrameFormat,
1146 0 : pLastBox, 0 );
1147 :
1148 0 : if( bChkBorder )
1149 : {
1150 0 : pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pNewLine->GetTabBoxes()[ 0 ]->ClaimFrameFormat());
1151 0 : SvxBoxItem aTmp( pCpyBoxFrameFormat->GetBox() );
1152 0 : aTmp.SetLine( 0, SvxBoxItemLine::TOP );
1153 0 : pCpyBoxFrameFormat->SetFormatAttr( aTmp );
1154 0 : bChkBorder = false;
1155 : }
1156 :
1157 0 : if( bMoveNodes )
1158 : {
1159 0 : const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
1160 0 : if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() )
1161 : {
1162 : // Move TextNodes
1163 0 : SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd );
1164 0 : pLastBox = pNewLine->GetTabBoxes()[0]; // reset
1165 0 : SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
1166 0 : pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, false);
1167 0 : pDoc->GetNodes().Delete( aInsPos, 1 ); // delete the empty one
1168 : }
1169 : }
1170 : }
1171 : }
1172 : // In Boxes with Lines, we can only have Size/Fillorder
1173 0 : pFrameFormat = static_cast<SwTableBoxFormat*>(pNewBox->ClaimFrameFormat());
1174 0 : pFrameFormat->ResetFormatAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1175 0 : pFrameFormat->ResetFormatAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
1176 0 : }
1177 :
1178 0 : delete[] pRowHeights;
1179 :
1180 0 : GCLines();
1181 :
1182 0 : aFndBox.MakeFrms( *this );
1183 :
1184 : CHECKBOXWIDTH
1185 : CHECKTABLELAYOUT
1186 0 : return true;
1187 : }
1188 :
1189 1 : bool SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
1190 : {
1191 : OSL_ENSURE( pDoc && !rBoxes.empty() && nCnt, "No valid values" );
1192 1 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1193 1 : if( !pTableNd )
1194 0 : return false;
1195 :
1196 : // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1197 : // the table too complex to be handled with chart.
1198 : // Thus we tell the charts to use their own data provider and forget about this table
1199 1 : pDoc->getIDocumentChartDataProviderAccess().CreateChartInternalDataProviders( this );
1200 :
1201 1 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
1202 1 : SwSelBoxes aSelBoxes(rBoxes);
1203 1 : ExpandSelection( aSelBoxes );
1204 :
1205 : // Find Lines for the Layout update
1206 2 : _FndBox aFndBox( 0, 0 );
1207 1 : aFndBox.SetTableLines( aSelBoxes, *this );
1208 1 : aFndBox.DelFrms( *this );
1209 :
1210 2 : _CpyTabFrms aFrmArr;
1211 2 : std::vector<SwTableBoxFormat*> aLastBoxArr;
1212 3 : for (size_t n = 0; n < aSelBoxes.size(); ++n)
1213 : {
1214 2 : SwTableBox* pSelBox = aSelBoxes[n];
1215 : OSL_ENSURE( pSelBox, "Box is not in the table" );
1216 :
1217 : // We don't want to split small table cells into very very small cells
1218 2 : if( pSelBox->GetFrameFormat()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 )
1219 0 : continue;
1220 :
1221 : // Then split the nCnt Box up into nCnt Boxes
1222 2 : SwTableLine* pInsLine = pSelBox->GetUpper();
1223 2 : sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().GetPos( pSelBox );
1224 :
1225 : // Find the Frame Format in the Frame Format Array
1226 : SwTableBoxFormat* pLastBoxFormat;
1227 2 : _CpyTabFrm aFindFrm( static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat()) );
1228 2 : _CpyTabFrms::const_iterator itFind = aFrmArr.lower_bound( aFindFrm );
1229 2 : const size_t nFndPos = itFind - aFrmArr.begin();
1230 2 : if( itFind == aFrmArr.end() || !(*itFind == aFindFrm) )
1231 : {
1232 : // Change the FrameFormat
1233 2 : aFindFrm.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->ClaimFrameFormat());
1234 2 : SwTwips nBoxSz = aFindFrm.pNewFrameFormat->GetFrmSize().GetWidth();
1235 2 : SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
1236 : aFindFrm.pNewFrameFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE,
1237 2 : nNewBoxSz, 0 ) );
1238 2 : aFrmArr.insert( aFindFrm );
1239 :
1240 2 : pLastBoxFormat = aFindFrm.pNewFrameFormat;
1241 2 : if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
1242 : {
1243 : // We have a remainder, so we need to define an own Format
1244 : // for the last Box.
1245 0 : pLastBoxFormat = new SwTableBoxFormat( *aFindFrm.pNewFrameFormat );
1246 : pLastBoxFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE,
1247 0 : nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
1248 : }
1249 2 : aLastBoxArr.insert( aLastBoxArr.begin() + nFndPos, pLastBoxFormat );
1250 : }
1251 : else
1252 : {
1253 0 : aFindFrm = aFrmArr[ nFndPos ];
1254 0 : pSelBox->ChgFrameFormat( aFindFrm.pNewFrameFormat );
1255 0 : pLastBoxFormat = aLastBoxArr[ nFndPos ];
1256 : }
1257 :
1258 : // Insert the Boxes at the Position
1259 2 : for( sal_uInt16 i = 1; i < nCnt; ++i )
1260 : ::_InsTableBox( pDoc, pTableNd, pInsLine, aFindFrm.pNewFrameFormat,
1261 0 : pSelBox, nBoxPos + i ); // insert after
1262 :
1263 : ::_InsTableBox( pDoc, pTableNd, pInsLine, pLastBoxFormat,
1264 2 : pSelBox, nBoxPos + nCnt ); // insert after
1265 :
1266 : // Special treatment for the Border:
1267 2 : const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrameFormat->GetBox();
1268 2 : if( aSelBoxItem.GetRight() )
1269 : {
1270 2 : pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrameFormat();
1271 :
1272 2 : SvxBoxItem aTmp( aSelBoxItem );
1273 2 : aTmp.SetLine( 0, SvxBoxItemLine::RIGHT );
1274 2 : aFindFrm.pNewFrameFormat->SetFormatAttr( aTmp );
1275 :
1276 : // Remove the Format from the "cache"
1277 6 : for( auto i = aFrmArr.size(); i; )
1278 : {
1279 2 : const _CpyTabFrm& rCTF = aFrmArr[ --i ];
1280 2 : if( rCTF.pNewFrameFormat == aFindFrm.pNewFrameFormat ||
1281 0 : rCTF.Value.pFrameFormat == aFindFrm.pNewFrameFormat )
1282 : {
1283 2 : aFrmArr.erase( aFrmArr.begin() + i );
1284 2 : aLastBoxArr.erase( aLastBoxArr.begin() + i );
1285 : }
1286 2 : }
1287 : }
1288 : }
1289 :
1290 : // Update Layout
1291 1 : aFndBox.MakeFrms( *this );
1292 :
1293 : CHECKBOXWIDTH
1294 : CHECKTABLELAYOUT
1295 2 : return true;
1296 : }
1297 :
1298 : /*
1299 : * >> MERGE <<
1300 : * Algorithm:
1301 : * If we only have one Line in the _FndBox, take this Line and test
1302 : * the Box count:
1303 : * If we have more than one Box, we merge on Box level, meaning
1304 : * the new Box will be as wide as the old ones.
1305 : * All Lines that are above/under the Area, are inserted into
1306 : * the Box as Line + Box.
1307 : * All Lines that come before/after the Area, are inserted into
1308 : * the Boxes Left/Right.
1309 : *
1310 : * >> MERGE <<
1311 : */
1312 0 : static void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd,
1313 : SwTableLines& rLines,
1314 : SwTableBox* pInsBox,
1315 : sal_uInt16 nPos = USHRT_MAX )
1316 : {
1317 0 : for( sal_uInt16 n = nStt; n < nEnd; ++n )
1318 0 : rLines[n]->SetUpper( pInsBox );
1319 0 : if( USHRT_MAX == nPos )
1320 0 : nPos = pInsBox->GetTabLines().size();
1321 0 : pInsBox->GetTabLines().insert( pInsBox->GetTabLines().begin() + nPos,
1322 0 : rLines.begin() + nStt, rLines.begin() + nEnd );
1323 0 : rLines.erase( rLines.begin() + nStt, rLines.begin() + nEnd );
1324 0 : }
1325 :
1326 0 : static void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd,
1327 : SwTableBoxes& rBoxes,
1328 : SwTableLine* pInsLine,
1329 : sal_uInt16 nPos = USHRT_MAX )
1330 : {
1331 0 : for( sal_uInt16 n = nStt; n < nEnd; ++n )
1332 0 : rBoxes[n]->SetUpper( pInsLine );
1333 0 : if( USHRT_MAX == nPos )
1334 0 : nPos = pInsLine->GetTabBoxes().size();
1335 0 : pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + nPos,
1336 0 : rBoxes.begin() + nStt, rBoxes.begin() + nEnd );
1337 0 : rBoxes.erase( rBoxes.begin() + nStt, rBoxes.begin() + nEnd );
1338 0 : }
1339 :
1340 0 : static void lcl_CalcWidth( SwTableBox* pBox )
1341 : {
1342 : // Assertion: Every Line in the Box is as large
1343 0 : SwFrameFormat* pFormat = pBox->ClaimFrameFormat();
1344 : OSL_ENSURE( pBox->GetTabLines().size(), "Box does not have any Lines" );
1345 :
1346 0 : SwTableLine* pLine = pBox->GetTabLines()[0];
1347 : OSL_ENSURE( pLine, "Box is not within a Line" );
1348 :
1349 0 : long nWidth = 0;
1350 0 : for( auto pTabBox : pLine->GetTabBoxes() )
1351 0 : nWidth += pTabBox->GetFrameFormat()->GetFrmSize().GetWidth();
1352 :
1353 0 : pFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
1354 :
1355 : // Boxes with Lines can only have Size/Fillorder
1356 0 : pFormat->ResetFormatAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1357 0 : pFormat->ResetFormatAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
1358 0 : }
1359 :
1360 : struct _InsULPara
1361 : {
1362 : SwTableNode* pTableNd;
1363 : SwTableLine* pInsLine;
1364 : SwTableBox* pInsBox;
1365 : bool bUL_LR : 1; // Upper-Lower(true) or Left-Right(false) ?
1366 : bool bUL : 1; // Upper-Left(true) or Lower-Right(false) ?
1367 :
1368 : SwTableBox* pLeftBox;
1369 : SwTableBox* pRightBox;
1370 : SwTableBox* pMergeBox;
1371 :
1372 0 : _InsULPara( SwTableNode* pTNd, bool bUpperLower, bool bUpper,
1373 : SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight,
1374 : SwTableLine* pLine=0, SwTableBox* pBox=0 )
1375 : : pTableNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ),
1376 0 : pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge )
1377 0 : { bUL_LR = bUpperLower; bUL = bUpper; }
1378 :
1379 0 : void SetLeft( SwTableBox* pBox=0 )
1380 0 : { bUL_LR = false; bUL = true; if( pBox ) pInsBox = pBox; }
1381 0 : void SetRight( SwTableBox* pBox=0 )
1382 0 : { bUL_LR = false; bUL = false; if( pBox ) pInsBox = pBox; }
1383 0 : void SetLower( SwTableLine* pLine=0 )
1384 0 : { bUL_LR = true; bUL = false; if( pLine ) pInsLine = pLine; }
1385 : };
1386 :
1387 : static void lcl_Merge_MoveLine(_FndLine & rFndLine, _InsULPara *const pULPara);
1388 :
1389 0 : static void lcl_Merge_MoveBox(_FndBox & rFndBox, _InsULPara *const pULPara)
1390 : {
1391 : SwTableBoxes* pBoxes;
1392 :
1393 0 : sal_uInt16 nStt = 0, nEnd = rFndBox.GetLines().size();
1394 0 : sal_uInt16 nInsPos = USHRT_MAX;
1395 0 : if( !pULPara->bUL_LR ) // Left/Right
1396 : {
1397 : sal_uInt16 nPos;
1398 0 : SwTableBox* pFndTableBox = rFndBox.GetBox();
1399 0 : pBoxes = &pFndTableBox->GetUpper()->GetTabBoxes();
1400 0 : if( pULPara->bUL ) // Left ?
1401 : {
1402 : // if there are Boxes before it, move them
1403 0 : if( 0 != ( nPos = pBoxes->GetPos( pFndTableBox ) ) )
1404 0 : lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
1405 : }
1406 : else // Right
1407 : // if there are Boxes behind it, move them
1408 0 : if( (nPos = pBoxes->GetPos( pFndTableBox )) +1 < (sal_uInt16)pBoxes->size() )
1409 : {
1410 0 : nInsPos = pULPara->pInsLine->GetTabBoxes().size();
1411 0 : lcl_CpyBoxes( nPos+1, pBoxes->size(),
1412 0 : *pBoxes, pULPara->pInsLine );
1413 : }
1414 : }
1415 : // Upper/Lower and still deeper?
1416 0 : else if (!rFndBox.GetLines().empty())
1417 : {
1418 : // Only search the Line from which we need to move
1419 0 : nStt = pULPara->bUL ? 0 : rFndBox.GetLines().size()-1;
1420 0 : nEnd = nStt+1;
1421 : }
1422 :
1423 0 : pBoxes = &pULPara->pInsLine->GetTabBoxes();
1424 :
1425 : // Is there still a level to step down to?
1426 0 : if (rFndBox.GetBox()->GetTabLines().size())
1427 : {
1428 : SwTableBox* pBox = new SwTableBox(
1429 0 : static_cast<SwTableBoxFormat*>(rFndBox.GetBox()->GetFrameFormat()),
1430 0 : 0, pULPara->pInsLine );
1431 0 : _InsULPara aPara( *pULPara );
1432 0 : aPara.pInsBox = pBox;
1433 0 : for (_FndLines::iterator it = rFndBox.GetLines().begin() + nStt;
1434 0 : it != rFndBox.GetLines().begin() + nEnd; ++it )
1435 : {
1436 0 : lcl_Merge_MoveLine(*it, &aPara );
1437 : }
1438 0 : if( pBox->GetTabLines().size() )
1439 : {
1440 0 : if( USHRT_MAX == nInsPos )
1441 0 : nInsPos = pBoxes->size();
1442 0 : pBoxes->insert( pBoxes->begin() + nInsPos, pBox );
1443 0 : lcl_CalcWidth( pBox ); // calculate the Box's width
1444 : }
1445 : else
1446 0 : delete pBox;
1447 : }
1448 0 : }
1449 :
1450 0 : static void lcl_Merge_MoveLine(_FndLine& rFndLine, _InsULPara *const pULPara)
1451 : {
1452 : SwTableLines* pLines;
1453 :
1454 0 : sal_uInt16 nStt = 0, nEnd = rFndLine.GetBoxes().size();
1455 0 : sal_uInt16 nInsPos = USHRT_MAX;
1456 0 : if( pULPara->bUL_LR ) // UpperLower ?
1457 : {
1458 : sal_uInt16 nPos;
1459 0 : SwTableLine* pFndLn = rFndLine.GetLine();
1460 0 : pLines = pFndLn->GetUpper() ?
1461 0 : &pFndLn->GetUpper()->GetTabLines() :
1462 0 : &pULPara->pTableNd->GetTable().GetTabLines();
1463 :
1464 0 : SwTableBox* pLBx = rFndLine.GetBoxes().front().GetBox();
1465 0 : SwTableBox* pRBx = rFndLine.GetBoxes().back().GetBox();
1466 0 : sal_uInt16 nLeft = pFndLn->GetTabBoxes().GetPos( pLBx );
1467 0 : sal_uInt16 nRight = pFndLn->GetTabBoxes().GetPos( pRBx );
1468 :
1469 0 : if( !nLeft || nRight == pFndLn->GetTabBoxes().size() )
1470 : {
1471 0 : if( pULPara->bUL ) // Upper ?
1472 : {
1473 : // If there are Lines before it, move them
1474 0 : if( 0 != ( nPos = pLines->GetPos( pFndLn )) )
1475 0 : lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
1476 : }
1477 : else
1478 : // If there are Lines after it, move them
1479 0 : if( (nPos = pLines->GetPos( pFndLn )) + 1 < (sal_uInt16)pLines->size() )
1480 : {
1481 0 : nInsPos = pULPara->pInsBox->GetTabLines().size();
1482 0 : lcl_CpyLines( nPos+1, pLines->size(), *pLines,
1483 0 : pULPara->pInsBox );
1484 : }
1485 : }
1486 : else
1487 : {
1488 : // There are still Boxes on the left side, so put the Left-
1489 : // and Merge-Box into one Box and Line, insert before/after
1490 : // a Line with a Box, into which the upper/lower Lines are
1491 : // inserted
1492 0 : SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
1493 : SwTableBox* pLMBox = new SwTableBox(
1494 0 : static_cast<SwTableBoxFormat*>(pULPara->pLeftBox->GetFrameFormat()), 0, pInsLine );
1495 : SwTableLine* pLMLn = new SwTableLine(
1496 0 : static_cast<SwTableLineFormat*>(pInsLine->GetFrameFormat()), 2, pLMBox );
1497 0 : pLMLn->ClaimFrameFormat()->ResetFormatAttr( RES_FRM_SIZE );
1498 :
1499 0 : pLMBox->GetTabLines().insert( pLMBox->GetTabLines().begin(), pLMLn );
1500 :
1501 0 : lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
1502 :
1503 0 : pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin(), pLMBox );
1504 :
1505 0 : if( pULPara->bUL ) // Upper ?
1506 : {
1507 : // If there are Lines before it, move them
1508 0 : if( 0 != ( nPos = pLines->GetPos( pFndLn )) )
1509 0 : lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
1510 : }
1511 : else
1512 : // If there are Lines after it, move them
1513 0 : if( (nPos = pLines->GetPos( pFndLn )) + 1 < (sal_uInt16)pLines->size() )
1514 0 : lcl_CpyLines( nPos+1, pLines->size(), *pLines,
1515 0 : pLMBox );
1516 0 : lcl_CalcWidth( pLMBox ); // calculate the Box's width
1517 : }
1518 : }
1519 : // Left/Right
1520 : else
1521 : {
1522 : // Find only the Line from which we need to move
1523 0 : nStt = pULPara->bUL ? 0 : rFndLine.GetBoxes().size()-1;
1524 0 : nEnd = nStt+1;
1525 : }
1526 0 : pLines = &pULPara->pInsBox->GetTabLines();
1527 :
1528 : SwTableLine* pNewLine = new SwTableLine(
1529 0 : static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()), 0, pULPara->pInsBox );
1530 0 : _InsULPara aPara( *pULPara ); // copying
1531 0 : aPara.pInsLine = pNewLine;
1532 0 : _FndBoxes & rLineBoxes = rFndLine.GetBoxes();
1533 0 : for (_FndBoxes::iterator it = rLineBoxes.begin() + nStt;
1534 0 : it != rLineBoxes.begin() + nEnd; ++it)
1535 : {
1536 0 : lcl_Merge_MoveBox(*it, &aPara);
1537 : }
1538 :
1539 0 : if( !pNewLine->GetTabBoxes().empty() )
1540 : {
1541 0 : if( USHRT_MAX == nInsPos )
1542 0 : nInsPos = pLines->size();
1543 0 : pLines->insert( pLines->begin() + nInsPos, pNewLine );
1544 : }
1545 : else
1546 0 : delete pNewLine;
1547 0 : }
1548 :
1549 : static void lcl_BoxSetHeadCondColl( const SwTableBox* pBox );
1550 :
1551 0 : bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
1552 : SwTableBox* pMergeBox, SwUndoTableMerge* pUndo )
1553 : {
1554 : OSL_ENSURE( !rBoxes.empty() && pMergeBox, "no valid values" );
1555 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1556 0 : if( !pTableNd )
1557 0 : return false;
1558 :
1559 : // Find all Boxes/Lines
1560 0 : _FndBox aFndBox( 0, 0 );
1561 : {
1562 0 : _FndPara aPara( rBoxes, &aFndBox );
1563 0 : ForEach_FndLineCopyCol( GetTabLines(), &aPara );
1564 : }
1565 0 : if( aFndBox.GetLines().empty() )
1566 0 : return false;
1567 :
1568 : // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1569 : // the table too complex to be handled with chart.
1570 : // Thus we tell the charts to use their own data provider and forget about this table
1571 0 : pDoc->getIDocumentChartDataProviderAccess().CreateChartInternalDataProviders( this );
1572 :
1573 0 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
1574 :
1575 0 : if( pUndo )
1576 0 : pUndo->SetSelBoxes( rBoxes );
1577 :
1578 : // Find Lines for the Layout update
1579 0 : aFndBox.SetTableLines( *this );
1580 0 : aFndBox.DelFrms( *this );
1581 :
1582 0 : _FndBox* pFndBox = &aFndBox;
1583 0 : while( 1 == pFndBox->GetLines().size() &&
1584 0 : 1 == pFndBox->GetLines().front().GetBoxes().size() )
1585 : {
1586 0 : pFndBox = &pFndBox->GetLines().front().GetBoxes().front();
1587 : }
1588 :
1589 : SwTableLine* pInsLine = new SwTableLine(
1590 0 : static_cast<SwTableLineFormat*>(pFndBox->GetLines().front().GetLine()->GetFrameFormat()), 0,
1591 0 : !pFndBox->GetUpper() ? 0 : pFndBox->GetBox() );
1592 0 : pInsLine->ClaimFrameFormat()->ResetFormatAttr( RES_FRM_SIZE );
1593 :
1594 : // Add the new Line
1595 0 : SwTableLines* pLines = pFndBox->GetUpper() ?
1596 0 : &pFndBox->GetBox()->GetTabLines() : &GetTabLines();
1597 :
1598 0 : SwTableLine* pNewLine = pFndBox->GetLines().front().GetLine();
1599 0 : sal_uInt16 nInsPos = pLines->GetPos( pNewLine );
1600 0 : pLines->insert( pLines->begin() + nInsPos, pInsLine );
1601 :
1602 0 : SwTableBox* pLeftBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pMergeBox->GetFrameFormat()), 0, pInsLine );
1603 0 : SwTableBox* pRightBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pMergeBox->GetFrameFormat()), 0, pInsLine );
1604 0 : pMergeBox->SetUpper( pInsLine );
1605 0 : pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin(), pLeftBox );
1606 0 : pLeftBox->ClaimFrameFormat();
1607 0 : pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + 1, pMergeBox);
1608 0 : pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + 2, pRightBox );
1609 0 : pRightBox->ClaimFrameFormat();
1610 :
1611 : // This contains all Lines that are above the selected Area,
1612 : // thus they form a Upper/Lower Line
1613 0 : _InsULPara aPara( pTableNd, true, true, pLeftBox, pMergeBox, pRightBox, pInsLine );
1614 :
1615 : // Move the overlapping upper/lower Lines of the selected Area
1616 0 : _FndBoxes& rLineBoxes = pFndBox->GetLines().front().GetBoxes();
1617 0 : for (_FndBoxes::iterator it = rLineBoxes.begin(); it != rLineBoxes.end(); ++it)
1618 : {
1619 0 : lcl_Merge_MoveBox(*it, &aPara);
1620 : }
1621 0 : aPara.SetLower( pInsLine );
1622 0 : const auto nEnd = pFndBox->GetLines().size()-1;
1623 0 : rLineBoxes = pFndBox->GetLines()[nEnd].GetBoxes();
1624 0 : for (_FndBoxes::iterator it = rLineBoxes.begin(); it != rLineBoxes.end(); ++it)
1625 : {
1626 0 : lcl_Merge_MoveBox(*it, &aPara);
1627 : }
1628 :
1629 : // Move the Boxes extending into the selected Area from left/right
1630 0 : aPara.SetLeft( pLeftBox );
1631 0 : for (_FndLine& rFndLine : pFndBox->GetLines() )
1632 0 : lcl_Merge_MoveLine( rFndLine, &aPara );
1633 :
1634 0 : aPara.SetRight( pRightBox );
1635 0 : for(_FndLine& rFndLine : pFndBox->GetLines() )
1636 0 : lcl_Merge_MoveLine( rFndLine, &aPara );
1637 :
1638 0 : if( pLeftBox->GetTabLines().empty() )
1639 0 : _DeleteBox( *this, pLeftBox, 0, false, false );
1640 : else
1641 : {
1642 0 : lcl_CalcWidth( pLeftBox ); // calculate the Box's width
1643 0 : if( pUndo && pLeftBox->GetSttNd() )
1644 0 : pUndo->AddNewBox( pLeftBox->GetSttIdx() );
1645 : }
1646 0 : if( pRightBox->GetTabLines().empty() )
1647 0 : _DeleteBox( *this, pRightBox, 0, false, false );
1648 : else
1649 : {
1650 0 : lcl_CalcWidth( pRightBox ); // calculate the Box's width
1651 0 : if( pUndo && pRightBox->GetSttNd() )
1652 0 : pUndo->AddNewBox( pRightBox->GetSttIdx() );
1653 : }
1654 :
1655 0 : DeleteSel( pDoc, rBoxes, 0, 0, false, false );
1656 :
1657 : // Clean up this Line's structure once again, generally all of them
1658 0 : GCLines();
1659 :
1660 0 : for( SwTableBoxes::iterator it = GetTabLines()[0]->GetTabBoxes().begin();
1661 0 : it != GetTabLines()[0]->GetTabBoxes().end(); ++it)
1662 0 : lcl_BoxSetHeadCondColl(*it);
1663 :
1664 0 : aFndBox.MakeFrms( *this );
1665 :
1666 : CHECKBOXWIDTH
1667 : CHECKTABLELAYOUT
1668 :
1669 0 : return true;
1670 : }
1671 :
1672 0 : static void lcl_CheckRowSpan( SwTable &rTable )
1673 : {
1674 0 : const long nLineCount = static_cast<long>(rTable.GetTabLines().size());
1675 0 : long nMaxSpan = nLineCount;
1676 0 : long nMinSpan = 1;
1677 0 : while( nMaxSpan )
1678 : {
1679 0 : SwTableLine* pLine = rTable.GetTabLines()[ nLineCount - nMaxSpan ];
1680 0 : for( auto pBox : pLine->GetTabBoxes() )
1681 : {
1682 0 : long nRowSpan = pBox->getRowSpan();
1683 0 : if( nRowSpan > nMaxSpan )
1684 0 : pBox->setRowSpan( nMaxSpan );
1685 0 : else if( nRowSpan < nMinSpan )
1686 0 : pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
1687 : }
1688 0 : --nMaxSpan;
1689 0 : nMinSpan = -nMaxSpan;
1690 : }
1691 0 : }
1692 :
1693 0 : static sal_uInt16 lcl_GetBoxOffset( const _FndBox& rBox )
1694 : {
1695 : // Find the first Box
1696 0 : const _FndBox* pFirstBox = &rBox;
1697 0 : while( !pFirstBox->GetLines().empty() )
1698 0 : pFirstBox = &pFirstBox->GetLines().front().GetBoxes().front();
1699 :
1700 0 : sal_uInt16 nRet = 0;
1701 : // Calculate the position relative to above via the Lines
1702 0 : const SwTableBox* pBox = pFirstBox->GetBox();
1703 0 : do {
1704 0 : const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
1705 0 : for( auto pCmp : rBoxes )
1706 : {
1707 0 : if (pBox==pCmp)
1708 0 : break;
1709 0 : nRet = nRet + (sal_uInt16) pCmp->GetFrameFormat()->GetFrmSize().GetWidth();
1710 : }
1711 0 : pBox = pBox->GetUpper()->GetUpper();
1712 : } while( pBox );
1713 0 : return nRet;
1714 : }
1715 :
1716 0 : static sal_uInt16 lcl_GetLineWidth( const _FndLine& rLine )
1717 : {
1718 0 : sal_uInt16 nRet = 0;
1719 0 : for( auto n = rLine.GetBoxes().size(); n; )
1720 : {
1721 0 : nRet = nRet + static_cast<sal_uInt16>(rLine.GetBoxes()[--n].GetBox()
1722 0 : ->GetFrameFormat()->GetFrmSize().GetWidth());
1723 : }
1724 0 : return nRet;
1725 : }
1726 :
1727 0 : static void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara )
1728 : {
1729 0 : rPara.pWidths.reset();
1730 0 : const size_t nLineCount = rFndLines.size();
1731 0 : if( nLineCount )
1732 : {
1733 0 : rPara.pWidths = boost::shared_ptr< std::vector< std::vector< sal_uLong > > >
1734 0 : ( new std::vector< std::vector< sal_uLong > >( nLineCount ));
1735 : // First we collect information about the left/right borders of all
1736 : // selected cells
1737 0 : for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1738 : {
1739 0 : std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
1740 0 : const _FndLine *pFndLine = &rFndLines[ nLine ];
1741 0 : if( pFndLine && pFndLine->GetBoxes().size() )
1742 : {
1743 0 : const SwTableLine *pLine = pFndLine->GetLine();
1744 0 : if( pLine && !pLine->GetTabBoxes().empty() )
1745 : {
1746 0 : size_t nBoxCount = pLine->GetTabBoxes().size();
1747 0 : sal_uLong nPos = 0;
1748 : // The first selected box...
1749 : const SwTableBox *const pSel =
1750 0 : pFndLine->GetBoxes().front().GetBox();
1751 0 : size_t nBox = 0;
1752 : // Sum up the width of all boxes before the first selected box
1753 0 : while( nBox < nBoxCount )
1754 : {
1755 0 : SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
1756 0 : if( pBox != pSel )
1757 0 : nPos += pBox->GetFrameFormat()->GetFrmSize().GetWidth();
1758 : else
1759 0 : break;
1760 : }
1761 : // nPos is now the left border of the first selected box
1762 0 : if( rPara.nMinLeft > nPos )
1763 0 : rPara.nMinLeft = nPos;
1764 0 : nBoxCount = pFndLine->GetBoxes().size();
1765 0 : rWidth = std::vector< sal_uLong >( nBoxCount+2 );
1766 0 : rWidth[ 0 ] = nPos;
1767 : // Add now the widths of all selected boxes and store
1768 : // the positions in the vector
1769 0 : for( nBox = 0; nBox < nBoxCount; )
1770 : {
1771 0 : nPos += pFndLine->GetBoxes()[nBox]
1772 0 : .GetBox()->GetFrameFormat()->GetFrmSize().GetWidth();
1773 0 : rWidth[ ++nBox ] = nPos;
1774 : }
1775 : // nPos: The right border of the last selected box
1776 0 : if( rPara.nMaxRight < nPos )
1777 0 : rPara.nMaxRight = nPos;
1778 0 : if( nPos <= rWidth[ 0 ] )
1779 0 : rWidth.clear();
1780 : }
1781 : }
1782 : }
1783 : }
1784 : // Second step: calculate the new widths for the copied cells
1785 0 : sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft;
1786 0 : if( nSelSize )
1787 : {
1788 0 : for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1789 : {
1790 0 : std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
1791 0 : const size_t nCount = rWidth.size();
1792 0 : if( nCount > 2 )
1793 : {
1794 0 : rWidth[ nCount - 1 ] = rPara.nMaxRight;
1795 0 : sal_uLong nLastPos = 0;
1796 0 : for( size_t nBox = 0; nBox < nCount; ++nBox )
1797 : {
1798 0 : sal_uInt64 nNextPos = rWidth[ nBox ];
1799 0 : nNextPos -= rPara.nMinLeft;
1800 0 : nNextPos *= rPara.nNewSize;
1801 0 : nNextPos /= nSelSize;
1802 0 : rWidth[ nBox ] = (sal_uLong)(nNextPos - nLastPos);
1803 0 : nLastPos = (sal_uLong)nNextPos;
1804 : }
1805 : }
1806 : }
1807 : }
1808 0 : }
1809 :
1810 : static void
1811 : lcl_CopyLineToDoc(_FndLine const& rpFndLn, _CpyPara *const pCpyPara);
1812 :
1813 0 : static void lcl_CopyBoxToDoc(_FndBox const& rFndBox, _CpyPara *const pCpyPara)
1814 : {
1815 : // Calculation of new size
1816 : sal_uLong nRealSize;
1817 0 : sal_uLong nDummy1 = 0;
1818 0 : sal_uLong nDummy2 = 0;
1819 0 : if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1820 : {
1821 0 : if( pCpyPara->nBoxIdx == 1 )
1822 0 : nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0];
1823 0 : nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
1824 0 : if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 )
1825 0 : nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
1826 : }
1827 : else
1828 : {
1829 0 : nRealSize = pCpyPara->nNewSize;
1830 0 : nRealSize *= rFndBox.GetBox()->GetFrameFormat()->GetFrmSize().GetWidth();
1831 0 : if (pCpyPara->nOldSize == 0)
1832 0 : throw o3tl::divide_by_zero();
1833 0 : nRealSize /= pCpyPara->nOldSize;
1834 : }
1835 :
1836 : sal_uLong nSize;
1837 0 : bool bDummy = nDummy1 > 0;
1838 0 : if( bDummy )
1839 0 : nSize = nDummy1;
1840 : else
1841 : {
1842 0 : nSize = nRealSize;
1843 0 : nRealSize = 0;
1844 : }
1845 0 : do
1846 : {
1847 : // Find the Frame Format in the list of all Frame Formats
1848 0 : _CpyTabFrm aFindFrm(static_cast<SwTableBoxFormat*>(rFndBox.GetBox()->GetFrameFormat()));
1849 :
1850 0 : SwFormatFrmSize aFrmSz;
1851 0 : _CpyTabFrms::const_iterator itFind = pCpyPara->rTabFrmArr.lower_bound( aFindFrm );
1852 0 : const _CpyTabFrms::size_type nFndPos = itFind - pCpyPara->rTabFrmArr.begin();
1853 0 : if( itFind == pCpyPara->rTabFrmArr.end() || !(*itFind == aFindFrm) ||
1854 0 : ( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrameFormat->
1855 0 : GetFrmSize()).GetWidth() != (SwTwips)nSize )
1856 : {
1857 : // It doesn't exist yet, so copy it
1858 0 : aFindFrm.pNewFrameFormat = pCpyPara->pDoc->MakeTableBoxFormat();
1859 0 : aFindFrm.pNewFrameFormat->CopyAttrs( *rFndBox.GetBox()->GetFrameFormat() );
1860 0 : if( !pCpyPara->bCpyContent )
1861 0 : aFindFrm.pNewFrameFormat->ResetFormatAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1862 0 : aFrmSz.SetWidth( nSize );
1863 0 : aFindFrm.pNewFrameFormat->SetFormatAttr( aFrmSz );
1864 0 : pCpyPara->rTabFrmArr.insert( aFindFrm );
1865 : }
1866 :
1867 : SwTableBox* pBox;
1868 0 : if (!rFndBox.GetLines().empty())
1869 : {
1870 : pBox = new SwTableBox( aFindFrm.pNewFrameFormat,
1871 0 : rFndBox.GetLines().size(), pCpyPara->pInsLine );
1872 0 : pCpyPara->pInsLine->GetTabBoxes().insert( pCpyPara->pInsLine->GetTabBoxes().begin() + pCpyPara->nInsPos++, pBox );
1873 0 : _CpyPara aPara( *pCpyPara, pBox );
1874 0 : aPara.nNewSize = nSize; // get the size
1875 0 : for(_FndLine const& rFndLine : rFndBox.GetLines())
1876 0 : lcl_CopyLineToDoc( rFndLine, &aPara );
1877 : }
1878 : else
1879 : {
1880 : // Create an empty Box
1881 0 : pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTableNd, pCpyPara->pInsLine,
1882 : aFindFrm.pNewFrameFormat,
1883 : pCpyPara->pDoc->GetDfltTextFormatColl(),
1884 0 : 0, pCpyPara->nInsPos );
1885 0 : pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
1886 0 : if( bDummy )
1887 0 : pBox->setDummyFlag( true );
1888 0 : else if( pCpyPara->bCpyContent )
1889 : {
1890 : // Copy the content into this empty Box
1891 0 : pBox->setRowSpan(rFndBox.GetBox()->getRowSpan());
1892 :
1893 : // We can also copy formulas and values, if we copy the content
1894 : {
1895 0 : SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(),
1896 0 : RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
1897 0 : aBoxAttrSet.Put(rFndBox.GetBox()->GetFrameFormat()->GetAttrSet());
1898 0 : if( aBoxAttrSet.Count() )
1899 : {
1900 : const SfxPoolItem* pItem;
1901 0 : SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( false );
1902 0 : if( pN && pN->HasMergeFormatTable() && SfxItemState::SET == aBoxAttrSet.
1903 0 : GetItemState( RES_BOXATR_FORMAT, false, &pItem ) )
1904 : {
1905 0 : sal_uLong nOldIdx = static_cast<const SwTableBoxNumFormat*>(pItem)->GetValue();
1906 0 : sal_uLong nNewIdx = pN->GetMergeFormatIndex( nOldIdx );
1907 0 : if( nNewIdx != nOldIdx )
1908 0 : aBoxAttrSet.Put( SwTableBoxNumFormat( nNewIdx ));
1909 : }
1910 0 : pBox->ClaimFrameFormat()->SetFormatAttr( aBoxAttrSet );
1911 0 : }
1912 : }
1913 0 : SwDoc* pFromDoc = rFndBox.GetBox()->GetFrameFormat()->GetDoc();
1914 0 : SwNodeRange aCpyRg( *rFndBox.GetBox()->GetSttNd(), 1,
1915 0 : *rFndBox.GetBox()->GetSttNd()->EndOfSectionNode() );
1916 0 : SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
1917 :
1918 0 : pFromDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly( aCpyRg, 0, aInsIdx, NULL, false );
1919 : // Delete the initial TextNode
1920 0 : pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 );
1921 : }
1922 0 : ++pCpyPara->nInsPos;
1923 : }
1924 0 : if( nRealSize )
1925 : {
1926 0 : bDummy = false;
1927 0 : nSize = nRealSize;
1928 0 : nRealSize = 0;
1929 : }
1930 : else
1931 : {
1932 0 : bDummy = true;
1933 0 : nSize = nDummy2;
1934 0 : nDummy2 = 0;
1935 0 : }
1936 : }
1937 : while( nSize );
1938 0 : }
1939 :
1940 : static void
1941 0 : lcl_CopyLineToDoc(const _FndLine& rFndLine, _CpyPara *const pCpyPara)
1942 : {
1943 : // Find the Frame Format in the list of all Frame Formats
1944 0 : _CpyTabFrm aFindFrm( static_cast<SwTableBoxFormat*>(rFndLine.GetLine()->GetFrameFormat()) );
1945 0 : _CpyTabFrms::const_iterator itFind = pCpyPara->rTabFrmArr.find( aFindFrm );
1946 0 : if( itFind == pCpyPara->rTabFrmArr.end() )
1947 : {
1948 : // It doesn't exist yet, so copy it
1949 0 : aFindFrm.pNewFrameFormat = reinterpret_cast<SwTableBoxFormat*>(pCpyPara->pDoc->MakeTableLineFormat());
1950 0 : aFindFrm.pNewFrameFormat->CopyAttrs( *rFndLine.GetLine()->GetFrameFormat() );
1951 0 : pCpyPara->rTabFrmArr.insert( aFindFrm );
1952 : }
1953 : else
1954 0 : aFindFrm = *itFind;
1955 :
1956 : SwTableLine* pNewLine = new SwTableLine( reinterpret_cast<SwTableLineFormat*>(aFindFrm.pNewFrameFormat),
1957 0 : rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
1958 0 : if( pCpyPara->pInsBox )
1959 : {
1960 0 : SwTableLines& rLines = pCpyPara->pInsBox->GetTabLines();
1961 0 : rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
1962 : }
1963 : else
1964 : {
1965 0 : SwTableLines& rLines = pCpyPara->pTableNd->GetTable().GetTabLines();
1966 0 : rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine);
1967 : }
1968 :
1969 0 : _CpyPara aPara( *pCpyPara, pNewLine );
1970 :
1971 0 : if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1972 : {
1973 0 : aPara.nOldSize = 0; // will not be used
1974 0 : aPara.nBoxIdx = 1;
1975 : }
1976 0 : else if( rFndLine.GetBoxes().size() ==
1977 0 : rFndLine.GetLine()->GetTabBoxes().size() )
1978 : {
1979 : // Get the Parent's size
1980 : const SwFrameFormat* pFormat;
1981 :
1982 0 : if( rFndLine.GetLine()->GetUpper() )
1983 0 : pFormat = rFndLine.GetLine()->GetUpper()->GetFrameFormat();
1984 : else
1985 0 : pFormat = pCpyPara->pTableNd->GetTable().GetFrameFormat();
1986 0 : aPara.nOldSize = pFormat->GetFrmSize().GetWidth();
1987 : }
1988 : else
1989 : // Calculate it
1990 0 : for( auto &rBox : rFndLine.GetBoxes() )
1991 : {
1992 0 : aPara.nOldSize += rBox.GetBox()->GetFrameFormat()->GetFrmSize().GetWidth();
1993 : }
1994 :
1995 0 : const _FndBoxes& rBoxes = rFndLine.GetBoxes();
1996 0 : for (_FndBoxes::const_iterator it = rBoxes.begin(); it != rBoxes.end(); ++it)
1997 0 : lcl_CopyBoxToDoc(*it, &aPara);
1998 0 : if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1999 0 : ++pCpyPara->nLnIdx;
2000 0 : }
2001 :
2002 0 : bool SwTable::CopyHeadlineIntoTable( SwTableNode& rTableNd )
2003 : {
2004 : // Find all Boxes/Lines
2005 0 : SwSelBoxes aSelBoxes;
2006 0 : SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
2007 0 : pBox = GetTableBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
2008 0 : SelLineFromBox( pBox, aSelBoxes, true );
2009 :
2010 0 : _FndBox aFndBox( 0, 0 );
2011 : {
2012 0 : _FndPara aPara( aSelBoxes, &aFndBox );
2013 0 : ForEach_FndLineCopyCol( GetTabLines(), &aPara );
2014 : }
2015 0 : if( aFndBox.GetLines().empty() )
2016 0 : return false;
2017 :
2018 : {
2019 : // Convert Table formulas to their relative representation
2020 0 : SwTableFormulaUpdate aMsgHint( this );
2021 0 : aMsgHint.eFlags = TBL_RELBOXNAME;
2022 0 : GetFrameFormat()->GetDoc()->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2023 : }
2024 :
2025 0 : _CpyTabFrms aCpyFormat;
2026 0 : _CpyPara aPara( &rTableNd, 1, aCpyFormat, true );
2027 0 : aPara.nNewSize = aPara.nOldSize = rTableNd.GetTable().GetFrameFormat()->GetFrmSize().GetWidth();
2028 : // Copy
2029 0 : if( IsNewModel() )
2030 0 : lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2031 0 : for( _FndLine& rFndLine : aFndBox.GetLines() )
2032 0 : lcl_CopyLineToDoc( rFndLine, &aPara );
2033 0 : if( rTableNd.GetTable().IsNewModel() )
2034 : { // The copied line must not contain any row span attributes > 1
2035 0 : SwTableLine* pLine = rTableNd.GetTable().GetTabLines()[0];
2036 : OSL_ENSURE( !pLine->GetTabBoxes().empty(), "Empty Table Line" );
2037 0 : for( auto pTableBox : pLine->GetTabBoxes() )
2038 : {
2039 : OSL_ENSURE( pTableBox, "Missing Table Box" );
2040 0 : pTableBox->setRowSpan( 1 );
2041 : }
2042 : }
2043 :
2044 0 : return true;
2045 : }
2046 :
2047 0 : bool SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos,
2048 : const SwSelBoxes& rSelBoxes, bool bCpyNds,
2049 : bool bCpyName ) const
2050 : {
2051 : // Find all Boxes/Lines
2052 0 : _FndBox aFndBox( 0, 0 );
2053 : {
2054 0 : _FndPara aPara( rSelBoxes, &aFndBox );
2055 0 : ForEach_FndLineCopyCol( (SwTableLines&)GetTabLines(), &aPara );
2056 : }
2057 0 : if( aFndBox.GetLines().empty() )
2058 0 : return false;
2059 :
2060 : // First copy the PoolTemplates for the Table, so that the Tables are
2061 : // actually copied and have valid values.
2062 0 : SwDoc* pSrcDoc = GetFrameFormat()->GetDoc();
2063 0 : if( pSrcDoc != pInsDoc )
2064 : {
2065 0 : pInsDoc->CopyTextColl( *pSrcDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TABLE ) );
2066 0 : pInsDoc->CopyTextColl( *pSrcDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TABLE_HDLN ) );
2067 : }
2068 :
2069 : SwTable* pNewTable = const_cast<SwTable*>(pInsDoc->InsertTable(
2070 : SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ),
2071 0 : rPos, 1, 1, GetFrameFormat()->GetHoriOrient().GetHoriOrient(),
2072 0 : 0, 0, false, IsNewModel() ));
2073 0 : if( !pNewTable )
2074 0 : return false;
2075 :
2076 0 : SwNodeIndex aIdx( rPos.nNode, -1 );
2077 0 : SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
2078 0 : ++aIdx;
2079 : OSL_ENSURE( pTableNd, "Where is the TableNode now?" );
2080 :
2081 0 : pTableNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
2082 :
2083 0 : if( IS_TYPE( SwDDETable, this ))
2084 : {
2085 : // A DDE-Table is being copied
2086 : // Does the new Document actually have it's FieldType?
2087 0 : SwFieldType* pFieldType = pInsDoc->getIDocumentFieldsAccess().InsertFieldType(
2088 0 : *static_cast<const SwDDETable*>(this)->GetDDEFieldType() );
2089 : OSL_ENSURE( pFieldType, "unknown FieldType" );
2090 :
2091 : // Change the Table Pointer at the Node
2092 : pNewTable = new SwDDETable( *pNewTable,
2093 0 : static_cast<SwDDEFieldType*>(pFieldType) );
2094 0 : pTableNd->SetNewTable( pNewTable, false );
2095 : }
2096 :
2097 0 : pNewTable->GetFrameFormat()->CopyAttrs( *GetFrameFormat() );
2098 0 : pNewTable->SetTableChgMode( GetTableChgMode() );
2099 :
2100 : // Destroy the already created Frames
2101 0 : pTableNd->DelFrms();
2102 :
2103 : {
2104 : // Conver the Table formulas to their relative representation
2105 0 : SwTableFormulaUpdate aMsgHint( this );
2106 0 : aMsgHint.eFlags = TBL_RELBOXNAME;
2107 0 : pSrcDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2108 : }
2109 :
2110 0 : SwTableNumFormatMerge aTNFM( *pSrcDoc, *pInsDoc );
2111 :
2112 : // Also copy Names or enforce a new unique one
2113 0 : if( bCpyName )
2114 0 : pNewTable->GetFrameFormat()->SetName( GetFrameFormat()->GetName() );
2115 :
2116 0 : _CpyTabFrms aCpyFormat;
2117 0 : _CpyPara aPara( pTableNd, 1, aCpyFormat, bCpyNds );
2118 0 : aPara.nNewSize = aPara.nOldSize = GetFrameFormat()->GetFrmSize().GetWidth();
2119 :
2120 0 : if( IsNewModel() )
2121 0 : lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2122 : // Copy
2123 0 : for( _FndLine& rFndLine : aFndBox.GetLines() )
2124 0 : lcl_CopyLineToDoc( rFndLine, &aPara );
2125 :
2126 : // Set the "right" margin above/below
2127 : {
2128 0 : _FndLine* pFndLn = &aFndBox.GetLines().front();
2129 0 : SwTableLine* pLn = pFndLn->GetLine();
2130 0 : const SwTableLine* pTmp = pLn;
2131 0 : sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp );
2132 0 : if( USHRT_MAX != nLnPos && nLnPos )
2133 : {
2134 : // There is a Line before it
2135 0 : SwCollectTableLineBoxes aLnPara( false, HEADLINE_BORDERCOPY );
2136 :
2137 0 : pLn = GetTabLines()[ nLnPos - 1 ];
2138 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
2139 0 : it != pLn->GetTabBoxes().end(); ++it)
2140 0 : sw_Box_CollectBox( *it, &aLnPara );
2141 :
2142 0 : if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2143 0 : lcl_GetLineWidth( *pFndLn )) )
2144 : {
2145 0 : aLnPara.SetValues( true );
2146 0 : pLn = pNewTable->GetTabLines()[ 0 ];
2147 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
2148 0 : it != pLn->GetTabBoxes().end(); ++it)
2149 0 : sw_BoxSetSplitBoxFormats(*it, &aLnPara );
2150 0 : }
2151 : }
2152 :
2153 0 : pFndLn = &aFndBox.GetLines().back();
2154 0 : pLn = pFndLn->GetLine();
2155 0 : pTmp = pLn;
2156 0 : nLnPos = GetTabLines().GetPos( pTmp );
2157 0 : if( nLnPos < GetTabLines().size() - 1 )
2158 : {
2159 : // There is a Line following it
2160 0 : SwCollectTableLineBoxes aLnPara( true, HEADLINE_BORDERCOPY );
2161 :
2162 0 : pLn = GetTabLines()[ nLnPos + 1 ];
2163 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
2164 0 : it != pLn->GetTabBoxes().end(); ++it)
2165 0 : sw_Box_CollectBox( *it, &aLnPara );
2166 :
2167 0 : if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2168 0 : lcl_GetLineWidth( *pFndLn )) )
2169 : {
2170 0 : aLnPara.SetValues( false );
2171 0 : pLn = pNewTable->GetTabLines().back();
2172 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
2173 0 : it != pLn->GetTabBoxes().end(); ++it)
2174 0 : sw_BoxSetSplitBoxFormats(*it, &aLnPara );
2175 0 : }
2176 : }
2177 : }
2178 :
2179 : // We need to delete the initial Box
2180 0 : _DeleteBox( *pNewTable, pNewTable->GetTabLines().back()->GetTabBoxes()[0],
2181 0 : 0, false, false );
2182 :
2183 0 : if( pNewTable->IsNewModel() )
2184 0 : lcl_CheckRowSpan( *pNewTable );
2185 : // Clean up
2186 0 : pNewTable->GCLines();
2187 :
2188 0 : pTableNd->MakeFrms( &aIdx ); // re-generate the Frames
2189 :
2190 : CHECKTABLELAYOUT
2191 :
2192 0 : return true;
2193 : }
2194 :
2195 : // Find the next Box with content from this Line
2196 81 : SwTableBox* SwTableLine::FindNextBox( const SwTable& rTable,
2197 : const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2198 : {
2199 81 : const SwTableLine* pLine = this; // for M800
2200 : SwTableBox* pBox;
2201 : sal_uInt16 nFndPos;
2202 297 : if( !GetTabBoxes().empty() && pSrchBox &&
2203 197 : USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
2204 58 : nFndPos + 1 != (sal_uInt16)GetTabBoxes().size() )
2205 : {
2206 0 : pBox = GetTabBoxes()[ nFndPos + 1 ];
2207 0 : while( !pBox->GetTabLines().empty() )
2208 0 : pBox = pBox->GetTabLines().front()->GetTabBoxes()[0];
2209 0 : return pBox;
2210 : }
2211 :
2212 81 : if( GetUpper() )
2213 : {
2214 0 : nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2215 : OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
2216 : // Is there another Line?
2217 0 : if( nFndPos+1 >= (sal_uInt16)GetUpper()->GetTabLines().size() )
2218 0 : return GetUpper()->GetUpper()->FindNextBox( rTable, GetUpper(), bOvrTableLns );
2219 0 : pLine = GetUpper()->GetTabLines()[nFndPos+1];
2220 : }
2221 81 : else if( bOvrTableLns ) // Over a Table's the "BaseLines"??
2222 : {
2223 : // Search for the next Line in the Table
2224 81 : nFndPos = rTable.GetTabLines().GetPos( pLine );
2225 81 : if( nFndPos + 1 >= (sal_uInt16)rTable.GetTabLines().size() )
2226 40 : return 0; // there are no more Boxes
2227 :
2228 41 : pLine = rTable.GetTabLines()[ nFndPos+1 ];
2229 : }
2230 : else
2231 0 : return 0;
2232 :
2233 41 : if( !pLine->GetTabBoxes().empty() )
2234 : {
2235 41 : pBox = pLine->GetTabBoxes().front();
2236 82 : while( !pBox->GetTabLines().empty() )
2237 0 : pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
2238 41 : return pBox;
2239 : }
2240 0 : return pLine->FindNextBox( rTable, 0, bOvrTableLns );
2241 : }
2242 :
2243 : // Find the previous Box from this Line
2244 2 : SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTable,
2245 : const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2246 : {
2247 2 : const SwTableLine* pLine = this; // for M800
2248 : SwTableBox* pBox;
2249 : sal_uInt16 nFndPos;
2250 4 : if( !GetTabBoxes().empty() && pSrchBox &&
2251 2 : USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
2252 : nFndPos )
2253 : {
2254 0 : pBox = GetTabBoxes()[ nFndPos - 1 ];
2255 0 : while( !pBox->GetTabLines().empty() )
2256 : {
2257 0 : pLine = pBox->GetTabLines().back();
2258 0 : pBox = pLine->GetTabBoxes().back();
2259 : }
2260 0 : return pBox;
2261 : }
2262 :
2263 2 : if( GetUpper() )
2264 : {
2265 0 : nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2266 : OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
2267 : // Is there another Line?
2268 0 : if( !nFndPos )
2269 0 : return GetUpper()->GetUpper()->FindPreviousBox( rTable, GetUpper(), bOvrTableLns );
2270 0 : pLine = GetUpper()->GetTabLines()[nFndPos-1];
2271 : }
2272 2 : else if( bOvrTableLns ) // Over a Table's the "BaseLines"??
2273 : {
2274 : // Search for the next Line in the Table
2275 2 : nFndPos = rTable.GetTabLines().GetPos( pLine );
2276 2 : if( !nFndPos )
2277 0 : return 0; // there are no more Boxes
2278 :
2279 2 : pLine = rTable.GetTabLines()[ nFndPos-1 ];
2280 : }
2281 : else
2282 0 : return 0;
2283 :
2284 2 : if( !pLine->GetTabBoxes().empty() )
2285 : {
2286 2 : pBox = pLine->GetTabBoxes().back();
2287 4 : while( !pBox->GetTabLines().empty() )
2288 : {
2289 0 : pLine = pBox->GetTabLines().back();
2290 0 : pBox = pLine->GetTabBoxes().back();
2291 : }
2292 2 : return pBox;
2293 : }
2294 0 : return pLine->FindPreviousBox( rTable, 0, bOvrTableLns );
2295 : }
2296 :
2297 : // Find the next Box with content from this Line
2298 0 : SwTableBox* SwTableBox::FindNextBox( const SwTable& rTable,
2299 : const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2300 : {
2301 0 : if( !pSrchBox && GetTabLines().empty() )
2302 0 : return const_cast<SwTableBox*>(this);
2303 : return GetUpper()->FindNextBox( rTable, pSrchBox ? pSrchBox : this,
2304 0 : bOvrTableLns );
2305 :
2306 : }
2307 :
2308 : // Find the next Box with content from this Line
2309 0 : SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTable,
2310 : const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2311 : {
2312 0 : if( !pSrchBox && GetTabLines().empty() )
2313 0 : return const_cast<SwTableBox*>(this);
2314 : return GetUpper()->FindPreviousBox( rTable, pSrchBox ? pSrchBox : this,
2315 0 : bOvrTableLns );
2316 : }
2317 :
2318 0 : static void lcl_BoxSetHeadCondColl( const SwTableBox* pBox )
2319 : {
2320 : // We need to adapt the paragraphs with conditional templates in the HeadLine
2321 0 : const SwStartNode* pSttNd = pBox->GetSttNd();
2322 0 : if( pSttNd )
2323 0 : pSttNd->CheckSectionCondColl();
2324 : else
2325 0 : for( const SwTableLine* pLine : pBox->GetTabLines() )
2326 0 : sw_LineSetHeadCondColl( pLine );
2327 0 : }
2328 :
2329 0 : void sw_LineSetHeadCondColl( const SwTableLine* pLine )
2330 : {
2331 0 : for( const SwTableBox* pBox : pLine->GetTabBoxes() )
2332 0 : lcl_BoxSetHeadCondColl(pBox);
2333 0 : }
2334 :
2335 0 : static SwTwips lcl_GetDistance( SwTableBox* pBox, bool bLeft )
2336 : {
2337 0 : bool bFirst = true;
2338 0 : SwTwips nRet = 0;
2339 : SwTableLine* pLine;
2340 0 : while( pBox && 0 != ( pLine = pBox->GetUpper() ) )
2341 : {
2342 0 : sal_uInt16 nStt = 0, nPos = pLine->GetTabBoxes().GetPos( pBox );
2343 :
2344 0 : if( bFirst && !bLeft )
2345 0 : ++nPos;
2346 0 : bFirst = false;
2347 :
2348 0 : while( nStt < nPos )
2349 0 : nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrameFormat()
2350 0 : ->GetFrmSize().GetWidth();
2351 0 : pBox = pLine->GetUpper();
2352 : }
2353 0 : return nRet;
2354 : }
2355 :
2356 0 : static bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2357 : SwTwips nDist, bool bCheck )
2358 : {
2359 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2360 0 : for( auto pBox : rBoxes )
2361 : {
2362 0 : SwFrameFormat* pFormat = pBox->GetFrameFormat();
2363 0 : const SwFormatFrmSize& rSz = pFormat->GetFrmSize();
2364 0 : SwTwips nWidth = rSz.GetWidth();
2365 0 : bool bGreaterBox = false;
2366 :
2367 0 : if( bCheck )
2368 : {
2369 0 : for( auto pLn : pBox->GetTabLines() )
2370 0 : if( !::lcl_SetSelBoxWidth( pLn, rParam, nDist, true ))
2371 0 : return false;
2372 :
2373 : // Collect all "ContentBoxes"
2374 0 : if( (bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide) ||
2375 0 : ( !rParam.bBigger && ( std::abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) )
2376 : {
2377 0 : rParam.bAnyBoxFnd = true;
2378 : SwTwips nLowerDiff;
2379 0 : if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
2380 : {
2381 : // The "other Boxes" have been adapted, so change by this value
2382 0 : nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2383 0 : nLowerDiff *= rParam.nDiff;
2384 0 : nLowerDiff /= rParam.nMaxSize;
2385 0 : nLowerDiff = rParam.nDiff - nLowerDiff;
2386 : }
2387 : else
2388 0 : nLowerDiff = rParam.nDiff;
2389 :
2390 0 : if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
2391 0 : return false;
2392 : }
2393 : }
2394 : else
2395 : {
2396 0 : SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2397 0 : for( auto pLn : pBox->GetTabLines() )
2398 : {
2399 0 : rParam.nLowerDiff = 0;
2400 0 : lcl_SetSelBoxWidth( pLn, rParam, nDist, false );
2401 :
2402 0 : if( nLowerDiff < rParam.nLowerDiff )
2403 0 : nLowerDiff = rParam.nLowerDiff;
2404 : }
2405 0 : rParam.nLowerDiff = nOldLower;
2406 :
2407 0 : if( nLowerDiff ||
2408 0 : (bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode &&
2409 0 : ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide) ||
2410 0 : ( std::abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth )
2411 0 : - rParam.nSide ) < COLFUZZY ))
2412 : {
2413 : // This column contains the Cursor - so decrease/increase
2414 0 : SwFormatFrmSize aNew( rSz );
2415 :
2416 0 : if( !nLowerDiff )
2417 : {
2418 0 : if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
2419 : {
2420 : // The "other Boxes" have been adapted, so change by this value
2421 0 : nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2422 0 : nLowerDiff *= rParam.nDiff;
2423 0 : nLowerDiff /= rParam.nMaxSize;
2424 0 : nLowerDiff = rParam.nDiff - nLowerDiff;
2425 : }
2426 : else
2427 0 : nLowerDiff = rParam.nDiff;
2428 : }
2429 :
2430 0 : rParam.nLowerDiff += nLowerDiff;
2431 :
2432 0 : if( rParam.bBigger )
2433 0 : aNew.SetWidth( nWidth + nLowerDiff );
2434 : else
2435 0 : aNew.SetWidth( nWidth - nLowerDiff );
2436 0 : rParam.aShareFormats.SetSize( *pBox, aNew );
2437 0 : break;
2438 : }
2439 : }
2440 :
2441 0 : if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
2442 0 : break;
2443 :
2444 0 : nDist += nWidth;
2445 :
2446 : // If it gets bigger, then that's it
2447 0 : if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) &&
2448 0 : nDist >= rParam.nSide )
2449 0 : break;
2450 : }
2451 0 : return true;
2452 : }
2453 :
2454 0 : static bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2455 : SwTwips nDist, bool bCheck )
2456 : {
2457 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2458 0 : for( auto pBox : rBoxes )
2459 : {
2460 0 : SwFrameFormat* pFormat = pBox->GetFrameFormat();
2461 0 : const SwFormatFrmSize& rSz = pFormat->GetFrmSize();
2462 0 : SwTwips nWidth = rSz.GetWidth();
2463 :
2464 0 : if( bCheck )
2465 : {
2466 0 : for( auto pLn : pBox->GetTabLines() )
2467 0 : if( !::lcl_SetOtherBoxWidth( pLn, rParam, nDist, true ))
2468 0 : return false;
2469 :
2470 0 : if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode
2471 0 : ? std::abs( nDist - rParam.nSide ) < COLFUZZY
2472 0 : : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2473 0 : : nDist >= rParam.nSide - COLFUZZY )) )
2474 : {
2475 0 : rParam.bAnyBoxFnd = true;
2476 : SwTwips nDiff;
2477 0 : if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2478 : {
2479 : // calculate relative
2480 0 : nDiff = nWidth;
2481 0 : nDiff *= rParam.nDiff;
2482 0 : nDiff /= rParam.nMaxSize;
2483 : }
2484 : else
2485 0 : nDiff = rParam.nDiff;
2486 :
2487 0 : if( nWidth < nDiff || nWidth - nDiff < MINLAY )
2488 0 : return false;
2489 : }
2490 : }
2491 : else
2492 : {
2493 0 : SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2494 0 : for( auto pLn : pBox->GetTabLines() )
2495 : {
2496 0 : rParam.nLowerDiff = 0;
2497 0 : lcl_SetOtherBoxWidth( pLn, rParam, nDist, false );
2498 :
2499 0 : if( nLowerDiff < rParam.nLowerDiff )
2500 0 : nLowerDiff = rParam.nLowerDiff;
2501 : }
2502 0 : rParam.nLowerDiff = nOldLower;
2503 :
2504 0 : if( nLowerDiff ||
2505 0 : ( TBLFIX_CHGABS == rParam.nMode
2506 0 : ? std::abs( nDist - rParam.nSide ) < COLFUZZY
2507 0 : : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2508 0 : : nDist >= rParam.nSide - COLFUZZY)
2509 : ) )
2510 : {
2511 0 : SwFormatFrmSize aNew( rSz );
2512 :
2513 0 : if( !nLowerDiff )
2514 : {
2515 0 : if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2516 : {
2517 : // calculate relative
2518 0 : nLowerDiff = nWidth;
2519 0 : nLowerDiff *= rParam.nDiff;
2520 0 : nLowerDiff /= rParam.nMaxSize;
2521 : }
2522 : else
2523 0 : nLowerDiff = rParam.nDiff;
2524 : }
2525 :
2526 0 : rParam.nLowerDiff += nLowerDiff;
2527 :
2528 0 : if( rParam.bBigger )
2529 0 : aNew.SetWidth( nWidth - nLowerDiff );
2530 : else
2531 0 : aNew.SetWidth( nWidth + nLowerDiff );
2532 :
2533 0 : rParam.aShareFormats.SetSize( *pBox, aNew );
2534 : }
2535 : }
2536 :
2537 0 : nDist += nWidth;
2538 0 : if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) &&
2539 0 : nDist > rParam.nSide )
2540 0 : break;
2541 : }
2542 0 : return true;
2543 : }
2544 :
2545 0 : static bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2546 : SwTwips nDist, bool bCheck )
2547 : {
2548 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2549 0 : for( size_t n = 0; n < rBoxes.size(); ++n )
2550 : {
2551 0 : SwTableBox* pBox = rBoxes[ n ];
2552 0 : SwTableBoxFormat* pFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
2553 0 : const SwFormatFrmSize& rSz = pFormat->GetFrmSize();
2554 0 : SwTwips nWidth = rSz.GetWidth();
2555 :
2556 0 : int nCmp {0};
2557 :
2558 0 : if( bCheck )
2559 : {
2560 0 : for( size_t i = 0; i < pBox->GetTabLines().size(); ++i )
2561 0 : if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam,
2562 0 : nDist, true ))
2563 0 : return false;
2564 :
2565 : // Collect all "ContentBoxes"
2566 0 : if( std::abs( nDist + ( rParam.bLeft ? 0 : nWidth )
2567 0 : - rParam.nSide ) < COLFUZZY )
2568 0 : nCmp = 1;
2569 0 : else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide )
2570 0 : nCmp = 2;
2571 :
2572 0 : if( nCmp )
2573 : {
2574 0 : rParam.bAnyBoxFnd = true;
2575 0 : if( pFormat->GetProtect().IsContentProtected() )
2576 0 : return false;
2577 :
2578 0 : if( rParam.bSplittBox &&
2579 0 : nWidth - rParam.nDiff <= COLFUZZY +
2580 : ( 567 / 2 /*leave room for at least 0.5 cm*/) )
2581 0 : return false;
2582 :
2583 0 : if( pBox->GetSttNd() )
2584 : {
2585 0 : rParam.m_Boxes.insert(pBox);
2586 : }
2587 :
2588 0 : break;
2589 : }
2590 : }
2591 : else
2592 : {
2593 0 : SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2594 0 : for( auto pLn : pBox->GetTabLines() )
2595 : {
2596 0 : rParam.nLowerDiff = 0;
2597 0 : lcl_InsSelBox( pLn, rParam, nDist, false );
2598 :
2599 0 : if( nLowerDiff < rParam.nLowerDiff )
2600 0 : nLowerDiff = rParam.nLowerDiff;
2601 : }
2602 0 : rParam.nLowerDiff = nOldLower;
2603 :
2604 0 : if( nLowerDiff )
2605 0 : nCmp = 1;
2606 0 : else if( std::abs( nDist + ( rParam.bLeft ? 0 : nWidth )
2607 0 : - rParam.nSide ) < COLFUZZY )
2608 0 : nCmp = 2;
2609 0 : else if( nDist + nWidth / 2 > rParam.nSide )
2610 0 : nCmp = 3;
2611 :
2612 0 : if( nCmp )
2613 : {
2614 : // This column contains the Cursor - so decrease/increase
2615 0 : if( 1 == nCmp )
2616 : {
2617 0 : if( !rParam.bSplittBox )
2618 : {
2619 : // the current Box on
2620 0 : SwFormatFrmSize aNew( rSz );
2621 0 : aNew.SetWidth( nWidth + rParam.nDiff );
2622 0 : rParam.aShareFormats.SetSize( *pBox, aNew );
2623 : }
2624 : }
2625 : else
2626 : {
2627 : OSL_ENSURE( pBox->GetSttNd(), "This must be an EndBox!");
2628 :
2629 0 : if( !rParam.bLeft && 3 != nCmp )
2630 0 : ++n;
2631 :
2632 : ::_InsTableBox( pFormat->GetDoc(), rParam.pTableNd,
2633 0 : pLine, pFormat, pBox, n );
2634 :
2635 0 : SwTableBox* pNewBox = rBoxes[ n ];
2636 0 : SwFormatFrmSize aNew( rSz );
2637 0 : aNew.SetWidth( rParam.nDiff );
2638 0 : rParam.aShareFormats.SetSize( *pNewBox, aNew );
2639 :
2640 : // Special case: There is no space in the other Boxes, but in the Cell
2641 0 : if( rParam.bSplittBox )
2642 : {
2643 : // the current Box on
2644 0 : SwFormatFrmSize aNewSize( rSz );
2645 0 : aNewSize.SetWidth( nWidth - rParam.nDiff );
2646 0 : rParam.aShareFormats.SetSize( *pBox, aNewSize );
2647 : }
2648 :
2649 : // Special treatment for the Border
2650 : // The right one needs to be removed
2651 : {
2652 0 : const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
2653 0 : if( rBoxItem.GetRight() )
2654 : {
2655 0 : SvxBoxItem aTmp( rBoxItem );
2656 0 : aTmp.SetLine( 0, SvxBoxItemLine::RIGHT );
2657 : rParam.aShareFormats.SetAttr( rParam.bLeft
2658 : ? *pNewBox
2659 0 : : *pBox, aTmp );
2660 : }
2661 0 : }
2662 : }
2663 :
2664 0 : rParam.nLowerDiff = rParam.nDiff;
2665 0 : break;
2666 : }
2667 : }
2668 :
2669 0 : if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
2670 0 : break;
2671 :
2672 0 : nDist += nWidth;
2673 : }
2674 0 : return true;
2675 : }
2676 :
2677 0 : static bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2678 : SwTwips nDist, bool bCheck )
2679 : {
2680 : // Special case: There is no space in the other Boxes, but in the cell
2681 0 : if( rParam.bSplittBox )
2682 0 : return true;
2683 :
2684 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2685 :
2686 : // Table fixed, proportional
2687 0 : if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode )
2688 : {
2689 : // Find the right width to which the relative width adjustment
2690 : // corresponds to
2691 0 : SwTwips nTmpDist = nDist;
2692 0 : for( auto pBox : rBoxes )
2693 : {
2694 0 : SwTwips nWidth = pBox->GetFrameFormat()->GetFrmSize().GetWidth();
2695 0 : if( (nTmpDist + nWidth / 2 ) > rParam.nSide )
2696 : {
2697 : rParam.nRemainWidth = rParam.bLeft
2698 : ? sal_uInt16(nTmpDist)
2699 0 : : sal_uInt16(rParam.nTableWidth - nTmpDist);
2700 0 : break;
2701 : }
2702 0 : nTmpDist += nWidth;
2703 : }
2704 : }
2705 :
2706 0 : for( SwTableBoxes::size_type n = 0; n < rBoxes.size(); ++n )
2707 : {
2708 0 : SwTableBox* pBox = rBoxes[ n ];
2709 0 : SwFrameFormat* pFormat = pBox->GetFrameFormat();
2710 0 : const SwFormatFrmSize& rSz = pFormat->GetFrmSize();
2711 0 : SwTwips nWidth = rSz.GetWidth();
2712 :
2713 0 : if( bCheck )
2714 : {
2715 0 : for( auto pLn : pBox->GetTabLines() )
2716 0 : if( !::lcl_InsOtherBox( pLn, rParam, nDist, true ))
2717 0 : return false;
2718 :
2719 0 : if(
2720 0 : rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
2721 0 : (TBLFIX_CHGABS != rParam.nMode ||
2722 0 : (n < rBoxes.size() &&
2723 0 : (nDist + nWidth + rBoxes[ n+1 ]->
2724 0 : GetFrameFormat()->GetFrmSize().GetWidth() / 2)
2725 0 : > rParam.nSide) ))
2726 0 : : (nDist + nWidth / 2 ) > rParam.nSide
2727 : )
2728 : {
2729 0 : rParam.bAnyBoxFnd = true;
2730 : SwTwips nDiff;
2731 0 : if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2732 : {
2733 : // calculate relatively
2734 0 : nDiff = nWidth;
2735 0 : nDiff *= rParam.nDiff;
2736 0 : nDiff /= rParam.nRemainWidth;
2737 :
2738 0 : if( nWidth < nDiff || nWidth - nDiff < MINLAY )
2739 0 : return false;
2740 : }
2741 : else
2742 : {
2743 0 : nDiff = rParam.nDiff;
2744 :
2745 : // See if the left or right Box is big enough to give up space.
2746 : // We're inserting a Box before or after.
2747 0 : SwTwips nTmpWidth = nWidth;
2748 0 : if( rParam.bLeft && pBox->GetUpper()->GetUpper() )
2749 : {
2750 0 : const SwTableBox* pTmpBox = pBox;
2751 0 : sal_uInt16 nBoxPos = n;
2752 0 : while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() )
2753 : {
2754 0 : pTmpBox = pTmpBox->GetUpper()->GetUpper();
2755 0 : nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox );
2756 : }
2757 0 : nTmpWidth = pTmpBox->GetFrameFormat()->GetFrmSize().GetWidth();
2758 : }
2759 :
2760 0 : if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY )
2761 0 : return false;
2762 0 : break;
2763 : }
2764 : }
2765 : }
2766 : else
2767 : {
2768 0 : SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2769 0 : for( auto pLn : pBox->GetTabLines() )
2770 : {
2771 0 : rParam.nLowerDiff = 0;
2772 0 : lcl_InsOtherBox( pLn, rParam, nDist, false );
2773 :
2774 0 : if( nLowerDiff < rParam.nLowerDiff )
2775 0 : nLowerDiff = rParam.nLowerDiff;
2776 : }
2777 0 : rParam.nLowerDiff = nOldLower;
2778 :
2779 0 : if( nLowerDiff ||
2780 0 : (rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
2781 0 : (TBLFIX_CHGABS != rParam.nMode ||
2782 0 : (n < rBoxes.size() &&
2783 0 : (nDist + nWidth + rBoxes[ n+1 ]->
2784 0 : GetFrameFormat()->GetFrmSize().GetWidth() / 2)
2785 0 : > rParam.nSide) ))
2786 0 : : (nDist + nWidth / 2 ) > rParam.nSide ))
2787 : {
2788 0 : if( !nLowerDiff )
2789 : {
2790 0 : if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2791 : {
2792 : // Calculate relatively
2793 0 : nLowerDiff = nWidth;
2794 0 : nLowerDiff *= rParam.nDiff;
2795 0 : nLowerDiff /= rParam.nRemainWidth;
2796 : }
2797 : else
2798 0 : nLowerDiff = rParam.nDiff;
2799 : }
2800 :
2801 0 : SwFormatFrmSize aNew( rSz );
2802 0 : rParam.nLowerDiff += nLowerDiff;
2803 :
2804 0 : if( rParam.bBigger )
2805 0 : aNew.SetWidth( nWidth - nLowerDiff );
2806 : else
2807 0 : aNew.SetWidth( nWidth + nLowerDiff );
2808 0 : rParam.aShareFormats.SetSize( *pBox, aNew );
2809 :
2810 0 : if( TBLFIX_CHGABS == rParam.nMode )
2811 0 : break;
2812 : }
2813 : }
2814 :
2815 0 : nDist += nWidth;
2816 : }
2817 0 : return true;
2818 : }
2819 :
2820 : // The position comparison's result
2821 : // POS_BEFORE, // Box comes before
2822 : // POS_BEHIND, // Box comes after
2823 : // POS_INSIDE, // Box is completely wthin start/end
2824 : // POS_OUTSIDE, // Box overlaps start/end completely
2825 : // POS_EQUAL, // Box and start/end are the same
2826 : // POS_OVERLAP_BEFORE, // Box overlapps the start
2827 : // POS_OVERLAP_BEHIND // Box overlapps the end
2828 0 : SwComparePosition _CheckBoxInRange( sal_uInt16 nStt, sal_uInt16 nEnd,
2829 : sal_uInt16 nBoxStt, sal_uInt16 nBoxEnd )
2830 : {
2831 : // Still treat COLFUZZY!
2832 : SwComparePosition nRet;
2833 0 : if( nBoxStt + COLFUZZY < nStt )
2834 : {
2835 0 : if( nBoxEnd > nStt + COLFUZZY )
2836 : {
2837 0 : if( nBoxEnd >= nEnd + COLFUZZY )
2838 0 : nRet = POS_OUTSIDE;
2839 : else
2840 0 : nRet = POS_OVERLAP_BEFORE;
2841 : }
2842 : else
2843 0 : nRet = POS_BEFORE;
2844 : }
2845 0 : else if( nEnd > nBoxStt + COLFUZZY )
2846 : {
2847 0 : if( nEnd + COLFUZZY >= nBoxEnd )
2848 : {
2849 0 : if( COLFUZZY > std::abs( long(nEnd) - long(nBoxEnd) ) &&
2850 0 : COLFUZZY > std::abs( long(nStt) - long(nBoxStt) ) )
2851 0 : nRet = POS_EQUAL;
2852 : else
2853 0 : nRet = POS_INSIDE;
2854 : }
2855 : else
2856 0 : nRet = POS_OVERLAP_BEHIND;
2857 : }
2858 : else
2859 0 : nRet = POS_BEHIND;
2860 :
2861 0 : return nRet;
2862 : }
2863 :
2864 0 : static void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam,
2865 : SwTwips nWidth )
2866 : {
2867 : // 1. step: Calculate own width
2868 0 : SwTableBoxes& rBoxes = rLine.GetTabBoxes();
2869 0 : SwTwips nBoxWidth = 0;
2870 :
2871 0 : for( auto n = rBoxes.size(); n; )
2872 0 : nBoxWidth += rBoxes[ --n ]->GetFrameFormat()->GetFrmSize().GetWidth();
2873 :
2874 0 : if( COLFUZZY < std::abs( nWidth - nBoxWidth ))
2875 : {
2876 : // Thus, they need to be adjusted
2877 0 : for( auto n = rBoxes.size(); n; )
2878 : {
2879 0 : SwTableBox* pBox = rBoxes[ --n ];
2880 0 : SwFormatFrmSize aNew( pBox->GetFrameFormat()->GetFrmSize() );
2881 0 : long nDiff = aNew.GetWidth();
2882 0 : nDiff *= nWidth;
2883 0 : nDiff /= nBoxWidth;
2884 0 : aNew.SetWidth( nDiff );
2885 :
2886 0 : rParam.aShareFormats.SetSize( *pBox, aNew );
2887 :
2888 0 : if( !pBox->GetSttNd() )
2889 : {
2890 : // Has Lower itself, so also adjust that
2891 0 : for( auto i = pBox->GetTabLines().size(); i; )
2892 0 : ::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ],
2893 0 : rParam, nDiff );
2894 : }
2895 0 : }
2896 : }
2897 0 : }
2898 :
2899 0 : static void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam,
2900 : const SwFormatFrmSize& rOldSz,
2901 : sal_uInt16& rDelWidth, SwTwips nDist )
2902 : {
2903 0 : long nDiff = 0;
2904 0 : bool bSetSize = false;
2905 :
2906 0 : switch( rParam.nMode )
2907 : {
2908 : case TBLFIX_CHGABS: // Fixed width table, change neighbor
2909 0 : nDiff = rDelWidth + rParam.nLowerDiff;
2910 0 : bSetSize = true;
2911 0 : break;
2912 :
2913 : case TBLFIX_CHGPROP: // Fixed width table, change all neighbors
2914 0 : if( !rParam.nRemainWidth )
2915 : {
2916 : // Calculate
2917 0 : if( rParam.bLeft )
2918 0 : rParam.nRemainWidth = sal_uInt16(nDist);
2919 : else
2920 0 : rParam.nRemainWidth = sal_uInt16(rParam.nTableWidth - nDist);
2921 : }
2922 :
2923 : // Calculate relatively
2924 0 : nDiff = rOldSz.GetWidth();
2925 0 : nDiff *= rDelWidth + rParam.nLowerDiff;
2926 0 : nDiff /= rParam.nRemainWidth;
2927 :
2928 0 : bSetSize = true;
2929 0 : break;
2930 :
2931 : case TBLVAR_CHGABS: // Variable table, change all neighbors
2932 0 : if( COLFUZZY < std::abs( rParam.nBoxWidth -
2933 0 : ( rDelWidth + rParam.nLowerDiff )))
2934 : {
2935 0 : nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth;
2936 0 : if( 0 < nDiff )
2937 0 : rDelWidth = rDelWidth - sal_uInt16(nDiff);
2938 : else
2939 0 : rDelWidth = rDelWidth + sal_uInt16(-nDiff);
2940 0 : bSetSize = true;
2941 : }
2942 0 : break;
2943 : }
2944 :
2945 0 : if( bSetSize )
2946 : {
2947 0 : SwFormatFrmSize aNew( rOldSz );
2948 0 : aNew.SetWidth( aNew.GetWidth() + nDiff );
2949 0 : rParam.aShareFormats.SetSize( rBox, aNew );
2950 :
2951 : // Change the Lower once again
2952 0 : for( auto i = rBox.GetTabLines().size(); i; )
2953 0 : ::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam,
2954 0 : aNew.GetWidth() );
2955 : }
2956 0 : }
2957 :
2958 0 : static bool lcl_DeleteBox_Recursive( CR_SetBoxWidth& rParam, SwTableBox& rBox,
2959 : bool bCheck )
2960 : {
2961 0 : bool bRet = true;
2962 0 : if( rBox.GetSttNd() )
2963 : {
2964 0 : if( bCheck )
2965 : {
2966 0 : rParam.bAnyBoxFnd = true;
2967 0 : if( rBox.GetFrameFormat()->GetProtect().IsContentProtected() )
2968 0 : bRet = false;
2969 : else
2970 : {
2971 0 : SwTableBox* pBox = &rBox;
2972 0 : rParam.m_Boxes.insert(pBox);
2973 : }
2974 : }
2975 : else
2976 0 : ::_DeleteBox( rParam.pTableNd->GetTable(), &rBox,
2977 0 : rParam.pUndo, false, true, &rParam.aShareFormats );
2978 : }
2979 : else
2980 : {
2981 : // We need to delete these sequentially via the ContentBoxes
2982 0 : for( auto i = rBox.GetTabLines().size(); i; )
2983 : {
2984 0 : SwTableLine& rLine = *rBox.GetTabLines()[ --i ];
2985 0 : for( auto n = rLine.GetTabBoxes().size(); n; )
2986 : {
2987 0 : if (!::lcl_DeleteBox_Recursive( rParam,
2988 0 : *rLine.GetTabBoxes()[ --n ], bCheck ))
2989 : {
2990 0 : return false;
2991 : }
2992 : }
2993 : }
2994 : }
2995 0 : return bRet;
2996 : }
2997 :
2998 0 : static bool lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam,
2999 : SwTwips nDist, bool bCheck )
3000 : {
3001 0 : SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
3002 : SwTableBoxes::size_type n;
3003 : SwTableBoxes::size_type nCntEnd;
3004 :
3005 0 : sal_uInt16 nBoxChkStt, nBoxChkEnd, nDelWidth = 0;
3006 0 : if( rParam.bLeft )
3007 : {
3008 0 : n = rBoxes.size();
3009 0 : nCntEnd = 0;
3010 0 : nBoxChkStt = (sal_uInt16)rParam.nSide;
3011 0 : nBoxChkEnd = static_cast<sal_uInt16>(rParam.nSide + rParam.nBoxWidth);
3012 : }
3013 : else
3014 : {
3015 0 : n = 0;
3016 0 : nCntEnd = rBoxes.size();
3017 0 : nBoxChkStt = static_cast<sal_uInt16>(rParam.nSide - rParam.nBoxWidth);
3018 0 : nBoxChkEnd = (sal_uInt16)rParam.nSide;
3019 : }
3020 :
3021 0 : while( n != nCntEnd )
3022 : {
3023 : SwTableBox* pBox;
3024 0 : if( rParam.bLeft )
3025 0 : pBox = rBoxes[ --n ];
3026 : else
3027 0 : pBox = rBoxes[ n++ ];
3028 :
3029 0 : SwFrameFormat* pFormat = pBox->GetFrameFormat();
3030 0 : const SwFormatFrmSize& rSz = pFormat->GetFrmSize();
3031 0 : long nWidth = rSz.GetWidth();
3032 0 : bool bDelBox = false, bChgLowers = false;
3033 :
3034 : // Test the Box width and react accordingly
3035 : SwComparePosition ePosType = ::_CheckBoxInRange(
3036 : nBoxChkStt, nBoxChkEnd,
3037 : sal_uInt16(rParam.bLeft ? nDist - nWidth : nDist),
3038 0 : sal_uInt16(rParam.bLeft ? nDist : nDist + nWidth));
3039 :
3040 0 : switch( ePosType )
3041 : {
3042 : case POS_BEFORE:
3043 0 : if( bCheck )
3044 : {
3045 0 : if( rParam.bLeft )
3046 0 : return true;
3047 : }
3048 0 : else if( rParam.bLeft )
3049 : {
3050 0 : ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
3051 0 : if( TBLFIX_CHGABS == rParam.nMode )
3052 0 : n = nCntEnd;
3053 : }
3054 0 : break;
3055 :
3056 : case POS_BEHIND:
3057 0 : if( bCheck )
3058 : {
3059 0 : if( !rParam.bLeft )
3060 0 : return true;
3061 : }
3062 0 : else if( !rParam.bLeft )
3063 : {
3064 0 : ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
3065 0 : if( TBLFIX_CHGABS == rParam.nMode )
3066 0 : n = nCntEnd;
3067 : }
3068 0 : break;
3069 :
3070 : case POS_OUTSIDE: // Box fully overlaps start/end
3071 : case POS_INSIDE: // Box is completely within start/end
3072 : case POS_EQUAL: // Box and start/end are the same
3073 0 : bDelBox = true;
3074 0 : break;
3075 :
3076 : case POS_OVERLAP_BEFORE: // Box overlaps the start
3077 0 : if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2
3078 : : nWidth / 2 )))
3079 : {
3080 0 : if( !pBox->GetSttNd() )
3081 0 : bChgLowers = true;
3082 : else
3083 0 : bDelBox = true;
3084 : }
3085 0 : else if( !bCheck && rParam.bLeft )
3086 : {
3087 0 : if( !pBox->GetSttNd() )
3088 0 : bChgLowers = true;
3089 : else
3090 : {
3091 0 : ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
3092 0 : if( TBLFIX_CHGABS == rParam.nMode )
3093 0 : n = nCntEnd;
3094 : }
3095 : }
3096 0 : break;
3097 :
3098 : case POS_OVERLAP_BEHIND: // Box overlaps the end
3099 : // JP 10.02.99:
3100 : // Delete generally or (like in OVERLAP_BEFORE) only delete the one who reaches up to the half into the delete Box?
3101 0 : if( !pBox->GetSttNd() )
3102 0 : bChgLowers = true;
3103 : else
3104 0 : bDelBox = true;
3105 0 : break;
3106 0 : default: break;
3107 : }
3108 :
3109 0 : if( bDelBox )
3110 : {
3111 0 : nDelWidth = nDelWidth + sal_uInt16(nWidth);
3112 0 : if( bCheck )
3113 : {
3114 : // The last/first Box can only be deleted for the variable Table,
3115 : // if it's as large as the change in the Table.
3116 0 : if( (( TBLVAR_CHGABS != rParam.nMode ||
3117 0 : nDelWidth != rParam.nBoxWidth ) &&
3118 : COLFUZZY > std::abs( rParam.bLeft
3119 : ? nWidth - nDist
3120 0 : : (nDist + nWidth - rParam.nTableWidth )))
3121 0 : || !::lcl_DeleteBox_Recursive(rParam, *pBox, bCheck))
3122 : {
3123 0 : return false;
3124 : }
3125 :
3126 0 : if( pFormat->GetProtect().IsContentProtected() )
3127 0 : return false;
3128 : }
3129 : else
3130 : {
3131 0 : ::lcl_DeleteBox_Recursive(rParam, *pBox, bCheck);
3132 :
3133 0 : if( !rParam.bLeft )
3134 0 : --n, --nCntEnd;
3135 : }
3136 : }
3137 0 : else if( bChgLowers )
3138 : {
3139 0 : bool bFirst = true, bCorrLowers = false;
3140 0 : long nLowerDiff = 0;
3141 0 : long nOldLower = rParam.nLowerDiff;
3142 0 : sal_uInt16 nOldRemain = rParam.nRemainWidth;
3143 :
3144 0 : for( auto i = pBox->GetTabLines().size(); i; )
3145 : {
3146 0 : rParam.nLowerDiff = nDelWidth + nOldLower;
3147 0 : rParam.nRemainWidth = nOldRemain;
3148 0 : SwTableLine* pLine = pBox->GetTabLines()[ --i ];
3149 0 : if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck ))
3150 0 : return false;
3151 :
3152 : // Do the Box and its Lines still exist?
3153 0 : if( n < rBoxes.size() &&
3154 0 : pBox == rBoxes[ rParam.bLeft ? n : n-1 ] &&
3155 0 : i < pBox->GetTabLines().size() &&
3156 0 : pLine == pBox->GetTabLines()[ i ] )
3157 : {
3158 0 : if( !bFirst && !bCorrLowers &&
3159 0 : COLFUZZY < std::abs( nLowerDiff - rParam.nLowerDiff ) )
3160 0 : bCorrLowers = true;
3161 :
3162 : // The largest deletion width counts, but only if we don't
3163 : // delete the whole Line
3164 0 : if( nLowerDiff < rParam.nLowerDiff )
3165 0 : nLowerDiff = rParam.nLowerDiff;
3166 :
3167 0 : bFirst = false;
3168 : }
3169 : }
3170 0 : rParam.nLowerDiff = nOldLower;
3171 0 : rParam.nRemainWidth = nOldRemain;
3172 :
3173 : // Did we delete all Boxes? Then the deletion width = the Box width, of course
3174 0 : if( !nLowerDiff )
3175 0 : nLowerDiff = nWidth;
3176 :
3177 : // Adjust deletion width!
3178 0 : nDelWidth = nDelWidth + sal_uInt16(nLowerDiff);
3179 :
3180 0 : if( !bCheck )
3181 : {
3182 : // Has the Box already been removed?
3183 0 : if( n > rBoxes.size() ||
3184 0 : pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] )
3185 : {
3186 : // Then change the loop variable when deleting to the right
3187 0 : if( !rParam.bLeft )
3188 0 : --n, --nCntEnd;
3189 : }
3190 : else
3191 : {
3192 : // Or else we need to adapt the Box's size
3193 0 : SwFormatFrmSize aNew( rSz );
3194 0 : bool bCorrRel = false;
3195 :
3196 0 : if( TBLVAR_CHGABS != rParam.nMode )
3197 : {
3198 0 : switch( ePosType )
3199 : {
3200 : case POS_OVERLAP_BEFORE: // Box overlaps the start
3201 0 : if( TBLFIX_CHGPROP == rParam.nMode )
3202 0 : bCorrRel = rParam.bLeft;
3203 0 : else if( rParam.bLeft ) // TBLFIX_CHGABS
3204 : {
3205 0 : nLowerDiff = nLowerDiff - nDelWidth;
3206 0 : bCorrLowers = true;
3207 0 : n = nCntEnd;
3208 : }
3209 0 : break;
3210 :
3211 : case POS_OVERLAP_BEHIND: // Box overlaps the end
3212 0 : if( TBLFIX_CHGPROP == rParam.nMode )
3213 0 : bCorrRel = !rParam.bLeft;
3214 0 : else if( !rParam.bLeft ) // TBLFIX_CHGABS
3215 : {
3216 0 : nLowerDiff = nLowerDiff - nDelWidth;
3217 0 : bCorrLowers = true;
3218 0 : n = nCntEnd;
3219 : }
3220 0 : break;
3221 :
3222 : default:
3223 : OSL_ENSURE( !pBox, "we should never reach this!" );
3224 0 : break;
3225 : }
3226 : }
3227 :
3228 0 : if( bCorrRel )
3229 : {
3230 0 : if( !rParam.nRemainWidth )
3231 : {
3232 : // Calculate
3233 0 : if( rParam.bLeft )
3234 0 : rParam.nRemainWidth = sal_uInt16(nDist - nLowerDiff);
3235 : else
3236 : rParam.nRemainWidth = sal_uInt16(rParam.nTableWidth - nDist
3237 0 : - nLowerDiff );
3238 : }
3239 :
3240 0 : long nDiff = aNew.GetWidth() - nLowerDiff;
3241 0 : nDiff *= nDelWidth + rParam.nLowerDiff;
3242 0 : nDiff /= rParam.nRemainWidth;
3243 :
3244 0 : aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff );
3245 : }
3246 : else
3247 0 : aNew.SetWidth( aNew.GetWidth() - nLowerDiff );
3248 0 : rParam.aShareFormats.SetSize( *pBox, aNew );
3249 :
3250 0 : if( bCorrLowers )
3251 : {
3252 : // Adapt the Lower once again
3253 0 : for( auto i = pBox->GetTabLines().size(); i; )
3254 : ::lcl_DelSelBox_CorrLowers( *pBox->
3255 0 : GetTabLines()[ --i ], rParam, aNew.GetWidth() );
3256 0 : }
3257 : }
3258 : }
3259 : }
3260 :
3261 0 : if( rParam.bLeft )
3262 0 : nDist -= nWidth;
3263 : else
3264 0 : nDist += nWidth;
3265 : }
3266 0 : rParam.nLowerDiff = nDelWidth;
3267 0 : return true;
3268 : }
3269 :
3270 : // Dummy function for the method SetColWidth
3271 0 : static bool lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , bool )
3272 : {
3273 0 : return true;
3274 : }
3275 :
3276 0 : static void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
3277 : {
3278 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
3279 0 : for( auto pBox : rBoxes )
3280 : {
3281 0 : SwFormatFrmSize aSz( pBox->GetFrameFormat()->GetFrmSize() );
3282 0 : SwTwips nWidth = aSz.GetWidth();
3283 0 : nWidth *= rParam.nDiff;
3284 0 : nWidth /= rParam.nMaxSize;
3285 0 : aSz.SetWidth( nWidth );
3286 0 : rParam.aShareFormats.SetSize( *pBox, aSz );
3287 :
3288 0 : for( auto pLn : pBox->GetTabLines() )
3289 0 : ::lcl_AjustLines( pLn, rParam );
3290 0 : }
3291 0 : }
3292 :
3293 : #ifdef DBG_UTIL
3294 : void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
3295 : {
3296 : const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
3297 :
3298 : SwTwips nAktSize = 0;
3299 : // See if the tables have a correct width
3300 : for (SwTableBoxes::const_iterator i(rBoxes.begin()); i != rBoxes.end(); ++i)
3301 : {
3302 : const SwTableBox* pBox = *i;
3303 : const SwTwips nBoxW = pBox->GetFrameFormat()->GetFrmSize().GetWidth();
3304 : nAktSize += nBoxW;
3305 :
3306 : for( auto pLn : pBox->GetTabLines() )
3307 : _CheckBoxWidth( *pLn, nBoxW );
3308 : }
3309 :
3310 : if (sal::static_int_cast< unsigned long >(std::abs(nAktSize - nSize)) >
3311 : (COLFUZZY * rBoxes.size()))
3312 : {
3313 : OSL_FAIL( "Line's Boxes are too small or too large" );
3314 : }
3315 : }
3316 : #endif
3317 :
3318 0 : static _FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo,
3319 : SwTableSortBoxes& rTmpLst, SwTwips nDistStt )
3320 : {
3321 : // Find all Boxes/Lines
3322 0 : SwTable& rTable = rParam.pTableNd->GetTable();
3323 :
3324 0 : if (rParam.m_Boxes.empty())
3325 : {
3326 : // Get the Boxes
3327 0 : if( rParam.bBigger )
3328 0 : for( auto pLn : rTable.GetTabLines() )
3329 0 : ::lcl_DelSelBox( pLn, rParam, nDistStt, true );
3330 : else
3331 0 : for( auto pLn : rTable.GetTabLines() )
3332 0 : ::lcl_InsSelBox( pLn, rParam, nDistStt, true );
3333 : }
3334 :
3335 : // Prevent deleting the whole Table
3336 0 : if (rParam.bBigger
3337 0 : && rParam.m_Boxes.size() == rTable.GetTabSortBoxes().size())
3338 : {
3339 0 : return 0;
3340 : }
3341 :
3342 0 : _FndBox* pFndBox = new _FndBox( 0, 0 );
3343 0 : if( rParam.bBigger )
3344 0 : pFndBox->SetTableLines( rParam.m_Boxes, rTable );
3345 : else
3346 : {
3347 0 : _FndPara aPara(rParam.m_Boxes, pFndBox);
3348 0 : ForEach_FndLineCopyCol( rTable.GetTabLines(), &aPara );
3349 : OSL_ENSURE( pFndBox->GetLines().size(), "Where are the Boxes" );
3350 0 : pFndBox->SetTableLines( rTable );
3351 :
3352 0 : if( ppUndo )
3353 0 : rTmpLst.insert( rTable.GetTabSortBoxes() );
3354 : }
3355 :
3356 : // Find Lines for the Layout update
3357 0 : pFndBox->DelFrms( rTable );
3358 :
3359 : // TL_CHART2: this function gest called from SetColWidth exclusively,
3360 : // thus it is currently speculated that nothing needs to be done here.
3361 : // Note: that SetColWidth is currently not completely understood though :-(
3362 :
3363 0 : return pFndBox;
3364 : }
3365 :
3366 0 : bool SwTable::SetColWidth( SwTableBox& rAktBox, sal_uInt16 eType,
3367 : SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo )
3368 : {
3369 0 : SetHTMLTableLayout( 0 ); // Delete HTML Layout
3370 :
3371 0 : const SwFormatFrmSize& rSz = GetFrameFormat()->GetFrmSize();
3372 0 : const SvxLRSpaceItem& rLR = GetFrameFormat()->GetLRSpace();
3373 :
3374 0 : boost::scoped_ptr<_FndBox> xFndBox; // for insertion/deletion
3375 0 : SwTableSortBoxes aTmpLst; // for Undo
3376 : bool bBigger,
3377 0 : bRet = false,
3378 0 : bLeft = nsTableChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
3379 0 : nsTableChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ),
3380 0 : bInsDel = 0 != (eType & nsTableChgWidthHeightType::WH_FLAG_INSDEL );
3381 : sal_uInt16 n;
3382 0 : sal_uLong nBoxIdx = rAktBox.GetSttIdx();
3383 :
3384 : // Get the current Box's edge
3385 : // Only needed for manipulating the width
3386 0 : const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft );
3387 0 : SwTwips nDistStt = 0;
3388 : CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(),
3389 0 : bLeft ? nDist : rSz.GetWidth() - nDist,
3390 0 : const_cast<SwTableNode*>(rAktBox.GetSttNd()->FindTableNode()) );
3391 0 : bBigger = aParam.bBigger;
3392 :
3393 : FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
3394 0 : if( bInsDel )
3395 : {
3396 0 : if( bBigger )
3397 : {
3398 0 : fnSelBox = lcl_DelSelBox;
3399 0 : fnOtherBox = lcl_DelOtherBox;
3400 0 : aParam.nBoxWidth = (sal_uInt16)rAktBox.GetFrameFormat()->GetFrmSize().GetWidth();
3401 0 : if( bLeft )
3402 0 : nDistStt = rSz.GetWidth();
3403 : }
3404 : else
3405 : {
3406 0 : fnSelBox = lcl_InsSelBox;
3407 0 : fnOtherBox = lcl_InsOtherBox;
3408 : }
3409 : }
3410 : else
3411 : {
3412 0 : fnSelBox = lcl_SetSelBoxWidth;
3413 0 : fnOtherBox = lcl_SetOtherBoxWidth;
3414 : }
3415 :
3416 0 : switch( eType & 0xff )
3417 : {
3418 : case nsTableChgWidthHeightType::WH_COL_RIGHT:
3419 : case nsTableChgWidthHeightType::WH_COL_LEFT:
3420 0 : if( TBLVAR_CHGABS == eTableChgMode )
3421 : {
3422 0 : if( bInsDel )
3423 0 : bBigger = !bBigger;
3424 :
3425 : // First test if we have room at all
3426 0 : bool bChgLRSpace = true;
3427 0 : if( bBigger )
3428 : {
3429 0 : if( GetFrameFormat()->getIDocumentSettingAccess()->get(DocumentSettingId::BROWSE_MODE) &&
3430 0 : !rSz.GetWidthPercent() )
3431 : {
3432 0 : bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff;
3433 0 : bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
3434 0 : : rLR.GetRight() >= nAbsDiff;
3435 : }
3436 : else
3437 0 : bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
3438 0 : : rLR.GetRight() >= nAbsDiff;
3439 :
3440 0 : if( !bRet && bInsDel &&
3441 : // Is the room on the other side?
3442 0 : ( bLeft ? rLR.GetRight() >= nAbsDiff
3443 0 : : rLR.GetLeft() >= nAbsDiff ))
3444 : {
3445 0 : bRet = true; bLeft = !bLeft;
3446 : }
3447 :
3448 0 : if( !bRet )
3449 : {
3450 : // Then call itself recursively; only with another mode (proportional)
3451 0 : TableChgMode eOld = eTableChgMode;
3452 0 : eTableChgMode = TBLFIX_CHGPROP;
3453 :
3454 : bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
3455 0 : ppUndo );
3456 0 : eTableChgMode = eOld;
3457 0 : return bRet;
3458 : }
3459 : }
3460 : else
3461 : {
3462 0 : bRet = true;
3463 0 : for( n = 0; n < aLines.size(); ++n )
3464 : {
3465 0 : aParam.LoopClear();
3466 0 : if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, true ))
3467 : {
3468 0 : bRet = false;
3469 0 : break;
3470 : }
3471 : }
3472 : }
3473 :
3474 0 : if( bRet )
3475 : {
3476 0 : if( bInsDel )
3477 : {
3478 : xFndBox.reset(::lcl_SaveInsDelData( aParam, ppUndo,
3479 0 : aTmpLst, nDistStt));
3480 0 : if (aParam.bBigger &&
3481 0 : aParam.m_Boxes.size() == m_TabSortContentBoxes.size())
3482 : {
3483 : // This whole Table is to be deleted!
3484 0 : GetFrameFormat()->GetDoc()->DeleteRowCol(aParam.m_Boxes);
3485 0 : return false;
3486 : }
3487 :
3488 0 : if( ppUndo )
3489 : *ppUndo = aParam.CreateUndo(
3490 : aParam.bBigger ? UNDO_COL_DELETE
3491 0 : : UNDO_TABLE_INSCOL );
3492 : }
3493 0 : else if( ppUndo )
3494 0 : *ppUndo = new SwUndoAttrTable( *aParam.pTableNd, true );
3495 :
3496 0 : long nFrmWidth = LONG_MAX;
3497 0 : LockModify();
3498 0 : SwFormatFrmSize aSz( rSz );
3499 0 : SvxLRSpaceItem aLR( rLR );
3500 0 : if( bBigger )
3501 : {
3502 : // If the Table does not have any room to grow, we need to create some!
3503 0 : if( aSz.GetWidth() + nRelDiff > USHRT_MAX )
3504 : {
3505 : // Break down to USHRT_MAX / 2
3506 0 : CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2,
3507 0 : 0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTableNd );
3508 0 : for( size_t nLn = 0; nLn < aLines.size(); ++nLn )
3509 0 : ::lcl_AjustLines( aLines[ nLn ], aTmpPara );
3510 0 : aSz.SetWidth( aSz.GetWidth() / 2 );
3511 0 : aParam.nDiff = nRelDiff /= 2;
3512 0 : aParam.nSide /= 2;
3513 0 : aParam.nMaxSize /= 2;
3514 : }
3515 :
3516 0 : if( bLeft )
3517 0 : aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) );
3518 : else
3519 0 : aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) );
3520 : }
3521 0 : else if( bLeft )
3522 0 : aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) );
3523 : else
3524 0 : aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) );
3525 :
3526 0 : if( bChgLRSpace )
3527 0 : GetFrameFormat()->SetFormatAttr( aLR );
3528 0 : const SwFormatHoriOrient& rHOri = GetFrameFormat()->GetHoriOrient();
3529 0 : if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
3530 0 : (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
3531 0 : (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
3532 : {
3533 0 : SwFormatHoriOrient aHOri( rHOri );
3534 0 : aHOri.SetHoriOrient( text::HoriOrientation::NONE );
3535 0 : GetFrameFormat()->SetFormatAttr( aHOri );
3536 :
3537 : // If the Table happens to contain relative values (USHORT_MAX),
3538 : // we need to convert them to absolute ones now.
3539 : // Bug 61494
3540 0 : if( GetFrameFormat()->getIDocumentSettingAccess()->get(DocumentSettingId::BROWSE_MODE) &&
3541 0 : !rSz.GetWidthPercent() )
3542 : {
3543 0 : SwTabFrm* pTabFrm = SwIterator<SwTabFrm,SwFormat>( *GetFrameFormat() ).First();
3544 0 : if( pTabFrm &&
3545 0 : pTabFrm->Prt().Width() != rSz.GetWidth() )
3546 : {
3547 0 : nFrmWidth = pTabFrm->Prt().Width();
3548 0 : if( bBigger )
3549 0 : nFrmWidth += nAbsDiff;
3550 : else
3551 0 : nFrmWidth -= nAbsDiff;
3552 : }
3553 0 : }
3554 : }
3555 :
3556 0 : if( bBigger )
3557 0 : aSz.SetWidth( aSz.GetWidth() + nRelDiff );
3558 : else
3559 0 : aSz.SetWidth( aSz.GetWidth() - nRelDiff );
3560 :
3561 0 : if( rSz.GetWidthPercent() )
3562 0 : aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) /
3563 0 : ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
3564 :
3565 0 : GetFrameFormat()->SetFormatAttr( aSz );
3566 0 : aParam.nTableWidth = sal_uInt16( aSz.GetWidth() );
3567 :
3568 0 : UnlockModify();
3569 :
3570 0 : for( n = aLines.size(); n; )
3571 : {
3572 0 : --n;
3573 0 : aParam.LoopClear();
3574 0 : (*fnSelBox)( aLines[ n ], aParam, nDistStt, false );
3575 : }
3576 :
3577 : // If the Table happens to contain relative values (USHORT_MAX),
3578 : // we need to convert them to absolute ones now.
3579 : // Bug 61494
3580 0 : if( LONG_MAX != nFrmWidth )
3581 : {
3582 0 : SwFormatFrmSize aAbsSz( aSz );
3583 0 : aAbsSz.SetWidth( nFrmWidth );
3584 0 : GetFrameFormat()->SetFormatAttr( aAbsSz );
3585 0 : }
3586 : }
3587 : }
3588 0 : else if( bInsDel ||
3589 0 : ( bLeft ? nDist != 0 : std::abs( rSz.GetWidth() - nDist ) > COLFUZZY ) )
3590 : {
3591 0 : bRet = true;
3592 0 : if( bLeft && TBLFIX_CHGABS == eTableChgMode && !bInsDel )
3593 0 : aParam.bBigger = !bBigger;
3594 :
3595 : // First test if we have room at all
3596 0 : if( bInsDel )
3597 : {
3598 0 : if( aParam.bBigger )
3599 : {
3600 0 : for( n = 0; n < aLines.size(); ++n )
3601 : {
3602 0 : aParam.LoopClear();
3603 0 : if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, true ))
3604 : {
3605 0 : bRet = false;
3606 0 : break;
3607 : }
3608 : }
3609 : }
3610 : else
3611 : {
3612 0 : if( ( bRet = bLeft ? nDist != 0
3613 0 : : ( rSz.GetWidth() - nDist ) > COLFUZZY ) )
3614 : {
3615 0 : for( n = 0; n < aLines.size(); ++n )
3616 : {
3617 0 : aParam.LoopClear();
3618 0 : if( !(*fnOtherBox)( aLines[ n ], aParam, 0, true ))
3619 : {
3620 0 : bRet = false;
3621 0 : break;
3622 : }
3623 : }
3624 0 : if( bRet && !aParam.bAnyBoxFnd )
3625 0 : bRet = false;
3626 : }
3627 :
3628 0 : if( !bRet && rAktBox.GetFrameFormat()->GetFrmSize().GetWidth()
3629 0 : - nRelDiff > COLFUZZY +
3630 : ( 567 / 2 /*leave room for at least 0.5 cm*/) )
3631 : {
3632 : // Consume the space from the current Cell
3633 0 : aParam.bSplittBox = true;
3634 : // We also need to test this!
3635 0 : bRet = true;
3636 :
3637 0 : for( n = 0; n < aLines.size(); ++n )
3638 : {
3639 0 : aParam.LoopClear();
3640 0 : if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, true ))
3641 : {
3642 0 : bRet = false;
3643 0 : break;
3644 : }
3645 : }
3646 : }
3647 : }
3648 : }
3649 0 : else if( aParam.bBigger )
3650 : {
3651 0 : for( n = 0; n < aLines.size(); ++n )
3652 : {
3653 0 : aParam.LoopClear();
3654 0 : if( !(*fnOtherBox)( aLines[ n ], aParam, 0, true ))
3655 : {
3656 0 : bRet = false;
3657 0 : break;
3658 : }
3659 : }
3660 : }
3661 : else
3662 : {
3663 0 : for( n = 0; n < aLines.size(); ++n )
3664 : {
3665 0 : aParam.LoopClear();
3666 0 : if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, true ))
3667 : {
3668 0 : bRet = false;
3669 0 : break;
3670 : }
3671 : }
3672 : }
3673 :
3674 : // If true, set it
3675 0 : if( bRet )
3676 : {
3677 0 : CR_SetBoxWidth aParam1( aParam );
3678 0 : if( bInsDel )
3679 : {
3680 0 : aParam1.bBigger = !aParam.bBigger;
3681 0 : xFndBox.reset(::lcl_SaveInsDelData(aParam, ppUndo, aTmpLst, nDistStt));
3682 0 : if( ppUndo )
3683 : *ppUndo = aParam.CreateUndo(
3684 : aParam.bBigger ? UNDO_TABLE_DELBOX
3685 0 : : UNDO_TABLE_INSCOL );
3686 : }
3687 0 : else if( ppUndo )
3688 0 : *ppUndo = new SwUndoAttrTable( *aParam.pTableNd, true );
3689 :
3690 0 : if( bInsDel
3691 0 : ? ( TBLFIX_CHGABS == eTableChgMode ? (bBigger && bLeft) : bLeft )
3692 0 : : ( TBLFIX_CHGABS != eTableChgMode && bLeft ) )
3693 : {
3694 0 : for( n = aLines.size(); n; )
3695 : {
3696 0 : --n;
3697 0 : aParam.LoopClear();
3698 0 : aParam1.LoopClear();
3699 0 : (*fnSelBox)( aLines[ n ], aParam, nDistStt, false );
3700 0 : (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, false );
3701 : }
3702 : }
3703 : else
3704 : {
3705 0 : for( n = aLines.size(); n; )
3706 : {
3707 0 : --n;
3708 0 : aParam.LoopClear();
3709 0 : aParam1.LoopClear();
3710 0 : (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, false );
3711 0 : (*fnSelBox)( aLines[ n ], aParam, nDistStt, false );
3712 : }
3713 0 : }
3714 : }
3715 : }
3716 0 : break;
3717 :
3718 : case nsTableChgWidthHeightType::WH_CELL_RIGHT:
3719 : case nsTableChgWidthHeightType::WH_CELL_LEFT:
3720 0 : if( TBLVAR_CHGABS == eTableChgMode )
3721 : {
3722 : // Then call itself recursively; only with another mode (proportional)
3723 0 : TableChgMode eOld = eTableChgMode;
3724 0 : eTableChgMode = TBLFIX_CHGABS;
3725 :
3726 : bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
3727 0 : ppUndo );
3728 0 : eTableChgMode = eOld;
3729 0 : return bRet;
3730 : }
3731 0 : else if( bInsDel || ( bLeft ? nDist != 0
3732 0 : : (rSz.GetWidth() - nDist) > COLFUZZY ))
3733 : {
3734 0 : if( bLeft && TBLFIX_CHGABS == eTableChgMode && !bInsDel )
3735 0 : aParam.bBigger = !bBigger;
3736 :
3737 : // First, see if there is enough room at all
3738 0 : SwTableBox* pBox = &rAktBox;
3739 0 : SwTableLine* pLine = rAktBox.GetUpper();
3740 0 : while( pLine->GetUpper() )
3741 : {
3742 0 : const SwTableBoxes::size_type nPos = pLine->GetTabBoxes().GetPos( pBox );
3743 0 : if( bLeft ? nPos != 0 : nPos + 1 != pLine->GetTabBoxes().size() )
3744 0 : break;
3745 :
3746 0 : pBox = pLine->GetUpper();
3747 0 : pLine = pBox->GetUpper();
3748 : }
3749 :
3750 0 : if( pLine->GetUpper() )
3751 : {
3752 : // We need to correct the distance once again!
3753 0 : aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), true );
3754 :
3755 0 : if( bLeft )
3756 0 : aParam.nMaxSize = aParam.nSide;
3757 : else
3758 0 : aParam.nMaxSize = pLine->GetUpper()->GetFrameFormat()->
3759 0 : GetFrmSize().GetWidth() - aParam.nSide;
3760 : }
3761 :
3762 : // First, see if there is enough room at all
3763 0 : if( bInsDel )
3764 : {
3765 0 : if( ( bRet = bLeft ? nDist != 0
3766 0 : : ( rSz.GetWidth() - nDist ) > COLFUZZY ) &&
3767 0 : !aParam.bBigger )
3768 : {
3769 0 : bRet = (*fnOtherBox)( pLine, aParam, 0, true );
3770 0 : if( bRet && !aParam.bAnyBoxFnd )
3771 0 : bRet = false;
3772 : }
3773 :
3774 0 : if( !bRet && !aParam.bBigger && rAktBox.GetFrameFormat()->
3775 0 : GetFrmSize().GetWidth() - nRelDiff > COLFUZZY +
3776 : ( 567 / 2 /*leave room for at least 0.5 cm*/) )
3777 : {
3778 : // Consume the room from the current Cell
3779 0 : aParam.bSplittBox = true;
3780 0 : bRet = true;
3781 : }
3782 : }
3783 : else
3784 : {
3785 0 : FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
3786 0 : bRet = (*fnTmp)( pLine, aParam, nDistStt, true );
3787 : }
3788 :
3789 : // If true, set it
3790 0 : if( bRet )
3791 : {
3792 0 : CR_SetBoxWidth aParam1( aParam );
3793 0 : if( bInsDel )
3794 : {
3795 0 : aParam1.bBigger = !aParam.bBigger;
3796 0 : xFndBox.reset(::lcl_SaveInsDelData(aParam, ppUndo, aTmpLst, nDistStt));
3797 0 : if( ppUndo )
3798 : *ppUndo = aParam.CreateUndo(
3799 : aParam.bBigger ? UNDO_TABLE_DELBOX
3800 0 : : UNDO_TABLE_INSCOL );
3801 : }
3802 0 : else if( ppUndo )
3803 0 : *ppUndo = new SwUndoAttrTable( *aParam.pTableNd, true );
3804 :
3805 0 : if( bInsDel
3806 0 : ? ( TBLFIX_CHGABS == eTableChgMode ? (bBigger && bLeft) : bLeft )
3807 0 : : ( TBLFIX_CHGABS != eTableChgMode && bLeft ) )
3808 : {
3809 0 : (*fnSelBox)( pLine, aParam, nDistStt, false );
3810 0 : (*fnOtherBox)( pLine, aParam1, nDistStt, false );
3811 : }
3812 : else
3813 : {
3814 0 : (*fnOtherBox)( pLine, aParam1, nDistStt, false );
3815 0 : (*fnSelBox)( pLine, aParam, nDistStt, false );
3816 0 : }
3817 : }
3818 : }
3819 0 : break;
3820 :
3821 : }
3822 :
3823 0 : if( xFndBox )
3824 : {
3825 : // Clean up the structure of all Lines
3826 0 : GCLines();
3827 :
3828 : // Update Layout
3829 0 : if( !bBigger || xFndBox->AreLinesToRestore( *this ) )
3830 0 : xFndBox->MakeFrms( *this );
3831 :
3832 : // TL_CHART2: it is currently unclear if sth has to be done here.
3833 : // The function name hints that nothing needs to be done, on the other
3834 : // hand there is a case where sth gets deleted. :-(
3835 :
3836 0 : xFndBox.reset();
3837 :
3838 0 : if( ppUndo && *ppUndo )
3839 : {
3840 : aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTableChgMode), eType,
3841 0 : nAbsDiff, nRelDiff );
3842 0 : if( !aParam.bBigger )
3843 0 : aParam.pUndo->SaveNewBoxes( *aParam.pTableNd, aTmpLst );
3844 : }
3845 : }
3846 :
3847 : if( bRet )
3848 : {
3849 : CHECKBOXWIDTH
3850 : CHECKTABLELAYOUT
3851 : }
3852 :
3853 0 : return bRet;
3854 : }
3855 :
3856 0 : static _FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo,
3857 : SwTableSortBoxes& rTmpLst )
3858 : {
3859 : // Find all Boxes/Lines
3860 0 : SwTable& rTable = rParam.pTableNd->GetTable();
3861 :
3862 : OSL_ENSURE( !rParam.m_Boxes.empty(), "We can't go on without Boxes!" );
3863 :
3864 : // Prevent deleting the whole Table
3865 0 : if (!rParam.bBigger
3866 0 : && rParam.m_Boxes.size() == rTable.GetTabSortBoxes().size())
3867 : {
3868 0 : return 0;
3869 : }
3870 :
3871 0 : _FndBox* pFndBox = new _FndBox( 0, 0 );
3872 0 : if( !rParam.bBigger )
3873 0 : pFndBox->SetTableLines( rParam.m_Boxes, rTable );
3874 : else
3875 : {
3876 0 : _FndPara aPara(rParam.m_Boxes, pFndBox);
3877 0 : ForEach_FndLineCopyCol( rTable.GetTabLines(), &aPara );
3878 : OSL_ENSURE( pFndBox->GetLines().size(), "Where are the Boxes?" );
3879 0 : pFndBox->SetTableLines( rTable );
3880 :
3881 0 : if( ppUndo )
3882 0 : rTmpLst.insert( rTable.GetTabSortBoxes() );
3883 : }
3884 :
3885 : // Find Lines for the Layout update
3886 0 : pFndBox->DelFrms( rTable );
3887 :
3888 : // TL_CHART2: it is currently unclear if sth has to be done here.
3889 :
3890 0 : return pFndBox;
3891 : }
3892 :
3893 0 : void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
3894 : bool bMinSize )
3895 : {
3896 0 : SwLayoutFrm* pLineFrm = GetRowFrm( rLine );
3897 : OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine?" );
3898 :
3899 0 : SwFrameFormat* pFormat = rLine.ClaimFrameFormat();
3900 :
3901 0 : SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height();
3902 0 : if( !nOldHeight ) // the BaseLine and absolute
3903 0 : nMyNewH = nMyOldH + nNewHeight;
3904 : else
3905 : {
3906 : // Calculate as exactly as possible
3907 0 : Fraction aTmp( nMyOldH );
3908 0 : aTmp *= Fraction( nNewHeight, nOldHeight );
3909 0 : aTmp += Fraction( 1, 2 ); // round up if needed
3910 0 : nMyNewH = aTmp;
3911 : }
3912 :
3913 0 : SwFrmSize eSize = ATT_MIN_SIZE;
3914 0 : if( !bMinSize &&
3915 0 : ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY ))
3916 0 : eSize = ATT_FIX_SIZE;
3917 :
3918 0 : pFormat->SetFormatAttr( SwFormatFrmSize( eSize, 0, nMyNewH ) );
3919 :
3920 : // First adapt all internal ones
3921 0 : for( auto pBox : rLine.GetTabBoxes() )
3922 : {
3923 0 : for( auto pLine : pBox->GetTabLines() )
3924 0 : SetLineHeight( *pLine, nMyOldH, nMyNewH, bMinSize );
3925 : }
3926 0 : }
3927 :
3928 0 : static bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
3929 : SwTwips nDist, bool bCheck )
3930 : {
3931 0 : bool bRet = true;
3932 0 : if( !bCheck )
3933 : {
3934 : // Set line height
3935 : SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
3936 0 : rParam.bBigger );
3937 : }
3938 0 : else if( !rParam.bBigger )
3939 : {
3940 : // Calculate the new relative size by means of the old one
3941 0 : SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
3942 : OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine?" );
3943 0 : SwTwips nRstHeight = CalcRowRstHeight( pLineFrm );
3944 0 : if( (nRstHeight + ROWFUZZY) < nDist )
3945 0 : bRet = false;
3946 : }
3947 0 : return bRet;
3948 : }
3949 :
3950 0 : static bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
3951 : SwTwips nDist, bool bCheck )
3952 : {
3953 0 : bool bRet = true;
3954 0 : if( bCheck )
3955 : {
3956 0 : if( rParam.bBigger )
3957 : {
3958 : // Calculate the new relative size by means of the old one
3959 0 : SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
3960 : OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine?" );
3961 :
3962 0 : if( TBLFIX_CHGPROP == rParam.nMode )
3963 : {
3964 0 : nDist *= pLineFrm->Frm().Height();
3965 0 : nDist /= rParam.nMaxHeight;
3966 : }
3967 0 : bRet = nDist <= CalcRowRstHeight( pLineFrm );
3968 : }
3969 : }
3970 : else
3971 : {
3972 : // Set line height
3973 : // pLine is the following/preceding, thus adjust it
3974 0 : if( TBLFIX_CHGPROP == rParam.nMode )
3975 : {
3976 0 : SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
3977 : OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine??" );
3978 :
3979 : // Calculate the new relative size by means of the old one
3980 : // If the selected Box get bigger, adjust via the max space else
3981 : // via the max height.
3982 : if( true /*!rParam.bBigger*/ )
3983 : {
3984 0 : nDist *= pLineFrm->Frm().Height();
3985 0 : nDist /= rParam.nMaxHeight;
3986 : }
3987 : else
3988 : {
3989 : // Calculate the new relative size by means of the old one
3990 : nDist *= CalcRowRstHeight( pLineFrm );
3991 : nDist /= rParam.nMaxSpace;
3992 : }
3993 : }
3994 : SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
3995 0 : !rParam.bBigger );
3996 : }
3997 0 : return bRet;
3998 : }
3999 :
4000 0 : static bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
4001 : SwTwips nDist, bool bCheck )
4002 : {
4003 0 : bool bRet = true;
4004 0 : if( !bCheck )
4005 : {
4006 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
4007 0 : SwDoc* pDoc = pLine->GetFrameFormat()->GetDoc();
4008 0 : if( !rParam.bBigger )
4009 : {
4010 0 : for (size_t n = rBoxes.size(); n; )
4011 : {
4012 0 : ::lcl_SaveUpperLowerBorder( rParam.pTableNd->GetTable(),
4013 0 : *rBoxes[ --n ],
4014 0 : rParam.aShareFormats );
4015 : }
4016 0 : for (size_t n = rBoxes.size(); n; )
4017 : {
4018 0 : ::_DeleteBox( rParam.pTableNd->GetTable(),
4019 0 : rBoxes[ --n ], rParam.pUndo, false,
4020 0 : false, &rParam.aShareFormats );
4021 : }
4022 : }
4023 : else
4024 : {
4025 : // Insert Line
4026 : SwTableLine* pNewLine = new SwTableLine( static_cast<SwTableLineFormat*>(pLine->GetFrameFormat()),
4027 0 : rBoxes.size(), pLine->GetUpper() );
4028 : SwTableLines* pLines;
4029 0 : if( pLine->GetUpper() )
4030 0 : pLines = &pLine->GetUpper()->GetTabLines();
4031 : else
4032 0 : pLines = &rParam.pTableNd->GetTable().GetTabLines();
4033 0 : sal_uInt16 nPos = pLines->GetPos( pLine );
4034 0 : if( !rParam.bTop )
4035 0 : ++nPos;
4036 0 : pLines->insert( pLines->begin() + nPos, pNewLine );
4037 :
4038 0 : SwFrameFormat* pNewFormat = pNewLine->ClaimFrameFormat();
4039 0 : pNewFormat->SetFormatAttr( SwFormatFrmSize( ATT_MIN_SIZE, 0, nDist ) );
4040 :
4041 : // And once again calculate the Box count
4042 0 : SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes();
4043 0 : for( SwTableBoxes::size_type n = 0; n < rBoxes.size(); ++n )
4044 : {
4045 0 : SwTwips nWidth = 0;
4046 0 : SwTableBox* pOld = rBoxes[ n ];
4047 0 : if( !pOld->GetSttNd() )
4048 : {
4049 : // Not a normal content Box, so fall back to the 1st next Box
4050 0 : nWidth = pOld->GetFrameFormat()->GetFrmSize().GetWidth();
4051 0 : while( !pOld->GetSttNd() )
4052 0 : pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
4053 : }
4054 : ::_InsTableBox( pDoc, rParam.pTableNd, pNewLine,
4055 0 : static_cast<SwTableBoxFormat*>(pOld->GetFrameFormat()), pOld, n );
4056 :
4057 : // Special treatment for the border:
4058 : // The top one needs to be removed
4059 0 : const SvxBoxItem& rBoxItem = pOld->GetFrameFormat()->GetBox();
4060 0 : if( rBoxItem.GetTop() )
4061 : {
4062 0 : SvxBoxItem aTmp( rBoxItem );
4063 0 : aTmp.SetLine( 0, SvxBoxItemLine::TOP );
4064 : rParam.aShareFormats.SetAttr( rParam.bTop
4065 : ? *pOld
4066 0 : : *rNewBoxes[ n ], aTmp );
4067 : }
4068 :
4069 0 : if( nWidth )
4070 0 : rParam.aShareFormats.SetAttr( *rNewBoxes[ n ],
4071 0 : SwFormatFrmSize( ATT_FIX_SIZE, nWidth, 0 ) );
4072 : }
4073 : }
4074 : }
4075 : else
4076 : {
4077 : // Collect Boxes!
4078 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
4079 0 : for( auto n = rBoxes.size(); n; )
4080 : {
4081 0 : SwTableBox* pBox = rBoxes[ --n ];
4082 0 : if( pBox->GetFrameFormat()->GetProtect().IsContentProtected() )
4083 0 : return false;
4084 :
4085 0 : if( pBox->GetSttNd() )
4086 : {
4087 0 : rParam.m_Boxes.insert(pBox);
4088 : }
4089 : else
4090 : {
4091 0 : for( auto i = pBox->GetTabLines().size(); i; )
4092 0 : lcl_InsDelSelLine( pBox->GetTabLines()[ --i ],
4093 0 : rParam, 0, true );
4094 : }
4095 : }
4096 : }
4097 0 : return bRet;
4098 : }
4099 :
4100 0 : bool SwTable::SetRowHeight( SwTableBox& rAktBox, sal_uInt16 eType,
4101 : SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo )
4102 : {
4103 0 : SwTableLine* pLine = rAktBox.GetUpper();
4104 :
4105 0 : SwTableLine* pBaseLine = pLine;
4106 0 : while( pBaseLine->GetUpper() )
4107 0 : pBaseLine = pBaseLine->GetUpper()->GetUpper();
4108 :
4109 0 : boost::scoped_ptr<_FndBox> xFndBox; // for insertion/deletion
4110 0 : SwTableSortBoxes aTmpLst; // for Undo
4111 : bool bBigger,
4112 0 : bRet = false,
4113 0 : bTop = nsTableChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) ||
4114 0 : nsTableChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ),
4115 0 : bInsDel = 0 != (eType & nsTableChgWidthHeightType::WH_FLAG_INSDEL );
4116 0 : sal_uInt16 nBaseLinePos = GetTabLines().GetPos( pBaseLine );
4117 0 : sal_uLong nBoxIdx = rAktBox.GetSttIdx();
4118 :
4119 : CR_SetLineHeight aParam( eType,
4120 0 : const_cast<SwTableNode*>(rAktBox.GetSttNd()->FindTableNode()) );
4121 0 : bBigger = aParam.bBigger;
4122 :
4123 0 : FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight;
4124 0 : if( bInsDel )
4125 0 : fnSelLine = lcl_InsDelSelLine;
4126 : else
4127 0 : fnSelLine = lcl_SetSelLineHeight;
4128 :
4129 0 : SwTableLines* pLines = &aLines;
4130 :
4131 : // How do we get to the height?
4132 0 : switch( eType & 0xff )
4133 : {
4134 : case nsTableChgWidthHeightType::WH_CELL_TOP:
4135 : case nsTableChgWidthHeightType::WH_CELL_BOTTOM:
4136 0 : if( pLine == pBaseLine )
4137 0 : break; // it doesn't work then!
4138 :
4139 : // Is a nested Line (Box!)
4140 0 : pLines = &pLine->GetUpper()->GetTabLines();
4141 0 : nBaseLinePos = pLines->GetPos( pLine );
4142 0 : pBaseLine = pLine;
4143 : // no break!
4144 :
4145 : case nsTableChgWidthHeightType::WH_ROW_TOP:
4146 : case nsTableChgWidthHeightType::WH_ROW_BOTTOM:
4147 : {
4148 0 : if( bInsDel && !bBigger ) // By how much does it get higher?
4149 : {
4150 0 : nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height();
4151 : }
4152 :
4153 0 : if( TBLVAR_CHGABS == eTableChgMode )
4154 : {
4155 : // First test if we have room at all
4156 0 : if( bBigger )
4157 0 : bRet = true;
4158 : else
4159 0 : bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4160 0 : nAbsDiff, true );
4161 :
4162 0 : if( bRet )
4163 : {
4164 0 : if( bInsDel )
4165 : {
4166 0 : if (aParam.m_Boxes.empty())
4167 : {
4168 0 : ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
4169 0 : aParam, 0, true );
4170 : }
4171 :
4172 0 : xFndBox.reset(::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst ));
4173 :
4174 : // delete complete table when last row is deleted
4175 0 : if( !bBigger &&
4176 0 : aParam.m_Boxes.size() == m_TabSortContentBoxes.size())
4177 : {
4178 0 : GetFrameFormat()->GetDoc()->DeleteRowCol(aParam.m_Boxes);
4179 0 : return false;
4180 : }
4181 :
4182 0 : if( ppUndo )
4183 : *ppUndo = aParam.CreateUndo(
4184 : bBigger ? UNDO_TABLE_INSROW
4185 0 : : UNDO_ROW_DELETE );
4186 : }
4187 0 : else if( ppUndo )
4188 0 : *ppUndo = new SwUndoAttrTable( *aParam.pTableNd, true );
4189 :
4190 0 : (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4191 0 : nAbsDiff, false );
4192 : }
4193 : }
4194 : else
4195 : {
4196 0 : bRet = true;
4197 : SwTableLines::size_type nStt;
4198 : SwTableLines::size_type nEnd;
4199 0 : if( bTop )
4200 0 : nStt = 0, nEnd = nBaseLinePos;
4201 : else
4202 0 : nStt = nBaseLinePos + 1, nEnd = pLines->size();
4203 :
4204 : // Get the current Lines' height
4205 0 : if( TBLFIX_CHGPROP == eTableChgMode )
4206 : {
4207 0 : for( auto n = nStt; n < nEnd; ++n )
4208 : {
4209 0 : SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] );
4210 : OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine??" );
4211 0 : aParam.nMaxSpace += CalcRowRstHeight( pLineFrm );
4212 0 : aParam.nMaxHeight += pLineFrm->Frm().Height();
4213 : }
4214 0 : if( bBigger && aParam.nMaxSpace < nAbsDiff )
4215 0 : bRet = false;
4216 : }
4217 : else
4218 : {
4219 0 : if( bTop ? nEnd != 0 : nStt < nEnd )
4220 : {
4221 0 : if( bTop )
4222 0 : nStt = nEnd - 1;
4223 : else
4224 0 : nEnd = nStt + 1;
4225 : }
4226 : else
4227 0 : bRet = false;
4228 : }
4229 :
4230 0 : if( bRet )
4231 : {
4232 0 : if( bBigger )
4233 : {
4234 0 : for( auto n = nStt; n < nEnd; ++n )
4235 : {
4236 0 : if( !(*fnOtherLine)( (*pLines)[ n ], aParam,
4237 0 : nAbsDiff, true ))
4238 : {
4239 0 : bRet = false;
4240 0 : break;
4241 : }
4242 : }
4243 : }
4244 : else
4245 0 : bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4246 0 : nAbsDiff, true );
4247 : }
4248 :
4249 0 : if( bRet )
4250 : {
4251 : // Adjust
4252 0 : if( bInsDel )
4253 : {
4254 0 : if (aParam.m_Boxes.empty())
4255 : {
4256 0 : ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
4257 0 : aParam, 0, true );
4258 : }
4259 0 : xFndBox.reset(::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst ));
4260 0 : if( ppUndo )
4261 : *ppUndo = aParam.CreateUndo(
4262 : bBigger ? UNDO_TABLE_INSROW
4263 0 : : UNDO_ROW_DELETE );
4264 : }
4265 0 : else if( ppUndo )
4266 0 : *ppUndo = new SwUndoAttrTable( *aParam.pTableNd, true );
4267 :
4268 0 : CR_SetLineHeight aParam1( aParam );
4269 0 : if( TBLFIX_CHGPROP == eTableChgMode && !bBigger &&
4270 0 : !aParam.nMaxSpace )
4271 : {
4272 : // We need to distribute the space evenly among all the Lines.
4273 : // That's why we need their count.
4274 0 : aParam1.nLines = nEnd - nStt;
4275 : }
4276 :
4277 0 : if( bTop )
4278 : {
4279 0 : (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4280 0 : nAbsDiff, false );
4281 0 : for( auto n = nStt; n < nEnd; ++n )
4282 0 : (*fnOtherLine)( (*pLines)[ n ], aParam1,
4283 0 : nAbsDiff, false );
4284 : }
4285 : else
4286 : {
4287 0 : for( auto n = nStt; n < nEnd; ++n )
4288 0 : (*fnOtherLine)( (*pLines)[ n ], aParam1,
4289 0 : nAbsDiff, false );
4290 0 : (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4291 0 : nAbsDiff, false );
4292 0 : }
4293 : }
4294 : else
4295 : {
4296 : // Then call itself recursively; only with another mode (proportional)
4297 0 : TableChgMode eOld = eTableChgMode;
4298 0 : eTableChgMode = TBLVAR_CHGABS;
4299 :
4300 : bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
4301 0 : nRelDiff, ppUndo );
4302 :
4303 0 : eTableChgMode = eOld;
4304 0 : xFndBox.reset();
4305 : }
4306 : }
4307 : }
4308 0 : break;
4309 : }
4310 :
4311 0 : if( xFndBox )
4312 : {
4313 : // then clean up the structure of all Lines
4314 0 : GCLines();
4315 :
4316 : // Update Layout
4317 0 : if( bBigger || xFndBox->AreLinesToRestore( *this ) )
4318 0 : xFndBox->MakeFrms( *this );
4319 :
4320 : // TL_CHART2: it is currently unclear if sth has to be done here.
4321 :
4322 0 : xFndBox.reset();
4323 :
4324 0 : if (ppUndo && *ppUndo && aParam.pUndo)
4325 : {
4326 : aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTableChgMode), eType,
4327 0 : nAbsDiff, nRelDiff );
4328 0 : if( bBigger )
4329 0 : aParam.pUndo->SaveNewBoxes( *aParam.pTableNd, aTmpLst );
4330 : }
4331 : }
4332 :
4333 : CHECKTABLELAYOUT
4334 :
4335 0 : return bRet;
4336 : }
4337 :
4338 116 : SwFrameFormat* SwShareBoxFormat::GetFormat( long nWidth ) const
4339 : {
4340 116 : SwFrameFormat *pRet = 0, *pTmp;
4341 487 : for( auto n = aNewFormats.size(); n; )
4342 273 : if( ( pTmp = aNewFormats[ --n ])->GetFrmSize().GetWidth()
4343 : == nWidth )
4344 : {
4345 18 : pRet = pTmp;
4346 18 : break;
4347 : }
4348 116 : return pRet;
4349 : }
4350 :
4351 0 : SwFrameFormat* SwShareBoxFormat::GetFormat( const SfxPoolItem& rItem ) const
4352 : {
4353 : const SfxPoolItem* pItem;
4354 0 : sal_uInt16 nWhich = rItem.Which();
4355 0 : SwFrameFormat *pRet = 0, *pTmp;
4356 0 : const SfxPoolItem& rFrmSz = pOldFormat->GetFormatAttr( RES_FRM_SIZE, false );
4357 0 : for( auto n = aNewFormats.size(); n; )
4358 0 : if( SfxItemState::SET == ( pTmp = aNewFormats[ --n ])->
4359 0 : GetItemState( nWhich, false, &pItem ) && *pItem == rItem &&
4360 0 : pTmp->GetFormatAttr( RES_FRM_SIZE, false ) == rFrmSz )
4361 : {
4362 0 : pRet = pTmp;
4363 0 : break;
4364 : }
4365 0 : return pRet;
4366 : }
4367 :
4368 6864 : void SwShareBoxFormat::AddFormat( SwFrameFormat& rNew )
4369 : {
4370 6864 : aNewFormats.push_back( &rNew );
4371 6864 : }
4372 :
4373 15 : bool SwShareBoxFormat::RemoveFormat( const SwFrameFormat& rFormat )
4374 : {
4375 : // returns true, if we can delete
4376 15 : if( pOldFormat == &rFormat )
4377 4 : return true;
4378 :
4379 11 : std::vector<SwFrameFormat*>::iterator it = std::find( aNewFormats.begin(), aNewFormats.end(), &rFormat );
4380 11 : if( aNewFormats.end() != it )
4381 1 : aNewFormats.erase( it );
4382 11 : return aNewFormats.empty();
4383 : }
4384 :
4385 3229 : SwShareBoxFormats::~SwShareBoxFormats()
4386 : {
4387 3229 : }
4388 :
4389 6879 : SwFrameFormat* SwShareBoxFormats::GetFormat( const SwFrameFormat& rFormat, long nWidth ) const
4390 : {
4391 : sal_uInt16 nPos;
4392 6879 : return Seek_Entry( rFormat, &nPos )
4393 116 : ? aShareArr[ nPos ].GetFormat( nWidth )
4394 6995 : : 0;
4395 : }
4396 3 : SwFrameFormat* SwShareBoxFormats::GetFormat( const SwFrameFormat& rFormat,
4397 : const SfxPoolItem& rItem ) const
4398 : {
4399 : sal_uInt16 nPos;
4400 3 : return Seek_Entry( rFormat, &nPos )
4401 0 : ? aShareArr[ nPos ].GetFormat( rItem )
4402 3 : : 0;
4403 : }
4404 :
4405 6864 : void SwShareBoxFormats::AddFormat( const SwFrameFormat& rOld, SwFrameFormat& rNew )
4406 : {
4407 : {
4408 : sal_uInt16 nPos;
4409 : SwShareBoxFormat* pEntry;
4410 6864 : if( !Seek_Entry( rOld, &nPos ))
4411 : {
4412 6766 : pEntry = new SwShareBoxFormat( rOld );
4413 6766 : aShareArr.insert( aShareArr.begin() + nPos, pEntry );
4414 : }
4415 : else
4416 98 : pEntry = &aShareArr[ nPos ];
4417 :
4418 6864 : pEntry->AddFormat( rNew );
4419 : }
4420 6864 : }
4421 :
4422 18 : void SwShareBoxFormats::ChangeFrameFormat( SwTableBox* pBox, SwTableLine* pLn,
4423 : SwFrameFormat& rFormat )
4424 : {
4425 18 : SwClient aCl;
4426 18 : SwFrameFormat* pOld = 0;
4427 18 : if( pBox )
4428 : {
4429 18 : pOld = pBox->GetFrameFormat();
4430 18 : pOld->Add( &aCl );
4431 18 : pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(&rFormat) );
4432 : }
4433 0 : else if( pLn )
4434 : {
4435 0 : pOld = pLn->GetFrameFormat();
4436 0 : pOld->Add( &aCl );
4437 0 : pLn->ChgFrameFormat( static_cast<SwTableLineFormat*>(&rFormat) );
4438 : }
4439 18 : if( pOld && pOld->HasOnlyOneListener() )
4440 : {
4441 3 : RemoveFormat( *pOld );
4442 3 : delete pOld;
4443 18 : }
4444 18 : }
4445 :
4446 6879 : void SwShareBoxFormats::SetSize( SwTableBox& rBox, const SwFormatFrmSize& rSz )
4447 : {
4448 6879 : SwFrameFormat *pBoxFormat = rBox.GetFrameFormat(),
4449 6879 : *pRet = GetFormat( *pBoxFormat, rSz.GetWidth() );
4450 6879 : if( pRet )
4451 18 : ChangeFrameFormat( &rBox, 0, *pRet );
4452 : else
4453 : {
4454 6861 : pRet = rBox.ClaimFrameFormat();
4455 6861 : pRet->SetFormatAttr( rSz );
4456 6861 : AddFormat( *pBoxFormat, *pRet );
4457 : }
4458 6879 : }
4459 :
4460 3 : void SwShareBoxFormats::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem )
4461 : {
4462 3 : SwFrameFormat *pBoxFormat = rBox.GetFrameFormat(),
4463 3 : *pRet = GetFormat( *pBoxFormat, rItem );
4464 3 : if( pRet )
4465 0 : ChangeFrameFormat( &rBox, 0, *pRet );
4466 : else
4467 : {
4468 3 : pRet = rBox.ClaimFrameFormat();
4469 3 : pRet->SetFormatAttr( rItem );
4470 3 : AddFormat( *pBoxFormat, *pRet );
4471 : }
4472 3 : }
4473 :
4474 0 : void SwShareBoxFormats::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem )
4475 : {
4476 0 : SwFrameFormat *pLineFormat = rLine.GetFrameFormat(),
4477 0 : *pRet = GetFormat( *pLineFormat, rItem );
4478 0 : if( pRet )
4479 0 : ChangeFrameFormat( 0, &rLine, *pRet );
4480 : else
4481 : {
4482 0 : pRet = rLine.ClaimFrameFormat();
4483 0 : pRet->SetFormatAttr( rItem );
4484 0 : AddFormat( *pLineFormat, *pRet );
4485 : }
4486 0 : }
4487 :
4488 12 : void SwShareBoxFormats::RemoveFormat( const SwFrameFormat& rFormat )
4489 : {
4490 39 : for( auto i = aShareArr.size(); i; )
4491 15 : if( aShareArr[ --i ].RemoveFormat( rFormat ))
4492 5 : aShareArr.erase( aShareArr.begin() + i );
4493 12 : }
4494 :
4495 13746 : bool SwShareBoxFormats::Seek_Entry( const SwFrameFormat& rFormat, sal_uInt16* pPos ) const
4496 : {
4497 13746 : sal_uLong nIdx = reinterpret_cast<sal_uLong>(&rFormat);
4498 13746 : _SwShareBoxFormats::size_type nO = aShareArr.size(), nU = 0;
4499 13746 : if( nO > 0 )
4500 : {
4501 9056 : nO--;
4502 30589 : while( nU <= nO )
4503 : {
4504 15031 : const auto nM = nU + ( nO - nU ) / 2;
4505 15031 : sal_uLong nFormat = reinterpret_cast<sal_uLong>(&aShareArr[ nM ].GetOldFormat());
4506 15031 : if( nFormat == nIdx )
4507 : {
4508 214 : if( pPos )
4509 214 : *pPos = nM;
4510 214 : return true;
4511 : }
4512 14817 : else if( nFormat < nIdx )
4513 11538 : nU = nM + 1;
4514 3279 : else if( nM == 0 )
4515 : {
4516 2340 : if( pPos )
4517 2340 : *pPos = nU;
4518 2340 : return false;
4519 : }
4520 : else
4521 939 : nO = nM - 1;
4522 : }
4523 : }
4524 11192 : if( pPos )
4525 11192 : *pPos = nU;
4526 11192 : return false;
4527 177 : }
4528 :
4529 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|