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"
31 #include <svl/itemset.hxx>
34 class ScEditDataArray
;
37 class ScFlatBoolRowSegments
;
39 class SfxItemPoolCache
;
40 class SfxStyleSheetBase
;
44 namespace editeng
{ class SvxBorderLine
; }
46 #define SC_LINE_EMPTY 0
48 #define SC_LINE_DONTCARE 2
50 #define SC_ATTRARRAY_DELTA 4
52 #define DEBUG_SC_TESTATTRARRAY 0
63 ScLineFlags() : nLeft(SC_LINE_EMPTY
),nRight(SC_LINE_EMPTY
),nTop(SC_LINE_EMPTY
),
64 nBottom(SC_LINE_EMPTY
),nHori(SC_LINE_EMPTY
),nVert(SC_LINE_EMPTY
) {}
67 struct ScMergePatternState
69 std::optional
<SfxItemSet
> pItemSet
;
70 const ScPatternAttr
* pOld1
; ///< existing objects, temporary
71 const ScPatternAttr
* pOld2
;
73 bool mbValidPatternId
;
74 sal_uInt64 mnPatternId
;
76 ScMergePatternState() : pOld1(nullptr), pOld2(nullptr),
77 mbValidPatternId(true), mnPatternId(0) {}
80 // we store an array of these where the pattern applies to all rows up till nEndRow
84 const ScPatternAttr
* pPattern
;
85 bool operator==( const ScAttrEntry
& other
) const
87 return nEndRow
== other
.nEndRow
&& pPattern
== other
.pPattern
;
96 ScDocument
& rDocument
;
98 std::vector
<ScAttrEntry
> mvData
;
100 friend class ScDocument
; // for FillInfo
101 friend class ScDocumentIterator
;
102 friend class ScAttrIterator
;
103 friend class ScHorizontalAttrIterator
;
105 bool ApplyFrame( const SvxBoxItem
& rLineOuter
, const SvxBoxInfoItem
* pLineInner
,
106 SCROW nStartRow
, SCROW nEndRow
,
107 bool bLeft
, SCCOL nDistRight
, bool bTop
, SCROW nDistBottom
);
109 void RemoveCellCharAttribs( SCROW nStartRow
, SCROW nEndRow
,
110 const ScPatternAttr
* pPattern
, ScEditDataArray
* pDataArray
);
111 void SetDefaultIfNotInit( SCSIZE nNeeded
= 1 );
112 bool HasAttrib_Impl(const ScPatternAttr
* pPattern
, HasAttrFlags nMask
, SCROW nRow1
, SCROW nRow2
, SCSIZE i
) const;
114 ScAttrArray(const ScAttrArray
&) = delete;
115 ScAttrArray
& operator=(const ScAttrArray
&) = delete;
118 ScAttrArray( SCCOL nNewCol
, SCTAB nNewTab
, ScDocument
& rDoc
, ScAttrArray
* pNextColAttrArray
);
121 ScDocument
& GetDoc() { return rDocument
; }
122 const ScDocument
& GetDoc() const { return rDocument
; }
123 void SetTab(SCTAB nNewTab
) { nTab
= nNewTab
; }
124 void SetCol(SCCOL nNewCol
) { nCol
= nNewCol
; }
125 #if DEBUG_SC_TESTATTRARRAY
126 void TestData() const;
128 void Reset( const ScPatternAttr
* pPattern
);
129 bool Concat(SCSIZE nPos
);
131 const ScPatternAttr
* GetPattern( SCROW nRow
) const;
133 /** Returns if you search for attributes at nRow the range from rStartRow
134 to rEndRow where that attribute combination (ScPatternAttr) is applied.
135 The next ScPatternAttr different from this one starts at rEndRow+1
136 (if that is <= MAXROW).
138 const ScPatternAttr
* GetPatternRange( SCROW
& rStartRow
, SCROW
& rEndRow
, SCROW nRow
) const;
140 void MergePatternArea( SCROW nStartRow
, SCROW nEndRow
, ScMergePatternState
& rState
, bool bDeep
) const;
142 void MergeBlockFrame( SvxBoxItem
* pLineOuter
, SvxBoxInfoItem
* pLineInner
, ScLineFlags
& rFlags
,
143 SCROW nStartRow
, SCROW nEndRow
, bool bLeft
, SCCOL nDistRight
) const;
144 void ApplyBlockFrame(const SvxBoxItem
& rLineOuter
, const SvxBoxInfoItem
* pLineInner
,
145 SCROW nStartRow
, SCROW nEndRow
, bool bLeft
, SCCOL nDistRight
);
147 void SetPattern( SCROW nRow
, const ScPatternAttr
* pPattern
, bool bPutToPool
= false )
148 { SetPatternAreaImpl(nRow
, nRow
, pPattern
, bPutToPool
, nullptr, /*bPassingOwnership*/false); }
149 const ScPatternAttr
* SetPattern( SCROW nRow
, std::unique_ptr
<ScPatternAttr
> pPattern
, bool bPutToPool
= false )
150 { return SetPatternAreaImpl(nRow
, nRow
, pPattern
.release(), bPutToPool
, nullptr, /*bPassingOwnership*/true); }
151 void SetPatternArea( SCROW nStartRow
, SCROW nEndRow
, std::unique_ptr
<ScPatternAttr
> pPattern
,
152 bool bPutToPool
= false, ScEditDataArray
* pDataArray
= nullptr)
153 { SetPatternAreaImpl(nStartRow
, nEndRow
, pPattern
.release(), bPutToPool
, pDataArray
, /*bPassingOwnership*/true); }
154 void SetPatternArea( SCROW nStartRow
, SCROW nEndRow
, const ScPatternAttr
* pPattern
,
155 bool bPutToPool
= false, ScEditDataArray
* pDataArray
= nullptr)
156 { SetPatternAreaImpl(nStartRow
, nEndRow
, pPattern
, bPutToPool
, pDataArray
, /*bPassingOwnership*/false); }
157 void ApplyStyleArea( SCROW nStartRow
, SCROW nEndRow
, const ScStyleSheet
& rStyle
);
158 void ApplyCacheArea( SCROW nStartRow
, SCROW nEndRow
, SfxItemPoolCache
* pCache
,
159 ScEditDataArray
* pDataArray
= nullptr, bool* const pIsChanged
= nullptr );
160 void SetAttrEntries(std::vector
<ScAttrEntry
> && vNewData
);
161 void ApplyLineStyleArea( SCROW nStartRow
, SCROW nEndRow
,
162 const ::editeng::SvxBorderLine
* pLine
, bool bColorOnly
);
164 void AddCondFormat( SCROW nStartRow
, SCROW nEndRow
, sal_uInt32 nIndex
);
165 /// if nIndex == 0, remove all conditional format data
166 void RemoveCondFormat( SCROW nStartRow
, SCROW nEndRow
, sal_uInt32 nIndex
);
168 void ClearItems( SCROW nStartRow
, SCROW nEndRow
, const sal_uInt16
* pWhich
);
169 void ChangeIndent( SCROW nStartRow
, SCROW nEndRow
, bool bIncrement
);
171 /// Including current, may return -1
172 SCROW
GetNextUnprotected( SCROW nRow
, bool bUp
) const;
174 /// May return -1 if not found
176 SCROW nRow
, const ScStyleSheet
* pSearchStyle
, bool bUp
,
177 const ScMarkArray
* pMarkArray
= nullptr) const;
179 bool SearchStyleRange(
180 SCROW
& rRow
, SCROW
& rEndRow
, const ScStyleSheet
* pSearchStyle
, bool bUp
,
181 const ScMarkArray
* pMarkArray
= nullptr) const;
183 bool ApplyFlags( SCROW nStartRow
, SCROW nEndRow
, ScMF nFlags
);
184 bool RemoveFlags( SCROW nStartRow
, SCROW nEndRow
, ScMF nFlags
);
186 bool Search( SCROW nRow
, SCSIZE
& nIndex
) const;
188 bool HasAttrib( SCROW nRow1
, SCROW nRow2
, HasAttrFlags nMask
) const;
189 bool HasAttrib( SCROW nRow
, HasAttrFlags nMask
, SCROW
* nStartRow
= nullptr, SCROW
* nEndRow
= nullptr ) const;
190 bool IsMerged( SCROW nRow
) const;
191 bool ExtendMerge( SCCOL nThisCol
, SCROW nStartRow
, SCROW nEndRow
,
192 SCCOL
& rPaintCol
, SCROW
& rPaintRow
,
194 void RemoveAreaMerge( SCROW nStartRow
, SCROW nEndRow
);
196 void FindStyleSheet( const SfxStyleSheetBase
* pStyleSheet
, ScFlatBoolRowSegments
& rUsedRows
, bool bReset
);
197 bool IsStyleSheetUsed( const ScStyleSheet
& rStyle
) const;
199 void SetPatternAreaSafe( SCROW nStartRow
, SCROW nEndRow
,
200 const ScPatternAttr
* pWantedPattern
, bool bDefault
);
201 void CopyAreaSafe( SCROW nStartRow
, SCROW nEndRow
, tools::Long nDy
, ScAttrArray
& rAttrArray
);
203 bool IsEmpty() const;
205 bool GetFirstVisibleAttr( SCROW
& rFirstRow
) const;
206 bool GetLastVisibleAttr( SCROW
& rLastRow
, SCROW nLastData
) const;
207 bool HasVisibleAttrIn( SCROW nStartRow
, SCROW nEndRow
) const;
208 bool IsVisibleEqual( const ScAttrArray
& rOther
,
209 SCROW nStartRow
, SCROW nEndRow
) const;
210 bool IsAllEqual( const ScAttrArray
& rOther
, SCROW nStartRow
, SCROW nEndRow
) const;
212 bool TestInsertCol( SCROW nStartRow
, SCROW nEndRow
) const;
213 bool TestInsertRow( SCSIZE nSize
) const;
214 void InsertRow( SCROW nStartRow
, SCSIZE nSize
);
215 void DeleteRow( SCROW nStartRow
, SCSIZE nSize
);
216 void DeleteRange( SCSIZE nStartIndex
, SCSIZE nEndIndex
);
217 void DeleteArea( SCROW nStartRow
, SCROW nEndRow
);
218 void MoveTo( SCROW nStartRow
, SCROW nEndRow
, ScAttrArray
& rAttrArray
);
220 SCROW nStartRow
, SCROW nEndRow
, tools::Long nDy
, ScAttrArray
& rAttrArray
, ScMF nStripFlags
= ScMF::NONE
) const;
222 void DeleteHardAttr( SCROW nStartRow
, SCROW nEndRow
);
224 /* i123909: Pre-calculate needed memory, and pre-reserve enough memory */
225 bool Reserve( SCSIZE nReserve
);
226 SCSIZE
Count() const { return mvData
.size(); }
227 SCSIZE
Count( SCROW nRow1
, SCROW nRow2
) const;
230 const ScPatternAttr
* SetPatternAreaImpl( SCROW nStartRow
, SCROW nEndRow
, const ScPatternAttr
* pPattern
,
231 bool bPutToPool
= false, ScEditDataArray
* pDataArray
= nullptr,
232 bool bPassingPatternOwnership
= false );
235 // Iterator for attributes
239 const ScAttrArray
* pArray
;
240 const ScPatternAttr
* pDefPattern
;
245 inline ScAttrIterator( const ScAttrArray
* pNewArray
, SCROW nStart
, SCROW nEnd
, const ScPatternAttr
* pDefaultPattern
);
246 inline const ScPatternAttr
* Next( SCROW
& rTop
, SCROW
& rBottom
);
247 inline const ScPatternAttr
* Resync( SCROW nRow
, SCROW
& rTop
, SCROW
& rBottom
);
248 SCROW
GetNextRow() const { return nRow
; }
251 inline ScAttrIterator::ScAttrIterator( const ScAttrArray
* pNewArray
, SCROW nStart
, SCROW nEnd
, const ScPatternAttr
* pDefaultPattern
) :
253 pDefPattern( pDefaultPattern
),
257 if ( pArray
->Count() )
260 pArray
->Search( nStart
, nPos
);
268 inline const ScPatternAttr
* ScAttrIterator::Next( SCROW
& rTop
, SCROW
& rBottom
)
270 const ScPatternAttr
* pRet
;
271 if ( !pArray
->Count() )
276 if ( nRow
> pArray
->GetDoc().MaxRow())
279 rBottom
= std::min( nEndRow
, pArray
->GetDoc().MaxRow());
286 if ( nPos
< pArray
->Count() && nRow
<= nEndRow
)
289 rBottom
= std::min( pArray
->mvData
[nPos
].nEndRow
, nEndRow
);
290 pRet
= pArray
->mvData
[nPos
].pPattern
;
299 inline const ScPatternAttr
* ScAttrIterator::Resync( SCROW nRowP
, SCROW
& rTop
, SCROW
& rBottom
)
302 if ( !pArray
->Count() )
305 return Next( rTop
, rBottom
);
307 // Chances are high that the pattern changed on nRowP introduced a span
308 // starting right there. Assume that Next() was called so nPos already
309 // advanced. Another high chance is that the change extended a previous or
310 // next pattern. In all these cases we don't need to search.
311 if (3 <= nPos
&& nPos
<= pArray
->Count() && pArray
->mvData
[nPos
-3].nEndRow
< nRowP
&&
312 nRowP
<= pArray
->mvData
[nPos
-2].nEndRow
)
314 else if (2 <= nPos
&& nPos
<= pArray
->Count() && pArray
->mvData
[nPos
-2].nEndRow
< nRowP
&&
315 nRowP
<= pArray
->mvData
[nPos
-1].nEndRow
)
317 else if (pArray
->Count() > 0 && nRowP
<= pArray
->mvData
[0].nEndRow
)
320 pArray
->Search( nRowP
, nPos
);
321 return Next( rTop
, rBottom
);
324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */