xref: /trunk/main/sc/inc/address.hxx (revision 38d50f7b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef SC_ADDRESS_HXX
25 #define SC_ADDRESS_HXX
26 
27 #include <tools/stream.hxx>
28 #include <tools/string.hxx>
29 #include <tools/solar.h>
30 #include <tools/debug.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <osl/endian.h>
33 
34 #ifndef INCLUDED_LIMITS
35 #include <limits>
36 #define INCLUDED_LIMITS
37 #endif
38 #include "scdllapi.h"
39 #include <formula/grammar.hxx>
40 
41 #include <com/sun/star/uno/Sequence.hxx>
42 
43 namespace com { namespace sun { namespace star {
44     namespace sheet {
45         struct ExternalLinkInfo;
46     }
47 }}}
48 
49 class ScDocument;
50 
51 // The typedefs
52 typedef sal_Int32 SCROW;
53 typedef sal_Int16 SCCOL;
54 typedef sal_Int16 SCTAB;
55 typedef sal_Int32 SCCOLROW;     // a type capable of holding either SCCOL or SCROW
56 
57 // temporarily signed typedefs
58 typedef sal_Int32 SCsROW;
59 typedef sal_Int16 SCsCOL;
60 typedef sal_Int16 SCsTAB;
61 typedef sal_Int32 SCsCOLROW;
62 
63 // size_t typedef to be able to find places where code was changed from USHORT
64 // to size_t and is used to read/write from/to streams.
65 typedef size_t SCSIZE;
66 
67 // Maximum possible value of data type, NOT maximum row value.
68 // MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is
69 // included, we should not be using those stupid macros anyway.
70 #undef min
71 #undef max
72 const SCROW    SCROW_MAX    = ::std::numeric_limits<SCROW>::max();
73 const SCCOL    SCCOL_MAX    = ::std::numeric_limits<SCCOL>::max();
74 const SCTAB    SCTAB_MAX    = ::std::numeric_limits<SCTAB>::max();
75 const SCCOLROW SCCOLROW_MAX = ::std::numeric_limits<SCCOLROW>::max();
76 const SCSIZE   SCSIZE_MAX   = ::std::numeric_limits<SCSIZE>::max();
77 
78 // A define to handle critical sections we hopefully don't need very often.
79 #define SC_ROWLIMIT_MORE_THAN_32K 1     /* set to 1 if we throw the switch */
80 
81 // The maximum values. Defines are needed for preprocessor checks, for example
82 // in bcaslot.cxx, otherwise type safe constants are preferred.
83 //#define MAXROWCOUNT_DEFINE 65536
84 #define MAXROWCOUNT_DEFINE 1048576
85 #define MAXCOLCOUNT_DEFINE 1024
86 
87 // Count values
88 const SCROW       MAXROWCOUNT    = MAXROWCOUNT_DEFINE;
89 const SCCOL       MAXCOLCOUNT    = MAXCOLCOUNT_DEFINE;
90 const SCTAB       MAXTABCOUNT    = 256;
91 const SCCOLROW    MAXCOLROWCOUNT = MAXROWCOUNT;
92 // Maximum values
93 const SCROW       MAXROW         = MAXROWCOUNT - 1;
94 const SCCOL       MAXCOL         = MAXCOLCOUNT - 1;
95 const SCTAB       MAXTAB         = MAXTABCOUNT - 1;
96 const SCCOLROW    MAXCOLROW      = MAXROW;
97 
98 
99 // Special values
100 const SCTAB SC_TAB_APPEND     = SCTAB_MAX;
101 const SCTAB TABLEID_DOC       = SCTAB_MAX;  // entire document, e.g. protect
102 const SCROW SCROWS32K         = 32000;
103 const SCCOL SCCOL_REPEAT_NONE = SCCOL_MAX;
104 const SCROW SCROW_REPEAT_NONE = SCROW_MAX;
105 
106 
107 // We hope to get rid of the binary file format. If not, these are the places
108 // we'd have to investigate because variable types changed. Just place code in
109 // #if SC_ROWLIMIT_STREAM_ACCESS for now.
110 #define SC_ROWLIMIT_STREAM_ACCESS 0
111 // usage:
112 //#if SC_ROWLIMIT_STREAM_ACCESS
113 //#error address types changed!
114 //... code ...
115 //#endif // SC_ROWLIMIT_STREAM_ACCESS
116 
117 
118 // For future reference, place in code where more than 64k rows would need a
119 // special handling:
120 // #if SC_ROWLIMIT_MORE_THAN_64K
121 // #error row limit 64k
122 // #endif
123 #if MAXROWCOUNT_DEFINE > 65536
124 #define SC_ROWLIMIT_MORE_THAN_64K 1
125 #else
126 #define SC_ROWLIMIT_MORE_THAN_64K 0
127 #endif
128 const SCROW SCROWS64K = 65536;
129 
130 // === old stuff defines =====================================================
131 
132 #define MAXROW_30   8191
133 #define MAXROW_40   31999
134 
135 #ifdef SC_LIMIT_ROWS
136 #undef MAXROWCOUNT_DEFINE
137 #define MAXROWCOUNT_DEFINE 8192
138 const SCROW W16MAXROWCOUNT = MAXROWCOUNT_DEFINE;
139 const SCROW W16MAXROW = W16MAXROWCOUNT - 1;
140 #define MAXROWCOUNT W16MAXROWCOUNT
141 #define MAXROW      W16MAXROW
142 #endif
143 
144 #define VALIDCOL(nCol)                  (ValidCol(nCol))
145 #define VALIDROW(nRow)                  (ValidRow(nRow))
146 #define VALIDTAB(nTab)                  (ValidTab(nTab))
147 #define VALIDCOLROW(nCol,nRow)          (ValidColRow(nCol,nRow))
148 #define VALIDCOLROWTAB(nCol,nRow,nTab)  (ValidColRowTab(nCol,nRow,nTab))
149 
150 // === old stuff defines end =================================================
151 
ValidCol(SCCOL nCol)152 inline bool ValidCol( SCCOL nCol )
153 {
154     return static_cast<SCCOL>(0) <= nCol && nCol <= MAXCOL;
155 }
156 
ValidRow(SCROW nRow)157 inline bool ValidRow( SCROW nRow )
158 {
159     return static_cast<SCROW>(0) <= nRow && nRow <= MAXROW;
160 }
161 
ValidTab(SCTAB nTab)162 inline bool ValidTab( SCTAB nTab )
163 {
164     return static_cast<SCTAB>(0) <= nTab && nTab <= MAXTAB;
165 }
166 
ValidTab(SCTAB nTab,SCTAB nMaxTab)167 inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
168 {
169     return static_cast<SCTAB>(0) <= nTab && nTab <= nMaxTab;
170 }
171 
ValidColRow(SCCOL nCol,SCROW nRow)172 inline bool ValidColRow( SCCOL nCol, SCROW nRow )
173 {
174     return ValidCol( nCol) && ValidRow( nRow);
175 }
176 
ValidColRowTab(SCCOL nCol,SCROW nRow,SCTAB nTab)177 inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab )
178 {
179     return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab);
180 }
181 
SanitizeCol(SCCOL nCol)182 inline SCCOL SanitizeCol( SCCOL nCol )
183 {
184     return nCol < 0 ? 0 : (nCol > MAXCOL ? MAXCOL : nCol);
185 }
186 
SanitizeRow(SCROW nRow)187 inline SCROW SanitizeRow( SCROW nRow )
188 {
189     return nRow < 0 ? 0 : (nRow > MAXROW ? MAXROW : nRow);
190 }
191 
SanitizeTab(SCTAB nTab)192 inline SCTAB SanitizeTab( SCTAB nTab )
193 {
194     return nTab < 0 ? 0 : (nTab > MAXTAB ? MAXTAB : nTab);
195 }
196 
SanitizeTab(SCTAB nTab,SCTAB nMaxTab)197 inline SCTAB SanitizeTab( SCTAB nTab, SCTAB nMaxTab )
198 {
199     return nTab < 0 ? 0 : (nTab > nMaxTab ? nMaxTab : nTab);
200 }
201 
202 // === ScAddress =============================================================
203 
204 // The old cell address is combined in one UINT32:
205 // +---+---+-------+
206 // |Tab|Col|  Row  |
207 // +---+---+-------+
208 // For speed reasons access isn't done by shifting bits but by using platform
209 // dependent casts, which unfortunately also leads to aliasing problems when
210 // not using gcc -fno-strict-aliasing
211 
212 // The result of ConvertRef() is a bit group of the following:
213 
214 #define SCA_COL_ABSOLUTE    0x01
215 #define SCA_ROW_ABSOLUTE    0x02
216 #define SCA_TAB_ABSOLUTE    0x04
217 #define SCA_TAB_3D          0x08
218 #define SCA_COL2_ABSOLUTE   0x10
219 #define SCA_ROW2_ABSOLUTE   0x20
220 #define SCA_TAB2_ABSOLUTE   0x40
221 #define SCA_TAB2_3D         0x80
222 #define SCA_VALID_ROW       0x0100
223 #define SCA_VALID_COL       0x0200
224 #define SCA_VALID_TAB       0x0400
225 // somewhat cheesy kludge to force the display of the document name even for
226 // local references.  Requires TAB_3D to be valid
227 #define SCA_FORCE_DOC       0x0800
228 #define SCA_VALID_ROW2      0x1000
229 #define SCA_VALID_COL2      0x2000
230 #define SCA_VALID_TAB2      0x4000
231 #define SCA_VALID           0x8000
232 
233 #define SCA_ABS               SCA_VALID \
234                             | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE
235 
236 #define SCR_ABS               SCA_ABS \
237                             | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE | SCA_TAB2_ABSOLUTE
238 
239 #define SCA_ABS_3D          SCA_ABS | SCA_TAB_3D
240 #define SCR_ABS_3D          SCR_ABS | SCA_TAB_3D
241 
242 // === ScAddress =============================================================
243 
244 class ScAddress
245 {
246 private:
247     SCROW   nRow;
248     SCCOL   nCol;
249     SCTAB   nTab;
250 
251 public:
252 
253     enum Uninitialized      { UNINITIALIZED };
254     enum InitializeInvalid  { INITIALIZE_INVALID };
255 
256     struct Details {
257         formula::FormulaGrammar::AddressConvention  eConv;
258         SCROW       nRow;
259         SCCOL       nCol;
DetailsScAddress::Details260         inline Details( formula::FormulaGrammar::AddressConvention eConvP, SCROW nRowP, SCCOL nColP )
261             : eConv( eConvP ), nRow( nRowP ), nCol( nColP )
262             {}
DetailsScAddress::Details263         inline Details( formula::FormulaGrammar::AddressConvention eConvP, ScAddress const & rAddr )
264             : eConv( eConvP ), nRow( rAddr.Row() ), nCol( rAddr.Col() )
265             {}
DetailsScAddress::Details266         inline Details( formula::FormulaGrammar::AddressConvention eConvP)
267             : eConv( eConvP ), nRow( 0 ), nCol( 0 )
268             {}
269         /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
270         Details( const ScDocument* pDoc, const ScAddress & rAddr );
271 //UNUSED2009-05 void SetPos( const ScDocument* pDoc, const ScAddress & rAddr );
272     };
273     SC_DLLPUBLIC static const Details detailsOOOa1;
274 
275     struct ExternalInfo
276     {
277         String      maTabName;
278         sal_uInt16  mnFileId;
279         bool        mbExternal;
280 
ExternalInfoScAddress::ExternalInfo281         inline ExternalInfo() : mnFileId(0), mbExternal(false) {}
282     };
283 
ScAddress()284     inline ScAddress() : nRow(0), nCol(0), nTab(0) {}
ScAddress(SCCOL nColP,SCROW nRowP,SCTAB nTabP)285     inline ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
286         : nRow(nRowP), nCol(nColP), nTab(nTabP)
287         {}
288     /** Yes, it is what it seems to be: Uninitialized. May be used for
289         performance reasons if it is initialized by other means. */
ScAddress(Uninitialized)290     inline ScAddress( Uninitialized ) {}
ScAddress(InitializeInvalid)291     inline ScAddress( InitializeInvalid )
292         : nRow(-1), nCol(-1), nTab(-1) {}
ScAddress(const ScAddress & r)293     inline ScAddress( const ScAddress& r )
294         : nRow(r.nRow), nCol(r.nCol), nTab(r.nTab)
295         {}
296     inline ScAddress& operator=( const ScAddress& r );
297 
298     inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
Row() const299     inline SCROW Row() const { return nRow; }
Col() const300     inline SCCOL Col() const { return nCol; }
Tab() const301     inline SCTAB Tab() const { return nTab; }
SetRow(SCROW nRowP)302     inline void SetRow( SCROW nRowP ) { nRow = nRowP; }
SetCol(SCCOL nColP)303     inline void SetCol( SCCOL nColP ) { nCol = nColP; }
SetTab(SCTAB nTabP)304     inline void SetTab( SCTAB nTabP ) { nTab = nTabP; }
SetInvalid()305     inline void SetInvalid() { nRow = -1; nCol = -1; nTab = -1; }
IsValid() const306     inline bool IsValid() const { return (nRow >= 0) && (nCol >= 0) && (nTab >= 0); }
307     inline void PutInOrder( ScAddress& r );
IncRow(SCsROW n=1)308     inline void IncRow( SCsROW n=1 ) { nRow = sal::static_int_cast<SCROW>(nRow + n); }
IncCol(SCsCOL n=1)309     inline void IncCol( SCsCOL n=1 ) { nCol = sal::static_int_cast<SCCOL>(nCol + n); }
IncTab(SCsTAB n=1)310     inline void IncTab( SCsTAB n=1 ) { nTab = sal::static_int_cast<SCTAB>(nTab + n); }
GetVars(SCCOL & nColP,SCROW & nRowP,SCTAB & nTabP) const311     inline void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
312     { nColP = nCol; nRowP = nRow; nTabP = nTab; }
313 
314     SC_DLLPUBLIC sal_uInt16 Parse( const String&, ScDocument* = NULL,
315                   const Details& rDetails = detailsOOOa1,
316                   ExternalInfo* pExtInfo = NULL,
317                   const ::com::sun::star::uno::Sequence<
318                     const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
319 
320     SC_DLLPUBLIC void Format( String&, sal_uInt16 = 0, ScDocument* = NULL,
321                  const Details& rDetails = detailsOOOa1) const;
322 
323     // The document for the maximum defined sheet number
324     SC_DLLPUBLIC bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL );
325     inline bool operator==( const ScAddress& r ) const;
326     inline bool operator!=( const ScAddress& r ) const;
327     inline bool operator<( const ScAddress& r ) const;
328     inline bool operator<=( const ScAddress& r ) const;
329     inline bool operator>( const ScAddress& r ) const;
330     inline bool operator>=( const ScAddress& r ) const;
331 
332     inline size_t hash() const;
333 
334     /// "A1" or "$A$1" or R1C1 or R[1]C[1]
335     String GetColRowString( bool bAbsolute = sal_False,
336                             const Details& rDetails = detailsOOOa1) const;
337 };
338 
PutInOrder(ScAddress & r)339 inline void ScAddress::PutInOrder( ScAddress& r )
340 {
341     if ( r.Col() < Col() )
342     {
343         SCCOL nTmp = r.Col();
344         r.SetCol( Col() );
345         SetCol( nTmp );
346     }
347     if ( r.Row() < Row() )
348     {
349         SCROW nTmp = r.Row();
350         r.SetRow( Row() );
351         SetRow( nTmp );
352     }
353     if ( r.Tab() < Tab() )
354     {
355         SCTAB nTmp = r.Tab();
356         r.SetTab( Tab() );
357         SetTab( nTmp );
358     }
359 }
360 
Set(SCCOL nColP,SCROW nRowP,SCTAB nTabP)361 inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
362 {
363     nCol = nColP;
364     nRow = nRowP;
365     nTab = nTabP;
366 }
367 
operator =(const ScAddress & r)368 inline ScAddress& ScAddress::operator=( const ScAddress& r )
369 {
370     nCol = r.nCol;
371     nRow = r.nRow;
372     nTab = r.nTab;
373     return *this;
374 }
375 
operator ==(const ScAddress & r) const376 inline bool ScAddress::operator==( const ScAddress& r ) const
377 {
378     return nRow == r.nRow && nCol == r.nCol && nTab == r.nTab;
379 }
380 
operator !=(const ScAddress & r) const381 inline bool ScAddress::operator!=( const ScAddress& r ) const
382 {
383     return !operator==( r );
384 }
385 
operator <(const ScAddress & r) const386 inline bool ScAddress::operator<( const ScAddress& r ) const
387 {
388     // Same behavior as the old sal_uInt32 nAddress < r.nAddress with encoded
389     // tab|col|row bit fields.
390     if (nTab == r.nTab)
391     {
392         if (nCol == r.nCol)
393             return nRow < r.nRow;
394         else
395             return nCol < r.nCol;
396     }
397     else
398         return nTab < r.nTab;
399 }
400 
operator <=(const ScAddress & r) const401 inline bool ScAddress::operator<=( const ScAddress& r ) const
402 {
403     return operator<( r ) || operator==( r );
404 }
405 
operator >(const ScAddress & r) const406 inline bool ScAddress::operator>( const ScAddress& r ) const
407 {
408     return !operator<=( r );
409 }
410 
operator >=(const ScAddress & r) const411 inline bool ScAddress::operator>=( const ScAddress& r ) const
412 {
413     return !operator<( r );
414 }
415 
416 
hash() const417 inline size_t ScAddress::hash() const
418 {
419     // Assume that there are not that many addresses with row > 2^16 AND column
420     // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
421     if (nRow <= 0xffff)
422         return (static_cast<size_t>(nTab) << 24) ^
423             (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
424     else
425         return (static_cast<size_t>(nTab) << 28) ^
426             (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
427 }
428 
429 struct ScAddressHashFunctor
430 {
operator ()ScAddressHashFunctor431     size_t operator()( const ScAddress & rAdr ) const
432     {
433         return rAdr.hash();
434     }
435 };
436 
437 struct ScAddressEqualFunctor
438 {
operator ()ScAddressEqualFunctor439     bool operator()( const ScAddress & rAdr1, const ScAddress & rAdr2 ) const
440     {
441         return rAdr1 == rAdr2;
442     }
443 };
444 
445 
446 // === ScRange ===============================================================
447 
448 class ScRange
449 {
450 public:
451     ScAddress aStart, aEnd;
ScRange()452     inline ScRange() : aStart(), aEnd() {}
ScRange(ScAddress::Uninitialized e)453     inline ScRange( ScAddress::Uninitialized e )
454         : aStart( e ), aEnd( e ) {}
ScRange(ScAddress::InitializeInvalid e)455     inline ScRange( ScAddress::InitializeInvalid e )
456         : aStart( e ), aEnd( e ) {}
ScRange(const ScAddress & s,const ScAddress & e)457     inline ScRange( const ScAddress& s, const ScAddress& e )
458         : aStart( s ), aEnd( e ) { aStart.PutInOrder( aEnd ); }
ScRange(const ScRange & r)459     inline ScRange( const ScRange& r ) : aStart( r.aStart ), aEnd( r.aEnd ) {}
ScRange(const ScAddress & r)460     inline ScRange( const ScAddress& r ) : aStart( r ), aEnd( r ) {}
ScRange(SCCOL nCol,SCROW nRow,SCTAB nTab)461     inline ScRange( SCCOL nCol, SCROW nRow, SCTAB nTab )
462         : aStart( nCol, nRow, nTab ), aEnd( aStart ) {}
ScRange(SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2)463     inline ScRange( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
464              SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
465         : aStart( nCol1, nRow1, nTab1 ), aEnd( nCol2, nRow2, nTab2 ) {}
466 
operator =(const ScRange & r)467     inline ScRange& operator=( const ScRange& r )
468     { aStart = r.aStart; aEnd = r.aEnd; return *this; }
operator =(const ScAddress & rPos)469     inline ScRange& operator=( const ScAddress& rPos )
470     { aStart = aEnd = rPos; return *this; }
SetInvalid()471     inline void SetInvalid() { aStart.SetInvalid(); aEnd.SetInvalid(); }
IsValid() const472     inline bool IsValid() const { return aStart.IsValid() && aEnd.IsValid(); }
473     inline bool In( const ScAddress& ) const;   // is Address& in Range?
474     inline bool In( const ScRange& ) const;     // is Range& in Range?
475 
476     sal_uInt16 Parse( const String&, ScDocument* = NULL,
477                   const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
478                   ScAddress::ExternalInfo* pExtInfo = NULL,
479                   const ::com::sun::star::uno::Sequence<
480                     const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
481 
482     sal_uInt16 ParseAny( const String&, ScDocument* = NULL,
483                      const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
484     SC_DLLPUBLIC sal_uInt16 ParseCols( const String&, ScDocument* = NULL,
485                      const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
486     SC_DLLPUBLIC sal_uInt16 ParseRows( const String&, ScDocument* = NULL,
487                      const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
488 
489     /** Parse an Excel style reference up to and including the sheet name
490         separator '!', including detection of external documents and sheet
491         names, and in case of MOOXML import the bracketed index is used to
492         determine the actual document name passed in pExternalLinks. For
493         internal references (resulting rExternDocName empty), aStart.nTab and
494         aEnd.nTab are set, or -1 if sheet name not found.
495         @param bOnlyAcceptSingle  If <TRUE/>, a 3D reference (Sheet1:Sheet2)
496             encountered results in an error (NULL returned).
497         @param pExternalLinks  pointer to ExternalLinkInfo sequence, may be
498             NULL for non-filter usage, in which case indices such as [1] are
499             not resolved.
500         @returns
501             Pointer to the position after '!' if successfully parsed, and
502             rExternDocName, rStartTabName and/or rEndTabName filled if
503             applicable. SCA_... flags set in nFlags.
504             Or if no valid document and/or sheet header could be parsed the start
505             position passed with pString.
506             Or NULL if a 3D sheet header could be parsed but
507             bOnlyAcceptSingle==true was given.
508      */
509     const sal_Unicode* Parse_XL_Header( const sal_Unicode* pString, const ScDocument* pDoc,
510             String& rExternDocName, String& rStartTabName, String& rEndTabName, sal_uInt16& nFlags,
511             bool bOnlyAcceptSingle,
512             const ::com::sun::star::uno::Sequence<
513                 const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
514 
515     SC_DLLPUBLIC void Format( String&, sal_uInt16 = 0, ScDocument* = NULL,
516                  const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ) const;
517 
518     inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
519         SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
520     // The document for the maximum defined sheet number
521     SC_DLLPUBLIC bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL );
522     SC_DLLPUBLIC void Justify();
523     SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
524     SC_DLLPUBLIC bool Intersects( const ScRange& ) const;    // do two ranges intersect?
525     inline bool operator==( const ScRange& r ) const;
526     inline bool operator!=( const ScRange& r ) const;
527     inline bool operator<( const ScRange& r ) const;
528     inline bool operator<=( const ScRange& r ) const;
529     inline bool operator>( const ScRange& r ) const;
530     inline bool operator>=( const ScRange& r ) const;
531 
532     /// Hash 2D area ignoring table number.
533     inline size_t hashArea() const;
534     /// Hash start column and start and end rows.
535     inline size_t hashStartColumn() const;
536 };
537 
GetVars(SCCOL & nCol1,SCROW & nRow1,SCTAB & nTab1,SCCOL & nCol2,SCROW & nRow2,SCTAB & nTab2) const538 inline void ScRange::GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
539         SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const
540 {
541     aStart.GetVars( nCol1, nRow1, nTab1 );
542     aEnd.GetVars( nCol2, nRow2, nTab2 );
543 }
544 
operator ==(const ScRange & r) const545 inline bool ScRange::operator==( const ScRange& r ) const
546 {
547     return ( (aStart == r.aStart) && (aEnd == r.aEnd) );
548 }
549 
operator !=(const ScRange & r) const550 inline bool ScRange::operator!=( const ScRange& r ) const
551 {
552     return !operator==( r );
553 }
554 
555 // Sort on upper left corner, if equal then use lower right too.
operator <(const ScRange & r) const556 inline bool ScRange::operator<( const ScRange& r ) const
557 {
558     return aStart < r.aStart || (aStart == r.aStart && aEnd < r.aEnd) ;
559 }
560 
operator <=(const ScRange & r) const561 inline bool ScRange::operator<=( const ScRange& r ) const
562 {
563     return operator<( r ) || operator==( r );
564 }
565 
operator >(const ScRange & r) const566 inline bool ScRange::operator>( const ScRange& r ) const
567 {
568     return !operator<=( r );
569 }
570 
operator >=(const ScRange & r) const571 inline bool ScRange::operator>=( const ScRange& r ) const
572 {
573     return !operator<( r );
574 }
575 
In(const ScAddress & rAddr) const576 inline bool ScRange::In( const ScAddress& rAddr ) const
577 {
578     return
579         aStart.Col() <= rAddr.Col() && rAddr.Col() <= aEnd.Col() &&
580         aStart.Row() <= rAddr.Row() && rAddr.Row() <= aEnd.Row() &&
581         aStart.Tab() <= rAddr.Tab() && rAddr.Tab() <= aEnd.Tab();
582 }
583 
In(const ScRange & r) const584 inline bool ScRange::In( const ScRange& r ) const
585 {
586     return
587         aStart.Col() <= r.aStart.Col() && r.aEnd.Col() <= aEnd.Col() &&
588         aStart.Row() <= r.aStart.Row() && r.aEnd.Row() <= aEnd.Row() &&
589         aStart.Tab() <= r.aStart.Tab() && r.aEnd.Tab() <= aEnd.Tab();
590 }
591 
592 
hashArea() const593 inline size_t ScRange::hashArea() const
594 {
595     // Assume that there are not that many ranges with identical corners so we
596     // won't have too many collisions. Also assume that more lower row and
597     // column numbers are used so that there are not too many conflicts with
598     // the columns hashed into the values, and that start row and column
599     // usually don't exceed certain values. High bits are not masked off and
600     // may overlap with lower bits of other values, e.g. if start column is
601     // greater than assumed.
602     return
603         (static_cast<size_t>(aStart.Row()) << 26) ^ // start row <= 2^6
604         (static_cast<size_t>(aStart.Col()) << 21) ^ // start column <= 2^5
605         (static_cast<size_t>(aEnd.Col()) << 15) ^   // end column <= 2^6
606         static_cast<size_t>(aEnd.Row());            // end row <= 2^15
607 }
608 
609 
hashStartColumn() const610 inline size_t ScRange::hashStartColumn() const
611 {
612     // Assume that for the start row more lower row numbers are used so that
613     // there are not too many conflicts with the column hashed into the higher
614     // values.
615     return
616         (static_cast<size_t>(aStart.Col()) << 24) ^ // start column <= 2^8
617         (static_cast<size_t>(aStart.Row()) << 16) ^ // start row <= 2^8
618         static_cast<size_t>(aEnd.Row());
619 }
620 
621 
622 struct ScRangeHashAreaFunctor
623 {
operator ()ScRangeHashAreaFunctor624     size_t operator()( const ScRange & rRange ) const
625     {
626         return rRange.hashArea();
627     }
628 };
629 
630 struct ScRangeEqualFunctor
631 {
operator ()ScRangeEqualFunctor632     bool operator()( const ScRange & rRange1, const ScRange & rRange2 ) const
633     {
634         return rRange1 == rRange2;
635     }
636 };
637 
638 
639 // === ScRangePair ===========================================================
640 
641 class ScRangePair
642 {
643 private:
644     ScRange aRange[2];
645 
646 public:
ScRangePair()647     ScRangePair() {}
ScRangePair(const ScRangePair & r)648     ScRangePair( const ScRangePair& r )
649         { aRange[0] = r.aRange[0]; aRange[1] = r.aRange[1]; }
ScRangePair(const ScRange & r1,const ScRange & r2)650     ScRangePair( const ScRange& r1, const ScRange& r2 )
651         {  aRange[0] = r1; aRange[1] = r2; }
652 
653     inline ScRangePair& operator= ( const ScRangePair& r );
GetRange(sal_uInt16 n) const654     const ScRange&      GetRange( sal_uInt16 n ) const { return aRange[n]; }
GetRange(sal_uInt16 n)655     ScRange&            GetRange( sal_uInt16 n ) { return aRange[n]; }
656     inline int operator==( const ScRangePair& ) const;
657     inline int operator!=( const ScRangePair& ) const;
658 };
659 
operator =(const ScRangePair & r)660 inline ScRangePair& ScRangePair::operator= ( const ScRangePair& r )
661 {
662     aRange[0] = r.aRange[0];
663     aRange[1] = r.aRange[1];
664     return *this;
665 }
666 
operator ==(const ScRangePair & r) const667 inline int ScRangePair::operator==( const ScRangePair& r ) const
668 {
669     return ( (aRange[0] == r.aRange[0]) && (aRange[1] == r.aRange[1]) );
670 }
671 
operator !=(const ScRangePair & r) const672 inline int ScRangePair::operator!=( const ScRangePair& r ) const
673 {
674     return !operator==( r );
675 }
676 
677 // === ScRefAddress ==========================================================
678 
679 class ScRefAddress
680 {
681             ScAddress           aAdr;
682             bool                bRelCol;
683             bool                bRelRow;
684             bool                bRelTab;
685 public:
ScRefAddress()686     inline ScRefAddress() : bRelCol(false), bRelRow(false), bRelTab(false)
687         {}
ScRefAddress(SCCOL nCol,SCROW nRow,SCTAB nTab,bool bRelColP,bool bRelRowP,bool bRelTabP)688     inline ScRefAddress( SCCOL nCol, SCROW nRow, SCTAB nTab,
689             bool bRelColP, bool bRelRowP, bool bRelTabP ) :
690         aAdr(nCol, nRow, nTab),
691         bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP)
692         {}
ScRefAddress(const ScAddress & rAdr,bool bRelColP,bool bRelRowP,bool bRelTabP)693     inline ScRefAddress( const ScAddress& rAdr,
694             bool bRelColP, bool bRelRowP, bool bRelTabP ) :
695         aAdr(rAdr),
696         bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP)
697         {}
ScRefAddress(const ScRefAddress & rRef)698     inline ScRefAddress( const ScRefAddress& rRef ) :
699             aAdr(rRef.aAdr), bRelCol(rRef.bRelCol), bRelRow(rRef.bRelRow),
700             bRelTab(rRef.bRelTab)
701             {}
702 
703     inline  ScRefAddress&   operator=( const ScRefAddress& );
704 
IsRelCol() const705     inline  bool    IsRelCol() const { return bRelCol; }
IsRelRow() const706     inline  bool    IsRelRow() const { return bRelRow; }
IsRelTab() const707     inline  bool    IsRelTab() const { return bRelTab; }
708 
SetRelCol(bool bNewRelCol)709     inline  void    SetRelCol(bool bNewRelCol) { bRelCol = bNewRelCol; }
SetRelRow(bool bNewRelRow)710     inline  void    SetRelRow(bool bNewRelRow) { bRelRow = bNewRelRow; }
SetRelTab(bool bNewRelTab)711     inline  void    SetRelTab(bool bNewRelTab) { bRelTab = bNewRelTab; }
712 
713     inline  void    Set( const ScAddress& rAdr,
714                         bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
715     inline  void    Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
716                         bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
717 
GetAddress() const718     inline  const ScAddress&    GetAddress() const { return aAdr; }
Col() const719     inline  SCCOL   Col() const { return aAdr.Col(); }
Row() const720     inline  SCROW   Row() const { return aAdr.Row(); }
Tab() const721     inline  SCTAB   Tab() const { return aAdr.Tab(); }
722 
723     inline  int     operator == ( const ScRefAddress& r ) const;
operator !=(const ScRefAddress & r) const724     inline  int     operator != ( const ScRefAddress& r ) const
725                     { return !(operator==(r)); }
726 
727             String  GetRefString( ScDocument* pDoc, SCTAB nActTab,
728                                   const ScAddress::Details& rDetails = ScAddress::detailsOOOa1) const;
729 };
730 
operator =(const ScRefAddress & rRef)731 inline ScRefAddress& ScRefAddress::operator=( const ScRefAddress& rRef )
732 {
733     aAdr = rRef.aAdr;
734     bRelCol = rRef.bRelCol;
735     bRelRow = rRef.bRelRow;
736     bRelTab = rRef.bRelTab;
737     return *this;
738 }
739 
Set(const ScAddress & rAdr,bool bNewRelCol,bool bNewRelRow,bool bNewRelTab)740 inline void ScRefAddress::Set( const ScAddress& rAdr,
741         bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
742 {
743     aAdr = rAdr;
744     bRelCol = bNewRelCol;
745     bRelRow = bNewRelRow;
746     bRelTab = bNewRelTab;
747 }
748 
Set(SCCOL nNewCol,SCROW nNewRow,SCTAB nNewTab,bool bNewRelCol,bool bNewRelRow,bool bNewRelTab)749 inline void ScRefAddress::Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
750         bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
751 {
752     aAdr.Set( nNewCol, nNewRow, nNewTab);
753     bRelCol = bNewRelCol;
754     bRelRow = bNewRelRow;
755     bRelTab = bNewRelTab;
756 }
757 
operator ==(const ScRefAddress & r) const758 inline int ScRefAddress::operator==( const ScRefAddress& r ) const
759 {
760     return aAdr == r.aAdr && bRelCol == r.bRelCol && bRelRow == r.bRelRow &&
761         bRelTab == r.bRelTab;
762 }
763 
764 // ===========================================================================
765 // Global functions
766 // ===========================================================================
767 
768 // Special values for cells always broadcasting or listening (RECALCMODE_ALWAYS
769 // and the like).
770 #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
771 #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
772 
PutInOrder(T & nStart,T & nEnd)773 template< typename T > void PutInOrder( T& nStart, T& nEnd )
774 {
775     if (nEnd < nStart)
776     {
777         T nTemp;
778         nTemp = nEnd;
779         nEnd = nStart;
780         nStart = nTemp;
781     }
782 }
783 
784 bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
785         SCTAB nDefTab, ScRefAddress& rRefAddress,
786         const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
787         ScAddress::ExternalInfo* pExtInfo = NULL );
788 
789 bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString,
790         SCTAB nDefTab, ScRefAddress& rStartRefAddress,
791         ScRefAddress& rEndRefAddress,
792         const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
793         ScAddress::ExternalInfo* pExtInfo = NULL );
794 
795 /// append alpha representation of column to buffer
796 SC_DLLPUBLIC void ScColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol);
797 
ScColToAlpha(String & rStr,SCCOL nCol)798 inline void ScColToAlpha( String& rStr, SCCOL nCol)
799 {
800     rtl::OUStringBuffer aBuf(2);
801     ScColToAlpha( aBuf, nCol);
802     rStr.Append( aBuf.getStr(), static_cast<xub_StrLen>(aBuf.getLength()));
803 }
804 
ScColToAlpha(SCCOL nCol)805 inline String ScColToAlpha( SCCOL nCol )
806 {
807     rtl::OUStringBuffer aBuf(2);
808     ScColToAlpha( aBuf, nCol);
809     return aBuf.makeStringAndClear();
810 }
811 
812 /// get column number of A..IV... string
813 bool AlphaToCol( SCCOL& rCol, const String& rStr);
814 
815 #endif // SC_ADDRESS_HXX
816 
817