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