Line data Source code
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 : #include "simplerangelist.hxx"
21 : #include "rangelst.hxx"
22 :
23 : using ::std::list;
24 : using ::std::pair;
25 : using ::std::max;
26 :
27 0 : ScSimpleRangeList::Range::Range(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) :
28 0 : mnCol1(nCol1), mnRow1(nRow1), mnCol2(nCol2), mnRow2(nRow2) {}
29 :
30 0 : ScSimpleRangeList::ScSimpleRangeList()
31 : {
32 0 : }
33 :
34 : namespace {
35 :
36 0 : bool maybeJoin(ScSimpleRangeList::Range& rOld, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
37 : {
38 0 : if (rOld.mnRow1 == nRow1 && rOld.mnRow2 == nRow2)
39 : {
40 : // Check their column spans to see if they overlap.
41 0 : if (rOld.mnCol1 == nCol1)
42 : {
43 : // Their share the start column position.
44 0 : rOld.mnCol2 = max(rOld.mnCol2, nCol2);
45 0 : return true;
46 : }
47 0 : else if (rOld.mnCol1 < nCol1)
48 : {
49 : // Old range sits on the left.
50 0 : if (nCol1 - rOld.mnCol2 <= 1)
51 : {
52 0 : rOld.mnCol2 = max(rOld.mnCol2, nCol2);
53 0 : return true;
54 : }
55 : }
56 0 : else if (nCol1 < rOld.mnCol1)
57 : {
58 : // New range sits on the left.
59 0 : if (nCol1 - rOld.mnCol2 <= 1)
60 : {
61 0 : rOld.mnCol1 = nCol1;
62 0 : rOld.mnCol2 = max(rOld.mnCol2, nCol2);
63 0 : return true;
64 : }
65 : }
66 : }
67 :
68 0 : if (rOld.mnCol1 == nCol1 && rOld.mnCol2 == nCol2)
69 : {
70 0 : if (rOld.mnRow1 == nRow1)
71 : {
72 : // Their share the start row position.
73 0 : rOld.mnRow2 = max(rOld.mnRow2, nRow2);
74 0 : return true;
75 : }
76 0 : else if (rOld.mnRow1 < nRow1)
77 : {
78 : // Old range sits above.
79 0 : if (nRow1 - rOld.mnRow2 <= 1)
80 : {
81 0 : rOld.mnRow2 = max(rOld.mnRow2, nRow2);
82 0 : return true;
83 : }
84 : }
85 0 : else if (nRow1 < rOld.mnRow1)
86 : {
87 : // New range sits above.
88 0 : if (nRow1 - rOld.mnRow2 <= 1)
89 : {
90 0 : rOld.mnRow1 = nRow1;
91 0 : rOld.mnRow2 = max(rOld.mnRow2, nRow2);
92 0 : return true;
93 : }
94 : }
95 : }
96 :
97 0 : return false;
98 : }
99 :
100 : }
101 :
102 0 : void ScSimpleRangeList::addRange(const ScRange& rRange)
103 : {
104 0 : SCCOL nCol1 = rRange.aStart.Col();
105 0 : SCROW nRow1 = rRange.aStart.Row();
106 0 : SCTAB nTab1 = rRange.aStart.Tab();
107 0 : SCCOL nCol2 = rRange.aEnd.Col();
108 0 : SCROW nRow2 = rRange.aEnd.Row();
109 0 : SCTAB nTab2 = rRange.aEnd.Tab();
110 :
111 0 : for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
112 : {
113 0 : RangeListRef pRef = findTab(nTab);
114 0 : if (!pRef)
115 : // This should never happen!
116 0 : return;
117 :
118 0 : if (pRef->empty() || !maybeJoin(pRef->back(), nCol1, nRow1, nCol2, nRow2))
119 : // Not joinable. Append it to the list.
120 0 : pRef->push_back(Range(nCol1, nRow1, nCol2, nRow2));
121 0 : }
122 : }
123 :
124 0 : void ScSimpleRangeList::insertCol(SCCOL nCol, SCTAB nTab)
125 : {
126 0 : RangeListRef pRef = findTab(nTab);
127 0 : if (!pRef)
128 : // This should never happen!
129 0 : return;
130 :
131 0 : list<Range>::iterator itr = pRef->begin(), itrEnd = pRef->end();
132 0 : for (; itr != itrEnd; ++itr)
133 : {
134 0 : Range& r = *itr;
135 0 : if (r.mnCol2 < nCol)
136 : // insertion point to the right of the range.
137 0 : continue;
138 :
139 0 : if (nCol <= r.mnCol1)
140 : {
141 : // insertion point to the left of the range.
142 0 : ++r.mnCol1;
143 0 : ++r.mnCol2;
144 : }
145 0 : else if (nCol <= r.mnCol2)
146 : {
147 : // insertion point cuts through the range.
148 0 : ++r.mnCol2;
149 : }
150 0 : }
151 : }
152 :
153 0 : void ScSimpleRangeList::getRangeList(list<ScRange>& rList) const
154 : {
155 0 : list<ScRange> aList;
156 0 : for (TabType::const_iterator itrTab = maTabs.begin(), itrTabEnd = maTabs.end(); itrTab != itrTabEnd; ++itrTab)
157 : {
158 0 : SCTAB nTab = itrTab->first;
159 0 : const RangeListRef& pRanges = itrTab->second;
160 0 : list<Range>::const_iterator itr = pRanges->begin(), itrEnd = pRanges->end();
161 0 : for (; itr != itrEnd; ++itr)
162 : {
163 0 : const Range& r = *itr;
164 0 : aList.push_back(ScRange(r.mnCol1, r.mnRow1, nTab, r.mnCol2, r.mnRow2, nTab));
165 : }
166 : }
167 0 : rList.swap(aList);
168 0 : }
169 :
170 0 : void ScSimpleRangeList::clear()
171 : {
172 0 : maTabs.clear();
173 0 : }
174 :
175 0 : ScSimpleRangeList::RangeListRef ScSimpleRangeList::findTab(SCTAB nTab)
176 : {
177 0 : TabType::iterator itr = maTabs.find(nTab);
178 0 : if (itr == maTabs.end())
179 : {
180 0 : RangeListRef p(new list<Range>);
181 0 : pair<TabType::iterator, bool> r = maTabs.insert(TabType::value_type(nTab, p));
182 0 : if (!r.second)
183 0 : return RangeListRef();
184 0 : itr = r.first;
185 : }
186 :
187 0 : return itr->second;
188 : }
189 :
190 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|