summaryrefslogtreecommitdiff
path: root/sc/inc/address.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/inc/address.hxx')
-rw-r--r--sc/inc/address.hxx820
1 files changed, 820 insertions, 0 deletions
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
new file mode 100644
index 000000000000..64dd9e3e7ea6
--- /dev/null
+++ b/sc/inc/address.hxx
@@ -0,0 +1,820 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_ADDRESS_HXX
+#define SC_ADDRESS_HXX
+
+#include <tools/stream.hxx>
+#include <tools/string.hxx>
+#include <tools/solar.h>
+#include <tools/debug.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/endian.h>
+
+#ifndef INCLUDED_LIMITS
+#include <limits>
+#define INCLUDED_LIMITS
+#endif
+#include "scdllapi.h"
+#include <formula/grammar.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+namespace com { namespace sun { namespace star {
+ namespace sheet {
+ struct ExternalLinkInfo;
+ }
+}}}
+
+class ScDocument;
+
+// The typedefs
+typedef sal_Int32 SCROW;
+typedef sal_Int16 SCCOL;
+typedef sal_Int16 SCTAB;
+typedef sal_Int32 SCCOLROW; // a type capable of holding either SCCOL or SCROW
+
+// temporarily signed typedefs
+typedef sal_Int32 SCsROW;
+typedef sal_Int16 SCsCOL;
+typedef sal_Int16 SCsTAB;
+typedef sal_Int32 SCsCOLROW;
+
+// size_t typedef to be able to find places where code was changed from USHORT
+// to size_t and is used to read/write from/to streams.
+typedef size_t SCSIZE;
+
+// Maximum possible value of data type, NOT maximum row value.
+// MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is
+// included, we should not be using those stupid macros anyway.
+#undef min
+#undef max
+const SCROW SCROW_MAX = ::std::numeric_limits<SCROW>::max();
+const SCCOL SCCOL_MAX = ::std::numeric_limits<SCCOL>::max();
+const SCTAB SCTAB_MAX = ::std::numeric_limits<SCTAB>::max();
+const SCCOLROW SCCOLROW_MAX = ::std::numeric_limits<SCCOLROW>::max();
+const SCSIZE SCSIZE_MAX = ::std::numeric_limits<SCSIZE>::max();
+
+// A define to handle critical sections we hopefully don't need very often.
+#define SC_ROWLIMIT_MORE_THAN_32K 1 /* set to 1 if we throw the switch */
+
+// The maximum values. Defines are needed for preprocessor checks, for example
+// in bcaslot.cxx, otherwise type safe constants are preferred.
+//#define MAXROWCOUNT_DEFINE 65536
+#define MAXROWCOUNT_DEFINE 1048576
+#define MAXCOLCOUNT_DEFINE 1024
+
+// Count values
+const SCROW MAXROWCOUNT = MAXROWCOUNT_DEFINE;
+const SCCOL MAXCOLCOUNT = MAXCOLCOUNT_DEFINE;
+const SCTAB MAXTABCOUNT = 256;
+const SCCOLROW MAXCOLROWCOUNT = MAXROWCOUNT;
+// Maximum values
+const SCROW MAXROW = MAXROWCOUNT - 1;
+const SCCOL MAXCOL = MAXCOLCOUNT - 1;
+const SCTAB MAXTAB = MAXTABCOUNT - 1;
+const SCCOLROW MAXCOLROW = MAXROW;
+
+
+// Special values
+const SCTAB SC_TAB_APPEND = SCTAB_MAX;
+const SCTAB TABLEID_DOC = SCTAB_MAX; // entire document, e.g. protect
+const SCROW SCROWS32K = 32000;
+const SCCOL SCCOL_REPEAT_NONE = SCCOL_MAX;
+const SCROW SCROW_REPEAT_NONE = SCROW_MAX;
+
+
+// We hope to get rid of the binary file format. If not, these are the places
+// we'd have to investigate because variable types changed. Just place code in
+// #if SC_ROWLIMIT_STREAM_ACCESS for now.
+#define SC_ROWLIMIT_STREAM_ACCESS 0
+// usage:
+//#if SC_ROWLIMIT_STREAM_ACCESS
+//#error address types changed!
+//... code ...
+//#endif // SC_ROWLIMIT_STREAM_ACCESS
+
+
+// For future reference, place in code where more than 64k rows would need a
+// special handling:
+// #if SC_ROWLIMIT_MORE_THAN_64K
+// #error row limit 64k
+// #endif
+#if MAXROWCOUNT_DEFINE > 65536
+#define SC_ROWLIMIT_MORE_THAN_64K 1
+#else
+#define SC_ROWLIMIT_MORE_THAN_64K 0
+#endif
+const SCROW SCROWS64K = 65536;
+
+// === old stuff defines =====================================================
+
+#define MAXROW_30 8191
+#define MAXROW_40 31999
+
+#ifdef SC_LIMIT_ROWS
+#undef MAXROWCOUNT_DEFINE
+#define MAXROWCOUNT_DEFINE 8192
+const SCROW W16MAXROWCOUNT = MAXROWCOUNT_DEFINE;
+const SCROW W16MAXROW = W16MAXROWCOUNT - 1;
+#define MAXROWCOUNT W16MAXROWCOUNT
+#define MAXROW W16MAXROW
+#endif
+
+#define VALIDCOL(nCol) (ValidCol(nCol))
+#define VALIDROW(nRow) (ValidRow(nRow))
+#define VALIDTAB(nTab) (ValidTab(nTab))
+#define VALIDCOLROW(nCol,nRow) (ValidColRow(nCol,nRow))
+#define VALIDCOLROWTAB(nCol,nRow,nTab) (ValidColRowTab(nCol,nRow,nTab))
+
+// === old stuff defines end =================================================
+
+inline bool ValidCol( SCCOL nCol )
+{
+ return static_cast<SCCOL>(0) <= nCol && nCol <= MAXCOL;
+}
+
+inline bool ValidRow( SCROW nRow )
+{
+ return static_cast<SCROW>(0) <= nRow && nRow <= MAXROW;
+}
+
+inline bool ValidTab( SCTAB nTab )
+{
+ return static_cast<SCTAB>(0) <= nTab && nTab <= MAXTAB;
+}
+
+inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
+{
+ return static_cast<SCTAB>(0) <= nTab && nTab <= nMaxTab;
+}
+
+inline bool ValidColRow( SCCOL nCol, SCROW nRow )
+{
+ return ValidCol( nCol) && ValidRow( nRow);
+}
+
+inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab )
+{
+ return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab);
+}
+
+inline SCCOL SanitizeCol( SCCOL nCol )
+{
+ return nCol < 0 ? 0 : (nCol > MAXCOL ? MAXCOL : nCol);
+}
+
+inline SCROW SanitizeRow( SCROW nRow )
+{
+ return nRow < 0 ? 0 : (nRow > MAXROW ? MAXROW : nRow);
+}
+
+inline SCTAB SanitizeTab( SCTAB nTab )
+{
+ return nTab < 0 ? 0 : (nTab > MAXTAB ? MAXTAB : nTab);
+}
+
+inline SCTAB SanitizeTab( SCTAB nTab, SCTAB nMaxTab )
+{
+ return nTab < 0 ? 0 : (nTab > nMaxTab ? nMaxTab : nTab);
+}
+
+// === ScAddress =============================================================
+
+// The old cell address is combined in one UINT32:
+// +---+---+-------+
+// |Tab|Col| Row |
+// +---+---+-------+
+// For speed reasons access isn't done by shifting bits but by using platform
+// dependent casts, which unfortunately also leads to aliasing problems when
+// not using gcc -fno-strict-aliasing
+
+// The result of ConvertRef() is a bit group of the following:
+
+#define SCA_COL_ABSOLUTE 0x01
+#define SCA_ROW_ABSOLUTE 0x02
+#define SCA_TAB_ABSOLUTE 0x04
+#define SCA_TAB_3D 0x08
+#define SCA_COL2_ABSOLUTE 0x10
+#define SCA_ROW2_ABSOLUTE 0x20
+#define SCA_TAB2_ABSOLUTE 0x40
+#define SCA_TAB2_3D 0x80
+#define SCA_VALID_ROW 0x0100
+#define SCA_VALID_COL 0x0200
+#define SCA_VALID_TAB 0x0400
+// somewhat cheesy kludge to force the display of the document name even for
+// local references. Requires TAB_3D to be valid
+#define SCA_FORCE_DOC 0x0800
+#define SCA_VALID_ROW2 0x1000
+#define SCA_VALID_COL2 0x2000
+#define SCA_VALID_TAB2 0x4000
+#define SCA_VALID 0x8000
+
+#define SCA_ABS SCA_VALID \
+ | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE
+
+#define SCR_ABS SCA_ABS \
+ | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE | SCA_TAB2_ABSOLUTE
+
+#define SCA_ABS_3D SCA_ABS | SCA_TAB_3D
+#define SCR_ABS_3D SCR_ABS | SCA_TAB_3D
+
+// === ScAddress =============================================================
+
+class ScAddress
+{
+private:
+ SCROW nRow;
+ SCCOL nCol;
+ SCTAB nTab;
+
+public:
+
+ enum Uninitialized { UNINITIALIZED };
+ enum InitializeInvalid { INITIALIZE_INVALID };
+
+ struct Details {
+ formula::FormulaGrammar::AddressConvention eConv;
+ SCROW nRow;
+ SCCOL nCol;
+ inline Details( formula::FormulaGrammar::AddressConvention eConvP, SCROW nRowP, SCCOL nColP )
+ : eConv( eConvP ), nRow( nRowP ), nCol( nColP )
+ {}
+ inline Details( formula::FormulaGrammar::AddressConvention eConvP, ScAddress const & rAddr )
+ : eConv( eConvP ), nRow( rAddr.Row() ), nCol( rAddr.Col() )
+ {}
+ inline Details( formula::FormulaGrammar::AddressConvention eConvP)
+ : eConv( eConvP ), nRow( 0 ), nCol( 0 )
+ {}
+ /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
+ Details( const ScDocument* pDoc, const ScAddress & rAddr );
+//UNUSED2009-05 void SetPos( const ScDocument* pDoc, const ScAddress & rAddr );
+ };
+ SC_DLLPUBLIC static const Details detailsOOOa1;
+
+ struct ExternalInfo
+ {
+ String maTabName;
+ sal_uInt16 mnFileId;
+ bool mbExternal;
+
+ inline ExternalInfo() : mnFileId(0), mbExternal(false) {}
+ };
+
+ inline ScAddress() : nRow(0), nCol(0), nTab(0) {}
+ inline ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
+ : nRow(nRowP), nCol(nColP), nTab(nTabP)
+ {}
+ /** Yes, it is what it seems to be: Uninitialized. May be used for
+ performance reasons if it is initialized by other means. */
+ inline ScAddress( Uninitialized ) {}
+ inline ScAddress( InitializeInvalid )
+ : nRow(-1), nCol(-1), nTab(-1) {}
+ inline ScAddress( const ScAddress& r )
+ : nRow(r.nRow), nCol(r.nCol), nTab(r.nTab)
+ {}
+ inline ScAddress& operator=( const ScAddress& r );
+
+ inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
+ inline SCROW Row() const { return nRow; }
+ inline SCCOL Col() const { return nCol; }
+ inline SCTAB Tab() const { return nTab; }
+ inline void SetRow( SCROW nRowP ) { nRow = nRowP; }
+ inline void SetCol( SCCOL nColP ) { nCol = nColP; }
+ inline void SetTab( SCTAB nTabP ) { nTab = nTabP; }
+ inline void SetInvalid() { nRow = -1; nCol = -1; nTab = -1; }
+ inline bool IsValid() const { return (nRow >= 0) && (nCol >= 0) && (nTab >= 0); }
+ inline void PutInOrder( ScAddress& r );
+ inline void IncRow( SCsROW n=1 ) { nRow = sal::static_int_cast<SCROW>(nRow + n); }
+ inline void IncCol( SCsCOL n=1 ) { nCol = sal::static_int_cast<SCCOL>(nCol + n); }
+ inline void IncTab( SCsTAB n=1 ) { nTab = sal::static_int_cast<SCTAB>(nTab + n); }
+ inline void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
+ { nColP = nCol; nRowP = nRow; nTabP = nTab; }
+
+ SC_DLLPUBLIC USHORT Parse( const String&, ScDocument* = NULL,
+ const Details& rDetails = detailsOOOa1,
+ ExternalInfo* pExtInfo = NULL,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
+
+ SC_DLLPUBLIC void Format( String&, USHORT = 0, ScDocument* = NULL,
+ const Details& rDetails = detailsOOOa1) const;
+
+ // The document for the maximum defined sheet number
+ SC_DLLPUBLIC bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL );
+ inline bool operator==( const ScAddress& r ) const;
+ inline bool operator!=( const ScAddress& r ) const;
+ inline bool operator<( const ScAddress& r ) const;
+ inline bool operator<=( const ScAddress& r ) const;
+ inline bool operator>( const ScAddress& r ) const;
+ inline bool operator>=( const ScAddress& r ) const;
+
+ inline size_t hash() const;
+
+ /// "A1" or "$A$1" or R1C1 or R[1]C[1]
+ String GetColRowString( bool bAbsolute = FALSE,
+ const Details& rDetails = detailsOOOa1) const;
+};
+
+inline void ScAddress::PutInOrder( ScAddress& r )
+{
+ if ( r.Col() < Col() )
+ {
+ SCCOL nTmp = r.Col();
+ r.SetCol( Col() );
+ SetCol( nTmp );
+ }
+ if ( r.Row() < Row() )
+ {
+ SCROW nTmp = r.Row();
+ r.SetRow( Row() );
+ SetRow( nTmp );
+ }
+ if ( r.Tab() < Tab() )
+ {
+ SCTAB nTmp = r.Tab();
+ r.SetTab( Tab() );
+ SetTab( nTmp );
+ }
+}
+
+inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
+{
+ nCol = nColP;
+ nRow = nRowP;
+ nTab = nTabP;
+}
+
+inline ScAddress& ScAddress::operator=( const ScAddress& r )
+{
+ nCol = r.nCol;
+ nRow = r.nRow;
+ nTab = r.nTab;
+ return *this;
+}
+
+inline bool ScAddress::operator==( const ScAddress& r ) const
+{
+ return nRow == r.nRow && nCol == r.nCol && nTab == r.nTab;
+}
+
+inline bool ScAddress::operator!=( const ScAddress& r ) const
+{
+ return !operator==( r );
+}
+
+inline bool ScAddress::operator<( const ScAddress& r ) const
+{
+ // Same behavior as the old UINT32 nAddress < r.nAddress with encoded
+ // tab|col|row bit fields.
+ if (nTab == r.nTab)
+ {
+ if (nCol == r.nCol)
+ return nRow < r.nRow;
+ else
+ return nCol < r.nCol;
+ }
+ else
+ return nTab < r.nTab;
+}
+
+inline bool ScAddress::operator<=( const ScAddress& r ) const
+{
+ return operator<( r ) || operator==( r );
+}
+
+inline bool ScAddress::operator>( const ScAddress& r ) const
+{
+ return !operator<=( r );
+}
+
+inline bool ScAddress::operator>=( const ScAddress& r ) const
+{
+ return !operator<( r );
+}
+
+
+inline size_t ScAddress::hash() const
+{
+ // Assume that there are not that many addresses with row > 2^16 AND column
+ // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
+ if (nRow <= 0xffff)
+ return (static_cast<size_t>(nTab) << 24) ^
+ (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
+ else
+ return (static_cast<size_t>(nTab) << 28) ^
+ (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
+}
+
+struct ScAddressHashFunctor
+{
+ size_t operator()( const ScAddress & rAdr ) const
+ {
+ return rAdr.hash();
+ }
+};
+
+struct ScAddressEqualFunctor
+{
+ bool operator()( const ScAddress & rAdr1, const ScAddress & rAdr2 ) const
+ {
+ return rAdr1 == rAdr2;
+ }
+};
+
+
+// === ScRange ===============================================================
+
+class ScRange
+{
+public:
+ ScAddress aStart, aEnd;
+ inline ScRange() : aStart(), aEnd() {}
+ inline ScRange( ScAddress::Uninitialized e )
+ : aStart( e ), aEnd( e ) {}
+ inline ScRange( ScAddress::InitializeInvalid e )
+ : aStart( e ), aEnd( e ) {}
+ inline ScRange( const ScAddress& s, const ScAddress& e )
+ : aStart( s ), aEnd( e ) { aStart.PutInOrder( aEnd ); }
+ inline ScRange( const ScRange& r ) : aStart( r.aStart ), aEnd( r.aEnd ) {}
+ inline ScRange( const ScAddress& r ) : aStart( r ), aEnd( r ) {}
+ inline ScRange( SCCOL nCol, SCROW nRow, SCTAB nTab )
+ : aStart( nCol, nRow, nTab ), aEnd( aStart ) {}
+ inline ScRange( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
+ SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
+ : aStart( nCol1, nRow1, nTab1 ), aEnd( nCol2, nRow2, nTab2 ) {}
+
+ inline ScRange& operator=( const ScRange& r )
+ { aStart = r.aStart; aEnd = r.aEnd; return *this; }
+ inline ScRange& operator=( const ScAddress& rPos )
+ { aStart = aEnd = rPos; return *this; }
+ inline void SetInvalid() { aStart.SetInvalid(); aEnd.SetInvalid(); }
+ inline bool IsValid() const { return aStart.IsValid() && aEnd.IsValid(); }
+ inline bool In( const ScAddress& ) const; // is Address& in Range?
+ inline bool In( const ScRange& ) const; // is Range& in Range?
+
+ USHORT Parse( const String&, ScDocument* = NULL,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
+
+ USHORT ParseAny( const String&, ScDocument* = NULL,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
+ SC_DLLPUBLIC USHORT ParseCols( const String&, ScDocument* = NULL,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
+ SC_DLLPUBLIC USHORT ParseRows( const String&, ScDocument* = NULL,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
+
+ /** Parse an Excel style reference up to and including the sheet name
+ separator '!', including detection of external documents and sheet
+ names, and in case of MOOXML import the bracketed index is used to
+ determine the actual document name passed in pExternalLinks. For
+ internal references (resulting rExternDocName empty), aStart.nTab and
+ aEnd.nTab are set, or -1 if sheet name not found.
+ @param bOnlyAcceptSingle If <TRUE/>, a 3D reference (Sheet1:Sheet2)
+ encountered results in an error (NULL returned).
+ @param pExternalLinks pointer to ExternalLinkInfo sequence, may be
+ NULL for non-filter usage, in which case indices such as [1] are
+ not resolved.
+ @returns
+ Pointer to the position after '!' if successfully parsed, and
+ rExternDocName, rStartTabName and/or rEndTabName filled if
+ applicable. SCA_... flags set in nFlags.
+ Or if no valid document and/or sheet header could be parsed the start
+ position passed with pString.
+ Or NULL if a 3D sheet header could be parsed but
+ bOnlyAcceptSingle==true was given.
+ */
+ const sal_Unicode* Parse_XL_Header( const sal_Unicode* pString, const ScDocument* pDoc,
+ String& rExternDocName, String& rStartTabName, String& rEndTabName, USHORT& nFlags,
+ bool bOnlyAcceptSingle,
+ const ::com::sun::star::uno::Sequence<
+ const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
+
+ SC_DLLPUBLIC void Format( String&, USHORT = 0, ScDocument* = NULL,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ) const;
+
+ inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
+ SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
+ // The document for the maximum defined sheet number
+ SC_DLLPUBLIC bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL );
+ SC_DLLPUBLIC void Justify();
+ SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
+ SC_DLLPUBLIC bool Intersects( const ScRange& ) const; // do two ranges intersect?
+ inline bool operator==( const ScRange& r ) const;
+ inline bool operator!=( const ScRange& r ) const;
+ inline bool operator<( const ScRange& r ) const;
+ inline bool operator<=( const ScRange& r ) const;
+ inline bool operator>( const ScRange& r ) const;
+ inline bool operator>=( const ScRange& r ) const;
+
+ /// Hash 2D area ignoring table number.
+ inline size_t hashArea() const;
+ /// Hash start column and start and end rows.
+ inline size_t hashStartColumn() const;
+};
+
+inline void ScRange::GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
+ SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const
+{
+ aStart.GetVars( nCol1, nRow1, nTab1 );
+ aEnd.GetVars( nCol2, nRow2, nTab2 );
+}
+
+inline bool ScRange::operator==( const ScRange& r ) const
+{
+ return ( (aStart == r.aStart) && (aEnd == r.aEnd) );
+}
+
+inline bool ScRange::operator!=( const ScRange& r ) const
+{
+ return !operator==( r );
+}
+
+// Sort on upper left corner, if equal then use lower right too.
+inline bool ScRange::operator<( const ScRange& r ) const
+{
+ return aStart < r.aStart || (aStart == r.aStart && aEnd < r.aEnd) ;
+}
+
+inline bool ScRange::operator<=( const ScRange& r ) const
+{
+ return operator<( r ) || operator==( r );
+}
+
+inline bool ScRange::operator>( const ScRange& r ) const
+{
+ return !operator<=( r );
+}
+
+inline bool ScRange::operator>=( const ScRange& r ) const
+{
+ return !operator<( r );
+}
+
+inline bool ScRange::In( const ScAddress& rAddr ) const
+{
+ return
+ aStart.Col() <= rAddr.Col() && rAddr.Col() <= aEnd.Col() &&
+ aStart.Row() <= rAddr.Row() && rAddr.Row() <= aEnd.Row() &&
+ aStart.Tab() <= rAddr.Tab() && rAddr.Tab() <= aEnd.Tab();
+}
+
+inline bool ScRange::In( const ScRange& r ) const
+{
+ return
+ aStart.Col() <= r.aStart.Col() && r.aEnd.Col() <= aEnd.Col() &&
+ aStart.Row() <= r.aStart.Row() && r.aEnd.Row() <= aEnd.Row() &&
+ aStart.Tab() <= r.aStart.Tab() && r.aEnd.Tab() <= aEnd.Tab();
+}
+
+
+inline size_t ScRange::hashArea() const
+{
+ // Assume that there are not that many ranges with identical corners so we
+ // won't have too many collisions. Also assume that more lower row and
+ // column numbers are used so that there are not too many conflicts with
+ // the columns hashed into the values, and that start row and column
+ // usually don't exceed certain values. High bits are not masked off and
+ // may overlap with lower bits of other values, e.g. if start column is
+ // greater than assumed.
+ return
+ (static_cast<size_t>(aStart.Row()) << 26) ^ // start row <= 2^6
+ (static_cast<size_t>(aStart.Col()) << 21) ^ // start column <= 2^5
+ (static_cast<size_t>(aEnd.Col()) << 15) ^ // end column <= 2^6
+ static_cast<size_t>(aEnd.Row()); // end row <= 2^15
+}
+
+
+inline size_t ScRange::hashStartColumn() const
+{
+ // Assume that for the start row more lower row numbers are used so that
+ // there are not too many conflicts with the column hashed into the higher
+ // values.
+ return
+ (static_cast<size_t>(aStart.Col()) << 24) ^ // start column <= 2^8
+ (static_cast<size_t>(aStart.Row()) << 16) ^ // start row <= 2^8
+ static_cast<size_t>(aEnd.Row());
+}
+
+
+struct ScRangeHashAreaFunctor
+{
+ size_t operator()( const ScRange & rRange ) const
+ {
+ return rRange.hashArea();
+ }
+};
+
+struct ScRangeEqualFunctor
+{
+ bool operator()( const ScRange & rRange1, const ScRange & rRange2 ) const
+ {
+ return rRange1 == rRange2;
+ }
+};
+
+
+// === ScRangePair ===========================================================
+
+class ScRangePair
+{
+private:
+ ScRange aRange[2];
+
+public:
+ ScRangePair() {}
+ ScRangePair( const ScRangePair& r )
+ { aRange[0] = r.aRange[0]; aRange[1] = r.aRange[1]; }
+ ScRangePair( const ScRange& r1, const ScRange& r2 )
+ { aRange[0] = r1; aRange[1] = r2; }
+
+ inline ScRangePair& operator= ( const ScRangePair& r );
+ const ScRange& GetRange( USHORT n ) const { return aRange[n]; }
+ ScRange& GetRange( USHORT n ) { return aRange[n]; }
+ inline int operator==( const ScRangePair& ) const;
+ inline int operator!=( const ScRangePair& ) const;
+};
+
+inline ScRangePair& ScRangePair::operator= ( const ScRangePair& r )
+{
+ aRange[0] = r.aRange[0];
+ aRange[1] = r.aRange[1];
+ return *this;
+}
+
+inline int ScRangePair::operator==( const ScRangePair& r ) const
+{
+ return ( (aRange[0] == r.aRange[0]) && (aRange[1] == r.aRange[1]) );
+}
+
+inline int ScRangePair::operator!=( const ScRangePair& r ) const
+{
+ return !operator==( r );
+}
+
+// === ScRefAddress ==========================================================
+
+class ScRefAddress
+{
+ ScAddress aAdr;
+ bool bRelCol;
+ bool bRelRow;
+ bool bRelTab;
+public:
+ inline ScRefAddress() : bRelCol(false), bRelRow(false), bRelTab(false)
+ {}
+ inline ScRefAddress( SCCOL nCol, SCROW nRow, SCTAB nTab,
+ bool bRelColP, bool bRelRowP, bool bRelTabP ) :
+ aAdr(nCol, nRow, nTab),
+ bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP)
+ {}
+ inline ScRefAddress( const ScAddress& rAdr,
+ bool bRelColP, bool bRelRowP, bool bRelTabP ) :
+ aAdr(rAdr),
+ bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP)
+ {}
+ inline ScRefAddress( const ScRefAddress& rRef ) :
+ aAdr(rRef.aAdr), bRelCol(rRef.bRelCol), bRelRow(rRef.bRelRow),
+ bRelTab(rRef.bRelTab)
+ {}
+
+ inline ScRefAddress& operator=( const ScRefAddress& );
+
+ inline bool IsRelCol() const { return bRelCol; }
+ inline bool IsRelRow() const { return bRelRow; }
+ inline bool IsRelTab() const { return bRelTab; }
+
+ inline void SetRelCol(bool bNewRelCol) { bRelCol = bNewRelCol; }
+ inline void SetRelRow(bool bNewRelRow) { bRelRow = bNewRelRow; }
+ inline void SetRelTab(bool bNewRelTab) { bRelTab = bNewRelTab; }
+
+ inline void Set( const ScAddress& rAdr,
+ bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
+ inline void Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
+ bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
+
+ inline const ScAddress& GetAddress() const { return aAdr; }
+ inline SCCOL Col() const { return aAdr.Col(); }
+ inline SCROW Row() const { return aAdr.Row(); }
+ inline SCTAB Tab() const { return aAdr.Tab(); }
+
+ inline int operator == ( const ScRefAddress& r ) const;
+ inline int operator != ( const ScRefAddress& r ) const
+ { return !(operator==(r)); }
+
+ String GetRefString( ScDocument* pDoc, SCTAB nActTab,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1) const;
+};
+
+inline ScRefAddress& ScRefAddress::operator=( const ScRefAddress& rRef )
+{
+ aAdr = rRef.aAdr;
+ bRelCol = rRef.bRelCol;
+ bRelRow = rRef.bRelRow;
+ bRelTab = rRef.bRelTab;
+ return *this;
+}
+
+inline void ScRefAddress::Set( const ScAddress& rAdr,
+ bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
+{
+ aAdr = rAdr;
+ bRelCol = bNewRelCol;
+ bRelRow = bNewRelRow;
+ bRelTab = bNewRelTab;
+}
+
+inline void ScRefAddress::Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
+ bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
+{
+ aAdr.Set( nNewCol, nNewRow, nNewTab);
+ bRelCol = bNewRelCol;
+ bRelRow = bNewRelRow;
+ bRelTab = bNewRelTab;
+}
+
+inline int ScRefAddress::operator==( const ScRefAddress& r ) const
+{
+ return aAdr == r.aAdr && bRelCol == r.bRelCol && bRelRow == r.bRelRow &&
+ bRelTab == r.bRelTab;
+}
+
+// ===========================================================================
+// Global functions
+// ===========================================================================
+
+// Special values for cells always broadcasting or listening (RECALCMODE_ALWAYS
+// and the like).
+#define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
+#define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
+
+template< typename T > void PutInOrder( T& nStart, T& nEnd )
+{
+ if (nEnd < nStart)
+ {
+ T nTemp;
+ nTemp = nEnd;
+ nEnd = nStart;
+ nStart = nTemp;
+ }
+}
+
+bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+ SCTAB nDefTab, ScRefAddress& rRefAddress,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL );
+
+bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString,
+ SCTAB nDefTab, ScRefAddress& rStartRefAddress,
+ ScRefAddress& rEndRefAddress,
+ const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
+ ScAddress::ExternalInfo* pExtInfo = NULL );
+
+/// append alpha representation of column to buffer
+SC_DLLPUBLIC void ScColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol);
+
+inline void ScColToAlpha( String& rStr, SCCOL nCol)
+{
+ rtl::OUStringBuffer aBuf(2);
+ ScColToAlpha( aBuf, nCol);
+ rStr.Append( aBuf.getStr(), static_cast<xub_StrLen>(aBuf.getLength()));
+}
+
+inline String ScColToAlpha( SCCOL nCol )
+{
+ rtl::OUStringBuffer aBuf(2);
+ ScColToAlpha( aBuf, nCol);
+ return aBuf.makeStringAndClear();
+}
+
+/// get column number of A..IV... string
+bool AlphaToCol( SCCOL& rCol, const String& rStr);
+
+#endif // SC_ADDRESS_HXX
+