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_sc.hxx" 30 31 // INCLUDE --------------------------------------------------------------- 32 33 #include <tools/debug.hxx> 34 35 #include "refupdat.hxx" 36 #include "document.hxx" 37 #include "compiler.hxx" 38 #include "bigrange.hxx" 39 #include "chgtrack.hxx" 40 41 //------------------------------------------------------------------------ 42 43 template< typename R, typename S, typename U > 44 sal_Bool lcl_MoveStart( R& rRef, U nStart, S nDelta, U nMask ) 45 { 46 sal_Bool bCut = sal_False; 47 if ( rRef >= nStart ) 48 rRef = sal::static_int_cast<R>( rRef + nDelta ); 49 else if ( nDelta < 0 && rRef >= nStart + nDelta ) 50 rRef = nStart + nDelta; //! begrenzen ??? 51 if ( rRef < 0 ) 52 { 53 rRef = 0; 54 bCut = sal_True; 55 } 56 else if ( rRef > nMask ) 57 { 58 rRef = nMask; 59 bCut = sal_True; 60 } 61 return bCut; 62 } 63 64 template< typename R, typename S, typename U > 65 sal_Bool lcl_MoveEnd( R& rRef, U nStart, S nDelta, U nMask ) 66 { 67 sal_Bool bCut = sal_False; 68 if ( rRef >= nStart ) 69 rRef = sal::static_int_cast<R>( rRef + nDelta ); 70 else if ( nDelta < 0 && rRef >= nStart + nDelta ) 71 rRef = nStart + nDelta - 1; //! begrenzen ??? 72 if ( rRef < 0 ) 73 { 74 rRef = 0; 75 bCut = sal_True; 76 } 77 else if ( rRef > nMask ) 78 { 79 rRef = nMask; 80 bCut = sal_True; 81 } 82 return bCut; 83 } 84 85 template< typename R, typename S, typename U > 86 sal_Bool lcl_MoveReorder( R& rRef, U nStart, U nEnd, S nDelta ) 87 { 88 if ( rRef >= nStart && rRef <= nEnd ) 89 { 90 rRef = sal::static_int_cast<R>( rRef + nDelta ); 91 return sal_True; 92 } 93 94 if ( nDelta > 0 ) // nach hinten schieben 95 { 96 if ( rRef >= nStart && rRef <= nEnd + nDelta ) 97 { 98 if ( rRef <= nEnd ) 99 rRef = sal::static_int_cast<R>( rRef + nDelta ); // in the moved range 100 else 101 rRef -= nEnd - nStart + 1; // nachruecken 102 return sal_True; 103 } 104 } 105 else // nach vorne schieben 106 { 107 if ( rRef >= nStart + nDelta && rRef <= nEnd ) 108 { 109 if ( rRef >= nStart ) 110 rRef = sal::static_int_cast<R>( rRef + nDelta ); // in the moved range 111 else 112 rRef += nEnd - nStart + 1; // nachruecken 113 return sal_True; 114 } 115 } 116 117 return sal_False; 118 } 119 120 template< typename R, typename S, typename U > 121 sal_Bool lcl_MoveItCut( R& rRef, S nDelta, U nMask ) 122 { 123 sal_Bool bCut = sal_False; 124 rRef = sal::static_int_cast<R>( rRef + nDelta ); 125 if ( rRef < 0 ) 126 { 127 rRef = 0; 128 bCut = sal_True; 129 } 130 else if ( rRef > nMask ) 131 { 132 rRef = nMask; 133 bCut = sal_True; 134 } 135 return bCut; 136 } 137 138 template< typename R, typename S, typename U > 139 void lcl_MoveItWrap( R& rRef, S nDelta, U nMask ) 140 { 141 rRef = sal::static_int_cast<R>( rRef + nDelta ); 142 if ( rRef < 0 ) 143 rRef += nMask+1; 144 else if ( rRef > nMask ) 145 rRef -= nMask+1; 146 } 147 148 template< typename R, typename S, typename U > 149 sal_Bool lcl_MoveRefPart( R& rRef1Val, sal_Bool& rRef1Del, sal_Bool bDo1, 150 R& rRef2Val, sal_Bool& rRef2Del, sal_Bool bDo2, 151 U nStart, U nEnd, S nDelta, U nMask ) 152 { 153 if ( nDelta ) 154 { 155 sal_Bool bDel, bCut1, bCut2; 156 bDel = bCut1 = bCut2 = sal_False; 157 S n; 158 if (bDo1 && bDo2) 159 { 160 if ( nDelta < 0 ) 161 { 162 n = nStart + nDelta; 163 if ( n <= rRef1Val && rRef1Val < nStart 164 && n <= rRef2Val && rRef2Val < nStart ) 165 bDel = sal_True; 166 } 167 else 168 { 169 n = nEnd + nDelta; 170 if ( nEnd < rRef1Val && rRef1Val <= n 171 && nEnd < rRef2Val && rRef2Val <= n ) 172 bDel = sal_True; 173 } 174 } 175 if ( bDel ) 176 { // move deleted along 177 rRef1Val = sal::static_int_cast<R>( rRef1Val + nDelta ); 178 rRef2Val = sal::static_int_cast<R>( rRef2Val + nDelta ); 179 } 180 else 181 { 182 if (bDo1) 183 { 184 if ( rRef1Del ) 185 rRef1Val = sal::static_int_cast<R>( rRef1Val + nDelta ); 186 else 187 bCut1 = lcl_MoveStart( rRef1Val, nStart, nDelta, nMask ); 188 } 189 if (bDo2) 190 { 191 if ( rRef2Del ) 192 rRef2Val = sal::static_int_cast<R>( rRef2Val + nDelta ); 193 else 194 bCut2 = lcl_MoveEnd( rRef2Val, nStart, nDelta, nMask ); 195 } 196 } 197 if ( bDel || (bCut1 && bCut2) ) 198 rRef1Del = rRef2Del = sal_True; 199 return bDel || bCut1 || bCut2 || rRef1Del || rRef2Del; 200 } 201 else 202 return sal_False; 203 } 204 205 template< typename R, typename S, typename U > 206 sal_Bool IsExpand( R n1, R n2, U nStart, S nD ) 207 { //! vor normalem Move... 208 return 209 nD > 0 // Insert 210 && n1 < n2 // mindestens zwei Cols/Rows/Tabs in Ref 211 && ( 212 (nStart <= n1 && n1 < nStart + nD) // n1 innerhalb des Insert 213 || (n2 + 1 == nStart) // n2 direkt vor Insert 214 ); // n1 < nStart <= n2 wird sowieso expanded! 215 } 216 217 218 template< typename R, typename S, typename U > 219 void Expand( R& n1, R& n2, U nStart, S nD ) 220 { //! nach normalem Move..., nur wenn IsExpand vorher sal_True war! 221 //! erst das Ende 222 if ( n2 + 1 == nStart ) 223 { // am Ende 224 n2 = sal::static_int_cast<R>( n2 + nD ); 225 return; 226 } 227 // am Anfang 228 n1 = sal::static_int_cast<R>( n1 - nD ); 229 } 230 231 232 sal_Bool lcl_IsWrapBig( sal_Int32 nRef, sal_Int32 nDelta ) 233 { 234 if ( nRef > 0 && nDelta > 0 ) 235 return nRef + nDelta <= 0; 236 else if ( nRef < 0 && nDelta < 0 ) 237 return nRef + nDelta >= 0; 238 return sal_False; 239 } 240 241 242 sal_Bool lcl_MoveBig( sal_Int32& rRef, sal_Int32 nStart, sal_Int32 nDelta ) 243 { 244 sal_Bool bCut = sal_False; 245 if ( rRef >= nStart ) 246 { 247 if ( nDelta > 0 ) 248 bCut = lcl_IsWrapBig( rRef, nDelta ); 249 if ( bCut ) 250 rRef = nInt32Max; 251 else 252 rRef += nDelta; 253 } 254 return bCut; 255 } 256 257 sal_Bool lcl_MoveItCutBig( sal_Int32& rRef, sal_Int32 nDelta ) 258 { 259 sal_Bool bCut = lcl_IsWrapBig( rRef, nDelta ); 260 rRef += nDelta; 261 return bCut; 262 } 263 264 265 ScRefUpdateRes ScRefUpdate::Update( ScDocument* pDoc, UpdateRefMode eUpdateRefMode, 266 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 267 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 268 SCsCOL nDx, SCsROW nDy, SCsTAB nDz, 269 SCCOL& theCol1, SCROW& theRow1, SCTAB& theTab1, 270 SCCOL& theCol2, SCROW& theRow2, SCTAB& theTab2 ) 271 { 272 ScRefUpdateRes eRet = UR_NOTHING; 273 274 SCCOL oldCol1 = theCol1; 275 SCROW oldRow1 = theRow1; 276 SCTAB oldTab1 = theTab1; 277 SCCOL oldCol2 = theCol2; 278 SCROW oldRow2 = theRow2; 279 SCTAB oldTab2 = theTab2; 280 281 sal_Bool bCut1, bCut2; 282 283 if (eUpdateRefMode == URM_INSDEL) 284 { 285 sal_Bool bExpand = pDoc->IsExpandRefs(); 286 if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) && 287 (theTab1 >= nTab1) && (theTab2 <= nTab2) ) 288 { 289 sal_Bool bExp = (bExpand && IsExpand( theCol1, theCol2, nCol1, nDx )); 290 bCut1 = lcl_MoveStart( theCol1, nCol1, nDx, MAXCOL ); 291 bCut2 = lcl_MoveEnd( theCol2, nCol1, nDx, MAXCOL ); 292 if ( theCol2 < theCol1 ) 293 { 294 eRet = UR_INVALID; 295 theCol2 = theCol1; 296 } 297 else if ( bCut1 || bCut2 ) 298 eRet = UR_UPDATED; 299 if ( bExp ) 300 { 301 Expand( theCol1, theCol2, nCol1, nDx ); 302 eRet = UR_UPDATED; 303 } 304 } 305 if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) && 306 (theTab1 >= nTab1) && (theTab2 <= nTab2) ) 307 { 308 sal_Bool bExp = (bExpand && IsExpand( theRow1, theRow2, nRow1, nDy )); 309 bCut1 = lcl_MoveStart( theRow1, nRow1, nDy, MAXROW ); 310 bCut2 = lcl_MoveEnd( theRow2, nRow1, nDy, MAXROW ); 311 if ( theRow2 < theRow1 ) 312 { 313 eRet = UR_INVALID; 314 theRow2 = theRow1; 315 } 316 else if ( bCut1 || bCut2 ) 317 eRet = UR_UPDATED; 318 if ( bExp ) 319 { 320 Expand( theRow1, theRow2, nRow1, nDy ); 321 eRet = UR_UPDATED; 322 } 323 } 324 if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) && 325 (theRow1 >= nRow1) && (theRow2 <= nRow2) ) 326 { 327 SCsTAB nMaxTab = pDoc->GetTableCount() - 1; 328 nMaxTab = sal::static_int_cast<SCsTAB>(nMaxTab + nDz); // adjust to new count 329 sal_Bool bExp = (bExpand && IsExpand( theTab1, theTab2, nTab1, nDz )); 330 bCut1 = lcl_MoveStart( theTab1, nTab1, nDz, static_cast<SCTAB>(nMaxTab) ); 331 bCut2 = lcl_MoveEnd( theTab2, nTab1, nDz, static_cast<SCTAB>(nMaxTab) ); 332 if ( theTab2 < theTab1 ) 333 { 334 eRet = UR_INVALID; 335 theTab2 = theTab1; 336 } 337 else if ( bCut1 || bCut2 ) 338 eRet = UR_UPDATED; 339 if ( bExp ) 340 { 341 Expand( theTab1, theTab2, nTab1, nDz ); 342 eRet = UR_UPDATED; 343 } 344 } 345 } 346 else if (eUpdateRefMode == URM_MOVE) 347 { 348 if ((theCol1 >= nCol1-nDx) && (theRow1 >= nRow1-nDy) && (theTab1 >= nTab1-nDz) && 349 (theCol2 <= nCol2-nDx) && (theRow2 <= nRow2-nDy) && (theTab2 <= nTab2-nDz)) 350 { 351 if ( nDx ) 352 { 353 bCut1 = lcl_MoveItCut( theCol1, nDx, MAXCOL ); 354 bCut2 = lcl_MoveItCut( theCol2, nDx, MAXCOL ); 355 if ( bCut1 || bCut2 ) 356 eRet = UR_UPDATED; 357 } 358 if ( nDy ) 359 { 360 bCut1 = lcl_MoveItCut( theRow1, nDy, MAXROW ); 361 bCut2 = lcl_MoveItCut( theRow2, nDy, MAXROW ); 362 if ( bCut1 || bCut2 ) 363 eRet = UR_UPDATED; 364 } 365 if ( nDz ) 366 { 367 SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; 368 bCut1 = lcl_MoveItCut( theTab1, nDz, static_cast<SCTAB>(nMaxTab) ); 369 bCut2 = lcl_MoveItCut( theTab2, nDz, static_cast<SCTAB>(nMaxTab) ); 370 if ( bCut1 || bCut2 ) 371 eRet = UR_UPDATED; 372 } 373 } 374 } 375 else if (eUpdateRefMode == URM_REORDER) 376 { 377 // bisher nur fuer nDz (MoveTab) 378 DBG_ASSERT ( !nDx && !nDy, "URM_REORDER fuer x und y noch nicht implementiert" ); 379 380 if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) && 381 (theRow1 >= nRow1) && (theRow2 <= nRow2) ) 382 { 383 bCut1 = lcl_MoveReorder( theTab1, nTab1, nTab2, nDz ); 384 bCut2 = lcl_MoveReorder( theTab2, nTab1, nTab2, nDz ); 385 if ( bCut1 || bCut2 ) 386 eRet = UR_UPDATED; 387 } 388 } 389 390 if ( eRet == UR_NOTHING ) 391 { 392 if (oldCol1 != theCol1 393 || oldRow1 != theRow1 394 || oldTab1 != theTab1 395 || oldCol2 != theCol2 396 || oldRow2 != theRow2 397 || oldTab2 != theTab2 398 ) 399 eRet = UR_UPDATED; 400 } 401 return eRet; 402 } 403 404 405 // simples UpdateReference fuer ScBigRange (ScChangeAction/ScChangeTrack) 406 // Referenzen koennen auch ausserhalb des Dokuments liegen! 407 // Ganze Spalten/Zeilen (nInt32Min..nInt32Max) bleiben immer solche! 408 ScRefUpdateRes ScRefUpdate::Update( UpdateRefMode eUpdateRefMode, 409 const ScBigRange& rWhere, sal_Int32 nDx, sal_Int32 nDy, sal_Int32 nDz, 410 ScBigRange& rWhat ) 411 { 412 ScRefUpdateRes eRet = UR_NOTHING; 413 const ScBigRange aOldRange( rWhat ); 414 415 sal_Int32 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2; 416 sal_Int32 theCol1, theRow1, theTab1, theCol2, theRow2, theTab2; 417 rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 418 rWhat.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ); 419 420 sal_Bool bCut1, bCut2; 421 422 if (eUpdateRefMode == URM_INSDEL) 423 { 424 if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) && 425 (theTab1 >= nTab1) && (theTab2 <= nTab2) && 426 !(theCol1 == nInt32Min && theCol2 == nInt32Max) ) 427 { 428 bCut1 = lcl_MoveBig( theCol1, nCol1, nDx ); 429 bCut2 = lcl_MoveBig( theCol2, nCol1, nDx ); 430 if ( bCut1 || bCut2 ) 431 eRet = UR_UPDATED; 432 rWhat.aStart.SetCol( theCol1 ); 433 rWhat.aEnd.SetCol( theCol2 ); 434 } 435 if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) && 436 (theTab1 >= nTab1) && (theTab2 <= nTab2) && 437 !(theRow1 == nInt32Min && theRow2 == nInt32Max) ) 438 { 439 bCut1 = lcl_MoveBig( theRow1, nRow1, nDy ); 440 bCut2 = lcl_MoveBig( theRow2, nRow1, nDy ); 441 if ( bCut1 || bCut2 ) 442 eRet = UR_UPDATED; 443 rWhat.aStart.SetRow( theRow1 ); 444 rWhat.aEnd.SetRow( theRow2 ); 445 } 446 if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) && 447 (theRow1 >= nRow1) && (theRow2 <= nRow2) && 448 !(theTab1 == nInt32Min && theTab2 == nInt32Max) ) 449 { 450 bCut1 = lcl_MoveBig( theTab1, nTab1, nDz ); 451 bCut2 = lcl_MoveBig( theTab2, nTab1, nDz ); 452 if ( bCut1 || bCut2 ) 453 eRet = UR_UPDATED; 454 rWhat.aStart.SetTab( theTab1 ); 455 rWhat.aEnd.SetTab( theTab2 ); 456 } 457 } 458 else if (eUpdateRefMode == URM_MOVE) 459 { 460 if ( rWhere.In( rWhat ) ) 461 { 462 if ( nDx && !(theCol1 == nInt32Min && theCol2 == nInt32Max) ) 463 { 464 bCut1 = lcl_MoveItCutBig( theCol1, nDx ); 465 bCut2 = lcl_MoveItCutBig( theCol2, nDx ); 466 if ( bCut1 || bCut2 ) 467 eRet = UR_UPDATED; 468 rWhat.aStart.SetCol( theCol1 ); 469 rWhat.aEnd.SetCol( theCol2 ); 470 } 471 if ( nDy && !(theRow1 == nInt32Min && theRow2 == nInt32Max) ) 472 { 473 bCut1 = lcl_MoveItCutBig( theRow1, nDy ); 474 bCut2 = lcl_MoveItCutBig( theRow2, nDy ); 475 if ( bCut1 || bCut2 ) 476 eRet = UR_UPDATED; 477 rWhat.aStart.SetRow( theRow1 ); 478 rWhat.aEnd.SetRow( theRow2 ); 479 } 480 if ( nDz && !(theTab1 == nInt32Min && theTab2 == nInt32Max) ) 481 { 482 bCut1 = lcl_MoveItCutBig( theTab1, nDz ); 483 bCut2 = lcl_MoveItCutBig( theTab2, nDz ); 484 if ( bCut1 || bCut2 ) 485 eRet = UR_UPDATED; 486 rWhat.aStart.SetTab( theTab1 ); 487 rWhat.aEnd.SetTab( theTab2 ); 488 } 489 } 490 } 491 492 if ( eRet == UR_NOTHING && rWhat != aOldRange ) 493 eRet = UR_UPDATED; 494 495 return eRet; 496 } 497 498 499 ScRefUpdateRes ScRefUpdate::Update( ScDocument* pDoc, UpdateRefMode eMode, 500 const ScAddress& rPos, const ScRange& r, 501 SCsCOL nDx, SCsROW nDy, SCsTAB nDz, 502 ScComplexRefData& rRef, WhatType eWhat ) 503 { 504 ScRefUpdateRes eRet = UR_NOTHING; 505 506 SCCOL nCol1 = r.aStart.Col(); 507 SCROW nRow1 = r.aStart.Row(); 508 SCTAB nTab1 = r.aStart.Tab(); 509 SCCOL nCol2 = r.aEnd.Col(); 510 SCROW nRow2 = r.aEnd.Row(); 511 SCTAB nTab2 = r.aEnd.Tab(); 512 513 if( eMode == URM_INSDEL ) 514 { 515 sal_Bool bExpand = pDoc->IsExpandRefs(); 516 517 const ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); 518 sal_Bool bInDeleteUndo = 519 ( pChangeTrack ? pChangeTrack->IsInDeleteUndo() : sal_False ); 520 521 SCCOL oldCol1 = rRef.Ref1.nCol; 522 SCROW oldRow1 = rRef.Ref1.nRow; 523 SCTAB oldTab1 = rRef.Ref1.nTab; 524 SCCOL oldCol2 = rRef.Ref2.nCol; 525 SCROW oldRow2 = rRef.Ref2.nRow; 526 SCTAB oldTab2 = rRef.Ref2.nTab; 527 528 sal_Bool bRef1ColDel = rRef.Ref1.IsColDeleted(); 529 sal_Bool bRef2ColDel = rRef.Ref2.IsColDeleted(); 530 sal_Bool bRef1RowDel = rRef.Ref1.IsRowDeleted(); 531 sal_Bool bRef2RowDel = rRef.Ref2.IsRowDeleted(); 532 sal_Bool bRef1TabDel = rRef.Ref1.IsTabDeleted(); 533 sal_Bool bRef2TabDel = rRef.Ref2.IsTabDeleted(); 534 535 if( nDx && 536 ((rRef.Ref1.nRow >= nRow1 537 && rRef.Ref2.nRow <= nRow2) || (bRef1RowDel || bRef2RowDel)) 538 && 539 ((rRef.Ref1.nTab >= nTab1 540 && rRef.Ref2.nTab <= nTab2) || (bRef1TabDel || bRef2TabDel)) 541 ) 542 { 543 sal_Bool bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nCol, 544 rRef.Ref2.nCol, nCol1, nDx )); 545 sal_Bool bDo1 = (eWhat == ScRefUpdate::ALL || (eWhat == 546 ScRefUpdate::ABSOLUTE && !rRef.Ref1.IsColRel())); 547 sal_Bool bDo2 = (eWhat == ScRefUpdate::ALL || (eWhat == 548 ScRefUpdate::ABSOLUTE && !rRef.Ref2.IsColRel())); 549 if ( lcl_MoveRefPart( rRef.Ref1.nCol, bRef1ColDel, bDo1, 550 rRef.Ref2.nCol, bRef2ColDel, bDo2, 551 nCol1, nCol2, nDx, MAXCOL ) ) 552 { 553 eRet = UR_UPDATED; 554 if ( bInDeleteUndo && (bRef1ColDel || bRef2ColDel) ) 555 { 556 if ( bRef1ColDel && nCol1 <= rRef.Ref1.nCol && 557 rRef.Ref1.nCol <= nCol1 + nDx ) 558 rRef.Ref1.SetColDeleted( sal_False ); 559 if ( bRef2ColDel && nCol1 <= rRef.Ref2.nCol && 560 rRef.Ref2.nCol <= nCol1 + nDx ) 561 rRef.Ref2.SetColDeleted( sal_False ); 562 } 563 else 564 { 565 if ( bRef1ColDel ) 566 rRef.Ref1.SetColDeleted( sal_True ); 567 if ( bRef2ColDel ) 568 rRef.Ref2.SetColDeleted( sal_True ); 569 } 570 } 571 if ( bExp ) 572 { 573 Expand( rRef.Ref1.nCol, rRef.Ref2.nCol, nCol1, nDx ); 574 eRet = UR_UPDATED; 575 } 576 } 577 if( nDy && 578 ((rRef.Ref1.nCol >= nCol1 579 && rRef.Ref2.nCol <= nCol2) || (bRef1ColDel || bRef2ColDel)) 580 && 581 ((rRef.Ref1.nTab >= nTab1 582 && rRef.Ref2.nTab <= nTab2) || (bRef1TabDel || bRef2TabDel)) 583 ) 584 { 585 sal_Bool bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nRow, 586 rRef.Ref2.nRow, nRow1, nDy )); 587 sal_Bool bDo1 = (eWhat == ScRefUpdate::ALL || (eWhat == 588 ScRefUpdate::ABSOLUTE && !rRef.Ref1.IsRowRel())); 589 sal_Bool bDo2 = (eWhat == ScRefUpdate::ALL || (eWhat == 590 ScRefUpdate::ABSOLUTE && !rRef.Ref2.IsRowRel())); 591 if ( lcl_MoveRefPart( rRef.Ref1.nRow, bRef1RowDel, bDo1, 592 rRef.Ref2.nRow, bRef2RowDel, bDo2, 593 nRow1, nRow2, nDy, MAXROW ) ) 594 { 595 eRet = UR_UPDATED; 596 if ( bInDeleteUndo && (bRef1RowDel || bRef2RowDel) ) 597 { 598 if ( bRef1RowDel && nRow1 <= rRef.Ref1.nRow && 599 rRef.Ref1.nRow <= nRow1 + nDy ) 600 rRef.Ref1.SetRowDeleted( sal_False ); 601 if ( bRef2RowDel && nRow1 <= rRef.Ref2.nRow && 602 rRef.Ref2.nRow <= nRow1 + nDy ) 603 rRef.Ref2.SetRowDeleted( sal_False ); 604 } 605 else 606 { 607 if ( bRef1RowDel ) 608 rRef.Ref1.SetRowDeleted( sal_True ); 609 if ( bRef2RowDel ) 610 rRef.Ref2.SetRowDeleted( sal_True ); 611 } 612 } 613 if ( bExp ) 614 { 615 Expand( rRef.Ref1.nRow, rRef.Ref2.nRow, nRow1, nDy ); 616 eRet = UR_UPDATED; 617 } 618 } 619 if( nDz && 620 ((rRef.Ref1.nCol >= nCol1 621 && rRef.Ref2.nCol <= nCol2) || (bRef1ColDel || bRef2ColDel)) 622 && 623 ((rRef.Ref1.nRow >= nRow1 624 && rRef.Ref2.nRow <= nRow2) || (bRef1RowDel || bRef2RowDel)) 625 ) 626 { 627 sal_Bool bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nTab, 628 rRef.Ref2.nTab, nTab1, nDz )); 629 SCTAB nMaxTab = pDoc->GetTableCount() - 1; 630 sal_Bool bDo1 = (eWhat == ScRefUpdate::ALL || (eWhat == 631 ScRefUpdate::ABSOLUTE && !rRef.Ref1.IsTabRel())); 632 sal_Bool bDo2 = (eWhat == ScRefUpdate::ALL || (eWhat == 633 ScRefUpdate::ABSOLUTE && !rRef.Ref2.IsTabRel())); 634 if ( lcl_MoveRefPart( rRef.Ref1.nTab, bRef1TabDel, bDo1, 635 rRef.Ref2.nTab, bRef2TabDel, bDo2, 636 nTab1, nTab2, nDz, nMaxTab ) ) 637 { 638 eRet = UR_UPDATED; 639 if ( bInDeleteUndo && (bRef1TabDel || bRef2TabDel) ) 640 { 641 if ( bRef1TabDel && nTab1 <= rRef.Ref1.nTab && 642 rRef.Ref1.nTab <= nTab1 + nDz ) 643 rRef.Ref1.SetTabDeleted( sal_False ); 644 if ( bRef2TabDel && nTab1 <= rRef.Ref2.nTab && 645 rRef.Ref2.nTab <= nTab1 + nDz ) 646 rRef.Ref2.SetTabDeleted( sal_False ); 647 } 648 else 649 { 650 if ( bRef1TabDel ) 651 rRef.Ref1.SetTabDeleted( sal_True ); 652 if ( bRef2TabDel ) 653 rRef.Ref2.SetTabDeleted( sal_True ); 654 } 655 } 656 if ( bExp ) 657 { 658 Expand( rRef.Ref1.nTab, rRef.Ref2.nTab, nTab1, nDz ); 659 eRet = UR_UPDATED; 660 } 661 } 662 if ( eRet == UR_NOTHING ) 663 { 664 if (oldCol1 != rRef.Ref1.nCol 665 || oldRow1 != rRef.Ref1.nRow 666 || oldTab1 != rRef.Ref1.nTab 667 || oldCol2 != rRef.Ref2.nCol 668 || oldRow2 != rRef.Ref2.nRow 669 || oldTab2 != rRef.Ref2.nTab 670 ) 671 eRet = UR_UPDATED; 672 } 673 if (eWhat != ScRefUpdate::ABSOLUTE) 674 rRef.CalcRelFromAbs( rPos ); 675 } 676 else 677 { 678 if( eMode == URM_MOVE ) 679 { 680 if ( rRef.Ref1.nCol >= nCol1-nDx 681 && rRef.Ref1.nRow >= nRow1-nDy 682 && rRef.Ref1.nTab >= nTab1-nDz 683 && rRef.Ref2.nCol <= nCol2-nDx 684 && rRef.Ref2.nRow <= nRow2-nDy 685 && rRef.Ref2.nTab <= nTab2-nDz ) 686 { 687 eRet = Move( pDoc, rPos, nDx, nDy, nDz, rRef, sal_False, sal_True ); // immer verschieben 688 } 689 else if ( nDz && r.In( rPos ) ) 690 { 691 rRef.Ref1.SetFlag3D( sal_True ); 692 rRef.Ref2.SetFlag3D( sal_True ); 693 eRet = UR_UPDATED; 694 if (eWhat != ScRefUpdate::ABSOLUTE) 695 rRef.CalcRelFromAbs( rPos ); 696 } 697 else if (eWhat != ScRefUpdate::ABSOLUTE) 698 rRef.CalcRelFromAbs( rPos ); 699 } 700 else if( eMode == URM_COPY && r.In( rPos ) ) 701 eRet = Move( pDoc, rPos, nDx, nDy, nDz, rRef, sal_False, sal_False ); // nur relative 702 // sollte nicht mehr verwendet werden muessen 703 else if (eWhat != ScRefUpdate::ABSOLUTE) 704 rRef.CalcRelFromAbs( rPos ); 705 } 706 return eRet; 707 } 708 709 710 ScRefUpdateRes ScRefUpdate::Move( ScDocument* pDoc, const ScAddress& rPos, 711 SCsCOL nDx, SCsROW nDy, SCsTAB nDz, 712 ScComplexRefData& rRef, sal_Bool bWrap, sal_Bool bAbsolute ) 713 { 714 ScRefUpdateRes eRet = UR_NOTHING; 715 716 SCCOL oldCol1 = rRef.Ref1.nCol; 717 SCROW oldRow1 = rRef.Ref1.nRow; 718 SCTAB oldTab1 = rRef.Ref1.nTab; 719 SCCOL oldCol2 = rRef.Ref2.nCol; 720 SCROW oldRow2 = rRef.Ref2.nRow; 721 SCTAB oldTab2 = rRef.Ref2.nTab; 722 723 sal_Bool bCut1, bCut2; 724 if ( nDx ) 725 { 726 bCut1 = bCut2 = sal_False; 727 if( bAbsolute || rRef.Ref1.IsColRel() ) 728 { 729 if( bWrap ) 730 lcl_MoveItWrap( rRef.Ref1.nCol, nDx, MAXCOL ); 731 else 732 bCut1 = lcl_MoveItCut( rRef.Ref1.nCol, nDx, MAXCOL ); 733 } 734 if( bAbsolute || rRef.Ref2.IsColRel() ) 735 { 736 if( bWrap ) 737 lcl_MoveItWrap( rRef.Ref2.nCol, nDx, MAXCOL ); 738 else 739 bCut2 = lcl_MoveItCut( rRef.Ref2.nCol, nDx, MAXCOL ); 740 } 741 if ( bCut1 || bCut2 ) 742 eRet = UR_UPDATED; 743 if ( bCut1 && bCut2 ) 744 { 745 rRef.Ref1.SetColDeleted( sal_True ); 746 rRef.Ref2.SetColDeleted( sal_True ); 747 } 748 } 749 if ( nDy ) 750 { 751 bCut1 = bCut2 = sal_False; 752 if( bAbsolute || rRef.Ref1.IsRowRel() ) 753 { 754 if( bWrap ) 755 lcl_MoveItWrap( rRef.Ref1.nRow, nDy, MAXROW ); 756 else 757 bCut1 = lcl_MoveItCut( rRef.Ref1.nRow, nDy, MAXROW ); 758 } 759 if( bAbsolute || rRef.Ref2.IsRowRel() ) 760 { 761 if( bWrap ) 762 lcl_MoveItWrap( rRef.Ref2.nRow, nDy, MAXROW ); 763 else 764 bCut2 = lcl_MoveItCut( rRef.Ref2.nRow, nDy, MAXROW ); 765 } 766 if ( bCut1 || bCut2 ) 767 eRet = UR_UPDATED; 768 if ( bCut1 && bCut2 ) 769 { 770 rRef.Ref1.SetRowDeleted( sal_True ); 771 rRef.Ref2.SetRowDeleted( sal_True ); 772 } 773 } 774 if ( nDz ) 775 { 776 bCut1 = bCut2 = sal_False; 777 SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; 778 if( bAbsolute || rRef.Ref1.IsTabRel() ) 779 { 780 if( bWrap ) 781 lcl_MoveItWrap( rRef.Ref1.nTab, nDz, static_cast<SCTAB>(nMaxTab) ); 782 else 783 bCut1 = lcl_MoveItCut( rRef.Ref1.nTab, nDz, static_cast<SCTAB>(nMaxTab) ); 784 rRef.Ref1.SetFlag3D( rPos.Tab() != rRef.Ref1.nTab ); 785 } 786 if( bAbsolute || rRef.Ref2.IsTabRel() ) 787 { 788 if( bWrap ) 789 lcl_MoveItWrap( rRef.Ref2.nTab, nDz, static_cast<SCTAB>(nMaxTab) ); 790 else 791 bCut2 = lcl_MoveItCut( rRef.Ref2.nTab, nDz, static_cast<SCTAB>(nMaxTab) ); 792 rRef.Ref2.SetFlag3D( rPos.Tab() != rRef.Ref2.nTab ); 793 } 794 if ( bCut1 || bCut2 ) 795 eRet = UR_UPDATED; 796 if ( bCut1 && bCut2 ) 797 { 798 rRef.Ref1.SetTabDeleted( sal_True ); 799 rRef.Ref2.SetTabDeleted( sal_True ); 800 } 801 } 802 803 if ( eRet == UR_NOTHING ) 804 { 805 if (oldCol1 != rRef.Ref1.nCol 806 || oldRow1 != rRef.Ref1.nRow 807 || oldTab1 != rRef.Ref1.nTab 808 || oldCol2 != rRef.Ref2.nCol 809 || oldRow2 != rRef.Ref2.nRow 810 || oldTab2 != rRef.Ref2.nTab 811 ) 812 eRet = UR_UPDATED; 813 } 814 if ( bWrap && eRet != UR_NOTHING ) 815 rRef.PutInOrder(); 816 rRef.CalcRelFromAbs( rPos ); 817 return eRet; 818 } 819 820 void ScRefUpdate::MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos, 821 SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef ) 822 { 823 if( rRef.Ref1.IsColRel() ) 824 { 825 rRef.Ref1.nCol = rRef.Ref1.nRelCol + rPos.Col(); 826 lcl_MoveItWrap( rRef.Ref1.nCol, static_cast<SCsCOL>(0), nMaxCol ); 827 } 828 if( rRef.Ref2.IsColRel() ) 829 { 830 rRef.Ref2.nCol = rRef.Ref2.nRelCol + rPos.Col(); 831 lcl_MoveItWrap( rRef.Ref2.nCol, static_cast<SCsCOL>(0), nMaxCol ); 832 } 833 if( rRef.Ref1.IsRowRel() ) 834 { 835 rRef.Ref1.nRow = rRef.Ref1.nRelRow + rPos.Row(); 836 lcl_MoveItWrap( rRef.Ref1.nRow, static_cast<SCsROW>(0), nMaxRow ); 837 } 838 if( rRef.Ref2.IsRowRel() ) 839 { 840 rRef.Ref2.nRow = rRef.Ref2.nRelRow + rPos.Row(); 841 lcl_MoveItWrap( rRef.Ref2.nRow, static_cast<SCsROW>(0), nMaxRow ); 842 } 843 SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; 844 if( rRef.Ref1.IsTabRel() ) 845 { 846 rRef.Ref1.nTab = rRef.Ref1.nRelTab + rPos.Tab(); 847 lcl_MoveItWrap( rRef.Ref1.nTab, static_cast<SCsTAB>(0), static_cast<SCTAB>(nMaxTab) ); 848 } 849 if( rRef.Ref2.IsTabRel() ) 850 { 851 rRef.Ref2.nTab = rRef.Ref2.nRelTab + rPos.Tab(); 852 lcl_MoveItWrap( rRef.Ref2.nTab, static_cast<SCsTAB>(0), static_cast<SCTAB>(nMaxTab) ); 853 } 854 rRef.PutInOrder(); 855 rRef.CalcRelFromAbs( rPos ); 856 } 857 858 //------------------------------------------------------------------ 859 860 void ScRefUpdate::DoTranspose( SCsCOL& rCol, SCsROW& rRow, SCsTAB& rTab, 861 ScDocument* pDoc, const ScRange& rSource, const ScAddress& rDest ) 862 { 863 SCsTAB nDz = ((SCsTAB)rDest.Tab())-(SCsTAB)rSource.aStart.Tab(); 864 if (nDz) 865 { 866 SCsTAB nNewTab = rTab+nDz; 867 SCsTAB nCount = pDoc->GetTableCount(); 868 while (nNewTab<0) nNewTab = sal::static_int_cast<SCsTAB>( nNewTab + nCount ); 869 while (nNewTab>=nCount) nNewTab = sal::static_int_cast<SCsTAB>( nNewTab - nCount ); 870 rTab = nNewTab; 871 } 872 DBG_ASSERT( rCol>=rSource.aStart.Col() && rRow>=rSource.aStart.Row(), 873 "UpdateTranspose: Pos. falsch" ); 874 875 SCsCOL nRelX = rCol - (SCsCOL)rSource.aStart.Col(); 876 SCsROW nRelY = rRow - (SCsROW)rSource.aStart.Row(); 877 878 rCol = static_cast<SCsCOL>(static_cast<SCsCOLROW>(rDest.Col()) + 879 static_cast<SCsCOLROW>(nRelY)); 880 rRow = static_cast<SCsROW>(static_cast<SCsCOLROW>(rDest.Row()) + 881 static_cast<SCsCOLROW>(nRelX)); 882 } 883 884 885 ScRefUpdateRes ScRefUpdate::UpdateTranspose( ScDocument* pDoc, 886 const ScRange& rSource, const ScAddress& rDest, 887 ScComplexRefData& rRef ) 888 { 889 ScRefUpdateRes eRet = UR_NOTHING; 890 if ( rRef.Ref1.nCol >= rSource.aStart.Col() && rRef.Ref2.nCol <= rSource.aEnd.Col() && 891 rRef.Ref1.nRow >= rSource.aStart.Row() && rRef.Ref2.nRow <= rSource.aEnd.Row() && 892 rRef.Ref1.nTab >= rSource.aStart.Tab() && rRef.Ref2.nTab <= rSource.aEnd.Tab() ) 893 { 894 DoTranspose( rRef.Ref1.nCol, rRef.Ref1.nRow, rRef.Ref1.nTab, pDoc, rSource, rDest ); 895 DoTranspose( rRef.Ref2.nCol, rRef.Ref2.nRow, rRef.Ref2.nTab, pDoc, rSource, rDest ); 896 eRet = UR_UPDATED; 897 } 898 return eRet; 899 } 900 901 //------------------------------------------------------------------ 902 903 // UpdateGrow - erweitert Referenzen, die genau auf den Bereich zeigen 904 // kommt ohne Dokument aus 905 906 907 ScRefUpdateRes ScRefUpdate::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY, 908 ScComplexRefData& rRef ) 909 { 910 ScRefUpdateRes eRet = UR_NOTHING; 911 912 // in Y-Richtung darf die Ref auch eine Zeile weiter unten anfangen, 913 // falls ein Bereich Spaltenkoepfe enthaelt 914 915 sal_Bool bUpdateX = ( nGrowX && 916 rRef.Ref1.nCol == rArea.aStart.Col() && rRef.Ref2.nCol == rArea.aEnd.Col() && 917 rRef.Ref1.nRow >= rArea.aStart.Row() && rRef.Ref2.nRow <= rArea.aEnd.Row() && 918 rRef.Ref1.nTab >= rArea.aStart.Tab() && rRef.Ref2.nTab <= rArea.aEnd.Tab() ); 919 sal_Bool bUpdateY = ( nGrowY && 920 rRef.Ref1.nCol >= rArea.aStart.Col() && rRef.Ref2.nCol <= rArea.aEnd.Col() && 921 ( rRef.Ref1.nRow == rArea.aStart.Row() || rRef.Ref1.nRow == rArea.aStart.Row()+1 ) && 922 rRef.Ref2.nRow == rArea.aEnd.Row() && 923 rRef.Ref1.nTab >= rArea.aStart.Tab() && rRef.Ref2.nTab <= rArea.aEnd.Tab() ); 924 925 if ( bUpdateX ) 926 { 927 rRef.Ref2.nCol = sal::static_int_cast<SCsCOL>( rRef.Ref2.nCol + nGrowX ); 928 eRet = UR_UPDATED; 929 } 930 if ( bUpdateY ) 931 { 932 rRef.Ref2.nRow = sal::static_int_cast<SCsROW>( rRef.Ref2.nRow + nGrowY ); 933 eRet = UR_UPDATED; 934 } 935 936 return eRet; 937 } 938 939 940