Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sc / inc / address.hxx
blob37a401ef01949a2b3bf9d4564a62b205c8d17b4a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
2 /*
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 #ifndef INCLUDED_SC_INC_ADDRESS_HXX
21 #define INCLUDED_SC_INC_ADDRESS_HXX
23 #include <rtl/ustrbuf.hxx>
24 #include <rtl/strbuf.hxx>
26 #include <array>
27 #include <limits>
28 #include <ostream>
30 #include "scdllapi.h"
31 #include "types.hxx"
32 #include <formula/grammar.hxx>
34 #include <o3tl/typed_flags_set.hxx>
35 #include <com/sun/star/uno/Sequence.hxx>
37 namespace com { namespace sun { namespace star {
38 namespace sheet {
39 struct ExternalLinkInfo;
41 }}}
43 class ScDocument;
45 /** size_t typedef to be able to find places where code was changed from USHORT
46 to size_t and is used to read/write from/to streams. */
47 typedef size_t SCSIZE;
49 // Maximum possible value of data type, NOT maximum row value.
50 // MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is
51 // included, we should not be using those stupid macros anyway.
52 #undef min
53 #undef max
54 const SCROW SCROW_MAX = ::std::numeric_limits<SCROW>::max();
55 const SCCOL SCCOL_MAX = ::std::numeric_limits<SCCOL>::max();
56 const SCTAB SCTAB_MAX = ::std::numeric_limits<SCTAB>::max();
57 const SCCOLROW SCCOLROW_MAX = ::std::numeric_limits<SCCOLROW>::max();
58 const SCSIZE SCSIZE_MAX = ::std::numeric_limits<SCSIZE>::max();
60 // The maximum values. Defines are needed for preprocessor checks, for example
61 // in bcaslot.cxx, otherwise type safe constants are preferred.
62 #define MAXROWCOUNT_DEFINE 1048576
63 #define MAXCOLCOUNT_DEFINE 1024
65 // Count values
66 const SCROW MAXROWCOUNT = MAXROWCOUNT_DEFINE;
67 const SCCOL MAXCOLCOUNT = MAXCOLCOUNT_DEFINE;
68 /// limiting to 10000 for now, problem with 32 bit builds for now
69 const SCTAB MAXTABCOUNT = 10000;
70 const SCCOLROW MAXCOLROWCOUNT = MAXROWCOUNT;
71 // Maximum values
72 const SCROW MAXROW = MAXROWCOUNT - 1;
73 const SCCOL MAXCOL = MAXCOLCOUNT - 1;
74 const SCTAB MAXTAB = MAXTABCOUNT - 1;
75 const SCCOLROW MAXCOLROW = MAXROW;
76 // Maximun tiled rendering values
77 const SCROW MAXTILEDROW = 500000;
78 // Limit the initial tab count to prevent users to set the count too high,
79 // which could cause the memory usage of blank documents to exceed the
80 // available system memory.
81 const SCTAB MAXINITTAB = 1024;
82 const SCTAB MININITTAB = 1;
84 // Special values
85 const SCTAB SC_TAB_APPEND = SCTAB_MAX;
86 const SCTAB TABLEID_DOC = SCTAB_MAX; // entire document, e.g. protect
87 const SCROW SCROWS32K = 32000;
88 const SCCOL SCCOL_REPEAT_NONE = SCCOL_MAX;
89 const SCROW SCROW_REPEAT_NONE = SCROW_MAX;
91 #define MAXROW_30 8191
93 SAL_WARN_UNUSED_RESULT inline bool ValidCol( SCCOL nCol )
95 return nCol >= 0 && nCol <= MAXCOL;
98 SAL_WARN_UNUSED_RESULT inline bool ValidRow( SCROW nRow )
100 return nRow >= 0 && nRow <= MAXROW;
103 SAL_WARN_UNUSED_RESULT inline bool ValidTab( SCTAB nTab )
105 return nTab >= 0 && nTab <= MAXTAB;
108 SAL_WARN_UNUSED_RESULT inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
110 return nTab >= 0 && nTab <= nMaxTab;
113 SAL_WARN_UNUSED_RESULT inline bool ValidColRow( SCCOL nCol, SCROW nRow )
115 return ValidCol( nCol) && ValidRow( nRow);
118 SAL_WARN_UNUSED_RESULT inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab )
120 return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab);
123 SAL_WARN_UNUSED_RESULT inline SCCOL SanitizeCol( SCCOL nCol )
125 return nCol < 0 ? 0 : std::min(nCol, MAXCOL);
128 SAL_WARN_UNUSED_RESULT inline SCROW SanitizeRow( SCROW nRow )
130 return nRow < 0 ? 0 : std::min(nRow, MAXROW);
133 SAL_WARN_UNUSED_RESULT inline SCTAB SanitizeTab( SCTAB nTab )
135 return nTab < 0 ? 0 : std::min(nTab, MAXTAB);
138 // The result of ConvertRef() is a bit group of the following:
139 enum class ScRefFlags : sal_uInt16
141 ZERO = 0x0000,
142 COL_ABS = 0x0001,
143 ROW_ABS = 0x0002,
144 TAB_ABS = 0x0004,
145 TAB_3D = 0x0008,
146 COL2_ABS = 0x0010,
147 ROW2_ABS = 0x0020,
148 TAB2_ABS = 0x0040,
149 TAB2_3D = 0x0080,
150 ROW_VALID = 0x0100,
151 COL_VALID = 0x0200,
152 TAB_VALID = 0x0400,
153 // BITS for convenience
154 BITS = COL_ABS | ROW_ABS | TAB_ABS | TAB_3D
155 | ROW_VALID | COL_VALID | TAB_VALID,
156 // somewhat cheesy kludge to force the display of the document name even for
157 // local references. Requires TAB_3D to be valid
158 FORCE_DOC = 0x0800,
159 ROW2_VALID = 0x1000,
160 COL2_VALID = 0x2000,
161 TAB2_VALID = 0x4000,
162 VALID = 0x8000,
164 TAB_ABS_3D = TAB_ABS | TAB_3D,
166 ADDR_ABS = VALID | COL_ABS | ROW_ABS | TAB_ABS,
168 RANGE_ABS = ADDR_ABS | COL2_ABS | ROW2_ABS | TAB2_ABS,
170 ADDR_ABS_3D = ADDR_ABS | TAB_3D,
171 RANGE_ABS_3D = RANGE_ABS | TAB_3D
174 namespace o3tl
176 template<> struct typed_flags<ScRefFlags> : is_typed_flags<ScRefFlags, 0xffff> {};
178 inline void applyStartToEndFlags(ScRefFlags &target,const ScRefFlags source)
180 target |= ScRefFlags(static_cast<std::underlying_type<ScRefFlags>::type>(source) << 4);
182 inline void applyStartToEndFlags(ScRefFlags &target)
184 target |= ScRefFlags(static_cast<std::underlying_type<ScRefFlags>::type>(target) << 4);
187 // ScAddress
188 class SAL_WARN_UNUSED ScAddress
190 private:
191 // Even if the fields are in the order "row, column, tab", in all (?) the ScAddress and
192 // ScDocument APIs that take separate row, column, and tab parameters, the parameters are in the
193 // order "column, row, tab", which matches the most common (A1) address syntax, if you ignore
194 // the sheet (tab). Don't let this confuse you, like it confused me for a while.
196 SCROW nRow;
197 SCCOL nCol;
198 SCTAB nTab;
200 public:
202 enum Uninitialized { UNINITIALIZED };
203 enum InitializeInvalid { INITIALIZE_INVALID };
205 struct Details
207 formula::FormulaGrammar::AddressConvention eConv;
208 SCROW nRow;
209 SCCOL nCol;
211 Details( formula::FormulaGrammar::AddressConvention eConvP, SCROW nRowP, SCCOL nColP ) :
212 eConv(eConvP), nRow(nRowP), nCol(nColP)
214 Details( formula::FormulaGrammar::AddressConvention eConvP, ScAddress const & rAddr ) :
215 eConv(eConvP), nRow(rAddr.Row()), nCol(rAddr.Col())
217 Details( formula::FormulaGrammar::AddressConvention eConvP) :
218 eConv(eConvP), nRow(0), nCol(0)
220 /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
221 Details( const ScDocument* pDoc, const ScAddress & rAddr );
223 SC_DLLPUBLIC static const Details detailsOOOa1;
225 struct ExternalInfo
227 OUString maTabName;
228 sal_uInt16 mnFileId;
229 bool mbExternal;
231 ExternalInfo() :
232 mnFileId(0), mbExternal(false)
236 ScAddress() :
237 nRow(0), nCol(0), nTab(0)
239 ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) :
240 nRow(nRowP), nCol(nColP), nTab(nTabP)
242 /** Yes, it is what it seems to be: Uninitialized. May be used for
243 performance reasons if it is initialized by other means. */
244 ScAddress( Uninitialized )
246 ScAddress( InitializeInvalid ) :
247 nRow(-1), nCol(-1), nTab(-1)
249 ScAddress( const ScAddress& rAddress ) :
250 nRow(rAddress.nRow), nCol(rAddress.nCol), nTab(rAddress.nTab)
252 inline ScAddress& operator=( const ScAddress& rAddress );
254 inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
256 SCROW Row() const
258 return nRow;
261 SCCOL Col() const
263 return nCol;
265 SCTAB Tab() const
267 return nTab;
269 void SetRow( SCROW nRowP )
271 nRow = nRowP;
273 void SetCol( SCCOL nColP )
275 nCol = nColP;
277 void SetTab( SCTAB nTabP )
279 nTab = nTabP;
281 void SetInvalid()
283 nRow = -1;
284 nCol = -1;
285 nTab = -1;
287 bool IsValid() const
289 return (nRow >= 0) && (nCol >= 0) && (nTab >= 0);
292 inline void PutInOrder( ScAddress& rAddress );
294 void IncRow( SCROW nDelta = 1 )
296 nRow = sal::static_int_cast<SCROW>(nRow + nDelta);
298 void IncCol( SCCOL nDelta = 1 )
300 nCol = sal::static_int_cast<SCCOL>(nCol + nDelta);
302 void IncTab( SCTAB nDelta = 1 )
304 nTab = sal::static_int_cast<SCTAB>(nTab + nDelta);
306 void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
308 nColP = nCol;
309 nRowP = nRow;
310 nTabP = nTab;
314 @param pSheetEndPos
315 If given and Parse() successfully parsed a sheet name it returns
316 the end position (exclusive) behind the sheet name AND a
317 following sheet name separator. This independent of whether the
318 resulting reference is fully valid or not.
320 SC_DLLPUBLIC ScRefFlags Parse(
321 const OUString&, const ScDocument* = nullptr,
322 const Details& rDetails = detailsOOOa1,
323 ExternalInfo* pExtInfo = nullptr,
324 const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
325 sal_Int32* pSheetEndPos = nullptr,
326 const OUString* pErrRef = nullptr );
328 SC_DLLPUBLIC void Format( OStringBuffer& r, ScRefFlags nFlags,
329 const ScDocument* pDocument = nullptr,
330 const Details& rDetails = detailsOOOa1) const;
332 SC_DLLPUBLIC OUString Format( ScRefFlags nFlags,
333 const ScDocument* pDocument = nullptr,
334 const Details& rDetails = detailsOOOa1) const;
337 @param rErrorPos
338 If FALSE is returned, the positions contain <0 or >MAX...
339 values if shifted out of bounds.
340 @param pDocument
341 The document for the maximum defined sheet number.
343 SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool Move( SCCOL nDeltaX, SCROW nDeltaY, SCTAB nDeltaZ,
344 ScAddress& rErrorPos, const ScDocument* pDocument = nullptr );
346 inline bool operator==( const ScAddress& rAddress ) const;
347 inline bool operator!=( const ScAddress& rAddress ) const;
348 inline bool operator<( const ScAddress& rAddress ) const;
349 inline bool operator<=( const ScAddress& rAddress ) const;
350 inline bool lessThanByRow( const ScAddress& rAddress ) const;
352 inline size_t hash() const;
355 * Create a human-readable string representation of the cell address. You
356 * cannot specify precise formatting with this method; use Format() if you
357 * need to specify how the address needs to be formatted.
359 * The address string does not display sheet name.
361 * @return human-readable string representation of the cell address.
363 OUString GetColRowString() const;
366 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
367 template<typename charT, typename traits>
368 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScAddress& rAddress)
370 stream <<
371 rAddress.Tab()+1 << "!"
372 "R" << rAddress.Row()+1 <<
373 "C" << rAddress.Col()+1;
375 return stream;
378 inline void ScAddress::PutInOrder( ScAddress& rAddress )
380 if ( rAddress.Col() < Col() )
382 SCCOL nTmp = rAddress.Col();
383 rAddress.SetCol( Col() );
384 SetCol( nTmp );
386 if ( rAddress.Row() < Row() )
388 SCROW nTmp = rAddress.Row();
389 rAddress.SetRow( Row() );
390 SetRow( nTmp );
392 if ( rAddress.Tab() < Tab() )
394 SCTAB nTmp = rAddress.Tab();
395 rAddress.SetTab( Tab() );
396 SetTab( nTmp );
400 inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
402 nCol = nColP;
403 nRow = nRowP;
404 nTab = nTabP;
407 inline ScAddress& ScAddress::operator=( const ScAddress& rAddress )
409 nCol = rAddress.nCol;
410 nRow = rAddress.nRow;
411 nTab = rAddress.nTab;
412 return *this;
415 inline bool ScAddress::operator==( const ScAddress& rAddress ) const
417 return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == rAddress.nTab;
420 inline bool ScAddress::operator!=( const ScAddress& rAddress ) const
422 return !operator==( rAddress );
425 /** Less than ordered by tab,col,row. */
426 inline bool ScAddress::operator<( const ScAddress& rAddress ) const
428 if (nTab == rAddress.nTab)
430 if (nCol == rAddress.nCol)
431 return nRow < rAddress.nRow;
432 else
433 return nCol < rAddress.nCol;
435 else
436 return nTab < rAddress.nTab;
439 inline bool ScAddress::operator<=( const ScAddress& rAddress ) const
441 return operator<( rAddress ) || operator==( rAddress );
444 /** Less than ordered by tab,row,col as needed by row-wise import/export */
445 inline bool ScAddress::lessThanByRow( const ScAddress& rAddress ) const
447 if (nTab == rAddress.nTab)
449 if (nRow == rAddress.nRow)
450 return nCol < rAddress.nCol;
451 else
452 return nRow < rAddress.nRow;
454 else
455 return nTab < rAddress.nTab;
458 inline size_t ScAddress::hash() const
460 // Assume that there are not that many addresses with row > 2^16 AND column
461 // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
462 if (nRow <= 0xffff)
463 return (static_cast<size_t>(nTab) << 24) ^
464 (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
465 else
466 return (static_cast<size_t>(nTab) << 28) ^
467 (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
470 struct ScAddressHashFunctor
472 size_t operator()( const ScAddress & rAddress ) const
474 return rAddress.hash();
478 inline bool ValidAddress( const ScAddress& rAddress )
480 return ValidCol(rAddress.Col()) && ValidRow(rAddress.Row()) && ValidTab(rAddress.Tab());
483 // ScRange
484 class SAL_WARN_UNUSED ScRange final
486 public:
487 ScAddress aStart;
488 ScAddress aEnd;
490 ScRange() :
491 aStart(), aEnd()
494 ScRange( ScAddress::Uninitialized eUninitialized ) :
495 aStart( eUninitialized ), aEnd( eUninitialized )
497 ScRange( ScAddress::InitializeInvalid eInvalid ) :
498 aStart( eInvalid ), aEnd( eInvalid )
500 ScRange( const ScAddress& aInputStart, const ScAddress& aInputEnd ) :
501 aStart( aInputStart ), aEnd( aInputEnd )
503 aStart.PutInOrder( aEnd );
505 ScRange( const ScRange& rRange ) :
506 aStart( rRange.aStart ), aEnd( rRange.aEnd )
508 ScRange( const ScAddress& rRange ) :
509 aStart( rRange ), aEnd( rRange )
511 ScRange( SCCOL nCol, SCROW nRow, SCTAB nTab ) :
512 aStart( nCol, nRow, nTab ), aEnd( aStart )
514 ScRange( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) :
515 aStart( nCol1, nRow1, nTab1 ), aEnd( nCol2, nRow2, nTab2 )
518 ScRange& operator=( const ScRange& rRange )
520 aStart = rRange.aStart;
521 aEnd = rRange.aEnd;
522 return *this;
524 ScRange& operator=( const ScAddress& rPos )
526 aStart = aEnd = rPos;
527 return *this;
529 void SetInvalid()
531 aStart.SetInvalid();
532 aEnd.SetInvalid();
534 bool IsValid() const
536 return aStart.IsValid() && aEnd.IsValid();
538 inline bool In( const ScAddress& ) const; ///< is Address& in Range?
539 inline bool In( const ScRange& ) const; ///< is Range& in Range?
541 SC_DLLPUBLIC ScRefFlags Parse( const OUString&, const ScDocument* = nullptr,
542 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
543 ScAddress::ExternalInfo* pExtInfo = nullptr,
544 const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
545 const OUString* pErrRef = nullptr );
547 SC_DLLPUBLIC ScRefFlags ParseAny( const OUString&, const ScDocument*,
548 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
549 SC_DLLPUBLIC ScRefFlags ParseCols( const OUString&,
550 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
551 SC_DLLPUBLIC void ParseRows( const OUString&,
552 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
554 /** Parse an Excel style reference up to and including the sheet name
555 separator '!', including detection of external documents and sheet
556 names, and in case of MOOXML import the bracketed index is used to
557 determine the actual document name passed in pExternalLinks. For
558 internal references (resulting rExternDocName empty), aStart.nTab and
559 aEnd.nTab are set, or -1 if sheet name not found.
560 @param bOnlyAcceptSingle If <TRUE/>, a 3D reference (Sheet1:Sheet2)
561 encountered results in an error (NULL returned).
562 @param pExternalLinks pointer to ExternalLinkInfo sequence, may be
563 NULL for non-filter usage, in which case indices such as [1] are
564 not resolved.
565 @param pErrRef pointer to "#REF!" string if to be accepted.
566 @returns
567 Pointer to the position after '!' if successfully parsed, and
568 rExternDocName, rStartTabName and/or rEndTabName filled if
569 applicable. ScRefFlags::... flags set in nFlags.
570 Or if no valid document and/or sheet header could be parsed the start
571 position passed with pString.
572 Or NULL if a 3D sheet header could be parsed but
573 bOnlyAcceptSingle==true was given.
575 const sal_Unicode* Parse_XL_Header( const sal_Unicode* pString, const ScDocument* pDocument,
576 OUString& rExternDocName, OUString& rStartTabName,
577 OUString& rEndTabName, ScRefFlags& nFlags,
578 bool bOnlyAcceptSingle,
579 const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
580 const OUString* pErrRef = nullptr );
582 /** Returns string with formatted cell range from aStart to aEnd,
583 according to provided address convention.
584 @param nFlags
585 Cell reference flags
586 @param pDocument
587 Pointer to document which is used for example to get tab names.
588 @param rDetails
589 Provide information about required address convention.
590 Supported address conventions are:
591 CONV_OOO 'doc'#sheet.A1:sheet2.B2
592 CONV_XL_A1, [doc]sheet:sheet2!A1:B2
593 CONV_XL_OOX, [#]sheet:sheet2!A1:B2
594 CONV_XL_R1C1, [doc]sheet:sheet2!R1C1:R2C2
595 @param bFullAddressNotation
596 If TRUE, the full address notation will be used.
597 For example in case all columns are used, "A1:AMJ177" is full address notation
598 and "1:177" is shortened address notation.
599 @returns
600 String contains formatted cell range in address convention
602 SC_DLLPUBLIC OUString Format( ScRefFlags nFlags = ScRefFlags::ZERO,
603 const ScDocument* pDocument = nullptr,
604 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
605 bool bFullAddressNotation = false ) const;
607 inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
608 SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
609 SC_DLLPUBLIC void PutInOrder();
612 @param rErrorRange
613 If FALSE is returned, the positions contain <0 or >MAX...
614 values if shifted out of bounds.
615 @param pDocument
616 The document for the maximum defined sheet number.
618 SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool Move( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
619 ScRange& rErrorRange, const ScDocument* pDocument = nullptr );
621 /** Same as Move() but with sticky end col/row anchors. */
622 SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT bool MoveSticky( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
623 ScRange& rErrorRange );
625 SC_DLLPUBLIC void IncColIfNotLessThan(SCCOL nStartCol, SCCOL nOffset);
626 SC_DLLPUBLIC void IncRowIfNotLessThan(SCROW nStartRow, SCROW nOffset);
628 SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
629 SC_DLLPUBLIC bool Intersects( const ScRange& rRange ) const; // do two ranges intersect?
631 ScRange Intersection( const ScRange& rOther ) const;
633 /// If maximum end column should not be adapted during reference update.
634 inline bool IsEndColSticky() const;
635 /// If maximum end row should not be adapted during reference update.
636 inline bool IsEndRowSticky() const;
638 /** Increment or decrement end column unless sticky or until it becomes
639 sticky. Checks if the range encompasses at least two columns so should
640 be called before adjusting the start column. */
641 void IncEndColSticky( SCCOL nDelta );
643 /** Increment or decrement end row unless sticky or until it becomes
644 sticky. Checks if the range encompasses at least two rows so should
645 be called before adjusting the start row. */
646 void IncEndRowSticky( SCROW nDelta );
648 inline bool operator==( const ScRange& rRange ) const;
649 inline bool operator!=( const ScRange& rRange ) const;
650 inline bool operator<( const ScRange& rRange ) const;
651 inline bool operator<=( const ScRange& rRange ) const;
653 /// Hash 2D area ignoring table number.
654 inline size_t hashArea() const;
655 /// Hash start column and start and end rows.
656 inline size_t hashStartColumn() const;
659 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
660 template<typename charT, typename traits>
661 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScRange& rRange)
663 stream << rRange.aStart;
664 if (rRange.aEnd != rRange.aStart)
666 stream << ":";
667 if (rRange.aEnd.Tab() != rRange.aStart.Tab())
668 stream << rRange.aEnd;
669 else
670 stream <<
671 "R" << rRange.aEnd.Row()+1 <<
672 "C" << rRange.aEnd.Col()+1;
675 return stream;
678 inline void ScRange::GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
679 SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const
681 aStart.GetVars( nCol1, nRow1, nTab1 );
682 aEnd.GetVars( nCol2, nRow2, nTab2 );
685 inline bool ScRange::IsEndColSticky() const
687 // Only in an actual column range, i.e. not if both columns are MAXCOL.
688 return aEnd.Col() == MAXCOL && aStart.Col() < aEnd.Col();
691 inline bool ScRange::IsEndRowSticky() const
693 // Only in an actual row range, i.e. not if both rows are MAXROW.
694 return aEnd.Row() == MAXROW && aStart.Row() < aEnd.Row();
697 inline bool ScRange::operator==( const ScRange& rRange ) const
699 return ( (aStart == rRange.aStart) && (aEnd == rRange.aEnd) );
702 inline bool ScRange::operator!=( const ScRange& rRange ) const
704 return !operator==( rRange );
707 /// Sort on upper left corner tab,col,row, if equal then use lower right too.
708 inline bool ScRange::operator<( const ScRange& r ) const
710 return aStart < r.aStart || (aStart == r.aStart && aEnd < r.aEnd) ;
713 inline bool ScRange::operator<=( const ScRange& rRange ) const
715 return operator<( rRange ) || operator==( rRange );
718 inline bool ScRange::In( const ScAddress& rAddress ) const
720 return
721 aStart.Col() <= rAddress.Col() && rAddress.Col() <= aEnd.Col() &&
722 aStart.Row() <= rAddress.Row() && rAddress.Row() <= aEnd.Row() &&
723 aStart.Tab() <= rAddress.Tab() && rAddress.Tab() <= aEnd.Tab();
726 inline bool ScRange::In( const ScRange& rRange ) const
728 return
729 aStart.Col() <= rRange.aStart.Col() && rRange.aEnd.Col() <= aEnd.Col() &&
730 aStart.Row() <= rRange.aStart.Row() && rRange.aEnd.Row() <= aEnd.Row() &&
731 aStart.Tab() <= rRange.aStart.Tab() && rRange.aEnd.Tab() <= aEnd.Tab();
734 inline size_t ScRange::hashArea() const
736 // Assume that there are not that many ranges with identical corners so we
737 // won't have too many collisions. Also assume that more lower row and
738 // column numbers are used so that there are not too many conflicts with
739 // the columns hashed into the values, and that start row and column
740 // usually don't exceed certain values. High bits are not masked off and
741 // may overlap with lower bits of other values, e.g. if start column is
742 // greater than assumed.
743 return
744 (static_cast<size_t>(aStart.Row()) << 26) ^ // start row <= 2^6
745 (static_cast<size_t>(aStart.Col()) << 21) ^ // start column <= 2^5
746 (static_cast<size_t>(aEnd.Col()) << 15) ^ // end column <= 2^6
747 static_cast<size_t>(aEnd.Row()); // end row <= 2^15
750 inline size_t ScRange::hashStartColumn() const
752 // Assume that for the start row more lower row numbers are used so that
753 // there are not too many conflicts with the column hashed into the higher
754 // values.
755 return
756 (static_cast<size_t>(aStart.Col()) << 24) ^ // start column <= 2^8
757 (static_cast<size_t>(aStart.Row()) << 16) ^ // start row <= 2^8
758 static_cast<size_t>(aEnd.Row());
761 inline bool ValidRange( const ScRange& rRange )
763 return ValidAddress(rRange.aStart) && ValidAddress(rRange.aEnd);
766 // ScRangePair
767 class SAL_WARN_UNUSED ScRangePair final
769 private:
770 std::array<ScRange,2> aRange;
772 public:
773 ScRangePair( const ScRangePair& r )
775 aRange[0] = r.aRange[0];
776 aRange[1] = r.aRange[1];
778 ScRangePair( const ScRange& rRange1, const ScRange& rRange2 )
780 aRange[0] = rRange1;
781 aRange[1] = rRange2;
784 inline ScRangePair& operator= ( const ScRangePair& rRange );
785 const ScRange& GetRange( sal_uInt16 n ) const
787 return aRange[n];
789 ScRange& GetRange( sal_uInt16 n )
791 return aRange[n];
795 inline ScRangePair& ScRangePair::operator= ( const ScRangePair& rRange )
797 aRange[0] = rRange.aRange[0];
798 aRange[1] = rRange.aRange[1];
799 return *this;
802 // ScRefAddress
803 class SAL_WARN_UNUSED ScRefAddress
805 private:
806 ScAddress aAdr;
807 bool bRelCol;
808 bool bRelRow;
809 bool bRelTab;
810 public:
811 ScRefAddress() :
812 bRelCol(false), bRelRow(false), bRelTab(false)
814 ScRefAddress( SCCOL nCol, SCROW nRow, SCTAB nTab ) :
815 aAdr(nCol, nRow, nTab),
816 bRelCol(false), bRelRow(false), bRelTab(false)
818 ScRefAddress( const ScRefAddress& rRef ) :
819 aAdr(rRef.aAdr), bRelCol(rRef.bRelCol), bRelRow(rRef.bRelRow),
820 bRelTab(rRef.bRelTab)
823 inline ScRefAddress& operator=( const ScRefAddress& );
825 bool IsRelCol() const
827 return bRelCol;
829 bool IsRelRow() const
831 return bRelRow;
833 bool IsRelTab() const
835 return bRelTab;
838 void SetRelCol(bool bNewRelCol)
840 bRelCol = bNewRelCol;
842 void SetRelRow(bool bNewRelRow)
844 bRelRow = bNewRelRow;
846 void SetRelTab(bool bNewRelTab)
848 bRelTab = bNewRelTab;
851 inline void Set( const ScAddress& rAdr,
852 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
853 inline void Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
854 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
856 const ScAddress& GetAddress() const
858 return aAdr;
861 SCCOL Col() const
863 return aAdr.Col();
865 SCROW Row() const
867 return aAdr.Row();
869 SCTAB Tab() const
871 return aAdr.Tab();
874 inline bool operator == ( const ScRefAddress& r ) const;
876 OUString GetRefString( const ScDocument* pDocument, SCTAB nActTab,
877 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1) const;
880 inline ScRefAddress& ScRefAddress::operator=( const ScRefAddress& rRef )
882 aAdr = rRef.aAdr;
883 bRelCol = rRef.bRelCol;
884 bRelRow = rRef.bRelRow;
885 bRelTab = rRef.bRelTab;
886 return *this;
889 inline void ScRefAddress::Set( const ScAddress& rAdr,
890 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
892 aAdr = rAdr;
893 bRelCol = bNewRelCol;
894 bRelRow = bNewRelRow;
895 bRelTab = bNewRelTab;
898 inline void ScRefAddress::Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
899 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
901 aAdr.Set( nNewCol, nNewRow, nNewTab);
902 bRelCol = bNewRelCol;
903 bRelRow = bNewRelRow;
904 bRelTab = bNewRelTab;
907 inline bool ScRefAddress::operator==( const ScRefAddress& rRefAddress ) const
909 return aAdr == rRefAddress.aAdr &&
910 bRelCol == rRefAddress.bRelCol &&
911 bRelRow == rRefAddress.bRelRow &&
912 bRelTab == rRefAddress.bRelTab;
915 // Global functions
917 // Special values for cells always broadcasting or listening (ScRecalcMode::ALWAYS
918 // and the like).
919 #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
920 #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
922 template< typename T > void PutInOrder( T& nStart, T& nEnd )
924 if (nEnd < nStart)
926 std::swap(nStart, nEnd);
930 bool ConvertSingleRef( const ScDocument* pDocument, const OUString& rRefString,
931 SCTAB nDefTab, ScRefAddress& rRefAddress,
932 const ScAddress::Details& rDetails,
933 ScAddress::ExternalInfo* pExtInfo = nullptr );
935 bool ConvertDoubleRef( const ScDocument* pDocument, const OUString& rRefString,
936 SCTAB nDefTab, ScRefAddress& rStartRefAddress,
937 ScRefAddress& rEndRefAddress,
938 const ScAddress::Details& rDetails,
939 ScAddress::ExternalInfo* pExtInfo = nullptr );
941 /// append alpha representation of column to buffer
942 SC_DLLPUBLIC void ScColToAlpha( OUStringBuffer& rBuffer, SCCOL nCol);
944 inline void ScColToAlpha( OUString& rStr, SCCOL nCol)
946 OUStringBuffer aBuf(2);
947 ScColToAlpha( aBuf, nCol);
948 rStr += aBuf.makeStringAndClear();
951 inline OUString ScColToAlpha( SCCOL nCol )
953 OUStringBuffer aBuf(2);
954 ScColToAlpha( aBuf, nCol);
955 return aBuf.makeStringAndClear();
958 /// get column number of A..IV... string
959 bool AlphaToCol( SCCOL& rCol, const OUString& rStr);
961 #endif // INCLUDED_SC_INC_ADDRESS_HXX
963 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */