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