1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
24 #include "document.hxx"
25 #include "patattr.hxx"
30 #include <svl/itemset.hxx>
33 class ScEditDataArray
;
36 class ScFlatBoolRowSegments
;
38 class ScItemPoolCache
;
39 class SfxStyleSheetBase
;
43 namespace editeng
{ class SvxBorderLine
; }
45 #define SC_LINE_EMPTY 0
47 #define SC_LINE_DONTCARE 2
49 #define SC_ATTRARRAY_DELTA 4
51 #define DEBUG_SC_TESTATTRARRAY 0
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
82 CellAttributeHolder aPattern
;
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
);
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;
131 ScAttrArray( SCCOL nNewCol
, SCTAB nNewTab
, ScDocument
& rDoc
, ScAttrArray
* pNextColAttrArray
);
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;
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
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
,
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
);
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;
236 const ScPatternAttr
* SetPatternAreaImpl(
237 SCROW nStartRow
, SCROW nEndRow
, const CellAttributeHolder
& rPattern
, ScEditDataArray
* pDataArray
= nullptr);
240 // Iterator for attributes
244 const ScAttrArray
* pArray
;
245 const ScPatternAttr
* pDefPattern
;
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
) :
258 pDefPattern( pDefaultPattern
),
262 if ( pArray
->Count() )
265 pArray
->Search( nStart
, nPos
);
273 inline const ScPatternAttr
* ScAttrIterator::Next( SCROW
& rTop
, SCROW
& rBottom
)
275 const ScPatternAttr
* pRet
;
276 if ( !pArray
->Count() )
281 if ( nRow
> pArray
->GetDoc().MaxRow())
284 rBottom
= std::min( nEndRow
, pArray
->GetDoc().MaxRow());
291 if ( nPos
< pArray
->Count() && nRow
<= nEndRow
)
294 rBottom
= std::min( pArray
->mvData
[nPos
].nEndRow
, nEndRow
);
295 pRet
= pArray
->mvData
[nPos
].getScPatternAttr();
304 inline const ScPatternAttr
* ScAttrIterator::Resync( SCROW nRowP
, SCROW
& rTop
, SCROW
& rBottom
)
307 if ( !pArray
->Count() )
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
)
319 else if (2 <= nPos
&& nPos
<= pArray
->Count() && pArray
->mvData
[nPos
-2].nEndRow
< nRowP
&&
320 nRowP
<= pArray
->mvData
[nPos
-1].nEndRow
)
322 else if (pArray
->Count() > 0 && nRowP
<= pArray
->mvData
[0].nEndRow
)
325 pArray
->Search( nRowP
, nPos
);
326 return Next( rTop
, rBottom
);
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */