LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / inc / address.hxx
blob8cf39ccfdf647cdd7a6208feaac7c02039f06ef1
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 #pragma once
22 #include <rtl/ustrbuf.hxx>
23 #include <rtl/strbuf.hxx>
25 #include <array>
26 #include <limits>
27 #include <ostream>
29 #include "scdllapi.h"
30 #include "types.hxx"
31 #include <formula/grammar.hxx>
33 #include <o3tl/typed_flags_set.hxx>
34 #include <o3tl/underlyingenumvalue.hxx>
36 namespace com::sun::star {
37 namespace sheet {
38 struct ExternalLinkInfo;
42 namespace com::sun::star::uno { template <typename > class Sequence; }
44 class ScDocument;
46 /** size_t typedef to be able to find places where code was changed from USHORT
47 to size_t and is used to read/write from/to streams. */
48 typedef size_t SCSIZE;
50 // Maximum possible value of data type, NOT maximum row value.
51 // MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is
52 // included, we should not be using those stupid macros anyway.
53 #undef min
54 #undef max
55 const SCROW SCROW_MAX = ::std::numeric_limits<SCROW>::max();
56 const SCCOL SCCOL_MAX = ::std::numeric_limits<SCCOL>::max();
57 const SCTAB SCTAB_MAX = ::std::numeric_limits<SCTAB>::max();
58 const SCCOLROW SCCOLROW_MAX = ::std::numeric_limits<SCCOLROW>::max();
59 const SCSIZE SCSIZE_MAX = ::std::numeric_limits<SCSIZE>::max();
61 // Count values
62 const SCROW MAXROWCOUNT = 1048576;
63 const SCCOL MAXCOLCOUNT = 16384;
64 const SCCOL INITIALCOLCOUNT = 1; // initial number of columns we allocate memory for
65 /// limiting to 10000 for now, problem with 32 bit builds for now
66 const SCTAB MAXTABCOUNT = 10000;
67 // Maximum values
68 const SCROW MAXROW = MAXROWCOUNT - 1;
69 const SCCOL MAXCOL = MAXCOLCOUNT - 1;
70 const SCTAB MAXTAB = MAXTABCOUNT - 1;
71 const SCCOLROW MAXCOLROW = MAXROW;
72 const SCROW MAXROWCOUNT_JUMBO = 16 * 1024 * 1024;
73 const SCCOL MAXCOLCOUNT_JUMBO = 16384;
74 const SCROW MAXROW_JUMBO = MAXROWCOUNT_JUMBO - 1;
75 const SCCOL MAXCOL_JUMBO = MAXCOLCOUNT_JUMBO - 1;
76 // Maximum tiled rendering values
77 const SCROW MAXTILEDROW = MAXROW;
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 inline constexpr OUStringLiteral MAXROW_STRING(u"1048575");
85 inline constexpr OUStringLiteral MAXCOL_STRING(u"XFD");
86 inline constexpr OUStringLiteral MAXROW_JUMBO_STRING(u"16777215");
87 inline constexpr OUStringLiteral MAXCOL_JUMBO_STRING(u"XFD");
89 // Special values
90 const SCTAB SC_TAB_APPEND = SCTAB_MAX;
91 const SCTAB TABLEID_DOC = SCTAB_MAX; // entire document, e.g. protect
92 const SCROW SCROWS32K = 32000; // for fuzzing
93 const SCCOL SCCOL_REPEAT_NONE = SCCOL_MAX;
94 const SCROW SCROW_REPEAT_NONE = SCROW_MAX;
95 const SCCOL SC_TABSTART_NONE = SCCOL_MAX;
97 const SCROW MAXROW_30 = 8191;
99 [[nodiscard]] inline bool ValidCol( SCCOL nCol, SCCOL nMaxCol )
101 assert(nMaxCol == MAXCOL || nMaxCol == MAXCOL_JUMBO); // temporary to debug jumbo sheets work
102 return nCol >= 0 && nCol <= nMaxCol;
105 [[nodiscard]] inline bool ValidRow( SCROW nRow, SCROW nMaxRow)
107 assert(nMaxRow == MAXROW || nMaxRow == MAXROW_JUMBO); // temporary to debug jumbo sheets work
108 return nRow >= 0 && nRow <= nMaxRow;
111 [[nodiscard]] inline bool ValidTab( SCTAB nTab )
113 return nTab >= 0 && nTab <= MAXTAB;
116 [[nodiscard]] inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
118 return nTab >= 0 && nTab <= nMaxTab;
121 [[nodiscard]] inline bool ValidColRow( SCCOL nCol, SCROW nRow, 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);
127 [[nodiscard]] inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab, SCCOL nMaxCol, SCROW nMaxRow )
129 assert(nMaxRow == MAXROW || nMaxRow == MAXROW_JUMBO); // temporary to debug jumbo sheets work
130 return ValidCol(nCol,nMaxCol) && ValidRow(nRow,nMaxRow) && ValidTab( nTab);
133 [[nodiscard]] inline SCCOL SanitizeCol( SCCOL nCol, SCCOL nMaxCol )
135 assert(nMaxCol == MAXCOL || nMaxCol == MAXCOL_JUMBO); // temporary to debug jumbo sheets work
136 return nCol < 0 ? 0 : (nCol > nMaxCol ? nMaxCol : nCol);
139 [[nodiscard]] inline SCROW SanitizeRow( SCROW nRow, SCROW nMaxRow )
141 assert(nMaxRow == MAXROW || nMaxRow == MAXROW_JUMBO); // temporary to debug jumbo sheets work
142 return nRow < 0 ? 0 : (nRow > nMaxRow ? nMaxRow : nRow);
145 [[nodiscard]] inline SCTAB SanitizeTab( SCTAB nTab )
147 return nTab < 0 ? 0 : (nTab > MAXTAB ? MAXTAB : nTab);
150 // The result of ConvertRef() is a bit group of the following:
151 enum class ScRefFlags : sal_uInt16
153 ZERO = 0x0000,
154 COL_ABS = 0x0001,
155 ROW_ABS = 0x0002,
156 TAB_ABS = 0x0004,
157 TAB_3D = 0x0008,
158 COL2_ABS = 0x0010,
159 ROW2_ABS = 0x0020,
160 TAB2_ABS = 0x0040,
161 TAB2_3D = 0x0080,
162 ROW_VALID = 0x0100,
163 COL_VALID = 0x0200,
164 TAB_VALID = 0x0400,
165 // BITS for convenience
166 BITS = COL_ABS | ROW_ABS | TAB_ABS | TAB_3D
167 | ROW_VALID | COL_VALID | TAB_VALID,
168 // somewhat cheesy kludge to force the display of the document name even for
169 // local references. Requires TAB_3D to be valid
170 FORCE_DOC = 0x0800,
171 ROW2_VALID = 0x1000,
172 COL2_VALID = 0x2000,
173 TAB2_VALID = 0x4000,
174 VALID = 0x8000,
176 TAB_ABS_3D = TAB_ABS | TAB_3D,
178 ADDR_ABS = VALID | COL_ABS | ROW_ABS | TAB_ABS,
180 RANGE_ABS = ADDR_ABS | COL2_ABS | ROW2_ABS | TAB2_ABS,
182 ADDR_ABS_3D = ADDR_ABS | TAB_3D,
183 RANGE_ABS_3D = RANGE_ABS | TAB_3D
186 namespace o3tl
188 template<> struct typed_flags<ScRefFlags> : is_typed_flags<ScRefFlags, 0xffff> {};
190 inline void applyStartToEndFlags(ScRefFlags &target,const ScRefFlags source)
192 target |= ScRefFlags(o3tl::to_underlying(source) << 4);
194 inline void applyStartToEndFlags(ScRefFlags &target)
196 target |= ScRefFlags(o3tl::to_underlying(target) << 4);
199 // ScAddress
200 class SAL_WARN_UNUSED ScAddress
202 private:
203 // Even if the fields are in the order "row, column, tab", in all (?) the ScAddress and
204 // ScDocument APIs that take separate row, column, and tab parameters, the parameters are in the
205 // order "column, row, tab", which matches the most common (A1) address syntax, if you ignore
206 // the sheet (tab). Don't let this confuse you, like it confused me for a while.
208 SCROW nRow;
209 SCCOL nCol;
210 SCTAB nTab;
212 public:
214 enum Uninitialized { UNINITIALIZED };
215 enum InitializeInvalid { INITIALIZE_INVALID };
217 struct Details
219 formula::FormulaGrammar::AddressConvention eConv;
220 SCROW nRow;
221 SCCOL nCol;
223 Details( formula::FormulaGrammar::AddressConvention eConvP, SCROW nRowP, SCCOL nColP ) :
224 eConv(eConvP), nRow(nRowP), nCol(nColP)
226 Details( formula::FormulaGrammar::AddressConvention eConvP, ScAddress const & rAddr ) :
227 eConv(eConvP), nRow(rAddr.Row()), nCol(rAddr.Col())
229 Details( formula::FormulaGrammar::AddressConvention eConvP) :
230 eConv(eConvP), nRow(0), nCol(0)
232 /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
233 Details( const ScDocument& rDoc, const ScAddress& rAddr );
235 SC_DLLPUBLIC static const Details detailsOOOa1;
237 struct ExternalInfo
239 OUString maTabName;
240 sal_uInt16 mnFileId;
241 bool mbExternal;
243 ExternalInfo() :
244 mnFileId(0), mbExternal(false)
248 ScAddress() :
249 nRow(0), nCol(0), nTab(0)
251 ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) :
252 nRow(nRowP), nCol(nColP), nTab(nTabP)
254 /** coverity[uninit_member] - Yes, it is what it seems to be: Uninitialized.
255 May be used for performance reasons if it is initialized by other means. */
256 ScAddress( Uninitialized )
258 ScAddress( InitializeInvalid ) :
259 nRow(-1), nCol(-1), nTab(-1)
261 ScAddress( const ScAddress& rAddress ) :
262 nRow(rAddress.nRow), nCol(rAddress.nCol), nTab(rAddress.nTab)
264 inline ScAddress& operator=( const ScAddress& rAddress );
266 inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
268 SCROW Row() const
270 return nRow;
273 SCCOL Col() const
275 return nCol;
277 SCTAB Tab() const
279 return nTab;
281 void SetRow( SCROW nRowP )
283 nRow = nRowP;
285 void SetCol( SCCOL nColP )
287 nCol = nColP;
289 void SetTab( SCTAB nTabP )
291 nTab = nTabP;
293 void SetInvalid()
295 nRow = -1;
296 nCol = -1;
297 nTab = -1;
299 bool IsValid() const
301 return (nRow >= 0) && (nCol >= 0) && (nTab >= 0);
304 inline void PutInOrder( ScAddress& rAddress );
306 void IncRow( SCROW nDelta = 1 )
308 nRow = sal::static_int_cast<SCROW>(nRow + nDelta);
310 void IncCol( SCCOL nDelta = 1 )
312 nCol = sal::static_int_cast<SCCOL>(nCol + nDelta);
314 void IncTab( SCTAB nDelta = 1 )
316 nTab = sal::static_int_cast<SCTAB>(nTab + nDelta);
318 void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
320 nColP = nCol;
321 nRowP = nRow;
322 nTabP = nTab;
326 @param pSheetEndPos
327 If given and Parse() successfully parsed a sheet name it returns
328 the end position (exclusive) behind the sheet name AND a
329 following sheet name separator. This independent of whether the
330 resulting reference is fully valid or not.
332 SC_DLLPUBLIC ScRefFlags Parse(
333 const OUString&, const ScDocument&,
334 const Details& rDetails = detailsOOOa1,
335 ExternalInfo* pExtInfo = nullptr,
336 const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
337 sal_Int32* pSheetEndPos = nullptr,
338 const OUString* pErrRef = nullptr );
340 SC_DLLPUBLIC void Format( OStringBuffer& r, ScRefFlags nFlags,
341 const ScDocument* pDocument = nullptr,
342 const Details& rDetails = detailsOOOa1) const;
344 SC_DLLPUBLIC OUString Format( ScRefFlags nFlags,
345 const ScDocument* pDocument = nullptr,
346 const Details& rDetails = detailsOOOa1) const;
349 @param rErrorPos
350 If FALSE is returned, the positions contain <0 or >MAX...
351 values if shifted out of bounds.
352 @param pDocument
353 The document for the maximum defined sheet number.
355 [[nodiscard]] SC_DLLPUBLIC bool Move( SCCOL nDeltaX, SCROW nDeltaY, SCTAB nDeltaZ,
356 ScAddress& rErrorPos, const ScDocument& rDoc );
358 inline bool operator==( const ScAddress& rAddress ) const;
359 inline bool operator!=( const ScAddress& rAddress ) const;
360 inline bool operator<( const ScAddress& rAddress ) const;
361 inline bool operator<=( const ScAddress& rAddress ) const;
362 inline bool lessThanByRow( const ScAddress& rAddress ) const;
364 inline size_t hash() const;
367 * Create a human-readable string representation of the cell address. You
368 * cannot specify precise formatting with this method; use Format() if you
369 * need to specify how the address needs to be formatted.
371 * The address string does not display sheet name.
373 * @return human-readable string representation of the cell address.
375 OUString GetColRowString() const;
378 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
379 template<typename charT, typename traits>
380 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScAddress& rAddress)
382 stream <<
383 rAddress.Tab()+1 << "!"
384 "R" << rAddress.Row()+1 <<
385 "C" << rAddress.Col()+1;
387 return stream;
390 inline void ScAddress::PutInOrder( ScAddress& rAddress )
392 if ( rAddress.Col() < Col() )
394 SCCOL nTmp = rAddress.Col();
395 rAddress.SetCol( Col() );
396 SetCol( nTmp );
398 if ( rAddress.Row() < Row() )
400 SCROW nTmp = rAddress.Row();
401 rAddress.SetRow( Row() );
402 SetRow( nTmp );
404 if ( rAddress.Tab() < Tab() )
406 SCTAB nTmp = rAddress.Tab();
407 rAddress.SetTab( Tab() );
408 SetTab( nTmp );
412 inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
414 nCol = nColP;
415 nRow = nRowP;
416 nTab = nTabP;
419 inline ScAddress& ScAddress::operator=( const ScAddress& rAddress )
421 nCol = rAddress.nCol;
422 nRow = rAddress.nRow;
423 nTab = rAddress.nTab;
424 return *this;
427 inline bool ScAddress::operator==( const ScAddress& rAddress ) const
429 return nRow == rAddress.nRow && nCol == rAddress.nCol && nTab == rAddress.nTab;
432 inline bool ScAddress::operator!=( const ScAddress& rAddress ) const
434 return !operator==( rAddress );
437 /** Less than ordered by tab,col,row. */
438 inline bool ScAddress::operator<( const ScAddress& rAddress ) const
440 if (nTab == rAddress.nTab)
442 if (nCol == rAddress.nCol)
443 return nRow < rAddress.nRow;
444 else
445 return nCol < rAddress.nCol;
447 else
448 return nTab < rAddress.nTab;
451 inline bool ScAddress::operator<=( const ScAddress& rAddress ) const
453 return operator<( rAddress ) || operator==( rAddress );
456 /** Less than ordered by tab,row,col as needed by row-wise import/export */
457 inline bool ScAddress::lessThanByRow( const ScAddress& rAddress ) const
459 if (nTab == rAddress.nTab)
461 if (nRow == rAddress.nRow)
462 return nCol < rAddress.nCol;
463 else
464 return nRow < rAddress.nRow;
466 else
467 return nTab < rAddress.nTab;
470 inline size_t ScAddress::hash() const
472 #if SAL_TYPES_SIZEOFPOINTER == 8
473 // 16 bits for the columns, and 20 bits for the rows
474 return (static_cast<size_t>(nTab) << 36) ^
475 (static_cast<size_t>(nCol) << 20) ^
476 static_cast<size_t>(nRow);
477 #else
478 // Assume that there are not that many addresses with row > 2^16 AND column
479 // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
480 if (nRow <= 0xffff)
481 return (static_cast<size_t>(nTab) << 24) ^
482 (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
483 else
484 return (static_cast<size_t>(nTab) << 28) ^
485 (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
486 #endif
489 struct ScAddressHashFunctor
491 size_t operator()( const ScAddress & rAddress ) const
493 return rAddress.hash();
497 [[nodiscard]] inline bool ValidAddress( const ScAddress& rAddress, SCCOL nMaxCol, SCROW nMaxRow )
499 return ValidCol(rAddress.Col(), nMaxCol) && ValidRow(rAddress.Row(), nMaxRow) && ValidTab(rAddress.Tab());
502 // ScRange
503 class SAL_WARN_UNUSED SC_DLLPUBLIC ScRange final
505 public:
506 ScAddress aStart;
507 ScAddress aEnd;
509 ScRange() :
510 aStart(), aEnd()
513 ScRange( ScAddress::Uninitialized eUninitialized ) :
514 aStart( eUninitialized ), aEnd( eUninitialized )
516 ScRange( ScAddress::InitializeInvalid eInvalid ) :
517 aStart( eInvalid ), aEnd( eInvalid )
519 ScRange( const ScAddress& aInputStart, const ScAddress& aInputEnd ) :
520 aStart( aInputStart ), aEnd( aInputEnd )
522 aStart.PutInOrder( aEnd );
524 ScRange( const ScRange& rRange ) :
525 aStart( rRange.aStart ), aEnd( rRange.aEnd )
527 ScRange( const ScAddress& rRange ) :
528 aStart( rRange ), aEnd( rRange )
530 ScRange( SCCOL nCol, SCROW nRow, SCTAB nTab ) :
531 aStart( nCol, nRow, nTab ), aEnd( aStart )
533 ScRange( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) :
534 aStart( nCol1, nRow1, nTab1 ), aEnd( nCol2, nRow2, nTab2 )
537 ScRange& operator=( const ScRange& rRange )
539 aStart = rRange.aStart;
540 aEnd = rRange.aEnd;
541 return *this;
543 ScRange& operator=( const ScAddress& rPos )
545 aStart = aEnd = rPos;
546 return *this;
548 void SetInvalid()
550 aStart.SetInvalid();
551 aEnd.SetInvalid();
553 bool IsValid() const
555 return aStart.IsValid() && aEnd.IsValid();
557 inline bool In( const ScAddress& ) const; ///< is Address& in Range?
558 inline bool In( const ScRange& ) const; ///< is Range& in Range?
560 ScRefFlags Parse( const OUString&, const ScDocument&,
561 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
562 ScAddress::ExternalInfo* pExtInfo = nullptr,
563 const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
564 const OUString* pErrRef = nullptr );
566 ScRefFlags ParseAny( const OUString&, const ScDocument&,
567 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
568 ScRefFlags ParseCols( const ScDocument& rDoc,
569 const OUString&,
570 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
571 void ParseRows( const ScDocument& rDoc,
572 const OUString&,
573 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
575 /** Parse an Excel style reference up to and including the sheet name
576 separator '!', including detection of external documents and sheet
577 names, and in case of MOOXML import the bracketed index is used to
578 determine the actual document name passed in pExternalLinks. For
579 internal references (resulting rExternDocName empty), aStart.nTab and
580 aEnd.nTab are set, or -1 if sheet name not found.
581 @param bOnlyAcceptSingle If <TRUE/>, a 3D reference (Sheet1:Sheet2)
582 encountered results in an error (NULL returned).
583 @param pExternalLinks pointer to ExternalLinkInfo sequence, may be
584 NULL for non-filter usage, in which case indices such as [1] are
585 not resolved.
586 @param pErrRef pointer to "#REF!" string if to be accepted.
587 @returns
588 Pointer to the position after '!' if successfully parsed, and
589 rExternDocName, rStartTabName and/or rEndTabName filled if
590 applicable. ScRefFlags::... flags set in nFlags.
591 Or if no valid document and/or sheet header could be parsed the start
592 position passed with pString.
593 Or NULL if a 3D sheet header could be parsed but
594 bOnlyAcceptSingle==true was given.
596 const sal_Unicode* Parse_XL_Header( const sal_Unicode* pString, const ScDocument& rDocument,
597 OUString& rExternDocName, OUString& rStartTabName,
598 OUString& rEndTabName, ScRefFlags& nFlags,
599 bool bOnlyAcceptSingle,
600 const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
601 const OUString* pErrRef = nullptr );
603 /** Returns string with formatted cell range from aStart to aEnd,
604 according to provided address convention.
605 @param nFlags
606 Cell reference flags
607 @param rDocument
608 Reference to document which is used for example to get tab names.
609 @param rDetails
610 Provide information about required address convention.
611 Supported address conventions are:
612 CONV_OOO 'doc'#sheet.A1:sheet2.B2
613 CONV_XL_A1, [doc]sheet:sheet2!A1:B2
614 CONV_XL_OOX, [#]sheet:sheet2!A1:B2
615 CONV_XL_R1C1, [doc]sheet:sheet2!R1C1:R2C2
616 @param bFullAddressNotation
617 If TRUE, the full address notation will be used.
618 For example in case all columns are used, "A1:AMJ177" is full address notation
619 and "1:177" is shortened address notation.
620 @returns
621 String contains formatted cell range in address convention
623 OUString Format( const ScDocument& rDocument,
624 ScRefFlags nFlags = ScRefFlags::ZERO,
625 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
626 bool bFullAddressNotation = false ) const;
628 inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
629 SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
630 void PutInOrder();
633 @param rErrorRange
634 If FALSE is returned, the positions contain <0 or >MAX...
635 values if shifted out of bounds.
636 @param pDocument
637 The document for the maximum defined sheet number.
639 [[nodiscard]] bool Move( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
640 ScRange& rErrorRange, const ScDocument& rDoc );
642 /** Same as Move() but with sticky end col/row anchors. */
643 [[nodiscard]] bool MoveSticky( const ScDocument& rDoc, SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
644 ScRange& rErrorRange );
646 void IncColIfNotLessThan(const ScDocument& rDoc, SCCOL nStartCol, SCCOL nOffset);
647 void IncRowIfNotLessThan(const ScDocument& rDoc, SCROW nStartRow, SCROW nOffset);
649 void ExtendTo( const ScRange& rRange );
650 bool Intersects( const ScRange& rRange ) const; // do two ranges intersect?
652 ScRange Intersection( const ScRange& rOther ) const;
654 /// If maximum end column should not be adapted during reference update.
655 bool IsEndColSticky( const ScDocument& rDoc ) const;
656 /// If maximum end row should not be adapted during reference update.
657 bool IsEndRowSticky( const ScDocument& rDoc ) const;
659 /** Increment or decrement end column unless sticky or until it becomes
660 sticky. Checks if the range encompasses at least two columns so should
661 be called before adjusting the start column. */
662 void IncEndColSticky( const ScDocument& rDoc, SCCOL nDelta );
664 /** Increment or decrement end row unless sticky or until it becomes
665 sticky. Checks if the range encompasses at least two rows so should
666 be called before adjusting the start row. */
667 void IncEndRowSticky( const ScDocument& rDoc, SCROW nDelta );
669 inline bool operator==( const ScRange& rRange ) const;
670 inline bool operator!=( const ScRange& rRange ) const;
671 inline bool operator<( const ScRange& rRange ) const;
672 inline bool operator<=( const ScRange& rRange ) const;
674 /// Hash 2D area ignoring table number.
675 inline size_t hashArea() const;
676 /// Hash start column and start and end rows.
677 inline size_t hashStartColumn() const;
680 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
681 template<typename charT, typename traits>
682 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScRange& rRange)
684 stream << rRange.aStart;
685 if (rRange.aEnd != rRange.aStart)
687 stream << ":";
688 if (rRange.aEnd.Tab() != rRange.aStart.Tab())
689 stream << rRange.aEnd;
690 else
691 stream <<
692 "R" << rRange.aEnd.Row()+1 <<
693 "C" << rRange.aEnd.Col()+1;
696 return stream;
699 inline void ScRange::GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
700 SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const
702 aStart.GetVars( nCol1, nRow1, nTab1 );
703 aEnd.GetVars( nCol2, nRow2, nTab2 );
706 inline bool ScRange::operator==( const ScRange& rRange ) const
708 return ( (aStart == rRange.aStart) && (aEnd == rRange.aEnd) );
711 inline bool ScRange::operator!=( const ScRange& rRange ) const
713 return !operator==( rRange );
716 /// Sort on upper left corner tab,col,row, if equal then use lower right too.
717 inline bool ScRange::operator<( const ScRange& r ) const
719 return aStart < r.aStart || (aStart == r.aStart && aEnd < r.aEnd) ;
722 inline bool ScRange::operator<=( const ScRange& rRange ) const
724 return operator<( rRange ) || operator==( rRange );
727 inline bool ScRange::In( const ScAddress& rAddress ) const
729 return
730 aStart.Col() <= rAddress.Col() && rAddress.Col() <= aEnd.Col() &&
731 aStart.Row() <= rAddress.Row() && rAddress.Row() <= aEnd.Row() &&
732 aStart.Tab() <= rAddress.Tab() && rAddress.Tab() <= aEnd.Tab();
735 inline bool ScRange::In( const ScRange& rRange ) const
737 return
738 aStart.Col() <= rRange.aStart.Col() && rRange.aEnd.Col() <= aEnd.Col() &&
739 aStart.Row() <= rRange.aStart.Row() && rRange.aEnd.Row() <= aEnd.Row() &&
740 aStart.Tab() <= rRange.aStart.Tab() && rRange.aEnd.Tab() <= aEnd.Tab();
743 inline size_t ScRange::hashArea() const
745 #if SAL_TYPES_SIZEOFPOINTER == 8
746 // 12 bits for the columns and 20 bits for the rows
747 return
748 (static_cast<size_t>(aStart.Row()) << 44) ^
749 (static_cast<size_t>(aStart.Col()) << 32) ^
750 (static_cast<size_t>(aEnd.Col()) << 20) ^
751 static_cast<size_t>(aEnd.Row());
752 #else
753 // Assume that there are not that many ranges with identical corners so we
754 // won't have too many collisions. Also assume that more lower row and
755 // column numbers are used so that there are not too many conflicts with
756 // the columns hashed into the values, and that start row and column
757 // usually don't exceed certain values. High bits are not masked off and
758 // may overlap with lower bits of other values, e.g. if start column is
759 // greater than assumed.
760 return
761 (static_cast<size_t>(aStart.Row()) << 26) ^ // start row <= 2^6
762 (static_cast<size_t>(aStart.Col()) << 21) ^ // start column <= 2^5
763 (static_cast<size_t>(aEnd.Col()) << 15) ^ // end column <= 2^6
764 static_cast<size_t>(aEnd.Row()); // end row <= 2^15
765 #endif
768 inline size_t ScRange::hashStartColumn() const
770 #if SAL_TYPES_SIZEOFPOINTER == 8
771 // 20 bits for the rows
772 return
773 (static_cast<size_t>(aStart.Col()) << 40) ^
774 (static_cast<size_t>(aStart.Row()) << 20) ^
775 static_cast<size_t>(aEnd.Row());
776 #else
777 // Assume that for the start row more lower row numbers are used so that
778 // there are not too many conflicts with the column hashed into the higher
779 // values.
780 return
781 (static_cast<size_t>(aStart.Col()) << 24) ^ // start column <= 2^8
782 (static_cast<size_t>(aStart.Row()) << 16) ^ // start row <= 2^8
783 static_cast<size_t>(aEnd.Row());
784 #endif
787 [[nodiscard]] inline bool ValidRange( const ScRange& rRange, SCCOL nMaxCol, SCROW nMaxRow )
789 return ValidAddress(rRange.aStart, nMaxCol, nMaxRow) && ValidAddress(rRange.aEnd, nMaxCol, nMaxRow);
792 // ScRangePair
793 class SAL_WARN_UNUSED ScRangePair final
795 private:
796 std::array<ScRange,2> aRange;
798 public:
799 ScRangePair( const ScRangePair& r )
801 aRange[0] = r.aRange[0];
802 aRange[1] = r.aRange[1];
804 ScRangePair( const ScRange& rRange1, const ScRange& rRange2 )
806 aRange[0] = rRange1;
807 aRange[1] = rRange2;
810 inline ScRangePair& operator= ( const ScRangePair& rRange );
811 const ScRange& GetRange( sal_uInt16 n ) const
813 return aRange[n];
815 ScRange& GetRange( sal_uInt16 n )
817 return aRange[n];
821 inline ScRangePair& ScRangePair::operator= ( const ScRangePair& rRange )
823 aRange[0] = rRange.aRange[0];
824 aRange[1] = rRange.aRange[1];
825 return *this;
828 // ScRefAddress
829 class SAL_WARN_UNUSED ScRefAddress
831 private:
832 ScAddress aAdr;
833 bool bRelCol;
834 bool bRelRow;
835 bool bRelTab;
836 public:
837 ScRefAddress() :
838 bRelCol(false), bRelRow(false), bRelTab(false)
840 ScRefAddress( SCCOL nCol, SCROW nRow, SCTAB nTab ) :
841 aAdr(nCol, nRow, nTab),
842 bRelCol(false), bRelRow(false), bRelTab(false)
844 ScRefAddress( const ScRefAddress& rRef ) :
845 aAdr(rRef.aAdr), bRelCol(rRef.bRelCol), bRelRow(rRef.bRelRow),
846 bRelTab(rRef.bRelTab)
849 inline ScRefAddress& operator=( const ScRefAddress& );
851 bool IsRelCol() const
853 return bRelCol;
855 bool IsRelRow() const
857 return bRelRow;
859 bool IsRelTab() const
861 return bRelTab;
864 void SetRelCol(bool bNewRelCol)
866 bRelCol = bNewRelCol;
868 void SetRelRow(bool bNewRelRow)
870 bRelRow = bNewRelRow;
872 void SetRelTab(bool bNewRelTab)
874 bRelTab = bNewRelTab;
877 inline void Set( const ScAddress& rAdr,
878 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
879 inline void Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
880 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
882 const ScAddress& GetAddress() const
884 return aAdr;
887 SCCOL Col() const
889 return aAdr.Col();
891 SCROW Row() const
893 return aAdr.Row();
895 SCTAB Tab() const
897 return aAdr.Tab();
900 inline bool operator == ( const ScRefAddress& r ) const;
902 OUString GetRefString( const ScDocument& rDocument, SCTAB nActTab,
903 const ScAddress::Details& rDetails = ScAddress::detailsOOOa1) const;
906 inline ScRefAddress& ScRefAddress::operator=( const ScRefAddress& rRef )
908 aAdr = rRef.aAdr;
909 bRelCol = rRef.bRelCol;
910 bRelRow = rRef.bRelRow;
911 bRelTab = rRef.bRelTab;
912 return *this;
915 inline void ScRefAddress::Set( const ScAddress& rAdr,
916 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
918 aAdr = rAdr;
919 bRelCol = bNewRelCol;
920 bRelRow = bNewRelRow;
921 bRelTab = bNewRelTab;
924 inline void ScRefAddress::Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
925 bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
927 aAdr.Set( nNewCol, nNewRow, nNewTab);
928 bRelCol = bNewRelCol;
929 bRelRow = bNewRelRow;
930 bRelTab = bNewRelTab;
933 inline bool ScRefAddress::operator==( const ScRefAddress& rRefAddress ) const
935 return aAdr == rRefAddress.aAdr &&
936 bRelCol == rRefAddress.bRelCol &&
937 bRelRow == rRefAddress.bRelRow &&
938 bRelTab == rRefAddress.bRelTab;
941 // Global functions
943 // Special values for cells always broadcasting or listening (ScRecalcMode::ALWAYS
944 // and the like).
945 #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
946 #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
948 template< typename T > inline void PutInOrder( T& nStart, T& nEnd )
950 if (nEnd < nStart)
952 std::swap(nStart, nEnd);
956 bool ConvertSingleRef( const ScDocument& pDocument, const OUString& rRefString,
957 SCTAB nDefTab, ScRefAddress& rRefAddress,
958 const ScAddress::Details& rDetails,
959 ScAddress::ExternalInfo* pExtInfo = nullptr );
961 bool ConvertDoubleRef( const ScDocument& rDocument, const OUString& rRefString,
962 SCTAB nDefTab, ScRefAddress& rStartRefAddress,
963 ScRefAddress& rEndRefAddress,
964 const ScAddress::Details& rDetails,
965 ScAddress::ExternalInfo* pExtInfo = nullptr );
967 /// append alpha representation of column to buffer
968 SC_DLLPUBLIC void ScColToAlpha( OUStringBuffer& rBuffer, SCCOL nCol);
970 inline void ScColToAlpha( OUString& rStr, SCCOL nCol)
972 OUStringBuffer aBuf(4);
973 ScColToAlpha( aBuf, nCol);
974 rStr += aBuf;
977 inline OUString ScColToAlpha( SCCOL nCol )
979 OUStringBuffer aBuf(4);
980 ScColToAlpha( aBuf, nCol);
981 return aBuf.makeStringAndClear();
984 /// get column number of A..IV... string
985 bool AlphaToCol(const ScDocument& rDoc, SCCOL& rCol, const OUString& rStr);
987 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */