/src/libreoffice/sc/inc/attarray.hxx
Line | Count | Source |
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 | | #pragma once |
21 | | |
22 | | #include "global.hxx" |
23 | | #include "attrib.hxx" |
24 | | #include "document.hxx" |
25 | | #include "patattr.hxx" |
26 | | |
27 | | #include <algorithm> |
28 | | #include <optional> |
29 | | |
30 | | #include <svl/itemset.hxx> |
31 | | |
32 | | class ScEditDataArray; |
33 | | class ScMarkArray; |
34 | | class ScStyleSheet; |
35 | | class ScFlatBoolRowSegments; |
36 | | |
37 | | class ScItemPoolCache; |
38 | | class SfxStyleSheetBase; |
39 | | class SvxBoxItem; |
40 | | class SvxBoxInfoItem; |
41 | | |
42 | | namespace editeng { class SvxBorderLine; } |
43 | | |
44 | 0 | #define SC_LINE_EMPTY 0 |
45 | 0 | #define SC_LINE_SET 1 |
46 | 0 | #define SC_LINE_DONTCARE 2 |
47 | | |
48 | 5.51M | #define SC_ATTRARRAY_DELTA 4 |
49 | | |
50 | | #define DEBUG_SC_TESTATTRARRAY 0 |
51 | | |
52 | | struct ScLineFlags |
53 | | { |
54 | | sal_uInt8 nLeft; |
55 | | sal_uInt8 nRight; |
56 | | sal_uInt8 nTop; |
57 | | sal_uInt8 nBottom; |
58 | | sal_uInt8 nHori; |
59 | | sal_uInt8 nVert; |
60 | | |
61 | 0 | ScLineFlags() : nLeft(SC_LINE_EMPTY),nRight(SC_LINE_EMPTY),nTop(SC_LINE_EMPTY), |
62 | 0 | nBottom(SC_LINE_EMPTY),nHori(SC_LINE_EMPTY),nVert(SC_LINE_EMPTY) {} |
63 | | }; |
64 | | |
65 | | struct ScMergePatternState |
66 | | { |
67 | | std::optional<SfxItemSet> pItemSet; |
68 | | CellAttributeHolder aOld1; ///< existing objects, temporary |
69 | | CellAttributeHolder aOld2; |
70 | | |
71 | | bool mbValidPatternId; |
72 | | sal_uInt64 mnPatternId; |
73 | | |
74 | 2.12k | ScMergePatternState() : aOld1(), aOld2(), |
75 | 2.12k | mbValidPatternId(true), mnPatternId(0) {} |
76 | | }; |
77 | | |
78 | | // we store an array of these where the pattern applies to all rows up till nEndRow |
79 | | class ScAttrEntry |
80 | | { |
81 | | CellAttributeHolder aPattern; |
82 | | |
83 | | public: |
84 | | ScAttrEntry() |
85 | 172M | : aPattern() |
86 | 172M | , nEndRow(0) |
87 | 172M | {} |
88 | | |
89 | | SCROW nEndRow; |
90 | | |
91 | 7.99M | const CellAttributeHolder& getCellAttributeHolder() const { return aPattern; } |
92 | 1.99M | void setCellAttributeHolder(const CellAttributeHolder& rNew) { aPattern = rNew; } |
93 | | |
94 | 336M | const ScPatternAttr* getScPatternAttr() const { return aPattern.getScPatternAttr(); } |
95 | 173M | void setScPatternAttr(const ScPatternAttr* pNew, bool bPassingOwnership = false) { aPattern.setScPatternAttr(pNew, bPassingOwnership); } |
96 | | |
97 | | bool operator==( const ScAttrEntry& other ) const |
98 | 144M | { |
99 | 144M | return nEndRow == other.nEndRow && CellAttributeHolder::areSame(&aPattern, &other.aPattern); |
100 | 144M | } |
101 | | }; |
102 | | |
103 | | class ScAttrArray |
104 | | { |
105 | | private: |
106 | | SCCOL nCol; |
107 | | SCTAB nTab; |
108 | | ScDocument& rDocument; |
109 | | |
110 | | std::vector<ScAttrEntry> mvData; |
111 | | |
112 | | friend class ScDocument; // for FillInfo |
113 | | friend class ScDocumentIterator; |
114 | | friend class ScAttrIterator; |
115 | | friend class ScHorizontalAttrIterator; |
116 | | |
117 | | bool ApplyFrame( const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner, |
118 | | SCROW nStartRow, SCROW nEndRow, |
119 | | bool bLeft, SCCOL nDistRight, bool bTop, SCROW nDistBottom ); |
120 | | |
121 | | void RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow, |
122 | | const ScPatternAttr* pPattern, ScEditDataArray* pDataArray ); |
123 | | void SetDefaultIfNotInit( SCSIZE nNeeded = 1 ); |
124 | | bool HasAttrib_Impl(const ScPatternAttr* pPattern, HasAttrFlags nMask, SCROW nRow1, SCROW nRow2, SCSIZE i) const; |
125 | | |
126 | | ScAttrArray(const ScAttrArray&) = delete; |
127 | | ScAttrArray& operator=(const ScAttrArray&) = delete; |
128 | | |
129 | | public: |
130 | | ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument& rDoc, ScAttrArray* pNextColAttrArray ); |
131 | | ~ScAttrArray(); |
132 | | |
133 | 698M | ScDocument& GetDoc() { return rDocument; } |
134 | 2.21M | const ScDocument& GetDoc() const { return rDocument; } |
135 | 1.45M | void SetTab(SCTAB nNewTab) { nTab = nNewTab; } |
136 | 0 | void SetCol(SCCOL nNewCol) { nCol = nNewCol; } |
137 | | #if DEBUG_SC_TESTATTRARRAY |
138 | | void TestData() const; |
139 | | #endif |
140 | | void Reset(const CellAttributeHolder& rPattern); |
141 | | bool Concat(SCSIZE nPos); |
142 | | |
143 | | const ScPatternAttr* GetPattern( SCROW nRow ) const; |
144 | | |
145 | | /** Returns if you search for attributes at nRow the range from rStartRow |
146 | | to rEndRow where that attribute combination (ScPatternAttr) is applied. |
147 | | The next ScPatternAttr different from this one starts at rEndRow+1 |
148 | | (if that is <= MAXROW). |
149 | | */ |
150 | | const ScPatternAttr* GetPatternRange( SCROW& rStartRow, SCROW& rEndRow, SCROW nRow ) const; |
151 | | |
152 | | void MergePatternArea( SCROW nStartRow, SCROW nEndRow, ScMergePatternState& rState, bool bDeep ) const; |
153 | | |
154 | | void MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags, |
155 | | SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const; |
156 | | void ApplyBlockFrame(const SvxBoxItem& rLineOuter, const SvxBoxInfoItem* pLineInner, |
157 | | SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight); |
158 | | |
159 | | void SetPattern( SCROW nRow, const CellAttributeHolder& rPattern ) |
160 | 3.45M | { SetPatternAreaImpl(nRow, nRow, rPattern, nullptr); } |
161 | | void SetPatternArea( SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rPattern, ScEditDataArray* pDataArray = nullptr) |
162 | 24.3M | { SetPatternAreaImpl(nStartRow, nEndRow, rPattern, pDataArray); } |
163 | | void ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle ); |
164 | | void ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, ScItemPoolCache& rCache, |
165 | | ScEditDataArray* pDataArray = nullptr, bool* const pIsChanged = nullptr ); |
166 | | void SetAttrEntries(std::vector<ScAttrEntry> && vNewData); |
167 | | void ApplyLineStyleArea( SCROW nStartRow, SCROW nEndRow, |
168 | | const ::editeng::SvxBorderLine* pLine, bool bColorOnly ); |
169 | | |
170 | | void AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex ); |
171 | | /// if nIndex == 0, remove all conditional format data |
172 | | void RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex ); |
173 | | |
174 | | void ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich ); |
175 | | void ChangeIndent( SCROW nStartRow, SCROW nEndRow, bool bIncrement ); |
176 | | |
177 | | /// Including current, may return -1 |
178 | | SCROW GetNextUnprotected( SCROW nRow, bool bUp ) const; |
179 | | |
180 | | /// May return -1 if not found |
181 | | SCROW SearchStyle( |
182 | | SCROW nRow, const ScStyleSheet* pSearchStyle, bool bUp, |
183 | | const ScMarkArray* pMarkArray = nullptr) const; |
184 | | |
185 | | bool SearchStyleRange( |
186 | | SCROW& rRow, SCROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp, |
187 | | const ScMarkArray* pMarkArray = nullptr) const; |
188 | | |
189 | | bool ApplyFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags ); |
190 | | bool RemoveFlags( SCROW nStartRow, SCROW nEndRow, ScMF nFlags ); |
191 | | |
192 | | bool Search( SCROW nRow, SCSIZE& nIndex, std::optional<SCROW> nIndexHint = {} ) const; |
193 | | |
194 | | bool HasAttrib( SCROW nRow1, SCROW nRow2, HasAttrFlags nMask ) const; |
195 | | bool HasAttrib( SCROW nRow, HasAttrFlags nMask, SCROW* nStartRow = nullptr, SCROW* nEndRow = nullptr ) const; |
196 | | bool IsMerged( SCROW nRow ) const; |
197 | | bool ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow, |
198 | | SCCOL& rPaintCol, SCROW& rPaintRow, |
199 | | bool bRefresh ); |
200 | | void RemoveAreaMerge( SCROW nStartRow, SCROW nEndRow ); |
201 | | |
202 | | void FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset ); |
203 | | bool IsStyleSheetUsed( const ScStyleSheet& rStyle ) const; |
204 | | |
205 | | void SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rWantedPattern ); |
206 | | void CopyAreaSafe( SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& rAttrArray ); |
207 | | |
208 | | bool IsEmpty() const; |
209 | | |
210 | | bool GetFirstVisibleAttr( SCROW& rFirstRow ) const; |
211 | | bool GetLastVisibleAttr( SCROW& rLastRow, SCROW nLastData, bool bSkipEmpty ) const; |
212 | | bool HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const; |
213 | | bool IsVisibleEqual( const ScAttrArray& rOther, |
214 | | SCROW nStartRow, SCROW nEndRow ) const; |
215 | | bool IsAllEqual( const ScAttrArray& rOther, SCROW nStartRow, SCROW nEndRow ) const; |
216 | | |
217 | | bool TestInsertCol( SCROW nStartRow, SCROW nEndRow) const; |
218 | | bool TestInsertRow( SCSIZE nSize ) const; |
219 | | void InsertRow( SCROW nStartRow, SCSIZE nSize ); |
220 | | void DeleteRow( SCROW nStartRow, SCSIZE nSize ); |
221 | | void DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex ); |
222 | | void DeleteArea( SCROW nStartRow, SCROW nEndRow ); |
223 | | void MoveTo( SCROW nStartRow, SCROW nEndRow, ScAttrArray& rAttrArray ); |
224 | | void CopyArea( |
225 | | SCROW nStartRow, SCROW nEndRow, tools::Long nDy, ScAttrArray& rAttrArray, ScMF nStripFlags = ScMF::NONE) const; |
226 | | |
227 | | void DeleteHardAttr( SCROW nStartRow, SCROW nEndRow ); |
228 | | |
229 | | /* i123909: Pre-calculate needed memory, and pre-reserve enough memory */ |
230 | | bool Reserve( SCSIZE nReserve ); |
231 | 28.3M | SCSIZE Count() const { return mvData.size(); } |
232 | | SCSIZE Count( SCROW nRow1, SCROW nRow2 ) const; |
233 | | |
234 | | private: |
235 | | const ScPatternAttr* SetPatternAreaImpl( |
236 | | SCROW nStartRow, SCROW nEndRow, const CellAttributeHolder& rPattern, ScEditDataArray* pDataArray = nullptr); |
237 | | }; |
238 | | |
239 | | // Iterator for attributes |
240 | | |
241 | | class ScAttrIterator |
242 | | { |
243 | | const ScAttrArray* pArray; |
244 | | const ScPatternAttr* pDefPattern; |
245 | | SCSIZE nPos; |
246 | | SCROW nRow; |
247 | | SCROW nEndRow; |
248 | | public: |
249 | | inline ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd, const ScPatternAttr* pDefaultPattern ); |
250 | | inline const ScPatternAttr* Next( SCROW& rTop, SCROW& rBottom ); |
251 | | inline const ScPatternAttr* Resync( SCROW nRow, SCROW& rTop, SCROW& rBottom ); |
252 | 0 | SCROW GetNextRow() const { return nRow; } |
253 | | }; |
254 | | |
255 | | inline ScAttrIterator::ScAttrIterator( const ScAttrArray* pNewArray, SCROW nStart, SCROW nEnd, const ScPatternAttr* pDefaultPattern ) : |
256 | 2.08M | pArray( pNewArray ), |
257 | 2.08M | pDefPattern( pDefaultPattern ), |
258 | 2.08M | nRow( nStart ), |
259 | 2.08M | nEndRow( nEnd ) |
260 | 2.08M | { |
261 | 2.08M | if ( pArray->Count() ) |
262 | 1.52M | { |
263 | 1.52M | if ( nStart > 0 ) |
264 | 1.82k | pArray->Search( nStart, nPos ); |
265 | 1.52M | else |
266 | 1.52M | nPos = 0; |
267 | 1.52M | } |
268 | 562k | else |
269 | 562k | nPos = 0; |
270 | 2.08M | } |
271 | | |
272 | | inline const ScPatternAttr* ScAttrIterator::Next( SCROW& rTop, SCROW& rBottom ) |
273 | 9.51M | { |
274 | 9.51M | const ScPatternAttr* pRet; |
275 | 9.51M | if ( !pArray->Count() ) |
276 | 1.64M | { |
277 | 1.64M | if ( !nPos ) |
278 | 1.10M | { |
279 | 1.10M | ++nPos; |
280 | 1.10M | if ( nRow > pArray->GetDoc().MaxRow()) |
281 | 0 | return nullptr; |
282 | 1.10M | rTop = nRow; |
283 | 1.10M | rBottom = std::min( nEndRow, pArray->GetDoc().MaxRow()); |
284 | 1.10M | nRow = rBottom + 1; |
285 | 1.10M | return pDefPattern; |
286 | 1.10M | } |
287 | 535k | return nullptr; |
288 | 1.64M | } |
289 | | |
290 | 7.86M | if ( nPos < pArray->Count() && nRow <= nEndRow ) |
291 | 6.31M | { |
292 | 6.31M | rTop = nRow; |
293 | 6.31M | rBottom = std::min( pArray->mvData[nPos].nEndRow, nEndRow ); |
294 | 6.31M | pRet = pArray->mvData[nPos].getScPatternAttr(); |
295 | 6.31M | nRow = rBottom + 1; |
296 | 6.31M | ++nPos; |
297 | 6.31M | } |
298 | 1.54M | else |
299 | 1.54M | pRet = nullptr; |
300 | 7.86M | return pRet; |
301 | 9.51M | } |
302 | | |
303 | | inline const ScPatternAttr* ScAttrIterator::Resync( SCROW nRowP, SCROW& rTop, SCROW& rBottom ) |
304 | 3.46M | { |
305 | 3.46M | nRow = nRowP; |
306 | 3.46M | if ( !pArray->Count() ) |
307 | 545k | { |
308 | 545k | nPos = 0; |
309 | 545k | return Next( rTop, rBottom ); |
310 | 545k | } |
311 | | // Chances are high that the pattern changed on nRowP introduced a span |
312 | | // starting right there. Assume that Next() was called so nPos already |
313 | | // advanced. Another high chance is that the change extended a previous or |
314 | | // next pattern. In all these cases we don't need to search. |
315 | 2.91M | if (3 <= nPos && nPos <= pArray->Count() && pArray->mvData[nPos-3].nEndRow < nRowP && |
316 | 1.21M | nRowP <= pArray->mvData[nPos-2].nEndRow) |
317 | 44 | nPos -= 2; |
318 | 2.91M | else if (2 <= nPos && nPos <= pArray->Count() && pArray->mvData[nPos-2].nEndRow < nRowP && |
319 | 1.66M | nRowP <= pArray->mvData[nPos-1].nEndRow) |
320 | 1.66M | --nPos; |
321 | 1.24M | else if (pArray->Count() > 0 && nRowP <= pArray->mvData[0].nEndRow) |
322 | 1.24M | nPos = 0; |
323 | 134 | else |
324 | 134 | pArray->Search( nRowP, nPos ); |
325 | 2.91M | return Next( rTop, rBottom); |
326 | 3.46M | } |
327 | | |
328 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |