/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" // INCLUDE --------------------------------------------------------------- #include #include "refupdat.hxx" #include "document.hxx" #include "compiler.hxx" #include "bigrange.hxx" #include "chgtrack.hxx" //------------------------------------------------------------------------ template< typename R, typename S, typename U > sal_Bool lcl_MoveStart( R& rRef, U nStart, S nDelta, U nMask ) { sal_Bool bCut = sal_False; if ( rRef >= nStart ) rRef = sal::static_int_cast( rRef + nDelta ); else if ( nDelta < 0 && rRef >= nStart + nDelta ) rRef = nStart + nDelta; //! begrenzen ??? if ( rRef < 0 ) { rRef = 0; bCut = sal_True; } else if ( rRef > nMask ) { rRef = nMask; bCut = sal_True; } return bCut; } template< typename R, typename S, typename U > sal_Bool lcl_MoveEnd( R& rRef, U nStart, S nDelta, U nMask ) { sal_Bool bCut = sal_False; if ( rRef >= nStart ) rRef = sal::static_int_cast( rRef + nDelta ); else if ( nDelta < 0 && rRef >= nStart + nDelta ) rRef = nStart + nDelta - 1; //! begrenzen ??? if ( rRef < 0 ) { rRef = 0; bCut = sal_True; } else if ( rRef > nMask ) { rRef = nMask; bCut = sal_True; } return bCut; } template< typename R, typename S, typename U > sal_Bool lcl_MoveReorder( R& rRef, U nStart, U nEnd, S nDelta ) { if ( rRef >= nStart && rRef <= nEnd ) { rRef = sal::static_int_cast( rRef + nDelta ); return sal_True; } if ( nDelta > 0 ) // nach hinten schieben { if ( rRef >= nStart && rRef <= nEnd + nDelta ) { if ( rRef <= nEnd ) rRef = sal::static_int_cast( rRef + nDelta ); // in the moved range else rRef -= nEnd - nStart + 1; // nachruecken return sal_True; } } else // nach vorne schieben { if ( rRef >= nStart + nDelta && rRef <= nEnd ) { if ( rRef >= nStart ) rRef = sal::static_int_cast( rRef + nDelta ); // in the moved range else rRef += nEnd - nStart + 1; // nachruecken return sal_True; } } return sal_False; } template< typename R, typename S, typename U > sal_Bool lcl_MoveItCut( R& rRef, S nDelta, U nMask ) { sal_Bool bCut = sal_False; rRef = sal::static_int_cast( rRef + nDelta ); if ( rRef < 0 ) { rRef = 0; bCut = sal_True; } else if ( rRef > nMask ) { rRef = nMask; bCut = sal_True; } return bCut; } template< typename R, typename S, typename U > void lcl_MoveItWrap( R& rRef, S nDelta, U nMask ) { rRef = sal::static_int_cast( rRef + nDelta ); if ( rRef < 0 ) rRef += nMask+1; else if ( rRef > nMask ) rRef -= nMask+1; } template< typename R, typename S, typename U > sal_Bool lcl_MoveRefPart( R& rRef1Val, sal_Bool& rRef1Del, sal_Bool bDo1, R& rRef2Val, sal_Bool& rRef2Del, sal_Bool bDo2, U nStart, U nEnd, S nDelta, U nMask ) { if ( nDelta ) { sal_Bool bDel, bCut1, bCut2; bDel = bCut1 = bCut2 = sal_False; S n; if (bDo1 && bDo2) { if ( nDelta < 0 ) { n = nStart + nDelta; if ( n <= rRef1Val && rRef1Val < nStart && n <= rRef2Val && rRef2Val < nStart ) bDel = sal_True; } else { n = nEnd + nDelta; if ( nEnd < rRef1Val && rRef1Val <= n && nEnd < rRef2Val && rRef2Val <= n ) bDel = sal_True; } } if ( bDel ) { // move deleted along rRef1Val = sal::static_int_cast( rRef1Val + nDelta ); rRef2Val = sal::static_int_cast( rRef2Val + nDelta ); } else { if (bDo1) { if ( rRef1Del ) rRef1Val = sal::static_int_cast( rRef1Val + nDelta ); else bCut1 = lcl_MoveStart( rRef1Val, nStart, nDelta, nMask ); } if (bDo2) { if ( rRef2Del ) rRef2Val = sal::static_int_cast( rRef2Val + nDelta ); else bCut2 = lcl_MoveEnd( rRef2Val, nStart, nDelta, nMask ); } } if ( bDel || (bCut1 && bCut2) ) rRef1Del = rRef2Del = sal_True; return bDel || bCut1 || bCut2 || rRef1Del || rRef2Del; } else return sal_False; } template< typename R, typename S, typename U > sal_Bool IsExpand( R n1, R n2, U nStart, S nD ) { //! vor normalem Move... return nD > 0 // Insert && n1 < n2 // mindestens zwei Cols/Rows/Tabs in Ref && ( (nStart <= n1 && n1 < nStart + nD) // n1 innerhalb des Insert || (n2 + 1 == nStart) // n2 direkt vor Insert ); // n1 < nStart <= n2 wird sowieso expanded! } template< typename R, typename S, typename U > void Expand( R& n1, R& n2, U nStart, S nD ) { //! nach normalem Move..., nur wenn IsExpand vorher sal_True war! //! erst das Ende if ( n2 + 1 == nStart ) { // am Ende n2 = sal::static_int_cast( n2 + nD ); return; } // am Anfang n1 = sal::static_int_cast( n1 - nD ); } sal_Bool lcl_IsWrapBig( sal_Int32 nRef, sal_Int32 nDelta ) { if ( nRef > 0 && nDelta > 0 ) return nRef + nDelta <= 0; else if ( nRef < 0 && nDelta < 0 ) return nRef + nDelta >= 0; return sal_False; } sal_Bool lcl_MoveBig( sal_Int32& rRef, sal_Int32 nStart, sal_Int32 nDelta ) { sal_Bool bCut = sal_False; if ( rRef >= nStart ) { if ( nDelta > 0 ) bCut = lcl_IsWrapBig( rRef, nDelta ); if ( bCut ) rRef = nInt32Max; else rRef += nDelta; } return bCut; } sal_Bool lcl_MoveItCutBig( sal_Int32& rRef, sal_Int32 nDelta ) { sal_Bool bCut = lcl_IsWrapBig( rRef, nDelta ); rRef += nDelta; return bCut; } ScRefUpdateRes ScRefUpdate::Update( ScDocument* pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, SCCOL& theCol1, SCROW& theRow1, SCTAB& theTab1, SCCOL& theCol2, SCROW& theRow2, SCTAB& theTab2 ) { ScRefUpdateRes eRet = UR_NOTHING; SCCOL oldCol1 = theCol1; SCROW oldRow1 = theRow1; SCTAB oldTab1 = theTab1; SCCOL oldCol2 = theCol2; SCROW oldRow2 = theRow2; SCTAB oldTab2 = theTab2; sal_Bool bCut1, bCut2; if (eUpdateRefMode == URM_INSDEL) { sal_Bool bExpand = pDoc->IsExpandRefs(); if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) && (theTab1 >= nTab1) && (theTab2 <= nTab2) ) { sal_Bool bExp = (bExpand && IsExpand( theCol1, theCol2, nCol1, nDx )); bCut1 = lcl_MoveStart( theCol1, nCol1, nDx, MAXCOL ); bCut2 = lcl_MoveEnd( theCol2, nCol1, nDx, MAXCOL ); if ( theCol2 < theCol1 ) { eRet = UR_INVALID; theCol2 = theCol1; } else if ( bCut1 || bCut2 ) eRet = UR_UPDATED; if ( bExp ) { Expand( theCol1, theCol2, nCol1, nDx ); eRet = UR_UPDATED; } } if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) && (theTab1 >= nTab1) && (theTab2 <= nTab2) ) { sal_Bool bExp = (bExpand && IsExpand( theRow1, theRow2, nRow1, nDy )); bCut1 = lcl_MoveStart( theRow1, nRow1, nDy, MAXROW ); bCut2 = lcl_MoveEnd( theRow2, nRow1, nDy, MAXROW ); if ( theRow2 < theRow1 ) { eRet = UR_INVALID; theRow2 = theRow1; } else if ( bCut1 || bCut2 ) eRet = UR_UPDATED; if ( bExp ) { Expand( theRow1, theRow2, nRow1, nDy ); eRet = UR_UPDATED; } } if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) && (theRow1 >= nRow1) && (theRow2 <= nRow2) ) { SCsTAB nMaxTab = pDoc->GetTableCount() - 1; nMaxTab = sal::static_int_cast(nMaxTab + nDz); // adjust to new count sal_Bool bExp = (bExpand && IsExpand( theTab1, theTab2, nTab1, nDz )); bCut1 = lcl_MoveStart( theTab1, nTab1, nDz, static_cast(nMaxTab) ); bCut2 = lcl_MoveEnd( theTab2, nTab1, nDz, static_cast(nMaxTab) ); if ( theTab2 < theTab1 ) { eRet = UR_INVALID; theTab2 = theTab1; } else if ( bCut1 || bCut2 ) eRet = UR_UPDATED; if ( bExp ) { Expand( theTab1, theTab2, nTab1, nDz ); eRet = UR_UPDATED; } } } else if (eUpdateRefMode == URM_MOVE) { if ((theCol1 >= nCol1-nDx) && (theRow1 >= nRow1-nDy) && (theTab1 >= nTab1-nDz) && (theCol2 <= nCol2-nDx) && (theRow2 <= nRow2-nDy) && (theTab2 <= nTab2-nDz)) { if ( nDx ) { bCut1 = lcl_MoveItCut( theCol1, nDx, MAXCOL ); bCut2 = lcl_MoveItCut( theCol2, nDx, MAXCOL ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; } if ( nDy ) { bCut1 = lcl_MoveItCut( theRow1, nDy, MAXROW ); bCut2 = lcl_MoveItCut( theRow2, nDy, MAXROW ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; } if ( nDz ) { SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; bCut1 = lcl_MoveItCut( theTab1, nDz, static_cast(nMaxTab) ); bCut2 = lcl_MoveItCut( theTab2, nDz, static_cast(nMaxTab) ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; } } } else if (eUpdateRefMode == URM_REORDER) { // bisher nur fuer nDz (MoveTab) DBG_ASSERT ( !nDx && !nDy, "URM_REORDER fuer x und y noch nicht implementiert" ); if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) && (theRow1 >= nRow1) && (theRow2 <= nRow2) ) { bCut1 = lcl_MoveReorder( theTab1, nTab1, nTab2, nDz ); bCut2 = lcl_MoveReorder( theTab2, nTab1, nTab2, nDz ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; } } if ( eRet == UR_NOTHING ) { if (oldCol1 != theCol1 || oldRow1 != theRow1 || oldTab1 != theTab1 || oldCol2 != theCol2 || oldRow2 != theRow2 || oldTab2 != theTab2 ) eRet = UR_UPDATED; } return eRet; } // simples UpdateReference fuer ScBigRange (ScChangeAction/ScChangeTrack) // Referenzen koennen auch ausserhalb des Dokuments liegen! // Ganze Spalten/Zeilen (nInt32Min..nInt32Max) bleiben immer solche! ScRefUpdateRes ScRefUpdate::Update( UpdateRefMode eUpdateRefMode, const ScBigRange& rWhere, sal_Int32 nDx, sal_Int32 nDy, sal_Int32 nDz, ScBigRange& rWhat ) { ScRefUpdateRes eRet = UR_NOTHING; const ScBigRange aOldRange( rWhat ); sal_Int32 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2; sal_Int32 theCol1, theRow1, theTab1, theCol2, theRow2, theTab2; rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); rWhat.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ); sal_Bool bCut1, bCut2; if (eUpdateRefMode == URM_INSDEL) { if ( nDx && (theRow1 >= nRow1) && (theRow2 <= nRow2) && (theTab1 >= nTab1) && (theTab2 <= nTab2) && !(theCol1 == nInt32Min && theCol2 == nInt32Max) ) { bCut1 = lcl_MoveBig( theCol1, nCol1, nDx ); bCut2 = lcl_MoveBig( theCol2, nCol1, nDx ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; rWhat.aStart.SetCol( theCol1 ); rWhat.aEnd.SetCol( theCol2 ); } if ( nDy && (theCol1 >= nCol1) && (theCol2 <= nCol2) && (theTab1 >= nTab1) && (theTab2 <= nTab2) && !(theRow1 == nInt32Min && theRow2 == nInt32Max) ) { bCut1 = lcl_MoveBig( theRow1, nRow1, nDy ); bCut2 = lcl_MoveBig( theRow2, nRow1, nDy ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; rWhat.aStart.SetRow( theRow1 ); rWhat.aEnd.SetRow( theRow2 ); } if ( nDz && (theCol1 >= nCol1) && (theCol2 <= nCol2) && (theRow1 >= nRow1) && (theRow2 <= nRow2) && !(theTab1 == nInt32Min && theTab2 == nInt32Max) ) { bCut1 = lcl_MoveBig( theTab1, nTab1, nDz ); bCut2 = lcl_MoveBig( theTab2, nTab1, nDz ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; rWhat.aStart.SetTab( theTab1 ); rWhat.aEnd.SetTab( theTab2 ); } } else if (eUpdateRefMode == URM_MOVE) { if ( rWhere.In( rWhat ) ) { if ( nDx && !(theCol1 == nInt32Min && theCol2 == nInt32Max) ) { bCut1 = lcl_MoveItCutBig( theCol1, nDx ); bCut2 = lcl_MoveItCutBig( theCol2, nDx ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; rWhat.aStart.SetCol( theCol1 ); rWhat.aEnd.SetCol( theCol2 ); } if ( nDy && !(theRow1 == nInt32Min && theRow2 == nInt32Max) ) { bCut1 = lcl_MoveItCutBig( theRow1, nDy ); bCut2 = lcl_MoveItCutBig( theRow2, nDy ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; rWhat.aStart.SetRow( theRow1 ); rWhat.aEnd.SetRow( theRow2 ); } if ( nDz && !(theTab1 == nInt32Min && theTab2 == nInt32Max) ) { bCut1 = lcl_MoveItCutBig( theTab1, nDz ); bCut2 = lcl_MoveItCutBig( theTab2, nDz ); if ( bCut1 || bCut2 ) eRet = UR_UPDATED; rWhat.aStart.SetTab( theTab1 ); rWhat.aEnd.SetTab( theTab2 ); } } } if ( eRet == UR_NOTHING && rWhat != aOldRange ) eRet = UR_UPDATED; return eRet; } ScRefUpdateRes ScRefUpdate::Update( ScDocument* pDoc, UpdateRefMode eMode, const ScAddress& rPos, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, ScComplexRefData& rRef, WhatType eWhat ) { ScRefUpdateRes eRet = UR_NOTHING; SCCOL nCol1 = r.aStart.Col(); SCROW nRow1 = r.aStart.Row(); SCTAB nTab1 = r.aStart.Tab(); SCCOL nCol2 = r.aEnd.Col(); SCROW nRow2 = r.aEnd.Row(); SCTAB nTab2 = r.aEnd.Tab(); if( eMode == URM_INSDEL ) { sal_Bool bExpand = pDoc->IsExpandRefs(); const ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); sal_Bool bInDeleteUndo = ( pChangeTrack ? pChangeTrack->IsInDeleteUndo() : sal_False ); SCCOL oldCol1 = rRef.Ref1.nCol; SCROW oldRow1 = rRef.Ref1.nRow; SCTAB oldTab1 = rRef.Ref1.nTab; SCCOL oldCol2 = rRef.Ref2.nCol; SCROW oldRow2 = rRef.Ref2.nRow; SCTAB oldTab2 = rRef.Ref2.nTab; sal_Bool bRef1ColDel = rRef.Ref1.IsColDeleted(); sal_Bool bRef2ColDel = rRef.Ref2.IsColDeleted(); sal_Bool bRef1RowDel = rRef.Ref1.IsRowDeleted(); sal_Bool bRef2RowDel = rRef.Ref2.IsRowDeleted(); sal_Bool bRef1TabDel = rRef.Ref1.IsTabDeleted(); sal_Bool bRef2TabDel = rRef.Ref2.IsTabDeleted(); if( nDx && ((rRef.Ref1.nRow >= nRow1 && rRef.Ref2.nRow <= nRow2) || (bRef1RowDel || bRef2RowDel)) && ((rRef.Ref1.nTab >= nTab1 && rRef.Ref2.nTab <= nTab2) || (bRef1TabDel || bRef2TabDel)) ) { sal_Bool bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nCol, rRef.Ref2.nCol, nCol1, nDx )); sal_Bool bDo1 = (eWhat == ScRefUpdate::ALL || (eWhat == ScRefUpdate::ABSOLUTE && !rRef.Ref1.IsColRel())); sal_Bool bDo2 = (eWhat == ScRefUpdate::ALL || (eWhat == ScRefUpdate::ABSOLUTE && !rRef.Ref2.IsColRel())); if ( lcl_MoveRefPart( rRef.Ref1.nCol, bRef1ColDel, bDo1, rRef.Ref2.nCol, bRef2ColDel, bDo2, nCol1, nCol2, nDx, MAXCOL ) ) { eRet = UR_UPDATED; if ( bInDeleteUndo && (bRef1ColDel || bRef2ColDel) ) { if ( bRef1ColDel && nCol1 <= rRef.Ref1.nCol && rRef.Ref1.nCol <= nCol1 + nDx ) rRef.Ref1.SetColDeleted( sal_False ); if ( bRef2ColDel && nCol1 <= rRef.Ref2.nCol && rRef.Ref2.nCol <= nCol1 + nDx ) rRef.Ref2.SetColDeleted( sal_False ); } else { if ( bRef1ColDel ) rRef.Ref1.SetColDeleted( sal_True ); if ( bRef2ColDel ) rRef.Ref2.SetColDeleted( sal_True ); } } if ( bExp ) { Expand( rRef.Ref1.nCol, rRef.Ref2.nCol, nCol1, nDx ); eRet = UR_UPDATED; } } if( nDy && ((rRef.Ref1.nCol >= nCol1 && rRef.Ref2.nCol <= nCol2) || (bRef1ColDel || bRef2ColDel)) && ((rRef.Ref1.nTab >= nTab1 && rRef.Ref2.nTab <= nTab2) || (bRef1TabDel || bRef2TabDel)) ) { sal_Bool bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nRow, rRef.Ref2.nRow, nRow1, nDy )); sal_Bool bDo1 = (eWhat == ScRefUpdate::ALL || (eWhat == ScRefUpdate::ABSOLUTE && !rRef.Ref1.IsRowRel())); sal_Bool bDo2 = (eWhat == ScRefUpdate::ALL || (eWhat == ScRefUpdate::ABSOLUTE && !rRef.Ref2.IsRowRel())); if ( lcl_MoveRefPart( rRef.Ref1.nRow, bRef1RowDel, bDo1, rRef.Ref2.nRow, bRef2RowDel, bDo2, nRow1, nRow2, nDy, MAXROW ) ) { eRet = UR_UPDATED; if ( bInDeleteUndo && (bRef1RowDel || bRef2RowDel) ) { if ( bRef1RowDel && nRow1 <= rRef.Ref1.nRow && rRef.Ref1.nRow <= nRow1 + nDy ) rRef.Ref1.SetRowDeleted( sal_False ); if ( bRef2RowDel && nRow1 <= rRef.Ref2.nRow && rRef.Ref2.nRow <= nRow1 + nDy ) rRef.Ref2.SetRowDeleted( sal_False ); } else { if ( bRef1RowDel ) rRef.Ref1.SetRowDeleted( sal_True ); if ( bRef2RowDel ) rRef.Ref2.SetRowDeleted( sal_True ); } } if ( bExp ) { Expand( rRef.Ref1.nRow, rRef.Ref2.nRow, nRow1, nDy ); eRet = UR_UPDATED; } } if( nDz && ((rRef.Ref1.nCol >= nCol1 && rRef.Ref2.nCol <= nCol2) || (bRef1ColDel || bRef2ColDel)) && ((rRef.Ref1.nRow >= nRow1 && rRef.Ref2.nRow <= nRow2) || (bRef1RowDel || bRef2RowDel)) ) { sal_Bool bExp = (bExpand && !bInDeleteUndo && IsExpand( rRef.Ref1.nTab, rRef.Ref2.nTab, nTab1, nDz )); SCTAB nMaxTab = pDoc->GetTableCount() - 1; sal_Bool bDo1 = (eWhat == ScRefUpdate::ALL || (eWhat == ScRefUpdate::ABSOLUTE && !rRef.Ref1.IsTabRel())); sal_Bool bDo2 = (eWhat == ScRefUpdate::ALL || (eWhat == ScRefUpdate::ABSOLUTE && !rRef.Ref2.IsTabRel())); if ( lcl_MoveRefPart( rRef.Ref1.nTab, bRef1TabDel, bDo1, rRef.Ref2.nTab, bRef2TabDel, bDo2, nTab1, nTab2, nDz, nMaxTab ) ) { eRet = UR_UPDATED; if ( bInDeleteUndo && (bRef1TabDel || bRef2TabDel) ) { if ( bRef1TabDel && nTab1 <= rRef.Ref1.nTab && rRef.Ref1.nTab <= nTab1 + nDz ) rRef.Ref1.SetTabDeleted( sal_False ); if ( bRef2TabDel && nTab1 <= rRef.Ref2.nTab && rRef.Ref2.nTab <= nTab1 + nDz ) rRef.Ref2.SetTabDeleted( sal_False ); } else { if ( bRef1TabDel ) rRef.Ref1.SetTabDeleted( sal_True ); if ( bRef2TabDel ) rRef.Ref2.SetTabDeleted( sal_True ); } } if ( bExp ) { Expand( rRef.Ref1.nTab, rRef.Ref2.nTab, nTab1, nDz ); eRet = UR_UPDATED; } } if ( eRet == UR_NOTHING ) { if (oldCol1 != rRef.Ref1.nCol || oldRow1 != rRef.Ref1.nRow || oldTab1 != rRef.Ref1.nTab || oldCol2 != rRef.Ref2.nCol || oldRow2 != rRef.Ref2.nRow || oldTab2 != rRef.Ref2.nTab ) eRet = UR_UPDATED; } if (eWhat != ScRefUpdate::ABSOLUTE) rRef.CalcRelFromAbs( rPos ); } else { if( eMode == URM_MOVE ) { if ( rRef.Ref1.nCol >= nCol1-nDx && rRef.Ref1.nRow >= nRow1-nDy && rRef.Ref1.nTab >= nTab1-nDz && rRef.Ref2.nCol <= nCol2-nDx && rRef.Ref2.nRow <= nRow2-nDy && rRef.Ref2.nTab <= nTab2-nDz ) { eRet = Move( pDoc, rPos, nDx, nDy, nDz, rRef, sal_False, sal_True ); // immer verschieben } else if ( nDz && r.In( rPos ) ) { rRef.Ref1.SetFlag3D( sal_True ); rRef.Ref2.SetFlag3D( sal_True ); eRet = UR_UPDATED; if (eWhat != ScRefUpdate::ABSOLUTE) rRef.CalcRelFromAbs( rPos ); } else if (eWhat != ScRefUpdate::ABSOLUTE) rRef.CalcRelFromAbs( rPos ); } else if( eMode == URM_COPY && r.In( rPos ) ) eRet = Move( pDoc, rPos, nDx, nDy, nDz, rRef, sal_False, sal_False ); // nur relative // sollte nicht mehr verwendet werden muessen else if (eWhat != ScRefUpdate::ABSOLUTE) rRef.CalcRelFromAbs( rPos ); } return eRet; } ScRefUpdateRes ScRefUpdate::Move( ScDocument* pDoc, const ScAddress& rPos, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, ScComplexRefData& rRef, sal_Bool bWrap, sal_Bool bAbsolute ) { ScRefUpdateRes eRet = UR_NOTHING; SCCOL oldCol1 = rRef.Ref1.nCol; SCROW oldRow1 = rRef.Ref1.nRow; SCTAB oldTab1 = rRef.Ref1.nTab; SCCOL oldCol2 = rRef.Ref2.nCol; SCROW oldRow2 = rRef.Ref2.nRow; SCTAB oldTab2 = rRef.Ref2.nTab; sal_Bool bCut1, bCut2; if ( nDx ) { bCut1 = bCut2 = sal_False; if( bAbsolute || rRef.Ref1.IsColRel() ) { if( bWrap ) lcl_MoveItWrap( rRef.Ref1.nCol, nDx, MAXCOL ); else bCut1 = lcl_MoveItCut( rRef.Ref1.nCol, nDx, MAXCOL ); } if( bAbsolute || rRef.Ref2.IsColRel() ) { if( bWrap ) lcl_MoveItWrap( rRef.Ref2.nCol, nDx, MAXCOL ); else bCut2 = lcl_MoveItCut( rRef.Ref2.nCol, nDx, MAXCOL ); } if ( bCut1 || bCut2 ) eRet = UR_UPDATED; if ( bCut1 && bCut2 ) { rRef.Ref1.SetColDeleted( sal_True ); rRef.Ref2.SetColDeleted( sal_True ); } } if ( nDy ) { bCut1 = bCut2 = sal_False; if( bAbsolute || rRef.Ref1.IsRowRel() ) { if( bWrap ) lcl_MoveItWrap( rRef.Ref1.nRow, nDy, MAXROW ); else bCut1 = lcl_MoveItCut( rRef.Ref1.nRow, nDy, MAXROW ); } if( bAbsolute || rRef.Ref2.IsRowRel() ) { if( bWrap ) lcl_MoveItWrap( rRef.Ref2.nRow, nDy, MAXROW ); else bCut2 = lcl_MoveItCut( rRef.Ref2.nRow, nDy, MAXROW ); } if ( bCut1 || bCut2 ) eRet = UR_UPDATED; if ( bCut1 && bCut2 ) { rRef.Ref1.SetRowDeleted( sal_True ); rRef.Ref2.SetRowDeleted( sal_True ); } } if ( nDz ) { bCut1 = bCut2 = sal_False; SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; if( bAbsolute || rRef.Ref1.IsTabRel() ) { if( bWrap ) lcl_MoveItWrap( rRef.Ref1.nTab, nDz, static_cast(nMaxTab) ); else bCut1 = lcl_MoveItCut( rRef.Ref1.nTab, nDz, static_cast(nMaxTab) ); rRef.Ref1.SetFlag3D( rPos.Tab() != rRef.Ref1.nTab ); } if( bAbsolute || rRef.Ref2.IsTabRel() ) { if( bWrap ) lcl_MoveItWrap( rRef.Ref2.nTab, nDz, static_cast(nMaxTab) ); else bCut2 = lcl_MoveItCut( rRef.Ref2.nTab, nDz, static_cast(nMaxTab) ); rRef.Ref2.SetFlag3D( rPos.Tab() != rRef.Ref2.nTab ); } if ( bCut1 || bCut2 ) eRet = UR_UPDATED; if ( bCut1 && bCut2 ) { rRef.Ref1.SetTabDeleted( sal_True ); rRef.Ref2.SetTabDeleted( sal_True ); } } if ( eRet == UR_NOTHING ) { if (oldCol1 != rRef.Ref1.nCol || oldRow1 != rRef.Ref1.nRow || oldTab1 != rRef.Ref1.nTab || oldCol2 != rRef.Ref2.nCol || oldRow2 != rRef.Ref2.nRow || oldTab2 != rRef.Ref2.nTab ) eRet = UR_UPDATED; } if ( bWrap && eRet != UR_NOTHING ) rRef.PutInOrder(); rRef.CalcRelFromAbs( rPos ); return eRet; } void ScRefUpdate::MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef ) { if( rRef.Ref1.IsColRel() ) { rRef.Ref1.nCol = rRef.Ref1.nRelCol + rPos.Col(); lcl_MoveItWrap( rRef.Ref1.nCol, static_cast(0), nMaxCol ); } if( rRef.Ref2.IsColRel() ) { rRef.Ref2.nCol = rRef.Ref2.nRelCol + rPos.Col(); lcl_MoveItWrap( rRef.Ref2.nCol, static_cast(0), nMaxCol ); } if( rRef.Ref1.IsRowRel() ) { rRef.Ref1.nRow = rRef.Ref1.nRelRow + rPos.Row(); lcl_MoveItWrap( rRef.Ref1.nRow, static_cast(0), nMaxRow ); } if( rRef.Ref2.IsRowRel() ) { rRef.Ref2.nRow = rRef.Ref2.nRelRow + rPos.Row(); lcl_MoveItWrap( rRef.Ref2.nRow, static_cast(0), nMaxRow ); } SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; if( rRef.Ref1.IsTabRel() ) { rRef.Ref1.nTab = rRef.Ref1.nRelTab + rPos.Tab(); lcl_MoveItWrap( rRef.Ref1.nTab, static_cast(0), static_cast(nMaxTab) ); } if( rRef.Ref2.IsTabRel() ) { rRef.Ref2.nTab = rRef.Ref2.nRelTab + rPos.Tab(); lcl_MoveItWrap( rRef.Ref2.nTab, static_cast(0), static_cast(nMaxTab) ); } rRef.PutInOrder(); rRef.CalcRelFromAbs( rPos ); } //------------------------------------------------------------------ void ScRefUpdate::DoTranspose( SCsCOL& rCol, SCsROW& rRow, SCsTAB& rTab, ScDocument* pDoc, const ScRange& rSource, const ScAddress& rDest ) { SCsTAB nDz = ((SCsTAB)rDest.Tab())-(SCsTAB)rSource.aStart.Tab(); if (nDz) { SCsTAB nNewTab = rTab+nDz; SCsTAB nCount = pDoc->GetTableCount(); while (nNewTab<0) nNewTab = sal::static_int_cast( nNewTab + nCount ); while (nNewTab>=nCount) nNewTab = sal::static_int_cast( nNewTab - nCount ); rTab = nNewTab; } DBG_ASSERT( rCol>=rSource.aStart.Col() && rRow>=rSource.aStart.Row(), "UpdateTranspose: Pos. falsch" ); SCsCOL nRelX = rCol - (SCsCOL)rSource.aStart.Col(); SCsROW nRelY = rRow - (SCsROW)rSource.aStart.Row(); rCol = static_cast(static_cast(rDest.Col()) + static_cast(nRelY)); rRow = static_cast(static_cast(rDest.Row()) + static_cast(nRelX)); } ScRefUpdateRes ScRefUpdate::UpdateTranspose( ScDocument* pDoc, const ScRange& rSource, const ScAddress& rDest, ScComplexRefData& rRef ) { ScRefUpdateRes eRet = UR_NOTHING; if ( rRef.Ref1.nCol >= rSource.aStart.Col() && rRef.Ref2.nCol <= rSource.aEnd.Col() && rRef.Ref1.nRow >= rSource.aStart.Row() && rRef.Ref2.nRow <= rSource.aEnd.Row() && rRef.Ref1.nTab >= rSource.aStart.Tab() && rRef.Ref2.nTab <= rSource.aEnd.Tab() ) { DoTranspose( rRef.Ref1.nCol, rRef.Ref1.nRow, rRef.Ref1.nTab, pDoc, rSource, rDest ); DoTranspose( rRef.Ref2.nCol, rRef.Ref2.nRow, rRef.Ref2.nTab, pDoc, rSource, rDest ); eRet = UR_UPDATED; } return eRet; } //------------------------------------------------------------------ // UpdateGrow - erweitert Referenzen, die genau auf den Bereich zeigen // kommt ohne Dokument aus ScRefUpdateRes ScRefUpdate::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY, ScComplexRefData& rRef ) { ScRefUpdateRes eRet = UR_NOTHING; // in Y-Richtung darf die Ref auch eine Zeile weiter unten anfangen, // falls ein Bereich Spaltenkoepfe enthaelt sal_Bool bUpdateX = ( nGrowX && rRef.Ref1.nCol == rArea.aStart.Col() && rRef.Ref2.nCol == rArea.aEnd.Col() && rRef.Ref1.nRow >= rArea.aStart.Row() && rRef.Ref2.nRow <= rArea.aEnd.Row() && rRef.Ref1.nTab >= rArea.aStart.Tab() && rRef.Ref2.nTab <= rArea.aEnd.Tab() ); sal_Bool bUpdateY = ( nGrowY && rRef.Ref1.nCol >= rArea.aStart.Col() && rRef.Ref2.nCol <= rArea.aEnd.Col() && ( rRef.Ref1.nRow == rArea.aStart.Row() || rRef.Ref1.nRow == rArea.aStart.Row()+1 ) && rRef.Ref2.nRow == rArea.aEnd.Row() && rRef.Ref1.nTab >= rArea.aStart.Tab() && rRef.Ref2.nTab <= rArea.aEnd.Tab() ); if ( bUpdateX ) { rRef.Ref2.nCol = sal::static_int_cast( rRef.Ref2.nCol + nGrowX ); eRet = UR_UPDATED; } if ( bUpdateY ) { rRef.Ref2.nRow = sal::static_int_cast( rRef.Ref2.nRow + nGrowY ); eRet = UR_UPDATED; } return eRet; }