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 : #include "column.hxx"
21 : #include "scitems.hxx"
22 : #include "formulacell.hxx"
23 : #include "document.hxx"
24 : #include "docpool.hxx"
25 : #include "attarray.hxx"
26 : #include "patattr.hxx"
27 : #include "compiler.hxx"
28 : #include "brdcst.hxx"
29 : #include "markdata.hxx"
30 : #include "detfunc.hxx" // for Notes in Sort/Swap
31 : #include "postit.hxx"
32 : #include "globalnames.hxx"
33 : #include "cellvalue.hxx"
34 : #include "tokenarray.hxx"
35 : #include "cellform.hxx"
36 : #include "clipcontext.hxx"
37 : #include "types.hxx"
38 : #include "editutil.hxx"
39 : #include "mtvcellfunc.hxx"
40 : #include "columnspanset.hxx"
41 : #include "scopetools.hxx"
42 :
43 : #include <svl/poolcach.hxx>
44 : #include <svl/zforlist.hxx>
45 : #include <editeng/scripttypeitem.hxx>
46 : #include "editeng/fieldupdater.hxx"
47 :
48 : #include <cstring>
49 : #include <map>
50 : #include <cstdio>
51 : #include <boost/scoped_ptr.hpp>
52 :
53 : using ::editeng::SvxBorderLine;
54 : using namespace formula;
55 :
56 : namespace {
57 :
58 29699 : inline bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
59 : {
60 : //! move to a header file
61 99 : return ( nScript != SCRIPTTYPE_LATIN &&
62 99 : nScript != SCRIPTTYPE_ASIAN &&
63 29798 : nScript != SCRIPTTYPE_COMPLEX &&
64 29699 : nScript != 0 );
65 : }
66 :
67 : }
68 :
69 129310 : ScNeededSizeOptions::ScNeededSizeOptions() :
70 129310 : pPattern(NULL), bFormula(false), bSkipMerged(true), bGetFont(true), bTotalSize(false)
71 : {
72 129310 : }
73 :
74 1658880 : ScColumn::ScColumn() :
75 : maCellTextAttrs(MAXROWCOUNT),
76 : maBroadcasters(MAXROWCOUNT),
77 : maCells(MAXROWCOUNT),
78 : nCol( 0 ),
79 : pAttrArray( NULL ),
80 : pDocument( NULL ),
81 1658880 : mbDirtyGroups(true)
82 : {
83 1658880 : }
84 :
85 :
86 3108864 : ScColumn::~ScColumn()
87 : {
88 1554432 : FreeAll();
89 1554432 : delete pAttrArray;
90 1554432 : }
91 :
92 :
93 1658880 : void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
94 : {
95 1658880 : nCol = nNewCol;
96 1658880 : nTab = nNewTab;
97 1658880 : pDocument = pDoc;
98 1658880 : pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
99 1658880 : }
100 :
101 :
102 0 : SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
103 : {
104 0 : return pAttrArray->GetNextUnprotected(nRow, bUp);
105 : }
106 :
107 :
108 239331 : sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
109 : {
110 : using namespace sc;
111 :
112 239331 : if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
113 0 : return 0;
114 :
115 239331 : ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
116 :
117 239331 : if (nRow1 == nRow2)
118 : {
119 238308 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
120 238308 : if (aPos.first->type != sc::element_type_formula)
121 237992 : return 0;
122 :
123 316 : const ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second);
124 316 : if (!pCell->GetMatrixFlag())
125 316 : return 0;
126 :
127 0 : return pCell->GetMatrixEdge(aOrigin);
128 : }
129 :
130 1023 : bool bOpen = false;
131 1023 : sal_uInt16 nEdges = 0;
132 :
133 1023 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
134 1023 : sc::CellStoreType::const_iterator it = aPos.first;
135 1023 : size_t nOffset = aPos.second;
136 1023 : SCROW nRow = nRow1;
137 2812 : for (;it != maCells.end() && nRow <= nRow2; ++it, nOffset = 0)
138 : {
139 1789 : if (it->type != sc::element_type_formula)
140 : {
141 : // Skip this block.
142 1761 : nRow += it->size - nOffset;
143 1761 : continue;
144 : }
145 :
146 28 : size_t nRowsToRead = nRow2 - nRow + 1;
147 28 : size_t nEnd = std::min(it->size, nRowsToRead);
148 28 : sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
149 28 : std::advance(itCell, nOffset);
150 86 : for (size_t i = nOffset; i < nEnd; ++itCell, ++i)
151 : {
152 : // Loop inside the formula block.
153 58 : const ScFormulaCell* pCell = *itCell;
154 58 : if (!pCell->GetMatrixFlag())
155 58 : continue;
156 :
157 0 : nEdges = pCell->GetMatrixEdge(aOrigin);
158 0 : if (!nEdges)
159 0 : continue;
160 :
161 0 : if (nEdges & MatrixEdgeTop)
162 0 : bOpen = true; // top edge opens, keep on looking
163 0 : else if (!bOpen)
164 0 : return nEdges | MatrixEdgeOpen; // there's something that wasn't opened
165 0 : else if (nEdges & MatrixEdgeInside)
166 0 : return nEdges; // inside
167 : // (nMask & 16 and (4 and not 16)) or
168 : // (nMask & 4 and (16 and not 4))
169 0 : if (((nMask & MatrixEdgeRight) && (nEdges & MatrixEdgeLeft) && !(nEdges & MatrixEdgeRight)) ||
170 0 : ((nMask & MatrixEdgeLeft) && (nEdges & MatrixEdgeRight) && !(nEdges & MatrixEdgeLeft)))
171 0 : return nEdges; // only left/right edge
172 :
173 0 : if (nEdges & MatrixEdgeBottom)
174 0 : bOpen = false; // bottom edge closes
175 : }
176 :
177 28 : nRow += nEnd;
178 : }
179 1023 : if (bOpen)
180 0 : nEdges |= MatrixEdgeOpen; // not closed, matrix continues
181 :
182 1023 : return nEdges;
183 : }
184 :
185 :
186 68608 : bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
187 : {
188 : using namespace sc;
189 :
190 68608 : if (!rMark.IsMultiMarked())
191 0 : return false;
192 :
193 68608 : ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
194 68608 : ScAddress aCurOrigin = aOrigin;
195 :
196 68608 : bool bOpen = false;
197 68608 : ScRangeList aRanges = rMark.GetMarkedRanges();
198 292864 : for (size_t i = 0, n = aRanges.size(); i < n; ++i)
199 : {
200 224256 : const ScRange& r = *aRanges[i];
201 224256 : if (nTab < r.aStart.Tab() || r.aEnd.Tab() < nTab)
202 223787 : continue;
203 :
204 224256 : if (nCol < r.aStart.Col() || r.aEnd.Col() < nCol)
205 223787 : continue;
206 :
207 469 : SCROW nTop = r.aStart.Row(), nBottom = r.aEnd.Row();
208 469 : SCROW nRow = nTop;
209 469 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
210 469 : sc::CellStoreType::const_iterator it = aPos.first;
211 469 : size_t nOffset = aPos.second;
212 :
213 973 : for (;it != maCells.end() && nRow <= nBottom; ++it, nOffset = 0)
214 : {
215 504 : if (it->type != sc::element_type_formula)
216 : {
217 : // Skip this block.
218 504 : nRow += it->size - nOffset;
219 504 : continue;
220 : }
221 :
222 : // This is a formula cell block.
223 0 : size_t nRowsToRead = nBottom - nRow + 1;
224 0 : size_t nEnd = std::min(it->size, nRowsToRead);
225 0 : sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
226 0 : std::advance(itCell, nOffset);
227 0 : for (size_t j = nOffset; j < nEnd; ++itCell, ++j)
228 : {
229 : // Loop inside the formula block.
230 0 : const ScFormulaCell* pCell = *itCell;
231 0 : if (!pCell->GetMatrixFlag())
232 : // cell is not a part of a matrix.
233 0 : continue;
234 :
235 0 : sal_uInt16 nEdges = pCell->GetMatrixEdge(aOrigin);
236 0 : if (!nEdges)
237 0 : continue;
238 :
239 0 : bool bFound = false;
240 :
241 0 : if (nEdges & MatrixEdgeTop)
242 0 : bOpen = true; // top edge opens, keep on looking
243 0 : else if (!bOpen)
244 0 : return true; // there's something that wasn't opened
245 0 : else if (nEdges & MatrixEdgeInside)
246 0 : bFound = true; // inside, all selected?
247 :
248 0 : if ((((nEdges & MatrixEdgeLeft) | MatrixEdgeRight) ^ ((nEdges & MatrixEdgeRight) | MatrixEdgeLeft)))
249 : // either left or right, but not both.
250 0 : bFound = true; // only left/right edge, all selected?
251 :
252 0 : if (nEdges & MatrixEdgeBottom)
253 0 : bOpen = false; // bottom edge closes
254 :
255 0 : if (bFound)
256 : {
257 : // Check if the matrix is inside the selection in its entirety.
258 : //
259 : // TODO: It's more efficient to skip the matrix range if
260 : // it's within selection, to avoid checking it again and
261 : // again.
262 :
263 0 : if (aCurOrigin != aOrigin)
264 : { // new matrix to check?
265 0 : aCurOrigin = aOrigin;
266 : const ScFormulaCell* pFCell;
267 0 : if (pCell->GetMatrixFlag() == MM_REFERENCE)
268 0 : pFCell = pDocument->GetFormulaCell(aOrigin);
269 : else
270 0 : pFCell = pCell;
271 :
272 : SCCOL nC;
273 : SCROW nR;
274 0 : pFCell->GetMatColsRows(nC, nR);
275 0 : ScRange aRange(aOrigin, ScAddress(aOrigin.Col()+nC-1, aOrigin.Row()+nR-1, aOrigin.Tab()));
276 0 : if (rMark.IsAllMarked(aRange))
277 0 : bFound = false;
278 : }
279 : else
280 0 : bFound = false; // done already
281 : }
282 :
283 0 : if (bFound)
284 0 : return true;
285 : }
286 :
287 0 : nRow += nEnd;
288 : }
289 : }
290 :
291 68608 : if (bOpen)
292 0 : return true;
293 :
294 68608 : return false;
295 : }
296 :
297 :
298 11554225 : bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
299 : {
300 11554225 : return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
301 : }
302 :
303 :
304 0 : bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
305 : {
306 0 : bool bFound = false;
307 :
308 : SCROW nTop;
309 : SCROW nBottom;
310 :
311 0 : if (rMark.IsMultiMarked())
312 : {
313 0 : ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
314 0 : while (aMarkIter.Next( nTop, nBottom ) && !bFound)
315 : {
316 0 : if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
317 0 : bFound = true;
318 0 : }
319 : }
320 :
321 0 : return bFound;
322 : }
323 :
324 :
325 5977 : bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
326 : SCCOL& rPaintCol, SCROW& rPaintRow,
327 : bool bRefresh )
328 : {
329 5977 : return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
330 : }
331 :
332 :
333 128000 : void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
334 : {
335 : SCROW nTop;
336 : SCROW nBottom;
337 :
338 128000 : if ( rMark.IsMultiMarked() )
339 : {
340 128000 : const ScMarkArray* pArray = rMark.GetArray() + nCol;
341 128000 : if ( pArray->HasMarks() )
342 : {
343 6900 : ScMarkArrayIter aMarkIter( pArray );
344 20781 : while (aMarkIter.Next( nTop, nBottom ))
345 13881 : pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
346 : }
347 : }
348 128000 : }
349 :
350 :
351 55839 : void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
352 : {
353 55839 : pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
354 55839 : }
355 :
356 :
357 176 : void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
358 : ScLineFlags& rFlags,
359 : SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
360 : {
361 176 : pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
362 176 : }
363 :
364 :
365 1721 : void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
366 : SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
367 : {
368 1721 : pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
369 1721 : }
370 :
371 :
372 41682 : const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
373 : {
374 41682 : return pAttrArray->GetPattern( nRow );
375 : }
376 :
377 :
378 10756 : const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
379 : {
380 10756 : return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
381 : }
382 :
383 :
384 10496 : const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
385 : {
386 10496 : ::std::map< const ScPatternAttr*, size_t > aAttrMap;
387 10496 : const ScPatternAttr* pMaxPattern = 0;
388 10496 : size_t nMaxCount = 0;
389 :
390 10496 : ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
391 : const ScPatternAttr* pPattern;
392 10496 : SCROW nAttrRow1 = 0, nAttrRow2 = 0;
393 :
394 31518 : while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
395 : {
396 10526 : size_t& rnCount = aAttrMap[ pPattern ];
397 10526 : rnCount += (nAttrRow2 - nAttrRow1 + 1);
398 10526 : if( rnCount > nMaxCount )
399 : {
400 10526 : pMaxPattern = pPattern;
401 10526 : nMaxCount = rnCount;
402 : }
403 : }
404 :
405 10496 : return pMaxPattern;
406 : }
407 :
408 10 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
409 : {
410 : SCROW nPatStartRow, nPatEndRow;
411 10 : const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
412 10 : sal_uInt32 nFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
413 30 : while (nEndRow > nPatEndRow)
414 : {
415 10 : nStartRow = nPatEndRow + 1;
416 10 : pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
417 10 : sal_uInt32 nTmpFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
418 10 : if (nFormat != nTmpFormat)
419 0 : return 0;
420 : }
421 10 : return nFormat;
422 : }
423 :
424 :
425 51812 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
426 : {
427 51812 : return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
428 : }
429 :
430 :
431 68608 : SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray )
432 : {
433 68608 : SCROW nTop = 0;
434 68608 : SCROW nBottom = 0;
435 68608 : bool bFound = false;
436 :
437 68608 : if ( rMark.IsMultiMarked() )
438 : {
439 68608 : ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
440 137695 : while (aMarkIter.Next( nTop, nBottom ))
441 : {
442 479 : pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray );
443 479 : bFound = true;
444 68608 : }
445 : }
446 :
447 68608 : if (!bFound)
448 68145 : return -1;
449 463 : else if (nTop==0 && nBottom==MAXROW)
450 0 : return 0;
451 : else
452 463 : return nBottom;
453 : }
454 :
455 :
456 6144 : void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
457 : {
458 : SCROW nTop;
459 : SCROW nBottom;
460 :
461 6144 : if ( pAttrArray && rMark.IsMultiMarked() )
462 : {
463 6144 : ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
464 12314 : while (aMarkIter.Next( nTop, nBottom ))
465 6170 : pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
466 : }
467 6144 : }
468 :
469 0 : void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
470 : {
471 : SCROW nTop;
472 : SCROW nBottom;
473 :
474 0 : if ( pAttrArray && rMark.IsMultiMarked() )
475 : {
476 0 : ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
477 0 : while (aMarkIter.Next( nTop, nBottom ))
478 0 : pAttrArray->ClearItems(nTop, nBottom, pWhich);
479 : }
480 0 : }
481 :
482 :
483 79872 : void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
484 : {
485 : SCROW nTop;
486 : SCROW nBottom;
487 :
488 79872 : if ( rMark.IsMultiMarked() )
489 : {
490 79872 : ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
491 159906 : while (aMarkIter.Next( nTop, nBottom ))
492 80034 : DeleteArea(nTop, nBottom, nDelFlag);
493 : }
494 79872 : }
495 :
496 :
497 188 : void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
498 : {
499 188 : const SfxItemSet* pSet = &rPatAttr.GetItemSet();
500 188 : SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
501 :
502 188 : const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
503 :
504 : // true = keep old content
505 :
506 188 : ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, true );
507 188 : ScDocumentPool::CheckRef( *pPattern );
508 188 : ScDocumentPool::CheckRef( *pNewPattern );
509 :
510 188 : if (pNewPattern != pPattern)
511 188 : pAttrArray->SetPattern( nRow, pNewPattern );
512 188 : }
513 :
514 :
515 29833 : void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
516 : ScEditDataArray* pDataArray )
517 : {
518 29833 : const SfxItemSet* pSet = &rPatAttr.GetItemSet();
519 29833 : SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
520 29833 : pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray );
521 29833 : }
522 :
523 25281 : bool ScColumn::SetAttrEntries(ScAttrEntry* pData, SCSIZE nSize)
524 : {
525 25281 : return pAttrArray->SetAttrEntries(pData, nSize);
526 : }
527 :
528 0 : void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
529 : const ScPatternAttr& rPattern, short nNewType )
530 : {
531 0 : const SfxItemSet* pSet = &rPattern.GetItemSet();
532 0 : SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
533 0 : SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
534 0 : SCROW nEndRow = rRange.aEnd.Row();
535 0 : for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
536 : {
537 : SCROW nRow1, nRow2;
538 : const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
539 0 : nRow1, nRow2, nRow );
540 0 : sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
541 0 : short nOldType = pFormatter->GetType( nFormat );
542 0 : if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
543 0 : nRow = nRow2;
544 : else
545 : {
546 0 : SCROW nNewRow1 = std::max( nRow1, nRow );
547 0 : SCROW nNewRow2 = std::min( nRow2, nEndRow );
548 0 : pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
549 0 : nRow = nNewRow2;
550 : }
551 0 : }
552 0 : }
553 :
554 4360 : void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
555 : {
556 4360 : pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
557 4360 : }
558 :
559 0 : void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
560 : {
561 0 : pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex );
562 0 : }
563 :
564 :
565 3 : void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
566 : {
567 3 : const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
568 3 : ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
569 3 : if (pNewPattern)
570 : {
571 3 : pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
572 3 : pAttrArray->SetPattern(nRow, pNewPattern, true);
573 3 : delete pNewPattern;
574 : }
575 3 : }
576 :
577 :
578 78865 : void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
579 : {
580 78865 : pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
581 78865 : }
582 :
583 :
584 109568 : void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
585 : {
586 : SCROW nTop;
587 : SCROW nBottom;
588 :
589 109568 : if ( rMark.IsMultiMarked() )
590 : {
591 109568 : ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
592 219875 : while (aMarkIter.Next( nTop, nBottom ))
593 110307 : pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
594 : }
595 109568 : }
596 :
597 :
598 0 : void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
599 : const SvxBorderLine* pLine, bool bColorOnly )
600 : {
601 0 : if ( bColorOnly && !pLine )
602 0 : return;
603 :
604 : SCROW nTop;
605 : SCROW nBottom;
606 :
607 0 : if (rMark.IsMultiMarked())
608 : {
609 0 : ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
610 0 : while (aMarkIter.Next( nTop, nBottom ))
611 0 : pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
612 : }
613 : }
614 :
615 :
616 44 : const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
617 : {
618 44 : return pAttrArray->GetPattern( nRow )->GetStyleSheet();
619 : }
620 :
621 :
622 6224 : const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
623 : {
624 6224 : rFound = false;
625 6224 : if (!rMark.IsMultiMarked())
626 : {
627 : OSL_FAIL("No selection in ScColumn::GetSelectionStyle");
628 0 : return NULL;
629 : }
630 :
631 6224 : bool bEqual = true;
632 :
633 6224 : const ScStyleSheet* pStyle = NULL;
634 : const ScStyleSheet* pNewStyle;
635 :
636 6224 : ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
637 : SCROW nTop;
638 : SCROW nBottom;
639 18700 : while (bEqual && aMarkIter.Next( nTop, nBottom ))
640 : {
641 6252 : ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
642 : SCROW nRow;
643 : SCROW nDummy;
644 : const ScPatternAttr* pPattern;
645 18836 : while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
646 : {
647 6332 : pNewStyle = pPattern->GetStyleSheet();
648 6332 : rFound = true;
649 6332 : if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
650 0 : bEqual = false; // difference
651 6332 : pStyle = pNewStyle;
652 : }
653 : }
654 :
655 6224 : return bEqual ? pStyle : NULL;
656 : }
657 :
658 :
659 12398 : const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
660 : {
661 12398 : rFound = false;
662 :
663 12398 : bool bEqual = true;
664 :
665 12398 : const ScStyleSheet* pStyle = NULL;
666 : const ScStyleSheet* pNewStyle;
667 :
668 12398 : ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
669 : SCROW nRow;
670 : SCROW nDummy;
671 : const ScPatternAttr* pPattern;
672 37194 : while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
673 : {
674 12398 : pNewStyle = pPattern->GetStyleSheet();
675 12398 : rFound = true;
676 12398 : if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
677 0 : bEqual = false; // difference
678 12398 : pStyle = pNewStyle;
679 : }
680 :
681 12398 : return bEqual ? pStyle : NULL;
682 : }
683 :
684 3075072 : void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
685 : {
686 3075072 : pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
687 3075072 : }
688 :
689 0 : bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
690 : {
691 0 : return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
692 : }
693 :
694 :
695 4498 : bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
696 : {
697 4498 : return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
698 : }
699 :
700 :
701 5761 : bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
702 : {
703 5761 : return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
704 : }
705 :
706 :
707 5 : void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
708 : {
709 5 : pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
710 5 : }
711 :
712 :
713 163 : void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, bool bPutToPool )
714 : {
715 163 : pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
716 163 : }
717 :
718 :
719 31 : void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
720 : const ScPatternAttr& rPatAttr, bool bPutToPool )
721 : {
722 31 : pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
723 31 : }
724 :
725 :
726 2268 : void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
727 : {
728 : // in order to only create a new SetItem, we don't need SfxItemPoolCache.
729 : //! Warning: SfxItemPoolCache seems to create to many Refs for the new SetItem ??
730 :
731 2268 : ScDocumentPool* pDocPool = pDocument->GetPool();
732 :
733 2268 : const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
734 2268 : ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
735 2268 : pTemp->GetItemSet().Put(rAttr);
736 2268 : const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
737 :
738 2268 : if ( pNewPattern != pOldPattern )
739 2244 : pAttrArray->SetPattern( nRow, pNewPattern );
740 : else
741 24 : pDocPool->Remove( *pNewPattern ); // free up resources
742 :
743 2268 : delete pTemp;
744 2268 : }
745 :
746 192 : ScDocument& ScColumn::GetDoc()
747 : {
748 192 : return *pDocument;
749 : }
750 :
751 1131 : const ScDocument& ScColumn::GetDoc() const
752 : {
753 1131 : return *pDocument;
754 : }
755 :
756 88489 : ScRefCellValue ScColumn::GetCellValue( SCROW nRow ) const
757 : {
758 88489 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
759 88489 : if (aPos.first == maCells.end())
760 0 : return ScRefCellValue();
761 :
762 88489 : return GetCellValue(aPos.first, aPos.second);
763 : }
764 :
765 89817 : ScRefCellValue ScColumn::GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset ) const
766 : {
767 89817 : ScRefCellValue aVal; // Defaults to empty cell.
768 89817 : switch (itPos->type)
769 : {
770 : case sc::element_type_numeric:
771 : // Numeric cell
772 41609 : aVal.mfValue = sc::numeric_block::at(*itPos->data, nOffset);
773 41609 : aVal.meType = CELLTYPE_VALUE;
774 41609 : break;
775 : case sc::element_type_string:
776 : // String cell
777 15503 : aVal.mpString = &sc::string_block::at(*itPos->data, nOffset);
778 15503 : aVal.meType = CELLTYPE_STRING;
779 15503 : break;
780 : case sc::element_type_edittext:
781 : // Edit cell
782 904 : aVal.mpEditText = sc::edittext_block::at(*itPos->data, nOffset);
783 904 : aVal.meType = CELLTYPE_EDIT;
784 904 : break;
785 : case sc::element_type_formula:
786 : // Formula cell
787 3735 : aVal.mpFormula = sc::formula_block::at(*itPos->data, nOffset);
788 3735 : aVal.meType = CELLTYPE_FORMULA;
789 3735 : break;
790 : default:
791 : ;
792 : }
793 :
794 89817 : return aVal;
795 : }
796 :
797 : namespace {
798 :
799 0 : ScFormulaCell* cloneFormulaCell(ScDocument* pDoc, const ScAddress& rNewPos, ScFormulaCell& rOldCell)
800 : {
801 0 : ScFormulaCell* pNew = new ScFormulaCell(rOldCell, *pDoc, rNewPos, SC_CLONECELL_ADJUST3DREL);
802 0 : rOldCell.EndListeningTo(pDoc);
803 0 : pNew->StartListeningTo(pDoc);
804 0 : pNew->SetDirty();
805 0 : return pNew;
806 : }
807 :
808 : }
809 :
810 45 : void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
811 : {
812 45 : if (nRow1 == nRow2)
813 : // Nothing to swap.
814 39 : return;
815 :
816 : // Ensure that nRow1 < nRow2.
817 45 : if (nRow2 < nRow1)
818 0 : std::swap(nRow1, nRow2);
819 :
820 : // Broadcasters (if exist) should NOT be swapped.
821 :
822 45 : sc::CellStoreType::position_type aPos1 = maCells.position(nRow1);
823 45 : if (aPos1.first == maCells.end())
824 0 : return;
825 :
826 45 : sc::CellStoreType::position_type aPos2 = maCells.position(aPos1.first, nRow2);
827 45 : if (aPos2.first == maCells.end())
828 0 : return;
829 :
830 45 : std::vector<SCROW> aRows;
831 45 : aRows.reserve(2);
832 45 : aRows.push_back(nRow1);
833 45 : aRows.push_back(nRow2);
834 :
835 45 : sc::CellStoreType::iterator it1 = aPos1.first, it2 = aPos2.first;
836 :
837 45 : if (it1->type == it2->type)
838 : {
839 : // Both positions are of the same type. Do a simple value swap.
840 36 : switch (it1->type)
841 : {
842 : case sc::element_type_empty:
843 : // Both are empty. Nothing to swap.
844 28 : return;
845 : case sc::element_type_numeric:
846 : std::swap(
847 6 : sc::numeric_block::at(*it1->data, aPos1.second),
848 12 : sc::numeric_block::at(*it2->data, aPos2.second));
849 6 : break;
850 : case sc::element_type_string:
851 : std::swap(
852 2 : sc::string_block::at(*it1->data, aPos1.second),
853 4 : sc::string_block::at(*it2->data, aPos2.second));
854 2 : break;
855 : case sc::element_type_edittext:
856 : std::swap(
857 0 : sc::edittext_block::at(*it1->data, aPos1.second),
858 0 : sc::edittext_block::at(*it2->data, aPos2.second));
859 0 : break;
860 : case sc::element_type_formula:
861 : {
862 : // Swapping of formula cells involve adjustment of references wrt their positions.
863 0 : sc::formula_block::iterator itf1 = sc::formula_block::begin(*it1->data);
864 0 : sc::formula_block::iterator itf2 = sc::formula_block::begin(*it2->data);
865 0 : std::advance(itf1, aPos1.second);
866 0 : std::advance(itf2, aPos2.second);
867 :
868 : // TODO: Find out a way to adjust references without cloning new instances.
869 0 : boost::scoped_ptr<ScFormulaCell> pOld1(*itf1);
870 0 : boost::scoped_ptr<ScFormulaCell> pOld2(*itf2);
871 0 : DetouchFormulaCell(aPos1, **itf1);
872 0 : DetouchFormulaCell(aPos2, **itf2);
873 0 : ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2);
874 0 : ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1);
875 0 : *itf1 = pNew1;
876 0 : *itf2 = pNew2;
877 :
878 0 : ActivateNewFormulaCell(aPos1, *pNew1);
879 0 : ActivateNewFormulaCell(aPos2, *pNew2);
880 : }
881 0 : break;
882 : default:
883 : ;
884 : }
885 :
886 8 : SwapCellTextAttrs(nRow1, nRow2);
887 8 : CellStorageModified();
888 8 : BroadcastCells(aRows);
889 8 : return;
890 : }
891 :
892 : // The two cells are of different types.
893 :
894 9 : ScRefCellValue aCell1 = GetCellValue(aPos1.first, aPos1.second);
895 15 : ScRefCellValue aCell2 = GetCellValue(aPos2.first, aPos2.second);
896 :
897 : // Make sure to put cells in row 1 first then row 2!
898 :
899 9 : if (aCell1.meType == CELLTYPE_NONE)
900 : {
901 : // cell 1 is empty and cell 2 is not.
902 3 : switch (aCell2.meType)
903 : {
904 : case CELLTYPE_VALUE:
905 2 : it1 = maCells.set(it1, nRow1, aCell2.mfValue); // it2 becomes invalid.
906 2 : maCells.set_empty(it1, nRow2, nRow2);
907 2 : break;
908 : case CELLTYPE_STRING:
909 1 : it1 = maCells.set(it1, nRow1, *aCell2.mpString);
910 1 : maCells.set_empty(it1, nRow2, nRow2);
911 1 : break;
912 : case CELLTYPE_EDIT:
913 : {
914 0 : it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
915 : EditTextObject* p;
916 0 : maCells.release(it1, nRow2, p);
917 : }
918 0 : break;
919 : case CELLTYPE_FORMULA:
920 : {
921 : // cell 1 is empty and cell 2 is a formula cell.
922 0 : ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
923 0 : DetouchFormulaCell(aPos2, *aCell2.mpFormula);
924 0 : it1 = maCells.set(it1, nRow1, pNew);
925 0 : maCells.set_empty(it1, nRow2, nRow2); // original formula cell gets deleted.
926 0 : ActivateNewFormulaCell(it1, nRow1, *pNew);
927 : }
928 0 : break;
929 : default:
930 : ;
931 : }
932 :
933 3 : SwapCellTextAttrs(nRow1, nRow2);
934 3 : CellStorageModified();
935 3 : BroadcastCells(aRows);
936 3 : return;
937 : }
938 :
939 6 : if (aCell2.meType == CELLTYPE_NONE)
940 : {
941 : // cell 1 is not empty and cell 2 is empty.
942 0 : switch (aCell1.meType)
943 : {
944 : case CELLTYPE_VALUE:
945 : // Value is copied in Cell1.
946 0 : it1 = maCells.set_empty(it1, nRow1, nRow1);
947 0 : maCells.set(it1, nRow2, aCell1.mfValue);
948 0 : break;
949 : case CELLTYPE_STRING:
950 : {
951 0 : OUString aStr = *aCell1.mpString; // make a copy.
952 0 : it1 = maCells.set_empty(it1, nRow1, nRow1); // original string is gone.
953 0 : maCells.set(it1, nRow2, aStr);
954 : }
955 0 : break;
956 : case CELLTYPE_EDIT:
957 : {
958 : EditTextObject* p;
959 0 : it1 = maCells.release(it1, nRow1, p);
960 0 : maCells.set(it1, nRow2, p);
961 : }
962 0 : break;
963 : case CELLTYPE_FORMULA:
964 : {
965 : // cell 1 is a formula cell and cell 2 is empty.
966 0 : ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
967 0 : DetouchFormulaCell(aPos1, *aCell1.mpFormula);
968 0 : it1 = maCells.set_empty(it1, nRow1, nRow1); // original formula cell is gone.
969 0 : it1 = maCells.set(it1, nRow2, pNew);
970 0 : ActivateNewFormulaCell(it1, nRow2, *pNew);
971 : }
972 0 : break;
973 : default:
974 : ;
975 : }
976 :
977 0 : SwapCellTextAttrs(nRow1, nRow2);
978 0 : CellStorageModified();
979 0 : BroadcastCells(aRows);
980 0 : return;
981 : }
982 :
983 : // Neither cells are empty, and they are of different types.
984 6 : switch (aCell1.meType)
985 : {
986 : case CELLTYPE_VALUE:
987 : {
988 2 : switch (aCell2.meType)
989 : {
990 : case CELLTYPE_STRING:
991 2 : it1 = maCells.set(it1, nRow1, *aCell2.mpString);
992 2 : break;
993 : case CELLTYPE_EDIT:
994 : {
995 0 : it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
996 : EditTextObject* p;
997 0 : it1 = maCells.release(it1, nRow2, p);
998 : }
999 0 : break;
1000 : case CELLTYPE_FORMULA:
1001 : {
1002 0 : DetouchFormulaCell(aPos2, *aCell2.mpFormula);
1003 0 : ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
1004 0 : it1 = maCells.set(it1, nRow1, pNew);
1005 0 : ActivateNewFormulaCell(it1, nRow1, *pNew);
1006 : // The old formula cell will get overwritten below.
1007 : }
1008 0 : break;
1009 : default:
1010 : ;
1011 : }
1012 :
1013 2 : maCells.set(it1, nRow2, aCell1.mfValue);
1014 :
1015 : }
1016 2 : break;
1017 : case CELLTYPE_STRING:
1018 : {
1019 4 : OUString aStr = *aCell1.mpString; // make a copy.
1020 4 : switch (aCell2.meType)
1021 : {
1022 : case CELLTYPE_VALUE:
1023 4 : it1 = maCells.set(it1, nRow1, aCell2.mfValue);
1024 4 : break;
1025 : case CELLTYPE_EDIT:
1026 : {
1027 0 : it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
1028 : EditTextObject* p;
1029 0 : it1 = maCells.release(it1, nRow2, p); // prevent it being overwritten.
1030 : }
1031 0 : break;
1032 : case CELLTYPE_FORMULA:
1033 : {
1034 : // cell 1 - string, cell 2 - formula
1035 0 : DetouchFormulaCell(aPos2, *aCell2.mpFormula);
1036 0 : ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
1037 0 : it1 = maCells.set(it1, nRow1, pNew);
1038 0 : ActivateNewFormulaCell(it1, nRow1, *pNew);
1039 : // Old formula cell will get overwritten below.
1040 : }
1041 0 : break;
1042 : default:
1043 : ;
1044 : }
1045 :
1046 4 : maCells.set(it1, nRow2, aStr);
1047 : }
1048 4 : break;
1049 : case CELLTYPE_EDIT:
1050 : {
1051 : EditTextObject* p;
1052 0 : it1 = maCells.release(it1, nRow1, p);
1053 :
1054 0 : switch (aCell2.meType)
1055 : {
1056 : case CELLTYPE_VALUE:
1057 0 : it1 = maCells.set(it1, nRow1, aCell2.mfValue);
1058 0 : break;
1059 : case CELLTYPE_STRING:
1060 0 : it1 = maCells.set(it1, nRow1, *aCell2.mpString);
1061 0 : break;
1062 : case CELLTYPE_FORMULA:
1063 : {
1064 0 : DetouchFormulaCell(aPos2, *aCell2.mpFormula);
1065 0 : ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
1066 0 : it1 = maCells.set(it1, nRow1, pNew);
1067 0 : ActivateNewFormulaCell(it1, nRow1, *pNew);
1068 : // Old formula cell will get overwritten below.
1069 : }
1070 0 : break;
1071 : default:
1072 : ;
1073 : }
1074 :
1075 0 : maCells.set(it1, nRow2, aCell1.mpEditText);
1076 : }
1077 0 : break;
1078 : case CELLTYPE_FORMULA:
1079 : {
1080 : // cell 1 is a formula cell and cell 2 is not.
1081 0 : DetouchFormulaCell(aPos1, *aCell1.mpFormula);
1082 0 : ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
1083 0 : switch (aCell2.meType)
1084 : {
1085 : case CELLTYPE_VALUE:
1086 0 : it1 = maCells.set(it1, nRow1, aCell2.mfValue);
1087 0 : break;
1088 : case CELLTYPE_STRING:
1089 0 : it1 = maCells.set(it1, nRow1, *aCell2.mpString);
1090 0 : break;
1091 : case CELLTYPE_EDIT:
1092 : {
1093 0 : it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
1094 : EditTextObject* p;
1095 0 : it1 = maCells.release(it1, nRow2, p);
1096 : }
1097 0 : break;
1098 : default:
1099 : ;
1100 : }
1101 :
1102 0 : it1 = maCells.set(it1, nRow2, pNew);
1103 0 : ActivateNewFormulaCell(it1, nRow2, *pNew);
1104 : }
1105 0 : break;
1106 : default:
1107 : ;
1108 : }
1109 :
1110 6 : SwapCellTextAttrs(nRow1, nRow2);
1111 6 : CellStorageModified();
1112 12 : BroadcastCells(aRows);
1113 : }
1114 :
1115 : namespace {
1116 :
1117 : /**
1118 : * Adjust references in formula cell with respect to column-wise relocation.
1119 : */
1120 0 : void updateRefInFormulaCell( ScFormulaCell& rCell, SCCOL nCol, SCTAB nTab, SCCOL nColDiff )
1121 : {
1122 0 : ScRange aRange(ScAddress(nCol, 0, nTab), ScAddress(nCol, MAXROW, nTab));
1123 0 : rCell.aPos.SetCol(nCol);
1124 0 : rCell.UpdateReference(URM_MOVE, aRange, nColDiff, 0, 0);
1125 0 : }
1126 :
1127 : }
1128 :
1129 0 : void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol)
1130 : {
1131 0 : sc::CellStoreType::position_type aPos1 = maCells.position(nRow);
1132 0 : sc::CellStoreType::position_type aPos2 = rCol.maCells.position(nRow);
1133 :
1134 0 : if (aPos1.first->type == sc::element_type_formula)
1135 : {
1136 0 : ScFormulaCell& rCell = *sc::formula_block::at(*aPos1.first->data, aPos1.second);
1137 0 : updateRefInFormulaCell(rCell, rCol.nCol, nTab, rCol.nCol - nCol);
1138 0 : UnshareFormulaCell(aPos1, rCell);
1139 : }
1140 :
1141 0 : if (aPos2.first->type == sc::element_type_formula)
1142 : {
1143 0 : ScFormulaCell& rCell = *sc::formula_block::at(*aPos2.first->data, aPos2.second);
1144 0 : updateRefInFormulaCell(rCell, nCol, nTab, nCol - rCol.nCol);
1145 0 : UnshareFormulaCell(aPos2, rCell);
1146 : }
1147 :
1148 0 : maCells.swap(nRow, nRow, rCol.maCells, nRow);
1149 0 : maCellTextAttrs.swap(nRow, nRow, rCol.maCellTextAttrs, nRow);
1150 :
1151 0 : aPos1 = maCells.position(nRow);
1152 0 : aPos2 = rCol.maCells.position(nRow);
1153 :
1154 0 : if (aPos1.first->type == sc::element_type_formula)
1155 : {
1156 0 : ScFormulaCell& rCell = *sc::formula_block::at(*aPos1.first->data, aPos1.second);
1157 0 : JoinNewFormulaCell(aPos1, rCell);
1158 : }
1159 :
1160 0 : if (aPos2.first->type == sc::element_type_formula)
1161 : {
1162 0 : ScFormulaCell& rCell = *sc::formula_block::at(*aPos2.first->data, aPos2.second);
1163 0 : rCol.JoinNewFormulaCell(aPos2, rCell);
1164 : }
1165 :
1166 0 : CellStorageModified();
1167 0 : rCol.CellStorageModified();
1168 0 : }
1169 :
1170 :
1171 11 : bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
1172 : {
1173 11 : if (IsEmpty())
1174 11 : return true;
1175 :
1176 : // Return false if we have any non-empty cells between nStartRow and nEndRow inclusive.
1177 0 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
1178 0 : sc::CellStoreType::const_iterator it = aPos.first;
1179 0 : if (it->type != sc::element_type_empty)
1180 0 : return false;
1181 :
1182 : // Get the length of the remaining empty segment.
1183 0 : size_t nLen = it->size - aPos.second;
1184 0 : SCROW nNextNonEmptyRow = nStartRow + nLen;
1185 0 : if (nNextNonEmptyRow <= nEndRow)
1186 0 : return false;
1187 :
1188 : // AttrArray only looks for merged cells
1189 :
1190 0 : return pAttrArray ? pAttrArray->TestInsertCol(nStartRow, nEndRow) : true;
1191 : }
1192 :
1193 :
1194 9221 : bool ScColumn::TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const
1195 : {
1196 : // AttrArray only looks for merged cells
1197 : {
1198 9221 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
1199 9221 : sc::CellStoreType::const_iterator it = aPos.first;
1200 9221 : if (it->type == sc::element_type_empty && maCells.block_size() == 1)
1201 : // The entire cell array is empty.
1202 9211 : return pAttrArray->TestInsertRow(nSize);
1203 : }
1204 :
1205 : // See if there would be any non-empty cell that gets pushed out.
1206 :
1207 : // Find the position of the last non-empty cell below nStartRow.
1208 10 : size_t nLastNonEmptyRow = MAXROW;
1209 10 : sc::CellStoreType::const_reverse_iterator it = maCells.rbegin();
1210 10 : if (it->type == sc::element_type_empty)
1211 10 : nLastNonEmptyRow -= it->size;
1212 :
1213 10 : if (nLastNonEmptyRow < static_cast<size_t>(nStartRow))
1214 : // No cells would get pushed out.
1215 6 : return pAttrArray->TestInsertRow(nSize);
1216 :
1217 4 : if (nLastNonEmptyRow + nSize > static_cast<size_t>(MAXROW))
1218 : // At least one cell would get pushed out. Not good.
1219 0 : return false;
1220 :
1221 4 : return pAttrArray->TestInsertRow(nSize);
1222 : }
1223 :
1224 :
1225 9221 : void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
1226 : {
1227 9221 : pAttrArray->InsertRow( nStartRow, nSize );
1228 :
1229 9221 : maBroadcasters.insert_empty(nStartRow, nSize);
1230 9221 : maBroadcasters.resize(MAXROWCOUNT);
1231 :
1232 9221 : maCellTextAttrs.insert_empty(nStartRow, nSize);
1233 9221 : maCellTextAttrs.resize(MAXROWCOUNT);
1234 :
1235 9221 : maCells.insert_empty(nStartRow, nSize);
1236 9221 : maCells.resize(MAXROWCOUNT);
1237 :
1238 9221 : CellStorageModified();
1239 :
1240 : // We *probably* don't need to broadcast here since the parent call seems
1241 : // to take care of it.
1242 9221 : }
1243 :
1244 : namespace {
1245 :
1246 : class CopyToClipHandler
1247 : {
1248 : const ScColumn& mrSrcCol;
1249 : ScColumn& mrDestCol;
1250 : sc::ColumnBlockPosition maDestPos;
1251 : sc::ColumnBlockPosition* mpDestPos;
1252 :
1253 36 : void setDefaultAttrsToDest(size_t nRow, size_t nSize)
1254 : {
1255 36 : std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
1256 72 : maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1257 72 : maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
1258 36 : }
1259 :
1260 : public:
1261 27 : CopyToClipHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos) :
1262 27 : mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos)
1263 : {
1264 27 : if (mpDestPos)
1265 27 : maDestPos = *mpDestPos;
1266 : else
1267 0 : mrDestCol.InitBlockPosition(maDestPos);
1268 27 : }
1269 :
1270 27 : ~CopyToClipHandler()
1271 : {
1272 27 : if (mpDestPos)
1273 27 : *mpDestPos = maDestPos;
1274 27 : }
1275 :
1276 47 : void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1277 : {
1278 47 : size_t nTopRow = aNode.position + nOffset;
1279 :
1280 47 : switch (aNode.type)
1281 : {
1282 : case sc::element_type_numeric:
1283 : {
1284 8 : sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
1285 8 : std::advance(it, nOffset);
1286 8 : sc::numeric_block::const_iterator itEnd = it;
1287 8 : std::advance(itEnd, nDataSize);
1288 8 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
1289 8 : setDefaultAttrsToDest(nTopRow, nDataSize);
1290 : }
1291 8 : break;
1292 : case sc::element_type_string:
1293 : {
1294 15 : sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
1295 15 : std::advance(it, nOffset);
1296 15 : sc::string_block::const_iterator itEnd = it;
1297 15 : std::advance(itEnd, nDataSize);
1298 15 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
1299 15 : setDefaultAttrsToDest(nTopRow, nDataSize);
1300 : }
1301 15 : break;
1302 : case sc::element_type_edittext:
1303 : {
1304 0 : sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
1305 0 : std::advance(it, nOffset);
1306 0 : sc::edittext_block::const_iterator itEnd = it;
1307 0 : std::advance(itEnd, nDataSize);
1308 :
1309 0 : std::vector<EditTextObject*> aCloned;
1310 0 : aCloned.reserve(nDataSize);
1311 0 : for (; it != itEnd; ++it)
1312 0 : aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
1313 :
1314 0 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1315 0 : maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
1316 :
1317 0 : setDefaultAttrsToDest(nTopRow, nDataSize);
1318 : }
1319 0 : break;
1320 : case sc::element_type_formula:
1321 : {
1322 13 : sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
1323 13 : std::advance(it, nOffset);
1324 13 : sc::formula_block::const_iterator itEnd = it;
1325 13 : std::advance(itEnd, nDataSize);
1326 :
1327 13 : std::vector<ScFormulaCell*> aCloned;
1328 13 : aCloned.reserve(nDataSize);
1329 13 : ScAddress aDestPos(mrDestCol.GetCol(), nTopRow, mrDestCol.GetTab());
1330 35 : for (; it != itEnd; ++it, aDestPos.IncRow())
1331 : {
1332 22 : const ScFormulaCell& rOld = **it;
1333 22 : if (rOld.GetDirty() && mrSrcCol.GetDoc().GetAutoCalc())
1334 9 : const_cast<ScFormulaCell&>(rOld).Interpret();
1335 :
1336 22 : aCloned.push_back(new ScFormulaCell(rOld, mrDestCol.GetDoc(), aDestPos));
1337 : }
1338 :
1339 26 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1340 13 : maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
1341 :
1342 13 : setDefaultAttrsToDest(nTopRow, nDataSize);
1343 : }
1344 13 : break;
1345 : default:
1346 : ;
1347 : }
1348 47 : }
1349 : };
1350 :
1351 : }
1352 :
1353 27 : void ScColumn::CopyToClip(
1354 : sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const
1355 : {
1356 : pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
1357 27 : rCxt.isKeepScenarioFlags() ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
1358 :
1359 27 : CopyToClipHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol));
1360 27 : sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
1361 27 : rColumn.RegroupFormulaCells(nRow1, nRow2);
1362 27 : rColumn.CellStorageModified();
1363 27 : }
1364 :
1365 3 : void ScColumn::CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol)
1366 : {
1367 3 : if (nRow1 > nRow2)
1368 3 : return;
1369 :
1370 3 : sc::ColumnBlockPosition aDestPos;
1371 3 : CopyCellTextAttrsToDocument(nRow1, nRow2, rDestCol);
1372 :
1373 : // First, clear the destination column for the specified row range.
1374 3 : rDestCol.maCells.set_empty(nRow1, nRow2);
1375 :
1376 3 : aDestPos.miCellPos = rDestCol.maCells.begin();
1377 :
1378 3 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
1379 3 : sc::CellStoreType::const_iterator it = aPos.first;
1380 3 : size_t nOffset = aPos.second;
1381 3 : size_t nDataSize = 0;
1382 3 : size_t nCurRow = nRow1;
1383 :
1384 6 : for (; it != maCells.end() && nCurRow <= static_cast<size_t>(nRow2); ++it, nOffset = 0, nCurRow += nDataSize)
1385 : {
1386 4 : bool bLastBlock = false;
1387 4 : nDataSize = it->size - nOffset;
1388 4 : if (nCurRow + nDataSize - 1 > static_cast<size_t>(nRow2))
1389 : {
1390 : // Truncate the block to copy to clipboard.
1391 1 : nDataSize = nRow2 - nCurRow + 1;
1392 1 : bLastBlock = true;
1393 : }
1394 :
1395 4 : switch (it->type)
1396 : {
1397 : case sc::element_type_numeric:
1398 : {
1399 1 : sc::numeric_block::const_iterator itData = sc::numeric_block::begin(*it->data);
1400 1 : std::advance(itData, nOffset);
1401 1 : sc::numeric_block::const_iterator itDataEnd = itData;
1402 1 : std::advance(itDataEnd, nDataSize);
1403 1 : aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
1404 : }
1405 1 : break;
1406 : case sc::element_type_string:
1407 : {
1408 1 : sc::string_block::const_iterator itData = sc::string_block::begin(*it->data);
1409 1 : std::advance(itData, nOffset);
1410 1 : sc::string_block::const_iterator itDataEnd = itData;
1411 1 : std::advance(itDataEnd, nDataSize);
1412 1 : aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
1413 : }
1414 1 : break;
1415 : case sc::element_type_edittext:
1416 : {
1417 0 : sc::edittext_block::const_iterator itData = sc::edittext_block::begin(*it->data);
1418 0 : std::advance(itData, nOffset);
1419 0 : sc::edittext_block::const_iterator itDataEnd = itData;
1420 0 : std::advance(itDataEnd, nDataSize);
1421 :
1422 : // Convert to simple strings.
1423 0 : std::vector<OUString> aConverted;
1424 0 : aConverted.reserve(nDataSize);
1425 0 : for (; itData != itDataEnd; ++itData)
1426 : {
1427 0 : const EditTextObject& rObj = **itData;
1428 0 : aConverted.push_back(ScEditUtil::GetString(rObj));
1429 : }
1430 0 : aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, aConverted.begin(), aConverted.end());
1431 : }
1432 0 : break;
1433 : case sc::element_type_formula:
1434 : {
1435 1 : sc::formula_block::const_iterator itData = sc::formula_block::begin(*it->data);
1436 1 : std::advance(itData, nOffset);
1437 1 : sc::formula_block::const_iterator itDataEnd = itData;
1438 1 : std::advance(itDataEnd, nDataSize);
1439 :
1440 : // Interpret and convert to raw values.
1441 2 : for (SCROW i = 0; itData != itDataEnd; ++itData, ++i)
1442 : {
1443 1 : SCROW nRow = nCurRow + i;
1444 :
1445 1 : ScFormulaCell& rFC = const_cast<ScFormulaCell&>(**itData);
1446 1 : if (rFC.GetDirty() && pDocument->GetAutoCalc())
1447 0 : rFC.Interpret();
1448 :
1449 1 : if (rFC.GetErrCode())
1450 : // Skip cells with error.
1451 0 : break;
1452 :
1453 1 : if (rFC.IsValue())
1454 1 : aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, rFC.GetValue());
1455 : else
1456 0 : aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, rFC.GetString());
1457 : }
1458 : }
1459 1 : break;
1460 : default:
1461 : ;
1462 : }
1463 :
1464 4 : if (bLastBlock)
1465 1 : break;
1466 : }
1467 :
1468 3 : rDestCol.RegroupFormulaCells(nRow1, nRow2);
1469 3 : rDestCol.CellStorageModified();
1470 : }
1471 :
1472 0 : void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol )
1473 : {
1474 0 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nSrcRow);
1475 0 : sc::CellStoreType::const_iterator it = aPos.first;
1476 0 : bool bSet = true;
1477 0 : switch (it->type)
1478 : {
1479 : case sc::element_type_numeric:
1480 0 : rDestCol.maCells.set(nDestRow, sc::numeric_block::at(*it->data, aPos.second));
1481 0 : break;
1482 : case sc::element_type_string:
1483 0 : rDestCol.maCells.set(nDestRow, sc::string_block::at(*it->data, aPos.second));
1484 0 : break;
1485 : case sc::element_type_edittext:
1486 : {
1487 0 : EditTextObject* p = sc::edittext_block::at(*it->data, aPos.second);
1488 0 : if (pDocument == rDestCol.pDocument)
1489 0 : rDestCol.maCells.set(nDestRow, p->Clone());
1490 : else
1491 0 : rDestCol.maCells.set(nDestRow, ScEditUtil::Clone(*p, *rDestCol.pDocument));
1492 : }
1493 0 : break;
1494 : case sc::element_type_formula:
1495 : {
1496 0 : ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
1497 0 : if (p->GetDirty() && pDocument->GetAutoCalc())
1498 0 : p->Interpret();
1499 :
1500 0 : ScAddress aDestPos = p->aPos;
1501 0 : aDestPos.SetRow(nDestRow);
1502 0 : ScFormulaCell* pNew = new ScFormulaCell(*p, *rDestCol.pDocument, aDestPos);
1503 0 : rDestCol.maCells.set(nDestRow, pNew);
1504 : }
1505 0 : break;
1506 : case sc::element_type_empty:
1507 : default:
1508 : // empty
1509 0 : rDestCol.maCells.set_empty(nDestRow, nDestRow);
1510 0 : bSet = false;
1511 : }
1512 :
1513 0 : if (bSet)
1514 0 : rDestCol.maCellTextAttrs.set(nDestRow, maCellTextAttrs.get<sc::CellTextAttr>(nSrcRow));
1515 : else
1516 0 : rDestCol.maCellTextAttrs.set_empty(nDestRow, nDestRow);
1517 :
1518 0 : rDestCol.RegroupFormulaCells(nDestRow);
1519 0 : rDestCol.CellStorageModified();
1520 0 : }
1521 :
1522 : namespace {
1523 :
1524 1122 : bool canCopyValue(const ScDocument& rDoc, const ScAddress& rPos, sal_uInt16 nFlags)
1525 : {
1526 1122 : sal_uInt32 nNumIndex = static_cast<const SfxUInt32Item*>(rDoc.GetAttr(rPos, ATTR_VALUE_FORMAT))->GetValue();
1527 1122 : short nType = rDoc.GetFormatTable()->GetType(nNumIndex);
1528 1122 : if ((nType == NUMBERFORMAT_DATE) || (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME))
1529 0 : return ((nFlags & IDF_DATETIME) != 0);
1530 :
1531 1122 : return ((nFlags & IDF_VALUE) != 0);
1532 : }
1533 :
1534 : class CopyAsLinkHandler
1535 : {
1536 : const ScColumn& mrSrcCol;
1537 : ScColumn& mrDestCol;
1538 : sc::ColumnBlockPosition maDestPos;
1539 : sc::ColumnBlockPosition* mpDestPos;
1540 : sal_uInt16 mnCopyFlags;
1541 : std::vector<ScFormulaCell*> maCellBuffer;
1542 :
1543 0 : void setDefaultAttrToDest(size_t nRow)
1544 : {
1545 0 : maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1546 0 : maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
1547 0 : }
1548 :
1549 0 : void setDefaultAttrsToDest(size_t nRow, size_t nSize)
1550 : {
1551 0 : std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
1552 0 : maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1553 0 : maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
1554 0 : }
1555 :
1556 0 : ScFormulaCell* createRefCell(size_t nRow)
1557 : {
1558 : ScSingleRefData aRef;
1559 0 : aRef.InitAddress(ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab())); // Absolute reference.
1560 0 : aRef.SetFlag3D(true);
1561 :
1562 0 : ScTokenArray aArr;
1563 0 : aArr.AddSingleReference(aRef);
1564 0 : return new ScFormulaCell(&mrDestCol.GetDoc(), ScAddress(mrDestCol.GetCol(), nRow, mrDestCol.GetTab()), &aArr);
1565 : }
1566 :
1567 0 : void createRefBlock(const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1568 : {
1569 0 : size_t nTopRow = aNode.position + nOffset;
1570 :
1571 0 : maCellBuffer.clear();
1572 0 : maCellBuffer.reserve(nDataSize);
1573 :
1574 0 : for (size_t i = 0; i < nDataSize; ++i)
1575 0 : maCellBuffer.push_back(createRefCell(nTopRow + i));
1576 :
1577 0 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, maCellBuffer.begin(), maCellBuffer.end());
1578 0 : setDefaultAttrsToDest(nTopRow, nDataSize);
1579 0 : }
1580 :
1581 : public:
1582 0 : CopyAsLinkHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, sal_uInt16 nCopyFlags) :
1583 0 : mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mnCopyFlags(nCopyFlags)
1584 : {
1585 0 : if (mpDestPos)
1586 0 : maDestPos = *mpDestPos;
1587 0 : }
1588 :
1589 0 : ~CopyAsLinkHandler()
1590 0 : {
1591 0 : if (mpDestPos)
1592 0 : *mpDestPos = maDestPos;
1593 0 : }
1594 :
1595 0 : void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1596 : {
1597 0 : size_t nRow = aNode.position + nOffset;
1598 :
1599 0 : switch (aNode.type)
1600 : {
1601 : case sc::element_type_numeric:
1602 : {
1603 0 : if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == 0)
1604 0 : return;
1605 :
1606 0 : sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
1607 0 : std::advance(it, nOffset);
1608 0 : sc::numeric_block::const_iterator itEnd = it;
1609 0 : std::advance(itEnd, nDataSize);
1610 :
1611 0 : ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
1612 0 : for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
1613 : {
1614 0 : if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
1615 0 : continue;
1616 :
1617 0 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, createRefCell(nRow));
1618 0 : setDefaultAttrToDest(nRow);
1619 : }
1620 : }
1621 0 : break;
1622 : case sc::element_type_string:
1623 : case sc::element_type_edittext:
1624 : {
1625 0 : if (!(mnCopyFlags & IDF_STRING))
1626 0 : return;
1627 :
1628 0 : createRefBlock(aNode, nOffset, nDataSize);
1629 : }
1630 0 : break;
1631 : case sc::element_type_formula:
1632 : {
1633 0 : if (!(mnCopyFlags & IDF_FORMULA))
1634 0 : return;
1635 :
1636 0 : createRefBlock(aNode, nOffset, nDataSize);
1637 : }
1638 0 : break;
1639 : default:
1640 : ;
1641 : }
1642 : }
1643 : };
1644 :
1645 : class CopyByCloneHandler
1646 : {
1647 : const ScColumn& mrSrcCol;
1648 : ScColumn& mrDestCol;
1649 : sc::ColumnBlockPosition maDestPos;
1650 : sc::ColumnBlockPosition* mpDestPos;
1651 : sal_uInt16 mnCopyFlags;
1652 :
1653 2225 : void setDefaultAttrToDest(size_t nRow)
1654 : {
1655 4450 : maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1656 2225 : maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
1657 2225 : }
1658 :
1659 2 : void setDefaultAttrsToDest(size_t nRow, size_t nSize)
1660 : {
1661 2 : std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
1662 4 : maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1663 4 : maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
1664 2 : }
1665 :
1666 156 : void cloneFormulaCell(size_t nRow, ScFormulaCell& rSrcCell)
1667 : {
1668 156 : ScAddress aDestPos(mrDestCol.GetCol(), nRow, mrDestCol.GetTab());
1669 :
1670 156 : bool bCloneValue = (mnCopyFlags & IDF_VALUE) != 0;
1671 156 : bool bCloneDateTime = (mnCopyFlags & IDF_DATETIME) != 0;
1672 156 : bool bCloneString = (mnCopyFlags & IDF_STRING) != 0;
1673 156 : bool bCloneSpecialBoolean = (mnCopyFlags & IDF_SPECIAL_BOOLEAN) != 0;
1674 156 : bool bCloneFormula = (mnCopyFlags & IDF_FORMULA) != 0;
1675 :
1676 156 : bool bForceFormula = false;
1677 :
1678 156 : if (bCloneSpecialBoolean)
1679 : {
1680 : // See if the formula consists of =TRUE() or =FALSE().
1681 0 : ScTokenArray* pCode = rSrcCell.GetCode();
1682 0 : if (pCode && pCode->GetLen() == 1)
1683 : {
1684 0 : const formula::FormulaToken* p = pCode->First();
1685 0 : if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
1686 : // This is a boolean formula.
1687 0 : bForceFormula = true;
1688 : }
1689 : }
1690 :
1691 156 : if (bForceFormula || bCloneFormula)
1692 : {
1693 : // Clone as formula cell.
1694 156 : ScFormulaCell* pCell = new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos);
1695 156 : pCell->SetDirtyVar();
1696 156 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, pCell);
1697 156 : setDefaultAttrToDest(nRow);
1698 156 : return;
1699 : }
1700 :
1701 0 : if (mrDestCol.GetDoc().IsUndo())
1702 0 : return;
1703 :
1704 0 : if (bCloneValue)
1705 : {
1706 0 : sal_uInt16 nErr = rSrcCell.GetErrCode();
1707 0 : if (nErr)
1708 : {
1709 : // error codes are cloned with values
1710 0 : ScFormulaCell* pErrCell = new ScFormulaCell(&mrDestCol.GetDoc(), aDestPos);
1711 0 : pErrCell->SetErrCode(nErr);
1712 0 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1713 0 : maDestPos.miCellPos, nRow, new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos));
1714 0 : setDefaultAttrToDest(nRow);
1715 0 : return;
1716 : }
1717 : }
1718 :
1719 0 : if (bCloneValue || bCloneDateTime)
1720 : {
1721 0 : if (rSrcCell.IsValue())
1722 : {
1723 0 : if (canCopyValue(mrSrcCol.GetDoc(), ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab()), mnCopyFlags))
1724 : {
1725 0 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1726 0 : maDestPos.miCellPos, nRow, rSrcCell.GetValue());
1727 0 : setDefaultAttrToDest(nRow);
1728 : }
1729 :
1730 0 : return;
1731 : }
1732 : }
1733 :
1734 0 : if (bCloneString)
1735 : {
1736 0 : OUString aStr = rSrcCell.GetString();
1737 0 : if (aStr.isEmpty())
1738 : // Don't create empty string cells.
1739 0 : return;
1740 :
1741 0 : if (rSrcCell.IsMultilineResult())
1742 : {
1743 : // Clone as an edit text object.
1744 0 : EditEngine& rEngine = mrDestCol.GetDoc().GetEditEngine();
1745 0 : rEngine.SetText(aStr);
1746 0 : maDestPos.miCellPos =
1747 0 : mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rEngine.CreateTextObject());
1748 : }
1749 : else
1750 : {
1751 0 : maDestPos.miCellPos =
1752 0 : mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aStr);
1753 : }
1754 :
1755 0 : setDefaultAttrToDest(nRow);
1756 : }
1757 : }
1758 :
1759 : public:
1760 79951 : CopyByCloneHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, sal_uInt16 nCopyFlags) :
1761 79951 : mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mnCopyFlags(nCopyFlags)
1762 : {
1763 79951 : if (mpDestPos)
1764 79951 : maDestPos = *mpDestPos;
1765 79951 : }
1766 :
1767 79951 : ~CopyByCloneHandler()
1768 : {
1769 79951 : if (mpDestPos)
1770 79951 : *mpDestPos = maDestPos;
1771 79951 : }
1772 :
1773 81560 : void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1774 : {
1775 81560 : size_t nRow = aNode.position + nOffset;
1776 :
1777 81560 : switch (aNode.type)
1778 : {
1779 : case sc::element_type_numeric:
1780 : {
1781 716 : if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == 0)
1782 118 : return;
1783 :
1784 598 : sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
1785 598 : std::advance(it, nOffset);
1786 598 : sc::numeric_block::const_iterator itEnd = it;
1787 598 : std::advance(itEnd, nDataSize);
1788 :
1789 598 : ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
1790 1720 : for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
1791 : {
1792 1122 : if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
1793 0 : continue;
1794 :
1795 1122 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, *it);
1796 1122 : setDefaultAttrToDest(nRow);
1797 : }
1798 : }
1799 598 : break;
1800 : case sc::element_type_string:
1801 : {
1802 520 : if (!(mnCopyFlags & IDF_STRING))
1803 101 : return;
1804 :
1805 419 : sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
1806 419 : std::advance(it, nOffset);
1807 419 : sc::string_block::const_iterator itEnd = it;
1808 419 : std::advance(itEnd, nDataSize);
1809 :
1810 1366 : for (; it != itEnd; ++it, ++nRow)
1811 : {
1812 947 : const OUString& rStr = *it;
1813 947 : if (rStr.isEmpty())
1814 : {
1815 : // String cell with empty value is used to special-case cell value removal.
1816 0 : maDestPos.miCellPos = mrDestCol.GetCellStore().set_empty(
1817 0 : maDestPos.miCellPos, nRow, nRow);
1818 0 : maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set_empty(
1819 0 : maDestPos.miCellTextAttrPos, nRow, nRow);
1820 : }
1821 : else
1822 : {
1823 2841 : maDestPos.miCellPos =
1824 1894 : mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rStr);
1825 947 : setDefaultAttrToDest(nRow);
1826 : }
1827 : }
1828 : }
1829 419 : break;
1830 : case sc::element_type_edittext:
1831 : {
1832 2 : if (!(mnCopyFlags & IDF_STRING))
1833 0 : return;
1834 :
1835 2 : sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
1836 2 : std::advance(it, nOffset);
1837 2 : sc::edittext_block::const_iterator itEnd = it;
1838 2 : std::advance(itEnd, nDataSize);
1839 :
1840 2 : std::vector<EditTextObject*> aCloned;
1841 2 : aCloned.reserve(nDataSize);
1842 4 : for (; it != itEnd; ++it)
1843 2 : aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
1844 :
1845 4 : maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1846 2 : maDestPos.miCellPos, nRow, aCloned.begin(), aCloned.end());
1847 :
1848 2 : setDefaultAttrsToDest(nRow, nDataSize);
1849 : }
1850 2 : break;
1851 : case sc::element_type_formula:
1852 : {
1853 73 : sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
1854 73 : std::advance(it, nOffset);
1855 73 : sc::formula_block::const_iterator itEnd = it;
1856 73 : std::advance(itEnd, nDataSize);
1857 :
1858 229 : for (; it != itEnd; ++it, ++nRow)
1859 156 : cloneFormulaCell(nRow, const_cast<ScFormulaCell&>(**it));
1860 : }
1861 73 : break;
1862 : default:
1863 : ;
1864 : }
1865 : }
1866 : };
1867 :
1868 : }
1869 :
1870 82937 : void ScColumn::CopyToColumn(
1871 : sc::CopyToDocContext& rCxt,
1872 : SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked, ScColumn& rColumn,
1873 : const ScMarkData* pMarkData, bool bAsLink) const
1874 : {
1875 82937 : if (bMarked)
1876 : {
1877 : SCROW nStart, nEnd;
1878 1458 : if (pMarkData && pMarkData->IsMultiMarked())
1879 : {
1880 1458 : ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
1881 :
1882 3364 : while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
1883 : {
1884 448 : if ( nEnd >= nRow1 )
1885 896 : CopyToColumn(rCxt, std::max(nRow1,nStart), std::min(nRow2,nEnd),
1886 1344 : nFlags, false, rColumn, pMarkData, bAsLink );
1887 1458 : }
1888 : }
1889 : else
1890 : {
1891 : OSL_FAIL("CopyToColumn: bMarked, but no mark");
1892 : }
1893 84395 : return;
1894 : }
1895 :
1896 81479 : if ( (nFlags & IDF_ATTRIB) != 0 )
1897 : {
1898 46281 : if ( (nFlags & IDF_STYLES) != IDF_STYLES )
1899 : { // keep the StyleSheets in the target document
1900 : // e.g. DIF and RTF Clipboard-Import
1901 0 : for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1902 : {
1903 : const ScStyleSheet* pStyle =
1904 0 : rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
1905 0 : const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
1906 0 : ScPatternAttr* pNewPattern = new ScPatternAttr( *pPattern );
1907 0 : pNewPattern->SetStyleSheet( (ScStyleSheet*)pStyle );
1908 0 : rColumn.pAttrArray->SetPattern( nRow, pNewPattern, true );
1909 0 : delete pNewPattern;
1910 : }
1911 : }
1912 : else
1913 46281 : pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
1914 : }
1915 :
1916 81479 : if ((nFlags & IDF_CONTENTS) != 0)
1917 : {
1918 79951 : if (bAsLink)
1919 : {
1920 0 : CopyAsLinkHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
1921 0 : sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
1922 : }
1923 : else
1924 : {
1925 79951 : CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
1926 79951 : sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
1927 : }
1928 :
1929 79951 : rColumn.RegroupFormulaCells(nRow1, nRow2);
1930 79951 : rColumn.CellStorageModified();
1931 : }
1932 : }
1933 :
1934 :
1935 6 : void ScColumn::UndoToColumn(
1936 : sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked,
1937 : ScColumn& rColumn, const ScMarkData* pMarkData ) const
1938 : {
1939 6 : if (nRow1 > 0)
1940 6 : CopyToColumn(rCxt, 0, nRow1-1, IDF_FORMULA, false, rColumn);
1941 :
1942 6 : CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData); //! bMarked ????
1943 :
1944 6 : if (nRow2 < MAXROW)
1945 6 : CopyToColumn(rCxt, nRow2+1, MAXROW, IDF_FORMULA, false, rColumn);
1946 6 : }
1947 :
1948 :
1949 0 : void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
1950 : {
1951 : // Copy cells from this column to the destination column only for those
1952 : // rows that are present in the position column (rPosCol).
1953 :
1954 : // First, mark all the non-empty cell ranges from the position column.
1955 0 : sc::SingleColumnSpanSet aRangeSet;
1956 0 : aRangeSet.scan(rPosCol);
1957 :
1958 : // Now, copy cells from this column to the destination column for those
1959 : // marked row ranges.
1960 0 : sc::SingleColumnSpanSet::SpansType aRanges;
1961 0 : aRangeSet.getSpans(aRanges);
1962 :
1963 0 : CopyToClipHandler aFunc(*this, rDestCol, NULL);
1964 0 : sc::CellStoreType::const_iterator itPos = maCells.begin();
1965 0 : sc::SingleColumnSpanSet::SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
1966 0 : for (; it != itEnd; ++it)
1967 : {
1968 0 : itPos = sc::ParseBlock(itPos, maCells, aFunc, it->mnRow1, it->mnRow2);
1969 0 : rDestCol.RegroupFormulaCells(it->mnRow1, it->mnRow2);
1970 : }
1971 :
1972 0 : rDestCol.CellStorageModified();
1973 0 : }
1974 :
1975 :
1976 0 : void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
1977 : {
1978 : // This is the scenario table, the data is copied into it
1979 0 : sc::CopyToDocContext aCxt(*pDocument);
1980 0 : ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
1981 0 : SCROW nStart = -1, nEnd = -1;
1982 0 : const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1983 0 : while (pPattern)
1984 : {
1985 0 : if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
1986 : {
1987 0 : DeleteArea( nStart, nEnd, IDF_CONTENTS );
1988 : ((ScColumn&)rSrcCol).
1989 0 : CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, *this);
1990 :
1991 : // UpdateUsed not needed, already done in TestCopyScenario (obsolete comment ?)
1992 :
1993 0 : SCsTAB nDz = nTab - rSrcCol.nTab;
1994 : UpdateReference(
1995 0 : URM_COPY, ScRange(nCol, nStart, nTab, nCol, nEnd, nTab), 0, 0, nDz, NULL);
1996 0 : UpdateCompile();
1997 : }
1998 :
1999 : //! make CopyToColumn "const" !!! (obsolete comment ?)
2000 :
2001 0 : pPattern = aAttrIter.Next( nStart, nEnd );
2002 0 : }
2003 0 : }
2004 :
2005 :
2006 0 : void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
2007 : {
2008 : // This is the scenario table, the data is copied to the other
2009 0 : sc::CopyToDocContext aCxt(*rDestCol.pDocument);
2010 0 : ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
2011 0 : SCROW nStart = -1, nEnd = -1;
2012 0 : const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
2013 0 : while (pPattern)
2014 : {
2015 0 : if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
2016 : {
2017 0 : rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
2018 : ((ScColumn*)this)->
2019 0 : CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, rDestCol);
2020 :
2021 : // UpdateUsed not needed, is already done in TestCopyScenario (obsolete comment ?)
2022 :
2023 0 : SCsTAB nDz = rDestCol.nTab - nTab;
2024 : rDestCol.UpdateReference(
2025 : URM_COPY, ScRange(rDestCol.nCol, nStart, rDestCol.nTab, rDestCol.nCol, nEnd, rDestCol.nTab),
2026 0 : 0, 0, nDz, NULL);
2027 0 : rDestCol.UpdateCompile();
2028 : }
2029 :
2030 : //! make CopyToColumn "const" !!! (obsolete comment ?)
2031 :
2032 0 : pPattern = aAttrIter.Next( nStart, nEnd );
2033 0 : }
2034 0 : }
2035 :
2036 :
2037 0 : bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
2038 : {
2039 0 : bool bOk = true;
2040 0 : ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
2041 0 : SCROW nStart = 0, nEnd = 0;
2042 0 : const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
2043 0 : while (pPattern && bOk)
2044 : {
2045 0 : if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
2046 0 : if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
2047 0 : bOk = false;
2048 :
2049 0 : pPattern = aAttrIter.Next( nStart, nEnd );
2050 : }
2051 0 : return bOk;
2052 : }
2053 :
2054 :
2055 1024 : void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
2056 : {
2057 1024 : ScRange aRange( nCol, 0, nTab );
2058 :
2059 1024 : ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
2060 1024 : SCROW nStart = -1, nEnd = -1;
2061 1024 : const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
2062 3086 : while (pPattern)
2063 : {
2064 1038 : if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
2065 : {
2066 14 : aRange.aStart.SetRow( nStart );
2067 14 : aRange.aEnd.SetRow( nEnd );
2068 14 : rDestMark.SetMultiMarkArea( aRange, true );
2069 : }
2070 :
2071 1038 : pPattern = aAttrIter.Next( nStart, nEnd );
2072 : }
2073 1024 : }
2074 :
2075 : namespace {
2076 :
2077 26586 : void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol)
2078 : {
2079 26586 : sc::CellStoreType::iterator it = rCells.begin(), itEnd = rCells.end();
2080 53194 : for (; it != itEnd; ++it)
2081 : {
2082 26608 : if (it->type != sc::element_type_formula)
2083 26608 : continue;
2084 :
2085 0 : sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
2086 0 : sc::formula_block::iterator itCellEnd = sc::formula_block::end(*it->data);
2087 0 : for (; itCell != itCellEnd; ++itCell)
2088 : {
2089 0 : ScFormulaCell& rCell = **itCell;
2090 0 : rCell.aPos.SetCol(nCol);
2091 : }
2092 : }
2093 26586 : }
2094 :
2095 : }
2096 :
2097 13293 : void ScColumn::SwapCol(ScColumn& rCol)
2098 : {
2099 13293 : maCells.swap(rCol.maCells);
2100 13293 : maCellTextAttrs.swap(rCol.maCellTextAttrs);
2101 :
2102 13293 : ScAttrArray* pTempAttr = rCol.pAttrArray;
2103 13293 : rCol.pAttrArray = pAttrArray;
2104 13293 : pAttrArray = pTempAttr;
2105 :
2106 : // AttrArray needs to have the right column number
2107 13293 : pAttrArray->SetCol(nCol);
2108 13293 : rCol.pAttrArray->SetCol(rCol.nCol);
2109 :
2110 13293 : std::swap(mbDirtyGroups, rCol.mbDirtyGroups);
2111 :
2112 : // Reset column positions in formula cells.
2113 13293 : resetColumnPosition(maCells, nCol);
2114 13293 : resetColumnPosition(rCol.maCells, rCol.nCol);
2115 :
2116 13293 : CellStorageModified();
2117 13293 : rCol.CellStorageModified();
2118 :
2119 13293 : }
2120 :
2121 6093 : void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
2122 : {
2123 6093 : pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
2124 :
2125 : // Mark the non-empty cells within the specified range, for later broadcasting.
2126 6093 : sc::SingleColumnSpanSet aNonEmpties;
2127 6093 : aNonEmpties.scan(*this, nStartRow, nEndRow);
2128 12186 : sc::SingleColumnSpanSet::SpansType aRanges;
2129 6093 : aNonEmpties.getSpans(aRanges);
2130 :
2131 : // Move the broadcasters to the destination column.
2132 6093 : maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
2133 6093 : maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
2134 6093 : maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
2135 :
2136 6093 : RegroupFormulaCells(nStartRow, nEndRow);
2137 6093 : rCol.RegroupFormulaCells(nStartRow, nEndRow);
2138 6093 : CellStorageModified();
2139 6093 : rCol.CellStorageModified();
2140 :
2141 : // Broadcast on moved ranges. Area-broadcast only.
2142 12186 : ScHint aHint(SC_HINT_DATACHANGED, ScAddress(nCol, 0, nTab));
2143 6093 : ScAddress& rPos = aHint.GetAddress();
2144 6093 : sc::SingleColumnSpanSet::SpansType::const_iterator itRange = aRanges.begin(), itRangeEnd = aRanges.end();
2145 6098 : for (; itRange != itRangeEnd; ++itRange)
2146 : {
2147 10 : for (SCROW nRow = itRange->mnRow1; nRow <= itRange->mnRow2; ++nRow)
2148 : {
2149 5 : rPos.SetRow(nRow);
2150 5 : pDocument->AreaBroadcast(aHint);
2151 : }
2152 6093 : }
2153 6093 : }
2154 :
2155 : namespace {
2156 :
2157 : class SubTotalCellPicker
2158 : {
2159 : sc::ColumnSpanSet& mrSet;
2160 : SCTAB mnTab;
2161 : SCCOL mnCol;
2162 : bool mbVal;
2163 : public:
2164 6 : SubTotalCellPicker(sc::ColumnSpanSet& rSet, SCTAB nTab, SCCOL nCol, bool bVal) :
2165 6 : mrSet(rSet), mnTab(nTab), mnCol(nCol), mbVal(bVal) {}
2166 :
2167 3 : void operator() (size_t nRow, const ScFormulaCell* pCell)
2168 : {
2169 3 : if (pCell->IsSubTotal())
2170 3 : mrSet.set(mnTab, mnCol, nRow, mbVal);
2171 3 : }
2172 : };
2173 :
2174 : }
2175 :
2176 6 : void ScColumn::MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nRow2, bool bVal ) const
2177 : {
2178 6 : SubTotalCellPicker aFunc(rSet, nTab, nCol, bVal);
2179 6 : sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
2180 6 : }
2181 :
2182 : namespace {
2183 :
2184 : class UpdateRefOnCopy
2185 : {
2186 : protected:
2187 : ScRange maRange;
2188 : SCCOL mnDx;
2189 : SCROW mnDy;
2190 : SCTAB mnDz;
2191 : ScDocument* mpUndoDoc;
2192 : bool mbUpdated;
2193 :
2194 : public:
2195 5206 : UpdateRefOnCopy(const ScRange& rRange, SCCOL nDx, SCROW nDy, SCTAB nDz, ScDocument* pUndoDoc) :
2196 5206 : maRange(rRange), mnDx(nDx), mnDy(nDy), mnDz(nDz), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
2197 :
2198 5206 : bool isUpdated() const { return mbUpdated; }
2199 :
2200 5302 : void operator() (sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
2201 : {
2202 5302 : if (node.type != sc::element_type_formula)
2203 10596 : return;
2204 :
2205 8 : sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
2206 8 : std::advance(it, nOffset);
2207 8 : sc::formula_block::iterator itEnd = it;
2208 8 : std::advance(itEnd, nDataSize);
2209 :
2210 25 : for (; it != itEnd; ++it)
2211 : {
2212 17 : ScFormulaCell& rCell = **it;
2213 17 : mbUpdated |= rCell.UpdateReference(URM_COPY, maRange, mnDx, mnDy, mnDz, mpUndoDoc);
2214 : }
2215 : }
2216 : };
2217 :
2218 : class UpdateRefOnNonCopy
2219 : {
2220 : SCCOL mnCol;
2221 : SCROW mnTab;
2222 : ScRange maRange;
2223 : SCCOL mnDx;
2224 : SCROW mnDy;
2225 : SCTAB mnDz;
2226 : UpdateRefMode meMode;
2227 : ScDocument* mpUndoDoc;
2228 : bool mbUpdated;
2229 :
2230 : public:
2231 64512 : UpdateRefOnNonCopy(
2232 : SCCOL nCol, SCTAB nTab, const ScRange& rRange,
2233 : SCCOL nDx, SCROW nDy, SCTAB nDz, UpdateRefMode eMode,
2234 : ScDocument* pUndoDoc) :
2235 : mnCol(nCol), mnTab(nTab), maRange(rRange),
2236 64512 : mnDx(nDx), mnDy(nDy), mnDz(nDz), meMode(eMode), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
2237 :
2238 34 : void operator() (size_t nRow, ScFormulaCell* pCell)
2239 : {
2240 34 : ScAddress aUndoPos(mnCol, nRow, mnTab);
2241 34 : mbUpdated |= pCell->UpdateReference(meMode, maRange, mnDx, mnDy, mnDz, mpUndoDoc, &aUndoPos);
2242 34 : }
2243 :
2244 64512 : bool isUpdated() const { return mbUpdated; }
2245 : };
2246 :
2247 : }
2248 :
2249 69718 : bool ScColumn::UpdateReference(
2250 : UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
2251 : ScDocument* pUndoDoc )
2252 : {
2253 69718 : if (eUpdateRefMode == URM_COPY)
2254 : {
2255 5206 : UpdateRefOnCopy aHandler(rRange, nDx, nDy, nDz, pUndoDoc);
2256 5206 : FormulaCellsUndecided(rRange.aStart.Row(), rRange.aEnd.Row());
2257 5206 : sc::ProcessBlock(maCells.begin(), maCells, aHandler, rRange.aStart.Row(), rRange.aEnd.Row());
2258 5206 : return aHandler.isUpdated();
2259 : }
2260 :
2261 64512 : UpdateRefOnNonCopy aHandler(nCol, nTab, rRange, nDx, nDy, nDz, eUpdateRefMode, pUndoDoc);
2262 64512 : FormulaCellsUndecided(0, MAXROW);
2263 64512 : sc::ProcessFormula(maCells, aHandler);
2264 64512 : return aHandler.isUpdated();
2265 : }
2266 :
2267 : namespace {
2268 :
2269 : class UpdateTransHandler
2270 : {
2271 : ScRange maSource;
2272 : ScAddress maDest;
2273 : ScDocument* mpUndoDoc;
2274 : public:
2275 0 : UpdateTransHandler(const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
2276 0 : maSource(rSource), maDest(rDest), mpUndoDoc(pUndoDoc) {}
2277 :
2278 0 : void operator() (size_t, ScFormulaCell* pCell)
2279 : {
2280 0 : pCell->UpdateTranspose(maSource, maDest, mpUndoDoc);
2281 0 : }
2282 : };
2283 :
2284 : class UpdateGrowHandler
2285 : {
2286 : ScRange maArea;
2287 : SCCOL mnGrowX;
2288 : SCROW mnGrowY;
2289 : public:
2290 0 : UpdateGrowHandler(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
2291 0 : maArea(rArea), mnGrowX(nGrowX), mnGrowY(nGrowY) {}
2292 :
2293 0 : void operator() (size_t, ScFormulaCell* pCell)
2294 : {
2295 0 : pCell->UpdateGrow(maArea, mnGrowX, mnGrowY);
2296 0 : }
2297 : };
2298 :
2299 : class InsertTabUpdater
2300 : {
2301 : sc::CellTextAttrStoreType& mrTextAttrs;
2302 : sc::CellTextAttrStoreType::iterator miAttrPos;
2303 : SCTAB mnTab;
2304 : SCTAB mnInsPos;
2305 : SCTAB mnNewSheets;
2306 : bool mbModified;
2307 :
2308 : public:
2309 58368 : InsertTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nInsPos, SCTAB nNewSheets) :
2310 : mrTextAttrs(rTextAttrs),
2311 : miAttrPos(rTextAttrs.begin()),
2312 : mnTab(nTab),
2313 : mnInsPos(nInsPos),
2314 : mnNewSheets(nNewSheets),
2315 58368 : mbModified(false) {}
2316 :
2317 6 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2318 : {
2319 6 : pCell->UpdateInsertTab(mnInsPos, mnNewSheets);
2320 6 : mbModified = true;
2321 6 : }
2322 :
2323 0 : void operator() (size_t nRow, EditTextObject* pCell)
2324 : {
2325 0 : editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2326 0 : aUpdater.updateTableFields(mnTab);
2327 0 : miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2328 0 : mbModified = true;
2329 0 : }
2330 :
2331 58368 : bool isModified() const { return mbModified; }
2332 : };
2333 :
2334 : class DeleteTabUpdater
2335 : {
2336 : sc::CellTextAttrStoreType& mrTextAttrs;
2337 : sc::CellTextAttrStoreType::iterator miAttrPos;
2338 : SCTAB mnDelPos;
2339 : SCTAB mnSheets;
2340 : SCTAB mnTab;
2341 : bool mbIsMove;
2342 : bool mbModified;
2343 : public:
2344 124928 : DeleteTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nDelPos, SCTAB nSheets, SCTAB nTab, bool bIsMove) :
2345 : mrTextAttrs(rTextAttrs),
2346 : miAttrPos(rTextAttrs.begin()),
2347 : mnDelPos(nDelPos),
2348 : mnSheets(nSheets),
2349 : mnTab(nTab),
2350 : mbIsMove(bIsMove),
2351 124928 : mbModified(false) {}
2352 :
2353 60 : void operator() (size_t, ScFormulaCell* pCell)
2354 : {
2355 60 : pCell->UpdateDeleteTab(mnDelPos, mbIsMove, mnSheets);
2356 60 : mbModified = true;
2357 60 : }
2358 :
2359 0 : void operator() (size_t nRow, EditTextObject* pCell)
2360 : {
2361 0 : editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2362 0 : aUpdater.updateTableFields(mnTab);
2363 0 : miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2364 0 : mbModified = true;
2365 0 : }
2366 :
2367 124928 : bool isModified() const { return mbModified; }
2368 : };
2369 :
2370 : class InsertAbsTabUpdater
2371 : {
2372 : sc::CellTextAttrStoreType& mrTextAttrs;
2373 : sc::CellTextAttrStoreType::iterator miAttrPos;
2374 : SCTAB mnTab;
2375 : SCTAB mnNewPos;
2376 : bool mbModified;
2377 : public:
2378 4096 : InsertAbsTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nNewPos) :
2379 : mrTextAttrs(rTextAttrs),
2380 : miAttrPos(rTextAttrs.begin()),
2381 : mnTab(nTab),
2382 : mnNewPos(nNewPos),
2383 4096 : mbModified(false) {}
2384 :
2385 0 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2386 : {
2387 0 : pCell->UpdateInsertTabAbs(mnNewPos);
2388 0 : mbModified = true;
2389 0 : }
2390 :
2391 0 : void operator() (size_t nRow, EditTextObject* pCell)
2392 : {
2393 0 : editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2394 0 : aUpdater.updateTableFields(mnTab);
2395 0 : miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2396 0 : mbModified = true;
2397 0 : }
2398 :
2399 4096 : bool isModified() const { return mbModified; }
2400 : };
2401 :
2402 : class MoveTabUpdater
2403 : {
2404 : sc::CellTextAttrStoreType& mrTextAttrs;
2405 : sc::CellTextAttrStoreType::iterator miAttrPos;
2406 : SCTAB mnTab;
2407 : SCTAB mnOldPos;
2408 : SCTAB mnNewPos;
2409 : bool mbModified;
2410 : public:
2411 10240 : MoveTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nOldPos, SCTAB nNewPos) :
2412 : mrTextAttrs(rTextAttrs),
2413 : miAttrPos(rTextAttrs.begin()),
2414 : mnTab(nTab),
2415 : mnOldPos(nOldPos),
2416 : mnNewPos(nNewPos),
2417 10240 : mbModified(false) {}
2418 :
2419 0 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2420 : {
2421 0 : pCell->UpdateMoveTab(mnOldPos, mnNewPos, mnTab);
2422 0 : mbModified = true;
2423 0 : }
2424 :
2425 0 : void operator() (size_t nRow, EditTextObject* pCell)
2426 : {
2427 0 : editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2428 0 : aUpdater.updateTableFields(mnTab);
2429 0 : miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2430 0 : mbModified = true;
2431 0 : }
2432 :
2433 10240 : bool isModified() const { return mbModified; }
2434 : };
2435 :
2436 : class UpdateCompileHandler
2437 : {
2438 : bool mbForceIfNameInUse:1;
2439 : public:
2440 185344 : UpdateCompileHandler(bool bForceIfNameInUse) :
2441 185344 : mbForceIfNameInUse(bForceIfNameInUse) {}
2442 :
2443 58 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2444 : {
2445 58 : pCell->UpdateCompile(mbForceIfNameInUse);
2446 58 : }
2447 : };
2448 :
2449 : class TabNoSetter
2450 : {
2451 : SCTAB mnTab;
2452 : public:
2453 3072 : TabNoSetter(SCTAB nTab) : mnTab(nTab) {}
2454 :
2455 5 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2456 : {
2457 5 : pCell->aPos.SetTab(mnTab);
2458 5 : }
2459 : };
2460 :
2461 : class UsedRangeNameFinder
2462 : {
2463 : std::set<sal_uInt16>& mrIndexes;
2464 : public:
2465 7 : UsedRangeNameFinder(std::set<sal_uInt16>& rIndexes) : mrIndexes(rIndexes) {}
2466 :
2467 1 : void operator() (size_t /*nRow*/, const ScFormulaCell* pCell)
2468 : {
2469 1 : pCell->FindRangeNamesInUse(mrIndexes);
2470 1 : }
2471 : };
2472 :
2473 : struct SetDirtyVarHandler
2474 : {
2475 590 : void operator() (size_t /*nRow*/, ScFormulaCell* p)
2476 : {
2477 590 : p->SetDirtyVar();
2478 590 : }
2479 : };
2480 :
2481 : class SetDirtyHandler
2482 : {
2483 : ScDocument& mrDoc;
2484 : public:
2485 412672 : SetDirtyHandler(ScDocument& rDoc) : mrDoc(rDoc) {}
2486 :
2487 72 : void operator() (size_t /*nRow*/, ScFormulaCell* p)
2488 : {
2489 72 : p->SetDirtyVar();
2490 72 : if (!mrDoc.IsInFormulaTree(p))
2491 57 : mrDoc.PutInFormulaTree(p);
2492 72 : }
2493 : };
2494 :
2495 3333 : class SetDirtyOnRangeHandler
2496 : {
2497 : sc::SingleColumnSpanSet maValueRanges;
2498 : ScColumn& mrColumn;
2499 : public:
2500 3333 : SetDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
2501 :
2502 36 : void operator() (size_t /*nRow*/, ScFormulaCell* p)
2503 : {
2504 36 : p->SetDirty();
2505 36 : }
2506 :
2507 3452 : void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
2508 : {
2509 3452 : if (type == sc::element_type_empty)
2510 : // Ignore empty blocks.
2511 6567 : return;
2512 :
2513 : // Non-formula cells.
2514 337 : SCROW nRow1 = nTopRow;
2515 337 : SCROW nRow2 = nTopRow + nDataSize - 1;
2516 337 : maValueRanges.set(nRow1, nRow2, true);
2517 : }
2518 :
2519 3333 : void broadcast()
2520 : {
2521 3333 : std::vector<SCROW> aRows;
2522 3333 : maValueRanges.getRows(aRows);
2523 3333 : mrColumn.BroadcastCells(aRows);
2524 3333 : }
2525 : };
2526 :
2527 32 : class SetTableOpDirtyOnRangeHandler
2528 : {
2529 : sc::SingleColumnSpanSet maValueRanges;
2530 : ScColumn& mrColumn;
2531 : public:
2532 32 : SetTableOpDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
2533 :
2534 0 : void operator() (size_t /*nRow*/, ScFormulaCell* p)
2535 : {
2536 0 : p->SetTableOpDirty();
2537 0 : }
2538 :
2539 32 : void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
2540 : {
2541 32 : if (type == sc::element_type_empty)
2542 : // Ignore empty blocks.
2543 64 : return;
2544 :
2545 : // Non-formula cells.
2546 0 : SCROW nRow1 = nTopRow;
2547 0 : SCROW nRow2 = nTopRow + nDataSize - 1;
2548 0 : maValueRanges.set(nRow1, nRow2, true);
2549 : }
2550 :
2551 32 : void broadcast()
2552 : {
2553 32 : std::vector<SCROW> aRows;
2554 32 : maValueRanges.getRows(aRows);
2555 32 : mrColumn.BroadcastCells(aRows);
2556 32 : }
2557 : };
2558 :
2559 : struct SetDirtyAfterLoadHandler
2560 : {
2561 2473 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2562 : {
2563 : #if 1
2564 : // Simply set dirty and append to FormulaTree, without broadcasting,
2565 : // which is a magnitude faster. This is used to calculate the entire
2566 : // document, e.g. when loading alien file formats.
2567 2473 : pCell->SetDirtyAfterLoad();
2568 : #else
2569 : /* This was used with the binary file format that stored results, where only
2570 : * newly compiled and volatile functions and their dependents had to be
2571 : * recalculated, which was faster then. Since that was moved to 'binfilter' to
2572 : * convert to an XML file this isn't needed anymore, and not used for other
2573 : * file formats. Kept for reference in case mechanism needs to be reactivated
2574 : * for some file formats, we'd have to introduce a controlling parameter to
2575 : * this method here then.
2576 : */
2577 :
2578 : // If the cell was alsready dirty because of CalcAfterLoad,
2579 : // FormulaTracking has to take place.
2580 : if (pCell->GetDirty())
2581 : pCell->SetDirty();
2582 : #endif
2583 2473 : }
2584 : };
2585 :
2586 : struct SetRelNameDirtyHandler
2587 : {
2588 29 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2589 : {
2590 29 : if (pCell->HasRelNameReference())
2591 0 : pCell->SetDirty();
2592 29 : }
2593 : };
2594 :
2595 : struct CalcAllHandler
2596 : {
2597 590 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2598 : {
2599 : #if OSL_DEBUG_LEVEL > 1
2600 : // after F9 ctrl-F9: check the calculation for each FormulaTree
2601 : double nOldVal, nNewVal;
2602 : nOldVal = pCell->GetValue();
2603 : #endif
2604 590 : pCell->Interpret();
2605 : #if OSL_DEBUG_LEVEL > 1
2606 : if (pCell->GetCode()->IsRecalcModeNormal())
2607 : nNewVal = pCell->GetValue();
2608 : else
2609 : nNewVal = nOldVal; // random(), jetzt() etc.
2610 :
2611 : OSL_ENSURE(nOldVal == nNewVal, "CalcAll: nOldVal != nNewVal");
2612 : #endif
2613 590 : }
2614 : };
2615 :
2616 : struct CompileAllHandler
2617 : {
2618 6 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2619 : {
2620 : // for unconditional compilation
2621 : // bCompile=true and pCode->nError=0
2622 6 : pCell->GetCode()->SetCodeError(0);
2623 6 : pCell->SetCompile(true);
2624 6 : pCell->CompileTokenArray();
2625 6 : }
2626 : };
2627 :
2628 : class CompileXMLHandler
2629 : {
2630 : ScProgress& mrProgress;
2631 : const ScColumn& mrCol;
2632 : public:
2633 172032 : CompileXMLHandler(ScProgress& rProgress, const ScColumn& rCol) :
2634 : mrProgress(rProgress),
2635 172032 : mrCol(rCol) {}
2636 :
2637 448 : void operator() (size_t nRow, ScFormulaCell* pCell)
2638 : {
2639 448 : sal_uInt32 nFormat = mrCol.GetNumberFormat(nRow);
2640 448 : if( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
2641 145 : pCell->SetNeedNumberFormat(false);
2642 : else
2643 303 : pCell->SetDirty(true);
2644 :
2645 448 : pCell->CompileXML(mrProgress);
2646 448 : }
2647 : };
2648 :
2649 : class CompileErrorCellsHandler
2650 : {
2651 : sal_uInt16 mnErrCode;
2652 : FormulaGrammar::Grammar meGram;
2653 : bool mbCompiled;
2654 : public:
2655 0 : CompileErrorCellsHandler(sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) :
2656 0 : mnErrCode(nErrCode), meGram(eGram), mbCompiled(false) {}
2657 :
2658 0 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2659 : {
2660 0 : sal_uInt16 nCurError = pCell->GetRawError();
2661 0 : if (!nCurError)
2662 : // It's not an error cell. Skip it.
2663 0 : return;
2664 :
2665 0 : if (mnErrCode && nCurError != mnErrCode)
2666 : // Error code is specified, and it doesn't match. Skip it.
2667 0 : return;
2668 :
2669 0 : pCell->GetCode()->SetCodeError(0);
2670 0 : OUStringBuffer aBuf;
2671 0 : pCell->GetFormula(aBuf, meGram);
2672 0 : pCell->Compile(aBuf.makeStringAndClear(), false, meGram);
2673 :
2674 0 : mbCompiled = true;
2675 : }
2676 :
2677 0 : bool isCompiled() const { return mbCompiled; }
2678 : };
2679 :
2680 : struct CalcAfterLoadHandler
2681 : {
2682 2473 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2683 : {
2684 2473 : pCell->CalcAfterLoad();
2685 2473 : }
2686 : };
2687 :
2688 : struct ResetChangedHandler
2689 : {
2690 268 : void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2691 : {
2692 268 : pCell->SetChanged(false);
2693 268 : }
2694 : };
2695 :
2696 : /**
2697 : * Ambiguous script type counts as edit cell.
2698 : */
2699 : class FindEditCellsHandler
2700 : {
2701 : ScColumn& mrColumn;
2702 : sc::CellTextAttrStoreType::iterator miAttrPos;
2703 :
2704 : public:
2705 751402 : FindEditCellsHandler(ScColumn& rColumn, sc::CellTextAttrStoreType& rAttrs) :
2706 751402 : mrColumn(rColumn), miAttrPos(rAttrs.begin()) {}
2707 :
2708 121 : bool operator() (size_t, const EditTextObject*)
2709 : {
2710 121 : return true;
2711 : }
2712 :
2713 216 : bool operator() (size_t nRow, const ScFormulaCell* p)
2714 : {
2715 216 : sal_uInt8 nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow);
2716 216 : if (IsAmbiguousScriptNonZero(nScriptType))
2717 0 : return true;
2718 :
2719 216 : return const_cast<ScFormulaCell*>(p)->IsMultilineResult();
2720 : }
2721 :
2722 751958 : std::pair<size_t,bool> operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
2723 : {
2724 : typedef std::pair<size_t,bool> RetType;
2725 :
2726 751958 : if (type == sc::element_type_empty)
2727 749315 : return RetType(0, false);
2728 :
2729 32126 : for (size_t i = 0; i < nDataSize; ++i)
2730 : {
2731 29483 : SCROW nRow = nTopRow + i;
2732 29483 : sal_uInt8 nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow);
2733 29483 : if (IsAmbiguousScriptNonZero(nScriptType))
2734 : // Return the offset from the first row.
2735 0 : return RetType(i, true);
2736 : }
2737 :
2738 2643 : return RetType(0, false);
2739 : }
2740 : };
2741 :
2742 : }
2743 :
2744 0 : void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
2745 : ScDocument* pUndoDoc )
2746 : {
2747 0 : UpdateTransHandler aFunc(rSource, rDest, pUndoDoc);
2748 0 : sc::ProcessFormula(maCells, aFunc);
2749 0 : RegroupFormulaCells();
2750 0 : }
2751 :
2752 :
2753 0 : void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
2754 : {
2755 0 : UpdateGrowHandler aFunc(rArea, nGrowX, nGrowY);
2756 0 : sc::ProcessFormula(maCells, aFunc);
2757 0 : RegroupFormulaCells();
2758 0 : }
2759 :
2760 :
2761 58368 : void ScColumn::UpdateInsertTab(SCTAB nInsPos, SCTAB nNewSheets)
2762 : {
2763 58368 : if (nTab >= nInsPos)
2764 : {
2765 50176 : nTab += nNewSheets;
2766 50176 : pAttrArray->SetTab(nTab);
2767 : }
2768 :
2769 58368 : UpdateInsertTabOnlyCells(nInsPos, nNewSheets);
2770 58368 : }
2771 :
2772 58368 : void ScColumn::UpdateInsertTabOnlyCells(SCTAB nInsPos, SCTAB nNewSheets)
2773 : {
2774 58368 : InsertTabUpdater aFunc(maCellTextAttrs, nTab, nInsPos, nNewSheets);
2775 58368 : sc::ProcessFormulaEditText(maCells, aFunc);
2776 58368 : if (aFunc.isModified())
2777 : {
2778 3 : RegroupFormulaCells();
2779 3 : CellStorageModified();
2780 : }
2781 58368 : }
2782 :
2783 124928 : void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* /*pRefUndo*/, SCTAB nSheets)
2784 : {
2785 124928 : if (nTab > nDelPos)
2786 : {
2787 33792 : nTab -= nSheets;
2788 33792 : pAttrArray->SetTab(nTab);
2789 : }
2790 :
2791 124928 : DeleteTabUpdater aFunc(maCellTextAttrs, nDelPos, nSheets, nTab, bIsMove);
2792 124928 : sc::ProcessFormulaEditText(maCells, aFunc);
2793 124928 : if (aFunc.isModified())
2794 : {
2795 23 : RegroupFormulaCells();
2796 23 : CellStorageModified();
2797 : }
2798 124928 : }
2799 :
2800 4096 : void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
2801 : {
2802 4096 : InsertAbsTabUpdater aFunc(maCellTextAttrs, nTab, nNewPos);
2803 4096 : sc::ProcessFormulaEditText(maCells, aFunc);
2804 4096 : if (aFunc.isModified())
2805 : {
2806 0 : RegroupFormulaCells();
2807 0 : CellStorageModified();
2808 : }
2809 4096 : }
2810 :
2811 10240 : void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
2812 : {
2813 10240 : nTab = nTabNo;
2814 10240 : pAttrArray->SetTab( nTabNo );
2815 :
2816 10240 : MoveTabUpdater aFunc(maCellTextAttrs, nTab, nOldPos, nNewPos);
2817 10240 : sc::ProcessFormulaEditText(maCells, aFunc);
2818 10240 : if (aFunc.isModified())
2819 : {
2820 0 : RegroupFormulaCells();
2821 0 : CellStorageModified();
2822 : }
2823 10240 : }
2824 :
2825 :
2826 185344 : void ScColumn::UpdateCompile( bool bForceIfNameInUse )
2827 : {
2828 185344 : UpdateCompileHandler aFunc(bForceIfNameInUse);
2829 185344 : sc::ProcessFormula(maCells, aFunc);
2830 185344 : RegroupFormulaCells();
2831 185344 : }
2832 :
2833 :
2834 3072 : void ScColumn::SetTabNo(SCTAB nNewTab)
2835 : {
2836 3072 : nTab = nNewTab;
2837 3072 : pAttrArray->SetTab( nNewTab );
2838 :
2839 3072 : TabNoSetter aFunc(nTab);
2840 3072 : sc::ProcessFormula(maCells, aFunc);
2841 3072 : }
2842 :
2843 7 : void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
2844 : {
2845 7 : UsedRangeNameFinder aFunc(rIndexes);
2846 7 : sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
2847 7 : }
2848 :
2849 190464 : void ScColumn::SetDirtyVar()
2850 : {
2851 : SetDirtyVarHandler aFunc;
2852 190464 : sc::ProcessFormula(maCells, aFunc);
2853 190464 : }
2854 :
2855 0 : bool ScColumn::IsFormulaDirty( SCROW nRow ) const
2856 : {
2857 0 : if (!ValidRow(nRow))
2858 0 : return false;
2859 :
2860 0 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
2861 0 : sc::CellStoreType::const_iterator it = aPos.first;
2862 0 : if (it->type != sc::element_type_formula)
2863 : // This is not a formula cell block.
2864 0 : return false;
2865 :
2866 0 : const ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
2867 0 : return p->GetDirty();
2868 : }
2869 :
2870 412672 : void ScColumn::SetDirty()
2871 : {
2872 : // is only done documentwide, no FormulaTracking
2873 412672 : sc::AutoCalcSwitch aSwitch(*pDocument, false);
2874 412672 : SetDirtyHandler aFunc(*pDocument);
2875 412672 : sc::ProcessFormula(maCells, aFunc);
2876 412672 : }
2877 :
2878 3333 : void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2 )
2879 : {
2880 : // broadcasts everything within the range, with FormulaTracking
2881 3333 : sc::AutoCalcSwitch aSwitch(*pDocument, false);
2882 :
2883 6666 : SetDirtyOnRangeHandler aHdl(*this);
2884 3333 : sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
2885 6666 : aHdl.broadcast();
2886 3333 : }
2887 :
2888 32 : void ScColumn::SetTableOpDirty( const ScRange& rRange )
2889 : {
2890 32 : sc::AutoCalcSwitch aSwitch(*pDocument, false);
2891 :
2892 32 : SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
2893 64 : SetTableOpDirtyOnRangeHandler aHdl(*this);
2894 32 : sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
2895 64 : aHdl.broadcast();
2896 32 : }
2897 :
2898 166912 : void ScColumn::SetDirtyAfterLoad()
2899 : {
2900 166912 : sc::AutoCalcSwitch aSwitch(*pDocument, false);
2901 : SetDirtyAfterLoadHandler aFunc;
2902 166912 : sc::ProcessFormula(maCells, aFunc);
2903 166912 : }
2904 :
2905 60416 : void ScColumn::SetRelNameDirty()
2906 : {
2907 60416 : sc::AutoCalcSwitch aSwitch(*pDocument, false);
2908 : SetRelNameDirtyHandler aFunc;
2909 60416 : sc::ProcessFormula(maCells, aFunc);
2910 60416 : }
2911 :
2912 190464 : void ScColumn::CalcAll()
2913 : {
2914 : CalcAllHandler aFunc;
2915 190464 : sc::ProcessFormula(maCells, aFunc);
2916 190464 : }
2917 :
2918 3072 : void ScColumn::CompileAll()
2919 : {
2920 : CompileAllHandler aFunc;
2921 3072 : sc::ProcessFormula(maCells, aFunc);
2922 3072 : }
2923 :
2924 172032 : void ScColumn::CompileXML( ScProgress& rProgress )
2925 : {
2926 172032 : CompileXMLHandler aFunc(rProgress, *this);
2927 172032 : sc::ProcessFormula(maCells, aFunc);
2928 172032 : RegroupFormulaCells();
2929 172032 : }
2930 :
2931 0 : bool ScColumn::CompileErrorCells(sal_uInt16 nErrCode)
2932 : {
2933 0 : CompileErrorCellsHandler aHdl(nErrCode, pDocument->GetGrammar());
2934 0 : sc::ProcessFormula(maCells, aHdl);
2935 0 : if (aHdl.isCompiled())
2936 : // TODO: Probably more efficient to do this individually rather than the whole column.
2937 0 : RegroupFormulaCells();
2938 :
2939 0 : return aHdl.isCompiled();
2940 : }
2941 :
2942 166912 : void ScColumn::CalcAfterLoad()
2943 : {
2944 : CalcAfterLoadHandler aFunc;
2945 166912 : sc::ProcessFormula(maCells, aFunc);
2946 166912 : }
2947 :
2948 17080 : void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
2949 : {
2950 : ResetChangedHandler aFunc;
2951 17080 : sc::ProcessFormula(maCells.begin(), maCells, nStartRow, nEndRow, aFunc);
2952 17080 : }
2953 :
2954 751402 : bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
2955 : {
2956 : // used in GetOptimalHeight - ambiguous script type counts as edit cell
2957 :
2958 751402 : FindEditCellsHandler aFunc(*this, maCellTextAttrs);
2959 : std::pair<sc::CellStoreType::const_iterator,size_t> aPos =
2960 751402 : sc::FindFormulaEditText(maCells, nStartRow, nEndRow, aFunc);
2961 :
2962 751402 : if (aPos.first == maCells.end())
2963 751281 : return false;
2964 :
2965 121 : rFirst = aPos.first->position + aPos.second;
2966 121 : return true;
2967 : }
2968 :
2969 :
2970 0 : SCsROW ScColumn::SearchStyle(
2971 : SCsROW nRow, const ScStyleSheet* pSearchStyle, bool bUp, bool bInSelection,
2972 : const ScMarkData& rMark) const
2973 : {
2974 0 : if (bInSelection)
2975 : {
2976 0 : if (rMark.IsMultiMarked())
2977 0 : return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, rMark.GetArray()+nCol);
2978 : else
2979 0 : return -1;
2980 : }
2981 : else
2982 0 : return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
2983 : }
2984 :
2985 :
2986 0 : bool ScColumn::SearchStyleRange(
2987 : SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp,
2988 : bool bInSelection, const ScMarkData& rMark) const
2989 : {
2990 0 : if (bInSelection)
2991 : {
2992 0 : if (rMark.IsMultiMarked())
2993 : return pAttrArray->SearchStyleRange(
2994 0 : rRow, rEndRow, pSearchStyle, bUp, rMark.GetArray() + nCol);
2995 : else
2996 0 : return false;
2997 : }
2998 : else
2999 0 : return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
3000 93 : }
3001 :
3002 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|