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
ScCellCursorObj(ScDocShell * pDocSh,const ScRange & rR)52 ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) :
53 ScCellRangeObj( pDocSh, rR )
54 {
55 }
56
~ScCellCursorObj()57 ScCellCursorObj::~ScCellCursorObj()
58 {
59 }
60
queryInterface(const uno::Type & rType)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
acquire()70 void SAL_CALL ScCellCursorObj::acquire() throw()
71 {
72 ScCellRangeObj::acquire();
73 }
74
release()75 void SAL_CALL ScCellCursorObj::release() throw()
76 {
77 ScCellRangeObj::release();
78 }
79
getTypes()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
getImplementationId()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
collapseToCurrentRegion()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
collapseToCurrentArray()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
collapseToMergedArea()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
expandToEntireColumns()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
expandToEntireRows()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
collapseToSize(sal_Int32 nColumns,sal_Int32 nRows)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
gotoStartOfUsedArea(sal_Bool bExpand)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
gotoEndOfUsedArea(sal_Bool bExpand)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
gotoStart()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
gotoEnd()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
gotoNext()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
gotoPrevious()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
gotoOffset(sal_Int32 nColumnOffset,sal_Int32 nRowOffset)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
getSpreadsheet()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
getCellByPosition(sal_Int32 nColumn,sal_Int32 nRow)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
getCellRangeByPosition(sal_Int32 nLeft,sal_Int32 nTop,sal_Int32 nRight,sal_Int32 nBottom)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
getCellRangeByName(const rtl::OUString & rRange)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
getImplementationName()469 rtl::OUString SAL_CALL ScCellCursorObj::getImplementationName() throw(uno::RuntimeException)
470 {
471 return rtl::OUString::createFromAscii( "ScCellCursorObj" );
472 }
473
supportsService(const rtl::OUString & rServiceName)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
getSupportedServiceNames()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