xref: /trunk/main/sw/source/core/doc/tblrwcl.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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