]> git.saurik.com Git - wxWidgets.git/blame - src/html/m_tables.cpp
const consistent for Clone(). Load/Save split to DoLoad/DoSave. Build fixes, warning...
[wxWidgets.git] / src / html / m_tables.cpp
CommitLineData
5526e819 1/////////////////////////////////////////////////////////////////////////////
c88293a4 2// Name: m_tables.cpp
5526e819
VS
3// Purpose: wxHtml module for tables
4// Author: Vaclav Slavik
69941f05 5// RCS-ID: $Id$
5526e819 6// Copyright: (c) 1999 Vaclav Slavik
65571936 7// Licence: wxWindows licence
5526e819
VS
8/////////////////////////////////////////////////////////////////////////////
9
3096bd2f 10#include "wx/wxprec.h"
3364ab79 11
314260fb 12#include "wx/defs.h"
f6bcfd97 13#if wxUSE_HTML && wxUSE_STREAMS
2b5f62a0 14#ifdef __BORLANDC__
3364ab79
RS
15#pragma hdrstop
16#endif
17
18#ifndef WXPRECOMP
3364ab79
RS
19#endif
20
69941f05
VS
21#include "wx/html/forcelnk.h"
22#include "wx/html/m_templ.h"
5526e819 23
69941f05 24#include "wx/html/htmlcell.h"
5526e819 25
c88293a4 26FORCE_LINK_ME(m_tables)
5526e819
VS
27
28
29#define TABLE_BORDER_CLR_1 wxColour(0xC5, 0xC2, 0xC5)
30#define TABLE_BORDER_CLR_2 wxColour(0x62, 0x61, 0x62)
31
32
33//-----------------------------------------------------------------------------
34// wxHtmlTableCell
35//-----------------------------------------------------------------------------
36
37
79d6c018
VS
38struct colStruct
39{
40 int width, units;
41 // width of the column either in pixels or percents
42 // ('width' is the number, 'units' determines its meaning)
43 int minWidth, maxWidth;
44 // minimal/maximal column width. This is needed by HTML 4.0
45 // layouting algorithm and can be determined by trying to
46 // layout table cells with width=1 and width=infinity
47 int leftpos, pixwidth, maxrealwidth;
48 // temporary (depends on actual width of table)
49};
50
51enum cellState
52{
53 cellSpan,
54 cellUsed,
55 cellFree
56};
57
58struct cellStruct
59{
60 wxHtmlContainerCell *cont;
61 int colspan, rowspan;
62 int minheight, valign;
63 cellState flag;
ca16b7a9 64 bool nowrap;
79d6c018 65};
5526e819
VS
66
67
68class wxHtmlTableCell : public wxHtmlContainerCell
69{
79d6c018
VS
70protected:
71 /* These are real attributes: */
72
73 // should we draw borders or not?
74 bool m_HasBorders;
75 // number of columns; rows
76 int m_NumCols, m_NumRows;
77 // array of column information
78 colStruct *m_ColsInfo;
79 // 2D array of all cells in the table : m_CellInfo[row][column]
80 cellStruct **m_CellInfo;
81 // spaces between cells
82 int m_Spacing;
83 // cells internal indentation
84 int m_Padding;
85
86private:
87 /* ...and these are valid only when parsing the table: */
88
89 // number of actual column (ranging from 0..m_NumCols)
90 int m_ActualCol, m_ActualRow;
91
92 // default values (for table and row):
93 wxColour m_tBkg, m_rBkg;
94 wxString m_tValign, m_rValign;
95
96 double m_PixelScale;
97
98
99public:
100 wxHtmlTableCell(wxHtmlContainerCell *parent, const wxHtmlTag& tag, double pixel_scale = 1.0);
101 ~wxHtmlTableCell();
102 virtual void Layout(int w);
103
104 void AddRow(const wxHtmlTag& tag);
105 void AddCell(wxHtmlContainerCell *cell, const wxHtmlTag& tag);
106
107private:
108 // Reallocates memory to given number of cols/rows
109 // and changes m_NumCols/m_NumRows value to reflect this change
110 // NOTE! You CAN'T change m_NumCols/m_NumRows before calling this!!
111 void ReallocCols(int cols);
112 void ReallocRows(int rows);
113
114 // Computes minimal and maximal widths of columns. Needs to be called
25c71ccc 115 // only once, before first Layout().
79d6c018 116 void ComputeMinMaxWidths();
22f3361e
VZ
117
118 DECLARE_NO_COPY_CLASS(wxHtmlTableCell)
5526e819
VS
119};
120
121
122
edbd0635 123wxHtmlTableCell::wxHtmlTableCell(wxHtmlContainerCell *parent, const wxHtmlTag& tag, double pixel_scale)
5526e819
VS
124 : wxHtmlContainerCell(parent)
125{
edbd0635 126 m_PixelScale = pixel_scale;
25c71ccc 127 m_HasBorders =
b0bdbbfe 128 (tag.HasParam(wxT("BORDER")) && tag.GetParam(wxT("BORDER")) != wxT("0"));
5526e819
VS
129 m_ColsInfo = NULL;
130 m_NumCols = m_NumRows = 0;
131 m_CellInfo = NULL;
132 m_ActualCol = m_ActualRow = -1;
133
134 /* scan params: */
04dbb646 135 if (tag.HasParam(wxT("BGCOLOR")))
8bd72d90 136 tag.GetParamAsColour(wxT("BGCOLOR"), &m_tBkg);
04dbb646
VZ
137 if (tag.HasParam(wxT("VALIGN")))
138 m_tValign = tag.GetParam(wxT("VALIGN"));
139 else
8bd72d90
VS
140 m_tValign = wxEmptyString;
141 if (!tag.GetParamAsInt(wxT("CELLSPACING"), &m_Spacing))
142 m_Spacing = 2;
143 if (!tag.GetParamAsInt(wxT("CELLPADDING"), &m_Padding))
144 m_Padding = 3;
edbd0635
VS
145 m_Spacing = (int)(m_PixelScale * (double)m_Spacing);
146 m_Padding = (int)(m_PixelScale * (double)m_Padding);
5526e819
VS
147
148 if (m_HasBorders)
149 SetBorder(TABLE_BORDER_CLR_1, TABLE_BORDER_CLR_2);
150}
151
152
153
154wxHtmlTableCell::~wxHtmlTableCell()
155{
156 if (m_ColsInfo) free(m_ColsInfo);
04dbb646 157 if (m_CellInfo)
4f9297b0 158 {
5526e819
VS
159 for (int i = 0; i < m_NumRows; i++)
160 free(m_CellInfo[i]);
161 free(m_CellInfo);
162 }
163}
164
165
166
167void wxHtmlTableCell::ReallocCols(int cols)
168{
169 int i,j;
170
04dbb646 171 for (i = 0; i < m_NumRows; i++)
4f9297b0 172 {
5526e819
VS
173 m_CellInfo[i] = (cellStruct*) realloc(m_CellInfo[i], sizeof(cellStruct) * cols);
174 for (j = m_NumCols; j < cols; j++)
175 m_CellInfo[i][j].flag = cellFree;
176 }
177
178 m_ColsInfo = (colStruct*) realloc(m_ColsInfo, sizeof(colStruct) * cols);
04dbb646 179 for (j = m_NumCols; j < cols; j++)
4f9297b0 180 {
5526e819 181 m_ColsInfo[j].width = 0;
efba2b89 182 m_ColsInfo[j].units = wxHTML_UNITS_PERCENT;
79d6c018 183 m_ColsInfo[j].minWidth = m_ColsInfo[j].maxWidth = -1;
5526e819
VS
184 }
185
186 m_NumCols = cols;
187}
188
189
190
191void wxHtmlTableCell::ReallocRows(int rows)
192{
193 m_CellInfo = (cellStruct**) realloc(m_CellInfo, sizeof(cellStruct*) * rows);
04dbb646 194 for (int row = m_NumRows; row < rows ; row++)
80eab469 195 {
04dbb646 196 if (m_NumCols == 0)
80eab469 197 m_CellInfo[row] = NULL;
04dbb646 198 else
80eab469
VS
199 {
200 m_CellInfo[row] = (cellStruct*) malloc(sizeof(cellStruct) * m_NumCols);
201 for (int col = 0; col < m_NumCols; col++)
202 m_CellInfo[row][col].flag = cellFree;
203 }
5526e819 204 }
5526e819
VS
205 m_NumRows = rows;
206}
207
208
5526e819
VS
209void wxHtmlTableCell::AddRow(const wxHtmlTag& tag)
210{
5526e819 211 m_ActualCol = -1;
d361bbff
VS
212 // VS: real allocation of row entry is done in AddCell in order
213 // to correctly handle empty rows (i.e. "<tr></tr>")
214 // m_ActualCol == -1 indicates that AddCell has to allocate new row.
5526e819 215
d361bbff 216 // scan params:
5526e819 217 m_rBkg = m_tBkg;
04dbb646 218 if (tag.HasParam(wxT("BGCOLOR")))
8bd72d90 219 tag.GetParamAsColour(wxT("BGCOLOR"), &m_rBkg);
04dbb646
VZ
220 if (tag.HasParam(wxT("VALIGN")))
221 m_rValign = tag.GetParam(wxT("VALIGN"));
222 else
d361bbff 223 m_rValign = m_tValign;
5526e819
VS
224}
225
226
227
228void wxHtmlTableCell::AddCell(wxHtmlContainerCell *cell, const wxHtmlTag& tag)
229{
d361bbff
VS
230 // Is this cell in new row?
231 // VS: we can't do it in AddRow, see my comment there
232 if (m_ActualCol == -1)
233 {
234 if (m_ActualRow + 1 > m_NumRows - 1)
235 ReallocRows(m_ActualRow + 2);
236 m_ActualRow++;
237 }
238
239 // cells & columns:
04dbb646 240 do
4f9297b0 241 {
5526e819 242 m_ActualCol++;
04dbb646 243 } while ((m_ActualCol < m_NumCols) &&
8bd72d90 244 (m_CellInfo[m_ActualRow][m_ActualCol].flag != cellFree));
04dbb646 245
5526e819
VS
246 if (m_ActualCol > m_NumCols - 1)
247 ReallocCols(m_ActualCol + 1);
248
249 int r = m_ActualRow, c = m_ActualCol;
250
251 m_CellInfo[r][c].cont = cell;
252 m_CellInfo[r][c].colspan = 1;
253 m_CellInfo[r][c].rowspan = 1;
254 m_CellInfo[r][c].flag = cellUsed;
255 m_CellInfo[r][c].minheight = 0;
efba2b89 256 m_CellInfo[r][c].valign = wxHTML_ALIGN_TOP;
5526e819
VS
257
258 /* scan for parameters: */
259
260 // width:
261 {
8bd72d90 262 if (tag.HasParam(wxT("WIDTH")))
2fa3b707 263 {
8bd72d90 264 wxString wd = tag.GetParam(wxT("WIDTH"));
5526e819 265
8bd72d90 266 if (wd[wd.Length()-1] == wxT('%'))
2fa3b707 267 {
66a77a74 268 wxSscanf(wd.c_str(), wxT("%i%%"), &m_ColsInfo[c].width);
efba2b89 269 m_ColsInfo[c].units = wxHTML_UNITS_PERCENT;
5526e819 270 }
04dbb646 271 else
2fa3b707 272 {
66a77a74 273 wxSscanf(wd.c_str(), wxT("%i"), &m_ColsInfo[c].width);
edbd0635 274 m_ColsInfo[c].width = (int)(m_PixelScale * (double)m_ColsInfo[c].width);
efba2b89 275 m_ColsInfo[c].units = wxHTML_UNITS_PIXELS;
5526e819
VS
276 }
277 }
278 }
279
280
281 // spanning:
282 {
8bd72d90
VS
283 tag.GetParamAsInt(wxT("COLSPAN"), &m_CellInfo[r][c].colspan);
284 tag.GetParamAsInt(wxT("ROWSPAN"), &m_CellInfo[r][c].rowspan);
fbe77cea
VS
285
286 // VS: the standard says this about col/rowspan:
25c71ccc
VZ
287 // "This attribute specifies the number of rows spanned by the
288 // current cell. The default value of this attribute is one ("1").
289 // The value zero ("0") means that the cell spans all rows from the
290 // current row to the last row of the table." All mainstream
fbe77cea 291 // browsers act as if 0==1, though, and so does wxHTML.
25c71ccc 292 if (m_CellInfo[r][c].colspan < 1)
fbe77cea 293 m_CellInfo[r][c].colspan = 1;
25c71ccc 294 if (m_CellInfo[r][c].rowspan < 1)
fbe77cea
VS
295 m_CellInfo[r][c].rowspan = 1;
296
297 if ((m_CellInfo[r][c].colspan > 1) || (m_CellInfo[r][c].rowspan > 1))
2fa3b707 298 {
5526e819
VS
299 int i, j;
300
04dbb646 301 if (r + m_CellInfo[r][c].rowspan > m_NumRows)
8bd72d90 302 ReallocRows(r + m_CellInfo[r][c].rowspan);
04dbb646 303 if (c + m_CellInfo[r][c].colspan > m_NumCols)
8bd72d90 304 ReallocCols(c + m_CellInfo[r][c].colspan);
5526e819
VS
305 for (i = r; i < r + m_CellInfo[r][c].rowspan; i++)
306 for (j = c; j < c + m_CellInfo[r][c].colspan; j++)
307 m_CellInfo[i][j].flag = cellSpan;
308 m_CellInfo[r][c].flag = cellUsed;
309 }
310 }
311
312 //background color:
313 {
8bd72d90 314 wxColour bk = m_rBkg;
04dbb646 315 if (tag.HasParam(wxT("BGCOLOR")))
8bd72d90
VS
316 tag.GetParamAsColour(wxT("BGCOLOR"), &bk);
317 if (bk.Ok())
318 cell->SetBackgroundColour(bk);
5526e819
VS
319 }
320 if (m_HasBorders)
4f9297b0 321 cell->SetBorder(TABLE_BORDER_CLR_2, TABLE_BORDER_CLR_1);
5526e819
VS
322
323 // vertical alignment:
324 {
325 wxString valign;
04dbb646
VZ
326 if (tag.HasParam(wxT("VALIGN")))
327 valign = tag.GetParam(wxT("VALIGN"));
328 else
8bd72d90 329 valign = m_tValign;
5526e819 330 valign.MakeUpper();
04dbb646 331 if (valign == wxT("TOP"))
8bd72d90 332 m_CellInfo[r][c].valign = wxHTML_ALIGN_TOP;
04dbb646 333 else if (valign == wxT("BOTTOM"))
8bd72d90 334 m_CellInfo[r][c].valign = wxHTML_ALIGN_BOTTOM;
efba2b89 335 else m_CellInfo[r][c].valign = wxHTML_ALIGN_CENTER;
5526e819
VS
336 }
337
ca16b7a9
VS
338 // nowrap
339 if (tag.HasParam(wxT("NOWRAP")))
340 m_CellInfo[r][c].nowrap = true;
341 else
342 m_CellInfo[r][c].nowrap = false;
343
4f9297b0 344 cell->SetIndent(m_Padding, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
5526e819
VS
345}
346
79d6c018
VS
347void wxHtmlTableCell::ComputeMinMaxWidths()
348{
d1da8872 349 if (m_NumCols == 0 || m_ColsInfo[0].minWidth != wxDefaultCoord) return;
25c71ccc 350
ca16b7a9
VS
351 m_MaxTotalWidth = 0;
352 int percentage = 0;
79d6c018
VS
353 for (int c = 0; c < m_NumCols; c++)
354 {
355 for (int r = 0; r < m_NumRows; r++)
356 {
357 cellStruct& cell = m_CellInfo[r][c];
358 if (cell.flag == cellUsed)
359 {
026d1fac 360 cell.cont->Layout(2*m_Padding + 1);
ca16b7a9
VS
361 int maxWidth = cell.cont->GetMaxTotalWidth();
362 int width = cell.nowrap?maxWidth:cell.cont->GetWidth();
026d1fac 363 width -= (cell.colspan-1) * m_Spacing;
ca16b7a9 364 maxWidth -= (cell.colspan-1) * m_Spacing;
79d6c018 365 // HTML 4.0 says it is acceptable to distribute min/max
79d6c018 366 width /= cell.colspan;
ca16b7a9
VS
367 maxWidth /= cell.colspan;
368 for (int j = 0; j < cell.colspan; j++) {
79d6c018
VS
369 if (width > m_ColsInfo[c+j].minWidth)
370 m_ColsInfo[c+j].minWidth = width;
ca16b7a9
VS
371 if (maxWidth > m_ColsInfo[c+j].maxWidth)
372 m_ColsInfo[c+j].maxWidth = maxWidth;
373 }
79d6c018
VS
374 }
375 }
ca16b7a9
VS
376 // Calculate maximum table width, required for nested tables
377 if (m_ColsInfo[c].units == wxHTML_UNITS_PIXELS)
378 m_MaxTotalWidth += wxMax(m_ColsInfo[c].width, m_ColsInfo[c].minWidth);
379 else if ((m_ColsInfo[c].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[c].width != 0))
380 percentage += m_ColsInfo[c].width;
381 else
382 m_MaxTotalWidth += m_ColsInfo[c].maxWidth;
79d6c018 383 }
5526e819 384
ca16b7a9
VS
385 if (percentage >= 100)
386 {
387 // Table would have infinite length
388 // Make it ridiculous large
389 m_MaxTotalWidth = 0xFFFFFF;
390 }
391 else
392 m_MaxTotalWidth = m_MaxTotalWidth * 100 / (100 - percentage);
393
394 m_MaxTotalWidth += (m_NumCols + 1) * m_Spacing;
395}
5526e819
VS
396
397void wxHtmlTableCell::Layout(int w)
398{
79d6c018 399 ComputeMinMaxWidths();
25c71ccc 400
026d1fac 401 wxHtmlCell::Layout(w);
79d6c018 402
5526e819
VS
403 /*
404
405 WIDTH ADJUSTING :
406
407 */
408
04dbb646 409 if (m_WidthFloatUnits == wxHTML_UNITS_PERCENT)
4f9297b0 410 {
ca16b7a9
VS
411 if (m_WidthFloat < 0)
412 {
413 if (m_WidthFloat < -100)
414 m_WidthFloat = -100;
415 m_Width = (100 + m_WidthFloat) * w / 100;
416 }
25c71ccc 417 else
ca16b7a9
VS
418 {
419 if (m_WidthFloat > 100)
420 m_WidthFloat = 100;
421 m_Width = m_WidthFloat * w / 100;
422 }
5526e819 423 }
04dbb646 424 else
4f9297b0 425 {
5526e819
VS
426 if (m_WidthFloat < 0) m_Width = w + m_WidthFloat;
427 else m_Width = m_WidthFloat;
428 }
429
430
431 /*
432
433 LAYOUTING :
434
435 */
436
25c71ccc
VZ
437 /* 1. setup columns widths:
438
ca16b7a9
VS
439 The algorithm tries to keep the table size less than w if possible.
440 */
5526e819
VS
441 {
442 int wpix = m_Width - (m_NumCols + 1) * m_Spacing;
443 int i, j;
5526e819
VS
444
445 // 1a. setup fixed-width columns:
446 for (i = 0; i < m_NumCols; i++)
efba2b89 447 if (m_ColsInfo[i].units == wxHTML_UNITS_PIXELS)
79d6c018 448 {
25c71ccc 449 m_ColsInfo[i].pixwidth = wxMax(m_ColsInfo[i].width,
79d6c018
VS
450 m_ColsInfo[i].minWidth);
451 wpix -= m_ColsInfo[i].pixwidth;
452 }
5526e819 453
ca16b7a9
VS
454 // 1b. Calculate maximum possible width if line wrapping would be disabled
455 // Recalculate total width if m_WidthFloat is zero to keep tables as small
456 // as possible.
457 int maxWidth = 0;
458 for (i = 0; i < m_NumCols; i++)
459 if (m_ColsInfo[i].width == 0)
460 {
461 maxWidth += m_ColsInfo[i].maxWidth;
462 }
463
464 if (!m_WidthFloat)
465 {
466 // Recalculate table width since no table width was initially given
467 int newWidth = m_Width - wpix + maxWidth;
468
469 // Make sure that floating-width columns will have the right size.
470 // Calculate sum of all floating-width columns
471 int percentage = 0;
472 for (i = 0; i < m_NumCols; i++)
473 if ((m_ColsInfo[i].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0))
474 percentage += m_ColsInfo[i].width;
475
476 if (percentage >= 100)
477 newWidth = w;
478 else
479 newWidth = newWidth * 100 / (100 - percentage);
25c71ccc 480
ca16b7a9
VS
481 newWidth = wxMin(newWidth, w - (m_NumCols + 1) * m_Spacing);
482 wpix -= m_Width - newWidth;
483 m_Width = newWidth;
484 }
25c71ccc 485
ca16b7a9
VS
486
487 // 1c. setup floating-width columns:
488 int wtemp = wpix;
5526e819 489 for (i = 0; i < m_NumCols; i++)
efba2b89 490 if ((m_ColsInfo[i].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0))
79d6c018 491 {
ca16b7a9
VS
492 m_ColsInfo[i].pixwidth = wxMin(m_ColsInfo[i].width, 100) * wpix / 100;
493
494 // Make sure to leave enough space for the other columns
495 int minRequired = 0;
496 for (j = 0; j < m_NumCols; j++)
497 {
498 if ((m_ColsInfo[j].units == wxHTML_UNITS_PERCENT && j > i) ||
499 !m_ColsInfo[j].width)
500 minRequired += m_ColsInfo[j].minWidth;
501 }
502 m_ColsInfo[i].pixwidth = wxMax(wxMin(wtemp - minRequired, m_ColsInfo[i].pixwidth), m_ColsInfo[i].minWidth);
503
504 wtemp -= m_ColsInfo[i].pixwidth;
79d6c018 505 }
ca16b7a9
VS
506 wpix = wtemp;
507
508 // 1d. setup default columns (no width specification supplied):
509 // The algorithm assigns calculates the maximum possible width if line
510 // wrapping would be disabled and assigns column width as a fraction
511 // based upon the maximum width of a column
512 // FIXME: I'm not sure if this algorithm is conform to HTML standard,
513 // though it seems to be much better than the old one
5526e819 514
5526e819
VS
515 for (i = j = 0; i < m_NumCols; i++)
516 if (m_ColsInfo[i].width == 0) j++;
ca16b7a9
VS
517 if (wpix < 0)
518 wpix = 0;
519
520 // Assign widths
5526e819
VS
521 for (i = 0; i < m_NumCols; i++)
522 if (m_ColsInfo[i].width == 0)
8c571f46 523 {
ca16b7a9
VS
524 // Assign with, make sure not to drop below minWidth
525 if (maxWidth)
25c71ccc 526 m_ColsInfo[i].pixwidth = (int)(wpix * (m_ColsInfo[i].maxWidth / (float)maxWidth) + 0.5);
ca16b7a9
VS
527 else
528 m_ColsInfo[i].pixwidth = wpix / j;
25c71ccc 529
ca16b7a9
VS
530 // Make sure to leave enough space for the other columns
531 int minRequired = 0;
532 int r;
533 for (r = i + 1; r < m_NumCols; r++)
534 {
535 if (!m_ColsInfo[r].width)
536 minRequired += m_ColsInfo[r].minWidth;
537 }
538 m_ColsInfo[i].pixwidth = wxMax(wxMin(wpix - minRequired, m_ColsInfo[i].pixwidth), m_ColsInfo[i].minWidth);
539
540 if (maxWidth)
541 {
542 if (m_ColsInfo[i].pixwidth > (wpix * (m_ColsInfo[i].maxWidth / (float)maxWidth) + 0.5))
543 {
25c71ccc 544 int diff = (int)(m_ColsInfo[i].pixwidth - (wpix * m_ColsInfo[i].maxWidth / (float)maxWidth + 0.5));
ca16b7a9
VS
545 maxWidth += diff - m_ColsInfo[i].maxWidth;
546 }
547 else
548 maxWidth -= m_ColsInfo[i].maxWidth;
549 }
550 wpix -= m_ColsInfo[i].pixwidth;
8c571f46 551 }
5526e819
VS
552 }
553
554 /* 2. compute positions of columns: */
555 {
556 int wpos = m_Spacing;
04dbb646 557 for (int i = 0; i < m_NumCols; i++)
2fa3b707 558 {
5526e819
VS
559 m_ColsInfo[i].leftpos = wpos;
560 wpos += m_ColsInfo[i].pixwidth + m_Spacing;
561 }
562 }
563
564 /* 3. sub-layout all cells: */
565 {
2776d7c3 566 int *ypos = new int[m_NumRows + 1];
5526e819
VS
567
568 int actcol, actrow;
569 int fullwid;
570 wxHtmlContainerCell *actcell;
571
2fa3b707
VS
572 ypos[0] = m_Spacing;
573 for (actrow = 1; actrow <= m_NumRows; actrow++) ypos[actrow] = -1;
04dbb646 574 for (actrow = 0; actrow < m_NumRows; actrow++)
2fa3b707
VS
575 {
576 if (ypos[actrow] == -1) ypos[actrow] = ypos[actrow-1];
5526e819
VS
577 // 3a. sub-layout and detect max height:
578
579 for (actcol = 0; actcol < m_NumCols; actcol++) {
580 if (m_CellInfo[actrow][actcol].flag != cellUsed) continue;
581 actcell = m_CellInfo[actrow][actcol].cont;
582 fullwid = 0;
583 for (int i = actcol; i < m_CellInfo[actrow][actcol].colspan + actcol; i++)
584 fullwid += m_ColsInfo[i].pixwidth;
a97a264f 585 fullwid += (m_CellInfo[actrow][actcol].colspan - 1) * m_Spacing;
4f9297b0
VS
586 actcell->SetMinHeight(m_CellInfo[actrow][actcol].minheight, m_CellInfo[actrow][actcol].valign);
587 actcell->Layout(fullwid);
5526e819 588
4f9297b0 589 if (ypos[actrow] + actcell->GetHeight() + m_CellInfo[actrow][actcol].rowspan * m_Spacing > ypos[actrow + m_CellInfo[actrow][actcol].rowspan])
5526e819 590 ypos[actrow + m_CellInfo[actrow][actcol].rowspan] =
4f9297b0 591 ypos[actrow] + actcell->GetHeight() + m_CellInfo[actrow][actcol].rowspan * m_Spacing;
5526e819
VS
592 }
593 }
594
04dbb646 595 for (actrow = 0; actrow < m_NumRows; actrow++)
2fa3b707 596 {
5526e819
VS
597 // 3b. place cells in row & let'em all have same height:
598
04dbb646 599 for (actcol = 0; actcol < m_NumCols; actcol++)
2fa3b707 600 {
5526e819
VS
601 if (m_CellInfo[actrow][actcol].flag != cellUsed) continue;
602 actcell = m_CellInfo[actrow][actcol].cont;
4f9297b0 603 actcell->SetMinHeight(
a97a264f 604 ypos[actrow + m_CellInfo[actrow][actcol].rowspan] - ypos[actrow] - m_Spacing,
5526e819
VS
605 m_CellInfo[actrow][actcol].valign);
606 fullwid = 0;
607 for (int i = actcol; i < m_CellInfo[actrow][actcol].colspan + actcol; i++)
608 fullwid += m_ColsInfo[i].pixwidth;
a97a264f 609 fullwid += (m_CellInfo[actrow][actcol].colspan - 1) * m_Spacing;
4f9297b0
VS
610 actcell->Layout(fullwid);
611 actcell->SetPos(m_ColsInfo[actcol].leftpos, ypos[actrow]);
5526e819 612 }
5526e819
VS
613 }
614 m_Height = ypos[m_NumRows];
2776d7c3 615 delete[] ypos;
5526e819 616 }
8c571f46
VS
617
618 /* 4. adjust table's width if it was too small: */
619 if (m_NumCols > 0)
620 {
25c71ccc 621 int twidth = m_ColsInfo[m_NumCols-1].leftpos +
8c571f46
VS
622 m_ColsInfo[m_NumCols-1].pixwidth + m_Spacing;
623 if (twidth > m_Width)
624 m_Width = twidth;
625 }
5526e819
VS
626}
627
628
629
630
631
632
633//-----------------------------------------------------------------------------
634// The tables handler:
635//-----------------------------------------------------------------------------
636
637
638TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
639
640 TAG_HANDLER_VARS
641 wxHtmlTableCell* m_Table;
642 wxString m_tAlign, m_rAlign;
5526e819
VS
643
644 TAG_HANDLER_CONSTR(TABLE)
645 {
646 m_Table = NULL;
01325161 647 m_tAlign = m_rAlign = wxEmptyString;
5526e819
VS
648 }
649
650
651 TAG_HANDLER_PROC(tag)
652 {
653 wxHtmlContainerCell *c;
654
655 // new table started, backup upper-level table (if any) and create new:
04dbb646 656 if (tag.GetName() == wxT("TABLE"))
2fa3b707 657 {
5526e819
VS
658 wxHtmlTableCell *oldt = m_Table;
659 wxHtmlContainerCell *oldcont;
5526e819 660
4f9297b0 661 oldcont = c = m_WParser->OpenContainer();
5526e819 662
ca16b7a9
VS
663 m_Table = new wxHtmlTableCell(c, tag);
664
665 // width:
666 {
667 if (tag.HasParam(wxT("WIDTH")))
668 {
669 wxString wd = tag.GetParam(wxT("WIDTH"));
670
671 if (wd[wd.Length()-1] == wxT('%'))
672 {
673 int width = 0;
674 wxSscanf(wd.c_str(), wxT("%i%%"), &width);
675 m_Table->SetWidthFloat(width, wxHTML_UNITS_PERCENT);
676 }
677 else
678 {
679 int width = 0;
680 wxSscanf(wd.c_str(), wxT("%i"), &width);
25c71ccc 681 m_Table->SetWidthFloat((int)(m_WParser->GetPixelScale() * width), wxHTML_UNITS_PIXELS);
ca16b7a9
VS
682 }
683 }
684 else
685 m_Table->SetWidthFloat(0, wxHTML_UNITS_PIXELS);
686 }
2755d437 687 int oldAlign = m_WParser->GetAlign();
5526e819 688 m_tAlign = wxEmptyString;
8bd72d90
VS
689 if (tag.HasParam(wxT("ALIGN")))
690 m_tAlign = tag.GetParam(wxT("ALIGN"));
5526e819
VS
691
692 ParseInner(tag);
693
2755d437 694 m_WParser->SetAlign(oldAlign);
4f9297b0
VS
695 m_WParser->SetContainer(oldcont);
696 m_WParser->CloseContainer();
25c71ccc 697
5526e819 698 m_Table = oldt;
d1da8872 699 return true;
5526e819
VS
700 }
701
702
211dfedd 703 else if (m_Table)
2fa3b707 704 {
5526e819 705 // new row in table
04dbb646 706 if (tag.GetName() == wxT("TR"))
2fa3b707 707 {
4f9297b0 708 m_Table->AddRow(tag);
5526e819 709 m_rAlign = m_tAlign;
04dbb646 710 if (tag.HasParam(wxT("ALIGN")))
8bd72d90 711 m_rAlign = tag.GetParam(wxT("ALIGN"));
5526e819
VS
712 }
713
714 // new cell
04dbb646 715 else
2fa3b707 716 {
4f9297b0
VS
717 c = m_WParser->SetContainer(new wxHtmlContainerCell(m_Table));
718 m_Table->AddCell(c, tag);
5526e819 719
4f9297b0 720 m_WParser->OpenContainer();
5526e819 721
04dbb646 722 if (tag.GetName() == wxT("TH")) /*header style*/
4f9297b0 723 m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
2755d437
VS
724 else
725 m_WParser->SetAlign(wxHTML_ALIGN_LEFT);
726
727 wxString als;
728
729 als = m_rAlign;
730 if (tag.HasParam(wxT("ALIGN")))
731 als = tag.GetParam(wxT("ALIGN"));
732 als.MakeUpper();
733 if (als == wxT("RIGHT"))
734 m_WParser->SetAlign(wxHTML_ALIGN_RIGHT);
735 else if (als == wxT("LEFT"))
736 m_WParser->SetAlign(wxHTML_ALIGN_LEFT);
737 else if (als == wxT("CENTER"))
738 m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
739
4f9297b0 740 m_WParser->OpenContainer();
5526e819
VS
741 }
742 }
d1da8872 743 return false;
5526e819
VS
744 }
745
746TAG_HANDLER_END(TABLE)
747
748
749
750
751
752TAGS_MODULE_BEGIN(Tables)
753
754 TAGS_MODULE_ADD(TABLE)
755
756TAGS_MODULE_END(Tables)
757
758
759#endif