xref: /aoo41x/main/sc/source/core/tool/refupdat.cxx (revision cdf0e10c)
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