diff --git a/render/box.c b/render/box.c index 79327602d..3fc6348d9 100644 --- a/render/box.c +++ b/render/box.c @@ -1,5 +1,5 @@ /** - * $Id: box.c,v 1.5 2002/06/18 21:24:21 bursa Exp $ + * $Id: box.c,v 1.6 2002/06/21 18:16:24 bursa Exp $ */ #include @@ -176,6 +176,12 @@ struct css_style * box_get_style(struct css_stylesheet * stylesheet, struct css_ memcpy(style, parent_style, sizeof(struct css_style)); css_get_style(stylesheet, selector, depth, style); + if ((s = xmlGetProp(n, "clear"))) { + if (strcmp(s, "all") == 0) style->clear = CSS_CLEAR_BOTH; + else if (strcmp(s, "left") == 0) style->clear = CSS_CLEAR_LEFT; + else if (strcmp(s, "right") == 0) style->clear = CSS_CLEAR_RIGHT; + } + if ((s = xmlGetProp(n, "width"))) { if (strrchr(s, '%')) style->width.width = CSS_WIDTH_PERCENT, @@ -216,7 +222,8 @@ void box_dump(struct box * box, unsigned int depth) switch (box->type) { case BOX_BLOCK: fprintf(stderr, "BOX_BLOCK <%s> ", box->node->name); break; case BOX_INLINE_CONTAINER: fprintf(stderr, "BOX_INLINE_CONTAINER "); break; - case BOX_INLINE: fprintf(stderr, "BOX_INLINE '%.*s' ", box->length, box->text); 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; diff --git a/render/css.c b/render/css.c index 6e36bfeed..73af7fbb3 100644 --- a/render/css.c +++ b/render/css.c @@ -1,5 +1,5 @@ /** - * $Id: css.c,v 1.5 2002/06/19 15:17:45 bursa Exp $ + * $Id: css.c,v 1.6 2002/06/21 18:16:24 bursa Exp $ */ #include @@ -31,6 +31,7 @@ struct css_stylesheet { }; static int parse_length(struct css_length * const length, const char *s); +static void parse_clear(struct css_style * const style, const char * const value); static void parse_display(struct css_style * const style, const char * const value); static void parse_float(struct css_style * const style, const char * const value); static void parse_font_size(struct css_style * const style, const char * const value); @@ -51,33 +52,36 @@ static void dump_selector(const struct css_selector * const sel); static void dump_rule(const struct rule * rule); const struct css_style css_base_style = { + CSS_CLEAR_NONE, CSS_DISPLAY_BLOCK, CSS_FLOAT_NONE, - { CSS_FONT_SIZE_LENGTH, {12, CSS_UNIT_PT} }, - { CSS_HEIGHT_AUTO }, - { CSS_LINE_HEIGHT_ABSOLUTE, 1.2 }, + { CSS_FONT_SIZE_LENGTH, { { 12, CSS_UNIT_PT } } }, + { CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } }, + { CSS_LINE_HEIGHT_ABSOLUTE, { 1.2 } }, CSS_TEXT_ALIGN_LEFT, - { CSS_WIDTH_AUTO } + { CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } } }; const struct css_style css_empty_style = { + CSS_CLEAR_INHERIT, CSS_DISPLAY_INHERIT, CSS_FLOAT_INHERIT, - { CSS_FONT_SIZE_INHERIT }, - { CSS_HEIGHT_AUTO }, - { CSS_LINE_HEIGHT_INHERIT }, + { CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } }, + { CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } }, + { CSS_LINE_HEIGHT_INHERIT, { 1.2 } }, CSS_TEXT_ALIGN_INHERIT, - { CSS_WIDTH_INHERIT } + { CSS_WIDTH_INHERIT, { { 1, CSS_UNIT_EM } } } }; const struct css_style css_blank_style = { + CSS_CLEAR_NONE, CSS_DISPLAY_BLOCK, CSS_FLOAT_NONE, - { CSS_FONT_SIZE_INHERIT }, - { CSS_HEIGHT_AUTO }, - { CSS_LINE_HEIGHT_INHERIT }, + { CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } }, + { CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } }, + { CSS_LINE_HEIGHT_INHERIT, { 1.2 } }, CSS_TEXT_ALIGN_INHERIT, - { CSS_WIDTH_AUTO } + { CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } } }; @@ -94,6 +98,11 @@ static int parse_length(struct css_length * const length, const char *s) return 0; } +static void parse_clear(struct css_style * const style, const char * const value) +{ + style->clear = css_clear_parse(value); +} + static void parse_display(struct css_style * const style, const char * const value) { style->display = css_display_parse(value); @@ -183,6 +192,7 @@ static struct property { const char * const name; void (*parse) (struct css_style * const s, const char * const value); } const property[] = { + { "clear", parse_clear }, { "display", parse_display }, { "float", parse_float }, { "font-size", parse_font_size }, @@ -464,6 +474,7 @@ static void dump_length(const struct css_length * const length) void css_dump_style(const struct css_style * const style) { fprintf(stderr, "{ "); + fprintf(stderr, "clear: %s; ", css_clear_name[style->clear]); fprintf(stderr, "display: %s; ", css_display_name[style->display]); fprintf(stderr, "float: %s; ", css_float_name[style->float_]); fprintf(stderr, "font-size: "); @@ -539,9 +550,10 @@ void css_dump_stylesheet(const struct css_stylesheet * stylesheet) void css_cascade(struct css_style * const style, const struct css_style * const apply) { float f; + if (apply->clear != CSS_CLEAR_INHERIT) style->clear = apply->clear; if (apply->display != CSS_DISPLAY_INHERIT) style->display = apply->display; if (apply->float_ != CSS_FLOAT_INHERIT) style->float_ = apply->float_; - style->height = apply->height; + if (apply->height.height != CSS_HEIGHT_INHERIT) style->height = apply->height; if (apply->text_align != CSS_TEXT_ALIGN_INHERIT) style->text_align = apply->text_align; if (apply->width.width != CSS_WIDTH_INHERIT) style->width = apply->width; diff --git a/render/css.h b/render/css.h index b1429e33e..5869ad832 100644 --- a/render/css.h +++ b/render/css.h @@ -1,5 +1,5 @@ /** - * $Id: css.h,v 1.4 2002/06/19 15:17:45 bursa Exp $ + * $Id: css.h,v 1.5 2002/06/21 18:16:24 bursa Exp $ */ #include "css_enum.h" @@ -17,6 +17,7 @@ struct css_length { }; struct css_style { + css_clear clear; css_display display; css_float float_; @@ -26,14 +27,15 @@ struct css_style { CSS_FONT_SIZE_LENGTH, CSS_FONT_SIZE_PERCENT } size; union { - float absolute; struct css_length length; + float absolute; float percent; } value; } font_size; struct { - enum { CSS_HEIGHT_AUTO, + enum { CSS_HEIGHT_INHERIT, + CSS_HEIGHT_AUTO, CSS_HEIGHT_LENGTH } height; struct css_length length; } height; diff --git a/render/css_enums b/render/css_enums index 0f5b7a87e..8417e8d7e 100644 --- a/render/css_enums +++ b/render/css_enums @@ -4,7 +4,7 @@ css_background_position inherit top center bottom left right length percent css_background_repeat inherit repeat repeat_x repeat_y no_repeat css_border_width inherit medium thin thick length css_border_style inherit none dashed dotted double groove inset outset ridge solid -css_clear none both left right +css_clear inherit none both left right css_display inherit inline block list-item run-in compact marker table inline-table table-row-group table-header-group table-footer-group table-row table-column-group table-column table-cell table-caption none css_float inherit none left right css_font_style normal italic oblique diff --git a/render/layout.c b/render/layout.c index d208fdd24..c47211879 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1,5 +1,5 @@ /** - * $Id: layout.c,v 1.7 2002/06/19 15:17:45 bursa Exp $ + * $Id: layout.c,v 1.8 2002/06/21 18:16:24 bursa Exp $ */ #include @@ -91,16 +91,17 @@ void layout_block(struct box * box, unsigned long width, struct box * cont, assert(box->type == BOX_BLOCK || box->type == BOX_FLOAT); switch (style->width.width) { - case CSS_WIDTH_AUTO: - /* take all available width */ - box->width = width; - break; case CSS_WIDTH_LENGTH: box->width = len(&style->width.value.length, box->style); break; case CSS_WIDTH_PERCENT: box->width = width * style->width.value.percent / 100; break; + case CSS_WIDTH_AUTO: + default: + /* take all available width */ + box->width = width; + break; } box->height = layout_block_children(box, box->width, cont, cx, cy); switch (style->height.height) { @@ -129,6 +130,25 @@ unsigned long layout_block_children(struct box * box, unsigned long width, struc assert(box->type == BOX_BLOCK || box->type == BOX_FLOAT || box->type == BOX_TABLE_CELL); for (c = box->children; c != 0; c = c->next) { + if (c->style && c->style->clear != CSS_CLEAR_NONE) { + unsigned long x0, x1; + struct box * left, * right; + do { + x0 = cx; + x1 = cx + width; + find_sides(cont->float_children, cy + y, cy + y, + &x0, &x1, &left, &right); + if ((c->style->clear == CSS_CLEAR_LEFT || c->style->clear == CSS_CLEAR_BOTH) + && left != 0) + y = left->y + left->height - cy + 1; + if ((c->style->clear == CSS_CLEAR_RIGHT || c->style->clear == CSS_CLEAR_BOTH) + && right != 0) + if (cy + y < right->y + right->height + 1) + y = right->y + right->height - cy + 1; + } while ((c->style->clear == CSS_CLEAR_LEFT && left != 0) || + (c->style->clear == CSS_CLEAR_RIGHT && right != 0) || + (c->style->clear == CSS_CLEAR_BOTH && (left != 0 || right != 0))); + } switch (c->type) { case BOX_BLOCK: layout_block(c, width, cont, cx, cy + y); @@ -172,6 +192,7 @@ unsigned long layout_block_children(struct box * box, unsigned long width, struc void find_sides(struct box * fl, unsigned long y0, unsigned long y1, unsigned long * x0, unsigned long * x1, struct box ** left, struct box ** right) { +/* fprintf(stderr, "find_sides: y0 %li y1 %li x0 %li x1 %li => ", y0, y1, *x0, *x1); */ *left = *right = 0; for (; fl; fl = fl->next_float) { if (y0 <= fl->y + fl->height && fl->y <= y1) { @@ -184,7 +205,7 @@ void find_sides(struct box * fl, unsigned long y0, unsigned long y1, } } } -/* fprintf(stderr, "find_sides: y0 %li y1 %li => x0 %li x1 %li\n", y0, y1, *x0, *x1); */ +/* fprintf(stderr, "x0 %li x1 %li left 0x%x right 0x%x\n", *x0, *x1, *left, *right); */ } @@ -238,6 +259,7 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long struct box * b; struct box * c; struct box * d; + int move_y = 0; /* fprintf(stderr, "layout_line: '%.*s' %li %li %li\n", first->length, first->text, width, *y, cy); */ @@ -259,20 +281,23 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long } /* find new sides using this height */ + x0 = 0; + x1 = width; find_sides(cont->float_children, cy, cy + height, &x0, &x1, &left, &right); /* pass 2: place boxes in line */ - for (x = xp = 0, b = first; x < x1 - x0 && b != 0; b = b->next) { + for (x = xp = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) { if (b->type == BOX_INLINE) { b->x = x; xp = x; b->width = font_width(b->style, b->text, b->length); x += b->width; c = b; + move_y = 1; /* fprintf(stderr, "layout_line: '%.*s' %li %li\n", b->length, b->text, xp, x); */ } else { b->float_children = 0; - css_dump_style(b->style); +/* css_dump_style(b->style); */ layout_block(b, width, b, 0, 0); if (b->width < (x1 - x0) - x || (left == 0 && right == 0 && x == 0)) { /* fits next to this line, or this line is empty with no floats */ @@ -302,18 +327,27 @@ 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 = font_width(c->style, c->text, space - c->text), wp = w; + unsigned long w, wp = w; struct box * c2; + if (space == 0) + w = font_width(c->style, c->text, c->length); + else + 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 */ - c2 = memcpy(xcalloc(1, sizeof(struct box)), c, sizeof(struct box)); - c2->text = space + 1; - c2->length = c->length - (c2->text - c->text); - c->length = space - c->text; - c2->next = c->next; - c->next = c2; - b = c2; + if (space == 0) { + b = c->next; + } else { + c2 = memcpy(xcalloc(1, sizeof(struct box)), c, sizeof(struct box)); + c2->text = space + 1; + c2->length = c->length - (c2->text - c->text); + c->length = space - c->text; + c2->next = c->next; + c->next = c2; + b = c2; + } /* fprintf(stderr, "layout_line: overflow, forcing\n"); */ } else if (x1 - x0 < xp + w) { /* first word doesn't fit, but full width not available so leave for later */ @@ -321,6 +355,7 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long /* fprintf(stderr, "layout_line: overflow, leaving\n"); */ } else { /* fit as many words as possible */ + assert(space != 0); while (xp + w < x1 - x0) { /* fprintf(stderr, "%li + %li = %li < %li = %li - %li\n", */ /* xp, w, xp + w, x1 - x0, x1, x0); */ @@ -340,6 +375,7 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long } c->width = wp; x = xp + wp; + move_y = 1; } /* set positions */ @@ -355,7 +391,7 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long } } - *y += height + 1; + if (move_y) *y += height + 1; return b; } @@ -442,6 +478,7 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, used_width += table_width * c->style->width.value.percent / 100; break; case CSS_WIDTH_AUTO: + default: auto_columns++; break; } @@ -467,6 +504,7 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, x += table_width * c->style->width.value.percent / 100 + extra_width; break; case CSS_WIDTH_AUTO: + default: x += auto_width; break; } diff --git a/render/render.c b/render/render.c index 66009fe65..7e31f4c65 100644 --- a/render/render.c +++ b/render/render.c @@ -1,5 +1,5 @@ /** - * $Id: render.c,v 1.13 2002/06/18 21:24:21 bursa Exp $ + * $Id: render.c,v 1.14 2002/06/21 18:16:24 bursa Exp $ */ #include @@ -20,6 +20,7 @@ void render_plain_element(char * g, struct box * box, unsigned long x, unsigned long y); void render_plain(struct box * box); +void render_dump(struct box * box, unsigned long x, unsigned long y); /** @@ -108,7 +109,7 @@ void render_dump(struct box * box, unsigned long x, unsigned long y) printf("rect %li %li %li %li \"%s\" \"", x + box->x, y + box->y, box->width, box->height, name); if (box->type == BOX_INLINE) { - int i; + unsigned int i; for (i = 0; i < box->length; i++) { if (box->text[i] == '"') printf("\\\""); diff --git a/utils/utils.c b/utils/utils.c index 857c205c1..ffdf029ae 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -1,5 +1,5 @@ /** - * $Id: utils.c,v 1.3 2002/06/18 21:24:21 bursa Exp $ + * $Id: utils.c,v 1.4 2002/06/21 18:16:24 bursa Exp $ */ #include @@ -63,10 +63,10 @@ char * load(const char * const path) if (fp == 0) die("Failed to open file"); if (fseek(fp, 0, SEEK_END) != 0) die("fseek() failed"); if ((size = ftell(fp)) == -1) die("ftell() failed"); - buf = xcalloc(size, 1); + buf = xcalloc((size_t) size, 1); if (fseek(fp, 0, SEEK_SET) != 0) die("fseek() failed"); - read = fread(buf, 1, size, fp); + read = fread(buf, 1, (size_t) size, fp); if (read < size) die("fread() failed"); return buf;