xref: /trunk/main/sc/source/core/tool/refdata.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 #include "refdata.hxx"
34 
35 
36 void ScSingleRefData::CalcRelFromAbs( const ScAddress& rPos )
37 {
38     nRelCol = nCol - rPos.Col();
39     nRelRow = nRow - rPos.Row();
40     nRelTab = nTab - rPos.Tab();
41 }
42 
43 
44 void ScSingleRefData::SmartRelAbs( const ScAddress& rPos )
45 {
46     if ( Flags.bColRel )
47         nCol = nRelCol + rPos.Col();
48     else
49         nRelCol = nCol - rPos.Col();
50 
51     if ( Flags.bRowRel )
52         nRow = nRelRow + rPos.Row();
53     else
54         nRelRow = nRow - rPos.Row();
55 
56     if ( Flags.bTabRel )
57         nTab = nRelTab + rPos.Tab();
58     else
59         nRelTab = nTab - rPos.Tab();
60 }
61 
62 
63 void ScSingleRefData::CalcAbsIfRel( const ScAddress& rPos )
64 {
65     if ( Flags.bColRel )
66     {
67         nCol = nRelCol + rPos.Col();
68         if ( !VALIDCOL( nCol ) )
69             Flags.bColDeleted = sal_True;
70     }
71     if ( Flags.bRowRel )
72     {
73         nRow = nRelRow + rPos.Row();
74         if ( !VALIDROW( nRow ) )
75             Flags.bRowDeleted = sal_True;
76     }
77     if ( Flags.bTabRel )
78     {
79         nTab = nRelTab + rPos.Tab();
80         if ( !VALIDTAB( nTab ) )
81             Flags.bTabDeleted = sal_True;
82     }
83 }
84 
85 //UNUSED2008-05  void ScSingleRefData::OldBoolsToNewFlags( const OldSingleRefBools& rBools )
86 //UNUSED2008-05  {
87 //UNUSED2008-05      switch ( rBools.bRelCol )
88 //UNUSED2008-05      {
89 //UNUSED2008-05          case SR_DELETED :
90 //UNUSED2008-05              Flags.bColRel = sal_True;           // der war verlorengegangen
91 //UNUSED2008-05              Flags.bColDeleted = sal_True;
92 //UNUSED2008-05              break;
93 //UNUSED2008-05          case SR_ABSOLUTE :
94 //UNUSED2008-05              Flags.bColRel = sal_False;
95 //UNUSED2008-05              Flags.bColDeleted = sal_False;
96 //UNUSED2008-05              break;
97 //UNUSED2008-05          case SR_RELABS :
98 //UNUSED2008-05          case SR_RELATIVE :
99 //UNUSED2008-05          default:
100 //UNUSED2008-05              Flags.bColRel = sal_True;
101 //UNUSED2008-05              Flags.bColDeleted = sal_False;
102 //UNUSED2008-05      }
103 //UNUSED2008-05      switch ( rBools.bRelRow )
104 //UNUSED2008-05      {
105 //UNUSED2008-05          case SR_DELETED :
106 //UNUSED2008-05              Flags.bRowRel = sal_True;           // der war verlorengegangen
107 //UNUSED2008-05              Flags.bRowDeleted = sal_True;
108 //UNUSED2008-05              break;
109 //UNUSED2008-05          case SR_ABSOLUTE :
110 //UNUSED2008-05              Flags.bRowRel = sal_False;
111 //UNUSED2008-05              Flags.bRowDeleted = sal_False;
112 //UNUSED2008-05              break;
113 //UNUSED2008-05          case SR_RELABS :
114 //UNUSED2008-05          case SR_RELATIVE :
115 //UNUSED2008-05          default:
116 //UNUSED2008-05              Flags.bRowRel = sal_True;
117 //UNUSED2008-05              Flags.bRowDeleted = sal_False;
118 //UNUSED2008-05      }
119 //UNUSED2008-05      switch ( rBools.bRelTab )
120 //UNUSED2008-05      {
121 //UNUSED2008-05          case SR_DELETED :
122 //UNUSED2008-05              Flags.bTabRel = sal_True;           // der war verlorengegangen
123 //UNUSED2008-05              Flags.bTabDeleted = sal_True;
124 //UNUSED2008-05              break;
125 //UNUSED2008-05          case SR_ABSOLUTE :
126 //UNUSED2008-05              Flags.bTabRel = sal_False;
127 //UNUSED2008-05              Flags.bTabDeleted = sal_False;
128 //UNUSED2008-05              break;
129 //UNUSED2008-05          case SR_RELABS :
130 //UNUSED2008-05          case SR_RELATIVE :
131 //UNUSED2008-05          default:
132 //UNUSED2008-05              Flags.bTabRel = sal_True;
133 //UNUSED2008-05              Flags.bTabDeleted = sal_False;
134 //UNUSED2008-05      }
135 //UNUSED2008-05      Flags.bFlag3D = (rBools.bOldFlag3D & SRF_3D ? sal_True : sal_False);
136 //UNUSED2008-05      Flags.bRelName = (rBools.bOldFlag3D & SRF_RELNAME ? sal_True : sal_False);
137 //UNUSED2008-05      if ( !Flags.bFlag3D )
138 //UNUSED2008-05          Flags.bTabRel = sal_True;   // ist bei einigen aelteren Dokumenten nicht gesetzt
139 //UNUSED2008-05  }
140 //UNUSED2008-05
141 //UNUSED2008-05
142 //UNUSED2008-05  /*
143 //UNUSED2008-05   bis Release 3.1 sah Store so aus
144 //UNUSED2008-05
145 //UNUSED2008-05      sal_uInt8 n = ( ( r.bOldFlag3D & 0x03 ) << 6 )   // RelName, 3D
146 //UNUSED2008-05              | ( ( r.bRelTab & 0x03 ) << 4 )     // Relative, RelAbs
147 //UNUSED2008-05              | ( ( r.bRelRow & 0x03 ) << 2 )
148 //UNUSED2008-05              |   ( r.bRelCol & 0x03 );
149 //UNUSED2008-05
150 //UNUSED2008-05   bis Release 3.1 sah Load so aus
151 //UNUSED2008-05
152 //UNUSED2008-05      r.bRelCol = ( n & 0x03 );
153 //UNUSED2008-05      r.bRelRow = ( ( n >> 2 ) & 0x03 );
154 //UNUSED2008-05      r.bRelTab = ( ( n >> 4 ) & 0x03 );
155 //UNUSED2008-05      r.bOldFlag3D = ( ( n >> 6 ) & 0x03 );
156 //UNUSED2008-05
157 //UNUSED2008-05   bRelCol == SR_DELETED war identisch mit bRelCol == (SR_RELATIVE | SR_RELABS)
158 //UNUSED2008-05   leider..
159 //UNUSED2008-05   3.1 liest Zukunft: Deleted wird nicht unbedingt erkannt, nur wenn auch Relativ.
160 //UNUSED2008-05   Aber immer noch nCol > MAXCOL und gut sollte sein..
161 //UNUSED2008-05   */
162 //UNUSED2008-05
163 //UNUSED2008-05  sal_uInt8 ScSingleRefData::CreateStoreByteFromFlags() const
164 //UNUSED2008-05  {
165 //UNUSED2008-05      return (sal_uInt8)(
166 //UNUSED2008-05            ( (Flags.bRelName     & 0x01) << 7 )
167 //UNUSED2008-05          | ( (Flags.bFlag3D      & 0x01) << 6 )
168 //UNUSED2008-05          | ( (Flags.bTabDeleted  & 0x01) << 5 )
169 //UNUSED2008-05          | ( (Flags.bTabRel      & 0x01) << 4 )
170 //UNUSED2008-05          | ( (Flags.bRowDeleted  & 0x01) << 3 )
171 //UNUSED2008-05          | ( (Flags.bRowRel      & 0x01) << 2 )
172 //UNUSED2008-05          | ( (Flags.bColDeleted  & 0x01) << 1 )
173 //UNUSED2008-05          |   (Flags.bColRel      & 0x01)
174 //UNUSED2008-05          );
175 //UNUSED2008-05  }
176 //UNUSED2008-05
177 //UNUSED2008-05
178 //UNUSED2008-05  void ScSingleRefData::CreateFlagsFromLoadByte( sal_uInt8 n )
179 //UNUSED2008-05  {
180 //UNUSED2008-05      Flags.bColRel       = (n & 0x01 );
181 //UNUSED2008-05      Flags.bColDeleted   = ( (n >> 1) & 0x01 );
182 //UNUSED2008-05      Flags.bRowRel       = ( (n >> 2) & 0x01 );
183 //UNUSED2008-05      Flags.bRowDeleted   = ( (n >> 3) & 0x01 );
184 //UNUSED2008-05      Flags.bTabRel       = ( (n >> 4) & 0x01 );
185 //UNUSED2008-05      Flags.bTabDeleted   = ( (n >> 5) & 0x01 );
186 //UNUSED2008-05      Flags.bFlag3D       = ( (n >> 6) & 0x01 );
187 //UNUSED2008-05      Flags.bRelName      = ( (n >> 7) & 0x01 );
188 //UNUSED2008-05  }
189 
190 
191 sal_Bool ScSingleRefData::operator==( const ScSingleRefData& r ) const
192 {
193     return bFlags == r.bFlags &&
194         (Flags.bColRel ? nRelCol == r.nRelCol : nCol == r.nCol) &&
195         (Flags.bRowRel ? nRelRow == r.nRelRow : nRow == r.nRow) &&
196         (Flags.bTabRel ? nRelTab == r.nRelTab : nTab == r.nTab);
197 }
198 
199 bool ScSingleRefData::operator!=( const ScSingleRefData& r ) const
200 {
201     return !operator==(r);
202 }
203 
204 static void lcl_putInOrder( ScSingleRefData & rRef1, ScSingleRefData & rRef2 )
205 {
206     SCCOL nCol1, nCol2;
207     SCROW nRow1, nRow2;
208     SCTAB nTab1, nTab2;
209     sal_Bool bTmp;
210     sal_uInt8 nRelState1, nRelState2;
211     if ( rRef1.Flags.bRelName )
212         nRelState1 =
213             ((rRef1.Flags.bTabRel & 0x01) << 2)
214             | ((rRef1.Flags.bRowRel & 0x01) << 1)
215             | ((rRef1.Flags.bColRel & 0x01));
216     else
217         nRelState1 = 0;
218     if ( rRef2.Flags.bRelName )
219         nRelState2 =
220             ((rRef2.Flags.bTabRel & 0x01) << 2)
221             | ((rRef2.Flags.bRowRel & 0x01) << 1)
222             | ((rRef2.Flags.bColRel & 0x01));
223     else
224         nRelState2 = 0;
225     if ( (nCol1 = rRef1.nCol) > (nCol2 = rRef2.nCol) )
226     {
227         rRef1.nCol = nCol2;
228         rRef2.nCol = nCol1;
229         nCol1 = rRef1.nRelCol;
230         rRef1.nRelCol = rRef2.nRelCol;
231         rRef2.nRelCol = nCol1;
232         if ( rRef1.Flags.bRelName && rRef1.Flags.bColRel )
233             nRelState2 |= 1;
234         else
235             nRelState2 &= ~1;
236         if ( rRef2.Flags.bRelName && rRef2.Flags.bColRel )
237             nRelState1 |= 1;
238         else
239             nRelState1 &= ~1;
240         bTmp = rRef1.Flags.bColRel;
241         rRef1.Flags.bColRel = rRef2.Flags.bColRel;
242         rRef2.Flags.bColRel = bTmp;
243         bTmp = rRef1.Flags.bColDeleted;
244         rRef1.Flags.bColDeleted = rRef2.Flags.bColDeleted;
245         rRef2.Flags.bColDeleted = bTmp;
246     }
247     if ( (nRow1 = rRef1.nRow) > (nRow2 = rRef2.nRow) )
248     {
249         rRef1.nRow = nRow2;
250         rRef2.nRow = nRow1;
251         nRow1 = rRef1.nRelRow;
252         rRef1.nRelRow = rRef2.nRelRow;
253         rRef2.nRelRow = nRow1;
254         if ( rRef1.Flags.bRelName && rRef1.Flags.bRowRel )
255             nRelState2 |= 2;
256         else
257             nRelState2 &= ~2;
258         if ( rRef2.Flags.bRelName && rRef2.Flags.bRowRel )
259             nRelState1 |= 2;
260         else
261             nRelState1 &= ~2;
262         bTmp = rRef1.Flags.bRowRel;
263         rRef1.Flags.bRowRel = rRef2.Flags.bRowRel;
264         rRef2.Flags.bRowRel = bTmp;
265         bTmp = rRef1.Flags.bRowDeleted;
266         rRef1.Flags.bRowDeleted = rRef2.Flags.bRowDeleted;
267         rRef2.Flags.bRowDeleted = bTmp;
268     }
269     if ( (nTab1 = rRef1.nTab) > (nTab2 = rRef2.nTab) )
270     {
271         rRef1.nTab = nTab2;
272         rRef2.nTab = nTab1;
273         nTab1 = rRef1.nRelTab;
274         rRef1.nRelTab = rRef2.nRelTab;
275         rRef2.nRelTab = nTab1;
276         if ( rRef1.Flags.bRelName && rRef1.Flags.bTabRel )
277             nRelState2 |= 4;
278         else
279             nRelState2 &= ~4;
280         if ( rRef2.Flags.bRelName && rRef2.Flags.bTabRel )
281             nRelState1 |= 4;
282         else
283             nRelState1 &= ~4;
284         bTmp = rRef1.Flags.bTabRel;
285         rRef1.Flags.bTabRel = rRef2.Flags.bTabRel;
286         rRef2.Flags.bTabRel = bTmp;
287         bTmp = rRef1.Flags.bTabDeleted;
288         rRef1.Flags.bTabDeleted = rRef2.Flags.bTabDeleted;
289         rRef2.Flags.bTabDeleted = bTmp;
290     }
291     rRef1.Flags.bRelName = ( nRelState1 ? sal_True : sal_False );
292     rRef2.Flags.bRelName = ( nRelState2 ? sal_True : sal_False );
293 }
294 
295 
296 void ScComplexRefData::PutInOrder()
297 {
298     lcl_putInOrder( Ref1, Ref2);
299 }
300 
301 
302 static void lcl_adjustInOrder( ScSingleRefData & rRef1, ScSingleRefData & rRef2, bool bFirstLeader )
303 {
304     // a1:a2:a3, bFirstLeader: rRef1==a1==r1, rRef2==a3==r2
305     //                   else: rRef1==a3==r2, rRef2==a2==r1
306     ScSingleRefData& r1 = (bFirstLeader ? rRef1 : rRef2);
307     ScSingleRefData& r2 = (bFirstLeader ? rRef2 : rRef1);
308     if (r1.Flags.bFlag3D && !r2.Flags.bFlag3D)
309     {
310         // [$]Sheet1.A5:A6 on Sheet2 do still refer only Sheet1.
311         r2.nTab = r1.nTab;
312         r2.nRelTab = r1.nRelTab;
313         r2.Flags.bTabRel = r1.Flags.bTabRel;
314     }
315     lcl_putInOrder( rRef1, rRef2);
316 }
317 
318 
319 ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const ScAddress & rPos )
320 {
321     CalcAbsIfRel( rPos);
322     ScSingleRefData aRef = rRef;
323     aRef.CalcAbsIfRel( rPos);
324     bool bInherit3D = Ref1.IsFlag3D() && !Ref2.IsFlag3D();
325     bool bInherit3Dtemp = bInherit3D && !rRef.IsFlag3D();
326     if (aRef.nCol < Ref1.nCol || aRef.nRow < Ref1.nRow || aRef.nTab < Ref1.nTab)
327     {
328         lcl_adjustInOrder( Ref1, aRef, true);
329         aRef = rRef;
330         aRef.CalcAbsIfRel( rPos);
331     }
332     if (aRef.nCol > Ref2.nCol || aRef.nRow > Ref2.nRow || aRef.nTab > Ref2.nTab)
333     {
334         if (bInherit3D)
335             Ref2.SetFlag3D( true);
336         lcl_adjustInOrder( aRef, Ref2, false);
337         if (bInherit3Dtemp)
338             Ref2.SetFlag3D( false);
339         aRef = rRef;
340         aRef.CalcAbsIfRel( rPos);
341     }
342     // In Ref2 use absolute/relative addressing from non-extended parts if
343     // equal and therefor not adjusted.
344     // A$5:A5 => A$5:A$5:A5 => A$5:A5, and not A$5:A$5
345     // A$6:$A5 => A$6:A$6:$A5 => A5:$A$6
346     if (Ref2.nCol == aRef.nCol)
347         Ref2.SetColRel( aRef.IsColRel());
348     if (Ref2.nRow == aRef.nRow)
349         Ref2.SetRowRel( aRef.IsRowRel());
350     // $Sheet1.$A$5:$A$6 => $Sheet1.$A$5:$A$5:$A$6 => $Sheet1.$A$5:$A$6, and
351     // not $Sheet1.$A$5:Sheet1.$A$6 (with invisible second 3D, but relative).
352     if (Ref2.nTab == aRef.nTab)
353         Ref2.SetTabRel( bInherit3Dtemp ? Ref1.IsTabRel() : aRef.IsTabRel());
354     Ref2.CalcRelFromAbs( rPos);
355     // Force 3D if necessary. References to other sheets always.
356     if (Ref1.nTab != rPos.Tab())
357         Ref1.SetFlag3D( true);
358     // In the second part only if different sheet thus not inherited.
359     if (Ref2.nTab != Ref1.nTab)
360         Ref2.SetFlag3D( true);
361     // Merge Flag3D to Ref2 in case there was nothing to inherit and/or range
362     // wasn't extended as in A5:A5:Sheet1.A5 if on Sheet1.
363     if (rRef.IsFlag3D())
364         Ref2.SetFlag3D( true);
365     return *this;
366 }
367 
368 
369 ScComplexRefData& ScComplexRefData::Extend( const ScComplexRefData & rRef, const ScAddress & rPos )
370 {
371     return Extend( rRef.Ref1, rPos).Extend( rRef.Ref2, rPos);
372 }
373