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