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