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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 #include "scitems.hxx" 30 #include <svl/intitem.hxx> 31 #include <svl/zforlist.hxx> 32 #include <rtl/uuid.h> 33 34 #include "cursuno.hxx" 35 #include "cellsuno.hxx" 36 #include "docsh.hxx" 37 #include "hints.hxx" 38 #include "markdata.hxx" 39 #include "dociter.hxx" 40 #include "unoguard.hxx" 41 #include "miscuno.hxx" 42 43 using namespace com::sun::star; 44 45 //------------------------------------------------------------------------ 46 47 #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor" 48 #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor" 49 50 //------------------------------------------------------------------------ 51 52 ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) : 53 ScCellRangeObj( pDocSh, rR ) 54 { 55 } 56 57 ScCellCursorObj::~ScCellCursorObj() 58 { 59 } 60 61 uno::Any SAL_CALL ScCellCursorObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) 62 { 63 SC_QUERYINTERFACE( sheet::XSheetCellCursor ) 64 SC_QUERYINTERFACE( sheet::XUsedAreaCursor ) 65 SC_QUERYINTERFACE( table::XCellCursor ) 66 67 return ScCellRangeObj::queryInterface( rType ); 68 } 69 70 void SAL_CALL ScCellCursorObj::acquire() throw() 71 { 72 ScCellRangeObj::acquire(); 73 } 74 75 void SAL_CALL ScCellCursorObj::release() throw() 76 { 77 ScCellRangeObj::release(); 78 } 79 80 uno::Sequence<uno::Type> SAL_CALL ScCellCursorObj::getTypes() throw(uno::RuntimeException) 81 { 82 static uno::Sequence<uno::Type> aTypes; 83 if ( aTypes.getLength() == 0 ) 84 { 85 uno::Sequence<uno::Type> aParentTypes(ScCellRangeObj::getTypes()); 86 long nParentLen = aParentTypes.getLength(); 87 const uno::Type* pParentPtr = aParentTypes.getConstArray(); 88 89 aTypes.realloc( nParentLen + 3 ); 90 uno::Type* pPtr = aTypes.getArray(); 91 pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSheetCellCursor>*)0); 92 pPtr[nParentLen + 1] = getCppuType((const uno::Reference<sheet::XUsedAreaCursor>*)0); 93 pPtr[nParentLen + 2] = getCppuType((const uno::Reference<table::XCellCursor>*)0); 94 95 for (long i=0; i<nParentLen; i++) 96 pPtr[i] = pParentPtr[i]; // parent types first 97 } 98 return aTypes; 99 } 100 101 uno::Sequence<sal_Int8> SAL_CALL ScCellCursorObj::getImplementationId() throw(uno::RuntimeException) 102 { 103 static uno::Sequence< sal_Int8 > aId; 104 if( aId.getLength() == 0 ) 105 { 106 aId.realloc( 16 ); 107 rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); 108 } 109 return aId; 110 } 111 112 // XSheetCellCursor 113 114 void SAL_CALL ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException) 115 { 116 ScUnoGuard aGuard; 117 const ScRangeList& rRanges = GetRangeList(); 118 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 119 ScRange aOneRange(*rRanges.GetObject(0)); 120 121 aOneRange.Justify(); 122 ScDocShell* pDocSh = GetDocShell(); 123 if ( pDocSh ) 124 { 125 SCCOL nStartCol = aOneRange.aStart.Col(); 126 SCROW nStartRow = aOneRange.aStart.Row(); 127 SCCOL nEndCol = aOneRange.aEnd.Col(); 128 SCROW nEndRow = aOneRange.aEnd.Row(); 129 SCTAB nTab = aOneRange.aStart.Tab(); 130 131 pDocSh->GetDocument()->GetDataArea( 132 nTab, nStartCol, nStartRow, nEndCol, nEndRow, sal_True, false ); 133 134 ScRange aNew( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); 135 SetNewRange( aNew ); 136 } 137 } 138 139 void SAL_CALL ScCellCursorObj::collapseToCurrentArray() throw(uno::RuntimeException) 140 { 141 ScUnoGuard aGuard; 142 const ScRangeList& rRanges = GetRangeList(); 143 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 144 ScRange aOneRange(*rRanges.GetObject(0)); 145 146 aOneRange.Justify(); 147 ScAddress aCursor(aOneRange.aStart); // use the start address of the range 148 149 ScDocShell* pDocSh = GetDocShell(); 150 if ( pDocSh ) 151 { 152 ScDocument* pDoc = pDocSh->GetDocument(); 153 ScRange aMatrix; 154 155 // finding the matrix range is now in GetMatrixFormulaRange in the document 156 if ( pDoc->GetMatrixFormulaRange( aCursor, aMatrix ) ) 157 { 158 SetNewRange( aMatrix ); 159 } 160 } 161 // thats a Bug, that this assertion comes; the API Reference says, that 162 // if there is no Matrix, the Range is left unchanged; they says nothing 163 // about a exception 164 /*if (!bFound) 165 { 166 DBG_ERROR("keine Matrix"); 167 //! Exception, oder was? 168 }*/ 169 } 170 171 void SAL_CALL ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException) 172 { 173 ScUnoGuard aGuard; 174 ScDocShell* pDocSh = GetDocShell(); 175 if ( pDocSh ) 176 { 177 const ScRangeList& rRanges = GetRangeList(); 178 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 179 ScRange aNewRange(*rRanges.GetObject(0)); 180 181 ScDocument* pDoc = pDocSh->GetDocument(); 182 pDoc->ExtendOverlapped( aNewRange ); 183 pDoc->ExtendMerge( aNewRange ); // after ExtendOverlapped! 184 185 SetNewRange( aNewRange ); 186 } 187 } 188 189 void SAL_CALL ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException) 190 { 191 ScUnoGuard aGuard; 192 const ScRangeList& rRanges = GetRangeList(); 193 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 194 ScRange aNewRange(*rRanges.GetObject(0)); 195 196 aNewRange.aStart.SetRow( 0 ); 197 aNewRange.aEnd.SetRow( MAXROW ); 198 199 SetNewRange( aNewRange ); 200 } 201 202 void SAL_CALL ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException) 203 { 204 ScUnoGuard aGuard; 205 const ScRangeList& rRanges = GetRangeList(); 206 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 207 ScRange aNewRange(*rRanges.GetObject(0)); 208 209 aNewRange.aStart.SetCol( 0 ); 210 aNewRange.aEnd.SetCol( MAXCOL ); 211 212 SetNewRange( aNewRange ); 213 } 214 215 void SAL_CALL ScCellCursorObj::collapseToSize( sal_Int32 nColumns, sal_Int32 nRows ) 216 throw(uno::RuntimeException) 217 { 218 ScUnoGuard aGuard; 219 if ( nColumns <= 0 || nRows <= 0 ) 220 { 221 DBG_ERROR("leerer Range geht nicht"); 222 //! und dann? 223 } 224 else 225 { 226 const ScRangeList& rRanges = GetRangeList(); 227 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 228 ScRange aNewRange(*rRanges.GetObject(0)); 229 230 aNewRange.Justify(); //! wirklich? 231 232 long nEndX = aNewRange.aStart.Col() + nColumns - 1; 233 long nEndY = aNewRange.aStart.Row() + nRows - 1; 234 if ( nEndX < 0 ) nEndX = 0; 235 if ( nEndX > MAXCOL ) nEndX = MAXCOL; 236 if ( nEndY < 0 ) nEndY = 0; 237 if ( nEndY > MAXROW ) nEndY = MAXROW; 238 //! Fehler/Exception oder so, wenn zu gross/zu klein? 239 240 aNewRange.aEnd.SetCol((SCCOL)nEndX); 241 aNewRange.aEnd.SetRow((SCROW)nEndY); 242 243 aNewRange.Justify(); //! wirklich? 244 245 SetNewRange( aNewRange ); 246 } 247 } 248 249 // XUsedAreaCursor 250 251 void SAL_CALL ScCellCursorObj::gotoStartOfUsedArea( sal_Bool bExpand ) 252 throw(uno::RuntimeException) 253 { 254 ScUnoGuard aGuard; 255 ScDocShell* pDocSh = GetDocShell(); 256 if ( pDocSh ) 257 { 258 const ScRangeList& rRanges = GetRangeList(); 259 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 260 ScRange aNewRange(*rRanges.GetObject(0)); 261 SCTAB nTab = aNewRange.aStart.Tab(); 262 263 SCCOL nUsedX = 0; // Anfang holen 264 SCROW nUsedY = 0; 265 if (!pDocSh->GetDocument()->GetDataStart( nTab, nUsedX, nUsedY )) 266 { 267 nUsedX = 0; 268 nUsedY = 0; 269 } 270 271 aNewRange.aStart.SetCol( nUsedX ); 272 aNewRange.aStart.SetRow( nUsedY ); 273 if (!bExpand) 274 aNewRange.aEnd = aNewRange.aStart; 275 SetNewRange( aNewRange ); 276 } 277 } 278 279 void SAL_CALL ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand ) 280 throw(uno::RuntimeException) 281 { 282 ScUnoGuard aGuard; 283 ScDocShell* pDocSh = GetDocShell(); 284 if ( pDocSh ) 285 { 286 const ScRangeList& rRanges = GetRangeList(); 287 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 288 ScRange aNewRange(*rRanges.GetObject(0)); 289 SCTAB nTab = aNewRange.aStart.Tab(); 290 291 SCCOL nUsedX = 0; // Ende holen 292 SCROW nUsedY = 0; 293 if (!pDocSh->GetDocument()->GetTableArea( nTab, nUsedX, nUsedY )) 294 { 295 nUsedX = 0; 296 nUsedY = 0; 297 } 298 299 aNewRange.aEnd.SetCol( nUsedX ); 300 aNewRange.aEnd.SetRow( nUsedY ); 301 if (!bExpand) 302 aNewRange.aStart = aNewRange.aEnd; 303 SetNewRange( aNewRange ); 304 } 305 } 306 307 // XCellCursor 308 309 void SAL_CALL ScCellCursorObj::gotoStart() throw(uno::RuntimeException) 310 { 311 // this is similar to collapseToCurrentRegion 312 //! something like gotoEdge with 4 possible directions is needed 313 314 ScUnoGuard aGuard; 315 const ScRangeList& rRanges = GetRangeList(); 316 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 317 ScRange aOneRange(*rRanges.GetObject(0)); 318 319 aOneRange.Justify(); 320 ScDocShell* pDocSh = GetDocShell(); 321 if ( pDocSh ) 322 { 323 SCCOL nStartCol = aOneRange.aStart.Col(); 324 SCROW nStartRow = aOneRange.aStart.Row(); 325 SCCOL nEndCol = aOneRange.aEnd.Col(); 326 SCROW nEndRow = aOneRange.aEnd.Row(); 327 SCTAB nTab = aOneRange.aStart.Tab(); 328 329 pDocSh->GetDocument()->GetDataArea( 330 nTab, nStartCol, nStartRow, nEndCol, nEndRow, sal_False, false ); 331 332 ScRange aNew( nStartCol, nStartRow, nTab ); 333 SetNewRange( aNew ); 334 } 335 } 336 337 void SAL_CALL ScCellCursorObj::gotoEnd() throw(uno::RuntimeException) 338 { 339 // this is similar to collapseToCurrentRegion 340 //! something like gotoEdge with 4 possible directions is needed 341 342 ScUnoGuard aGuard; 343 const ScRangeList& rRanges = GetRangeList(); 344 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 345 ScRange aOneRange(*rRanges.GetObject(0)); 346 347 aOneRange.Justify(); 348 ScDocShell* pDocSh = GetDocShell(); 349 if ( pDocSh ) 350 { 351 SCCOL nStartCol = aOneRange.aStart.Col(); 352 SCROW nStartRow = aOneRange.aStart.Row(); 353 SCCOL nEndCol = aOneRange.aEnd.Col(); 354 SCROW nEndRow = aOneRange.aEnd.Row(); 355 SCTAB nTab = aOneRange.aStart.Tab(); 356 357 pDocSh->GetDocument()->GetDataArea( 358 nTab, nStartCol, nStartRow, nEndCol, nEndRow, sal_False, false ); 359 360 ScRange aNew( nEndCol, nEndRow, nTab ); 361 SetNewRange( aNew ); 362 } 363 } 364 365 void SAL_CALL ScCellCursorObj::gotoNext() throw(uno::RuntimeException) 366 { 367 ScUnoGuard aGuard; 368 const ScRangeList& rRanges = GetRangeList(); 369 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 370 ScRange aOneRange(*rRanges.GetObject(0)); 371 372 aOneRange.Justify(); 373 ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen 374 375 ScMarkData aMark; // not used with bMarked=FALSE 376 SCCOL nNewX = aCursor.Col(); 377 SCROW nNewY = aCursor.Row(); 378 SCTAB nTab = aCursor.Tab(); 379 ScDocShell* pDocSh = GetDocShell(); 380 if ( pDocSh ) 381 pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, 1,0, sal_False,sal_True, aMark ); 382 //! sonst Exception oder so 383 384 SetNewRange( ScRange( nNewX, nNewY, nTab ) ); 385 } 386 387 void SAL_CALL ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException) 388 { 389 ScUnoGuard aGuard; 390 const ScRangeList& rRanges = GetRangeList(); 391 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 392 ScRange aOneRange(*rRanges.GetObject(0)); 393 394 aOneRange.Justify(); 395 ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen 396 397 ScMarkData aMark; // not used with bMarked=FALSE 398 SCCOL nNewX = aCursor.Col(); 399 SCROW nNewY = aCursor.Row(); 400 SCTAB nTab = aCursor.Tab(); 401 ScDocShell* pDocSh = GetDocShell(); 402 if ( pDocSh ) 403 pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, -1,0, sal_False,sal_True, aMark ); 404 //! sonst Exception oder so 405 406 SetNewRange( ScRange( nNewX, nNewY, nTab ) ); 407 } 408 409 void SAL_CALL ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset, sal_Int32 nRowOffset ) 410 throw(uno::RuntimeException) 411 { 412 ScUnoGuard aGuard; 413 const ScRangeList& rRanges = GetRangeList(); 414 DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); 415 ScRange aOneRange(*rRanges.GetObject(0)); 416 aOneRange.Justify(); 417 418 if ( aOneRange.aStart.Col() + nColumnOffset >= 0 && 419 aOneRange.aEnd.Col() + nColumnOffset <= MAXCOL && 420 aOneRange.aStart.Row() + nRowOffset >= 0 && 421 aOneRange.aEnd.Row() + nRowOffset <= MAXROW ) 422 { 423 ScRange aNew( (SCCOL)(aOneRange.aStart.Col() + nColumnOffset), 424 (SCROW)(aOneRange.aStart.Row() + nRowOffset), 425 aOneRange.aStart.Tab(), 426 (SCCOL)(aOneRange.aEnd.Col() + nColumnOffset), 427 (SCROW)(aOneRange.aEnd.Row() + nRowOffset), 428 aOneRange.aEnd.Tab() ); 429 SetNewRange( aNew ); 430 } 431 } 432 433 // XSheetCellRange 434 435 uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellCursorObj::getSpreadsheet() 436 throw(uno::RuntimeException) 437 { 438 ScUnoGuard aGuard; 439 return ScCellRangeObj::getSpreadsheet(); 440 } 441 442 // XCellRange 443 444 uno::Reference<table::XCell> SAL_CALL ScCellCursorObj::getCellByPosition( 445 sal_Int32 nColumn, sal_Int32 nRow ) 446 throw(lang::IndexOutOfBoundsException, uno::RuntimeException) 447 { 448 ScUnoGuard aGuard; 449 return ScCellRangeObj::getCellByPosition(nColumn,nRow); 450 } 451 452 uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByPosition( 453 sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) 454 throw(lang::IndexOutOfBoundsException, uno::RuntimeException) 455 { 456 ScUnoGuard aGuard; 457 return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom); 458 } 459 460 uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByName( 461 const rtl::OUString& rRange ) throw(uno::RuntimeException) 462 { 463 ScUnoGuard aGuard; 464 return ScCellRangeObj::getCellRangeByName(rRange); 465 } 466 467 // XServiceInfo 468 469 rtl::OUString SAL_CALL ScCellCursorObj::getImplementationName() throw(uno::RuntimeException) 470 { 471 return rtl::OUString::createFromAscii( "ScCellCursorObj" ); 472 } 473 474 sal_Bool SAL_CALL ScCellCursorObj::supportsService( const rtl::OUString& rServiceName ) 475 throw(uno::RuntimeException) 476 { 477 String aServiceStr( rServiceName ); 478 return aServiceStr.EqualsAscii( SCSHEETCELLCURSOR_SERVICE ) || 479 aServiceStr.EqualsAscii( SCCELLCURSOR_SERVICE ) || 480 ScCellRangeObj::supportsService(rServiceName); 481 } 482 483 uno::Sequence<rtl::OUString> SAL_CALL ScCellCursorObj::getSupportedServiceNames() 484 throw(uno::RuntimeException) 485 { 486 // get all service names from cell range 487 uno::Sequence<rtl::OUString> aParentSeq(ScCellRangeObj::getSupportedServiceNames()); 488 sal_Int32 nParentLen = aParentSeq.getLength(); 489 const rtl::OUString* pParentArr = aParentSeq.getConstArray(); 490 491 // SheetCellCursor should be first (?) 492 uno::Sequence<rtl::OUString> aTotalSeq( nParentLen + 2 ); 493 rtl::OUString* pTotalArr = aTotalSeq.getArray(); 494 pTotalArr[0] = rtl::OUString::createFromAscii( SCSHEETCELLCURSOR_SERVICE ); 495 pTotalArr[1] = rtl::OUString::createFromAscii( SCCELLCURSOR_SERVICE ); 496 497 // append cell range services 498 for (long i=0; i<nParentLen; i++) 499 pTotalArr[i+2] = pParentArr[i]; 500 501 return aTotalSeq; 502 } 503 504 505 506 507