summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--render/box.c103
-rw-r--r--render/layout.c6
-rw-r--r--utils/utils.c25
-rw-r--r--utils/utils.h1
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);