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/.
10 #include "columnspanset.hxx"
13 #include "document.hxx"
14 #include "mtvfunctions.hxx"
15 #include "markdata.hxx"
16 #include "rangelst.hxx"
17 #include <fstalgorithm.hxx>
18 #include <boost/checked_delete.hpp>
28 ColumnSpanSet::ColumnSpansType
& mrRanges
;
31 ColumnScanner(ColumnSpanSet::ColumnSpansType
& rRanges
, bool bVal
) :
32 mrRanges(rRanges
), mbVal(bVal
) {}
34 void operator() (const sc::CellStoreType::value_type
& node
, size_t nOffset
, size_t nDataSize
)
36 if (node
.type
== sc::element_type_empty
)
39 size_t nRow
= node
.position
+ nOffset
;
40 size_t nEndRow
= nRow
+ nDataSize
; // Last row of current block plus 1
41 mrRanges
.insert_back(nRow
, nEndRow
, mbVal
);
47 RowSpan::RowSpan(SCROW nRow1
, SCROW nRow2
) : mnRow1(nRow1
), mnRow2(nRow2
) {}
49 ColRowSpan::ColRowSpan(SCCOLROW nStart
, SCCOLROW nEnd
) : mnStart(nStart
), mnEnd(nEnd
) {}
51 ColumnSpanSet::ColumnType::ColumnType(SCROW nStart
, SCROW nEnd
, bool bInit
) :
52 maSpans(nStart
, nEnd
+1, bInit
), miPos(maSpans
.begin()) {}
54 ColumnSpanSet::Action::~Action() {}
55 void ColumnSpanSet::Action::startColumn(SCTAB
/*nTab*/, SCCOL
/*nCol*/) {}
57 ColumnSpanSet::ColumnAction::~ColumnAction() {}
59 ColumnSpanSet::ColumnSpanSet(bool bInit
) : mbInit(bInit
) {}
61 ColumnSpanSet::~ColumnSpanSet()
63 DocType::iterator itTab
= maDoc
.begin(), itTabEnd
= maDoc
.end();
64 for (; itTab
!= itTabEnd
; ++itTab
)
66 TableType
* pTab
= *itTab
;
70 std::for_each(pTab
->begin(), pTab
->end(), boost::checked_deleter
<ColumnType
>());
75 ColumnSpanSet::ColumnType
& ColumnSpanSet::getColumn(SCTAB nTab
, SCCOL nCol
)
77 if (static_cast<size_t>(nTab
) >= maDoc
.size())
78 maDoc
.resize(nTab
+1, NULL
);
81 maDoc
[nTab
] = new TableType
;
83 TableType
& rTab
= *maDoc
[nTab
];
84 if (static_cast<size_t>(nCol
) >= rTab
.size())
85 rTab
.resize(nCol
+1, NULL
);
88 rTab
[nCol
] = new ColumnType(0, MAXROW
, mbInit
);
93 void ColumnSpanSet::set(SCTAB nTab
, SCCOL nCol
, SCROW nRow
, bool bVal
)
95 if (!ValidTab(nTab
) || !ValidCol(nCol
) || !ValidRow(nRow
))
98 ColumnType
& rCol
= getColumn(nTab
, nCol
);
99 rCol
.miPos
= rCol
.maSpans
.insert(rCol
.miPos
, nRow
, nRow
+1, bVal
).first
;
102 void ColumnSpanSet::set(SCTAB nTab
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
, bool bVal
)
104 if (!ValidTab(nTab
) || !ValidCol(nCol
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
107 ColumnType
& rCol
= getColumn(nTab
, nCol
);
108 rCol
.miPos
= rCol
.maSpans
.insert(rCol
.miPos
, nRow1
, nRow2
+1, bVal
).first
;
111 void ColumnSpanSet::set(const ScRange
& rRange
, bool bVal
)
113 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
115 for (SCCOL nCol
= rRange
.aStart
.Col(); nCol
<= rRange
.aEnd
.Col(); ++nCol
)
117 ColumnType
& rCol
= getColumn(nTab
, nCol
);
118 rCol
.miPos
= rCol
.maSpans
.insert(rCol
.miPos
, rRange
.aStart
.Row(), rRange
.aEnd
.Row()+1, bVal
).first
;
123 void ColumnSpanSet::set( SCTAB nTab
, SCCOL nCol
, const SingleColumnSpanSet
& rSingleSet
, bool bVal
)
125 SingleColumnSpanSet::SpansType aSpans
;
126 rSingleSet
.getSpans(aSpans
);
127 SingleColumnSpanSet::SpansType::const_iterator it
= aSpans
.begin(), itEnd
= aSpans
.end();
128 for (; it
!= itEnd
; ++it
)
129 set(nTab
, nCol
, it
->mnRow1
, it
->mnRow2
, bVal
);
132 void ColumnSpanSet::scan(
133 const ScDocument
& rDoc
, SCTAB nTab
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, bool bVal
)
135 if (!ValidColRow(nCol1
, nRow1
) || !ValidColRow(nCol2
, nRow2
))
138 if (nCol1
> nCol2
|| nRow1
> nRow2
)
141 const ScTable
* pTab
= rDoc
.FetchTable(nTab
);
145 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
147 ColumnType
& rCol
= getColumn(nTab
, nCol
);
149 const CellStoreType
& rSrcCells
= pTab
->aCol
[nCol
].maCells
;
151 ColumnScanner
aScanner(rCol
.maSpans
, bVal
);
152 ParseBlock(rSrcCells
.begin(), rSrcCells
, aScanner
, nRow1
, nRow2
);
156 void ColumnSpanSet::executeAction(Action
& ac
) const
158 for (size_t nTab
= 0; nTab
< maDoc
.size(); ++nTab
)
163 const TableType
& rTab
= *maDoc
[nTab
];
164 for (size_t nCol
= 0; nCol
< rTab
.size(); ++nCol
)
169 ac
.startColumn(nTab
, nCol
);
170 ColumnType
& rCol
= *rTab
[nCol
];
171 ColumnSpansType::const_iterator it
= rCol
.maSpans
.begin(), itEnd
= rCol
.maSpans
.end();
174 bool bVal
= it
->second
;
175 for (++it
; it
!= itEnd
; ++it
)
178 ac
.execute(ScAddress(nCol
, nRow1
, nTab
), nRow2
-nRow1
+1, bVal
);
180 nRow1
= nRow2
+1; // for the next iteration.
187 void ColumnSpanSet::executeColumnAction(ScDocument
& rDoc
, ColumnAction
& ac
) const
189 for (size_t nTab
= 0; nTab
< maDoc
.size(); ++nTab
)
194 const TableType
& rTab
= *maDoc
[nTab
];
195 for (size_t nCol
= 0; nCol
< rTab
.size(); ++nCol
)
200 ScTable
* pTab
= rDoc
.FetchTable(nTab
);
211 ScColumn
& rColumn
= pTab
->aCol
[nCol
];
212 ac
.startColumn(&rColumn
);
213 ColumnType
& rCol
= *rTab
[nCol
];
214 ColumnSpansType::const_iterator it
= rCol
.maSpans
.begin(), itEnd
= rCol
.maSpans
.end();
217 bool bVal
= it
->second
;
218 for (++it
; it
!= itEnd
; ++it
)
221 ac
.execute(nRow1
, nRow2
, bVal
);
223 nRow1
= nRow2
+1; // for the next iteration.
230 void ColumnSpanSet::swap( ColumnSpanSet
& r
)
233 std::swap(mbInit
, r
.mbInit
);
240 SingleColumnSpanSet::ColumnSpansType
& mrRanges
;
242 Scanner(SingleColumnSpanSet::ColumnSpansType
& rRanges
) : mrRanges(rRanges
) {}
244 void operator() (const sc::CellStoreType::value_type
& node
, size_t nOffset
, size_t nDataSize
)
246 if (node
.type
== sc::element_type_empty
)
249 size_t nRow
= node
.position
+ nOffset
;
250 size_t nEndRow
= nRow
+ nDataSize
; // Last row of current block plus 1
251 mrRanges
.insert_back(nRow
, nEndRow
, true);
257 SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT
, false) {}
259 void SingleColumnSpanSet::scan(const ScColumn
& rColumn
)
261 const CellStoreType
& rCells
= rColumn
.maCells
;
262 sc::CellStoreType::const_iterator it
= rCells
.begin(), itEnd
= rCells
.end();
264 for (;it
!= itEnd
; ++it
)
266 SCROW nEndRow
= nCurRow
+ it
->size
; // Last row of current block plus 1.
267 if (it
->type
!= sc::element_type_empty
)
268 maSpans
.insert_back(nCurRow
, nEndRow
, true);
274 void SingleColumnSpanSet::scan(const ScColumn
& rColumn
, SCROW nStart
, SCROW nEnd
)
276 const CellStoreType
& rCells
= rColumn
.maCells
;
277 Scanner
aScanner(maSpans
);
278 sc::ParseBlock(rCells
.begin(), rCells
, aScanner
, nStart
, nEnd
);
281 void SingleColumnSpanSet::scan(
282 ColumnBlockConstPosition
& rBlockPos
, const ScColumn
& rColumn
, SCROW nStart
, SCROW nEnd
)
284 const CellStoreType
& rCells
= rColumn
.maCells
;
285 Scanner
aScanner(maSpans
);
286 rBlockPos
.miCellPos
= sc::ParseBlock(rBlockPos
.miCellPos
, rCells
, aScanner
, nStart
, nEnd
);
289 void SingleColumnSpanSet::scan(const ScMarkData
& rMark
, SCTAB nTab
, SCCOL nCol
)
291 if (!rMark
.GetTableSelect(nTab
))
292 // This table is not selected. Nothing to scan.
295 ScRangeList aRanges
= rMark
.GetMarkedRanges();
296 scan(aRanges
, nTab
, nCol
);
299 void SingleColumnSpanSet::scan(const ScRangeList
& rRanges
, SCTAB nTab
, SCCOL nCol
)
301 for (size_t i
= 0, n
= rRanges
.size(); i
< n
; ++i
)
303 const ScRange
* p
= rRanges
[i
];
304 if (nTab
< p
->aStart
.Tab() || p
->aEnd
.Tab() < nTab
)
307 if (nCol
< p
->aStart
.Col() || p
->aEnd
.Col() < nCol
)
308 // This column is not in this range. Skip it.
311 maSpans
.insert_back(p
->aStart
.Row(), p
->aEnd
.Row()+1, true);
315 void SingleColumnSpanSet::set(SCROW nRow1
, SCROW nRow2
, bool bVal
)
317 maSpans
.insert_back(nRow1
, nRow2
+1, bVal
);
320 void SingleColumnSpanSet::getRows(std::vector
<SCROW
> &rRows
) const
322 std::vector
<SCROW
> aRows
;
326 SpansType::const_iterator it
= aRanges
.begin(), itEnd
= aRanges
.end();
327 for (; it
!= itEnd
; ++it
)
329 for (SCROW nRow
= it
->mnRow1
; nRow
<= it
->mnRow2
; ++nRow
)
330 aRows
.push_back(nRow
);
336 void SingleColumnSpanSet::getSpans(SpansType
& rSpans
) const
338 SpansType aSpans
= toSpanArray
<SCROW
,RowSpan
>(maSpans
);
342 void SingleColumnSpanSet::swap( SingleColumnSpanSet
& r
)
344 maSpans
.swap(r
.maSpans
);
349 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */