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