diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/box.c | 190 | ||||
-rw-r--r-- | render/font.h | 37 | ||||
-rw-r--r-- | render/html.c | 36 | ||||
-rw-r--r-- | render/layout.c | 10 |
4 files changed, 175 insertions, 98 deletions
diff --git a/render/box.c b/render/box.c index 737a6fb93..b1f2edeb5 100644 --- a/render/box.c +++ b/render/box.c @@ -110,7 +110,7 @@ static struct box_result box_button(xmlNode *n, struct box_status *status, struct css_style *style); static struct box_result box_frameset(xmlNode *n, struct box_status *status, struct css_style *style); -static void add_option(xmlNode* n, struct form_control* current_select, char *text); +static void add_option(xmlNode* n, struct form_control* current_select, const char *text); static void box_normalise_block(struct box *block, pool box_pool); static void box_normalise_table(struct box *table, pool box_pool); void box_normalise_table_row_group(struct box *row_group, @@ -259,7 +259,7 @@ void xml_to_box(xmlNode *n, struct content *c) c->data.html.style = xcalloc(1, sizeof(struct css_style)); memcpy(c->data.html.style, &css_base_style, sizeof(struct css_style)); c->data.html.style->font_size.value.length.value = option_font_size * 0.1; - c->data.html.fonts = font_new_set(); + c->data.html.fonts = nsfont_new_set(); c->data.html.object_count = 0; c->data.html.object = xcalloc(0, sizeof(*c->data.html.object)); @@ -346,7 +346,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, /* extract title attribute, if present */ if ((title0 = xmlGetProp(n, (const xmlChar *) "title"))) { - status.title = title = squash_tolat1(title0); + status.title = title = squash_whitespace(title0); xmlFree(title0); } @@ -392,7 +392,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, 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); + char *text = squash_whitespace(n->content); /* if the text is just a space, combine it with the preceding * text node, if any */ @@ -418,7 +418,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, box->text = text; box->style_clone = 1; box->length = strlen(text); - if (text[box->length - 1] == ' ') { + /* strip ending space char off */ + if (box->length > 1 && text[box->length - 1] == ' ') { box->space = 1; box->length--; } @@ -427,32 +428,38 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, parent_style->text_transform); if (parent_style->white_space == CSS_WHITE_SPACE_NOWRAP) { unsigned int i; - for (i = 0; i != box->length; i++) - if (text[i] == ' ') - text[i] = 160; + for (i = 0; i != box->length && text[i] != ' '; ++i) + /* no body */; + if (i != box->length) { + /* there is a space in text block and we + * want all spaces to be converted to NBSP + */ + char *org_text = box->text; + org_text[box->length] = '\0'; + box->text = cnv_space2nbsp(org_text); + free(org_text); + box->length = strlen(box->text); + } } - box->font = font_open(content->data.html.fonts, box->style); + box->font = nsfont_open(content->data.html.fonts, box->style); box_add_child(inline_container, box); - if (text[0] == ' ') { + if (box->text[0] == ' ') { box->length--; - memmove(text, text + 1, box->length); - if (box->prev != 0) + memmove(box->text, &box->text[1], box->length); + if (box->prev != NULL) box->prev->space = 1; } goto end; } else if (n->type == XML_TEXT_NODE) { /* white-space: pre */ - char *text = tolat1_pre(n->content); + char *text = cnv_space2nbsp(n->content); char *current; assert(parent_style->white_space == CSS_WHITE_SPACE_PRE); if (parent_style->text_transform != CSS_TEXT_TRANSFORM_NONE) box_text_transform(text, strlen(text), parent_style->text_transform); - for (current = text; *current; current++) - if (*current == ' ' || *current == '\t') - *current = 160; current = text; do { size_t len = strcspn(current, "\r\n"); @@ -470,7 +477,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct content *content, box->style_clone = 1; box->text = xstrdup(current); box->length = strlen(box->text); - box->font = font_open(content->data.html.fonts, box->style); + box->font = nsfont_open(content->data.html.fonts, box->style); box_add_child(inline_container, box); current[len] = old; current += len; @@ -744,7 +751,7 @@ struct css_style * box_get_style(struct content *c, /** - * Apply the CSS text-transform property to some text. + * Apply the CSS text-transform property to given text for its ASCII chars. * * \param s string to transform * \param len length of s @@ -759,17 +766,20 @@ void box_text_transform(char *s, unsigned int len, return; switch (tt) { case CSS_TEXT_TRANSFORM_UPPERCASE: - for (i = 0; i != len; i++) - s[i] = toupper(s[i]); + for (i = 0; i < len; ++i) + if (s[i] < 0x80) + s[i] = toupper(s[i]); break; case CSS_TEXT_TRANSFORM_LOWERCASE: - for (i = 0; i != len; i++) - s[i] = tolower(s[i]); + for (i = 0; i < len; ++i) + if (s[i] < 0x80) + s[i] = tolower(s[i]); break; case CSS_TEXT_TRANSFORM_CAPITALIZE: - s[0] = toupper(s[0]); - for (i = 1; i != len; i++) - if (isspace(s[i - 1])) + if (s[0] < 0x80) + s[0] = toupper(s[0]); + for (i = 1; i < len; ++i) + if (s[i] < 0x80 && isspace(s[i - 1])) s[i] = toupper(s[i]); break; default: @@ -838,9 +848,9 @@ struct box_result box_image(xmlNode *n, struct box_status *status, /* handle alt text */ if ((s2 = xmlGetProp(n, (const xmlChar *) "alt"))) { - box->text = squash_tolat1(s2); + box->text = squash_whitespace(s2); box->length = strlen(box->text); - box->font = font_open(status->content->data.html.fonts, style); + box->font = nsfont_open(status->content->data.html.fonts, style); xmlFree(s2); } @@ -861,7 +871,6 @@ struct box_result box_image(xmlNode *n, struct box_status *status, /* remove leading and trailing whitespace */ s1 = strip(s); - url = url_join(s1, status->content->data.html.base_url); if (!url) { xmlFree(s); @@ -959,9 +968,16 @@ struct box_result box_textarea(xmlNode *n, struct box_status *status, status->content->data.html.box_pool); inline_box->type = BOX_INLINE; inline_box->style_clone = 1; - inline_box->text = tolat1(current); + if ((inline_box->text = strdup(current)) == NULL) { + box_free(inline_box); + box_free(inline_container); + box_free(box); + current[len] = old; + xmlFree(content); + return (struct box_result) {NULL, false, false}; + } inline_box->length = strlen(inline_box->text); - inline_box->font = font_open(status->content->data.html.fonts, style); + inline_box->font = nsfont_open(status->content->data.html.fonts, style); box_add_child(inline_container, inline_box); box_add_child(box, inline_container); current[len] = old; @@ -1009,14 +1025,14 @@ struct box_result box_select(xmlNode *n, struct box_status *status, for (c = n->children; c != 0; c = c->next) { if (strcmp((const char *) c->name, "option") == 0) { xmlChar *content = xmlNodeGetContent(c); - add_option(c, gadget, squash_tolat1(content)); + add_option(c, gadget, content); xmlFree(content); gadget->data.select.num_items++; } else if (strcmp((const char *) c->name, "optgroup") == 0) { for (c2 = c->children; c2; c2 = c2->next) { if (strcmp((const char *) c2->name, "option") == 0) { xmlChar *content = xmlNodeGetContent(c2); - add_option(c2, gadget, squash_tolat1(content)); + add_option(c2, gadget, content); xmlFree(content); gadget->data.select.num_items++; } @@ -1070,15 +1086,20 @@ struct box_result box_select(xmlNode *n, struct box_status *status, inline_box->text = xstrdup(messages_get("Form_Many")); inline_box->length = strlen(inline_box->text); - inline_box->font = font_open(status->content->data.html.fonts, style); + inline_box->font = nsfont_open(status->content->data.html.fonts, style); return (struct box_result) {box, false, false}; } -void add_option(xmlNode* n, struct form_control* current_select, char *text) +void add_option(xmlNode* n, struct form_control* current_select, const char *text) { struct form_option *option = xcalloc(1, sizeof(struct form_option)); - char *s, *c; + const char *s; + + if ((text = squash_whitespace(text)) == NULL) { + free(option); + return; + } assert(current_select != 0); @@ -1095,9 +1116,14 @@ void add_option(xmlNode* n, struct form_control* current_select, char *text) option->value = xstrdup(text); } - for (c = text; *c; c++) - if (*c == ' ') - *c = 160; + /* Convert all spaces into NBSP. */ + for (s = text; *s != '\0' && *s != ' '; ++s) + /* no body */; + if (*s == ' ') { + const char *org_text = text; + text = cnv_space2nbsp(org_text); + free(org_text); + } option->selected = option->initial_selected = false; option->text = text; @@ -1138,7 +1164,7 @@ struct box_result box_input(xmlNode *n, struct box_status *status, return (struct box_result) {0, false, true}; } gadget->box = box; - box->font = font_open(status->content->data.html.fonts, style); + box->font = nsfont_open(status->content->data.html.fonts, style); } else if (type && strcasecmp(type, "hidden") == 0) { /* no box for hidden inputs */ @@ -1199,14 +1225,21 @@ struct box_result box_input(xmlNode *n, struct box_status *status, status->content->data.html.box_pool); inline_box->type = BOX_INLINE; inline_box->style_clone = 1; - if (box->gadget->value) - inline_box->text = tolat1(box->gadget->value); + if (box->gadget->value != NULL) + inline_box->text = strdup(box->gadget->value); else if (box->gadget->type == GADGET_SUBMIT) - inline_box->text = xstrdup(messages_get("Form_Submit")); + inline_box->text = strdup(messages_get("Form_Submit")); else - inline_box->text = xstrdup(messages_get("Form_Reset")); + inline_box->text = strdup(messages_get("Form_Reset")); + if (inline_box->text == NULL) { + box_free(inline_box); + box_free(inline_container); + box_free(box); + xmlFree(type); + return (struct box_result) {NULL, false, false}; + } inline_box->length = strlen(inline_box->text); - inline_box->font = font_open(status->content->data.html.fonts, style); + inline_box->font = nsfont_open(status->content->data.html.fonts, style); box_add_child(inline_container, inline_box); box_add_child(box, inline_container); @@ -1228,7 +1261,7 @@ struct box_result box_input(xmlNode *n, struct box_status *status, inline_box->text = xstrdup("Button"); } inline_box->length = strlen(inline_box->text); - inline_box->font = font_open(status->content->data.html.fonts, style); + inline_box->font = nsfont_open(status->content->data.html.fonts, style); box_add_child(inline_container, inline_box); box_add_child(box, inline_container); @@ -1286,7 +1319,6 @@ struct box *box_input_text(xmlNode *n, struct box_status *status, struct css_style *style, bool password) { char *s; - unsigned int i; struct box *box = box_create(style, 0, 0, status->content->data.html.box_pool); struct box *inline_container, *inline_box; @@ -1302,10 +1334,14 @@ struct box *box_input_text(xmlNode *n, struct box_status *status, } s = (char *) xmlGetProp(n, (const xmlChar *) "value"); - box->gadget->value = s ? tolat1(s) : xstrdup(""); - box->gadget->initial_value = xstrdup(box->gadget->value); + box->gadget->value = strdup((s != NULL) ? s : ""); + box->gadget->initial_value = strdup(box->gadget->value); if (s) xmlFree(s); + if (box->gadget->value == NULL || box->gadget->initial_value == NULL) { + box_free(box); + return NULL; + } inline_container = box_create(0, 0, 0, status->content->data.html.box_pool); @@ -1314,21 +1350,19 @@ struct box *box_input_text(xmlNode *n, struct box_status *status, status->content->data.html.box_pool); inline_box->type = BOX_INLINE; inline_box->style_clone = 1; - inline_box->length = strlen(box->gadget->value); if (password) { box->gadget->type = GADGET_PASSWORD; - inline_box->text = xcalloc(inline_box->length + 1, 1); - for (i = 0; i != inline_box->length; i++) - inline_box->text[i] = '*'; + inline_box->length = strlen(box->gadget->value); + inline_box->text = malloc(inline_box->length + 1); + memset(inline_box->text, '*', inline_box->length); + inline_box->text[inline_box->length] = '\0'; } else { box->gadget->type = GADGET_TEXTBOX; - inline_box->text = xstrdup(box->gadget->value); - /* replace spaces with hard spaces to prevent line wrapping */ - for (i = 0; i != inline_box->length; i++) - if (inline_box->text[i] == ' ') - inline_box->text[i] = 160; + /* replace spaces/TABs with hard spaces to prevent line wrapping */ + inline_box->text = cnv_space2nbsp(box->gadget->value); + inline_box->length = strlen(inline_box->text); } - inline_box->font = font_open(status->content->data.html.fonts, style); + inline_box->font = nsfont_open(status->content->data.html.fonts, style); box_add_child(inline_container, inline_box); box_add_child(box, inline_container); @@ -1389,7 +1423,7 @@ struct box_result box_button(xmlNode *n, struct box_status *status, /** - * print a box tree to standard output + * print a box tree to stderr */ void box_dump(struct box * box, unsigned int depth) @@ -1463,9 +1497,9 @@ void box_normalise_block(struct box *block, pool box_pool) struct css_style *style; assert(block != 0); + LOG(("block %p, block->type %u", block, block->type)); assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK || block->type == BOX_TABLE_CELL); - LOG(("block %p, block->type %u", block, block->type)); gui_multitask(); for (child = block->children; child != 0; child = next_child) { @@ -1496,6 +1530,7 @@ void box_normalise_block(struct box *block, pool box_pool) case BOX_TABLE_CELL: /* insert implied table */ style = xcalloc(1, sizeof(struct css_style)); + assert(block->style != NULL); memcpy(style, block->style, sizeof(struct css_style)); css_cascade(style, &css_blank_style); table = box_create(style, block->href, 0, box_pool); @@ -1558,6 +1593,7 @@ void box_normalise_table(struct box *table, pool box_pool) case BOX_TABLE_CELL: /* insert implied table row group */ style = xcalloc(1, sizeof(struct css_style)); + assert(table->style != NULL); memcpy(style, table->style, sizeof(struct css_style)); css_cascade(style, &css_blank_style); row_group = box_create(style, table->href, 0, @@ -1648,6 +1684,7 @@ void box_normalise_table_row_group(struct box *row_group, case BOX_TABLE_CELL: /* insert implied table row */ style = xcalloc(1, sizeof(struct css_style)); + assert(row_group->style != NULL); memcpy(style, row_group->style, sizeof(struct css_style)); css_cascade(style, &css_blank_style); row = box_create(style, row_group->href, 0, @@ -1735,6 +1772,7 @@ void box_normalise_table_row(struct box *row, case BOX_TABLE_ROW: /* insert implied table cell */ style = xcalloc(1, sizeof(struct css_style)); + assert(row->style != NULL); memcpy(style, row->style, sizeof(struct css_style)); css_cascade(style, &css_blank_style); cell = box_create(style, row->href, 0, box_pool); @@ -1939,15 +1977,15 @@ struct box_result box_object(xmlNode *n, struct box_status *status, /* object data */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "data"))) { - url = url_join(s, status->content->data.html.base_url); - if (!url) { - free(po); - xmlFree(s); - return (struct box_result) {box, true, true}; - } - po->data = strdup(s); - LOG(("object '%s'", po->data)); - xmlFree(s); + url = url_join(s, status->content->data.html.base_url); + if (!url) { + free(po); + xmlFree(s); + return (struct box_result) {box, true, true}; + } + po->data = strdup(s); + LOG(("object '%s'", po->data)); + xmlFree(s); } /* imagemap associated with this object */ @@ -2079,13 +2117,13 @@ struct box_result box_embed(xmlNode *n, struct box_status *status, /* embed src */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) { - url = url_join(s, status->content->data.html.base_url); - if (!url) { - free(po); - xmlFree(s); - return (struct box_result) {box, false, true}; - } - LOG(("embed '%s'", url)); + url = url_join(s, status->content->data.html.base_url); + if (!url) { + free(po); + xmlFree(s); + return (struct box_result) {box, false, true}; + } + LOG(("embed '%s'", url)); po->data = strdup(s); xmlFree(s); } diff --git a/render/font.h b/render/font.h index 9e76cfdcf..667b177e0 100644 --- a/render/font.h +++ b/render/font.h @@ -4,6 +4,7 @@ * http://www.opensource.org/licenses/gpl-license * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net> * Copyright 2003 James Bursa <bursa@users.sourceforge.net> + * Copyright 2004 John Tytgat <John.Tytgat@aaug.net> */ #ifndef _NETSURF_RENDER_FONT_H_ @@ -11,22 +12,40 @@ #include "netsurf/css/css.h" +typedef enum { + FONTTYPE_UFONT, + FONTTYPE_STANDARD_UTF8ENC, + FONTTYPE_STANDARD_LATIN1 +} fonttype_e; + struct font_data { - int id; + int id; int handle; + fonttype_e ftype; unsigned int size; unsigned int space_width; struct font_data *next; }; -struct font_set *font_new_set(void); -struct font_data *font_open(struct font_set *set, struct css_style *style); -void font_free_set(struct font_set *set); -unsigned long font_width(struct font_data *font, const char * text, unsigned int length); -void font_position_in_string(const char* text, struct font_data *font, - unsigned int length, unsigned long x, int* char_offset, int* pixel_offset); -char * font_split(struct font_data *data, const char * text, unsigned int length, +struct font_set *nsfont_new_set(void); +struct font_data *nsfont_open(struct font_set *set, struct css_style *style); +void nsfont_free_set(struct font_set *set); +unsigned long nsfont_width(struct font_data *font, const char *text, + unsigned int length); +void nsfont_position_in_string(struct font_data *font, const char *text, + unsigned int length, unsigned long x, int *char_offset, + int *pixel_offset); +char *nsfont_split(struct font_data *font, const char *text, + unsigned int length, unsigned int width, unsigned int *used_width); -const char *enumerate_fonts(struct font_set *set, int *handle); +void nsfont_paint(struct font_data *font, const char *str, + int xpos, int ypos, void *trfm, int length); +void nsfont_txtenum(struct font_data *font, const char *text, + unsigned int length, + unsigned int *width, + const char **rofontname, + const char **rotext, + unsigned int *rolength, + unsigned int *consumed); #endif diff --git a/render/html.c b/render/html.c index dfbc3c106..422528ad0 100644 --- a/render/html.c +++ b/render/html.c @@ -10,6 +10,7 @@ */ #include <assert.h> +#include <ctype.h> #include <string.h> #include <strings.h> #include <stdlib.h> @@ -56,25 +57,44 @@ bool html_create(struct content *c, const char *params[]) unsigned int i; struct content_html_data *html = &c->data.html; union content_msg_data msg_data; - xmlCharEncoding encoding = XML_CHAR_ENCODING_NONE; + xmlCharEncoding encXML = XML_CHAR_ENCODING_NONE; + const char *encStr = NULL; html->encoding = NULL; html->getenc = true; for (i = 0; params[i]; i += 2) { if (strcasecmp(params[i], "charset") == 0) { - encoding = xmlParseCharEncoding(params[i + 1]); - if (encoding != XML_CHAR_ENCODING_ERROR - && encoding != XML_CHAR_ENCODING_NONE) { + encXML = xmlParseCharEncoding(params[i + 1]); + if (encXML != XML_CHAR_ENCODING_ERROR + && encXML != XML_CHAR_ENCODING_NONE) { /* encoding specified - trust the server... */ - html->encoding = xstrdup(xmlGetCharEncodingName(encoding)); + html->encoding = xstrdup(xmlGetCharEncodingName(encXML)); html->getenc = false; + } else { + encStr = xstrdup(params[i + 1]); } break; } } - html->parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0, encoding); + html->parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0, encXML); + if (encStr != NULL) { + xmlCharEncodingHandlerPtr handler; + if ((handler = xmlFindCharEncodingHandler(encStr)) != NULL) { + if (xmlSwitchToEncoding(html->parser, handler) == 0) { + html->encoding = encStr; + html->getenc = false; + } else { + LOG(("xmlSwitchToEncoding failed for <%s>\n", encStr)); + free(encStr); + } + } else { + LOG(("xmlFindCharEncodingHandler() failed for <%s>\n", encStr)); + free(encStr); + } + } + html->base_url = xstrdup(c->url); html->base_url = strdup(c->url); html->layout = 0; html->background_colour = TRANSPARENT; @@ -267,7 +287,7 @@ void html_head(struct content *c, xmlNode *head) if (!c->title && strcmp(node->name, "title") == 0) { xmlChar *title = xmlNodeGetContent(node); - c->title = squash_tolat1(title); + c->title = squash_whitespace(title); xmlFree(title); } else if (strcmp(node->name, "base") == 0) { @@ -852,7 +872,7 @@ void html_destroy(struct content *c) free(c->data.html.style); if (c->data.html.fonts) - font_free_set(c->data.html.fonts); + nsfont_free_set(c->data.html.fonts); /* Free objects */ for (i = 0; i != c->data.html.object_count; i++) { diff --git a/render/layout.c b/render/layout.c index 7928f4122..caf76abe9 100644 --- a/render/layout.c +++ b/render/layout.c @@ -738,7 +738,7 @@ bool layout_line(struct box *first, int width, int *y, if (b->text) { if (b->width == UNKNOWN_WIDTH) - b->width = font_width(b->font, b->text, + b->width = nsfont_width(b->font, b->text, b->length); x += b->width + b->space ? b->font->space_width : 0; @@ -937,7 +937,7 @@ bool layout_line(struct box *first, int width, int *y, if (space == 0) w = split_box->width; else - w = font_width(split_box->font, split_box->text, space); + w = nsfont_width(split_box->font, split_box->text, space); LOG(("splitting: split_box %p, space %u, w %i, left %p, " "right %p, inline_count %u", @@ -987,7 +987,7 @@ bool layout_line(struct box *first, int width, int *y, } else { /* fit as many words as possible */ assert(space != 0); - space = font_split(split_box->font, split_box->text, + space = nsfont_split(split_box->font, split_box->text, split_box->length, x1 - x0 - x - space_before, &w) - split_box->text; @@ -1654,7 +1654,7 @@ void calculate_inline_widths(struct box *box, int *min, int *line_max) int width; /* max = all one line */ - box->width = font_width(box->font, box->text, box->length); + box->width = nsfont_width(box->font, box->text, box->length); *line_max += box->width; if (box->next && box->space) *line_max += box->font->space_width; @@ -1664,7 +1664,7 @@ void calculate_inline_widths(struct box *box, int *min, int *line_max) do { for (j = i; j != box->length && box->text[j] != ' '; j++) ; - width = font_width(box->font, box->text + i, (j - i)); + width = nsfont_width(box->font, box->text + i, j - i); if (*min < width) *min = width; i = j + 1; } while (j != box->length); |