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