1 /* This file is part of the KDE project
2 Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
3 Copyright (C) 2000 Torben Weis <weis@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21 // Local
22 #include "Cluster.h"
23
24 #include <stdlib.h>
25
26 #include "SheetsDebug.h"
27 #include "Cell.h"
28 #include "RowColumnFormat.h"
29
30 using namespace Calligra::Sheets;
31
32 /****************************************************
33 *
34 * ColumnCluster
35 *
36 ****************************************************/
37
ColumnCluster()38 ColumnCluster::ColumnCluster()
39 : m_first(0), m_autoDelete(false)
40 {
41 m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**));
42
43 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
44 m_cluster[ x ] = 0;
45 }
46
~ColumnCluster()47 ColumnCluster::~ColumnCluster()
48 {
49 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
50 ColumnFormat** cl = m_cluster[ x ];
51 if (cl) {
52 free(cl);
53 m_cluster[ x ] = 0;
54 }
55 }
56
57 if (m_autoDelete) {
58 ColumnFormat* cell = m_first;
59 while (cell) {
60 ColumnFormat* n = cell->next();
61 delete cell;
62 cell = n;
63 }
64 }
65
66
67 free(m_cluster);
68 }
69
lookup(int col)70 ColumnFormat* ColumnCluster::lookup(int col)
71 {
72 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
73 debugSheets << "ColumnCluster::lookup: invalid column value (col:"
74 << col << ")" << endl;
75 return 0;
76 }
77
78 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
79 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
80
81 ColumnFormat** cl = m_cluster[ cx ];
82 if (!cl)
83 return 0;
84
85 return cl[ dx ];
86 }
87
lookup(int col) const88 const ColumnFormat* ColumnCluster::lookup(int col) const
89 {
90 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
91 debugSheets << "ColumnCluster::lookup: invalid column value (col:"
92 << col << ")" << endl;
93 return 0;
94 }
95
96 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
97 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
98
99 ColumnFormat** cl = m_cluster[ cx ];
100 if (!cl)
101 return 0;
102
103 return cl[ dx ];
104 }
105
clear()106 void ColumnCluster::clear()
107 {
108 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
109 ColumnFormat** cl = m_cluster[ x ];
110 if (cl) {
111 free(cl);
112 m_cluster[ x ] = 0;
113 }
114 }
115
116 if (m_autoDelete) {
117 ColumnFormat* cell = m_first;
118 while (cell) {
119 ColumnFormat* n = cell->next();
120 delete cell;
121 cell = n;
122 }
123 }
124
125 m_first = 0;
126 }
127
insertElement(ColumnFormat * lay,int col)128 void ColumnCluster::insertElement(ColumnFormat* lay, int col)
129 {
130 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
131 debugSheets << "ColumnCluster::insertElement: invalid column value (col:"
132 << col << ")" << endl;
133 return;
134 }
135
136 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
137 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
138
139 ColumnFormat** cl = m_cluster[ cx ];
140 if (!cl) {
141 cl = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*));
142 m_cluster[ cx ] = cl;
143
144 for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a)
145 cl[ a ] = 0;
146 }
147
148 if (cl[ dx ])
149 removeElement(col);
150
151 cl[ dx ] = lay;
152
153 if (m_first) {
154 lay->setNext(m_first);
155 m_first->setPrevious(lay);
156 }
157 m_first = lay;
158 }
159
removeElement(int col)160 void ColumnCluster::removeElement(int col)
161 {
162 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
163 debugSheets << "ColumnCluster::removeElement: invalid column value (col:"
164 << col << ")" << endl;
165 return;
166 }
167
168 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
169 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
170
171 ColumnFormat** cl = m_cluster[ cx ];
172 if (!cl)
173 return;
174
175 ColumnFormat* c = cl[ dx ];
176 if (!c)
177 return;
178
179 cl[ dx ] = 0;
180
181 if (m_autoDelete) {
182 if (m_first == c)
183 m_first = c->next();
184 delete c;
185 } else {
186 if (m_first == c)
187 m_first = c->next();
188 if (c->previous())
189 c->previous()->setNext(c->next());
190 if (c->next())
191 c->next()->setPrevious(c->previous());
192 c->setNext(0);
193 c->setPrevious(0);
194 }
195 }
196
insertColumn(int col)197 bool ColumnCluster::insertColumn(int col)
198 {
199 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
200 debugSheets << "ColumnCluster::insertColumn: invalid column value (col:"
201 << col << ")" << endl;
202 return false;
203 }
204
205 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
206 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
207
208 // Is there a column layout at the right most position ?
209 // In this case the shift is impossible.
210 ColumnFormat** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ];
211 if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ])
212 return false;
213
214 bool a = autoDelete();
215 setAutoDelete(false);
216
217 for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) {
218 ColumnFormat** cl = m_cluster[ i ];
219 if (cl) {
220 int left = 0;
221 if (i == cx)
222 left = dx;
223 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
224 if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1)
225 right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2;
226 for (int k = right; k >= left; --k) {
227 ColumnFormat* c = cl[ k ];
228 if (c) {
229 removeElement(c->column());
230 c->setColumn(c->column() + 1);
231 insertElement(c, c->column());
232 }
233 }
234 }
235 }
236
237 setAutoDelete(a);
238
239 return true;
240 }
241
removeColumn(int column)242 bool ColumnCluster::removeColumn(int column)
243 {
244 if (column >= CALLIGRA_SHEETS_CLUSTER_MAX || column < 0) {
245 debugSheets << "ColumnCluster::removeColumn: invalid column value (col:"
246 << column << ")" << endl;
247 return false;
248 }
249
250 int cx = column / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
251 int dx = column % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
252
253 removeElement(column);
254
255 bool a = autoDelete();
256 setAutoDelete(false);
257
258 for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
259 ColumnFormat** cl = m_cluster[ i ];
260 if (cl) {
261 int left = 0;
262 if (i == cx)
263 left = dx + 1;
264 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
265 for (int k = left; k <= right; ++k) {
266 ColumnFormat* c = cl[ k ];
267 if (c) {
268 removeElement(c->column());
269 c->setColumn(c->column() - 1);
270 insertElement(c, c->column());
271 }
272 }
273 }
274 }
275
276 setAutoDelete(a);
277
278 return true;
279 }
280
setAutoDelete(bool a)281 void ColumnCluster::setAutoDelete(bool a)
282 {
283 m_autoDelete = a;
284 }
285
autoDelete() const286 bool ColumnCluster::autoDelete() const
287 {
288 return m_autoDelete;
289 }
290
next(int col) const291 ColumnFormat* ColumnCluster::next(int col) const
292 {
293 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
294 debugSheets << "ColumnCluster::next: invalid column value (col:"
295 << col << ")" << endl;
296 return 0;
297 }
298
299 int cx = (col + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
300 int dx = (col + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
301
302 while (cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1) {
303 if (m_cluster[ cx ]) {
304 while (dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2) {
305
306 if (m_cluster[ cx ][ dx ]) {
307 return m_cluster[ cx ][ dx ];
308 }
309 ++dx;
310 }
311 }
312 ++cx;
313 dx = 0;
314 }
315 return 0;
316 }
317
operator =(const ColumnCluster & other)318 void ColumnCluster::operator=(const ColumnCluster & other)
319 {
320 m_first = 0;
321 m_autoDelete = other.m_autoDelete;
322 // TODO Stefan: Optimize!
323 m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**));
324 for (int i = 0; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
325 if (other.m_cluster[i]) {
326 m_cluster[i] = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*));
327 for (int j = 0; j < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++j) {
328 m_cluster[i][j] = 0;
329 if (other.m_cluster[i][j]) {
330 ColumnFormat* columnFormat = new ColumnFormat(*other.m_cluster[i][j]);
331 columnFormat->setNext(0);
332 columnFormat->setPrevious(0);
333 insertElement(columnFormat, columnFormat->column());
334 }
335 }
336 } else
337 m_cluster[i] = 0;
338 }
339 }
340
341
342