merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / doc / tblrwcl.cxx
blobe07062d5dee11d102b1c7d246af10e6648bcedf4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tblrwcl.cxx,v $
10 * $Revision: 1.29 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <com/sun/star/text/HoriOrientation.hpp>
35 #include <com/sun/star/chart2/XChartDocument.hpp>
36 #include <hintids.hxx>
38 #define _ZFORLIST_DECLARE_TABLE
39 #include <svx/brshitem.hxx>
40 #include <svx/lrspitem.hxx>
41 #include <svx/protitem.hxx>
42 #include <svx/boxitem.hxx>
43 #include <tools/fract.hxx>
44 #include <fmtfsize.hxx>
45 #include <fmtornt.hxx>
46 #include <doc.hxx>
47 #include <cntfrm.hxx>
48 #include <tabfrm.hxx>
49 #include <frmtool.hxx>
50 #include <pam.hxx>
51 #include <swtable.hxx>
52 #include <ndtxt.hxx>
53 #include <tblsel.hxx>
54 #include <fldbas.hxx>
55 #include <swundo.hxx>
56 #include <rowfrm.hxx>
57 #include <ddefld.hxx>
58 #include <undobj.hxx>
59 #include <cellatr.hxx>
60 #include <mvsave.hxx>
61 #include <swtblfmt.hxx>
62 #include <swddetbl.hxx>
63 #include <poolfmt.hxx>
64 #include <tblrwcl.hxx>
65 #include <unochart.hxx>
66 #include <boost/shared_ptr.hpp>
68 using namespace com::sun::star;
69 using namespace com::sun::star::uno;
72 #define COLFUZZY 20
73 #define ROWFUZZY 10
75 using namespace ::com::sun::star;
77 #ifdef PRODUCT
78 #define CHECK_TABLE(t)
79 #else
80 #ifdef DEBUG
81 #define CHECK_TABLE(t) (t).CheckConsistency();
82 #else
83 #define CHECK_TABLE(t)
84 #endif
85 #endif
87 typedef SwTableLine* SwTableLinePtr;
88 SV_DECL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr, 16, 16 )
89 SV_IMPL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr );
91 SV_IMPL_PTRARR( _SwShareBoxFmts, SwShareBoxFmt* )
93 // fuers setzen der Frame-Formate an den Boxen reicht es, das aktuelle
94 // im Array zu suchen. Ist es vorhanden, so gebe das neue zurueck
95 struct _CpyTabFrm
97 union {
98 SwTableBoxFmt *pFrmFmt; // fuer CopyCol
99 SwTwips nSize; // fuer DelCol
100 } Value;
101 SwTableBoxFmt *pNewFrmFmt;
103 _CpyTabFrm( SwTableBoxFmt* pAktFrmFmt ) : pNewFrmFmt( 0 )
104 { Value.pFrmFmt = pAktFrmFmt; }
106 _CpyTabFrm& operator=( const _CpyTabFrm& );
108 BOOL operator==( const _CpyTabFrm& rCpyTabFrm )
109 { return (ULONG)Value.nSize == (ULONG)rCpyTabFrm.Value.nSize; }
110 BOOL operator<( const _CpyTabFrm& rCpyTabFrm )
111 { return (ULONG)Value.nSize < (ULONG)rCpyTabFrm.Value.nSize; }
114 struct CR_SetBoxWidth
116 SwSelBoxes aBoxes;
117 SwSortTableLines aLines;
118 SvUShorts aLinesWidth;
119 SwShareBoxFmts aShareFmts;
120 SwTableNode* pTblNd;
121 SwUndoTblNdsChg* pUndo;
122 SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
123 TblChgMode nMode;
124 USHORT nTblWidth, nRemainWidth, nBoxWidth;
125 BOOL bBigger, bLeft, bSplittBox, bAnyBoxFnd;
127 CR_SetBoxWidth( USHORT eType, SwTwips nDif, SwTwips nSid, SwTwips nTblW,
128 SwTwips nMax, SwTableNode* pTNd )
129 : pTblNd( pTNd ),
130 nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ),
131 nTblWidth( (USHORT)nTblW ), nRemainWidth( 0 ), nBoxWidth( 0 ),
132 bSplittBox( FALSE ), bAnyBoxFnd( FALSE )
134 bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
135 nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff );
136 bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
137 nMode = pTblNd->GetTable().GetTblChgMode();
139 CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
140 : pTblNd( rCpy.pTblNd ),
141 pUndo( rCpy.pUndo ),
142 nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
143 nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
144 nMode( rCpy.nMode ), nTblWidth( rCpy.nTblWidth ),
145 nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( nBoxWidth ),
146 bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ),
147 bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
149 aLines.Insert( &rCpy.aLines );
150 aLinesWidth.Insert( &rCpy.aLinesWidth, 0 );
153 SwUndoTblNdsChg* CreateUndo( SwUndoId eUndoType )
155 return pUndo = new SwUndoTblNdsChg( eUndoType, aBoxes, *pTblNd );
158 void LoopClear()
160 nLowerDiff = 0; nRemainWidth = 0;
163 void AddBoxWidth( const SwTableBox& rBox, USHORT nWidth )
165 SwTableLinePtr p = (SwTableLine*)rBox.GetUpper();
166 USHORT nFndPos;
167 if( aLines.Insert( p, nFndPos ))
168 aLinesWidth.Insert( nWidth, nFndPos );
169 else
170 aLinesWidth[ nFndPos ] = aLinesWidth[ nFndPos ] + nWidth;
173 USHORT GetBoxWidth( const SwTableLine& rLn ) const
175 SwTableLinePtr p = (SwTableLine*)&rLn;
176 USHORT nFndPos;
177 if( aLines.Seek_Entry( p, &nFndPos ) )
178 nFndPos = aLinesWidth[ nFndPos ];
179 else
180 nFndPos = 0;
181 return nFndPos;
185 BOOL lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
186 SwTwips nDist, BOOL bCheck );
187 BOOL lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
188 SwTwips nDist, BOOL bCheck );
189 BOOL lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
190 SwTwips nDist, BOOL bCheck );
191 BOOL lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
192 SwTwips nDist, BOOL bCheck );
193 BOOL lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
194 SwTwips nDist, BOOL bCheck );
195 BOOL lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
196 SwTwips nDist, BOOL bCheck );
198 typedef BOOL (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, BOOL );
200 #if !defined( PRODUCT ) || defined( JP_DEBUG )
202 void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize );
204 #define CHECKBOXWIDTH \
206 SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \
207 for( USHORT nTmp = 0; nTmp < aLines.Count(); ++nTmp ) \
208 ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \
211 #define CHECKTABLELAYOUT \
213 for ( USHORT i = 0; i < GetTabLines().Count(); ++i ) \
215 SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \
216 SwClientIter aIter( *pFmt ); \
217 SwClient* pLast = aIter.GoStart(); \
218 if( pLast ) \
220 do \
222 SwFrm *pFrm = PTR_CAST( SwFrm, pLast ); \
223 if ( pFrm && \
224 ((SwRowFrm*)pFrm)->GetTabLine() == GetTabLines()[i] ) \
226 ASSERT( pFrm->GetUpper()->IsTabFrm(), \
227 "Table layout does not match table structure" ) \
229 } while ( 0 != ( pLast = aIter++ ) ); \
234 #else
236 #define CHECKBOXWIDTH
237 #define CHECKTABLELAYOUT
239 #endif
242 struct CR_SetLineHeight
244 SwSelBoxes aBoxes;
245 SwShareBoxFmts aShareFmts;
246 SwTableNode* pTblNd;
247 SwUndoTblNdsChg* pUndo;
248 SwTwips nMaxSpace, nMaxHeight;
249 TblChgMode nMode;
250 USHORT nLines;
251 BOOL bBigger, bTop, bSplittBox, bAnyBoxFnd;
253 CR_SetLineHeight( USHORT eType, SwTableNode* pTNd )
254 : pTblNd( pTNd ), pUndo( 0 ),
255 nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ),
256 bSplittBox( FALSE ), bAnyBoxFnd( FALSE )
258 bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff );
259 bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
260 if( eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL )
261 bBigger = !bBigger;
262 nMode = pTblNd->GetTable().GetTblChgMode();
264 CR_SetLineHeight( const CR_SetLineHeight& rCpy )
265 : pTblNd( rCpy.pTblNd ), pUndo( rCpy.pUndo ),
266 nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
267 nMode( rCpy.nMode ), nLines( rCpy.nLines ),
268 bBigger( rCpy.bBigger ), bTop( rCpy.bTop ),
269 bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
272 SwUndoTblNdsChg* CreateUndo( SwUndoId nUndoType )
274 return pUndo = new SwUndoTblNdsChg( nUndoType, aBoxes, *pTblNd );
278 BOOL lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
279 SwTwips nDist, BOOL bCheck );
280 BOOL lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
281 SwTwips nDist, BOOL bCheck );
282 BOOL lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
283 SwTwips nDist, BOOL bCheck );
285 typedef BOOL (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, BOOL );
287 _CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm )
289 pNewFrmFmt = rCpyTabFrm.pNewFrmFmt;
290 Value = rCpyTabFrm.Value;
291 return *this;
294 SV_DECL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm, 0, 50 )
295 SV_IMPL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm )
297 void lcl_DelCpyTabFrmFmts( _CpyTabFrm& rArr );
299 // ---------------------------------------------------------------
301 struct _CpyPara
303 boost::shared_ptr< std::vector< std::vector< ULONG > > > pWidths;
304 SwDoc* pDoc;
305 SwTableNode* pTblNd;
306 _CpyTabFrms& rTabFrmArr;
307 SwTableLine* pInsLine;
308 SwTableBox* pInsBox;
309 ULONG nOldSize, nNewSize; // zum Korrigieren der Size-Attribute
310 ULONG nMinLeft, nMaxRight;
311 USHORT nCpyCnt, nInsPos;
312 USHORT nLnIdx, nBoxIdx;
313 BYTE nDelBorderFlag;
314 BOOL bCpyCntnt;
316 _CpyPara( SwTableNode* pNd, USHORT nCopies, _CpyTabFrms& rFrmArr,
317 BOOL bCopyContent = TRUE )
318 : pDoc( pNd->GetDoc() ), pTblNd( pNd ), rTabFrmArr(rFrmArr),
319 pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0),
320 nMinLeft(ULONG_MAX), nMaxRight(0),
321 nCpyCnt(nCopies), nInsPos(0),
322 nLnIdx(0), nBoxIdx(0),
323 nDelBorderFlag(0), bCpyCntnt( bCopyContent )
325 _CpyPara( const _CpyPara& rPara, SwTableLine* pLine )
326 : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
327 rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
328 nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
329 nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
330 nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
331 nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
333 _CpyPara( const _CpyPara& rPara, SwTableBox* pBox )
334 : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
335 rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
336 nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
337 nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
338 nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
339 nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
341 void SetBoxWidth( SwTableBox* pBox );
345 BOOL lcl_CopyCol( const _FndBox*& rpFndBox, void* pPara )
347 _CpyPara* pCpyPara = (_CpyPara*)pPara;
349 // suche das FrmFmt im Array aller Frame-Formate
350 SwTableBox* pBox = (SwTableBox*)rpFndBox->GetBox();
351 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pBox->GetFrmFmt() );
353 USHORT nFndPos;
354 if( pCpyPara->nCpyCnt )
356 if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
358 // fuer das verschachtelte Kopieren sicher auch das neue Format
359 // als alt.
360 SwTableBoxFmt* pNewFmt = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
362 // suche die selektierten Boxen in der Line:
363 _FndLine* pCmpLine = NULL;
364 SwFmtFrmSize aFrmSz( pNewFmt->GetFrmSize() );
366 bool bDiffCount = false;
367 if( pBox->GetTabLines().Count() )
369 pCmpLine = rpFndBox->GetLines()[ 0 ];
370 if ( pCmpLine->GetBoxes().Count() != pCmpLine->GetLine()->GetTabBoxes().Count() )
371 bDiffCount = true;
374 if( bDiffCount )
376 // die erste Line sollte reichen
377 _FndBoxes& rFndBoxes = pCmpLine->GetBoxes();
378 long nSz = 0;
379 for( USHORT n = rFndBoxes.Count(); n; )
380 nSz += rFndBoxes[ --n ]->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
381 aFrmSz.SetWidth( aFrmSz.GetWidth() -
382 nSz / ( pCpyPara->nCpyCnt + 1 ) );
383 pNewFmt->SetFmtAttr( aFrmSz );
384 aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
386 // fuer die neue Box ein neues Format mit der Groesse anlegen!
387 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pNewFmt->GetDoc()->
388 MakeTableLineFmt();
389 *aFindFrm.pNewFrmFmt = *pNewFmt;
390 aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
392 else
394 aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
395 pNewFmt->SetFmtAttr( aFrmSz );
397 aFindFrm.pNewFrmFmt = pNewFmt;
398 pCpyPara->rTabFrmArr.Insert( aFindFrm );
399 aFindFrm.Value.pFrmFmt = pNewFmt;
400 pCpyPara->rTabFrmArr.Insert( aFindFrm );
403 else
405 aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
406 // aFindFrm.pNewFrmFmt->Add( pBox );
407 pBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
410 else
412 if( pCpyPara->nDelBorderFlag &&
413 pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
414 aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
415 else
416 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
419 if( rpFndBox->GetLines().Count() )
421 pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
422 rpFndBox->GetLines().Count(), pCpyPara->pInsLine );
423 pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++);
424 _CpyPara aPara( *pCpyPara, pBox );
425 aPara.nDelBorderFlag &= 7;
427 ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyRow, &aPara );
429 else
431 ::_InsTblBox( pCpyPara->pDoc, pCpyPara->pTblNd, pCpyPara->pInsLine,
432 aFindFrm.pNewFrmFmt, pBox, pCpyPara->nInsPos++ );
434 const _FndBoxes& rFndBxs = rpFndBox->GetUpper()->GetBoxes();
435 if( 8 > pCpyPara->nDelBorderFlag
436 ? pCpyPara->nDelBorderFlag
437 : rpFndBox == rFndBxs[ rFndBxs.Count() - 1 ] )
439 const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
440 if( 8 > pCpyPara->nDelBorderFlag
441 ? rBoxItem.GetTop()
442 : rBoxItem.GetRight() )
444 aFindFrm.Value.pFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
446 SvxBoxItem aNew( rBoxItem );
447 if( 8 > pCpyPara->nDelBorderFlag )
448 aNew.SetLine( 0, BOX_LINE_TOP );
449 else
450 aNew.SetLine( 0, BOX_LINE_RIGHT );
452 if( 1 == pCpyPara->nDelBorderFlag ||
453 8 == pCpyPara->nDelBorderFlag )
455 // es wird dahinter kopiert, bei allen Boxen die
456 // TopBorderLine loeschen
457 pBox = pCpyPara->pInsLine->GetTabBoxes()[
458 pCpyPara->nInsPos - 1 ];
461 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
463 // ansonsten wird davor kopiert und die erste Line behaelt
464 // die TopLine und an der originalen wird sie entfernt
465 pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
467 if( !pCpyPara->nCpyCnt )
468 pCpyPara->rTabFrmArr.Insert( aFindFrm );
472 return TRUE;
475 BOOL lcl_CopyRow( const _FndLine*& rpFndLine, void* pPara )
477 _CpyPara* pCpyPara = (_CpyPara*)pPara;
478 SwTableLine* pNewLine = new SwTableLine(
479 (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(),
480 rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox );
481 if( pCpyPara->pInsBox )
483 pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
485 else
487 pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
488 pCpyPara->nInsPos++ );
491 _CpyPara aPara( *pCpyPara, pNewLine );
492 ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyCol, &aPara );
494 pCpyPara->nDelBorderFlag &= 0xf8;
495 return TRUE;
498 //-----------------------------------------------------------
500 void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, USHORT nCpyCnt,
501 BOOL bBehind )
503 // Bug 29124: nicht nur in den Grundlines kopieren. Wenns geht, so weit
504 // runter wie moeglich.
505 _FndBox* pFBox;
506 if( 1 == pFndLn->GetBoxes().Count() &&
507 !( pFBox = pFndLn->GetBoxes()[ 0 ] )->GetBox()->GetSttNd() )
509 // eine Box mit mehreren Lines, also in diese Lines einfuegen
510 for( USHORT n = 0; n < pFBox->GetLines().Count(); ++n )
511 lcl_InsCol( pFBox->GetLines()[ n ], rCpyPara, nCpyCnt, bBehind );
513 else
515 rCpyPara.pInsLine = pFndLn->GetLine();
516 SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
517 pFndLn->GetBoxes().Count()-1 : 0 ]->GetBox();
518 rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
519 if( bBehind )
520 ++rCpyPara.nInsPos;
522 for( USHORT n = 0; n < nCpyCnt; ++n )
524 if( n + 1 == nCpyCnt && bBehind )
525 rCpyPara.nDelBorderFlag = 9;
526 else
527 rCpyPara.nDelBorderFlag = 8;
528 pFndLn->GetBoxes().ForEach( &lcl_CopyCol, &rCpyPara );
533 SwRowFrm* GetRowFrm( SwTableLine& rLine )
535 SwClientIter aIter( *rLine.GetFrmFmt() );
536 for( SwClient* pFrm = aIter.First( TYPE( SwRowFrm )); pFrm;
537 pFrm = aIter.Next() )
538 if( ((SwRowFrm*)pFrm)->GetTabLine() == &rLine )
539 return (SwRowFrm*)pFrm;
540 return 0;
544 BOOL SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, USHORT nCnt, BOOL bBehind )
546 ASSERT( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
547 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
548 if( !pTblNd )
549 return FALSE;
551 BOOL bRes = TRUE;
552 if( IsNewModel() )
553 bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind );
554 else
556 // suche alle Boxen / Lines
557 _FndBox aFndBox( 0, 0 );
559 _FndPara aPara( rBoxes, &aFndBox );
560 GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
562 if( !aFndBox.GetLines().Count() )
563 return FALSE;
565 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
567 //Lines fuer das Layout-Update herausuchen.
568 aFndBox.SetTableLines( *this );
569 aFndBox.DelFrms( *this );
571 // TL_CHART2: nothing to be done since chart2 currently does not want to
572 // get notified about new rows/cols.
574 _CpyTabFrms aTabFrmArr;
575 _CpyPara aCpyPara( pTblNd, nCnt, aTabFrmArr );
577 for( USHORT n = 0; n < aFndBox.GetLines().Count(); ++n )
578 lcl_InsCol( aFndBox.GetLines()[ n ], aCpyPara, nCnt, bBehind );
580 // dann raeume die Struktur dieser Line noch mal auf, generell alle
581 GCLines();
583 //Layout updaten
584 aFndBox.MakeFrms( *this );
586 CHECKBOXWIDTH
587 CHECKTABLELAYOUT
588 bRes = TRUE;
591 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
592 if (pPCD && nCnt)
593 pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
594 pDoc->UpdateCharts( GetFrmFmt()->GetName() );
596 return bRes;
599 BOOL SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
600 USHORT nCnt, BOOL bBehind )
602 ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
603 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
604 if( !pTblNd )
605 return FALSE;
607 // suche alle Boxen / Lines
608 _FndBox aFndBox( 0, 0 );
610 _FndPara aPara( rBoxes, &aFndBox );
611 GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
613 if( !aFndBox.GetLines().Count() )
614 return FALSE;
616 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
618 _FndBox* pFndBox = &aFndBox;
620 _FndLine* pFndLine;
621 while( 1 == pFndBox->GetLines().Count() &&
622 1 == ( pFndLine = pFndBox->GetLines()[ 0 ])->GetBoxes().Count() )
624 // nicht zu weit runter, eine Line mit Boxen muss nachbleiben!!
625 _FndBox* pTmpBox = pFndLine->GetBoxes()[ 0 ];
626 if( pTmpBox->GetLines().Count() )
627 pFndBox = pTmpBox;
628 else
629 break;
633 //Lines fuer das Layout-Update herausuchen.
634 const BOOL bLayout = !IsNewModel() &&
635 0 != SwClientIter( *GetFrmFmt() ).First( TYPE(SwTabFrm) );
637 if ( bLayout )
639 aFndBox.SetTableLines( *this );
640 if( pFndBox != &aFndBox )
641 aFndBox.DelFrms( *this );
642 // TL_CHART2: nothing to be done since chart2 currently does not want to
643 // get notified about new rows/cols.
646 _CpyTabFrms aTabFrmArr;
647 _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
649 SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
650 pFndBox->GetLines().Count()-1 : 0 ]->GetLine();
651 if( &aFndBox == pFndBox )
652 aCpyPara.nInsPos = GetTabLines().C40_GETPOS( SwTableLine, pLine );
653 else
655 aCpyPara.pInsBox = pFndBox->GetBox();
656 aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().C40_GETPOS( SwTableLine, pLine );
659 if( bBehind )
661 ++aCpyPara.nInsPos;
662 aCpyPara.nDelBorderFlag = 1;
664 else
665 aCpyPara.nDelBorderFlag = 2;
667 for( USHORT nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
669 if( bBehind )
670 aCpyPara.nDelBorderFlag = 1;
671 pFndBox->GetLines().ForEach( &lcl_CopyRow, &aCpyPara );
674 // dann raeume die Struktur dieser Line noch mal auf, generell alle
675 if( !pDoc->IsInReading() )
676 GCLines();
678 //Layout updaten
679 if ( bLayout )
681 if( pFndBox != &aFndBox )
682 aFndBox.MakeFrms( *this );
683 else
684 aFndBox.MakeNewFrms( *this, nCnt, bBehind );
687 CHECKBOXWIDTH
688 CHECKTABLELAYOUT
690 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
691 if (pPCD && nCnt)
692 pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
693 pDoc->UpdateCharts( GetFrmFmt()->GetName() );
695 return TRUE;
698 BOOL _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara );
700 BOOL _FndBoxAppendRowBox( const SwTableBox*& rpBox, void* pPara )
702 _FndPara* pFndPara = (_FndPara*)pPara;
703 _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine );
704 if( rpBox->GetTabLines().Count() )
706 _FndPara aPara( *pFndPara, pFndBox );
707 pFndBox->GetBox()->GetTabLines().ForEach( &_FndBoxAppendRowLine, &aPara );
708 if( !pFndBox->GetLines().Count() )
709 delete pFndBox;
711 else
712 pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox,
713 pFndPara->pFndLine->GetBoxes().Count() );
714 return TRUE;
717 BOOL _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara )
719 _FndPara* pFndPara = (_FndPara*)pPara;
720 _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox );
721 _FndPara aPara( *pFndPara, pFndLine );
722 pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxAppendRowBox, &aPara );
723 if( pFndLine->GetBoxes().Count() )
725 pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine,
726 pFndPara->pFndBox->GetLines().Count() );
728 else
729 delete pFndLine;
730 return TRUE;
734 BOOL SwTable::AppendRow( SwDoc* pDoc, USHORT nCnt )
736 SwTableNode* pTblNd = (SwTableNode*)aSortCntBoxes[0]->GetSttNd()->FindTableNode();
737 if( !pTblNd )
738 return FALSE;
740 // suche alle Boxen / Lines
741 _FndBox aFndBox( 0, 0 );
743 const SwTableLine* pLLine = GetTabLines()[ GetTabLines().Count()-1 ];
745 const SwSelBoxes* pBxs = 0; // Dummy !!!
746 _FndPara aPara( *pBxs, &aFndBox );
748 _FndBoxAppendRowLine( pLLine, &aPara );
750 if( !aFndBox.GetLines().Count() )
751 return FALSE;
753 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
755 //Lines fuer das Layout-Update herausuchen.
756 const BOOL bLayout = 0 != SwClientIter( *GetFrmFmt() ).First( TYPE(SwTabFrm) );
757 if( bLayout )
759 aFndBox.SetTableLines( *this );
760 // TL_CHART2: nothing to be done since chart2 currently does not want to
761 // get notified about new rows/cols.
764 _CpyTabFrms aTabFrmArr;
765 _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
766 aCpyPara.nInsPos = GetTabLines().Count();
767 aCpyPara.nDelBorderFlag = 1;
769 for( USHORT nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
771 aCpyPara.nDelBorderFlag = 1;
772 aFndBox.GetLines().ForEach( &lcl_CopyRow, &aCpyPara );
775 // dann raeume die Struktur dieser Line noch mal auf, generell alle
776 if( !pDoc->IsInReading() )
777 GCLines();
779 //Layout updaten
780 if ( bLayout )
782 aFndBox.MakeNewFrms( *this, nCnt, TRUE );
784 // TL_CHART2: need to inform chart of probably changed cell names
785 pDoc->UpdateCharts( GetFrmFmt()->GetName() );
787 CHECKBOXWIDTH
788 CHECKTABLELAYOUT
790 return TRUE;
794 void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
795 BOOL bFirst, SwShareBoxFmts& rShareFmts );
797 void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset,
798 BOOL bFirst, SwShareBoxFmts& rShareFmts )
800 for ( USHORT i = 0; i < rLines.Count(); ++i )
801 ::lcl_LastBoxSetWidth( rLines[i]->GetTabBoxes(), nOffset, bFirst,
802 rShareFmts );
805 void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
806 BOOL bFirst, SwShareBoxFmts& rShareFmts )
808 SwTableBox& rBox = *rBoxes[ bFirst ? 0 : rBoxes.Count() - 1 ];
809 if( !rBox.GetSttNd() )
810 ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
811 bFirst, rShareFmts );
813 //Die Box anpassen
814 SwFrmFmt *pBoxFmt = rBox.GetFrmFmt();
815 SwFmtFrmSize aNew( pBoxFmt->GetFrmSize() );
816 aNew.SetWidth( aNew.GetWidth() + nOffset );
817 SwFrmFmt *pFmt = rShareFmts.GetFormat( *pBoxFmt, aNew );
818 if( pFmt )
819 rBox.ChgFrmFmt( (SwTableBoxFmt*)pFmt );
820 else
822 pFmt = rBox.ClaimFrmFmt();
824 pFmt->LockModify();
825 pFmt->SetFmtAttr( aNew );
826 pFmt->UnlockModify();
828 rShareFmts.AddFormat( *pBoxFmt, *pFmt );
832 void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo,
833 BOOL bCalcNewSize, const BOOL bCorrBorder,
834 SwShareBoxFmts* pShareFmts )
836 do {
837 SwTwips nBoxSz = bCalcNewSize ?
838 pBox->GetFrmFmt()->GetFrmSize().GetWidth() : 0;
839 SwTableLine* pLine = pBox->GetUpper();
840 SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
841 USHORT nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox );
842 SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
844 // Sonderbehandlung fuer Umrandung:
845 if( bCorrBorder && 1 < rTblBoxes.Count() )
847 BOOL bChgd = FALSE;
848 const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
850 if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
852 //JP 02.04.97: 1.Teil fuer Bug 36271
853 // zuerst die linken/rechten Kanten
854 if( nDelPos + 1 < rTblBoxes.Count() )
856 SwTableBox* pNxtBox = rTblBoxes[ nDelPos + 1 ];
857 const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
859 SwTableBox* pPrvBox = nDelPos ? rTblBoxes[ nDelPos - 1 ] : 0;
861 if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
862 ( !pPrvBox || !pPrvBox->GetFrmFmt()->GetBox().GetRight()) )
864 SvxBoxItem aTmp( rNxtBoxItem );
865 aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
866 : rBoxItem.GetRight(),
867 BOX_LINE_LEFT );
868 if( pShareFmts )
869 pShareFmts->SetAttr( *pNxtBox, aTmp );
870 else
871 pNxtBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
872 bChgd = TRUE;
875 if( !bChgd && nDelPos )
877 SwTableBox* pPrvBox = rTblBoxes[ nDelPos - 1 ];
878 const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
880 SwTableBox* pNxtBox = nDelPos + 1 < rTblBoxes.Count()
881 ? rTblBoxes[ nDelPos + 1 ] : 0;
883 if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
884 ( !pNxtBox || !pNxtBox->GetFrmFmt()->GetBox().GetLeft()) )
886 SvxBoxItem aTmp( rPrvBoxItem );
887 aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
888 : rBoxItem.GetRight(),
889 BOX_LINE_RIGHT );
890 if( pShareFmts )
891 pShareFmts->SetAttr( *pPrvBox, aTmp );
892 else
893 pPrvBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
900 // erst die Box, dann die Nodes loeschen!!
901 SwStartNode* pSttNd = (SwStartNode*)pBox->GetSttNd();
902 if( pShareFmts )
903 pShareFmts->RemoveFormat( *rTblBoxes[ nDelPos ]->GetFrmFmt() );
904 rTblBoxes.DeleteAndDestroy( nDelPos );
906 if( pSttNd )
908 // ist das UndoObject zum speichern der Section vorbereitet?
909 if( pUndo && pUndo->IsDelBox() )
910 ((SwUndoTblNdsChg*)pUndo)->SaveSection( pSttNd );
911 else
912 pSttNd->GetDoc()->DeleteSection( pSttNd );
915 // auch die Zeile noch loeschen ??
916 if( rTblBoxes.Count() )
918 // dann passe noch die Frame-SSize an
919 BOOL bLastBox = nDelPos == rTblBoxes.Count();
920 if( bLastBox )
921 --nDelPos;
922 pBox = rTblBoxes[nDelPos];
923 if( bCalcNewSize )
925 SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
926 aNew.SetWidth( aNew.GetWidth() + nBoxSz );
927 if( pShareFmts )
928 pShareFmts->SetSize( *pBox, aNew );
929 else
930 pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
932 if( !pBox->GetSttNd() )
934 // dann muss es auch rekursiv in allen Zeilen, in allen
935 // Zellen erfolgen!
936 SwShareBoxFmts aShareFmts;
937 ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
938 !bLastBox,
939 pShareFmts ? *pShareFmts
940 : aShareFmts );
943 break; // nichts mehr loeschen
945 // loesche die Line aus Tabelle/Box
946 if( !pUpperBox )
948 // dann loesche auch noch die Line aus der Tabelle
949 nDelPos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
950 if( pShareFmts )
951 pShareFmts->RemoveFormat( *rTbl.GetTabLines()[ nDelPos ]->GetFrmFmt() );
952 rTbl.GetTabLines().DeleteAndDestroy( nDelPos );
953 break; // mehr kann nicht geloescht werden
956 // dann loesche auch noch die Line
957 pBox = pUpperBox;
958 nDelPos = pBox->GetTabLines().C40_GETPOS( SwTableLine, pLine );
959 if( pShareFmts )
960 pShareFmts->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrmFmt() );
961 pBox->GetTabLines().DeleteAndDestroy( nDelPos );
962 } while( !pBox->GetTabLines().Count() );
965 SwTableBox* lcl_FndNxtPrvDelBox( const SwTableLines& rTblLns,
966 SwTwips nBoxStt, SwTwips nBoxWidth,
967 USHORT nLinePos, BOOL bNxt,
968 SwSelBoxes* pAllDelBoxes, USHORT* pCurPos )
970 SwTableBox* pFndBox = 0;
971 do {
972 if( bNxt )
973 ++nLinePos;
974 else
975 --nLinePos;
976 SwTableLine* pLine = rTblLns[ nLinePos ];
977 SwTwips nFndBoxWidth = 0;
978 SwTwips nFndWidth = nBoxStt + nBoxWidth;
979 USHORT nBoxCnt = pLine->GetTabBoxes().Count();
981 pFndBox = pLine->GetTabBoxes()[ 0 ];
982 for( USHORT n = 0; 0 < nFndWidth && n < nBoxCnt; ++n )
984 pFndBox = pLine->GetTabBoxes()[ n ];
985 nFndWidth -= (nFndBoxWidth = pFndBox->GetFrmFmt()->
986 GetFrmSize().GetWidth());
989 // suche die erste ContentBox
990 while( !pFndBox->GetSttNd() )
992 const SwTableLines& rLowLns = pFndBox->GetTabLines();
993 if( bNxt )
994 pFndBox = rLowLns[ 0 ]->GetTabBoxes()[ 0 ];
995 else
996 pFndBox = rLowLns[ rLowLns.Count() - 1 ]->GetTabBoxes()[ 0 ];
999 if( Abs( nFndWidth ) > COLFUZZY ||
1000 Abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
1001 pFndBox = 0;
1002 else if( pAllDelBoxes )
1004 // falls der Vorganger auch geloscht wird, ist nicht zu tun
1005 USHORT nFndPos;
1006 if( !pAllDelBoxes->Seek_Entry( pFndBox, &nFndPos ) )
1007 break;
1009 // sonst noch mal weitersuchen
1010 // Die Box muessen wir aber nicht nochmal abpruefen
1011 pFndBox = 0;
1012 if( nFndPos <= *pCurPos )
1013 --*pCurPos;
1014 pAllDelBoxes->Remove( nFndPos );
1016 } while( bNxt ? ( nLinePos + 1 < rTblLns.Count() ) : nLinePos );
1017 return pFndBox;
1020 void lcl_SaveUpperLowerBorder( SwTable& rTbl, const SwTableBox& rBox,
1021 SwShareBoxFmts& rShareFmts,
1022 SwSelBoxes* pAllDelBoxes = 0,
1023 USHORT* pCurPos = 0 )
1025 //JP 16.04.97: 2.Teil fuer Bug 36271
1026 BOOL bChgd = FALSE;
1027 const SwTableLine* pLine = rBox.GetUpper();
1028 const SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
1029 const SwTableBox* pUpperBox = &rBox;
1030 USHORT nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pUpperBox );
1031 pUpperBox = rBox.GetUpper()->GetUpper();
1032 const SvxBoxItem& rBoxItem = rBox.GetFrmFmt()->GetBox();
1034 // dann die unteren/oberen Kanten
1035 if( rBoxItem.GetTop() || rBoxItem.GetBottom() )
1037 bChgd = FALSE;
1038 const SwTableLines* pTblLns;
1039 if( pUpperBox )
1040 pTblLns = &pUpperBox->GetTabLines();
1041 else
1042 pTblLns = &rTbl.GetTabLines();
1044 USHORT nLnPos = pTblLns->GetPos( pLine );
1046 // bestimme die Attr.Position der akt. zu loeschenden Box
1047 // und suche dann in der unteren / oberen Line die entspr.
1048 // Gegenstuecke
1049 SwTwips nBoxStt = 0;
1050 for( USHORT n = 0; n < nDelPos; ++n )
1051 nBoxStt += rTblBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
1052 SwTwips nBoxWidth = rBox.GetFrmFmt()->GetFrmSize().GetWidth();
1054 SwTableBox *pPrvBox = 0, *pNxtBox = 0;
1055 if( nLnPos ) // Vorgaenger?
1056 pPrvBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
1057 nLnPos, FALSE, pAllDelBoxes, pCurPos );
1059 if( nLnPos + 1 < pTblLns->Count() ) // Nachfolger?
1060 pNxtBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
1061 nLnPos, TRUE, pAllDelBoxes, pCurPos );
1063 if( pNxtBox && pNxtBox->GetSttNd() )
1065 const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
1066 if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
1067 !pPrvBox->GetFrmFmt()->GetBox().GetBottom()) )
1069 SvxBoxItem aTmp( rNxtBoxItem );
1070 aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
1071 : rBoxItem.GetBottom(),
1072 BOX_LINE_TOP );
1073 rShareFmts.SetAttr( *pNxtBox, aTmp );
1074 bChgd = TRUE;
1077 if( !bChgd && pPrvBox && pPrvBox->GetSttNd() )
1079 const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
1080 if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
1081 !pNxtBox->GetFrmFmt()->GetBox().GetTop()) )
1083 SvxBoxItem aTmp( rPrvBoxItem );
1084 aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
1085 : rBoxItem.GetBottom(),
1086 BOX_LINE_BOTTOM );
1087 rShareFmts.SetAttr( *pPrvBox, aTmp );
1095 BOOL SwTable::DeleteSel(
1096 SwDoc* pDoc
1098 const SwSelBoxes& rBoxes,
1099 const SwSelBoxes* pMerged, SwUndo* pUndo,
1100 const BOOL bDelMakeFrms, const BOOL bCorrBorder )
1102 ASSERT( pDoc, "No doc?" );
1103 SwTableNode* pTblNd = 0;
1104 if( rBoxes.Count() )
1106 pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
1107 if( !pTblNd )
1108 return FALSE;
1111 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
1113 //Lines fuer das Layout-Update herausuchen.
1114 _FndBox aFndBox( 0, 0 );
1115 if ( bDelMakeFrms )
1117 if( pMerged && pMerged->Count() )
1118 aFndBox.SetTableLines( *pMerged, *this );
1119 else if( rBoxes.Count() )
1120 aFndBox.SetTableLines( rBoxes, *this );
1121 aFndBox.DelFrms( *this );
1124 SwShareBoxFmts aShareFmts;
1126 // erst die Umrandung umsetzen, dann loeschen
1127 if( bCorrBorder )
1129 SwSelBoxes aBoxes;
1130 aBoxes.Insert( &rBoxes );
1131 for( USHORT n = 0; n < aBoxes.Count(); ++n )
1132 ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFmts,
1133 &aBoxes, &n );
1136 PrepareDelBoxes( rBoxes );
1138 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
1140 // delete boxes from last to first
1141 for( USHORT n = 0; n < rBoxes.Count(); ++n )
1143 USHORT nIdx = rBoxes.Count() - 1 - n;
1145 // first adapt the data-sequence for chart if necessary
1146 // (needed to move the implementation cursor properly to it's new
1147 // position which can't be done properly if the cell is already gone)
1148 if (pPCD && pTblNd)
1149 pPCD->DeleteBox( &pTblNd->GetTable(), *rBoxes[nIdx] );
1151 // ... then delete the boxes
1152 _DeleteBox( *this, rBoxes[nIdx], pUndo, TRUE, bCorrBorder, &aShareFmts );
1155 // dann raeume die Struktur aller Lines auf
1156 GCLines();
1158 if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) )
1159 aFndBox.MakeFrms( *this );
1161 // TL_CHART2: now inform chart that sth has changed
1162 pDoc->UpdateCharts( GetFrmFmt()->GetName() );
1164 CHECKTABLELAYOUT
1165 CHECK_TABLE( *this )
1167 return TRUE;
1171 // ---------------------------------------------------------------
1173 BOOL SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, USHORT nCnt,
1174 BOOL bSameHeight )
1176 ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" );
1177 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
1178 if( !pTblNd )
1179 return FALSE;
1181 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1182 // the table to complex to be handled with chart.
1183 // Thus we tell the charts to use their own data provider and forget about this table
1184 pDoc->CreateChartInternalDataProviders( this );
1186 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
1188 // If the rows should get the same (min) height, we first have
1189 // to store the old row heights before deleting the frames
1190 long* pRowHeights = 0;
1191 if ( bSameHeight )
1193 pRowHeights = new long[ rBoxes.Count() ];
1194 for( USHORT n = 0; n < rBoxes.Count(); ++n )
1196 SwTableBox* pSelBox = *( rBoxes.GetData() + n );
1197 const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() );
1198 ASSERT( pRow, "wo ist der Frm von der SwTableLine?" )
1199 SWRECTFN( pRow )
1200 pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)();
1204 //Lines fuer das Layout-Update herausuchen.
1205 _FndBox aFndBox( 0, 0 );
1206 aFndBox.SetTableLines( rBoxes, *this );
1207 aFndBox.DelFrms( *this );
1209 for( USHORT n = 0; n < rBoxes.Count(); ++n )
1211 SwTableBox* pSelBox = *( rBoxes.GetData() + n );
1212 ASSERT( pSelBox, "Box steht nicht in der Tabelle" );
1214 // dann fuege in die Box nCnt neue Zeilen ein
1215 SwTableLine* pInsLine = pSelBox->GetUpper();
1216 SwTableBoxFmt* pFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
1218 // Hoehe der Line beachten, gegebenenfalls neu setzen
1219 SwFmtFrmSize aFSz( pInsLine->GetFrmFmt()->GetFrmSize() );
1220 if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() )
1221 aFSz.SetHeightSizeType( ATT_MIN_SIZE );
1223 BOOL bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
1224 if ( bChgLineSz )
1225 aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
1226 (nCnt + 1) );
1228 SwTableBox* pNewBox = new SwTableBox( pFrmFmt, nCnt, pInsLine );
1229 USHORT nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
1230 pInsLine->GetTabBoxes().Remove( nBoxPos ); // alte loeschen
1231 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox, nBoxPos );
1233 // Hintergrund- / Rand Attribut loeschen
1234 SwTableBox* pLastBox = pSelBox; // zum verteilen der TextNodes !!
1235 // sollte Bereiche in der Box stehen, dann bleibt sie so bestehen
1236 // !! FALLS DAS GEAENDERT WIRD MUSS DAS UNDO ANGEPASST WERDEN !!!
1237 BOOL bMoveNodes = TRUE;
1239 ULONG nSttNd = pLastBox->GetSttIdx() + 1,
1240 nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
1241 while( nSttNd < nEndNd )
1242 if( !pDoc->GetNodes()[ nSttNd++ ]->IsTxtNode() )
1244 bMoveNodes = FALSE;
1245 break;
1249 SwTableBoxFmt* pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
1250 BOOL bChkBorder = 0 != pCpyBoxFrmFmt->GetBox().GetTop();
1251 if( bChkBorder )
1252 pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
1254 for( USHORT i = 0; i <= nCnt; ++i )
1256 // also erstmal eine neue Linie in der neuen Box
1257 SwTableLine* pNewLine = new SwTableLine(
1258 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pNewBox );
1259 if( bChgLineSz )
1261 pNewLine->ClaimFrmFmt()->SetFmtAttr( aFSz );
1264 pNewBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, i );
1265 // dann eine neue Box in der Line
1266 if( !i ) // haenge die originale Box ein
1268 pSelBox->SetUpper( pNewLine );
1269 pNewLine->GetTabBoxes().C40_INSERT( SwTableBox, pSelBox, 0 );
1271 else
1273 ::_InsTblBox( pDoc, pTblNd, pNewLine, pCpyBoxFrmFmt,
1274 pLastBox, 0 );
1276 if( bChkBorder )
1278 pCpyBoxFrmFmt = (SwTableBoxFmt*)pNewLine->GetTabBoxes()[ 0 ]->ClaimFrmFmt();
1279 SvxBoxItem aTmp( pCpyBoxFrmFmt->GetBox() );
1280 aTmp.SetLine( 0, BOX_LINE_TOP );
1281 pCpyBoxFrmFmt->SetFmtAttr( aTmp );
1282 bChkBorder = FALSE;
1285 if( bMoveNodes )
1287 const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
1288 if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() )
1290 // TextNodes verschieben
1291 SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd );
1292 pLastBox = pNewLine->GetTabBoxes()[0]; // neu setzen
1293 SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
1294 pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, FALSE);
1295 pDoc->GetNodes().Delete( aInsPos, 1 ); // den leeren noch loeschen
1300 // in Boxen mit Lines darf es nur noch Size/Fillorder geben
1301 pFrmFmt = (SwTableBoxFmt*)pNewBox->ClaimFrmFmt();
1302 pFrmFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1303 pFrmFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
1306 delete[] pRowHeights;
1308 GCLines();
1310 aFndBox.MakeFrms( *this );
1312 CHECKBOXWIDTH
1313 CHECKTABLELAYOUT
1314 return TRUE;
1317 BOOL SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, USHORT nCnt )
1319 ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" );
1320 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
1321 if( !pTblNd )
1322 return FALSE;
1324 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1325 // the table to complex to be handled with chart.
1326 // Thus we tell the charts to use their own data provider and forget about this table
1327 pDoc->CreateChartInternalDataProviders( this );
1329 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
1330 SwSelBoxes aSelBoxes;
1331 aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
1332 ExpandSelection( aSelBoxes );
1334 //Lines fuer das Layout-Update herausuchen.
1335 _FndBox aFndBox( 0, 0 );
1336 aFndBox.SetTableLines( aSelBoxes, *this );
1337 aFndBox.DelFrms( *this );
1339 _CpyTabFrms aFrmArr;
1340 SvPtrarr aLastBoxArr;
1341 USHORT nFndPos;
1342 for( USHORT n = 0; n < aSelBoxes.Count(); ++n )
1344 SwTableBox* pSelBox = *( aSelBoxes.GetData() + n );
1345 ASSERT( pSelBox, "Box steht nicht in der Tabelle" );
1347 // We don't want to split small table cells into very very small cells
1348 if( pSelBox->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 )
1349 continue;
1351 // dann teile die Box nCnt in nCnt Boxen
1352 SwTableLine* pInsLine = pSelBox->GetUpper();
1353 USHORT nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
1355 // suche das FrmFmt im Array aller Frame-Formate
1356 SwTableBoxFmt* pLastBoxFmt;
1357 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pSelBox->GetFrmFmt() );
1358 if( !aFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
1360 // aender das FrmFmt
1361 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
1362 SwTwips nBoxSz = aFindFrm.pNewFrmFmt->GetFrmSize().GetWidth();
1363 SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
1364 aFindFrm.pNewFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
1365 nNewBoxSz, 0 ) );
1366 aFrmArr.Insert( aFindFrm );
1368 pLastBoxFmt = aFindFrm.pNewFrmFmt;
1369 if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
1371 // es bleibt ein Rest, also muss fuer die letzte Box ein
1372 // eigenes Format definiert werden
1373 pLastBoxFmt = new SwTableBoxFmt( *aFindFrm.pNewFrmFmt );
1374 pLastBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
1375 nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
1377 void* p = pLastBoxFmt;
1378 aLastBoxArr.Insert( p, nFndPos );
1380 else
1382 aFindFrm = aFrmArr[ nFndPos ];
1383 pSelBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
1384 pLastBoxFmt = (SwTableBoxFmt*)aLastBoxArr[ nFndPos ];
1387 // dann fuege mal an der Position die neuen Boxen ein
1388 for( USHORT i = 1; i < nCnt; ++i )
1389 ::_InsTblBox( pDoc, pTblNd, pInsLine, aFindFrm.pNewFrmFmt,
1390 pSelBox, nBoxPos + i ); // dahinter einfuegen
1392 ::_InsTblBox( pDoc, pTblNd, pInsLine, pLastBoxFmt,
1393 pSelBox, nBoxPos + nCnt ); // dahinter einfuegen
1395 // Sonderbehandlung fuer die Umrandung:
1396 const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrmFmt->GetBox();
1397 if( aSelBoxItem.GetRight() )
1399 pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrmFmt();
1401 SvxBoxItem aTmp( aSelBoxItem );
1402 aTmp.SetLine( 0, BOX_LINE_RIGHT );
1403 aFindFrm.pNewFrmFmt->SetFmtAttr( aTmp );
1405 // und dann das Format aus dem "cache" entfernen
1406 for( USHORT i = aFrmArr.Count(); i; )
1408 const _CpyTabFrm& rCTF = aFrmArr[ --i ];
1409 if( rCTF.pNewFrmFmt == aFindFrm.pNewFrmFmt ||
1410 rCTF.Value.pFrmFmt == aFindFrm.pNewFrmFmt )
1412 aFrmArr.Remove( i );
1413 aLastBoxArr.Remove( i );
1419 //Layout updaten
1420 aFndBox.MakeFrms( *this );
1422 CHECKBOXWIDTH
1423 CHECKTABLELAYOUT
1424 return TRUE;
1427 // ---------------------------------------------------------------
1430 ----------------------- >> MERGE << ------------------------
1431 Algorithmus:
1432 ist in der _FndBox nur eine Line angegeben, nehme die Line
1433 und teste die Anzahl der Boxen
1434 - ist mehr als 1 Box angegeben, so wird auf Boxenebene zusammen-
1435 gefasst, d.H. die neue Box wird so Breit wie die alten.
1436 - Alle Lines die ueber/unter dem Bereich liegen werden in die
1437 Box als Line + Box mit Lines eingefuegt
1438 - Alle Lines die vor/hinter dem Bereich liegen werden in
1439 die Boxen Left/Right eingetragen
1441 ----------------------- >> MERGE << ------------------------
1444 void lcl_CpyLines( USHORT nStt, USHORT nEnd,
1445 SwTableLines& rLines,
1446 SwTableBox* pInsBox,
1447 USHORT nPos = USHRT_MAX )
1449 for( USHORT n = nStt; n < nEnd; ++n )
1450 rLines[n]->SetUpper( pInsBox );
1451 if( USHRT_MAX == nPos )
1452 nPos = pInsBox->GetTabLines().Count();
1453 pInsBox->GetTabLines().Insert( &rLines, nPos, nStt, nEnd );
1454 rLines.Remove( nStt, nEnd - nStt );
1457 void lcl_CpyBoxes( USHORT nStt, USHORT nEnd,
1458 SwTableBoxes& rBoxes,
1459 SwTableLine* pInsLine,
1460 USHORT nPos = USHRT_MAX )
1462 for( USHORT n = nStt; n < nEnd; ++n )
1463 rBoxes[n]->SetUpper( pInsLine );
1464 if( USHRT_MAX == nPos )
1465 nPos = pInsLine->GetTabBoxes().Count();
1466 pInsLine->GetTabBoxes().Insert( &rBoxes, nPos, nStt, nEnd );
1467 rBoxes.Remove( nStt, nEnd - nStt );
1470 void lcl_CalcWidth( SwTableBox* pBox )
1472 // Annahme: jede Line in der Box ist gleich gross
1473 SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
1474 ASSERT( pBox->GetTabLines().Count(), "Box hat keine Lines" );
1476 SwTableLine* pLine = pBox->GetTabLines()[0];
1477 ASSERT( pLine, "Box steht in keiner Line" );
1479 long nWidth = 0;
1480 for( USHORT n = 0; n < pLine->GetTabBoxes().Count(); ++n )
1481 nWidth += pLine->GetTabBoxes()[n]->GetFrmFmt()->GetFrmSize().GetWidth();
1483 pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
1485 // in Boxen mit Lines darf es nur noch Size/Fillorder geben
1486 pFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1487 pFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
1492 struct _InsULPara
1494 SwTableNode* pTblNd;
1495 SwTableLine* pInsLine;
1496 SwTableBox* pInsBox;
1497 BOOL bUL_LR : 1; // Upper-Lower(TRUE) oder Left-Right(FALSE) ?
1498 BOOL bUL : 1; // Upper-Left(TRUE) oder Lower-Right(FALSE) ?
1500 SwTableBox* pLeftBox;
1501 SwTableBox* pRightBox;
1502 SwTableBox* pMergeBox;
1504 _InsULPara( SwTableNode* pTNd, BOOL bUpperLower, BOOL bUpper,
1505 SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight,
1506 SwTableLine* pLine=0, SwTableBox* pBox=0 )
1507 : pTblNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ),
1508 pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge )
1509 { bUL_LR = bUpperLower; bUL = bUpper; }
1511 void SetLeft( SwTableBox* pBox=0 )
1512 { bUL_LR = FALSE; bUL = TRUE; if( pBox ) pInsBox = pBox; }
1513 void SetRight( SwTableBox* pBox=0 )
1514 { bUL_LR = FALSE; bUL = FALSE; if( pBox ) pInsBox = pBox; }
1515 void SetUpper( SwTableLine* pLine=0 )
1516 { bUL_LR = TRUE; bUL = TRUE; if( pLine ) pInsLine = pLine; }
1517 void SetLower( SwTableLine* pLine=0 )
1518 { bUL_LR = TRUE; bUL = FALSE; if( pLine ) pInsLine = pLine; }
1522 BOOL lcl_Merge_MoveBox( const _FndBox*& rpFndBox, void* pPara )
1524 _InsULPara* pULPara = (_InsULPara*)pPara;
1525 SwTableBoxes* pBoxes;
1527 USHORT nStt = 0, nEnd = rpFndBox->GetLines().Count();
1528 USHORT nInsPos = USHRT_MAX;
1529 if( !pULPara->bUL_LR ) // Left/Right
1531 USHORT nPos;
1532 SwTableBox* pFndBox = (SwTableBox*)rpFndBox->GetBox();
1533 pBoxes = &pFndBox->GetUpper()->GetTabBoxes();
1534 if( pULPara->bUL ) // Left ?
1536 // gibt es noch davor Boxen, dann move sie
1537 if( 0 != ( nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) )
1538 lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
1540 else // Right
1541 // gibt es noch dahinter Boxen, dann move sie
1542 if( (nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) +1 < pBoxes->Count() )
1544 nInsPos = pULPara->pInsLine->GetTabBoxes().Count();
1545 lcl_CpyBoxes( nPos+1, pBoxes->Count(),
1546 *pBoxes, pULPara->pInsLine );
1549 // Upper/Lower und gehts noch tiefer ??
1550 else if( rpFndBox->GetLines().Count() )
1552 // suche nur die Line, ab der Verschoben werden muss
1553 nStt = pULPara->bUL ? 0 : rpFndBox->GetLines().Count()-1;
1554 nEnd = nStt+1;
1557 pBoxes = &pULPara->pInsLine->GetTabBoxes();
1559 // geht es noch eine weitere Stufe runter?
1560 if( rpFndBox->GetBox()->GetTabLines().Count() )
1562 SwTableBox* pBox = new SwTableBox(
1563 (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt(), 0, pULPara->pInsLine );
1564 _InsULPara aPara( *pULPara );
1565 aPara.pInsBox = pBox;
1566 ((_FndBox*)rpFndBox)->GetLines().ForEach( nStt, nEnd,
1567 &lcl_Merge_MoveLine, &aPara );
1568 if( pBox->GetTabLines().Count() )
1570 if( USHRT_MAX == nInsPos )
1571 nInsPos = pBoxes->Count();
1572 pBoxes->C40_INSERT( SwTableBox, pBox, nInsPos );
1573 lcl_CalcWidth( pBox ); // bereche die Breite der Box
1575 else
1576 delete pBox;
1578 return TRUE;
1581 BOOL lcl_Merge_MoveLine( const _FndLine*& rpFndLine, void* pPara )
1583 _InsULPara* pULPara = (_InsULPara*)pPara;
1584 SwTableLines* pLines;
1586 USHORT nStt = 0, nEnd = rpFndLine->GetBoxes().Count();
1587 USHORT nInsPos = USHRT_MAX;
1588 if( pULPara->bUL_LR ) // UpperLower ?
1590 USHORT nPos;
1591 SwTableLine* pFndLn = (SwTableLine*)rpFndLine->GetLine();
1592 pLines = pFndLn->GetUpper() ?
1593 &pFndLn->GetUpper()->GetTabLines() :
1594 &pULPara->pTblNd->GetTable().GetTabLines();
1596 SwTableBox* pLBx = rpFndLine->GetBoxes()[0]->GetBox();
1597 SwTableBox* pRBx = rpFndLine->GetBoxes()[
1598 rpFndLine->GetBoxes().Count()-1]->GetBox();
1599 USHORT nLeft = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pLBx );
1600 USHORT nRight = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pRBx );
1602 // if( ( nLeft && nRight+1 < pFndLn->GetTabBoxes().Count() ) ||
1603 // ( !nLeft && nRight+1 >= pFndLn->GetTabBoxes().Count() ) )
1604 if( !nLeft || nRight == pFndLn->GetTabBoxes().Count() )
1606 if( pULPara->bUL ) // Upper ?
1608 // gibt es noch davor Zeilen, dann move sie
1609 if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
1610 lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
1612 else
1613 // gibt es noch dahinter Zeilen, dann move sie
1614 if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
1616 nInsPos = pULPara->pInsBox->GetTabLines().Count();
1617 lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
1618 pULPara->pInsBox );
1621 else if( nLeft )
1623 // es gibt links noch weitere Boxen, also setze Left-
1624 // und Merge-Box in eine Box und Line, fuege davor/dahinter
1625 // eine Line mit Box ein, in die die oberen/unteren Lines
1626 // eingefuegt werden
1627 SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
1628 SwTableBox* pLMBox = new SwTableBox(
1629 (SwTableBoxFmt*)pULPara->pLeftBox->GetFrmFmt(), 0, pInsLine );
1630 SwTableLine* pLMLn = new SwTableLine(
1631 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pLMBox );
1632 pLMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
1634 pLMBox->GetTabLines().C40_INSERT( SwTableLine, pLMLn, 0 );
1636 lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
1638 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLMBox, 0 );
1640 if( pULPara->bUL ) // Upper ?
1642 // gibt es noch davor Zeilen, dann move sie
1643 if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
1644 lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
1646 else
1647 // gibt es noch dahinter Zeilen, dann move sie
1648 if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
1649 lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
1650 pLMBox );
1651 lcl_CalcWidth( pLMBox ); // bereche die Breite der Box
1653 else if( nRight+1 < pFndLn->GetTabBoxes().Count() )
1655 // es gibt rechts noch weitere Boxen, also setze Right-
1656 // und Merge-Box in eine Box und Line, fuege davor/dahinter
1657 // eine Line mit Box ein, in die die oberen/unteren Lines
1658 // eingefuegt werden
1659 SwTableLine* pInsLine = pULPara->pRightBox->GetUpper();
1660 SwTableBox* pRMBox;
1661 if( pULPara->pLeftBox->GetUpper() == pInsLine )
1663 pRMBox = new SwTableBox(
1664 (SwTableBoxFmt*)pULPara->pRightBox->GetFrmFmt(), 0, pInsLine );
1665 SwTableLine* pRMLn = new SwTableLine(
1666 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pRMBox );
1667 pRMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
1668 pRMBox->GetTabLines().C40_INSERT( SwTableLine, pRMLn, 0 );
1670 lcl_CpyBoxes( 1, 3, pInsLine->GetTabBoxes(), pRMLn );
1672 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
1674 else
1676 // Left und Merge wurden schon zusammengefuegt, also move
1677 // Right auch mit in die Line
1679 pInsLine = pULPara->pLeftBox->GetUpper();
1680 USHORT nMvPos = pULPara->pRightBox->GetUpper()->GetTabBoxes().
1681 C40_GETPOS( SwTableBox, pULPara->pRightBox );
1682 lcl_CpyBoxes( nMvPos, nMvPos+1,
1683 pULPara->pRightBox->GetUpper()->GetTabBoxes(),
1684 pInsLine );
1685 pRMBox = pInsLine->GetUpper();
1687 // sind schon Lines vorhanden, dann muessen diese in eine
1688 // neue Line und Box
1689 nMvPos = pRMBox->GetTabLines().C40_GETPOS( SwTableLine, pInsLine );
1690 if( pULPara->bUL ? nMvPos
1691 : nMvPos+1 < pRMBox->GetTabLines().Count() )
1693 // alle Lines zu einer neuen Line und Box zusammenfassen
1694 SwTableLine* pNewLn = new SwTableLine(
1695 (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pRMBox );
1696 pNewLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
1697 pRMBox->GetTabLines().C40_INSERT( SwTableLine, pNewLn,
1698 pULPara->bUL ? nMvPos : nMvPos+1 );
1699 pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
1700 pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
1702 USHORT nPos1, nPos2;
1703 if( pULPara->bUL )
1704 nPos1 = 0,
1705 nPos2 = nMvPos;
1706 else
1707 nPos1 = nMvPos+2,
1708 nPos2 = pNewLn->GetUpper()->GetTabLines().Count();
1710 lcl_CpyLines( nPos1, nPos2,
1711 pNewLn->GetUpper()->GetTabLines(), pRMBox );
1712 lcl_CalcWidth( pRMBox ); // bereche die Breite der Box
1714 pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
1715 pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox,
1716 pNewLn->GetTabBoxes().Count() );
1719 if( pULPara->bUL ) // Upper ?
1721 // gibt es noch davor Zeilen, dann move sie
1722 if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
1723 lcl_CpyLines( 0, nPos, *pLines, pRMBox, 0 );
1725 else
1726 // gibt es noch dahinter Zeilen, dann move sie
1727 if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
1728 lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
1729 pRMBox );
1730 lcl_CalcWidth( pRMBox ); // bereche die Breite der Box
1732 else {
1733 ASSERT( FALSE , "Was denn nun" );
1736 // Left/Right
1737 else
1739 // suche nur die Line, ab der Verschoben werden muss
1740 nStt = pULPara->bUL ? 0 : rpFndLine->GetBoxes().Count()-1;
1741 nEnd = nStt+1;
1743 pLines = &pULPara->pInsBox->GetTabLines();
1745 SwTableLine* pNewLine = new SwTableLine(
1746 (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), 0, pULPara->pInsBox );
1747 _InsULPara aPara( *pULPara ); // kopieren
1748 aPara.pInsLine = pNewLine;
1749 ((_FndLine*)rpFndLine)->GetBoxes().ForEach( nStt, nEnd,
1750 &lcl_Merge_MoveBox, &aPara );
1751 if( pNewLine->GetTabBoxes().Count() )
1753 if( USHRT_MAX == nInsPos )
1754 nInsPos = pLines->Count();
1755 pLines->C40_INSERT( SwTableLine, pNewLine, nInsPos );
1757 else
1758 delete pNewLine;
1760 return TRUE;
1764 BOOL SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
1765 SwTableBox* pMergeBox, SwUndoTblMerge* pUndo )
1767 ASSERT( rBoxes.Count() && pMergeBox, "keine gueltigen Werte" );
1768 SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
1769 if( !pTblNd )
1770 return FALSE;
1772 // suche alle Boxen / Lines
1773 _FndBox aFndBox( 0, 0 );
1775 _FndPara aPara( rBoxes, &aFndBox );
1776 GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
1778 if( !aFndBox.GetLines().Count() )
1779 return FALSE;
1781 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1782 // the table to complex to be handled with chart.
1783 // Thus we tell the charts to use their own data provider and forget about this table
1784 pDoc->CreateChartInternalDataProviders( this );
1786 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
1788 if( pUndo )
1789 pUndo->SetSelBoxes( rBoxes );
1791 //Lines fuer das Layout-Update herausuchen.
1792 aFndBox.SetTableLines( *this );
1793 aFndBox.DelFrms( *this );
1795 _FndBox* pFndBox = &aFndBox;
1796 while( 1 == pFndBox->GetLines().Count() &&
1797 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
1798 pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
1800 SwTableLine* pInsLine = new SwTableLine(
1801 (SwTableLineFmt*)pFndBox->GetLines()[0]->GetLine()->GetFrmFmt(), 0,
1802 !pFndBox->GetUpper() ? 0 : pFndBox->GetBox() );
1803 pInsLine->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
1805 // trage die neue Line ein
1806 SwTableLines* pLines = pFndBox->GetUpper() ?
1807 &pFndBox->GetBox()->GetTabLines() : &GetTabLines();
1809 SwTableLine* pNewLine = pFndBox->GetLines()[0]->GetLine();
1810 USHORT nInsPos = pLines->C40_GETPOS( SwTableLine, pNewLine );
1811 pLines->C40_INSERT( SwTableLine, pInsLine, nInsPos );
1813 SwTableBox* pLeftBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
1814 SwTableBox* pRightBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
1815 pMergeBox->SetUpper( pInsLine );
1816 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLeftBox, 0 );
1817 pLeftBox->ClaimFrmFmt();
1818 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pMergeBox, 1 );
1819 pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRightBox, 2 );
1820 pRightBox->ClaimFrmFmt();
1822 // in diese kommen alle Lines, die ueber dem selektierten Bereich stehen
1823 // Sie bilden also eine Upper/Lower Line
1824 _InsULPara aPara( pTblNd, TRUE, TRUE, pLeftBox, pMergeBox, pRightBox, pInsLine );
1826 // move die oben/unten ueberhaengenden Lines vom selektierten Bereich
1827 pFndBox->GetLines()[0]->GetBoxes().ForEach( &lcl_Merge_MoveBox,
1828 &aPara );
1829 aPara.SetLower( pInsLine );
1830 USHORT nEnd = pFndBox->GetLines().Count()-1;
1831 pFndBox->GetLines()[nEnd]->GetBoxes().ForEach( &lcl_Merge_MoveBox,
1832 &aPara );
1834 // move die links/rechts hereinreichenden Boxen vom selektierten Bereich
1835 aPara.SetLeft( pLeftBox );
1836 pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara );
1838 aPara.SetRight( pRightBox );
1839 pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara );
1841 if( !pLeftBox->GetTabLines().Count() )
1842 _DeleteBox( *this, pLeftBox, 0, FALSE, FALSE );
1843 else
1845 lcl_CalcWidth( pLeftBox ); // bereche die Breite der Box
1846 if( pUndo && pLeftBox->GetSttNd() )
1847 pUndo->AddNewBox( pLeftBox->GetSttIdx() );
1849 if( !pRightBox->GetTabLines().Count() )
1850 _DeleteBox( *this, pRightBox, 0, FALSE, FALSE );
1851 else
1853 lcl_CalcWidth( pRightBox ); // bereche die Breite der Box
1854 if( pUndo && pRightBox->GetSttNd() )
1855 pUndo->AddNewBox( pRightBox->GetSttIdx() );
1858 DeleteSel( pDoc, rBoxes, 0, 0, FALSE, FALSE );
1860 // dann raeume die Struktur dieser Line noch mal auf:
1861 // generell alle Aufraeumen
1862 GCLines();
1864 GetTabLines()[0]->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
1866 aFndBox.MakeFrms( *this );
1868 CHECKBOXWIDTH
1869 CHECKTABLELAYOUT
1871 return TRUE;
1874 // ---------------------------------------------------------------
1876 void lcl_CheckRowSpan( SwTable &rTbl )
1878 USHORT nLineCount = rTbl.GetTabLines().Count();
1879 USHORT nMaxSpan = nLineCount;
1880 long nMinSpan = 1;
1881 while( nMaxSpan )
1883 SwTableLine* pLine = rTbl.GetTabLines()[ nLineCount - nMaxSpan ];
1884 for( USHORT nBox = 0; nBox < pLine->GetTabBoxes().Count(); ++nBox )
1886 SwTableBox* pBox = pLine->GetTabBoxes()[nBox];
1887 long nRowSpan = pBox->getRowSpan();
1888 if( nRowSpan > nMaxSpan )
1889 pBox->setRowSpan( nMaxSpan );
1890 else if( nRowSpan < nMinSpan )
1891 pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
1893 --nMaxSpan;
1894 nMinSpan = -nMaxSpan;
1898 USHORT lcl_GetBoxOffset( const _FndBox& rBox )
1900 // suche die erste Box
1901 const _FndBox* pFirstBox = &rBox;
1902 while( pFirstBox->GetLines().Count() )
1903 pFirstBox = pFirstBox->GetLines()[ 0 ]->GetBoxes()[ 0 ];
1905 USHORT nRet = 0;
1906 // dann ueber die Lines nach oben die Position bestimmen
1907 const SwTableBox* pBox = pFirstBox->GetBox();
1908 do {
1909 const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
1910 const SwTableBox* pCmp;
1911 for( USHORT n = 0; pBox != ( pCmp = rBoxes[ n ] ); ++n )
1912 nRet = nRet + (USHORT) pCmp->GetFrmFmt()->GetFrmSize().GetWidth();
1913 pBox = pBox->GetUpper()->GetUpper();
1914 } while( pBox );
1915 return nRet;
1918 USHORT lcl_GetLineWidth( const _FndLine& rLine )
1920 USHORT nRet = 0;
1921 for( USHORT n = rLine.GetBoxes().Count(); n; )
1922 nRet = nRet + (USHORT)rLine.GetBoxes()[ --n ]->GetBox()->GetFrmFmt()
1923 ->GetFrmSize().GetWidth();
1924 return nRet;
1927 void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara )
1929 rPara.pWidths.reset();
1930 USHORT nLineCount = rFndLines.Count();
1931 if( nLineCount )
1933 rPara.pWidths = boost::shared_ptr< std::vector< std::vector< ULONG > > >
1934 ( new std::vector< std::vector< ULONG > >( nLineCount ));
1935 // First we collect information about the left/right borders of all
1936 // selected cells
1937 for( USHORT nLine = 0; nLine < nLineCount; ++nLine )
1939 std::vector< ULONG > &rWidth = (*rPara.pWidths.get())[ nLine ];
1940 const _FndLine *pFndLine = rFndLines[ nLine ];
1941 if( pFndLine && pFndLine->GetBoxes().Count() )
1943 const SwTableLine *pLine = pFndLine->GetLine();
1944 if( pLine && pLine->GetTabBoxes().Count() )
1946 USHORT nBoxCount = pLine->GetTabBoxes().Count();
1947 ULONG nPos = 0;
1948 // The first selected box...
1949 const SwTableBox *pSel = pFndLine->GetBoxes()[0]->GetBox();
1950 USHORT nBox = 0;
1951 // Sum up the width of all boxes before the first selected box
1952 while( nBox < nBoxCount )
1954 SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
1955 if( pBox != pSel )
1956 nPos += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1957 else
1958 break;
1960 // nPos is now the left border of the first selceted box
1961 if( rPara.nMinLeft > nPos )
1962 rPara.nMinLeft = nPos;
1963 nBoxCount = pFndLine->GetBoxes().Count();
1964 rWidth = std::vector< ULONG >( nBoxCount+2 );
1965 rWidth[ 0 ] = nPos;
1966 // Add now the widths of all selected boxes and store
1967 // the positions in the vector
1968 for( nBox = 0; nBox < nBoxCount; )
1970 nPos += pFndLine->GetBoxes()[nBox]
1971 ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
1972 rWidth[ ++nBox ] = nPos;
1974 // nPos: The right border of the last selected box
1975 if( rPara.nMaxRight < nPos )
1976 rPara.nMaxRight = nPos;
1977 if( nPos <= rWidth[ 0 ] )
1978 rWidth.clear();
1983 // Second step: calculate the new widths for the copied cells
1984 ULONG nSelSize = rPara.nMaxRight - rPara.nMinLeft;
1985 if( nSelSize )
1987 for( USHORT nLine = 0; nLine < nLineCount; ++nLine )
1989 std::vector< ULONG > &rWidth = (*rPara.pWidths.get())[ nLine ];
1990 USHORT nCount = (USHORT)rWidth.size();
1991 if( nCount > 2 )
1993 rWidth[ nCount - 1 ] = rPara.nMaxRight;
1994 ULONG nLastPos = 0;
1995 for( USHORT nBox = 0; nBox < nCount; ++nBox )
1997 sal_uInt64 nNextPos = rWidth[ nBox ];
1998 nNextPos -= rPara.nMinLeft;
1999 nNextPos *= rPara.nNewSize;
2000 nNextPos /= nSelSize;
2001 rWidth[ nBox ] = (ULONG)(nNextPos - nLastPos);
2002 nLastPos = (ULONG)nNextPos;
2009 BOOL lcl_CopyBoxToDoc( const _FndBox*& rpFndBox, void* pPara )
2011 _CpyPara* pCpyPara = (_CpyPara*)pPara;
2013 // Calculation of new size
2014 ULONG nRealSize;
2015 ULONG nDummy1 = 0;
2016 ULONG nDummy2 = 0;
2017 if( pCpyPara->pTblNd->GetTable().IsNewModel() )
2019 if( pCpyPara->nBoxIdx == 1 )
2020 nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0];
2021 nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
2022 if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 )
2023 nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
2025 else
2027 nRealSize = pCpyPara->nNewSize;
2028 nRealSize *= rpFndBox->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
2029 nRealSize /= pCpyPara->nOldSize;
2032 ULONG nSize;
2033 bool bDummy = nDummy1 > 0;
2034 if( bDummy )
2035 nSize = nDummy1;
2036 else
2038 nSize = nRealSize;
2039 nRealSize = 0;
2043 // suche das Frame-Format in der Liste aller Frame-Formate
2044 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt() );
2046 SwFmtFrmSize aFrmSz;
2047 USHORT nFndPos;
2048 if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ) ||
2049 ( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrmFmt->
2050 GetFrmSize()).GetWidth() != (SwTwips)nSize )
2052 // es ist noch nicht vorhanden, also kopiere es
2053 aFindFrm.pNewFrmFmt = pCpyPara->pDoc->MakeTableBoxFmt();
2054 aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndBox->GetBox()->GetFrmFmt() );
2055 if( !pCpyPara->bCpyCntnt )
2056 aFindFrm.pNewFrmFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
2057 aFrmSz.SetWidth( nSize );
2058 aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
2059 pCpyPara->rTabFrmArr.Insert( aFindFrm );
2062 SwTableBox* pBox;
2063 if( rpFndBox->GetLines().Count() )
2065 pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
2066 rpFndBox->GetLines().Count(), pCpyPara->pInsLine );
2067 pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++ );
2068 _CpyPara aPara( *pCpyPara, pBox );
2069 aPara.nNewSize = nSize; // hole die Groesse
2070 ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
2072 else
2074 // erzeuge eine leere Box
2075 pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTblNd, pCpyPara->pInsLine,
2076 aFindFrm.pNewFrmFmt,
2077 (SwTxtFmtColl*)pCpyPara->pDoc->GetDfltTxtFmtColl(),
2078 0, pCpyPara->nInsPos );
2079 pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
2080 if( bDummy )
2081 pBox->setDummyFlag( true );
2082 else if( pCpyPara->bCpyCntnt )
2084 // dann kopiere mal den Inhalt in diese leere Box
2085 pBox->setRowSpan( rpFndBox->GetBox()->getRowSpan() );
2087 // der Inhalt kopiert wird, dann koennen auch Formeln&Values
2088 // kopiert werden.
2090 SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(),
2091 RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2092 aBoxAttrSet.Put( rpFndBox->GetBox()->GetFrmFmt()->GetAttrSet() );
2093 if( aBoxAttrSet.Count() )
2095 const SfxPoolItem* pItem;
2096 SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( FALSE );
2097 if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
2098 GetItemState( RES_BOXATR_FORMAT, FALSE, &pItem ) )
2100 ULONG nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
2101 ULONG nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
2102 if( nNewIdx != nOldIdx )
2103 aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
2105 pBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
2108 SwDoc* pFromDoc = rpFndBox->GetBox()->GetFrmFmt()->GetDoc();
2109 SwNodeRange aCpyRg( *rpFndBox->GetBox()->GetSttNd(), 1,
2110 *rpFndBox->GetBox()->GetSttNd()->EndOfSectionNode() );
2111 SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
2113 pFromDoc->CopyWithFlyInFly( aCpyRg, 0, aInsIdx, FALSE );
2114 // den initialen TextNode loeschen
2115 pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 );
2117 ++pCpyPara->nInsPos;
2119 if( nRealSize )
2121 bDummy = false;
2122 nSize = nRealSize;
2123 nRealSize = 0;
2125 else
2127 bDummy = true;
2128 nSize = nDummy2;
2129 nDummy2 = 0;
2132 while( nSize );
2133 return TRUE;
2136 BOOL lcl_CopyLineToDoc( const _FndLine*& rpFndLine, void* pPara )
2138 _CpyPara* pCpyPara = (_CpyPara*)pPara;
2140 // suche das Format in der Liste aller Formate
2141 _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndLine->GetLine()->GetFrmFmt() );
2142 USHORT nFndPos;
2143 if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
2145 // es ist noch nicht vorhanden, also kopiere es
2146 aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pCpyPara->pDoc->MakeTableLineFmt();
2147 aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndLine->GetLine()->GetFrmFmt() );
2148 pCpyPara->rTabFrmArr.Insert( aFindFrm );
2150 else
2151 aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
2153 SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)aFindFrm.pNewFrmFmt,
2154 rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox );
2155 if( pCpyPara->pInsBox )
2157 pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
2159 else
2161 pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
2162 pCpyPara->nInsPos++ );
2165 _CpyPara aPara( *pCpyPara, pNewLine );
2167 if( pCpyPara->pTblNd->GetTable().IsNewModel() )
2169 aPara.nOldSize = 0; // will not be used
2170 aPara.nBoxIdx = 1;
2172 else if( rpFndLine->GetBoxes().Count() ==
2173 rpFndLine->GetLine()->GetTabBoxes().Count() )
2175 // hole die Size vom Parent
2176 const SwFrmFmt* pFmt;
2178 if( rpFndLine->GetLine()->GetUpper() )
2179 pFmt = rpFndLine->GetLine()->GetUpper()->GetFrmFmt();
2180 else
2181 pFmt = pCpyPara->pTblNd->GetTable().GetFrmFmt();
2182 aPara.nOldSize = pFmt->GetFrmSize().GetWidth();
2184 else
2185 // errechne sie
2186 for( USHORT n = 0; n < rpFndLine->GetBoxes().Count(); ++n )
2187 aPara.nOldSize += rpFndLine->GetBoxes()[n]
2188 ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
2190 ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyBoxToDoc, &aPara );
2191 if( pCpyPara->pTblNd->GetTable().IsNewModel() )
2192 ++pCpyPara->nLnIdx;
2193 return TRUE;
2196 BOOL SwTable::CopyHeadlineIntoTable( SwTableNode& rTblNd )
2198 // suche alle Boxen / Lines
2199 SwSelBoxes aSelBoxes;
2200 SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
2201 pBox = GetTblBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
2202 SelLineFromBox( pBox, aSelBoxes, TRUE );
2204 _FndBox aFndBox( 0, 0 );
2206 _FndPara aPara( aSelBoxes, &aFndBox );
2207 ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
2209 if( !aFndBox.GetLines().Count() )
2210 return FALSE;
2213 // Tabellen-Formeln in die relative Darstellung umwandeln
2214 SwTableFmlUpdate aMsgHnt( this );
2215 aMsgHnt.eFlags = TBL_RELBOXNAME;
2216 GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt );
2219 _CpyTabFrms aCpyFmt;
2220 _CpyPara aPara( &rTblNd, 1, aCpyFmt, TRUE );
2221 aPara.nNewSize = aPara.nOldSize = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
2222 // dann kopiere mal
2223 if( IsNewModel() )
2224 lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2225 aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
2226 if( rTblNd.GetTable().IsNewModel() )
2227 { // The copied line must not contain any row span attributes > 1
2228 SwTableLine* pLine = rTblNd.GetTable().GetTabLines()[0];
2229 USHORT nColCount = pLine->GetTabBoxes().Count();
2230 ASSERT( nColCount, "Empty Table Line" )
2231 for( USHORT nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
2233 SwTableBox* pTableBox = pLine->GetTabBoxes()[nCurrCol];
2234 ASSERT( pTableBox, "Missing Table Box" );
2235 pTableBox->setRowSpan( 1 );
2239 return TRUE;
2242 BOOL SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos,
2243 const SwSelBoxes& rSelBoxes, BOOL bCpyNds,
2244 BOOL bCpyName ) const
2246 // suche alle Boxen / Lines
2247 _FndBox aFndBox( 0, 0 );
2249 _FndPara aPara( rSelBoxes, &aFndBox );
2250 ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
2252 if( !aFndBox.GetLines().Count() )
2253 return FALSE;
2255 // erst die Poolvorlagen fuer die Tabelle kopieren, damit die dann
2256 // wirklich kopiert und damit die gueltigen Werte haben.
2257 SwDoc* pSrcDoc = GetFrmFmt()->GetDoc();
2258 if( pSrcDoc != pInsDoc )
2260 pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE ) );
2261 pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ) );
2264 SwTable* pNewTbl = (SwTable*)pInsDoc->InsertTable(
2265 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ),
2266 rPos, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(),
2267 0, 0, FALSE, IsNewModel() );
2268 if( !pNewTbl )
2269 return FALSE;
2271 SwNodeIndex aIdx( rPos.nNode, -1 );
2272 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
2273 aIdx++;
2274 ASSERT( pTblNd, "wo ist denn nun der TableNode?" );
2276 pTblNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
2278 if( IS_TYPE( SwDDETable, this ))
2280 // es wird eine DDE-Tabelle kopiert
2281 // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
2282 SwFieldType* pFldType = pInsDoc->InsertFldType(
2283 *((SwDDETable*)this)->GetDDEFldType() );
2284 ASSERT( pFldType, "unbekannter FieldType" );
2286 // tauschen am Node den Tabellen-Pointer aus
2287 pNewTbl = new SwDDETable( *pNewTbl,
2288 (SwDDEFieldType*)pFldType );
2289 pTblNd->SetNewTable( pNewTbl, FALSE );
2292 pNewTbl->GetFrmFmt()->CopyAttrs( *GetFrmFmt() );
2293 pNewTbl->SetTblChgMode( GetTblChgMode() );
2295 //Vernichten der Frms die bereits angelegt wurden.
2296 pTblNd->DelFrms();
2299 // Tabellen-Formeln in die relative Darstellung umwandeln
2300 SwTableFmlUpdate aMsgHnt( this );
2301 aMsgHnt.eFlags = TBL_RELBOXNAME;
2302 pSrcDoc->UpdateTblFlds( &aMsgHnt );
2305 SwTblNumFmtMerge aTNFM( *pSrcDoc, *pInsDoc );
2307 // Namen auch kopieren oder neuen eindeutigen erzeugen
2308 if( bCpyName )
2309 pNewTbl->GetFrmFmt()->SetName( GetFrmFmt()->GetName() );
2311 _CpyTabFrms aCpyFmt;
2312 _CpyPara aPara( pTblNd, 1, aCpyFmt, bCpyNds );
2313 aPara.nNewSize = aPara.nOldSize = GetFrmFmt()->GetFrmSize().GetWidth();
2315 if( IsNewModel() )
2316 lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2317 // dann kopiere mal
2318 aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
2320 // dann setze oben und unten noch die "richtigen" Raender:
2322 _FndLine* pFndLn = aFndBox.GetLines()[ 0 ];
2323 SwTableLine* pLn = pFndLn->GetLine();
2324 const SwTableLine* pTmp = pLn;
2325 USHORT nLnPos = GetTabLines().GetPos( pTmp );
2326 if( USHRT_MAX != nLnPos && nLnPos )
2328 // es gibt eine Line davor
2329 SwCollectTblLineBoxes aLnPara( FALSE, HEADLINE_BORDERCOPY );
2331 pLn = GetTabLines()[ nLnPos - 1 ];
2332 pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
2334 if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2335 lcl_GetLineWidth( *pFndLn )) )
2337 aLnPara.SetValues( TRUE );
2338 pLn = pNewTbl->GetTabLines()[ 0 ];
2339 pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
2343 pFndLn = aFndBox.GetLines()[ aFndBox.GetLines().Count() -1 ];
2344 pLn = pFndLn->GetLine();
2345 pTmp = pLn;
2346 nLnPos = GetTabLines().GetPos( pTmp );
2347 if( nLnPos < GetTabLines().Count() - 1 )
2349 // es gibt eine Line dahinter
2350 SwCollectTblLineBoxes aLnPara( TRUE, HEADLINE_BORDERCOPY );
2352 pLn = GetTabLines()[ nLnPos + 1 ];
2353 pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
2355 if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2356 lcl_GetLineWidth( *pFndLn )) )
2358 aLnPara.SetValues( FALSE );
2359 pLn = pNewTbl->GetTabLines()[ pNewTbl->GetTabLines().Count()-1 ];
2360 pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
2365 // die initiale Box muss noch geloescht werden
2366 _DeleteBox( *pNewTbl, pNewTbl->GetTabLines()[
2367 pNewTbl->GetTabLines().Count() - 1 ]->GetTabBoxes()[0],
2368 0, FALSE, FALSE );
2370 if( pNewTbl->IsNewModel() )
2371 lcl_CheckRowSpan( *pNewTbl );
2372 // Mal kurz aufraeumen:
2373 pNewTbl->GCLines();
2375 pTblNd->MakeFrms( &aIdx ); // erzeuge die Frames neu
2377 CHECKTABLELAYOUT
2379 return TRUE;
2384 // ---------------------------------------------------------------
2386 // suche ab dieser Line nach der naechsten Box mit Inhalt
2387 SwTableBox* SwTableLine::FindNextBox( const SwTable& rTbl,
2388 const SwTableBox* pSrchBox, BOOL bOvrTblLns ) const
2390 const SwTableLine* pLine = this; // fuer M800
2391 SwTableBox* pBox;
2392 USHORT nFndPos;
2393 if( GetTabBoxes().Count() && pSrchBox &&
2394 USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
2395 nFndPos + 1 != GetTabBoxes().Count() )
2397 pBox = GetTabBoxes()[ nFndPos + 1 ];
2398 while( pBox->GetTabLines().Count() )
2399 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
2400 return pBox;
2403 if( GetUpper() )
2405 nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2406 ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" );
2407 // gibts eine weitere Line
2408 if( nFndPos+1 >= GetUpper()->GetTabLines().Count() )
2409 return GetUpper()->GetUpper()->FindNextBox( rTbl, GetUpper(), bOvrTblLns );
2410 pLine = GetUpper()->GetTabLines()[nFndPos+1];
2412 else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ?
2414 // suche in der Tabelle nach der naechsten Line
2415 nFndPos = rTbl.GetTabLines().GetPos( pLine );
2416 if( nFndPos + 1 >= rTbl.GetTabLines().Count() )
2417 return 0; // es gibt keine weitere Box mehr
2419 pLine = rTbl.GetTabLines()[ nFndPos+1 ];
2421 else
2422 return 0;
2424 if( pLine->GetTabBoxes().Count() )
2426 pBox = pLine->GetTabBoxes()[0];
2427 while( pBox->GetTabLines().Count() )
2428 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
2429 return pBox;
2431 return pLine->FindNextBox( rTbl, 0, bOvrTblLns );
2434 // suche ab dieser Line nach der vorherigen Box
2435 SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTbl,
2436 const SwTableBox* pSrchBox, BOOL bOvrTblLns ) const
2438 const SwTableLine* pLine = this; // fuer M800
2439 SwTableBox* pBox;
2440 USHORT nFndPos;
2441 if( GetTabBoxes().Count() && pSrchBox &&
2442 USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
2443 nFndPos )
2445 pBox = GetTabBoxes()[ nFndPos - 1 ];
2446 while( pBox->GetTabLines().Count() )
2448 pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
2449 pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
2451 return pBox;
2454 if( GetUpper() )
2456 nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2457 ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" );
2458 // gibts eine weitere Line
2459 if( !nFndPos )
2460 return GetUpper()->GetUpper()->FindPreviousBox( rTbl, GetUpper(), bOvrTblLns );
2461 pLine = GetUpper()->GetTabLines()[nFndPos-1];
2463 else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ?
2465 // suche in der Tabelle nach der naechsten Line
2466 nFndPos = rTbl.GetTabLines().GetPos( pLine );
2467 if( !nFndPos )
2468 return 0; // es gibt keine weitere Box mehr
2470 pLine = rTbl.GetTabLines()[ nFndPos-1 ];
2472 else
2473 return 0;
2475 if( pLine->GetTabBoxes().Count() )
2477 pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
2478 while( pBox->GetTabLines().Count() )
2480 pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
2481 pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
2483 return pBox;
2485 return pLine->FindPreviousBox( rTbl, 0, bOvrTblLns );
2488 // suche ab dieser Line nach der naechsten Box mit Inhalt
2489 SwTableBox* SwTableBox::FindNextBox( const SwTable& rTbl,
2490 const SwTableBox* pSrchBox, BOOL bOvrTblLns ) const
2492 if( !pSrchBox && !GetTabLines().Count() )
2493 return (SwTableBox*)this;
2494 return GetUpper()->FindNextBox( rTbl, pSrchBox ? pSrchBox : this,
2495 bOvrTblLns );
2499 // suche ab dieser Line nach der naechsten Box mit Inhalt
2500 SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTbl,
2501 const SwTableBox* pSrchBox, BOOL bOvrTblLns ) const
2503 if( !pSrchBox && !GetTabLines().Count() )
2504 return (SwTableBox*)this;
2505 return GetUpper()->FindPreviousBox( rTbl, pSrchBox ? pSrchBox : this,
2506 bOvrTblLns );
2510 BOOL lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* )
2512 // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
2513 const SwStartNode* pSttNd = rpBox->GetSttNd();
2514 if( pSttNd )
2515 pSttNd->CheckSectionCondColl();
2516 else
2517 ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_LineSetHeadCondColl, 0 );
2518 return TRUE;
2521 BOOL lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* )
2523 ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
2524 return TRUE;
2527 /* \f */
2529 SwTwips lcl_GetDistance( SwTableBox* pBox, BOOL bLeft )
2531 BOOL bFirst = TRUE;
2532 SwTwips nRet = 0;
2533 SwTableLine* pLine;
2534 while( pBox && 0 != ( pLine = pBox->GetUpper() ) )
2536 USHORT nStt = 0, nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
2538 if( bFirst && !bLeft )
2539 ++nPos;
2540 bFirst = FALSE;
2542 while( nStt < nPos )
2543 nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrmFmt()
2544 ->GetFrmSize().GetWidth();
2545 pBox = pLine->GetUpper();
2547 return nRet;
2550 BOOL lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2551 SwTwips nDist, BOOL bCheck )
2553 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2554 for( USHORT n = 0; n < rBoxes.Count(); ++n )
2556 SwTableBox* pBox = rBoxes[ n ];
2557 SwFrmFmt* pFmt = pBox->GetFrmFmt();
2558 const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
2559 SwTwips nWidth = rSz.GetWidth();
2560 BOOL bGreaterBox = FALSE;
2562 if( bCheck )
2564 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2565 if( !::lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam,
2566 nDist, TRUE ))
2567 return FALSE;
2569 // dann noch mal alle "ContentBoxen" sammeln
2570 if( ( 0 != ( bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
2571 ( !rParam.bBigger && ( Abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) )
2573 rParam.bAnyBoxFnd = TRUE;
2574 SwTwips nLowerDiff;
2575 if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
2577 // die "anderen Boxen" wurden angepasst,
2578 // also sich um diesen Betrag aendern
2579 nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2580 nLowerDiff *= rParam.nDiff;
2581 nLowerDiff /= rParam.nMaxSize;
2582 nLowerDiff = rParam.nDiff - nLowerDiff;
2584 else
2585 nLowerDiff = rParam.nDiff;
2587 if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
2588 return FALSE;
2591 else
2593 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2594 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2596 rParam.nLowerDiff = 0;
2597 lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, nDist, FALSE );
2599 if( nLowerDiff < rParam.nLowerDiff )
2600 nLowerDiff = rParam.nLowerDiff;
2602 rParam.nLowerDiff = nOldLower;
2605 if( nLowerDiff ||
2606 ( 0 != ( bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode &&
2607 ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
2608 ( Abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth )
2609 - rParam.nSide ) < COLFUZZY ))
2611 // in dieser Spalte ist der Cursor - also verkleinern / vergroessern
2612 SwFmtFrmSize aNew( rSz );
2614 if( !nLowerDiff )
2616 if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
2618 // die "anderen Boxen" wurden angepasst,
2619 // also sich um diesen Betrag aendern
2620 nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2621 nLowerDiff *= rParam.nDiff;
2622 nLowerDiff /= rParam.nMaxSize;
2623 nLowerDiff = rParam.nDiff - nLowerDiff;
2625 else
2626 nLowerDiff = rParam.nDiff;
2629 rParam.nLowerDiff += nLowerDiff;
2631 if( rParam.bBigger )
2632 aNew.SetWidth( nWidth + nLowerDiff );
2633 else
2634 aNew.SetWidth( nWidth - nLowerDiff );
2635 rParam.aShareFmts.SetSize( *pBox, aNew );
2636 break;
2640 if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
2641 break;
2643 nDist += nWidth;
2645 // wenns groesser wird, dann wars das
2646 if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) &&
2647 nDist >= rParam.nSide )
2648 break;
2650 return TRUE;
2653 BOOL lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2654 SwTwips nDist, BOOL bCheck )
2656 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2657 for( USHORT n = 0; n < rBoxes.Count(); ++n )
2659 SwTableBox* pBox = rBoxes[ n ];
2660 SwFrmFmt* pFmt = pBox->GetFrmFmt();
2661 const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
2662 SwTwips nWidth = rSz.GetWidth();
2664 if( bCheck )
2666 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2667 if( !::lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ],
2668 rParam, nDist, TRUE ))
2669 return FALSE;
2671 if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode
2672 ? Abs( nDist - rParam.nSide ) < COLFUZZY
2673 : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2674 : nDist >= rParam.nSide - COLFUZZY )) )
2676 rParam.bAnyBoxFnd = TRUE;
2677 SwTwips nDiff;
2678 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
2680 // relativ berechnen
2681 nDiff = nWidth;
2682 nDiff *= rParam.nDiff;
2683 nDiff /= rParam.nMaxSize;
2685 else
2686 nDiff = rParam.nDiff;
2688 if( nWidth < nDiff || nWidth - nDiff < MINLAY )
2689 return FALSE;
2692 else
2694 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2695 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2697 rParam.nLowerDiff = 0;
2698 lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], rParam,
2699 nDist, FALSE );
2701 if( nLowerDiff < rParam.nLowerDiff )
2702 nLowerDiff = rParam.nLowerDiff;
2704 rParam.nLowerDiff = nOldLower;
2706 if( nLowerDiff ||
2707 ( TBLFIX_CHGABS == rParam.nMode
2708 ? Abs( nDist - rParam.nSide ) < COLFUZZY
2709 : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2710 : nDist >= rParam.nSide - COLFUZZY)
2713 SwFmtFrmSize aNew( rSz );
2715 if( !nLowerDiff )
2717 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
2719 // relativ berechnen
2720 nLowerDiff = nWidth;
2721 nLowerDiff *= rParam.nDiff;
2722 nLowerDiff /= rParam.nMaxSize;
2724 else
2725 nLowerDiff = rParam.nDiff;
2728 rParam.nLowerDiff += nLowerDiff;
2730 if( rParam.bBigger )
2731 aNew.SetWidth( nWidth - nLowerDiff );
2732 else
2733 aNew.SetWidth( nWidth + nLowerDiff );
2735 rParam.aShareFmts.SetSize( *pBox, aNew );
2739 nDist += nWidth;
2740 if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) &&
2741 nDist > rParam.nSide )
2742 break;
2744 return TRUE;
2747 /*\f*/
2749 BOOL lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2750 SwTwips nDist, BOOL bCheck )
2752 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2753 USHORT n, nCmp;
2754 for( n = 0; n < rBoxes.Count(); ++n )
2756 SwTableBox* pBox = rBoxes[ n ];
2757 SwTableBoxFmt* pFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
2758 const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
2759 SwTwips nWidth = rSz.GetWidth();
2761 if( bCheck )
2763 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2764 if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam,
2765 nDist, TRUE ))
2766 return FALSE;
2768 // dann noch mal alle "ContentBoxen" sammeln
2769 if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
2770 - rParam.nSide ) < COLFUZZY )
2771 nCmp = 1;
2772 else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide )
2773 nCmp = 2;
2774 else
2775 nCmp = 0;
2777 if( nCmp )
2779 rParam.bAnyBoxFnd = TRUE;
2780 if( pFmt->GetProtect().IsCntntProtected() )
2781 return FALSE;
2783 if( rParam.bSplittBox &&
2784 nWidth - rParam.nDiff <= COLFUZZY +
2785 ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
2786 return FALSE;
2788 if( pBox->GetSttNd() )
2789 rParam.aBoxes.Insert( pBox );
2791 break;
2794 else
2796 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2797 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2799 rParam.nLowerDiff = 0;
2800 lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, nDist, FALSE );
2802 if( nLowerDiff < rParam.nLowerDiff )
2803 nLowerDiff = rParam.nLowerDiff;
2805 rParam.nLowerDiff = nOldLower;
2807 if( nLowerDiff )
2808 nCmp = 1;
2809 else if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
2810 - rParam.nSide ) < COLFUZZY )
2811 nCmp = 2;
2812 else if( nDist + nWidth / 2 > rParam.nSide )
2813 nCmp = 3;
2814 else
2815 nCmp = 0;
2817 if( nCmp )
2819 // in dieser Spalte ist der Cursor - also verkleinern / vergroessern
2820 if( 1 == nCmp )
2822 if( !rParam.bSplittBox )
2824 // die akt. Box auf
2825 SwFmtFrmSize aNew( rSz );
2826 aNew.SetWidth( nWidth + rParam.nDiff );
2827 rParam.aShareFmts.SetSize( *pBox, aNew );
2830 else
2832 ASSERT( pBox->GetSttNd(), "Das muss eine EndBox sein!");
2834 if( !rParam.bLeft && 3 != nCmp )
2835 ++n;
2837 ::_InsTblBox( pFmt->GetDoc(), rParam.pTblNd,
2838 pLine, pFmt, pBox, n );
2840 SwTableBox* pNewBox = rBoxes[ n ];
2841 SwFmtFrmSize aNew( rSz );
2842 aNew.SetWidth( rParam.nDiff );
2843 rParam.aShareFmts.SetSize( *pNewBox, aNew );
2845 // Sonderfall: kein Platz in den anderen Boxen
2846 // aber in der Zelle
2847 if( rParam.bSplittBox )
2849 // die akt. Box auf
2850 SwFmtFrmSize aNewSize( rSz );
2851 aNewSize.SetWidth( nWidth - rParam.nDiff );
2852 rParam.aShareFmts.SetSize( *pBox, aNewSize );
2855 // Sonderbehandlung fuer Umrandung die Rechte muss
2856 // entfernt werden
2858 const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
2859 if( rBoxItem.GetRight() )
2861 SvxBoxItem aTmp( rBoxItem );
2862 aTmp.SetLine( 0, BOX_LINE_RIGHT );
2863 rParam.aShareFmts.SetAttr( rParam.bLeft
2864 ? *pNewBox
2865 : *pBox, aTmp );
2870 rParam.nLowerDiff = rParam.nDiff;
2871 break;
2875 if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
2876 break;
2878 nDist += nWidth;
2880 return TRUE;
2883 BOOL lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2884 SwTwips nDist, BOOL bCheck )
2886 // Sonderfall: kein Platz in den anderen Boxen aber in der Zelle
2887 if( rParam.bSplittBox )
2888 return TRUE;
2890 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2891 USHORT n;
2893 // Tabelle fix, proport.
2894 if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode )
2896 // dann die richtige Breite suchen, auf die sich die relative
2897 // Breitenanpassung bezieht.
2898 SwTwips nTmpDist = nDist;
2899 for( n = 0; n < rBoxes.Count(); ++n )
2901 SwTwips nWidth = rBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
2902 if( (nTmpDist + nWidth / 2 ) > rParam.nSide )
2904 rParam.nRemainWidth = rParam.bLeft
2905 ? USHORT(nTmpDist)
2906 : USHORT(rParam.nTblWidth - nTmpDist);
2907 break;
2909 nTmpDist += nWidth;
2913 for( n = 0; n < rBoxes.Count(); ++n )
2915 SwTableBox* pBox = rBoxes[ n ];
2916 SwFrmFmt* pFmt = pBox->GetFrmFmt();
2917 const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
2918 SwTwips nWidth = rSz.GetWidth();
2920 if( bCheck )
2922 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2923 if( !::lcl_InsOtherBox( pBox->GetTabLines()[ i ],
2924 rParam, nDist, TRUE ))
2925 return FALSE;
2928 rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
2929 (TBLFIX_CHGABS != rParam.nMode ||
2930 n < rBoxes.Count() &&
2931 (nDist + nWidth + rBoxes[ n+1 ]->
2932 GetFrmFmt()->GetFrmSize().GetWidth() / 2)
2933 > rParam.nSide ))
2934 : (nDist + nWidth / 2 ) > rParam.nSide
2937 rParam.bAnyBoxFnd = TRUE;
2938 SwTwips nDiff;
2939 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
2941 // relativ berechnen
2942 nDiff = nWidth;
2943 nDiff *= rParam.nDiff;
2944 nDiff /= rParam.nRemainWidth;
2946 if( nWidth < nDiff || nWidth - nDiff < MINLAY )
2947 return FALSE;
2949 else
2951 nDiff = rParam.nDiff;
2953 // teste ob die linke oder rechte Box gross genug
2954 // ist, um den Platz abzugeben!
2955 // es wird davor oder dahinter eine Box eingefuegt!
2956 SwTwips nTmpWidth = nWidth;
2957 if( rParam.bLeft && pBox->GetUpper()->GetUpper() )
2959 const SwTableBox* pTmpBox = pBox;
2960 USHORT nBoxPos = n;
2961 while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() )
2963 pTmpBox = pTmpBox->GetUpper()->GetUpper();
2964 nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox );
2966 // if( nBoxPos )
2967 nTmpWidth = pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
2968 // else
2969 // nTmpWidth = 0;
2972 if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY )
2973 return FALSE;
2974 break;
2978 else
2980 SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2981 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
2983 rParam.nLowerDiff = 0;
2984 lcl_InsOtherBox( pBox->GetTabLines()[ i ], rParam,
2985 nDist, FALSE );
2987 if( nLowerDiff < rParam.nLowerDiff )
2988 nLowerDiff = rParam.nLowerDiff;
2990 rParam.nLowerDiff = nOldLower;
2992 if( nLowerDiff ||
2993 (rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
2994 (TBLFIX_CHGABS != rParam.nMode ||
2995 n < rBoxes.Count() &&
2996 (nDist + nWidth + rBoxes[ n+1 ]->
2997 GetFrmFmt()->GetFrmSize().GetWidth() / 2)
2998 > rParam.nSide ))
2999 : (nDist + nWidth / 2 ) > rParam.nSide ))
3001 if( !nLowerDiff )
3003 if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
3005 // relativ berechnen
3006 nLowerDiff = nWidth;
3007 nLowerDiff *= rParam.nDiff;
3008 nLowerDiff /= rParam.nRemainWidth;
3010 else
3011 nLowerDiff = rParam.nDiff;
3014 SwFmtFrmSize aNew( rSz );
3015 rParam.nLowerDiff += nLowerDiff;
3017 if( rParam.bBigger )
3018 aNew.SetWidth( nWidth - nLowerDiff );
3019 else
3020 aNew.SetWidth( nWidth + nLowerDiff );
3021 rParam.aShareFmts.SetSize( *pBox, aNew );
3023 if( TBLFIX_CHGABS == rParam.nMode )
3024 break;
3028 nDist += nWidth;
3030 return TRUE;
3034 // das Ergebnis des Positions Vergleiches
3035 // POS_BEFORE, // Box liegt davor
3036 // POS_BEHIND, // Box liegt dahinter
3037 // POS_INSIDE, // Box liegt vollstaendig in Start/End
3038 // POS_OUTSIDE, // Box ueberlappt Start/End vollstaendig
3039 // POS_EQUAL, // Box und Start/End sind gleich
3040 // POS_OVERLAP_BEFORE, // Box ueberlappt den Start
3041 // POS_OVERLAP_BEHIND // Box ueberlappt das Ende
3043 SwComparePosition _CheckBoxInRange( USHORT nStt, USHORT nEnd,
3044 USHORT nBoxStt, USHORT nBoxEnd )
3046 // COLFUZZY noch beachten!!
3047 SwComparePosition nRet;
3048 if( nBoxStt + COLFUZZY < nStt )
3050 if( nBoxEnd > nStt + COLFUZZY )
3052 if( nBoxEnd >= nEnd + COLFUZZY )
3053 nRet = POS_OUTSIDE;
3054 else
3055 nRet = POS_OVERLAP_BEFORE;
3057 else
3058 nRet = POS_BEFORE;
3060 else if( nEnd > nBoxStt + COLFUZZY )
3062 if( nEnd + COLFUZZY >= nBoxEnd )
3064 if( COLFUZZY > Abs( long(nEnd) - long(nBoxEnd) ) &&
3065 COLFUZZY > Abs( long(nStt) - long(nBoxStt) ) )
3066 nRet = POS_EQUAL;
3067 else
3068 nRet = POS_INSIDE;
3070 else
3071 nRet = POS_OVERLAP_BEHIND;
3073 else
3074 nRet = POS_BEHIND;
3076 return nRet;
3079 void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam,
3080 SwTwips nWidth )
3082 // 1. Schritt die eigene Breite feststellen
3083 SwTableBoxes& rBoxes = rLine.GetTabBoxes();
3084 SwTwips nBoxWidth = 0;
3085 USHORT n;
3087 for( n = rBoxes.Count(); n; )
3088 nBoxWidth += rBoxes[ --n ]->GetFrmFmt()->GetFrmSize().GetWidth();
3090 if( COLFUZZY < Abs( nWidth - nBoxWidth ))
3092 // sie muessen also angepasst werden
3093 for( n = rBoxes.Count(); n; )
3095 SwTableBox* pBox = rBoxes[ --n ];
3096 SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
3097 long nDiff = aNew.GetWidth();
3098 nDiff *= nWidth;
3099 nDiff /= nBoxWidth;
3100 aNew.SetWidth( nDiff );
3102 rParam.aShareFmts.SetSize( *pBox, aNew );
3104 if( !pBox->GetSttNd() )
3106 // hat selbst auch Lower, also auch die anpassen
3107 for( USHORT i = pBox->GetTabLines().Count(); i; )
3108 ::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ],
3109 rParam, nDiff );
3115 void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam,
3116 const SwFmtFrmSize& rOldSz,
3117 USHORT& rDelWidth, SwTwips nDist )
3119 long nDiff;
3120 BOOL bSetSize = FALSE;
3122 switch( rParam.nMode )
3124 case TBLFIX_CHGABS: // Tabelle feste Breite, den Nachbar andern
3125 nDiff = rDelWidth + rParam.nLowerDiff;
3126 bSetSize = TRUE;
3127 break;
3129 case TBLFIX_CHGPROP: // Tabelle feste Breite, alle Nachbarn aendern
3130 if( !rParam.nRemainWidth )
3132 // dann kurz berechnen:
3133 if( rParam.bLeft )
3134 rParam.nRemainWidth = USHORT(nDist);
3135 else
3136 rParam.nRemainWidth = USHORT(rParam.nTblWidth - nDist);
3139 // relativ berechnen
3140 nDiff = rOldSz.GetWidth();
3141 nDiff *= rDelWidth + rParam.nLowerDiff;
3142 nDiff /= rParam.nRemainWidth;
3144 bSetSize = TRUE;
3145 break;
3147 case TBLVAR_CHGABS: // Tabelle variable, alle Nachbarn aendern
3148 if( COLFUZZY < Abs( rParam.nBoxWidth -
3149 ( rDelWidth + rParam.nLowerDiff )))
3151 nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth;
3152 if( 0 < nDiff )
3153 rDelWidth = rDelWidth - USHORT(nDiff);
3154 else
3155 rDelWidth = rDelWidth + USHORT(-nDiff);
3156 bSetSize = TRUE;
3158 break;
3161 if( bSetSize )
3163 SwFmtFrmSize aNew( rOldSz );
3164 aNew.SetWidth( aNew.GetWidth() + nDiff );
3165 rParam.aShareFmts.SetSize( rBox, aNew );
3167 // dann leider nochmals die Lower anpassen
3168 for( USHORT i = rBox.GetTabLines().Count(); i; )
3169 ::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam,
3170 aNew.GetWidth() );
3174 BOOL lcl_DeleteBox_Rekursiv( CR_SetBoxWidth& rParam, SwTableBox& rBox,
3175 BOOL bCheck )
3177 BOOL bRet = TRUE;
3178 if( rBox.GetSttNd() )
3180 if( bCheck )
3182 rParam.bAnyBoxFnd = TRUE;
3183 if( rBox.GetFrmFmt()->GetProtect().IsCntntProtected() )
3184 bRet = FALSE;
3185 else
3187 SwTableBox* pBox = &rBox;
3188 rParam.aBoxes.Insert( pBox );
3191 else
3192 ::_DeleteBox( rParam.pTblNd->GetTable(), &rBox,
3193 rParam.pUndo, FALSE, TRUE, &rParam.aShareFmts );
3195 else
3197 // die muessen leider alle sequentiel ueber die
3198 // Contentboxen geloescht werden
3199 for( USHORT i = rBox.GetTabLines().Count(); i; )
3201 SwTableLine& rLine = *rBox.GetTabLines()[ --i ];
3202 for( USHORT n = rLine.GetTabBoxes().Count(); n; )
3203 if( !::lcl_DeleteBox_Rekursiv( rParam,
3204 *rLine.GetTabBoxes()[ --n ], bCheck ))
3205 return FALSE;
3208 return bRet;
3211 BOOL lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam,
3212 SwTwips nDist, BOOL bCheck )
3214 SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
3215 USHORT n, nCntEnd, nBoxChkStt, nBoxChkEnd, nDelWidth = 0;
3216 if( rParam.bLeft )
3218 n = rBoxes.Count();
3219 nCntEnd = 0;
3220 nBoxChkStt = (USHORT)rParam.nSide;
3221 nBoxChkEnd = static_cast<USHORT>(rParam.nSide + rParam.nBoxWidth);
3223 else
3225 n = 0;
3226 nCntEnd = rBoxes.Count();
3227 nBoxChkStt = static_cast<USHORT>(rParam.nSide - rParam.nBoxWidth);
3228 nBoxChkEnd = (USHORT)rParam.nSide;
3232 while( n != nCntEnd )
3234 SwTableBox* pBox;
3235 if( rParam.bLeft )
3236 pBox = rBoxes[ --n ];
3237 else
3238 pBox = rBoxes[ n++ ];
3240 SwFrmFmt* pFmt = pBox->GetFrmFmt();
3241 const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
3242 long nWidth = rSz.GetWidth();
3243 BOOL bDelBox = FALSE, bChgLowers = FALSE;
3245 // die Boxenbreite testen und entpsrechend reagieren
3246 SwComparePosition ePosType = ::_CheckBoxInRange(
3247 nBoxChkStt, nBoxChkEnd,
3248 USHORT(rParam.bLeft ? nDist - nWidth : nDist),
3249 USHORT(rParam.bLeft ? nDist : nDist + nWidth));
3251 switch( ePosType )
3253 case POS_BEFORE:
3254 if( bCheck )
3256 if( rParam.bLeft )
3257 return TRUE;
3259 else if( rParam.bLeft )
3261 ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
3262 if( TBLFIX_CHGABS == rParam.nMode )
3263 n = nCntEnd;
3265 break;
3267 case POS_BEHIND:
3268 if( bCheck )
3270 if( !rParam.bLeft )
3271 return TRUE;
3273 else if( !rParam.bLeft )
3275 ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
3276 if( TBLFIX_CHGABS == rParam.nMode )
3277 n = nCntEnd;
3279 break;
3281 case POS_OUTSIDE: // Box ueberlappt Start/End vollstaendig
3282 case POS_INSIDE: // Box liegt vollstaendig in Start/End
3283 case POS_EQUAL: // Box und Start/End sind gleich
3284 bDelBox = TRUE;
3285 break;
3287 case POS_OVERLAP_BEFORE: // Box ueberlappt den Start
3288 if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2
3289 : nWidth / 2 )))
3291 if( !pBox->GetSttNd() )
3292 bChgLowers = TRUE;
3293 else
3294 bDelBox = TRUE;
3296 else if( !bCheck && rParam.bLeft )
3298 if( !pBox->GetSttNd() )
3299 bChgLowers = TRUE;
3300 else
3302 ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
3303 if( TBLFIX_CHGABS == rParam.nMode )
3304 n = nCntEnd;
3307 break;
3309 case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende
3310 // JP 10.02.99:
3311 // generell loeschen oder wie beim OVERLAP_Before nur die, die
3312 // bis zur Haelfte in die "Loesch-"Box reicht ???
3313 if( !pBox->GetSttNd() )
3314 bChgLowers = TRUE;
3315 else
3316 bDelBox = TRUE;
3317 break;
3318 default: break;
3321 if( bDelBox )
3323 nDelWidth = nDelWidth + USHORT(nWidth);
3324 if( bCheck )
3326 // die letzte/erste Box kann nur bei Tbl-Var geloescht werden,
3327 // wenn diese so gross ist, wie die Aenderung an der Tabelle
3328 if( (( TBLVAR_CHGABS != rParam.nMode ||
3329 nDelWidth != rParam.nBoxWidth ) &&
3330 COLFUZZY > Abs( rParam.bLeft
3331 ? nWidth - nDist
3332 : (nDist + nWidth - rParam.nTblWidth )))
3333 || !::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ) )
3334 return FALSE;
3336 if( pFmt->GetProtect().IsCntntProtected() )
3337 return FALSE;
3339 else
3341 ::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck );
3343 if( !rParam.bLeft )
3344 --n, --nCntEnd;
3347 else if( bChgLowers )
3349 BOOL bFirst = TRUE, bCorrLowers = FALSE;
3350 long nLowerDiff = 0;
3351 long nOldLower = rParam.nLowerDiff;
3352 USHORT nOldRemain = rParam.nRemainWidth;
3353 USHORT i;
3355 for( i = pBox->GetTabLines().Count(); i; )
3357 rParam.nLowerDiff = nDelWidth + nOldLower;
3358 rParam.nRemainWidth = nOldRemain;
3359 SwTableLine* pLine = pBox->GetTabLines()[ --i ];
3360 if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck ))
3361 return FALSE;
3363 // gibt es die Box und die darin enthaltenen Lines noch??
3364 if( n < rBoxes.Count() &&
3365 pBox == rBoxes[ rParam.bLeft ? n : n-1 ] &&
3366 i < pBox->GetTabLines().Count() &&
3367 pLine == pBox->GetTabLines()[ i ] )
3369 if( !bFirst && !bCorrLowers &&
3370 COLFUZZY < Abs( nLowerDiff - rParam.nLowerDiff ) )
3371 bCorrLowers = TRUE;
3373 // die groesste "loesch" Breite entscheidet, aber nur wenn
3374 // nicht die gesamte Line geloescht wurde
3375 if( nLowerDiff < rParam.nLowerDiff )
3376 nLowerDiff = rParam.nLowerDiff;
3378 bFirst = FALSE;
3381 rParam.nLowerDiff = nOldLower;
3382 rParam.nRemainWidth = nOldRemain;
3384 // wurden alle Boxen geloescht? Dann ist die DelBreite natuerlich
3385 // die Boxenbreite
3386 if( !nLowerDiff )
3387 nLowerDiff = nWidth;
3389 // DelBreite anpassen!!
3390 nDelWidth = nDelWidth + USHORT(nLowerDiff);
3392 if( !bCheck )
3394 // wurde die Box schon entfernt?
3395 if( n > rBoxes.Count() ||
3396 pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] )
3398 // dann beim Loeschen nach rechts die Laufvar. anpassen
3399 if( !rParam.bLeft )
3400 --n, --nCntEnd;
3402 else
3404 // sonst muss die Groesse der Box angepasst werden
3405 SwFmtFrmSize aNew( rSz );
3406 BOOL bCorrRel = FALSE;
3408 if( TBLVAR_CHGABS != rParam.nMode )
3410 switch( ePosType )
3412 case POS_OVERLAP_BEFORE: // Box ueberlappt den Start
3413 if( TBLFIX_CHGPROP == rParam.nMode )
3414 bCorrRel = rParam.bLeft;
3415 else if( rParam.bLeft ) // TBLFIX_CHGABS
3417 nLowerDiff = nLowerDiff - nDelWidth;
3418 bCorrLowers = TRUE;
3419 n = nCntEnd;
3421 break;
3423 case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende
3424 if( TBLFIX_CHGPROP == rParam.nMode )
3425 bCorrRel = !rParam.bLeft;
3426 else if( !rParam.bLeft ) // TBLFIX_CHGABS
3428 nLowerDiff = nLowerDiff - nDelWidth;
3429 bCorrLowers = TRUE;
3430 n = nCntEnd;
3432 break;
3434 default:
3435 ASSERT( !pBox, "hier sollte man nie hinkommen" );
3436 break;
3440 if( bCorrRel )
3442 if( !rParam.nRemainWidth )
3444 // dann kurz berechnen:
3445 if( rParam.bLeft )
3446 rParam.nRemainWidth = USHORT(nDist - nLowerDiff);
3447 else
3448 rParam.nRemainWidth = USHORT(rParam.nTblWidth - nDist
3449 - nLowerDiff );
3452 long nDiff = aNew.GetWidth() - nLowerDiff;
3453 nDiff *= nDelWidth + rParam.nLowerDiff;
3454 nDiff /= rParam.nRemainWidth;
3456 aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff );
3458 else
3459 aNew.SetWidth( aNew.GetWidth() - nLowerDiff );
3460 rParam.aShareFmts.SetSize( *pBox, aNew );
3462 if( bCorrLowers )
3464 // dann leider nochmals die Lower anpassen
3465 for( i = pBox->GetTabLines().Count(); i; )
3466 ::lcl_DelSelBox_CorrLowers( *pBox->
3467 GetTabLines()[ --i ], rParam, aNew.GetWidth() );
3473 if( rParam.bLeft )
3474 nDist -= nWidth;
3475 else
3476 nDist += nWidth;
3478 rParam.nLowerDiff = nDelWidth;
3479 return TRUE;
3482 // Dummy Funktion fuer die Methode SetColWidth
3483 BOOL lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , BOOL )
3485 return TRUE;
3488 /*\f*/
3490 void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
3492 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
3493 for( USHORT n = 0; n < rBoxes.Count(); ++n )
3495 SwTableBox* pBox = rBoxes[ n ];
3497 SwFmtFrmSize aSz( pBox->GetFrmFmt()->GetFrmSize() );
3498 SwTwips nWidth = aSz.GetWidth();
3499 nWidth *= rParam.nDiff;
3500 nWidth /= rParam.nMaxSize;
3501 aSz.SetWidth( nWidth );
3502 rParam.aShareFmts.SetSize( *pBox, aSz );
3504 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
3505 ::lcl_AjustLines( pBox->GetTabLines()[ i ], rParam );
3509 #if !defined( PRODUCT ) || defined( JP_DEBUG )
3511 void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
3513 const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
3515 SwTwips nAktSize = 0;
3516 // checke doch mal ob die Tabellen korrekte Breiten haben
3517 for( USHORT n = 0; n < rBoxes.Count(); ++n )
3519 const SwTableBox* pBox = rBoxes[ n ];
3520 const SwTwips nBoxW = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
3521 nAktSize += nBoxW;
3523 for( USHORT i = 0; i < pBox->GetTabLines().Count(); ++i )
3524 _CheckBoxWidth( *pBox->GetTabLines()[ i ], nBoxW );
3527 if( Abs( nAktSize - nSize ) > ( COLFUZZY * rBoxes.Count() ) )
3529 DBG_ERROR( "Boxen der Line zu klein/gross" );
3530 #if defined( WNT ) && defined( JP_DEBUG )
3531 __asm int 3;
3532 #endif
3536 #endif
3538 _FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo,
3539 SwTableSortBoxes& rTmpLst, SwTwips nDistStt )
3541 // suche alle Boxen / Lines
3542 SwTable& rTbl = rParam.pTblNd->GetTable();
3544 if( !rParam.aBoxes.Count() )
3546 // erstmal die Boxen besorgen !
3547 if( rParam.bBigger )
3548 for( USHORT n = 0; n < rTbl.GetTabLines().Count(); ++n )
3549 ::lcl_DelSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, TRUE );
3550 else
3551 for( USHORT n = 0; n < rTbl.GetTabLines().Count(); ++n )
3552 ::lcl_InsSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, TRUE );
3555 // loeschen der gesamten Tabelle verhindern
3556 if( rParam.bBigger && rParam.aBoxes.Count() ==
3557 rTbl.GetTabSortBoxes().Count() )
3558 return 0;
3560 _FndBox* pFndBox = new _FndBox( 0, 0 );
3561 if( rParam.bBigger )
3562 pFndBox->SetTableLines( rParam.aBoxes, rTbl );
3563 else
3565 _FndPara aPara( rParam.aBoxes, pFndBox );
3566 rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
3567 ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" );
3568 pFndBox->SetTableLines( rTbl );
3570 if( ppUndo )
3571 rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
3574 //Lines fuer das Layout-Update herausuchen.
3575 pFndBox->DelFrms( rTbl );
3577 // TL_CHART2: this function gest called from SetColWidth exclusively,
3578 // thus it is currently speculated that nothing needs to be done here.
3579 // Note: that SetColWidth is currently not completely understood though :-(
3581 return pFndBox;
3584 BOOL SwTable::SetColWidth( SwTableBox& rAktBox, USHORT eType,
3585 SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo )
3587 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
3589 const SwFmtFrmSize& rSz = GetFrmFmt()->GetFrmSize();
3590 const SvxLRSpaceItem& rLR = GetFrmFmt()->GetLRSpace();
3592 _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen
3593 SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo
3594 BOOL bBigger,
3595 bRet = FALSE,
3596 bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
3597 nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ),
3598 bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
3599 USHORT n;
3600 ULONG nBoxIdx = rAktBox.GetSttIdx();
3602 // bestimme die akt. Kante der Box
3603 // wird nur fuer die Breitenmanipulation benoetigt!
3604 const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft );
3605 SwTwips nDistStt = 0;
3606 CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(),
3607 bLeft ? nDist : rSz.GetWidth() - nDist,
3608 (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
3609 bBigger = aParam.bBigger;
3611 FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
3612 if( bInsDel )
3614 if( bBigger )
3616 fnSelBox = lcl_DelSelBox;
3617 fnOtherBox = lcl_DelOtherBox;
3618 aParam.nBoxWidth = (USHORT)rAktBox.GetFrmFmt()->GetFrmSize().GetWidth();
3619 if( bLeft )
3620 nDistStt = rSz.GetWidth();
3622 else
3624 fnSelBox = lcl_InsSelBox;
3625 fnOtherBox = lcl_InsOtherBox;
3628 else
3630 fnSelBox = lcl_SetSelBoxWidth;
3631 fnOtherBox = lcl_SetOtherBoxWidth;
3635 switch( eType & 0xff )
3637 case nsTblChgWidthHeightType::WH_COL_RIGHT:
3638 case nsTblChgWidthHeightType::WH_COL_LEFT:
3639 if( TBLVAR_CHGABS == eTblChgMode )
3641 if( bInsDel )
3642 bBigger = !bBigger;
3644 // erstmal testen, ob ueberhaupt Platz ist
3645 BOOL bChgLRSpace = TRUE;
3646 if( bBigger )
3648 if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
3649 !rSz.GetWidthPercent() )
3651 bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff;
3652 bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
3653 : rLR.GetRight() >= nAbsDiff;
3655 else
3656 bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
3657 : rLR.GetRight() >= nAbsDiff;
3659 if( !bRet && bInsDel &&
3660 // auf der anderen Seite Platz?
3661 ( bLeft ? rLR.GetRight() >= nAbsDiff
3662 : rLR.GetLeft() >= nAbsDiff ))
3664 bRet = TRUE; bLeft = !bLeft;
3667 if( !bRet )
3669 // dann sich selbst rekursiv aufrufen; nur mit
3670 // einem anderen Mode -> proprotional
3671 TblChgMode eOld = eTblChgMode;
3672 eTblChgMode = TBLFIX_CHGPROP;
3674 bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
3675 ppUndo );
3676 eTblChgMode = eOld;
3677 return bRet;
3680 else
3682 bRet = TRUE;
3683 for( n = 0; n < aLines.Count(); ++n )
3685 aParam.LoopClear();
3686 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, TRUE ))
3688 bRet = FALSE;
3689 break;
3694 if( bRet )
3696 if( bInsDel )
3698 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
3699 aTmpLst, nDistStt );
3700 if( aParam.bBigger && aParam.aBoxes.Count() ==
3701 aSortCntBoxes.Count() )
3703 // dies gesamte Tabelle soll geloescht werden!!
3704 GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
3705 return FALSE;
3708 if( ppUndo )
3709 *ppUndo = aParam.CreateUndo(
3710 aParam.bBigger ? UNDO_COL_DELETE
3711 : UNDO_TABLE_INSCOL );
3713 else if( ppUndo )
3714 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, TRUE );
3716 long nFrmWidth = LONG_MAX;
3717 LockModify();
3718 SwFmtFrmSize aSz( rSz );
3719 SvxLRSpaceItem aLR( rLR );
3720 if( bBigger )
3722 // falls die Tabelle keinen Platz zum Wachsen hat, dann
3723 // muessen wir welchen schaffen!
3724 if( aSz.GetWidth() + nRelDiff > USHRT_MAX )
3726 // dann mal herunterbrechen auf USHRT_MAX / 2
3727 CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2,
3728 0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTblNd );
3729 for( USHORT nLn = 0; nLn < aLines.Count(); ++nLn )
3730 ::lcl_AjustLines( aLines[ nLn ], aTmpPara );
3731 aSz.SetWidth( aSz.GetWidth() / 2 );
3732 aParam.nDiff = nRelDiff /= 2;
3733 aParam.nSide /= 2;
3734 aParam.nMaxSize /= 2;
3737 if( bLeft )
3738 aLR.SetLeft( USHORT( aLR.GetLeft() - nAbsDiff ) );
3739 else
3740 aLR.SetRight( USHORT( aLR.GetRight() - nAbsDiff ) );
3742 else if( bLeft )
3743 aLR.SetLeft( USHORT( aLR.GetLeft() + nAbsDiff ) );
3744 else
3745 aLR.SetRight( USHORT( aLR.GetRight() + nAbsDiff ) );
3747 if( bChgLRSpace )
3748 GetFrmFmt()->SetFmtAttr( aLR );
3749 const SwFmtHoriOrient& rHOri = GetFrmFmt()->GetHoriOrient();
3750 if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
3751 (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
3752 (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
3754 SwFmtHoriOrient aHOri( rHOri );
3755 aHOri.SetHoriOrient( text::HoriOrientation::NONE );
3756 GetFrmFmt()->SetFmtAttr( aHOri );
3758 // sollte die Tabelle noch auf relativen Werten
3759 // (USHRT_MAX) stehen dann muss es jetzt auf absolute
3760 // umgerechnet werden. Bug 61494
3761 if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
3762 !rSz.GetWidthPercent() )
3764 SwTabFrm* pTabFrm = (SwTabFrm*)SwClientIter(
3765 *GetFrmFmt() ).First( TYPE( SwTabFrm ));
3766 if( pTabFrm &&
3767 pTabFrm->Prt().Width() != rSz.GetWidth() )
3769 nFrmWidth = pTabFrm->Prt().Width();
3770 if( bBigger )
3771 nFrmWidth += nAbsDiff;
3772 else
3773 nFrmWidth -= nAbsDiff;
3778 if( bBigger )
3779 aSz.SetWidth( aSz.GetWidth() + nRelDiff );
3780 else
3781 aSz.SetWidth( aSz.GetWidth() - nRelDiff );
3783 if( rSz.GetWidthPercent() )
3784 aSz.SetWidthPercent( static_cast<BYTE>(( aSz.GetWidth() * 100 ) /
3785 ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
3787 GetFrmFmt()->SetFmtAttr( aSz );
3788 aParam.nTblWidth = USHORT( aSz.GetWidth() );
3790 UnlockModify();
3792 for( n = aLines.Count(); n; )
3794 --n;
3795 aParam.LoopClear();
3796 (*fnSelBox)( aLines[ n ], aParam, nDistStt, FALSE );
3799 // sollte die Tabelle noch auf relativen Werten
3800 // (USHRT_MAX) stehen dann muss es jetzt auf absolute
3801 // umgerechnet werden. Bug 61494
3802 if( LONG_MAX != nFrmWidth )
3804 SwFmtFrmSize aAbsSz( aSz );
3805 aAbsSz.SetWidth( nFrmWidth );
3806 GetFrmFmt()->SetFmtAttr( aAbsSz );
3810 else if( bInsDel ||
3811 ( bLeft ? nDist : Abs( rSz.GetWidth() - nDist ) > COLFUZZY ) )
3813 bRet = TRUE;
3814 if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
3815 aParam.bBigger = !bBigger;
3817 // erstmal testen, ob ueberhaupt Platz ist
3818 if( bInsDel )
3820 if( aParam.bBigger )
3822 for( n = 0; n < aLines.Count(); ++n )
3824 aParam.LoopClear();
3825 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, TRUE ))
3827 bRet = FALSE;
3828 break;
3832 else
3834 if( 0 != ( bRet = bLeft ? nDist != 0
3835 : ( rSz.GetWidth() - nDist ) > COLFUZZY ) )
3837 for( n = 0; n < aLines.Count(); ++n )
3839 aParam.LoopClear();
3840 if( !(*fnOtherBox)( aLines[ n ], aParam, 0, TRUE ))
3842 bRet = FALSE;
3843 break;
3846 if( bRet && !aParam.bAnyBoxFnd )
3847 bRet = FALSE;
3850 if( !bRet && rAktBox.GetFrmFmt()->GetFrmSize().GetWidth()
3851 - nRelDiff > COLFUZZY +
3852 ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
3854 // dann den Platz von der akt. Zelle nehmen
3855 aParam.bSplittBox = TRUE;
3856 // aber das muss auch mal getestet werden!
3857 bRet = TRUE;
3859 for( n = 0; n < aLines.Count(); ++n )
3861 aParam.LoopClear();
3862 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, TRUE ))
3864 bRet = FALSE;
3865 break;
3871 else if( aParam.bBigger )
3873 for( n = 0; n < aLines.Count(); ++n )
3875 aParam.LoopClear();
3876 if( !(*fnOtherBox)( aLines[ n ], aParam, 0, TRUE ))
3878 bRet = FALSE;
3879 break;
3883 else
3885 for( n = 0; n < aLines.Count(); ++n )
3887 aParam.LoopClear();
3888 if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, TRUE ))
3890 bRet = FALSE;
3891 break;
3896 // wenn ja, dann setzen
3897 if( bRet )
3899 CR_SetBoxWidth aParam1( aParam );
3900 if( bInsDel )
3902 aParam1.bBigger = !aParam.bBigger;
3903 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
3904 aTmpLst, nDistStt );
3905 if( ppUndo )
3906 *ppUndo = aParam.CreateUndo(
3907 aParam.bBigger ? UNDO_TABLE_DELBOX
3908 : UNDO_TABLE_INSCOL );
3910 else if( ppUndo )
3911 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, TRUE );
3913 if( bInsDel
3914 ? ( TBLFIX_CHGABS == eTblChgMode ? bLeft : bLeft )
3915 : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
3917 for( n = aLines.Count(); n; )
3919 --n;
3920 aParam.LoopClear();
3921 aParam1.LoopClear();
3922 (*fnSelBox)( aLines[ n ], aParam, nDistStt, FALSE );
3923 (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, FALSE );
3926 else
3927 for( n = aLines.Count(); n; )
3929 --n;
3930 aParam.LoopClear();
3931 aParam1.LoopClear();
3932 (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, FALSE );
3933 (*fnSelBox)( aLines[ n ], aParam, nDistStt, FALSE );
3937 break;
3939 case nsTblChgWidthHeightType::WH_CELL_RIGHT:
3940 case nsTblChgWidthHeightType::WH_CELL_LEFT:
3941 if( TBLVAR_CHGABS == eTblChgMode )
3943 // dann sich selbst rekursiv aufrufen; nur mit
3944 // einem anderen Mode -> Nachbarn
3945 TblChgMode eOld = eTblChgMode;
3946 eTblChgMode = TBLFIX_CHGABS;
3948 bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
3949 ppUndo );
3950 eTblChgMode = eOld;
3951 return bRet;
3953 else if( bInsDel || ( bLeft ? nDist
3954 : (rSz.GetWidth() - nDist) > COLFUZZY ))
3956 if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
3957 aParam.bBigger = !bBigger;
3959 // erstmal testen, ob ueberhaupt Platz ist
3960 SwTableBox* pBox = &rAktBox;
3961 SwTableLine* pLine = rAktBox.GetUpper();
3962 while( pLine->GetUpper() )
3964 USHORT nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
3965 if( bLeft ? nPos : nPos + 1 != pLine->GetTabBoxes().Count() )
3966 break;
3968 pBox = pLine->GetUpper();
3969 pLine = pBox->GetUpper();
3972 if( pLine->GetUpper() )
3974 // dann muss die Distanz wieder korriegiert werden!
3975 aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), TRUE );
3977 if( bLeft )
3978 aParam.nMaxSize = aParam.nSide;
3979 else
3980 aParam.nMaxSize = pLine->GetUpper()->GetFrmFmt()->
3981 GetFrmSize().GetWidth() - aParam.nSide;
3984 // erstmal testen, ob ueberhaupt Platz ist
3985 if( bInsDel )
3987 if( 0 != ( bRet = bLeft ? nDist != 0
3988 : ( rSz.GetWidth() - nDist ) > COLFUZZY ) &&
3989 !aParam.bBigger )
3991 bRet = (*fnOtherBox)( pLine, aParam, 0, TRUE );
3992 if( bRet && !aParam.bAnyBoxFnd )
3993 bRet = FALSE;
3996 if( !bRet && !aParam.bBigger && rAktBox.GetFrmFmt()->
3997 GetFrmSize().GetWidth() - nRelDiff > COLFUZZY +
3998 ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
4000 // dann den Platz von der akt. Zelle nehmen
4001 aParam.bSplittBox = TRUE;
4002 bRet = TRUE;
4005 else
4007 FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
4008 bRet = (*fnTmp)( pLine, aParam, nDistStt, TRUE );
4011 // wenn ja, dann setzen
4012 if( bRet )
4014 CR_SetBoxWidth aParam1( aParam );
4015 if( bInsDel )
4017 aParam1.bBigger = !aParam.bBigger;
4018 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst, nDistStt );
4019 if( ppUndo )
4020 *ppUndo = aParam.CreateUndo(
4021 aParam.bBigger ? UNDO_TABLE_DELBOX
4022 : UNDO_TABLE_INSCOL );
4024 else if( ppUndo )
4025 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, TRUE );
4027 if( bInsDel
4028 ? ( TBLFIX_CHGABS == eTblChgMode ? (bBigger && bLeft) : bLeft )
4029 : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
4031 (*fnSelBox)( pLine, aParam, nDistStt, FALSE );
4032 (*fnOtherBox)( pLine, aParam1, nDistStt, FALSE );
4034 else
4036 (*fnOtherBox)( pLine, aParam1, nDistStt, FALSE );
4037 (*fnSelBox)( pLine, aParam, nDistStt, FALSE );
4041 break;
4045 if( pFndBox )
4047 // dann raeume die Struktur aller Lines auf
4048 GCLines();
4050 //Layout updaten
4051 if( !bBigger || pFndBox->AreLinesToRestore( *this ) )
4052 pFndBox->MakeFrms( *this );
4054 // TL_CHART2: it is currently unclear if sth has to be done here.
4055 // The function name hints that nothing needs to be done, on the other
4056 // hand there is a case where sth gets deleted. :-(
4058 delete pFndBox;
4060 if( ppUndo && *ppUndo )
4062 aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<USHORT>(eTblChgMode), eType,
4063 nAbsDiff, nRelDiff );
4064 if( !aParam.bBigger )
4065 aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
4069 if( bRet )
4071 CHECKBOXWIDTH
4072 CHECKTABLELAYOUT
4075 return bRet;
4077 /* \f */
4079 _FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo,
4080 SwTableSortBoxes& rTmpLst )
4082 // suche alle Boxen / Lines
4083 SwTable& rTbl = rParam.pTblNd->GetTable();
4085 ASSERT( rParam.aBoxes.Count(), "ohne Boxen ist nichts zu machen!" );
4087 // loeschen der gesamten Tabelle verhindern
4088 if( !rParam.bBigger && rParam.aBoxes.Count() ==
4089 rTbl.GetTabSortBoxes().Count() )
4090 return 0;
4092 _FndBox* pFndBox = new _FndBox( 0, 0 );
4093 if( !rParam.bBigger )
4094 pFndBox->SetTableLines( rParam.aBoxes, rTbl );
4095 else
4097 _FndPara aPara( rParam.aBoxes, pFndBox );
4098 rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
4099 ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" );
4100 pFndBox->SetTableLines( rTbl );
4102 if( ppUndo )
4103 rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
4106 //Lines fuer das Layout-Update heraussuchen.
4107 pFndBox->DelFrms( rTbl );
4109 // TL_CHART2: it is currently unclear if sth has to be done here.
4111 return pFndBox;
4114 void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
4115 BOOL bMinSize )
4117 SwLayoutFrm* pLineFrm = GetRowFrm( rLine );
4118 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
4120 SwFrmFmt* pFmt = rLine.ClaimFrmFmt();
4122 SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height();
4123 if( !nOldHeight ) // die BaseLine und absolut
4124 nMyNewH = nMyOldH + nNewHeight;
4125 else
4127 // moeglichst genau rechnen
4128 Fraction aTmp( nMyOldH );
4129 aTmp *= Fraction( nNewHeight, nOldHeight );
4130 aTmp += Fraction( 1, 2 ); // ggfs. aufrunden
4131 nMyNewH = aTmp;
4134 SwFrmSize eSize = ATT_MIN_SIZE;
4135 if( !bMinSize &&
4136 ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY ))
4137 eSize = ATT_FIX_SIZE;
4139 pFmt->SetFmtAttr( SwFmtFrmSize( eSize, 0, nMyNewH ) );
4141 // erst alle inneren anpassen
4142 SwTableBoxes& rBoxes = rLine.GetTabBoxes();
4143 for( USHORT n = 0; n < rBoxes.Count(); ++n )
4145 SwTableBox& rBox = *rBoxes[ n ];
4146 for( USHORT i = 0; i < rBox.GetTabLines().Count(); ++i )
4147 SetLineHeight( *rBox.GetTabLines()[ i ], nMyOldH, nMyNewH, bMinSize );
4151 BOOL lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
4152 SwTwips nDist, BOOL bCheck )
4154 BOOL bRet = TRUE;
4155 if( !bCheck )
4157 // Zeilenhoehe einstellen
4158 SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
4159 rParam.bBigger );
4161 else if( !rParam.bBigger )
4163 // anhand der alten Size die neue relative errechnen
4164 SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
4165 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
4166 SwTwips nRstHeight = CalcRowRstHeight( pLineFrm );
4167 if( (nRstHeight + ROWFUZZY) < nDist )
4168 bRet = FALSE;
4170 return bRet;
4173 BOOL lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
4174 SwTwips nDist, BOOL bCheck )
4176 BOOL bRet = TRUE;
4177 if( bCheck )
4179 if( rParam.bBigger )
4181 // anhand der alten Size die neue relative errechnen
4182 SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
4183 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
4185 if( TBLFIX_CHGPROP == rParam.nMode )
4187 nDist *= pLineFrm->Frm().Height();
4188 nDist /= rParam.nMaxHeight;
4190 bRet = nDist <= CalcRowRstHeight( pLineFrm );
4193 else
4195 // Zeilenhoehe einstellen
4196 // pLine ist die nachfolgende / vorhergehende -> also anpassen
4197 if( TBLFIX_CHGPROP == rParam.nMode )
4199 SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
4200 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
4202 // aus der alten Size die neue relative errechnen
4203 // Wird die selektierte Box groesser ueber den MaxSpace anpassen,
4204 // sonst ueber die MaxHeight
4205 if( 1 /*!rParam.bBigger*/ )
4207 nDist *= pLineFrm->Frm().Height();
4208 nDist /= rParam.nMaxHeight;
4210 else
4212 // aus der alten Size die neue relative errechnen
4213 nDist *= CalcRowRstHeight( pLineFrm );
4214 nDist /= rParam.nMaxSpace;
4217 SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
4218 !rParam.bBigger );
4220 return bRet;
4223 BOOL lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
4224 SwTwips nDist, BOOL bCheck )
4226 BOOL bRet = TRUE;
4227 if( !bCheck )
4229 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
4230 SwDoc* pDoc = pLine->GetFrmFmt()->GetDoc();
4231 if( !rParam.bBigger )
4233 USHORT n;
4235 for( n = rBoxes.Count(); n; )
4236 ::lcl_SaveUpperLowerBorder( rParam.pTblNd->GetTable(),
4237 *rBoxes[ --n ],
4238 rParam.aShareFmts );
4239 for( n = rBoxes.Count(); n; )
4240 ::_DeleteBox( rParam.pTblNd->GetTable(),
4241 rBoxes[ --n ], rParam.pUndo, FALSE,
4242 FALSE, &rParam.aShareFmts );
4244 else
4246 // Zeile einfuegen
4247 SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)pLine->GetFrmFmt(),
4248 rBoxes.Count(), pLine->GetUpper() );
4249 SwTableLines* pLines;
4250 if( pLine->GetUpper() )
4251 pLines = &pLine->GetUpper()->GetTabLines();
4252 else
4253 pLines = &rParam.pTblNd->GetTable().GetTabLines();
4254 USHORT nPos = pLines->C40_GETPOS( SwTableLine, pLine );
4255 if( !rParam.bTop )
4256 ++nPos;
4257 pLines->C40_INSERT( SwTableLine, pNewLine, nPos );
4259 SwFrmFmt* pNewFmt = pNewLine->ClaimFrmFmt();
4260 pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE, 0, nDist ) );
4262 // und noch mal die Anzahl Boxen erzeugen
4263 SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes();
4264 for( USHORT n = 0; n < rBoxes.Count(); ++n )
4266 SwTwips nWidth = 0;
4267 SwTableBox* pOld = rBoxes[ n ];
4268 if( !pOld->GetSttNd() )
4270 // keine normale "Content"-Box also auf die 1. naechste
4271 // Box zurueckfallen
4272 nWidth = pOld->GetFrmFmt()->GetFrmSize().GetWidth();
4273 while( !pOld->GetSttNd() )
4274 pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
4276 ::_InsTblBox( pDoc, rParam.pTblNd, pNewLine,
4277 (SwTableBoxFmt*)pOld->GetFrmFmt(), pOld, n );
4279 // Sonderbehandlung fuer Umrandung die Obere muss
4280 // entfernt werden
4281 const SvxBoxItem& rBoxItem = pOld->GetFrmFmt()->GetBox();
4282 if( rBoxItem.GetTop() )
4284 SvxBoxItem aTmp( rBoxItem );
4285 aTmp.SetLine( 0, BOX_LINE_TOP );
4286 rParam.aShareFmts.SetAttr( rParam.bTop
4287 ? *pOld
4288 : *rNewBoxes[ n ], aTmp );
4291 if( nWidth )
4292 rParam.aShareFmts.SetAttr( *rNewBoxes[ n ],
4293 SwFmtFrmSize( ATT_FIX_SIZE, nWidth, 0 ) );
4297 else
4299 // Boxen einsammeln!
4300 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
4301 for( USHORT n = rBoxes.Count(); n; )
4303 SwTableBox* pBox = rBoxes[ --n ];
4304 if( pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
4305 return FALSE;
4307 if( pBox->GetSttNd() )
4308 rParam.aBoxes.Insert( pBox );
4309 else
4311 for( USHORT i = pBox->GetTabLines().Count(); i; )
4312 lcl_InsDelSelLine( pBox->GetTabLines()[ --i ],
4313 rParam, 0, TRUE );
4317 return bRet;
4320 BOOL SwTable::SetRowHeight( SwTableBox& rAktBox, USHORT eType,
4321 SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo )
4323 SwTableLine* pLine = rAktBox.GetUpper();
4325 SwTableLine* pBaseLine = pLine;
4326 while( pBaseLine->GetUpper() )
4327 pBaseLine = pBaseLine->GetUpper()->GetUpper();
4329 _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen
4330 SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo
4331 BOOL bBigger,
4332 bRet = FALSE,
4333 bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) ||
4334 nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ),
4335 bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
4336 USHORT n, nBaseLinePos = GetTabLines().C40_GETPOS( SwTableLine, pBaseLine );
4337 ULONG nBoxIdx = rAktBox.GetSttIdx();
4339 CR_SetLineHeight aParam( eType,
4340 (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
4341 bBigger = aParam.bBigger;
4343 FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight;
4344 if( bInsDel )
4345 fnSelLine = lcl_InsDelSelLine;
4346 else
4347 fnSelLine = lcl_SetSelLineHeight;
4349 SwTableLines* pLines = &aLines;
4351 // wie kommt man an die Hoehen heran?
4352 switch( eType & 0xff )
4354 case nsTblChgWidthHeightType::WH_CELL_TOP:
4355 case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
4356 if( pLine == pBaseLine )
4357 break; // dann geht es nicht!
4359 // ist eine verschachtelte Line (Box!)
4360 pLines = &pLine->GetUpper()->GetTabLines();
4361 nBaseLinePos = pLines->C40_GETPOS( SwTableLine, pLine );
4362 pBaseLine = pLine;
4363 // kein break!
4365 case nsTblChgWidthHeightType::WH_ROW_TOP:
4366 case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
4368 if( bInsDel && !bBigger ) // um wieviel wird es Hoeher?
4370 nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height();
4373 if( TBLVAR_CHGABS == eTblChgMode )
4375 // erstmal testen, ob ueberhaupt Platz ist
4376 if( bBigger )
4378 bRet = TRUE;
4379 // was ist mit Top, was ist mit Tabelle im Rahmen oder in Kopf-/Fusszeile
4380 // mit fester Hoehe ??
4381 if( !bRet )
4383 // dann sich selbst rekursiv aufrufen; nur mit
4384 // einem anderen Mode -> proprotional
4385 TblChgMode eOld = eTblChgMode;
4386 eTblChgMode = TBLFIX_CHGPROP;
4388 bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
4389 nRelDiff, ppUndo );
4391 eTblChgMode = eOld;
4392 return bRet;
4395 else
4396 bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4397 nAbsDiff, TRUE );
4399 if( bRet )
4401 if( bInsDel )
4403 if( !aParam.aBoxes.Count() )
4404 ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
4405 aParam, 0, TRUE );
4407 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
4409 // #110525# delete complete table when last row is
4410 // deleted
4411 if( !bBigger &&
4412 aParam.aBoxes.Count() == aSortCntBoxes.Count() )
4414 GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
4415 return FALSE;
4419 if( ppUndo )
4420 *ppUndo = aParam.CreateUndo(
4421 bBigger ? UNDO_TABLE_INSROW
4422 : UNDO_ROW_DELETE );
4424 else if( ppUndo )
4425 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, TRUE );
4427 (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4428 nAbsDiff, FALSE );
4431 else
4433 bRet = TRUE;
4434 USHORT nStt, nEnd;
4435 if( bTop )
4436 nStt = 0, nEnd = nBaseLinePos;
4437 else
4438 nStt = nBaseLinePos + 1, nEnd = pLines->Count();
4440 // die akt. Hoehe der Lines besorgen
4441 if( TBLFIX_CHGPROP == eTblChgMode )
4443 for( n = nStt; n < nEnd; ++n )
4445 SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] );
4446 ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
4447 aParam.nMaxSpace += CalcRowRstHeight( pLineFrm );
4448 aParam.nMaxHeight += pLineFrm->Frm().Height();
4450 if( bBigger && aParam.nMaxSpace < nAbsDiff )
4451 bRet = FALSE;
4453 else
4455 if( bTop ? nEnd : nStt < nEnd )
4457 if( bTop )
4458 nStt = nEnd - 1;
4459 else
4460 nEnd = nStt + 1;
4462 else
4463 bRet = FALSE;
4466 if( bRet )
4468 if( bBigger )
4470 for( n = nStt; n < nEnd; ++n )
4472 if( !(*fnOtherLine)( (*pLines)[ n ], aParam,
4473 nAbsDiff, TRUE ))
4475 bRet = FALSE;
4476 break;
4480 else
4481 bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4482 nAbsDiff, TRUE );
4485 if( bRet )
4487 // dann mal anpassen
4488 if( bInsDel )
4490 if( !aParam.aBoxes.Count() )
4491 ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
4492 aParam, 0, TRUE );
4493 pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
4494 if( ppUndo )
4495 *ppUndo = aParam.CreateUndo(
4496 bBigger ? UNDO_TABLE_INSROW
4497 : UNDO_ROW_DELETE );
4499 else if( ppUndo )
4500 *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, TRUE );
4502 CR_SetLineHeight aParam1( aParam );
4503 if( TBLFIX_CHGPROP == eTblChgMode && !bBigger &&
4504 !aParam.nMaxSpace )
4506 // dann muss der gesamte Platz auf alle Lines
4507 // gleichmaessig verteilt werden. Dafuer wird die
4508 // Anzahl benoetigt
4509 aParam1.nLines = nEnd - nStt;
4512 if( bTop )
4514 (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4515 nAbsDiff, FALSE );
4516 for( n = nStt; n < nEnd; ++n )
4517 (*fnOtherLine)( (*pLines)[ n ], aParam1,
4518 nAbsDiff, FALSE );
4520 else
4522 for( n = nStt; n < nEnd; ++n )
4523 (*fnOtherLine)( (*pLines)[ n ], aParam1,
4524 nAbsDiff, FALSE );
4525 (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
4526 nAbsDiff, FALSE );
4529 else
4531 // dann sich selbst rekursiv aufrufen; nur mit
4532 // einem anderen Mode -> proprotional
4533 TblChgMode eOld = eTblChgMode;
4534 eTblChgMode = TBLVAR_CHGABS;
4536 bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
4537 nRelDiff, ppUndo );
4539 eTblChgMode = eOld;
4540 pFndBox = 0;
4544 break;
4547 if( pFndBox )
4549 // dann raeume die Struktur aller Lines auf
4550 GCLines();
4552 //Layout updaten
4553 if( bBigger || pFndBox->AreLinesToRestore( *this ) )
4554 pFndBox->MakeFrms( *this );
4556 // TL_CHART2: it is currently unclear if sth has to be done here.
4558 delete pFndBox;
4560 if( ppUndo && *ppUndo )
4562 aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<USHORT>(eTblChgMode), eType,
4563 nAbsDiff, nRelDiff );
4564 if( bBigger )
4565 aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
4569 CHECKTABLELAYOUT
4571 return bRet;
4574 /* \f */
4576 SwFrmFmt* SwShareBoxFmt::GetFormat( long nWidth ) const
4578 SwFrmFmt *pRet = 0, *pTmp;
4579 for( USHORT n = aNewFmts.Count(); n; )
4580 if( ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->GetFrmSize().GetWidth()
4581 == nWidth )
4583 pRet = pTmp;
4584 break;
4586 return pRet;
4589 SwFrmFmt* SwShareBoxFmt::GetFormat( const SfxPoolItem& rItem ) const
4591 const SfxPoolItem* pItem;
4592 USHORT nWhich = rItem.Which();
4593 SwFrmFmt *pRet = 0, *pTmp;
4594 const SfxPoolItem& rFrmSz = pOldFmt->GetFmtAttr( RES_FRM_SIZE, FALSE );
4595 for( USHORT n = aNewFmts.Count(); n; )
4596 if( SFX_ITEM_SET == ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->
4597 GetItemState( nWhich, FALSE, &pItem ) && *pItem == rItem &&
4598 pTmp->GetFmtAttr( RES_FRM_SIZE, FALSE ) == rFrmSz )
4600 pRet = pTmp;
4601 break;
4603 return pRet;
4606 void SwShareBoxFmt::AddFormat( const SwFrmFmt& rNew )
4608 void* pFmt = (void*)&rNew;
4609 aNewFmts.Insert( pFmt, aNewFmts.Count() );
4612 BOOL SwShareBoxFmt::RemoveFormat( const SwFrmFmt& rFmt )
4614 // returnt TRUE, wenn geloescht werden kann
4615 if( pOldFmt == &rFmt )
4616 return TRUE;
4618 void* p = (void*)&rFmt;
4619 USHORT nFnd = aNewFmts.GetPos( p );
4620 if( USHRT_MAX != nFnd )
4621 aNewFmts.Remove( nFnd );
4622 return 0 == aNewFmts.Count();
4625 SwShareBoxFmts::~SwShareBoxFmts()
4629 SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, long nWidth ) const
4631 USHORT nPos;
4632 return Seek_Entry( rFmt, &nPos )
4633 ? aShareArr[ nPos ]->GetFormat( nWidth )
4634 : 0;
4636 SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt,
4637 const SfxPoolItem& rItem ) const
4639 USHORT nPos;
4640 return Seek_Entry( rFmt, &nPos )
4641 ? aShareArr[ nPos ]->GetFormat( rItem )
4642 : 0;
4645 void SwShareBoxFmts::AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew )
4647 // wenn das Format nicht geshared ist, braucht es auch nicht in die
4648 // Liste aufgenommen werden. Denn es gibt keinen 2. der es sucht.
4649 //leider werden auch die CellFrms gefunden
4650 // if( !rOld.IsLastDepend() )
4652 USHORT nPos;
4653 SwShareBoxFmt* pEntry;
4654 if( !Seek_Entry( rOld, &nPos ))
4656 pEntry = new SwShareBoxFmt( rOld );
4657 aShareArr.C40_INSERT( SwShareBoxFmt, pEntry, nPos );
4659 else
4660 pEntry = aShareArr[ nPos ];
4662 pEntry->AddFormat( rNew );
4665 void SwShareBoxFmts::ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn,
4666 SwFrmFmt& rFmt )
4668 SwClient aCl;
4669 SwFrmFmt* pOld = 0;
4670 if( pBox )
4672 pOld = pBox->GetFrmFmt();
4673 pOld->Add( &aCl );
4674 pBox->ChgFrmFmt( (SwTableBoxFmt*)&rFmt );
4676 else if( pLn )
4678 pOld = pLn->GetFrmFmt();
4679 pOld->Add( &aCl );
4680 pLn->ChgFrmFmt( (SwTableLineFmt*)&rFmt );
4682 if( pOld && pOld->IsLastDepend() )
4684 RemoveFormat( *pOld );
4685 delete pOld;
4689 void SwShareBoxFmts::SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz )
4691 SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
4692 *pRet = GetFormat( *pBoxFmt, rSz.GetWidth() );
4693 if( pRet )
4694 ChangeFrmFmt( &rBox, 0, *pRet );
4695 else
4697 pRet = rBox.ClaimFrmFmt();
4698 pRet->SetFmtAttr( rSz );
4699 AddFormat( *pBoxFmt, *pRet );
4703 void SwShareBoxFmts::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem )
4705 SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
4706 *pRet = GetFormat( *pBoxFmt, rItem );
4707 if( pRet )
4708 ChangeFrmFmt( &rBox, 0, *pRet );
4709 else
4711 pRet = rBox.ClaimFrmFmt();
4712 pRet->SetFmtAttr( rItem );
4713 AddFormat( *pBoxFmt, *pRet );
4717 void SwShareBoxFmts::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem )
4719 SwFrmFmt *pLineFmt = rLine.GetFrmFmt(),
4720 *pRet = GetFormat( *pLineFmt, rItem );
4721 if( pRet )
4722 ChangeFrmFmt( 0, &rLine, *pRet );
4723 else
4725 pRet = rLine.ClaimFrmFmt();
4726 pRet->SetFmtAttr( rItem );
4727 AddFormat( *pLineFmt, *pRet );
4731 void SwShareBoxFmts::RemoveFormat( const SwFrmFmt& rFmt )
4733 for( USHORT i = aShareArr.Count(); i; )
4734 if( aShareArr[ --i ]->RemoveFormat( rFmt ))
4735 aShareArr.DeleteAndDestroy( i );
4738 BOOL SwShareBoxFmts::Seek_Entry( const SwFrmFmt& rFmt, USHORT* pPos ) const
4740 ULONG nIdx = (ULONG)&rFmt;
4741 USHORT nO = aShareArr.Count(), nM, nU = 0;
4742 if( nO > 0 )
4744 nO--;
4745 while( nU <= nO )
4747 nM = nU + ( nO - nU ) / 2;
4748 ULONG nFmt = (ULONG)&aShareArr[ nM ]->GetOldFormat();
4749 if( nFmt == nIdx )
4751 if( pPos )
4752 *pPos = nM;
4753 return TRUE;
4755 else if( nFmt < nIdx )
4756 nU = nM + 1;
4757 else if( nM == 0 )
4759 if( pPos )
4760 *pPos = nU;
4761 return FALSE;
4763 else
4764 nO = nM - 1;
4767 if( pPos )
4768 *pPos = nU;
4769 return FALSE;