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 : // === old stuff defines end =================================================
125 :
126 3385351 : inline bool ValidCol( SCCOL nCol )
127 : {
128 3385351 : return static_cast<SCCOL>(0) <= nCol && nCol <= MAXCOL;
129 : }
130 :
131 35891097 : inline bool ValidRow( SCROW nRow )
132 : {
133 35891097 : return static_cast<SCROW>(0) <= nRow && nRow <= MAXROW;
134 : }
135 :
136 33708612 : inline bool ValidTab( SCTAB nTab )
137 : {
138 33708612 : return static_cast<SCTAB>(0) <= nTab && nTab <= MAXTAB;
139 : }
140 :
141 9158 : inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
142 : {
143 9158 : return static_cast<SCTAB>(0) <= nTab && nTab <= nMaxTab;
144 : }
145 :
146 308201 : inline bool ValidColRow( SCCOL nCol, SCROW nRow )
147 : {
148 308201 : return ValidCol( nCol) && ValidRow( nRow);
149 : }
150 :
151 29 : inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab )
152 : {
153 29 : return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab);
154 : }
155 :
156 812 : inline SCCOL SanitizeCol( SCCOL nCol )
157 : {
158 812 : return nCol < 0 ? 0 : (nCol > MAXCOL ? MAXCOL : nCol);
159 : }
160 :
161 812 : inline SCROW SanitizeRow( SCROW nRow )
162 : {
163 812 : return nRow < 0 ? 0 : (nRow > MAXROW ? MAXROW : nRow);
164 : }
165 :
166 : inline SCTAB SanitizeTab( SCTAB nTab )
167 : {
168 : return nTab < 0 ? 0 : (nTab > MAXTAB ? MAXTAB : nTab);
169 : }
170 :
171 : inline SCTAB SanitizeTab( SCTAB nTab, SCTAB nMaxTab )
172 : {
173 : return nTab < 0 ? 0 : (nTab > nMaxTab ? nMaxTab : nTab);
174 : }
175 :
176 : // === ScAddress =============================================================
177 :
178 : // The old cell address is combined in one UINT32:
179 : // +---+---+-------+
180 : // |Tab|Col| Row |
181 : // +---+---+-------+
182 : // For speed reasons access isn't done by shifting bits but by using platform
183 : // dependent casts, which unfortunately also leads to aliasing problems when
184 : // not using gcc -fno-strict-aliasing
185 :
186 : // The result of ConvertRef() is a bit group of the following:
187 :
188 : #define SCA_COL_ABSOLUTE 0x01
189 : #define SCA_ROW_ABSOLUTE 0x02
190 : #define SCA_TAB_ABSOLUTE 0x04
191 : #define SCA_TAB_3D 0x08
192 : #define SCA_COL2_ABSOLUTE 0x10
193 : #define SCA_ROW2_ABSOLUTE 0x20
194 : #define SCA_TAB2_ABSOLUTE 0x40
195 : #define SCA_TAB2_3D 0x80
196 : #define SCA_VALID_ROW 0x0100
197 : #define SCA_VALID_COL 0x0200
198 : #define SCA_VALID_TAB 0x0400
199 : // SCA_BITS is a convience for
200 : // (SCA_VALID_TAB | SCA_VALID_COL | SCA_VALID_ROW | SCA_TAB_3D | SCA_TAB_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_COL_ABSOLUTE)
201 : #define SCA_BITS 0x070F
202 : // somewhat cheesy kludge to force the display of the document name even for
203 : // local references. Requires TAB_3D to be valid
204 : #define SCA_FORCE_DOC 0x0800
205 : #define SCA_VALID_ROW2 0x1000
206 : #define SCA_VALID_COL2 0x2000
207 : #define SCA_VALID_TAB2 0x4000
208 : #define SCA_VALID 0x8000
209 :
210 : #define SCA_ABS SCA_VALID \
211 : | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE
212 :
213 : #define SCR_ABS SCA_ABS \
214 : | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE | SCA_TAB2_ABSOLUTE
215 :
216 : #define SCA_ABS_3D SCA_ABS | SCA_TAB_3D
217 : #define SCR_ABS_3D SCR_ABS | SCA_TAB_3D
218 :
219 : // === ScAddress =============================================================
220 :
221 : class ScAddress
222 : {
223 : private:
224 : SCROW nRow;
225 : SCCOL nCol;
226 : SCTAB nTab;
227 :
228 : public:
229 :
230 : enum Uninitialized { UNINITIALIZED };
231 : enum InitializeInvalid { INITIALIZE_INVALID };
232 :
233 : struct Details {
234 : formula::FormulaGrammar::AddressConvention eConv;
235 : SCROW nRow;
236 : SCCOL nCol;
237 355 : inline Details( formula::FormulaGrammar::AddressConvention eConvP, SCROW nRowP, SCCOL nColP )
238 355 : : eConv( eConvP ), nRow( nRowP ), nCol( nColP )
239 355 : {}
240 4362 : inline Details( formula::FormulaGrammar::AddressConvention eConvP, ScAddress const & rAddr )
241 4362 : : eConv( eConvP ), nRow( rAddr.Row() ), nCol( rAddr.Col() )
242 4362 : {}
243 1912 : inline Details( formula::FormulaGrammar::AddressConvention eConvP)
244 1912 : : eConv( eConvP ), nRow( 0 ), nCol( 0 )
245 1912 : {}
246 : /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
247 : Details( const ScDocument* pDoc, const ScAddress & rAddr );
248 : };
249 : SC_DLLPUBLIC static const Details detailsOOOa1;
250 :
251 4574 : struct ExternalInfo
252 : {
253 : OUString maTabName;
254 : sal_uInt16 mnFileId;
255 : bool mbExternal;
256 :
257 4574 : inline ExternalInfo() : mnFileId(0), mbExternal(false) {}
258 : };
259 :
260 160210 : inline ScAddress() : nRow(0), nCol(0), nTab(0) {}
261 1772833 : inline ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
262 1772833 : : nRow(nRowP), nCol(nColP), nTab(nTabP)
263 1772833 : {}
264 : /** Yes, it is what it seems to be: Uninitialized. May be used for
265 : performance reasons if it is initialized by other means. */
266 251192 : inline ScAddress( Uninitialized ) {}
267 310888 : inline ScAddress( InitializeInvalid )
268 310888 : : nRow(-1), nCol(-1), nTab(-1) {}
269 1782252 : inline ScAddress( const ScAddress& r )
270 1782252 : : nRow(r.nRow), nCol(r.nCol), nTab(r.nTab)
271 1782252 : {}
272 : inline ScAddress& operator=( const ScAddress& r );
273 :
274 : inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab );
275 44575909 : inline SCROW Row() const { return nRow; }
276 33190940 : inline SCCOL Col() const { return nCol; }
277 5495828 : inline SCTAB Tab() const { return nTab; }
278 21234323 : inline void SetRow( SCROW nRowP ) { nRow = nRowP; }
279 40459956 : inline void SetCol( SCCOL nColP ) { nCol = nColP; }
280 267686 : inline void SetTab( SCTAB nTabP ) { nTab = nTabP; }
281 94 : inline void SetInvalid() { nRow = -1; nCol = -1; nTab = -1; }
282 12080 : inline bool IsValid() const { return (nRow >= 0) && (nCol >= 0) && (nTab >= 0); }
283 : inline void PutInOrder( ScAddress& r );
284 2533 : inline void IncRow( SCsROW n=1 ) { nRow = sal::static_int_cast<SCROW>(nRow + n); }
285 32069 : inline void IncCol( SCsCOL n=1 ) { nCol = sal::static_int_cast<SCCOL>(nCol + n); }
286 467 : inline void IncTab( SCsTAB n=1 ) { nTab = sal::static_int_cast<SCTAB>(nTab + n); }
287 22182 : inline void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const
288 22182 : { nColP = nCol; nRowP = nRow; nTabP = nTab; }
289 :
290 : SC_DLLPUBLIC sal_uInt16 Parse( const String&, ScDocument* = NULL,
291 : const Details& rDetails = detailsOOOa1,
292 : ExternalInfo* pExtInfo = NULL,
293 : const ::com::sun::star::uno::Sequence<
294 : const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
295 :
296 : SC_DLLPUBLIC void Format( OUString&, sal_uInt16 = 0, const ScDocument* = NULL,
297 : const Details& rDetails = detailsOOOa1) const;
298 : SC_DLLPUBLIC void Format( String&, sal_uInt16 = 0, const ScDocument* = NULL,
299 : const Details& rDetails = detailsOOOa1) const;
300 :
301 : // The document for the maximum defined sheet number
302 : SC_DLLPUBLIC bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL );
303 : inline bool operator==( const ScAddress& r ) const;
304 : inline bool operator!=( const ScAddress& r ) const;
305 : inline bool operator<( const ScAddress& r ) const;
306 : inline bool operator<=( const ScAddress& r ) const;
307 : inline bool operator>( const ScAddress& r ) const;
308 : inline bool operator>=( const ScAddress& r ) const;
309 :
310 : inline size_t hash() const;
311 :
312 : /// "A1" or "$A$1" or R1C1 or R[1]C[1]
313 : String GetColRowString( bool bAbsolute = false,
314 : const Details& rDetails = detailsOOOa1) const;
315 : };
316 :
317 42035 : inline void ScAddress::PutInOrder( ScAddress& r )
318 : {
319 42035 : if ( r.Col() < Col() )
320 : {
321 0 : SCCOL nTmp = r.Col();
322 0 : r.SetCol( Col() );
323 0 : SetCol( nTmp );
324 : }
325 42035 : if ( r.Row() < Row() )
326 : {
327 0 : SCROW nTmp = r.Row();
328 0 : r.SetRow( Row() );
329 0 : SetRow( nTmp );
330 : }
331 42035 : if ( r.Tab() < Tab() )
332 : {
333 0 : SCTAB nTmp = r.Tab();
334 0 : r.SetTab( Tab() );
335 0 : SetTab( nTmp );
336 : }
337 42035 : }
338 :
339 28340 : inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
340 : {
341 28340 : nCol = nColP;
342 28340 : nRow = nRowP;
343 28340 : nTab = nTabP;
344 28340 : }
345 :
346 115454 : inline ScAddress& ScAddress::operator=( const ScAddress& r )
347 : {
348 115454 : nCol = r.nCol;
349 115454 : nRow = r.nRow;
350 115454 : nTab = r.nTab;
351 115454 : return *this;
352 : }
353 :
354 205681 : inline bool ScAddress::operator==( const ScAddress& r ) const
355 : {
356 205681 : return nRow == r.nRow && nCol == r.nCol && nTab == r.nTab;
357 : }
358 :
359 120138 : inline bool ScAddress::operator!=( const ScAddress& r ) const
360 : {
361 120138 : return !operator==( r );
362 : }
363 :
364 : /** Same behavior as the old sal_uInt32 nAddress < r.nAddress with encoded
365 : tab|col|row bit fields. */
366 284 : inline bool ScAddress::operator<( const ScAddress& r ) const
367 : {
368 284 : if (nTab == r.nTab)
369 : {
370 284 : if (nCol == r.nCol)
371 57 : return nRow < r.nRow;
372 : else
373 227 : return nCol < r.nCol;
374 : }
375 : else
376 0 : return nTab < r.nTab;
377 : }
378 :
379 : inline bool ScAddress::operator<=( const ScAddress& r ) const
380 : {
381 : return operator<( r ) || operator==( r );
382 : }
383 :
384 : inline bool ScAddress::operator>( const ScAddress& r ) const
385 : {
386 : return !operator<=( r );
387 : }
388 :
389 : inline bool ScAddress::operator>=( const ScAddress& r ) const
390 : {
391 : return !operator<( r );
392 : }
393 :
394 :
395 : inline size_t ScAddress::hash() const
396 : {
397 : // Assume that there are not that many addresses with row > 2^16 AND column
398 : // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
399 : if (nRow <= 0xffff)
400 : return (static_cast<size_t>(nTab) << 24) ^
401 : (static_cast<size_t>(nCol) << 16) ^ static_cast<size_t>(nRow);
402 : else
403 : return (static_cast<size_t>(nTab) << 28) ^
404 : (static_cast<size_t>(nCol) << 24) ^ static_cast<size_t>(nRow);
405 : }
406 :
407 : struct ScAddressHashFunctor
408 : {
409 : size_t operator()( const ScAddress & rAdr ) const
410 : {
411 : return rAdr.hash();
412 : }
413 : };
414 :
415 : struct ScAddressEqualFunctor
416 : {
417 : bool operator()( const ScAddress & rAdr1, const ScAddress & rAdr2 ) const
418 : {
419 : return rAdr1 == rAdr2;
420 : }
421 : };
422 :
423 :
424 : // === ScRange ===============================================================
425 :
426 : class ScRange
427 : {
428 : public:
429 : ScAddress aStart, aEnd;
430 67416 : inline ScRange() : aStart(), aEnd() {}
431 604 : inline ScRange( ScAddress::Uninitialized e )
432 604 : : aStart( e ), aEnd( e ) {}
433 390 : inline ScRange( ScAddress::InitializeInvalid e )
434 390 : : aStart( e ), aEnd( e ) {}
435 42027 : inline ScRange( const ScAddress& s, const ScAddress& e )
436 42027 : : aStart( s ), aEnd( e ) { aStart.PutInOrder( aEnd ); }
437 471378 : inline ScRange( const ScRange& r ) : aStart( r.aStart ), aEnd( r.aEnd ) {}
438 10156 : inline ScRange( const ScAddress& r ) : aStart( r ), aEnd( r ) {}
439 521033 : inline ScRange( SCCOL nCol, SCROW nRow, SCTAB nTab )
440 521033 : : aStart( nCol, nRow, nTab ), aEnd( aStart ) {}
441 47779 : inline ScRange( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
442 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
443 47779 : : aStart( nCol1, nRow1, nTab1 ), aEnd( nCol2, nRow2, nTab2 ) {}
444 :
445 46511 : inline ScRange& operator=( const ScRange& r )
446 46511 : { aStart = r.aStart; aEnd = r.aEnd; return *this; }
447 0 : inline ScRange& operator=( const ScAddress& rPos )
448 0 : { aStart = aEnd = rPos; return *this; }
449 40 : inline void SetInvalid() { aStart.SetInvalid(); aEnd.SetInvalid(); }
450 461 : inline bool IsValid() const { return aStart.IsValid() && aEnd.IsValid(); }
451 : inline bool In( const ScAddress& ) const; ///< is Address& in Range?
452 : inline bool In( const ScRange& ) const; ///< is Range& in Range?
453 :
454 : SC_DLLPUBLIC sal_uInt16 Parse( const String&, ScDocument* = NULL,
455 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
456 : ScAddress::ExternalInfo* pExtInfo = NULL,
457 : const ::com::sun::star::uno::Sequence<
458 : const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
459 :
460 : SC_DLLPUBLIC sal_uInt16 ParseAny( const String&, ScDocument* = NULL,
461 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
462 : SC_DLLPUBLIC sal_uInt16 ParseCols( const String&, ScDocument* = NULL,
463 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
464 : SC_DLLPUBLIC sal_uInt16 ParseRows( const String&, ScDocument* = NULL,
465 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
466 :
467 : /** Parse an Excel style reference up to and including the sheet name
468 : separator '!', including detection of external documents and sheet
469 : names, and in case of MOOXML import the bracketed index is used to
470 : determine the actual document name passed in pExternalLinks. For
471 : internal references (resulting rExternDocName empty), aStart.nTab and
472 : aEnd.nTab are set, or -1 if sheet name not found.
473 : @param bOnlyAcceptSingle If <TRUE/>, a 3D reference (Sheet1:Sheet2)
474 : encountered results in an error (NULL returned).
475 : @param pExternalLinks pointer to ExternalLinkInfo sequence, may be
476 : NULL for non-filter usage, in which case indices such as [1] are
477 : not resolved.
478 : @returns
479 : Pointer to the position after '!' if successfully parsed, and
480 : rExternDocName, rStartTabName and/or rEndTabName filled if
481 : applicable. SCA_... flags set in nFlags.
482 : Or if no valid document and/or sheet header could be parsed the start
483 : position passed with pString.
484 : Or NULL if a 3D sheet header could be parsed but
485 : bOnlyAcceptSingle==true was given.
486 : */
487 : const sal_Unicode* Parse_XL_Header( const sal_Unicode* pString, const ScDocument* pDoc,
488 : String& rExternDocName, String& rStartTabName, String& rEndTabName, sal_uInt16& nFlags,
489 : bool bOnlyAcceptSingle,
490 : const ::com::sun::star::uno::Sequence<
491 : const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks = NULL );
492 :
493 : SC_DLLPUBLIC void Format( String&, sal_uInt16 = 0, const ScDocument* = NULL,
494 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ) const;
495 :
496 : SC_DLLPUBLIC void Format( OUString&, sal_uInt16 = 0, const ScDocument* = NULL,
497 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ) const;
498 :
499 : inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
500 : SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
501 : // The document for the maximum defined sheet number
502 : SC_DLLPUBLIC bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL );
503 : SC_DLLPUBLIC void Justify();
504 : SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
505 : SC_DLLPUBLIC bool Intersects( const ScRange& ) const; // do two ranges intersect?
506 : inline bool operator==( const ScRange& r ) const;
507 : inline bool operator!=( const ScRange& r ) const;
508 : inline bool operator<( const ScRange& r ) const;
509 : inline bool operator<=( const ScRange& r ) const;
510 : inline bool operator>( const ScRange& r ) const;
511 : inline bool operator>=( const ScRange& r ) const;
512 :
513 : /// Hash 2D area ignoring table number.
514 : inline size_t hashArea() const;
515 : /// Hash start column and start and end rows.
516 : inline size_t hashStartColumn() const;
517 : };
518 :
519 11090 : inline void ScRange::GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
520 : SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const
521 : {
522 11090 : aStart.GetVars( nCol1, nRow1, nTab1 );
523 11090 : aEnd.GetVars( nCol2, nRow2, nTab2 );
524 11090 : }
525 :
526 16153 : inline bool ScRange::operator==( const ScRange& r ) const
527 : {
528 16153 : return ( (aStart == r.aStart) && (aEnd == r.aEnd) );
529 : }
530 :
531 1729 : inline bool ScRange::operator!=( const ScRange& r ) const
532 : {
533 1729 : return !operator==( r );
534 : }
535 :
536 : /// Sort on upper left corner, if equal then use lower right too.
537 138 : inline bool ScRange::operator<( const ScRange& r ) const
538 : {
539 138 : return aStart < r.aStart || (aStart == r.aStart && aEnd < r.aEnd) ;
540 : }
541 :
542 : inline bool ScRange::operator<=( const ScRange& r ) const
543 : {
544 : return operator<( r ) || operator==( r );
545 : }
546 :
547 : inline bool ScRange::operator>( const ScRange& r ) const
548 : {
549 : return !operator<=( r );
550 : }
551 :
552 : inline bool ScRange::operator>=( const ScRange& r ) const
553 : {
554 : return !operator<( r );
555 : }
556 :
557 2681 : inline bool ScRange::In( const ScAddress& rAddr ) const
558 : {
559 : return
560 6456 : aStart.Col() <= rAddr.Col() && rAddr.Col() <= aEnd.Col() &&
561 4040 : aStart.Row() <= rAddr.Row() && rAddr.Row() <= aEnd.Row() &&
562 4579 : aStart.Tab() <= rAddr.Tab() && rAddr.Tab() <= aEnd.Tab();
563 : }
564 :
565 2567430 : inline bool ScRange::In( const ScRange& r ) const
566 : {
567 : return
568 3866068 : aStart.Col() <= r.aStart.Col() && r.aEnd.Col() <= aEnd.Col() &&
569 28112 : aStart.Row() <= r.aStart.Row() && r.aEnd.Row() <= aEnd.Row() &&
570 2583845 : aStart.Tab() <= r.aStart.Tab() && r.aEnd.Tab() <= aEnd.Tab();
571 : }
572 :
573 :
574 8394 : inline size_t ScRange::hashArea() const
575 : {
576 : // Assume that there are not that many ranges with identical corners so we
577 : // won't have too many collisions. Also assume that more lower row and
578 : // column numbers are used so that there are not too many conflicts with
579 : // the columns hashed into the values, and that start row and column
580 : // usually don't exceed certain values. High bits are not masked off and
581 : // may overlap with lower bits of other values, e.g. if start column is
582 : // greater than assumed.
583 : return
584 16788 : (static_cast<size_t>(aStart.Row()) << 26) ^ // start row <= 2^6
585 16788 : (static_cast<size_t>(aStart.Col()) << 21) ^ // start column <= 2^5
586 16788 : (static_cast<size_t>(aEnd.Col()) << 15) ^ // end column <= 2^6
587 16788 : static_cast<size_t>(aEnd.Row()); // end row <= 2^15
588 : }
589 :
590 :
591 65 : inline size_t ScRange::hashStartColumn() const
592 : {
593 : // Assume that for the start row more lower row numbers are used so that
594 : // there are not too many conflicts with the column hashed into the higher
595 : // values.
596 : return
597 130 : (static_cast<size_t>(aStart.Col()) << 24) ^ // start column <= 2^8
598 130 : (static_cast<size_t>(aStart.Row()) << 16) ^ // start row <= 2^8
599 130 : static_cast<size_t>(aEnd.Row());
600 : }
601 :
602 :
603 : struct ScRangeHashAreaFunctor
604 : {
605 : size_t operator()( const ScRange & rRange ) const
606 : {
607 : return rRange.hashArea();
608 : }
609 : };
610 :
611 : struct ScRangeEqualFunctor
612 : {
613 : bool operator()( const ScRange & rRange1, const ScRange & rRange2 ) const
614 : {
615 : return rRange1 == rRange2;
616 : }
617 : };
618 :
619 :
620 : // === ScRangePair ===========================================================
621 :
622 : class ScRangePair
623 : {
624 : private:
625 : ScRange aRange[2];
626 :
627 : public:
628 : ScRangePair() {}
629 11 : ScRangePair( const ScRangePair& r )
630 11 : { aRange[0] = r.aRange[0]; aRange[1] = r.aRange[1]; }
631 4 : ScRangePair( const ScRange& r1, const ScRange& r2 )
632 4 : { aRange[0] = r1; aRange[1] = r2; }
633 :
634 : inline ScRangePair& operator= ( const ScRangePair& r );
635 2 : const ScRange& GetRange( sal_uInt16 n ) const { return aRange[n]; }
636 15 : ScRange& GetRange( sal_uInt16 n ) { return aRange[n]; }
637 : inline int operator==( const ScRangePair& ) const;
638 : inline int operator!=( const ScRangePair& ) const;
639 : };
640 :
641 0 : inline ScRangePair& ScRangePair::operator= ( const ScRangePair& r )
642 : {
643 0 : aRange[0] = r.aRange[0];
644 0 : aRange[1] = r.aRange[1];
645 0 : return *this;
646 : }
647 :
648 0 : inline int ScRangePair::operator==( const ScRangePair& r ) const
649 : {
650 0 : return ( (aRange[0] == r.aRange[0]) && (aRange[1] == r.aRange[1]) );
651 : }
652 :
653 0 : inline int ScRangePair::operator!=( const ScRangePair& r ) const
654 : {
655 0 : return !operator==( r );
656 : }
657 :
658 : // === ScRefAddress ==========================================================
659 :
660 : class ScRefAddress
661 : {
662 : ScAddress aAdr;
663 : bool bRelCol;
664 : bool bRelRow;
665 : bool bRelTab;
666 : public:
667 71 : inline ScRefAddress() : bRelCol(false), bRelRow(false), bRelTab(false)
668 71 : {}
669 12 : inline ScRefAddress( SCCOL nCol, SCROW nRow, SCTAB nTab,
670 : bool bRelColP, bool bRelRowP, bool bRelTabP ) :
671 : aAdr(nCol, nRow, nTab),
672 12 : bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP)
673 12 : {}
674 : inline ScRefAddress( const ScAddress& rAdr,
675 : bool bRelColP, bool bRelRowP, bool bRelTabP ) :
676 : aAdr(rAdr),
677 : bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP)
678 : {}
679 12 : inline ScRefAddress( const ScRefAddress& rRef ) :
680 : aAdr(rRef.aAdr), bRelCol(rRef.bRelCol), bRelRow(rRef.bRelRow),
681 12 : bRelTab(rRef.bRelTab)
682 12 : {}
683 :
684 : inline ScRefAddress& operator=( const ScRefAddress& );
685 :
686 : inline bool IsRelCol() const { return bRelCol; }
687 : inline bool IsRelRow() const { return bRelRow; }
688 : inline bool IsRelTab() const { return bRelTab; }
689 :
690 0 : inline void SetRelCol(bool bNewRelCol) { bRelCol = bNewRelCol; }
691 0 : inline void SetRelRow(bool bNewRelRow) { bRelRow = bNewRelRow; }
692 0 : inline void SetRelTab(bool bNewRelTab) { bRelTab = bNewRelTab; }
693 :
694 : inline void Set( const ScAddress& rAdr,
695 : bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
696 : inline void Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
697 : bool bNewRelCol, bool bNewRelRow, bool bNewRelTab );
698 :
699 2 : inline const ScAddress& GetAddress() const { return aAdr; }
700 22 : inline SCCOL Col() const { return aAdr.Col(); }
701 22 : inline SCROW Row() const { return aAdr.Row(); }
702 42 : inline SCTAB Tab() const { return aAdr.Tab(); }
703 :
704 : inline int operator == ( const ScRefAddress& r ) const;
705 : inline int operator != ( const ScRefAddress& r ) const
706 : { return !(operator==(r)); }
707 :
708 : String GetRefString( ScDocument* pDoc, SCTAB nActTab,
709 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1) const;
710 : };
711 :
712 12 : inline ScRefAddress& ScRefAddress::operator=( const ScRefAddress& rRef )
713 : {
714 12 : aAdr = rRef.aAdr;
715 12 : bRelCol = rRef.bRelCol;
716 12 : bRelRow = rRef.bRelRow;
717 12 : bRelTab = rRef.bRelTab;
718 12 : return *this;
719 : }
720 :
721 22 : inline void ScRefAddress::Set( const ScAddress& rAdr,
722 : bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
723 : {
724 22 : aAdr = rAdr;
725 22 : bRelCol = bNewRelCol;
726 22 : bRelRow = bNewRelRow;
727 22 : bRelTab = bNewRelTab;
728 22 : }
729 :
730 4 : inline void ScRefAddress::Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
731 : bool bNewRelCol, bool bNewRelRow, bool bNewRelTab )
732 : {
733 4 : aAdr.Set( nNewCol, nNewRow, nNewTab);
734 4 : bRelCol = bNewRelCol;
735 4 : bRelRow = bNewRelRow;
736 4 : bRelTab = bNewRelTab;
737 4 : }
738 :
739 0 : inline int ScRefAddress::operator==( const ScRefAddress& r ) const
740 : {
741 0 : return aAdr == r.aAdr && bRelCol == r.bRelCol && bRelRow == r.bRelRow &&
742 0 : bRelTab == r.bRelTab;
743 : }
744 :
745 : // ===========================================================================
746 : // Global functions
747 : // ===========================================================================
748 :
749 : // Special values for cells always broadcasting or listening (RECALCMODE_ALWAYS
750 : // and the like).
751 : #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
752 : #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
753 :
754 39867 : template< typename T > void PutInOrder( T& nStart, T& nEnd )
755 : {
756 39867 : if (nEnd < nStart)
757 : {
758 0 : T nTemp;
759 4 : nTemp = nEnd;
760 4 : nEnd = nStart;
761 4 : nStart = nTemp;
762 : }
763 39867 : }
764 :
765 : bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
766 : SCTAB nDefTab, ScRefAddress& rRefAddress,
767 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
768 : ScAddress::ExternalInfo* pExtInfo = NULL );
769 :
770 : bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString,
771 : SCTAB nDefTab, ScRefAddress& rStartRefAddress,
772 : ScRefAddress& rEndRefAddress,
773 : const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
774 : ScAddress::ExternalInfo* pExtInfo = NULL );
775 :
776 : /// append alpha representation of column to buffer
777 : SC_DLLPUBLIC void ScColToAlpha( OUStringBuffer& rBuffer, SCCOL nCol);
778 :
779 2242 : inline void ScColToAlpha( String& rStr, SCCOL nCol)
780 : {
781 2242 : OUStringBuffer aBuf(2);
782 2242 : ScColToAlpha( aBuf, nCol);
783 2242 : rStr.Append( aBuf.getStr(), static_cast<xub_StrLen>(aBuf.getLength()));
784 2242 : }
785 :
786 4233 : inline String ScColToAlpha( SCCOL nCol )
787 : {
788 4233 : OUStringBuffer aBuf(2);
789 4233 : ScColToAlpha( aBuf, nCol);
790 4233 : return aBuf.makeStringAndClear();
791 : }
792 :
793 : /// get column number of A..IV... string
794 : bool AlphaToCol( SCCOL& rCol, const String& rStr);
795 :
796 : #endif // SC_ADDRESS_HXX
797 :
798 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|