Branch libreoffice-24-8-3
[LibreOffice.git] / sc / inc / attarray.hxx
blob6de20af590a213d7e88be91555cbb7b10002e02d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #pragma once
22 #include "global.hxx"
23 #include "attrib.hxx"
24 #include "document.hxx"
25 #include "patattr.hxx"
27 #include <algorithm>
28 #include <optional>
30 #include <svl/itemset.hxx>
32 class ScDocument;
33 class ScEditDataArray;
34 class ScMarkArray;
35 class ScStyleSheet;
36 class ScFlatBoolRowSegments;
38 class ScItemPoolCache;
39 class SfxStyleSheetBase;
40 class SvxBoxItem;
41 class SvxBoxInfoItem;
43 namespace editeng { class SvxBorderLine; }
45 #define SC_LINE_EMPTY 0
46 #define SC_LINE_SET 1
47 #define SC_LINE_DONTCARE 2
49 #define SC_ATTRARRAY_DELTA 4
51 #define DEBUG_SC_TESTATTRARRAY 0
53 struct ScLineFlags
55 sal_uInt8 nLeft;
56 sal_uInt8 nRight;
57 sal_uInt8 nTop;
58 sal_uInt8 nBottom;
59 sal_uInt8 nHori;
60 sal_uInt8 nVert;
62 ScLineFlags() : nLeft(SC_LINE_EMPTY),nRight(SC_LINE_EMPTY),nTop(SC_LINE_EMPTY),
63 nBottom(SC_LINE_EMPTY),nHori(SC_LINE_EMPTY),nVert(SC_LINE_EMPTY) {}
66 struct ScMergePatternState
68 std::optional<SfxItemSet> pItemSet;
69 CellAttributeHolder aOld1; ///< existing objects, temporary
70 CellAttributeHolder aOld2;
72 bool mbValidPatternId;
73 sal_uInt64 mnPatternId;
75 ScMergePatternState() : aOld1(), aOld2(),
76 mbValidPatternId(true), mnPatternId(0) {}
79 // we store an array of these where the pattern applies to all rows up till nEndRow
80 class ScAttrEntry
82 CellAttributeHolder aPattern;
84 public:
85 ScAttrEntry()
86 : aPattern()
87 , nEndRow(0)
90 SCROW nEndRow;
92 const CellAttributeHolder& getCellAttributeHolder() const { return aPattern; }
93 void setCellAttributeHolder(const CellAttributeHolder& rNew) { aPattern = rNew; }
95 const ScPatternAttr* getScPatternAttr() const { return aPattern.getScPatternAttr(); }
96 void setScPatternAttr(const ScPatternAttr* pNew, bool bPassingOwnership = false) { aPattern.setScPatternAttr(pNew, bPassingOwnership); }
98 bool operator==( const ScAttrEntry& other ) const
100 return nEndRow == other.nEndRow && CellAttributeHolder::areSame(&aPattern, &other.aPattern);
104 class ScAttrArray
106 private:
107 SCCOL nCol;
108 SCTAB nTab;
109 ScDocument& rDocument;
111 std::vector<ScAttrEntry> mvData;
113 friend class ScDocument; // for FillInfo
114 friend class ScDocumentIterator;
115 friend class ScAttrIterator;
116 friend class ScHorizontalAttrIterator;
118 bool ApplyFrame( const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner,
119 SCROW nStartRow, SCROW nEndRow,
120 bool bLeft, SCCOL nDistRight, bool bTop, SCROW nDistBottom );
122 void RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
123 const ScPatternAttr* pPattern, ScEditDataArray* pDataArray );
124 void SetDefaultIfNotInit( SCSIZE nNeeded = 1 );
125 bool HasAttrib_Impl(const ScPatternAttr* pPattern, HasAttrFlags nMask, SCROW nRow1, SCROW nRow2, SCSIZE i) const;
127 ScAttrArray(const ScAttrArray&) = delete;
128 ScAttrArray& operator=(const ScAttrArray&) = delete;
130 public:
131 ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument& rDoc, ScAttrArray* pNextColAttrArray );
132 ~ScAttrArray();
134 ScDocument& GetDoc() { return rDocument; }
135 const ScDocument& GetDoc() const { return rDocument; }
136 void SetTab(SCTAB nNewTab) { nTab = nNewTab; }
137 void SetCol(SCCOL nNewCol) { nCol = nNewCol; }
138 #if DEBUG_SC_TESTATTRARRAY
139 void TestData() const;
140 #endif
141 void Reset(const CellAttributeHolder& rPattern);
142 bool Concat(SCSIZE nPos);
144 const ScPatternAttr* GetPattern( SCROW nRow ) const;
146 /** Returns if you search for attributes at nRow the range from rStartRow
147 to rEndRow where that attribute combination (ScPatternAttr) is applied.
148 The next ScPatternAttr different from this one starts at rEndRow+1
149 (if that is <= MAXROW).
151 const ScPatternAttr* GetPatternRange( SCROW& rStartRow, SCROW& rEndRow, SCROW nRow ) const;
153 void MergePatternArea( SCROW nStartRow, SCROW nEndRow, ScMergePatternState& rState, bool bDeep ) const;
155 void MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
156 SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const;
157 void ApplyBlockFrame(const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner,
158 SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight);
160 void SetPattern( SCROW nRow, const CellAttributeHolder& rPattern )
161 { SetPatternAreaImpl(nRow, nRow, rPattern, nullptr); }
162 void SetPatternArea( SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rPattern, ScEditDataArray* pDataArray = nullptr)
163 { SetPatternAreaImpl(nStartRow, nEndRow, rPattern, pDataArray); }
164 void ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle );
165 void ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, ScItemPoolCache& rCache,
166 ScEditDataArray* pDataArray = nullptr, bool* const pIsChanged = nullptr );
167 void SetAttrEntries(std::vector<ScAttrEntry> && vNewData);
168 void ApplyLineStyleArea( SCROW nStartRow, SCROW nEndRow,
169 const ::editeng::SvxBorderLine* pLine, bool bColorOnly );
171 void AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex );
172 /// if nIndex == 0, remove all conditional format data
173 void RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex );
175 void ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich );
176 void ChangeIndent( SCROW nStartRow, SCROW nEndRow, bool bIncrement );
178 /// Including current, may return -1
179 SCROW GetNextUnprotected( SCROW nRow, bool bUp ) const;
181 /// May return -1 if not found
182 SCROW SearchStyle(
183 SCROW nRow, const ScStyleSheet* pSearchStyle, bool bUp,
184 const ScMarkArray* pMarkArray = nullptr) const;
186 bool SearchStyleRange(
187 SCROW& rRow, SCROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp,
188 const ScMarkArray* pMarkArray = nullptr) const;
190 bool ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags );
191 bool RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags );
193 bool Search( SCROW nRow, SCSIZE& nIndex, std::optional<SCROW> nIndexHint = {} ) const;
195 bool HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const;
196 bool HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const;
197 bool IsMerged( SCROW nRow ) const;
198 bool ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
199 SCCOL& rPaintCol, SCROW& rPaintRow,
200 bool bRefresh );
201 void RemoveAreaMerge( SCROW nStartRow, SCROW nEndRow );
203 void FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset );
204 bool IsStyleSheetUsed( const ScStyleSheet& rStyle ) const;
206 void SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rWantedPattern );
207 void CopyAreaSafe( SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& rAttrArray );
209 bool IsEmpty() const;
211 bool GetFirstVisibleAttr( SCROW& rFirstRow ) const;
212 bool GetLastVisibleAttr( SCROW& rLastRow, SCROW nLastData, bool bSkipEmpty ) const;
213 bool HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const;
214 bool IsVisibleEqual( const ScAttrArray& rOther,
215 SCROW nStartRow, SCROW nEndRow ) const;
216 bool IsAllEqual( const ScAttrArray& rOther, SCROW nStartRow, SCROW nEndRow ) const;
218 bool TestInsertCol( SCROW nStartRow, SCROW nEndRow) const;
219 bool TestInsertRow( SCSIZE nSize ) const;
220 void InsertRow( SCROW nStartRow, SCSIZE nSize );
221 void DeleteRow( SCROW nStartRow, SCSIZE nSize );
222 void DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex );
223 void DeleteArea( SCROW nStartRow, SCROW nEndRow );
224 void MoveTo( SCROW nStartRow, SCROW nEndRow, ScAttrArray& rAttrArray );
225 void CopyArea(
226 SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& rAttrArray, ScMF nStripFlags = ScMF::NONE) const;
228 void DeleteHardAttr( SCROW nStartRow, SCROW nEndRow );
230 /* i123909: Pre-calculate needed memory, and pre-reserve enough memory */
231 bool Reserve( SCSIZE nReserve );
232 SCSIZE Count() const { return mvData.size(); }
233 SCSIZE Count( SCROW nRow1, SCROW nRow2 ) const;
235 private:
236 const ScPatternAttr* SetPatternAreaImpl(
237 SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rPattern, ScEditDataArray* pDataArray = nullptr);
240 // Iterator for attributes
242 class ScAttrIterator
244 const ScAttrArray* pArray;
245 const ScPatternAttr* pDefPattern;
246 SCSIZE nPos;
247 SCROW nRow;
248 SCROW nEndRow;
249 public:
250 inline ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd, const ScPatternAttr* pDefaultPattern );
251 inline const ScPatternAttr* Next( SCROW& rTop, SCROW& rBottom );
252 inline const ScPatternAttr* Resync( SCROW nRow, SCROW& rTop, SCROW& rBottom );
253 SCROW GetNextRow() const { return nRow; }
256 inline ScAttrIterator::ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd, const ScPatternAttr* pDefaultPattern ) :
257 pArray( pNewArray ),
258 pDefPattern( pDefaultPattern ),
259 nRow( nStart ),
260 nEndRow( nEnd )
262 if ( pArray->Count() )
264 if ( nStart > 0 )
265 pArray->Search( nStart, nPos );
266 else
267 nPos = 0;
269 else
270 nPos = 0;
273 inline const ScPatternAttr* ScAttrIterator::Next( SCROW& rTop, SCROW& rBottom )
275 const ScPatternAttr* pRet;
276 if ( !pArray->Count() )
278 if ( !nPos )
280 ++nPos;
281 if ( nRow > pArray->GetDoc().MaxRow())
282 return nullptr;
283 rTop = nRow;
284 rBottom = std::min( nEndRow, pArray->GetDoc().MaxRow());
285 nRow = rBottom + 1;
286 return pDefPattern;
288 return nullptr;
291 if ( nPos < pArray->Count() && nRow <= nEndRow )
293 rTop = nRow;
294 rBottom = std::min( pArray->mvData[nPos].nEndRow, nEndRow );
295 pRet = pArray->mvData[nPos].getScPatternAttr();
296 nRow = rBottom + 1;
297 ++nPos;
299 else
300 pRet = nullptr;
301 return pRet;
304 inline const ScPatternAttr* ScAttrIterator::Resync( SCROW nRowP, SCROW& rTop, SCROW& rBottom )
306 nRow = nRowP;
307 if ( !pArray->Count() )
309 nPos = 0;
310 return Next( rTop, rBottom );
312 // Chances are high that the pattern changed on nRowP introduced a span
313 // starting right there. Assume that Next() was called so nPos already
314 // advanced. Another high chance is that the change extended a previous or
315 // next pattern. In all these cases we don't need to search.
316 if (3 <= nPos && nPos <= pArray->Count() && pArray->mvData[nPos-3].nEndRow < nRowP &&
317 nRowP <= pArray->mvData[nPos-2].nEndRow)
318 nPos -= 2;
319 else if (2 <= nPos && nPos <= pArray->Count() && pArray->mvData[nPos-2].nEndRow < nRowP &&
320 nRowP <= pArray->mvData[nPos-1].nEndRow)
321 --nPos;
322 else if (pArray->Count() > 0 && nRowP <= pArray->mvData[0].nEndRow)
323 nPos = 0;
324 else
325 pArray->Search( nRowP, nPos );
326 return Next( rTop, rBottom);
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */