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