filters

tablehandler.cpp
1/* This file is part of the KOffice project
2 Copyright (C) 2002 Werner Trobin <trobin@kde.org>
3 Copyright (C) 2002 David Faure <faure@kde.org>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "tablehandler.h"
21
22#include <wv2/word97_generated.h>
23
24#include <kdebug.h>
25#include <KoRect.h>
26#include <tqtl.h>
27
28KWordTableHandler::KWordTableHandler()
29{
30 tableEnd();
31}
32
33// Called by Document before invoking the table-row-functors
34void KWordTableHandler::tableStart( KWord::Table* table )
35{
36 Q_ASSERT( table );
37 Q_ASSERT( !table->name.isEmpty() );
38 m_currentTable = table;
39 qHeapSort( table->m_cellEdges );
40#if 0
41 for (unsigned int i = 0; i < table->m_cellEdges.size(); i++)
42 kdDebug(30513) << table->m_cellEdges[i] << endl;
43#endif
44 m_row = -1;
45 m_currentY = 0;
46}
47
48void KWordTableHandler::tableEnd()
49{
50 m_currentTable = 0L; // we don't own it, the table-queue does!
51 m_row = -2;
52 m_column = -2;
53 // Warning: if doing more here, check that it's still ok to call this from the ctor
54}
55
56void KWordTableHandler::tableRowStart( wvWare::SharedPtr<const wvWare::Word97::TAP> tap )
57{
58 if ( m_row == -2 )
59 {
60 kdWarning(30513) << "tableRowStart: tableStart not called previously!" << endl;
61 return;
62 }
63 Q_ASSERT( m_currentTable );
64 Q_ASSERT( !m_currentTable->name.isEmpty() );
65 m_row++;
66 m_column = -1;
67 m_tap = tap;
68 kdDebug(30513) << "tableRowStart row=" << m_row << endl;
69}
70
71void KWordTableHandler::tableRowEnd()
72{
73 kdDebug(30513) << "tableRowEnd" << endl;
74 m_currentY += rowHeight();
75}
76
77void KWordTableHandler::tableCellStart()
78{
79 Q_ASSERT( m_tap );
80 if ( !m_tap )
81 return;
82 m_column++;
83 int nbCells = m_tap->itcMac;
84 Q_ASSERT( m_column < nbCells );
85 if ( m_column >= nbCells )
86 return;
87
88 // Get table cell descriptor
89 const wvWare::Word97::TC& tc = m_tap->rgtc[ m_column ];
90
91 int left = m_tap->rgdxaCenter[ m_column ]; // in DXAs
92 int right = m_tap->rgdxaCenter[ m_column+1 ]; // in DXAs
93
94 // Check for merged cells
95 // ## We can ignore that one. Our cell-edge magic is much more flexible.
96#if 0
97 int colSize = 1;
98 if ( tc.fFirstMerged )
99 {
100 // This cell is the first one of a series of merged cells ->
101 // we want to find out its size.
102 int i = m_column + 1;
103 while ( i < nbCells && m_tap->rgtc[ i ].fMerged && !m_tap->rgtc[i].fFirstMerged ) {
104 ++colSize;
105 ++i;
106 }
107 }
108#endif
109 int rowSpan = 1;
110 if ( tc.fVertRestart )
111 {
112 //kdDebug(30513) << "fVertRestart is set!" << endl;
113 // This cell is the first one of a series of vertically merged cells ->
114 // we want to find out its size.
115 TQValueList<KWord::Row>::Iterator it = m_currentTable->rows.at( m_row + 1 );
116 for( ; it != m_currentTable->rows.end(); ++it ) {
117 // Find cell right below us in row (*it), if any
118 KWord::TAPptr tapBelow = (*it).tap;
119 const wvWare::Word97::TC* tcBelow = 0L;
120 for ( int c = 0; !tcBelow && c < tapBelow->itcMac ; ++c )
121 {
122 if ( TQABS( tapBelow->rgdxaCenter[ c ] - left ) <= 3
123 && TQABS( tapBelow->rgdxaCenter[ c + 1 ] - right ) <= 3 ) {
124 tcBelow = &tapBelow->rgtc[ c ];
125 //kdDebug(30513) << "found cell below, at (Word) column " << c << " fVertMerge:" << tcBelow->fVertMerge << endl;
126 }
127 }
128 if ( tcBelow && tcBelow->fVertMerge && !tcBelow->fVertRestart )
129 ++rowSpan;
130 else
131 break;
132 }
133 //kdDebug(30513) << "rowSpan=" << rowSpan << endl;
134 }
135 // Skip cells that are part of a vertically merged cell, KWord doesn't want them
136 // The MSWord spec says they must be empty anyway (and we'll get a warning if not).
137 if ( tc.fVertMerge && !tc.fVertRestart )
138 return;
139
140 // Check how many cells that mean, according to our cell edge array
141 int leftCellNumber = m_currentTable->columnNumber( left );
142 int rightCellNumber = m_currentTable->columnNumber( right );
143
144 // In cases where not all columns are present, ensure that the last
145 // column spans the remainder of the table.
146 // ### It would actually be more closer to the original if we created
147 // an empty cell from m_column+1 to the last column. (table-6.doc)
148 if ( m_column == nbCells - 1 ) {
149 rightCellNumber = m_currentTable->m_cellEdges.size() - 1;
150 right = m_currentTable->m_cellEdges[ rightCellNumber ];
151 }
152
153 Q_ASSERT( rightCellNumber >= leftCellNumber ); // you'd better be...
154 int colSpan = rightCellNumber - leftCellNumber; // the resulting number of merged cells
155
156 KoRect cellRect( left / 20.0, // left
157 m_currentY, // top
158 ( right - left ) / 20.0, // width
159 rowHeight() ); // height
160
161 kdDebug(30513) << " tableCellStart row=" << m_row << " WordColumn=" << m_column << " colSpan=" << colSpan << " (from " << leftCellNumber << " to " << rightCellNumber << " for KWord) rowSpan=" << rowSpan << " cellRect=" << cellRect << endl;
162
163 // Sort out the borders.
164 // It seems we get this on the cells that are adjacent
165 // to one has a border, as if it means "whatever the adjacent cell on this border
166 // specifies". (cf table-22.doc)
167 // We need to set the adjacent cell's border instead, in that case.
168 // ### No idea how to do it properly for top/bottom though. The cell above might not have the same size...
169 const wvWare::Word97::BRC& brcTop = tc.brcTop;
170 const wvWare::Word97::BRC& brcBottom = tc.brcBottom;
171 const wvWare::Word97::BRC& brcLeft =
172 ( tc.brcLeft.cv == 255 && tc.brcLeft.dptLineWidth == 255 && m_column > 0 ) ?
173 m_tap->rgtc[ m_column - 1 ].brcRight
174 : tc.brcLeft;
175 const wvWare::Word97::BRC& brcRight =
176 ( tc.brcRight.cv == 255 && tc.brcRight.dptLineWidth == 255 && m_column < nbCells - 1 ) ?
177 m_tap->rgtc[ m_column + 1 ].brcLeft
178 : tc.brcRight;
179
180 emit sigTableCellStart( m_row, leftCellNumber, rowSpan, colSpan, cellRect, m_currentTable->name, brcTop, brcBottom, brcLeft, brcRight, m_tap->rgshd[ m_column ] );
181}
182
183void KWordTableHandler::tableCellEnd()
184{
185 kdDebug(30513) << " tableCellEnd" << endl;
186 emit sigTableCellEnd();
187}
188
189
190// Add cell edge into the cache of cell edges for a given table.
191void KWord::Table::cacheCellEdge(int cellEdge)
192{
193 uint size = m_cellEdges.size();
194 // Do we already know about this edge?
195 for (unsigned int i = 0; i < size; i++)
196 {
197 if (m_cellEdges[i] == cellEdge) {
198 kdDebug(30513) << k_funcinfo << cellEdge << " -> found" << endl;
199 return;
200 }
201 }
202
203 // Add the edge to the array.
204 m_cellEdges.resize(size + 1, TQGArray::SpeedOptim);
205 m_cellEdges[size] = cellEdge;
206 kdDebug(30513) << k_funcinfo << cellEdge << " -> added. Size=" << size+1 << endl;
207}
208
209// Lookup a cell edge from the cache of cell edges
210// And return the column number
211int KWord::Table::columnNumber(int cellEdge) const
212{
213 for (unsigned int i = 0; i < m_cellEdges.size(); i++)
214 {
215 if (m_cellEdges[i] == cellEdge)
216 return i;
217 }
218 // This can't happen, if cacheCellEdge has been properly called
219 kdWarning(30513) << "Column not found for cellEdge x=" << cellEdge << " - BUG." << endl;
220 return 0;
221}
222
223double KWordTableHandler::rowHeight() const
224{
225 return TQMAX( m_tap->dyaRowHeight / 20.0, 20);
226}
227
228#include "tablehandler.moc"