filters

tablehandler.cpp

00001 /* This file is part of the KOffice project
00002    Copyright (C) 2002 Werner Trobin <trobin@kde.org>
00003    Copyright (C) 2002 David Faure <faure@kde.org>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; see the file COPYING.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "tablehandler.h"
00021 
00022 #include <wv2/word97_generated.h>
00023 
00024 #include <kdebug.h>
00025 #include <KoRect.h>
00026 #include <qtl.h>
00027 
00028 KWordTableHandler::KWordTableHandler()
00029 {
00030     tableEnd();
00031 }
00032 
00033 // Called by Document before invoking the table-row-functors
00034 void KWordTableHandler::tableStart( KWord::Table* table )
00035 {
00036     Q_ASSERT( table );
00037     Q_ASSERT( !table->name.isEmpty() );
00038     m_currentTable = table;
00039     qHeapSort( table->m_cellEdges );
00040 #if 0
00041     for (unsigned int i = 0; i < table->m_cellEdges.size(); i++)
00042         kdDebug(30513) << table->m_cellEdges[i] << endl;
00043 #endif
00044     m_row = -1;
00045     m_currentY = 0;
00046 }
00047 
00048 void KWordTableHandler::tableEnd()
00049 {
00050     m_currentTable = 0L; // we don't own it, the table-queue does!
00051     m_row = -2;
00052     m_column = -2;
00053     // Warning: if doing more here, check that it's still ok to call this from the ctor
00054 }
00055 
00056 void KWordTableHandler::tableRowStart( wvWare::SharedPtr<const wvWare::Word97::TAP> tap )
00057 {
00058     if ( m_row == -2 )
00059     {
00060         kdWarning(30513) << "tableRowStart: tableStart not called previously!" << endl;
00061         return;
00062     }
00063     Q_ASSERT( m_currentTable );
00064     Q_ASSERT( !m_currentTable->name.isEmpty() );
00065     m_row++;
00066     m_column = -1;
00067     m_tap = tap;
00068     kdDebug(30513) << "tableRowStart row=" << m_row << endl;
00069 }
00070 
00071 void KWordTableHandler::tableRowEnd()
00072 {
00073     kdDebug(30513) << "tableRowEnd" << endl;
00074     m_currentY += rowHeight();
00075 }
00076 
00077 void KWordTableHandler::tableCellStart()
00078 {
00079     Q_ASSERT( m_tap );
00080     if ( !m_tap )
00081         return;
00082     m_column++;
00083     int nbCells = m_tap->itcMac;
00084     Q_ASSERT( m_column < nbCells );
00085     if ( m_column >= nbCells )
00086         return;
00087 
00088     // Get table cell descriptor
00089     const wvWare::Word97::TC& tc = m_tap->rgtc[ m_column ];
00090 
00091     int left = m_tap->rgdxaCenter[ m_column ]; // in DXAs
00092     int right = m_tap->rgdxaCenter[ m_column+1 ]; // in DXAs
00093 
00094     // Check for merged cells
00095     // ## We can ignore that one. Our cell-edge magic is much more flexible.
00096 #if 0
00097     int colSize = 1;
00098     if ( tc.fFirstMerged )
00099     {
00100         // This cell is the first one of a series of merged cells ->
00101         // we want to find out its size.
00102         int i = m_column + 1;
00103         while ( i < nbCells && m_tap->rgtc[ i ].fMerged && !m_tap->rgtc[i].fFirstMerged ) {
00104             ++colSize;
00105             ++i;
00106         }
00107     }
00108 #endif
00109     int rowSpan = 1;
00110     if ( tc.fVertRestart )
00111     {
00112         //kdDebug(30513) << "fVertRestart is set!" << endl;
00113         // This cell is the first one of a series of vertically merged cells ->
00114         // we want to find out its size.
00115         QValueList<KWord::Row>::Iterator it = m_currentTable->rows.at( m_row + 1 );
00116         for( ; it != m_currentTable->rows.end(); ++it )  {
00117             // Find cell right below us in row (*it), if any
00118             KWord::TAPptr tapBelow = (*it).tap;
00119             const wvWare::Word97::TC* tcBelow = 0L;
00120             for ( int c = 0; !tcBelow && c < tapBelow->itcMac ; ++c )
00121             {
00122                  if ( QABS( tapBelow->rgdxaCenter[ c ] - left ) <= 3
00123                       && QABS( tapBelow->rgdxaCenter[ c + 1 ] - right ) <= 3 ) {
00124                      tcBelow = &tapBelow->rgtc[ c ];
00125                      //kdDebug(30513) << "found cell below, at (Word) column " << c << " fVertMerge:" << tcBelow->fVertMerge << endl;
00126                  }
00127             }
00128             if ( tcBelow && tcBelow->fVertMerge && !tcBelow->fVertRestart )
00129                 ++rowSpan;
00130             else
00131                 break;
00132         }
00133         //kdDebug(30513) << "rowSpan=" << rowSpan << endl;
00134     }
00135     // Skip cells that are part of a vertically merged cell, KWord doesn't want them
00136     // The MSWord spec says they must be empty anyway (and we'll get a warning if not).
00137     if ( tc.fVertMerge && !tc.fVertRestart )
00138         return;
00139 
00140     // Check how many cells that mean, according to our cell edge array
00141     int leftCellNumber = m_currentTable->columnNumber( left );
00142     int rightCellNumber = m_currentTable->columnNumber( right );
00143 
00144     // In cases where not all columns are present, ensure that the last
00145     // column spans the remainder of the table.
00146     // ### It would actually be more closer to the original if we created
00147     // an empty cell from m_column+1 to the last column. (table-6.doc)
00148     if ( m_column == nbCells - 1 )  {
00149         rightCellNumber = m_currentTable->m_cellEdges.size() - 1;
00150         right = m_currentTable->m_cellEdges[ rightCellNumber ];
00151     }
00152 
00153     Q_ASSERT( rightCellNumber >= leftCellNumber ); // you'd better be...
00154     int colSpan = rightCellNumber - leftCellNumber; // the resulting number of merged cells
00155 
00156     KoRect cellRect( left / 20.0, // left
00157                      m_currentY, // top
00158                      ( right - left ) / 20.0, // width
00159                      rowHeight() ); // height
00160 
00161     kdDebug(30513) << " tableCellStart row=" << m_row << " WordColumn=" << m_column << " colSpan=" << colSpan << " (from " << leftCellNumber << " to " << rightCellNumber << " for KWord) rowSpan=" << rowSpan << " cellRect=" << cellRect << endl;
00162 
00163     // Sort out the borders.
00164     // It seems we get this on the cells that are adjacent
00165     // to one has a border, as if it means "whatever the adjacent cell on this border
00166     // specifies". (cf table-22.doc)
00167     // We need to set the adjacent cell's border instead, in that case.
00168     // ### No idea how to do it properly for top/bottom though. The cell above might not have the same size...
00169     const wvWare::Word97::BRC& brcTop = tc.brcTop;
00170     const wvWare::Word97::BRC& brcBottom = tc.brcBottom;
00171     const wvWare::Word97::BRC& brcLeft =
00172      ( tc.brcLeft.ico == 255 && tc.brcLeft.dptLineWidth == 255 && m_column > 0 ) ?
00173         m_tap->rgtc[ m_column - 1 ].brcRight
00174         : tc.brcLeft;
00175     const wvWare::Word97::BRC& brcRight =
00176       ( tc.brcRight.ico == 255 && tc.brcRight.dptLineWidth == 255 && m_column < nbCells - 1 ) ?
00177         m_tap->rgtc[ m_column + 1 ].brcLeft
00178         : tc.brcRight;
00179 
00180     emit sigTableCellStart( m_row, leftCellNumber, rowSpan, colSpan, cellRect, m_currentTable->name, brcTop, brcBottom, brcLeft, brcRight, m_tap->rgshd[ m_column ] );
00181 }
00182 
00183 void KWordTableHandler::tableCellEnd()
00184 {
00185     kdDebug(30513) << " tableCellEnd" << endl;
00186     emit sigTableCellEnd();
00187 }
00188 
00189 
00190 // Add cell edge into the cache of cell edges for a given table.
00191 void KWord::Table::cacheCellEdge(int cellEdge)
00192 {
00193     uint size = m_cellEdges.size();
00194     // Do we already know about this edge?
00195     for (unsigned int i = 0; i < size; i++)
00196     {
00197         if (m_cellEdges[i] == cellEdge)  {
00198             kdDebug(30513) << k_funcinfo << cellEdge << " -> found" << endl;
00199             return;
00200         }
00201     }
00202 
00203     // Add the edge to the array.
00204     m_cellEdges.resize(size + 1, QGArray::SpeedOptim);
00205     m_cellEdges[size] = cellEdge;
00206     kdDebug(30513) << k_funcinfo << cellEdge << " -> added. Size=" << size+1 << endl;
00207 }
00208 
00209 // Lookup a cell edge from the cache of cell edges
00210 // And return the column number
00211 int KWord::Table::columnNumber(int cellEdge) const
00212 {
00213     for (unsigned int i = 0; i < m_cellEdges.size(); i++)
00214     {
00215         if (m_cellEdges[i] == cellEdge)
00216             return i;
00217     }
00218     // This can't happen, if cacheCellEdge has been properly called
00219     kdWarning(30513) << "Column not found for cellEdge x=" << cellEdge << " - BUG." << endl;
00220     return 0;
00221 }
00222 
00223 double KWordTableHandler::rowHeight() const
00224 {
00225     return QMAX( m_tap->dyaRowHeight / 20.0, 20);
00226 }
00227 
00228 #include "tablehandler.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys