Line data Source code
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 :
21 : #include "svx/svdotable.hxx"
22 : #include "cellcursor.hxx"
23 : #include "tablelayouter.hxx"
24 : #include "cell.hxx"
25 : #include "svx/svdmodel.hxx"
26 : #include "svx/svdstr.hrc"
27 : #include "svx/svdglob.hxx"
28 :
29 : // -----------------------------------------------------------------------------
30 :
31 : using ::rtl::OUString;
32 : using namespace ::com::sun::star::uno;
33 : using namespace ::com::sun::star::lang;
34 : using namespace ::com::sun::star::container;
35 : using namespace ::com::sun::star::beans;
36 : using namespace ::com::sun::star::table;
37 :
38 : // -----------------------------------------------------------------------------
39 :
40 : namespace sdr { namespace table {
41 :
42 : // -----------------------------------------------------------------------------
43 : // CellCursor
44 : // -----------------------------------------------------------------------------
45 :
46 8 : CellCursor::CellCursor( const TableModelRef & xTable, sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
47 8 : : CellCursorBase( xTable, nLeft, nTop, nRight, nBottom )
48 : {
49 8 : }
50 :
51 : // -----------------------------------------------------------------------------
52 :
53 16 : CellCursor::~CellCursor()
54 : {
55 16 : }
56 :
57 : // -----------------------------------------------------------------------------
58 : // XCellCursor
59 : // -----------------------------------------------------------------------------
60 :
61 0 : Reference< XCell > SAL_CALL CellCursor::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException)
62 : {
63 0 : return CellRange::getCellByPosition( nColumn, nRow );
64 : }
65 :
66 : // -----------------------------------------------------------------------------
67 :
68 0 : Reference< XCellRange > SAL_CALL CellCursor::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) throw (IndexOutOfBoundsException, RuntimeException)
69 : {
70 0 : return CellRange::getCellRangeByPosition( nLeft, nTop, nRight, nBottom );
71 : }
72 :
73 : // -----------------------------------------------------------------------------
74 :
75 0 : Reference< XCellRange > SAL_CALL CellCursor::getCellRangeByName( const OUString& aRange ) throw (RuntimeException)
76 : {
77 0 : return CellRange::getCellRangeByName( aRange );
78 : }
79 :
80 : // -----------------------------------------------------------------------------
81 : // XCellCursor
82 : // -----------------------------------------------------------------------------
83 :
84 0 : void SAL_CALL CellCursor::gotoStart( ) throw (RuntimeException)
85 : {
86 0 : mnRight = mnLeft;
87 0 : mnBottom = mnTop;
88 0 : }
89 :
90 : // -----------------------------------------------------------------------------
91 :
92 0 : void SAL_CALL CellCursor::gotoEnd( ) throw (RuntimeException)
93 : {
94 0 : mnLeft = mnRight;
95 0 : mnTop = mnBottom;
96 0 : }
97 :
98 : // -----------------------------------------------------------------------------
99 :
100 0 : void SAL_CALL CellCursor::gotoNext( ) throw (RuntimeException)
101 : {
102 0 : if( mxTable.is() )
103 : {
104 0 : mnRight++;
105 0 : if( mnRight >= mxTable->getColumnCount() )
106 : {
107 : // if we past the last column, try skip to the row line
108 0 : mnTop++;
109 0 : if( mnTop >= mxTable->getRowCount() )
110 : {
111 : // if we past the last row, do not move cursor at all
112 0 : mnTop--;
113 0 : mnRight--;
114 : }
115 : else
116 : {
117 : // restart at the first column on the next row
118 0 : mnRight = 0;
119 : }
120 : }
121 : }
122 :
123 0 : mnLeft = mnRight;
124 0 : mnTop = mnBottom;
125 0 : }
126 :
127 : // -----------------------------------------------------------------------------
128 :
129 0 : void SAL_CALL CellCursor::gotoPrevious( ) throw (RuntimeException)
130 : {
131 0 : if( mxTable.is() )
132 : {
133 0 : if( mnLeft > 0 )
134 : {
135 0 : --mnLeft;
136 : }
137 0 : else if( mnTop > 0 )
138 : {
139 0 : --mnTop;
140 0 : mnLeft = mxTable->getColumnCount() - 1;
141 : }
142 : }
143 :
144 0 : mnRight = mnLeft;
145 0 : mnBottom = mnTop;
146 0 : }
147 :
148 : // -----------------------------------------------------------------------------
149 :
150 0 : void SAL_CALL CellCursor::gotoOffset( ::sal_Int32 nColumnOffset, ::sal_Int32 nRowOffset ) throw (RuntimeException)
151 : {
152 0 : if( mxTable.is() )
153 : {
154 0 : const sal_Int32 nLeft = mnLeft + nColumnOffset;
155 0 : if( (nLeft >= 0) && (nLeft < mxTable->getColumnCount() ) )
156 0 : mnRight = mnLeft = nLeft;
157 :
158 0 : const sal_Int32 nTop = mnTop + nRowOffset;
159 0 : if( (nTop >= 0) && (nTop < mxTable->getRowCount()) )
160 0 : mnTop = mnBottom = nTop;
161 : }
162 0 : }
163 :
164 : // -----------------------------------------------------------------------------
165 : // XMergeableCellCursor
166 : // -----------------------------------------------------------------------------
167 :
168 : /** returns true and the merged cell positions if a merge is valid or false if a merge is
169 : not valid for that range */
170 16 : bool CellCursor::GetMergedSelection( CellPos& rStart, CellPos& rEnd )
171 : {
172 16 : rStart.mnCol = mnLeft; rStart.mnRow = mnTop;
173 16 : rEnd.mnCol = mnRight; rEnd.mnRow = mnBottom;
174 :
175 : // single cell merge is never valid
176 16 : if( mxTable.is() && ((mnLeft != mnRight) || (mnTop != mnBottom)) ) try
177 : {
178 16 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( mnLeft, mnTop ).get() ) );
179 :
180 : // check if first cell is merged
181 16 : if( xCell.is() && xCell->isMerged() )
182 0 : findMergeOrigin( mxTable, mnLeft, mnTop, rStart.mnCol, rStart.mnRow );
183 :
184 : // check if last cell is merged
185 16 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( mnRight, mnBottom ).get() ) );
186 16 : if( xCell.is() )
187 : {
188 16 : if( xCell->isMerged() )
189 : {
190 0 : findMergeOrigin( mxTable, mnRight, mnBottom, rEnd.mnCol, rEnd.mnRow );
191 : // merge not possible if selection is only one cell and all its merges
192 0 : if( rEnd == rStart )
193 0 : return false;
194 0 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( rEnd.mnCol, rEnd.mnRow ).get() ) );
195 : }
196 : }
197 16 : if( xCell.is() )
198 : {
199 16 : rEnd.mnCol += xCell->getColumnSpan()-1;
200 16 : rEnd.mnRow += xCell->getRowSpan()-1;
201 : }
202 :
203 : // now check if everything is inside the given bounds
204 : sal_Int32 nRow, nCol;
205 54 : for( nRow = rStart.mnRow; nRow <= rEnd.mnRow; nRow++ )
206 : {
207 76 : for( nCol = rStart.mnCol; nCol <= rEnd.mnCol; nCol++ )
208 : {
209 38 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
210 38 : if( !xCell.is() )
211 0 : continue;
212 :
213 38 : if( xCell->isMerged() )
214 : {
215 : sal_Int32 nOriginCol, nOriginRow;
216 0 : if( findMergeOrigin( mxTable, nCol, nRow, nOriginCol, nOriginRow ) )
217 : {
218 0 : if( (nOriginCol < rStart.mnCol) || (nOriginRow < rStart.mnRow) )
219 0 : return false;
220 :
221 0 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( nOriginCol, nOriginRow ).get() ) );
222 0 : if( xCell.is() )
223 : {
224 0 : nOriginCol += xCell->getColumnSpan()-1;
225 0 : nOriginRow += xCell->getRowSpan()-1;
226 :
227 0 : if( (nOriginCol > rEnd.mnCol) || (nOriginRow > rEnd.mnRow) )
228 0 : return false;
229 : }
230 : }
231 : }
232 38 : else if( ((nCol + xCell->getColumnSpan() - 1) > rEnd.mnCol) || ((nRow + xCell->getRowSpan() - 1 ) > rEnd.mnRow) )
233 : {
234 0 : return false;
235 : }
236 : }
237 : }
238 16 : return true;
239 : }
240 0 : catch( Exception& )
241 : {
242 : OSL_FAIL("sdr::table::SvmxTableController::GetMergedSelection(), exception caught!");
243 : }
244 0 : return false;
245 : }
246 :
247 : // -----------------------------------------------------------------------------
248 :
249 8 : void SAL_CALL CellCursor::merge( ) throw (NoSupportException, RuntimeException)
250 : {
251 8 : CellPos aStart, aEnd;
252 8 : if( !GetMergedSelection( aStart, aEnd ) )
253 0 : throw NoSupportException();
254 :
255 8 : if( !mxTable.is() || (mxTable->getSdrTableObj() == 0) )
256 0 : throw DisposedException();
257 :
258 8 : SdrModel* pModel = mxTable->getSdrTableObj()->GetModel();
259 8 : const bool bUndo = pModel && mxTable->getSdrTableObj()->IsInserted() && pModel->IsUndoEnabled();
260 :
261 8 : if( bUndo )
262 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
263 :
264 : try
265 : {
266 8 : mxTable->merge( aStart.mnCol, aStart.mnRow, aEnd.mnCol - aStart.mnCol + 1, aEnd.mnRow - aStart.mnRow + 1 );
267 8 : mxTable->optimize();
268 8 : mxTable->setModified(sal_True);
269 : }
270 0 : catch( Exception& )
271 : {
272 : OSL_FAIL("sdr::table::CellCursor::merge(), exception caught!");
273 : }
274 :
275 8 : if( bUndo )
276 0 : pModel->EndUndo();
277 :
278 8 : if( pModel )
279 8 : pModel->SetChanged();
280 8 : }
281 :
282 : // -----------------------------------------------------------------------------
283 :
284 0 : void CellCursor::split_column( sal_Int32 nCol, sal_Int32 nColumns, std::vector< sal_Int32 >& rLeftOvers )
285 : {
286 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
287 :
288 0 : sal_Int32 nNewCols = 0, nRow;
289 :
290 : // first check how many columns we need to add
291 0 : for( nRow = mnTop; nRow <= mnBottom; ++nRow )
292 : {
293 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
294 0 : if( xCell.is() && !xCell->isMerged() )
295 0 : nNewCols = std::max( nNewCols, nColumns - xCell->getColumnSpan() + 1 - rLeftOvers[nRow] );
296 0 : }
297 :
298 0 : if( nNewCols > 0 )
299 : {
300 0 : const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM("Width") );
301 0 : Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
302 0 : Reference< XPropertySet > xRefColumn( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
303 0 : sal_Int32 nWidth = 0;
304 0 : xRefColumn->getPropertyValue( sWidth ) >>= nWidth;
305 0 : const sal_Int32 nNewWidth = nWidth / (nNewCols + 1);
306 :
307 : // reference column gets new width + rounding errors
308 0 : xRefColumn->setPropertyValue( sWidth, Any( nWidth - (nNewWidth * nNewCols) ) );
309 :
310 0 : xCols->insertByIndex( nCol + 1, nNewCols );
311 0 : mnRight += nNewCols;
312 :
313 : // distribute new width
314 0 : for( sal_Int32 nNewCol = nCol + nNewCols; nNewCol > nCol; --nNewCol )
315 : {
316 0 : Reference< XPropertySet > xNewCol( xCols->getByIndex( nNewCol ), UNO_QUERY_THROW );
317 0 : xNewCol->setPropertyValue( sWidth, Any( nNewWidth ) );
318 0 : }
319 : }
320 :
321 0 : for( nRow = 0; nRow < nRowCount; ++nRow )
322 : {
323 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
324 0 : if( !xCell.is() || xCell->isMerged() )
325 : {
326 0 : if( nNewCols > 0 )
327 : {
328 : // merged cells are ignored, but newly added columns will be added to leftovers
329 0 : xCell.set( dynamic_cast< Cell* >(mxTable->getCellByPosition( nCol+1, nRow ).get() ) );
330 0 : if( !xCell.is() || !xCell->isMerged() )
331 0 : rLeftOvers[nRow] += nNewCols;
332 : }
333 : }
334 : else
335 : {
336 0 : sal_Int32 nRowSpan = xCell->getRowSpan() - 1;
337 0 : sal_Int32 nColSpan = xCell->getColumnSpan() - 1;
338 :
339 0 : if( (nRow >= mnTop) && (nRow <= mnBottom) )
340 : {
341 0 : sal_Int32 nCellsAvailable = 1 + nColSpan + rLeftOvers[nRow];
342 0 : if( nColSpan == 0 )
343 0 : nCellsAvailable += nNewCols;
344 :
345 : DBG_ASSERT( nCellsAvailable > nColumns, "sdr::table::CellCursor::split_column(), somethings wrong" );
346 :
347 0 : sal_Int32 nSplitSpan = (nCellsAvailable / (nColumns + 1)) - 1;
348 :
349 0 : sal_Int32 nSplitCol = nCol;
350 0 : sal_Int32 nSplits = nColumns + 1;
351 0 : while( nSplits-- )
352 : {
353 : // last split eats rounding cells
354 0 : if( nSplits == 0 )
355 0 : nSplitSpan = nCellsAvailable - ((nSplitSpan+1) * nColumns) - 1;
356 :
357 0 : mxTable->merge( nSplitCol, nRow, nSplitSpan + 1, nRowSpan + 1);
358 0 : if( nSplits > 0 )
359 0 : nSplitCol += nSplitSpan + 1;
360 : }
361 :
362 0 : do
363 : {
364 0 : rLeftOvers[nRow++] = 0;
365 : }
366 : while( nRowSpan-- );
367 0 : --nRow;
368 : }
369 : else
370 : {
371 : // cope with outside cells, merge if needed
372 0 : if( nColSpan < (rLeftOvers[nRow] + nNewCols) )
373 0 : mxTable->merge( nCol, nRow, (rLeftOvers[nRow] + nNewCols) + 1, nRowSpan + 1 );
374 :
375 0 : do
376 : {
377 0 : rLeftOvers[nRow++] = 0; // consumed
378 : }
379 : while( nRowSpan-- );
380 0 : --nRow;
381 : }
382 : }
383 0 : }
384 0 : }
385 :
386 : // -----------------------------------------------------------------------------
387 :
388 0 : void CellCursor::split_horizontal( sal_Int32 nColumns )
389 : {
390 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
391 :
392 0 : std::vector< sal_Int32 > aLeftOvers( nRowCount );
393 :
394 0 : for( sal_Int32 nCol = mnRight; nCol >= mnLeft; --nCol )
395 0 : split_column( nCol, nColumns, aLeftOvers );
396 0 : }
397 :
398 : // -----------------------------------------------------------------------------
399 :
400 0 : void CellCursor::split_row( sal_Int32 nRow, sal_Int32 nRows, std::vector< sal_Int32 >& rLeftOvers )
401 : {
402 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
403 :
404 0 : sal_Int32 nNewRows = 0, nCol;
405 :
406 : // first check how many columns we need to add
407 0 : for( nCol = mnLeft; nCol <= mnRight; ++nCol )
408 : {
409 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
410 0 : if( xCell.is() && !xCell->isMerged() )
411 0 : nNewRows = std::max( nNewRows, nRows - xCell->getRowSpan() + 1 - rLeftOvers[nCol] );
412 0 : }
413 :
414 0 : if( nNewRows > 0 )
415 : {
416 0 : const OUString sHeight( RTL_CONSTASCII_USTRINGPARAM("Height") );
417 0 : Reference< XTableRows > xRows( mxTable->getRows(), UNO_QUERY_THROW );
418 0 : Reference< XPropertySet > xRefRow( xRows->getByIndex( nRow ), UNO_QUERY_THROW );
419 0 : sal_Int32 nHeight = 0;
420 0 : xRefRow->getPropertyValue( sHeight ) >>= nHeight;
421 0 : const sal_Int32 nNewHeight = nHeight / (nNewRows + 1);
422 :
423 : // reference row gets new height + rounding errors
424 0 : xRefRow->setPropertyValue( sHeight, Any( nHeight - (nNewHeight * nNewRows) ) );
425 :
426 0 : xRows->insertByIndex( nRow + 1, nNewRows );
427 0 : mnBottom += nNewRows;
428 :
429 : // distribute new width
430 0 : for( sal_Int32 nNewRow = nRow + nNewRows; nNewRow > nRow; --nNewRow )
431 : {
432 0 : Reference< XPropertySet > xNewRow( xRows->getByIndex( nNewRow ), UNO_QUERY_THROW );
433 0 : xNewRow->setPropertyValue( sHeight, Any( nNewHeight ) );
434 0 : }
435 : }
436 :
437 0 : for( nCol = 0; nCol < nColCount; ++nCol )
438 : {
439 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
440 0 : if( !xCell.is() || xCell->isMerged() )
441 : {
442 0 : if( nNewRows )
443 : {
444 : // merged cells are ignored, but newly added columns will be added to leftovers
445 0 : xCell.set( dynamic_cast< Cell* >(mxTable->getCellByPosition( nCol, nRow+1 ).get() ) );
446 0 : if( !xCell.is() || !xCell->isMerged() )
447 0 : rLeftOvers[nCol] += nNewRows;
448 : }
449 : }
450 : else
451 : {
452 0 : sal_Int32 nRowSpan = xCell->getRowSpan() - 1;
453 0 : sal_Int32 nColSpan = xCell->getColumnSpan() - 1;
454 :
455 0 : if( (nCol >= mnLeft) && (nCol <= mnRight) )
456 : {
457 0 : sal_Int32 nCellsAvailable = 1 + nRowSpan + rLeftOvers[nCol];
458 0 : if( nRowSpan == 0 )
459 0 : nCellsAvailable += nNewRows;
460 :
461 : DBG_ASSERT( nCellsAvailable > nRows, "sdr::table::CellCursor::split_row(), somethings wrong" );
462 :
463 0 : sal_Int32 nSplitSpan = (nCellsAvailable / (nRows + 1)) - 1;
464 :
465 0 : sal_Int32 nSplitRow = nRow;
466 0 : sal_Int32 nSplits = nRows + 1;
467 0 : while( nSplits-- )
468 : {
469 : // last split eats rounding cells
470 0 : if( nSplits == 0 )
471 0 : nSplitSpan = nCellsAvailable - ((nSplitSpan+1) * nRows) - 1;
472 :
473 0 : mxTable->merge( nCol, nSplitRow, nColSpan + 1, nSplitSpan + 1 );
474 0 : if( nSplits > 0 )
475 0 : nSplitRow += nSplitSpan + 1;
476 : }
477 :
478 0 : do
479 : {
480 0 : rLeftOvers[nCol++] = 0;
481 : }
482 : while( nColSpan-- );
483 0 : --nCol;
484 : }
485 : else
486 : {
487 : // cope with outside cells, merge if needed
488 0 : if( nRowSpan < (rLeftOvers[nCol] + nNewRows) )
489 0 : mxTable->merge( nCol, nRow, nColSpan + 1, (rLeftOvers[nCol] + nNewRows) + 1 );
490 :
491 0 : do
492 : {
493 0 : rLeftOvers[nCol++] = 0; // consumed
494 : }
495 : while( nColSpan-- );
496 0 : --nCol;
497 : }
498 : }
499 0 : }
500 0 : }
501 :
502 : // -----------------------------------------------------------------------------
503 :
504 0 : void CellCursor::split_vertical( sal_Int32 nRows )
505 : {
506 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
507 :
508 0 : std::vector< sal_Int32 > aLeftOvers( nColCount );
509 :
510 0 : for( sal_Int32 nRow = mnBottom; nRow >= mnTop; --nRow )
511 0 : split_row( nRow, nRows, aLeftOvers );
512 0 : }
513 :
514 : // -----------------------------------------------------------------------------
515 :
516 0 : void SAL_CALL CellCursor::split( sal_Int32 nColumns, sal_Int32 nRows ) throw (NoSupportException, IllegalArgumentException, RuntimeException)
517 : {
518 0 : if( (nColumns < 0) || (nRows < 0) )
519 0 : throw IllegalArgumentException();
520 :
521 0 : if( !mxTable.is() || (mxTable->getSdrTableObj() == 0) )
522 0 : throw DisposedException();
523 :
524 0 : SdrModel* pModel = mxTable->getSdrTableObj()->GetModel();
525 0 : const bool bUndo = pModel && mxTable->getSdrTableObj()->IsInserted() && pModel->IsUndoEnabled();
526 0 : if( bUndo )
527 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
528 :
529 : try
530 : {
531 0 : if( nColumns > 0 )
532 0 : split_horizontal( nColumns );
533 :
534 0 : if( nRows > 0 )
535 0 : split_vertical( nRows );
536 :
537 0 : if( nColumns > 0 ||nRows > 0 )
538 0 : mxTable->setModified(sal_True);
539 : }
540 0 : catch( Exception& )
541 : {
542 : OSL_FAIL("sdr::table::CellCursor::split(), exception caught!");
543 0 : throw NoSupportException();
544 : }
545 :
546 0 : if( bUndo )
547 0 : pModel->EndUndo();
548 :
549 0 : if( pModel )
550 0 : pModel->SetChanged();
551 0 : }
552 :
553 : // -----------------------------------------------------------------------------
554 :
555 8 : sal_Bool SAL_CALL CellCursor::isMergeable( ) throw (RuntimeException)
556 : {
557 8 : CellPos aStart, aEnd;
558 8 : return GetMergedSelection( aStart, aEnd ) ? sal_True : sal_False;
559 : }
560 :
561 : // -----------------------------------------------------------------------------
562 :
563 0 : sal_Bool SAL_CALL CellCursor::isUnmergeable( ) throw (RuntimeException)
564 : {
565 : // this is true if there is at least one merged cell in the current range
566 0 : for( sal_Int32 nRow = mnTop; nRow <= mnBottom; nRow++ )
567 : {
568 0 : for( sal_Int32 nCol = mnLeft; nCol <= mnRight; nCol++ )
569 : {
570 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
571 0 : if( xCell.is() && ( (xCell->getRowSpan() > 1) || (xCell->getColumnSpan() > 1) ) )
572 0 : return sal_True;
573 0 : }
574 : }
575 0 : return sal_False;
576 : }
577 :
578 : // -----------------------------------------------------------------------------
579 :
580 : } }
581 :
582 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|