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 <kdebug.h>
27
28#include "Cell.h"
29#include "RowColumnFormat.h"
30
31using namespace Calligra::Sheets;
32
33#if 0
34/****************************************************
35 *
36 * Cluster
37 *
38 ****************************************************/
39
40/* Generate a matrix LEVEL1 with the size LEVEL1*LEVEL1 */
41Cluster::Cluster()
42 : m_first(0), m_autoDelete(false), m_biggestX(0), m_biggestY(0)
43{
44 m_cluster = (Cell***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(Cell**));
45
46 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
47 for (int y = 0; y < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y)
48 m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ] = 0;
49}
50
51/* Delete the matrix LEVEL1 and all existing LEVEL2 matrizes */
52Cluster::~Cluster()
53{
54// Can't we use clear(), to remove double code - Philipp?
55 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
56 for (int y = 0; y < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y) {
57 Cell** cl = m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ];
58 if (cl) {
59 free(cl);
60 m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ] = 0;
61 }
62 }
63
64 if (m_autoDelete) {
65 Cell* cell = m_first;
66 while (cell) {
67 Cell* n = cell->nextCell();
68 delete cell;
69 cell = n;
70 }
71 }
72
73 free(m_cluster);
74}
75
76void Cluster::clear()
77{
78 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
79 for (int y = 0; y < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y) {
80 Cell** cl = m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ];
81 if (cl) {
82 free(cl);
83 m_cluster[ y * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x ] = 0;
84 }
85 }
86
87 if (m_autoDelete) {
88 Cell* cell = m_first;
89 while (cell) {
90 Cell* n = cell->nextCell();
91 delete cell;
92 cell = n;
93 }
94 }
95
96 m_first = 0;
97 m_biggestX = m_biggestY = 0;
98}
99
100Cell* Cluster::lookup(int x, int y) const
101{
102 if (x >= CALLIGRA_SHEETS_CLUSTER_MAX || x < 0 || y >= CALLIGRA_SHEETS_CLUSTER_MAX || y < 0) {
103 kDebug(36001) << "Cluster::lookup: invalid column or row value (col:"
104 << x << " | row: " << y << ")" << endl;
105 return 0;
106 }
107 int cx = x / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
108 int cy = y / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
109 int dx = x % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
110 int dy = y % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
111
112 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
113 if (!cl)
114 return 0;
115
116 return cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ];
117}
118
119/* Paste a cell in LEVEL2 (it's more paste than insert) */
120void Cluster::insert(Cell* cell, int x, int y)
121{
122 if (x >= CALLIGRA_SHEETS_CLUSTER_MAX || x < 0 || y >= CALLIGRA_SHEETS_CLUSTER_MAX || y < 0) {
123 kDebug(36001) << "Cluster::insert: invalid column or row value (col:"
124 << x << " | row: " << y << ")" << endl;
125 return;
126 }
127
128 int cx = x / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
129 int cy = y / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
130 int dx = x % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
131 int dy = y % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
132
133 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
134 if (!cl) {
135 cl = (Cell**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(Cell*));
136 m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] = cl;
137
138 for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a)
139 for (int b = 0; b < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++b)
140 cl[ b * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + a ] = 0;
141 }
142
143 if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ])
144 remove(x, y);
145
146 cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ] = cell;
147
148 if (m_first) {
149 cell->setNextCell(m_first);
150 m_first->setPreviousCell(cell);
151 }
152 m_first = cell;
153
154 if (x > m_biggestX) m_biggestX = x;
155 if (y > m_biggestY) m_biggestY = y;
156}
157
158/* Removes the cell of a matrix, the matrix itself keeps unchanged */
159void Cluster::remove(int x, int y)
160{
161 if (x >= CALLIGRA_SHEETS_CLUSTER_MAX || x < 0 || y >= CALLIGRA_SHEETS_CLUSTER_MAX || y < 0) {
162 kDebug(36001) << "Cluster::remove: invalid column or row value (col:"
163 << x << " | row: " << y << ")" << endl;
164 return;
165 }
166
167 int cx = x / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
168 int cy = y / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
169 int dx = x % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
170 int dy = y % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
171
172 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
173 if (!cl)
174 return;
175
176 Cell* c = cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ];
177 if (!c)
178 return;
179
180 cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ] = 0;
181
182 if (m_autoDelete) {
183 if (m_first == c)
184 m_first = c->nextCell();
185 if (c->doesMergeCells()) {
186 c->mergeCells(c->column(), c->row(), 0, 0);
187 }
188 delete c;
189 } else {
190 if (m_first == c)
191 m_first = c->nextCell();
192 if (c->previousCell())
193 c->previousCell()->setNextCell(c->nextCell());
194 if (c->nextCell())
195 c->nextCell()->setPreviousCell(c->previousCell());
196 c->setNextCell(0);
197 c->setPreviousCell(0);
198 }
199}
200
201bool Cluster::insertShiftRight(const QPoint& marker)
202{
203 bool dummy;
204 return insertShiftRight(marker, dummy);
205}
206
207bool Cluster::insertShiftDown(const QPoint& marker)
208{
209 bool dummy;
210 return insertShiftDown(marker, dummy);
211}
212
213void Cluster::removeShiftUp(const QPoint& marker)
214{
215 bool dummy;
216 removeShiftUp(marker, dummy);
217}
218
219void Cluster::removeShiftLeft(const QPoint& marker)
220{
221 bool dummy;
222 removeShiftLeft(marker, dummy);
223}
224
225void Cluster::setAutoDelete(bool b)
226{
227 m_autoDelete = b;
228}
229
230bool Cluster::autoDelete() const
231{
232 return m_autoDelete;
233}
234
235Cell* Cluster::firstCell() const
236{
237 return m_first;
238}
239
240bool Cluster::insertShiftRight(const QPoint& marker, bool& work)
241{
242 work = false;
243
244 if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 ||
245 marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) {
246 kDebug(36001) << "Cluster::insertShiftRight: invalid column or row value (col:"
247 << marker.x() << " | row: " << marker.y() << ")" << endl;
248 return false;
249 }
250
251 int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
252 int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
253 int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
254 int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
255
256 // Is there a cell at the bottom most position ?
257 // In this case the shift is impossible.
258 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ];
259 if (cl && cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ])
260 return false;
261
262 bool a = autoDelete();
263 setAutoDelete(false);
264
265 // Move cells in this row one down.
266 for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) {
267 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + i ];
268 if (cl) {
269 work = true;
270 int left = 0;
271 if (i == cx)
272 left = dx;
273 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
274 if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1)
275 right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2;
276 for (int k = right; k >= left; --k) {
277 Cell* c = cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + k ];
278 if (c) {
279 remove(c->column(), c->row());
280 c->move(c->column() + 1, c->row());
281 insert(c, c->column(), c->row());
282 }
283 }
284 }
285 }
286
287 setAutoDelete(a);
288
289 return true;
290}
291
292bool Cluster::insertShiftDown(const QPoint& marker, bool& work)
293{
294 work = false;
295
296 if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 ||
297 marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) {
298 kDebug(36001) << "Cluster::insertShiftDown: invalid column or row value (col:"
299 << marker.x() << " | row: " << marker.y() << ")" << endl;
300 return false;
301 }
302
303 int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
304 int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
305 int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
306 int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
307
308 // Is there a cell at the right most position ?
309 // In this case the shift is impossible.
310 Cell** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 * (CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) + cx ];
311 if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 *(CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1) + dx ])
312 return false;
313
314 bool a = autoDelete();
315 setAutoDelete(false);
316
317 // Move cells in this column one right.
318 for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cy ; --i) {
319 Cell** cl = m_cluster[ i * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
320 if (cl) {
321 work = true;
322
323 int top = 0;
324 if (i == cy)
325 top = dy;
326 int bottom = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
327 if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1)
328 bottom = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2;
329 for (int k = bottom; k >= top; --k) {
330 Cell* c = cl[ k * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ];
331 if (c) {
332 remove(c->column(), c->row());
333 c->move(c->column(), c->row() + 1);
334 insert(c, c->column(), c->row());
335 }
336 }
337 }
338 }
339
340 setAutoDelete(a);
341
342 return true;
343}
344
345bool Cluster::insertColumn(int col)
346{
347 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
348 kDebug(36001) << "Cluster::insertColumn: invalid column value (col:"
349 << col << ")" << endl;
350 return false;
351 }
352
353 // Is there a cell at the right most position ?
354 // In this case the shift is impossible.
355 for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) {
356 Cell** cl = m_cluster[ t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ];
357 if (cl)
358 for (int t2 = 0; t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2)
359 if (cl[ t2 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ])
360 return false;
361 }
362
363 for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) {
364 bool work = true;
365 for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2)
366 insertShiftRight(QPoint(col, t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2), work);
367 }
368
369 return true;
370}
371
372bool Cluster::insertRow(int row)
373{
374 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
375 kDebug(36001) << "Cluster::insertRow: invalid row value (row:"
376 << row << ")" << endl;
377 return false;
378 }
379
380 // Is there a cell at the bottom most position ?
381 // In this case the shift is impossible.
382 for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) {
383 Cell** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 * (CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1) + t1 ];
384 if (cl)
385 for (int t2 = 0; t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2)
386 if (cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 *(CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1) + t2 ])
387 return false;
388 }
389
390 for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) {
391 bool work = true;
392 for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2)
393 insertShiftDown(QPoint(t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2, row), work);
394 }
395
396 return true;
397}
398
399void Cluster::removeShiftUp(const QPoint& marker, bool& work)
400{
401 work = false;
402
403 if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 ||
404 marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) {
405 kDebug(36001) << "Cluster::removeShiftUp: invalid column or row value (col:"
406 << marker.x() << " | row: " << marker.y() << ")" << endl;
407 return;
408 }
409
410 int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
411 int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
412 int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
413 int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
414
415 bool a = autoDelete();
416 setAutoDelete(false);
417
418 // Move cells in this column one column to the left.
419 for (int i = cy; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
420 Cell** cl = m_cluster[ i * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
421 if (cl) {
422 work = true;
423
424 int top = 0;
425 if (i == cy)
426 top = dy + 1;
427 int bottom = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
428 for (int k = top; k <= bottom; ++k) {
429 Cell* c = cl[ k * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ];
430 if (c) {
431 remove(c->column(), c->row());
432 c->move(c->column(), c->row() - 1);
433 insert(c, c->column(), c->row());
434 }
435 }
436 }
437 }
438
439 setAutoDelete(a);
440}
441
442void Cluster::removeShiftLeft(const QPoint& marker, bool& work)
443{
444 work = false;
445
446 if (marker.x() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.x() < 0 ||
447 marker.y() >= CALLIGRA_SHEETS_CLUSTER_MAX || marker.y() < 0) {
448 kDebug(36001) << "Cluster::removeShiftLeft: invalid column or row value (col:"
449 << marker.x() << " | row: " << marker.y() << ")" << endl;
450 return;
451 }
452
453 int cx = marker.x() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
454 int cy = marker.y() / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
455 int dx = marker.x() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
456 int dy = marker.y() % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
457
458 bool a = autoDelete();
459 setAutoDelete(false);
460
461 // Move cells in this row one row up.
462 for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
463 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + i ];
464 if (cl) {
465 work = true;
466
467 int left = 0;
468 if (i == cx)
469 left = dx + 1;
470 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
471 for (int k = left; k <= right; ++k) {
472 Cell* c = cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + k ];
473 if (c) {
474 remove(c->column(), c->row());
475 c->move(c->column() - 1, c->row());
476 insert(c, c->column(), c->row());
477 }
478 }
479 }
480 }
481
482 setAutoDelete(a);
483}
484
485void Cluster::removeColumn(int col)
486{
487 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
488 kDebug(36001) << "Cluster::removeColumn: invalid column value (col:"
489 << col << ")" << endl;
490 return;
491 }
492
493 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
494 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
495
496 for (int y1 = 0; y1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++y1) {
497 Cell** cl = m_cluster[ y1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
498 if (cl)
499 for (int y2 = 0; y2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++y2)
500 if (cl[ y2 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ])
501 remove(col, y1 * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + y2);
502 }
503
504 for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) {
505 bool work = true;
506 for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2)
507 removeShiftLeft(QPoint(col, t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2), work);
508 }
509}
510
511void Cluster::removeRow(int row)
512{
513 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
514 kDebug(36001) << "Cluster::removeRow: invalid row value (row:"
515 << row << ")" << endl;
516 return;
517 }
518
519 int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
520 int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
521
522 for (int x1 = 0; x1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x1) {
523 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + x1 ];
524 if (cl)
525 for (int x2 = 0; x2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++x2)
526 if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + x2 ])
527 remove(x1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + x2, row);
528 }
529
530 for (int t1 = 0; t1 < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++t1) {
531 bool work = true;
532 for (int t2 = 0; work && t2 < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++t2)
533 removeShiftUp(QPoint(t1 * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + t2, row), work);
534 }
535}
536
537void Cluster::clearColumn(int col)
538{
539 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
540 kDebug(36001) << "Cluster::clearColumn: invalid column value (col:"
541 << col << ")" << endl;
542 return;
543 }
544
545 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
546 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
547
548 for (int cy = 0; cy < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++cy) {
549 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ];
550 if (cl)
551 for (int dy = 0; dy < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++dy)
552 if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]) {
553 int row = cy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dy ;
554 remove(col, row);
555 }
556 }
557}
558
559void Cluster::clearRow(int row)
560{
561 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
562 kDebug(36001) << "Cluster::clearRow: invalid row value (row:"
563 << row << ")" << endl;
564 return;
565 }
566
567 int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
568 int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
569
570 for (int cx = 0; cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++cx) {
571 Cell** cl = m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + cx ];
572 if (cl)
573 for (int dx = 0; dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++dx)
574 if (cl[ dy * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ]) {
575 int column = cx * CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx ;
576 remove(column, row);
577 }
578 }
579}
580
581Value Cluster::valueRange(int col1, int row1,
582 int col2, int row2) const
583{
584 Value empty;
585
586 //swap first/second values if needed
587 if (col1 > col2) {
588 int p = col1; col1 = col2; col2 = p;
589 }
590 if (row1 > row2) {
591 int p = row1; row1 = col2; row2 = p;
592 }
593 if ((row1 < 0) || (col1 < 0) || (row2 > CALLIGRA_SHEETS_CLUSTER_MAX) ||
594 (col2 > CALLIGRA_SHEETS_CLUSTER_MAX))
595 return empty;
596
597 // if we are out of range occupied by cells, we return an empty
598 // array of the requested size
599 if ((row1 > m_biggestY) || (col1 > m_biggestX))
600 return Value(Value::Array);
601
602 return makeArray(col1, row1, col2, row2);
603}
604
605Value Cluster::makeArray(int col1, int row1, int col2, int row2) const
606{
607 // this generates an array of values
608 Value array(Value::Array);
609 for (int row = row1; row <= row2; ++row) {
610 for (Cell* cell = getFirstCellRow(row); cell; cell = getNextCellRight(cell->column(), row)) {
611 if (cell->column() >= col1 && cell->column() <= col2)
612 array.setElement(cell->column() - col1, row - row1, cell->value());
613 }
614 }
615 //return the result
616 return array;
617}
618
619Cell* Cluster::getFirstCellColumn(int col) const
620{
621 Cell* cell = lookup(col, 1);
622
623 if (cell == 0) {
624 cell = getNextCellDown(col, 1);
625 }
626 return cell;
627}
628
629Cell* Cluster::getLastCellColumn(int col) const
630{
631 Cell* cell = lookup(col, KS_rowMax);
632
633 if (cell == 0) {
634 cell = getNextCellUp(col, KS_rowMax);
635 }
636 return cell;
637}
638
639Cell* Cluster::getFirstCellRow(int row) const
640{
641 Cell* cell = lookup(1, row);
642
643 if (cell == 0) {
644 cell = getNextCellRight(1, row);
645 }
646 return cell;
647}
648
649Cell* Cluster::getLastCellRow(int row) const
650{
651 Cell* cell = lookup(KS_colMax, row);
652
653 if (cell == 0) {
654 cell = getNextCellLeft(KS_colMax, row);
655 }
656 return cell;
657}
658
659Cell* Cluster::getNextCellUp(int col, int row) const
660{
661 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
662 int cy = (row - 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
663 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
664 int dy = (row - 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
665
666 while (cy >= 0) {
667 if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) {
668 while (dy >= 0) {
669
670 if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx]
671 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) {
672 return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]
673 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx];
674 }
675 dy--;
676 }
677 }
678 cy--;
679 dy = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
680 }
681 return 0;
682}
683
684Cell* Cluster::getNextCellDown(int col, int row) const
685{
686 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
687 int cy = (row + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
688 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
689 int dy = (row + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
690
691 while (cy < CALLIGRA_SHEETS_CLUSTER_LEVEL1) {
692 if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) {
693 while (dy < CALLIGRA_SHEETS_CLUSTER_LEVEL2) {
694
695 if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx]
696 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) {
697 return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]
698 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx];
699 }
700 dy++;
701 }
702 }
703 cy++;
704 dy = 0;
705 }
706 return 0;
707}
708
709Cell* Cluster::getNextCellLeft(int col, int row) const
710{
711 int cx = (col - 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
712 int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
713 int dx = (col - 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
714 int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
715
716 while (cx >= 0) {
717 if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) {
718 while (dx >= 0) {
719
720 if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx]
721 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) {
722 return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]
723 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx];
724 }
725 dx--;
726 }
727 }
728 cx--;
729 dx = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
730 }
731 return 0;
732}
733
734Cell* Cluster::getNextCellRight(int col, int row) const
735{
736 int cx = (col + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
737 int cy = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
738 int dx = (col + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
739 int dy = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
740
741 while (cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1) {
742 if (m_cluster[ cy * CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ] != 0) {
743 while (dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2) {
744
745 if (m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx]
746 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx] != 0) {
747 return m_cluster[ cy*CALLIGRA_SHEETS_CLUSTER_LEVEL1 + cx ]
748 [ dy*CALLIGRA_SHEETS_CLUSTER_LEVEL2 + dx];
749 }
750 dx++;
751 }
752 }
753 cx++;
754 dx = 0;
755 }
756 return 0;
757}
758#endif
759
760/****************************************************
761 *
762 * ColumnCluster
763 *
764 ****************************************************/
765
766ColumnCluster::ColumnCluster()
767 : m_first(0), m_autoDelete(false)
768{
769 m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**));
770
771 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
772 m_cluster[ x ] = 0;
773}
774
775ColumnCluster::~ColumnCluster()
776{
777 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
778 ColumnFormat** cl = m_cluster[ x ];
779 if (cl) {
780 free(cl);
781 m_cluster[ x ] = 0;
782 }
783 }
784
785 if (m_autoDelete) {
786 ColumnFormat* cell = m_first;
787 while (cell) {
788 ColumnFormat* n = cell->next();
789 delete cell;
790 cell = n;
791 }
792 }
793
794
795 free(m_cluster);
796}
797
798ColumnFormat* ColumnCluster::lookup(int col)
799{
800 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
801 kDebug(36001) << "ColumnCluster::lookup: invalid column value (col:"
802 << col << ")" << endl;
803 return 0;
804 }
805
806 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
807 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
808
809 ColumnFormat** cl = m_cluster[ cx ];
810 if (!cl)
811 return 0;
812
813 return cl[ dx ];
814}
815
816const ColumnFormat* ColumnCluster::lookup(int col) const
817{
818 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
819 kDebug(36001) << "ColumnCluster::lookup: invalid column value (col:"
820 << col << ")" << endl;
821 return 0;
822 }
823
824 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
825 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
826
827 ColumnFormat** cl = m_cluster[ cx ];
828 if (!cl)
829 return 0;
830
831 return cl[ dx ];
832}
833
834void ColumnCluster::clear()
835{
836 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
837 ColumnFormat** cl = m_cluster[ x ];
838 if (cl) {
839 free(cl);
840 m_cluster[ x ] = 0;
841 }
842 }
843
844 if (m_autoDelete) {
845 ColumnFormat* cell = m_first;
846 while (cell) {
847 ColumnFormat* n = cell->next();
848 delete cell;
849 cell = n;
850 }
851 }
852
853 m_first = 0;
854}
855
856void ColumnCluster::insertElement(ColumnFormat* lay, int col)
857{
858 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
859 kDebug(36001) << "ColumnCluster::insertElement: invalid column value (col:"
860 << col << ")" << endl;
861 return;
862 }
863
864 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
865 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
866
867 ColumnFormat** cl = m_cluster[ cx ];
868 if (!cl) {
869 cl = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*));
870 m_cluster[ cx ] = cl;
871
872 for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a)
873 cl[ a ] = 0;
874 }
875
876 if (cl[ dx ])
877 removeElement(col);
878
879 cl[ dx ] = lay;
880
881 if (m_first) {
882 lay->setNext(m_first);
883 m_first->setPrevious(lay);
884 }
885 m_first = lay;
886}
887
888void ColumnCluster::removeElement(int col)
889{
890 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
891 kDebug(36001) << "ColumnCluster::removeElement: invalid column value (col:"
892 << col << ")" << endl;
893 return;
894 }
895
896 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
897 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
898
899 ColumnFormat** cl = m_cluster[ cx ];
900 if (!cl)
901 return;
902
903 ColumnFormat* c = cl[ dx ];
904 if (!c)
905 return;
906
907 cl[ dx ] = 0;
908
909 if (m_autoDelete) {
910 if (m_first == c)
911 m_first = c->next();
912 delete c;
913 } else {
914 if (m_first == c)
915 m_first = c->next();
916 if (c->previous())
917 c->previous()->setNext(c->next());
918 if (c->next())
919 c->next()->setPrevious(c->previous());
920 c->setNext(0);
921 c->setPrevious(0);
922 }
923}
924
925bool ColumnCluster::insertColumn(int col)
926{
927 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
928 kDebug(36001) << "ColumnCluster::insertColumn: invalid column value (col:"
929 << col << ")" << endl;
930 return false;
931 }
932
933 int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
934 int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
935
936 // Is there a column layout at the right most position ?
937 // In this case the shift is impossible.
938 ColumnFormat** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ];
939 if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ])
940 return false;
941
942 bool a = autoDelete();
943 setAutoDelete(false);
944
945 for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) {
946 ColumnFormat** cl = m_cluster[ i ];
947 if (cl) {
948 int left = 0;
949 if (i == cx)
950 left = dx;
951 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
952 if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1)
953 right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2;
954 for (int k = right; k >= left; --k) {
955 ColumnFormat* c = cl[ k ];
956 if (c) {
957 removeElement(c->column());
958 c->setColumn(c->column() + 1);
959 insertElement(c, c->column());
960 }
961 }
962 }
963 }
964
965 setAutoDelete(a);
966
967 return true;
968}
969
970bool ColumnCluster::removeColumn(int column)
971{
972 if (column >= CALLIGRA_SHEETS_CLUSTER_MAX || column < 0) {
973 kDebug(36001) << "ColumnCluster::removeColumn: invalid column value (col:"
974 << column << ")" << endl;
975 return false;
976 }
977
978 int cx = column / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
979 int dx = column % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
980
981 removeElement(column);
982
983 bool a = autoDelete();
984 setAutoDelete(false);
985
986 for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
987 ColumnFormat** cl = m_cluster[ i ];
988 if (cl) {
989 int left = 0;
990 if (i == cx)
991 left = dx + 1;
992 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
993 for (int k = left; k <= right; ++k) {
994 ColumnFormat* c = cl[ k ];
995 if (c) {
996 removeElement(c->column());
997 c->setColumn(c->column() - 1);
998 insertElement(c, c->column());
999 }
1000 }
1001 }
1002 }
1003
1004 setAutoDelete(a);
1005
1006 return true;
1007}
1008
1009void ColumnCluster::setAutoDelete(bool a)
1010{
1011 m_autoDelete = a;
1012}
1013
1014bool ColumnCluster::autoDelete() const
1015{
1016 return m_autoDelete;
1017}
1018
1019ColumnFormat* ColumnCluster::next(int col) const
1020{
1021 if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
1022 kDebug(36001) << "ColumnCluster::next: invalid column value (col:"
1023 << col << ")" << endl;
1024 return 0;
1025 }
1026
1027 int cx = (col + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1028 int dx = (col + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1029
1030 while (cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1) {
1031 if (m_cluster[ cx ]) {
1032 while (dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2) {
1033
1034 if (m_cluster[ cx ][ dx ]) {
1035 return m_cluster[ cx ][ dx ];
1036 }
1037 ++dx;
1038 }
1039 }
1040 ++cx;
1041 dx = 0;
1042 }
1043 return 0;
1044}
1045
1046void ColumnCluster::operator=(const ColumnCluster & other)
1047{
1048 m_first = 0;
1049 m_autoDelete = other.m_autoDelete;
1050 // TODO Stefan: Optimize!
1051 m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**));
1052 for (int i = 0; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
1053 if (other.m_cluster[i]) {
1054 m_cluster[i] = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*));
1055 for (int j = 0; j < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++j) {
1056 m_cluster[i][j] = 0;
1057 if (other.m_cluster[i][j]) {
1058 ColumnFormat* columnFormat = new ColumnFormat(*other.m_cluster[i][j]);
1059 columnFormat->setNext(0);
1060 columnFormat->setPrevious(0);
1061 insertElement(columnFormat, columnFormat->column());
1062 }
1063 }
1064 } else
1065 m_cluster[i] = 0;
1066 }
1067}
1068
1069/****************************************************
1070 *
1071 * RowCluster
1072 *
1073 ****************************************************/
1074
1075RowCluster::RowCluster()
1076 : m_first(0), m_autoDelete(false)
1077{
1078 m_cluster = (RowFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(RowFormat**));
1079
1080 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
1081 m_cluster[ x ] = 0;
1082}
1083
1084RowCluster::~RowCluster()
1085{
1086 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
1087 RowFormat** cl = m_cluster[ x ];
1088 if (cl) {
1089 free(cl);
1090 m_cluster[ x ] = 0;
1091 }
1092 }
1093
1094 if (m_autoDelete) {
1095 RowFormat* cell = m_first;
1096 while (cell) {
1097 RowFormat* n = cell->next();
1098 delete cell;
1099 cell = n;
1100 }
1101 }
1102
1103 free(m_cluster);
1104}
1105
1106const RowFormat* RowCluster::lookup(int row) const
1107{
1108 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
1109 kDebug(36001) << "RowCluster::lookup: invalid row value (row:"
1110 << row << ")" << endl;
1111 return 0;
1112 }
1113
1114 int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1115 int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1116
1117 RowFormat** cl = m_cluster[ cx ];
1118 if (!cl)
1119 return 0;
1120
1121 return cl[ dx ];
1122}
1123
1124RowFormat* RowCluster::lookup(int row)
1125{
1126 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
1127 kDebug(36001) << "RowCluster::lookup: invalid row value (row:"
1128 << row << ")" << endl;
1129 return 0;
1130 }
1131
1132 int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1133 int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1134
1135 RowFormat** cl = m_cluster[ cx ];
1136 if (!cl)
1137 return 0;
1138
1139 return cl[ dx ];
1140}
1141
1142void RowCluster::clear()
1143{
1144 for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
1145 RowFormat** cl = m_cluster[ x ];
1146 if (cl) {
1147 free(cl);
1148 m_cluster[ x ] = 0;
1149 }
1150 }
1151
1152 if (m_autoDelete) {
1153 RowFormat* cell = m_first;
1154 while (cell) {
1155 RowFormat* n = cell->next();
1156 delete cell;
1157 cell = n;
1158 }
1159 }
1160
1161 m_first = 0;
1162}
1163
1164void RowCluster::insertElement(RowFormat* lay, int row)
1165{
1166 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
1167 kDebug(36001) << "RowCluster::insertElement: invalid row value (row:"
1168 << row << ")" << endl;
1169 return;
1170 }
1171
1172 int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1173 int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1174
1175 RowFormat** cl = m_cluster[ cx ];
1176 if (!cl) {
1177 cl = (RowFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(RowFormat*));
1178 m_cluster[ cx ] = cl;
1179
1180 for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a)
1181 cl[ a ] = 0;
1182 }
1183
1184 if (cl[ dx ])
1185 removeElement(row);
1186
1187 cl[ dx ] = lay;
1188
1189 if (m_first) {
1190 lay->setNext(m_first);
1191 m_first->setPrevious(lay);
1192 }
1193 m_first = lay;
1194}
1195
1196void RowCluster::removeElement(int row)
1197{
1198 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
1199 kDebug(36001) << "RowCluster::removeElement: invalid row value (row:"
1200 << row << ")" << endl;
1201 return;
1202 }
1203
1204 int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1205 int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1206
1207 RowFormat** cl = m_cluster[ cx ];
1208 if (!cl)
1209 return;
1210
1211 RowFormat* c = cl[ dx ];
1212 if (!c)
1213 return;
1214
1215 cl[ dx ] = 0;
1216
1217 if (m_autoDelete) {
1218 if (m_first == c)
1219 m_first = c->next();
1220 delete c;
1221 } else {
1222 if (m_first == c)
1223 m_first = c->next();
1224 if (c->previous())
1225 c->previous()->setNext(c->next());
1226 if (c->next())
1227 c->next()->setPrevious(c->previous());
1228 c->setNext(0);
1229 c->setPrevious(0);
1230 }
1231}
1232
1233bool RowCluster::insertRow(int row)
1234{
1235 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
1236 kDebug(36001) << "RowCluster::insertRow: invalid row value (row:"
1237 << row << ")" << endl;
1238 return false;
1239 }
1240
1241 int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1242 int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1243
1244 // Is there a row layout at the bottom most position ?
1245 // In this case the shift is impossible.
1246 RowFormat** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ];
1247 if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ])
1248 return false;
1249
1250 bool a = autoDelete();
1251 setAutoDelete(false);
1252
1253 for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) {
1254 RowFormat** cl = m_cluster[ i ];
1255 if (cl) {
1256 int left = 0;
1257 if (i == cx)
1258 left = dx;
1259 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
1260 if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1)
1261 right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2;
1262 for (int k = right; k >= left; --k) {
1263 RowFormat* c = cl[ k ];
1264 if (c) {
1265 removeElement(c->row());
1266 c->setRow(c->row() + 1);
1267 insertElement(c, c->row());
1268 }
1269 }
1270 }
1271 }
1272
1273 setAutoDelete(a);
1274
1275 return true;
1276}
1277
1278bool RowCluster::removeRow(int row)
1279{
1280 if (row >= CALLIGRA_SHEETS_CLUSTER_MAX || row < 0) {
1281 kDebug(36001) << "RowCluster::removeRow: invalid row value (row:"
1282 << row << ")" << endl;
1283 return false;
1284 }
1285
1286 int cx = row / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1287 int dx = row % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
1288
1289 removeElement(row);
1290
1291 bool a = autoDelete();
1292 setAutoDelete(false);
1293
1294 for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
1295 RowFormat** cl = m_cluster[ i ];
1296 if (cl) {
1297 int left = 0;
1298 if (i == cx)
1299 left = dx + 1;
1300 int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
1301 for (int k = left; k <= right; ++k) {
1302 RowFormat* c = cl[ k ];
1303 if (c) {
1304 removeElement(c->row());
1305 c->setRow(c->row() - 1);
1306 insertElement(c, c->row());
1307 }
1308 }
1309 }
1310 }
1311
1312 setAutoDelete(a);
1313
1314 return true;
1315}
1316
1317void RowCluster::setAutoDelete(bool a)
1318{
1319 m_autoDelete = a;
1320}
1321
1322bool RowCluster::autoDelete() const
1323{
1324 return m_autoDelete;
1325}
1326
1327void RowCluster::operator=(const RowCluster & other)
1328{
1329 m_first = 0;
1330 m_autoDelete = other.m_autoDelete;
1331 // TODO Stefan: Optimize!
1332 m_cluster = (RowFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(RowFormat**));
1333 for (int i = 0; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
1334 if (other.m_cluster[i]) {
1335 m_cluster[i] = (RowFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(RowFormat*));
1336 for (int j = 0; j < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++j) {
1337 m_cluster[i][j] = 0;
1338 if (other.m_cluster[i][j]) {
1339 RowFormat* rowFormat = new RowFormat(*other.m_cluster[i][j]);
1340 rowFormat->setNext(0);
1341 rowFormat->setPrevious(0);
1342 insertElement(rowFormat, rowFormat->row());
1343 }
1344 }
1345 } else
1346 m_cluster[i] = 0;
1347 }
1348}
1349