| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 sal_uInt16 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&, sal_uInt16 = 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 = sal_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 sal_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? |
| |
| sal_uInt16 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 ); |
| |
| sal_uInt16 ParseAny( const String&, ScDocument* = NULL, |
| const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ); |
| SC_DLLPUBLIC sal_uInt16 ParseCols( const String&, ScDocument* = NULL, |
| const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ); |
| SC_DLLPUBLIC sal_uInt16 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, sal_uInt16& nFlags, |
| bool bOnlyAcceptSingle, |
| const ::com::sun::star::uno::Sequence< |
| const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL ); |
| |
| SC_DLLPUBLIC void Format( String&, sal_uInt16 = 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( sal_uInt16 n ) const { return aRange[n]; } |
| ScRange& GetRange( sal_uInt16 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 |
| |