From bbcdf13fe04bc56a3671db581df40307e65b81da Mon Sep 17 00:00:00 2001 From: James Bursa Date: Tue, 7 Oct 2003 21:34:39 +0000 Subject: [project @ 2003-10-07 21:34:39 by bursa] Implement white-space property. svn path=/import/netsurf/; revision=348 --- render/box.c | 103 ++++++++++++++++++++++++++++++++++++++++++-------------- render/layout.c | 6 +++- utils/utils.c | 25 ++++++++++++++ utils/utils.h | 1 + 4 files changed, 108 insertions(+), 27 deletions(-) diff --git a/render/box.c b/render/box.c index b0a5c85d1..24b559132 100644 --- a/render/box.c +++ b/render/box.c @@ -256,7 +256,6 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, struct css_style * style = 0; xmlNode * c; char * s; - char * text = 0; xmlChar * title0; char * title = 0; int convert_children = 1; @@ -320,7 +319,20 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, box->type = box_map[style->display]; } else if (n->type == XML_TEXT_NODE) { - text = squash_tolat1(n->content); + /* text node: added to inline container below */ + + } else { + /* not an element or text node: ignore it (eg. comment) */ + LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); + goto end; + } + + content->size += sizeof(struct box) + sizeof(struct css_style); + + if (n->type == XML_TEXT_NODE && + (parent_style->white_space == CSS_WHITE_SPACE_NORMAL || + parent_style->white_space == CSS_WHITE_SPACE_NOWRAP)) { + char *text = squash_tolat1(n->content); /* if the text is just a space, combine it with the preceding * text node, if any */ @@ -330,32 +342,79 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, inline_container->last->space = 1; } xfree(text); - LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); goto end; } - /* text nodes are converted to inline boxes */ + if (inline_container == 0) { + /* this is the first inline node: make a container */ + inline_container = box_create(0, 0, 0); + inline_container->type = BOX_INLINE_CONTAINER; + box_add_child(parent, inline_container); + } + box = box_create(parent_style, status.href, title); + box->text = text; box->style_clone = 1; box->length = strlen(text); if (text[box->length - 1] == ' ') { box->space = 1; box->length--; } - box->text = text; + if (parent_style->white_space == CSS_WHITE_SPACE_NOWRAP) { + int i; + for (i = 0; i != box->length; i++) + if (text[i] == ' ') + text[i] = 160; + } box->font = font_open(content->data.html.fonts, box->style); - } else { - /* not an element or text node: ignore it (eg. comment) */ - LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); + box_add_child(inline_container, box); + if (text[0] == ' ') { + box->length--; + memmove(text, text + 1, box->length); + if (box->prev != 0) + box->prev->space = 1; + } goto end; - } - content->size += sizeof(struct box) + sizeof(struct css_style); - assert(box != 0); + } else if (n->type == XML_TEXT_NODE) { + /* white-space: pre */ + char *text = tolat1_pre(n->content); + char *current; + bool first = true; + assert(parent_style->white_space == CSS_WHITE_SPACE_PRE); + for (current = text; *current; current++) + if (*current == ' ' || *current == '\t') + *current = 160; + current = text; + do { + size_t len = strcspn(current, "\r\n"); + char old = current[len]; + current[len] = 0; + if (!first || !inline_container) { + inline_container = box_create(0, 0, 0); + inline_container->type = BOX_INLINE_CONTAINER; + } + first = false; + box = box_create(parent_style, status.href, title); + box->type = BOX_INLINE; + box->style_clone = 1; + box->text = xstrdup(current); + box->length = strlen(box->text); + box->font = font_open(content->data.html.fonts, box->style); + box_add_child(inline_container, box); + box_add_child(parent, inline_container); + current[len] = old; + current += len; + if (current[0] == '\r' && current[1] == '\n') + current += 2; + else if (current[0] == '\n') + current++; + } while (*current); + xfree(text); + goto end; - if (text != 0 || - box->type == BOX_INLINE || + } else if (box->type == BOX_INLINE || box->type == BOX_INLINE_BLOCK || style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT) { @@ -367,18 +426,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, box_add_child(parent, inline_container); } - if (text != 0) { - /* text box */ - box_add_child(inline_container, box); - if (text[0] == ' ') { - box->length--; - memmove(text, text + 1, box->length); - if (box->prev != 0) - box->prev->space = 1; - } - LOG(("depth %i, node %p, node type %i END", depth, n, n->type)); - goto end; - } else if (box->type == BOX_INLINE) { + if (box->type == BOX_INLINE) { /* inline box: add to tree and recurse */ box_add_child(inline_container, box); if (convert_children) { @@ -711,7 +759,10 @@ struct result box_textarea(xmlNode *n, struct status *status, box_add_child(box, inline_container); current[len] = old; current += len; - current += strspn(current, "\r\n"); + if (current[0] == '\r' && current[1] == '\n') + current += 2; + else if (current[0] == '\n') + current++; } while (*current); xmlFree(content); diff --git a/render/layout.c b/render/layout.c index 2c3d04e05..7474f2755 100644 --- a/render/layout.c +++ b/render/layout.c @@ -838,7 +838,6 @@ void calculate_inline_container_widths(struct box *box) { struct box *child; unsigned long min = 0, max = 0, width; - char *word, *space; int i, j; for (child = box->children; child != 0; child = child->next) { @@ -907,6 +906,11 @@ void calculate_inline_container_widths(struct box *box) } } + if (box->parent && box->parent->style && + (box->parent->style->white_space == CSS_WHITE_SPACE_PRE || + box->parent->style->white_space == CSS_WHITE_SPACE_NOWRAP)) + min = max; + assert(min <= max); box->min_width = min; box->max_width = max; diff --git a/utils/utils.c b/utils/utils.c index a62f7256a..bc912fdc7 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -129,6 +129,31 @@ char * tolat1(xmlChar * s) return d0; } +char * tolat1_pre(xmlChar * s) +{ + unsigned int length = strlen((char*) s); + char *d = xcalloc(length + 1, sizeof(char)); + char *d0 = d; + int u, chars; + + while (*s != 0) { + chars = length; + u = xmlGetUTF8Char((unsigned char *) s, &chars); + s += chars; + length -= chars; + if (u == 0x09 || u == 0x0a || u == 0x0d || + (0x20 <= u && u <= 0x7f) || + (0xa0 <= u && u <= 0xff)) + *d = u; + else + *d = '?'; + d++; + } + *d = 0; + + return d0; +} + char *squash_tolat1(xmlChar *s) { /* TODO: optimize */ diff --git a/utils/utils.h b/utils/utils.h index 3e491648e..9403d194e 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -21,6 +21,7 @@ char * xstrdup(const char * const s); char * load(const char * const path); char * squash_whitespace(const char * s); char * tolat1(xmlChar * s); +char * tolat1_pre(xmlChar * s); char *squash_tolat1(xmlChar *s); char *url_join(const char* new, const char* base); -- cgit v1.2.3