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