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