From df3341cb4305831a94c9983219f4a814406dc692 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Wed, 26 Jun 2002 23:27:30 +0000 Subject: [project @ 2002-06-26 23:27:30 by bursa] Implied table elements and colspan implemented. svn path=/import/netsurf/; revision=24 --- render/box.c | 124 +++++++++++++++++++++++++++++++++++++++----------- render/box.h | 11 +++-- render/css.h | 3 +- render/layout.c | 29 +++++++----- render/render.c | 8 +++- render/test/test1.css | 6 +-- 6 files changed, 135 insertions(+), 46 deletions(-) diff --git a/render/box.c b/render/box.c index 4844be597..e94f3909c 100644 --- a/render/box.c +++ b/render/box.c @@ -1,5 +1,5 @@ /** - * $Id: box.c,v 1.7 2002/06/26 12:19:24 bursa Exp $ + * $Id: box.c,v 1.8 2002/06/26 23:27:30 bursa Exp $ */ #include @@ -18,6 +18,7 @@ */ void box_add_child(struct box * parent, struct box * child); +struct box * box_create(xmlNode * node, box_type type, struct css_style * style); struct css_style * box_get_style(struct css_stylesheet * stylesheet, struct css_style * parent_style, xmlNode * n, struct css_selector * selector, unsigned int depth); @@ -37,6 +38,18 @@ void box_add_child(struct box * parent, struct box * child) child->parent = parent; } +/** + * create a box tree node + */ + +struct box * box_create(xmlNode * node, box_type type, struct css_style * style) +{ + struct box * box = xcalloc(1, sizeof(struct box)); + box->node = node; + box->type = type; + box->style = style; + return box; +} /** * make a box tree with style data from an xml tree @@ -60,17 +73,17 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css { struct box * box; struct box * inline_container_c; - struct css_style * style; + struct css_style * style, * style2; xmlNode * c; - xmlChar * s; + char * s; if (n->type == XML_ELEMENT_NODE) { /* work out the style for this element */ *selector = xrealloc(*selector, (depth + 1) * sizeof(struct css_selector)); (*selector)[depth].element = (const char *) n->name; (*selector)[depth].class = (*selector)[depth].id = 0; - if ((s = xmlGetProp(n, (xmlChar *) "class"))) - (*selector)[depth].class = (char *) s; + if ((s = (char *) xmlGetProp(n, (xmlChar *) "class"))) + (*selector)[depth].class = s; style = box_get_style(stylesheet, parent_style, n, *selector, depth + 1); } @@ -81,6 +94,33 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css if (inline_container == 0) { /* this is the first inline node: make a container */ inline_container = xcalloc(1, sizeof(struct box)); inline_container->type = BOX_INLINE_CONTAINER; + switch (parent->type) { + case BOX_TABLE: + /* insert implied table row and cell */ + style2 = xcalloc(1, sizeof(struct css_style)); + memcpy(style2, parent_style, sizeof(struct css_style)); + css_cascade(style2, &css_blank_style); + box = box_create(0, BOX_TABLE_ROW, style2); + box_add_child(parent, box); + parent = box; + /* fall through */ + case BOX_TABLE_ROW: + /* insert implied table cell */ + style2 = xcalloc(1, sizeof(struct css_style)); + memcpy(style2, parent_style, sizeof(struct css_style)); + css_cascade(style2, &css_blank_style); + box = box_create(0, BOX_TABLE_CELL, style2); + box->colspan = 1; + box_add_child(parent, box); + parent = box; + break; + case BOX_BLOCK: + case BOX_TABLE_CELL: + case BOX_FLOAT: + break; + default: + assert(0); + } box_add_child(parent, inline_container); } box = calloc(1, sizeof(struct box)); @@ -102,10 +142,34 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css } else if (n->type == XML_ELEMENT_NODE) { switch (style->display) { case CSS_DISPLAY_BLOCK: /* blocks get a node in the box tree */ - box = xcalloc(1, sizeof(struct box)); - box->node = n; - box->type = BOX_BLOCK; - box->style = style; + switch (parent->type) { + case BOX_TABLE: + /* insert implied table row and cell */ + style2 = xcalloc(1, sizeof(struct css_style)); + memcpy(style2, parent_style, sizeof(struct css_style)); + css_cascade(style2, &css_blank_style); + box = box_create(0, BOX_TABLE_ROW, style2); + box_add_child(parent, box); + parent = box; + /* fall through */ + case BOX_TABLE_ROW: + /* insert implied table cell */ + style2 = xcalloc(1, sizeof(struct css_style)); + memcpy(style2, parent_style, sizeof(struct css_style)); + css_cascade(style2, &css_blank_style); + box = box_create(0, BOX_TABLE_CELL, style2); + box->colspan = 1; + box_add_child(parent, box); + parent = box; + break; + case BOX_BLOCK: + case BOX_TABLE_CELL: + case BOX_FLOAT: + break; + default: + assert(0); + } + box = box_create(n, BOX_BLOCK, style); box_add_child(parent, box); inline_container_c = 0; for (c = n->children; c != 0; c = c->next) @@ -119,10 +183,7 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css selector, depth + 1, parent, inline_container); break; case CSS_DISPLAY_TABLE: - box = xcalloc(1, sizeof(struct box)); - box->node = n; - box->type = BOX_TABLE; - box->style = style; + box = box_create(n, BOX_TABLE, style); box_add_child(parent, box); for (c = n->children; c != 0; c = c->next) xml_to_box(c, style, stylesheet, @@ -130,11 +191,17 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css inline_container = 0; break; case CSS_DISPLAY_TABLE_ROW: + if (parent->type != BOX_TABLE) { + /* insert implied table */ + style2 = xcalloc(1, sizeof(struct css_style)); + memcpy(style2, parent_style, sizeof(struct css_style)); + css_cascade(style2, &css_blank_style); + box = box_create(0, BOX_TABLE, style2); + box_add_child(parent, box); + parent = box; + } assert(parent->type == BOX_TABLE); - box = xcalloc(1, sizeof(struct box)); - box->node = n; - box->type = BOX_TABLE_ROW; - box->style = style; + box = box_create(n, BOX_TABLE_ROW, style); box_add_child(parent, box); for (c = n->children; c != 0; c = c->next) xml_to_box(c, style, stylesheet, @@ -143,10 +210,12 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css break; case CSS_DISPLAY_TABLE_CELL: assert(parent->type == BOX_TABLE_ROW); - box = xcalloc(1, sizeof(struct box)); - box->node = n; - box->type = BOX_TABLE_CELL; - box->style = style; + box = box_create(n, BOX_TABLE_CELL, style); + if ((s = (char *) xmlGetProp(n, (xmlChar *) "colspan"))) { + if ((box->colspan = strtol(s, 0, 10)) == 0) + box->colspan = 1; + } else + box->colspan = 1; box_add_child(parent, box); inline_container_c = 0; for (c = n->children; c != 0; c = c->next) @@ -221,16 +290,19 @@ void box_dump(struct box * box, unsigned int depth) fprintf(stderr, "x%li y%li w%li h%li ", box->x, box->y, box->width, box->height); switch (box->type) { - case BOX_BLOCK: fprintf(stderr, "BOX_BLOCK <%s> ", box->node->name); break; + case BOX_BLOCK: fprintf(stderr, "BOX_BLOCK "); break; case BOX_INLINE_CONTAINER: fprintf(stderr, "BOX_INLINE_CONTAINER "); break; case BOX_INLINE: fprintf(stderr, "BOX_INLINE '%.*s' ", (int) box->length, box->text); break; - case BOX_TABLE: fprintf(stderr, "BOX_TABLE <%s> ", box->node->name); break; - case BOX_TABLE_ROW: fprintf(stderr, "BOX_TABLE_ROW <%s> ", box->node->name); break; - case BOX_TABLE_CELL: fprintf(stderr, "BOX_TABLE_CELL <%s> ", box->node->name); break; - case BOX_FLOAT: fprintf(stderr, "BOX_FLOAT <%s> ", box->node->name); break; + case BOX_TABLE: fprintf(stderr, "BOX_TABLE "); break; + case BOX_TABLE_ROW: fprintf(stderr, "BOX_TABLE_ROW "); break; + case BOX_TABLE_CELL: fprintf(stderr, "BOX_TABLE_CELL [colspan %i] ", + box->colspan); break; + case BOX_FLOAT: fprintf(stderr, "BOX_FLOAT "); break; default: fprintf(stderr, "Unknown box type "); } + if (box->node) + fprintf(stderr, "<%s> ", box->node->name); if (box->style) css_dump_style(box->style); fprintf(stderr, "\n"); diff --git a/render/box.h b/render/box.h index 0aa8e56f3..76a3e69ac 100644 --- a/render/box.h +++ b/render/box.h @@ -1,19 +1,24 @@ /** - * $Id: box.h,v 1.3 2002/06/18 21:24:21 bursa Exp $ + * $Id: box.h,v 1.4 2002/06/26 23:27:30 bursa Exp $ */ /** * structures */ +typedef enum { + BOX_BLOCK, BOX_INLINE_CONTAINER, BOX_INLINE, + BOX_TABLE, BOX_TABLE_ROW, BOX_TABLE_CELL, BOX_FLOAT +} box_type; + struct box { - enum { BOX_BLOCK, BOX_INLINE_CONTAINER, BOX_INLINE, - BOX_TABLE, BOX_TABLE_ROW, BOX_TABLE_CELL, BOX_FLOAT } type; + box_type type; xmlNode * node; struct css_style * style; unsigned long x, y, width, height; const char * text; unsigned int length; + unsigned int colspan; struct box * next; struct box * children; struct box * last; diff --git a/render/css.h b/render/css.h index 5869ad832..c01d20ada 100644 --- a/render/css.h +++ b/render/css.h @@ -1,5 +1,5 @@ /** - * $Id: css.h,v 1.5 2002/06/21 18:16:24 bursa Exp $ + * $Id: css.h,v 1.6 2002/06/26 23:27:30 bursa Exp $ */ #include "css_enum.h" @@ -76,6 +76,7 @@ struct css_selector { extern const struct css_style css_base_style; extern const struct css_style css_empty_style; +extern const struct css_style css_blank_style; /** * interface diff --git a/render/layout.c b/render/layout.c index 45a51bd88..5b7de47ce 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1,5 +1,5 @@ /** - * $Id: layout.c,v 1.9 2002/06/26 12:19:24 bursa Exp $ + * $Id: layout.c,v 1.10 2002/06/26 23:27:30 bursa Exp $ */ #include @@ -327,13 +327,13 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long /* the last box went over the end */ char * space = strchr(c->text, ' '); char * space2 = space; - unsigned long w, wp = w; + unsigned long w, wp; struct box * c2; if (space == 0) - w = font_width(c->style, c->text, c->length); + wp = w = font_width(c->style, c->text, c->length); else - w = font_width(c->style, c->text, space - c->text); + wp = w = font_width(c->style, c->text, space - c->text); if (x1 - x0 < xp + w && left == 0 && right == 0 && c == first) { /* first word doesn't fit, but no floats and first on line so force in */ @@ -447,6 +447,7 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, unsigned long y = 0; unsigned long * xs; unsigned int i; + unsigned int subcol; struct box * c; struct box * r; @@ -479,10 +480,10 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, break; case CSS_WIDTH_AUTO: default: - auto_columns++; + auto_columns += c->colspan; break; } - columns++; + columns += c->colspan; } if (auto_columns == 0 && table->style->width.width != CSS_WIDTH_AUTO) @@ -495,13 +496,14 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, /* find column widths */ xs = xcalloc(columns + 1, sizeof(*xs)); xs[0] = x = 0; - for (i = 1, c = table->children->children; c != 0; i++, c = c->next) { + for (i = 1, c = table->children->children, subcol = 1; c != 0; i++) { switch (c->style->width.width) { case CSS_WIDTH_LENGTH: - x += len(&c->style->width.value.length, c->style) + extra_width; + x += len(&c->style->width.value.length, c->style) / c->colspan + extra_width; break; case CSS_WIDTH_PERCENT: - x += table_width * c->style->width.value.percent / 100 + extra_width; + x += table_width * c->style->width.value.percent / 100 / c->colspan + + extra_width; break; case CSS_WIDTH_AUTO: default: @@ -509,6 +511,11 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, break; } xs[i] = x; + if (subcol == c->colspan) + c = c->next, + subcol = 1; + else + subcol++; /*printf("%i ", x);*/ } /*printf("\n");*/ @@ -519,8 +526,8 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, /* position cells */ for (r = table->children; r != 0; r = r->next) { unsigned long height = 0; - for (i = 0, c = r->children; c != 0; i++, c = c->next) { - c->width = xs[i+1] - xs[i]; + for (i = 0, c = r->children; c != 0; i += c->colspan, c = c->next) { + c->width = xs[i + c->colspan] - xs[i]; c->float_children = 0; c->height = layout_block_children(c, c->width, c, 0, 0); switch (c->style->height.height) { diff --git a/render/render.c b/render/render.c index 6a92d45cf..e4d5b1b76 100644 --- a/render/render.c +++ b/render/render.c @@ -1,5 +1,5 @@ /** - * $Id: render.c,v 1.15 2002/06/26 12:19:24 bursa Exp $ + * $Id: render.c,v 1.16 2002/06/26 23:27:30 bursa Exp $ */ #include @@ -102,7 +102,7 @@ void render_dump(struct box * box, unsigned long x, unsigned long y) case BOX_TABLE_ROW: case BOX_TABLE_CELL: case BOX_FLOAT: - case BOX_BLOCK: name = (const char *) box->node->name; + case BOX_BLOCK: if (box->node) name = (const char *) box->node->name; break; case BOX_INLINE: case BOX_INLINE_CONTAINER: @@ -117,6 +117,10 @@ void render_dump(struct box * box, unsigned long x, unsigned long y) for (i = 0; i < box->length; i++) { if (box->text[i] == '"') printf("\\\""); + else if (box->text[i] == '[') + printf("\\["); + else if (box->text[i] == '$') + printf("\\$"); else printf("%c", box->text[i]); } diff --git a/render/test/test1.css b/render/test/test1.css index 2158e3a7a..faf1354b8 100644 --- a/render/test/test1.css +++ b/render/test/test1.css @@ -3,10 +3,10 @@ html { font-size: medium } address, blockquote, body, dd, div, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, html, -object, ol, p, ul +object, ol, p, ul, hr, menu, pre { display: block } -a, abbr, acronym, b, code -em, i, q, s, strong, u, +a, abbr, acronym, b, code, +em, i, q, s, strong, u, font, span, var { display: inline } li { display: list-item } head { display: none } -- cgit v1.2.3