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