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 4097 : ScSimpleRangeList::Range::Range(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) :
28 4097 : mnCol1(nCol1), mnRow1(nRow1), mnCol2(nCol2), mnRow2(nRow2) {}
29 :
30 1514 : ScSimpleRangeList::ScSimpleRangeList()
31 : {
32 1514 : }
33 :
34 : namespace {
35 :
36 7998 : bool maybeJoin(ScSimpleRangeList::Range& rOld, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
37 : {
38 7998 : if (rOld.mnRow1 == nRow1 && rOld.mnRow2 == nRow2)
39 : {
40 : // Check their column spans to see if they overlap.
41 1241 : 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 1241 : else if (rOld.mnCol1 < nCol1)
48 : {
49 : // Old range sits on the left.
50 1241 : if (nCol1 - rOld.mnCol2 <= 1)
51 : {
52 104 : rOld.mnCol2 = max(rOld.mnCol2, nCol2);
53 104 : 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 7894 : if (rOld.mnCol1 == nCol1 && rOld.mnCol2 == nCol2)
69 : {
70 5455 : 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 5455 : else if (rOld.mnRow1 < nRow1)
77 : {
78 : // Old range sits above.
79 5455 : if (nRow1 - rOld.mnRow2 <= 1)
80 : {
81 5301 : rOld.mnRow2 = max(rOld.mnRow2, nRow2);
82 5301 : 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 2593 : return false;
98 : }
99 :
100 : }
101 :
102 9502 : void ScSimpleRangeList::addRange(const ScRange& rRange)
103 : {
104 9502 : SCCOL nCol1 = rRange.aStart.Col();
105 9502 : SCROW nRow1 = rRange.aStart.Row();
106 9502 : SCTAB nTab1 = rRange.aStart.Tab();
107 9502 : SCCOL nCol2 = rRange.aEnd.Col();
108 9502 : SCROW nRow2 = rRange.aEnd.Row();
109 9502 : SCTAB nTab2 = rRange.aEnd.Tab();
110 :
111 19004 : for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
112 : {
113 9502 : RangeListRef pRef = findTab(nTab);
114 9502 : if (!pRef)
115 : // This should never happen!
116 9502 : return;
117 :
118 9502 : if (pRef->empty() || !maybeJoin(pRef->back(), nCol1, nRow1, nCol2, nRow2))
119 : // Not joinable. Append it to the list.
120 4097 : pRef->push_back(Range(nCol1, nRow1, nCol2, nRow2));
121 9502 : }
122 : }
123 :
124 8874 : void ScSimpleRangeList::insertCol(SCCOL nCol, SCTAB nTab)
125 : {
126 8874 : RangeListRef pRef = findTab(nTab);
127 8874 : if (!pRef)
128 : // This should never happen!
129 8874 : return;
130 :
131 8874 : list<Range>::iterator itr = pRef->begin(), itrEnd = pRef->end();
132 17999 : for (; itr != itrEnd; ++itr)
133 : {
134 9125 : Range& r = *itr;
135 9125 : if (r.mnCol2 < nCol)
136 : // insertion point to the right of the range.
137 9125 : 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 8874 : }
151 : }
152 :
153 1504 : void ScSimpleRangeList::getRangeList(list<ScRange>& rList) const
154 : {
155 1504 : list<ScRange> aList;
156 3008 : for (TabType::const_iterator itrTab = maTabs.begin(), itrTabEnd = maTabs.end(); itrTab != itrTabEnd; ++itrTab)
157 : {
158 1504 : SCTAB nTab = itrTab->first;
159 1504 : const RangeListRef& pRanges = itrTab->second;
160 1504 : list<Range>::const_iterator itr = pRanges->begin(), itrEnd = pRanges->end();
161 5601 : for (; itr != itrEnd; ++itr)
162 : {
163 4097 : const Range& r = *itr;
164 4097 : aList.push_back(ScRange(r.mnCol1, r.mnRow1, nTab, r.mnCol2, r.mnRow2, nTab));
165 : }
166 : }
167 1504 : rList.swap(aList);
168 1504 : }
169 :
170 1479 : void ScSimpleRangeList::clear()
171 : {
172 1479 : maTabs.clear();
173 1479 : }
174 :
175 18376 : ScSimpleRangeList::RangeListRef ScSimpleRangeList::findTab(SCTAB nTab)
176 : {
177 18376 : TabType::iterator itr = maTabs.find(nTab);
178 18376 : if (itr == maTabs.end())
179 : {
180 1504 : RangeListRef p(new list<Range>);
181 1504 : pair<TabType::iterator, bool> r = maTabs.insert(TabType::value_type(nTab, p));
182 1504 : if (!r.second)
183 0 : return RangeListRef();
184 1504 : itr = r.first;
185 : }
186 :
187 18376 : return itr->second;
188 156 : }
189 :
190 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|