1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "refdata.hxx"
22 void ScSingleRefData::InitAddress( const ScAddress
& rAdr
)
24 InitAddress( rAdr
.Col(), rAdr
.Row(), rAdr
.Tab());
27 void ScSingleRefData::InitAddress( SCCOL nColP
, SCROW nRowP
, SCTAB nTabP
)
35 void ScSingleRefData::InitAddressRel( const ScAddress
& rAdr
, const ScAddress
& rPos
)
41 SetAddress(rAdr
, rPos
);
44 void ScSingleRefData::InitFromRefAddress( const ScRefAddress
& rRef
, const ScAddress
& rPos
)
47 SetColRel( rRef
.IsRelCol());
48 SetRowRel( rRef
.IsRelRow());
49 SetTabRel( rRef
.IsRelTab());
50 SetFlag3D( rRef
.Tab() != rPos
.Tab());
51 SetAddress( rRef
.GetAddress(), rPos
);
54 void ScSingleRefData::SetAbsCol( SCCOL nVal
)
56 Flags
.bColRel
= false;
60 void ScSingleRefData::SetRelCol( SCCOL nVal
)
66 void ScSingleRefData::IncCol( SCCOL nInc
)
71 void ScSingleRefData::SetAbsRow( SCROW nVal
)
73 Flags
.bRowRel
= false;
77 void ScSingleRefData::SetRelRow( SCROW nVal
)
83 void ScSingleRefData::IncRow( SCROW nInc
)
88 void ScSingleRefData::SetAbsTab( SCTAB nVal
)
90 Flags
.bTabRel
= false;
94 void ScSingleRefData::SetRelTab( SCTAB nVal
)
100 void ScSingleRefData::IncTab( SCTAB nInc
)
105 void ScSingleRefData::SetColDeleted( bool bVal
)
107 Flags
.bColDeleted
= bVal
;
110 void ScSingleRefData::SetRowDeleted( bool bVal
)
112 Flags
.bRowDeleted
= bVal
;
115 void ScSingleRefData::SetTabDeleted( bool bVal
)
117 Flags
.bTabDeleted
= bVal
;
120 bool ScSingleRefData::IsDeleted() const
122 return IsColDeleted() || IsRowDeleted() || IsTabDeleted();
125 bool ScSingleRefData::Valid() const
127 return ColValid() && RowValid() && TabValid();
130 bool ScSingleRefData::ColValid() const
134 if (mnCol
< -MAXCOL
|| MAXCOL
< mnCol
)
139 if (mnCol
< 0 || MAXCOL
< mnCol
)
146 bool ScSingleRefData::RowValid() const
150 if (mnRow
< -MAXROW
|| MAXROW
< mnRow
)
155 if (mnRow
< 0 || MAXROW
< mnRow
)
162 bool ScSingleRefData::TabValid() const
166 if (mnTab
< -MAXTAB
|| MAXTAB
< mnTab
)
171 if (mnTab
< 0 || MAXTAB
< mnTab
)
178 bool ScSingleRefData::ValidExternal() const
180 return ColValid() && RowValid() && mnTab
== -1;
183 ScAddress
ScSingleRefData::toAbs( const ScAddress
& rPos
) const
185 SCCOL nRetCol
= Flags
.bColRel
? mnCol
+ rPos
.Col() : mnCol
;
186 SCROW nRetRow
= Flags
.bRowRel
? mnRow
+ rPos
.Row() : mnRow
;
187 SCTAB nRetTab
= Flags
.bTabRel
? mnTab
+ rPos
.Tab() : mnTab
;
189 ScAddress
aAbs(ScAddress::INITIALIZE_INVALID
);
191 if (ValidCol(nRetCol
))
192 aAbs
.SetCol(nRetCol
);
194 if (ValidRow(nRetRow
))
195 aAbs
.SetRow(nRetRow
);
197 if (ValidTab(nRetTab
))
198 aAbs
.SetTab(nRetTab
);
203 void ScSingleRefData::SetAddress( const ScAddress
& rAddr
, const ScAddress
& rPos
)
206 mnCol
= rAddr
.Col() - rPos
.Col();
211 mnRow
= rAddr
.Row() - rPos
.Row();
216 mnTab
= rAddr
.Tab() - rPos
.Tab();
221 SCROW
ScSingleRefData::Row() const
223 if (Flags
.bRowDeleted
)
228 SCCOL
ScSingleRefData::Col() const
230 if (Flags
.bColDeleted
)
235 SCTAB
ScSingleRefData::Tab() const
237 if (Flags
.bTabDeleted
)
243 void ScSingleRefData::PutInOrder( ScSingleRefData
& rRef1
, ScSingleRefData
& rRef2
, const ScAddress
& rPos
)
245 sal_uInt8 nRelState1
= rRef1
.Flags
.bRelName
?
246 ((rRef1
.Flags
.bTabRel
? 4 : 0) |
247 (rRef1
.Flags
.bRowRel
? 2 : 0) |
248 (rRef1
.Flags
.bColRel
? 1 : 0)) :
251 sal_uInt8 nRelState2
= rRef2
.Flags
.bRelName
?
252 ((rRef2
.Flags
.bTabRel
? 4 : 0) |
253 (rRef2
.Flags
.bRowRel
? 2 : 0) |
254 (rRef2
.Flags
.bColRel
? 1 : 0)) :
257 SCCOL nCol1
= rRef1
.Flags
.bColRel
? rPos
.Col() + rRef1
.mnCol
: rRef1
.mnCol
;
258 SCCOL nCol2
= rRef2
.Flags
.bColRel
? rPos
.Col() + rRef2
.mnCol
: rRef2
.mnCol
;
261 rRef1
.mnCol
= rRef2
.Flags
.bColRel
? nCol2
- rPos
.Col() : nCol2
;
262 rRef2
.mnCol
= rRef1
.Flags
.bColRel
? nCol1
- rPos
.Col() : nCol1
;
263 if (rRef1
.Flags
.bRelName
&& rRef1
.Flags
.bColRel
)
267 if (rRef2
.Flags
.bRelName
&& rRef2
.Flags
.bColRel
)
271 bool bTmp
= rRef1
.Flags
.bColRel
;
272 rRef1
.Flags
.bColRel
= rRef2
.Flags
.bColRel
;
273 rRef2
.Flags
.bColRel
= bTmp
;
274 bTmp
= rRef1
.Flags
.bColDeleted
;
275 rRef1
.Flags
.bColDeleted
= rRef2
.Flags
.bColDeleted
;
276 rRef2
.Flags
.bColDeleted
= bTmp
;
279 SCROW nRow1
= rRef1
.Flags
.bRowRel
? rPos
.Row() + rRef1
.mnRow
: rRef1
.mnRow
;
280 SCROW nRow2
= rRef2
.Flags
.bRowRel
? rPos
.Row() + rRef2
.mnRow
: rRef2
.mnRow
;
283 rRef1
.mnRow
= rRef2
.Flags
.bRowRel
? nRow2
- rPos
.Row() : nRow2
;
284 rRef2
.mnRow
= rRef1
.Flags
.bRowRel
? nRow1
- rPos
.Row() : nRow1
;
285 if (rRef1
.Flags
.bRelName
&& rRef1
.Flags
.bRowRel
)
289 if (rRef2
.Flags
.bRelName
&& rRef2
.Flags
.bRowRel
)
293 bool bTmp
= rRef1
.Flags
.bRowRel
;
294 rRef1
.Flags
.bRowRel
= rRef2
.Flags
.bRowRel
;
295 rRef2
.Flags
.bRowRel
= bTmp
;
296 bTmp
= rRef1
.Flags
.bRowDeleted
;
297 rRef1
.Flags
.bRowDeleted
= rRef2
.Flags
.bRowDeleted
;
298 rRef2
.Flags
.bRowDeleted
= bTmp
;
301 SCTAB nTab1
= rRef1
.Flags
.bTabRel
? rPos
.Tab() + rRef1
.mnTab
: rRef1
.mnTab
;
302 SCTAB nTab2
= rRef2
.Flags
.bTabRel
? rPos
.Tab() + rRef2
.mnTab
: rRef2
.mnTab
;
305 rRef1
.mnTab
= rRef2
.Flags
.bTabRel
? nTab2
- rPos
.Tab() : nTab2
;
306 rRef2
.mnTab
= rRef1
.Flags
.bTabRel
? nTab1
- rPos
.Tab() : nTab1
;
307 if (rRef1
.Flags
.bRelName
&& rRef1
.Flags
.bTabRel
)
311 if (rRef2
.Flags
.bRelName
&& rRef2
.Flags
.bTabRel
)
315 bool bTmp
= rRef1
.Flags
.bTabRel
;
316 rRef1
.Flags
.bTabRel
= rRef2
.Flags
.bTabRel
;
317 rRef2
.Flags
.bTabRel
= bTmp
;
318 bTmp
= rRef1
.Flags
.bTabDeleted
;
319 rRef1
.Flags
.bTabDeleted
= rRef2
.Flags
.bTabDeleted
;
320 rRef2
.Flags
.bTabDeleted
= bTmp
;
323 // bFlag3D stays the same on both references.
325 rRef1
.Flags
.bRelName
= (nRelState1
!= 0);
326 rRef2
.Flags
.bRelName
= (nRelState2
!= 0);
329 bool ScSingleRefData::operator==( const ScSingleRefData
& r
) const
331 return mnFlagValue
== r
.mnFlagValue
&& mnCol
== r
.mnCol
&& mnRow
== r
.mnRow
&& mnTab
== r
.mnTab
;
334 bool ScSingleRefData::operator!=( const ScSingleRefData
& r
) const
336 return !operator==(r
);
339 #if DEBUG_FORMULA_COMPILER
340 void ScSingleRefData::Dump( int nIndent
) const
343 for (int i
= 0; i
< nIndent
; ++i
)
346 cout
<< aIndent
<< "address type column: " << (IsColRel()?"relative":"absolute")
347 << " row : " << (IsRowRel()?"relative":"absolute") << " sheet: "
348 << (IsTabRel()?"relative":"absolute") << endl
;
349 cout
<< aIndent
<< "deleted column: " << (IsColDeleted()?"yes":"no")
350 << " row : " << (IsRowDeleted()?"yes":"no") << " sheet: "
351 << (IsTabDeleted()?"yes":"no") << endl
;
352 cout
<< aIndent
<< "column: " << mnCol
<< " row: " << mnRow
<< " sheet: " << mnTab
<< endl
;
353 cout
<< aIndent
<< "3d ref: " << (IsFlag3D()?"yes":"no") << endl
;
357 void ScComplexRefData::InitFromRefAddresses( const ScRefAddress
& rRef1
, const ScRefAddress
& rRef2
, const ScAddress
& rPos
)
360 Ref1
.SetColRel( rRef1
.IsRelCol());
361 Ref1
.SetRowRel( rRef1
.IsRelRow());
362 Ref1
.SetTabRel( rRef1
.IsRelTab());
363 Ref1
.SetFlag3D( rRef1
.Tab() != rPos
.Tab() || rRef1
.Tab() != rRef2
.Tab());
364 Ref2
.SetColRel( rRef2
.IsRelCol());
365 Ref2
.SetRowRel( rRef2
.IsRelRow());
366 Ref2
.SetTabRel( rRef2
.IsRelTab());
367 Ref2
.SetFlag3D( rRef1
.Tab() != rRef2
.Tab());
368 SetRange( ScRange( rRef1
.GetAddress(), rRef2
.GetAddress()), rPos
);
371 ScComplexRefData
& ScComplexRefData::Extend( const ScSingleRefData
& rRef
, const ScAddress
& rPos
)
373 bool bInherit3D
= (Ref1
.IsFlag3D() && !Ref2
.IsFlag3D() && !rRef
.IsFlag3D());
374 ScRange aAbsRange
= toAbs(rPos
);
376 ScSingleRefData aRef
= rRef
;
377 // If no sheet was given in the extending part, let it point to the same
378 // sheet as this reference's end point, inheriting the absolute/relative
380 // [$]Sheet1.A5:A6:A7 on Sheet2 do still reference only Sheet1.
381 if (!rRef
.IsFlag3D())
384 aRef
.SetRelTab( Ref2
.Tab());
386 aRef
.SetAbsTab( Ref2
.Tab());
388 ScAddress aAbs
= aRef
.toAbs(rPos
);
390 if (aAbs
.Col() < aAbsRange
.aStart
.Col())
391 aAbsRange
.aStart
.SetCol(aAbs
.Col());
393 if (aAbs
.Row() < aAbsRange
.aStart
.Row())
394 aAbsRange
.aStart
.SetRow(aAbs
.Row());
396 if (aAbs
.Tab() < aAbsRange
.aStart
.Tab())
397 aAbsRange
.aStart
.SetTab(aAbs
.Tab());
399 if (aAbsRange
.aEnd
.Col() < aAbs
.Col())
400 aAbsRange
.aEnd
.SetCol(aAbs
.Col());
402 if (aAbsRange
.aEnd
.Row() < aAbs
.Row())
403 aAbsRange
.aEnd
.SetRow(aAbs
.Row());
405 if (aAbsRange
.aEnd
.Tab() < aAbs
.Tab())
406 aAbsRange
.aEnd
.SetTab(aAbs
.Tab());
408 // In Ref2 inherit absolute/relative addressing from the extending part.
409 // A$5:A5 => A$5:A$5:A5 => A$5:A5, and not A$5:A$5
410 // A$6:$A5 => A$6:A$6:$A5 => A5:$A$6
411 if (aAbsRange
.aEnd
.Col() == aAbs
.Col())
412 Ref2
.SetColRel( rRef
.IsColRel());
413 if (aAbsRange
.aEnd
.Row() == aAbs
.Row())
414 Ref2
.SetRowRel( rRef
.IsRowRel());
416 // In Ref1 inherit relative sheet from extending part if given.
417 if (aAbsRange
.aStart
.Tab() == aAbs
.Tab() && rRef
.IsFlag3D())
418 Ref1
.SetTabRel( rRef
.IsTabRel());
420 // In Ref2 inherit relative sheet from either Ref1 or extending part.
421 // Use the original 3D flags to determine which.
422 // $Sheet1.$A$5:$A$6 => $Sheet1.$A$5:$A$5:$A$6 => $Sheet1.$A$5:$A$6, and
423 // not $Sheet1.$A$5:Sheet1.$A$6 (with invisible second 3D, but relative).
424 if (aAbsRange
.aEnd
.Tab() == aAbs
.Tab())
425 Ref2
.SetTabRel( bInherit3D
? Ref1
.IsTabRel() : rRef
.IsTabRel());
427 // Force 3D flag in Ref1 if different sheet or more than one sheet
429 if (aAbsRange
.aStart
.Tab() != rPos
.Tab() || aAbsRange
.aStart
.Tab() != aAbsRange
.aEnd
.Tab())
430 Ref1
.SetFlag3D(true);
432 // Force 3D flag in Ref2 if more than one sheet referenced.
433 if (aAbsRange
.aStart
.Tab() != aAbsRange
.aEnd
.Tab())
434 Ref2
.SetFlag3D(true);
436 // Inherit 3D flag in Ref1 from extending part in case range wasn't
437 // extended as in A5:A5:Sheet1.A5 if on Sheet1.
439 Ref1
.SetFlag3D( true);
441 SetRange(aAbsRange
, rPos
);
446 ScComplexRefData
& ScComplexRefData::Extend( const ScComplexRefData
& rRef
, const ScAddress
& rPos
)
448 return Extend( rRef
.Ref1
, rPos
).Extend( rRef
.Ref2
, rPos
);
451 bool ScComplexRefData::Valid() const
453 return Ref1
.Valid() && Ref2
.Valid();
456 bool ScComplexRefData::ValidExternal() const
458 return Ref1
.ValidExternal() && Ref2
.ColValid() && Ref2
.RowValid() && Ref1
.Tab() <= Ref2
.Tab();
461 ScRange
ScComplexRefData::toAbs( const ScAddress
& rPos
) const
463 return ScRange(Ref1
.toAbs(rPos
), Ref2
.toAbs(rPos
));
466 void ScComplexRefData::SetRange( const ScRange
& rRange
, const ScAddress
& rPos
)
468 Ref1
.SetAddress(rRange
.aStart
, rPos
);
469 Ref2
.SetAddress(rRange
.aEnd
, rPos
);
472 void ScComplexRefData::PutInOrder( const ScAddress
& rPos
)
474 ScSingleRefData::PutInOrder( Ref1
, Ref2
, rPos
);
477 #if DEBUG_FORMULA_COMPILER
478 void ScComplexRefData::Dump( int nIndent
) const
481 for (int i
= 0; i
< nIndent
; ++i
)
484 cout
<< aIndent
<< "ref 1" << endl
;
485 Ref1
.Dump(nIndent
+1);
486 cout
<< aIndent
<< "ref 2" << endl
;
487 Ref2
.Dump(nIndent
+1);
491 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */