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