kspread Library API Documentation

kspread_cluster.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
00003    Copyright (C) 2000 Torben Weis <weis@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <stdlib.h>
00022 
00023 #include <kdebug.h>
00024 
00025 #include "kspread_cluster.h"
00026 #include "kspread_cell.h"
00027 
00028 /****************************************************
00029  *
00030  * KSpreadCluster
00031  *
00032  ****************************************************/
00033 
00034 /* Generate a matrix LEVEL1 with the size LEVEL1*LEVEL1 */
00035 KSpreadCluster::KSpreadCluster()
00036     : m_first( 0 ), m_autoDelete( FALSE ), m_biggestX(0), m_biggestY(0)
00037 {
00038     m_cluster = (KSpreadCell***)malloc( KSPREAD_CLUSTER_LEVEL1 * KSPREAD_CLUSTER_LEVEL1 * sizeof( KSpreadCell** ) );
00039 
00040     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
00041     for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y )
00042         m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0;
00043 }
00044 
00045 /* Delete the matrix LEVEL1 and all existing LEVEL2 matrizes */
00046 KSpreadCluster::~KSpreadCluster()
00047 {
00048 // Can't we use clear(), to remove double code - Philipp?
00049     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
00050     for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y )
00051         {
00052         KSpreadCell** cl = m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ];
00053         if ( cl )
00054         {
00055         free( cl );
00056         m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0;
00057         }
00058     }
00059 
00060     if ( m_autoDelete )
00061     {
00062     KSpreadCell* cell = m_first;
00063     while( cell )
00064         {
00065         KSpreadCell* n = cell->nextCell();
00066         delete cell;
00067         cell = n;
00068     }
00069     }
00070 
00071     free( m_cluster );
00072 }
00073 
00074 void KSpreadCluster::clear()
00075 {
00076     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
00077     for( int y = 0; y < KSPREAD_CLUSTER_LEVEL1; ++y )
00078         {
00079         KSpreadCell** cl = m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ];
00080         if ( cl )
00081         {
00082         free( cl );
00083         m_cluster[ y * KSPREAD_CLUSTER_LEVEL1 + x ] = 0;
00084         }
00085     }
00086 
00087     if ( m_autoDelete )
00088     {
00089     KSpreadCell* cell = m_first;
00090     while( cell )
00091         {
00092         KSpreadCell* n = cell->nextCell();
00093         delete cell;
00094         cell = n;
00095     }
00096     }
00097 
00098     m_first = 0;
00099     m_biggestX = m_biggestY = 0;
00100 }
00101 
00102 KSpreadCell* KSpreadCluster::lookup( int x, int y ) const
00103 {
00104     if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 )
00105     {
00106     kdDebug(36001) << "KSpreadCluster::lookup: invalid column or row value (col: "
00107                << x << "  | row: " << y << ")" << endl;
00108     return 0;
00109     }
00110     int cx = x / KSPREAD_CLUSTER_LEVEL2;
00111     int cy = y / KSPREAD_CLUSTER_LEVEL2;
00112     int dx = x % KSPREAD_CLUSTER_LEVEL2;
00113     int dy = y % KSPREAD_CLUSTER_LEVEL2;
00114 
00115     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ];
00116     if ( !cl )
00117     return 0;
00118 
00119     return cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ];
00120 }
00121 
00122 /* Paste a cell in LEVEL2 (it's more paste than insert) */
00123 void KSpreadCluster::insert( KSpreadCell* cell, int x, int y )
00124 {
00125     if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 )
00126     {
00127     kdDebug(36001) << "KSpreadCluster::insert: invalid column or row value (col: "
00128                << x << "  | row: " << y << ")" << endl;
00129     return;
00130     }
00131 
00132     int cx = x / KSPREAD_CLUSTER_LEVEL2;
00133     int cy = y / KSPREAD_CLUSTER_LEVEL2;
00134     int dx = x % KSPREAD_CLUSTER_LEVEL2;
00135     int dy = y % KSPREAD_CLUSTER_LEVEL2;
00136 
00137     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ];
00138     if ( !cl )
00139     {
00140     cl = (KSpreadCell**)malloc(  KSPREAD_CLUSTER_LEVEL2 * KSPREAD_CLUSTER_LEVEL2 * sizeof( KSpreadCell*  ) );
00141     m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] = cl;
00142 
00143     for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a )
00144         for( int b = 0; b < KSPREAD_CLUSTER_LEVEL2; ++b )
00145         cl[ b * KSPREAD_CLUSTER_LEVEL2 + a ] = 0;
00146     }
00147 
00148     if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] )
00149     remove( x, y );
00150 
00151     cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] = cell;
00152 
00153     if ( m_first )
00154     {
00155     cell->setNextCell( m_first );
00156     m_first->setPreviousCell( cell );
00157     }
00158     m_first = cell;
00159     
00160     if (x > m_biggestX) m_biggestX = x;
00161     if (y > m_biggestY) m_biggestY = y;
00162 }
00163 
00164 /* Removes the cell of a matrix, the matrix itself keeps unchanged */
00165 void KSpreadCluster::remove( int x, int y )
00166 {
00167     if ( x >= KSPREAD_CLUSTER_MAX || x < 0 || y >= KSPREAD_CLUSTER_MAX || y < 0 )
00168     {
00169     kdDebug(36001) << "KSpreadCluster::remove: invalid column or row value (col: "
00170                << x << "  | row: " << y << ")" << endl;
00171     return;
00172     }
00173 
00174     int cx = x / KSPREAD_CLUSTER_LEVEL2;
00175     int cy = y / KSPREAD_CLUSTER_LEVEL2;
00176     int dx = x % KSPREAD_CLUSTER_LEVEL2;
00177     int dy = y % KSPREAD_CLUSTER_LEVEL2;
00178 
00179     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ];
00180     if ( !cl )
00181     return;
00182 
00183     KSpreadCell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ];
00184     if ( !c )
00185     return;
00186 
00187     cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] = 0;
00188 
00189     if ( m_autoDelete )
00190     {
00191     if ( m_first == c )
00192         m_first = c->nextCell();
00193         if(c->isForceExtraCells())
00194         {
00195         c->forceExtraCells(c->column(),c->row(),0,0);
00196         }
00197     delete c;
00198     }
00199     else
00200     {
00201     if ( m_first == c )
00202         m_first = c->nextCell();
00203     if ( c->previousCell() )
00204         c->previousCell()->setNextCell( c->nextCell() );
00205     if ( c->nextCell() )
00206         c->nextCell()->setPreviousCell( c->previousCell() );
00207     c->setNextCell( 0 );
00208     c->setPreviousCell( 0 );
00209     }
00210 }
00211 
00212 bool KSpreadCluster::shiftRow( const QPoint& marker )
00213 {
00214     bool dummy;
00215     return shiftRow( marker, dummy );
00216 }
00217 
00218 bool KSpreadCluster::shiftColumn( const QPoint& marker )
00219 {
00220     bool dummy;
00221     return shiftColumn( marker, dummy );
00222 }
00223 
00224 void KSpreadCluster::unshiftColumn( const QPoint& marker )
00225 {
00226     bool dummy;
00227     unshiftColumn( marker, dummy );
00228 }
00229 
00230 void KSpreadCluster::unshiftRow( const QPoint& marker )
00231 {
00232     bool dummy;
00233     unshiftRow( marker, dummy );
00234 }
00235 
00236 void KSpreadCluster::setAutoDelete( bool b )
00237 {
00238     m_autoDelete = b;
00239 }
00240 
00241 bool KSpreadCluster::autoDelete() const
00242 {
00243     return m_autoDelete;
00244 }
00245 
00246 KSpreadCell* KSpreadCluster::firstCell() const
00247 {
00248     return m_first;
00249 }
00250 
00251 bool KSpreadCluster::shiftRow( const QPoint& marker, bool& work )
00252 {
00253     work = FALSE;
00254 
00255     if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 ||
00256      marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 )
00257     {
00258     kdDebug(36001) << "KSpreadCluster::shiftRow: invalid column or row value (col: "
00259                << marker.x() << "  | row: " << marker.y() << ")" << endl;
00260     return FALSE;
00261     }
00262 
00263     int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2;
00264     int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2;
00265     int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2;
00266     int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2;
00267 
00268     // Is there a cell at the bottom most position ?
00269     // In this case the shift is impossible.
00270     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + KSPREAD_CLUSTER_LEVEL1 - 1 ];
00271     if ( cl && cl[ dy * KSPREAD_CLUSTER_LEVEL2 + KSPREAD_CLUSTER_LEVEL2 - 1 ] )
00272     return FALSE;
00273 
00274     bool a = autoDelete();
00275     setAutoDelete( FALSE );
00276 
00277     // Move cells in this row one down.
00278     for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i )
00279     {
00280     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + i ];
00281     if ( cl )
00282         {
00283         work = TRUE;
00284         int left = 0;
00285         if ( i == cx )
00286         left = dx;
00287         int right = KSPREAD_CLUSTER_LEVEL2 - 1;
00288         if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 )
00289         right = KSPREAD_CLUSTER_LEVEL2 - 2;
00290         for( int k = right; k >= left; --k )
00291         {
00292         KSpreadCell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + k ];
00293         if ( c )
00294             {
00295             remove( c->column(), c->row() );
00296             c->move( c->column() + 1, c->row() );
00297             insert( c, c->column(), c->row() );
00298         }
00299         }
00300     }
00301     }
00302 
00303     setAutoDelete( a );
00304 
00305     return TRUE;
00306 }
00307 
00308 bool KSpreadCluster::shiftColumn( const QPoint& marker, bool& work )
00309 {
00310     work = FALSE;
00311 
00312     if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 ||
00313      marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 )
00314     {
00315     kdDebug(36001) << "KSpreadCluster::shiftColumn: invalid column or row value (col: "
00316                << marker.x() << "  | row: " << marker.y() << ")" << endl;
00317     return FALSE;
00318     }
00319 
00320     int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2;
00321     int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2;
00322     int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2;
00323     int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2;
00324 
00325     // Is there a cell at the right most position ?
00326     // In this case the shift is impossible.
00327     KSpreadCell** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 * ( KSPREAD_CLUSTER_LEVEL1 - 1 ) + cx ];
00328     if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 * ( KSPREAD_CLUSTER_LEVEL2 - 1 ) + dx ] )
00329     return FALSE;
00330 
00331     bool a = autoDelete();
00332     setAutoDelete( FALSE );
00333 
00334     // Move cells in this column one right.
00335     for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cy ; --i )
00336     {
00337     KSpreadCell** cl = m_cluster[ i * KSPREAD_CLUSTER_LEVEL1 + cx ];
00338     if ( cl )
00339         {
00340         work = TRUE;
00341 
00342         int top = 0;
00343         if ( i == cy )
00344         top = dy;
00345         int bottom = KSPREAD_CLUSTER_LEVEL2 - 1;
00346         if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 )
00347         bottom = KSPREAD_CLUSTER_LEVEL2 - 2;
00348         for( int k = bottom; k >= top; --k )
00349         {
00350         KSpreadCell* c = cl[ k * KSPREAD_CLUSTER_LEVEL2 + dx ];
00351         if ( c )
00352             {
00353             remove( c->column(), c->row() );
00354             c->move( c->column(), c->row() + 1 );
00355             insert( c, c->column(), c->row() );
00356         }
00357         }
00358     }
00359     }
00360 
00361     setAutoDelete( a );
00362 
00363     return TRUE;
00364 }
00365 
00366 bool KSpreadCluster::insertColumn( int col )
00367 {
00368     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
00369     {
00370     kdDebug(36001) << "KSpreadCluster::insertColumn: invalid column value (col: "
00371                << col << ")" << endl;
00372     return FALSE;
00373     }
00374 
00375     // Is there a cell at the right most position ?
00376     // In this case the shift is impossible.
00377     for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 )
00378     {
00379     KSpreadCell** cl = m_cluster[ t1 * KSPREAD_CLUSTER_LEVEL1 + KSPREAD_CLUSTER_LEVEL1 - 1 ];
00380     if ( cl )
00381         for( int t2 = 0; t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 )
00382         if ( cl[ t2 * KSPREAD_CLUSTER_LEVEL2 + KSPREAD_CLUSTER_LEVEL2 - 1 ] )
00383             return FALSE;
00384     }
00385 
00386     for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 )
00387     {
00388     bool work = TRUE;
00389     for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 )
00390         shiftRow( QPoint( col, t1 * KSPREAD_CLUSTER_LEVEL2 + t2 ), work );
00391     }
00392 
00393     return TRUE;
00394 }
00395 
00396 bool KSpreadCluster::insertRow( int row )
00397 {
00398     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
00399     {
00400     kdDebug(36001) << "KSpreadCluster::insertRow: invalid row value (row: "
00401                << row << ")" << endl;
00402     return FALSE;
00403     }
00404 
00405     // Is there a cell at the bottom most position ?
00406     // In this case the shift is impossible.
00407     for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 )
00408     {
00409     KSpreadCell** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 * ( KSPREAD_CLUSTER_LEVEL1 - 1 ) + t1 ];
00410     if ( cl )
00411         for( int t2 = 0; t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 )
00412         if ( cl[ KSPREAD_CLUSTER_LEVEL2 * ( KSPREAD_CLUSTER_LEVEL2 - 1 ) + t2 ] )
00413             return FALSE;
00414     }
00415 
00416     for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 )
00417     {
00418     bool work = TRUE;
00419     for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 )
00420         shiftColumn( QPoint( t1 * KSPREAD_CLUSTER_LEVEL2 + t2, row ), work );
00421     }
00422 
00423     return TRUE;
00424 }
00425 
00426 void KSpreadCluster::unshiftColumn( const QPoint& marker, bool& work )
00427 {
00428     work = FALSE;
00429 
00430     if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 ||
00431      marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 )
00432     {
00433     kdDebug(36001) << "KSpreadCluster::unshiftColumn: invalid column or row value (col: "
00434                << marker.x() << "  | row: " << marker.y() << ")" << endl;
00435     return;
00436     }
00437 
00438     int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2;
00439     int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2;
00440     int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2;
00441     int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2;
00442 
00443     bool a = autoDelete();
00444     setAutoDelete( FALSE );
00445 
00446     // Move cells in this column one column to the left.
00447     for( int i = cy; i < KSPREAD_CLUSTER_LEVEL1; ++i )
00448     {
00449     KSpreadCell** cl = m_cluster[ i * KSPREAD_CLUSTER_LEVEL1 + cx ];
00450     if ( cl )
00451         {
00452         work = TRUE;
00453 
00454         int top = 0;
00455         if ( i == cy )
00456         top = dy + 1;
00457         int bottom = KSPREAD_CLUSTER_LEVEL2 - 1;
00458         for( int k = top; k <= bottom; ++k )
00459         {
00460         KSpreadCell* c = cl[ k * KSPREAD_CLUSTER_LEVEL2 + dx ];
00461         if ( c )
00462             {
00463             remove( c->column(), c->row() );
00464             c->move( c->column(), c->row() - 1 );
00465             insert( c, c->column(), c->row() );
00466         }
00467         }
00468     }
00469     }
00470 
00471     setAutoDelete( a );
00472 }
00473 
00474 void KSpreadCluster::unshiftRow( const QPoint& marker, bool& work )
00475 {
00476     work = FALSE;
00477 
00478     if ( marker.x() >= KSPREAD_CLUSTER_MAX || marker.x() < 0 ||
00479      marker.y() >= KSPREAD_CLUSTER_MAX || marker.y() < 0 )
00480     {
00481     kdDebug(36001) << "KSpreadCluster::unshiftRow: invalid column or row value (col: "
00482                << marker.x() << "  | row: " << marker.y() << ")" << endl;
00483     return;
00484     }
00485 
00486     int cx = marker.x() / KSPREAD_CLUSTER_LEVEL2;
00487     int cy = marker.y() / KSPREAD_CLUSTER_LEVEL2;
00488     int dx = marker.x() % KSPREAD_CLUSTER_LEVEL2;
00489     int dy = marker.y() % KSPREAD_CLUSTER_LEVEL2;
00490 
00491     bool a = autoDelete();
00492     setAutoDelete( FALSE );
00493 
00494     // Move cells in this row one row up.
00495     for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i )
00496     {
00497     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + i ];
00498     if ( cl )
00499         {
00500         work = TRUE;
00501 
00502         int left = 0;
00503         if ( i == cx )
00504         left = dx + 1;
00505         int right = KSPREAD_CLUSTER_LEVEL2 - 1;
00506         for( int k = left; k <= right; ++k )
00507         {
00508         KSpreadCell* c = cl[ dy * KSPREAD_CLUSTER_LEVEL2 + k ];
00509         if ( c )
00510             {
00511             remove( c->column(), c->row() );
00512             c->move( c->column() - 1, c->row() );
00513             insert( c, c->column(), c->row() );
00514         }
00515         }
00516     }
00517     }
00518 
00519     setAutoDelete( a );
00520 }
00521 
00522 void KSpreadCluster::removeColumn( int col )
00523 {
00524     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
00525     {
00526     kdDebug(36001) << "KSpreadCluster::removeColumn: invalid column value (col: "
00527                << col << ")" << endl;
00528     return;
00529     }
00530 
00531     int cx = col / KSPREAD_CLUSTER_LEVEL2;
00532     int dx = col % KSPREAD_CLUSTER_LEVEL2;
00533 
00534     for( int y1 = 0; y1 < KSPREAD_CLUSTER_LEVEL1; ++y1 )
00535     {
00536     KSpreadCell** cl = m_cluster[ y1 * KSPREAD_CLUSTER_LEVEL1 + cx ];
00537     if ( cl )
00538         for( int y2 = 0; y2 < KSPREAD_CLUSTER_LEVEL2; ++y2 )
00539         if ( cl[ y2 * KSPREAD_CLUSTER_LEVEL2 + dx ] )
00540             remove( col, y1 * KSPREAD_CLUSTER_LEVEL1 + y2 );
00541     }
00542 
00543     for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 )
00544     {
00545     bool work = TRUE;
00546     for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 )
00547         unshiftRow( QPoint( col, t1 * KSPREAD_CLUSTER_LEVEL2 + t2 ), work );
00548     }
00549 }
00550 
00551 void KSpreadCluster::removeRow( int row )
00552 {
00553     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
00554     {
00555     kdDebug(36001) << "KSpreadCluster::removeRow: invalid row value (row: "
00556                << row << ")" << endl;
00557     return;
00558     }
00559 
00560     int cy = row / KSPREAD_CLUSTER_LEVEL2;
00561     int dy = row % KSPREAD_CLUSTER_LEVEL2;
00562 
00563     for( int x1 = 0; x1 < KSPREAD_CLUSTER_LEVEL1; ++x1 )
00564     {
00565     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + x1 ];
00566     if ( cl )
00567         for( int x2 = 0; x2 < KSPREAD_CLUSTER_LEVEL2; ++x2 )
00568         if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + x2 ] )
00569             remove( x1 * KSPREAD_CLUSTER_LEVEL2 + x2, row );
00570     }
00571 
00572     for( int t1 = 0; t1 < KSPREAD_CLUSTER_LEVEL1; ++t1 )
00573     {
00574     bool work = TRUE;
00575     for( int t2 = 0; work && t2 < KSPREAD_CLUSTER_LEVEL2; ++t2 )
00576         unshiftColumn( QPoint( t1 * KSPREAD_CLUSTER_LEVEL2 + t2, row ), work );
00577     }
00578 }
00579 
00580 void KSpreadCluster::clearColumn( int col )
00581 {
00582   if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
00583   {
00584     kdDebug(36001) << "KSpreadCluster::clearColumn: invalid column value (col: "
00585     << col << ")" << endl;
00586     return;
00587   }
00588 
00589   int cx = col / KSPREAD_CLUSTER_LEVEL2;
00590   int dx = col % KSPREAD_CLUSTER_LEVEL2;
00591 
00592   for( int cy = 0; cy < KSPREAD_CLUSTER_LEVEL1; ++cy )
00593   {
00594     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ];
00595     if ( cl )
00596       for( int dy = 0; dy < KSPREAD_CLUSTER_LEVEL2; ++dy )
00597         if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] )
00598         {
00599           int row = cy * KSPREAD_CLUSTER_LEVEL2 + dy ;
00600           remove( col, row );
00601         }
00602   }
00603 }
00604 
00605 void KSpreadCluster::clearRow( int row )
00606 {
00607   if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
00608   {
00609     kdDebug(36001) << "KSpreadCluster::clearRow: invalid row value (row: "
00610         << row << ")" << endl;
00611     return;
00612   }
00613 
00614   int cy = row / KSPREAD_CLUSTER_LEVEL2;
00615   int dy = row % KSPREAD_CLUSTER_LEVEL2;
00616 
00617   for( int cx = 0; cx < KSPREAD_CLUSTER_LEVEL1; ++cx )
00618   {
00619     KSpreadCell** cl = m_cluster[ cy * KSPREAD_CLUSTER_LEVEL2 + cx ];
00620     if ( cl )
00621       for( int dx = 0; dx < KSPREAD_CLUSTER_LEVEL2; ++dx )
00622         if ( cl[ dy * KSPREAD_CLUSTER_LEVEL2 + dx ] )
00623         {
00624           int column = cx * KSPREAD_CLUSTER_LEVEL2 + dx ;
00625           remove( column, row );
00626         }
00627   }
00628 }
00629 
00630 KSpreadValue KSpreadCluster::valueRange (int col1, int row1,
00631     int col2, int row2) const
00632 {
00633   KSpreadValue empty;
00634   
00635   //swap first/second values if needed
00636   if (col1 > col2)
00637   {
00638     int p = col1; col1 = col2; col2 = p;
00639   }
00640   if (row1 > row2)
00641   {
00642     int p = row1; row1 = col2; row2 = p;
00643   }
00644   if ((row1 < 0) || (col1 < 0) || (row2 > KSPREAD_CLUSTER_MAX) ||
00645       (col2 > KSPREAD_CLUSTER_MAX))
00646     return empty;
00647 
00648   //return nothing if we are out of range occupied by cells
00649   if ((row1 > m_biggestY) || (col1 > m_biggestX))
00650     return empty;
00651 
00652   //split the requested range into cluster-sized sections
00653   int x1, y1, x2, y2;
00654   x1 = col1 / KSPREAD_CLUSTER_LEVEL2;
00655   y1 = row1 / KSPREAD_CLUSTER_LEVEL2;
00656   x2 = col2 / KSPREAD_CLUSTER_LEVEL2;
00657   y2 = row2 / KSPREAD_CLUSTER_LEVEL2;
00658   
00659   if ((x1 == x2) && (y1 == y2))  //start/end in the same chunk
00660   {
00661     return makeArray (col1, row1, col2, row2);
00662   }
00663   
00664   KSpreadValue result (x2 - x1 + 1, y2 - y1 + 1);
00665   
00666   //fill up each section with cell values - if a cell contains a range,
00667   //we only take one its element - or else we'd have problems with
00668   //matrix functions and expansion of returned matrices to nearby cells
00669   for (int y = y1; y <= y2; ++y)
00670     for (int x = x1; x <= x2; ++x)
00671       //check whether the current element contains anything
00672       if (m_cluster[y * KSPREAD_CLUSTER_LEVEL1 + x])
00673       {
00674         //compute start/end indexes
00675         int xx1, xx2, yy1, yy2;
00676         xx1 = x * KSPREAD_CLUSTER_LEVEL2;
00677         xx2 = (x + 1) * KSPREAD_CLUSTER_LEVEL2 - 1;
00678         yy1 = y * KSPREAD_CLUSTER_LEVEL2;
00679         yy2 = (y + 1) * KSPREAD_CLUSTER_LEVEL2 - 1;
00680         if (xx1 < col1) xx1 = col1;
00681         if (yy1 < row1) yy1 = row1;
00682         if (xx2 > col2) xx2 = col2;
00683         if (yy2 > row2) yy2 = row2;
00684         
00685         //fill the array element
00686         result.setElement (x, y, makeArray (xx1, yy1, xx2, yy2));
00687       }
00688   //now return the result
00689   return result;
00690 }
00691 
00692 KSpreadValue KSpreadCluster::makeArray (int col1, int row1,
00693     int col2, int row2) const
00694 {
00695   //this generates a simple, one-dimensional array
00696   int cols = col2 - col1 + 1;
00697   int rows = row2 - row1 + 1;
00698   KSpreadValue array (cols, rows);
00699   for (int row = row1; row <= row2; ++row)
00700     for (int col = col1; col <= col2; ++col)
00701     {
00702       KSpreadCell *cell = lookup (col, row);
00703       if (cell)
00704       {
00705         KSpreadValue val = cell->value();
00706         while (val.isArray ())
00707           val = val.element (0, 0);
00708         array.setElement (col-col1, row-row1, val); 
00709       }
00710     }
00711   
00712   //return the result
00713   return array;
00714 }
00715 
00716 KSpreadCell* KSpreadCluster::getFirstCellColumn(int col) const
00717 {
00718   KSpreadCell* cell = lookup(col, 1);
00719 
00720   if (cell == NULL)
00721   {
00722     cell = getNextCellDown(col, 1);
00723   }
00724   return cell;
00725 }
00726 
00727 KSpreadCell* KSpreadCluster::getLastCellColumn(int col) const
00728 {
00729   KSpreadCell* cell = lookup(col, KS_rowMax);
00730 
00731   if (cell == NULL)
00732   {
00733     cell = getNextCellUp(col, KS_rowMax);
00734   }
00735   return cell;
00736 }
00737 
00738 KSpreadCell* KSpreadCluster::getFirstCellRow(int row) const
00739 {
00740   KSpreadCell* cell = lookup(1, row);
00741 
00742   if (cell == NULL)
00743   {
00744     cell = getNextCellRight(1, row);
00745   }
00746   return cell;
00747 }
00748 
00749 KSpreadCell* KSpreadCluster::getLastCellRow(int row) const
00750 {
00751   KSpreadCell* cell = lookup(KS_colMax, row);
00752 
00753   if (cell == NULL)
00754   {
00755     cell = getNextCellLeft(KS_colMax, row);
00756   }
00757   return cell;
00758 }
00759 
00760 KSpreadCell* KSpreadCluster::getNextCellUp(int col, int row) const
00761 {
00762   int cx = col / KSPREAD_CLUSTER_LEVEL2;
00763   int cy = (row - 1) / KSPREAD_CLUSTER_LEVEL2;
00764   int dx = col % KSPREAD_CLUSTER_LEVEL2;
00765   int dy = (row - 1) % KSPREAD_CLUSTER_LEVEL2;
00766 
00767   while (cy >= 0)
00768   {
00769     if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL )
00770     {
00771       while (dy >= 0)
00772       {
00773 
00774         if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx]
00775              [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL )
00776         {
00777           return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ]
00778             [ dy*KSPREAD_CLUSTER_LEVEL2 + dx];
00779         }
00780         dy--;
00781       }
00782     }
00783     cy--;
00784     dy = KSPREAD_CLUSTER_LEVEL2 - 1;
00785   }
00786   return NULL;
00787 }
00788 
00789 KSpreadCell* KSpreadCluster::getNextCellDown(int col, int row) const
00790 {
00791   int cx = col / KSPREAD_CLUSTER_LEVEL2;
00792   int cy = (row + 1) / KSPREAD_CLUSTER_LEVEL2;
00793   int dx = col % KSPREAD_CLUSTER_LEVEL2;
00794   int dy = (row + 1) % KSPREAD_CLUSTER_LEVEL2;
00795 
00796   while (cy < KSPREAD_CLUSTER_LEVEL1)
00797   {
00798     if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL )
00799     {
00800       while (dy < KSPREAD_CLUSTER_LEVEL2)
00801       {
00802 
00803         if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx]
00804              [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL )
00805         {
00806           return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ]
00807             [ dy*KSPREAD_CLUSTER_LEVEL2 + dx];
00808         }
00809         dy++;
00810       }
00811     }
00812     cy++;
00813     dy = 0;
00814   }
00815   return NULL;
00816 }
00817 
00818 KSpreadCell* KSpreadCluster::getNextCellLeft(int col, int row) const
00819 {
00820   int cx = (col - 1) / KSPREAD_CLUSTER_LEVEL2;
00821   int cy = row / KSPREAD_CLUSTER_LEVEL2;
00822   int dx = (col - 1) % KSPREAD_CLUSTER_LEVEL2;
00823   int dy = row % KSPREAD_CLUSTER_LEVEL2;
00824 
00825   while (cx >= 0)
00826   {
00827     if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL )
00828     {
00829       while (dx >= 0)
00830       {
00831 
00832         if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx]
00833              [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL )
00834         {
00835           return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ]
00836             [ dy*KSPREAD_CLUSTER_LEVEL2 + dx];
00837         }
00838         dx--;
00839       }
00840     }
00841     cx--;
00842     dx = KSPREAD_CLUSTER_LEVEL2 - 1;
00843   }
00844   return NULL;
00845 }
00846 
00847 KSpreadCell* KSpreadCluster::getNextCellRight(int col, int row) const
00848 {
00849   int cx = (col + 1) / KSPREAD_CLUSTER_LEVEL2;
00850   int cy = row / KSPREAD_CLUSTER_LEVEL2;
00851   int dx = (col + 1) % KSPREAD_CLUSTER_LEVEL2;
00852   int dy = row % KSPREAD_CLUSTER_LEVEL2;
00853 
00854   while (cx < KSPREAD_CLUSTER_LEVEL1)
00855   {
00856     if ( m_cluster[ cy * KSPREAD_CLUSTER_LEVEL1 + cx ] != NULL )
00857     {
00858       while (dx < KSPREAD_CLUSTER_LEVEL2)
00859       {
00860 
00861         if ( m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx]
00862              [ dy*KSPREAD_CLUSTER_LEVEL2 + dx] != NULL )
00863         {
00864           return m_cluster[ cy*KSPREAD_CLUSTER_LEVEL1 + cx ]
00865             [ dy*KSPREAD_CLUSTER_LEVEL2 + dx];
00866         }
00867         dx++;
00868       }
00869     }
00870     cx++;
00871     dx = 0;
00872   }
00873   return NULL;
00874 }
00875 
00876 /****************************************************
00877  *
00878  * KSpreadColumnCluster
00879  *
00880  ****************************************************/
00881 
00882 KSpreadColumnCluster::KSpreadColumnCluster()
00883     : m_first( 0 ), m_autoDelete( FALSE )
00884 {
00885     m_cluster = (ColumnFormat***)malloc( KSPREAD_CLUSTER_LEVEL1 * sizeof( ColumnFormat** ) );
00886 
00887     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
00888     m_cluster[ x ] = 0;
00889 }
00890 
00891 KSpreadColumnCluster::~KSpreadColumnCluster()
00892 {
00893     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
00894     {
00895     ColumnFormat** cl = m_cluster[ x ];
00896     if ( cl )
00897         {
00898         free( cl );
00899         m_cluster[ x ] = 0;
00900     }
00901     }
00902 
00903     if ( m_autoDelete )
00904     {
00905     ColumnFormat* cell = m_first;
00906     while( cell )
00907         {
00908         ColumnFormat* n = cell->next();
00909         delete cell;
00910         cell = n;
00911     }
00912     }
00913 
00914 
00915     free( m_cluster );
00916 }
00917 
00918 ColumnFormat* KSpreadColumnCluster::lookup( int col )
00919 {
00920     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
00921     {
00922     kdDebug(36001) << "KSpreadColumnCluster::lookup: invalid column value (col: "
00923                << col << ")" << endl;
00924     return 0;
00925     }
00926 
00927     int cx = col / KSPREAD_CLUSTER_LEVEL2;
00928     int dx = col % KSPREAD_CLUSTER_LEVEL2;
00929 
00930     ColumnFormat** cl = m_cluster[ cx ];
00931     if ( !cl )
00932     return 0;
00933 
00934     return cl[ dx ];
00935 }
00936 
00937 const ColumnFormat* KSpreadColumnCluster::lookup( int col ) const
00938 {
00939     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
00940     {
00941     kdDebug(36001) << "KSpreadColumnCluster::lookup: invalid column value (col: "
00942                << col << ")" << endl;
00943     return 0;
00944     }
00945 
00946     int cx = col / KSPREAD_CLUSTER_LEVEL2;
00947     int dx = col % KSPREAD_CLUSTER_LEVEL2;
00948 
00949     ColumnFormat** cl = m_cluster[ cx ];
00950     if ( !cl )
00951     return 0;
00952 
00953     return cl[ dx ];
00954 }
00955 
00956 void KSpreadColumnCluster::clear()
00957 {
00958     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
00959     {
00960     ColumnFormat** cl = m_cluster[ x ];
00961     if ( cl )
00962         {
00963         free( cl );
00964         m_cluster[ x ] = 0;
00965     }
00966     }
00967 
00968     if ( m_autoDelete )
00969     {
00970     ColumnFormat* cell = m_first;
00971     while( cell )
00972         {
00973         ColumnFormat* n = cell->next();
00974         delete cell;
00975         cell = n;
00976     }
00977     }
00978 
00979     m_first = 0;
00980 }
00981 
00982 void KSpreadColumnCluster::insertElement( ColumnFormat* lay, int col )
00983 {
00984     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
00985     {
00986     kdDebug(36001) << "KSpreadColumnCluster::insertElement: invalid column value (col: "
00987                << col << ")" << endl;
00988     return;
00989     }
00990 
00991     int cx = col / KSPREAD_CLUSTER_LEVEL2;
00992     int dx = col % KSPREAD_CLUSTER_LEVEL2;
00993 
00994     ColumnFormat** cl = m_cluster[ cx ];
00995     if ( !cl )
00996     {
00997     cl = (ColumnFormat**)malloc( KSPREAD_CLUSTER_LEVEL2 * sizeof( ColumnFormat*  ) );
00998     m_cluster[ cx ] = cl;
00999 
01000     for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a )
01001         cl[ a ] = 0;
01002     }
01003 
01004     if ( cl[ dx ] )
01005     removeElement( col );
01006 
01007     cl[ dx ] = lay;
01008 
01009     if ( m_first )
01010     {
01011     lay->setNext( m_first );
01012     m_first->setPrevious( lay );
01013     }
01014     m_first = lay;
01015 }
01016 
01017 void KSpreadColumnCluster::removeElement( int col )
01018 {
01019     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
01020     {
01021     kdDebug(36001) << "KSpreadColumnCluster::removeElement: invalid column value (col: "
01022                << col << ")" << endl;
01023     return;
01024     }
01025 
01026     int cx = col / KSPREAD_CLUSTER_LEVEL2;
01027     int dx = col % KSPREAD_CLUSTER_LEVEL2;
01028 
01029     ColumnFormat** cl = m_cluster[ cx ];
01030     if ( !cl )
01031     return;
01032 
01033     ColumnFormat* c = cl[ dx ];
01034     if ( !c )
01035     return;
01036 
01037     cl[ dx ] = 0;
01038 
01039     if ( m_autoDelete )
01040     {
01041     if ( m_first == c )
01042         m_first = c->next();
01043     delete c;
01044     }
01045     else
01046     {
01047     if ( m_first == c )
01048         m_first = c->next();
01049     if ( c->previous() )
01050         c->previous()->setNext( c->next() );
01051     if ( c->next() )
01052         c->next()->setPrevious( c->previous() );
01053     c->setNext( 0 );
01054     c->setPrevious( 0 );
01055     }
01056 }
01057 
01058 bool KSpreadColumnCluster::insertColumn( int col )
01059 {
01060     if ( col >= KSPREAD_CLUSTER_MAX || col < 0 )
01061     {
01062     kdDebug(36001) << "KSpreadColumnCluster::insertColumn: invalid column value (col: "
01063                << col << ")" << endl;
01064     return FALSE;
01065     }
01066 
01067     int cx = col / KSPREAD_CLUSTER_LEVEL2;
01068     int dx = col % KSPREAD_CLUSTER_LEVEL2;
01069 
01070     // Is there a column layout at the right most position ?
01071     // In this case the shift is impossible.
01072     ColumnFormat** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 - 1 ];
01073     if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 - 1 ] )
01074     return FALSE;
01075 
01076     bool a = autoDelete();
01077     setAutoDelete( FALSE );
01078 
01079     for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i )
01080     {
01081     ColumnFormat** cl = m_cluster[ i ];
01082     if ( cl )
01083         {
01084         int left = 0;
01085         if ( i == cx )
01086         left = dx;
01087         int right = KSPREAD_CLUSTER_LEVEL2 - 1;
01088         if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 )
01089         right = KSPREAD_CLUSTER_LEVEL2 - 2;
01090         for( int k = right; k >= left; --k )
01091         {
01092         ColumnFormat* c = cl[ k ];
01093         if ( c )
01094             {
01095             removeElement( c->column() );
01096             c->setColumn( c->column() + 1 );
01097             insertElement( c, c->column() );
01098         }
01099         }
01100     }
01101     }
01102 
01103     setAutoDelete( a );
01104 
01105     return TRUE;
01106 }
01107 
01108 bool KSpreadColumnCluster::removeColumn( int column )
01109 {
01110     if ( column >= KSPREAD_CLUSTER_MAX || column < 0 )
01111     {
01112     kdDebug(36001) << "KSpreadColumnCluster::removeColumn: invalid column value (col: "
01113                << column << ")" << endl;
01114     return FALSE;
01115     }
01116 
01117     int cx = column / KSPREAD_CLUSTER_LEVEL2;
01118     int dx = column % KSPREAD_CLUSTER_LEVEL2;
01119 
01120     removeElement( column );
01121 
01122     bool a = autoDelete();
01123     setAutoDelete( FALSE );
01124 
01125     for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i )
01126     {
01127     ColumnFormat** cl = m_cluster[ i ];
01128     if ( cl )
01129         {
01130         int left = 0;
01131         if ( i == cx )
01132         left = dx + 1;
01133         int right = KSPREAD_CLUSTER_LEVEL2 - 1;
01134         for( int k = left; k <= right; ++k )
01135         {
01136         ColumnFormat* c = cl[ k ];
01137         if ( c )
01138             {
01139             removeElement( c->column() );
01140             c->setColumn( c->column() - 1 );
01141             insertElement( c, c->column() );
01142         }
01143         }
01144     }
01145     }
01146 
01147     setAutoDelete( a );
01148 
01149     return TRUE;
01150 }
01151 
01152 void KSpreadColumnCluster::setAutoDelete( bool a )
01153 {
01154     m_autoDelete = a;
01155 }
01156 
01157 bool KSpreadColumnCluster::autoDelete() const
01158 {
01159     return m_autoDelete;
01160 }
01161 
01162 /****************************************************
01163  *
01164  * KSpreadRowCluster
01165  *
01166  ****************************************************/
01167 
01168 KSpreadRowCluster::KSpreadRowCluster()
01169     : m_first( 0 ), m_autoDelete( FALSE )
01170 {
01171     m_cluster = (RowFormat***)malloc( KSPREAD_CLUSTER_LEVEL1 * sizeof( RowFormat** ) );
01172 
01173     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
01174         m_cluster[ x ] = 0;
01175 }
01176 
01177 KSpreadRowCluster::~KSpreadRowCluster()
01178 {
01179     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
01180     {
01181     RowFormat** cl = m_cluster[ x ];
01182     if ( cl )
01183         {
01184         free( cl );
01185         m_cluster[ x ] = 0;
01186     }
01187     }
01188 
01189     if ( m_autoDelete )
01190     {
01191     RowFormat* cell = m_first;
01192     while( cell )
01193         {
01194         RowFormat* n = cell->next();
01195         delete cell;
01196         cell = n;
01197     }
01198     }
01199 
01200     free( m_cluster );
01201 }
01202 
01203 const RowFormat* KSpreadRowCluster::lookup( int row ) const
01204 {
01205     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
01206     {
01207     kdDebug(36001) << "KSpreadRowCluster::lookup: invalid row value (row: "
01208                << row << ")" << endl;
01209     return 0;
01210     }
01211 
01212     int cx = row / KSPREAD_CLUSTER_LEVEL2;
01213     int dx = row % KSPREAD_CLUSTER_LEVEL2;
01214 
01215     RowFormat** cl = m_cluster[ cx ];
01216     if ( !cl )
01217     return 0;
01218 
01219     return cl[ dx ];
01220 }
01221 
01222 RowFormat* KSpreadRowCluster::lookup( int row )
01223 {
01224     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
01225     {
01226     kdDebug(36001) << "KSpreadRowCluster::lookup: invalid row value (row: "
01227                << row << ")" << endl;
01228     return 0;
01229     }
01230 
01231     int cx = row / KSPREAD_CLUSTER_LEVEL2;
01232     int dx = row % KSPREAD_CLUSTER_LEVEL2;
01233 
01234     RowFormat** cl = m_cluster[ cx ];
01235     if ( !cl )
01236     return 0;
01237 
01238     return cl[ dx ];
01239 }
01240 
01241 void KSpreadRowCluster::clear()
01242 {
01243     for( int x = 0; x < KSPREAD_CLUSTER_LEVEL1; ++x )
01244     {
01245     RowFormat** cl = m_cluster[ x ];
01246     if ( cl )
01247         {
01248         free( cl );
01249         m_cluster[ x ] = 0;
01250     }
01251     }
01252 
01253     if ( m_autoDelete )
01254     {
01255     RowFormat* cell = m_first;
01256     while( cell )
01257         {
01258         RowFormat* n = cell->next();
01259         delete cell;
01260         cell = n;
01261     }
01262     }
01263 
01264     m_first = 0;
01265 }
01266 
01267 void KSpreadRowCluster::insertElement( RowFormat* lay, int row )
01268 {
01269     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
01270     {
01271     kdDebug(36001) << "KSpreadRowCluster::insertElement: invalid row value (row: "
01272                << row << ")" << endl;
01273     return;
01274     }
01275 
01276     int cx = row / KSPREAD_CLUSTER_LEVEL2;
01277     int dx = row % KSPREAD_CLUSTER_LEVEL2;
01278 
01279     RowFormat** cl = m_cluster[ cx ];
01280     if ( !cl )
01281     {
01282     cl = (RowFormat**)malloc( KSPREAD_CLUSTER_LEVEL2 * sizeof( RowFormat*  ) );
01283     m_cluster[ cx ] = cl;
01284 
01285     for( int a = 0; a < KSPREAD_CLUSTER_LEVEL2; ++a )
01286         cl[ a ] = 0;
01287     }
01288 
01289     if ( cl[ dx ] )
01290     removeElement( row );
01291 
01292     cl[ dx ] = lay;
01293 
01294     if ( m_first )
01295     {
01296     lay->setNext( m_first );
01297     m_first->setPrevious( lay );
01298     }
01299     m_first = lay;
01300 }
01301 
01302 void KSpreadRowCluster::removeElement( int row )
01303 {
01304     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
01305     {
01306     kdDebug(36001) << "KSpreadRowCluster::removeElement: invalid row value (row: "
01307                << row << ")" << endl;
01308     return;
01309     }
01310 
01311     int cx = row / KSPREAD_CLUSTER_LEVEL2;
01312     int dx = row % KSPREAD_CLUSTER_LEVEL2;
01313 
01314     RowFormat** cl = m_cluster[ cx ];
01315     if ( !cl )
01316     return;
01317 
01318     RowFormat* c = cl[ dx ];
01319     if ( !c )
01320     return;
01321 
01322     cl[ dx ] = 0;
01323 
01324     if ( m_autoDelete )
01325     {
01326     if ( m_first == c )
01327         m_first = c->next();
01328     delete c;
01329     }
01330     else
01331     {
01332     if ( m_first == c )
01333         m_first = c->next();
01334     if ( c->previous() )
01335         c->previous()->setNext( c->next() );
01336     if ( c->next() )
01337         c->next()->setPrevious( c->previous() );
01338     c->setNext( 0 );
01339     c->setPrevious( 0 );
01340     }
01341 }
01342 
01343 bool KSpreadRowCluster::insertRow( int row )
01344 {
01345     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
01346     {
01347     kdDebug(36001) << "KSpreadRowCluster::insertRow: invalid row value (row: "
01348                << row << ")" << endl;
01349     return FALSE;
01350     }
01351 
01352     int cx = row / KSPREAD_CLUSTER_LEVEL2;
01353     int dx = row % KSPREAD_CLUSTER_LEVEL2;
01354 
01355     // Is there a row layout at the bottom most position ?
01356     // In this case the shift is impossible.
01357     RowFormat** cl = m_cluster[ KSPREAD_CLUSTER_LEVEL1 - 1 ];
01358     if ( cl && cl[ KSPREAD_CLUSTER_LEVEL2 - 1 ] )
01359     return FALSE;
01360 
01361     bool a = autoDelete();
01362     setAutoDelete( FALSE );
01363 
01364     for( int i = KSPREAD_CLUSTER_LEVEL1 - 1; i >= cx ; --i )
01365     {
01366     RowFormat** cl = m_cluster[ i ];
01367     if ( cl )
01368         {
01369         int left = 0;
01370         if ( i == cx )
01371         left = dx;
01372         int right = KSPREAD_CLUSTER_LEVEL2 - 1;
01373         if ( i == KSPREAD_CLUSTER_LEVEL1 - 1 )
01374         right = KSPREAD_CLUSTER_LEVEL2 - 2;
01375         for( int k = right; k >= left; --k )
01376         {
01377         RowFormat* c = cl[ k ];
01378         if ( c )
01379             {
01380             removeElement( c->row() );
01381             c->setRow( c->row() + 1 );
01382             insertElement( c, c->row() );
01383         }
01384         }
01385     }
01386     }
01387 
01388     setAutoDelete( a );
01389 
01390     return TRUE;
01391 }
01392 
01393 bool KSpreadRowCluster::removeRow( int row )
01394 {
01395     if ( row >= KSPREAD_CLUSTER_MAX || row < 0 )
01396     {
01397     kdDebug(36001) << "KSpreadRowCluster::removeRow: invalid row value (row: "
01398                << row << ")" << endl;
01399     return FALSE;
01400     }
01401 
01402     int cx = row / KSPREAD_CLUSTER_LEVEL2;
01403     int dx = row % KSPREAD_CLUSTER_LEVEL2;
01404 
01405     removeElement( row );
01406 
01407     bool a = autoDelete();
01408     setAutoDelete( FALSE );
01409 
01410     for( int i = cx; i < KSPREAD_CLUSTER_LEVEL1; ++i )
01411     {
01412     RowFormat** cl = m_cluster[ i ];
01413     if ( cl )
01414         {
01415         int left = 0;
01416         if ( i == cx )
01417         left = dx + 1;
01418         int right = KSPREAD_CLUSTER_LEVEL2 - 1;
01419         for( int k = left; k <= right; ++k )
01420         {
01421         RowFormat* c = cl[ k ];
01422         if ( c )
01423             {
01424             removeElement( c->row() );
01425             c->setRow( c->row() - 1 );
01426             insertElement( c, c->row() );
01427         }
01428         }
01429     }
01430     }
01431 
01432     setAutoDelete( a );
01433 
01434     return TRUE;
01435 }
01436 
01437 void KSpreadRowCluster::setAutoDelete( bool a )
01438 {
01439     m_autoDelete = a;
01440 }
01441 
01442 bool KSpreadRowCluster::autoDelete() const
01443 {
01444     return m_autoDelete;
01445 }
KDE Logo
This file is part of the documentation for kspread Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:42:53 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003