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