xref: /core/sc/source/core/data/column3.cxx (revision a9753917)
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 
22 #include <scitems.hxx>
23 #include <formulacell.hxx>
24 #include <document.hxx>
25 #include <attarray.hxx>
26 #include <patattr.hxx>
27 #include <cellform.hxx>
28 #include <typedstrdata.hxx>
29 #include <formula/errorcodes.hxx>
30 #include <formula/token.hxx>
31 #include <brdcst.hxx>
32 #include <docoptio.hxx>
33 #include <subtotal.hxx>
34 #include <markdata.hxx>
35 #include <stringutil.hxx>
36 #include <docpool.hxx>
37 #include <cellvalue.hxx>
38 #include <tokenarray.hxx>
39 #include <clipcontext.hxx>
40 #include <columnspanset.hxx>
41 #include <mtvcellfunc.hxx>
42 #include <scopetools.hxx>
43 #include <editutil.hxx>
44 #include <sharedformula.hxx>
45 #include <listenercontext.hxx>
46 #include <filterentries.hxx>
47 
48 #include <com/sun/star/i18n/LocaleDataItem2.hpp>
49 #include <com/sun/star/lang/IllegalArgumentException.hpp>
50 
51 #include <memory>
52 
53 #include <rtl/tencinfo.h>
54 
55 #include <svl/zforlist.hxx>
56 #include <svl/zformat.hxx>
57 #include <svl/sharedstringpool.hxx>
58 
59 #include <cstdio>
60 #include <refdata.hxx>
61 
62 using ::com::sun::star::i18n::LocaleDataItem2;
63 
64 using namespace formula;
65 
66 void ScColumn::Broadcast( SCROW nRow )
67 {
68     ScHint aHint(SfxHintId::ScDataChanged, ScAddress(nCol, nRow, nTab));
69     GetDoc()->Broadcast(aHint);
70 }
71 
72 void ScColumn::BroadcastCells( const std::vector<SCROW>& rRows, SfxHintId nHint )
73 {
74     if (rRows.empty())
75         return;
76 
77     // Broadcast the changes.
78     ScDocument* pDocument = GetDoc();
79     ScHint aHint(nHint, ScAddress(nCol, 0, nTab));
80     for (const auto& rRow : rRows)
81     {
82         aHint.GetAddress().SetRow(rRow);
83         pDocument->Broadcast(aHint);
84     }
85 }
86 
87 void ScColumn::BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint )
88 {
89     sc::SingleColumnSpanSet aSpanSet;
90     aSpanSet.scan(*this, nStartRow, nEndRow);
91     std::vector<SCROW> aRows;
92     aSpanSet.getRows(aRows);
93     BroadcastCells(aRows, nHint);
94 }
95 
96 namespace {
97 
98 struct DirtyCellInterpreter
99 {
100     void operator() (size_t, ScFormulaCell* p)
101     {
102         if (p->GetDirty())
103             p->Interpret();
104     }
105 };
106 
107 }
108 
109 void ScColumn::InterpretDirtyCells( SCROW nRow1, SCROW nRow2 )
110 {
111     if (!GetDoc()->ValidRow(nRow1) || !GetDoc()->ValidRow(nRow2) || nRow1 > nRow2)
112         return;
113 
114     DirtyCellInterpreter aFunc;
115     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
116 }
117 
118 void ScColumn::DeleteContent( SCROW nRow, bool bBroadcast )
119 {
120     sc::CellStoreType::position_type aPos = maCells.position(nRow);
121     sc::CellStoreType::iterator it = aPos.first;
122     if (it == maCells.end())
123         return;
124 
125     if (it->type == sc::element_type_formula)
126     {
127         ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
128         p->EndListeningTo(GetDoc());
129         sc::SharedFormulaUtil::unshareFormulaCell(aPos, *p);
130     }
131     maCells.set_empty(nRow, nRow);
132 
133     if (bBroadcast)
134     {
135         Broadcast(nRow);
136         CellStorageModified();
137     }
138 }
139 
140 void ScColumn::Delete( SCROW nRow )
141 {
142     DeleteContent(nRow, false);
143     maCellTextAttrs.set_empty(nRow, nRow);
144     maCellNotes.set_empty(nRow, nRow);
145 
146     Broadcast(nRow);
147     CellStorageModified();
148 }
149 
150 void ScColumn::FreeAll()
151 {
152     // Keep a logical empty range of 0-rDoc.MaxRow() at all times.
153     maCells.clear();
154     maCells.resize(MAXROWCOUNT);
155     maCellTextAttrs.clear();
156     maCellTextAttrs.resize(MAXROWCOUNT);
157     maCellNotes.clear();
158     maCellNotes.resize(MAXROWCOUNT);
159     CellStorageModified();
160 }
161 
162 void ScColumn::FreeNotes()
163 {
164     maCellNotes.clear();
165     maCellNotes.resize(MAXROWCOUNT);
166 }
167 
168 namespace {
169 
170 class ShiftFormulaPosHandler
171 {
172 public:
173 
174     void operator() (size_t nRow, ScFormulaCell* pCell)
175     {
176         pCell->aPos.SetRow(nRow);
177     }
178 };
179 
180 }
181 
182 void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize, std::vector<ScAddress>* pGroupPos )
183 {
184     pAttrArray->DeleteRow( nStartRow, nSize );
185 
186     SCROW nEndRow = nStartRow + nSize - 1;
187 
188     maBroadcasters.erase(nStartRow, nEndRow);
189     maBroadcasters.resize(MAXROWCOUNT);
190 
191     CellNotesDeleting(nStartRow, nEndRow, false);
192     maCellNotes.erase(nStartRow, nEndRow);
193     maCellNotes.resize(MAXROWCOUNT);
194 
195     // See if we have any cells that would get deleted or shifted by deletion.
196     sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
197     sc::CellStoreType::iterator itCell = aPos.first;
198     if (itCell->type == sc::element_type_empty)
199     {
200         // This is an empty block. If this is the last block, then there is no cells to delete or shift.
201         sc::CellStoreType::iterator itTest = itCell;
202         ++itTest;
203         if (itTest == maCells.end())
204         {
205             // No cells are affected by this deletion. Bail out.
206             CellStorageModified(); // broadcast array has been modified.
207             return;
208         }
209     }
210 
211     // Check if there are any cells below the end row that will get shifted.
212     bool bShiftCells = false;
213     if (nEndRow < GetDoc()->MaxRow()) //only makes sense to do this if there *is* a row after the end row
214     {
215         aPos = maCells.position(itCell, nEndRow+1);
216         itCell = aPos.first;
217         if (itCell->type == sc::element_type_empty)
218         {
219             // This block is empty. See if there is any block that follows.
220             sc::CellStoreType::iterator itTest = itCell;
221             ++itTest;
222             if (itTest != maCells.end())
223                 // Non-empty block follows -> cells that will get shifted.
224                 bShiftCells = true;
225         }
226         else
227             bShiftCells = true;
228     }
229 
230     sc::SingleColumnSpanSet aNonEmptySpans;
231     if (bShiftCells)
232     {
233         // Mark all non-empty cell positions below the end row.
234         sc::ColumnBlockConstPosition aBlockPos;
235         aBlockPos.miCellPos = itCell;
236         aNonEmptySpans.scan(aBlockPos, *this, nEndRow+1, GetDoc()->MaxRow());
237     }
238 
239     sc::AutoCalcSwitch aACSwitch(*GetDoc(), false);
240 
241     // Remove the cells.
242     maCells.erase(nStartRow, nEndRow);
243     maCells.resize(MAXROWCOUNT);
244 
245     // Get the position again after the container change.
246     aPos = maCells.position(nStartRow);
247 
248     // Shift the formula cell positions below the start row.
249     ShiftFormulaPosHandler aShiftFormulaFunc;
250     sc::ProcessFormula(aPos.first, maCells, nStartRow, GetDoc()->MaxRow(), aShiftFormulaFunc);
251 
252     bool bJoined = sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
253     if (bJoined && pGroupPos)
254         pGroupPos->push_back(ScAddress(nCol, nStartRow, nTab));
255 
256     // Shift the text attribute array too (before the broadcast).
257     maCellTextAttrs.erase(nStartRow, nEndRow);
258     maCellTextAttrs.resize(MAXROWCOUNT);
259 
260     CellStorageModified();
261 }
262 
263 sc::CellStoreType::iterator ScColumn::GetPositionToInsert( SCROW nRow, std::vector<SCROW>& rNewSharedRows,
264         bool bInsertFormula )
265 {
266     return GetPositionToInsert(maCells.begin(), nRow, rNewSharedRows, bInsertFormula);
267 }
268 
269 void ScColumn::JoinNewFormulaCell(
270     const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell )
271 {
272     // Check the previous row position for possible grouping.
273     if (aPos.first->type == sc::element_type_formula && aPos.second > 0)
274     {
275         ScFormulaCell& rPrev = *sc::formula_block::at(*aPos.first->data, aPos.second-1);
276         sc::CellStoreType::position_type aPosPrev = aPos;
277         --aPosPrev.second;
278         sc::SharedFormulaUtil::joinFormulaCells(aPosPrev, rPrev, rCell);
279     }
280 
281     // Check the next row position for possible grouping.
282     if (aPos.first->type == sc::element_type_formula && aPos.second+1 < aPos.first->size)
283     {
284         ScFormulaCell& rNext = *sc::formula_block::at(*aPos.first->data, aPos.second+1);
285         sc::SharedFormulaUtil::joinFormulaCells(aPos, rCell, rNext);
286     }
287 }
288 
289 void ScColumn::DetachFormulaCell(
290     const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, std::vector<SCROW>& rNewSharedRows )
291 {
292     if (!GetDoc()->IsClipOrUndo())
293     {
294 #if USE_FORMULA_GROUP_LISTENER
295         if (rCell.IsShared() && rCell.GetSharedLength() > 1)
296         {
297             // Record new spans (shared or remaining single) that will result
298             // from unsharing to reestablish listeners.
299             // Same cases as in unshareFormulaCell().
300             // XXX NOTE: this is not part of unshareFormulaCell() because that
301             // is called in other contexts as well, for which passing and
302             // determining the rows vector would be superfluous. If that was
303             // needed, move it there.
304             const SCROW nSharedTopRow = rCell.GetSharedTopRow();
305             const SCROW nSharedLength = rCell.GetSharedLength();
306             if (rCell.aPos.Row() == nSharedTopRow)
307             {
308                 // Top cell.
309                 // Next row will be new shared top or single cell.
310                 rNewSharedRows.push_back( nSharedTopRow + 1);
311                 rNewSharedRows.push_back( nSharedTopRow + nSharedLength - 1);
312             }
313             else if (rCell.aPos.Row() == nSharedTopRow + nSharedLength - 1)
314             {
315                 // Bottom cell.
316                 // Current shared top row will be new shared top again or
317                 // single cell.
318                 rNewSharedRows.push_back( nSharedTopRow);
319                 rNewSharedRows.push_back( rCell.aPos.Row() - 1);
320             }
321             else
322             {
323                 // Some mid cell.
324                 // Current shared top row will be new shared top again or
325                 // single cell, plus a new shared top below or single cell.
326                 rNewSharedRows.push_back( nSharedTopRow);
327                 rNewSharedRows.push_back( rCell.aPos.Row() - 1);
328                 rNewSharedRows.push_back( rCell.aPos.Row() + 1);
329                 rNewSharedRows.push_back( nSharedTopRow + nSharedLength - 1);
330             }
331         }
332 #endif
333 
334         // Have the dying formula cell stop listening.
335         // If in a shared formula group this ends the group listening.
336         rCell.EndListeningTo(GetDoc());
337     }
338 
339     sc::SharedFormulaUtil::unshareFormulaCell(aPos, rCell);
340 }
341 
342 void ScColumn::StartListeningUnshared( const std::vector<SCROW>& rNewSharedRows )
343 {
344     assert(rNewSharedRows.empty() || rNewSharedRows.size() == 2 || rNewSharedRows.size() == 4);
345     ScDocument* pDoc = GetDoc();
346     if (!rNewSharedRows.empty() && !pDoc->IsDelayedFormulaGrouping())
347     {
348         auto pPosSet = std::make_shared<sc::ColumnBlockPositionSet>(*pDoc);
349         sc::StartListeningContext aStartCxt(*pDoc, pPosSet);
350         sc::EndListeningContext aEndCxt(*pDoc, pPosSet);
351         if (rNewSharedRows.size() >= 2)
352         {
353             if(!pDoc->CanDelayStartListeningFormulaCells( this, rNewSharedRows[0], rNewSharedRows[1]))
354                 StartListeningFormulaCells(aStartCxt, aEndCxt, rNewSharedRows[0], rNewSharedRows[1]);
355         }
356         if (rNewSharedRows.size() >= 4)
357         {
358             if(!pDoc->CanDelayStartListeningFormulaCells( this, rNewSharedRows[2], rNewSharedRows[3]))
359                 StartListeningFormulaCells(aStartCxt, aEndCxt, rNewSharedRows[2], rNewSharedRows[3]);
360         }
361     }
362 }
363 
364 namespace {
365 
366 class AttachFormulaCellsHandler
367 {
368     sc::StartListeningContext& mrCxt;
369 
370 public:
371     explicit AttachFormulaCellsHandler(sc::StartListeningContext& rCxt)
372         : mrCxt(rCxt) {}
373 
374     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
375     {
376         pCell->StartListeningTo(mrCxt);
377     }
378 };
379 
380 class DetachFormulaCellsHandler
381 {
382     ScDocument* mpDoc;
383     sc::EndListeningContext* mpCxt;
384 
385 public:
386     DetachFormulaCellsHandler( ScDocument* pDoc, sc::EndListeningContext* pCxt ) :
387         mpDoc(pDoc), mpCxt(pCxt) {}
388 
389     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
390     {
391         if (mpCxt)
392             pCell->EndListeningTo(*mpCxt);
393         else
394             pCell->EndListeningTo(mpDoc);
395     }
396 };
397 
398 }
399 
400 void ScColumn::DetachFormulaCells(
401     const sc::CellStoreType::position_type& aPos, size_t nLength, std::vector<SCROW>* pNewSharedRows )
402 {
403     const size_t nRow = aPos.first->position + aPos.second;
404     const size_t nNextTopRow = nRow + nLength; // start row of next formula group.
405 
406     bool bLowerSplitOff = false;
407     if (pNewSharedRows && !GetDoc()->IsClipOrUndo())
408     {
409         const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos);
410         if (pFC)
411         {
412             const SCROW nTopRow = pFC->GetSharedTopRow();
413             const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
414             // nTopRow <= nRow <= nBotRow, because otherwise pFC would not exist.
415             if (nTopRow < static_cast<SCROW>(nRow))
416             {
417                 // Upper part will be split off.
418                 pNewSharedRows->push_back(nTopRow);
419                 pNewSharedRows->push_back(nRow - 1);
420             }
421             if (static_cast<SCROW>(nNextTopRow) <= nBotRow)
422             {
423                 // Lower part will be split off.
424                 pNewSharedRows->push_back(nNextTopRow);
425                 pNewSharedRows->push_back(nBotRow);
426                 bLowerSplitOff = true;
427             }
428         }
429     }
430 
431     // Split formula grouping at the top and bottom boundaries.
432     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, nullptr);
433 
434     if (nLength > 0 && GetDoc()->ValidRow(nNextTopRow))
435     {
436         if (pNewSharedRows && !bLowerSplitOff && !GetDoc()->IsClipOrUndo())
437         {
438             sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow-1);
439             const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos2);
440             if (pFC)
441             {
442                 const SCROW nTopRow = pFC->GetSharedTopRow();
443                 const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
444                 // nRow < nTopRow < nNextTopRow <= nBotRow
445                 if (static_cast<SCROW>(nNextTopRow) <= nBotRow)
446                 {
447                     // Lower part will be split off.
448                     pNewSharedRows->push_back(nNextTopRow);
449                     pNewSharedRows->push_back(nBotRow);
450                 }
451             }
452         }
453 
454         sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nNextTopRow);
455         sc::SharedFormulaUtil::splitFormulaCellGroup(aPos2, nullptr);
456     }
457 
458     if (GetDoc()->IsClipOrUndo())
459         return;
460 
461     DetachFormulaCellsHandler aFunc(GetDoc(), nullptr);
462     sc::ProcessFormula(aPos.first, maCells, nRow, nNextTopRow-1, aFunc);
463 }
464 
465 void ScColumn::AttachFormulaCells( sc::StartListeningContext& rCxt, SCROW nRow1, SCROW nRow2 )
466 {
467     sc::CellStoreType::position_type aPos = maCells.position(nRow1);
468     sc::CellStoreType::iterator it = aPos.first;
469 
470     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
471     if (GetDoc()->ValidRow(nRow2+1))
472     {
473         aPos = maCells.position(it, nRow2+1);
474         sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
475     }
476 
477     if (GetDoc()->IsClipOrUndo())
478         return;
479 
480     AttachFormulaCellsHandler aFunc(rCxt);
481     sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc);
482 }
483 
484 void ScColumn::DetachFormulaCells( sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2,
485         std::vector<SCROW>* pNewSharedRows )
486 {
487     sc::CellStoreType::position_type aPos = maCells.position(nRow1);
488     sc::CellStoreType::iterator it = aPos.first;
489 
490     bool bLowerSplitOff = false;
491     if (pNewSharedRows && !GetDoc()->IsClipOrUndo())
492     {
493         const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos);
494         if (pFC)
495         {
496             const SCROW nTopRow = pFC->GetSharedTopRow();
497             const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
498             // nTopRow <= nRow1 <= nBotRow, because otherwise pFC would not exist.
499             if (nTopRow < nRow1)
500             {
501                 // Upper part will be split off.
502                 pNewSharedRows->push_back(nTopRow);
503                 pNewSharedRows->push_back(nRow1 - 1);
504             }
505             if (nRow2 < nBotRow)
506             {
507                 // Lower part will be split off.
508                 pNewSharedRows->push_back(nRow2 + 1);
509                 pNewSharedRows->push_back(nBotRow);
510                 bLowerSplitOff = true;
511             }
512         }
513     }
514 
515     // Split formula grouping at the top and bottom boundaries.
516     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt);
517     if (GetDoc()->ValidRow(nRow2+1))
518     {
519         if (pNewSharedRows && !bLowerSplitOff && !GetDoc()->IsClipOrUndo())
520         {
521             sc::CellStoreType::position_type aPos2 = maCells.position(aPos.first, nRow2);
522             const ScFormulaCell* pFC = sc::SharedFormulaUtil::getSharedTopFormulaCell(aPos2);
523             if (pFC)
524             {
525                 const SCROW nTopRow = pFC->GetSharedTopRow();
526                 const SCROW nBotRow = nTopRow + pFC->GetSharedLength() - 1;
527                 // nRow1 < nTopRow <= nRow2 < nBotRow
528                 if (nRow2 < nBotRow)
529                 {
530                     // Lower part will be split off.
531                     pNewSharedRows->push_back(nRow2 + 1);
532                     pNewSharedRows->push_back(nBotRow);
533                 }
534             }
535         }
536 
537         aPos = maCells.position(it, nRow2+1);
538         sc::SharedFormulaUtil::splitFormulaCellGroup(aPos, &rCxt);
539     }
540 
541     if (GetDoc()->IsClipOrUndo())
542         return;
543 
544     DetachFormulaCellsHandler aFunc(GetDoc(), &rCxt);
545     sc::ProcessFormula(it, maCells, nRow1, nRow2, aFunc);
546 }
547 
548 static void lcl_AddFormulaGroupBoundaries(const sc::CellStoreType::position_type& rPos,
549         std::vector<SCROW>& rNewSharedRows )
550 {
551     sc::CellStoreType::iterator itRet = rPos.first;
552     if (itRet->type != sc::element_type_formula)
553         return;
554 
555     ScFormulaCell& rFC = *sc::formula_block::at(*itRet->data, rPos.second);
556     if ( rFC.IsShared() )
557     {
558         const SCROW nSharedTopRow = rFC.GetSharedTopRow();
559         const SCROW nSharedLength = rFC.GetSharedLength();
560         rNewSharedRows.push_back( nSharedTopRow);
561         rNewSharedRows.push_back( nSharedTopRow + nSharedLength - 1);
562     }
563     else
564     {
565         const SCROW nRow = rFC.aPos.Row();
566         rNewSharedRows.push_back( nRow);
567         rNewSharedRows.push_back( nRow);
568     }
569 }
570 
571 sc::CellStoreType::iterator ScColumn::GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow,
572         std::vector<SCROW>& rNewSharedRows, bool bInsertFormula )
573 {
574     // See if we are overwriting an existing formula cell.
575     sc::CellStoreType::position_type aPos = maCells.position(it, nRow);
576     sc::CellStoreType::iterator itRet = aPos.first;
577 
578     if (itRet->type == sc::element_type_formula)
579     {
580         ScFormulaCell& rCell = *sc::formula_block::at(*itRet->data, aPos.second);
581         DetachFormulaCell(aPos, rCell, rNewSharedRows);
582     }
583     else if (bInsertFormula && !GetDoc()->IsClipOrUndo())
584     {
585         if (nRow > 0)
586         {
587             sc::CellStoreType::position_type aPosBefore = maCells.position(maCells.begin(), nRow-1);
588             lcl_AddFormulaGroupBoundaries(aPosBefore, rNewSharedRows);
589         }
590         if (nRow < GetDoc()->MaxRow())
591         {
592             sc::CellStoreType::position_type aPosAfter = maCells.position(maCells.begin(), nRow+1);
593             lcl_AddFormulaGroupBoundaries(aPosAfter, rNewSharedRows);
594         }
595     }
596 
597     return itRet;
598 }
599 
600 void ScColumn::AttachNewFormulaCell(
601     const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell,
602     const std::vector<SCROW>& rNewSharedRows,
603     bool bJoin, sc::StartListeningType eListenType )
604 {
605     AttachNewFormulaCell(maCells.position(itPos, nRow), rCell, rNewSharedRows, bJoin, eListenType);
606 }
607 
608 void ScColumn::AttachNewFormulaCell(
609     const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell,
610     const std::vector<SCROW>& rNewSharedRows,
611     bool bJoin, sc::StartListeningType eListenType )
612 {
613     if (bJoin)
614         // See if this new formula cell can join an existing shared formula group.
615         JoinNewFormulaCell(aPos, rCell);
616 
617     // When we insert from the Clipboard we still have wrong (old) References!
618     // First they are rewired in CopyBlockFromClip via UpdateReference and the
619     // we call StartListeningFromClip and BroadcastFromClip.
620     // If we insert into the Clipboard/andoDoc, we do not use a Broadcast.
621     // After Import we call CalcAfterLoad and in there Listening.
622     ScDocument* pDocument = GetDoc();
623     if (pDocument->IsClipOrUndo() || pDocument->IsInsertingFromOtherDoc())
624         return;
625 
626     switch (eListenType)
627     {
628         case sc::ConvertToGroupListening:
629         {
630             auto pPosSet = std::make_shared<sc::ColumnBlockPositionSet>(*pDocument);
631             sc::StartListeningContext aStartCxt(*pDocument, pPosSet);
632             sc::EndListeningContext aEndCxt(*pDocument, pPosSet);
633             SCROW nStartRow, nEndRow;
634             nStartRow = nEndRow = aPos.first->position + aPos.second;
635             for (const SCROW nR : rNewSharedRows)
636             {
637                 if (nStartRow > nR)
638                     nStartRow = nR;
639                 if (nEndRow < nR)
640                     nEndRow = nR;
641             }
642             StartListeningFormulaCells(aStartCxt, aEndCxt, nStartRow, nEndRow);
643         }
644         break;
645         case sc::SingleCellListening:
646             rCell.StartListeningTo(pDocument);
647             StartListeningUnshared( rNewSharedRows);
648         break;
649         case sc::NoListening:
650         default:
651             if (!rNewSharedRows.empty())
652             {
653                 assert(rNewSharedRows.size() == 2 || rNewSharedRows.size() == 4);
654                 // Calling SetNeedsListeningGroup() with a top row sets it to
655                 // all affected formula cells of that group.
656                 const ScFormulaCell* pFC = GetFormulaCell( rNewSharedRows[0]);
657                 assert(pFC);    // that *is* supposed to be a top row
658                 if (pFC && !pFC->NeedsListening())
659                     SetNeedsListeningGroup( rNewSharedRows[0]);
660                 if (rNewSharedRows.size() > 2)
661                 {
662                     pFC = GetFormulaCell( rNewSharedRows[2]);
663                     assert(pFC);    // that *is* supposed to be a top row
664                     if (pFC && !pFC->NeedsListening())
665                         SetNeedsListeningGroup( rNewSharedRows[2]);
666                 }
667             }
668         break;
669     }
670 
671     if (!pDocument->IsCalcingAfterLoad())
672         rCell.SetDirty();
673 }
674 
675 void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength,
676         std::vector<SCROW>& rNewSharedRows )
677 {
678     // Make sure the whole length consists of formula cells.
679     if (aPos.first->type != sc::element_type_formula)
680         return;
681 
682     if (aPos.first->size < aPos.second + nLength)
683         // Block is shorter than specified length.
684         return;
685 
686     // Join the top and bottom cells only.
687     ScFormulaCell* pCell1 = sc::formula_block::at(*aPos.first->data, aPos.second);
688     JoinNewFormulaCell(aPos, *pCell1);
689 
690     sc::CellStoreType::position_type aPosLast = aPos;
691     aPosLast.second += nLength - 1;
692     ScFormulaCell* pCell2 = sc::formula_block::at(*aPosLast.first->data, aPosLast.second);
693     JoinNewFormulaCell(aPosLast, *pCell2);
694 
695     ScDocument* pDocument = GetDoc();
696     if (!pDocument->IsClipOrUndo() && !pDocument->IsInsertingFromOtherDoc())
697     {
698         const bool bShared = pCell1->IsShared() || pCell2->IsShared();
699         if (bShared)
700         {
701             const SCROW nTopRow = (pCell1->IsShared() ? pCell1->GetSharedTopRow() : pCell1->aPos.Row());
702             const SCROW nBotRow = (pCell2->IsShared() ?
703                     pCell2->GetSharedTopRow() + pCell2->GetSharedLength() - 1 : pCell2->aPos.Row());
704             if (rNewSharedRows.empty())
705             {
706                 rNewSharedRows.push_back( nTopRow);
707                 rNewSharedRows.push_back( nBotRow);
708             }
709             else if (rNewSharedRows.size() == 2)
710             {
711                 // Combine into one span.
712                 if (rNewSharedRows[0] > nTopRow)
713                     rNewSharedRows[0] = nTopRow;
714                 if (rNewSharedRows[1] < nBotRow)
715                     rNewSharedRows[1] = nBotRow;
716             }
717             else if (rNewSharedRows.size() == 4)
718             {
719                 // Merge into one span.
720                 // The original two spans are ordered from top to bottom.
721                 std::vector<SCROW> aRows(2);
722                 aRows[0] = std::min( rNewSharedRows[0], nTopRow);
723                 aRows[1] = std::max( rNewSharedRows[3], nBotRow);
724                 rNewSharedRows.swap( aRows);
725             }
726             else
727             {
728                 assert(!"rNewSharedRows?");
729             }
730         }
731         StartListeningUnshared( rNewSharedRows);
732 
733         sc::StartListeningContext aCxt(*pDocument);
734         ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second);
735         ScFormulaCell** ppEnd = pp + nLength;
736         for (; pp != ppEnd; ++pp)
737         {
738             if (!bShared)
739                 (*pp)->StartListeningTo(aCxt);
740             if (!pDocument->IsCalcingAfterLoad())
741                 (*pp)->SetDirty();
742         }
743     }
744 }
745 
746 void ScColumn::BroadcastNewCell( SCROW nRow )
747 {
748     // When we insert from the Clipboard we still have wrong (old) References!
749     // First they are rewired in CopyBlockFromClip via UpdateReference and the
750     // we call StartListeningFromClip and BroadcastFromClip.
751     // If we insert into the Clipboard/andoDoc, we do not use a Broadcast.
752     // After Import we call CalcAfterLoad and in there Listening.
753     if (GetDoc()->IsClipOrUndo() || GetDoc()->IsInsertingFromOtherDoc() || GetDoc()->IsCalcingAfterLoad())
754         return;
755 
756     Broadcast(nRow);
757 }
758 
759 bool ScColumn::UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow, sc::CellStoreType::iterator& itr )
760 {
761     if (rAttr.mnScriptType != SvtScriptType::UNKNOWN)
762         // Already updated. Nothing to do.
763         return false;
764 
765     // Script type not yet determined. Determine the real script
766     // type, and store it.
767     const ScPatternAttr* pPattern = GetPattern(nRow);
768     if (!pPattern)
769         return false;
770 
771     sc::CellStoreType::position_type pos = maCells.position(itr, nRow);
772     itr = pos.first;
773     size_t nOffset = pos.second;
774     ScRefCellValue aCell = GetCellValue( itr, nOffset );
775     ScAddress aPos(nCol, nRow, nTab);
776 
777     ScDocument* pDocument = GetDoc();
778     const SfxItemSet* pCondSet = nullptr;
779     ScConditionalFormatList* pCFList = pDocument->GetCondFormList(nTab);
780     if (pCFList)
781     {
782         const ScCondFormatItem& rItem =
783             pPattern->GetItem(ATTR_CONDITIONAL);
784         const ScCondFormatIndexes& rData = rItem.GetCondFormatData();
785         pCondSet = pDocument->GetCondResult(aCell, aPos, *pCFList, rData);
786     }
787 
788     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
789 
790     OUString aStr;
791     Color* pColor;
792     sal_uInt32 nFormat = pPattern->GetNumberFormat(pFormatter, pCondSet);
793     ScCellFormat::GetString(aCell, nFormat, aStr, &pColor, *pFormatter, pDocument);
794 
795     // Store the real script type to the array.
796     rAttr.mnScriptType = pDocument->GetStringScriptType(aStr);
797     return true;
798 }
799 
800 namespace {
801 
802 class DeleteAreaHandler
803 {
804     ScDocument& mrDoc;
805     std::vector<ScFormulaCell*> maFormulaCells;
806     sc::SingleColumnSpanSet maDeleteRanges;
807 
808     bool mbNumeric:1;
809     bool mbString:1;
810     bool mbFormula:1;
811     bool mbDateTime:1;
812     ScColumn& mrCol;
813 
814 public:
815     DeleteAreaHandler(ScDocument& rDoc, InsertDeleteFlags nDelFlag, ScColumn& rCol) :
816         mrDoc(rDoc),
817         mbNumeric(nDelFlag & InsertDeleteFlags::VALUE),
818         mbString(nDelFlag & InsertDeleteFlags::STRING),
819         mbFormula(nDelFlag & InsertDeleteFlags::FORMULA),
820         mbDateTime(nDelFlag & InsertDeleteFlags::DATETIME),
821         mrCol(rCol) {}
822 
823     void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
824     {
825         switch (node.type)
826         {
827             case sc::element_type_numeric:
828                 // Numeric type target datetime and number, thus we have a dedicated function
829                 if (!mbNumeric && !mbDateTime)
830                     return;
831 
832                 // If numeric and datetime selected, delete full range
833                 if (mbNumeric && mbDateTime)
834                     break;
835 
836                 deleteNumeric(node, nOffset, nDataSize);
837                 return;
838             break;
839             case sc::element_type_string:
840             case sc::element_type_edittext:
841                 if (!mbString)
842                     return;
843             break;
844             case sc::element_type_formula:
845             {
846                 if (!mbFormula)
847                     return;
848 
849                 sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
850                 std::advance(it, nOffset);
851                 sc::formula_block::iterator itEnd = it;
852                 std::advance(itEnd, nDataSize);
853 
854                 for (; it != itEnd; ++it)
855                     maFormulaCells.push_back(*it);
856             }
857             break;
858             case sc::element_type_empty:
859             default:
860                 return;
861         }
862 
863         // Tag these cells for deletion.
864         SCROW nRow1 = node.position + nOffset;
865         SCROW nRow2 = nRow1 + nDataSize - 1;
866         maDeleteRanges.set(nRow1, nRow2, true);
867     }
868 
869     void deleteNumeric(const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
870     {
871         size_t nStart = node.position + nOffset;
872         size_t nElements = 1;
873         bool bLastTypeDateTime = isDateTime(nStart); // true = datetime, false = numeric
874         size_t nCount = nStart + nDataSize;
875 
876         for (size_t i = nStart + 1; i < nCount; i++)
877         {
878             bool bIsDateTime = isDateTime(i);
879 
880             // same type as previous
881             if (bIsDateTime == bLastTypeDateTime)
882             {
883                 nElements++;
884             }
885             // type switching
886             else
887             {
888                 deleteNumberOrDateTime(nStart, nStart + nElements - 1, bLastTypeDateTime);
889                 nStart += nElements;
890                 nElements = 1;
891             }
892 
893             bLastTypeDateTime = bIsDateTime;
894         }
895 
896         // delete last cells
897         deleteNumberOrDateTime(nStart, nStart + nElements - 1, bLastTypeDateTime);
898     }
899 
900     void deleteNumberOrDateTime(SCROW nRow1, SCROW nRow2, bool dateTime)
901     {
902         if (!dateTime && !mbNumeric) // numeric flag must be selected
903             return;
904         if (dateTime && !mbDateTime) // datetime flag must be selected
905             return;
906         maDeleteRanges.set(nRow1, nRow2, true);
907     }
908 
909     bool isDateTime(size_t position)
910     {
911         SvNumFormatType nType = mrDoc.GetFormatTable()->GetType(
912                           mrCol.GetAttr(position, ATTR_VALUE_FORMAT).GetValue());
913 
914         return (nType == SvNumFormatType::DATE) || (nType == SvNumFormatType::TIME) ||
915                (nType == SvNumFormatType::DATETIME);
916     }
917 
918     void endFormulas()
919     {
920         mrDoc.EndListeningFormulaCells(maFormulaCells);
921     }
922 
923     sc::SingleColumnSpanSet& getSpans()
924     {
925         return maDeleteRanges;
926     }
927 };
928 
929 class EmptyCells
930 {
931     ScColumn& mrColumn;
932     sc::ColumnBlockPosition& mrPos;
933 
934     static void splitFormulaGrouping(const sc::CellStoreType::position_type& rPos)
935     {
936         if (rPos.first->type == sc::element_type_formula)
937         {
938             ScFormulaCell& rCell = *sc::formula_block::at(*rPos.first->data, rPos.second);
939             sc::SharedFormulaUtil::unshareFormulaCell(rPos, rCell);
940         }
941     }
942 
943 public:
944     EmptyCells( sc::ColumnBlockPosition& rPos, ScColumn& rColumn ) :
945         mrColumn(rColumn), mrPos(rPos) {}
946 
947     void operator() (const sc::RowSpan& rSpan)
948     {
949         sc::CellStoreType& rCells = mrColumn.GetCellStore();
950 
951         // First, split formula grouping at the top and bottom boundaries
952         // before emptying the cells.
953         sc::CellStoreType::position_type aPos = rCells.position(mrPos.miCellPos, rSpan.mnRow1);
954         splitFormulaGrouping(aPos);
955         aPos = rCells.position(aPos.first, rSpan.mnRow2);
956         splitFormulaGrouping(aPos);
957 
958         mrPos.miCellPos = rCells.set_empty(mrPos.miCellPos, rSpan.mnRow1, rSpan.mnRow2);
959         mrPos.miCellTextAttrPos = mrColumn.GetCellAttrStore().set_empty(mrPos.miCellTextAttrPos, rSpan.mnRow1, rSpan.mnRow2);
960     }
961 };
962 
963 }
964 
965 void ScColumn::DeleteCells(
966     sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nDelFlag,
967     sc::SingleColumnSpanSet& rDeleted )
968 {
969     // Determine which cells to delete based on the deletion flags.
970     DeleteAreaHandler aFunc(*GetDoc(), nDelFlag, *this);
971     sc::CellStoreType::iterator itPos = maCells.position(rBlockPos.miCellPos, nRow1).first;
972     sc::ProcessBlock(itPos, maCells, aFunc, nRow1, nRow2);
973     aFunc.endFormulas(); // Have the formula cells stop listening.
974 
975     // Get the deletion spans.
976     sc::SingleColumnSpanSet::SpansType aSpans;
977     aFunc.getSpans().getSpans(aSpans);
978 
979     // Delete the cells for real.
980     std::for_each(aSpans.begin(), aSpans.end(), EmptyCells(rBlockPos, *this));
981     CellStorageModified();
982 
983     aFunc.getSpans().swap(rDeleted);
984 }
985 
986 void ScColumn::DeleteArea(
987     SCROW nStartRow, SCROW nEndRow, InsertDeleteFlags nDelFlag, bool bBroadcast,
988     sc::ColumnSpanSet* pBroadcastSpans )
989 {
990     InsertDeleteFlags nContMask = InsertDeleteFlags::CONTENTS;
991     // InsertDeleteFlags::NOCAPTIONS needs to be passed too, if InsertDeleteFlags::NOTE is set
992     if( nDelFlag & InsertDeleteFlags::NOTE )
993         nContMask |= InsertDeleteFlags::NOCAPTIONS;
994     InsertDeleteFlags nContFlag = nDelFlag & nContMask;
995 
996     sc::SingleColumnSpanSet aDeletedRows;
997 
998     sc::ColumnBlockPosition aBlockPos;
999     InitBlockPosition(aBlockPos);
1000 
1001     if (!IsEmptyData() && nContFlag != InsertDeleteFlags::NONE)
1002     {
1003         DeleteCells(aBlockPos, nStartRow, nEndRow, nDelFlag, aDeletedRows);
1004         if (pBroadcastSpans)
1005         {
1006             sc::SingleColumnSpanSet::SpansType aSpans;
1007             aDeletedRows.getSpans(aSpans);
1008             for (const auto& rSpan : aSpans)
1009                 pBroadcastSpans->set(*GetDoc(), nTab, nCol, rSpan.mnRow1, rSpan.mnRow2, true);
1010         }
1011     }
1012 
1013     if (nDelFlag & InsertDeleteFlags::NOTE)
1014     {
1015         bool bForgetCaptionOwnership = ((nDelFlag & InsertDeleteFlags::FORGETCAPTIONS) != InsertDeleteFlags::NONE);
1016         DeleteCellNotes(aBlockPos, nStartRow, nEndRow, bForgetCaptionOwnership);
1017     }
1018 
1019     if ( nDelFlag & InsertDeleteFlags::EDITATTR )
1020     {
1021         OSL_ENSURE( nContFlag == InsertDeleteFlags::NONE, "DeleteArea: Wrong Flags" );
1022         RemoveEditAttribs( nStartRow, nEndRow );
1023     }
1024 
1025     // Delete attributes just now
1026     if ((nDelFlag & InsertDeleteFlags::ATTRIB) == InsertDeleteFlags::ATTRIB)
1027         pAttrArray->DeleteArea( nStartRow, nEndRow );
1028     else if ((nDelFlag & InsertDeleteFlags::HARDATTR) == InsertDeleteFlags::HARDATTR)
1029         pAttrArray->DeleteHardAttr( nStartRow, nEndRow );
1030 
1031     if (bBroadcast)
1032     {
1033         // Broadcast on only cells that were deleted; no point broadcasting on
1034         // cells that were already empty before the deletion.
1035         std::vector<SCROW> aRows;
1036         aDeletedRows.getRows(aRows);
1037         BroadcastCells(aRows, SfxHintId::ScDataChanged);
1038     }
1039 }
1040 
1041 void ScColumn::InitBlockPosition( sc::ColumnBlockPosition& rBlockPos )
1042 {
1043     rBlockPos.miBroadcasterPos = maBroadcasters.begin();
1044     rBlockPos.miCellNotePos = maCellNotes.begin();
1045     rBlockPos.miCellTextAttrPos = maCellTextAttrs.begin();
1046     rBlockPos.miCellPos = maCells.begin();
1047 }
1048 
1049 void ScColumn::InitBlockPosition( sc::ColumnBlockConstPosition& rBlockPos ) const
1050 {
1051     rBlockPos.miCellNotePos = maCellNotes.begin();
1052     rBlockPos.miCellTextAttrPos = maCellTextAttrs.begin();
1053     rBlockPos.miCellPos = maCells.begin();
1054 }
1055 
1056 namespace {
1057 
1058 class CopyAttrArrayByRange
1059 {
1060     ScAttrArray& mrDestAttrArray;
1061     ScAttrArray& mrSrcAttrArray;
1062     long mnRowOffset;
1063 public:
1064     CopyAttrArrayByRange(ScAttrArray& rDestAttrArray, ScAttrArray& rSrcAttrArray, long nRowOffset) :
1065         mrDestAttrArray(rDestAttrArray), mrSrcAttrArray(rSrcAttrArray), mnRowOffset(nRowOffset) {}
1066 
1067     void operator() (const sc::RowSpan& rSpan)
1068     {
1069         mrDestAttrArray.CopyAreaSafe(
1070             rSpan.mnRow1+mnRowOffset, rSpan.mnRow2+mnRowOffset, mnRowOffset, mrSrcAttrArray);
1071     }
1072 };
1073 
1074 class CopyCellsFromClipHandler
1075 {
1076     sc::CopyFromClipContext& mrCxt;
1077     ScColumn& mrSrcCol;
1078     ScColumn& mrDestCol;
1079     SCTAB mnTab;
1080     SCCOL mnCol;
1081     SCTAB mnSrcTab;
1082     SCCOL mnSrcCol;
1083     long mnRowOffset;
1084     sc::ColumnBlockPosition maDestBlockPos;
1085     sc::ColumnBlockPosition* mpDestBlockPos; // to save it for next iteration.
1086     svl::SharedStringPool* mpSharedStringPool;
1087 
1088     void insertRefCell(SCROW nSrcRow, SCROW nDestRow)
1089     {
1090         ScAddress aSrcPos(mnSrcCol, nSrcRow, mnSrcTab);
1091         ScAddress aDestPos(mnCol, nDestRow, mnTab);
1092         ScSingleRefData aRef;
1093         aRef.InitAddress(aSrcPos);
1094         aRef.SetFlag3D(true);
1095 
1096         ScTokenArray aArr(mrCxt.getDestDoc());
1097         aArr.AddSingleReference(aRef);
1098 
1099         mrDestCol.SetFormulaCell(
1100             maDestBlockPos, nDestRow, new ScFormulaCell(mrDestCol.GetDoc(), aDestPos, aArr));
1101     }
1102 
1103     void duplicateNotes(SCROW nStartRow, size_t nDataSize, bool bCloneCaption )
1104     {
1105         mrSrcCol.DuplicateNotes(nStartRow, nDataSize, mrDestCol, maDestBlockPos, bCloneCaption, mnRowOffset);
1106     }
1107 
1108 public:
1109     CopyCellsFromClipHandler(sc::CopyFromClipContext& rCxt, ScColumn& rSrcCol, ScColumn& rDestCol, SCTAB nDestTab, SCCOL nDestCol, long nRowOffset, svl::SharedStringPool* pSharedStringPool) :
1110         mrCxt(rCxt),
1111         mrSrcCol(rSrcCol),
1112         mrDestCol(rDestCol),
1113         mnTab(nDestTab),
1114         mnCol(nDestCol),
1115         mnSrcTab(rSrcCol.GetTab()),
1116         mnSrcCol(rSrcCol.GetCol()),
1117         mnRowOffset(nRowOffset),
1118         mpDestBlockPos(mrCxt.getBlockPosition(nDestTab, nDestCol)),
1119         mpSharedStringPool(pSharedStringPool)
1120     {
1121         if (mpDestBlockPos)
1122             maDestBlockPos = *mpDestBlockPos;
1123         else
1124             mrDestCol.InitBlockPosition(maDestBlockPos);
1125     }
1126 
1127     ~CopyCellsFromClipHandler()
1128     {
1129         if (mpDestBlockPos)
1130             // Don't forget to save this to the context!
1131             *mpDestBlockPos = maDestBlockPos;
1132     }
1133 
1134     void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
1135     {
1136         SCROW nSrcRow1 = node.position + nOffset;
1137         bool bCopyCellNotes = mrCxt.isCloneNotes();
1138 
1139         InsertDeleteFlags nFlags = mrCxt.getInsertFlag();
1140 
1141         if (node.type == sc::element_type_empty)
1142         {
1143             if (bCopyCellNotes && !mrCxt.isSkipAttrForEmptyCells())
1144             {
1145                 bool bCloneCaption = (nFlags & InsertDeleteFlags::NOCAPTIONS) == InsertDeleteFlags::NONE;
1146                 duplicateNotes(nSrcRow1, nDataSize, bCloneCaption );
1147             }
1148             return;
1149         }
1150 
1151         bool bNumeric = (nFlags & InsertDeleteFlags::VALUE) != InsertDeleteFlags::NONE;
1152         bool bDateTime = (nFlags & InsertDeleteFlags::DATETIME) != InsertDeleteFlags::NONE;
1153         bool bString   = (nFlags & InsertDeleteFlags::STRING) != InsertDeleteFlags::NONE;
1154         bool bBoolean  = (nFlags & InsertDeleteFlags::SPECIAL_BOOLEAN) != InsertDeleteFlags::NONE;
1155         bool bFormula  = (nFlags & InsertDeleteFlags::FORMULA) != InsertDeleteFlags::NONE;
1156 
1157         bool bAsLink = mrCxt.isAsLink();
1158 
1159         switch (node.type)
1160         {
1161             case sc::element_type_numeric:
1162             {
1163                 // We need to copy numeric cells individually because of date type check.
1164                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*node.data);
1165                 std::advance(it, nOffset);
1166                 sc::numeric_block::const_iterator itEnd = it;
1167                 std::advance(itEnd, nDataSize);
1168                 for (SCROW nSrcRow = nSrcRow1; it != itEnd; ++it, ++nSrcRow)
1169                 {
1170                     bool bCopy = mrCxt.isDateCell(mrSrcCol, nSrcRow) ? bDateTime : bNumeric;
1171                     if (!bCopy)
1172                         continue;
1173 
1174                     if (bAsLink)
1175                         insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1176                     else
1177                         mrDestCol.SetValue(maDestBlockPos, nSrcRow + mnRowOffset, *it);
1178                 }
1179             }
1180             break;
1181             case sc::element_type_string:
1182             {
1183                 if (!bString)
1184                     break;
1185 
1186                 sc::string_block::const_iterator it = sc::string_block::begin(*node.data);
1187                 std::advance(it, nOffset);
1188                 sc::string_block::const_iterator itEnd = it;
1189                 std::advance(itEnd, nDataSize);
1190                 for (SCROW nSrcRow = nSrcRow1; it != itEnd; ++it, ++nSrcRow)
1191                 {
1192                     if (bAsLink)
1193                         insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1194                     else if (mpSharedStringPool)
1195                     {
1196                         // Re-intern the string if source is a different document.
1197                         svl::SharedString aInterned = mpSharedStringPool->intern( (*it).getString());
1198                         mrDestCol.SetRawString(maDestBlockPos, nSrcRow + mnRowOffset, aInterned);
1199                     }
1200                     else
1201                         mrDestCol.SetRawString(maDestBlockPos, nSrcRow + mnRowOffset, *it);
1202                 }
1203             }
1204             break;
1205             case sc::element_type_edittext:
1206             {
1207                 if (!bString)
1208                     break;
1209 
1210                 sc::edittext_block::const_iterator it = sc::edittext_block::begin(*node.data);
1211                 std::advance(it, nOffset);
1212                 sc::edittext_block::const_iterator itEnd = it;
1213                 std::advance(itEnd, nDataSize);
1214                 for (SCROW nSrcRow = nSrcRow1; it != itEnd; ++it, ++nSrcRow)
1215                 {
1216 
1217                     if (bAsLink)
1218                         insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1219                     else
1220                         mrDestCol.SetEditText(maDestBlockPos, nSrcRow + mnRowOffset, **it);
1221                 }
1222             }
1223             break;
1224             case sc::element_type_formula:
1225             {
1226                 sc::formula_block::const_iterator it = sc::formula_block::begin(*node.data);
1227                 std::advance(it, nOffset);
1228                 sc::formula_block::const_iterator itEnd = it;
1229                 std::advance(itEnd, nDataSize);
1230                 for (SCROW nSrcRow = nSrcRow1; it != itEnd; ++it, ++nSrcRow)
1231                 {
1232                     ScFormulaCell& rSrcCell = **it;
1233                     bool bForceFormula = false;
1234                     if (bBoolean)
1235                     {
1236                         // See if the formula consists of =TRUE() or =FALSE().
1237                         const ScTokenArray* pCode = rSrcCell.GetCode();
1238                         if (pCode && pCode->GetLen() == 1)
1239                         {
1240                             const formula::FormulaToken* p = pCode->FirstToken();
1241                             if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
1242                                 // This is a boolean formula.
1243                                 bForceFormula = true;
1244                         }
1245                     }
1246 
1247                     ScAddress aDestPos(mnCol, nSrcRow + mnRowOffset, mnTab);
1248                     if (bFormula || bForceFormula)
1249                     {
1250                         if (bAsLink)
1251                             insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1252                         else
1253                         {
1254                             mrDestCol.SetFormulaCell(
1255                                 maDestBlockPos, nSrcRow + mnRowOffset,
1256                                 new ScFormulaCell(rSrcCell, *mrDestCol.GetDoc(), aDestPos),
1257                                 sc::SingleCellListening,
1258                                 rSrcCell.NeedsNumberFormat());
1259                         }
1260                     }
1261                     else if (bNumeric || bDateTime || bString)
1262                     {
1263                         // Always just copy the original row to the Undo Document;
1264                         // do not create Value/string cells from formulas
1265 
1266                         FormulaError nErr = rSrcCell.GetErrCode();
1267                         if (nErr != FormulaError::NONE)
1268                         {
1269                             // error codes are cloned with values
1270                             if (bNumeric)
1271                             {
1272                                 if (bAsLink)
1273                                     insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1274                                 else
1275                                 {
1276                                     ScFormulaCell* pErrCell = new ScFormulaCell(mrDestCol.GetDoc(), aDestPos);
1277                                     pErrCell->SetErrCode(nErr);
1278                                     mrDestCol.SetFormulaCell(
1279                                         maDestBlockPos, nSrcRow + mnRowOffset, pErrCell);
1280                                 }
1281                             }
1282                         }
1283                         else if (rSrcCell.IsEmptyDisplayedAsString())
1284                         {
1285                             // Empty stays empty and doesn't become 0.
1286                             continue;
1287                         }
1288                         else if (rSrcCell.IsValue())
1289                         {
1290                             bool bCopy = mrCxt.isDateCell(mrSrcCol, nSrcRow) ? bDateTime : bNumeric;
1291                             if (!bCopy)
1292                                 continue;
1293 
1294                             if (bAsLink)
1295                                 insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1296                             else
1297                                 mrDestCol.SetValue(maDestBlockPos, nSrcRow + mnRowOffset, rSrcCell.GetValue());
1298                         }
1299                         else if (bString)
1300                         {
1301                             svl::SharedString aStr = rSrcCell.GetString();
1302                             if (aStr.isEmpty())
1303                                 // do not clone empty string
1304                                 continue;
1305 
1306                             if (bAsLink)
1307                                 insertRefCell(nSrcRow, nSrcRow + mnRowOffset);
1308                             else if (rSrcCell.IsMultilineResult())
1309                             {
1310                                 // Clone as an edit text object.
1311                                 ScFieldEditEngine& rEngine = mrDestCol.GetDoc()->GetEditEngine();
1312                                 rEngine.SetTextCurrentDefaults(aStr.getString());
1313                                 mrDestCol.SetEditText(maDestBlockPos, nSrcRow + mnRowOffset, rEngine.CreateTextObject());
1314                             }
1315                             else if (mpSharedStringPool)
1316                             {
1317                                 // Re-intern the string if source is a different document.
1318                                 svl::SharedString aInterned = mpSharedStringPool->intern( aStr.getString());
1319                                 mrDestCol.SetRawString(maDestBlockPos, nSrcRow + mnRowOffset, aInterned);
1320                             }
1321                             else
1322                             {
1323                                 mrDestCol.SetRawString(maDestBlockPos, nSrcRow + mnRowOffset, aStr);
1324                             }
1325                         }
1326                     }
1327                 }
1328             }
1329             break;
1330             default:
1331                 ;
1332         }
1333         if (bCopyCellNotes)
1334         {
1335             bool bCloneCaption = (nFlags & InsertDeleteFlags::NOCAPTIONS) == InsertDeleteFlags::NONE;
1336             duplicateNotes(nSrcRow1, nDataSize, bCloneCaption );
1337         }
1338     }
1339 };
1340 
1341 class CopyTextAttrsFromClipHandler
1342 {
1343     sc::CellTextAttrStoreType& mrAttrs;
1344     size_t mnDelta;
1345     sc::ColumnBlockPosition maDestBlockPos;
1346     sc::ColumnBlockPosition* mpDestBlockPos; // to save it for next iteration.
1347 
1348 public:
1349     CopyTextAttrsFromClipHandler( sc::CopyFromClipContext& rCxt, sc::CellTextAttrStoreType& rAttrs,
1350                                   ScColumn& rDestCol, SCTAB nDestTab, SCCOL nDestCol, size_t nDelta ) :
1351         mrAttrs(rAttrs),
1352         mnDelta(nDelta),
1353         mpDestBlockPos(rCxt.getBlockPosition(nDestTab, nDestCol))
1354     {
1355         if (mpDestBlockPos)
1356             maDestBlockPos = *mpDestBlockPos;
1357         else
1358             rDestCol.InitBlockPosition(maDestBlockPos);
1359     }
1360 
1361     ~CopyTextAttrsFromClipHandler()
1362     {
1363         if (mpDestBlockPos)
1364             // Don't forget to save this to the context!
1365             *mpDestBlockPos = maDestBlockPos;
1366     }
1367 
1368     void operator() ( const sc::CellTextAttrStoreType::value_type& aNode, size_t nOffset, size_t nDataSize )
1369     {
1370         if (aNode.type != sc::element_type_celltextattr)
1371             return;
1372 
1373         sc::celltextattr_block::const_iterator it = sc::celltextattr_block::begin(*aNode.data);
1374         std::advance(it, nOffset);
1375         sc::celltextattr_block::const_iterator itEnd = it;
1376         std::advance(itEnd, nDataSize);
1377 
1378         size_t nPos = aNode.position + nOffset + mnDelta;
1379         maDestBlockPos.miCellTextAttrPos = mrAttrs.set(maDestBlockPos.miCellTextAttrPos, nPos, it, itEnd);
1380     }
1381 };
1382 
1383 }
1384 
1385 //  rColumn = source
1386 //  nRow1, nRow2 = target position
1387 
1388 void ScColumn::CopyFromClip(
1389     sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2, long nDy, ScColumn& rColumn )
1390 {
1391     if ((rCxt.getInsertFlag() & InsertDeleteFlags::ATTRIB) != InsertDeleteFlags::NONE)
1392     {
1393         if (rCxt.isSkipAttrForEmptyCells())
1394         {
1395             //  copy only attributes for non-empty cells between nRow1-nDy and nRow2-nDy.
1396             sc::SingleColumnSpanSet aSpanSet;
1397             aSpanSet.scan(rColumn, nRow1-nDy, nRow2-nDy);
1398             sc::SingleColumnSpanSet::SpansType aSpans;
1399             aSpanSet.getSpans(aSpans);
1400             std::for_each(
1401                 aSpans.begin(), aSpans.end(), CopyAttrArrayByRange(*rColumn.pAttrArray, *pAttrArray, nDy));
1402         }
1403         else
1404             rColumn.pAttrArray->CopyAreaSafe( nRow1, nRow2, nDy, *pAttrArray );
1405     }
1406     if ((rCxt.getInsertFlag() & InsertDeleteFlags::CONTENTS) == InsertDeleteFlags::NONE)
1407         return;
1408 
1409     ScDocument* pDocument = GetDoc();
1410     if (rCxt.isAsLink() && rCxt.getInsertFlag() == InsertDeleteFlags::ALL)
1411     {
1412         // We also reference empty cells for "ALL"
1413         // InsertDeleteFlags::ALL must always contain more flags when compared to "Insert contents" as
1414         // contents can be selected one by one!
1415 
1416         ScAddress aDestPos( nCol, 0, nTab ); // Adapt Row
1417 
1418         //  Create reference (Source Position)
1419         ScSingleRefData aRef;
1420         aRef.InitFlags(); // -> All absolute
1421         aRef.SetAbsCol(rColumn.nCol);
1422         aRef.SetAbsTab(rColumn.nTab);
1423         aRef.SetFlag3D(true);
1424 
1425         for (SCROW nDestRow = nRow1; nDestRow <= nRow2; nDestRow++)
1426         {
1427             aRef.SetAbsRow(nDestRow - nDy); // Source row
1428             aDestPos.SetRow( nDestRow );
1429 
1430             ScTokenArray aArr(GetDoc());
1431             aArr.AddSingleReference( aRef );
1432             SetFormulaCell(nDestRow, new ScFormulaCell(pDocument, aDestPos, aArr));
1433         }
1434 
1435         // Don't forget to copy the cell text attributes.
1436         CopyTextAttrsFromClipHandler aFunc(rCxt, maCellTextAttrs, *this, nTab, nCol, nDy);
1437         sc::ParseBlock(rColumn.maCellTextAttrs.begin(), rColumn.maCellTextAttrs, aFunc, nRow1-nDy, nRow2-nDy);
1438 
1439         return;
1440     }
1441 
1442     // Compare the ScDocumentPool* to determine if we are copying within the
1443     // same document. If not, re-intern shared strings.
1444     svl::SharedStringPool* pSharedStringPool = (rColumn.GetDoc()->GetPool() != pDocument->GetPool()) ?
1445         &pDocument->GetSharedStringPool() : nullptr;
1446 
1447     // nRow1 to nRow2 is for destination (this) column. Subtract nDy to get the source range.
1448     // Copy all cells in the source column (rColumn) from nRow1-nDy to nRow2-nDy to this column.
1449     {
1450         CopyCellsFromClipHandler aFunc(rCxt, rColumn, *this, nTab, nCol, nDy, pSharedStringPool);
1451         sc::ParseBlock(rColumn.maCells.begin(), rColumn.maCells, aFunc, nRow1-nDy, nRow2-nDy);
1452     }
1453 
1454     {
1455         // Don't forget to copy the cell text attributes.
1456         CopyTextAttrsFromClipHandler aFunc(rCxt, maCellTextAttrs, *this, nTab, nCol, nDy);
1457         sc::ParseBlock(rColumn.maCellTextAttrs.begin(), rColumn.maCellTextAttrs, aFunc, nRow1-nDy, nRow2-nDy);
1458     }
1459 }
1460 
1461 void ScColumn::MixMarked(
1462     sc::MixDocContext& rCxt, const ScMarkData& rMark, ScPasteFunc nFunction,
1463     bool bSkipEmpty, const ScColumn& rSrcCol )
1464 {
1465     SCROW nRow1, nRow2;
1466 
1467     if (rMark.IsMultiMarked())
1468     {
1469         ScMultiSelIter aIter( rMark.GetMultiSelData(), nCol );
1470         while (aIter.Next( nRow1, nRow2 ))
1471             MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, rSrcCol);
1472     }
1473 }
1474 
1475 namespace {
1476 
1477 // Result in rVal1
1478 bool lcl_DoFunction( double& rVal1, double nVal2, ScPasteFunc nFunction )
1479 {
1480     bool bOk = false;
1481     switch (nFunction)
1482     {
1483         case ScPasteFunc::ADD:
1484             bOk = SubTotal::SafePlus( rVal1, nVal2 );
1485             break;
1486         case ScPasteFunc::SUB:
1487             nVal2 = -nVal2;     // FIXME: Can we do this always without error?
1488             bOk = SubTotal::SafePlus( rVal1, nVal2 );
1489             break;
1490         case ScPasteFunc::MUL:
1491             bOk = SubTotal::SafeMult( rVal1, nVal2 );
1492             break;
1493         case ScPasteFunc::DIV:
1494             bOk = SubTotal::SafeDiv( rVal1, nVal2 );
1495             break;
1496         default: break;
1497     }
1498     return bOk;
1499 }
1500 
1501 void lcl_AddCode( ScTokenArray& rArr, const ScFormulaCell* pCell )
1502 {
1503     rArr.AddOpCode(ocOpen);
1504 
1505     const ScTokenArray* pCode = pCell->GetCode();
1506     if (pCode)
1507     {
1508         FormulaTokenArrayPlainIterator aIter(*pCode);
1509         const formula::FormulaToken* pToken = aIter.First();
1510         while (pToken)
1511         {
1512             rArr.AddToken( *pToken );
1513             pToken = aIter.Next();
1514         }
1515     }
1516 
1517     rArr.AddOpCode(ocClose);
1518 }
1519 
1520 class MixDataHandler
1521 {
1522     ScColumn& mrDestColumn;
1523     sc::ColumnBlockPosition& mrBlockPos;
1524 
1525     sc::CellStoreType maNewCells;
1526     sc::CellStoreType::iterator miNewCellsPos;
1527 
1528     size_t mnRowOffset;
1529     ScPasteFunc mnFunction;
1530 
1531     bool mbSkipEmpty;
1532 
1533     void doFunction( size_t nDestRow, double fVal1, double fVal2 )
1534     {
1535         bool bOk = lcl_DoFunction(fVal1, fVal2, mnFunction);
1536 
1537         if (bOk)
1538             miNewCellsPos = maNewCells.set(miNewCellsPos, nDestRow-mnRowOffset, fVal1);
1539         else
1540         {
1541             ScAddress aPos(mrDestColumn.GetCol(), nDestRow, mrDestColumn.GetTab());
1542 
1543             ScFormulaCell* pFC = new ScFormulaCell(mrDestColumn.GetDoc(), aPos);
1544             pFC->SetErrCode(FormulaError::NoValue);
1545 
1546             miNewCellsPos = maNewCells.set(miNewCellsPos, nDestRow-mnRowOffset, pFC);
1547         }
1548     }
1549 
1550 public:
1551     MixDataHandler(
1552         sc::ColumnBlockPosition& rBlockPos,
1553         ScColumn& rDestColumn,
1554         SCROW nRow1, SCROW nRow2,
1555         ScPasteFunc nFunction, bool bSkipEmpty) :
1556         mrDestColumn(rDestColumn),
1557         mrBlockPos(rBlockPos),
1558         maNewCells(nRow2 - nRow1 + 1),
1559         miNewCellsPos(maNewCells.begin()),
1560         mnRowOffset(nRow1),
1561         mnFunction(nFunction),
1562         mbSkipEmpty(bSkipEmpty)
1563     {
1564     }
1565 
1566     void operator() (size_t nRow, double f)
1567     {
1568         sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nRow);
1569         mrBlockPos.miCellPos = aPos.first;
1570         switch (aPos.first->type)
1571         {
1572             case sc::element_type_empty:
1573             case sc::element_type_numeric:
1574             {
1575                 double fSrcVal = 0.0;
1576                 if (aPos.first->type == sc::element_type_numeric)
1577                     fSrcVal = sc::numeric_block::at(*aPos.first->data, aPos.second);
1578 
1579                 // Both src and dest are of numeric type.
1580                 doFunction(nRow, f, fSrcVal);
1581             }
1582             break;
1583             case sc::element_type_formula:
1584             {
1585                 // Combination of value and at least one formula -> Create formula
1586                 ScTokenArray aArr(mrDestColumn.GetDoc());
1587 
1588                 // First row
1589                 aArr.AddDouble(f);
1590 
1591                 // Operator
1592                 OpCode eOp = ocAdd;
1593                 switch (mnFunction)
1594                 {
1595                     case ScPasteFunc::ADD: eOp = ocAdd; break;
1596                     case ScPasteFunc::SUB: eOp = ocSub; break;
1597                     case ScPasteFunc::MUL: eOp = ocMul; break;
1598                     case ScPasteFunc::DIV: eOp = ocDiv; break;
1599                     default: break;
1600                 }
1601                 aArr.AddOpCode(eOp); // Function
1602 
1603                 // Second row
1604                 ScFormulaCell* pDest = sc::formula_block::at(*aPos.first->data, aPos.second);
1605                 lcl_AddCode(aArr, pDest);
1606 
1607                 miNewCellsPos = maNewCells.set(
1608                     miNewCellsPos, nRow-mnRowOffset,
1609                     new ScFormulaCell(
1610                         mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), aArr));
1611             }
1612             break;
1613             case sc::element_type_string:
1614             case sc::element_type_edittext:
1615             {
1616                 // Destination cell is not a number. Just take the source cell.
1617                 miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, f);
1618             }
1619             break;
1620             default:
1621                 ;
1622         }
1623     }
1624 
1625     void operator() (size_t nRow, const svl::SharedString& rStr)
1626     {
1627         miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, rStr);
1628     }
1629 
1630     void operator() (size_t nRow, const EditTextObject* p)
1631     {
1632         miNewCellsPos = maNewCells.set(miNewCellsPos, nRow-mnRowOffset, p->Clone().release());
1633     }
1634 
1635     void operator() (size_t nRow, const ScFormulaCell* p)
1636     {
1637         sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nRow);
1638         mrBlockPos.miCellPos = aPos.first;
1639         switch (aPos.first->type)
1640         {
1641             case sc::element_type_numeric:
1642             {
1643                 // Source is formula, and dest is value.
1644                 ScTokenArray aArr(mrDestColumn.GetDoc());
1645 
1646                 // First row
1647                 lcl_AddCode(aArr, p);
1648 
1649                 // Operator
1650                 OpCode eOp = ocAdd;
1651                 switch (mnFunction)
1652                 {
1653                     case ScPasteFunc::ADD: eOp = ocAdd; break;
1654                     case ScPasteFunc::SUB: eOp = ocSub; break;
1655                     case ScPasteFunc::MUL: eOp = ocMul; break;
1656                     case ScPasteFunc::DIV: eOp = ocDiv; break;
1657                     default: break;
1658                 }
1659                 aArr.AddOpCode(eOp); // Function
1660 
1661                 // Second row
1662                 aArr.AddDouble(sc::numeric_block::at(*aPos.first->data, aPos.second));
1663 
1664                 miNewCellsPos = maNewCells.set(
1665                     miNewCellsPos, nRow-mnRowOffset,
1666                     new ScFormulaCell(
1667                         mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), aArr));
1668             }
1669             break;
1670             case sc::element_type_formula:
1671             {
1672                 // Both are formulas.
1673                 ScTokenArray aArr(mrDestColumn.GetDoc());
1674 
1675                 // First row
1676                 lcl_AddCode(aArr, p);
1677 
1678                 // Operator
1679                 OpCode eOp = ocAdd;
1680                 switch (mnFunction)
1681                 {
1682                     case ScPasteFunc::ADD: eOp = ocAdd; break;
1683                     case ScPasteFunc::SUB: eOp = ocSub; break;
1684                     case ScPasteFunc::MUL: eOp = ocMul; break;
1685                     case ScPasteFunc::DIV: eOp = ocDiv; break;
1686                     default: break;
1687                 }
1688                 aArr.AddOpCode(eOp); // Function
1689 
1690                 // Second row
1691                 ScFormulaCell* pDest = sc::formula_block::at(*aPos.first->data, aPos.second);
1692                 lcl_AddCode(aArr, pDest);
1693 
1694                 miNewCellsPos = maNewCells.set(
1695                     miNewCellsPos, nRow-mnRowOffset,
1696                     new ScFormulaCell(
1697                         mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), aArr));
1698             }
1699             break;
1700             case sc::element_type_string:
1701             case sc::element_type_edittext:
1702             case sc::element_type_empty:
1703             {
1704                 // Destination cell is not a number. Just take the source cell.
1705                 ScAddress aDestPos(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab());
1706                 miNewCellsPos = maNewCells.set(
1707                     miNewCellsPos, nRow-mnRowOffset, new ScFormulaCell(*p, *mrDestColumn.GetDoc(), aDestPos));
1708             }
1709             break;
1710             default:
1711                 ;
1712         }
1713     }
1714 
1715     /**
1716      * Empty cell series in the source (clip) document.
1717      */
1718     void operator() (mdds::mtv::element_t, size_t nTopRow, size_t nDataSize)
1719     {
1720         if (mbSkipEmpty)
1721             return;
1722 
1723         // Source cells are empty. Treat them as if they have a value of 0.0.
1724         for (size_t i = 0; i < nDataSize; ++i)
1725         {
1726             size_t nDestRow = nTopRow + i;
1727             sc::CellStoreType::position_type aPos = mrDestColumn.GetCellStore().position(mrBlockPos.miCellPos, nDestRow);
1728             mrBlockPos.miCellPos = aPos.first;
1729             switch (aPos.first->type)
1730             {
1731                 case sc::element_type_numeric:
1732                 {
1733                     double fVal2 = sc::numeric_block::at(*aPos.first->data, aPos.second);
1734                     doFunction(nDestRow, 0.0, fVal2);
1735                 }
1736                 break;
1737                 case sc::element_type_string:
1738                 {
1739                     const svl::SharedString& aVal = sc::string_block::at(*aPos.first->data, aPos.second);
1740                     miNewCellsPos = maNewCells.set(
1741                             miNewCellsPos, nDestRow-mnRowOffset, aVal);
1742                 }
1743                 break;
1744                 case sc::element_type_edittext:
1745                 {
1746                     EditTextObject* pObj = sc::edittext_block::at(*aPos.first->data, aPos.second);
1747                     miNewCellsPos = maNewCells.set(
1748                             miNewCellsPos, nDestRow-mnRowOffset, pObj->Clone().release());
1749                 }
1750                 break;
1751                 case sc::element_type_formula:
1752                 {
1753                     ScTokenArray aArr(mrDestColumn.GetDoc());
1754 
1755                     // First row
1756                     ScFormulaCell* pSrc = sc::formula_block::at(*aPos.first->data, aPos.second);
1757                     lcl_AddCode( aArr, pSrc);
1758 
1759                     // Operator
1760                     OpCode eOp = ocAdd;
1761                     switch (mnFunction)
1762                     {
1763                         case ScPasteFunc::ADD: eOp = ocAdd; break;
1764                         case ScPasteFunc::SUB: eOp = ocSub; break;
1765                         case ScPasteFunc::MUL: eOp = ocMul; break;
1766                         case ScPasteFunc::DIV: eOp = ocDiv; break;
1767                         default: break;
1768                     }
1769 
1770                     aArr.AddOpCode(eOp); // Function
1771                     aArr.AddDouble(0.0);
1772 
1773                     miNewCellsPos = maNewCells.set(
1774                         miNewCellsPos, nDestRow-mnRowOffset,
1775                         new ScFormulaCell(
1776                             mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nDestRow, mrDestColumn.GetTab()), aArr));
1777                 }
1778                 break;
1779                 default:
1780                     ;
1781             }
1782         }
1783     }
1784 
1785     /**
1786      * Set the new cells to the destination (this) column.
1787      */
1788     void commit()
1789     {
1790         sc::CellStoreType& rDestCells = mrDestColumn.GetCellStore();
1791 
1792         // Stop all formula cells in the destination range first.
1793         sc::CellStoreType::position_type aPos = rDestCells.position(mrBlockPos.miCellPos, mnRowOffset);
1794         mrDestColumn.DetachFormulaCells(aPos, maNewCells.size(), nullptr);
1795 
1796         // Move the new cells to the destination range.
1797         sc::CellStoreType::iterator& itDestPos = mrBlockPos.miCellPos;
1798         sc::CellTextAttrStoreType::iterator& itDestAttrPos = mrBlockPos.miCellTextAttrPos;
1799 
1800         for (const auto& rNewCell : maNewCells)
1801         {
1802             bool bHasContent = true;
1803             size_t nDestRow = mnRowOffset + rNewCell.position;
1804 
1805             switch (rNewCell.type)
1806             {
1807                 case sc::element_type_numeric:
1808                 {
1809                     sc::numeric_block::iterator itData = sc::numeric_block::begin(*rNewCell.data);
1810                     sc::numeric_block::iterator itDataEnd = sc::numeric_block::end(*rNewCell.data);
1811                     itDestPos = mrDestColumn.GetCellStore().set(itDestPos, nDestRow, itData, itDataEnd);
1812                 }
1813                 break;
1814                 case sc::element_type_string:
1815                 {
1816                     sc::string_block::iterator itData = sc::string_block::begin(*rNewCell.data);
1817                     sc::string_block::iterator itDataEnd = sc::string_block::end(*rNewCell.data);
1818                     itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
1819                 }
1820                 break;
1821                 case sc::element_type_edittext:
1822                 {
1823                     sc::edittext_block::iterator itData = sc::edittext_block::begin(*rNewCell.data);
1824                     sc::edittext_block::iterator itDataEnd = sc::edittext_block::end(*rNewCell.data);
1825                     itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
1826                 }
1827                 break;
1828                 case sc::element_type_formula:
1829                 {
1830                     sc::formula_block::iterator itData = sc::formula_block::begin(*rNewCell.data);
1831                     sc::formula_block::iterator itDataEnd = sc::formula_block::end(*rNewCell.data);
1832 
1833                     // Group new formula cells before inserting them.
1834                     sc::SharedFormulaUtil::groupFormulaCells(itData, itDataEnd);
1835 
1836                     // Insert the formula cells to the column.
1837                     itDestPos = rDestCells.set(itDestPos, nDestRow, itData, itDataEnd);
1838 
1839                     // Merge with the previous formula group (if any).
1840                     aPos = rDestCells.position(itDestPos, nDestRow);
1841                     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
1842 
1843                     // Merge with the next formula group (if any).
1844                     size_t nNextRow = nDestRow + rNewCell.size;
1845                     if (mrDestColumn.GetDoc()->ValidRow(nNextRow))
1846                     {
1847                         aPos = rDestCells.position(aPos.first, nNextRow);
1848                         sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
1849                     }
1850                 }
1851                 break;
1852                 case sc::element_type_empty:
1853                 {
1854                     itDestPos = rDestCells.set_empty(itDestPos, nDestRow, nDestRow+rNewCell.size-1);
1855                     bHasContent = false;
1856                 }
1857                 break;
1858                 default:
1859                     ;
1860             }
1861 
1862             sc::CellTextAttrStoreType& rDestAttrs = mrDestColumn.GetCellAttrStore();
1863             if (bHasContent)
1864             {
1865                 std::vector<sc::CellTextAttr> aAttrs(rNewCell.size, sc::CellTextAttr());
1866                 itDestAttrPos = rDestAttrs.set(itDestAttrPos, nDestRow, aAttrs.begin(), aAttrs.end());
1867             }
1868             else
1869                 itDestAttrPos = rDestAttrs.set_empty(itDestAttrPos, nDestRow, nDestRow+rNewCell.size-1);
1870         }
1871 
1872         maNewCells.release();
1873     }
1874 };
1875 
1876 }
1877 
1878 void ScColumn::MixData(
1879     sc::MixDocContext& rCxt, SCROW nRow1, SCROW nRow2, ScPasteFunc nFunction,
1880     bool bSkipEmpty, const ScColumn& rSrcCol )
1881 {
1882     // destination (this column) block position.
1883 
1884     sc::ColumnBlockPosition* p = rCxt.getBlockPosition(nTab, nCol);
1885     if (!p)
1886         return;
1887 
1888     MixDataHandler aFunc(*p, *this, nRow1, nRow2, nFunction, bSkipEmpty);
1889     sc::ParseAll(rSrcCol.maCells.begin(), rSrcCol.maCells, nRow1, nRow2, aFunc, aFunc);
1890 
1891     aFunc.commit();
1892     CellStorageModified();
1893 }
1894 
1895 std::unique_ptr<ScAttrIterator> ScColumn::CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const
1896 {
1897     return std::make_unique<ScAttrIterator>( pAttrArray.get(), nStartRow, nEndRow, GetDoc()->GetDefPattern() );
1898 }
1899 
1900 namespace {
1901 
1902 class StartListenersHandler
1903 {
1904     sc::StartListeningContext* mpCxt;
1905     bool mbAllListeners;
1906 
1907 public:
1908     StartListenersHandler( sc::StartListeningContext& rCxt, bool bAllListeners ) :
1909         mpCxt(&rCxt), mbAllListeners(bAllListeners) {}
1910 
1911     void operator() ( sc::CellStoreType::value_type& aBlk )
1912     {
1913         if (aBlk.type != sc::element_type_formula)
1914             return;
1915 
1916         ScFormulaCell** pp = &sc::formula_block::at(*aBlk.data, 0);
1917         ScFormulaCell** ppEnd = pp + aBlk.size;
1918 
1919         for (; pp != ppEnd; ++pp)
1920         {
1921             ScFormulaCell& rFC = **pp;
1922             if (!mbAllListeners && !rFC.NeedsListening())
1923                 continue;
1924 
1925             if (rFC.IsSharedTop())
1926             {
1927                 sc::SharedFormulaUtil::startListeningAsGroup(*mpCxt, pp);
1928                 pp += rFC.GetSharedLength() - 1; // Move to the last cell in the group.
1929             }
1930             else
1931                 rFC.StartListeningTo(*mpCxt);
1932         }
1933     }
1934 };
1935 
1936 }
1937 
1938 void ScColumn::StartListeners( sc::StartListeningContext& rCxt, bool bAll )
1939 {
1940     std::for_each(maCells.begin(), maCells.end(), StartListenersHandler(rCxt, bAll));
1941 }
1942 
1943 namespace {
1944 
1945 void applyTextNumFormat( ScColumn& rCol, SCROW nRow, SvNumberFormatter* pFormatter )
1946 {
1947     sal_uInt32 nFormat = pFormatter->GetStandardFormat(SvNumFormatType::TEXT);
1948     ScPatternAttr aNewAttrs(rCol.GetDoc()->GetPool());
1949     SfxItemSet& rSet = aNewAttrs.GetItemSet();
1950     rSet.Put(SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat));
1951     rCol.ApplyPattern(nRow, aNewAttrs);
1952 }
1953 
1954 }
1955 
1956 bool ScColumn::ParseString(
1957     ScCellValue& rCell, SCROW nRow, SCTAB nTabP, const OUString& rString,
1958     formula::FormulaGrammar::AddressConvention eConv,
1959     const ScSetStringParam* pParam )
1960 {
1961     if (rString.isEmpty())
1962         return false;
1963 
1964     bool bNumFmtSet = false;
1965 
1966     ScSetStringParam aParam;
1967 
1968     if (pParam)
1969         aParam = *pParam;
1970 
1971     sal_uInt32 nIndex = 0;
1972     sal_uInt32 nOldIndex = 0;
1973     SvNumFormatType eNumFormatType = SvNumFormatType::ALL;
1974     if (!aParam.mpNumFormatter)
1975         aParam.mpNumFormatter = GetDoc()->GetFormatTable();
1976 
1977     sal_Unicode cFirstChar = 0; // Text
1978     nIndex = nOldIndex = GetNumberFormat( GetDoc()->GetNonThreadedContext(), nRow );
1979     if ( rString.getLength() > 1 )
1980     {
1981         eNumFormatType = aParam.mpNumFormatter->GetType(nIndex);
1982         if ( eNumFormatType != SvNumFormatType::TEXT )
1983             cFirstChar = rString[0];
1984     }
1985 
1986     svl::SharedStringPool& rPool = GetDoc()->GetSharedStringPool();
1987 
1988     if ( cFirstChar == '=' )
1989     {
1990         if ( rString.getLength() == 1 ) // = Text
1991         {
1992             rCell.set(rPool.intern(rString));
1993         }
1994         else if (aParam.meSetTextNumFormat == ScSetStringParam::Always)
1995         {
1996             // Set the cell format type to Text.
1997             applyTextNumFormat(*this, nRow, aParam.mpNumFormatter);
1998             rCell.set(rPool.intern(rString));
1999         }
2000         else // = Formula
2001         {
2002             ScFormulaCell* pFormulaCell = new ScFormulaCell(
2003                     GetDoc(), ScAddress(nCol, nRow, nTabP), rString,
2004                     formula::FormulaGrammar::mergeToGrammar(formula::FormulaGrammar::GRAM_DEFAULT, eConv),
2005                     ScMatrixMode::NONE);
2006             if (aParam.mbCheckLinkFormula)
2007                 GetDoc()->CheckLinkFormulaNeedingCheck( *pFormulaCell->GetCode());
2008             rCell.set( pFormulaCell);
2009         }
2010     }
2011     else if ( cFirstChar == '\'') // 'Text
2012     {
2013         bool bNumeric = false;
2014         if (aParam.mbHandleApostrophe)
2015         {
2016             // Cell format is not 'Text', and the first char
2017             // is an apostrophe. Check if the input is considered a number.
2018             OUString aTest = rString.copy(1);
2019             double fTest;
2020             bNumeric = aParam.mpNumFormatter->IsNumberFormat(aTest, nIndex, fTest);
2021             if (bNumeric)
2022                 // This is a number. Strip out the first char.
2023                 rCell.set(rPool.intern(aTest));
2024         }
2025         if (!bNumeric)
2026             // This is normal text. Take it as-is.
2027             rCell.set(rPool.intern(rString));
2028     }
2029     else
2030     {
2031         double nVal;
2032 
2033         do
2034         {
2035             if (aParam.mbDetectNumberFormat)
2036             {
2037                 // Editing a date prefers the format's locale's edit date
2038                 // format's date acceptance patterns and YMD order.
2039                 /* TODO: this could be determined already far above when
2040                  * starting to edit a date "cell" and passed down. A problem
2041                  * could also be if a new date was typed over or written by a
2042                  * macro assuming the current locale if that conflicts somehow.
2043                  * You can't have everything. See tdf#116579 and tdf#125109. */
2044                 if (eNumFormatType == SvNumFormatType::ALL)
2045                     eNumFormatType = aParam.mpNumFormatter->GetType(nIndex);
2046                 bool bForceFormatDate = (eNumFormatType == SvNumFormatType::DATE
2047                         || eNumFormatType == SvNumFormatType::DATETIME);
2048                 const SvNumberformat* pOldFormat = nullptr;
2049                 NfEvalDateFormat eEvalDateFormat = NF_EVALDATEFORMAT_INTL_FORMAT;
2050                 if (bForceFormatDate)
2051                 {
2052                     ScRefCellValue aCell = GetCellValue(nRow);
2053                     if (aCell.meType == CELLTYPE_VALUE)
2054                     {
2055                         // Only for an actual date (serial number), not an
2056                         // arbitrary string or formula or empty cell.
2057                         // Also ensure the edit date format's pattern is used,
2058                         // not the display format's.
2059                         pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex);
2060                         if (!pOldFormat)
2061                             bForceFormatDate = false;
2062                         else
2063                         {
2064                             nIndex = aParam.mpNumFormatter->GetEditFormat( aCell.getValue(), nOldIndex, eNumFormatType,
2065                                     pOldFormat->GetLanguage(), pOldFormat);
2066                             eEvalDateFormat = aParam.mpNumFormatter->GetEvalDateFormat();
2067                             aParam.mpNumFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT_INTL);
2068                         }
2069                     }
2070                     else
2071                     {
2072                         bForceFormatDate = false;
2073                     }
2074                 }
2075 
2076                 const bool bIsNumberFormat = aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal);
2077 
2078                 if (bForceFormatDate)
2079                     aParam.mpNumFormatter->SetEvalDateFormat( eEvalDateFormat);
2080 
2081                 if (!bIsNumberFormat)
2082                     break;
2083 
2084                 // If we have bForceFormatDate, the pOldFormat was/is of
2085                 // nOldIndex date(+time) type already, if detected type is
2086                 // compatible keep the original format.
2087                 if (bForceFormatDate && SvNumberFormatter::IsCompatible(
2088                             eNumFormatType, aParam.mpNumFormatter->GetType( nIndex)))
2089                 {
2090                     nIndex = nOldIndex;
2091                 }
2092                 else
2093                 {
2094                     // convert back to the original language if a built-in format was detected
2095                     if (!pOldFormat)
2096                         pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex );
2097                     if (pOldFormat)
2098                         nIndex = aParam.mpNumFormatter->GetFormatForLanguageIfBuiltIn(
2099                                 nIndex, pOldFormat->GetLanguage());
2100                 }
2101 
2102                 rCell.set(nVal);
2103                 if ( nIndex != nOldIndex)
2104                 {
2105                     // #i22345# New behavior: Apply the detected number format only if
2106                     // the old one was the default number, date, time or boolean format.
2107                     // Exception: If the new format is boolean, always apply it.
2108 
2109                     bool bOverwrite = false;
2110                     if ( pOldFormat )
2111                     {
2112                         SvNumFormatType nOldType = pOldFormat->GetMaskedType();
2113                         if ( nOldType == SvNumFormatType::NUMBER || nOldType == SvNumFormatType::DATE ||
2114                              nOldType == SvNumFormatType::TIME || nOldType == SvNumFormatType::LOGICAL )
2115                         {
2116                             if ( nOldIndex == aParam.mpNumFormatter->GetStandardFormat(
2117                                                 nOldType, pOldFormat->GetLanguage() ) )
2118                             {
2119                                 bOverwrite = true; // default of these types can be overwritten
2120                             }
2121                         }
2122                     }
2123                     if ( !bOverwrite && aParam.mpNumFormatter->GetType( nIndex ) == SvNumFormatType::LOGICAL )
2124                     {
2125                         bOverwrite = true; // overwrite anything if boolean was detected
2126                     }
2127 
2128                     if ( bOverwrite )
2129                     {
2130                         ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT,
2131                             nIndex) );
2132                         bNumFmtSet = true;
2133                     }
2134                 }
2135             }
2136             else if (aParam.meSetTextNumFormat == ScSetStringParam::Never ||
2137                      aParam.meSetTextNumFormat == ScSetStringParam::SpecialNumberOnly)
2138             {
2139                 // Only check if the string is a regular number.
2140                 const LocaleDataWrapper* pLocale = aParam.mpNumFormatter->GetLocaleData();
2141                 if (!pLocale)
2142                     break;
2143 
2144                 const LocaleDataItem2& aLocaleItem = pLocale->getLocaleItem();
2145                 const OUString& rDecSep = aLocaleItem.decimalSeparator;
2146                 const OUString& rGroupSep = aLocaleItem.thousandSeparator;
2147                 const OUString& rDecSepAlt = aLocaleItem.decimalSeparatorAlternative;
2148                 if (rDecSep.getLength() != 1 || rGroupSep.getLength() != 1 || rDecSepAlt.getLength() > 1)
2149                     break;
2150 
2151                 sal_Unicode dsep = rDecSep[0];
2152                 sal_Unicode gsep = rGroupSep[0];
2153                 sal_Unicode dsepa = rDecSepAlt.toChar();
2154 
2155                 if (!ScStringUtil::parseSimpleNumber(rString, dsep, gsep, dsepa, nVal))
2156                     break;
2157 
2158                 rCell.set(nVal);
2159             }
2160         }
2161         while (false);
2162 
2163         if (rCell.meType == CELLTYPE_NONE)
2164         {
2165             // If we reach here with ScSetStringParam::SpecialNumberOnly it
2166             // means a simple number was not detected above, so test for
2167             // special numbers. In any case ScSetStringParam::Always does not
2168             // mean always, but only always for content that could be any
2169             // numeric.
2170             if ((aParam.meSetTextNumFormat == ScSetStringParam::Always ||
2171                  aParam.meSetTextNumFormat == ScSetStringParam::SpecialNumberOnly) &&
2172                     aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal))
2173             {
2174                 // Set the cell format type to Text.
2175                 applyTextNumFormat(*this, nRow, aParam.mpNumFormatter);
2176             }
2177 
2178             rCell.set(rPool.intern(rString));
2179         }
2180     }
2181 
2182     return bNumFmtSet;
2183 }
2184 
2185 /**
2186  * Returns true if the cell format was set as well
2187  */
2188 bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const OUString& rString,
2189                           formula::FormulaGrammar::AddressConvention eConv,
2190                           const ScSetStringParam* pParam )
2191 {
2192     if (!GetDoc()->ValidRow(nRow))
2193         return false;
2194 
2195     ScCellValue aNewCell;
2196     bool bNumFmtSet = ParseString(aNewCell, nRow, nTabP, rString, eConv, pParam);
2197     if (pParam)
2198         aNewCell.release(*this, nRow, pParam->meStartListening);
2199     else
2200         aNewCell.release(*this, nRow);
2201 
2202     // Do not set Formats and Formulas here anymore!
2203     // These are queried during output
2204 
2205     return bNumFmtSet;
2206 }
2207 
2208 void ScColumn::SetEditText( SCROW nRow, std::unique_ptr<EditTextObject> pEditText )
2209 {
2210     pEditText->NormalizeString(GetDoc()->GetSharedStringPool());
2211     std::vector<SCROW> aNewSharedRows;
2212     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, false);
2213     maCells.set(it, nRow, pEditText.release());
2214     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2215     CellStorageModified();
2216 
2217     StartListeningUnshared( aNewSharedRows);
2218 
2219     BroadcastNewCell(nRow);
2220 }
2221 
2222 void ScColumn::SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, std::unique_ptr<EditTextObject> pEditText )
2223 {
2224     pEditText->NormalizeString(GetDoc()->GetSharedStringPool());
2225     std::vector<SCROW> aNewSharedRows;
2226     rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow, aNewSharedRows, false);
2227     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, pEditText.release());
2228     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
2229         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
2230 
2231     CellStorageModified();
2232 
2233     StartListeningUnshared( aNewSharedRows);
2234 
2235     BroadcastNewCell(nRow);
2236 }
2237 
2238 void ScColumn::SetEditText( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const EditTextObject& rEditText )
2239 {
2240     if (GetDoc()->GetEditPool() == rEditText.GetPool())
2241     {
2242         SetEditText(rBlockPos, nRow, rEditText.Clone());
2243         return;
2244     }
2245 
2246     // rats, yet another "spool"
2247     // Sadly there is no other way to change the Pool than to
2248     // "spool" the Object through a corresponding Engine
2249     EditEngine& rEngine = GetDoc()->GetEditEngine();
2250     rEngine.SetText(rEditText);
2251     SetEditText(rBlockPos, nRow, rEngine.CreateTextObject());
2252 }
2253 
2254 void ScColumn::SetEditText( SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
2255 {
2256     if (pEditPool && GetDoc()->GetEditPool() == pEditPool)
2257     {
2258         SetEditText(nRow, rEditText.Clone());
2259         return;
2260     }
2261 
2262     // rats, yet another "spool"
2263     // Sadly there is no other way to change the Pool than to
2264     // "spool" the Object through a corresponding Engine
2265     EditEngine& rEngine = GetDoc()->GetEditEngine();
2266     rEngine.SetText(rEditText);
2267     SetEditText(nRow, rEngine.CreateTextObject());
2268 }
2269 
2270 void ScColumn::SetFormula( SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram )
2271 {
2272     ScAddress aPos(nCol, nRow, nTab);
2273 
2274     std::vector<SCROW> aNewSharedRows;
2275     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, true);
2276     ScFormulaCell* pCell = new ScFormulaCell(GetDoc(), aPos, rArray, eGram);
2277     sal_uInt32 nCellFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
2278     if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
2279         pCell->SetNeedNumberFormat(true);
2280     it = maCells.set(it, nRow, pCell);
2281     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2282 
2283     CellStorageModified();
2284 
2285     AttachNewFormulaCell(it, nRow, *pCell, aNewSharedRows);
2286 }
2287 
2288 void ScColumn::SetFormula( SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram )
2289 {
2290     ScAddress aPos(nCol, nRow, nTab);
2291 
2292     std::vector<SCROW> aNewSharedRows;
2293     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, true);
2294     ScFormulaCell* pCell = new ScFormulaCell(GetDoc(), aPos, rFormula, eGram);
2295     sal_uInt32 nCellFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
2296     if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
2297         pCell->SetNeedNumberFormat(true);
2298     it = maCells.set(it, nRow, pCell);
2299     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2300 
2301     CellStorageModified();
2302 
2303     AttachNewFormulaCell(it, nRow, *pCell, aNewSharedRows);
2304 }
2305 
2306 ScFormulaCell* ScColumn::SetFormulaCell(
2307     SCROW nRow, ScFormulaCell* pCell, sc::StartListeningType eListenType,
2308     bool bInheritNumFormatIfNeeded )
2309 {
2310     std::vector<SCROW> aNewSharedRows;
2311     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, true);
2312     sal_uInt32 nCellFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
2313     if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && bInheritNumFormatIfNeeded )
2314         pCell->SetNeedNumberFormat(true);
2315     it = maCells.set(it, nRow, pCell);
2316     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2317 
2318     CellStorageModified();
2319 
2320     AttachNewFormulaCell(it, nRow, *pCell, aNewSharedRows, true, eListenType);
2321 
2322     return pCell;
2323 }
2324 
2325 void ScColumn::SetFormulaCell(
2326     sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell,
2327     sc::StartListeningType eListenType,
2328     bool bInheritNumFormatIfNeeded )
2329 {
2330     std::vector<SCROW> aNewSharedRows;
2331     rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow, aNewSharedRows, true);
2332     sal_uInt32 nCellFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
2333     if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && bInheritNumFormatIfNeeded )
2334         pCell->SetNeedNumberFormat(true);
2335     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, pCell);
2336     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
2337         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
2338 
2339     CellStorageModified();
2340 
2341     AttachNewFormulaCell(rBlockPos.miCellPos, nRow, *pCell, aNewSharedRows, true, eListenType);
2342 }
2343 
2344 bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells )
2345 {
2346     if (!GetDoc()->ValidRow(nRow))
2347         return false;
2348 
2349     SCROW nEndRow = nRow + rCells.size() - 1;
2350     if (!GetDoc()->ValidRow(nEndRow))
2351         return false;
2352 
2353     sc::CellStoreType::position_type aPos = maCells.position(nRow);
2354 
2355     // Detach all formula cells that will be overwritten.
2356     std::vector<SCROW> aNewSharedRows;
2357     DetachFormulaCells(aPos, rCells.size(), &aNewSharedRows);
2358 
2359     if (!GetDoc()->IsClipOrUndo())
2360     {
2361         for (size_t i = 0, n = rCells.size(); i < n; ++i)
2362         {
2363             SCROW nThisRow = nRow + i;
2364             sal_uInt32 nFmt = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nThisRow);
2365             if ((nFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
2366                 rCells[i]->SetNeedNumberFormat(true);
2367         }
2368     }
2369 
2370     std::vector<sc::CellTextAttr> aDefaults(rCells.size(), sc::CellTextAttr());
2371     maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end());
2372 
2373     maCells.set(aPos.first, nRow, rCells.begin(), rCells.end());
2374 
2375     CellStorageModified();
2376 
2377     // Reget position_type as the type may have changed to formula, block and
2378     // block size changed, ...
2379     aPos = maCells.position(nRow);
2380     AttachNewFormulaCells(aPos, rCells.size(), aNewSharedRows);
2381 
2382     return true;
2383 }
2384 
2385 svl::SharedString ScColumn::GetSharedString( SCROW nRow ) const
2386 {
2387     sc::CellStoreType::const_position_type aPos = maCells.position(nRow);
2388     switch (aPos.first->type)
2389     {
2390         case sc::element_type_string:
2391             return sc::string_block::at(*aPos.first->data, aPos.second);
2392         case sc::element_type_edittext:
2393         {
2394             const EditTextObject* pObj = sc::edittext_block::at(*aPos.first->data, aPos.second);
2395             std::vector<svl::SharedString> aSSs = pObj->GetSharedStrings();
2396             if (aSSs.size() != 1)
2397                 // We don't handle multiline content for now.
2398                 return svl::SharedString();
2399 
2400             return aSSs[0];
2401         }
2402         break;
2403         default:
2404             ;
2405     }
2406     return svl::SharedString();
2407 }
2408 
2409 namespace {
2410 
2411 class FilterEntriesHandler
2412 {
2413     ScColumn& mrColumn;
2414     ScFilterEntries& mrFilterEntries;
2415 
2416     void processCell(SCROW nRow, ScRefCellValue& rCell)
2417     {
2418         SvNumberFormatter* pFormatter = mrColumn.GetDoc()->GetFormatTable();
2419         OUString aStr;
2420         sal_uLong nFormat = mrColumn.GetNumberFormat(mrColumn.GetDoc()->GetNonThreadedContext(), nRow);
2421         ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrColumn.GetDoc());
2422 
2423         if (rCell.hasString())
2424         {
2425             mrFilterEntries.push_back(ScTypedStrData(aStr));
2426             return;
2427         }
2428 
2429         double fVal = 0.0;
2430 
2431         switch (rCell.meType)
2432         {
2433             case CELLTYPE_VALUE:
2434                 fVal = rCell.mfValue;
2435                 break;
2436 
2437             case CELLTYPE_FORMULA:
2438             {
2439                 ScFormulaCell* pFC = rCell.mpFormula;
2440                 FormulaError nErr = pFC->GetErrCode();
2441                 if (nErr != FormulaError::NONE)
2442                 {
2443                     // Error cell is evaluated as string (for now).
2444                     OUString aErr = ScGlobal::GetErrorString(nErr);
2445                     if (!aErr.isEmpty())
2446                     {
2447                         mrFilterEntries.push_back(ScTypedStrData(aErr));
2448                         return;
2449                     }
2450                 }
2451                 else
2452                     fVal = pFC->GetValue();
2453             }
2454             break;
2455             default:
2456                 ;
2457         }
2458 
2459         SvNumFormatType nType = pFormatter->GetType(nFormat);
2460         bool bDate = false;
2461         if ((nType & SvNumFormatType::DATE) && !(nType & SvNumFormatType::TIME))
2462         {
2463             // special case for date values.  Disregard the time
2464             // element if the number format is of date type.
2465             fVal = rtl::math::approxFloor(fVal);
2466             mrFilterEntries.mbHasDates = true;
2467             bDate = true;
2468             // Convert string representation to ISO 8601 date to eliminate
2469             // locale dependent behaviour later when filtering for dates.
2470             sal_uInt32 nIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_YYYYMMDD);
2471             pFormatter->GetInputLineString( fVal, nIndex, aStr);
2472         }
2473         // maybe extend ScTypedStrData enum is also an option here
2474         mrFilterEntries.push_back(ScTypedStrData(aStr, fVal, ScTypedStrData::Value,bDate));
2475     }
2476 
2477 public:
2478     FilterEntriesHandler(ScColumn& rColumn, ScFilterEntries& rFilterEntries) :
2479         mrColumn(rColumn), mrFilterEntries(rFilterEntries) {}
2480 
2481     void operator() (size_t nRow, double fVal)
2482     {
2483         ScRefCellValue aCell(fVal);
2484         processCell(nRow, aCell);
2485     }
2486 
2487     void operator() (size_t nRow, const svl::SharedString& rStr)
2488     {
2489         ScRefCellValue aCell(&rStr);
2490         processCell(nRow, aCell);
2491     }
2492 
2493     void operator() (size_t nRow, const EditTextObject* p)
2494     {
2495         ScRefCellValue aCell(p);
2496         processCell(nRow, aCell);
2497     }
2498 
2499     void operator() (size_t nRow, const ScFormulaCell* p)
2500     {
2501         ScRefCellValue aCell(const_cast<ScFormulaCell*>(p));
2502         processCell(nRow, aCell);
2503     }
2504 
2505     void operator() (const int nElemType, size_t nRow, size_t /* nDataSize */)
2506     {
2507         if ( nElemType == sc::element_type_empty )
2508         {
2509             if (!mrFilterEntries.mbHasEmpties)
2510             {
2511                 mrFilterEntries.push_back(ScTypedStrData(OUString()));
2512                 mrFilterEntries.mbHasEmpties = true;
2513             }
2514             return;
2515         }
2516         ScRefCellValue aCell = mrColumn.GetCellValue(nRow);
2517         processCell(nRow, aCell);
2518     }
2519 };
2520 
2521 }
2522 
2523 void ScColumn::GetFilterEntries(
2524     sc::ColumnBlockConstPosition& rBlockPos, SCROW nStartRow, SCROW nEndRow,
2525     ScFilterEntries& rFilterEntries )
2526 {
2527     FilterEntriesHandler aFunc(*this, rFilterEntries);
2528     rBlockPos.miCellPos =
2529         sc::ParseAll(rBlockPos.miCellPos, maCells, nStartRow, nEndRow, aFunc, aFunc);
2530 }
2531 
2532 namespace {
2533 
2534 /**
2535  * Iterate over only string and edit-text cells.
2536  */
2537 class StrCellIterator
2538 {
2539     typedef std::pair<sc::CellStoreType::const_iterator,size_t> PosType;
2540     PosType maPos;
2541     sc::CellStoreType::const_iterator miBeg;
2542     sc::CellStoreType::const_iterator miEnd;
2543     const ScDocument* mpDoc;
2544 public:
2545     StrCellIterator(const sc::CellStoreType& rCells, SCROW nStart, const ScDocument* pDoc) :
2546         miBeg(rCells.begin()), miEnd(rCells.end()), mpDoc(pDoc)
2547     {
2548         if (pDoc->ValidRow(nStart))
2549             maPos = rCells.position(nStart);
2550         else
2551             // Make this iterator invalid.
2552             maPos.first = miEnd;
2553     }
2554 
2555     bool valid() const { return (maPos.first != miEnd); }
2556 
2557     bool has() const
2558     {
2559         return (maPos.first->type == sc::element_type_string || maPos.first->type == sc::element_type_edittext);
2560     }
2561 
2562     bool prev()
2563     {
2564         if (!has())
2565         {
2566             // Not in a string block. Move back until we hit a string block.
2567             while (!has())
2568             {
2569                 if (maPos.first == miBeg)
2570                     return false;
2571 
2572                 --maPos.first; // move to the preceding block.
2573                 maPos.second = maPos.first->size - 1; // last cell in the block.
2574             }
2575             return true;
2576         }
2577 
2578         // We are in a string block.
2579         if (maPos.second > 0)
2580         {
2581             // Move back one cell in the same block.
2582             --maPos.second;
2583         }
2584         else
2585         {
2586             // Move back to the preceding string block.
2587             while (true)
2588             {
2589                 if (maPos.first == miBeg)
2590                     return false;
2591 
2592                 // Move to the last cell of the previous block.
2593                 --maPos.first;
2594                 maPos.second = maPos.first->size - 1;
2595                 if (has())
2596                     break;
2597             }
2598         }
2599         return true;
2600     }
2601 
2602     bool next()
2603     {
2604         if (!has())
2605         {
2606             // Not in a string block. Move forward until we hit a string block.
2607             while (!has())
2608             {
2609                 ++maPos.first;
2610                 if (maPos.first == miEnd)
2611                     return false;
2612 
2613                 maPos.second = 0; // First cell in this block.
2614             }
2615             return true;
2616         }
2617 
2618         // We are in a string block.
2619         ++maPos.second;
2620         if (maPos.second >= maPos.first->size)
2621         {
2622             // Move to the next string block.
2623             while (true)
2624             {
2625                 ++maPos.first;
2626                 if (maPos.first == miEnd)
2627                     return false;
2628 
2629                 maPos.second = 0;
2630                 if (has())
2631                     break;
2632             }
2633         }
2634         return true;
2635     }
2636 
2637     OUString get() const
2638     {
2639         switch (maPos.first->type)
2640         {
2641             case sc::element_type_string:
2642                 return sc::string_block::at(*maPos.first->data, maPos.second).getString();
2643             case sc::element_type_edittext:
2644             {
2645                 const EditTextObject* p = sc::edittext_block::at(*maPos.first->data, maPos.second);
2646                 return ScEditUtil::GetString(*p, mpDoc);
2647             }
2648             default:
2649                 ;
2650         }
2651         return OUString();
2652     }
2653 };
2654 
2655 }
2656 
2657 // GetDataEntries - Strings from continuous Section around nRow
2658 
2659 // DATENT_MAX      - max. number of entries in list for auto entry
2660 // DATENT_SEARCH   - max. number of cells that get transparent - new: only count Strings
2661 #define DATENT_MAX      200
2662 #define DATENT_SEARCH   2000
2663 
2664 bool ScColumn::GetDataEntries(
2665     SCROW nStartRow, std::set<ScTypedStrData>& rStrings, bool bLimit ) const
2666 {
2667     // Start at the specified row position, and collect all string values
2668     // going upward and downward directions in parallel. The start position
2669     // cell must be skipped.
2670 
2671     StrCellIterator aItrUp(maCells, nStartRow, GetDoc());
2672     StrCellIterator aItrDown(maCells, nStartRow+1, GetDoc());
2673 
2674     bool bMoveUp = aItrUp.valid();
2675     if (!bMoveUp)
2676         // Current cell is invalid.
2677         return false;
2678 
2679     // Skip the start position cell.
2680     bMoveUp = aItrUp.prev(); // Find the previous string cell position.
2681 
2682     bool bMoveDown = aItrDown.valid();
2683     if (bMoveDown && !aItrDown.has())
2684         bMoveDown = aItrDown.next(); // Find the next string cell position.
2685 
2686     bool bFound = false;
2687     size_t nCellsSearched = 0;
2688     while (bMoveUp || bMoveDown)
2689     {
2690         if (bMoveUp)
2691         {
2692             // Get the current string and move up.
2693             OUString aStr = aItrUp.get();
2694             if (!aStr.isEmpty())
2695             {
2696                 bool bInserted = rStrings.insert(ScTypedStrData(aStr)).second;
2697                 if (bInserted && bLimit && rStrings.size() >= DATENT_MAX)
2698                     return true; // Maximum reached
2699                 bFound = true;
2700             }
2701 
2702             if (bLimit && ++nCellsSearched >= DATENT_SEARCH)
2703                 return bFound; // max search cell count reached.
2704 
2705             bMoveUp = aItrUp.prev();
2706         }
2707 
2708         if (bMoveDown)
2709         {
2710             // Get the current string and move down.
2711             OUString aStr = aItrDown.get();
2712             if (!aStr.isEmpty())
2713             {
2714                 bool bInserted = rStrings.insert(ScTypedStrData(aStr)).second;
2715                 if (bInserted && bLimit && rStrings.size() >= DATENT_MAX)
2716                     return true; // Maximum reached
2717                 bFound = true;
2718             }
2719 
2720             if (bLimit && ++nCellsSearched >= DATENT_SEARCH)
2721                 return bFound; // max search cell count reached.
2722 
2723             bMoveDown = aItrDown.next();
2724         }
2725     }
2726 
2727     return bFound;
2728 }
2729 
2730 namespace {
2731 
2732 class FormulaToValueHandler
2733 {
2734     struct Entry
2735     {
2736         SCROW mnRow;
2737         ScCellValue maValue;
2738 
2739         Entry(SCROW nRow, double f) : mnRow(nRow), maValue(f) {}
2740         Entry(SCROW nRow, const svl::SharedString& rStr) : mnRow(nRow), maValue(rStr) {}
2741     };
2742 
2743     typedef std::vector<Entry> EntriesType;
2744     EntriesType maEntries;
2745 
2746 public:
2747 
2748     void operator() (size_t nRow, const ScFormulaCell* p)
2749     {
2750         ScFormulaCell* p2 = const_cast<ScFormulaCell*>(p);
2751         if (p2->IsValue())
2752             maEntries.emplace_back(nRow, p2->GetValue());
2753         else
2754             maEntries.emplace_back(nRow, p2->GetString());
2755     }
2756 
2757     void commitCells(ScColumn& rColumn)
2758     {
2759         sc::ColumnBlockPosition aBlockPos;
2760         rColumn.InitBlockPosition(aBlockPos);
2761 
2762         for (const Entry& r : maEntries)
2763         {
2764             switch (r.maValue.meType)
2765             {
2766                 case CELLTYPE_VALUE:
2767                     rColumn.SetValue(aBlockPos, r.mnRow, r.maValue.mfValue, false);
2768                 break;
2769                 case CELLTYPE_STRING:
2770                     rColumn.SetRawString(aBlockPos, r.mnRow, *r.maValue.mpString, false);
2771                 break;
2772                 default:
2773                     ;
2774             }
2775         }
2776     }
2777 };
2778 
2779 }
2780 
2781 void ScColumn::RemoveProtected( SCROW nStartRow, SCROW nEndRow )
2782 {
2783     FormulaToValueHandler aFunc;
2784     sc::CellStoreType::const_iterator itPos = maCells.begin();
2785 
2786     ScAttrIterator aAttrIter( pAttrArray.get(), nStartRow, nEndRow, GetDoc()->GetDefPattern() );
2787     SCROW nTop = -1;
2788     SCROW nBottom = -1;
2789     const ScPatternAttr* pPattern = aAttrIter.Next( nTop, nBottom );
2790     while (pPattern)
2791     {
2792         const ScProtectionAttr* pAttr = &pPattern->GetItem(ATTR_PROTECTION);
2793         if ( pAttr->GetHideCell() )
2794             DeleteArea( nTop, nBottom, InsertDeleteFlags::CONTENTS );
2795         else if ( pAttr->GetHideFormula() )
2796         {
2797             // Replace all formula cells between nTop and nBottom with raw value cells.
2798             itPos = sc::ParseFormula(itPos, maCells, nTop, nBottom, aFunc);
2799         }
2800 
2801         pPattern = aAttrIter.Next( nTop, nBottom );
2802     }
2803 
2804     aFunc.commitCells(*this);
2805 }
2806 
2807 void ScColumn::SetError( SCROW nRow, const FormulaError nError)
2808 {
2809     if (!GetDoc()->ValidRow(nRow))
2810         return;
2811 
2812     ScFormulaCell* pCell = new ScFormulaCell(GetDoc(), ScAddress(nCol, nRow, nTab));
2813     pCell->SetErrCode(nError);
2814 
2815     std::vector<SCROW> aNewSharedRows;
2816     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, true);
2817     it = maCells.set(it, nRow, pCell);
2818     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2819 
2820     CellStorageModified();
2821 
2822     AttachNewFormulaCell(it, nRow, *pCell, aNewSharedRows);
2823 }
2824 
2825 void ScColumn::SetRawString( SCROW nRow, const OUString& rStr )
2826 {
2827     if (!GetDoc()->ValidRow(nRow))
2828         return;
2829 
2830     svl::SharedString aSS = GetDoc()->GetSharedStringPool().intern(rStr);
2831     if (!aSS.getData())
2832         return;
2833 
2834     SetRawString(nRow, aSS);
2835 }
2836 
2837 void ScColumn::SetRawString( SCROW nRow, const svl::SharedString& rStr )
2838 {
2839     if (!GetDoc()->ValidRow(nRow))
2840         return;
2841 
2842     std::vector<SCROW> aNewSharedRows;
2843     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, false);
2844     maCells.set(it, nRow, rStr);
2845     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2846 
2847     CellStorageModified();
2848 
2849     StartListeningUnshared( aNewSharedRows);
2850 
2851     BroadcastNewCell(nRow);
2852 }
2853 
2854 void ScColumn::SetRawString(
2855     sc::ColumnBlockPosition& rBlockPos, SCROW nRow, const svl::SharedString& rStr, bool bBroadcast )
2856 {
2857     if (!GetDoc()->ValidRow(nRow))
2858         return;
2859 
2860     std::vector<SCROW> aNewSharedRows;
2861     rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow, aNewSharedRows, false);
2862     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, rStr);
2863     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
2864         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
2865 
2866     CellStorageModified();
2867 
2868     StartListeningUnshared( aNewSharedRows);
2869 
2870     if (bBroadcast)
2871         BroadcastNewCell(nRow);
2872 }
2873 
2874 void ScColumn::SetValue( SCROW nRow, double fVal )
2875 {
2876     if (!GetDoc()->ValidRow(nRow))
2877         return;
2878 
2879     std::vector<SCROW> aNewSharedRows;
2880     sc::CellStoreType::iterator it = GetPositionToInsert(nRow, aNewSharedRows, false);
2881     maCells.set(it, nRow, fVal);
2882     maCellTextAttrs.set(nRow, sc::CellTextAttr());
2883 
2884     CellStorageModified();
2885 
2886     StartListeningUnshared( aNewSharedRows);
2887 
2888     BroadcastNewCell(nRow);
2889 }
2890 
2891 void ScColumn::SetValue(
2892     sc::ColumnBlockPosition& rBlockPos, SCROW nRow, double fVal, bool bBroadcast )
2893 {
2894     if (!GetDoc()->ValidRow(nRow))
2895         return;
2896 
2897     std::vector<SCROW> aNewSharedRows;
2898     rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow, aNewSharedRows, false);
2899     rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, fVal);
2900     rBlockPos.miCellTextAttrPos = maCellTextAttrs.set(
2901         rBlockPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
2902 
2903     CellStorageModified();
2904 
2905     StartListeningUnshared( aNewSharedRows);
2906 
2907     if (bBroadcast)
2908         BroadcastNewCell(nRow);
2909 }
2910 
2911 void ScColumn::GetString( const ScRefCellValue& aCell, SCROW nRow, OUString& rString, const ScInterpreterContext* pContext ) const
2912 {
2913     // ugly hack for ordering problem with GetNumberFormat and missing inherited formats
2914     if (aCell.meType == CELLTYPE_FORMULA)
2915         aCell.mpFormula->MaybeInterpret();
2916 
2917     sal_uInt32 nFormat = GetNumberFormat( pContext ? *pContext : GetDoc()->GetNonThreadedContext(), nRow);
2918     Color* pColor = nullptr;
2919     ScCellFormat::GetString(aCell, nFormat, rString, &pColor,
2920         pContext ? *(pContext->GetFormatTable()) : *(GetDoc()->GetFormatTable()), GetDoc());
2921 }
2922 
2923 double* ScColumn::GetValueCell( SCROW nRow )
2924 {
2925     std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(nRow);
2926     sc::CellStoreType::iterator it = aPos.first;
2927     if (it == maCells.end())
2928         return nullptr;
2929 
2930     if (it->type != sc::element_type_numeric)
2931         return nullptr;
2932 
2933     return &sc::numeric_block::at(*it->data, aPos.second);
2934 }
2935 
2936 void ScColumn::GetInputString( const ScRefCellValue& aCell, SCROW nRow, OUString& rString ) const
2937 {
2938     sal_uLong nFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow);
2939     ScCellFormat::GetInputString(aCell, nFormat, rString, *(GetDoc()->GetFormatTable()), GetDoc());
2940 }
2941 
2942 double ScColumn::GetValue( SCROW nRow ) const
2943 {
2944     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
2945     sc::CellStoreType::const_iterator it = aPos.first;
2946     switch (it->type)
2947     {
2948         case sc::element_type_numeric:
2949             return sc::numeric_block::at(*it->data, aPos.second);
2950         case sc::element_type_formula:
2951         {
2952             const ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
2953             ScFormulaCell* p2 = const_cast<ScFormulaCell*>(p);
2954             return p2->IsValue() ? p2->GetValue() : 0.0;
2955         }
2956         default:
2957             ;
2958     }
2959 
2960     return 0.0;
2961 }
2962 
2963 const EditTextObject* ScColumn::GetEditText( SCROW nRow ) const
2964 {
2965     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
2966     sc::CellStoreType::const_iterator it = aPos.first;
2967     if (it == maCells.end())
2968         return nullptr;
2969 
2970     if (it->type != sc::element_type_edittext)
2971         return nullptr;
2972 
2973     return sc::edittext_block::at(*it->data, aPos.second);
2974 }
2975 
2976 void ScColumn::RemoveEditTextCharAttribs( SCROW nRow, const ScPatternAttr& rAttr )
2977 {
2978     std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(nRow);
2979     sc::CellStoreType::iterator it = aPos.first;
2980     if (it == maCells.end())
2981         return;
2982 
2983     if (it->type != sc::element_type_edittext)
2984         return;
2985 
2986     EditTextObject* p = sc::edittext_block::at(*it->data, aPos.second);
2987     ScEditUtil::RemoveCharAttribs(*p, rAttr);
2988 }
2989 
2990 void ScColumn::GetFormula( SCROW nRow, OUString& rFormula ) const
2991 {
2992     const ScFormulaCell* p = FetchFormulaCell(nRow);
2993     if (p)
2994         p->GetFormula(rFormula);
2995     else
2996         rFormula = EMPTY_OUSTRING;
2997 }
2998 
2999 const ScFormulaCell* ScColumn::GetFormulaCell( SCROW nRow ) const
3000 {
3001     return FetchFormulaCell(nRow);
3002 }
3003 
3004 ScFormulaCell* ScColumn::GetFormulaCell( SCROW nRow )
3005 {
3006     return const_cast<ScFormulaCell*>(FetchFormulaCell(nRow));
3007 }
3008 
3009 CellType ScColumn::GetCellType( SCROW nRow ) const
3010 {
3011     switch (maCells.get_type(nRow))
3012     {
3013         case sc::element_type_numeric:
3014             return CELLTYPE_VALUE;
3015         case sc::element_type_string:
3016             return CELLTYPE_STRING;
3017         case sc::element_type_edittext:
3018             return CELLTYPE_EDIT;
3019         case sc::element_type_formula:
3020             return CELLTYPE_FORMULA;
3021         default:
3022             ;
3023     }
3024     return CELLTYPE_NONE;
3025 }
3026 
3027 namespace {
3028 
3029 /**
3030  * Count the number of all non-empty cells.
3031  */
3032 class CellCounter
3033 {
3034     size_t mnCount;
3035 public:
3036     CellCounter() : mnCount(0) {}
3037 
3038     void operator() (const sc::CellStoreType::value_type& node)
3039     {
3040         if (node.type == sc::element_type_empty)
3041             return;
3042 
3043         mnCount += node.size;
3044     }
3045 
3046     size_t getCount() const { return mnCount; }
3047 };
3048 
3049 }
3050 
3051 SCSIZE ScColumn::GetCellCount() const
3052 {
3053     CellCounter aFunc;
3054     aFunc = std::for_each(maCells.begin(), maCells.end(), aFunc);
3055     return aFunc.getCount();
3056 }
3057 
3058 FormulaError ScColumn::GetErrCode( SCROW nRow ) const
3059 {
3060     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
3061     sc::CellStoreType::const_iterator it = aPos.first;
3062     if (it == maCells.end())
3063         return FormulaError::NONE;
3064 
3065     if (it->type != sc::element_type_formula)
3066         return FormulaError::NONE;
3067 
3068     const ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
3069     return const_cast<ScFormulaCell*>(p)->GetErrCode();
3070 }
3071 
3072 bool ScColumn::HasStringData( SCROW nRow ) const
3073 {
3074     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
3075     switch (aPos.first->type)
3076     {
3077         case sc::element_type_string:
3078         case sc::element_type_edittext:
3079             return true;
3080         case sc::element_type_formula:
3081         {
3082             const ScFormulaCell* p = sc::formula_block::at(*aPos.first->data, aPos.second);
3083             return !const_cast<ScFormulaCell*>(p)->IsValue();
3084         }
3085         default:
3086             ;
3087     }
3088 
3089     return false;
3090 }
3091 
3092 bool ScColumn::HasValueData( SCROW nRow ) const
3093 {
3094     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
3095     switch (aPos.first->type)
3096     {
3097         case sc::element_type_numeric:
3098             return true;
3099         case sc::element_type_formula:
3100         {
3101             const ScFormulaCell* p = sc::formula_block::at(*aPos.first->data, aPos.second);
3102             return const_cast<ScFormulaCell*>(p)->IsValue();
3103         }
3104         default:
3105             ;
3106     }
3107 
3108     return false;
3109 }
3110 
3111 /**
3112  * Return true if there is a string or editcell in the range
3113  */
3114 bool ScColumn::HasStringCells( SCROW nStartRow, SCROW nEndRow ) const
3115 {
3116     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
3117     sc::CellStoreType::const_iterator it = aPos.first;
3118     size_t nOffset = aPos.second;
3119     SCROW nRow = nStartRow;
3120     for (; it != maCells.end() && nRow <= nEndRow; ++it)
3121     {
3122         if (it->type == sc::element_type_string || it->type == sc::element_type_edittext)
3123             return true;
3124 
3125         nRow += it->size - nOffset;
3126         nOffset = 0;
3127     }
3128 
3129     return false;
3130 }
3131 
3132 namespace {
3133 
3134 class MaxStringLenHandler
3135 {
3136     sal_Int32 mnMaxLen;
3137     const ScColumn& mrColumn;
3138     SvNumberFormatter* mpFormatter;
3139     rtl_TextEncoding meCharSet;
3140     bool mbOctetEncoding;
3141 
3142     void processCell(size_t nRow, const ScRefCellValue& rCell)
3143     {
3144         Color* pColor;
3145         OUString aString;
3146         sal_uInt32 nFormat = mrColumn.GetAttr(nRow, ATTR_VALUE_FORMAT).GetValue();
3147         ScCellFormat::GetString(rCell, nFormat, aString, &pColor, *mpFormatter, mrColumn.GetDoc());
3148         sal_Int32 nLen = 0;
3149         if (mbOctetEncoding)
3150         {
3151             OString aOString;
3152             if (!aString.convertToString(&aOString, meCharSet,
3153                         RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
3154                         RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
3155             {
3156                 // TODO: anything? this is used by the dBase export filter
3157                 // that throws an error anyway, but in case of another
3158                 // context we might want to indicate a conversion error
3159                 // early.
3160             }
3161             nLen = aOString.getLength();
3162         }
3163         else
3164             nLen = aString.getLength() * sizeof(sal_Unicode);
3165 
3166         if (mnMaxLen < nLen)
3167             mnMaxLen = nLen;
3168     }
3169 
3170 public:
3171     MaxStringLenHandler(const ScColumn& rColumn, rtl_TextEncoding eCharSet) :
3172         mnMaxLen(0),
3173         mrColumn(rColumn),
3174         mpFormatter(rColumn.GetDoc()->GetFormatTable()),
3175         meCharSet(eCharSet),
3176         mbOctetEncoding(rtl_isOctetTextEncoding(eCharSet))
3177     {
3178     }
3179 
3180     void operator() (size_t nRow, double fVal)
3181     {
3182         ScRefCellValue aCell(fVal);
3183         processCell(nRow, aCell);
3184     }
3185 
3186     void operator() (size_t nRow, const svl::SharedString& rStr)
3187     {
3188         ScRefCellValue aCell(&rStr);
3189         processCell(nRow, aCell);
3190     }
3191 
3192     void operator() (size_t nRow, const EditTextObject* p)
3193     {
3194         ScRefCellValue aCell(p);
3195         processCell(nRow, aCell);
3196     }
3197 
3198     void operator() (size_t nRow, const ScFormulaCell* p)
3199     {
3200         ScRefCellValue aCell(const_cast<ScFormulaCell*>(p));
3201         processCell(nRow, aCell);
3202     }
3203 
3204     sal_Int32 getMaxLen() const { return mnMaxLen; }
3205 };
3206 
3207 }
3208 
3209 sal_Int32 ScColumn::GetMaxStringLen( SCROW nRowStart, SCROW nRowEnd, rtl_TextEncoding eCharSet ) const
3210 {
3211     MaxStringLenHandler aFunc(*this, eCharSet);
3212     sc::ParseAllNonEmpty(maCells.begin(), maCells, nRowStart, nRowEnd, aFunc);
3213     return aFunc.getMaxLen();
3214 }
3215 
3216 namespace {
3217 
3218 class MaxNumStringLenHandler
3219 {
3220     const ScColumn& mrColumn;
3221     SvNumberFormatter* mpFormatter;
3222     sal_Int32 mnMaxLen;
3223     sal_uInt16 mnPrecision;
3224     sal_uInt16 mnMaxGeneralPrecision;
3225     bool mbHaveSigned;
3226 
3227     void processCell(size_t nRow, ScRefCellValue& rCell)
3228     {
3229         sal_uInt16 nCellPrecision = mnMaxGeneralPrecision;
3230         if (rCell.meType == CELLTYPE_FORMULA)
3231         {
3232             if (!rCell.mpFormula->IsValue())
3233                 return;
3234 
3235             // Limit unformatted formula cell precision to precision
3236             // encountered so far, if any, otherwise we'd end up with 15 just
3237             // because of =1/3 ...  If no precision yet then arbitrarily limit
3238             // to a maximum of 4 unless a maximum general precision is set.
3239             if (mnPrecision)
3240                 nCellPrecision = mnPrecision;
3241             else
3242                 nCellPrecision = (mnMaxGeneralPrecision >= 15) ? 4 : mnMaxGeneralPrecision;
3243         }
3244 
3245         double fVal = rCell.getValue();
3246         if (!mbHaveSigned && fVal < 0.0)
3247             mbHaveSigned = true;
3248 
3249         OUString aString;
3250         OUString aSep;
3251         sal_uInt16 nPrec;
3252         sal_uInt32 nFormat =
3253                 mrColumn.GetAttr(nRow, ATTR_VALUE_FORMAT).GetValue();
3254         if (nFormat % SV_COUNTRY_LANGUAGE_OFFSET)
3255         {
3256             aSep = mpFormatter->GetFormatDecimalSep(nFormat);
3257             ScCellFormat::GetInputString(rCell, nFormat, aString, *mpFormatter, mrColumn.GetDoc());
3258             const SvNumberformat* pEntry = mpFormatter->GetEntry(nFormat);
3259             if (pEntry)
3260             {
3261                 bool bThousand, bNegRed;
3262                 sal_uInt16 nLeading;
3263                 pEntry->GetFormatSpecialInfo(bThousand, bNegRed, nPrec, nLeading);
3264             }
3265             else
3266                 nPrec = mpFormatter->GetFormatPrecision(nFormat);
3267         }
3268         else
3269         {
3270             if (mnPrecision >= mnMaxGeneralPrecision)
3271                 return;     // early bail out for nothing changes here
3272 
3273             if (!fVal)
3274             {
3275                 // 0 doesn't change precision, but set a maximum length if none yet.
3276                 if (!mnMaxLen)
3277                     mnMaxLen = 1;
3278                 return;
3279             }
3280 
3281             // Simple number string with at most 15 decimals and trailing
3282             // decimal zeros eliminated.
3283             aSep = ".";
3284             aString = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_F, nCellPrecision, '.', true);
3285             nPrec = SvNumberFormatter::UNLIMITED_PRECISION;
3286         }
3287 
3288         sal_Int32 nLen = aString.getLength();
3289         if (nLen <= 0)
3290             // Ignore empty string.
3291             return;
3292 
3293         if (nPrec == SvNumberFormatter::UNLIMITED_PRECISION && mnPrecision < mnMaxGeneralPrecision)
3294         {
3295             if (nFormat % SV_COUNTRY_LANGUAGE_OFFSET)
3296             {
3297                 // For some reason we couldn't obtain a precision from the
3298                 // format, retry with simple number string.
3299                 aSep = ".";
3300                 aString = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_F, nCellPrecision, '.', true);
3301                 nLen = aString.getLength();
3302             }
3303             sal_Int32 nSep = aString.indexOf( aSep);
3304             if (nSep != -1)
3305                 nPrec = aString.getLength() - nSep - 1;
3306 
3307         }
3308 
3309         if (nPrec != SvNumberFormatter::UNLIMITED_PRECISION && nPrec > mnPrecision)
3310             mnPrecision = nPrec;
3311 
3312         if (mnPrecision)
3313         {   // less than mnPrecision in string => widen it
3314             // more => shorten it
3315             sal_Int32 nTmp = aString.indexOf(aSep);
3316             if ( nTmp == -1 )
3317                 nLen += mnPrecision + aSep.getLength();
3318             else
3319             {
3320                 nTmp = aString.getLength() - (nTmp + aSep.getLength());
3321                 if (nTmp != mnPrecision)
3322                     nLen += mnPrecision - nTmp;
3323                     // nPrecision > nTmp : nLen + Diff
3324                     // nPrecision < nTmp : nLen - Diff
3325             }
3326         }
3327 
3328         // Enlarge for sign if necessary. Bear in mind that
3329         // GetMaxNumberStringLen() is for determining dBase decimal field width
3330         // and precision where the overall field width must include the sign.
3331         // Fitting -1 into "#.##" (width 4, 2 decimals) does not work.
3332         if (mbHaveSigned && fVal >= 0.0)
3333             ++nLen;
3334 
3335         if (mnMaxLen < nLen)
3336             mnMaxLen = nLen;
3337     }
3338 
3339 public:
3340     MaxNumStringLenHandler(const ScColumn& rColumn, sal_uInt16 nMaxGeneralPrecision) :
3341         mrColumn(rColumn), mpFormatter(rColumn.GetDoc()->GetFormatTable()),
3342         mnMaxLen(0), mnPrecision(0), mnMaxGeneralPrecision(nMaxGeneralPrecision),
3343         mbHaveSigned(false)
3344     {
3345         // Limit the decimals passed to doubleToUString().
3346         // Also, the dBaseIII maximum precision is 15.
3347         if (mnMaxGeneralPrecision > 15)
3348             mnMaxGeneralPrecision = 15;
3349     }
3350 
3351     void operator() (size_t nRow, double fVal)
3352     {
3353         ScRefCellValue aCell(fVal);
3354         processCell(nRow, aCell);
3355     }
3356 
3357     void operator() (size_t nRow, const ScFormulaCell* p)
3358     {
3359         ScRefCellValue aCell(const_cast<ScFormulaCell*>(p));
3360         processCell(nRow, aCell);
3361     }
3362 
3363     sal_Int32 getMaxLen() const { return mnMaxLen; }
3364 
3365     sal_uInt16 getPrecision() const { return mnPrecision; }
3366 };
3367 
3368 }
3369 
3370 sal_Int32 ScColumn::GetMaxNumberStringLen(
3371     sal_uInt16& nPrecision, SCROW nRowStart, SCROW nRowEnd ) const
3372 {
3373     sal_uInt16 nMaxGeneralPrecision = GetDoc()->GetDocOptions().GetStdPrecision();
3374     MaxNumStringLenHandler aFunc(*this, nMaxGeneralPrecision);
3375     sc::ParseFormulaNumeric(maCells.begin(), maCells, nRowStart, nRowEnd, aFunc);
3376     nPrecision = aFunc.getPrecision();
3377     return aFunc.getMaxLen();
3378 }
3379 
3380 namespace {
3381 
3382 class GroupFormulaCells
3383 {
3384     std::vector<ScAddress>* mpGroupPos;
3385 
3386 public:
3387     explicit GroupFormulaCells(std::vector<ScAddress>* pGroupPos)
3388         : mpGroupPos(pGroupPos) {}
3389 
3390     void operator() (sc::CellStoreType::value_type& node)
3391     {
3392         if (node.type != sc::element_type_formula)
3393             // We are only interested in formula cells.
3394             return;
3395 
3396         size_t nRow = node.position; // start row position.
3397 
3398         sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
3399         sc::formula_block::iterator itEnd = sc::formula_block::end(*node.data);
3400 
3401         // This block should never be empty.
3402 
3403         ScFormulaCell* pPrev = *it;
3404         ScFormulaCellGroupRef xPrevGrp = pPrev->GetCellGroup();
3405         if (xPrevGrp)
3406         {
3407             // Move to the cell after the last cell of the current group.
3408             std::advance(it, xPrevGrp->mnLength);
3409             nRow += xPrevGrp->mnLength;
3410         }
3411         else
3412         {
3413             ++it;
3414             ++nRow;
3415         }
3416 
3417         ScFormulaCell* pCur = nullptr;
3418         ScFormulaCellGroupRef xCurGrp;
3419         for (; it != itEnd; pPrev = pCur, xPrevGrp = xCurGrp)
3420         {
3421             pCur = *it;
3422             xCurGrp = pCur->GetCellGroup();
3423 
3424             ScFormulaCell::CompareState eCompState = pPrev->CompareByTokenArray(*pCur);
3425             if (eCompState == ScFormulaCell::NotEqual)
3426             {
3427                 // different formula tokens.
3428                 if (xCurGrp)
3429                 {
3430                     // Move to the cell after the last cell of the current group.
3431                     if (xCurGrp->mnLength > std::distance(it, itEnd))
3432                         throw css::lang::IllegalArgumentException();
3433                     std::advance(it, xCurGrp->mnLength);
3434                     nRow += xCurGrp->mnLength;
3435                 }
3436                 else
3437                 {
3438                     ++it;
3439                     ++nRow;
3440                 }
3441 
3442                 continue;
3443             }
3444 
3445             // Formula tokens equal those of the previous formula cell or cell group.
3446             if (xPrevGrp)
3447             {
3448                 // Previous cell is a group.
3449                 if (xCurGrp)
3450                 {
3451                     // The current cell is a group.  Merge these two groups.
3452                     xPrevGrp->mnLength += xCurGrp->mnLength;
3453                     pCur->SetCellGroup(xPrevGrp);
3454                     sc::formula_block::iterator itGrpEnd = it;
3455                     if (xCurGrp->mnLength > std::distance(itGrpEnd, itEnd))
3456                         throw css::lang::IllegalArgumentException();
3457                     std::advance(itGrpEnd, xCurGrp->mnLength);
3458                     for (++it; it != itGrpEnd; ++it)
3459                     {
3460                         ScFormulaCell* pCell = *it;
3461                         pCell->SetCellGroup(xPrevGrp);
3462                     }
3463                     nRow += xCurGrp->mnLength;
3464                 }
3465                 else
3466                 {
3467                     // Add this cell to the previous group.
3468                     pCur->SetCellGroup(xPrevGrp);
3469                     ++xPrevGrp->mnLength;
3470                     ++nRow;
3471                     ++it;
3472                 }
3473 
3474             }
3475             else if (xCurGrp)
3476             {
3477                 // Previous cell is a regular cell and current cell is a group.
3478                 nRow += xCurGrp->mnLength;
3479                 if (xCurGrp->mnLength > std::distance(it, itEnd))
3480                     throw css::lang::IllegalArgumentException();
3481                 std::advance(it, xCurGrp->mnLength);
3482                 pPrev->SetCellGroup(xCurGrp);
3483                 xCurGrp->mpTopCell = pPrev;
3484                 ++xCurGrp->mnLength;
3485                 xPrevGrp = xCurGrp;
3486             }
3487             else
3488             {
3489                 // Both previous and current cells are regular cells.
3490                 assert(pPrev->aPos.Row() == static_cast<SCROW>(nRow - 1));
3491                 xPrevGrp = pPrev->CreateCellGroup(2, eCompState == ScFormulaCell::EqualInvariant);
3492                 pCur->SetCellGroup(xPrevGrp);
3493                 ++nRow;
3494                 ++it;
3495             }
3496 
3497             if (mpGroupPos)
3498                 mpGroupPos->push_back(pCur->aPos);
3499 
3500             pCur = pPrev;
3501             xCurGrp = xPrevGrp;
3502         }
3503     }
3504 };
3505 
3506 }
3507 
3508 void ScColumn::RegroupFormulaCells( std::vector<ScAddress>* pGroupPos )
3509 {
3510     // re-build formula groups.
3511     std::for_each(maCells.begin(), maCells.end(), GroupFormulaCells(pGroupPos));
3512 }
3513 
3514 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3515