File indexing completed on 2024-04-28 16:21:20

0001 /* This file is part of the KDE project
0002    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
0003    Copyright (C) 2000 Torben Weis <weis@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 // Local
0022 #include "Cluster.h"
0023 
0024 #include <stdlib.h>
0025 
0026 #include "SheetsDebug.h"
0027 #include "Cell.h"
0028 #include "RowColumnFormat.h"
0029 
0030 using namespace Calligra::Sheets;
0031 
0032 /****************************************************
0033  *
0034  * ColumnCluster
0035  *
0036  ****************************************************/
0037 
0038 ColumnCluster::ColumnCluster()
0039         : m_first(0), m_autoDelete(false)
0040 {
0041     m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**));
0042 
0043     for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x)
0044         m_cluster[ x ] = 0;
0045 }
0046 
0047 ColumnCluster::~ColumnCluster()
0048 {
0049     for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
0050         ColumnFormat** cl = m_cluster[ x ];
0051         if (cl) {
0052             free(cl);
0053             m_cluster[ x ] = 0;
0054         }
0055     }
0056 
0057     if (m_autoDelete) {
0058         ColumnFormat* cell = m_first;
0059         while (cell) {
0060             ColumnFormat* n = cell->next();
0061             delete cell;
0062             cell = n;
0063         }
0064     }
0065 
0066 
0067     free(m_cluster);
0068 }
0069 
0070 ColumnFormat* ColumnCluster::lookup(int col)
0071 {
0072     if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
0073         debugSheets << "ColumnCluster::lookup: invalid column value (col:"
0074         << col << ")" << endl;
0075         return 0;
0076     }
0077 
0078     int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0079     int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0080 
0081     ColumnFormat** cl = m_cluster[ cx ];
0082     if (!cl)
0083         return 0;
0084 
0085     return cl[ dx ];
0086 }
0087 
0088 const ColumnFormat* ColumnCluster::lookup(int col) const
0089 {
0090     if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
0091         debugSheets << "ColumnCluster::lookup: invalid column value (col:"
0092         << col << ")" << endl;
0093         return 0;
0094     }
0095 
0096     int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0097     int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0098 
0099     ColumnFormat** cl = m_cluster[ cx ];
0100     if (!cl)
0101         return 0;
0102 
0103     return cl[ dx ];
0104 }
0105 
0106 void ColumnCluster::clear()
0107 {
0108     for (int x = 0; x < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++x) {
0109         ColumnFormat** cl = m_cluster[ x ];
0110         if (cl) {
0111             free(cl);
0112             m_cluster[ x ] = 0;
0113         }
0114     }
0115 
0116     if (m_autoDelete) {
0117         ColumnFormat* cell = m_first;
0118         while (cell) {
0119             ColumnFormat* n = cell->next();
0120             delete cell;
0121             cell = n;
0122         }
0123     }
0124 
0125     m_first = 0;
0126 }
0127 
0128 void ColumnCluster::insertElement(ColumnFormat* lay, int col)
0129 {
0130     if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
0131         debugSheets << "ColumnCluster::insertElement: invalid column value (col:"
0132         << col << ")" << endl;
0133         return;
0134     }
0135 
0136     int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0137     int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0138 
0139     ColumnFormat** cl = m_cluster[ cx ];
0140     if (!cl) {
0141         cl = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*));
0142         m_cluster[ cx ] = cl;
0143 
0144         for (int a = 0; a < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++a)
0145             cl[ a ] = 0;
0146     }
0147 
0148     if (cl[ dx ])
0149         removeElement(col);
0150 
0151     cl[ dx ] = lay;
0152 
0153     if (m_first) {
0154         lay->setNext(m_first);
0155         m_first->setPrevious(lay);
0156     }
0157     m_first = lay;
0158 }
0159 
0160 void ColumnCluster::removeElement(int col)
0161 {
0162     if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
0163         debugSheets << "ColumnCluster::removeElement: invalid column value (col:"
0164         << col << ")" << endl;
0165         return;
0166     }
0167 
0168     int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0169     int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0170 
0171     ColumnFormat** cl = m_cluster[ cx ];
0172     if (!cl)
0173         return;
0174 
0175     ColumnFormat* c = cl[ dx ];
0176     if (!c)
0177         return;
0178 
0179     cl[ dx ] = 0;
0180 
0181     if (m_autoDelete) {
0182         if (m_first == c)
0183             m_first = c->next();
0184         delete c;
0185     } else {
0186         if (m_first == c)
0187             m_first = c->next();
0188         if (c->previous())
0189             c->previous()->setNext(c->next());
0190         if (c->next())
0191             c->next()->setPrevious(c->previous());
0192         c->setNext(0);
0193         c->setPrevious(0);
0194     }
0195 }
0196 
0197 bool ColumnCluster::insertColumn(int col)
0198 {
0199     if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
0200         debugSheets << "ColumnCluster::insertColumn: invalid column value (col:"
0201         << col << ")" << endl;
0202         return false;
0203     }
0204 
0205     int cx = col / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0206     int dx = col % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0207 
0208     // Is there a column layout at the right most position ?
0209     // In this case the shift is impossible.
0210     ColumnFormat** cl = m_cluster[ CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1 ];
0211     if (cl && cl[ CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1 ])
0212         return false;
0213 
0214     bool a = autoDelete();
0215     setAutoDelete(false);
0216 
0217     for (int i = CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1; i >= cx ; --i) {
0218         ColumnFormat** cl = m_cluster[ i ];
0219         if (cl) {
0220             int left = 0;
0221             if (i == cx)
0222                 left = dx;
0223             int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
0224             if (i == CALLIGRA_SHEETS_CLUSTER_LEVEL1 - 1)
0225                 right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 2;
0226             for (int k = right; k >= left; --k) {
0227                 ColumnFormat* c = cl[ k ];
0228                 if (c) {
0229                     removeElement(c->column());
0230                     c->setColumn(c->column() + 1);
0231                     insertElement(c, c->column());
0232                 }
0233             }
0234         }
0235     }
0236 
0237     setAutoDelete(a);
0238 
0239     return true;
0240 }
0241 
0242 bool ColumnCluster::removeColumn(int column)
0243 {
0244     if (column >= CALLIGRA_SHEETS_CLUSTER_MAX || column < 0) {
0245         debugSheets << "ColumnCluster::removeColumn: invalid column value (col:"
0246         << column << ")" << endl;
0247         return false;
0248     }
0249 
0250     int cx = column / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0251     int dx = column % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0252 
0253     removeElement(column);
0254 
0255     bool a = autoDelete();
0256     setAutoDelete(false);
0257 
0258     for (int i = cx; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
0259         ColumnFormat** cl = m_cluster[ i ];
0260         if (cl) {
0261             int left = 0;
0262             if (i == cx)
0263                 left = dx + 1;
0264             int right = CALLIGRA_SHEETS_CLUSTER_LEVEL2 - 1;
0265             for (int k = left; k <= right; ++k) {
0266                 ColumnFormat* c = cl[ k ];
0267                 if (c) {
0268                     removeElement(c->column());
0269                     c->setColumn(c->column() - 1);
0270                     insertElement(c, c->column());
0271                 }
0272             }
0273         }
0274     }
0275 
0276     setAutoDelete(a);
0277 
0278     return true;
0279 }
0280 
0281 void ColumnCluster::setAutoDelete(bool a)
0282 {
0283     m_autoDelete = a;
0284 }
0285 
0286 bool ColumnCluster::autoDelete() const
0287 {
0288     return m_autoDelete;
0289 }
0290 
0291 ColumnFormat* ColumnCluster::next(int col) const
0292 {
0293     if (col >= CALLIGRA_SHEETS_CLUSTER_MAX || col < 0) {
0294         debugSheets << "ColumnCluster::next: invalid column value (col:"
0295         << col << ")" << endl;
0296         return 0;
0297     }
0298 
0299     int cx = (col + 1) / CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0300     int dx = (col + 1) % CALLIGRA_SHEETS_CLUSTER_LEVEL2;
0301 
0302     while (cx < CALLIGRA_SHEETS_CLUSTER_LEVEL1) {
0303         if (m_cluster[ cx ]) {
0304             while (dx < CALLIGRA_SHEETS_CLUSTER_LEVEL2) {
0305 
0306                 if (m_cluster[ cx ][  dx ]) {
0307                     return m_cluster[ cx ][ dx ];
0308                 }
0309                 ++dx;
0310             }
0311         }
0312         ++cx;
0313         dx = 0;
0314     }
0315     return 0;
0316 }
0317 
0318 void ColumnCluster::operator=(const ColumnCluster & other)
0319 {
0320     m_first = 0;
0321     m_autoDelete = other.m_autoDelete;
0322     // TODO Stefan: Optimize!
0323     m_cluster = (ColumnFormat***)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL1 * sizeof(ColumnFormat**));
0324     for (int i = 0; i < CALLIGRA_SHEETS_CLUSTER_LEVEL1; ++i) {
0325         if (other.m_cluster[i]) {
0326             m_cluster[i] = (ColumnFormat**)malloc(CALLIGRA_SHEETS_CLUSTER_LEVEL2 * sizeof(ColumnFormat*));
0327             for (int j = 0; j < CALLIGRA_SHEETS_CLUSTER_LEVEL2; ++j) {
0328                 m_cluster[i][j] = 0;
0329                 if (other.m_cluster[i][j]) {
0330                     ColumnFormat* columnFormat = new ColumnFormat(*other.m_cluster[i][j]);
0331                     columnFormat->setNext(0);
0332                     columnFormat->setPrevious(0);
0333                     insertElement(columnFormat, columnFormat->column());
0334                 }
0335             }
0336         } else
0337             m_cluster[i] = 0;
0338     }
0339 }
0340 
0341