Dillo v3.1.1-14-g8f67d6e0
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
30using namespace dw;
31using namespace dw::core;
32using namespace dw::core::style;
33
34/*
35 * Forward declarations
36 */
37
38static void Html_tag_open_table_cell(DilloHtml *html,
39 const char *tag, int tagsize,
42 const char *tag, int tagsize);
43
44/*
45 * <TABLE>
46 */
47void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
48{
49 const char *attrbuf;
50 int32_t border = -1, cellspacing = -1, cellpadding = -1, bgcolor = -1;
51 CssLength cssLength;
52
53 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "border")))
54 border = isdigit(attrbuf[0]) ? strtol (attrbuf, NULL, 10) : 1;
55 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellspacing"))) {
56 cellspacing = strtol (attrbuf, NULL, 10);
57 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
58 BUG_MSG("<table> cellspacing attribute is obsolete.");
59 }
60
61 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "cellpadding"))) {
62 cellpadding = strtol (attrbuf, NULL, 10);
63 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
64 BUG_MSG("<table> cellpadding attribute is obsolete.");
65 }
66
67 if (border != -1) {
68 cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX);
85 }
86
87 if (cellspacing != -1) {
88 cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX);
91 }
92
93 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
96 a_Html_parse_length (html, attrbuf));
97 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
98 BUG_MSG("<table> width attribute is obsolete.");
99 }
100
101 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) {
102 if (dStrAsciiCasecmp (attrbuf, "left") == 0)
105 else if (dStrAsciiCasecmp (attrbuf, "right") == 0)
108 else if (dStrAsciiCasecmp (attrbuf, "center") == 0)
111 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
112 BUG_MSG("<table> align attribute is obsolete.");
113 }
114
115 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
116 bgcolor = a_Html_color_parse(html, attrbuf, -1);
117 if (bgcolor != -1)
119 CSS_TYPE_COLOR, bgcolor);
120 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
121 BUG_MSG("<table> bgcolor attribute is obsolete.");
122 }
123
124 html->style (); // evaluate now, so we can build non-css hints for the cells
125
126 /* The style for the cells */
128 if (border > 0) {
129 cssLength = CSS_CREATE_LENGTH (1, CSS_LENGTH_TYPE_PX);
131 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
133 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
135 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
137 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
146 }
147
148 if (cellpadding != -1) {
149 cssLength = CSS_CREATE_LENGTH (cellpadding, CSS_LENGTH_TYPE_PX);
151 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
153 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
155 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
157 CSS_TYPE_LENGTH_PERCENTAGE, cssLength);
158 }
159
160}
161void Html_tag_content_table(DilloHtml *html, const char *tag, int tagsize)
162{
163 dw::core::Widget *table;
164
165 HT2TB(html)->addParbreak (0, html->wordStyle ());
166 table = new dw::Table(prefs.limit_text_width);
167 HT2TB(html)->addWidget (table, html->style ());
168 HT2TB(html)->addParbreak (0, html->wordStyle ());
169
170 S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP;
171 S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE;
172 S_TOP(html)->cell_text_align_set = FALSE;
173 S_TOP(html)->table = table;
174
175}
176
177/*
178 * <TR>
179 */
180void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
181{
182 const char *attrbuf;
183 int32_t bgcolor = -1;
184
186
187 switch (S_TOP(html)->table_mode) {
189 _MSG("Invalid HTML syntax: <tr> outside <table>\n");
190 return;
191
195
196 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
197 bgcolor = a_Html_color_parse(html, attrbuf, -1);
198 if (bgcolor != -1)
200 CSS_TYPE_COLOR, bgcolor);
201 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
202 BUG_MSG("<tr> bgcolor attribute is obsolete.");
203 }
204
205 if (a_Html_get_attr (html, tag, tagsize, "align")) {
206 S_TOP(html)->cell_text_align_set = TRUE;
207 a_Html_tag_set_align_attr (html, tag, tagsize);
208 }
209
211
212 if (bgcolor != -1) {
214 CSS_TYPE_COLOR, bgcolor);
215 }
216 a_Html_tag_set_valign_attr (html, tag, tagsize);
217 break;
218 default:
219 break;
220 }
221}
222
223void Html_tag_content_tr(DilloHtml *html, const char *tag, int tagsize)
224{
225 switch (S_TOP(html)->table_mode) {
227 return;
231 ((dw::Table*)S_TOP(html)->table)->addRow (html->style ());
232 default:
233 break;
234 }
235
236 S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TR;
237}
238
239/*
240 * <TD>
241 */
242void Html_tag_open_td(DilloHtml *html, const char *tag, int tagsize)
243{
244 Html_tag_open_table_cell (html, tag, tagsize,
246}
247
248void Html_tag_content_td(DilloHtml *html, const char *tag, int tagsize)
249{
250 Html_tag_content_table_cell (html, tag, tagsize);
251}
252
253/*
254 * <tbody>
255 */
256void Html_tag_open_tbody(DilloHtml *html, const char *tag, int tagsize)
257{
258}
259
260void Html_tag_content_tbody(DilloHtml *html, const char *tag, int tagsize)
261{
262}
263
264/*
265 * <tfoot>
266 */
267void Html_tag_open_tfoot(DilloHtml *html, const char *tag, int tagsize)
268{
269}
270
271/*
272 * <thead>
273 */
274void Html_tag_open_thead(DilloHtml *html, const char *tag, int tagsize)
275{
276}
277
278/*
279 * <TH>
280 */
281void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize)
282{
283 Html_tag_open_table_cell (html, tag, tagsize,
285}
286
287void Html_tag_content_th(DilloHtml *html, const char *tag, int tagsize)
288{
289 Html_tag_content_table_cell (html, tag, tagsize);
290}
291
292/*
293 * Utilities
294 */
295
300{
301 static int i_TABLE = -1;
302 if (i_TABLE == -1)
303 i_TABLE = a_Html_tag_index("table");
304
305 int s_idx = html->stack->size();
306 while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE)
307 ;
308 return html->stack->getRef(s_idx)->table_border_mode;
309}
310
316{
317 int s_idx = html->stack->size(), i_TABLE = a_Html_tag_index("table");
318
319 while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) ;
320 if (s_idx > 0)
321 html->stack->getRef(s_idx)->table_border_mode = mode;
322}
323
324/* WORKAROUND: collapsing border model requires moving rendering code from
325 * the cell to the table, and making table-code aware of each
326 * cell style.
327 * This workaround mimics collapsing model within separate model. This is not
328 * a complete emulation but should be enough for most cases.
329 */
331{
332 dw::core::style::Style *collapseStyle, *tableStyle;
333 dw::core::style::StyleAttrs collapseCellAttrs, collapseTableAttrs;
334 int borderWidth, marginWidth;
335
336 tableStyle = ((dw::Table*)S_TOP(html)->table)->getStyle ();
337 borderWidth = html->style ()->borderWidth.top;
338 marginWidth = tableStyle->margin.top;
339
340 collapseCellAttrs = *(html->style ());
341 collapseCellAttrs.margin.setVal (0);
342 collapseCellAttrs.borderWidth.left = 0;
343 collapseCellAttrs.borderWidth.top = 0;
344 collapseCellAttrs.borderWidth.right = borderWidth;
345 collapseCellAttrs.borderWidth.bottom = borderWidth;
346 collapseCellAttrs.hBorderSpacing = 0;
347 collapseCellAttrs.vBorderSpacing = 0;
348 collapseStyle = Style::create(&collapseCellAttrs);
349 col_tb->setStyle (collapseStyle);
350
353 collapseTableAttrs = *tableStyle;
354 collapseTableAttrs.margin.setVal (marginWidth);
355 collapseTableAttrs.borderWidth.left = borderWidth;
356 collapseTableAttrs.borderWidth.top = borderWidth;
357 collapseTableAttrs.borderWidth.right = 0;
358 collapseTableAttrs.borderWidth.bottom = 0;
359 collapseTableAttrs.hBorderSpacing = 0;
360 collapseTableAttrs.vBorderSpacing = 0;
361 collapseTableAttrs.borderColor = collapseCellAttrs.borderColor;
362 collapseTableAttrs.borderStyle = collapseCellAttrs.borderStyle;
363 /* CSS2 17.6.2: table does not have padding (in collapsing mode) */
364 collapseTableAttrs.padding.setVal (0);
365 collapseStyle = Style::create(&collapseTableAttrs);
366 ((dw::Table*)S_TOP(html)->table)->setStyle (collapseStyle);
367 }
368}
369
375{
376 dw::core::style::Style *separateStyle;
377 dw::core::style::StyleAttrs separateCellAttrs;
378
379 separateCellAttrs = *(html->style ());
380 /* CSS2 17.5: Internal table elements do not have margins */
381 separateCellAttrs.margin.setVal (0);
382 separateStyle = Style::create(&separateCellAttrs);
383 col_tb->setStyle (separateStyle);
384}
385
386/*
387 * used by <TD> and <TH>
388 */
390 const char *tag, int tagsize,
392{
393 const char *attrbuf;
394 int32_t bgcolor;
395
397
398 switch (S_TOP(html)->table_mode) {
400 return;
401
403 /* a_Dw_table_add_cell takes care that dillo does not crash. */
404 /* continues */
407 /* text style */
408 if (!S_TOP(html)->cell_text_align_set) {
410 CSS_TYPE_ENUM, text_align);
411 }
412 if (a_Html_get_attr(html, tag, tagsize, "nowrap")) {
413 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
414 BUG_MSG("<t%c> nowrap attribute is obsolete.",
415 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
418 }
419
420 a_Html_tag_set_align_attr (html, tag, tagsize);
421
422 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) {
425 a_Html_parse_length (html, attrbuf));
426 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
427 BUG_MSG("<t%c> width attribute is obsolete.",
428 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
429 }
430
431 a_Html_tag_set_valign_attr (html, tag, tagsize);
432
433 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) {
434 bgcolor = a_Html_color_parse(html, attrbuf, -1);
435 if (bgcolor != -1)
437 CSS_TYPE_COLOR, bgcolor);
438 if (html->DocType == DT_HTML && html->DocTypeVersion >= 5.0f)
439 BUG_MSG("<t%c> bgcolor attribute is obsolete.",
440 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
441 }
442 break;
443 default:
444 /* compiler happiness */
445 break;
446 }
447}
448
450 const char *tag, int tagsize)
451{
452 int colspan = 1, rowspan = 1;
453 const char *attrbuf;
454 Widget *col_tb;
455
456 switch (S_TOP(html)->table_mode) {
458 BUG_MSG("<t%c> outside <table>.",
459 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
460 return;
461
463 BUG_MSG("<t%c> outside <tr>.",
464 (tagsize >=3 && (D_ASCII_TOLOWER(tag[2]) == 'd')) ? 'd' : 'h');
465 /* a_Dw_table_add_cell takes care that dillo does not crash. */
466 /* fallthrough */
469 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "colspan"))) {
470 char *invalid;
471 colspan = strtol(attrbuf, &invalid, 10);
472 if ((colspan < 0) || (attrbuf == invalid))
473 colspan = 1;
474 }
475 /* TODO: check errors? */
476 if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan")))
477 rowspan = MAX(1, strtol (attrbuf, NULL, 10));
478 if (html->style ()->textAlign
480 col_tb = new AlignedTableCell (
481 ((dw::Table*)S_TOP(html)->table)->getCellRef (),
483 else
485
488 } else {
489 Html_set_separate_border_model(html, col_tb);
490 }
491
492 ((dw::Table*)S_TOP(html)->table)->addCell (col_tb, colspan, rowspan);
493 S_TOP(html)->textblock = html->dw = col_tb;
494 break;
495
496 default:
497 /* compiler happiness */
498 break;
499 }
500
501 S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TD;
502}
#define _MSG(...)
Definition bookmarks.c:45
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:24
virtual void setStyle(style::Style *style)
Change the style of a widget.
Definition widget.cc:1233
void setVal(int val)
Definition style.hh:509
struct dw::core::style::StyleAttrs::@20 borderColor
BorderCollapse borderCollapse
Definition style.hh:560
TextAlignType textAlign
Definition style.hh:542
struct dw::core::style::StyleAttrs::@21 borderStyle
static Style * create(StyleAttrs *attrs)
Definition style.hh:628
int size() const
Return the number of elements put into this vector.
Definition misc.hh:141
T * getRef(int i) const
Return the reference of one element.
Definition misc.hh:190
@ CSS_PROPERTY_PADDING_TOP
Definition css.hh:226
@ CSS_PROPERTY_BORDER_RIGHT_STYLE
Definition css.hh:176
@ CSS_PROPERTY_BORDER_RIGHT_WIDTH
Definition css.hh:177
@ CSS_PROPERTY_BORDER_LEFT_WIDTH
Definition css.hh:174
@ CSS_PROPERTY_PADDING_BOTTOM
Definition css.hh:223
@ CSS_PROPERTY_WIDTH
Definition css.hh:240
@ CSS_PROPERTY_BORDER_TOP_WIDTH
Definition css.hh:181
@ CSS_PROPERTY_PADDING_RIGHT
Definition css.hh:225
@ CSS_PROPERTY_PADDING_LEFT
Definition css.hh:224
@ CSS_PROPERTY_BORDER_SPACING
Definition css.hh:178
@ CSS_PROPERTY_BORDER_LEFT_STYLE
Definition css.hh:173
@ CSS_PROPERTY_TEXT_ALIGN
Definition css.hh:230
@ CSS_PROPERTY_BORDER_TOP_STYLE
Definition css.hh:180
@ CSS_PROPERTY_BACKGROUND_COLOR
Definition css.hh:164
@ CSS_PROPERTY_WHITE_SPACE
Definition css.hh:239
@ CSS_PROPERTY_BORDER_BOTTOM_STYLE
Definition css.hh:169
@ CSS_PROPERTY_BORDER_BOTTOM_WIDTH
Definition css.hh:170
@ 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
int CssLength
Lengths are represented as int in the following way:
Definition css.hh:91
CssLength CSS_CREATE_LENGTH(float v, CssLengthType t)
Definition css.hh:106
@ CSS_LENGTH_TYPE_PX
Definition css.hh:95
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:201
#define D_ASCII_TOLOWER(c)
Definition dlib.h:37
#define TRUE
Definition dlib.h:23
#define FALSE
Definition dlib.h:19
#define MAX(a, b)
Definition dlib.h:27
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:4262
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:362
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:1432
int32_t a_Html_color_parse(DilloHtml *html, const char *str, int32_t default_color)
Parse a color attribute.
Definition html.cc:1457
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:317
int a_Html_tag_index(const char *tag)
Get 'tag' index.
Definition html.cc:3606
@ 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:220
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:242
static void Html_set_collapsing_border_model(DilloHtml *html, Widget *col_tb)
Definition table.cc:330
void Html_tag_content_tbody(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:260
void Html_tag_open_tbody(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:256
void Html_tag_open_thead(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:274
static void Html_table_set_border_model(DilloHtml *html, DilloHtmlTableBorderMode mode)
Set current table's border model.
Definition table.cc:314
void Html_tag_content_th(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:287
void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:47
static void Html_tag_open_table_cell(DilloHtml *html, const char *tag, int tagsize, dw::core::style::TextAlignType text_align)
Definition table.cc:389
void Html_tag_open_tfoot(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:267
void Html_tag_content_td(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:248
static void Html_tag_content_table_cell(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:449
void Html_tag_content_tr(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:223
static int Html_table_get_border_model(DilloHtml *html)
The table border model is stored in the table's stack item.
Definition table.cc:299
void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:281
void Html_tag_content_table(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:161
static void Html_set_separate_border_model(DilloHtml *html, Widget *col_tb)
Adjust style for separate border model.
Definition table.cc:374
void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize)
Definition table.cc:180
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