summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2008-02-25 16:37:48 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2008-02-25 16:37:48 +0000
commita4e1ffda1af5e1a7853ab1cd97d05e645d3786f8 (patch)
tree23dbe9e8bc66f20c5d3b4854dfd9b8b6be1f1a33
parent11959f49f8591896b8bff3ca15beb1a395a6b112 (diff)
downloadnetsurf-a4e1ffda1af5e1a7853ab1cd97d05e645d3786f8.tar.gz
netsurf-a4e1ffda1af5e1a7853ab1cd97d05e645d3786f8.tar.bz2
Improve handling of HTML attributes / markup:
* Only apply presentational HTML attributes if no more important CSS has been set for the property. (NetSurf used to be a bit hit-and-miss when presentational markup and CSS were mixed.) * Change table cellpadding and border handling to happen as soon the boxes styles are available, rather than after the whole table has been constructed. Also fix default table border colour. * Improve handling of CENTER tag and ALIGN attribute. These could not be correctly supported in the default CSS file, so block level element alignment is now done during box construction. (Fixes #1891379, #1824492, #1723853) Form improvements: * Small MAXLENGTH values on text inputs now reduce element width. (Fixes #1894854) * Prevent select option text from wrapping. svn path=/trunk/netsurf/; revision=3866
-rw-r--r--!NetSurf/Resources/CSS,f7914
-rw-r--r--css/css.c148
-rw-r--r--css/css.h35
-rw-r--r--render/box_construct.c600
-rw-r--r--render/box_normalise.c8
5 files changed, 554 insertions, 251 deletions
diff --git a/!NetSurf/Resources/CSS,f79 b/!NetSurf/Resources/CSS,f79
index 3eca49ebb..ae45f5179 100644
--- a/!NetSurf/Resources/CSS,f79
+++ b/!NetSurf/Resources/CSS,f79
@@ -11,9 +11,6 @@ head { display: none; }
body { display: block; padding: 8px; line-height: 1.33; }
div { display: block; }
-div[align=left] > * { margin-right: auto; }
-div[align=center] > * { margin-left: auto; margin-right: auto; }
-div[align=right] > * { margin-left: auto; }
h1 { display: block; font-size: 2em; font-weight: bold; margin: .67em 0; }
h2 { display: block; font-size: 1.5em; font-weight: bold; margin: .69em 0; }
@@ -92,13 +89,9 @@ th { font-weight: bold; text-align: center; }
td[nowrap], th[nowrap] { white-space: nowrap; }
-td[align=left] > *, th[align=left] > * { margin-right: auto; }
-td[align=center] > *, th[align=center] > * { margin-left: auto; margin-right: auto; }
-td[align=right] > *, th[align=right] > * { margin-left: auto; }
-
-tr[align=left] > td, tr[align=left] > th { text-align: left; margin-right: auto; }
-tr[align=center] > td, tr[align=center] > th { text-align: center; margin-left: auto; margin-right: auto; }
-tr[align=right] > td, tr[align=right] > th { text-align: right; margin-left: auto; }
+tr[align=left] > td, tr[align=left] > th { text-align: left; }
+tr[align=center] > td, tr[align=center] > th { text-align: center; }
+tr[align=right] > td, tr[align=right] > th { text-align: right; }
col[valign=top], colgroup[valign=top], tbody[valign=top], td[valign=top], tfoot[valign=top], th[valign=top], thead[valign=top], tr[valign=top] { vertical-align: top; }
col[valign=middle], colgroup[valign=middle], tbody[valign=middle], td[valign=middle], tfoot[valign=middle], th[valign=middle], thead[valign=middle], tr[valign=middle] { vertical-align: middle; }
@@ -117,7 +110,6 @@ applet[align=left] { float: left; }
applet[align=right] { float: right; }
center { display: block; text-align: center; }
-center > * { margin-left: auto; margin-right: auto; }
tt { font-family: monospace; }
i { font-style: italic; }
diff --git a/css/css.c b/css/css.c
index 5c82cc1de..8dd7d0380 100644
--- a/css/css.c
+++ b/css/css.c
@@ -1,6 +1,7 @@
/*
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -131,6 +132,7 @@ static void css_dump_length(const struct css_length * const length);
static void css_dump_selector(const struct css_selector *r);
static void css_dump_working_stylesheet(
const struct css_working_stylesheet *ws);
+static void css_importance_reset(struct css_importance *i);
/** Default style for a document. These are the 'Initial values' from the
* spec. */
@@ -1124,15 +1126,19 @@ bool css_working_merge_chains(struct css_working_stylesheet *working_stylesheet,
* \param working_stylesheet working stylesheet
* \param element element in xml tree to match
* \param style style to update
+ * \pram author updated to indicate properties with author level css
+ * importance
*
* The style is updated with any rules that match the element.
*/
void css_get_style(struct css_working_stylesheet *working_stylesheet,
- xmlNode *element, struct css_style *style)
+ xmlNode *element, struct css_style *style,
+ struct css_importance *author)
{
unsigned int hash, rule_0 = 0, rule_h = 0;
struct css_selector *rule;
+ css_importance_reset(author); /* initialise to sub-author level */
hash = css_hash((const char *) element->name,
strlen((const char *) element->name));
@@ -1153,7 +1159,8 @@ void css_get_style(struct css_working_stylesheet *working_stylesheet,
rule_h++;
}
if (css_match_rule(rule, element))
- css_merge(style, rule->style);
+ css_merge(style, rule->style, rule->specificity,
+ author);
}
/* remaining rules from hash chain 0 */
@@ -1162,7 +1169,8 @@ void css_get_style(struct css_working_stylesheet *working_stylesheet,
rule = working_stylesheet->rule[0][rule_0];
rule_0++;
if (css_match_rule(rule, element))
- css_merge(style, rule->style);
+ css_merge(style, rule->style, rule->specificity,
+ author);
}
/* remaining rules from hash chain for element name */
@@ -1171,7 +1179,8 @@ void css_get_style(struct css_working_stylesheet *working_stylesheet,
rule = working_stylesheet->rule[hash][rule_h];
rule_h++;
if (css_match_rule(rule, element))
- css_merge(style, rule->style);
+ css_merge(style, rule->style, rule->specificity,
+ author);
}
}
@@ -2426,6 +2435,27 @@ void css_dump_working_stylesheet(const struct css_working_stylesheet *ws)
}
/**
+ * Set all members to FALSE
+ */
+void css_importance_reset(struct css_importance *i) {
+ i->background_color = FALSE;
+ i->background_image = FALSE;
+ i->border_spacing = FALSE;
+ i->color = FALSE;
+ i->height = FALSE;
+ i->width = FALSE;
+
+ /**< top, right, bottom, left */
+ for (int j = 0; j < 4; j++) {
+ i->border_color[j] = FALSE;
+ i->border_style[j] = FALSE;
+ i->border_width[j] = FALSE;
+ i->margin[j] = FALSE;
+ i->padding[j] = FALSE;
+ }
+}
+
+/**
* Dump a complete css_stylesheet to stderr in CSS syntax.
*/
@@ -2526,8 +2556,11 @@ void css_dump_selector(const struct css_selector *r)
/**
* Cascade styles.
*
- * \param style css_style to modify
- * \param apply css_style to cascade onto style
+ * \param style css_style to modify
+ * \param apply css_style to cascade onto style
+ * \param author updated to indicate which properties have greater
+ * than author level CSS importance. (NULL if
+ * importance isn't required.)
*
* Attributes which have the value 'inherit' or 'unset' in apply are
* unchanged in style.
@@ -2536,7 +2569,8 @@ void css_dump_selector(const struct css_selector *r)
*/
void css_cascade(struct css_style * const style,
- const struct css_style * const apply)
+ const struct css_style * const apply,
+ struct css_importance * const author)
{
unsigned int i;
float f;
@@ -2813,42 +2847,93 @@ void css_cascade(struct css_style * const style,
apply->pos[i].pos != CSS_POS_NOT_SET)
style->pos[i] = apply->pos[i];
}
+
+ /* Set author level CSS importance (used for HTML style attribute) */
+ if (author) {
+ if (apply->background_color != CSS_COLOR_NOT_SET)
+ author->background_color = TRUE;
+ if (apply->background_image.type !=
+ CSS_BACKGROUND_IMAGE_NOT_SET)
+ author->background_image = TRUE;
+ if (apply->border_spacing.border_spacing !=
+ CSS_BORDER_SPACING_NOT_SET)
+ author->border_spacing = TRUE;
+ if (apply->color != CSS_COLOR_NOT_SET)
+ author->color = TRUE;
+ if (apply->height.height != CSS_HEIGHT_NOT_SET)
+ author->height = TRUE;
+ if (apply->width.width != CSS_WIDTH_NOT_SET)
+ author->width = TRUE;
+
+ for (i = 0; i != 4; i++) {
+ if (apply->border[i].color != CSS_COLOR_NOT_SET)
+ author->border_color[i] = TRUE;
+ if (apply->border[i].width.width !=
+ CSS_BORDER_WIDTH_NOT_SET)
+ author->border_width[i] = TRUE;
+ if (apply->border[i].style != CSS_BORDER_STYLE_NOT_SET)
+ author->border_style[i] = TRUE;
+
+ if (apply->margin[i].margin != CSS_MARGIN_NOT_SET)
+ author->margin[i] = TRUE;
+
+ if (apply->padding[i].padding != CSS_PADDING_NOT_SET)
+ author->padding[i] = TRUE;
+ }
+ }
}
/**
* Merge styles.
*
- * \param style css_style to modify
- * \param apply css_style to merge onto style
+ * \param style css_style to modify
+ * \param apply css_style to merge onto style
+ * \param specificity specificity of current CSS rule
+ * \param author updated to indicate which properties have greater than
+ * author level CSS importance
*
* Attributes which have the value 'unset' in apply are unchanged in style.
* Other attributes are copied to style, overwriting it.
*/
void css_merge(struct css_style * const style,
- const struct css_style * const apply)
+ const struct css_style * const apply,
+ const unsigned long specificity,
+ struct css_importance * const author)
{
unsigned int i;
if (apply->background_attachment != CSS_BACKGROUND_ATTACHMENT_NOT_SET)
style->background_attachment = apply->background_attachment;
- if (apply->background_color != CSS_COLOR_NOT_SET)
+ if (apply->background_color != CSS_COLOR_NOT_SET) {
style->background_color = apply->background_color;
- if (apply->background_image.type != CSS_BACKGROUND_IMAGE_NOT_SET)
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->background_color = TRUE;
+ }
+ if (apply->background_image.type != CSS_BACKGROUND_IMAGE_NOT_SET) {
style->background_image = apply->background_image;
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->background_image = TRUE;
+ }
if (apply->background_repeat != CSS_BACKGROUND_REPEAT_NOT_SET)
style->background_repeat = apply->background_repeat;
if (apply->border_collapse != CSS_BORDER_COLLAPSE_NOT_SET)
style->border_collapse = apply->border_collapse;
- if (apply->border_spacing.border_spacing != CSS_BORDER_SPACING_NOT_SET)
+ if (apply->border_spacing.border_spacing != CSS_BORDER_SPACING_NOT_SET){
style->border_spacing = apply->border_spacing;
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->border_spacing = TRUE;
+ }
if (apply->caption_side != CSS_CAPTION_SIDE_NOT_SET)
style->caption_side = apply->caption_side;
if (apply->clear != CSS_CLEAR_NOT_SET)
style->clear = apply->clear;
- if (apply->color != CSS_COLOR_NOT_SET)
+ if (apply->color != CSS_COLOR_NOT_SET) {
style->color = apply->color;
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->color = TRUE;
+ }
if (apply->content.type != CSS_CONTENT_NOT_SET)
style->content = apply->content;
if (apply->counter_reset.type != CSS_COUNTER_RESET_NOT_SET)
@@ -2875,8 +2960,11 @@ void css_merge(struct css_style * const style,
style->font_variant = apply->font_variant;
if (apply->font_weight != CSS_FONT_WEIGHT_NOT_SET)
style->font_weight = apply->font_weight;
- if (apply->height.height != CSS_HEIGHT_NOT_SET)
+ if (apply->height.height != CSS_HEIGHT_NOT_SET) {
style->height = apply->height;
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->height = TRUE;
+ }
if (apply->letter_spacing.letter_spacing != CSS_LETTER_SPACING_NOT_SET)
style->letter_spacing = apply->letter_spacing;
if (apply->line_height.size != CSS_LINE_HEIGHT_NOT_SET)
@@ -2928,8 +3016,11 @@ void css_merge(struct css_style * const style,
style->white_space = apply->white_space;
if (apply->widows.widows != CSS_WIDOWS_NOT_SET)
style->widows = apply->widows;
- if (apply->width.width != CSS_WIDTH_NOT_SET)
+ if (apply->width.width != CSS_WIDTH_NOT_SET) {
style->width = apply->width;
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->width = TRUE;
+ }
if (apply->word_spacing.word_spacing != CSS_WORD_SPACING_NOT_SET)
style->word_spacing = apply->word_spacing;
if (apply->z_index.z_index != CSS_Z_INDEX_NOT_SET)
@@ -2965,18 +3056,33 @@ void css_merge(struct css_style * const style,
/* borders, margins, padding and box position */
for (i = 0; i != 4; i++) {
- if (apply->border[i].color != CSS_COLOR_NOT_SET)
+ if (apply->border[i].color != CSS_COLOR_NOT_SET) {
style->border[i].color = apply->border[i].color;
- if (apply->border[i].width.width != CSS_BORDER_WIDTH_NOT_SET)
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->border_color[i] = TRUE;
+ }
+ if (apply->border[i].width.width != CSS_BORDER_WIDTH_NOT_SET) {
style->border[i].width = apply->border[i].width;
- if (apply->border[i].style != CSS_BORDER_STYLE_NOT_SET)
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->border_width[i] = TRUE;
+ }
+ if (apply->border[i].style != CSS_BORDER_STYLE_NOT_SET) {
style->border[i].style = apply->border[i].style;
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->border_style[i] = TRUE;
+ }
- if (apply->margin[i].margin != CSS_MARGIN_NOT_SET)
+ if (apply->margin[i].margin != CSS_MARGIN_NOT_SET) {
style->margin[i] = apply->margin[i];
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->margin[i] = TRUE;
+ }
- if (apply->padding[i].padding != CSS_PADDING_NOT_SET)
+ if (apply->padding[i].padding != CSS_PADDING_NOT_SET) {
style->padding[i] = apply->padding[i];
+ if (specificity >= CSS_SPECIFICITY_AUTHOR)
+ author->padding[i] = TRUE;
+ }
if (apply->pos[i].pos != CSS_POS_NOT_SET)
style->pos[i] = apply->pos[i];
diff --git a/css/css.h b/css/css.h
index e9d374131..f7a7b3048 100644
--- a/css/css.h
+++ b/css/css.h
@@ -481,6 +481,31 @@ struct css_style {
} z_index;
};
+/** Author level CSS importance info for properties that may be set in HTML */
+struct css_importance {
+ /* background properties */
+ bool background_color;
+ bool background_image;
+
+ /* borders */
+ bool border_style[4]; /**< top, right, bottom, left */
+ bool border_color[4];
+ bool border_width[4];
+ bool border_spacing;
+
+ bool color;
+
+ bool height;
+
+ /* margins */
+ bool margin[4]; /**< top, right, bottom, left */
+
+ /* padding */
+ bool padding[4]; /**< top, right, bottom, left */
+
+ bool width;
+};
+
struct css_stylesheet;
typedef enum {
@@ -650,15 +675,19 @@ struct css_working_stylesheet *css_make_working_stylesheet(
struct content **stylesheet_content,
unsigned int stylesheet_count);
void css_get_style(struct css_working_stylesheet *working_stylesheet,
- xmlNode *element, struct css_style *style);
+ xmlNode *element, struct css_style *style,
+ struct css_importance *author);
struct css_style *css_duplicate_style(const struct css_style * const style);
void css_free_style(struct css_style *style);
void css_deep_free_content(struct css_content *content);
void css_deep_free_counter_control(struct css_counter_control *control);
void css_cascade(struct css_style * const style,
- const struct css_style * const apply);
+ const struct css_style * const apply,
+ struct css_importance * const author);
void css_merge(struct css_style * const style,
- const struct css_style * const apply);
+ const struct css_style * const apply,
+ const unsigned long specificity,
+ struct css_importance * const author);
void css_parse_property_list(struct content *c, struct css_style * style,
char * str);
colour named_colour(const char *name);
diff --git a/render/box_construct.c b/render/box_construct.c
index 9950eb421..b5c04be3b 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -3,6 +3,7 @@
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -87,29 +88,48 @@ const char *TARGET_PARENT = "_parent";
const char *TARGET_TOP = "_top";
const char *TARGET_BLANK = "_blank";
+/* keeps track of markup presentation */
+struct markup_track {
+ enum {
+ ALIGN_NONE,
+ ALIGN_LEFT,
+ ALIGN_CENTER,
+ ALIGN_RIGHT
+ } align;
+ bool cell_border;
+ colour border_color;
+
+ bool cell_padding;
+ long padding_width;
+};
static bool convert_xml_to_box(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
- char *href, const char *target, char *title);
+ char *href, const char *target, char *title,
+ struct markup_track markup_track,
+ struct css_importance *author);
bool box_construct_element(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
- char *href, const char *target, char *title);
+ char *href, const char *target, char *title,
+ struct markup_track markup_track,
+ struct css_importance *author);
bool box_construct_text(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
char *href, const char *target, char *title);
static struct css_style * box_get_style(struct content *c,
struct css_style *parent_style,
- xmlNode *n);
+ xmlNode *n, struct markup_track *markup_track,
+ struct css_importance *author);
static void box_solve_display(struct css_style *style, bool root);
-static void box_set_cellpadding(struct box *box, int value);
-static void box_set_table_border(struct box *box, int value, colour color);
static void box_text_transform(char *s, unsigned int len,
css_text_transform tt);
#define BOX_SPECIAL_PARAMS xmlNode *n, struct content *content, \
- struct box *box, bool *convert_children
+ struct box *box, bool *convert_children, \
+ struct markup_track markup_track, \
+ struct css_importance *author
static bool box_a(BOX_SPECIAL_PARAMS);
static bool box_body(BOX_SPECIAL_PARAMS);
static bool box_br(BOX_SPECIAL_PARAMS);
@@ -161,7 +181,6 @@ static const struct element_entry element_table[] = {
};
#define ELEMENT_TABLE_COUNT (sizeof(element_table) / sizeof(element_table[0]))
-
/**
* Construct a box tree from an xml tree and stylesheets.
*
@@ -174,6 +193,11 @@ bool xml_to_box(xmlNode *n, struct content *c)
{
struct box root;
struct box *inline_container = 0;
+ struct css_importance author;
+ struct markup_track markup_track;
+ markup_track.cell_border = false;
+ markup_track.cell_padding = false;
+ markup_track.align = ALIGN_NONE;
assert(c->type == CONTENT_HTML);
@@ -200,7 +224,7 @@ bool xml_to_box(xmlNode *n, struct content *c)
c->data.html.object = 0;
if (!convert_xml_to_box(n, c, c->data.html.style, &root,
- &inline_container, 0, 0, 0))
+ &inline_container, 0, 0, 0, markup_track, &author))
return false;
if (!box_normalise_block(&root, c))
@@ -247,19 +271,24 @@ static const box_type box_map[] = {
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
+ * \param markup_track track presentation markup that affects descendents
+ * \param author denotes whether current style has author level
+ * importance for certain properties
* \return true on success, false on memory exhaustion
*/
bool convert_xml_to_box(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
- char *href, const char *target, char *title)
+ char *href, const char *target, char *title,
+ struct markup_track markup_track,
+ struct css_importance *author)
{
switch (n->type) {
case XML_ELEMENT_NODE:
return box_construct_element(n, content, parent_style, parent,
inline_container,
- href, target, title);
+ href, target, title, markup_track, author);
case XML_TEXT_NODE:
return box_construct_text(n, content, parent_style, parent,
inline_container, href, target, title);
@@ -282,13 +311,18 @@ bool convert_xml_to_box(xmlNode *n, struct content *content,
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
+ * \param markup_track track presentation markup that affects descendents
+ * \param author denotes whether current style has author level
+ * importance for certain properties
* \return true on success, false on memory exhaustion
*/
bool box_construct_element(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
- char *href, const char *target, char *title)
+ char *href, const char *target, char *title,
+ struct markup_track markup_track,
+ struct css_importance *author)
{
bool convert_children = true;
char *id = 0;
@@ -298,7 +332,6 @@ bool box_construct_element(xmlNode *n, struct content *content,
struct box *inline_end;
struct css_style *style = 0;
struct element_entry *element;
- colour border_color = 0x888888;
xmlChar *title0;
xmlNode *c;
@@ -316,7 +349,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
*/
parent->strip_leading_newline = 0;
- style = box_get_style(content, parent_style, n);
+ style = box_get_style(content, parent_style, n, &markup_track, author);
if (!style)
return false;
@@ -349,11 +382,13 @@ bool box_construct_element(xmlNode *n, struct content *content,
(int (*)(const void *, const void *)) strcmp);
if (element) {
/* a special convert function exists for this element */
- if (!element->convert(n, content, box, &convert_children))
+ if (!element->convert(n, content, box, &convert_children,
+ markup_track, author))
return false;
href = box->href;
target = box->target;
}
+
if (style->display == CSS_DISPLAY_NONE) {
/* Free style and invalidate box's style pointer */
talloc_free(style);
@@ -395,7 +430,8 @@ bool box_construct_element(xmlNode *n, struct content *content,
for (c = n->children; c; c = c->next)
if (!convert_xml_to_box(c, content, style,
parent, inline_container,
- href, target, title))
+ href, target, title,
+ markup_track, author))
return false;
inline_end = box_create(style, href, target, title, id,
content);
@@ -416,7 +452,8 @@ bool box_construct_element(xmlNode *n, struct content *content,
for (c = n->children; convert_children && c; c = c->next)
if (!convert_xml_to_box(c, content, style, box,
&inline_container_c,
- href, target, title))
+ href, target, title, markup_track,
+ author))
return false;
} else {
if (style->float_ == CSS_FLOAT_LEFT ||
@@ -495,7 +532,8 @@ bool box_construct_element(xmlNode *n, struct content *content,
for (c = n->children; convert_children && c; c = c->next)
if (!convert_xml_to_box(c, content, style, box,
&inline_container_c,
- href, target, title))
+ href, target, title, markup_track,
+ author))
return false;
if (style->float_ == CSS_FLOAT_NONE)
/* new inline container unless this is a float */
@@ -519,32 +557,9 @@ bool box_construct_element(xmlNode *n, struct content *content,
}
xmlFree(s);
}
- if (strcmp((const char *) n->name, "table") == 0) {
- border_color = CSS_COLOR_NONE; /* not set */
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "cellpadding"))) {
- char *endp;
- long value = strtol(s, &endp, 10);
- if (*endp == 0 && 0 <= value && value < 1000)
- /* % not implemented */
- box_set_cellpadding(box, value);
- xmlFree(s);
- }
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "bordercolor"))) {
- parse_inline_colour(s, &border_color);
- xmlFree(s);
- }
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "border"))) {
- int value = atoi(s);
- if (!strrchr(s, '%') && 0 < value) /* % not implemented */
- box_set_table_border(box, value, border_color);
- xmlFree(s);
- }
- }
/* transfer <tr height="n"> down to the <td> elements */
+ /* \todo move this into box_get_style() */
if (strcmp((const char *) n->name, "tr") == 0) {
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "height"))) {
@@ -555,23 +570,25 @@ bool box_construct_element(xmlNode *n, struct content *content,
/* the specification doesn't make clear what
* percentage heights mean, so ignore them */
} else {
- /* The tree is not normalized yet, so accept cells not
- * in rows and rows not in row groups. */
+ /* The tree is not normalized yet, so accept
+ * cells not in rows and rows not in row
+ * groups. */
struct box *child;
float current;
- for (child = box->children; child; child = child->next) {
+ for (child = box->children; child;
+ child = child->next) {
if (child->type == BOX_TABLE_CELL) {
current = css_len2px(
- &child->style->height.length,
- child->style);
+ &child->style->height.
+ length, child->style);
value = (value > current) ?
- value : current;
+ value : current;
child->style->height.height =
- CSS_HEIGHT_LENGTH;
- child->style->height.length.unit =
- CSS_UNIT_PX;
- child->style->height.length.value =
- value;
+ CSS_HEIGHT_LENGTH;
+ child->style->height.length.
+ unit = CSS_UNIT_PX;
+ child->style->height.length.
+ value = value;
}
}
}
@@ -782,23 +799,41 @@ bool box_construct_text(xmlNode *n, struct content *content,
* \param c content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
* \param n node in xml tree
+ * \param markup_track track presentation markup that affects descendents
+ * \param author denotes whether current style has author level
+ * importance for certain properties
* \return the new style, or 0 on memory exhaustion
*
* The style is collected from three sources:
* 1. any styles for this element in the document stylesheet(s)
- * 2. non-CSS HTML attributes
- * 3. the 'style' attribute
+ * 2. the 'style' attribute
+ * 3. non-CSS HTML attributes (subject to importance of CSS style properties)
*/
struct css_style * box_get_style(struct content *c,
struct css_style *parent_style,
- xmlNode *n)
+ xmlNode *n, struct markup_track *markup_track,
+ struct css_importance *author)
{
char *s;
struct css_style *style;
struct css_style *style_new;
char *url;
url_func_result res;
+ colour border_color = 0x888888; /* mid-grey default for tables */
+
+ /* if not in a table, switch off cellpadding and cell borders */
+ if (strcmp(n->name, "thead") != 0 &&
+ strcmp(n->name, "tbody") != 0 &&
+ strcmp(n->name, "tfoot") != 0 &&
+ strcmp(n->name, "tr") != 0 &&
+ strcmp(n->name, "td") != 0 &&
+ strcmp(n->name, "th") != 0 &&
+ strcmp(n->name, "col") != 0 &&
+ strcmp(n->name, "colgroup") != 0) {
+ markup_track->cell_border = false;
+ markup_track->cell_padding = false;
+ }
style = talloc_memdup(c, parent_style, sizeof *style);
if (!style)
@@ -807,17 +842,37 @@ struct css_style * box_get_style(struct content *c,
style_new = talloc_memdup(c, &css_blank_style, sizeof *style_new);
if (!style_new)
return 0;
- css_get_style(c->data.html.working_stylesheet, n, style_new);
- css_cascade(style, style_new);
+ css_get_style(c->data.html.working_stylesheet, n, style_new, author);
+ css_cascade(style, style_new, NULL);
/* style_new isn't needed past this point */
talloc_free(style_new);
+ /* Handle style attribute. (style attribute values have high enough
+ * specificity to override existing style data.) */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) {
+ struct css_style *astyle;
+ astyle = css_duplicate_style(&css_empty_style);
+ if (!astyle) {
+ xmlFree(s);
+ return 0;
+ }
+ css_parse_property_list(c, astyle, s);
+ css_cascade(style, astyle, author);
+ css_free_style(astyle);
+ xmlFree(s);
+ }
+
+ /* Apply presentational HTML attributes to style
+ * (Only apply if style property does not have "author" level
+ * importance or higher.)
+ */
+
/* This property only applies to the body element, if you believe
* the spec. Many browsers seem to allow it on other elements too,
* so let's be generic ;) */
- if (((s = (char *) xmlGetProp(n, (const xmlChar *) "background"))) &&
- (style->background_image.type == CSS_BACKGROUND_IMAGE_NONE)) {
+ if (!author->background_image && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "background"))) {
res = url_join(s, c->data.html.base_url, &url);
xmlFree(s);
if (res == URL_FUNC_NOMEM) {
@@ -839,18 +894,20 @@ struct css_style * box_get_style(struct content *c,
}
}
- if (((s = (char *) xmlGetProp(n, (const xmlChar *) "bgcolor"))) &&
- (style->background_color == TRANSPARENT)) {
+ if (!author->background_color && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "bgcolor"))) {
parse_inline_colour(s, &style->background_color);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "color"))) {
+ if (!author->color && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "color"))) {
parse_inline_colour(s, &style->color);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "height"))) {
+ if (!author->height && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "height"))) {
float value = isdigit(s[0]) ? atof(s) : -1;
if (value <= 0 || strlen(s) == 0) {
/* ignore negative values and height="" */
@@ -865,9 +922,10 @@ struct css_style * box_get_style(struct content *c,
xmlFree(s);
}
- if (strcmp((const char *) n->name, "input") == 0) {
+ if (!author->width && strcmp((const char *) n->name, "input") == 0) {
+ int size = -1;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "size"))) {
- int size = isdigit(s[0]) ? atoi(s): -1;
+ size = isdigit(s[0]) ? atoi(s): -1;
if (0 < size) {
char *type = (char *) xmlGetProp(n,
(const xmlChar *) "type");
@@ -889,16 +947,41 @@ struct css_style * box_get_style(struct content *c,
}
xmlFree(s);
}
+ /* If valid maxlength value is provided, the size attribute is
+ * unset and maxlength is small, use it to reduce input width
+ * to sensible size */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *)
+ "maxlength"))) {
+ int maxlength = isdigit(s[0]) ? atoi(s): -1;
+ if (0 < maxlength && size == -1 && maxlength < 10) {
+ /* Bump up really small widths */
+ maxlength = maxlength < 5 ? maxlength + 1 :
+ maxlength;
+ char *type = (char *) xmlGetProp(n,
+ (const xmlChar *) "type");
+ style->width.width = CSS_WIDTH_LENGTH;
+ if (!type || strcasecmp(type, "text") == 0 ||
+ strcasecmp(type, "password") == 0)
+ /* in characters for text, password */
+ style->width.value.length.unit =
+ CSS_UNIT_EX;
+ style->width.value.length.value = maxlength;
+ if (type)
+ xmlFree(type);
+ }
+ xmlFree(s);
+ }
}
- if (strcmp((const char *) n->name, "body") == 0) {
+ if (!author->color && strcmp((const char *) n->name, "body") == 0) {
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "text"))) {
parse_inline_colour(s, &style->color);
xmlFree(s);
}
}
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "width"))) {
+ if (!author->width && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "width"))) {
float value = isdigit(s[0]) ? atof(s) : -1;
if (value < 0 || strlen(s) == 0) {
/* ignore negative values and width="" */
@@ -914,7 +997,8 @@ struct css_style * box_get_style(struct content *c,
}
if (strcmp((const char *) n->name, "textarea") == 0) {
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "rows"))) {
+ if (!author->height && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "rows"))) {
int value = isdigit(s[0]) ? atoi(s): -1;
if (0 < value) {
style->height.height = CSS_HEIGHT_LENGTH;
@@ -923,7 +1007,8 @@ struct css_style * box_get_style(struct content *c,
}
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "cols"))) {
+ if (!author->width && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "cols"))) {
int value = isdigit(s[0]) ? atoi(s): -1;
if (0 < value) {
style->width.width = CSS_WIDTH_LENGTH;
@@ -935,43 +1020,112 @@ struct css_style * box_get_style(struct content *c,
}
if (strcmp((const char *) n->name, "table") == 0) {
- if ((s = (char *) xmlGetProp(n,
- (const xmlChar *) "cellspacing"))) {
- if (!strrchr(s, '%')) { /* % not implemented */
+ if (!author->border_spacing && (s = (char *) xmlGetProp(n,
+ (const xmlChar *) "cellspacing"))) {
+ /* percentage cellspacing not implemented */
+ if (!strrchr(s, '%')) {
int value = isdigit(s[0]) ? atoi(s): -1;
if (0 <= value) {
style->border_spacing.border_spacing =
CSS_BORDER_SPACING_LENGTH;
style->border_spacing.horz.unit =
style->border_spacing.vert.unit =
- CSS_UNIT_PX;
+ CSS_UNIT_PX;
style->border_spacing.horz.value =
style->border_spacing.vert.value =
- value;
+ value;
+ }
+ }
+ xmlFree(s);
+ }
+
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "bordercolor"))) {
+ parse_inline_colour(s, &border_color);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "border"))) {
+ int border_width = atoi(s);
+ /* precentage border width not implemented */
+ if (!strrchr(s, '%') && 0 < border_width) {
+ for (unsigned int i = 0; i != 4; i++) {
+ if (!author->border_color[i])
+ style->border[i].color =
+ border_color;
+ if (!author->border_width[i]) {
+ style->border[i].width.width =
+ CSS_BORDER_WIDTH_LENGTH;
+ style->border[i].width.value.
+ value = border_width;
+ style->border[i].width.value.
+ unit = CSS_UNIT_PX;
+ }
+ if (!author->border_style[i])
+ style->border[i].style =
+ CSS_BORDER_STYLE_OUTSET;
}
}
xmlFree(s);
}
}
+ if (strcmp((const char *) n->name, "td") == 0 ||
+ strcmp((const char *) n->name, "th") == 0) {
+ /* set any cellborders stipulated by associated table */
+ if (markup_track->cell_border) {
+ for (unsigned int i = 0; i != 4; i++) {
+ if (!author->border_color[i])
+ style->border[i].color = markup_track->
+ border_color;
+ if (!author->border_width[i]) {
+ style->border[i].width.width =
+ CSS_BORDER_WIDTH_LENGTH;
+ style->border[i].width.value.value = 1;
+ style->border[i].width.value.unit =
+ CSS_UNIT_PX;
+ }
+ if (!author->border_style[i])
+ style->border[i].style =
+ CSS_BORDER_STYLE_INSET;
+ }
+ }
+ /* set any cellpadding stipulated by associated table */
+ if (markup_track->cell_padding) {
+ for (unsigned int i = 0; i != 4; i++) {
+ if (!author->padding[i]) {
+ style->padding[i].padding =
+ CSS_PADDING_LENGTH;
+ style->padding[i].value.length.value =
+ markup_track->padding_width;
+ style->padding[i].value.length.unit =
+ CSS_UNIT_PX;
+ }
+ }
+ }
+ }
+
if ((strcmp((const char *) n->name, "img") == 0) ||
(strcmp((const char *) n->name, "image") == 0) ||
(strcmp((const char *) n->name, "applet") == 0)) {
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "hspace"))) {
- if (!strrchr(s, '%')) { /* % not implemented */
+ /* percentage hspace not implemented */
+ if (!strrchr(s, '%')) {
int value = isdigit(s[0]) ? atoi(s): -1;
- if (0 <= value) {
+ if (0 <= value && !author->margin[LEFT]) {
style->margin[LEFT].margin =
CSS_MARGIN_LENGTH;
style->margin[LEFT].value.length.value =
value;
style->margin[LEFT].value.length.unit =
CSS_UNIT_PX;
+ }
+ if (0 <= value && !author->margin[RIGHT]) {
style->margin[RIGHT].margin =
CSS_MARGIN_LENGTH;
- style->margin[RIGHT].value.length.value =
- value;
+ style->margin[RIGHT].value.length.
+ value = value;
style->margin[RIGHT].value.length.unit =
CSS_UNIT_PX;
}
@@ -980,42 +1134,141 @@ struct css_style * box_get_style(struct content *c,
}
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "vspace"))) {
- if (!strrchr(s, '%')) { /* % not implemented */
+ /* percentage vspace not implemented */
+ if (!strrchr(s, '%')) {
int value = isdigit(s[0]) ? atoi(s): -1;
- if (0 <= value) {
+ if (0 <= value && !author->margin[TOP]) {
style->margin[TOP].margin =
CSS_MARGIN_LENGTH;
style->margin[TOP].value.length.value =
value;
style->margin[TOP].value.length.unit =
CSS_UNIT_PX;
+ }
+ if (0 <= value && !author->margin[BOTTOM]) {
style->margin[BOTTOM].margin =
CSS_MARGIN_LENGTH;
- style->margin[BOTTOM].value.length.value =
- value;
- style->margin[BOTTOM].value.length.unit =
- CSS_UNIT_PX;
+ style->margin[BOTTOM].value.length.
+ value = value;
+ style->margin[BOTTOM].value.length.
+ unit = CSS_UNIT_PX;
}
}
xmlFree(s);
}
}
- if ((s = (char *) xmlGetProp(n, (const xmlChar *) "style"))) {
- struct css_style *astyle;
- astyle = css_duplicate_style(&css_empty_style);
- if (!astyle) {
- xmlFree(s);
- return 0;
+ /* Handle markup-originating alignment of block level elements.
+ * Adjust left and right margins. text-align property is handled in
+ * the default CSS file.
+ */
+ if (markup_track->align != ALIGN_NONE &&
+ (style->display == CSS_DISPLAY_BLOCK ||
+ style->display == CSS_DISPLAY_TABLE)) {
+ if (!author->margin[LEFT]) {
+ if (markup_track->align == ALIGN_LEFT) {
+ /* left */
+ style->margin[LEFT].margin = CSS_MARGIN_LENGTH;
+ style->margin[LEFT].value.length.value = 0;
+ style->margin[LEFT].value.length.unit =
+ CSS_UNIT_PX;
+ } else
+ /* center or right */
+ style->margin[LEFT].margin = CSS_MARGIN_AUTO;
+ }
+
+ if (!author->margin[RIGHT]) {
+ if (markup_track->align == ALIGN_RIGHT) {
+ /* right */
+ style->margin[RIGHT].margin = CSS_MARGIN_LENGTH;
+ style->margin[RIGHT].value.length.value= 0;
+ style->margin[RIGHT].value.length.unit =
+ CSS_UNIT_PX;
+ } else
+ /* left or center */
+ style->margin[RIGHT].margin = CSS_MARGIN_AUTO;
+ }
+ if (author->margin[LEFT] || author->margin[RIGHT]) {
+ /* author stylesheet sets a margin so stop markup
+ * alignment model propagation */
+ markup_track->align = ALIGN_NONE;
}
- css_parse_property_list(c, astyle, s);
- css_cascade(style, astyle);
- css_free_style(astyle);
- xmlFree(s);
}
box_solve_display(style, !n->parent);
+ /* Update markup_track with attributes which affect children of
+ * current box. */
+
+ /* Handle html block level element alignment model.
+ * Note that only margins of block level children are considered,
+ * text-align for the current block can be handled in the default
+ * CSS file.
+ */
+ if (strcmp(n->name, "center") == 0)
+ markup_track->align = ALIGN_CENTER;
+ else if (strcmp(n->name, "div") == 0 ||
+ strcmp(n->name, "col") == 0 ||
+ strcmp(n->name, "colgroup") == 0 ||
+ strcmp(n->name, "tbody") == 0 ||
+ strcmp(n->name, "td") == 0 ||
+ strcmp(n->name, "tfoot") == 0 ||
+ strcmp(n->name, "th") == 0 ||
+ strcmp(n->name, "thead") == 0 ||
+ strcmp(n->name, "tr") == 0) {
+
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "align"))) {
+ if (strcasecmp(s, "center") == 0)
+ markup_track->align = ALIGN_CENTER;
+ else if (strcasecmp(s, "right") == 0)
+ markup_track->align = ALIGN_RIGHT;
+ else if (strcasecmp(s, "left") == 0)
+ markup_track->align = ALIGN_LEFT;
+ xmlFree(s);
+ }
+ }
+ /* Table cells without an align value have a default implied
+ * alignment */
+ if (strcmp(n->name, "td") == 0) {
+ if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "align")))
+ markup_track->align = ALIGN_LEFT;
+ else
+ xmlFree(s);
+ }
+ if (strcmp(n->name, "th") == 0) {
+ if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "align")))
+ markup_track->align = ALIGN_CENTER;
+ else
+ xmlFree(s);
+ }
+
+ /* Some of TABLE's attributes apply to the table cells contained
+ * within the table. Those details are stored so they may be applied
+ * to the cells when we get to them. */
+ if (strcmp((const char *) n->name, "table") == 0) {
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "cellpadding"))) {
+ char *endp;
+ long value = strtol(s, &endp, 10);
+ /* precentage padding width not implemented */
+ if (*endp == 0 && 0 <= value && value < 1000) {
+ markup_track->padding_width = value;
+ markup_track->cell_padding = true;
+ }
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "border"))) {
+ markup_track->border_color = border_color;
+ int border_width = atoi(s);
+ /* percentage border width not implemented */
+ if (!strrchr(s, '%') && 0 < border_width) {
+ markup_track->cell_border = true;
+ }
+ xmlFree(s);
+ }
+ }
+
return style;
}
@@ -1030,7 +1283,7 @@ struct css_style * box_get_style(struct content *c,
void box_solve_display(struct css_style *style, bool root)
{
- if (style->display == CSS_DISPLAY_NONE) /* 1. */
+ if (style->display == CSS_DISPLAY_NONE) /* 1. */
return;
else if (style->position == CSS_POSITION_ABSOLUTE ||
style->position == CSS_POSITION_FIXED) /* 2. */
@@ -1067,106 +1320,6 @@ void box_solve_display(struct css_style *style, bool root)
/**
- * Set the cellpadding on a table.
- *
- * \param box box to set cellpadding on
- * \param value padding in pixels
- *
- * The descendants of the box are searched for table cells, and the padding is
- * set on each one.
- */
-
-void box_set_cellpadding(struct box *box, int value)
-{
- /* The tree is not normalized yet, so accept cells not in rows and
- * rows not in row groups. */
- struct box *child;
- for (child = box->children; child; child = child->next) {
- switch (child->type) {
- case BOX_TABLE_ROW_GROUP:
- case BOX_TABLE_ROW:
- box_set_cellpadding(child, value);
- break;
- case BOX_TABLE_CELL:
- for (unsigned int i = 0; i != 4; i++) {
- child->style->padding[i].padding =
- CSS_PADDING_LENGTH;
- child->style->padding[i].value.length.value =
- value;
- child->style->padding[i].value.length.unit =
- CSS_UNIT_PX;
- }
- break;
- default:
- break;
- }
- }
-}
-
-
-/**
- * Set the borders on a table.
- *
- * \param box box to set cellpadding on
- * \param value border in pixels
- *
- * The descendants of the box are searched for table cells, and the border is
- * set on each one.
- */
-
-void box_set_table_border(struct box *box, int value, colour color)
-{
- struct box *child;
-
- if (box->type == BOX_TABLE) {
- for (unsigned int i = 0; i != 4; i++) {
- if (box->style->border[i].style ==
- CSS_BORDER_STYLE_NONE) {
- box->style->border[i].color = color;
- box->style->border[i].width.width =
- CSS_BORDER_WIDTH_LENGTH;
- box->style->border[i].width.value.value =
- value;
- box->style->border[i].width.value.unit =
- CSS_UNIT_PX;
- box->style->border[i].style =
- CSS_BORDER_STYLE_OUTSET;
- }
- }
- }
-
- /* The tree is not normalized yet, so accept cells not in rows and
- * rows not in row groups. */
- for (child = box->children; child; child = child->next) {
- switch (child->type) {
- case BOX_TABLE_ROW_GROUP:
- case BOX_TABLE_ROW:
- box_set_table_border(child, value, color);
- break;
- case BOX_TABLE_CELL:
- for (unsigned int i = 0; i != 4; i++) {
- if (child->style->border[i].style ==
- CSS_BORDER_STYLE_NONE) {
- child->style->border[i].color = color;
- child->style->border[i].width.width =
- CSS_BORDER_WIDTH_LENGTH;
- child->style->border[i].width.value.value =
- 1;
- child->style->border[i].width.value.unit =
- CSS_UNIT_PX;
- child->style->border[i].style =
- CSS_BORDER_STYLE_INSET;
- }
- }
- break;
- default:
- break;
- }
- }
-}
-
-
-/**
* Apply the CSS text-transform property to given text for its ASCII chars.
*
* \param s string to transform
@@ -1497,7 +1650,8 @@ bool box_object(BOX_SPECIAL_PARAMS)
/* convert children and place into fallback */
for (c = n->children; c; c = c->next) {
if (!convert_xml_to_box(c, content, box->style, box,
- &inline_container, 0, 0, 0))
+ &inline_container, 0, 0, 0, markup_track,
+ author))
return false;
}
box->fallback = box->children;
@@ -1576,25 +1730,29 @@ struct box_result box_applet(xmlNode *n, struct box_status *status,
if (!pp)
goto no_memory;
- if ((s = (char *) xmlGetProp(c, (const xmlChar *) "name")) != NULL) {
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "name")) != NULL) {
pp->name = strdup(s);
xmlFree(s);
if (!pp->name)
goto no_memory;
}
- if ((s = (char *) xmlGetProp(c, (const xmlChar *) "value")) != NULL) {
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "value")) != NULL) {
pp->value = strdup(s);
xmlFree(s);
if (!pp->value)
goto no_memory;
}
- if ((s = (char *) xmlGetProp(c, (const xmlChar *) "type")) != NULL) {
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "type")) != NULL) {
pp->type = strdup(s);
xmlFree(s);
if (!pp->type)
goto no_memory;
}
- if ((s = (char *) xmlGetProp(c, (const xmlChar *) "valuetype")) != NULL) {
+ if ((s = (char *) xmlGetProp(c, (const xmlChar *)
+ "valuetype")) != NULL) {
pp->valuetype = strdup(s);
xmlFree(s);
if (!pp->valuetype)
@@ -1660,7 +1818,8 @@ bool box_frameset(BOX_SPECIAL_PARAMS)
return true;
}
- content->data.html.frameset = talloc_zero(content, struct content_html_frames);
+ content->data.html.frameset = talloc_zero(content,
+ struct content_html_frames);
if (!content->data.html.frameset)
return false;
@@ -1723,7 +1882,8 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
default_border = false;
xmlFree(s);
}
- /* common extension: bordercolor="#RRGGBB|<named colour>" to control all children */
+ /* common extension: bordercolor="#RRGGBB|<named colour>" to control
+ *all children */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) {
parse_inline_colour(s, &default_border_colour);
xmlFree(s);
@@ -1733,7 +1893,8 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
f->cols = cols;
f->rows = rows;
f->scrolling = SCROLLING_NO;
- f->children = talloc_array(content, struct content_html_frames, (rows * cols));
+ f->children = talloc_array(content, struct content_html_frames,
+ (rows * cols));
for (row = 0; row < rows; row++) {
for (col = 0; col < cols; col++) {
index = (row * cols) + col;
@@ -1785,7 +1946,8 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
url = NULL;
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "src"))) {
- box_extract_link(s, content->data.html.base_url, &url);
+ box_extract_link(s, content->data.html.base_url,
+ &url);
xmlFree(s);
}
@@ -1793,7 +1955,8 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
if (url) {
/* no self-references */
if (strcmp(content->data.html.base_url, url))
- frame->url = talloc_strdup(content, url);
+ frame->url = talloc_strdup(content,
+ url);
free(url);
url = NULL;
}
@@ -1830,7 +1993,8 @@ bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
frame->margin_height = atoi(s);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(c, (const xmlChar *) "bordercolor"))) {
+ if ((s = (char *) xmlGetProp(c, (const xmlChar *)
+ "bordercolor"))) {
parse_inline_colour(s, &frame->border_colour);
xmlFree(s);
}
@@ -2020,7 +2184,8 @@ bool box_input(BOX_SPECIAL_PARAMS)
type = (char *) xmlGetProp(n, (const xmlChar *) "type");
if (type && strcasecmp(type, "password") == 0) {
- if (!box_input_text(n, content, box, 0, true))
+ if (!box_input_text(n, content, box, 0, markup_track, author,
+ true))
goto no_memory;
gadget = box->gadget;
gadget->box = box;
@@ -2070,7 +2235,7 @@ bool box_input(BOX_SPECIAL_PARAMS)
} else if (type && (strcasecmp(type, "submit") == 0 ||
strcasecmp(type, "reset") == 0)) {
struct box *inline_container, *inline_box;
- if (!box_button(n, content, box, 0))
+ if (!box_button(n, content, box, 0, markup_track, author))
goto no_memory;
inline_container = box_create(0, 0, 0, 0, 0, content);
if (!inline_container)
@@ -2098,7 +2263,7 @@ bool box_input(BOX_SPECIAL_PARAMS)
} else if (type && strcasecmp(type, "button") == 0) {
struct box *inline_container, *inline_box;
- if (!box_button(n, content, box, 0))
+ if (!box_button(n, content, box, 0, markup_track, author))
goto no_memory;
inline_container = box_create(0, 0, 0, 0, 0, content);
if (!inline_container)
@@ -2142,7 +2307,8 @@ bool box_input(BOX_SPECIAL_PARAMS)
html.base_url) != 0) {
if (!html_fetch_object(content, url,
box, image_types,
- content->available_width,
+ content->
+ available_width,
1000, false)) {
free(url);
goto no_memory;
@@ -2154,7 +2320,8 @@ bool box_input(BOX_SPECIAL_PARAMS)
} else {
/* the default type is "text" */
- if (!box_input_text(n, content, box, 0, false))
+ if (!box_input_text(n, content, box, 0, markup_track, author,
+ false))
goto no_memory;
gadget = box->gadget;
gadget->box = box;
@@ -2419,6 +2586,7 @@ bool box_select_add_option(struct form_control *control, xmlNode *n)
{
char *value = 0;
char *text = 0;
+ char *text_nowrap = 0;
bool selected;
xmlChar *content;
xmlChar *s;
@@ -2441,14 +2609,22 @@ bool box_select_add_option(struct form_control *control, xmlNode *n)
selected = xmlHasProp(n, (const xmlChar *) "selected");
- if (!form_add_option(control, value, text, selected))
+ /* replace spaces/TABs with hard spaces to prevent line wrapping */
+ text_nowrap = cnv_space2nbsp(text);
+ if (!text_nowrap)
+ goto no_memory;
+
+ if (!form_add_option(control, value, text_nowrap, selected))
goto no_memory;
+ free(text);
+
return true;
no_memory:
free(value);
free(text);
+ free(text_nowrap);
return false;
}
diff --git a/render/box_normalise.c b/render/box_normalise.c
index ce00bad15..37474856f 100644
--- a/render/box_normalise.c
+++ b/render/box_normalise.c
@@ -141,7 +141,7 @@ bool box_normalise_block(struct box *block, struct content *c)
style = talloc_memdup(c, block->style, sizeof *style);
if (!style)
return false;
- css_cascade(style, &css_blank_style);
+ css_cascade(style, &css_blank_style, NULL);
table = box_create(style, block->href, block->target,
0, 0, c);
if (!table) {
@@ -225,7 +225,7 @@ bool box_normalise_table(struct box *table, struct content * c)
free(col_info.spans);
return false;
}
- css_cascade(style, &css_blank_style);
+ css_cascade(style, &css_blank_style, NULL);
row_group = box_create(style, table->href,
table->target, 0, 0, c);
if (!row_group) {
@@ -401,7 +401,7 @@ bool box_normalise_table_row_group(struct box *row_group,
sizeof *style);
if (!style)
return false;
- css_cascade(style, &css_blank_style);
+ css_cascade(style, &css_blank_style, NULL);
row = box_create(style, row_group->href,
row_group->target, 0, 0, c);
if (!row) {
@@ -501,7 +501,7 @@ bool box_normalise_table_row(struct box *row,
style = talloc_memdup(c, row->style, sizeof *style);
if (!style)
return false;
- css_cascade(style, &css_blank_style);
+ css_cascade(style, &css_blank_style, NULL);
cell = box_create(style, row->href, row->target, 0, 0,
c);
if (!cell) {