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