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"
11 #include "stlalgorithm.hxx"
14 #include "document.hxx"
15 #include "mtvfunctions.hxx"
16 #include "markdata.hxx"
17 #include "rangelst.hxx"
23 ColumnSpanSet::ColumnType::ColumnType(SCROW nStart
, SCROW nEnd
, bool bInit
) :
24 maSpans(nStart
, nEnd
+1, bInit
), miPos(maSpans
.begin()) {}
26 ColumnSpanSet::Action::~Action() {}
27 void ColumnSpanSet::Action::startColumn(SCTAB
/*nTab*/, SCCOL
/*nCol*/) {}
29 ColumnSpanSet::ColumnAction::~ColumnAction() {}
31 ColumnSpanSet::ColumnSpanSet(bool bInit
) : mbInit(bInit
) {}
33 ColumnSpanSet::~ColumnSpanSet()
35 DocType::iterator itTab
= maDoc
.begin(), itTabEnd
= maDoc
.end();
36 for (; itTab
!= itTabEnd
; ++itTab
)
38 TableType
* pTab
= *itTab
;
42 std::for_each(pTab
->begin(), pTab
->end(), ScDeleteObjectByPtr
<ColumnType
>());
47 ColumnSpanSet::ColumnType
& ColumnSpanSet::getColumn(SCTAB nTab
, SCCOL nCol
)
49 if (static_cast<size_t>(nTab
) >= maDoc
.size())
50 maDoc
.resize(nTab
+1, NULL
);
53 maDoc
[nTab
] = new TableType
;
55 TableType
& rTab
= *maDoc
[nTab
];
56 if (static_cast<size_t>(nCol
) >= rTab
.size())
57 rTab
.resize(nCol
+1, NULL
);
60 rTab
[nCol
] = new ColumnType(0, MAXROW
, mbInit
);
65 void ColumnSpanSet::set(SCTAB nTab
, SCCOL nCol
, SCROW nRow
, bool bVal
)
67 if (!ValidTab(nTab
) || !ValidCol(nCol
) || !ValidRow(nRow
))
70 ColumnType
& rCol
= getColumn(nTab
, nCol
);
71 rCol
.miPos
= rCol
.maSpans
.insert(rCol
.miPos
, nRow
, nRow
+1, bVal
).first
;
74 void ColumnSpanSet::set(SCTAB nTab
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
, bool bVal
)
76 if (!ValidTab(nTab
) || !ValidCol(nCol
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
79 ColumnType
& rCol
= getColumn(nTab
, nCol
);
80 rCol
.miPos
= rCol
.maSpans
.insert(rCol
.miPos
, nRow1
, nRow2
+1, bVal
).first
;
83 void ColumnSpanSet::set(const ScRange
& rRange
, bool bVal
)
85 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
87 for (SCCOL nCol
= rRange
.aStart
.Col(); nCol
<= rRange
.aEnd
.Col(); ++nCol
)
89 ColumnType
& rCol
= getColumn(nTab
, nCol
);
90 rCol
.miPos
= rCol
.maSpans
.insert(rCol
.miPos
, rRange
.aStart
.Row(), rRange
.aEnd
.Row()+1, bVal
).first
;
95 void ColumnSpanSet::executeAction(Action
& ac
) const
97 for (size_t nTab
= 0; nTab
< maDoc
.size(); ++nTab
)
102 const TableType
& rTab
= *maDoc
[nTab
];
103 for (size_t nCol
= 0; nCol
< rTab
.size(); ++nCol
)
108 ac
.startColumn(nTab
, nCol
);
109 ColumnType
& rCol
= *rTab
[nCol
];
110 ColumnSpansType::const_iterator it
= rCol
.maSpans
.begin(), itEnd
= rCol
.maSpans
.end();
113 bool bVal
= it
->second
;
114 for (++it
; it
!= itEnd
; ++it
)
117 ac
.execute(ScAddress(nCol
, nRow1
, nTab
), nRow2
-nRow1
+1, bVal
);
119 nRow1
= nRow2
+1; // for the next iteration.
126 void ColumnSpanSet::executeColumnAction(ScDocument
& rDoc
, ColumnAction
& ac
) const
128 for (size_t nTab
= 0; nTab
< maDoc
.size(); ++nTab
)
133 const TableType
& rTab
= *maDoc
[nTab
];
134 for (size_t nCol
= 0; nCol
< rTab
.size(); ++nCol
)
139 ScTable
* pTab
= rDoc
.FetchTable(nTab
);
150 ScColumn
& rColumn
= pTab
->aCol
[nCol
];
151 ac
.startColumn(&rColumn
);
152 ColumnType
& rCol
= *rTab
[nCol
];
153 ColumnSpansType::const_iterator it
= rCol
.maSpans
.begin(), itEnd
= rCol
.maSpans
.end();
156 bool bVal
= it
->second
;
157 for (++it
; it
!= itEnd
; ++it
)
160 ac
.execute(nRow1
, nRow2
, bVal
);
162 nRow1
= nRow2
+1; // for the next iteration.
173 SingleColumnSpanSet::ColumnSpansType
& mrRanges
;
175 Scanner(SingleColumnSpanSet::ColumnSpansType
& rRanges
) : mrRanges(rRanges
) {}
177 void operator() (const sc::CellStoreType::value_type
& node
, size_t nOffset
, size_t nDataSize
)
179 if (node
.type
== sc::element_type_empty
)
182 size_t nRow
= node
.position
+ nOffset
;
183 size_t nEndRow
= nRow
+ nDataSize
; // Last row of current block plus 1
184 mrRanges
.insert_back(nRow
, nEndRow
, true);
190 SingleColumnSpanSet::SingleColumnSpanSet() : maSpans(0, MAXROWCOUNT
, false) {}
192 void SingleColumnSpanSet::scan(const ScColumn
& rColumn
)
194 const CellStoreType
& rCells
= rColumn
.maCells
;
195 sc::CellStoreType::const_iterator it
= rCells
.begin(), itEnd
= rCells
.end();
197 for (;it
!= itEnd
; ++it
)
199 SCROW nEndRow
= nCurRow
+ it
->size
; // Last row of current block plus 1.
200 if (it
->type
!= sc::element_type_empty
)
201 maSpans
.insert_back(nCurRow
, nEndRow
, true);
207 void SingleColumnSpanSet::scan(const ScColumn
& rColumn
, SCROW nStart
, SCROW nEnd
)
209 const CellStoreType
& rCells
= rColumn
.maCells
;
210 Scanner
aScanner(maSpans
);
211 sc::ParseBlock(rCells
.begin(), rCells
, aScanner
, nStart
, nEnd
);
214 void SingleColumnSpanSet::scan(
215 ColumnBlockConstPosition
& rBlockPos
, const ScColumn
& rColumn
, SCROW nStart
, SCROW nEnd
)
217 const CellStoreType
& rCells
= rColumn
.maCells
;
218 Scanner
aScanner(maSpans
);
219 rBlockPos
.miCellPos
= sc::ParseBlock(rBlockPos
.miCellPos
, rCells
, aScanner
, nStart
, nEnd
);
222 void SingleColumnSpanSet::scan(const ScMarkData
& rMark
, SCTAB nTab
, SCCOL nCol
)
224 if (!rMark
.GetTableSelect(nTab
))
225 // This table is not selected. Nothing to scan.
228 ScRangeList aRanges
= rMark
.GetMarkedRanges();
229 for (size_t i
= 0, n
= aRanges
.size(); i
< n
; ++i
)
231 const ScRange
* p
= aRanges
[i
];
232 if (nCol
< p
->aStart
.Col() || p
->aEnd
.Col() < nCol
)
233 // This column is not in this range. Skip it.
236 maSpans
.insert_back(p
->aStart
.Row(), p
->aEnd
.Row()+1, true);
240 void SingleColumnSpanSet::set(SCROW nRow1
, SCROW nRow2
, bool bVal
)
242 maSpans
.insert_back(nRow1
, nRow2
+1, bVal
);
245 void SingleColumnSpanSet::getRows(std::vector
<SCROW
> &rRows
) const
247 std::vector
<SCROW
> aRows
;
251 SpansType::const_iterator it
= aRanges
.begin(), itEnd
= aRanges
.end();
252 for (; it
!= itEnd
; ++it
)
254 for (SCROW nRow
= it
->mnRow1
; nRow
<= it
->mnRow2
; ++nRow
)
255 aRows
.push_back(nRow
);
261 void SingleColumnSpanSet::getSpans(SpansType
& rSpans
) const
264 ColumnSpansType::const_iterator it
= maSpans
.begin(), itEnd
= maSpans
.end();
265 SCROW nLastRow
= it
->first
;
266 bool bLastVal
= it
->second
;
267 for (++it
; it
!= itEnd
; ++it
)
269 SCROW nThisRow
= it
->first
;
270 bool bThisVal
= it
->second
;
273 aSpans
.push_back(Span(nLastRow
, nThisRow
-1));
284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */