1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <vcl/svapp.hxx>
21 #include <comphelper/sequence.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23
24 #include <cursuno.hxx>
25 #include <cellsuno.hxx>
26 #include <docsh.hxx>
27 #include <markdata.hxx>
28 #include <miscuno.hxx>
29
30 using namespace com::sun::star;
31
32 #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor"
33 #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor"
34
ScCellCursorObj(ScDocShell * pDocSh,const ScRange & rR)35 ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) :
36 ScCellRangeObj( pDocSh, rR )
37 {
38 }
39
~ScCellCursorObj()40 ScCellCursorObj::~ScCellCursorObj()
41 {
42 }
43
queryInterface(const uno::Type & rType)44 uno::Any SAL_CALL ScCellCursorObj::queryInterface( const uno::Type& rType )
45 {
46 SC_QUERYINTERFACE( sheet::XSheetCellCursor )
47 SC_QUERYINTERFACE( sheet::XUsedAreaCursor )
48 SC_QUERYINTERFACE( table::XCellCursor )
49
50 return ScCellRangeObj::queryInterface( rType );
51 }
52
acquire()53 void SAL_CALL ScCellCursorObj::acquire() noexcept
54 {
55 ScCellRangeObj::acquire();
56 }
57
release()58 void SAL_CALL ScCellCursorObj::release() noexcept
59 {
60 ScCellRangeObj::release();
61 }
62
getTypes()63 uno::Sequence<uno::Type> SAL_CALL ScCellCursorObj::getTypes()
64 {
65 return comphelper::concatSequences(
66 ScCellRangeObj::getTypes(),
67 uno::Sequence<uno::Type>
68 {
69 cppu::UnoType<sheet::XSheetCellCursor>::get(),
70 cppu::UnoType<sheet::XUsedAreaCursor>::get(),
71 cppu::UnoType<table::XCellCursor>::get()
72 } );
73 }
74
getImplementationId()75 uno::Sequence<sal_Int8> SAL_CALL ScCellCursorObj::getImplementationId()
76 {
77 return css::uno::Sequence<sal_Int8>();
78 }
79
80 // XSheetCellCursor
81
collapseToCurrentRegion()82 void SAL_CALL ScCellCursorObj::collapseToCurrentRegion()
83 {
84 SolarMutexGuard aGuard;
85 const ScRangeList& rRanges = GetRangeList();
86 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
87 ScRange aOneRange( rRanges[ 0 ] );
88
89 aOneRange.PutInOrder();
90 ScDocShell* pDocSh = GetDocShell();
91 if ( !pDocSh )
92 return;
93
94 SCCOL nStartCol = aOneRange.aStart.Col();
95 SCROW nStartRow = aOneRange.aStart.Row();
96 SCCOL nEndCol = aOneRange.aEnd.Col();
97 SCROW nEndRow = aOneRange.aEnd.Row();
98 SCTAB nTab = aOneRange.aStart.Tab();
99
100 pDocSh->GetDocument().GetDataArea(
101 nTab, nStartCol, nStartRow, nEndCol, nEndRow, true, false );
102
103 ScRange aNew( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
104 SetNewRange( aNew );
105 }
106
collapseToCurrentArray()107 void SAL_CALL ScCellCursorObj::collapseToCurrentArray()
108 {
109 SolarMutexGuard aGuard;
110 const ScRangeList& rRanges = GetRangeList();
111 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
112 ScRange aOneRange( rRanges[ 0 ] );
113
114 aOneRange.PutInOrder();
115 ScAddress aCursor(aOneRange.aStart); // use the start address of the range
116
117 ScDocShell* pDocSh = GetDocShell();
118 if ( pDocSh )
119 {
120 ScDocument& rDoc = pDocSh->GetDocument();
121 ScRange aMatrix;
122
123 // finding the matrix range is now in GetMatrixFormulaRange in the document
124 if ( rDoc.GetMatrixFormulaRange( aCursor, aMatrix ) )
125 {
126 SetNewRange( aMatrix );
127 }
128 }
129 // that's a Bug, that this assertion comes; the API Reference says, that
130 // if there is no Matrix, the Range is left unchanged; they say nothing
131 // about an exception
132 /*if (!bFound)
133 {
134 OSL_FAIL("no matrix");
135 //! Exception, or what?
136 }*/
137 }
138
collapseToMergedArea()139 void SAL_CALL ScCellCursorObj::collapseToMergedArea()
140 {
141 SolarMutexGuard aGuard;
142 ScDocShell* pDocSh = GetDocShell();
143 if ( pDocSh )
144 {
145 const ScRangeList& rRanges = GetRangeList();
146 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
147 ScRange aNewRange( rRanges[ 0 ] );
148
149 ScDocument& rDoc = pDocSh->GetDocument();
150 rDoc.ExtendOverlapped( aNewRange );
151 rDoc.ExtendMerge( aNewRange ); // after ExtendOverlapped!
152
153 SetNewRange( aNewRange );
154 }
155 }
156
expandToEntireColumns()157 void SAL_CALL ScCellCursorObj::expandToEntireColumns()
158 {
159 SolarMutexGuard aGuard;
160 const ScRangeList& rRanges = GetRangeList();
161 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
162 ScRange aNewRange( rRanges[ 0 ] );
163
164 aNewRange.aStart.SetRow( 0 );
165 aNewRange.aEnd.SetRow( GetDocShell()->GetDocument().MaxRow() );
166
167 SetNewRange( aNewRange );
168 }
169
expandToEntireRows()170 void SAL_CALL ScCellCursorObj::expandToEntireRows()
171 {
172 SolarMutexGuard aGuard;
173 const ScRangeList& rRanges = GetRangeList();
174 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
175 ScRange aNewRange( rRanges[ 0 ] );
176
177 aNewRange.aStart.SetCol( 0 );
178 aNewRange.aEnd.SetCol( GetDocShell()->GetDocument().MaxCol() );
179
180 SetNewRange( aNewRange );
181 }
182
collapseToSize(sal_Int32 nColumns,sal_Int32 nRows)183 void SAL_CALL ScCellCursorObj::collapseToSize( sal_Int32 nColumns, sal_Int32 nRows )
184 {
185 SolarMutexGuard aGuard;
186 if ( nColumns <= 0 || nRows <= 0 )
187 {
188 OSL_FAIL("Empty range not allowed");
189 //! and then?
190 }
191 else
192 {
193 const ScRangeList& rRanges = GetRangeList();
194 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
195 ScRange aNewRange( rRanges[ 0 ] );
196
197 aNewRange.PutInOrder(); //! really?
198
199 const auto & rDoc = GetDocShell()->GetDocument();
200 tools::Long nEndX = aNewRange.aStart.Col() + nColumns - 1;
201 tools::Long nEndY = aNewRange.aStart.Row() + nRows - 1;
202 if ( nEndX < 0 ) nEndX = 0;
203 if ( nEndX > rDoc.MaxCol() ) nEndX = rDoc.MaxCol();
204 if ( nEndY < 0 ) nEndY = 0;
205 if ( nEndY > rDoc.MaxRow() ) nEndY = rDoc.MaxRow();
206 //! error/exception or so, if too big/small
207
208 aNewRange.aEnd.SetCol(static_cast<SCCOL>(nEndX));
209 aNewRange.aEnd.SetRow(static_cast<SCROW>(nEndY));
210
211 aNewRange.PutInOrder(); //! really?
212
213 SetNewRange( aNewRange );
214 }
215 }
216
217 // XUsedAreaCursor
218
gotoStartOfUsedArea(sal_Bool bExpand)219 void SAL_CALL ScCellCursorObj::gotoStartOfUsedArea(sal_Bool bExpand)
220 {
221 SolarMutexGuard aGuard;
222 ScDocShell* pDocSh = GetDocShell();
223 if ( !pDocSh )
224 return;
225
226 const ScRangeList& rRanges = GetRangeList();
227 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
228 ScRange aNewRange( rRanges[0] );
229 SCTAB nTab = aNewRange.aStart.Tab();
230
231 SCCOL nUsedX = 0; // fetch the beginning
232 SCROW nUsedY = 0;
233 if (!pDocSh->GetDocument().GetDataStart( nTab, nUsedX, nUsedY ))
234 {
235 nUsedX = 0;
236 nUsedY = 0;
237 }
238
239 aNewRange.aStart.SetCol( nUsedX );
240 aNewRange.aStart.SetRow( nUsedY );
241 if (!bExpand)
242 aNewRange.aEnd = aNewRange.aStart;
243 SetNewRange( aNewRange );
244 }
245
gotoEndOfUsedArea(sal_Bool bExpand)246 void SAL_CALL ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand )
247 {
248 SolarMutexGuard aGuard;
249 ScDocShell* pDocSh = GetDocShell();
250 if ( !pDocSh )
251 return;
252
253 const ScRangeList& rRanges = GetRangeList();
254 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
255 ScRange aNewRange( rRanges[ 0 ]);
256 SCTAB nTab = aNewRange.aStart.Tab();
257
258 SCCOL nUsedX = 0; // fetch the end
259 SCROW nUsedY = 0;
260 if (!pDocSh->GetDocument().GetTableArea( nTab, nUsedX, nUsedY, true ))
261 {
262 nUsedX = 0;
263 nUsedY = 0;
264 }
265
266 aNewRange.aEnd.SetCol( nUsedX );
267 aNewRange.aEnd.SetRow( nUsedY );
268 if (!bExpand)
269 aNewRange.aStart = aNewRange.aEnd;
270 SetNewRange( aNewRange );
271 }
272
273 // XCellCursor
274
gotoStart()275 void SAL_CALL ScCellCursorObj::gotoStart()
276 {
277 // this is similar to collapseToCurrentRegion
278 //! something like gotoEdge with 4 possible directions is needed
279
280 SolarMutexGuard aGuard;
281 const ScRangeList& rRanges = GetRangeList();
282 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
283 ScRange aOneRange( rRanges[ 0 ]);
284
285 aOneRange.PutInOrder();
286 ScDocShell* pDocSh = GetDocShell();
287 if ( !pDocSh )
288 return;
289
290 SCCOL nStartCol = aOneRange.aStart.Col();
291 SCROW nStartRow = aOneRange.aStart.Row();
292 SCCOL nEndCol = aOneRange.aEnd.Col();
293 SCROW nEndRow = aOneRange.aEnd.Row();
294 SCTAB nTab = aOneRange.aStart.Tab();
295
296 pDocSh->GetDocument().GetDataArea(
297 nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, false );
298
299 ScRange aNew( nStartCol, nStartRow, nTab );
300 SetNewRange( aNew );
301 }
302
gotoEnd()303 void SAL_CALL ScCellCursorObj::gotoEnd()
304 {
305 // this is similar to collapseToCurrentRegion
306 //! something like gotoEdge with 4 possible directions is needed
307
308 SolarMutexGuard aGuard;
309 const ScRangeList& rRanges = GetRangeList();
310 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
311 ScRange aOneRange( rRanges[ 0 ] );
312
313 aOneRange.PutInOrder();
314 ScDocShell* pDocSh = GetDocShell();
315 if ( !pDocSh )
316 return;
317
318 SCCOL nStartCol = aOneRange.aStart.Col();
319 SCROW nStartRow = aOneRange.aStart.Row();
320 SCCOL nEndCol = aOneRange.aEnd.Col();
321 SCROW nEndRow = aOneRange.aEnd.Row();
322 SCTAB nTab = aOneRange.aStart.Tab();
323
324 pDocSh->GetDocument().GetDataArea(
325 nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, false );
326
327 ScRange aNew( nEndCol, nEndRow, nTab );
328 SetNewRange( aNew );
329 }
330
gotoNext()331 void SAL_CALL ScCellCursorObj::gotoNext()
332 {
333 SolarMutexGuard aGuard;
334 const ScRangeList& rRanges = GetRangeList();
335 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
336 ScRange aOneRange( rRanges[ 0 ] );
337
338 aOneRange.PutInOrder();
339 ScAddress aCursor(aOneRange.aStart); // always use start of block
340
341 ScMarkData aMark(GetDocument()->GetSheetLimits()); // not used with bMarked=FALSE
342 SCCOL nNewX = aCursor.Col();
343 SCROW nNewY = aCursor.Row();
344 SCTAB nTab = aCursor.Tab();
345 ScDocShell* pDocSh = GetDocShell();
346 if ( pDocSh )
347 pDocSh->GetDocument().GetNextPos( nNewX,nNewY, nTab, 1,0, false,true, aMark );
348 //! otherwise exception or so
349
350 SetNewRange( ScRange( nNewX, nNewY, nTab ) );
351 }
352
gotoPrevious()353 void SAL_CALL ScCellCursorObj::gotoPrevious()
354 {
355 SolarMutexGuard aGuard;
356 const ScRangeList& rRanges = GetRangeList();
357 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
358 ScRange aOneRange( rRanges[ 0 ] );
359
360 aOneRange.PutInOrder();
361 ScAddress aCursor(aOneRange.aStart); // always use start of block
362
363 ScMarkData aMark(GetDocument()->GetSheetLimits()); // not used with bMarked=FALSE
364 SCCOL nNewX = aCursor.Col();
365 SCROW nNewY = aCursor.Row();
366 SCTAB nTab = aCursor.Tab();
367 ScDocShell* pDocSh = GetDocShell();
368 if ( pDocSh )
369 pDocSh->GetDocument().GetNextPos( nNewX,nNewY, nTab, -1,0, false,true, aMark );
370 //! otherwise exception or so
371
372 SetNewRange( ScRange( nNewX, nNewY, nTab ) );
373 }
374
gotoOffset(sal_Int32 nColumnOffset,sal_Int32 nRowOffset)375 void SAL_CALL ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset, sal_Int32 nRowOffset )
376 {
377 SolarMutexGuard aGuard;
378 const ScRangeList& rRanges = GetRangeList();
379 OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
380 ScRange aOneRange( rRanges[ 0 ] );
381 aOneRange.PutInOrder();
382
383 const auto & rDoc = GetDocShell()->GetDocument();
384 if ( aOneRange.aStart.Col() + nColumnOffset >= 0 &&
385 aOneRange.aEnd.Col() + nColumnOffset <= rDoc.MaxCol() &&
386 aOneRange.aStart.Row() + nRowOffset >= 0 &&
387 aOneRange.aEnd.Row() + nRowOffset <= rDoc.MaxRow() )
388 {
389 ScRange aNew( static_cast<SCCOL>(aOneRange.aStart.Col() + nColumnOffset),
390 static_cast<SCROW>(aOneRange.aStart.Row() + nRowOffset),
391 aOneRange.aStart.Tab(),
392 static_cast<SCCOL>(aOneRange.aEnd.Col() + nColumnOffset),
393 static_cast<SCROW>(aOneRange.aEnd.Row() + nRowOffset),
394 aOneRange.aEnd.Tab() );
395 SetNewRange( aNew );
396 }
397 }
398
399 // XSheetCellRange
400
getSpreadsheet()401 uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellCursorObj::getSpreadsheet()
402 {
403 SolarMutexGuard aGuard;
404 return ScCellRangeObj::getSpreadsheet();
405 }
406
407 // XCellRange
408
getCellByPosition(sal_Int32 nColumn,sal_Int32 nRow)409 uno::Reference<table::XCell> SAL_CALL ScCellCursorObj::getCellByPosition(
410 sal_Int32 nColumn, sal_Int32 nRow )
411 {
412 SolarMutexGuard aGuard;
413 return ScCellRangeObj::getCellByPosition(nColumn,nRow);
414 }
415
getCellRangeByPosition(sal_Int32 nLeft,sal_Int32 nTop,sal_Int32 nRight,sal_Int32 nBottom)416 uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByPosition(
417 sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
418 {
419 SolarMutexGuard aGuard;
420 return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom);
421 }
422
getCellRangeByName(const OUString & rRange)423 uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByName(
424 const OUString& rRange )
425 {
426 SolarMutexGuard aGuard;
427 return ScCellRangeObj::getCellRangeByName(rRange);
428 }
429
430 // XServiceInfo
431
getImplementationName()432 OUString SAL_CALL ScCellCursorObj::getImplementationName()
433 {
434 return "ScCellCursorObj";
435 }
436
supportsService(const OUString & rServiceName)437 sal_Bool SAL_CALL ScCellCursorObj::supportsService( const OUString& rServiceName )
438 {
439 return cppu::supportsService(this, rServiceName);
440 }
441
getSupportedServiceNames()442 uno::Sequence<OUString> SAL_CALL ScCellCursorObj::getSupportedServiceNames()
443 {
444 // SheetCellCursor should be first (?)
445 return comphelper::concatSequences<OUString>(
446 { SCSHEETCELLCURSOR_SERVICE, SCCELLCURSOR_SERVICE },
447 ScCellRangeObj::getSupportedServiceNames());
448 }
449
450 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
451