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