Dillo v3.2.0-151-g90488cbf
Loading...
Searching...
No Matches
table.cc
Go to the documentation of this file.
1/*
2 * File: table.cc
3 *
4 * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
5 * Copyright 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
18#include "table.hh"
19#include "html_common.hh"
20
21#include "dw/style.hh"
22#include "dw/textblock.hh"
23#include "dw/table.hh"
24#include "dw/simpletablecell.hh"
25
26#include "prefs.h"
27#include "msg.h"
28#include "css.hh"
29#include "dlib/dlib.h" /* dIsdigit */
30
31using namespace dw;
32using namespace dw::core;
33using namespace dw::core::style;
34
35/*
36 * Forward declarations
37 */
38
39static void Html_tag_open_table_cell(DilloHtml *html,
40 const char *tag, int tagsize,
43 const char *tag, int tagsize);
44
45/*
46 * <TABLE>
47 */
48void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
49{
50 const char *attrbuf;
51 int32_t border = -1, cellspacing = -1, cellpadding = -1, bgcolor = -1;
52 CssLength cssLength;
53
54 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
55 border = dIsdigit(attrbuf[0]) ? strtol (attrbuf, NULL, 10) : 1;
56 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellspacing"))) {
57 cellspacing = strtol (attrbuf, NULL, 10);
58 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
59 BUG_MSG("<table> cellspacing attribute is obsolete.");
60 }
61
62 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellpadding"))) {
63 cellpadding = strtol (attrbuf, NULL, 10);
64 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
65 BUG_MSG("<table> cellpadding attribute is obsolete.");
66 }
67
68 if (border != -1) {
69 cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX);
86 }
87
88 if (cellspacing != -1) {
89 cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX);
92 }
93
94 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
97 a_Html_parse_length (html, attrbuf));
98 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
99 BUG_MSG("<table> width attribute is obsolete.");
100 }
101
102 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
103 if (dStrAsciiCasecmp (attrbuf, "left") == 0)
106 else if (dStrAsciiCasecmp (attrbuf, "right") == 0)
109 else if (dStrAsciiCasecmp (attrbuf, "center") == 0)
112 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
113 BUG_MSG("<table> align attribute is obsolete.");
114 }
115
116 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
117 bgcolor = a_Html_color_parse(html, attrbuf, -1);
118 if (bgcolor != -1)
120 CSS_TYPE_COLOR, bgcolor);
121 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
122 BUG_MSG("<table> bgcolor attribute is obsolete.");
123 }
124
125 html->style (); // evaluate now, so we can build non-css hints for the cells
126
127 /* The style for the cells */
129 if (border > 0) {
130 cssLength = CSS_CREATE_LENGTH (1, CSS_LENGTH_TYPE_PX);
132 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
134 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
136 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
138 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
147 }
148
149 if (cellpadding != -1) {
150 cssLength = CSS_CREATE_LENGTH (cellpadding, CSS_LENGTH_TYPE_PX);
152 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
154 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
156 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
158 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
159 }
160
161}
162void Html_tag_content_table(DilloHtml *html, const char *tag, int tagsize)
163{
164 dw::core::Widget *table;
165
166 HT2TB(html)->addParbreak (0, html->wordStyle ());
167 table = new dw::Table(prefs.limit_text_width);
168 HT2TB(html)->addWidget (table, html->style ());
169 HT2TB(html)->addParbreak (0, html->wordStyle ());
170
171 S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP;
172 S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE;
173 S_TOP(html)->cell_text_align_set = FALSE;
174 S_TOP(html)->table = table;
175
176}
177
178/*
179 * <TR>
180 */
181void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
182{
183 const char *attrbuf;
184 int32_t bgcolor = -1;
185
187
188 switch (S_TOP(html)->table_mode) {
190 _MSG("Invalid HTML syntax: <tr> outside <table>\n");
191 return;
192
196
197 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
198 bgcolor = a_Html_color_parse(html, attrbuf, -1);
199 if (bgcolor != -1)
201 CSS_TYPE_COLOR, bgcolor);
202 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
203 BUG_MSG("<tr> bgcolor attribute is obsolete.");
204 }
205
206 if (a_Html_get_attr (html, tag, tagsize, "align")) {
207 S_TOP(html)->cell_text_align_set = TRUE;
208 a_Html_tag_set_align_attr (html, tag, tagsize);
209 }
210
212
213 if (bgcolor != -1) {
215 CSS_TYPE_COLOR, bgcolor);
216 }
217 a_Html_tag_set_valign_attr (html, tag, tagsize);
218 break;
219 default:
220 break;
221 }
222}
223
224void Html_tag_content_tr(DilloHtml *html, const char *tag, int tagsize)
225{
226 switch (S_TOP(html)->table_mode) {
228 return;
232 ((dw::Table*)S_TOP(html)->table)->addRow (html->style ());
233 default:
234 break;
235 }
236
237 S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TR;
238}
239
240/*
241 * <TD>
242 */
243void Html_tag_open_td(DilloHtml *html, const char *tag, int tagsize)
244{
245 Html_tag_open_table_cell (html, tag, tagsize,
247}
248
249void Html_tag_content_td(DilloHtml *html, const char *tag, int tagsize)
250{
251 Html_tag_content_table_cell (html, tag, tagsize);
252}
253
254/*
255 * <tbody>
256 */
257void Html_tag_open_tbody(DilloHtml *html, const char *tag, int tagsize)
258{
259}
260
261void Html_tag_content_tbody(DilloHtml *html, const char *tag, int tagsize)
262{
263}
264
265/*
266 * <tfoot>
267 */
268void Html_tag_open_tfoot(DilloHtml *html, const char *tag, int tagsize)
269{
270}
271
272/*
273 * <thead>
274 */
275void Html_tag_open_thead(DilloHtml *html, const char *tag, int tagsize)
276{
277}
278
279/*
280 * <TH>
281 */
282void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize)
283{
284 Html_tag_open_table_cell (html, tag, tagsize,
286}
287
288void Html_tag_content_th(DilloHtml *html, const char *tag, int tagsize)
289{
290 Html_tag_content_table_cell (html, tag, tagsize);
291}
292
293/*
294 * Utilities
295 */
296
301{
302 static int i_TABLE = -1;
303 if (i_TABLE == -1)
304 i_TABLE = a_Html_tag_index("table");
305
306 int s_idx = html->stack->size();
307 while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE)
308 ;
309 return html->stack->getRef(s_idx)->table_border_mode;
310}
311
317{
318 int s_idx = html->stack->size(), i_TABLE = a_Html_tag_index("table");
319
320 while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) ;
321 if (s_idx > 0)
322 html->stack->getRef(s_idx)->table_border_mode = mode;
323}
324
325/* WORKAROUND: collapsing border model requires moving rendering code from
326 * the cell to the table, and making table-code aware of each
327 * cell style.
328 * This workaround mimics collapsing model within separate model. This is not
329 * a complete emulation but should be enough for most cases.
330 */
332{
333 dw::core::style::Style *collapseStyle, *tableStyle;
334 dw::core::style::StyleAttrs collapseCellAttrs, collapseTableAttrs;
335 int borderWidth, marginWidth;
336
337 tableStyle = ((dw::Table*)S_TOP(html)->table)->getStyle ();
338 borderWidth = html->style ()->borderWidth.top;
339 marginWidth = tableStyle->margin.top;
340
341 collapseCellAttrs = *(html->style ());
342 collapseCellAttrs.margin.setVal (0);
343 collapseCellAttrs.borderWidth.left = 0;
344 collapseCellAttrs.borderWidth.top = 0;
345 collapseCellAttrs.borderWidth.right = borderWidth;
346 collapseCellAttrs.borderWidth.bottom = borderWidth;
347 collapseCellAttrs.hBorderSpacing = 0;
348 collapseCellAttrs.vBorderSpacing = 0;
349 collapseStyle = Style::create(&collapseCellAttrs);
350 col_tb->setStyle (collapseStyle);
351
354 collapseTableAttrs = *tableStyle;
355 collapseTableAttrs.margin.setVal (marginWidth);
356 collapseTableAttrs.borderWidth.left = borderWidth;
357 collapseTableAttrs.borderWidth.top = borderWidth;
358 collapseTableAttrs.borderWidth.right = 0;
359 collapseTableAttrs.borderWidth.bottom = 0;
360 collapseTableAttrs.hBorderSpacing = 0;
361 collapseTableAttrs.vBorderSpacing = 0;
362 collapseTableAttrs.borderColor = collapseCellAttrs.borderColor;
363 collapseTableAttrs.borderStyle = collapseCellAttrs.borderStyle;
364 /* CSS2 17.6.2: table does not have padding (in collapsing mode) */
365 collapseTableAttrs.padding.setVal (0);
366 collapseStyle = Style::create(&collapseTableAttrs);
367 ((dw::Table*)S_TOP(html)->table)->setStyle (collapseStyle);
368 }
369}
370
376{
377 dw::core::style::Style *separateStyle;
378 dw::core::style::StyleAttrs separateCellAttrs;
379
380 separateCellAttrs = *(html->style ());
381 /* CSS2 17.5: Internal table elements do not have margins */
382 separateCellAttrs.margin.setVal (0);
383 separateStyle = Style::create(&separateCellAttrs);
384 col_tb->setStyle (separateStyle);
385}
386
387/*
388 * used by <TD> and <TH>
389 */
391 const char *tag, int tagsize,
393{
394 const char *attrbuf;
395 int32_t bgcolor;
396
398
399 switch (S_TOP(html)->table_mode) {
401 return;
402
404 /* a_Dw_table_add_cell takes care that dillo does not crash. */
405 /* continues */
408 /* text style */
409 if (!S_TOP(html)->cell_text_align_set) {
411 CSS_TYPE_ENUM, text_align);
412 }
413 if (a_Html_get_attr(html, tag, tagsize, "nowrap")) {
414 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
415 BUG_MSG("<t%c> nowrap attribute is obsolete.",
416 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
419 }
420
421 a_Html_tag_set_align_attr (html, tag, tagsize);
422
423 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
426 a_Html_parse_length (html, attrbuf));
427 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
428 BUG_MSG("<t%c> width attribute is obsolete.",
429 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
430 }
431
432 a_Html_tag_set_valign_attr (html, tag, tagsize);
433
434 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
435 bgcolor = a_Html_color_parse(html, attrbuf, -1);
436 if (bgcolor != -1)
438 CSS_TYPE_COLOR, bgcolor);
439 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
440 BUG_MSG("<t%c> bgcolor attribute is obsolete.",
441 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
442 }
443 break;
444 default:
445 /* compiler happiness */
446 break;
447 }
448}
449
451 const char *tag, int tagsize)
452{
453 int colspan = 1, rowspan = 1;
454 const char *attrbuf;
455 Widget *col_tb;
456
457 switch (S_TOP(html)->table_mode) {
459 BUG_MSG("<t%c> outside <table>.",
460 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
461 return;
462
464 BUG_MSG("<t%c> outside <tr>.",
465 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
466 /* a_Dw_table_add_cell takes care that dillo does not crash. */
467 /* fallthrough */
470 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "colspan"))) {
471 char *invalid;
472 colspan = strtol(attrbuf, &invalid, 10);
473 if ((colspan < 0) || (attrbuf == invalid))
474 colspan = 1;
475 }
476 /* TODO: check errors? */
477 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan")))
478 rowspan = MAX(1, strtol (attrbuf, NULL, 10));
479 if (html->style ()->textAlign
481 col_tb = new AlignedTableCell (
482 ((dw::Table*)S_TOP(html)->table)->getCellRef (),
484 else
486
489 } else {
490 Html_set_separate_border_model(html, col_tb);
491 }
492
493 ((dw::Table*)S_TOP(html)->table)->addCell (col_tb, colspan, rowspan);
494 S_TOP(html)->textblock = html->dw = col_tb;
495 break;
496
497 default:
498 /* compiler happiness */
499 break;
500 }
501
502 S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TD;
503}
#define _MSG(...)
Definition bookmarks.c:44
DilloHtmlDocumentType DocType
lout::misc::SimpleVector< DilloHtmlState > * stack
float DocTypeVersion
dw::core::style::Style * wordStyle()
dw::core::style::Style * style()
dw::core::Widget * dw
StyleEngine * styleEngine
void setNonCssHint(CssPropertyName name, CssValueType type, CssPropertyValue value)
void clearNonCssHints()
void inheritBackgroundColor()
Use of the background color of the parent style as default.
void inheritNonCssHints()
Instruct StyleEngine to use the nonCssHints from parent element This is only used for tables where no...
A Widget for rendering tables.
Definition table.hh:326
The base class of all dillo widgets.
Definition widget.hh:44
virtual void setStyle(style::Style *style)
Change the style of a widget.
Definition widget.cc:1316
void setVal(int val)
Definition style.hh:510
struct dw::core::style::StyleAttrs::@20 borderColor
BorderCollapse borderCollapse
Definition style.hh:561
TextAlignType textAlign
Definition style.hh:543
struct dw::core::style::StyleAttrs::@21 borderStyle
static Style * create(StyleAttrs *attrs)
Definition style.hh:629
int size() const
Return the number of elements put into this vector.
Definition misc.hh:162
T * getRef(int i) const
Return the reference of one element.
Definition misc.hh:211
@ CSS_PROPERTY_PADDING_TOP
Definition css.hh:228
@ CSS_PROPERTY_BORDER_RIGHT_STYLE
Definition css.hh:178
@ CSS_PROPERTY_BORDER_RIGHT_WIDTH
Definition css.hh:179
@ CSS_PROPERTY_BORDER_LEFT_WIDTH
Definition css.hh:176
@ CSS_PROPERTY_PADDING_BOTTOM
Definition css.hh:225
@ CSS_PROPERTY_WIDTH
Definition css.hh:242
@ CSS_PROPERTY_BORDER_TOP_WIDTH
Definition css.hh:183
@ CSS_PROPERTY_PADDING_RIGHT
Definition css.hh:227
@ CSS_PROPERTY_PADDING_LEFT
Definition css.hh:226
@ CSS_PROPERTY_BORDER_SPACING
Definition css.hh:180
@ CSS_PROPERTY_BORDER_LEFT_STYLE
Definition css.hh:175
@ CSS_PROPERTY_TEXT_ALIGN
Definition css.hh:232
@ CSS_PROPERTY_BORDER_TOP_STYLE
Definition css.hh:182
@ CSS_PROPERTY_BACKGROUND_COLOR
Definition css.hh:166
@ CSS_PROPERTY_WHITE_SPACE
Definition css.hh:241
@ CSS_PROPERTY_BORDER_BOTTOM_STYLE
Definition css.hh:171
@ CSS_PROPERTY_BORDER_BOTTOM_WIDTH
Definition css.hh:172
@ CSS_TYPE_ENUM
Value is i, if represented by enum_symbols[i].
Definition css.hh:39
@ CSS_TYPE_LENGTH_PERCENTAGE
<length> or <percentage>.
Definition css.hh:43
@ CSS_TYPE_COLOR
Represented as integer.
Definition css.hh:55
CssLength CSS_CREATE_LENGTH(float v, CssLengthType t)
Definition css.hh:102
@ CSS_LENGTH_TYPE_PX
Definition css.hh:76
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:202
static int dIsdigit(unsigned char c)
Definition dlib.h:50
#define D_ASCII_TOLOWER(c)
Definition dlib.h:60
#define TRUE
Definition dlib.h:36
#define FALSE
Definition dlib.h:32
#define MAX(a, b)
Definition dlib.h:40
const char * a_Html_get_attr(DilloHtml *html, const char *tag, int tagsize, const char *attrname)
Call Html_get_attr2 telling it to parse entities and strip the result.
Definition html.cc:4292
bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, int tagsize)
Evaluates the VALIGN attribute (top|bottom|middle|baseline) and sets the style in style_attrs.
Definition html.cc:363
CssLength a_Html_parse_length(DilloHtml *html, const char *attr)
Returns a length or a percentage, or UNDEF_LENGTH in case of an error, or if attr is NULL.
Definition html.cc:1443
int32_t a_Html_color_parse(DilloHtml *html, const char *str, int32_t default_color)
Parse a color attribute.
Definition html.cc:1468
void a_Html_tag_set_align_attr(DilloHtml *html, const char *tag, int tagsize)
Evaluates the ALIGN attribute (left|center|right|justify) and sets the style at the top of the stack.
Definition html.cc:318
int a_Html_tag_index(const char *tag)
Get 'tag' index.
Definition html.cc:3624
@ DILLO_HTML_TABLE_MODE_TD
inside of
@ DILLO_HTML_TABLE_MODE_NONE
no table at all
@ DILLO_HTML_TABLE_MODE_TR
inside of , outside of
@ DILLO_HTML_TABLE_MODE_TOP
outside of
#define HT2TB(html)
"html struct" to Textblock
#define BUG_MSG(...)
Add a bug-meter message.
#define S_TOP(html)
Top of the parsing stack.
DilloHtmlTableBorderMode
@ DILLO_HTML_TABLE_BORDER_COLLAPSE
@ DILLO_HTML_TABLE_BORDER_SEPARATE
@ DT_HTML
Anything related to Dillo Widget styles is defined here.
Definition style.cc:33
@ BORDER_MODEL_COLLAPSE
Definition style.hh:221
The core of Dw is defined in this namespace.
Definition core.hh:23
Dw is in this namespace, or sub namespaces of this one.
DilloPrefs prefs
Global Data.
Definition prefs.c:33
void Html_tag_open_td(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:243
static void Html_set_collapsing_border_model(DilloHtml *html, Widget *col_tb)
Definition table.cc:331
void Html_tag_content_tbody(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:261
void Html_tag_open_tbody(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:257
void Html_tag_open_thead(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:275
static void Html_table_set_border_model(DilloHtml *html, DilloHtmlTableBorderMode mode)
Set current table's border model.
Definition table.cc:315
void Html_tag_content_th(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:288
void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:48
static void Html_tag_open_table_cell(DilloHtml *html, const char *tag, int tagsize, dw::core::style::TextAlignType text_align)
Definition table.cc:390
void Html_tag_open_tfoot(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:268
void Html_tag_content_td(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:249
static void Html_tag_content_table_cell(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:450
void Html_tag_content_tr(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:224
static int Html_table_get_border_model(DilloHtml *html)
The table border model is stored in the table's stack item.
Definition table.cc:300
void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:282
void Html_tag_content_table(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:162
static void Html_set_separate_border_model(DilloHtml *html, Widget *col_tb)
Adjust style for separate border model.
Definition table.cc:375
void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:181
DilloHtmlTableBorderMode table_border_mode
int tag_idx
TagInfo index for the tag that's being processed.
bool_t limit_text_width
Definition prefs.h:71