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