1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
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>
32 #include <formula/grammar.hxx>
34 #include <o3tl/typed_flags_set.hxx>
35 #include <o3tl/underlyingenumvalue.hxx>
37 namespace com::sun::star
{
39 struct ExternalLinkInfo
;
43 namespace com::sun::star::uno
{ template <typename
> class Sequence
; }
47 /** size_t typedef to be able to find places where code was changed from USHORT
48 to size_t and is used to read/write from/to streams. */
49 typedef size_t SCSIZE
;
51 // Maximum possible value of data type, NOT maximum row value.
52 // MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is
53 // included, we should not be using those stupid macros anyway.
56 const SCROW SCROW_MAX
= ::std::numeric_limits
<SCROW
>::max();
57 const SCCOL SCCOL_MAX
= ::std::numeric_limits
<SCCOL
>::max();
58 const SCTAB SCTAB_MAX
= ::std::numeric_limits
<SCTAB
>::max();
59 const SCCOLROW SCCOLROW_MAX
= ::std::numeric_limits
<SCCOLROW
>::max();
60 const SCSIZE SCSIZE_MAX
= ::std::numeric_limits
<SCSIZE
>::max();
63 const SCROW MAXROWCOUNT
= 1048576;
64 const SCCOL MAXCOLCOUNT
= 1024;
65 const SCCOL INITIALCOLCOUNT
= 64; // initial number of columns we allocate memory for
66 /// limiting to 10000 for now, problem with 32 bit builds for now
67 const SCTAB MAXTABCOUNT
= 10000;
69 const SCROW MAXROW
= MAXROWCOUNT
- 1;
70 const SCCOL MAXCOL
= MAXCOLCOUNT
- 1;
71 const SCTAB MAXTAB
= MAXTABCOUNT
- 1;
72 const SCCOLROW MAXCOLROW
= MAXROW
;
73 const SCROW MAXROW_JUMBO
= 16 * 1000 * 1000 - 1;
74 const SCCOL MAXCOL_JUMBO
= 16384 - 1;
75 // Maximum tiled rendering values
76 const SCROW MAXTILEDROW
= 500000;
77 // Limit the initial tab count to prevent users to set the count too high,
78 // which could cause the memory usage of blank documents to exceed the
79 // available system memory.
80 const SCTAB MAXINITTAB
= 1024;
81 const SCTAB MININITTAB
= 1;
84 const SCTAB SC_TAB_APPEND
= SCTAB_MAX
;
85 const SCTAB TABLEID_DOC
= SCTAB_MAX
; // entire document, e.g. protect
86 const SCROW SCROWS32K
= 32000; // for fuzzing
87 const SCCOL SCCOL_REPEAT_NONE
= SCCOL_MAX
;
88 const SCROW SCROW_REPEAT_NONE
= SCROW_MAX
;
89 const SCCOL SC_TABSTART_NONE
= SCCOL_MAX
;
91 const SCROW MAXROW_30
= 8191;
93 [[nodiscard
]] inline bool ValidCol( SCCOL nCol
, SCCOL nMaxCol
)
95 assert(nMaxCol
== MAXCOL
|| nMaxCol
== MAXCOL_JUMBO
); // temporary to debug jumbo sheets work
96 return nCol
>= 0 && nCol
<= nMaxCol
;
99 [[nodiscard
]] inline bool ValidRow( SCROW nRow
, SCROW nMaxRow
)
101 assert(nMaxRow
== MAXROW
|| nMaxRow
== MAXROW_JUMBO
); // temporary to debug jumbo sheets work
102 return nRow
>= 0 && nRow
<= nMaxRow
;
105 [[nodiscard
]] inline bool ValidTab( SCTAB nTab
)
107 return nTab
>= 0 && nTab
<= MAXTAB
;
110 [[nodiscard
]] inline bool ValidTab( SCTAB nTab
, SCTAB nMaxTab
)
112 return nTab
>= 0 && nTab
<= nMaxTab
;
115 [[nodiscard
]] inline bool ValidColRow( SCCOL nCol
, SCROW nRow
, SCCOL nMaxCol
, SCROW nMaxRow
)
117 assert(nMaxRow
== MAXROW
|| nMaxRow
== MAXROW_JUMBO
); // temporary to debug jumbo sheets work
118 return ValidCol(nCol
,nMaxCol
) && ValidRow(nRow
,nMaxRow
);
121 [[nodiscard
]] inline bool ValidColRowTab( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, SCCOL nMaxCol
, SCROW nMaxRow
)
123 assert(nMaxRow
== MAXROW
|| nMaxRow
== MAXROW_JUMBO
); // temporary to debug jumbo sheets work
124 return ValidCol(nCol
,nMaxCol
) && ValidRow(nRow
,nMaxRow
) && ValidTab( nTab
);
127 [[nodiscard
]] inline SCCOL
SanitizeCol( SCCOL nCol
, SCCOL nMaxCol
)
129 assert(nMaxCol
== MAXCOL
|| nMaxCol
== MAXCOL_JUMBO
); // temporary to debug jumbo sheets work
130 return nCol
< 0 ? 0 : (nCol
> nMaxCol
? nMaxCol
: nCol
);
133 [[nodiscard
]] inline SCROW
SanitizeRow( SCROW nRow
, SCROW nMaxRow
)
135 assert(nMaxRow
== MAXROW
|| nMaxRow
== MAXROW_JUMBO
); // temporary to debug jumbo sheets work
136 return nRow
< 0 ? 0 : (nRow
> nMaxRow
? nMaxRow
: nRow
);
139 [[nodiscard
]] inline SCTAB
SanitizeTab( SCTAB nTab
)
141 return nTab
< 0 ? 0 : (nTab
> MAXTAB
? MAXTAB
: nTab
);
144 // The result of ConvertRef() is a bit group of the following:
145 enum class ScRefFlags
: sal_uInt16
159 // BITS for convenience
160 BITS
= COL_ABS
| ROW_ABS
| TAB_ABS
| TAB_3D
161 | ROW_VALID
| COL_VALID
| TAB_VALID
,
162 // somewhat cheesy kludge to force the display of the document name even for
163 // local references. Requires TAB_3D to be valid
170 TAB_ABS_3D
= TAB_ABS
| TAB_3D
,
172 ADDR_ABS
= VALID
| COL_ABS
| ROW_ABS
| TAB_ABS
,
174 RANGE_ABS
= ADDR_ABS
| COL2_ABS
| ROW2_ABS
| TAB2_ABS
,
176 ADDR_ABS_3D
= ADDR_ABS
| TAB_3D
,
177 RANGE_ABS_3D
= RANGE_ABS
| TAB_3D
182 template<> struct typed_flags
<ScRefFlags
> : is_typed_flags
<ScRefFlags
, 0xffff> {};
184 inline void applyStartToEndFlags(ScRefFlags
&target
,const ScRefFlags source
)
186 target
|= ScRefFlags(o3tl::underlyingEnumValue(source
) << 4);
188 inline void applyStartToEndFlags(ScRefFlags
&target
)
190 target
|= ScRefFlags(o3tl::underlyingEnumValue(target
) << 4);
194 class SAL_WARN_UNUSED ScAddress
197 // Even if the fields are in the order "row, column, tab", in all (?) the ScAddress and
198 // ScDocument APIs that take separate row, column, and tab parameters, the parameters are in the
199 // order "column, row, tab", which matches the most common (A1) address syntax, if you ignore
200 // the sheet (tab). Don't let this confuse you, like it confused me for a while.
208 enum Uninitialized
{ UNINITIALIZED
};
209 enum InitializeInvalid
{ INITIALIZE_INVALID
};
213 formula::FormulaGrammar::AddressConvention eConv
;
217 Details( formula::FormulaGrammar::AddressConvention eConvP
, SCROW nRowP
, SCCOL nColP
) :
218 eConv(eConvP
), nRow(nRowP
), nCol(nColP
)
220 Details( formula::FormulaGrammar::AddressConvention eConvP
, ScAddress
const & rAddr
) :
221 eConv(eConvP
), nRow(rAddr
.Row()), nCol(rAddr
.Col())
223 Details( formula::FormulaGrammar::AddressConvention eConvP
) :
224 eConv(eConvP
), nRow(0), nCol(0)
226 /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
227 Details( const ScDocument
& rDoc
, const ScAddress
& rAddr
);
229 SC_DLLPUBLIC
static const Details detailsOOOa1
;
238 mnFileId(0), mbExternal(false)
243 nRow(0), nCol(0), nTab(0)
245 ScAddress( SCCOL nColP
, SCROW nRowP
, SCTAB nTabP
) :
246 nRow(nRowP
), nCol(nColP
), nTab(nTabP
)
248 /** Yes, it is what it seems to be: Uninitialized. May be used for
249 performance reasons if it is initialized by other means. */
250 ScAddress( Uninitialized
)
252 ScAddress( InitializeInvalid
) :
253 nRow(-1), nCol(-1), nTab(-1)
255 ScAddress( const ScAddress
& rAddress
) :
256 nRow(rAddress
.nRow
), nCol(rAddress
.nCol
), nTab(rAddress
.nTab
)
258 inline ScAddress
& operator=( const ScAddress
& rAddress
);
260 inline void Set( SCCOL nCol
, SCROW nRow
, SCTAB nTab
);
275 void SetRow( SCROW nRowP
)
279 void SetCol( SCCOL nColP
)
283 void SetTab( SCTAB nTabP
)
295 return (nRow
>= 0) && (nCol
>= 0) && (nTab
>= 0);
298 inline void PutInOrder( ScAddress
& rAddress
);
300 void IncRow( SCROW nDelta
= 1 )
302 nRow
= sal::static_int_cast
<SCROW
>(nRow
+ nDelta
);
304 void IncCol( SCCOL nDelta
= 1 )
306 nCol
= sal::static_int_cast
<SCCOL
>(nCol
+ nDelta
);
308 void IncTab( SCTAB nDelta
= 1 )
310 nTab
= sal::static_int_cast
<SCTAB
>(nTab
+ nDelta
);
312 void GetVars( SCCOL
& nColP
, SCROW
& nRowP
, SCTAB
& nTabP
) const
321 If given and Parse() successfully parsed a sheet name it returns
322 the end position (exclusive) behind the sheet name AND a
323 following sheet name separator. This independent of whether the
324 resulting reference is fully valid or not.
326 SC_DLLPUBLIC ScRefFlags
Parse(
327 const OUString
&, const ScDocument
&,
328 const Details
& rDetails
= detailsOOOa1
,
329 ExternalInfo
* pExtInfo
= nullptr,
330 const css::uno::Sequence
<css::sheet::ExternalLinkInfo
>* pExternalLinks
= nullptr,
331 sal_Int32
* pSheetEndPos
= nullptr,
332 const OUString
* pErrRef
= nullptr );
334 SC_DLLPUBLIC
void Format( OStringBuffer
& r
, ScRefFlags nFlags
,
335 const ScDocument
* pDocument
= nullptr,
336 const Details
& rDetails
= detailsOOOa1
) const;
338 SC_DLLPUBLIC OUString
Format( ScRefFlags nFlags
,
339 const ScDocument
* pDocument
= nullptr,
340 const Details
& rDetails
= detailsOOOa1
) const;
344 If FALSE is returned, the positions contain <0 or >MAX...
345 values if shifted out of bounds.
347 The document for the maximum defined sheet number.
349 [[nodiscard
]] SC_DLLPUBLIC
bool Move( SCCOL nDeltaX
, SCROW nDeltaY
, SCTAB nDeltaZ
,
350 ScAddress
& rErrorPos
, const ScDocument
* pDocument
= nullptr );
352 inline bool operator==( const ScAddress
& rAddress
) const;
353 inline bool operator!=( const ScAddress
& rAddress
) const;
354 inline bool operator<( const ScAddress
& rAddress
) const;
355 inline bool operator<=( const ScAddress
& rAddress
) const;
356 inline bool lessThanByRow( const ScAddress
& rAddress
) const;
358 inline size_t hash() const;
361 * Create a human-readable string representation of the cell address. You
362 * cannot specify precise formatting with this method; use Format() if you
363 * need to specify how the address needs to be formatted.
365 * The address string does not display sheet name.
367 * @return human-readable string representation of the cell address.
369 OUString
GetColRowString() const;
372 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
373 template<typename charT
, typename traits
>
374 inline std::basic_ostream
<charT
, traits
> & operator <<(std::basic_ostream
<charT
, traits
> & stream
, const ScAddress
& rAddress
)
377 rAddress
.Tab()+1 << "!"
378 "R" << rAddress
.Row()+1 <<
379 "C" << rAddress
.Col()+1;
384 inline void ScAddress::PutInOrder( ScAddress
& rAddress
)
386 if ( rAddress
.Col() < Col() )
388 SCCOL nTmp
= rAddress
.Col();
389 rAddress
.SetCol( Col() );
392 if ( rAddress
.Row() < Row() )
394 SCROW nTmp
= rAddress
.Row();
395 rAddress
.SetRow( Row() );
398 if ( rAddress
.Tab() < Tab() )
400 SCTAB nTmp
= rAddress
.Tab();
401 rAddress
.SetTab( Tab() );
406 inline void ScAddress::Set( SCCOL nColP
, SCROW nRowP
, SCTAB nTabP
)
413 inline ScAddress
& ScAddress::operator=( const ScAddress
& rAddress
)
415 nCol
= rAddress
.nCol
;
416 nRow
= rAddress
.nRow
;
417 nTab
= rAddress
.nTab
;
421 inline bool ScAddress::operator==( const ScAddress
& rAddress
) const
423 return nRow
== rAddress
.nRow
&& nCol
== rAddress
.nCol
&& nTab
== rAddress
.nTab
;
426 inline bool ScAddress::operator!=( const ScAddress
& rAddress
) const
428 return !operator==( rAddress
);
431 /** Less than ordered by tab,col,row. */
432 inline bool ScAddress::operator<( const ScAddress
& rAddress
) const
434 if (nTab
== rAddress
.nTab
)
436 if (nCol
== rAddress
.nCol
)
437 return nRow
< rAddress
.nRow
;
439 return nCol
< rAddress
.nCol
;
442 return nTab
< rAddress
.nTab
;
445 inline bool ScAddress::operator<=( const ScAddress
& rAddress
) const
447 return operator<( rAddress
) || operator==( rAddress
);
450 /** Less than ordered by tab,row,col as needed by row-wise import/export */
451 inline bool ScAddress::lessThanByRow( const ScAddress
& rAddress
) const
453 if (nTab
== rAddress
.nTab
)
455 if (nRow
== rAddress
.nRow
)
456 return nCol
< rAddress
.nCol
;
458 return nRow
< rAddress
.nRow
;
461 return nTab
< rAddress
.nTab
;
464 inline size_t ScAddress::hash() const
466 #if SAL_TYPES_SIZEOFPOINTER == 8
467 // 16 bits for the columns, and 20 bits for the rows
468 return (static_cast<size_t>(nTab
) << 36) ^
469 (static_cast<size_t>(nCol
) << 20) ^
470 static_cast<size_t>(nRow
);
472 // Assume that there are not that many addresses with row > 2^16 AND column
473 // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
475 return (static_cast<size_t>(nTab
) << 24) ^
476 (static_cast<size_t>(nCol
) << 16) ^ static_cast<size_t>(nRow
);
478 return (static_cast<size_t>(nTab
) << 28) ^
479 (static_cast<size_t>(nCol
) << 24) ^ static_cast<size_t>(nRow
);
483 struct ScAddressHashFunctor
485 size_t operator()( const ScAddress
& rAddress
) const
487 return rAddress
.hash();
491 inline bool ValidAddress( const ScAddress
& rAddress
, SCCOL nMaxCol
= MAXCOL
, SCROW nMaxRow
= MAXROW
)
493 return ValidCol(rAddress
.Col(), nMaxCol
) && ValidRow(rAddress
.Row(), nMaxRow
) && ValidTab(rAddress
.Tab());
497 class SAL_WARN_UNUSED ScRange final
507 ScRange( ScAddress::Uninitialized eUninitialized
) :
508 aStart( eUninitialized
), aEnd( eUninitialized
)
510 ScRange( ScAddress::InitializeInvalid eInvalid
) :
511 aStart( eInvalid
), aEnd( eInvalid
)
513 ScRange( const ScAddress
& aInputStart
, const ScAddress
& aInputEnd
) :
514 aStart( aInputStart
), aEnd( aInputEnd
)
516 aStart
.PutInOrder( aEnd
);
518 ScRange( const ScRange
& rRange
) :
519 aStart( rRange
.aStart
), aEnd( rRange
.aEnd
)
521 ScRange( const ScAddress
& rRange
) :
522 aStart( rRange
), aEnd( rRange
)
524 ScRange( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) :
525 aStart( nCol
, nRow
, nTab
), aEnd( aStart
)
527 ScRange( SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
, SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
) :
528 aStart( nCol1
, nRow1
, nTab1
), aEnd( nCol2
, nRow2
, nTab2
)
531 ScRange
& operator=( const ScRange
& rRange
)
533 aStart
= rRange
.aStart
;
537 ScRange
& operator=( const ScAddress
& rPos
)
539 aStart
= aEnd
= rPos
;
549 return aStart
.IsValid() && aEnd
.IsValid();
551 inline bool In( const ScAddress
& ) const; ///< is Address& in Range?
552 inline bool In( const ScRange
& ) const; ///< is Range& in Range?
554 SC_DLLPUBLIC ScRefFlags
Parse( const OUString
&, const ScDocument
&,
555 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
,
556 ScAddress::ExternalInfo
* pExtInfo
= nullptr,
557 const css::uno::Sequence
<css::sheet::ExternalLinkInfo
>* pExternalLinks
= nullptr,
558 const OUString
* pErrRef
= nullptr );
560 SC_DLLPUBLIC ScRefFlags
ParseAny( const OUString
&, const ScDocument
&,
561 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
);
562 SC_DLLPUBLIC ScRefFlags
ParseCols( const ScDocument
& rDoc
,
564 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
);
565 SC_DLLPUBLIC
void ParseRows( const ScDocument
& rDoc
,
567 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
);
569 /** Parse an Excel style reference up to and including the sheet name
570 separator '!', including detection of external documents and sheet
571 names, and in case of MOOXML import the bracketed index is used to
572 determine the actual document name passed in pExternalLinks. For
573 internal references (resulting rExternDocName empty), aStart.nTab and
574 aEnd.nTab are set, or -1 if sheet name not found.
575 @param bOnlyAcceptSingle If <TRUE/>, a 3D reference (Sheet1:Sheet2)
576 encountered results in an error (NULL returned).
577 @param pExternalLinks pointer to ExternalLinkInfo sequence, may be
578 NULL for non-filter usage, in which case indices such as [1] are
580 @param pErrRef pointer to "#REF!" string if to be accepted.
582 Pointer to the position after '!' if successfully parsed, and
583 rExternDocName, rStartTabName and/or rEndTabName filled if
584 applicable. ScRefFlags::... flags set in nFlags.
585 Or if no valid document and/or sheet header could be parsed the start
586 position passed with pString.
587 Or NULL if a 3D sheet header could be parsed but
588 bOnlyAcceptSingle==true was given.
590 const sal_Unicode
* Parse_XL_Header( const sal_Unicode
* pString
, const ScDocument
& rDocument
,
591 OUString
& rExternDocName
, OUString
& rStartTabName
,
592 OUString
& rEndTabName
, ScRefFlags
& nFlags
,
593 bool bOnlyAcceptSingle
,
594 const css::uno::Sequence
<css::sheet::ExternalLinkInfo
>* pExternalLinks
= nullptr,
595 const OUString
* pErrRef
= nullptr );
597 /** Returns string with formatted cell range from aStart to aEnd,
598 according to provided address convention.
602 Reference to document which is used for example to get tab names.
604 Provide information about required address convention.
605 Supported address conventions are:
606 CONV_OOO 'doc'#sheet.A1:sheet2.B2
607 CONV_XL_A1, [doc]sheet:sheet2!A1:B2
608 CONV_XL_OOX, [#]sheet:sheet2!A1:B2
609 CONV_XL_R1C1, [doc]sheet:sheet2!R1C1:R2C2
610 @param bFullAddressNotation
611 If TRUE, the full address notation will be used.
612 For example in case all columns are used, "A1:AMJ177" is full address notation
613 and "1:177" is shortened address notation.
615 String contains formatted cell range in address convention
617 SC_DLLPUBLIC OUString
Format( const ScDocument
& rDocument
,
618 ScRefFlags nFlags
= ScRefFlags::ZERO
,
619 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
,
620 bool bFullAddressNotation
= false ) const;
622 inline void GetVars( SCCOL
& nCol1
, SCROW
& nRow1
, SCTAB
& nTab1
,
623 SCCOL
& nCol2
, SCROW
& nRow2
, SCTAB
& nTab2
) const;
624 SC_DLLPUBLIC
void PutInOrder();
628 If FALSE is returned, the positions contain <0 or >MAX...
629 values if shifted out of bounds.
631 The document for the maximum defined sheet number.
633 [[nodiscard
]] SC_DLLPUBLIC
bool Move( SCCOL aDeltaX
, SCROW aDeltaY
, SCTAB aDeltaZ
,
634 ScRange
& rErrorRange
, const ScDocument
* pDocument
= nullptr );
636 /** Same as Move() but with sticky end col/row anchors. */
637 [[nodiscard
]] SC_DLLPUBLIC
bool MoveSticky( const ScDocument
& rDoc
, SCCOL aDeltaX
, SCROW aDeltaY
, SCTAB aDeltaZ
,
638 ScRange
& rErrorRange
);
640 SC_DLLPUBLIC
void IncColIfNotLessThan(const ScDocument
& rDoc
, SCCOL nStartCol
, SCCOL nOffset
);
641 SC_DLLPUBLIC
void IncRowIfNotLessThan(const ScDocument
& rDoc
, SCROW nStartRow
, SCROW nOffset
);
643 SC_DLLPUBLIC
void ExtendTo( const ScRange
& rRange
);
644 SC_DLLPUBLIC
bool Intersects( const ScRange
& rRange
) const; // do two ranges intersect?
646 ScRange
Intersection( const ScRange
& rOther
) const;
648 /// If maximum end column should not be adapted during reference update.
649 inline bool IsEndColSticky() const;
650 /// If maximum end row should not be adapted during reference update.
651 inline bool IsEndRowSticky() const;
653 /** Increment or decrement end column unless sticky or until it becomes
654 sticky. Checks if the range encompasses at least two columns so should
655 be called before adjusting the start column. */
656 void IncEndColSticky( const ScDocument
& rDoc
, SCCOL nDelta
);
658 /** Increment or decrement end row unless sticky or until it becomes
659 sticky. Checks if the range encompasses at least two rows so should
660 be called before adjusting the start row. */
661 void IncEndRowSticky( const ScDocument
& rDoc
, SCROW nDelta
);
663 inline bool operator==( const ScRange
& rRange
) const;
664 inline bool operator!=( const ScRange
& rRange
) const;
665 inline bool operator<( const ScRange
& rRange
) const;
666 inline bool operator<=( const ScRange
& rRange
) const;
668 /// Hash 2D area ignoring table number.
669 inline size_t hashArea() const;
670 /// Hash start column and start and end rows.
671 inline size_t hashStartColumn() const;
674 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
675 template<typename charT
, typename traits
>
676 inline std::basic_ostream
<charT
, traits
> & operator <<(std::basic_ostream
<charT
, traits
> & stream
, const ScRange
& rRange
)
678 stream
<< rRange
.aStart
;
679 if (rRange
.aEnd
!= rRange
.aStart
)
682 if (rRange
.aEnd
.Tab() != rRange
.aStart
.Tab())
683 stream
<< rRange
.aEnd
;
686 "R" << rRange
.aEnd
.Row()+1 <<
687 "C" << rRange
.aEnd
.Col()+1;
693 inline void ScRange::GetVars( SCCOL
& nCol1
, SCROW
& nRow1
, SCTAB
& nTab1
,
694 SCCOL
& nCol2
, SCROW
& nRow2
, SCTAB
& nTab2
) const
696 aStart
.GetVars( nCol1
, nRow1
, nTab1
);
697 aEnd
.GetVars( nCol2
, nRow2
, nTab2
);
700 inline bool ScRange::IsEndColSticky() const
702 // Only in an actual column range, i.e. not if both columns are MAXCOL.
703 return aEnd
.Col() == MAXCOL
&& aStart
.Col() < aEnd
.Col();
706 inline bool ScRange::IsEndRowSticky() const
708 // Only in an actual row range, i.e. not if both rows are MAXROW.
709 return aEnd
.Row() == MAXROW
&& aStart
.Row() < aEnd
.Row();
712 inline bool ScRange::operator==( const ScRange
& rRange
) const
714 return ( (aStart
== rRange
.aStart
) && (aEnd
== rRange
.aEnd
) );
717 inline bool ScRange::operator!=( const ScRange
& rRange
) const
719 return !operator==( rRange
);
722 /// Sort on upper left corner tab,col,row, if equal then use lower right too.
723 inline bool ScRange::operator<( const ScRange
& r
) const
725 return aStart
< r
.aStart
|| (aStart
== r
.aStart
&& aEnd
< r
.aEnd
) ;
728 inline bool ScRange::operator<=( const ScRange
& rRange
) const
730 return operator<( rRange
) || operator==( rRange
);
733 inline bool ScRange::In( const ScAddress
& rAddress
) const
736 aStart
.Col() <= rAddress
.Col() && rAddress
.Col() <= aEnd
.Col() &&
737 aStart
.Row() <= rAddress
.Row() && rAddress
.Row() <= aEnd
.Row() &&
738 aStart
.Tab() <= rAddress
.Tab() && rAddress
.Tab() <= aEnd
.Tab();
741 inline bool ScRange::In( const ScRange
& rRange
) const
744 aStart
.Col() <= rRange
.aStart
.Col() && rRange
.aEnd
.Col() <= aEnd
.Col() &&
745 aStart
.Row() <= rRange
.aStart
.Row() && rRange
.aEnd
.Row() <= aEnd
.Row() &&
746 aStart
.Tab() <= rRange
.aStart
.Tab() && rRange
.aEnd
.Tab() <= aEnd
.Tab();
749 inline size_t ScRange::hashArea() const
751 #if SAL_TYPES_SIZEOFPOINTER == 8
752 // 12 bits for the columns and 20 bits for the rows
754 (static_cast<size_t>(aStart
.Row()) << 44) ^
755 (static_cast<size_t>(aStart
.Col()) << 32) ^
756 (static_cast<size_t>(aEnd
.Col()) << 20) ^
757 static_cast<size_t>(aEnd
.Row());
759 // Assume that there are not that many ranges with identical corners so we
760 // won't have too many collisions. Also assume that more lower row and
761 // column numbers are used so that there are not too many conflicts with
762 // the columns hashed into the values, and that start row and column
763 // usually don't exceed certain values. High bits are not masked off and
764 // may overlap with lower bits of other values, e.g. if start column is
765 // greater than assumed.
767 (static_cast<size_t>(aStart
.Row()) << 26) ^ // start row <= 2^6
768 (static_cast<size_t>(aStart
.Col()) << 21) ^ // start column <= 2^5
769 (static_cast<size_t>(aEnd
.Col()) << 15) ^ // end column <= 2^6
770 static_cast<size_t>(aEnd
.Row()); // end row <= 2^15
774 inline size_t ScRange::hashStartColumn() const
776 #if SAL_TYPES_SIZEOFPOINTER == 8
777 // 20 bits for the rows
779 (static_cast<size_t>(aStart
.Col()) << 40) ^
780 (static_cast<size_t>(aStart
.Row()) << 20) ^
781 static_cast<size_t>(aEnd
.Row());
783 // Assume that for the start row more lower row numbers are used so that
784 // there are not too many conflicts with the column hashed into the higher
787 (static_cast<size_t>(aStart
.Col()) << 24) ^ // start column <= 2^8
788 (static_cast<size_t>(aStart
.Row()) << 16) ^ // start row <= 2^8
789 static_cast<size_t>(aEnd
.Row());
793 inline bool ValidRange( const ScRange
& rRange
, SCCOL nMaxCol
= MAXCOL
, SCROW nMaxRow
= MAXROW
)
795 return ValidAddress(rRange
.aStart
, nMaxCol
, nMaxRow
) && ValidAddress(rRange
.aEnd
, nMaxCol
, nMaxRow
);
799 class SAL_WARN_UNUSED ScRangePair final
802 std::array
<ScRange
,2> aRange
;
805 ScRangePair( const ScRangePair
& r
)
807 aRange
[0] = r
.aRange
[0];
808 aRange
[1] = r
.aRange
[1];
810 ScRangePair( const ScRange
& rRange1
, const ScRange
& rRange2
)
816 inline ScRangePair
& operator= ( const ScRangePair
& rRange
);
817 const ScRange
& GetRange( sal_uInt16 n
) const
821 ScRange
& GetRange( sal_uInt16 n
)
827 inline ScRangePair
& ScRangePair::operator= ( const ScRangePair
& rRange
)
829 aRange
[0] = rRange
.aRange
[0];
830 aRange
[1] = rRange
.aRange
[1];
835 class SAL_WARN_UNUSED ScRefAddress
844 bRelCol(false), bRelRow(false), bRelTab(false)
846 ScRefAddress( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) :
847 aAdr(nCol
, nRow
, nTab
),
848 bRelCol(false), bRelRow(false), bRelTab(false)
850 ScRefAddress( const ScRefAddress
& rRef
) :
851 aAdr(rRef
.aAdr
), bRelCol(rRef
.bRelCol
), bRelRow(rRef
.bRelRow
),
852 bRelTab(rRef
.bRelTab
)
855 inline ScRefAddress
& operator=( const ScRefAddress
& );
857 bool IsRelCol() const
861 bool IsRelRow() const
865 bool IsRelTab() const
870 void SetRelCol(bool bNewRelCol
)
872 bRelCol
= bNewRelCol
;
874 void SetRelRow(bool bNewRelRow
)
876 bRelRow
= bNewRelRow
;
878 void SetRelTab(bool bNewRelTab
)
880 bRelTab
= bNewRelTab
;
883 inline void Set( const ScAddress
& rAdr
,
884 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
);
885 inline void Set( SCCOL nNewCol
, SCROW nNewRow
, SCTAB nNewTab
,
886 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
);
888 const ScAddress
& GetAddress() const
906 inline bool operator == ( const ScRefAddress
& r
) const;
908 OUString
GetRefString( const ScDocument
& rDocument
, SCTAB nActTab
,
909 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
) const;
912 inline ScRefAddress
& ScRefAddress::operator=( const ScRefAddress
& rRef
)
915 bRelCol
= rRef
.bRelCol
;
916 bRelRow
= rRef
.bRelRow
;
917 bRelTab
= rRef
.bRelTab
;
921 inline void ScRefAddress::Set( const ScAddress
& rAdr
,
922 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
)
925 bRelCol
= bNewRelCol
;
926 bRelRow
= bNewRelRow
;
927 bRelTab
= bNewRelTab
;
930 inline void ScRefAddress::Set( SCCOL nNewCol
, SCROW nNewRow
, SCTAB nNewTab
,
931 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
)
933 aAdr
.Set( nNewCol
, nNewRow
, nNewTab
);
934 bRelCol
= bNewRelCol
;
935 bRelRow
= bNewRelRow
;
936 bRelTab
= bNewRelTab
;
939 inline bool ScRefAddress::operator==( const ScRefAddress
& rRefAddress
) const
941 return aAdr
== rRefAddress
.aAdr
&&
942 bRelCol
== rRefAddress
.bRelCol
&&
943 bRelRow
== rRefAddress
.bRelRow
&&
944 bRelTab
== rRefAddress
.bRelTab
;
949 // Special values for cells always broadcasting or listening (ScRecalcMode::ALWAYS
951 #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
952 #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
954 template< typename T
> inline void PutInOrder( T
& nStart
, T
& nEnd
)
958 std::swap(nStart
, nEnd
);
962 bool ConvertSingleRef( const ScDocument
& pDocument
, const OUString
& rRefString
,
963 SCTAB nDefTab
, ScRefAddress
& rRefAddress
,
964 const ScAddress::Details
& rDetails
,
965 ScAddress::ExternalInfo
* pExtInfo
= nullptr );
967 bool ConvertDoubleRef( const ScDocument
& rDocument
, const OUString
& rRefString
,
968 SCTAB nDefTab
, ScRefAddress
& rStartRefAddress
,
969 ScRefAddress
& rEndRefAddress
,
970 const ScAddress::Details
& rDetails
,
971 ScAddress::ExternalInfo
* pExtInfo
= nullptr );
973 /// append alpha representation of column to buffer
974 SC_DLLPUBLIC
void ScColToAlpha( OUStringBuffer
& rBuffer
, SCCOL nCol
);
976 inline void ScColToAlpha( OUString
& rStr
, SCCOL nCol
)
978 OUStringBuffer
aBuf(4);
979 ScColToAlpha( aBuf
, nCol
);
983 inline OUString
ScColToAlpha( SCCOL nCol
)
985 OUStringBuffer
aBuf(4);
986 ScColToAlpha( aBuf
, nCol
);
987 return aBuf
.makeStringAndClear();
990 /// get column number of A..IV... string
991 bool AlphaToCol(const ScDocument
& rDoc
, SCCOL
& rCol
, const OUString
& rStr
);
993 #endif // INCLUDED_SC_INC_ADDRESS_HXX
995 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */