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