LibreOffice Module sc (master)  1
column.cxx
Go to the documentation of this file.
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 <table.hxx>
25 #include <docpool.hxx>
26 #include <attarray.hxx>
27 #include <patattr.hxx>
28 #include <compiler.hxx>
29 #include <brdcst.hxx>
30 #include <markdata.hxx>
31 #include <postit.hxx>
32 #include <cellvalue.hxx>
33 #include <tokenarray.hxx>
34 #include <clipcontext.hxx>
35 #include <types.hxx>
36 #include <editutil.hxx>
37 #include <mtvcellfunc.hxx>
38 #include <columnspanset.hxx>
39 #include <scopetools.hxx>
40 #include <sharedformula.hxx>
41 #include <refupdatecontext.hxx>
42 #include <listenercontext.hxx>
43 #include <formulagroup.hxx>
44 #include <drwlayer.hxx>
45 #include <mtvelements.hxx>
46 
47 #include <svl/numformat.hxx>
48 #include <svl/poolcach.hxx>
49 #include <svl/zforlist.hxx>
50 #include <svl/sharedstringpool.hxx>
51 #include <editeng/fieldupdater.hxx>
52 #include <formula/errorcodes.hxx>
53 #include <o3tl/safeint.hxx>
54 #include <osl/diagnose.h>
55 
56 #include <map>
57 #include <cstdio>
58 #include <memory>
59 
60 using ::editeng::SvxBorderLine;
61 using namespace formula;
62 
63 namespace {
64 
65 bool IsAmbiguousScriptNonZero( SvtScriptType nScript )
66 {
67  //TODO: move to a header file
68  return ( nScript != SvtScriptType::LATIN &&
69  nScript != SvtScriptType::ASIAN &&
70  nScript != SvtScriptType::COMPLEX &&
71  nScript != SvtScriptType::NONE );
72 }
73 
74 }
75 
77  pPattern(nullptr), bFormula(false), bSkipMerged(true), bGetFont(true), bTotalSize(false)
78 {
79 }
80 
81 ScColumn::ScColumn(ScSheetLimits const & rSheetLimits) :
82  maCellTextAttrs(rSheetLimits.GetMaxRowCount()),
83  maCellNotes(rSheetLimits.GetMaxRowCount()),
84  maBroadcasters(rSheetLimits.GetMaxRowCount()),
85  maCellsEvent(this),
86  maCells(maCellsEvent),
87  mnBlkCountFormula(0),
88  nCol( 0 ),
89  nTab( 0 ),
90  mbFiltering( false )
91 {
92  maCells.resize(rSheetLimits.GetMaxRowCount());
93 }
94 
95 ScColumn::~ScColumn() COVERITY_NOEXCEPT_FALSE
96 {
97  FreeAll();
98 }
99 
100 void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument& rDoc, bool bEmptyAttrArray)
101 {
102  nCol = nNewCol;
103  nTab = nNewTab;
104  if ( bEmptyAttrArray )
105  pAttrArray.reset(new ScAttrArray( nCol, nTab, rDoc, nullptr ));
106  else
107  pAttrArray.reset(new ScAttrArray( nCol, nTab, rDoc, &rDoc.maTabs[nTab]->aDefaultColAttrArray ));
108 }
109 
110 SCROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
111 {
112  return pAttrArray->GetNextUnprotected(nRow, bUp);
113 }
114 
116  bool bNoMatrixAtAll ) const
117 {
118  using namespace sc;
119 
120  if (!GetDoc().ValidRow(nRow1) || !GetDoc().ValidRow(nRow2) || nRow1 > nRow2)
121  return MatrixEdge::Nothing;
122 
124 
125  if (nRow1 == nRow2)
126  {
127  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
128  if (aPos.first->type != sc::element_type_formula)
129  return MatrixEdge::Nothing;
130 
131  const ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second);
132  if (pCell->GetMatrixFlag() == ScMatrixMode::NONE)
133  return MatrixEdge::Nothing;
134 
135  return pCell->GetMatrixEdge(GetDoc(), aOrigin);
136  }
137 
138  bool bOpen = false;
139  MatrixEdge nEdges = MatrixEdge::Nothing;
140 
141  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
142  sc::CellStoreType::const_iterator it = aPos.first;
143  size_t nOffset = aPos.second;
144  SCROW nRow = nRow1;
145  for (;it != maCells.end() && nRow <= nRow2; ++it, nOffset = 0)
146  {
147  if (it->type != sc::element_type_formula)
148  {
149  // Skip this block.
150  nRow += it->size - nOffset;
151  continue;
152  }
153 
154  size_t nRowsToRead = nRow2 - nRow + 1;
155  size_t nEnd = std::min(it->size, nOffset+nRowsToRead); // last row + 1
156  sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
157  std::advance(itCell, nOffset);
158  for (size_t i = nOffset; i < nEnd; ++itCell, ++i)
159  {
160  // Loop inside the formula block.
161  const ScFormulaCell* pCell = *itCell;
162  if (pCell->GetMatrixFlag() == ScMatrixMode::NONE)
163  continue;
164 
165  nEdges = pCell->GetMatrixEdge(GetDoc(), aOrigin);
166  if (nEdges == MatrixEdge::Nothing)
167  continue;
168 
169  // A 1x1 matrix array formula is OK even for no matrix at all.
170  if (bNoMatrixAtAll
171  && (nEdges != (MatrixEdge::Top | MatrixEdge::Left | MatrixEdge::Bottom | MatrixEdge::Right)))
172  return MatrixEdge::Inside; // per convention Inside
173 
174  if (nEdges & MatrixEdge::Top)
175  bOpen = true; // top edge opens, keep on looking
176  else if (!bOpen)
177  return nEdges | MatrixEdge::Open; // there's something that wasn't opened
178  else if (nEdges & MatrixEdge::Inside)
179  return nEdges; // inside
180  if (((nMask & MatrixEdge::Right) && (nEdges & MatrixEdge::Left) && !(nEdges & MatrixEdge::Right)) ||
181  ((nMask & MatrixEdge::Left) && (nEdges & MatrixEdge::Right) && !(nEdges & MatrixEdge::Left)))
182  return nEdges; // only left/right edge
183 
184  if (nEdges & MatrixEdge::Bottom)
185  bOpen = false; // bottom edge closes
186  }
187 
188  nRow += nEnd - nOffset;
189  }
190  if (bOpen)
191  nEdges |= MatrixEdge::Open; // not closed, matrix continues
192 
193  return nEdges;
194 }
195 
197 {
198  using namespace sc;
199 
200  if (!rMark.IsMultiMarked())
201  return false;
202 
204  ScAddress aCurOrigin = aOrigin;
205 
206  bool bOpen = false;
207  ScRangeList aRanges = rMark.GetMarkedRanges();
208  for (size_t i = 0, n = aRanges.size(); i < n; ++i)
209  {
210  const ScRange& r = aRanges[i];
211  if (nTab < r.aStart.Tab() || r.aEnd.Tab() < nTab)
212  continue;
213 
214  if (nCol < r.aStart.Col() || r.aEnd.Col() < nCol)
215  continue;
216 
217  SCROW nTop = r.aStart.Row(), nBottom = r.aEnd.Row();
218  SCROW nRow = nTop;
219  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
220  sc::CellStoreType::const_iterator it = aPos.first;
221  size_t nOffset = aPos.second;
222 
223  for (;it != maCells.end() && nRow <= nBottom; ++it, nOffset = 0)
224  {
225  if (it->type != sc::element_type_formula)
226  {
227  // Skip this block.
228  nRow += it->size - nOffset;
229  continue;
230  }
231 
232  // This is a formula cell block.
233  size_t nRowsToRead = nBottom - nRow + 1;
234  size_t nEnd = std::min(it->size, nRowsToRead);
235  sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
236  std::advance(itCell, nOffset);
237  for (size_t j = nOffset; j < nEnd; ++itCell, ++j)
238  {
239  // Loop inside the formula block.
240  const ScFormulaCell* pCell = *itCell;
241  if (pCell->GetMatrixFlag() == ScMatrixMode::NONE)
242  // cell is not a part of a matrix.
243  continue;
244 
245  MatrixEdge nEdges = pCell->GetMatrixEdge(GetDoc(), aOrigin);
246  if (nEdges == MatrixEdge::Nothing)
247  continue;
248 
249  bool bFound = false;
250 
251  if (nEdges & MatrixEdge::Top)
252  bOpen = true; // top edge opens, keep on looking
253  else if (!bOpen)
254  return true; // there's something that wasn't opened
255  else if (nEdges & MatrixEdge::Inside)
256  bFound = true; // inside, all selected?
257 
258  if (((nEdges & MatrixEdge::Left) | MatrixEdge::Right) ^ ((nEdges & MatrixEdge::Right) | MatrixEdge::Left))
259  // either left or right, but not both.
260  bFound = true; // only left/right edge, all selected?
261 
262  if (nEdges & MatrixEdge::Bottom)
263  bOpen = false; // bottom edge closes
264 
265  if (bFound)
266  {
267  // Check if the matrix is inside the selection in its entirety.
268  //
269  // TODO: It's more efficient to skip the matrix range if
270  // it's within selection, to avoid checking it again and
271  // again.
272 
273  if (aCurOrigin != aOrigin)
274  { // new matrix to check?
275  aCurOrigin = aOrigin;
276  const ScFormulaCell* pFCell;
277  if (pCell->GetMatrixFlag() == ScMatrixMode::Reference)
278  pFCell = GetDoc().GetFormulaCell(aOrigin);
279  else
280  pFCell = pCell;
281 
282  SCCOL nC;
283  SCROW nR;
284  pFCell->GetMatColsRows(nC, nR);
285  ScRange aRange(aOrigin, ScAddress(aOrigin.Col()+nC-1, aOrigin.Row()+nR-1, aOrigin.Tab()));
286  if (rMark.IsAllMarked(aRange))
287  bFound = false;
288  }
289  else
290  bFound = false; // done already
291  }
292 
293  if (bFound)
294  return true;
295  }
296 
297  nRow += nEnd;
298  }
299  }
300 
301  return bOpen;
302 }
303 
304 bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const
305 {
306  return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
307 }
308 
309 bool ScColumn::HasAttribSelection( const ScMarkData& rMark, HasAttrFlags nMask ) const
310 {
311  bool bFound = false;
312 
313  SCROW nTop;
314  SCROW nBottom;
315 
316  if (rMark.IsMultiMarked())
317  {
318  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
319  while (aMultiIter.Next( nTop, nBottom ) && !bFound)
320  {
321  if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
322  bFound = true;
323  }
324  }
325 
326  return bFound;
327 }
328 
329 bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
330  SCCOL& rPaintCol, SCROW& rPaintRow,
331  bool bRefresh )
332 {
333  return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
334 }
335 
336 void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
337 {
338  SCROW nTop;
339  SCROW nBottom;
340 
341  if ( rMark.IsMultiMarked() )
342  {
343  const ScMultiSel& rMultiSel = rMark.GetMultiSelData();
344  if ( rMultiSel.HasMarks( nCol ) )
345  {
346  ScMultiSelIter aMultiIter( rMultiSel, nCol );
347  while (aMultiIter.Next( nTop, nBottom ))
348  pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
349  }
350  }
351 }
352 
353 void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
354 {
355  pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
356 }
357 
358 void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
359  ScLineFlags& rFlags,
360  SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
361 {
362  pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
363 }
364 
365 void ScColumn::ApplyBlockFrame(const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner,
366  SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight)
367 {
368  pAttrArray->ApplyBlockFrame(rLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight);
369 }
370 
372 {
373  return pAttrArray->GetPattern( nRow );
374 }
375 
376 const SfxPoolItem& ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
377 {
378  return pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
379 }
380 
381 const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
382 {
383  ::std::map< const ScPatternAttr*, size_t > aAttrMap;
384  const ScPatternAttr* pMaxPattern = nullptr;
385  size_t nMaxCount = 0;
386 
387  ScAttrIterator aAttrIter( pAttrArray.get(), nStartRow, nEndRow, GetDoc().GetDefPattern() );
388  const ScPatternAttr* pPattern;
389  SCROW nAttrRow1 = 0, nAttrRow2 = 0;
390 
391  while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != nullptr )
392  {
393  size_t& rnCount = aAttrMap[ pPattern ];
394  rnCount += (nAttrRow2 - nAttrRow1 + 1);
395  if( rnCount > nMaxCount )
396  {
397  pMaxPattern = pPattern;
398  nMaxCount = rnCount;
399  }
400  }
401 
402  return pMaxPattern;
403 }
404 
405 sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
406 {
407  ScDocument& rDocument = GetDoc();
408  SCROW nPatStartRow, nPatEndRow;
409  const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
410  sal_uInt32 nFormat = pPattern->GetNumberFormat(rDocument.GetFormatTable());
411  while (nEndRow > nPatEndRow)
412  {
413  nStartRow = nPatEndRow + 1;
414  pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
415  sal_uInt32 nTmpFormat = pPattern->GetNumberFormat(rDocument.GetFormatTable());
416  if (nFormat != nTmpFormat)
417  return 0;
418  }
419  return nFormat;
420 }
421 
422 sal_uInt32 ScColumn::GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const
423 {
424  return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext.GetFormatTable() );
425 }
426 
427 SCROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged )
428 {
429  SCROW nTop = 0;
430  SCROW nBottom = 0;
431  bool bFound = false;
432 
433  if ( rMark.IsMultiMarked() )
434  {
435  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
436  while (aMultiIter.Next( nTop, nBottom ))
437  {
438  pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray, pIsChanged );
439  bFound = true;
440  }
441  }
442 
443  if (!bFound)
444  return -1;
445  else if (nTop==0 && nBottom==GetDoc().MaxRow())
446  return 0;
447  else
448  return nBottom;
449 }
450 
451 void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
452 {
453  SCROW nTop;
454  SCROW nBottom;
455 
456  if ( pAttrArray && rMark.IsMultiMarked() )
457  {
458  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
459  while (aMultiIter.Next( nTop, nBottom ))
460  pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
461  }
462 }
463 
464 void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
465 {
466  SCROW nTop;
467  SCROW nBottom;
468 
469  if (!pAttrArray)
470  return;
471 
472  if (rMark.IsMultiMarked() )
473  {
474  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
475  while (aMultiIter.Next( nTop, nBottom ))
476  pAttrArray->ClearItems(nTop, nBottom, pWhich);
477  }
478  else if (rMark.IsMarked())
479  {
480  ScRange aRange;
481  rMark.GetMarkArea(aRange);
482  if (aRange.aStart.Col() <= nCol && nCol <= aRange.aEnd.Col())
483  {
484  pAttrArray->ClearItems(aRange.aStart.Row(), aRange.aEnd.Row(), pWhich);
485  }
486  }
487 }
488 
489 void ScColumn::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, bool bBroadcast )
490 {
491  SCROW nTop;
492  SCROW nBottom;
493 
494  if ( rMark.IsMultiMarked() )
495  {
496  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
497  while (aMultiIter.Next( nTop, nBottom ))
498  DeleteArea(nTop, nBottom, nDelFlag, bBroadcast);
499  }
500 }
501 
502 void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
503 {
504  const SfxItemSet* pSet = &rPatAttr.GetItemSet();
505  SfxItemPoolCache aCache( GetDoc().GetPool(), pSet );
506 
507  const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
508 
509  // true = keep old content
510 
511  const ScPatternAttr* pNewPattern = static_cast<const ScPatternAttr*>( &aCache.ApplyTo( *pPattern ) );
512 
513  if (pNewPattern != pPattern)
514  pAttrArray->SetPattern( nRow, pNewPattern );
515 }
516 
517 void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
518  ScEditDataArray* pDataArray, bool* const pIsChanged )
519 {
520  const SfxItemSet* pSet = &rPatAttr.GetItemSet();
521  SfxItemPoolCache aCache( GetDoc().GetPool(), pSet );
522  pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray, pIsChanged );
523 }
524 
526  const ScPatternAttr& rPattern, SvNumFormatType nNewType )
527 {
528  const SfxItemSet* pSet = &rPattern.GetItemSet();
529  SfxItemPoolCache aCache( GetDoc().GetPool(), pSet );
530  SvNumberFormatter* pFormatter = GetDoc().GetFormatTable();
531  SCROW nEndRow = rRange.aEnd.Row();
532  for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
533  {
534  SCROW nRow1, nRow2;
535  const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
536  nRow1, nRow2, nRow );
537  sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
538  SvNumFormatType nOldType = pFormatter->GetType( nFormat );
539  if ( nOldType == nNewType || SvNumberFormatter::IsCompatible( nOldType, nNewType ) )
540  nRow = nRow2;
541  else
542  {
543  SCROW nNewRow1 = std::max( nRow1, nRow );
544  SCROW nNewRow2 = std::min( nRow2, nEndRow );
545  pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
546  nRow = nNewRow2;
547  }
548  }
549 }
550 
551 void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
552 {
553  pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
554 }
555 
556 void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
557 {
558  pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex );
559 }
560 
561 void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet* rStyle )
562 {
563  const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
564  std::unique_ptr<ScPatternAttr> pNewPattern(new ScPatternAttr(*pPattern));
565  pNewPattern->SetStyleSheet(const_cast<ScStyleSheet*>(rStyle));
566  pAttrArray->SetPattern(nRow, std::move(pNewPattern), true);
567 }
568 
569 void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
570 {
571  pAttrArray->ApplyStyleArea(nStartRow, nEndRow, rStyle);
572 }
573 
574 void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
575 {
576  SCROW nTop;
577  SCROW nBottom;
578 
579  if ( rMark.IsMultiMarked() )
580  {
581  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
582  while (aMultiIter.Next( nTop, nBottom ))
583  pAttrArray->ApplyStyleArea(nTop, nBottom, rStyle);
584  }
585 }
586 
588  const SvxBorderLine* pLine, bool bColorOnly )
589 {
590  if ( bColorOnly && !pLine )
591  return;
592 
593  SCROW nTop;
594  SCROW nBottom;
595 
596  if (rMark.IsMultiMarked())
597  {
598  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
599  while (aMultiIter.Next( nTop, nBottom ))
600  pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
601  }
602 }
603 
605 {
606  return pAttrArray->GetPattern( nRow )->GetStyleSheet();
607 }
608 
609 const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
610 {
611  rFound = false;
612  if (!rMark.IsMultiMarked())
613  {
614  OSL_FAIL("No selection in ScColumn::GetSelectionStyle");
615  return nullptr;
616  }
617 
618  bool bEqual = true;
619 
620  const ScStyleSheet* pStyle = nullptr;
621  const ScStyleSheet* pNewStyle;
622 
623  ScDocument& rDocument = GetDoc();
624  ScMultiSelIter aMultiIter( rMark.GetMultiSelData(), nCol );
625  SCROW nTop;
626  SCROW nBottom;
627  while (bEqual && aMultiIter.Next( nTop, nBottom ))
628  {
629  ScAttrIterator aAttrIter( pAttrArray.get(), nTop, nBottom, rDocument.GetDefPattern() );
630  SCROW nRow;
631  SCROW nDummy;
632  while (bEqual)
633  {
634  const ScPatternAttr* pPattern = aAttrIter.Next( nRow, nDummy );
635  if (!pPattern)
636  break;
637  pNewStyle = pPattern->GetStyleSheet();
638  rFound = true;
639  if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
640  bEqual = false; // difference
641  pStyle = pNewStyle;
642  }
643  }
644 
645  return bEqual ? pStyle : nullptr;
646 }
647 
648 const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
649 {
650  rFound = false;
651 
652  bool bEqual = true;
653 
654  const ScStyleSheet* pStyle = nullptr;
655  const ScStyleSheet* pNewStyle;
656 
657  ScAttrIterator aAttrIter( pAttrArray.get(), nRow1, nRow2, GetDoc().GetDefPattern() );
658  SCROW nRow;
659  SCROW nDummy;
660  while (bEqual)
661  {
662  const ScPatternAttr* pPattern = aAttrIter.Next( nRow, nDummy );
663  if (!pPattern)
664  break;
665  pNewStyle = pPattern->GetStyleSheet();
666  rFound = true;
667  if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
668  bEqual = false; // difference
669  pStyle = pNewStyle;
670  }
671 
672  return bEqual ? pStyle : nullptr;
673 }
674 
675 void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
676 {
677  pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
678 }
679 
680 bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const
681 {
682  return pAttrArray->IsStyleSheetUsed( rStyle );
683 }
684 
685 bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags )
686 {
687  return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
688 }
689 
690 bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags )
691 {
692  return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
693 }
694 
695 void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
696 {
697  pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
698 }
699 
700 const ScPatternAttr* ScColumn::SetPattern( SCROW nRow, std::unique_ptr<ScPatternAttr> pPatAttr )
701 {
702  return pAttrArray->SetPattern( nRow, std::move(pPatAttr), true/*bPutToPool*/ );
703 }
704 
705 void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
706 {
707  pAttrArray->SetPattern( nRow, &rPatAttr, true/*bPutToPool*/ );
708 }
709 
710 void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
711  const ScPatternAttr& rPatAttr )
712 {
713  pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, true/*bPutToPool*/ );
714 }
715 
716 void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
717 {
718  // in order to only create a new SetItem, we don't need SfxItemPoolCache.
719  //TODO: Warning: SfxItemPoolCache seems to create too many Refs for the new SetItem ??
720 
721  ScDocumentPool* pDocPool = GetDoc().GetPool();
722 
723  const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
724  ScPatternAttr aTemp(*pOldPattern);
725  aTemp.GetItemSet().Put(rAttr);
726  const ScPatternAttr* pNewPattern = &pDocPool->Put( aTemp );
727 
728  if ( pNewPattern != pOldPattern )
729  pAttrArray->SetPattern( nRow, pNewPattern );
730  else
731  pDocPool->Remove( *pNewPattern ); // free up resources
732 }
733 
735 {
736  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
737  if (aPos.first == maCells.end())
738  return ScRefCellValue();
739 
740  return GetCellValue(aPos.first, aPos.second);
741 }
742 
744 {
745  std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow);
746  if (aPos.first == maCells.end())
747  return ScRefCellValue();
748 
749  rBlockPos.miCellPos = aPos.first; // Store this for next call.
750  return GetCellValue(aPos.first, aPos.second);
751 }
752 
754 {
755  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow);
756  if (aPos.first == maCells.end())
757  return ScRefCellValue();
758 
759  rBlockPos.miCellPos = aPos.first; // Store this for next call.
760  return GetCellValue(aPos.first, aPos.second);
761 }
762 
763 ScRefCellValue ScColumn::GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
764 {
765  ScRefCellValue aVal; // Defaults to empty cell.
766  switch (itPos->type)
767  {
769  // Numeric cell
770  aVal.mfValue = sc::numeric_block::at(*itPos->data, nOffset);
771  aVal.meType = CELLTYPE_VALUE;
772  break;
774  // String cell
775  aVal.mpString = &sc::string_block::at(*itPos->data, nOffset);
776  aVal.meType = CELLTYPE_STRING;
777  break;
779  // Edit cell
780  aVal.mpEditText = sc::edittext_block::at(*itPos->data, nOffset);
781  aVal.meType = CELLTYPE_EDIT;
782  break;
784  // Formula cell
785  aVal.mpFormula = sc::formula_block::at(*itPos->data, nOffset);
786  aVal.meType = CELLTYPE_FORMULA;
787  break;
788  default:
789  ;
790  }
791 
792  return aVal;
793 }
794 
796 {
798  aBlockPos.miCellTextAttrPos = maCellTextAttrs.begin();
799  return GetCellTextAttr(aBlockPos, nRow);
800 }
801 
803 {
804  sc::CellTextAttrStoreType::const_position_type aPos = maCellTextAttrs.position(rBlockPos.miCellTextAttrPos, nRow);
805  if (aPos.first == maCellTextAttrs.end())
806  return nullptr;
807 
808  rBlockPos.miCellTextAttrPos = aPos.first;
809 
810  if (aPos.first->type != sc::element_type_celltextattr)
811  return nullptr;
812 
813  return &sc::celltextattr_block::at(*aPos.first->data, aPos.second);
814 }
815 
816 bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
817 {
818  if (IsEmptyData() && IsEmptyAttr())
819  return true;
820 
821  // Return false if we have any non-empty cells between nStartRow and nEndRow inclusive.
822  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
823  sc::CellStoreType::const_iterator it = aPos.first;
824  if (it->type != sc::element_type_empty)
825  return false;
826 
827  // Get the length of the remaining empty segment.
828  size_t nLen = it->size - aPos.second;
829  SCROW nNextNonEmptyRow = nStartRow + nLen;
830  if (nNextNonEmptyRow <= nEndRow)
831  return false;
832 
833  // AttrArray only looks for merged cells
834 
835  return pAttrArray == nullptr || pAttrArray->TestInsertCol(nStartRow, nEndRow);
836 }
837 
838 bool ScColumn::TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const
839 {
840  // AttrArray only looks for merged cells
841  {
842  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
843  sc::CellStoreType::const_iterator it = aPos.first;
844  if (it->type == sc::element_type_empty && maCells.block_size() == 1)
845  // The entire cell array is empty.
846  return pAttrArray->TestInsertRow(nSize);
847  }
848 
849  // See if there would be any non-empty cell that gets pushed out.
850 
851  // Find the position of the last non-empty cell below nStartRow.
852  size_t nLastNonEmptyRow = GetDoc().MaxRow();
853  sc::CellStoreType::const_reverse_iterator it = maCells.rbegin();
854  if (it->type == sc::element_type_empty)
855  nLastNonEmptyRow -= it->size;
856 
857  if (nLastNonEmptyRow < o3tl::make_unsigned(nStartRow))
858  // No cells would get pushed out.
859  return pAttrArray->TestInsertRow(nSize);
860 
861  if (nLastNonEmptyRow + nSize > o3tl::make_unsigned(GetDoc().MaxRow()))
862  // At least one cell would get pushed out. Not good.
863  return false;
864 
865  return pAttrArray->TestInsertRow(nSize);
866 }
867 
868 void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
869 {
870  pAttrArray->InsertRow( nStartRow, nSize );
871 
872  maCellNotes.insert_empty(nStartRow, nSize);
873  maCellNotes.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
874 
875  maBroadcasters.insert_empty(nStartRow, nSize);
876  maBroadcasters.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
877 
878  maCellTextAttrs.insert_empty(nStartRow, nSize);
879  maCellTextAttrs.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
880 
881  maCells.insert_empty(nStartRow, nSize);
882  maCells.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
883 
885 
886  // We *probably* don't need to broadcast here since the parent call seems
887  // to take care of it.
888 }
889 
890 namespace {
891 
892 class CopyToClipHandler
893 {
894  const ScDocument& mrSrcDoc;
895  const ScColumn& mrSrcCol;
896  ScColumn& mrDestCol;
897  sc::ColumnBlockPosition maDestPos;
898  sc::ColumnBlockPosition* mpDestPos;
899 
900  void setDefaultAttrsToDest(size_t nRow, size_t nSize)
901  {
902  std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
903  maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
904  maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
905  }
906 
907 public:
908  CopyToClipHandler(const ScDocument& rSrcDoc, const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos) :
909  mrSrcDoc(rSrcDoc), mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos)
910  {
911  if (mpDestPos)
912  maDestPos = *mpDestPos;
913  else
914  mrDestCol.InitBlockPosition(maDestPos);
915  }
916 
917  ~CopyToClipHandler()
918  {
919  if (mpDestPos)
920  *mpDestPos = maDestPos;
921  }
922 
923  void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
924  {
925  size_t nTopRow = aNode.position + nOffset;
926 
927  bool bSet = true;
928 
929  switch (aNode.type)
930  {
932  {
933  sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
934  std::advance(it, nOffset);
935  sc::numeric_block::const_iterator itEnd = it;
936  std::advance(itEnd, nDataSize);
937  maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
938  }
939  break;
941  {
942  sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
943  std::advance(it, nOffset);
944  sc::string_block::const_iterator itEnd = it;
945  std::advance(itEnd, nDataSize);
946  maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
947 
948  }
949  break;
951  {
952  sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
953  std::advance(it, nOffset);
954  sc::edittext_block::const_iterator itEnd = it;
955  std::advance(itEnd, nDataSize);
956 
957  std::vector<EditTextObject*> aCloned;
958  aCloned.reserve(nDataSize);
959  for (; it != itEnd; ++it)
960  aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()).release());
961 
962  maDestPos.miCellPos = mrDestCol.GetCellStore().set(
963  maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
964  }
965  break;
967  {
968  sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
969  std::advance(it, nOffset);
970  sc::formula_block::const_iterator itEnd = it;
971  std::advance(itEnd, nDataSize);
972 
973  std::vector<ScFormulaCell*> aCloned;
974  aCloned.reserve(nDataSize);
975  ScAddress aDestPos(mrDestCol.GetCol(), nTopRow, mrDestCol.GetTab());
976  for (; it != itEnd; ++it, aDestPos.IncRow())
977  {
978  const ScFormulaCell& rOld = **it;
979  if (rOld.GetDirty() && mrSrcCol.GetDoc().GetAutoCalc())
980  const_cast<ScFormulaCell&>(rOld).Interpret();
981 
982  aCloned.push_back(new ScFormulaCell(rOld, mrDestCol.GetDoc(), aDestPos));
983  }
984 
985  // Group the cloned formula cells.
986  if (!aCloned.empty())
987  sc::SharedFormulaUtil::groupFormulaCells(aCloned.begin(), aCloned.end());
988 
989  sc::CellStoreType& rDestCells = mrDestCol.GetCellStore();
990  maDestPos.miCellPos = rDestCells.set(
991  maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
992 
993  // Merge adjacent formula cell groups (if applicable).
994  sc::CellStoreType::position_type aPos =
995  rDestCells.position(maDestPos.miCellPos, nTopRow);
996  maDestPos.miCellPos = aPos.first;
998  size_t nLastRow = nTopRow + nDataSize;
999  if (nLastRow < o3tl::make_unsigned(mrSrcDoc.MaxRow()))
1000  {
1001  aPos = rDestCells.position(maDestPos.miCellPos, nLastRow+1);
1003  }
1004  }
1005  break;
1006  default:
1007  bSet = false;
1008  }
1009 
1010  if (bSet)
1011  setDefaultAttrsToDest(nTopRow, nDataSize);
1012 
1013  mrSrcCol.DuplicateNotes(nTopRow, nDataSize, mrDestCol, maDestPos, false);
1014  }
1015 };
1016 
1017 class CopyTextAttrToClipHandler
1018 {
1019  sc::CellTextAttrStoreType& mrDestAttrs;
1020  sc::CellTextAttrStoreType::iterator miPos;
1021 
1022 public:
1023  explicit CopyTextAttrToClipHandler( sc::CellTextAttrStoreType& rAttrs ) :
1024  mrDestAttrs(rAttrs), miPos(mrDestAttrs.begin()) {}
1025 
1026  void operator() ( const sc::CellTextAttrStoreType::value_type& aNode, size_t nOffset, size_t nDataSize )
1027  {
1028  if (aNode.type != sc::element_type_celltextattr)
1029  return;
1030 
1031  sc::celltextattr_block::const_iterator it = sc::celltextattr_block::begin(*aNode.data);
1032  std::advance(it, nOffset);
1033  sc::celltextattr_block::const_iterator itEnd = it;
1034  std::advance(itEnd, nDataSize);
1035 
1036  size_t nPos = aNode.position + nOffset;
1037  miPos = mrDestAttrs.set(miPos, nPos, it, itEnd);
1038  }
1039 };
1040 
1041 
1042 }
1043 
1045  sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const
1046 {
1047  pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
1049 
1050  {
1051  CopyToClipHandler aFunc(GetDoc(), *this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol));
1052  sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
1053  }
1054 
1055  {
1056  CopyTextAttrToClipHandler aFunc(rColumn.maCellTextAttrs);
1057  sc::ParseBlock(maCellTextAttrs.begin(), maCellTextAttrs, aFunc, nRow1, nRow2);
1058  }
1059 
1060  rColumn.CellStorageModified();
1061 }
1062 
1064  SCROW nRow1, SCROW nRow2, const SvNumberFormatterMergeMap& rMap, ScColumn& rDestCol )
1065 {
1066  if (nRow1 > nRow2)
1067  return;
1068 
1069  sc::ColumnBlockPosition aDestPos;
1070  CopyCellTextAttrsToDocument(nRow1, nRow2, rDestCol);
1071  CopyCellNotesToDocument(nRow1, nRow2, rDestCol);
1072 
1073  // First, clear the destination column for the specified row range.
1074  rDestCol.maCells.set_empty(nRow1, nRow2);
1075 
1076  aDestPos.miCellPos = rDestCol.maCells.begin();
1077 
1078  ScDocument& rDocument = GetDoc();
1079  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
1080  sc::CellStoreType::const_iterator it = aPos.first;
1081  size_t nOffset = aPos.second;
1082  size_t nDataSize = 0;
1083  size_t nCurRow = nRow1;
1084 
1085  for (; it != maCells.end() && nCurRow <= o3tl::make_unsigned(nRow2); ++it, nOffset = 0, nCurRow += nDataSize)
1086  {
1087  bool bLastBlock = false;
1088  nDataSize = it->size - nOffset;
1089  if (nCurRow + nDataSize - 1 > o3tl::make_unsigned(nRow2))
1090  {
1091  // Truncate the block to copy to clipboard.
1092  nDataSize = nRow2 - nCurRow + 1;
1093  bLastBlock = true;
1094  }
1095 
1096  switch (it->type)
1097  {
1099  {
1100  sc::numeric_block::const_iterator itData = sc::numeric_block::begin(*it->data);
1101  std::advance(itData, nOffset);
1102  sc::numeric_block::const_iterator itDataEnd = itData;
1103  std::advance(itDataEnd, nDataSize);
1104  aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
1105  }
1106  break;
1108  {
1109  sc::string_block::const_iterator itData = sc::string_block::begin(*it->data);
1110  std::advance(itData, nOffset);
1111  sc::string_block::const_iterator itDataEnd = itData;
1112  std::advance(itDataEnd, nDataSize);
1113  aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
1114  }
1115  break;
1117  {
1118  sc::edittext_block::const_iterator itData = sc::edittext_block::begin(*it->data);
1119  std::advance(itData, nOffset);
1120  sc::edittext_block::const_iterator itDataEnd = itData;
1121  std::advance(itDataEnd, nDataSize);
1122 
1123  // Convert to simple strings.
1124  std::vector<svl::SharedString> aConverted;
1125  aConverted.reserve(nDataSize);
1126  for (; itData != itDataEnd; ++itData)
1127  {
1128  const EditTextObject& rObj = **itData;
1129  svl::SharedString aSS = rDocument.GetSharedStringPool().intern(ScEditUtil::GetString(rObj, &rDocument));
1130  aConverted.push_back(aSS);
1131  }
1132  aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, aConverted.begin(), aConverted.end());
1133  }
1134  break;
1136  {
1137  sc::formula_block::const_iterator itData = sc::formula_block::begin(*it->data);
1138  std::advance(itData, nOffset);
1139  sc::formula_block::const_iterator itDataEnd = itData;
1140  std::advance(itDataEnd, nDataSize);
1141 
1142  // Interpret and convert to raw values.
1143  for (SCROW i = 0; itData != itDataEnd; ++itData, ++i)
1144  {
1145  SCROW nRow = nCurRow + i;
1146 
1147  ScFormulaCell& rFC = **itData;
1148  if (rFC.GetDirty() && rDocument.GetAutoCalc())
1149  rFC.Interpret();
1150 
1151  if (rFC.GetErrCode() != FormulaError::NONE)
1152  // Skip cells with error.
1153  continue;
1154 
1155  if (rFC.IsValue())
1156  aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, rFC.GetValue());
1157  else
1158  {
1159  svl::SharedString aSS = rFC.GetString();
1160  if (aSS.isValid())
1161  aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, aSS);
1162  }
1163  }
1164  }
1165  break;
1166  default:
1167  ;
1168  }
1169 
1170  if (bLastBlock)
1171  break;
1172  }
1173 
1174  // Don't forget to copy the number formats over. Charts may reference them.
1175  for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
1176  {
1177  sal_uInt32 nNumFmt = GetNumberFormat(rDocument.GetNonThreadedContext(), nRow);
1178  SvNumberFormatterMergeMap::const_iterator itNum = rMap.find(nNumFmt);
1179  if (itNum != rMap.end())
1180  nNumFmt = itNum->second;
1181 
1182  rDestCol.SetNumberFormat(nRow, nNumFmt);
1183  }
1184 
1185  rDestCol.CellStorageModified();
1186 }
1187 
1188 void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol )
1189 {
1190  ScDocument& rDocument = GetDoc();
1191  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nSrcRow);
1192  sc::CellStoreType::const_iterator it = aPos.first;
1193  bool bSet = true;
1194  switch (it->type)
1195  {
1197  rDestCol.maCells.set(nDestRow, sc::numeric_block::at(*it->data, aPos.second));
1198  break;
1200  rDestCol.maCells.set(nDestRow, sc::string_block::at(*it->data, aPos.second));
1201  break;
1203  {
1204  EditTextObject* p = sc::edittext_block::at(*it->data, aPos.second);
1205  if (&rDocument == &rDestCol.GetDoc())
1206  rDestCol.maCells.set(nDestRow, p->Clone().release());
1207  else
1208  rDestCol.maCells.set(nDestRow, ScEditUtil::Clone(*p, rDestCol.GetDoc()).release());
1209  }
1210  break;
1212  {
1213  ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
1214  if (p->GetDirty() && rDocument.GetAutoCalc())
1215  p->Interpret();
1216 
1217  ScAddress aDestPos = p->aPos;
1218  aDestPos.SetRow(nDestRow);
1219  ScFormulaCell* pNew = new ScFormulaCell(*p, rDestCol.GetDoc(), aDestPos);
1220  rDestCol.SetFormulaCell(nDestRow, pNew);
1221  }
1222  break;
1224  default:
1225  // empty
1226  rDestCol.maCells.set_empty(nDestRow, nDestRow);
1227  bSet = false;
1228  }
1229 
1230  if (bSet)
1231  {
1232  rDestCol.maCellTextAttrs.set(nDestRow, maCellTextAttrs.get<sc::CellTextAttr>(nSrcRow));
1233  ScPostIt* pNote = maCellNotes.get<ScPostIt*>(nSrcRow);
1234  if (pNote)
1235  {
1236  pNote = pNote->Clone(ScAddress(nCol, nSrcRow, nTab),
1237  rDestCol.GetDoc(),
1238  ScAddress(rDestCol.nCol, nDestRow, rDestCol.nTab),
1239  false).release();
1240  rDestCol.maCellNotes.set(nDestRow, pNote);
1241  pNote->UpdateCaptionPos(ScAddress(rDestCol.nCol, nDestRow, rDestCol.nTab));
1242  }
1243  else
1244  rDestCol.maCellNotes.set_empty(nDestRow, nDestRow);
1245  }
1246  else
1247  {
1248  rDestCol.maCellTextAttrs.set_empty(nDestRow, nDestRow);
1249  rDestCol.maCellNotes.set_empty(nDestRow, nDestRow);
1250  }
1251 
1252  rDestCol.CellStorageModified();
1253 }
1254 
1255 namespace {
1256 
1257 bool canCopyValue(const ScDocument& rDoc, const ScAddress& rPos, InsertDeleteFlags nFlags)
1258 {
1259  sal_uInt32 nNumIndex = rDoc.GetAttr(rPos, ATTR_VALUE_FORMAT)->GetValue();
1260  SvNumFormatType nType = rDoc.GetFormatTable()->GetType(nNumIndex);
1261  if ((nType == SvNumFormatType::DATE) || (nType == SvNumFormatType::TIME) || (nType == SvNumFormatType::DATETIME))
1263 
1265 }
1266 
1267 class CopyAsLinkHandler
1268 {
1269  const ScColumn& mrSrcCol;
1270  ScColumn& mrDestCol;
1271  sc::ColumnBlockPosition maDestPos;
1272  sc::ColumnBlockPosition* mpDestPos;
1273  InsertDeleteFlags mnCopyFlags;
1274 
1275  sc::StartListeningType meListenType;
1276 
1277  void setDefaultAttrToDest(size_t nRow)
1278  {
1279  maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1280  maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
1281  }
1282 
1283  void setDefaultAttrsToDest(size_t nRow, size_t nSize)
1284  {
1285  std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
1286  maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1287  maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
1288  }
1289 
1290  ScFormulaCell* createRefCell(size_t nRow)
1291  {
1292  ScSingleRefData aRef;
1293  aRef.InitAddress(ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab())); // Absolute reference.
1294  aRef.SetFlag3D(true);
1295 
1296  ScTokenArray aArr(mrDestCol.GetDoc());
1297  aArr.AddSingleReference(aRef);
1298  return new ScFormulaCell(mrDestCol.GetDoc(), ScAddress(mrDestCol.GetCol(), nRow, mrDestCol.GetTab()), aArr);
1299  }
1300 
1301  void createRefBlock(const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1302  {
1303  size_t nTopRow = aNode.position + nOffset;
1304 
1305  for (size_t i = 0; i < nDataSize; ++i)
1306  {
1307  SCROW nRow = nTopRow + i;
1308  mrDestCol.SetFormulaCell(maDestPos, nRow, createRefCell(nRow), meListenType);
1309  }
1310 
1311  setDefaultAttrsToDest(nTopRow, nDataSize);
1312  }
1313 
1314 public:
1315  CopyAsLinkHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, InsertDeleteFlags nCopyFlags) :
1316  mrSrcCol(rSrcCol),
1317  mrDestCol(rDestCol),
1318  mpDestPos(pDestPos),
1319  mnCopyFlags(nCopyFlags),
1320  meListenType(sc::SingleCellListening)
1321  {
1322  if (mpDestPos)
1323  maDestPos = *mpDestPos;
1324  }
1325 
1326  ~CopyAsLinkHandler()
1327  {
1328  if (mpDestPos)
1329  {
1330  // Similar to CopyByCloneHandler, don't copy a singular iterator.
1331  {
1332  sc::ColumnBlockPosition aTempBlock;
1333  mrDestCol.InitBlockPosition(aTempBlock);
1334  maDestPos.miBroadcasterPos = aTempBlock.miBroadcasterPos;
1335  }
1336 
1337  *mpDestPos = maDestPos;
1338  }
1339  }
1340 
1341  void setStartListening( bool b )
1342  {
1343  meListenType = b ? sc::SingleCellListening : sc::NoListening;
1344  }
1345 
1346  void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1347  {
1348  size_t nRow = aNode.position + nOffset;
1349 
1351  {
1352  bool bCloneCaption = (mnCopyFlags & InsertDeleteFlags::NOCAPTIONS) == InsertDeleteFlags::NONE;
1353  mrSrcCol.DuplicateNotes(nRow, nDataSize, mrDestCol, maDestPos, bCloneCaption);
1354  }
1355 
1356  switch (aNode.type)
1357  {
1359  {
1360  if ((mnCopyFlags & (InsertDeleteFlags::DATETIME|InsertDeleteFlags::VALUE)) == InsertDeleteFlags::NONE)
1361  return;
1362 
1363  sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
1364  std::advance(it, nOffset);
1365  sc::numeric_block::const_iterator itEnd = it;
1366  std::advance(itEnd, nDataSize);
1367 
1368  ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
1369  for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
1370  {
1371  if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
1372  continue;
1373 
1374  maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, createRefCell(nRow));
1375  setDefaultAttrToDest(nRow);
1376  }
1377  }
1378  break;
1381  {
1382  if (!(mnCopyFlags & InsertDeleteFlags::STRING))
1383  return;
1384 
1385  createRefBlock(aNode, nOffset, nDataSize);
1386  }
1387  break;
1389  {
1390  if (!(mnCopyFlags & InsertDeleteFlags::FORMULA))
1391  return;
1392 
1393  createRefBlock(aNode, nOffset, nDataSize);
1394  }
1395  break;
1396  default:
1397  ;
1398  }
1399  }
1400 };
1401 
1402 class CopyByCloneHandler
1403 {
1404  const ScColumn& mrSrcCol;
1405  ScColumn& mrDestCol;
1406  sc::ColumnBlockPosition maDestPos;
1407  sc::ColumnBlockPosition* mpDestPos;
1408  svl::SharedStringPool* mpSharedStringPool;
1409  InsertDeleteFlags mnCopyFlags;
1410 
1411  sc::StartListeningType meListenType;
1412  ScCloneFlags mnFormulaCellCloneFlags;
1413 
1414  void setDefaultAttrToDest(size_t nRow)
1415  {
1416  maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1417  maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
1418  }
1419 
1420  void setDefaultAttrsToDest(size_t nRow, size_t nSize)
1421  {
1422  std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
1423  maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
1424  maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
1425  }
1426 
1427  void cloneFormulaCell(size_t nRow, ScFormulaCell& rSrcCell)
1428  {
1429  ScAddress aDestPos(mrDestCol.GetCol(), nRow, mrDestCol.GetTab());
1430 
1431  bool bCloneValue = (mnCopyFlags & InsertDeleteFlags::VALUE) != InsertDeleteFlags::NONE;
1432  bool bCloneDateTime = (mnCopyFlags & InsertDeleteFlags::DATETIME) != InsertDeleteFlags::NONE;
1433  bool bCloneString = (mnCopyFlags & InsertDeleteFlags::STRING) != InsertDeleteFlags::NONE;
1434  bool bCloneSpecialBoolean = (mnCopyFlags & InsertDeleteFlags::SPECIAL_BOOLEAN) != InsertDeleteFlags::NONE;
1435  bool bCloneFormula = (mnCopyFlags & InsertDeleteFlags::FORMULA) != InsertDeleteFlags::NONE;
1436 
1437  bool bForceFormula = false;
1438 
1439  if (bCloneSpecialBoolean)
1440  {
1441  // See if the formula consists of =TRUE() or =FALSE().
1442  const ScTokenArray* pCode = rSrcCell.GetCode();
1443  if (pCode && pCode->GetLen() == 1)
1444  {
1445  const formula::FormulaToken* p = pCode->FirstToken();
1446  if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
1447  // This is a boolean formula.
1448  bForceFormula = true;
1449  }
1450  }
1451 
1452  if (bForceFormula || bCloneFormula)
1453  {
1454  // Clone as formula cell.
1455  ScFormulaCell* pCell = new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos, mnFormulaCellCloneFlags);
1456  pCell->SetDirtyVar();
1457  mrDestCol.SetFormulaCell(maDestPos, nRow, pCell, meListenType, rSrcCell.NeedsNumberFormat());
1458  setDefaultAttrToDest(nRow);
1459  return;
1460  }
1461 
1462  if (mrDestCol.GetDoc().IsUndo())
1463  return;
1464 
1465  if (bCloneValue)
1466  {
1467  FormulaError nErr = rSrcCell.GetErrCode();
1468  if (nErr != FormulaError::NONE)
1469  {
1470  // error codes are cloned with values
1471  ScFormulaCell* pErrCell = new ScFormulaCell(mrDestCol.GetDoc(), aDestPos);
1472  pErrCell->SetErrCode(nErr);
1473  mrDestCol.SetFormulaCell(maDestPos, nRow, pErrCell, meListenType);
1474  setDefaultAttrToDest(nRow);
1475  return;
1476  }
1477  }
1478 
1479  if (bCloneValue || bCloneDateTime)
1480  {
1481  if (rSrcCell.IsValue())
1482  {
1483  if (canCopyValue(mrSrcCol.GetDoc(), ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab()), mnCopyFlags))
1484  {
1485  maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1486  maDestPos.miCellPos, nRow, rSrcCell.GetValue());
1487  setDefaultAttrToDest(nRow);
1488  }
1489 
1490  return;
1491  }
1492  }
1493 
1494  if (!bCloneString)
1495  return;
1496 
1497  svl::SharedString aStr = rSrcCell.GetString();
1498  if (aStr.isEmpty())
1499  // Don't create empty string cells.
1500  return;
1501 
1502  if (rSrcCell.IsMultilineResult())
1503  {
1504  // Clone as an edit text object.
1505  EditEngine& rEngine = mrDestCol.GetDoc().GetEditEngine();
1506  rEngine.SetText(aStr.getString());
1507  maDestPos.miCellPos =
1508  mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rEngine.CreateTextObject().release());
1509  }
1510  else
1511  {
1512  maDestPos.miCellPos =
1513  mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aStr);
1514  }
1515 
1516  setDefaultAttrToDest(nRow);
1517  }
1518 
1519 public:
1520  CopyByCloneHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos,
1521  InsertDeleteFlags nCopyFlags, svl::SharedStringPool* pSharedStringPool, bool bGlobalNamesToLocal) :
1522  mrSrcCol(rSrcCol),
1523  mrDestCol(rDestCol),
1524  mpDestPos(pDestPos),
1525  mpSharedStringPool(pSharedStringPool),
1526  mnCopyFlags(nCopyFlags),
1527  meListenType(sc::SingleCellListening),
1528  mnFormulaCellCloneFlags(bGlobalNamesToLocal ? ScCloneFlags::NamesToLocal : ScCloneFlags::Default)
1529  {
1530  if (mpDestPos)
1531  maDestPos = *mpDestPos;
1532  }
1533 
1534  ~CopyByCloneHandler()
1535  {
1536  if (!mpDestPos)
1537  return;
1538 
1539  // If broadcasters were setup in the same column,
1540  // maDestPos.miBroadcasterPos doesn't match
1541  // mrDestCol.maBroadcasters because it is never passed anywhere.
1542  // Assign a corresponding iterator before copying all over.
1543  // Otherwise this may result in wrongly copying a singular
1544  // iterator.
1545 
1546  {
1547  /* XXX Using a temporary ColumnBlockPosition just for
1548  * initializing from ScColumn::maBroadcasters.begin() is ugly,
1549  * on the other hand we don't want to expose
1550  * ScColumn::maBroadcasters to the outer world and have a
1551  * getter. */
1552  sc::ColumnBlockPosition aTempBlock;
1553  mrDestCol.InitBlockPosition(aTempBlock);
1554  maDestPos.miBroadcasterPos = aTempBlock.miBroadcasterPos;
1555  }
1556 
1557  *mpDestPos = maDestPos;
1558  }
1559 
1560  void setStartListening( bool b )
1561  {
1562  meListenType = b ? sc::SingleCellListening : sc::NoListening;
1563  }
1564 
1565  void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
1566  {
1567  size_t nRow = aNode.position + nOffset;
1568 
1570  {
1571  bool bCloneCaption = (mnCopyFlags & InsertDeleteFlags::NOCAPTIONS) == InsertDeleteFlags::NONE;
1572  mrSrcCol.DuplicateNotes(nRow, nDataSize, mrDestCol, maDestPos, bCloneCaption);
1573  }
1574 
1575  switch (aNode.type)
1576  {
1578  {
1579  if ((mnCopyFlags & (InsertDeleteFlags::DATETIME|InsertDeleteFlags::VALUE)) == InsertDeleteFlags::NONE)
1580  return;
1581 
1582  sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
1583  std::advance(it, nOffset);
1584  sc::numeric_block::const_iterator itEnd = it;
1585  std::advance(itEnd, nDataSize);
1586 
1587  ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
1588  for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
1589  {
1590  if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
1591  continue;
1592 
1593  maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, *it);
1594  setDefaultAttrToDest(nRow);
1595  }
1596  }
1597  break;
1599  {
1600  if (!(mnCopyFlags & InsertDeleteFlags::STRING))
1601  return;
1602 
1603  sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
1604  std::advance(it, nOffset);
1605  sc::string_block::const_iterator itEnd = it;
1606  std::advance(itEnd, nDataSize);
1607 
1608  for (; it != itEnd; ++it, ++nRow)
1609  {
1610  const svl::SharedString& rStr = *it;
1611  if (rStr.isEmpty())
1612  {
1613  // String cell with empty value is used to special-case cell value removal.
1614  maDestPos.miCellPos = mrDestCol.GetCellStore().set_empty(
1615  maDestPos.miCellPos, nRow, nRow);
1616  maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set_empty(
1617  maDestPos.miCellTextAttrPos, nRow, nRow);
1618  }
1619  else
1620  {
1621  if (mpSharedStringPool)
1622  {
1623  // Re-intern the string if source is a different document.
1624  svl::SharedString aInterned = mpSharedStringPool->intern( rStr.getString());
1625  maDestPos.miCellPos =
1626  mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aInterned);
1627  }
1628  else
1629  {
1630  maDestPos.miCellPos =
1631  mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rStr);
1632  }
1633  setDefaultAttrToDest(nRow);
1634  }
1635  }
1636  }
1637  break;
1639  {
1640  if (!(mnCopyFlags & InsertDeleteFlags::STRING))
1641  return;
1642 
1643  sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
1644  std::advance(it, nOffset);
1645  sc::edittext_block::const_iterator itEnd = it;
1646  std::advance(itEnd, nDataSize);
1647 
1648  std::vector<EditTextObject*> aCloned;
1649  aCloned.reserve(nDataSize);
1650  for (; it != itEnd; ++it)
1651  aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()).release());
1652 
1653  maDestPos.miCellPos = mrDestCol.GetCellStore().set(
1654  maDestPos.miCellPos, nRow, aCloned.begin(), aCloned.end());
1655 
1656  setDefaultAttrsToDest(nRow, nDataSize);
1657  }
1658  break;
1660  {
1661  sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
1662  std::advance(it, nOffset);
1663  sc::formula_block::const_iterator itEnd = it;
1664  std::advance(itEnd, nDataSize);
1665 
1666  sc::DelayStartListeningFormulaCells startDelay(mrDestCol); // disabled
1667  if(nDataSize > 1024 && (mnCopyFlags & InsertDeleteFlags::FORMULA) != InsertDeleteFlags::NONE)
1668  {
1669  // If the column to be replaced contains a long formula group (tdf#102364), there can
1670  // be so many listeners in a single vector that the quadratic cost of repeatedly removing
1671  // the first element becomes very high. Optimize this by removing them in one go.
1672  sc::EndListeningContext context(mrDestCol.GetDoc());
1673  mrDestCol.EndListeningFormulaCells( context, nRow, nRow + nDataSize - 1, nullptr, nullptr );
1674  // There can be a similar problem with starting to listen to cells repeatedly (tdf#133302).
1675  // Delay it.
1676  startDelay.set();
1677  }
1678 
1679  for (; it != itEnd; ++it, ++nRow)
1680  cloneFormulaCell(nRow, **it);
1681  }
1682  break;
1683  default:
1684  ;
1685  }
1686  }
1687 };
1688 
1689 }
1690 
1692  sc::CopyToDocContext& rCxt,
1693  SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScColumn& rColumn,
1694  const ScMarkData* pMarkData, bool bAsLink, bool bGlobalNamesToLocal) const
1695 {
1696  if (bMarked)
1697  {
1698  SCROW nStart, nEnd;
1699  if (pMarkData && pMarkData->IsMultiMarked())
1700  {
1701  ScMultiSelIter aIter( pMarkData->GetMultiSelData(), nCol );
1702 
1703  while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
1704  {
1705  if ( nEnd >= nRow1 )
1706  CopyToColumn(rCxt, std::max(nRow1,nStart), std::min(nRow2,nEnd),
1707  nFlags, false, rColumn, pMarkData, bAsLink );
1708  }
1709  }
1710  else
1711  {
1712  OSL_FAIL("CopyToColumn: bMarked, but no mark");
1713  }
1714  return;
1715  }
1716 
1718  {
1719  if ( (nFlags & InsertDeleteFlags::STYLES) != InsertDeleteFlags::STYLES )
1720  { // keep the StyleSheets in the target document
1721  // e.g. DIF and RTF Clipboard-Import
1722  for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
1723  {
1724  const ScStyleSheet* pStyle =
1725  rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
1726  const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
1727  std::unique_ptr<ScPatternAttr> pNewPattern(new ScPatternAttr( *pPattern ));
1728  pNewPattern->SetStyleSheet( const_cast<ScStyleSheet*>(pStyle) );
1729  rColumn.pAttrArray->SetPattern( nRow, std::move(pNewPattern), true );
1730  }
1731  }
1732  else
1733  pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
1734  }
1735 
1737  return;
1738 
1739  if (bAsLink)
1740  {
1741  CopyAsLinkHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
1742  aFunc.setStartListening(rCxt.isStartListening());
1743  sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
1744  }
1745  else
1746  {
1747  // Compare the ScDocumentPool* to determine if we are copying
1748  // within the same document. If not, re-intern shared strings.
1749  svl::SharedStringPool* pSharedStringPool =
1750  (GetDoc().GetPool() != rColumn.GetDoc().GetPool()) ?
1751  &rColumn.GetDoc().GetSharedStringPool() : nullptr;
1752  CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags,
1753  pSharedStringPool, bGlobalNamesToLocal);
1754  aFunc.setStartListening(rCxt.isStartListening());
1755  sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
1756  }
1757 
1758  rColumn.CellStorageModified();
1759 }
1760 
1762  sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked,
1763  ScColumn& rColumn ) const
1764 {
1765  if (nRow1 > 0)
1766  CopyToColumn(rCxt, 0, nRow1-1, InsertDeleteFlags::FORMULA, false, rColumn);
1767 
1768  CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, rColumn); //TODO: bMarked ????
1769 
1770  if (nRow2 < GetDoc().MaxRow())
1771  CopyToColumn(rCxt, nRow2+1, GetDoc().MaxRow(), InsertDeleteFlags::FORMULA, false, rColumn);
1772 }
1773 
1774 void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
1775 {
1776  // Copy cells from this column to the destination column only for those
1777  // rows that are present in the position column (rPosCol).
1778 
1779  // First, mark all the non-empty cell ranges from the position column.
1780  sc::SingleColumnSpanSet aRangeSet(GetDoc().GetSheetLimits());
1781  aRangeSet.scan(rPosCol);
1782 
1783  // Now, copy cells from this column to the destination column for those
1784  // marked row ranges.
1786  aRangeSet.getSpans(aRanges);
1787 
1788  CopyToClipHandler aFunc(GetDoc(), *this, rDestCol, nullptr);
1789  sc::CellStoreType::const_iterator itPos = maCells.begin();
1790  for (const auto& rRange : aRanges)
1791  itPos = sc::ParseBlock(itPos, maCells, aFunc, rRange.mnRow1, rRange.mnRow2);
1792 
1793  rDestCol.CellStorageModified();
1794 }
1795 
1796 void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
1797 {
1798  // This is the scenario table, the data is copied into it
1799  ScDocument& rDocument = GetDoc();
1800  ScAttrIterator aAttrIter( pAttrArray.get(), 0, GetDoc().MaxRow(), rDocument.GetDefPattern() );
1801  SCROW nStart = -1, nEnd = -1;
1802  const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1803  while (pPattern)
1804  {
1805  if ( pPattern->GetItem( ATTR_MERGE_FLAG ).IsScenario() )
1806  {
1807  DeleteArea( nStart, nEnd, InsertDeleteFlags::CONTENTS );
1808  sc::CopyToDocContext aCxt(rDocument);
1809  rSrcCol.
1810  CopyToColumn(aCxt, nStart, nEnd, InsertDeleteFlags::CONTENTS, false, *this);
1811 
1812  // UpdateUsed not needed, already done in TestCopyScenario (obsolete comment ?)
1813 
1814  sc::RefUpdateContext aRefCxt(rDocument);
1815  aRefCxt.meMode = URM_COPY;
1816  aRefCxt.maRange = ScRange(nCol, nStart, nTab, nCol, nEnd, nTab);
1817  aRefCxt.mnTabDelta = nTab - rSrcCol.nTab;
1818  UpdateReferenceOnCopy(aRefCxt);
1819  UpdateCompile();
1820  }
1821  pPattern = aAttrIter.Next( nStart, nEnd );
1822  }
1823 }
1824 
1825 void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
1826 {
1827  // This is the scenario table, the data is copied to the other
1828  ScDocument& rDocument = GetDoc();
1829  ScAttrIterator aAttrIter( pAttrArray.get(), 0, GetDoc().MaxRow(), rDocument.GetDefPattern() );
1830  SCROW nStart = -1, nEnd = -1;
1831  const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1832  while (pPattern)
1833  {
1834  if ( pPattern->GetItem( ATTR_MERGE_FLAG ).IsScenario() )
1835  {
1836  rDestCol.DeleteArea( nStart, nEnd, InsertDeleteFlags::CONTENTS );
1837  sc::CopyToDocContext aCxt(rDestCol.GetDoc());
1838  CopyToColumn(aCxt, nStart, nEnd, InsertDeleteFlags::CONTENTS, false, rDestCol);
1839 
1840  sc::RefUpdateContext aRefCxt(rDocument);
1841  aRefCxt.meMode = URM_COPY;
1842  aRefCxt.maRange = ScRange(rDestCol.nCol, nStart, rDestCol.nTab, rDestCol.nCol, nEnd, rDestCol.nTab);
1843  aRefCxt.mnTabDelta = rDestCol.nTab - nTab;
1844  rDestCol.UpdateReferenceOnCopy(aRefCxt);
1845  rDestCol.UpdateCompile();
1846  }
1847  pPattern = aAttrIter.Next( nStart, nEnd );
1848  }
1849 }
1850 
1851 bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
1852 {
1853  bool bOk = true;
1854  ScAttrIterator aAttrIter( pAttrArray.get(), 0, GetDoc().MaxRow(), GetDoc().GetDefPattern() );
1855  SCROW nStart = 0, nEnd = 0;
1856  const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1857  while (pPattern && bOk)
1858  {
1859  if ( pPattern->GetItem( ATTR_MERGE_FLAG ).IsScenario() )
1860  if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HasAttrFlags::Protected ) )
1861  bOk = false;
1862 
1863  pPattern = aAttrIter.Next( nStart, nEnd );
1864  }
1865  return bOk;
1866 }
1867 
1868 void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
1869 {
1870  ScRange aRange( nCol, 0, nTab );
1871 
1872  ScAttrIterator aAttrIter( pAttrArray.get(), 0, GetDoc().MaxRow(), GetDoc().GetDefPattern() );
1873  SCROW nStart = -1, nEnd = -1;
1874  const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
1875  while (pPattern)
1876  {
1877  if ( pPattern->GetItem( ATTR_MERGE_FLAG ).IsScenario() )
1878  {
1879  aRange.aStart.SetRow( nStart );
1880  aRange.aEnd.SetRow( nEnd );
1881  rDestMark.SetMultiMarkArea( aRange );
1882  }
1883 
1884  pPattern = aAttrIter.Next( nStart, nEnd );
1885  }
1886 }
1887 
1888 namespace {
1889 
1890 void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol)
1891 {
1892  for (auto& rCellItem : rCells)
1893  {
1894  if (rCellItem.type != sc::element_type_formula)
1895  continue;
1896 
1897  sc::formula_block::iterator itCell = sc::formula_block::begin(*rCellItem.data);
1898  sc::formula_block::iterator itCellEnd = sc::formula_block::end(*rCellItem.data);
1899  for (; itCell != itCellEnd; ++itCell)
1900  {
1901  ScFormulaCell& rCell = **itCell;
1902  rCell.aPos.SetCol(nCol);
1903  }
1904  }
1905 }
1906 
1907 class NoteCaptionUpdater
1908 {
1909  SCCOL mnCol;
1910  SCTAB mnTab;
1911 public:
1912  NoteCaptionUpdater( SCCOL nCol, SCTAB nTab ) : mnCol(nCol), mnTab(nTab) {}
1913 
1914  void operator() ( size_t nRow, ScPostIt* p )
1915  {
1916  p->UpdateCaptionPos(ScAddress(mnCol,nRow,mnTab));
1917  }
1918 };
1919 
1920 }
1921 
1923 {
1924  NoteCaptionUpdater aFunc(nCol, nTab);
1925  sc::ProcessNote(maCellNotes.begin(), maCellNotes, nRow1, nRow2, aFunc);
1926 }
1927 
1928 void ScColumn::UpdateDrawObjects(std::vector<std::vector<SdrObject*>>& pObjects, SCROW nRowStart, SCROW nRowEnd)
1929 {
1930  assert(static_cast<int>(pObjects.size()) >= nRowEnd - nRowStart + 1);
1931 
1932  int nObj = 0;
1933  for (SCROW nCurrentRow = nRowStart; nCurrentRow <= nRowEnd; nCurrentRow++, nObj++)
1934  {
1935  if (pObjects[nObj].empty())
1936  continue; // No draw objects in this row
1937 
1938  UpdateDrawObjectsForRow(pObjects[nObj], nCol, nCurrentRow);
1939  }
1940 }
1941 
1942 void ScColumn::UpdateDrawObjectsForRow( std::vector<SdrObject*>& pObjects, SCCOL nTargetCol, SCROW nTargetRow )
1943 {
1944  for (auto &pObject : pObjects)
1945  {
1946  ScAddress aNewAddress(nTargetCol, nTargetRow, nTab);
1947 
1948  // Update draw object according to new anchor
1949  ScDrawLayer* pDrawLayer = GetDoc().GetDrawLayer();
1950  if (pDrawLayer)
1951  pDrawLayer->MoveObject(pObject, aNewAddress);
1952  }
1953 }
1954 
1955 bool ScColumn::IsDrawObjectsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const
1956 {
1957  ScDrawLayer* pDrawLayer = GetDoc().GetDrawLayer();
1958  if (!pDrawLayer)
1959  return true;
1960 
1961  ScRange aRange(nCol, nStartRow, nTab, nCol, nEndRow, nTab);
1962  return !pDrawLayer->HasObjectsAnchoredInRange(aRange);
1963 }
1964 
1966 {
1967  maBroadcasters.swap(rCol.maBroadcasters);
1968  maCells.swap(rCol.maCells);
1969  maCellTextAttrs.swap(rCol.maCellTextAttrs);
1970  maCellNotes.swap(rCol.maCellNotes);
1971 
1972  // Swap all CellStoreEvent mdds event_func related.
1973  std::swap( mnBlkCountFormula, rCol.mnBlkCountFormula);
1974 
1975  // notes update caption
1976  UpdateNoteCaptions(0, GetDoc().MaxRow());
1977  rCol.UpdateNoteCaptions(0, GetDoc().MaxRow());
1978 
1979  std::swap(pAttrArray, rCol.pAttrArray);
1980 
1981  // AttrArray needs to have the right column number
1982  pAttrArray->SetCol(nCol);
1983  rCol.pAttrArray->SetCol(rCol.nCol);
1984 
1985  // Reset column positions in formula cells.
1986  resetColumnPosition(maCells, nCol);
1987  resetColumnPosition(rCol.maCells, rCol.nCol);
1988 
1990  rCol.CellStorageModified();
1991 }
1992 
1993 void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
1994 {
1995  pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
1996 
1997  // Mark the non-empty cells within the specified range, for later broadcasting.
1998  sc::SingleColumnSpanSet aNonEmpties(GetDoc().GetSheetLimits());
1999  aNonEmpties.scan(*this, nStartRow, nEndRow);
2001  aNonEmpties.getSpans(aRanges);
2002 
2003  // Split the formula grouping at the top and bottom boundaries.
2004  sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
2006  if (GetDoc().ValidRow(nEndRow+1))
2007  {
2008  aPos = maCells.position(aPos.first, nEndRow+1);
2010  }
2011 
2012  // Do the same with the destination column.
2013  aPos = rCol.maCells.position(nStartRow);
2015  if (GetDoc().ValidRow(nEndRow+1))
2016  {
2017  aPos = rCol.maCells.position(aPos.first, nEndRow+1);
2019  }
2020 
2021  // Move the broadcasters to the destination column.
2022  maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
2023  maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
2024  maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
2025 
2026  // move the notes to the destination column
2027  maCellNotes.transfer(nStartRow, nEndRow, rCol.maCellNotes, nStartRow);
2028  UpdateNoteCaptions(0, GetDoc().MaxRow());
2029 
2030  // Re-group transferred formula cells.
2031  aPos = rCol.maCells.position(nStartRow);
2033  if (GetDoc().ValidRow(nEndRow+1))
2034  {
2035  aPos = rCol.maCells.position(aPos.first, nEndRow+1);
2037  }
2038 
2040  rCol.CellStorageModified();
2041 
2042  // Broadcast on moved ranges. Area-broadcast only.
2043  ScDocument& rDocument = GetDoc();
2044  ScHint aHint(SfxHintId::ScDataChanged, ScAddress(nCol, 0, nTab));
2045  ScAddress& rPos = aHint.GetAddress();
2046  for (const auto& rRange : aRanges)
2047  {
2048  for (SCROW nRow = rRange.mnRow1; nRow <= rRange.mnRow2; ++nRow)
2049  {
2050  rPos.SetRow(nRow);
2051  rDocument.AreaBroadcast(aHint);
2052  }
2053  }
2054 }
2055 
2056 namespace {
2057 
2058 class SharedTopFormulaCellPicker
2059 {
2060 public:
2061  SharedTopFormulaCellPicker() = default;
2062  SharedTopFormulaCellPicker(SharedTopFormulaCellPicker const &) = default;
2063  SharedTopFormulaCellPicker(SharedTopFormulaCellPicker &&) = default;
2064  SharedTopFormulaCellPicker & operator =(SharedTopFormulaCellPicker const &) = default;
2065  SharedTopFormulaCellPicker & operator =(SharedTopFormulaCellPicker &&) = default;
2066 
2067  virtual ~SharedTopFormulaCellPicker() {}
2068 
2069  void operator() ( sc::CellStoreType::value_type& node )
2070  {
2071  if (node.type != sc::element_type_formula)
2072  return;
2073 
2074  size_t nTopRow = node.position;
2075 
2076  sc::formula_block::iterator itBeg = sc::formula_block::begin(*node.data);
2077  sc::formula_block::iterator itEnd = sc::formula_block::end(*node.data);
2078 
2079  // Only pick shared formula cells that are the top cells of their
2080  // respective shared ranges.
2081  for (sc::formula_block::iterator it = itBeg; it != itEnd; ++it)
2082  {
2083  ScFormulaCell* pCell = *it;
2084  size_t nRow = nTopRow + std::distance(itBeg, it);
2085  if (!pCell->IsShared())
2086  {
2087  processNonShared(pCell, nRow);
2088  continue;
2089  }
2090 
2091  if (pCell->IsSharedTop())
2092  {
2093  ScFormulaCell** pp = &(*it);
2094  processSharedTop(pp, nRow, pCell->GetSharedLength());
2095 
2096  // Move to the last cell in the group, to get incremented to
2097  // the next cell in the next iteration.
2098  size_t nOffsetToLast = pCell->GetSharedLength() - 1;
2099  std::advance(it, nOffsetToLast);
2100  }
2101  }
2102  }
2103 
2104  virtual void processNonShared( ScFormulaCell* /*pCell*/, size_t /*nRow*/ ) {}
2105  virtual void processSharedTop( ScFormulaCell** /*ppCells*/, size_t /*nRow*/, size_t /*nLength*/ ) {}
2106 };
2107 
2108 class UpdateRefOnCopy
2109 {
2110  const sc::RefUpdateContext& mrCxt;
2111  ScDocument* mpUndoDoc;
2112  bool mbUpdated;
2113 
2114 public:
2115  UpdateRefOnCopy(const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc) :
2116  mrCxt(rCxt), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
2117 
2118  bool isUpdated() const { return mbUpdated; }
2119 
2120  void operator() (sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
2121  {
2122  if (node.type != sc::element_type_formula)
2123  return;
2124 
2125  sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
2126  std::advance(it, nOffset);
2127  sc::formula_block::iterator itEnd = it;
2128  std::advance(itEnd, nDataSize);
2129 
2130  for (; it != itEnd; ++it)
2131  {
2132  ScFormulaCell& rCell = **it;
2133  mbUpdated |= rCell.UpdateReference(mrCxt, mpUndoDoc);
2134  }
2135  }
2136 };
2137 
2138 class UpdateRefOnNonCopy
2139 {
2140  SCCOL mnCol;
2141  SCROW mnTab;
2142  const sc::RefUpdateContext* mpCxt;
2143  ScDocument* mpUndoDoc;
2144  bool mbUpdated;
2145  bool mbClipboardSource;
2146 
2147  void recompileTokenArray( ScFormulaCell& rTopCell )
2148  {
2149  // We need to re-compile the token array when a range name is
2150  // modified, to correctly reflect the new references in the
2151  // name.
2152  ScCompiler aComp(mpCxt->mrDoc, rTopCell.aPos, *rTopCell.GetCode(), mpCxt->mrDoc.GetGrammar(),
2153  true, rTopCell.GetMatrixFlag() != ScMatrixMode::NONE);
2154  aComp.CompileTokenArray();
2155  }
2156 
2157  void updateRefOnShift( sc::FormulaGroupEntry& rGroup )
2158  {
2159  if (!rGroup.mbShared)
2160  {
2161  ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
2162  mbUpdated |= rGroup.mpCell->UpdateReferenceOnShift(*mpCxt, mpUndoDoc, &aUndoPos);
2163  return;
2164  }
2165 
2166  // Update references of a formula group.
2167  ScFormulaCell** pp = rGroup.mpCells;
2168  ScFormulaCell** ppEnd = pp + rGroup.mnLength;
2169  ScFormulaCell* pTop = *pp;
2170  ScTokenArray* pCode = pTop->GetCode();
2171  std::unique_ptr<ScTokenArray> pOldCode(pCode->Clone());
2172  ScAddress aOldPos = pTop->aPos;
2173 
2174  // Run this before the position gets updated.
2175  sc::RefUpdateResult aRes = pCode->AdjustReferenceOnShift(*mpCxt, aOldPos);
2176 
2177  bool bGroupShifted = false;
2178  if (pTop->UpdatePosOnShift(*mpCxt))
2179  {
2180  ScAddress aErrorPos( ScAddress::UNINITIALIZED );
2181  // Update the positions of all formula cells.
2182  for (++pp; pp != ppEnd; ++pp) // skip the top cell.
2183  {
2184  ScFormulaCell* pFC = *pp;
2185  if (!pFC->aPos.Move(mpCxt->mnColDelta, mpCxt->mnRowDelta, mpCxt->mnTabDelta, aErrorPos))
2186  {
2187  assert(!"can't move formula cell");
2188  }
2189  }
2190 
2191  if (pCode->IsRecalcModeOnRefMove())
2192  aRes.mbValueChanged = true;
2193 
2194  // FormulaGroupAreaListener (contrary to ScBroadcastArea) is not
2195  // updated but needs to be re-setup, else at least its mpColumn
2196  // would indicate the old column to collect cells from. tdf#129396
2197  /* TODO: investigate if that could be short-cut to avoid all the
2198  * EndListeningTo() / StartListeningTo() overhead and is really
2199  * only necessary when shifting the column, not also when shifting
2200  * rows. */
2201  bGroupShifted = true;
2202  }
2203  else if (aRes.mbReferenceModified && pCode->IsRecalcModeOnRefMove())
2204  {
2205  // The cell itself hasn't shifted. But it may have ROW or COLUMN
2206  // referencing another cell that has.
2207  aRes.mbValueChanged = true;
2208  }
2209 
2210  if (aRes.mbNameModified)
2211  recompileTokenArray(*pTop);
2212 
2213  if (aRes.mbReferenceModified || aRes.mbNameModified || bGroupShifted)
2214  {
2215  sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get());
2216  aEndCxt.setPositionDelta(
2217  ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
2218 
2219  for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
2220  {
2221  ScFormulaCell* p = *pp;
2222  p->EndListeningTo(aEndCxt);
2223  p->SetNeedsListening(true);
2224  }
2225 
2226  mbUpdated = true;
2227 
2228  fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
2229  }
2230 
2231  if (aRes.mbValueChanged)
2232  {
2233  for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
2234  {
2235  ScFormulaCell* p = *pp;
2236  p->SetNeedsDirty(true);
2237  }
2238  }
2239  }
2240 
2241  void updateRefOnMove( sc::FormulaGroupEntry& rGroup )
2242  {
2243  if (!rGroup.mbShared)
2244  {
2245  ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
2246  mbUpdated |= rGroup.mpCell->UpdateReferenceOnMove(*mpCxt, mpUndoDoc, &aUndoPos);
2247  return;
2248  }
2249 
2250  // Update references of a formula group.
2251  ScFormulaCell** pp = rGroup.mpCells;
2252  ScFormulaCell** ppEnd = pp + rGroup.mnLength;
2253  ScFormulaCell* pTop = *pp;
2254  ScTokenArray* pCode = pTop->GetCode();
2255  std::unique_ptr<ScTokenArray> pOldCode(pCode->Clone());
2256 
2257  ScAddress aPos = pTop->aPos;
2258  ScAddress aOldPos = aPos;
2259 
2260  bool bCellMoved;
2261  if (mpCxt->maRange.In(aPos))
2262  {
2263  bCellMoved = true;
2264 
2265  // The cell is being moved or copied to a new position. The
2266  // position has already been updated prior to this call.
2267  // Determine its original position before the move which will be
2268  // used to adjust relative references later.
2269 
2270  aOldPos.Set(
2271  aPos.Col() - mpCxt->mnColDelta,
2272  aPos.Row() - mpCxt->mnRowDelta,
2273  aPos.Tab() - mpCxt->mnTabDelta);
2274  }
2275  else
2276  {
2277  bCellMoved = false;
2278  }
2279 
2280  bool bRecalcOnMove = pCode->IsRecalcModeOnRefMove();
2281  if (bRecalcOnMove)
2282  bRecalcOnMove = aPos != aOldPos;
2283 
2284  sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(*mpCxt, aOldPos, aPos);
2285 
2286  if (!(aRes.mbReferenceModified || aRes.mbNameModified || bRecalcOnMove))
2287  return;
2288 
2289  sc::AutoCalcSwitch aACSwitch(mpCxt->mrDoc, false);
2290 
2291  if (aRes.mbNameModified)
2292  recompileTokenArray(*pTop);
2293 
2294  // Perform end-listening, start-listening, and dirtying on all
2295  // formula cells in the group.
2296 
2297  // Make sure that the start and end listening contexts share the
2298  // same block position set, else an invalid iterator may ensue.
2299  auto pPosSet = std::make_shared<sc::ColumnBlockPositionSet>(mpCxt->mrDoc);
2300 
2301  sc::StartListeningContext aStartCxt(mpCxt->mrDoc, pPosSet);
2302  sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pPosSet, pOldCode.get());
2303 
2304  aEndCxt.setPositionDelta(
2305  ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
2306 
2307  for (; pp != ppEnd; ++pp)
2308  {
2309  ScFormulaCell* p = *pp;
2310  p->EndListeningTo(aEndCxt);
2311  p->StartListeningTo(aStartCxt);
2312  p->SetDirty();
2313  }
2314 
2315  mbUpdated = true;
2316 
2317  // Move from clipboard is Cut&Paste, then do not copy the original
2318  // positions' formula cells to the Undo document.
2319  if (!mbClipboardSource || !bCellMoved)
2320  fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
2321  }
2322 
2323  void fillUndoDoc( const ScAddress& rOldPos, SCROW nLength, const ScTokenArray& rOldCode )
2324  {
2325  if (!mpUndoDoc || nLength <= 0)
2326  return;
2327 
2328  // Insert the old formula group into the undo document.
2329  ScAddress aUndoPos = rOldPos;
2330  ScFormulaCell* pFC = new ScFormulaCell(*mpUndoDoc, aUndoPos, rOldCode.Clone());
2331 
2332  if (nLength == 1)
2333  {
2334  mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
2335  return;
2336  }
2337 
2338  std::vector<ScFormulaCell*> aCells;
2339  aCells.reserve(nLength);
2340  ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false);
2341  aCells.push_back(pFC);
2342  aUndoPos.IncRow();
2343  for (SCROW i = 1; i < nLength; ++i, aUndoPos.IncRow())
2344  {
2345  pFC = new ScFormulaCell(*mpUndoDoc, aUndoPos, xGroup);
2346  aCells.push_back(pFC);
2347  }
2348 
2349  if (!mpUndoDoc->SetFormulaCells(rOldPos, aCells))
2350  // Insertion failed. Delete all formula cells.
2351  std::for_each(aCells.begin(), aCells.end(), std::default_delete<ScFormulaCell>());
2352  }
2353 
2354 public:
2355  UpdateRefOnNonCopy(
2356  SCCOL nCol, SCTAB nTab, const sc::RefUpdateContext* pCxt,
2357  ScDocument* pUndoDoc) :
2358  mnCol(nCol), mnTab(nTab), mpCxt(pCxt),
2359  mpUndoDoc(pUndoDoc), mbUpdated(false),
2360  mbClipboardSource(pCxt->mrDoc.IsClipboardSource()){}
2361 
2362  void operator() ( sc::FormulaGroupEntry& rGroup )
2363  {
2364  switch (mpCxt->meMode)
2365  {
2366  case URM_INSDEL:
2367  updateRefOnShift(rGroup);
2368  return;
2369  case URM_MOVE:
2370  updateRefOnMove(rGroup);
2371  return;
2372  default:
2373  ;
2374  }
2375 
2376  if (rGroup.mbShared)
2377  {
2378  ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
2379  ScFormulaCell** pp = rGroup.mpCells;
2380  ScFormulaCell** ppEnd = pp + rGroup.mnLength;
2381  for (; pp != ppEnd; ++pp, aUndoPos.IncRow())
2382  {
2383  ScFormulaCell* p = *pp;
2384  mbUpdated |= p->UpdateReference(*mpCxt, mpUndoDoc, &aUndoPos);
2385  }
2386  }
2387  else
2388  {
2389  ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
2390  mbUpdated |= rGroup.mpCell->UpdateReference(*mpCxt, mpUndoDoc, &aUndoPos);
2391  }
2392  }
2393 
2394  bool isUpdated() const { return mbUpdated; }
2395 };
2396 
2397 class UpdateRefGroupBoundChecker : public SharedTopFormulaCellPicker
2398 {
2399  const sc::RefUpdateContext& mrCxt;
2400  std::vector<SCROW>& mrBounds;
2401 
2402 public:
2403  UpdateRefGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
2404  mrCxt(rCxt), mrBounds(rBounds) {}
2405 
2406  virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ ) override
2407  {
2408  // Check its tokens and record its reference boundaries.
2409  ScFormulaCell& rCell = **ppCells;
2410  const ScTokenArray& rCode = *rCell.GetCode();
2412  mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
2413  }
2414 };
2415 
2416 class UpdateRefExpandGroupBoundChecker : public SharedTopFormulaCellPicker
2417 {
2418  const sc::RefUpdateContext& mrCxt;
2419  std::vector<SCROW>& mrBounds;
2420 
2421 public:
2422  UpdateRefExpandGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
2423  mrCxt(rCxt), mrBounds(rBounds) {}
2424 
2425  virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ ) override
2426  {
2427  // Check its tokens and record its reference boundaries.
2428  ScFormulaCell& rCell = **ppCells;
2429  const ScTokenArray& rCode = *rCell.GetCode();
2431  mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
2432  }
2433 };
2434 
2435 class FormulaGroupPicker : public SharedTopFormulaCellPicker
2436 {
2437  std::vector<sc::FormulaGroupEntry>& mrGroups;
2438 
2439 public:
2440  explicit FormulaGroupPicker( std::vector<sc::FormulaGroupEntry>& rGroups ) : mrGroups(rGroups) {}
2441 
2442  virtual void processNonShared( ScFormulaCell* pCell, size_t nRow ) override
2443  {
2444  mrGroups.emplace_back(pCell, nRow);
2445  }
2446 
2447  virtual void processSharedTop( ScFormulaCell** ppCells, size_t nRow, size_t nLength ) override
2448  {
2449  mrGroups.emplace_back(ppCells, nRow, nLength);
2450  }
2451 };
2452 
2453 }
2454 
2456 {
2457  // When copying, the range equals the destination range where cells
2458  // are pasted, and the dx, dy, dz refer to the distance from the
2459  // source range.
2460 
2461  UpdateRefOnCopy aHandler(rCxt, pUndoDoc);
2462  sc::ColumnBlockPosition* blockPos = rCxt.getBlockPosition(nTab, nCol);
2463  sc::CellStoreType::position_type aPos = blockPos
2464  ? maCells.position(blockPos->miCellPos, rCxt.maRange.aStart.Row())
2465  : maCells.position(rCxt.maRange.aStart.Row());
2466  sc::ProcessBlock(aPos.first, maCells, aHandler, rCxt.maRange.aStart.Row(), rCxt.maRange.aEnd.Row());
2467 
2468  // The formula groups at the top and bottom boundaries are expected to
2469  // have been split prior to this call. Here, we only do the joining.
2471  if (rCxt.maRange.aEnd.Row() < GetDoc().MaxRow())
2472  {
2473  aPos = maCells.position(aPos.first, rCxt.maRange.aEnd.Row()+1);
2475  }
2476 
2477  return aHandler.isUpdated();
2478 }
2479 
2481 {
2482  if (rCxt.meMode == URM_COPY)
2483  return UpdateReferenceOnCopy(rCxt, pUndoDoc);
2484 
2485  if (IsEmptyData() || GetDoc().IsClipOrUndo())
2486  // Cells in this column are all empty, or clip or undo doc. No update needed.
2487  return false;
2488 
2489  std::vector<SCROW> aBounds;
2490 
2491  bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() &&
2492  rCxt.maRange.aStart.Col() <= nCol && nCol <= rCxt.maRange.aEnd.Col());
2493  if (bThisColShifted)
2494  {
2495  // Cells in this column is being shifted. Split formula grouping at
2496  // the top and bottom boundaries before they get shifted.
2497  // Also, for deleted rows split at the top of the deleted area to adapt
2498  // the affected group length.
2499  SCROW nSplitPos;
2500  if (rCxt.mnRowDelta < 0)
2501  {
2502  nSplitPos = rCxt.maRange.aStart.Row() + rCxt.mnRowDelta;
2503  if (GetDoc().ValidRow(nSplitPos))
2504  aBounds.push_back(nSplitPos);
2505  }
2506  nSplitPos = rCxt.maRange.aStart.Row();
2507  if (GetDoc().ValidRow(nSplitPos))
2508  {
2509  aBounds.push_back(nSplitPos);
2510  nSplitPos = rCxt.maRange.aEnd.Row() + 1;
2511  if (GetDoc().ValidRow(nSplitPos))
2512  aBounds.push_back(nSplitPos);
2513  }
2514  }
2515 
2516  // Check the row positions at which the group must be split per relative
2517  // references.
2518  UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds);
2519  std::for_each(maCells.begin(), maCells.end(), aBoundChecker);
2520 
2521  // If expand reference edges is on, splitting groups may happen anywhere
2522  // where a reference points to an adjacent row of the insertion.
2523  if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs())
2524  {
2525  UpdateRefExpandGroupBoundChecker aExpandChecker(rCxt, aBounds);
2526  std::for_each(maCells.begin(), maCells.end(), aExpandChecker);
2527  }
2528 
2529  // Do the actual splitting.
2530  const bool bSplit = sc::SharedFormulaUtil::splitFormulaCellGroups(GetDoc(), maCells, aBounds);
2531 
2532  // Collect all formula groups.
2533  std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
2534 
2535  // Process all collected formula groups.
2536  UpdateRefOnNonCopy aHandler(nCol, nTab, &rCxt, pUndoDoc);
2537  aHandler = std::for_each(aGroups.begin(), aGroups.end(), aHandler);
2538  if (bSplit || aHandler.isUpdated())
2539  rCxt.maRegroupCols.set(nTab, nCol);
2540 
2541  return aHandler.isUpdated();
2542 }
2543 
2544 std::vector<sc::FormulaGroupEntry> ScColumn::GetFormulaGroupEntries()
2545 {
2546  std::vector<sc::FormulaGroupEntry> aGroups;
2547  std::for_each(maCells.begin(), maCells.end(), FormulaGroupPicker(aGroups));
2548  return aGroups;
2549 }
2550 
2551 namespace {
2552 
2553 class UpdateTransHandler
2554 {
2555  ScColumn& mrColumn;
2556  sc::CellStoreType::iterator miPos;
2557  ScRange maSource;
2558  ScAddress maDest;
2559  ScDocument* mpUndoDoc;
2560 public:
2561  UpdateTransHandler(ScColumn& rColumn, const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
2562  mrColumn(rColumn),
2563  miPos(rColumn.GetCellStore().begin()),
2564  maSource(rSource), maDest(rDest), mpUndoDoc(pUndoDoc) {}
2565 
2566  void operator() (size_t nRow, ScFormulaCell* pCell)
2567  {
2568  sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
2569  miPos = aPos.first;
2571  pCell->UpdateTranspose(maSource, maDest, mpUndoDoc);
2572  ScColumn::JoinNewFormulaCell(aPos, *pCell);
2573  }
2574 };
2575 
2576 class UpdateGrowHandler
2577 {
2578  ScColumn& mrColumn;
2579  sc::CellStoreType::iterator miPos;
2580  ScRange maArea;
2581  SCCOL mnGrowX;
2582  SCROW mnGrowY;
2583 public:
2584  UpdateGrowHandler(ScColumn& rColumn, const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
2585  mrColumn(rColumn),
2586  miPos(rColumn.GetCellStore().begin()),
2587  maArea(rArea), mnGrowX(nGrowX), mnGrowY(nGrowY) {}
2588 
2589  void operator() (size_t nRow, ScFormulaCell* pCell)
2590  {
2591  sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
2592  miPos = aPos.first;
2594  pCell->UpdateGrow(maArea, mnGrowX, mnGrowY);
2595  ScColumn::JoinNewFormulaCell(aPos, *pCell);
2596  }
2597 };
2598 
2599 class InsertTabUpdater
2600 {
2602  sc::CellTextAttrStoreType& mrTextAttrs;
2603  sc::CellTextAttrStoreType::iterator miAttrPos;
2604  SCTAB mnTab;
2605  bool mbModified;
2606 
2607 public:
2608  InsertTabUpdater(sc::RefUpdateInsertTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
2609  mrCxt(rCxt),
2610  mrTextAttrs(rTextAttrs),
2611  miAttrPos(rTextAttrs.begin()),
2612  mnTab(nTab),
2613  mbModified(false) {}
2614 
2615  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2616  {
2617  pCell->UpdateInsertTab(mrCxt);
2618  mbModified = true;
2619  }
2620 
2621  void operator() (size_t nRow, EditTextObject* pCell)
2622  {
2623  editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2624  aUpdater.updateTableFields(mnTab);
2625  miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2626  mbModified = true;
2627  }
2628 
2629  bool isModified() const { return mbModified; }
2630 };
2631 
2632 class DeleteTabUpdater
2633 {
2635  sc::CellTextAttrStoreType& mrTextAttrs;
2636  sc::CellTextAttrStoreType::iterator miAttrPos;
2637  SCTAB mnTab;
2638  bool mbModified;
2639 public:
2640  DeleteTabUpdater(sc::RefUpdateDeleteTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
2641  mrCxt(rCxt),
2642  mrTextAttrs(rTextAttrs),
2643  miAttrPos(rTextAttrs.begin()),
2644  mnTab(nTab),
2645  mbModified(false) {}
2646 
2647  void operator() (size_t, ScFormulaCell* pCell)
2648  {
2649  pCell->UpdateDeleteTab(mrCxt);
2650  mbModified = true;
2651  }
2652 
2653  void operator() (size_t nRow, EditTextObject* pCell)
2654  {
2655  editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2656  aUpdater.updateTableFields(mnTab);
2657  miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2658  mbModified = true;
2659  }
2660 
2661  bool isModified() const { return mbModified; }
2662 };
2663 
2664 class InsertAbsTabUpdater
2665 {
2666  sc::CellTextAttrStoreType& mrTextAttrs;
2667  sc::CellTextAttrStoreType::iterator miAttrPos;
2668  SCTAB mnTab;
2669  SCTAB mnNewPos;
2670  bool mbModified;
2671 public:
2672  InsertAbsTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nNewPos) :
2673  mrTextAttrs(rTextAttrs),
2674  miAttrPos(rTextAttrs.begin()),
2675  mnTab(nTab),
2676  mnNewPos(nNewPos),
2677  mbModified(false) {}
2678 
2679  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2680  {
2681  pCell->UpdateInsertTabAbs(mnNewPos);
2682  mbModified = true;
2683  }
2684 
2685  void operator() (size_t nRow, EditTextObject* pCell)
2686  {
2687  editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2688  aUpdater.updateTableFields(mnTab);
2689  miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2690  mbModified = true;
2691  }
2692 
2693  bool isModified() const { return mbModified; }
2694 };
2695 
2696 class MoveTabUpdater
2697 {
2699  sc::CellTextAttrStoreType& mrTextAttrs;
2700  sc::CellTextAttrStoreType::iterator miAttrPos;
2701  SCTAB mnTab;
2702  bool mbModified;
2703 public:
2704  MoveTabUpdater(sc::RefUpdateMoveTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
2705  mrCxt(rCxt),
2706  mrTextAttrs(rTextAttrs),
2707  miAttrPos(rTextAttrs.begin()),
2708  mnTab(nTab),
2709  mbModified(false) {}
2710 
2711  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2712  {
2713  pCell->UpdateMoveTab(mrCxt, mnTab);
2714  mbModified = true;
2715  }
2716 
2717  void operator() (size_t nRow, EditTextObject* pCell)
2718  {
2719  editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
2720  aUpdater.updateTableFields(mnTab);
2721  miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
2722  mbModified = true;
2723  }
2724 
2725  bool isModified() const { return mbModified; }
2726 };
2727 
2728 class UpdateCompileHandler
2729 {
2730  bool mbForceIfNameInUse:1;
2731 public:
2732  explicit UpdateCompileHandler(bool bForceIfNameInUse) :
2733  mbForceIfNameInUse(bForceIfNameInUse) {}
2734 
2735  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2736  {
2737  pCell->UpdateCompile(mbForceIfNameInUse);
2738  }
2739 };
2740 
2741 class TabNoSetter
2742 {
2743  SCTAB mnTab;
2744 public:
2745  explicit TabNoSetter(SCTAB nTab) : mnTab(nTab) {}
2746 
2747  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2748  {
2749  pCell->aPos.SetTab(mnTab);
2750  }
2751 };
2752 
2753 class UsedRangeNameFinder
2754 {
2755  sc::UpdatedRangeNames& mrIndexes;
2756 public:
2757  explicit UsedRangeNameFinder(sc::UpdatedRangeNames& rIndexes) : mrIndexes(rIndexes) {}
2758 
2759  void operator() (size_t /*nRow*/, const ScFormulaCell* pCell)
2760  {
2761  pCell->FindRangeNamesInUse(mrIndexes);
2762  }
2763 };
2764 
2765 class CheckVectorizationHandler
2766 {
2767 public:
2768  CheckVectorizationHandler()
2769  {}
2770 
2771  void operator() (size_t /*nRow*/, ScFormulaCell* p)
2772  {
2773  ScTokenArray* pCode = p->GetCode();
2774  if (pCode && pCode->IsFormulaVectorDisabled())
2775  {
2776  pCode->ResetVectorState();
2777  FormulaTokenArrayPlainIterator aIter(*pCode);
2778  FormulaToken* pFT = aIter.First();
2779  while (pFT)
2780  {
2781  pCode->CheckToken(*pFT);
2782  pFT = aIter.Next();
2783  }
2784  }
2785  }
2786 };
2787 
2788 struct SetDirtyVarHandler
2789 {
2790  void operator() (size_t /*nRow*/, ScFormulaCell* p)
2791  {
2792  p->SetDirtyVar();
2793  }
2794 };
2795 
2796 class SetDirtyHandler
2797 {
2798  ScDocument& mrDoc;
2799  const sc::SetFormulaDirtyContext& mrCxt;
2800 public:
2801  SetDirtyHandler( ScDocument& rDoc, const sc::SetFormulaDirtyContext& rCxt ) :
2802  mrDoc(rDoc), mrCxt(rCxt) {}
2803 
2804  void operator() (size_t /*nRow*/, ScFormulaCell* p)
2805  {
2806  if (mrCxt.mbClearTabDeletedFlag)
2807  {
2808  if (!p->IsShared() || p->IsSharedTop())
2809  {
2810  ScTokenArray* pCode = p->GetCode();
2811  pCode->ClearTabDeleted(
2812  p->aPos, mrCxt.mnTabDeletedStart, mrCxt.mnTabDeletedEnd);
2813  }
2814  }
2815 
2816  p->SetDirtyVar();
2817  if (!mrDoc.IsInFormulaTree(p))
2818  mrDoc.PutInFormulaTree(p);
2819  }
2820 };
2821 
2822 class SetDirtyOnRangeHandler
2823 {
2824  sc::SingleColumnSpanSet maValueRanges;
2825  ScColumn& mrColumn;
2826 public:
2827  explicit SetDirtyOnRangeHandler(ScColumn& rColumn)
2828  : maValueRanges(rColumn.GetDoc().GetSheetLimits()),
2829  mrColumn(rColumn) {}
2830 
2831  void operator() (size_t /*nRow*/, ScFormulaCell* p)
2832  {
2833  p->SetDirty();
2834  }
2835 
2836  void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
2837  {
2838  if (type == sc::element_type_empty)
2839  // Ignore empty blocks.
2840  return;
2841 
2842  // Non-formula cells.
2843  SCROW nRow1 = nTopRow;
2844  SCROW nRow2 = nTopRow + nDataSize - 1;
2845  maValueRanges.set(nRow1, nRow2, true);
2846  }
2847 
2848  void broadcast()
2849  {
2850  std::vector<SCROW> aRows;
2851  maValueRanges.getRows(aRows);
2852  mrColumn.BroadcastCells(aRows, SfxHintId::ScDataChanged);
2853  }
2854 
2855  void fillBroadcastSpans( sc::ColumnSpanSet& rBroadcastSpans ) const
2856  {
2857  SCCOL nCol = mrColumn.GetCol();
2858  SCTAB nTab = mrColumn.GetTab();
2860  maValueRanges.getSpans(aSpans);
2861 
2862  for (const auto& rSpan : aSpans)
2863  rBroadcastSpans.set(mrColumn.GetDoc(), nTab, nCol, rSpan.mnRow1, rSpan.mnRow2, true);
2864  }
2865 };
2866 
2867 class SetTableOpDirtyOnRangeHandler
2868 {
2869  sc::SingleColumnSpanSet maValueRanges;
2870  ScColumn& mrColumn;
2871 public:
2872  explicit SetTableOpDirtyOnRangeHandler(ScColumn& rColumn)
2873  : maValueRanges(rColumn.GetDoc().GetSheetLimits()),
2874  mrColumn(rColumn) {}
2875 
2876  void operator() (size_t /*nRow*/, ScFormulaCell* p)
2877  {
2878  p->SetTableOpDirty();
2879  }
2880 
2881  void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
2882  {
2883  if (type == sc::element_type_empty)
2884  // Ignore empty blocks.
2885  return;
2886 
2887  // Non-formula cells.
2888  SCROW nRow1 = nTopRow;
2889  SCROW nRow2 = nTopRow + nDataSize - 1;
2890  maValueRanges.set(nRow1, nRow2, true);
2891  }
2892 
2893  void broadcast()
2894  {
2895  std::vector<SCROW> aRows;
2896  maValueRanges.getRows(aRows);
2897  mrColumn.BroadcastCells(aRows, SfxHintId::ScTableOpDirty);
2898  }
2899 };
2900 
2901 struct SetDirtyAfterLoadHandler
2902 {
2903  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2904  {
2905 #if 1
2906  // Simply set dirty and append to FormulaTree, without broadcasting,
2907  // which is a magnitude faster. This is used to calculate the entire
2908  // document, e.g. when loading alien file formats.
2909  pCell->SetDirtyAfterLoad();
2910 #else
2911 /* This was used with the binary file format that stored results, where only
2912  * newly compiled and volatile functions and their dependents had to be
2913  * recalculated, which was faster then. Since that was moved to 'binfilter' to
2914  * convert to an XML file this isn't needed anymore, and not used for other
2915  * file formats. Kept for reference in case mechanism needs to be reactivated
2916  * for some file formats, we'd have to introduce a controlling parameter to
2917  * this method here then.
2918 */
2919 
2920  // If the cell was already dirty because of CalcAfterLoad,
2921  // FormulaTracking has to take place.
2922  if (pCell->GetDirty())
2923  pCell->SetDirty();
2924 #endif
2925  }
2926 };
2927 
2928 struct SetDirtyIfPostponedHandler
2929 {
2930  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2931  {
2933  pCell->SetDirty();
2934  }
2935 };
2936 
2937 struct CalcAllHandler
2938 {
2939 #define DEBUG_SC_CHECK_FORMULATREE_CALCULATION 0
2940  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2941  {
2942 #if DEBUG_SC_CHECK_FORMULATREE_CALCULATION
2943  // after F9 ctrl-F9: check the calculation for each FormulaTree
2944  double nOldVal, nNewVal;
2945  nOldVal = pCell->GetValue();
2946 #endif
2947  pCell->Interpret();
2948 #if DEBUG_SC_CHECK_FORMULATREE_CALCULATION
2949  if (pCell->GetCode()->IsRecalcModeNormal())
2950  nNewVal = pCell->GetValue();
2951  else
2952  nNewVal = nOldVal; // random(), jetzt() etc.
2953 
2954  assert(nOldVal == nNewVal);
2955 #endif
2956  }
2957 #undef DEBUG_SC_CHECK_FORMULATREE_CALCULATION
2958 };
2959 
2960 class CompileAllHandler
2961 {
2963 public:
2964  explicit CompileAllHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {}
2965 
2966  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
2967  {
2968  // for unconditional compilation
2969  // bCompile=true and pCode->nError=0
2970  pCell->GetCode()->SetCodeError(FormulaError::NONE);
2971  pCell->SetCompile(true);
2972  pCell->CompileTokenArray(mrCxt);
2973  }
2974 };
2975 
2976 class CompileXMLHandler
2977 {
2979  ScProgress& mrProgress;
2980  const ScColumn& mrCol;
2981 public:
2982  CompileXMLHandler( sc::CompileFormulaContext& rCxt, ScProgress& rProgress, const ScColumn& rCol) :
2983  mrCxt(rCxt),
2984  mrProgress(rProgress),
2985  mrCol(rCol) {}
2986 
2987  void operator() (size_t nRow, ScFormulaCell* pCell)
2988  {
2989  sal_uInt32 nFormat = mrCol.GetNumberFormat(mrCol.GetDoc().GetNonThreadedContext(), nRow);
2990  if( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
2991  // Non-default number format is set.
2992  pCell->SetNeedNumberFormat(false);
2993  else if (pCell->NeedsNumberFormat())
2994  pCell->SetDirtyVar();
2995 
2996  if (pCell->GetMatrixFlag() != ScMatrixMode::NONE)
2997  pCell->SetDirtyVar();
2998 
2999  pCell->CompileXML(mrCxt, mrProgress);
3000  }
3001 };
3002 
3003 class CompileErrorCellsHandler
3004 {
3006  ScColumn& mrColumn;
3007  sc::CellStoreType::iterator miPos;
3008  FormulaError mnErrCode;
3009  bool mbCompiled;
3010 public:
3011  CompileErrorCellsHandler( sc::CompileFormulaContext& rCxt, ScColumn& rColumn, FormulaError nErrCode ) :
3012  mrCxt(rCxt),
3013  mrColumn(rColumn),
3014  miPos(mrColumn.GetCellStore().begin()),
3015  mnErrCode(nErrCode),
3016  mbCompiled(false)
3017  {
3018  }
3019 
3020  void operator() (size_t nRow, ScFormulaCell* pCell)
3021  {
3022  FormulaError nCurError = pCell->GetRawError();
3023  if (nCurError == FormulaError::NONE)
3024  // It's not an error cell. Skip it.
3025  return;
3026 
3027  if (mnErrCode != FormulaError::NONE && nCurError != mnErrCode)
3028  // Error code is specified, and it doesn't match. Skip it.
3029  return;
3030 
3031  sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
3032  miPos = aPos.first;
3034  pCell->GetCode()->SetCodeError(FormulaError::NONE);
3035  OUString aFormula = pCell->GetFormula(mrCxt);
3036  pCell->Compile(mrCxt, aFormula);
3037  ScColumn::JoinNewFormulaCell(aPos, *pCell);
3038 
3039  mbCompiled = true;
3040  }
3041 
3042  bool isCompiled() const { return mbCompiled; }
3043 };
3044 
3045 class CalcAfterLoadHandler
3046 {
3048  bool mbStartListening;
3049 
3050 public:
3051  CalcAfterLoadHandler( sc::CompileFormulaContext& rCxt, bool bStartListening ) :
3052  mrCxt(rCxt), mbStartListening(bStartListening) {}
3053 
3054  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
3055  {
3056  pCell->CalcAfterLoad(mrCxt, mbStartListening);
3057  }
3058 };
3059 
3060 struct ResetChangedHandler
3061 {
3062  void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
3063  {
3064  pCell->SetChanged(false);
3065  }
3066 };
3067 
3071 class FindEditCellsHandler
3072 {
3073  ScColumn& mrColumn;
3074  sc::CellTextAttrStoreType::iterator miAttrPos;
3075  sc::CellStoreType::iterator miCellPos;
3076 
3077 public:
3078  explicit FindEditCellsHandler(ScColumn& rCol) :
3079  mrColumn(rCol),
3080  miAttrPos(rCol.GetCellAttrStore().begin()),
3081  miCellPos(rCol.GetCellStore().begin()) {}
3082 
3083  bool operator() (size_t, const EditTextObject*)
3084  {
3085  // This is definitely an edit text cell.
3086  return true;
3087  }
3088 
3089  bool operator() (size_t nRow, const ScFormulaCell* p)
3090  {
3091  // With a formula cell, it's considered an edit text cell when either
3092  // the result is multi-line or it has more than one script types.
3093  SvtScriptType nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos);
3094  if (IsAmbiguousScriptNonZero(nScriptType))
3095  return true;
3096 
3097  return const_cast<ScFormulaCell*>(p)->IsMultilineResult();
3098  }
3099 
3103  std::pair<size_t,bool> operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
3104  {
3105  typedef std::pair<size_t,bool> RetType;
3106 
3107  if (node.type == sc::element_type_empty)
3108  // Ignore empty blocks.
3109  return RetType(0, false);
3110 
3111  // Check the script type of a non-empty element and see if it has
3112  // multiple script types.
3113  for (size_t i = 0; i < nDataSize; ++i)
3114  {
3115  SCROW nRow = node.position + i + nOffset;
3116  SvtScriptType nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos);
3117  if (IsAmbiguousScriptNonZero(nScriptType))
3118  // Return the offset from the first row.
3119  return RetType(i+nOffset, true);
3120  }
3121 
3122  // No edit text cell found.
3123  return RetType(0, false);
3124  }
3125 };
3126 
3127 }
3128 
3129 void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
3130  ScDocument* pUndoDoc )
3131 {
3132  UpdateTransHandler aFunc(*this, rSource, rDest, pUndoDoc);
3133  sc::ProcessFormula(maCells, aFunc);
3134 }
3135 
3136 void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
3137 {
3138  UpdateGrowHandler aFunc(*this, rArea, nGrowX, nGrowY);
3139  sc::ProcessFormula(maCells, aFunc);
3140 }
3141 
3143 {
3144  if (nTab >= rCxt.mnInsertPos)
3145  {
3146  nTab += rCxt.mnSheets;
3147  pAttrArray->SetTab(nTab);
3148  }
3149 
3151 }
3152 
3154 {
3155  InsertTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
3157  if (aFunc.isModified())
3159 }
3160 
3162 {
3163  if (nTab > rCxt.mnDeletePos)
3164  {
3165  nTab -= rCxt.mnSheets;
3166  pAttrArray->SetTab(nTab);
3167  }
3168 
3169  DeleteTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
3171  if (aFunc.isModified())
3173 }
3174 
3176 {
3177  InsertAbsTabUpdater aFunc(maCellTextAttrs, nTab, nNewPos);
3179  if (aFunc.isModified())
3181 }
3182 
3184 {
3185  nTab = nTabNo;
3186  pAttrArray->SetTab( nTabNo );
3187 
3188  MoveTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
3190  if (aFunc.isModified())
3192 }
3193 
3194 void ScColumn::UpdateCompile( bool bForceIfNameInUse )
3195 {
3196  UpdateCompileHandler aFunc(bForceIfNameInUse);
3197  sc::ProcessFormula(maCells, aFunc);
3198 }
3199 
3201 {
3202  nTab = nNewTab;
3203  pAttrArray->SetTab( nNewTab );
3204 
3205  TabNoSetter aFunc(nTab);
3206  sc::ProcessFormula(maCells, aFunc);
3207 }
3208 
3210 {
3211  UsedRangeNameFinder aFunc(rIndexes);
3212  sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
3213 }
3214 
3216 {
3217  SetDirtyVarHandler aFunc;
3218  sc::ProcessFormula(maCells, aFunc);
3219 }
3220 
3222 {
3223  if (!GetDoc().ValidRow(nRow))
3224  return false;
3225 
3226  std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
3227  sc::CellStoreType::const_iterator it = aPos.first;
3228  if (it->type != sc::element_type_formula)
3229  // This is not a formula cell block.
3230  return false;
3231 
3232  const ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
3233  return p->GetDirty();
3234 }
3235 
3237 {
3238  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3239  CheckVectorizationHandler aFunc;
3240  sc::ProcessFormula(maCells, aFunc);
3241 }
3242 
3244 {
3245  // is only done documentwide, no FormulaTracking
3246  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3247  SetDirtyHandler aFunc(GetDoc(), rCxt);
3248  sc::ProcessFormula(maCells, aFunc);
3249 }
3250 
3251 void ScColumn::SetDirtyFromClip( SCROW nRow1, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
3252 {
3253  // Set all formula cells in the range dirty, and pick up all non-formula
3254  // cells for later broadcasting. We don't broadcast here.
3255  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3256 
3257  SetDirtyOnRangeHandler aHdl(*this);
3258  sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
3259  aHdl.fillBroadcastSpans(rBroadcastSpans);
3260 }
3261 
3262 namespace {
3263 
3264 class BroadcastBroadcastersHandler
3265 {
3266  ScHint& mrHint;
3267  ScAddress& mrAddress;
3268  bool mbBroadcasted;
3269 
3270 public:
3271  explicit BroadcastBroadcastersHandler( ScHint& rHint )
3272  : mrHint(rHint)
3273  , mrAddress(mrHint.GetAddress())
3274  , mbBroadcasted(false)
3275  {
3276  }
3277 
3278  void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
3279  {
3280  mrAddress.SetRow(nRow);
3281  pBroadcaster->Broadcast(mrHint);
3282  mbBroadcasted = true;
3283  }
3284 
3285  bool wasBroadcasted() { return mbBroadcasted; }
3286 };
3287 
3288 }
3289 
3291 {
3292  rHint.GetAddress().SetCol(nCol);
3293  BroadcastBroadcastersHandler aBroadcasterHdl( rHint);
3294  sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aBroadcasterHdl);
3295  return aBroadcasterHdl.wasBroadcasted();
3296 }
3297 
3298 void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2, BroadcastMode eMode )
3299 {
3300  // broadcasts everything within the range, with FormulaTracking
3301  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3302 
3303  switch (eMode)
3304  {
3305  case BROADCAST_NONE:
3306  {
3307  // Handler only used with formula cells.
3308  SetDirtyOnRangeHandler aHdl(*this);
3309  sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl);
3310  }
3311  break;
3313  {
3314  // Handler used with both, formula and non-formula cells.
3315  SetDirtyOnRangeHandler aHdl(*this);
3316  sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
3317  aHdl.broadcast();
3318  }
3319  break;
3321  {
3322  // Handler only used with formula cells.
3323  SetDirtyOnRangeHandler aHdl(*this);
3324  sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl);
3325  // Broadcast all broadcasters in range.
3326  ScHint aHint( SfxHintId::ScDataChanged, ScAddress( nCol, nRow1, nTab));
3327  if (BroadcastBroadcasters( nRow1, nRow2, aHint))
3328  {
3329  // SetDirtyOnRangeHandler implicitly tracks notified
3330  // formulas via ScDocument::Broadcast(), which
3331  // BroadcastBroadcastersHandler doesn't, so explicitly
3332  // track them here.
3333  GetDoc().TrackFormulas();
3334  }
3335  }
3336  break;
3337  }
3338 }
3339 
3340 void ScColumn::SetTableOpDirty( const ScRange& rRange )
3341 {
3342  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3343 
3344  SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
3345  SetTableOpDirtyOnRangeHandler aHdl(*this);
3346  sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
3347  aHdl.broadcast();
3348 }
3349 
3351 {
3352  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3353  SetDirtyAfterLoadHandler aFunc;
3354  sc::ProcessFormula(maCells, aFunc);
3355 }
3356 
3357 namespace {
3358 
3359 class RecalcOnRefMoveCollector
3360 {
3361  std::vector<SCROW> maDirtyRows;
3362 public:
3363  void operator() (size_t nRow, ScFormulaCell* pCell)
3364  {
3365  if (pCell->GetDirty() && pCell->GetCode()->IsRecalcModeOnRefMove())
3366  maDirtyRows.push_back(nRow);
3367  }
3368 
3369  const std::vector<SCROW>& getDirtyRows() const
3370  {
3371  return maDirtyRows;
3372  }
3373 };
3374 
3375 }
3376 
3378 {
3379  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3380  SetDirtyIfPostponedHandler aFunc;
3381  sc::ProcessFormula(maCells, aFunc);
3382 }
3383 
3385 {
3386  sc::AutoCalcSwitch aSwitch(GetDoc(), false);
3387  RecalcOnRefMoveCollector aFunc;
3388  sc::ProcessFormula(maCells, aFunc);
3389  BroadcastCells(aFunc.getDirtyRows(), SfxHintId::ScDataChanged);
3390 }
3391 
3393 {
3394  CalcAllHandler aFunc;
3395  sc::ProcessFormula(maCells, aFunc);
3396 }
3397 
3399 {
3400  CompileAllHandler aFunc(rCxt);
3401  sc::ProcessFormula(maCells, aFunc);
3402 }
3403 
3405 {
3406  CompileXMLHandler aFunc(rCxt, rProgress, *this);
3407  sc::ProcessFormula(maCells, aFunc);
3409 }
3410 
3412 {
3413  CompileErrorCellsHandler aHdl(rCxt, *this, nErrCode);
3414  sc::ProcessFormula(maCells, aHdl);
3415  return aHdl.isCompiled();
3416 }
3417 
3418 void ScColumn::CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening )
3419 {
3420  CalcAfterLoadHandler aFunc(rCxt, bStartListening);
3421  sc::ProcessFormula(maCells, aFunc);
3422 }
3423 
3424 void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
3425 {
3426  ResetChangedHandler aFunc;
3427  sc::ProcessFormula(maCells.begin(), maCells, nStartRow, nEndRow, aFunc);
3428 }
3429 
3430 bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
3431 {
3432  // used in GetOptimalHeight - ambiguous script type counts as edit cell
3433 
3434  FindEditCellsHandler aFunc(*this);
3435  std::pair<sc::CellStoreType::const_iterator,size_t> aPos =
3436  sc::FindFormulaEditText(maCells, nStartRow, nEndRow, aFunc);
3437 
3438  if (aPos.first == maCells.end())
3439  return false;
3440 
3441  rFirst = aPos.first->position + aPos.second;
3442  return true;
3443 }
3444 
3446  SCROW nRow, const ScStyleSheet* pSearchStyle, bool bUp, bool bInSelection,
3447  const ScMarkData& rMark) const
3448 {
3449  if (bInSelection)
3450  {
3451  if (rMark.IsMultiMarked())
3452  {
3453  ScMarkArray aArray(rMark.GetMarkArray(nCol));
3454  return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, &aArray);
3455  }
3456  else
3457  return -1;
3458  }
3459  else
3460  return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp );
3461 }
3462 
3464  SCROW& rRow, SCROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp,
3465  bool bInSelection, const ScMarkData& rMark) const
3466 {
3467  if (bInSelection)
3468  {
3469  if (rMark.IsMultiMarked())
3470  {
3471  ScMarkArray aArray(rMark.GetMarkArray(nCol));
3472  return pAttrArray->SearchStyleRange(
3473  rRow, rEndRow, pSearchStyle, bUp, &aArray);
3474  }
3475  else
3476  return false;
3477  }
3478  else
3479  return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp );
3480 }
3481 
3482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sc::MatrixEdge GetBlockMatrixEdges(SCROW nRow1, SCROW nRow2, sc::MatrixEdge nMask, bool bNoMatrixAtAll) const
Definition: column.cxx:115
bool IsInFormulaTree(const ScFormulaCell *pCell) const
Definition: documen7.cxx:321
bool CompileErrorCells(sc::CompileFormulaContext &rCxt, FormulaError nErrCode)
Definition: column.cxx:3411
void CellStorageModified()
Called whenever the state of cell array gets modified i.e.
Definition: column2.cxx:1653
virtual editeng::FieldUpdater GetFieldUpdater()=0
Numeric values (and numeric results if InsertDeleteFlags::FORMULA is not set).
void ApplyStyle(SCROW nRow, const ScStyleSheet *rStyle)
Definition: column.cxx:561
void FreeAll()
Definition: column3.cxx:157
If set, global named expressions will be converted to sheet-local named expressions.
SCROW mnRowDelta
Amount and direction of movement in the row direction.
void UpdateNoteCaptions(SCROW nRow1, SCROW nRow2)
Definition: column.cxx:1922
Temporarily switch on/off auto calculation mode.
Definition: scopetools.hxx:26
CellTextAttrStoreType::const_iterator miCellTextAttrPos
::boost::intrusive_ptr< ScFormulaCellGroup > ScFormulaCellGroupRef
Definition: types.hxx:43
void setPositionDelta(const ScAddress &rDelta)
OUString getString() const
void SetDirty(SCROW nRow1, SCROW nRow2, BroadcastMode)
Definition: column.cxx:3298
CellStoreType::const_iterator miCellPos
ScAddress aStart
Definition: address.hxx:499
SharedString intern(const OUString &rStr)
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:566
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
void DeleteArea(SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast=true, sc::ColumnSpanSet *pBroadcastSpans=nullptr)
Definition: column3.cxx:989
void UpdateInsertTab(const sc::RefUpdateInsertTabContext &rCxt)
bool HasAttrib(SCROW nRow1, SCROW nRow2, HasAttrFlags nMask) const
Definition: column.cxx:304
std::unique_ptr< ScAttrArray > pAttrArray
Definition: column.hxx:131
ScDocument & GetDoc() const
Definition: column.hxx:184
void MergeSelectionPattern(ScMergePatternState &rState, const ScMarkData &rMark, bool bDeep) const
Definition: column.cxx:336
const ScPatternAttr * GetPattern(SCROW nRow) const
Definition: column.cxx:371
HasAttrFlags
Definition: global.hxx:193
const SfxPoolItem & GetAttr(SCROW nRow, sal_uInt16 nWhich) const
Definition: column.cxx:376
Sheet / outlining (grouping) information.
SCROW Row() const
Definition: address.hxx:261
ScCloneFlags
Definition: global.hxx:261
virtual void CheckToken(const formula::FormulaToken &r) override
Definition: token.cxx:1354
Single reference (one address) into the sheet.
Definition: refdata.hxx:29
void MarkScenarioIn(ScMarkData &rDestMark) const
Definition: column.cxx:1868
void UpdateInsertTabAbs(SCTAB nTable)
Hard cell attributes.
~ScColumn() COVERITY_NOEXCEPT_FALSE
Definition: column.cxx:95
CellTextAttrStoreType::iterator miCellTextAttrPos
const mdds::mtv::element_t element_type_celltextattr
Definition: mtvelements.hxx:45
broadcast only existing cell broadcasters => no AreaBroadcast of range!
Definition: column.hxx:176
void SetDirtyIfPostponed()
Definition: column.cxx:3377
bool IsRecalcModeOnRefMove() const
void CopyUpdated(const ScColumn &rPosCol, ScColumn &rDestCol) const
Definition: column.cxx:1774
void SetMultiMarkArea(const ScRange &rRange, bool bMark=true, bool bSetupMulti=false)
Definition: markdata.cxx:121
SC_DLLPUBLIC const ScFormulaCell * GetFormulaCell(const ScAddress &rPos) const
Definition: document.cxx:3754
void SetDirtyAfterLoad()
bool IsExpandRefs() const
Definition: document.hxx:2368
void GetFormula(OUString &rFormula, const formula::FormulaGrammar::Grammar=formula::FormulaGrammar::GRAM_DEFAULT, const ScInterpreterContext *pContext=nullptr) const
SCTAB nTab
Definition: column.hxx:136
ScTokenArray * GetCode()
bool GetDirty() const
bool mbValueChanged
When this flag is true, the result of the formula needs to be re-calculated either because it contain...
bool isStartListening() const
Context for reference update during shifting, moving or copying of cell ranges.
void CalcAfterLoad(sc::CompileFormulaContext &rCxt, bool bStartListening)
Definition: column.cxx:3418
void DuplicateNotes(SCROW nStartRow, size_t nDataSize, ScColumn &rDestCol, sc::ColumnBlockPosition &maDestBlockPos, bool bCloneCaption, SCROW nRowOffsetDest=0) const
Definition: column2.cxx:1956
void UpdateDeleteTab(const sc::RefUpdateDeleteTabContext &rCxt)
StoreT::const_iterator ParseBlock(const typename StoreT::const_iterator &itPos, const StoreT &rStore, Func &rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
Generic algorithm to parse blocks of multi_type_vector either partially or fully. ...
sal_Int64 n
void MergeBlockFrame(SvxBoxItem *pLineOuter, SvxBoxInfoItem *pLineInner, ScLineFlags &rFlags, SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight) const
Definition: column.cxx:358
bool IsUndo() const
Definition: document.hxx:1533
sal_Int32 mnCol
std::unordered_map< sal_uInt32, sal_uInt32 > SvNumberFormatterMergeMap
SvNumFormatType GetType(sal_uInt32 nFIndex) const
void UpdateDeleteTab(sc::RefUpdateDeleteTabContext &rCxt)
Definition: column.cxx:3161
void ResetChanged(SCROW nStartRow, SCROW nEndRow)
Definition: column.cxx:3424
Store position data for column array storage.
const SfxItemSet & GetItemSet() const
bool IsEmptyData() const
Definition: column2.cxx:1249
void CopyStaticToDocument(SCROW nRow1, SCROW nRow2, const SvNumberFormatterMergeMap &rMap, ScColumn &rDestCol)
Definition: column.cxx:1063
ScAddress aEnd
Definition: address.hxx:500
bool RemoveFlags(SCROW nStartRow, SCROW nEndRow, ScMF nFlags)
Definition: column.cxx:690
OpCode GetOpCode() const
void ApplyPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPatternAttr &rPatAttr, ScEditDataArray *pDataArray=nullptr, bool *const pIsChanged=nullptr)
Definition: column.cxx:517
bool ExtendMerge(SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow, SCCOL &rPaintCol, SCROW &rPaintRow, bool bRefresh)
Definition: column.cxx:329
void FindRangeNamesInUse(sc::UpdatedRangeNames &rIndexes) const
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
SC_DLLPUBLIC formula::FormulaGrammar::Grammar GetGrammar() const
Definition: document.hxx:984
void Remove(const SfxPoolItem &)
bool HasAttribSelection(const ScMarkData &rMark, HasAttrFlags nMask) const
Definition: column.cxx:309
SCROW GetMaxRowCount() const
Definition: sheetlimits.hxx:61
bool mbClearTabDeletedFlag
When true, go through all reference tokens and clears "sheet deleted" flag if its corresponding index...
void ChangeSelectionIndent(bool bIncrement, const ScMarkData &rMark)
Definition: column.cxx:451
mdds::multi_type_vector< CellFunc, CellStoreEvent > CellStoreType
EmbeddedObjectRef * pObject
void CompileAll(sc::CompileFormulaContext &rCxt)
Definition: column.cxx:3398
bool IsEmptyAttr() const
Definition: column2.cxx:1294
void ApplyBlockFrame(const SvxBoxItem &rLineOuter, const SvxBoxInfoItem *pLineInner, SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight)
Definition: column.cxx:365
RelNameRef HasRelNameReference() const
StoreT::iterator ProcessBlock(const typename StoreT::iterator &itPos, StoreT &rStore, Func &rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
Non-const variant of the above function.
void SetNeedsDirty(bool bVar)
bool BroadcastBroadcasters(SCROW nRow1, SCROW nRow2, ScHint &rHint)
Broadcast single broadcasters in range, without explicitly setting anything dirty, not doing area broadcasts.
Definition: column.cxx:3290
bool IsMultilineResult()
Determines whether or not the result string contains more than one paragraph.
const ScAddress & GetAddress() const
Definition: brdcst.hxx:30
void UpdateDrawObjectsForRow(std::vector< SdrObject * > &pObjects, SCCOL nTargetCol, SCROW nTargetRow)
Definition: column.cxx:1942
const SfxSetItem & ApplyTo(const SfxSetItem &rSetItem)
sc::RefUpdateResult AdjustReferenceOnMove(const sc::RefUpdateContext &rCxt, const ScAddress &rOldPos, const ScAddress &rNewPos)
Definition: token.cxx:3359
Internal use only (d&d undo): do not delete caption objects of cell notes.
bool UpdateReference(const sc::RefUpdateContext &rCxt, ScDocument *pUndoDoc=nullptr, const ScAddress *pUndoCellPos=nullptr)
void ApplySelectionStyle(const ScStyleSheet &rStyle, const ScMarkData &rMark)
Definition: column.cxx:574
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6087
void GetMarkArea(ScRange &rRange) const
Definition: markdata.cxx:111
static bool IsCompatible(SvNumFormatType eOldType, SvNumFormatType eNewType)
void ParseFormula(const CellStoreType &rStore, Func &rFunc)
Definition: mtvcellfunc.hxx:63
BroadcasterStoreType::iterator miBroadcasterPos
bool Next(SCROW &rTop, SCROW &rBottom)
Definition: markmulti.cxx:449
void CopyToColumn(sc::CopyToDocContext &rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScColumn &rColumn, const ScMarkData *pMarkData=nullptr, bool bAsLink=false, bool bGlobalNamesToLocal=false) const
Definition: column.cxx:1691
ScFormulaCell * SetFormulaCell(SCROW nRow, ScFormulaCell *pCell, sc::StartListeningType eListenType=sc::SingleCellListening, bool bInheritNumFormatIfNeeded=true)
Takes ownership of pCell.
Definition: column3.cxx:2315
void UpdateTranspose(const ScRange &rSource, const ScAddress &rDest, ScDocument *pUndoDoc)
Definition: column.cxx:3129
bool HasMarks(SCCOL nCol) const
Definition: markmulti.cxx:67
void SetDirtyVar()
Definition: column.cxx:3215
bool IsPostponedDirty() const
const mdds::mtv::element_t element_type_formula
Definition: mtvelements.hxx:49
void updateTableFields(int nTab)
void SetAllFormulasDirty(const sc::SetFormulaDirtyContext &rCxt)
Definition: column.cxx:3243
void ApplySelectionLineStyle(const ScMarkData &rMark, const ::editeng::SvxBorderLine *pLine, bool bColorOnly)
Definition: column.cxx:587
const EditTextObject * mpEditText
Definition: cellvalue.hxx:109
void CopyToClip(sc::CopyToClipContext &rCxt, SCROW nRow1, SCROW nRow2, ScColumn &rColumn) const
Definition: column.cxx:1044
Keep track of spans in a single column only.
void SetText(const OUString &rStr)
ScRefCellValue GetCellValue(SCROW nRow) const
Definition: column.cxx:734
enumrange< T >::Iterator begin(enumrange< T >)
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:872
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
void UpdateGrow(const ScRange &rArea, SCCOL nGrowX, SCROW nGrowY)
Definition: column.cxx:3136
Additional class containing cell annotation data.
Definition: postit.hxx:161
This is a rather odd datastructure.
Definition: markarr.hxx:43
void StartListeningTo(ScDocument &rDoc)
double GetValue()
bool IsMultiMarked() const
Definition: markdata.hxx:82
FormulaError GetErrCode()
TableContainer maTabs
Definition: document.hxx:375
void EndListeningFormulaCells(sc::EndListeningContext &rCxt, SCROW nRow1, SCROW nRow2, SCROW *pStartRow, SCROW *pEndRow)
Definition: column4.cxx:1510
void SetNumberFormat(SCROW nRow, sal_uInt32 nNumberFormat)
Definition: column2.cxx:3080
const ScStyleSheet * GetSelectionStyle(const ScMarkData &rMark, bool &rFound) const
Definition: column.cxx:609
sc::CellStoreType maCells
Definition: column.hxx:129
static bool splitFormulaCellGroup(const CellStoreType::position_type &aPos, sc::EndListeningContext *pCxt)
Split existing shared formula range at specified position.
void UpdateCompile(bool bForceIfNameInUse=false)
Definition: column.cxx:3194
Wrapper for ScDocument::EnableDelayStartListeningFormulaCells()
Definition: scopetools.hxx:84
bool SearchStyleRange(SCROW &rRow, SCROW &rEndRow, const ScStyleSheet *pSearchStyle, bool bUp, bool bInSelection, const ScMarkData &rMark) const
Definition: column.cxx:3463
ScColumn & operator=(const ScColumn &)=delete
void set(const ScDocument &rDoc, SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
void SetTableOpDirty()
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
SCTAB Tab() const
Definition: address.hxx:270
void SetRow(SCROW nRowP)
Definition: address.hxx:274
sc::MatrixEdge GetMatrixEdge(const ScDocument &rDoc, ScAddress &rOrgPos) const
sal_uInt32 GetNumberFormat(const ScInterpreterContext &rContext, SCROW nRow) const
Definition: column.cxx:422
ScAddress aPos
void CheckRelativeReferenceBounds(const sc::RefUpdateContext &rCxt, const ScAddress &rPos, SCROW nGroupLen, std::vector< SCROW > &rBounds) const
Definition: token.cxx:4728
void SetNeedNumberFormat(bool bVal)
void SetNeedsListening(bool bVar)
void SetCol(SCCOL nColP)
Definition: address.hxx:278
size_t mnBlkCountFormula
Definition: column.hxx:133
void SetDirty(bool bDirtyFlag=true)
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4745
void PutInFormulaTree(ScFormulaCell *pCell)
Definition: documen7.cxx:258
sal_uInt16 GetLen() const
Internal use only (copy from clip): do not delete existing cell contents when pasting notes...
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
Definition: patattr.hxx:70
void SetTabNo(SCTAB nNewTab)
Definition: column.cxx:3200
void SetDirtyFromClip(SCROW nRow1, SCROW nRow2, sc::ColumnSpanSet &rBroadcastSpans)
Definition: column.cxx:3251
bool UpdateReference(sc::RefUpdateContext &rCxt, ScDocument *pUndoDoc)
Update reference addresses in formula cell in response to mass cell movement.
Definition: column.cxx:2480
ColumnBlockPosition * getBlockPosition(SCTAB nTab, SCCOL nCol)
bool mbNameModified
When this flag is true, it indicates that the token array contains a range name that's been updated...
SCROW GetSharedLength() const
bool IsShared() const
static bool joinFormulaCellAbove(const CellStoreType::position_type &aPos)
Merge with an existing formula group (if any) located immediately above if the cell at specified posi...
void SetTab(SCTAB nTabP)
Definition: address.hxx:282
void InsertRow(SCROW nStartRow, SCSIZE nSize)
Definition: column.cxx:868
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1058
SCCOL nCol
Definition: column.hxx:135
void getSpans(SpansType &rSpans) const
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:441
SvtScriptType
bool IsStyleSheetUsed(const ScStyleSheet &rStyle) const
Definition: column.cxx:680
void InitBlockPosition(sc::ColumnBlockPosition &rBlockPos)
Definition: column3.cxx:1044
Keep track of all named expressions that have been updated during reference update.
void Broadcast(const SfxHint &rHint)
bool IsMarked() const
Definition: markdata.hxx:81
int i
void set(SCTAB nTab, SCCOL nCol)
Definition: columnset.cxx:15
void UndoToColumn(sc::CopyToDocContext &rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScColumn &rColumn) const
Definition: column.cxx:1761
bool NeedsNumberFormat() const
void UpdateCompile(bool bForceIfNameInUse)
bool isEmpty() const
UpdateRefMode meMode
update mode - insert/delete, copy, or move.
void ResetVectorState()
Definition: token.cxx:1799
void SetFlag3D(bool bVal)
Definition: refdata.hxx:89
const ScPatternAttr * GetMostUsedPattern(SCROW nStartRow, SCROW nEndRow) const
Definition: column.cxx:381
void Set(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: address.hxx:405
bool IsRecalcModeNormal() const
const svl::SharedString * mpString
Definition: cellvalue.hxx:108
void InitAddress(const ScAddress &rAdr)
InitAddress: InitFlags and set address.
Definition: refdata.cxx:27
sal_Int16 SCCOL
Definition: types.hxx:21
InsertDeleteFlags
Definition: global.hxx:158
void RegroupFormulaCells(std::vector< ScAddress > *pGroupPos=nullptr)
Regroup formula cells for the entire column.
Definition: column3.cxx:3571
sc::CellTextAttrStoreType maCellTextAttrs
Definition: column.hxx:118
std::unique_ptr< ScPostIt > Clone(const ScAddress &rOwnPos, ScDocument &rDestDoc, const ScAddress &rDestPos, bool bCloneCaption) const
Clones this note and its caption object, if specified.
Definition: postit.cxx:877
bool TestCopyScenarioTo(const ScColumn &rDestCol) const
Definition: column.cxx:1851
void CheckVectorizationState()
Definition: column.cxx:3236
SvNumberFormatter * GetFormatTable() const
bool HasSelectionMatrixFragment(const ScMarkData &rMark) const
Definition: column.cxx:196
void Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument &rDoc, bool bEmptyAttrArray)
Definition: column.cxx:100
const SvxPageUsage aArr[]
const ScStyleSheet * GetStyleSheet() const
Definition: patattr.hxx:126
const ScStyleSheet * GetStyle(SCROW nRow) const
Definition: column.cxx:604
const ScPatternAttr * SetPattern(SCROW nRow, std::unique_ptr< ScPatternAttr >)
Definition: column.cxx:700
void getRows(std::vector< SCROW > &rRows) const
StartListeningType
Definition: types.hxx:123
bool Interpret(SCROW nStartOffset=-1, SCROW nEndOffset=-1)
void UpdateInsertTab(sc::RefUpdateInsertTabContext &rCxt)
Definition: column.cxx:3142
static void JoinNewFormulaCell(const sc::CellStoreType::position_type &aPos, ScFormulaCell &rCell)
Definition: column3.cxx:277
std::unique_ptr< EditTextObject > CreateTextObject()
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
bool TestInsertRow(SCROW nStartRow, SCSIZE nSize) const
Definition: column.cxx:838
void UpdateDrawObjects(std::vector< std::vector< SdrObject * >> &pObjects, SCROW nRowStart, SCROW nRowEnd)
Definition: column.cxx:1928
const mdds::mtv::element_t element_type_empty
Definition: mtvelements.hxx:55
size_t size() const
Definition: rangelst.hxx:89
void set(SCROW nRow1, SCROW nRow2, bool bVal)
void IncRow(SCROW nDelta=1)
Definition: address.hxx:299
ScMarkArray GetMarkArray(SCCOL nCol) const
Definition: markdata.cxx:941
Structure that stores segments of boolean flags per column, and perform custom action on those segmen...
bool UpdatePosOnShift(const sc::RefUpdateContext &rCxt)
Shift the position of formula cell as part of reference update.
void Compile(const OUString &rFormula, bool bNoListening, const formula::FormulaGrammar::Grammar)
void MoveObject(SdrObject *pObj, const ScAddress &rNewPosition)
Definition: drwlayer.cxx:2552
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
SvNumFormatType
const mdds::mtv::element_t element_type_numeric
Mapped standard element types (for convenience).
Definition: mtvelements.hxx:54
void TrackFormulas(SfxHintId nHintId=SfxHintId::ScDataChanged)
Definition: documen7.cxx:527
bool IsSharedTop() const
void ProcessNote(CellNoteStoreType &rStore, Func &rFunc)
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1256
no relative reference from named expression
FormulaToken * FirstToken() const
void FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, sc::UpdatedRangeNames &rIndexes) const
Definition: column.cxx:3209
CellStoreType::iterator ProcessFormula(const CellStoreType::iterator &it, CellStoreType &rStore, SCROW nRow1, SCROW nRow2, std::function< void(size_t, ScFormulaCell *)> aFuncElem)
Process formula cells found within specified row range.
Definition: mtvcellfunc.cxx:12
bool In(const ScAddress &) const
is Address& in Range?
Definition: address.hxx:732
bool TestInsertCol(SCROW nStartRow, SCROW nEndRow) const
Definition: column.cxx:816
FormulaError GetRawError() const
void CheckExpandReferenceBounds(const sc::RefUpdateContext &rCxt, const ScAddress &rPos, SCROW nGroupLen, std::vector< SCROW > &rBounds) const
Definition: token.cxx:4799
bool UpdateReferenceOnCopy(sc::RefUpdateContext &rCxt, ScDocument *pUndoDoc=nullptr)
Definition: column.cxx:2455
ScRange maRange
Range of cells that are about to be moved for insert/delete/move modes.
void ApplyAttr(SCROW nRow, const SfxPoolItem &rAttr)
Definition: column.cxx:716
BroadcastMode
Broadcast mode for SetDirty(SCROW,SCROW,BroadcastMode).
Definition: column.hxx:172
const svl::SharedString & GetString()
FormulaError
SCCOL Col() const
Definition: address.hxx:266
void CopyScenarioTo(ScColumn &rDestCol) const
Definition: column.cxx:1825
CellStoreType::iterator miCellPos
ocFalse
void ClearItems(SCROW nStartRow, SCROW nEndRow, const sal_uInt16 *pWhich)
Definition: column.cxx:695
ScColumn(const ScColumn &)=delete
void ProcessFormulaEditText(CellStoreType &rStore, Func &rFunc)
void SetPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPatternAttr &)
Definition: column.cxx:710
void CopyCellNotesToDocument(SCROW nRow1, SCROW nRow2, ScColumn &rDestCol, bool bCloneCaption=true, SCROW nRowOffsetDest=0) const
Definition: column2.cxx:1934
SC_DLLPUBLIC bool Move(SCCOL nDeltaX, SCROW nDeltaY, SCTAB nDeltaZ, ScAddress &rErrorPos, const ScDocument *pDocument=nullptr)
Definition: address.cxx:2324
Internal use only (undo etc.): do not copy/delete caption objects of cell notes.
void UpdateTranspose(const ScRange &rSource, const ScAddress &rDest, ScDocument *pUndoDoc)
void UpdateGrow(const ScRange &rArea, SCCOL nGrowX, SCROW nGrowY)
bool ApplyFlags(SCROW nStartRow, SCROW nEndRow, ScMF nFlags)
Definition: column.cxx:685
CellType meType
Definition: cellvalue.hxx:105
void MergePatternArea(ScMergePatternState &rState, SCROW nRow1, SCROW nRow2, bool bDeep) const
Definition: column.cxx:353
static void unshareFormulaCell(const CellStoreType::position_type &aPos, ScFormulaCell &rCell)
Turn a shared formula cell into a non-shared one, and split it off from the adjacent formula cell gro...
ocTrue
constexpr TypedWhichId< ScMergeFlagAttr > ATTR_MERGE_FLAG(145)
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_Int32 SCROW
Definition: types.hxx:17
void UpdateInsertTabOnlyCells(sc::RefUpdateInsertTabContext &rCxt)
Definition: column.cxx:3153
void SetDirtyAfterLoad()
Definition: column.cxx:3350
sc::BroadcasterStoreType maBroadcasters
Definition: column.hxx:124
bool IsFormulaVectorDisabled() const
Definition: token.cxx:1806
SC_DLLPUBLIC ScFormulaCell * SetFormulaCell(const ScAddress &rPos, ScFormulaCell *pCell)
Set formula cell, and transfer its ownership to the document.
Definition: documen2.cxx:1086
ScMF
Definition: attrib.hxx:34
broadcast existing cells with position => does AreaBroadcast
Definition: column.hxx:175
sc::CellNoteStoreType maCellNotes
Definition: column.hxx:121
SCCOL GetCol() const
Definition: column.hxx:186
void SetTableOpDirty(const ScRange &)
Definition: column.cxx:3340
SvtScriptType GetRangeScriptType(sc::CellTextAttrStoreType::iterator &itPos, SCROW nRow1, SCROW nRow2, const sc::CellStoreType::iterator &itr)
Get combined script types of the specified range.
Definition: column2.cxx:2121
static void groupFormulaCells(const Iter &itBeg, const Iter &itEnd)
Group formula cells stored in the passed container.
SCTAB mnTabDelta
Amount and direction of movement in the sheet direction.
ScFormulaCell ** mpCells
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
sc::CellTextAttrStoreType & GetCellAttrStore()
Definition: column.hxx:190
void CopyCellTextAttrsToDocument(SCROW nRow1, SCROW nRow2, ScColumn &rDestCol) const
Definition: column2.cxx:1838
ScFormulaCell * mpCell
const mdds::mtv::element_t element_type_edittext
Definition: mtvelements.hxx:48
void DeleteSelection(InsertDeleteFlags nDelFlag, const ScMarkData &rMark, bool bBroadcast)
Definition: column.cxx:489
void MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn &rCol)
Definition: column.cxx:1993
void ClearSelectionItems(const sal_uInt16 *pWhich, const ScMarkData &rMark)
Definition: column.cxx:464
std::pair< CellStoreType::const_iterator, size_t > FindFormulaEditText(const CellStoreType &rStore, SCROW nRow1, SCROW nRow2, Func &rFunc)
Dates, times, datetime values.
void CompileTokenArray(bool bNoListening=false)
virtual std::unique_ptr< EditTextObject > Clone() const =0
void ApplyPattern(SCROW nRow, const ScPatternAttr &rPatAttr)
Definition: column.cxx:502
const T & Put(std::unique_ptr< T > xItem, sal_uInt16 nWhich=0)
static bool splitFormulaCellGroups(const ScDocument &rDoc, CellStoreType &rCells, std::vector< SCROW > &rBounds)
Split existing shared formula ranges at specified row positions.
void * p
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
void CopyScenarioFrom(const ScColumn &rSrcCol)
Definition: column.cxx:1796
std::vector< RowSpan > SpansType
ScFormulaCellGroupRef CreateCellGroup(SCROW nLen, bool bInvariant)
Turn a non-grouped cell into the top of a grouped cell.
std::vector< sc::FormulaGroupEntry > GetFormulaGroupEntries()
Get all non-grouped formula cells and formula cell groups in the whole column.
Definition: column.cxx:2544
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6082
void SetCompile(bool bVal)
SCROW SearchStyle(SCROW nRow, const ScStyleSheet *pSearchStyle, bool bUp, bool bInSelection, const ScMarkData &rMark) const
May return -1 if not found.
Definition: column.cxx:3445
void UpdateMoveTab(sc::RefUpdateMoveTabContext &rCxt, SCTAB nTabNo)
Definition: column.cxx:3183
bool mbReferenceModified
This flag indicates whether any reference in the token array has been modified.
void AddCondFormat(SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex)
Definition: column.cxx:551
void UpdateMoveTab(const sc::RefUpdateMoveTabContext &rCxt, SCTAB nTabNo)
bool IsDrawObjectsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const
Definition: column.cxx:1955
void scan(const ScColumn &rColumn)
Scan an entire column and tag all non-empty cell positions.
SCROW GetNextUnprotected(SCROW nRow, bool bUp) const
Including current, may return -1.
Definition: column.cxx:110
void SwapCol(ScColumn &rCol)
Definition: column.cxx:1965
void BroadcastCells(const std::vector< SCROW > &rRows, SfxHintId nHint)
Definition: column3.cxx:79
bool HasObjectsAnchoredInRange(const ScRange &rRange)
Definition: drwlayer.cxx:2504
void FindStyleSheet(const SfxStyleSheetBase *pStyleSheet, ScFlatBoolRowSegments &rUsedRows, bool bReset)
Definition: column.cxx:675
void ApplyStyleArea(SCROW nStartRow, SCROW nEndRow, const ScStyleSheet &rStyle)
Definition: column.cxx:569
static SC_DLLPUBLIC OUString GetString(const EditTextObject &rEditText, const ScDocument *pDoc)
Retrieves string with paragraphs delimited by new lines (' ').
Definition: editutil.cxx:113
ScInterpreterContext & GetNonThreadedContext() const
Definition: document.hxx:604
SCROW ApplySelectionCache(SfxItemPoolCache *pCache, const ScMarkData &rMark, ScEditDataArray *pDataArray, bool *const pIsChanged)
Definition: column.cxx:427
bool ValidRow(SCROW nRow, SCROW nMaxRow)
Definition: address.hxx:98
SCTAB GetTab() const
Definition: column.hxx:185
ScRangeList GetMarkedRanges() const
Definition: markdata.cxx:464
sc::RefUpdateResult AdjustReferenceOnShift(const sc::RefUpdateContext &rCxt, const ScAddress &rOldPos)
Adjust all references in response to shifting of cells during cell insertion and deletion.
Definition: token.cxx:3129
bool UpdateReferenceOnShift(const sc::RefUpdateContext &rCxt, ScDocument *pUndoDoc, const ScAddress *pUndoCellPos)
Update reference in response to cell insertion or deletion.
static std::unique_ptr< EditTextObject > Clone(const EditTextObject &rSrc, ScDocument &rDestDoc)
Definition: editutil.cxx:170
const ScMultiSel & GetMultiSelData() const
Definition: markdata.hxx:106
void CalcAll()
Definition: column.cxx:3392
void ApplyPatternIfNumberformatIncompatible(const ScRange &rRange, const ScPatternAttr &rPattern, SvNumFormatType nNewType)
Definition: column.cxx:525
bool IsFormulaDirty(SCROW nRow) const
Definition: column.cxx:3221
void SetCodeError(FormulaError n)
bool SetFormulaCells(const ScAddress &rPos, std::vector< ScFormulaCell * > &rCells)
Definition: documen2.cxx:1097
void RemoveCondFormat(SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex)
Definition: column.cxx:556
void BroadcastRecalcOnRefMove()
Definition: column.cxx:3384
const sc::CellTextAttr * GetCellTextAttr(SCROW nRow) const
Definition: column.cxx:795
const ScStyleSheet * GetAreaStyle(bool &rFound, SCROW nRow1, SCROW nRow2) const
Definition: column.cxx:648
bool isValid() const
MatrixEdge
Definition: types.hxx:65
SCCOL mnColDelta
Amount and direction of movement in the column direction.
ScMatrixMode GetMatrixFlag() const
void CopyCellToDocument(SCROW nSrcRow, SCROW nDestRow, ScColumn &rDestCol)
Definition: column.cxx:1188
void SetChanged(bool b)
void SetErrCode(FormulaError n)
const mdds::mtv::element_t element_type_string
Definition: mtvelements.hxx:47
void AreaBroadcast(const ScHint &rHint)
only area, no cell broadcast
Definition: documen7.cxx:190
mdds::multi_type_vector< CTAttrFunc > CellTextAttrStoreType
sc::CellStoreType & GetCellStore()
Definition: column.hxx:188
void EndListeningTo(ScDocument &rDoc, ScTokenArray *pArr=nullptr, ScAddress aPos=ScAddress())
void UpdateCaptionPos(const ScAddress &rPos)
Updates caption position according to position of the passed cell.
Definition: postit.cxx:1001
void CompileXML(sc::CompileFormulaContext &rCxt, ScProgress &rProgress)
aStr
bool UpdateReferenceOnMove(const sc::RefUpdateContext &rCxt, ScDocument *pUndoDoc, const ScAddress *pUndoCellPos)
Update reference in response to cell move.
void UpdateInsertTabAbs(SCTAB nNewPos)
Definition: column.cxx:3175
Strings (and string results if InsertDeleteFlags::FORMULA is not set).
std::unique_ptr< ScTokenArray > Clone() const
Definition: token.cxx:1930
SC_DLLPUBLIC ScFieldEditEngine & GetEditEngine()
Definition: documen2.cxx:457
bool HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW &rFirst)
Definition: column.cxx:3430
bool IsAllMarked(const ScRange &rRange) const
Definition: markdata.cxx:579
sal_uInt16 nPos
ColumnBlockPosition * getBlockPosition(SCTAB nTab, SCCOL nCol)
Definition: clipcontext.cxx:32
sal_Int16 SCTAB
Definition: types.hxx:22
dp table output
void CalcAfterLoad(sc::CompileFormulaContext &rCxt, bool bStartListening)
void ClearTabDeleted(const ScAddress &rPos, SCTAB nStartTab, SCTAB nEndTab)
Clear sheet deleted flag from internal reference tokens if the sheet index falls within specified ran...
Definition: token.cxx:4588
SC_DLLPUBLIC bool GetAutoCalc() const
Definition: document.hxx:1360
BroadcasterStoreType::iterator ProcessBroadcaster(const BroadcasterStoreType::iterator &it, BroadcasterStoreType &rStore, SCROW nRow1, SCROW nRow2, FuncElem &rFuncElem)
void CompileXML(sc::CompileFormulaContext &rCxt, ScProgress &rProgress)
Definition: column.cxx:3404
no broadcasting
Definition: column.hxx:174
bool isKeepScenarioFlags() const