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