| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| |
| |
| #include "scitems.hxx" |
| #include <svl/intitem.hxx> |
| #include <svl/zforlist.hxx> |
| #include <rtl/uuid.h> |
| |
| #include "cursuno.hxx" |
| #include "cellsuno.hxx" |
| #include "docsh.hxx" |
| #include "hints.hxx" |
| #include "markdata.hxx" |
| #include "dociter.hxx" |
| #include "unoguard.hxx" |
| #include "miscuno.hxx" |
| |
| using namespace com::sun::star; |
| |
| //------------------------------------------------------------------------ |
| |
| #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor" |
| #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor" |
| |
| //------------------------------------------------------------------------ |
| |
| ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) : |
| ScCellRangeObj( pDocSh, rR ) |
| { |
| } |
| |
| ScCellCursorObj::~ScCellCursorObj() |
| { |
| } |
| |
| uno::Any SAL_CALL ScCellCursorObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) |
| { |
| SC_QUERYINTERFACE( sheet::XSheetCellCursor ) |
| SC_QUERYINTERFACE( sheet::XUsedAreaCursor ) |
| SC_QUERYINTERFACE( table::XCellCursor ) |
| |
| return ScCellRangeObj::queryInterface( rType ); |
| } |
| |
| void SAL_CALL ScCellCursorObj::acquire() throw() |
| { |
| ScCellRangeObj::acquire(); |
| } |
| |
| void SAL_CALL ScCellCursorObj::release() throw() |
| { |
| ScCellRangeObj::release(); |
| } |
| |
| uno::Sequence<uno::Type> SAL_CALL ScCellCursorObj::getTypes() throw(uno::RuntimeException) |
| { |
| static uno::Sequence<uno::Type> aTypes; |
| if ( aTypes.getLength() == 0 ) |
| { |
| uno::Sequence<uno::Type> aParentTypes(ScCellRangeObj::getTypes()); |
| long nParentLen = aParentTypes.getLength(); |
| const uno::Type* pParentPtr = aParentTypes.getConstArray(); |
| |
| aTypes.realloc( nParentLen + 3 ); |
| uno::Type* pPtr = aTypes.getArray(); |
| pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSheetCellCursor>*)0); |
| pPtr[nParentLen + 1] = getCppuType((const uno::Reference<sheet::XUsedAreaCursor>*)0); |
| pPtr[nParentLen + 2] = getCppuType((const uno::Reference<table::XCellCursor>*)0); |
| |
| for (long i=0; i<nParentLen; i++) |
| pPtr[i] = pParentPtr[i]; // parent types first |
| } |
| return aTypes; |
| } |
| |
| uno::Sequence<sal_Int8> SAL_CALL ScCellCursorObj::getImplementationId() throw(uno::RuntimeException) |
| { |
| static uno::Sequence< sal_Int8 > aId; |
| if( aId.getLength() == 0 ) |
| { |
| aId.realloc( 16 ); |
| rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); |
| } |
| return aId; |
| } |
| |
| // XSheetCellCursor |
| |
| void SAL_CALL ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| |
| aOneRange.Justify(); |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| SCCOL nStartCol = aOneRange.aStart.Col(); |
| SCROW nStartRow = aOneRange.aStart.Row(); |
| SCCOL nEndCol = aOneRange.aEnd.Col(); |
| SCROW nEndRow = aOneRange.aEnd.Row(); |
| SCTAB nTab = aOneRange.aStart.Tab(); |
| |
| pDocSh->GetDocument()->GetDataArea( |
| nTab, nStartCol, nStartRow, nEndCol, nEndRow, sal_True, false ); |
| |
| ScRange aNew( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); |
| SetNewRange( aNew ); |
| } |
| } |
| |
| void SAL_CALL ScCellCursorObj::collapseToCurrentArray() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| |
| aOneRange.Justify(); |
| ScAddress aCursor(aOneRange.aStart); // use the start address of the range |
| |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| ScDocument* pDoc = pDocSh->GetDocument(); |
| ScRange aMatrix; |
| |
| // finding the matrix range is now in GetMatrixFormulaRange in the document |
| if ( pDoc->GetMatrixFormulaRange( aCursor, aMatrix ) ) |
| { |
| SetNewRange( aMatrix ); |
| } |
| } |
| // thats a Bug, that this assertion comes; the API Reference says, that |
| // if there is no Matrix, the Range is left unchanged; they says nothing |
| // about a exception |
| /*if (!bFound) |
| { |
| DBG_ERROR("keine Matrix"); |
| //! Exception, oder was? |
| }*/ |
| } |
| |
| void SAL_CALL ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aNewRange(*rRanges.GetObject(0)); |
| |
| ScDocument* pDoc = pDocSh->GetDocument(); |
| pDoc->ExtendOverlapped( aNewRange ); |
| pDoc->ExtendMerge( aNewRange ); // after ExtendOverlapped! |
| |
| SetNewRange( aNewRange ); |
| } |
| } |
| |
| void SAL_CALL ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aNewRange(*rRanges.GetObject(0)); |
| |
| aNewRange.aStart.SetRow( 0 ); |
| aNewRange.aEnd.SetRow( MAXROW ); |
| |
| SetNewRange( aNewRange ); |
| } |
| |
| void SAL_CALL ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aNewRange(*rRanges.GetObject(0)); |
| |
| aNewRange.aStart.SetCol( 0 ); |
| aNewRange.aEnd.SetCol( MAXCOL ); |
| |
| SetNewRange( aNewRange ); |
| } |
| |
| void SAL_CALL ScCellCursorObj::collapseToSize( sal_Int32 nColumns, sal_Int32 nRows ) |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| if ( nColumns <= 0 || nRows <= 0 ) |
| { |
| DBG_ERROR("leerer Range geht nicht"); |
| //! und dann? |
| } |
| else |
| { |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aNewRange(*rRanges.GetObject(0)); |
| |
| aNewRange.Justify(); //! wirklich? |
| |
| long nEndX = aNewRange.aStart.Col() + nColumns - 1; |
| long nEndY = aNewRange.aStart.Row() + nRows - 1; |
| if ( nEndX < 0 ) nEndX = 0; |
| if ( nEndX > MAXCOL ) nEndX = MAXCOL; |
| if ( nEndY < 0 ) nEndY = 0; |
| if ( nEndY > MAXROW ) nEndY = MAXROW; |
| //! Fehler/Exception oder so, wenn zu gross/zu klein? |
| |
| aNewRange.aEnd.SetCol((SCCOL)nEndX); |
| aNewRange.aEnd.SetRow((SCROW)nEndY); |
| |
| aNewRange.Justify(); //! wirklich? |
| |
| SetNewRange( aNewRange ); |
| } |
| } |
| |
| // XUsedAreaCursor |
| |
| void SAL_CALL ScCellCursorObj::gotoStartOfUsedArea( sal_Bool bExpand ) |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aNewRange(*rRanges.GetObject(0)); |
| SCTAB nTab = aNewRange.aStart.Tab(); |
| |
| SCCOL nUsedX = 0; // Anfang holen |
| SCROW nUsedY = 0; |
| if (!pDocSh->GetDocument()->GetDataStart( nTab, nUsedX, nUsedY )) |
| { |
| nUsedX = 0; |
| nUsedY = 0; |
| } |
| |
| aNewRange.aStart.SetCol( nUsedX ); |
| aNewRange.aStart.SetRow( nUsedY ); |
| if (!bExpand) |
| aNewRange.aEnd = aNewRange.aStart; |
| SetNewRange( aNewRange ); |
| } |
| } |
| |
| void SAL_CALL ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand ) |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aNewRange(*rRanges.GetObject(0)); |
| SCTAB nTab = aNewRange.aStart.Tab(); |
| |
| SCCOL nUsedX = 0; // Ende holen |
| SCROW nUsedY = 0; |
| if (!pDocSh->GetDocument()->GetTableArea( nTab, nUsedX, nUsedY )) |
| { |
| nUsedX = 0; |
| nUsedY = 0; |
| } |
| |
| aNewRange.aEnd.SetCol( nUsedX ); |
| aNewRange.aEnd.SetRow( nUsedY ); |
| if (!bExpand) |
| aNewRange.aStart = aNewRange.aEnd; |
| SetNewRange( aNewRange ); |
| } |
| } |
| |
| // XCellCursor |
| |
| void SAL_CALL ScCellCursorObj::gotoStart() throw(uno::RuntimeException) |
| { |
| // this is similar to collapseToCurrentRegion |
| //! something like gotoEdge with 4 possible directions is needed |
| |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| |
| aOneRange.Justify(); |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| SCCOL nStartCol = aOneRange.aStart.Col(); |
| SCROW nStartRow = aOneRange.aStart.Row(); |
| SCCOL nEndCol = aOneRange.aEnd.Col(); |
| SCROW nEndRow = aOneRange.aEnd.Row(); |
| SCTAB nTab = aOneRange.aStart.Tab(); |
| |
| pDocSh->GetDocument()->GetDataArea( |
| nTab, nStartCol, nStartRow, nEndCol, nEndRow, sal_False, false ); |
| |
| ScRange aNew( nStartCol, nStartRow, nTab ); |
| SetNewRange( aNew ); |
| } |
| } |
| |
| void SAL_CALL ScCellCursorObj::gotoEnd() throw(uno::RuntimeException) |
| { |
| // this is similar to collapseToCurrentRegion |
| //! something like gotoEdge with 4 possible directions is needed |
| |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| |
| aOneRange.Justify(); |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| { |
| SCCOL nStartCol = aOneRange.aStart.Col(); |
| SCROW nStartRow = aOneRange.aStart.Row(); |
| SCCOL nEndCol = aOneRange.aEnd.Col(); |
| SCROW nEndRow = aOneRange.aEnd.Row(); |
| SCTAB nTab = aOneRange.aStart.Tab(); |
| |
| pDocSh->GetDocument()->GetDataArea( |
| nTab, nStartCol, nStartRow, nEndCol, nEndRow, sal_False, false ); |
| |
| ScRange aNew( nEndCol, nEndRow, nTab ); |
| SetNewRange( aNew ); |
| } |
| } |
| |
| void SAL_CALL ScCellCursorObj::gotoNext() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| |
| aOneRange.Justify(); |
| ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen |
| |
| ScMarkData aMark; // not used with bMarked=FALSE |
| SCCOL nNewX = aCursor.Col(); |
| SCROW nNewY = aCursor.Row(); |
| SCTAB nTab = aCursor.Tab(); |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, 1,0, sal_False,sal_True, aMark ); |
| //! sonst Exception oder so |
| |
| SetNewRange( ScRange( nNewX, nNewY, nTab ) ); |
| } |
| |
| void SAL_CALL ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| |
| aOneRange.Justify(); |
| ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen |
| |
| ScMarkData aMark; // not used with bMarked=FALSE |
| SCCOL nNewX = aCursor.Col(); |
| SCROW nNewY = aCursor.Row(); |
| SCTAB nTab = aCursor.Tab(); |
| ScDocShell* pDocSh = GetDocShell(); |
| if ( pDocSh ) |
| pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, -1,0, sal_False,sal_True, aMark ); |
| //! sonst Exception oder so |
| |
| SetNewRange( ScRange( nNewX, nNewY, nTab ) ); |
| } |
| |
| void SAL_CALL ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset, sal_Int32 nRowOffset ) |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| const ScRangeList& rRanges = GetRangeList(); |
| DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); |
| ScRange aOneRange(*rRanges.GetObject(0)); |
| aOneRange.Justify(); |
| |
| if ( aOneRange.aStart.Col() + nColumnOffset >= 0 && |
| aOneRange.aEnd.Col() + nColumnOffset <= MAXCOL && |
| aOneRange.aStart.Row() + nRowOffset >= 0 && |
| aOneRange.aEnd.Row() + nRowOffset <= MAXROW ) |
| { |
| ScRange aNew( (SCCOL)(aOneRange.aStart.Col() + nColumnOffset), |
| (SCROW)(aOneRange.aStart.Row() + nRowOffset), |
| aOneRange.aStart.Tab(), |
| (SCCOL)(aOneRange.aEnd.Col() + nColumnOffset), |
| (SCROW)(aOneRange.aEnd.Row() + nRowOffset), |
| aOneRange.aEnd.Tab() ); |
| SetNewRange( aNew ); |
| } |
| } |
| |
| // XSheetCellRange |
| |
| uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellCursorObj::getSpreadsheet() |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| return ScCellRangeObj::getSpreadsheet(); |
| } |
| |
| // XCellRange |
| |
| uno::Reference<table::XCell> SAL_CALL ScCellCursorObj::getCellByPosition( |
| sal_Int32 nColumn, sal_Int32 nRow ) |
| throw(lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| return ScCellRangeObj::getCellByPosition(nColumn,nRow); |
| } |
| |
| uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByPosition( |
| sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) |
| throw(lang::IndexOutOfBoundsException, uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom); |
| } |
| |
| uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByName( |
| const rtl::OUString& rRange ) throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| return ScCellRangeObj::getCellRangeByName(rRange); |
| } |
| |
| // XServiceInfo |
| |
| rtl::OUString SAL_CALL ScCellCursorObj::getImplementationName() throw(uno::RuntimeException) |
| { |
| return rtl::OUString::createFromAscii( "ScCellCursorObj" ); |
| } |
| |
| sal_Bool SAL_CALL ScCellCursorObj::supportsService( const rtl::OUString& rServiceName ) |
| throw(uno::RuntimeException) |
| { |
| String aServiceStr( rServiceName ); |
| return aServiceStr.EqualsAscii( SCSHEETCELLCURSOR_SERVICE ) || |
| aServiceStr.EqualsAscii( SCCELLCURSOR_SERVICE ) || |
| ScCellRangeObj::supportsService(rServiceName); |
| } |
| |
| uno::Sequence<rtl::OUString> SAL_CALL ScCellCursorObj::getSupportedServiceNames() |
| throw(uno::RuntimeException) |
| { |
| // get all service names from cell range |
| uno::Sequence<rtl::OUString> aParentSeq(ScCellRangeObj::getSupportedServiceNames()); |
| sal_Int32 nParentLen = aParentSeq.getLength(); |
| const rtl::OUString* pParentArr = aParentSeq.getConstArray(); |
| |
| // SheetCellCursor should be first (?) |
| uno::Sequence<rtl::OUString> aTotalSeq( nParentLen + 2 ); |
| rtl::OUString* pTotalArr = aTotalSeq.getArray(); |
| pTotalArr[0] = rtl::OUString::createFromAscii( SCSHEETCELLCURSOR_SERVICE ); |
| pTotalArr[1] = rtl::OUString::createFromAscii( SCCELLCURSOR_SERVICE ); |
| |
| // append cell range services |
| for (long i=0; i<nParentLen; i++) |
| pTotalArr[i+2] = pParentArr[i]; |
| |
| return aTotalSeq; |
| } |
| |
| |
| |
| |