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