kword

KWTableFrameSet.cpp

00001 /*
00002     Copyright (C) 2001, S.R.Haque (srhaque@iee.org).
00003     This file is part of the KDE project
00004     Copyright (C) 2005 Thomas Zander <zander@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 
00021 DESCRIPTION
00022 
00023     This file implements KWord tables.
00024 */
00025 
00026 // ### TODO : multi page tables
00027 
00028 #include "KWTableFrameSet.h"
00029 #include "KWDocument.h"
00030 #include "KWAnchor.h"
00031 #include "KWCanvas.h"
00032 #include "KWCommand.h"
00033 #include "KWViewMode.h"
00034 #include "KWView.h"
00035 #include "KWordFrameSetIface.h"
00036 #include "KWordTableFrameSetIface.h"
00037 #include "KWFrameList.h"
00038 #include "KWPageManager.h"
00039 #include "KWPage.h"
00040 #include "KWOasisSaver.h"
00041 
00042 #include <KoOasisContext.h>
00043 #include <KoXmlWriter.h>
00044 #include <KoDom.h>
00045 #include <KoXmlNS.h>
00046 #include <KoTextObject.h> // for customItemChar !
00047 #include <KoTextParag.h>
00048 
00049 #include <kmessagebox.h>
00050 #include <kdebug.h>
00051 #include <klocale.h>
00052 #include <dcopobject.h>
00053 #include <qapplication.h>
00054 #include <qpopupmenu.h>
00055 #include <qclipboard.h>
00056 
00057 
00058 KWTableFrameSet::KWTableFrameSet( KWDocument *doc, const QString & name ) :
00059     KWFrameSet( doc )
00060 {
00061     m_rows = m_cols = m_nr_cells = 0;
00062     m_name = QString::null;
00063     m_active = true;
00064     m_frames.setAutoDelete(false);
00065     if ( name.isEmpty() )
00066         m_name = doc->generateFramesetName( i18n( "Table %1" ) );
00067     else
00068         m_name = name;
00069 }
00070 
00071 KWTableFrameSet::~KWTableFrameSet()
00072 {
00073     m_doc = 0L;
00074 }
00075 
00076 KWordFrameSetIface* KWTableFrameSet::dcopObject()
00077 {
00078     if ( !m_dcop )
00079     m_dcop = new KWordTableFrameSetIface( this );
00080 
00081     return m_dcop;
00082 }
00083 
00084 
00085 KWFrameSetEdit * KWTableFrameSet::createFrameSetEdit( KWCanvas * canvas )
00086 {
00087     return new KWTableFrameSetEdit( this, canvas );
00088 }
00089 
00090 void KWTableFrameSet::updateFrames( int flags )
00091 {
00092     for(TableIter c(this); c; ++c)
00093         c.current()->updateFrames( flags );
00094     if ( isFloating() )  {
00095         KWAnchor * anchor = findAnchor( 0 );
00096         if ( anchor )
00097              anchor->resize();
00098     }
00099 
00100     KWFrameSet::updateFrames( flags );
00101 }
00102 
00103 void KWTableFrameSet::moveFloatingFrame( int /*frameNum TODO */, const KoPoint &position )
00104 {
00105     // TODO multi-page case
00106 
00107     double dx = position.x() - m_colPositions[0];
00108     double dy = position.y() - m_rowPositions[0];
00109 
00110     KWTableFrameSet::Cell *daCell = cell(0,0);
00111     Q_ASSERT(daCell);
00112     if (! daCell) return; //hack to work around https://bugs.kde.org/show_bug.cgi?id=67216
00113     int oldPageNumber = daCell->frame(0)->pageNumber();
00114     // TODO multi-page case
00115 
00116     moveBy( dx, dy );
00117 
00118     if ( dx || dy ) {
00119         updateFrames();
00120         cell(0,0)->frame(0)->frameStack()->updateAfterMove( oldPageNumber );
00121     }
00122 }
00123 
00124 KoSize KWTableFrameSet::floatingFrameSize( int /*frameNum*/ )
00125 {
00126     return boundingRect().size();
00127 }
00128 
00129 KCommand * KWTableFrameSet::anchoredObjectCreateCommand( int /*frameNum*/ )
00130 {
00131     return new KWCreateTableCommand( i18n("Create Table"), this );
00132 }
00133 
00134 KCommand * KWTableFrameSet::anchoredObjectDeleteCommand( int /*frameNum*/ )
00135 {
00136     return new KWDeleteTableCommand( i18n("Delete Table"), this );
00137 }
00138 
00139 KWAnchor * KWTableFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
00140 {
00141     //kdDebug(32004) << "KWTableFrameSet::createAnchor" << endl;
00142     return new KWAnchor( txt, this, frameNum );
00143 }
00144 
00145 void KWTableFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
00146                                      bool repaint )
00147 {
00148     //kdDebug(32004) << "KWTableFrameSet::createAnchors" << endl;
00149     // TODO make one rect per page, and create one anchor per page
00150     // Anchor this frame, after the previous one
00151     KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), 0 );
00152     if ( !placeHolderExists )
00153         parag->insert( index, KoTextObject::customItemChar() );
00154     parag->setCustomItem( index, anchor, 0 );
00155     kdDebug(32004) << "KWTableFrameSet::createAnchors setting anchor" << endl;
00156     parag->setChanged( true );
00157     if ( repaint )
00158         emit repaintChanged( m_anchorTextFs );
00159 }
00160 
00161 void KWTableFrameSet::deleteAnchors()
00162 {
00163     KWAnchor * anchor = findAnchor( 0 );
00164     kdDebug(32004) << "KWTableFrameSet::deleteAnchors anchor=" << anchor << endl;
00165     deleteAnchor( anchor );
00166 }
00167 
00168 
00169 void KWTableFrameSet::addCell( Cell* daCell ) // called add but also used to 'update'
00170 {
00171     m_rows = kMax( daCell->rowAfter(), m_rows );
00172     m_cols = kMax( daCell->columnAfter(), m_cols );
00173 
00174     if ( m_rowArray.size() < daCell->rowAfter() )
00175         m_rowArray.resize( daCell->rowAfter() );
00176     for ( uint row = daCell->firstRow() ;row < daCell->rowAfter(); ++row )
00177     {
00178         if ( !m_rowArray[ row ] )
00179             m_rowArray.insert( row, new Row );
00180         m_rowArray[ row ]->addCell( daCell );
00181     }
00182 }
00183 
00184 void KWTableFrameSet::removeCell( Cell* daCell )
00185 {
00186     for ( uint row = daCell->firstRow() ; row < daCell->rowAfter(); ++row )
00187         m_rowArray[ row ]->removeCell( daCell );
00188 }
00189 
00190 void KWTableFrameSet::insertRowVector(uint index, Row *r)
00191 {
00192     if(m_rowArray.size() < m_rowArray.count() + 1)
00193         m_rowArray.resize(m_rowArray.count() + 1);
00194 
00195     for(uint i = m_rowArray.count(); i > index; i--)
00196         m_rowArray.insert(i, m_rowArray[i-1]);
00197 
00198     m_rowArray.insert(index, r);
00199 }
00200 
00201 /*
00202  * Inserts a new (empty) element into each row vector.
00203  * Elements in a row vector after index are moved back.
00204  */
00205 void KWTableFrameSet::insertEmptyColumn(uint index)
00206 {
00207     for(uint i = 0; i < m_rowArray.count(); ++i) {
00208        Row *r = m_rowArray[i];
00209        if(r->m_cellArray.size() < m_cols + 1)
00210            r->m_cellArray.resize(m_cols + 1);
00211        for(int j = m_cols - 1; j >= (int)index; --j)
00212            r->m_cellArray.insert(j + 1, r->m_cellArray[j]);
00213        r->m_cellArray.insert(index,  0);
00214     }
00215 }
00216 
00217 KWTableFrameSet::Row*
00218 KWTableFrameSet::removeRowVector(uint index)
00219 {
00220     Q_ASSERT(index < m_rowArray.count() );
00221     Row *ret = m_rowArray.at(index);
00222     Row *r;
00223     for(uint i = index; i < m_rowArray.size() - 1; ++i){
00224         r = m_rowArray.at(i+1);
00225         m_rowArray.remove(i+1);
00226         m_rowArray.insert(i,r);
00227     }
00228     return ret;
00229 }
00230 
00231 
00232 KoRect KWTableFrameSet::boundingRect() {
00233     KoRect outerRect(m_colPositions[0],    // left
00234                      m_rowPositions[0],      // top
00235                      m_colPositions.last()-m_colPositions[0], // width
00236                      m_rowPositions.last()-m_rowPositions[0]);// height
00237 
00238     // Add 1 'pixel' (at current zoom level) like KWFrame::outerKoRect(),
00239     // to avoid that the bottom line disappears due to rounding problems
00240     // (i.e. that it doesn't fit in the calculated paragraph height in pixels,
00241     // which depends on the paragraph's Y position)
00242     // Better have one pixel too much (caret looks too big by one pixel)
00243     // than one missing (bottom line of cell not painted)
00244     outerRect.rRight() += m_doc->zoomItX( 1 ) / m_doc->zoomedResolutionX();
00245     outerRect.rBottom() += m_doc->zoomItY( 1 ) / m_doc->zoomedResolutionY();
00246 
00247     return outerRect;
00248 
00249 }
00250 
00251 double KWTableFrameSet::topWithoutBorder()
00252 {
00253     double top = 0.0;
00254     for (uint i = 0; i < getColumns(); i++)
00255     {
00256         KWTableFrameSet::Cell *daCell = cell( 0, i );
00257         top = kMax( top, m_rowPositions[0] + daCell->topBorder() );
00258     }
00259     return top;
00260 }
00261 
00262 
00263 double KWTableFrameSet::leftWithoutBorder()
00264 {
00265     double left = 0.0;
00266     for (uint i=0; i < getRows(); i++)
00267     {
00268         KWTableFrameSet::Cell *daCell = cell( i, 0 );
00269         left = kMax( left, m_colPositions[0] + daCell->leftBorder() );
00270     }
00271     return left;
00272 }
00273 
00274 /* returns the cell that occupies row, col. */
00275 KWTableFrameSet::Cell *KWTableFrameSet::cell( unsigned int row, unsigned int col ) const
00276 {
00277     if ( row < m_rowArray.size() && col < m_rowArray[row]->size() ) {
00278         Cell* cell = (*m_rowArray[row])[col];
00279         if ( cell )
00280             return cell;
00281     }
00282 //    kdWarning() << name() << " cell " << row << "," << col << " => returning 0!" << kdBacktrace( 3 ) << endl;
00283 //#ifndef NDEBUG
00284 //    validate();
00285 //    printArrayDebug();
00286 //#endif
00287     return 0L;
00288 }
00289 
00290 KWTableFrameSet::Cell *KWTableFrameSet::cellByPos( double x, double y ) const
00291 {
00292     KWFrame *f = frameAtPos(x,y);
00293     if(f) return static_cast<KWTableFrameSet::Cell *> (f->frameSet());
00294     return 0L;
00295 }
00296 
00297 void KWTableFrameSet::recalcCols(unsigned int col,unsigned int row) {
00298     if(col >= getColumns())
00299         col = getColumns()-1;
00300     if(row >= getRows())
00301         row = getRows()-1;
00302     Cell *activeCell = cell(row,col);
00303     Q_ASSERT( activeCell );
00304     if ( !activeCell )
00305         return;
00306     double difference = 0;
00307 
00308     if(activeCell->frame(0)->left() - activeCell->leftBorder() != m_colPositions[activeCell->firstColumn()]) {
00309         // left border moved.
00310         col = activeCell->firstRow();
00311         difference = 0-(activeCell->frame(0)->left() - activeCell->leftBorder() - m_colPositions[activeCell->firstColumn()]);
00312     }
00313 
00314     if(activeCell->frame(0)->right() - activeCell->rightBorder() !=
00315             m_colPositions[activeCell->lastColumn()]) { // right border moved
00316 
00317         col = activeCell->columnAfter();
00318         double difference2 = activeCell->frame(0)->right() + activeCell->rightBorder() - m_colPositions[activeCell->columnAfter()];
00319 
00320         double moved=difference2+difference;
00321         if(moved > -0.01 && moved < 0.01) { // we were simply moved.
00322                 col=0;
00323                 difference = difference2;
00324             } else if(difference2!=0)
00325                 difference = difference2;
00326     }
00327 
00328     m_redrawFromCol=getColumns(); // possible reposition col starting with this one, done in recalcRows
00329     if(difference!=0) {
00330         double last=col==0?0:m_colPositions[col-1];
00331         for(unsigned int i=col; i < m_colPositions.count(); i++) {
00332             double &colPos = m_colPositions[i];
00333             colPos = colPos + difference;
00334             if(colPos-last < s_minFrameWidth) { // Never make it smaller then allowed!
00335                 difference += s_minFrameWidth - colPos;
00336                 colPos = s_minFrameWidth + last;
00337             }
00338             last=colPos;
00339         }
00340         m_redrawFromCol=col;
00341         if(col>0) m_redrawFromCol--;
00342         //if(activeCell) activeCell->frame(0)->setMinimumFrameHeight(0);
00343     }
00344     updateFrames();
00345     //kdDebug(32004) << "end KWTableFrameSet::recalcCols" << endl;
00346 }
00347 
00348 
00349 // Step through the whole table and recalculate the position and size
00350 // of each cell.
00351 
00352 void KWTableFrameSet::recalcRows(unsigned int col, unsigned int row) {
00353     kdDebug(32004) << name() << " KWTableFrameSet::recalcRows ("<< col <<"," << row << ")" << endl;
00354     //for(unsigned int i=0; i < m_rowPositions.count() ; i++) kdDebug(32004) << "row: " << i << " = " << m_rowPositions[i] << endl;
00355 
00356     Cell *activeCell = cell(row,col);
00357     Q_ASSERT( activeCell );
00358     if ( !activeCell ) // #122807
00359         return;
00360     double difference = 0;
00361 
00362     if(activeCell->frame(0)->height() != activeCell->frame(0)->minimumFrameHeight() &&
00363           activeCell->type() == FT_TEXT) {
00364         // when the amount of text changed and the frame has to be rescaled we are also called.
00365         // lets check the minimum size for all the cells in this row.
00366 
00367         // Take a square of table cells which depend on each others height. It is always the full
00368         // width of the table and the height is determined by joined cells, the minimum is one row.
00369         double minHeightOtherCols=0;    // The minimum height which the whole square of table cells can take
00370         double minHeightActiveRow=0;    // The minimum height our cell can get because of cells in his row
00371         double minHeightMyCol=0;        // The minimum height our column can get in the whole square
00372         unsigned int rowSpan = activeCell->rowSpan();
00373         unsigned int startRow = activeCell->firstRow();
00374         for (uint colCount = 0; colCount < getColumns(); ++colCount )
00375         {
00376             // for each column
00377             unsigned int rowCount=startRow;
00378             double thisColHeight=0;     // the total height of this column
00379             double thisColActiveRow=0;  // the total height of all cells in this col, completely in the
00380                                         // row of the activeCell
00381             do { // for each row (under startRow)
00382                 Cell *thisCell=cell(rowCount,colCount);
00383                 if ( !thisCell )
00384                     break; // ###
00385                 if(thisCell->firstRow() < startRow) { // above -> set startRow and restart
00386                     rowSpan += startRow - thisCell->firstRow();
00387                     startRow = thisCell->firstRow();
00388                     break;
00389                 }
00390                 if(thisCell->rowAfter() > startRow + rowSpan) {
00391                     rowSpan = thisCell->rowAfter() - startRow;
00392                     break;
00393                 }
00394 
00395                 thisColHeight+=thisCell->frame(0)->minimumFrameHeight();
00396                 thisColHeight+=thisCell->topBorder();
00397                 thisColHeight+=thisCell->bottomBorder();
00398 
00399                 if(thisCell->firstRow() >= activeCell->firstRow() && thisCell->rowAfter() <= activeCell->rowAfter())
00400                     thisColActiveRow+=thisCell->frame(0)->minimumFrameHeight();
00401 
00402                 rowCount += thisCell->rowSpan();
00403             } while (rowCount < rowSpan+startRow);
00404 
00405             if(colCount >= activeCell->firstColumn() &&
00406                   colCount < activeCell->columnAfter() )
00407                 minHeightMyCol = thisColHeight;
00408             else {
00409                 minHeightOtherCols = kMax(minHeightOtherCols, thisColHeight);
00410                 minHeightActiveRow = kMax(minHeightActiveRow, thisColActiveRow);
00411             }
00412         } // for each column
00413 
00414         bool bottomRow = (startRow+rowSpan == activeCell->rowAfter());
00415         if(!bottomRow) {
00416             Cell *bottomCell=cell(startRow+rowSpan-1, activeCell->firstColumn());
00417             bottomCell->frame(0)->setHeight(bottomCell->frame(0)->minimumFrameHeight() +
00418                     minHeightOtherCols - minHeightMyCol);
00419             // ### RECURSE ###
00420             recalcRows(bottomCell->firstColumn(), bottomCell->firstRow());
00421         }
00422         if(activeCell->frame(0)->minimumFrameHeight() > activeCell->frame(0)->height()) { // wants to grow
00423             activeCell->frame(0)->setHeight(activeCell->frame(0)->minimumFrameHeight());
00424             //kdDebug(32004) << activeCell->name() << " grew to its minheight: " << activeCell->frame(0)->minimumFrameHeight() << endl;
00425         } else { // wants to shrink
00426             double newHeight=kMax(activeCell->frame(0)->minimumFrameHeight(),minHeightActiveRow);
00427             if(bottomRow) // I'm a strech cell
00428                 newHeight=kMax(newHeight, minHeightOtherCols - (minHeightMyCol - activeCell->frame(0)->minimumFrameHeight()));
00429             activeCell->frame(0)->setHeight(newHeight);
00430             //kdDebug(32004) << activeCell->name() << " shrunk to: " << newHeight << endl;
00431         }
00432     }
00433 
00434     if(activeCell->frame(0)->top() - activeCell->topBorder() != getPositionOfRow(activeCell->firstRow())) {
00435         // top moved.
00436         row = activeCell->firstRow();
00437         difference = 0 - (activeCell->frame(0)->top() - activeCell->topBorder() - getPositionOfRow(row));
00438     }
00439 
00440 
00441     if(activeCell->frame(0)->bottom() + activeCell->bottomBorder() !=
00442             getPositionOfRow(activeCell->rowAfter())) { // bottom moved
00443 
00444         row = activeCell->rowAfter();
00445         double difference2 = activeCell->frame(0)->bottom() + activeCell->bottomBorder() - getPositionOfRow(row);
00446         double moved=difference2+difference;
00447         if(moved > -0.01 && moved < 0.01) { // we were simply moved.
00448             row=0;
00449             difference = difference2;
00450         } else if( difference2!=0)
00451             difference = difference2;
00452     }
00453 
00454     unsigned int fromRow = m_rows; // possible reposition rows starting with this one, default to no repositioning
00455     unsigned int untilRow=0;     // possible reposition rows ending with this one
00456     if( QABS( difference ) > 1E-10 ) { // means "difference != 0.0"
00457         QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
00458         QValueList<double>::iterator j = m_rowPositions.begin();
00459         double last=0.0;
00460         int lineNumber=-1;
00461         while(j != m_rowPositions.end()) {
00462             lineNumber++;
00463             if(pageBound!=m_pageBoundaries.end()) {
00464                 if((int)*pageBound == lineNumber) { // next page
00465                     if(lineNumber >= (int)row) { // then delete line j
00466                         QValueList<double>::iterator nextJ = j;
00467                         ++nextJ;
00468                         difference -= *(nextJ)-*(j);
00469                         kdDebug(32004) << "Deleting line with old pos: " << *j << endl;
00470                         j=m_rowPositions.remove(j);
00471                         j--;
00472                         QValueList<unsigned int>::iterator tmp = pageBound;
00473                         ++pageBound;
00474                         m_pageBoundaries.remove(tmp);
00475                         j++;
00476                         continue;
00477                     }
00478                     ++pageBound;
00479                     lineNumber--;
00480                 }
00481             }
00482             if(lineNumber >= (int)row)  { // below changed row
00483                 if(*(j)-last < s_minFrameHeight) // Never make it smaller then allowed!
00484                     difference += s_minFrameHeight - *(j) + last;
00485                 last=*(j);
00486                 kdDebug(32004) << "moving " << *(j) << " by " << difference << "; to " << (*j) + difference << endl;
00487                 (*j) += difference; // move line.
00488             }
00489             j++;
00490         }
00491         fromRow=row;
00492         if(row>0) fromRow--;
00493     } else {
00494         row=0;
00495     }
00496 #if 0
00497 { QValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
00498   unsigned int i=0;
00499   double last=0;
00500   do {
00501       double cur=m_rowPositions[i];
00502       if(pb!=m_pageBoundaries.end() && *(pb)==i) {
00503         kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
00504         ++pb;
00505       } else
00506         kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
00507       last=cur;
00508       i++;
00509   } while( i<m_rowPositions.count());
00510 }
00511 #endif
00512 #if 0 // def SUPPORT_MULTI_PAGE_TABLES
00513 
00514     //double pageHeight = m_doc->ptPaperHeight() - m_doc->ptBottomBorder() - m_doc->ptTopBorder();
00515     unsigned int pageNumber=cell(0,0)->frame(0)->pageNumber() +1;
00516     unsigned int lineNumber=1;
00517     QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
00518     QValueList<double>::iterator j = m_rowPositions.begin();
00519 
00520     double diff=0.0;
00521     double pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
00522     // kdDebug(32004) << "pageBottom; " << pageBottom << endl;
00523     while(++j!=m_rowPositions.end()) { // stuff for multipage tables.
00524         if(pageBound!=m_pageBoundaries.end() && *pageBound == lineNumber ) {
00525             if(*j > pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder() ) { // next page marker exists, and is accurate...
00526                 pageNumber++;
00527                 pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
00528                 // kdDebug(32004) << "pageBottom; " << pageBottom << endl;
00529                 untilRow=kMax(untilRow, *pageBound);
00530                 pageBound++;
00531             }
00532         }
00533 
00534 //kdDebug() << "checking; " << lineNumber << ", " << (*j) << endl;
00535         if((*j) + diff > pageBottom) { // a row falls off the page.
00536 //kdDebug(32004) << "row falls off of page"<< endl;
00537             untilRow = m_rows;
00538             bool hugeRow = false;
00539             unsigned int breakRow = lineNumber-1;
00540             // find out of no cells are spanning multiple rows meaning we have to break higher.
00541 #if 0
00542     // ### TODO: I did not get a chance do debug this yet!  TZ.
00543             for(int i=0; i < getColumns() ; i++) {
00544                 kdDebug() << "i: " << i<< endl;
00545                 Cell *c= cell(breakRow, i);
00546                 kdDebug() << "c: " << c->firstRow() << "," << c->m_col << " w: " << c->columnSpan() << ", h: " << c->rowSpan() << endl;
00547                 if(c->firstRow() < breakRow) {
00548                     breakRow = c->firstRow();
00549                     i=-1;
00550                 }
00551             }
00552             kdDebug() << "breakRow: " << breakRow<< endl;
00553             fromRow=kMin(fromRow, breakRow);
00554             if(breakRow < lineNumber+1) {
00555                 for(unsigned int i=lineNumber+1; i > breakRow;i--)
00556                     kdDebug() << "j--";
00557                 for(unsigned int i=lineNumber+1; i > breakRow;i--)
00558                     --j;
00559                 lineNumber=breakRow+1;
00560             }
00561 
00562             // find out if the next row (the new one on the page) does not contain cells higher then page.
00563             for(unsigned int i=0; i < getColumns() ; i++) {
00564                 if(cell(breakRow+1,i) && cell(breakRow+1,i)->frame(0)->height() > pageHeight)
00565                     hugeRow=true;
00566             }
00567             //if((*pageBound) != breakRow) { // I think that this has to be that way
00568                 // voeg top in in rowPositions
00569 #endif
00570 
00571             double topOfPage = m_doc->ptPaperHeight() * pageNumber + m_doc->ptTopBorder();
00572 
00573             QValueList<double>::iterator tmp = m_rowPositions.at(breakRow);
00574             diff += topOfPage - (*tmp); // diff between bottom of last row on page and top of new page
00575 //kdDebug() << "diff += " <<  topOfPage  << " - " << (*tmp) << ". diff += " << topOfPage - (*tmp) <<" ="<< diff  << endl;
00576             lineNumber++;
00577             m_rowPositions.insert(j, topOfPage);
00578 
00579             // insert new pageBound. It points to last LINE on previous page
00580             pageBound = m_pageBoundaries.insert(pageBound, breakRow);
00581             //kdDebug(32004) << "inserting new pageBound: " << breakRow  << " at " << m_rowPositions[breakRow] << endl;
00582             pageBound++;
00583             if(!hugeRow) {
00584                 // add header-rij toe. (en zet bool) TODO
00585                 //j++;
00586                 //lineNumber++;
00587                 // m_hasTmpHeaders = true;
00588             }
00589             pageNumber++;
00590             pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
00591             //kdDebug(32004) << " pageBottom: " << pageBottom << " pageNumber=" << pageNumber << endl;
00592             if((int)pageNumber > m_doc->numPages()) {
00593                 int num = m_doc->appendPage();
00594                 kdDebug(32004) << "Have appended page: " << num << " (one page mode!)" << endl;
00595                 m_doc->afterInsertPage( num );
00596             }
00597         }
00598         //if(diff > 0)  kdDebug(32004) << "   adding " << diff << ", line " << lineNumber << " " << *(j) <<" -> " << *(j)+diff << endl;
00599         if(diff > 0)
00600             (*j) = (*j) + diff;
00601         lineNumber++;
00602 
00603 #if 0 // def SUPPORT_MULTI_PAGE_TABLES
00604         // Note: produces much ouput!
00605         int i = 1; // DEBUG
00606         for ( QValueList<double>::iterator itDebug = m_rowPositions.begin(); itDebug != m_rowPositions.end(); ++itDebug, ++i )
00607         {
00608             kdDebug(32004) << "m_rowPosition[" << i << "]= " << (*itDebug) << endl;
00609         }
00610 #endif
00611 
00612     }
00613 #endif
00614 #if 0
00615 { QValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
00616   unsigned int i=0;
00617   double last=0;
00618   do {
00619       double cur=m_rowPositions[i];
00620       if(pb!=m_pageBoundaries.end() && *(pb)==i) {
00621         kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
00622         ++pb;
00623       } else
00624         kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
00625       last=cur;
00626       i++;
00627   } while( i<m_rowPositions.count());
00628 }
00629 #endif
00630 //for (unsigned int i=0; i < getRows(); kdDebug(32004)<<" pos of row["<<i<<"] = "<<getPositionOfRow(i)<<"/"<<getPositionOfRow(i,true)<<endl,i++);
00631     //kdDebug () << "Repositioning from row : " << fromRow << " until: " << untilRow << endl;
00632     //kdDebug () << "Repositioning from col > " << redrawFromCol << endl;
00633     // do positioning.
00634     //Cell *cell;
00635     //bool setMinFrameSize= activeCell->frame(0)->isSelected();
00636 
00637 #if 0 // def SUPPORT_MULTI_PAGE_TABLES
00638     for(TableIter cell(this); cell; ++cell) {
00639         if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->columnAfter() > m_redrawFromCol)
00640             position(cell, (cell==activeCell && cell->frame(0)->isSelected()));
00641     }
00642     m_redrawFromCol = getColumns();
00643 
00644     // check if any rowPosition entries are unused
00645 
00646     //   first create a hash of all row entries
00647     QMap<unsigned int,int> rows;        // rownr, count
00648     unsigned int top=m_rowPositions.count() - m_pageBoundaries.count()-1;
00649     for(unsigned int i=0; i < top; rows[i++]=0);
00650 
00651     //   fill hash with data
00652     for(TableIter i(this); i; ++i) {
00653         rows[i->firstRow()] += 1;
00654     }
00655     //   check if some entries have stayed unused.
00656     unsigned int counter=top;
00657     int adjustment=m_pageBoundaries.count()-1;
00658 
00659     do {
00660         counter--;
00661         if(adjustment >= 0 && counter == m_pageBoundaries[adjustment])
00662             adjustment--;
00663         if(rows[counter]==0) {
00664             kdDebug() << k_funcinfo << "no rows at counter=" << counter << " -> erasing" << endl;
00665             m_rows--;
00666             m_rowPositions.erase(m_rowPositions.at(counter+(adjustment>0?adjustment:0)));
00667             for (TableIter cell(this); cell; ++cell) {
00668                 if(cell->firstRow() < counter && cell->rowAfter() > counter)
00669                     cell->setRowSpan(cell->rowSpan()-1);
00670                 if(cell->firstRow() > counter)
00671                     cell->setFirstRow(cell->firstRow()-1);
00672             }
00673 
00674             if(adjustment >= -1) {
00675                 pageBound = m_pageBoundaries.at(adjustment+1);
00676                 while(pageBound!=m_pageBoundaries.end()) {
00677                     (*pageBound)= (*pageBound)-1;
00678                     pageBound++;
00679                 }
00680             }
00681         }
00682     } while(counter!=0);
00683 #endif
00684 
00685 
00686     m_redrawFromCol = 0;
00687     for (TableIter cell(this); cell; ++cell) {
00688         if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow)
00689            || cell->columnAfter() > m_redrawFromCol)
00690             position(cell);
00691     }
00692     m_redrawFromCol = getColumns();
00693     kdDebug(32004) << name() << " KWTableFrameSet::recalcRows done" << endl;
00694     updateFrames();
00695 }
00696 
00697 int KWTableFrameSet::columnEdgeAt( double x ) const
00698 {
00699     // We compare x with the middle of columns (left+right/2),
00700     // to find which column x is closest to.
00701     // m_colPositions is sorted, so we can remember the last column we looked at.
00702     double lastMiddlePos = 0;
00703     for ( uint i = 0; i < m_colPositions.count() - 1; i++ ) {
00704         double middlePos = ( m_colPositions[i] + m_colPositions[i+1] ) / 2;
00705         Q_ASSERT( lastMiddlePos < middlePos );
00706         if ( x > lastMiddlePos && x <= middlePos )
00707             return i;
00708         lastMiddlePos = middlePos;
00709     }
00710     return m_colPositions.count() - 1;
00711 }
00712 
00713 int KWTableFrameSet::rowEdgeAt( double y ) const
00714 {
00715     double lastMiddlePos = 0;
00716     for ( uint i = 0; i < m_rowPositions.count() - 1; i++ ) {
00717         double middlePos = ( m_rowPositions[i] + m_rowPositions[i+1] ) / 2;
00718         Q_ASSERT( lastMiddlePos < middlePos );
00719         if ( y > lastMiddlePos && y <= middlePos )
00720             return i;
00721         lastMiddlePos = middlePos;
00722     }
00723     return m_rowPositions.count() - 1;
00724 }
00725 
00726 double KWTableFrameSet::columnSize( unsigned int col )
00727 {
00728   return m_colPositions[ col ];
00729 }
00730 
00731 double KWTableFrameSet::rowSize( unsigned int row )
00732 {
00733   return m_rowPositions[ row ];
00734 }
00735 
00736 void KWTableFrameSet::resizeColumn( unsigned int col, double x )
00737 {
00738     kdDebug() << k_funcinfo << col << "," << x << endl;
00739     if ((col != 0) && (x - m_colPositions[ col-1 ] < s_minFrameWidth))
00740       m_colPositions[ col ] = m_colPositions[ col-1 ] + s_minFrameWidth;
00741     else
00742       if ((col != getColumns()) && (m_colPositions[ col + 1 ] - x < s_minFrameWidth))
00743         m_colPositions[col] = m_colPositions[ col + 1 ] - s_minFrameWidth;
00744       else
00745         m_colPositions[ col ] = x;
00746 
00747     // move all cells right of 'col'
00748     for (TableIter cell(this); cell; ++cell) {
00749         if ( cell->columnAfter() >= col ) {
00750             position(cell);
00751         }
00752     }
00753     recalcCols( col-1, 0 );
00754 }
00755 
00756 void KWTableFrameSet::resizeRow( unsigned int row, double y )
00757 {
00758     kdDebug() << k_funcinfo << row << "," << y << endl;
00759     double difference = m_rowPositions[row];
00760     if ((row != 0) && (y - m_rowPositions[ row-1 ] < s_minFrameHeight))
00761       m_rowPositions[ row ] = m_rowPositions[ row-1 ] + s_minFrameHeight;
00762     else
00763       if ((row != getRows()) && (m_rowPositions[ row + 1 ] - y < s_minFrameHeight))
00764         m_rowPositions[row] = m_rowPositions[ row + 1 ] - s_minFrameHeight;
00765       else
00766         m_rowPositions[ row ] = y;
00767     difference = m_rowPositions[row] - difference;
00768 
00769     //move all rows under 'row'
00770     if (row != 0)
00771        for (unsigned int i=row+1; i<= getRows(); i++)
00772            m_rowPositions[i] = m_rowPositions[i] + difference;
00773 
00774     // move all cells under 'row'
00775     for (TableIter cell(this); cell; ++cell) {
00776         if ( cell->rowAfter() >= row ) {
00777             position(cell);
00778         }
00779     }
00780     recalcRows( 0, row-1 );
00781 }
00782 
00783 void KWTableFrameSet::resizeWidth( double width ) {
00784     Q_ASSERT(width != 0);
00785     Q_ASSERT(boundingRect().width() != 0);
00786     kdDebug() << "bounding width before resize " << boundingRect().width() << endl;
00787     double growth = width / boundingRect().width();
00788 
00789     // since we move all the columns, we also move the 1st one,
00790     // depending where it is on the page.
00791     // just compensate by substracting that offset.
00792     double moveOffset = m_colPositions[0] * growth - m_colPositions[0];
00793 
00794     for (uint i=0; i<m_colPositions.count(); i++) {
00795         m_colPositions[i] = m_colPositions[i] * growth - moveOffset;
00796     }
00797     finalize();
00798     kdDebug() << "bounding width after resize" << boundingRect().width() << endl;
00799     Q_ASSERT(boundingRect().width() - width < 0.01);
00800 }
00801 
00802 void KWTableFrameSet::setBoundingRect( KoRect rect, CellSize widthMode, CellSize heightMode ) {
00803    // Column positions..
00804     m_colPositions.clear();
00805     unsigned int cols=0;
00806     for (TableIter c(this); c; ++c)
00807         cols = kMax(cols, c.current()->columnAfter());
00808     double colWidth = rect.width() / cols;
00809     if ( widthMode == TblAuto ) {
00810         KWPage *page = pageManager()->page(rect);
00811         rect.setLeft( page->leftMargin() );
00812         colWidth = (page->width() - page->leftMargin() - page->rightMargin()) / cols;
00813     }
00814 
00815     for(unsigned int i=0; i <= cols;i++) {
00816         m_colPositions.append(rect.x() + colWidth * i);
00817     }
00818 
00819     // Row positions..
00820     m_rowPositions.clear();
00821     m_pageBoundaries.clear();
00822     double rowHeight = 0;
00823     if( heightMode != TblAuto )
00824         rowHeight = rect.height() / m_rows;
00825     rowHeight=kMax(rowHeight, 22.0); // m_doc->getDefaultParagLayout()->getFormat().ptFontSize()) // TODO use table style font-size
00826 
00827     for(unsigned int i=0; i <= m_rows;i++) {
00828         m_rowPositions.append(rect.y() + rowHeight * i);
00829     }
00830 
00831     double oneMm = MM_TO_POINT( 1.0 );
00832     for (TableIter cell(this); cell; ++cell) {
00833         KWFrame *frame = cell->frame(0);
00834         frame->setPaddingLeft( oneMm );
00835         frame->setPaddingRight( oneMm );
00836         frame->setPaddingTop( oneMm );
00837         frame->setPaddingBottom( oneMm );
00838         frame->setNewFrameBehavior( KWFrame::NoFollowup );
00839         position(cell, true);
00840     }
00841 }
00842 
00843 void KWTableFrameSet::position( Cell *theCell, bool setMinFrameHeight ) {
00844     if(!theCell->frame(0)) { // sanity check.
00845         kdDebug(32004) << "errorous table cell!! row:" << theCell->firstRow()
00846             << ", col: " << theCell->firstColumn() << endl;
00847         return;
00848     }
00849     double x = *m_colPositions.at(theCell->firstColumn());
00850     double y = getPositionOfRow(theCell->firstRow());
00851     double width = (*m_colPositions.at(theCell->columnAfter())) - x;
00852     double height  = getPositionOfRow(theCell->lastRow(), true) - y;
00853 
00854 #if 0
00855     if(theCell->m_col==0) {
00856         kdDebug(32004) << "row "  << theCell->firstRow() << " has top: "
00857             << y << ", and bottom: " << y + height << endl;
00858     }
00859 #endif
00860 
00861     // Now take the border sizes and make the cell smaller so it still fits inside the grid.
00862     KWFrame *theFrame = theCell->frame(0);
00863     x+=theCell->leftBorder();
00864     width-=theCell->leftBorder();
00865     width-=theCell->rightBorder();
00866     y+=theCell->topBorder();
00867     height-=theCell->topBorder();
00868     height-=theCell->bottomBorder();
00869 
00870     theFrame->setRect( x,y,width,height);
00871     if( setMinFrameHeight )
00872         theFrame->setMinimumFrameHeight(height);
00873 
00874     if(!theCell->isVisible())
00875         theCell->setVisible(true);
00876 }
00877 
00878 double KWTableFrameSet::getPositionOfRow( unsigned int row, bool bottom ) {
00879     unsigned int adjustment=0;
00880     QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
00881     while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
00882         adjustment++;
00883         pageBound++;
00884     }
00885     if(m_rowPositions.count() < row+adjustment+(bottom?1:0))  // Requested row does not exist.
00886         return 0;
00887     return m_rowPositions[row+adjustment+(bottom?1:0)];
00888 }
00889 
00890 void KWTableFrameSet::moveBy( double dx, double dy ) {
00891     bool redraw=false;
00892     kdDebug(32004) << "KWTableFrameSet(" << name() << ")::moveBy(" << dx<<","<<dy<<")\n";
00893     //for(unsigned int i=0; i < m_rowPositions.count() ; kdDebug(32004) << "row " << i << ": " << m_rowPositions[i++] << endl);
00894     if(!(dy > -0.001 && dy < 0.001)) {
00895         redraw=true;
00896         QValueList<double>::iterator row = m_rowPositions.begin();
00897         while(row != m_rowPositions.end()) {
00898             (*row)= (*row)+dy;
00899             row++;
00900         }
00901     }
00902     if(!(dx > -0.001 && dx < 0.001)) {
00903         redraw=true;
00904         QValueList<double>::iterator col = m_colPositions.begin();
00905         while(col != m_colPositions.end()) {
00906             (*col)= (*col)+dx;
00907             col++;
00908         }
00909     }
00910 
00911     if(redraw) {
00912         for(TableIter cell(this);cell;++cell)
00913             position(cell);
00914     }
00915 }
00916 
00917 /* Delete all cells that are completely in this row.              */
00918 void KWTableFrameSet::deleteRow( unsigned int row, RemovedRow &rr, bool _recalc)
00919 {
00920     Q_ASSERT(row < m_rowArray.size());
00921     const unsigned int rowspan=1;
00922 
00923     double height= getPositionOfRow(row+rowspan-1,true) - getPositionOfRow(row);
00924     QValueList<double>::iterator tmp = m_rowPositions.at(row+rowspan);
00925     tmp=m_rowPositions.erase(tmp);
00926     while(tmp!=m_rowPositions.end()) {
00927         (*tmp)= (*tmp)-height;
00928         tmp++;
00929     }
00930 
00931     rr.m_index = row;
00932     rr.m_rowHeight = height;
00933     rr.m_row = m_rowArray[row];
00934 
00935     // move/delete cells.
00936     for ( TableIter cell(this); cell; ++cell ) {
00937         if ( row >= cell->firstRow() && row < cell->rowAfter()) { // cell is indeed in row
00938             if(cell->rowSpan() == 1) { // cell is wholly contained within row
00939                 m_frames.remove( cell->frame(0) );
00940             } else { // make cell span rowspan less rows
00941                 cell->setRowSpan(cell->rowSpan()-rowspan);
00942                 position(cell);
00943             }
00944 
00945         } else if ( cell->firstRow() > row ) {
00946             // move cell up
00947             cell->setFirstRow( cell->firstRow() - rowspan );
00948             position(cell);
00949         }
00950     }
00951 
00952     removeRowVector(row);
00953     m_rows -= rowspan;
00954     m_rowArray.resize( m_rows );
00955     validate();
00956 
00957     if ( _recalc )
00958         recalcRows( 0, row-1 );
00959 }
00960 
00961 void KWTableFrameSet::reInsertRow(RemovedRow &rr)
00962 {
00963    uint row = rr.index();
00964    Row *r =  rr.row();
00965    uint rlen = r->count();
00966 
00967    // adjust cell positions & sizes
00968    for(MarkedIterator cell(this); cell; ++cell) {
00969 
00970         if ( cell->firstRow() < row && cell->lastRow() >= row ){ // cell is indeed in row
00971                 cell->setRowSpan(cell->rowSpan() + 1);
00972         }
00973         else if(r->m_cellArray[cell->firstColumn()] == cell.current()) {
00974                 cell->setRowSpan(cell->rowSpan() + 1);
00975         }
00976         else if ( cell->firstRow() >= row ) {
00977             // move cell down
00978             cell->setFirstRow( cell->firstRow() + 1);
00979         }
00980    }
00981 
00982    // put back m_frames that were removed
00983    for(uint i = 0; i < rlen; i++){
00984        if( m_frames.findRef((*r)[i]->frame(0)) == -1 )
00985         m_frames.append( (*r)[i]->frame(0) );
00986    }
00987 
00988    // adjust row positions (ignores page boundaries!)a
00989    if(row == m_rows) {  //reinserting at bottom of table
00990        double d = m_rowPositions.last() + rr.height();
00991        m_rowPositions.append(d);
00992    }
00993    else {
00994        QValueList<double>::iterator top = m_rowPositions.at(row);
00995        QValueList<double>::iterator i = m_rowPositions.at(row+1);
00996        i = m_rowPositions.insert(i, *top + rr.height());
00997        i++;
00998        for(; i != m_rowPositions.end(); ++i) {
00999            *i = *i+ rr.height();
01000        }
01001    }
01002 
01003    // reinsert row into array
01004    m_rows++;
01005    insertRowVector(rr.index(), rr.takeRow());
01006 
01007    // don't actually have to visit all the cells, this could be optimised
01008    for(TableIter i(this); i ; ++i)
01009       position(i.current());
01010 
01011    validate();
01012 }
01013 
01014 void KWTableFrameSet::insertNewRow( uint idx, bool recalc, bool _removeable)
01015 {
01016 
01017     (void) _removeable; // unused parameter
01018     unsigned int copyFromRow = idx==0?0:idx-1;
01019     if(idx==0)
01020         copyFromRow=1;
01021     Row *copyRow = m_rowArray[copyFromRow];
01022 
01023     uint new_rows = m_rows + 1;
01024     // What height to use for the new row
01025     double height = getPositionOfRow(copyFromRow,true) - getPositionOfRow(copyFromRow);
01026 
01027     // Calculate offset in QValueList because of page breaks.
01028     unsigned int adjustment=0;
01029     unsigned int untilRow=m_rows;
01030     QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
01031     while(pageBound != m_pageBoundaries.end() && (*pageBound) <= idx) {
01032         // Find out how many pages we already had.
01033         adjustment++;
01034         pageBound++;
01035     }
01036 
01037     // Move all rows down from newRow to bottom of page
01038     QValueList<double>::iterator tmp = m_rowPositions.at(idx);
01039     double newPos = *tmp + height;
01040     tmp++;
01041     m_rowPositions.insert(tmp, newPos);
01042     for(unsigned int i=idx+adjustment+2; i < m_rowPositions.count(); i++) {
01043         double &rowPos = m_rowPositions[i];
01044         kdDebug(32004) << "adjusting " << rowPos << " -> " << rowPos + height << endl;
01045         rowPos = rowPos + height;
01046         if(*pageBound == i) {
01047             untilRow= *pageBound;
01048             break;              // stop at pageBreak.
01049         }
01050     }
01051 
01052     for ( MarkedIterator cells(this); cells; ++cells) {
01053         if ( cells->firstRow() >= idx ) { // move all cells beneath the new row.
01054             cells->setFirstRow(cells->firstRow()+1);
01055         }
01056     }
01057 
01058     insertRowVector(idx, new Row);
01059 
01060     unsigned int i = 0;
01061     while(i < getColumns()) {
01062 
01063         if(idx != 0 && (idx != m_rows)) {
01064             Cell *c = cell(idx - 1, i);
01065             if( c == cell(idx + 1, i) ) {
01066                 m_rowArray[idx]->addCell(c);
01067                 c->setRowSpan(c->rowSpan() + 1);
01068                 i += c->columnSpan();
01069                 continue; // don't need to make a new cell
01070             }
01071         }
01072 
01073         KWFrame *theFrame = new KWFrame(copyRow->m_cellArray[i]->frame(0));
01074         Cell *newCell=new Cell( this, idx, i, QString::null );
01075         newCell->setColumnSpan( cell(copyFromRow,i)->columnSpan() );
01076         addCell(newCell);
01077         newCell->addFrame( theFrame, false );
01078         position(newCell);
01079         i += newCell->columnSpan();
01080    }
01081 
01082     // Position all changed cells.
01083 
01084     m_rows = new_rows;
01085     validate();
01086     if ( recalc )
01087         finalize();
01088 }
01089 
01090 void KWTableFrameSet::deleteColumn(uint col, RemovedColumn &rc)
01091 {
01092     // keep these values in case we have to put it back
01093     if(!rc.m_initialized) {
01094         rc.m_index = col;
01095         rc.m_width = m_colPositions[col+1] - m_colPositions[col];
01096     }
01097 
01098     // move the colomn positions
01099     QValueList<double>::iterator tmp = m_colPositions.at(col+1);
01100     tmp = m_colPositions.erase(tmp);
01101     while(tmp != m_colPositions.end()) {
01102         (*tmp) = (*tmp) - rc.m_width;
01103         tmp++;
01104     }
01105 
01106     // remove cells that are wholy in this column,
01107     // otherwise reduce rowspan. pointers to all cells
01108     // are kept in the RemovedColumn
01109     CheckedIter iter(this);
01110     for(uint i = 0; i < m_rows; ++i) {
01111         Cell *daCell = cell(i, col);
01112 
01113         if(!rc.m_initialized) {
01114             rc.m_column.append(daCell);
01115             rc.m_removed.append(daCell->columnSpan() == 1);
01116         }
01117 
01118         if(daCell->columnSpan() == 1) { // lets remove it
01119             if(daCell->firstRow() == i) {
01120                 m_frames.remove( daCell->frame(0) );
01121                 m_nr_cells--;
01122             }
01123             m_rowArray[i]->m_cellArray.insert(col, 0);
01124         }
01125         else {                    // make cell span 1 less column
01126             if(daCell->firstRow() == i) {
01127                 daCell->setColumnSpan( daCell->columnSpan() - 1 );
01128                 position(daCell);
01129             }
01130         }
01131     }
01132 
01133     // adjust cells in a later column
01134     for(; iter; ++iter) {
01135         if (iter->firstColumn() > col ) {
01136             iter->setFirstColumn( iter->firstColumn() - 1);
01137             position(iter.current());
01138         }
01139     }
01140 
01141     // move pointers in 2d array back one column to occupy
01142     // removed column
01143     for(uint i = 0; i < m_rows; i++) {
01144         for(uint j = col + 1; j < m_cols; j++)
01145              m_rowArray[i]->m_cellArray.insert(j-1, m_rowArray[i]->m_cellArray[j]);
01146     }
01147     m_cols--;
01148     rc.m_initialized = true;
01149 
01150     validate();
01151     recalcCols( col, 0 );
01152     recalcRows( col, 0 );
01153 }
01154 
01155 void KWTableFrameSet::reInsertColumn(RemovedColumn &rc)
01156 {
01157     QValueList<double>::iterator tmp = m_colPositions.at(rc.m_index);
01158 
01159     tmp = m_colPositions.insert(tmp, *tmp);
01160     tmp++;
01161     while(tmp != m_colPositions.end()) {
01162         (*tmp) = (*tmp) + rc.m_width;
01163         tmp++;
01164     }
01165 
01166     // if a cell starts after the column we are inserting, it
01167     // must be moved to the right, except if it is going to
01168     // occury the reinserted column also.
01169     for ( MarkedIterator cells(this); cells ; ++cells ) {
01170         if ( cells->firstColumn() >= rc.m_index &&
01171             (rc.m_column.at(cells->firstRow()) != cells.current())) {
01172 
01173             cells->setFirstColumn(cells->firstColumn() + 1);
01174         }
01175     }
01176     insertEmptyColumn(rc.m_index);
01177     m_cols++;
01178 
01179     for(uint i = 0; i < m_rows; ++i) {
01180         bool removed = rc.m_removed[i];
01181         Cell *daCell = rc.m_column.at(i);
01182         if(i == daCell->firstRow()) {
01183             if(removed) {
01184                 daCell->setColumnSpan(1);
01185                 m_frames.append(daCell->frame(0));
01186                 m_nr_cells++;
01187             }
01188             else  {
01189                daCell->setColumnSpan(daCell->columnSpan() + 1);
01190             }
01191             addCell(daCell);
01192         }
01193     }
01194 
01195     validate();
01196     finalize();
01197 }
01198 
01199 void KWTableFrameSet::insertNewColumn( uint idx, double width)
01200 {
01201     QValueList<double>::iterator tmp = m_colPositions.at(idx);
01202 
01203     tmp = m_colPositions.insert(tmp, *tmp);
01204     tmp++;
01205     while(tmp!=m_colPositions.end()) {
01206         (*tmp)= (*tmp)+width;
01207         tmp++;
01208     }
01209 
01210     for ( MarkedIterator cells(this); cells ; ++cells ) {
01211         if ( cells->firstColumn() >= idx) { // move all cells right of the new col.
01212             cells->setFirstColumn(cells->firstColumn() + 1);
01213         }
01214     }
01215     insertEmptyColumn(idx);
01216     m_cols++;
01217     uint copyCol = (idx == 0) ? 1 : idx - 1 ;
01218 
01219     // make the new cells
01220     // note that the loop counter is mucked with in the loop!
01221     for( unsigned int i = 0; i < getRows(); i++ ) {
01222 
01223         // can't break a cell in half, so if there is the same cell
01224         // on both sides of inserted column, it occupies the new
01225         // column as well
01226         if(idx != 0 && (idx != m_cols -1)) {
01227             Cell *c = cell(i, idx - 1);
01228             if( c == cell(i, idx + 1) ) {
01229 //                m_rowArray[i]->m_cellArray.insert(idx, c);
01230                 c->setColumnSpan(c->columnSpan() + 1);
01231                 addCell(c);
01232                 i += c->rowSpan() - 1;
01233                 continue; // don't need to make a new cell
01234             }
01235         }
01236 
01237         Cell *newCell = new Cell( this, i, idx, QString::null );
01238         KWFrame *theFrame = new KWFrame(cell(i, copyCol)->frame(0));
01239         newCell->addFrame( theFrame, false );
01240         position(newCell);
01241         m_nr_cells++;
01242     }
01243     validate();
01244     finalize();
01245 }
01246 
01247 void KWTableFrameSet::ungroup()
01248 {
01249 //    m_cells.setAutoDelete( false );
01250 //    m_cells.clear();
01251     m_nr_cells = 0;
01252 
01253     m_active = false;
01254 }
01255 
01256 void KWTableFrameSet::group()
01257 {
01258 //   m_cells.setAutoDelete( true );
01259 //   m_cells.clear();
01260 
01261    m_nr_cells = 0;
01262    m_active = true;
01263 }
01264 
01265 KCommand *KWTableFrameSet::joinCells(unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd) {
01266     Cell *firstCell = cell(rowBegin, colBegin);
01267     // if just one cell selected for joining; exit.
01268     if(rowBegin == rowEnd && colBegin == colEnd || cell(rowBegin,colBegin) == cell(rowEnd,colEnd))
01269         return 0L;
01270     QPtrList<KWFrameSet> listFrameSet;
01271     QPtrList<KWFrame> listCopyFrame;
01272 
01273     // do the actual merge.
01274     for(unsigned int i=colBegin; i<=colEnd;i++) {
01275         for(unsigned int j=rowBegin; j<=rowEnd;j++) {
01276             Cell *daCell = cell(j,i);
01277             if(daCell && daCell!=firstCell) {
01278                 listFrameSet.append(daCell);
01279                 KWFrame* frame = daCell->frame(0);
01280                 Q_ASSERT(frame);
01281                 if(! frame) continue; // see bug #132642
01282                 listCopyFrame.append(frame->getCopy());
01283                 daCell->deleteFrame(frame);
01284             }
01285         }
01286     }
01287 
01288     Q_ASSERT(firstCell);
01289     // update firstcell properties to reflect the merge
01290     firstCell->setColumnSpan(colEnd-colBegin+1);
01291     firstCell->setRowSpan(rowEnd-rowBegin+1);
01292     addCell(firstCell);
01293     position(firstCell);
01294     validate();
01295 
01296     m_doc->updateAllFrames(); // TODO: only fs->updateFrames() & m_doc->updateFramesOnTopOrBelow(pageNum)
01297     m_doc->repaintAllViews();
01298     return new KWJoinCellCommand( i18n("Join Cells"), this,colBegin,rowBegin, colEnd,rowEnd,listFrameSet,listCopyFrame);
01299 }
01300 
01301 KCommand *KWTableFrameSet::splitCell(unsigned int intoRows, unsigned int intoCols, unsigned int col, unsigned int row, QPtrList<KWFrameSet> listFrameSet, QPtrList<KWFrame>listFrame) {
01302     if(intoRows < 1 || intoCols < 1)
01303         return 0L;
01304 
01305     kdDebug(32004) << "KWTableFrameSet::splitCell" << endl;
01306     Cell *daCell=cell(row,col);
01307     int rowsDiff = intoRows - daCell->rowSpan();
01308     int colsDiff = ((int) intoCols) - daCell->columnSpan();
01309 
01310     if(rowsDiff >0) {
01311         unsigned int adjustment=0;
01312         QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
01313         while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row) {
01314             adjustment++;
01315             pageBound++;
01316         }
01317         double height = (m_rowPositions[row+adjustment+1] - m_rowPositions[row+adjustment])/intoRows;
01318 
01319         QValueList<double>::iterator iRow = m_rowPositions.at(adjustment+row);
01320         for (int i=0; i < rowsDiff; i++) {
01321             double newPos = *iRow + height;
01322             iRow++;
01323             iRow=m_rowPositions.insert(iRow, newPos);
01324         }
01325 
01326         // insert more rows into m_rowArray
01327         for(int i = 0; i < rowsDiff; ++i) {
01328             insertRowVector(row+i+1, new Row);
01329             m_rows++;
01330         }
01331 
01332        // m_rows += rowsDiff;
01333         //for(unsigned int i=0; i < m_rowPositions.count() ; ++i)
01334         //    kdDebug(32004) << "row " << i << ": " << m_rowPositions[i] << endl);
01335     }
01336     if(colsDiff >0) {
01337         double width = (m_colPositions[col+1] - m_colPositions[col])/intoCols;
01338 
01339         QValueList<double>::iterator iCol = m_colPositions.at(col);
01340         for (int i=0; i < colsDiff; i++) {
01341             double newPos = *iCol + width;
01342             iCol++;
01343             iCol=m_colPositions.insert(iCol, newPos);
01344         }
01345 
01346         for(int i = 0; i < colsDiff; i++) {
01347             insertEmptyColumn(col+i+1);
01348             m_cols++;
01349         }
01350         //for(unsigned int i=0; i < m_colPositions.count(); ++i)
01351         //    kdDebug(32004) << "col " << i << ": " << m_colPositions[i] << endl);
01352         //m_cols += colsDiff;
01353     }
01354 
01355     // adjust cellspan and rowspan on other cells.
01356     for (CheckedIter i(this); i ; ++i) {
01357         if(daCell == i) continue;
01358 
01359         if(rowsDiff>0) {
01360             if(row >= i->firstRow()&& row < i->firstRow()+ i->rowSpan())
01361                 i->setRowSpan(i->rowSpan() + rowsDiff);
01362             if(i->firstRow() > row) {
01363                 i->setFirstRow(i->firstRow() + rowsDiff);
01364             //    theCell->frame(0)->setTop(theCell->frame(0)->top()+extraHeight);
01365             }
01366         }
01367         if(colsDiff>0) {
01368             if(col >= i->firstColumn() && col < i->columnAfter())
01369                 i->setColumnSpan(i->columnSpan() + colsDiff);
01370             if(i->firstColumn() > col)
01371                 i->setFirstColumn(i->firstColumn() + colsDiff);
01372         }
01373         /*if(extraHeight != 0 && theCell->firstRow()== row) {
01374             theCell->frame(0)->setHeight(theCell->frame(0)->height()+extraHeight);
01375         } */
01376         if ( rowsDiff > 0 || colsDiff > 0 ) // something changed?
01377             addCell( i ); // update arrays
01378     }
01379 
01380     int i=0;
01381     KWFrame *firstFrame = daCell->frame(0);
01382     // create new cells
01383     for (unsigned int y = 0; y < intoRows; y++) {
01384         for (unsigned int x = 0; x < intoCols; x++){
01385             if(x==0 && y==0)
01386                 continue; // the orig cell takes this spot.
01387 
01388             Cell *lastFrameSet=0L;
01389 
01390             if(listFrameSet.isEmpty())
01391                 lastFrameSet = new Cell( this, y + row, x + col );
01392             else
01393                 lastFrameSet = static_cast<KWTableFrameSet::Cell*> (listFrameSet.at(i));
01394             lastFrameSet->setGroupManager(this);
01395 
01396             KWFrame *theFrame=0L;
01397             if(listFrame.isEmpty())
01398             {
01399                 theFrame=firstFrame->getCopy();
01400                 theFrame->setRunAround( KWFrame::RA_NO );
01401                 theFrame->setFrameBehavior(KWFrame::AutoExtendFrame);
01402                 theFrame->setNewFrameBehavior(KWFrame::NoFollowup);
01403                 lastFrameSet->addFrame( theFrame,false );
01404             }
01405             else
01406                 lastFrameSet->addFrame( listFrame.at(i)->getCopy(),false );
01407             i++;
01408 
01409             // if the orig cell spans more rows/cols than it is split into, make first col/row wider.
01410             if(rowsDiff <0 && y==0)
01411                 lastFrameSet->setRowSpan(lastFrameSet->rowSpan() - rowsDiff);
01412             if(colsDiff <0 && x==0)
01413                 lastFrameSet->setColumnSpan(lastFrameSet->columnSpan() - colsDiff);
01414 
01415             addCell( lastFrameSet );
01416             position(lastFrameSet);
01417         }
01418     }
01419 
01420     // set new row and col-span. Use intermediate ints otherwise we get strange results as the
01421     // intermediate result could be negative (which goes wrong with unsigned ints)
01422     int r = (daCell->rowSpan() +1) - intoRows;
01423     if(r < 1) r=1;
01424     daCell->setRowSpan(r);
01425 
01426     int c = (daCell->columnSpan() + 1) - intoCols;
01427     if(c < 1)  c=1;
01428     daCell->setColumnSpan(c);
01429 
01430     position(daCell);
01431     addCell(daCell);
01432     validate();
01433 
01434     finalize();
01435 
01436     return new KWSplitCellCommand(i18n("Split Cells"),this,col,row,intoCols, intoRows);
01437 }
01438 
01439 void KWTableFrameSet::viewFormatting( QPainter &/*painter*/, int )
01440 {
01441 }
01442 
01443 void KWTableFrameSet::validate()
01444 {
01445     for(CheckedIter cells(this); cells; ++cells) {
01446         if(cells->columnSpan() == 0 || cells->rowSpan() == 0)  {
01447             kdDebug(32004) << " KWTableFrameSet::validate(): zero dimension" << endl;
01448             kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
01449                 << " " << cells->columnSpan() << endl;
01450         }
01451 
01452         for(uint i = cells->firstRow(); i < cells->rowAfter(); ++i) {
01453 
01454              for(uint j = cells->firstColumn(); j < cells->columnAfter(); ++j) {
01455                   if( cell(i,j) != cells.current() ) {
01456 
01457                       QString str = QString("| 0x%1 ").arg( (unsigned long)cells.current(), 0, 16 );
01458                       kdDebug(32004) << " KWTableFrameSet::validate() failed " << endl;
01459                       kdDebug(32004) << "at row:  "<< i << " col: "<< j << " cell: "<<  str << endl;
01460                       kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
01461                            << " " << cells->columnSpan() << endl;
01462                       //printArrayDebug();
01463                   }
01464              }
01465         }
01466     }
01467 }
01468 
01469 void KWTableFrameSet::createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode )
01470 {
01471     // Avoid iterating over all cells if we are out of view
01472     if ( !viewMode->normalToView( m_doc->zoomRect( boundingRect() ) ).intersects( crect ) )
01473         return;
01474 
01475     QRect outerRect( viewMode->normalToView( m_doc->zoomRect( boundingRect() )));
01476     outerRect &= crect;
01477         if ( !outerRect.isEmpty() )
01478             emptyRegion = emptyRegion.subtract( outerRect );
01479 
01480     QPtrListIterator<KWFrame> frameIt = frameIterator();
01481     for ( ; frameIt.current(); ++frameIt )
01482     {
01483         QRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
01484         //kdDebug(32004) << "KWTableFrameSet::createEmptyRegion outerRect=" << DEBUGRECT( outerRect )
01485         //          << " crect=" << DEBUGRECT( crect ) << endl;
01486         outerRect &= crect;
01487         if ( !outerRect.isEmpty() )
01488             emptyRegion = emptyRegion.subtract( outerRect );
01489     }
01490 }
01491 
01492 void KWTableFrameSet::drawBorders( QPainter& painter, const QRect &crect, KWViewMode *viewMode ) {
01493 
01494     /*  Draw the borders on top of the lines stores in the m_rowPositions and m_colPositions arrays.
01495      *  check the relevant cells for borders and thus line thickness.
01496      *  We move the outer lines (on row==0 and col==0 plus on col=getColumns() etc) a bit so they will stay
01497      *  inside the boundary of the table!
01498      */
01499     painter.save();
01500     QPen previewLinePen( QApplication::palette().color(  QPalette::Active, QColorGroup::Mid ) );
01501     QColor defaultBorderColor = KoTextFormat::defaultTextColor( &painter );
01502     const int minborder = 1;
01503     bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
01504 
01505     // *** draw horizontal lines *** //
01506     unsigned int row=0;
01507     QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
01508     for (unsigned int i=0 ; i < m_rowPositions.count() ; i++) {
01509         //kdDebug(32004) << "Horizontal line code. i: " << i << endl;
01510         bool bottom=false;
01511         if( (pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
01512             || i == m_rowPositions.count()-1)
01513             bottom=true;  // at end of page or end of table draw bottom border of cell.
01514 
01515         const KoBorder *border=0;
01516         double startPos =0;
01517         for(unsigned int col=0; col <= getColumns();) {
01518             //kdDebug(32004) << "bottom=" << bottom << " row=" << row << " col=" << col << endl;
01519             Cell *daCell = col < getColumns() ? cell(bottom?row-1:row, col) : 0;
01520             //if(daCell) kdDebug(32004) << "cell (" << daCell->firstRow()<< "," << daCell->firstColumn() << ")" << endl;
01521             //else kdDebug(32004) << "cell: " << daCell << endl;
01522 
01523             if(daCell && daCell->firstRow() != (bottom?row-1:row))
01524                 daCell=0;
01525 
01526             if(startPos!=0 && (!daCell || col == getColumns() || (
01527                     bottom && daCell->frame(0)->bottomBorder()!=*border ||
01528                     !bottom && daCell->frame(0)->topBorder()!=*border
01529                     ))) {
01530                 if(border->width() > 0 || drawPreviewLines) {
01531                     double y = m_rowPositions[i];
01532                     if(row==0)
01533                         y+=border->width() / 2; // move slightly down.
01534                     else if (row == getRows())
01535                         y-=border->width() / 2; // move slightly up.
01536                     int ypix = m_doc->zoomItY(y);
01537                     double offset=0.0;
01538                     if(border->width() > 0 && col!=getColumns()) { // offset border when not at right most cell.
01539                         if(daCell) offset=daCell->leftBorder();
01540                         if ( row > 0 ) {
01541                             Cell *c = cell(row-1, col);
01542                             if(c) offset=kMax(offset, c->leftBorder());
01543                         }
01544                     }
01545                     double x = m_colPositions[col] + offset;
01546                     QPoint topLeft = viewMode->normalToView(QPoint(m_doc->zoomItX(startPos), ypix));
01547                     QPoint bottomRight = viewMode->normalToView(QPoint(m_doc->zoomItX(x), ypix));
01548                     QRect line = QRect(topLeft, bottomRight);
01549                     if(crect.intersects( line )) {
01550                         //if(border->width() <= 0) kdDebug(32004) << "preview line" << endl;
01551                         if(border->width() <= 0)
01552                             painter.setPen( previewLinePen );
01553                         else {
01554                             int borderWidth = KoBorder::zoomWidthY( border->width(), m_doc, minborder );
01555                             painter.setPen( KoBorder::borderPen( *border, borderWidth, defaultBorderColor ) );
01556                         }
01557                         //kdDebug(32004) << "Paint: painter.drawHorizontalLine(" << line.left() << ","  << line.top() << "," <<  line.right() << ","  << line.bottom() << ")\n";
01558                         painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
01559                     }
01560                 }
01561                 // reset startPos
01562                 startPos = 0;
01563             }
01564             if(daCell && startPos==0) {
01565                 if(bottom)
01566                     border=&(daCell->frame(0)->bottomBorder());
01567                 else
01568                     border=&(daCell->frame(0)->topBorder());
01569 
01570                 if(col==0) // left most cell
01571                     startPos = m_colPositions[col];
01572                 else {
01573                     double offset=0.0;
01574                     if(border->width() > 0) { // move line to the left a bit to compensate for the left border
01575                         if(daCell) offset=daCell->leftBorder();
01576                         if ( row > 0 ) {
01577                             Cell *c = cell(row-1, col);
01578                             if(c) offset=kMax(offset, c->leftBorder());
01579                         }
01580                     }
01581                     startPos = m_colPositions[col] - offset;
01582                 }
01583             }
01584             col += daCell ? daCell->columnSpan() : 1;
01585         }
01586         if(pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
01587             pageBound++;
01588         else
01589             row++;
01590     }
01591 
01592     // *** draw vertical lines *** //
01593     for (unsigned int col=0 ; col < m_colPositions.count(); col++) {
01594         //kdDebug(32004) << "Vertical line code. col: " << col << endl;
01595         bool right = false;
01596         if(col == m_colPositions.count()-1)
01597             right = true; // draw right border of cell.
01598         int cellColumn = right?col-1:col; // the column we'll be looking for in the loop below
01599         Q_ASSERT( cellColumn >= 0 );
01600 
01601         const KoBorder *border = 0;
01602         int startRow = -1;
01603         for(unsigned int row=0; row <= getRows();) {
01604             //kdDebug(32004) << "row=" << row << " cellColumn=" << cellColumn << endl;
01605             Cell *daCell = row < getRows() ? cell(row, cellColumn) : 0;
01606 
01607             //kdDebug(32004) << "Drawing vert. Line for cell row: " << row << " col: " << cellColumn << endl;
01608             if(daCell && daCell->firstColumn() != (uint)cellColumn)
01609                 daCell=0;
01610 
01611 #if 0
01612             kdDebug() << "Condition: startRow:" << (startRow!=-1) << endl;
01613             if ( startRow != -1 )  {
01614                 Q_ASSERT( border );
01615                 kdDebug() << "Other conditions: cell:" << !daCell << endl;
01616                 kdDebug() << " or last row:" << ( row == ( int )getRows() ) << endl;
01617                 if ( daCell )
01618                     kdDebug() << "Different border:" <<
01619                 ( ( right && daCell->frame(0)->rightBorder() != *border) ||
01620                 ( !right && daCell->frame(0)->leftBorder() != *border) )
01621                     << endl;
01622             }
01623 #endif
01624 
01625             // be sure that the right border of the table is drawn even for joined cells
01626             if ( !daCell && startRow == -1 && cellColumn == ((int)m_colPositions.count()-2 ) && right )
01627             {
01628               // find the joined cell
01629               int col = cellColumn;
01630               while ( !daCell && col>0 )
01631               {
01632                 col--;
01633                 daCell = cell(row, col);
01634               }
01635               if ( daCell && daCell->isJoinedCell() && ( (int)daCell->columnSpan() + col -1 ) == cellColumn )
01636               {
01637                 border = &(daCell->frame(0)->rightBorder());
01638                 startRow = row;
01639               }
01640               else
01641                 daCell = 0;
01642             }
01643 
01644             // Draw when something changed (different kind of border) or we're at the end
01645             // This code could be rewritten in a more QRT-like way
01646             // (iterate and compare with next, instead of the startRow/cell/border hack...)
01647             if(startRow != -1 &&
01648                (!daCell || row == getRows() ||
01649                 ( right && daCell->frame(0)->rightBorder() != *border) ||
01650                 ( !right && daCell->frame(0)->leftBorder() != *border) )
01651                 ) {
01652                 if(border->width() > 0 || drawPreviewLines) {
01653                     double x = m_colPositions[col];
01654                     if(col==0) {
01655                         x+=border->width() / 2;
01656                     } else if(col==getColumns()) {
01657                         x-=border->width() / 2;
01658                     }
01659                     int xpix = m_doc->zoomItX(x);
01660                     QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
01661                     unsigned int topRow=startRow;
01662                     //kdDebug(32004) << "Drawing from topRow=" << topRow << endl;
01663                     do { // draw minimum of one line per page.
01664                         while( pageBound != m_pageBoundaries.end() && *(pageBound) < topRow )
01665                             pageBound++;
01666 
01667                         unsigned int bottomRow;
01668                         if(pageBound == m_pageBoundaries.end())
01669                             bottomRow = m_rowPositions.count()-1;
01670                         else
01671                             bottomRow = *(pageBound++);
01672 
01673                         //kdDebug(32004) << "from: " << topRow << " to: " << kMin((uint)row, bottomRow) << endl;
01674                         //kdDebug(32004) << "from: " << m_rowPositions[topRow] << " to: " << m_rowPositions[kMin((uint)row, bottomRow)] << endl;
01675                         double offset=0.0;
01676                         if(border->width() > 0) {
01677                             //kdDebug(32004) << "looking at topRow=" << topRow << " col=" << col << endl;
01678                             Cell *c=cell(topRow,col);
01679                             if(c) offset=c->topBorder();
01680                             if ( col > 0 ) {
01681                                 c=cell(topRow,col-1);
01682                                 if(c) offset=kMax(offset,c->topBorder());
01683                             }
01684                             if(topRow==0) offset=0.0;
01685                         }
01686                         double top=m_rowPositions[topRow]-offset;
01687 
01688                         unsigned int toRow=kMin((uint)row,bottomRow);
01689                         offset=0.0;
01690                         if(border->width() > 0 && toRow!=bottomRow) {
01691                             if(daCell) offset=daCell->topBorder();
01692                             Cell *c=cell(toRow,col-1);
01693                             if(c) offset=kMax(offset,c->topBorder());
01694                         }
01695                         double bottom=m_rowPositions[toRow] + offset;
01696 
01697                         QPoint topLeft = viewMode->normalToView(QPoint(xpix, m_doc->zoomItY(top)));
01698                         QPoint bottomRight = viewMode->normalToView(QPoint(xpix, m_doc->zoomItY(bottom)));
01699                         QRect line = QRect(topLeft, bottomRight);
01700                         if(crect.intersects( line )) {
01701                             if(border->width() <= 0)
01702                                 painter.setPen( previewLinePen );
01703                             else {
01704                                 int borderWidth = KoBorder::zoomWidthX( border->width(), m_doc, minborder );
01705                                 painter.setPen(KoBorder::borderPen( *border, borderWidth, defaultBorderColor ));
01706                             }
01707                             //kdDebug(32004) << "drawBorders(): painter.drawVerticalLine(" << line.left() << ","  << line.top() << "," <<  line.right() << ","  << line.bottom() << ")\n";
01708                             painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
01709                         }
01710 
01711                         topRow=bottomRow+1;
01712                     } while(topRow < (uint)row && topRow != m_rowPositions.count());
01713                 } // end "if border to be drawn"
01714 
01715                 // reset startRow
01716                 startRow = -1;
01717             }
01718 
01719             if(daCell && startRow == -1) {
01720                 startRow = row;
01721                 if(right)
01722                     border = &(daCell->frame(0)->rightBorder());
01723                 else
01724                     border = &(daCell->frame(0)->leftBorder());
01725                 //kdDebug(32004) << "startRow set to " << row << endl;
01726             }
01727             row += daCell ? daCell->rowSpan() : 1;
01728             //kdDebug(32004) << "End of loop, row=" << row << endl;
01729         }
01730     }
01731 
01732 #if 0
01733     if(drawPreviewLines) {
01734         QPen minsizeLinePen( red );
01735         painter.setPen( minsizeLinePen );
01736         for ( unsigned int i = 0; i < m_cells.count(); i++ ) {
01737             Cell *daCell = m_cells.at( i );
01738             double y = daCell->frame(0)->top() + daCell->frame(0)->minimumFrameHeight() + 1.5;
01739             if(y >= daCell->frame(0)->bottom()) continue;
01740             int ypix=m_doc->zoomItY(y);
01741             QPoint topLeft = viewMode->normalToView(QPoint(m_doc->zoomItX(daCell->frame(0)->left()), ypix));
01742             QPoint bottomRight = viewMode->normalToView(QPoint(m_doc->zoomItX(daCell->frame(0)->right()), ypix));
01743             QRect line = QRect(topLeft, bottomRight);
01744             if(crect.intersects( line )) {
01745                 painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
01746             }
01747         }
01748     }
01749 #endif
01750 
01751     painter.restore();
01752 }
01753 
01754 void KWTableFrameSet::drawContents( QPainter * painter, const QRect & crect,
01755                                     const QColorGroup & cg, bool onlyChanged, bool resetChanged,
01756                                     KWFrameSetEdit * edit, KWViewMode * viewMode,
01757                                     KWFrameViewManager *fvm )
01758 {
01759     for (TableIter cells(this) ; cells ; ++cells)
01760     {
01761         if (edit)
01762         {
01763             KWTableFrameSetEdit * tableEdit = static_cast<KWTableFrameSetEdit *>(edit);
01764             if ( tableEdit->currentCell() && ((Cell*) cells) == tableEdit->currentCell()->frameSet() )
01765             {
01766                 cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, tableEdit->currentCell(), viewMode, fvm );
01767                 continue;
01768             }
01769         }
01770         cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, 0L, viewMode, fvm );
01771     }
01772     drawBorders( *painter, crect, viewMode );
01773     //kdDebug(32004) << "drawContents()" << endl;
01774 }
01775 
01776 // Called by KWAnchor for inline tables
01777 // TODO: for non-inline ones we need a text-box around us...
01778 // Well, even for inline-as-char ones.... Currently being debated with OASIS.
01779 void KWTableFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool ) const
01780 {
01781     writer.startElement( "table:table" );
01782     writer.addAttribute( "table:name", name() );
01783     KoGenStyle tableStyle( KWDocument::STYLE_TABLE, "table" );
01784     tableStyle.addProperty( "table:align", "margins" );
01785     tableStyle.addPropertyPt( "style:width", m_colPositions.last()-m_colPositions[0] );
01786     const QString tableStyleName = context.mainStyles().lookup( tableStyle, "table" );
01787     writer.addAttribute( "table:style-name", tableStyleName );
01788 
01789     // ### to minimize the XML, we could use table:number-columns-repeated here
01790     // when a number of consecutive columns have the exact same style.
01791     for ( uint colNr = 0; colNr < getColumns(); ++colNr )
01792     {
01793         writer.startElement( "table:table-column" );
01794         KoGenStyle columnStyle( KWDocument::STYLE_TABLE_COLUMN, "table-column" );
01795         columnStyle.addPropertyPt( "style:column-width", m_colPositions[colNr+1] - m_colPositions[colNr] );
01796         const QString colStyleName = context.mainStyles().lookup( columnStyle, "col" );
01797         writer.addAttribute( "table:style-name", colStyleName );
01798         writer.endElement(); // table:table-column
01799     }
01800 
01801     // TODO table-header-rows once supported
01802 
01803     for ( uint row = 0; row < getRows(); ++row )
01804     {
01805         writer.startElement( "table:table-row" );
01806 
01807         KoGenStyle rowStyle( KWDocument::STYLE_TABLE_ROW, "table-row" );
01808         rowStyle.addPropertyPt( "table:row-height", m_rowPositions[row+1] - m_rowPositions[row] );
01809         // TODO is min-row-height or use-optimal-row-height necessary?
01810         const QString rowStyleName = context.mainStyles().lookup( rowStyle, "row" );
01811         writer.addAttribute( "table:style-name", rowStyleName );
01812 
01813         for ( uint col = 0; col < getColumns(); ++col )
01814         {
01815             Cell* daCell = cell(row, col);
01816             Q_ASSERT( daCell );
01817             if ( !daCell )
01818                 continue;
01819 
01820             if ( daCell->isFirstGridPosnFast( row, col ) )
01821             {
01822                 writer.startElement( "table:table-cell" );
01823 
01824                 // Style: background, border, padding.
01825                 KoGenStyle cellStyle( KWDocument::STYLE_TABLE_CELL_AUTO, "table-cell" );
01826                 daCell->frame( 0 )->saveBorderProperties( cellStyle );
01827                 const QString colStyleName = context.mainStyles().lookup( cellStyle, "cell" );
01828                 writer.addAttribute( "table:style-name", colStyleName );
01829 
01830                 // Attributes
01831                 if ( daCell->columnSpan() > 1 )
01832                     writer.addAttribute( "table:number-columns-spanned", daCell->columnSpan() );
01833                 if ( daCell->rowSpan() > 1 )
01834                     writer.addAttribute( "table:number-row-spanned", daCell->rowSpan() );
01835 
01836                 // Content
01837                 daCell->saveOasisContent( writer, context );
01838 
01839                 writer.endElement(); // table:table-cell
01840             }
01841             else
01842             {
01843                 // Empty element for the covered cell
01844                 writer.startElement( "table:covered-table-cell" );
01845                 writer.endElement();
01846             }
01847         }
01848         writer.endElement(); // table:table-row
01849     }
01850 
01851     writer.endElement(); // table:table
01852 }
01853 
01854 void KWTableFrameSet::loadOasis( const QDomElement& tableTag, KoOasisContext& context )
01855 {
01856     // Left position of each column. The last one defined is the right position of the last cell/column.
01857     QMemArray<double> columnLefts(4);
01858     uint maxColumns = columnLefts.size() - 1;
01859 
01860     uint col = 0;
01861     columnLefts[0] = 0.0; // Initialize left of first cell
01862     QDomElement elem;
01863     forEachElement( elem, tableTag )
01864     {
01865         if ( elem.localName() == "table-column" && elem.namespaceURI() == KoXmlNS::table )
01866         {
01867             uint repeat = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", "1").toUInt(); // Default 1 time
01868             if (!repeat)
01869                 repeat=1; // At least one column defined!
01870             KoStyleStack& styleStack = context.styleStack();
01871             styleStack.setTypeProperties( "table-column" );
01872             styleStack.save();
01873             context.fillStyleStack( elem, KoXmlNS::table, "style-name", "table-column" );
01874 
01875             QString strWidth = styleStack.attributeNS( KoXmlNS::style, "column-width" );
01876             double width = KoUnit::parseValue( strWidth );
01877 
01878             if ( width < 1.0 ) // Something is wrong with the width
01879             {
01880                 kdWarning(32004) << "Table column width ridiculous, assuming 1 inch!" << endl;
01881                 width = 72.0;
01882             }
01883             else
01884                 kdDebug(32004) << "- style width " << width << endl;
01885 
01886             for ( uint j = 0; j < repeat; ++j )
01887             {
01888                 ++col;
01889                 if ( col >= maxColumns )
01890                 {
01891                     // We need more columns
01892                     maxColumns += 4;
01893                     columnLefts.resize( maxColumns+1, QGArray::SpeedOptim );
01894                 }
01895                 columnLefts[col] = width + columnLefts[col-1];
01896                 kdDebug(32004) << "Cell column " << col-1 << " left " << columnLefts[col-1] << " right " << columnLefts[col] << endl;
01897             }
01898             styleStack.restore();
01899         }
01900     }
01901 
01902     uint row = 0;
01903     uint column = 0;
01904     parseInsideOfTable( tableTag, context, columnLefts, row, column, 0 );
01905 }
01906 
01907 void KWTableFrameSet::parseInsideOfTable( const QDomElement& parent, KoOasisContext& context,
01908                                           const QMemArray<double> & columnLefts, uint& row, uint& column,
01909                                           double currentRowHeight )
01910 {
01911     kdDebug(32004) << "parseInsideOfTable" << endl;
01912     KoStyleStack& styleStack = context.styleStack();
01913 
01914     QDomElement e;
01915     forEachElement( e, parent )
01916     {
01917         const QString localName = e.localName();
01918         const QString ns = e.namespaceURI();
01919         if ( ns != KoXmlNS::table ) {
01920             kdWarning(32004) << "Skipping element " << e.tagName() << " (in parseInsideOfTable)" << endl;
01921             continue;
01922         }
01923 
01924         styleStack.save();
01925         if ( localName == "table-cell" )
01926         {
01927             loadOasisCell( e, context, columnLefts, row, column, currentRowHeight );
01928             ++column;
01929         }
01930         else if ( localName == "covered-table-cell" )
01931         {
01932             ++column;
01933         }
01934         else if ( localName == "table-row" )
01935         {
01936             context.fillStyleStack( e, KoXmlNS::table, "style-name", "table-row" );
01937             context.styleStack().setTypeProperties( "table-row" );
01938 
01939             // Load row height in case it was set - note that it might not be set (e.g. OOo)
01940             double rowHeight = styleStack.attributeNS( KoXmlNS::table, "row-height" ).toDouble();
01941             column = 0;
01942             parseInsideOfTable( e, context, columnLefts, row, column, rowHeight );
01943             ++row;
01944         }
01945         else if ( localName == "table-header-rows" ) // ###TODO
01946         {
01947             // TODO: do we need to fillStyleStack?
01948             parseInsideOfTable( e, context, columnLefts, row, column, currentRowHeight );
01949         }
01950         else if ( localName == "table-column" )
01951         {
01952             // Already treated in loadOasis, we do not need to do anything here!
01953         }
01954         // TODO sub-table [ add to stack and expand at end of table loading ]
01955         else
01956         {
01957             kdWarning(32004) << "Skipping element " << localName << " (in parseInsideOfTable)" << endl;
01958         }
01959 
01960         styleStack.restore();
01961     }
01962 }
01963 
01964 void KWTableFrameSet::loadOasisCell( const QDomElement& element, KoOasisContext& context,
01965                                      const QMemArray<double> & columnLefts, uint row, uint column,
01966                                      double currentRowHeight )
01967 {
01968     //kdDebug(32004) << k_funcinfo << element.localName() << " " << row << "," << column << endl;
01969 
01970     KoStyleStack& styleStack = context.styleStack();
01971     uint rowSpan = element.attributeNS( KoXmlNS::table, "number-rows-spanned", QString::null ).toUInt();
01972     if ( rowSpan == 0 )
01973         rowSpan = 1;
01974     uint colSpan = element.attributeNS( KoXmlNS::table, "number-columns-spanned", QString::null ).toUInt();
01975     if ( colSpan == 0 )
01976         colSpan = 1;
01977 
01978     // m_rowPositions / m_colPositions could be QMemArrays, or QValueVectors...
01979     while(m_rowPositions.count() <= row + rowSpan + m_pageBoundaries.count()) {
01980         m_rowPositions.append(0);
01981     }
01982     while(m_colPositions.count() <= column + colSpan) {
01983         m_colPositions.append(0);
01984     }
01985 
01986     Cell *daCell = new Cell( this, row, column, QString::null /*unused*/ );
01987 
01988     daCell->setRowSpan( rowSpan );
01989     daCell->setColumnSpan( colSpan );
01990     addCell( daCell ); // rowSpan/colSpan have changed -> update array
01991 
01992     double width = columnLefts[ QMIN( column+colSpan, columnLefts.size()-1 ) ] - columnLefts[column];
01993     double height = currentRowHeight > 0 ? currentRowHeight : 20;
01994     KWFrame* frame = new KWFrame( daCell, columnLefts[column], 0, width, height );
01995     if ( currentRowHeight > 0 )
01996         frame->setMinimumFrameHeight( height ); // ensure that text formatting won't resize it down
01997     frame->setRunAround( KWFrame::RA_NO );
01998     frame->setFrameBehavior( KWFrame::AutoExtendFrame );
01999     frame->setNewFrameBehavior( KWFrame::NoFollowup );
02000     daCell->addFrame( frame, false );
02001 
02002     context.fillStyleStack( element, KoXmlNS::table, "style-name", "table-cell" );
02003     styleStack.setTypeProperties( "table-cell" );
02004 
02005     daCell->frame( 0 )->loadBorderProperties( styleStack );
02006 
02007     daCell->loadOasisContent( element, context );
02008     afterLoadingCell( daCell );
02009 }
02010 
02011 // Old XML
02012 QDomElement KWTableFrameSet::save( QDomElement &parentElem, bool saveFrames ) {
02013     // When saving to a file, we don't have anything specific to the frameset to save.
02014     // Save the cells only.
02015     for (TableIter cells(this) ; cells ; ++cells)
02016         cells->save(parentElem, saveFrames);
02017     return QDomElement(); // No englobing element for tables...
02018 }
02019 
02020 // Old XML
02021 QDomElement KWTableFrameSet::toXML( QDomElement &parentElem, bool saveFrames )
02022 {
02023     QDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
02024     parentElem.appendChild( framesetElem );
02025     KWFrameSet::saveCommon( framesetElem, false ); // Save the frameset attributes
02026     // Save the cells
02027     save( framesetElem, saveFrames );
02028     return framesetElem;
02029 }
02030 
02031 // Old XML
02032 void KWTableFrameSet::fromXML( QDomElement &framesetElem, bool loadFrames, bool useNames )
02033 {
02034     KWFrameSet::load( framesetElem, false ); // Load the frameset attributes
02035     // Load the cells
02036     QDomElement cellElem = framesetElem.firstChild().toElement();
02037     for ( ; !cellElem.isNull() ; cellElem = cellElem.nextSibling().toElement() )
02038     {
02039         if ( cellElem.tagName() == "FRAMESET" )
02040             loadCell( cellElem, loadFrames, useNames );
02041     }
02042 }
02043 
02044 // Old XML
02045 KWTableFrameSet::Cell* KWTableFrameSet::loadCell( QDomElement &framesetElem, bool loadFrames, bool useNames )
02046 {
02047     int _row = KWDocument::getAttribute( framesetElem, "row", 0 );
02048     if(_row <0) _row =0;
02049     unsigned int row=_row;
02050     int _col = KWDocument::getAttribute( framesetElem, "col", 0 );
02051     if(_col <0) _col =0;
02052     int _rows = KWDocument::getAttribute( framesetElem, "rows", 1 );
02053     if(_rows <0) _rows = 1;
02054     int _cols = KWDocument::getAttribute( framesetElem, "cols", 1 );
02055     if(_cols <0) _cols = 1;
02056 
02057     // m_rowPositions / m_colPositions could be QMemArrays, or QValueVectors...
02058     while(m_rowPositions.count() <= static_cast<unsigned int>(row + _rows + m_pageBoundaries.count())) {
02059         m_rowPositions.append(0);
02060     }
02061     while(m_colPositions.count() <= static_cast<unsigned int>(_col + _cols)) {
02062         m_colPositions.append(0);
02063     }
02064 
02065     Cell *daCell = new Cell( this, row, _col, QString::null /*unused*/ );
02066     QString autoName = daCell->name();
02067     //kdDebug(32004) << "KWTableFrameSet::loadCell autoName=" << autoName << endl;
02068     daCell->load( framesetElem, loadFrames );
02069     daCell->setRowSpan(_rows);
02070     daCell->setColumnSpan(_cols);
02071     addCell( daCell ); // rowSpan/colSpan have changed -> update array
02072     afterLoadingCell( daCell );
02073     if ( !useNames )
02074         daCell->setName( autoName );
02075     return daCell;
02076 }
02077 
02078 // Shared between old xml and oasis
02079 void KWTableFrameSet::afterLoadingCell( Cell* daCell )
02080 {
02081     uint row = daCell->firstRow();
02082     uint col = daCell->firstColumn();
02083     uint rowSpan = daCell->rowSpan();
02084     uint colSpan = daCell->columnSpan();
02085     if(m_pageBoundaries.count() > 0) {
02086         unsigned int adjustment=0;
02087         QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
02088         while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
02089             adjustment++;
02090             pageBound++;
02091         }
02092         row+=adjustment;
02093     }
02094 
02095     kdDebug(32004) << "loading cell (" << row << "," << col << ")\n";
02096     if(daCell->frame(0)) {
02097         daCell->frame(0)->setMinimumFrameHeight(daCell->frame(0)->height()); // TODO run the formatter over the text here
02098         QValueList<double>::iterator tmp = m_colPositions.at(col);
02099         if(*tmp == 0) (*tmp) = daCell->frame(0)->left();
02100         else (*tmp) = (daCell->frame(0)->left() + *tmp) / 2;
02101 
02102         tmp = m_colPositions.at(col+colSpan);
02103         if(*tmp == 0) (*tmp) = daCell->frame(0)->right();
02104         else (*tmp) = (daCell->frame(0)->right() + *tmp) / 2;
02105 
02106         tmp = m_rowPositions.at(row);
02107         if(*tmp == 0)
02108             (*tmp) = daCell->frame(0)->top();
02109         else {
02110             if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) < static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
02111                 kdDebug(32004) << "This cell is on a new page" << endl;
02112                 QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
02113                 while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
02114                 if(*pageBound!=row) {
02115                     m_pageBoundaries.insert(pageBound,row++);
02116                     ++tmp;
02117                     m_rowPositions.insert(tmp,daCell->frame(0)->top());
02118                 }
02119             } else
02120                 (*tmp) = (daCell->frame(0)->top() + *tmp) / 2;
02121         }
02122 
02123         tmp = m_rowPositions.at( row + rowSpan );
02124         if(*tmp == 0)
02125             (*tmp) = daCell->frame(0)->bottom();
02126         else { // untested...
02127             if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) > static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
02128                 kdDebug(32004) << "next cell is on a new page" << endl;
02129                 QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
02130                 while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
02131                 if(*pageBound!=row) {
02132                     m_pageBoundaries.insert(pageBound,row++);
02133                     m_rowPositions.insert(tmp,daCell->frame(0)->bottom());
02134                 }
02135             } else
02136                 (*tmp) = (daCell->frame(0)->bottom() + *tmp) / 2;
02137         }
02138     }
02139 
02140     if ( m_rowPositions.count() != m_rows + 1 ) {
02141         kdDebug() << name() << " loadCell: m_rowPositions=" << m_rowPositions.count() << " m_rows= " << m_rows << endl;
02142     }
02143 }
02144 
02145 int KWTableFrameSet::paragraphs()
02146 {
02147     int paragraphs = 0;
02148     for (TableIter cells(this) ; cells ; ++cells)
02149         paragraphs += cells->paragraphs();
02150     return paragraphs;
02151 }
02152 
02153 int KWTableFrameSet::paragraphsSelected()
02154 {
02155     int paragraphs = 0;
02156     for (TableIter cells(this) ; cells ; ++cells)
02157         paragraphs += cells->paragraphsSelected();
02158     return paragraphs;
02159 }
02160 
02161 bool KWTableFrameSet::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
02162     ulong & sentences, ulong & syllables, ulong & lines, bool selected )
02163 {
02164     for (TableIter cells(this) ; cells ; ++cells)
02165         if( ! cells->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected ) )
02166         {
02167             return false;
02168         }
02169     return true;
02170 }
02171 
02172 void KWTableFrameSet::finalize( ) {
02173     kdDebug(32004) << "KWTableFrameSet::finalize" << endl;
02174 
02175     for (TableIter cells(this) ; cells ; ++cells)
02176     {
02177         position( cells );
02178         cells->finalize();
02179     }
02180 
02181     recalcCols(0, 0);
02182     recalcRows(0, 0);
02183     KWFrameSet::finalize();
02184 }
02185 
02186 void KWTableFrameSet::layout()
02187 {
02188     for (TableIter cells(this) ; cells ; ++cells)
02189         cells->layout();
02190 }
02191 
02192 void KWTableFrameSet::invalidate()
02193 {
02194     for (TableIter cells(this) ; cells ; ++cells)
02195         cells->invalidate();
02196 }
02197 
02198 void KWTableFrameSet::setVisible( bool v )
02199 {
02200     for (TableIter cells(this) ; cells ; ++cells)
02201         cells->setVisible( v );
02202 
02203     KWFrameSet::setVisible( v );
02204 }
02205 
02206 bool KWTableFrameSet::canRemovePage( int num ) {
02207     /*  This one is a lot simpler then the one it overrides, we simply don't have
02208         to check if the frame contains something, the simple existence of a frame
02209         is enough
02210     */
02211     QPtrListIterator<KWFrame> frameIt( frameIterator() );
02212     for ( ; frameIt.current(); ++frameIt ) {
02213         if ( frameIt.current()->pageNumber() == num ) {
02214             return false;
02215         }
02216     }
02217     return true;
02218 }
02219 
02220 void KWTableFrameSet::addTextFrameSets( QPtrList<KWTextFrameSet> & lst, bool onlyReadWrite )
02221 {
02222     for (TableIter cells(this) ; cells ; ++cells)
02223         if (!cells->textObject()->protectContent() || onlyReadWrite )
02224             lst.append(cells);
02225 }
02226 
02227 KWTextFrameSet* KWTableFrameSet::nextTextObject( KWFrameSet *obj )
02228 {
02229     bool found = false;
02230     KWTableFrameSet::Cell *tmp = dynamic_cast<KWTableFrameSet::Cell *>(obj);
02231 
02232     // make sure we have this cell
02233     if ( tmp ) {
02234         for(TableIter i(this); i; ++i) {
02235             if(i.current() == tmp) {
02236                 found = true;
02237                 break;
02238             }
02239         }
02240     }
02241 
02242     TableIter iter(this);
02243     if(found)
02244         iter.goToCell(tmp);
02245 
02246     for(; iter; ++iter) {
02247         KWTextFrameSet *newFrm = iter->nextTextObject( obj );
02248         if(newFrm && newFrm->textObject()->needSpellCheck())
02249             return newFrm;
02250     }
02251 
02252     return 0L;
02253 }
02254 
02255 void KWTableFrameSet::setZOrder()
02256 {
02257     for( TableIter cells(this) ; cells ; ++cells ) {
02258         cells->setZOrder();
02259     }
02260 
02261 }
02262 
02263 // TODO provide toPlainText() (reimplemented from KWFrameSet)
02264 
02265 QByteArray KWTableFrameSet::convertTableToText() // should be const, but TableIter doesn't allow it
02266 {
02267     KWOasisSaver oasisSaver( m_doc );
02268     for (TableIter cells(this); cells; ++cells)
02269     {
02270         cells->textObject()->saveOasisContent( oasisSaver.bodyWriter(), oasisSaver.savingContext() );
02271     }
02272     if ( !oasisSaver.finish() )
02273         return QByteArray();
02274     return oasisSaver.data();
02275 }
02276 
02277 #ifndef NDEBUG
02278 void KWTableFrameSet::printDebug( KWFrame * theFrame )
02279 {
02280     KWTableFrameSet::Cell *daCell = dynamic_cast<KWTableFrameSet::Cell *>( theFrame->frameSet() );
02281     Q_ASSERT( daCell );
02282     if ( daCell ) {
02283         kdDebug(32004) << " |  |- row :" << daCell->firstRow() << endl;
02284         kdDebug(32004) << " |  |- col :" << daCell->firstColumn() << endl;
02285         kdDebug(32004) << " |  |- rows:" << daCell->rowSpan() << endl;
02286         kdDebug(32004) << " |  +- cols:" << daCell->columnSpan() << endl;
02287     }
02288 }
02289 
02290 void KWTableFrameSet::printArrayDebug() {
02291     kdDebug(32004) << " |  Row/Cell arrays" << endl;
02292     Q_ASSERT( m_rows == m_rowArray.size() );
02293     for ( unsigned int row = 0; row < m_rows; ++row )  {
02294         QString str = QString( " | Row %1: " ).arg( row );
02295         for ( unsigned int col = 0; col < getColumns(); ++col )
02296             str += QString("| 0x%1 ").arg( (unsigned long)(*m_rowArray[row])[col], 0, 16 );
02297         kdDebug(32004) << str<< " |" << endl;
02298     }
02299 }
02300 
02301 void KWTableFrameSet::printDebug() {
02302     kdDebug(32004) << " |  Table size (" << m_rows << "x" << getColumns() << ")" << endl;
02303     kdDebug(32004) << " |  col  " << 0 << ": " << m_colPositions[0] << endl;
02304     for(unsigned int i=1;i<m_colPositions.count(); ++i)
02305         kdDebug(32004) << " |    |  " << i << ": " << m_colPositions[i] << endl;
02306     kdDebug(32004) << " |  row  " << 0 << ": " << m_rowPositions[0] << endl;
02307     for(unsigned int i=1;i<m_rowPositions.count(); ++i)
02308         kdDebug(32004) << " |    |  " << i << ": " << m_rowPositions[i] << endl;
02309 
02310     printArrayDebug();
02311     KWFrameSet::printDebug();
02312 }
02313 
02314 #endif
02315 
02316 // ===
02317 
02318 KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, unsigned int row, unsigned int col, const QString &/*name*/ ) :
02319     KWTextFrameSet( table->m_doc,
02320                     // Generate frameset name from table_name+row+col
02321                     i18n("Hello dear translator :), 1 is the table name, 2 and 3 are row and column", "%1 Cell %2,%3")
02322                     .arg( table->name() ).arg(row).arg(col) )
02323 {
02324     m_row = row;
02325     m_col = col;
02326     m_rows = 1;
02327     m_cols = 1;
02328     m_isJoinedCell = false;
02329     setGroupManager( table );
02330     table->addCell( this );
02331 }
02332 
02333 KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, const Cell &original ) :
02334     KWTextFrameSet( table->m_doc, original.m_name+'_' )
02335 {
02336     m_row = original.m_row;
02337     m_col = original.m_col;
02338     m_rows = original.m_rows;
02339     m_cols = original.m_cols;
02340     m_isJoinedCell = original.m_isJoinedCell;
02341     setGroupManager( table );
02342     table->addCell( this );
02343 }
02344 
02345 KWTableFrameSet::Cell::~Cell()
02346 {
02347 }
02348 
02349 bool KWTableFrameSet::Cell::isAboveOrLeftOf( unsigned row, unsigned col ) const
02350 {
02351     return ( m_row < row ) || ( ( m_row == row ) && ( m_col < col ) );
02352 }
02353 
02354 bool KWTableFrameSet::Cell::containsCell( unsigned row, unsigned col ) const
02355 {
02356     return ( m_row <= row &&
02357              m_col <= col &&
02358              rowAfter() > row &&
02359              columnAfter() > col );
02360 }
02361 
02362 void KWTableFrameSet::Cell::addFrame(KWFrame *_frame, bool recalc) {
02363     if(groupmanager())
02364         groupmanager()->addFrame(_frame, recalc);
02365     KWTextFrameSet::addFrame(_frame, recalc);
02366 }
02367 
02368 void KWTableFrameSet::Cell::frameDeleted( KWFrame* frm, bool recalc )
02369 {
02370     if(groupmanager())
02371         groupmanager()->deleteFrame( frm, false, recalc );
02372 }
02373 
02374 double KWTableFrameSet::Cell::leftBorder() {
02375     double b = frame(0)->leftBorder().width();
02376     if(b==0.0)
02377         return 0.0;
02378     if(m_col==0) // left most cell
02379         return b;
02380     return (b / 2);
02381 }
02382 
02383 double KWTableFrameSet::Cell::rightBorder() {
02384     double b=frame(0)->rightBorder().width();
02385     if(b==0.0)
02386         return 0.0;
02387     if(m_col+m_cols==m_groupmanager->getColumns()) // right most cell
02388         return b;
02389     return (b / 2);
02390 }
02391 
02392 double KWTableFrameSet::Cell::topBorder() {
02393     double b = frame(0)->topBorder().width();
02394     if(b==0.0)
02395         return 0.0;
02396     if(m_row==0) // top most cell
02397         return b;
02398     return (b / 2);
02399 }
02400 
02401 double KWTableFrameSet::Cell::bottomBorder() {
02402     double b = frame(0)->bottomBorder().width();
02403     if(b==0.0)
02404         return 0.0;
02405     if(rowAfter() == m_groupmanager->m_rows) // bottom most cell
02406         return b;
02407     return (b / 2);
02408 }
02409 
02410 void KWTableFrameSet::Cell::setLeftBorder(KoBorder newBorder) {
02411     KWFrame *f = frame(0);
02412     double diff = f->leftBorder().width() - newBorder.width();
02413     f->setLeftBorder(newBorder);
02414 
02415     if((diff > 0.01 || diff < -0.01) && m_col!=0) {
02416         diff = diff / 2; // if not outer edge only use halve
02417         m_groupmanager->cell(m_row, m_col-1)->setRightBorder(newBorder);
02418     }
02419     f->setLeft(f->left() - diff);
02420 }
02421 
02422 void KWTableFrameSet::Cell::setRightBorder(KoBorder newBorder) {
02423     KWFrame *f = frame(0);
02424     double diff = f->rightBorder().width() - newBorder.width();
02425     f->setRightBorder(newBorder);
02426 
02427     if((diff > 0.01 || diff < -0.01) && m_col+m_cols!=m_groupmanager->getColumns()) {
02428         diff = diff / 2; // if not outer edge only use halve
02429         m_groupmanager->cell(m_row, m_col+1)->setLeftBorder(newBorder);
02430     }
02431     f->setRight(f->right() + diff);
02432 }
02433 
02434 void KWTableFrameSet::Cell::setTopBorder(KoBorder newBorder) {
02435     KWFrame *f = frame(0);
02436     double diff = f->topBorder().width() - newBorder.width();
02437     f->setTopBorder(newBorder);
02438 
02439     if((diff > 0.01 || diff < -0.01) && m_row!=0) {
02440         diff = diff / 2; // if not outer edge only use halve
02441         m_groupmanager->cell(m_row-1, m_col)->setBottomBorder(newBorder);
02442     }
02443     f->setTop(f->top() - diff);
02444 }
02445 
02446 void KWTableFrameSet::Cell::setBottomBorder(KoBorder newBorder) {
02447     KWFrame *f = frame(0);
02448     double diff = f->bottomBorder().width() - newBorder.width();
02449     f->setBottomBorder(newBorder);
02450 
02451     if((diff > 0.01 || diff < -0.01) && rowAfter() != m_groupmanager->m_rows) {
02452         diff = diff / 2; // if not outer edge only use halve
02453         m_groupmanager->cell(m_row+1, m_col)->setTopBorder(newBorder);
02454     }
02455     f->setBottom(f->bottom() + diff);
02456 }
02457 
02458 void KWTableFrameSet::Cell::setZOrder()
02459 {
02460     QPtrListIterator<KWFrame> frameIt = frameIterator();
02461     for ( ; frameIt.current(); ++frameIt )
02462     {
02463         (*frameIt)->setZOrder( kWordDocument()->maxZOrder( (*frameIt)->pageNumber() ) + 1 );
02464     }
02465 }
02466 
02467 void KWTableFrameSet::Cell::drawContents( QPainter * painter, const QRect & crect,
02468         const QColorGroup & cg, bool onlyChanged, bool resetChanged,
02469         KWFrameSetEdit * edit, KWViewMode * viewMode, KWFrameViewManager *fvm )
02470 {
02471     bool printing = painter->device()->devType() == QInternal::Printer;
02472     bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
02473     QRect cellRect = crect;
02474     if(!printing && drawPreviewLines) {
02475         // Make sure the clipping is changed so the preview lines (frame borders) are not overwritten.
02476         QRect zoomedRect( m_doc->zoomRect(*frame(0)) );
02477         QRect innerFrameRect( viewMode->normalToView( zoomedRect ) );
02478         innerFrameRect.addCoords(1, 1, -1, -1); // move and shrink
02479         cellRect = innerFrameRect.intersect(crect);
02480     }
02481     KWTextFrameSet::drawContents(painter, cellRect, cg, onlyChanged, resetChanged, edit, viewMode, fvm);
02482 }
02483 
02484 KWTableFrameSetEdit::~KWTableFrameSetEdit()
02485 {
02486     if ( m_currentCell )
02487         m_currentCell->terminate();
02488     delete m_currentCell;
02489 }
02490 
02491 void KWTableFrameSetEdit::mousePressEvent( QMouseEvent * e, const QPoint & nPoint, const KoPoint & dPoint )
02492 {
02493     setCurrentCell( dPoint );
02494     if ( m_currentCell )
02495         m_currentCell->mousePressEvent( e, nPoint, dPoint );
02496 }
02497 
02498 void KWTableFrameSetEdit::setCurrentCell( const KoPoint & dPoint )
02499 {
02500     KWFrameSet *fs = tableFrameSet()->cellByPos( dPoint.x(), dPoint.y() );
02501     KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(fs);
02502 
02503     if ( textframeSet&& textframeSet->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
02504         return;
02505 
02506     if ( fs && ( !m_currentCell || fs != m_currentCell->frameSet() ) )
02507         setCurrentCell( fs );
02508 }
02509 
02510 void KWTableFrameSetEdit::setCurrentCell( KWFrameSet * fs, bool eraseSelection )
02511 {
02512     bool oldProtectContent = false;
02513     KWTextFrameSet *textframeSet=0L;
02514     if ( m_currentCell )
02515         textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
02516     if ( textframeSet )
02517         oldProtectContent = textframeSet->protectContent();
02518 
02519     if ( m_currentCell )
02520     {
02521         m_currentCell->terminate(eraseSelection);
02522         delete m_currentCell;
02523     }
02524     m_currentCell = fs->createFrameSetEdit( m_canvas );
02525     textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
02526     if ( textframeSet )
02527     {
02528         if ( oldProtectContent != textframeSet->protectContent())
02529         {
02530             m_canvas->kWordDocument()->updateTextFrameSetEdit();
02531         }
02532     }
02533 
02534 
02535     m_currentFrame = fs->frame( 0 );
02536     KWTextFrameSetEdit *textframeSetEdit = dynamic_cast<KWTextFrameSetEdit *>(m_currentCell);
02537     if ( textframeSetEdit )
02538     {
02539         textframeSetEdit->ensureCursorVisible();
02540         //refresh koruler
02541         m_canvas->gui()->getView()->slotUpdateRuler();
02542     }
02543 }
02544 
02545 KWFrameSetEdit* KWTableFrameSetEdit::currentTextEdit()
02546 {
02547     return m_currentCell;
02548 }
02549 
02550 
02551 void KWTableFrameSetEdit::keyPressEvent( QKeyEvent * e )
02552 {
02553     // This method handles the up/left/down/right navigation keys in tables
02554     if ( !m_currentCell )
02555         return;
02556     KWTableFrameSet::Cell *cell = static_cast<KWTableFrameSet::Cell *>(m_currentCell->frameSet());
02557     KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
02558     bool moveToOtherCell = true;
02559     if(textframeSet)
02560     {
02561         // don't move to an adjacent cell when we are selecting text
02562         KoTextDocument * textdoc = textframeSet->textDocument();
02563         if(textdoc->hasSelection( KoTextDocument::Standard ))
02564             moveToOtherCell=false;
02565     }
02566     KWTableFrameSet::Cell *fs = 0L;
02567 
02568     bool tab=false; // No tab key pressed
02569     if(moveToOtherCell)
02570     {
02571         switch( e->key() ) {
02572             case QKeyEvent::Qt::Key_Up:
02573             {
02574                 if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->prev())
02575                 {
02576                     KWTableFrameSet* tableFrame=tableFrameSet();
02577                     int row = cell->firstRow() - 1;
02578                     int col = cell->firstColumn();
02579                     if (row < 0) {  // Wrap at top of table
02580                         col--; // Goes to column on the left
02581                         row = tableFrame->getRows() - 1;
02582                     }
02583                     if (col < 0) { // It was the first column
02584                         // Maybe exit the table instead?
02585                         col = tableFrame->getColumns() - 1;
02586                         row = tableFrame->getRows() - 1;
02587                     }
02588                     fs=tableFrame->cell(row,col);
02589                     // Not needed. cell gives us the right one already
02590                     //if (fs && fs->firstRow() != static_cast<unsigned int>(row)) { // Merged cell
02591                     //    fs=tableFrame->cell( row - fs->rowSpan() + 1, col );
02592                     //}
02593                 }
02594             }
02595             break;
02596             case QKeyEvent::Qt::Key_Down:
02597             {
02598                 if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->next())
02599                 {
02600                     KWTableFrameSet* tableFrame=tableFrameSet();
02601                     unsigned int row = cell->rowAfter();
02602                     unsigned int col = cell->firstColumn();
02603                     if(row >= tableFrame->getRows()) { // Wrap at bottom of table
02604                         row=0;
02605                         col++; // Go to next column
02606                     }
02607                     if(col >= tableFrame->getColumns()) { // It was the last one
02608                         // Maybe exit the table instead?
02609                         col=0;
02610                         row=0;
02611                     }
02612                     fs=tableFrame->cell(row,col);
02613                     Q_ASSERT( fs );
02614                     Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
02615                 }
02616             }
02617             break;
02618             case QKeyEvent::Qt::Key_Backtab:
02619                 tab=true;
02620                 if (e->state() & QKeyEvent::ControlButton)
02621                     break; // Break if tab was pressed with Control (in *any* key combination)
02622                 // Do not break
02623             case QKeyEvent::Qt::Key_Left:
02624             {
02625                 KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
02626                 if ( tab || (!cur->parag()->prev()&&cur->index()==0) )
02627                 {
02628                     KWTableFrameSet* tableFrame=tableFrameSet();
02629                     int row=cell->firstRow();
02630                     int col=cell->firstColumn() - 1;
02631                     if(col < 0) { // Wrap at first column
02632                         col = (int)tableFrame->getColumns()-1;
02633                         row--; // Go up
02634                     }
02635                     if(row < 0) { // It was the first row
02636                         // Maybe exit the table instead?
02637                         col = (int)tableFrame->getColumns()-1;
02638                         row = (int)tableFrame->getRows()-1;
02639                     }
02640                     fs=tableFrame->cell(row,col);
02641                     // Not needed. cell gives us the right one already
02642                     //if(fs && (int)fs->m_col != col) { // Merged cell
02643                     //    fs=tableFrame->cell( row, col - fs->columnSpan() + 1 );
02644                     //}
02645                 }
02646             }
02647             break;
02648             case QKeyEvent::Qt::Key_Tab:
02649                 tab=true;
02650                 if (e->state() & QKeyEvent::ControlButton)
02651                     break; // Break if tab was pressed with Control (in *any* key combination)
02652                 // Do not break
02653             case QKeyEvent::Qt::Key_Right:
02654             {
02655                 KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
02656                 if( tab || (!cur->parag()->next()&&cur->index()==cur->parag()->string()->length()-1) )
02657                 {
02658                     KWTableFrameSet* tableFrame=tableFrameSet();
02659                     unsigned int row = cell->firstRow();
02660                     unsigned int col = cell->columnAfter();
02661                     if(col >= tableFrame->getColumns()) { // Wrap after last column
02662                         col = 0;
02663                         row++; // Go down one row
02664                     }
02665                     if(row >= tableFrame->getRows()) { // It was the last row
02666                         // Maybe exit the table instead?
02667                         col = 0;
02668                         row = 0;
02669                     }
02670                     fs=tableFrame->cell(row,col);
02671                     Q_ASSERT( fs );
02672                     Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
02673                 }
02674             }
02675             break;
02676         }
02677     }
02678     if ( fs )
02679     {
02680         //don't switch to a protected cell protected when cursor in protected areas was disabled.
02681         if ( fs->textObject()->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
02682             return;
02683         setCurrentCell( fs );
02684     }
02685     else if ( textframeSet )
02686     {
02687         if ( !textframeSet->textObject()->protectContent() )
02688         {
02689             if (tab && (e->state() & QKeyEvent::ControlButton) )
02690             {
02691                 QKeyEvent event(QEvent::KeyPress, QKeyEvent::Qt::Key_Tab, 9, 0, QChar(9));
02692                 m_currentCell->keyPressEvent( &event );
02693             }
02694             else
02695                 m_currentCell->keyPressEvent( e );
02696         }
02697         else if(e->text().length() > 0)
02698             KMessageBox::information(0L, i18n("Read-only content cannot be changed. No modifications will be accepted."));
02699     }
02700 }
02701 
02702 void KWTableFrameSetEdit::keyReleaseEvent( QKeyEvent * e )
02703 {
02704     if ( m_currentCell )
02705         m_currentCell->keyReleaseEvent( e );
02706 }
02707 
02708 void KWTableFrameSetEdit::imStartEvent( QIMEvent* e )
02709 {
02710     if ( m_currentCell )
02711         m_currentCell->imStartEvent( e );
02712 }
02713 
02714 void KWTableFrameSetEdit::imComposeEvent( QIMEvent* e )
02715 {
02716     if ( m_currentCell )
02717         m_currentCell->imComposeEvent( e );
02718 }
02719 
02720 void KWTableFrameSetEdit::imEndEvent( QIMEvent* e )
02721 {
02722     if ( m_currentCell )
02723         m_currentCell->imEndEvent( e );
02724 }
02725 
02726 void KWTableFrameSetEdit::dragMoveEvent( QDragMoveEvent * e, const QPoint &n, const KoPoint &d )
02727 {
02728     kdDebug(32004)<<"m_currentCell :"<<m_currentCell<<endl;
02729     if ( m_currentCell )
02730     {
02731         KWFrameSet *fs = tableFrameSet()->cellByPos( d.x(), d.y() );
02732         kdDebug(32004)<<"fs :"<<fs <<endl;
02733         if(fs && fs != m_currentCell->frameSet())
02734             setCurrentCell(fs, false);
02735         if(m_currentCell)
02736             m_currentCell->dragMoveEvent( e, n, d );
02737     }
02738     else
02739     {
02740         setCurrentCell( d );
02741         kdDebug(32004)<<"after m_currentCell :"<<m_currentCell<<endl;
02742         if(m_currentCell)
02743             m_currentCell->dragMoveEvent( e, n, d );
02744     }
02745 }
02746 
02747 void KWTableFrameSet::Row::addCell( Cell *cell )
02748 {
02749     if ( m_cellArray.size() < cell->columnAfter())
02750         m_cellArray.resize( cell->columnAfter() );
02751     for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
02752         m_cellArray.insert( col, cell );
02753 }
02754 
02755 void KWTableFrameSet::Row::removeCell( Cell* cell )
02756 {
02757     for ( uint col = cell->firstColumn() ; col <  cell->columnAfter(); ++col )
02758         m_cellArray.remove( col );
02759 }
02760 
02761 template<>
02762 KWTableFrameSet::Cell*
02763 KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_CELL>::operator++()
02764 {
02765     if(!m_cell) return 0;
02766 
02767     Cell *ret = m_cell;
02768 
02769     do{
02770         // check for end of row first
02771         if(m_table->cell(m_row,m_col)->lastColumn() >= m_limit[RIGHT] ) {
02772             // now check for end of column
02773             if (m_row >= m_limit[LOW]){
02774                 // at end of traversal
02775                 m_cell = 0;
02776                 break;
02777             }
02778             else {
02779                 // goto first grid position in next row
02780                 m_row += 1;
02781                 m_col = m_limit[LEFT];
02782             }
02783         }
02784         else {
02785             // goto next cell in row
02786             m_col = m_table->cell(m_row, m_col)->columnAfter();
02787         }
02788 
02789         m_cell = m_table->cell(m_row,m_col);
02790     } while( m_cell && !m_cell->isFirstGridPosnFast(m_row,m_col) );
02791 
02792     return ret;
02793 }
02794 
02795 template<>
02796 KWTableFrameSet::Cell*
02797 KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_GRID>::operator++()
02798 {
02799     if(!m_cell) return 0;
02800 
02801     Cell *ret = m_cell;
02802     // check for end of row
02803     if(m_col == m_limit[RIGHT]) {
02804         if(m_row == m_limit[LOW]) { // end of traversal
02805             m_row = 0;
02806             m_col = 0;
02807             m_cell = 0;
02808         }
02809         else { // go to next row
02810             m_row += 1;
02811             m_col = m_limit[LEFT];
02812             m_cell = m_table->cell(m_row, m_col);
02813         }
02814     }
02815     else { // move to next cell in row
02816         m_col += 1;
02817         m_cell = m_table->cell(m_row, m_col);
02818     }
02819 
02820     return ret;
02821 }
02822 
02823 KWTableFrameSet::MarkedIterator::MarkedIterator(KWTableFrameSet *table) :
02824     GridIter(table)
02825 {
02826     // clear all the cell marks
02827     for(GridIter cell(table); cell; ++cell)
02828         cell->clearMark();
02829 
02830     if ( current() ) {
02831 //      kdDebug() << "MarkedIterator: visit: "
02832 //          << QString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
02833         current()->setMark();
02834     }
02835 }
02836 
02837 KWTableFrameSet::Cell *
02838 KWTableFrameSet::MarkedIterator::operator++()
02839 {
02840     Cell *ret = GridIter::operator++();
02841 
02842     while ( current() && current()->marked() ) {
02843         GridIter::operator++();
02844     }
02845     if ( current() ) {
02846 //      kdDebug() << "MarkedIterator: visit: "
02847 //          << QString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
02848         current()->setMark();
02849     }
02850     return ret;
02851 }
02852 
02853 template<>
02854 KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::TableIterator(KWTableFrameSet *table):
02855     m_table(table)
02856 {
02857     Q_ASSERT(m_table);
02858     set_limits(0, (int)m_table->getColumns() - 1, 0, (int)m_table->getRows() - 1);
02859 
02860     Cell *c = 0;
02861     for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
02862         for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
02863 
02864             c = m_table->cell(i,j);
02865             if(c) c->clearMark();
02866         }
02867     toFirstCell();
02868 }
02869 
02870 template<>
02871 KWTableFrameSet::Cell*
02872 KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::operator++ ()
02873 {
02874 
02875     Cell *ret = m_cell;
02876     if(!ret) return 0;
02877 
02878     ret->setMark();
02879     m_cell = 0;
02880     uint i = m_row; uint j = m_col;
02881 
02882     for(; i <= m_limit[LOW]; ++i) {
02883 
02884         for(j = 0; j <= m_limit[RIGHT]; ++j) {
02885             m_cell = m_table->cell(i,j);
02886             if( m_cell && !m_cell->marked() ){
02887                 m_row = i; m_col = j;
02888                 goto out;
02889             }
02890             else if(i == m_limit[LOW] && j == m_limit[RIGHT]){
02891                 m_cell = 0;
02892                 goto out;
02893             }
02894         }
02895     }
02896 
02897     out:
02898     return ret;
02899 }
02900 
02901 template<>
02902 KWTableFrameSet::Cell*
02903 KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::toFirstCell ()
02904 {
02905     m_cell = 0;
02906     for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
02907         for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
02908             m_cell = m_table->cell(i,j);
02909             if(m_cell) {
02910                 m_row = i; m_col = j;
02911                 goto out;
02912             }
02913         }
02914 
02915     out:
02916     return m_cell;
02917 }
02918 
02919 RemovedRow::RemovedRow() :
02920     m_row(0), m_index(0), m_rowHeight(0.0)
02921 {
02922 
02923 }
02924 
02925 RemovedRow::~RemovedRow()
02926 {
02927     // free cells as well ???
02928     delete m_row;
02929 }
02930 
02931 KWTableFrameSet::Row *RemovedRow::takeRow()
02932 {
02933     Q_ASSERT(m_row);
02934     KWTableFrameSet::Row *ret = m_row;
02935     m_row = 0;
02936     return ret;
02937 }
02938 
02939 RemovedColumn::RemovedColumn()
02940     : m_column(), m_removed(), m_index(0), m_width(0), m_initialized(false){ }
02941 
02942 
02943 #include "KWTableFrameSet.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys