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