diff --git a/src/document/css/apply.c b/src/document/css/apply.c index 563cf596..92c894a9 100644 --- a/src/document/css/apply.c +++ b/src/document/css/apply.c @@ -95,6 +95,38 @@ css_apply_font_attribute(struct html_context *html_context, element->attr.style.attr &= ~prop->value.font_attribute.rem; } +static void +css_apply_list_style(struct html_context *html_context, + struct html_element *element, struct css_property *prop) +{ + assert(prop->value_type == CSS_VT_LIST_STYLE); + + element->parattr.list_number = (prop->value.list_style > CSS_LIST_ORDINAL); + switch (prop->value.list_style) { + case CSS_LIST_NONE: element->parattr.flags = P_NO_BULLET; break; + case CSS_LIST_DISC: element->parattr.flags = P_O; break; + case CSS_LIST_CIRCLE: element->parattr.flags = P_O; break; + case CSS_LIST_SQUARE: element->parattr.flags = P_PLUS; break; + case CSS_LIST_DECIMAL: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_DECIMAL_LEADING_ZERO: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_LOWER_ROMAN: element->parattr.flags = P_roman; break; + case CSS_LIST_UPPER_ROMAN: element->parattr.flags = P_ROMAN; break; + case CSS_LIST_LOWER_ALPHA: element->parattr.flags = P_alpha; break; + case CSS_LIST_UPPER_ALPHA: element->parattr.flags = P_ALPHA; break; + case CSS_LIST_LOWER_GREEK: element->parattr.flags = P_roman; break; + case CSS_LIST_LOWER_LATIN: element->parattr.flags = P_alpha; break; + case CSS_LIST_UPPER_LATIN: element->parattr.flags = P_ALPHA; break; + case CSS_LIST_HEBREW: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_ARMENIAN: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_GEORGIAN: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_CJK_IDEOGRAPHIC: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_HIRAGANA: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_KATAKANA: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_HIRAGANA_IROHA: element->parattr.flags = P_NUMBER; break; + case CSS_LIST_KATAKANA_IROHA: element->parattr.flags = P_NUMBER; break; + } +} + /** @bug FIXME: Because the current CSS doesn't provide reasonable * defaults for each HTML element this applier will cause bad * rendering of @
 tags. */
@@ -115,6 +147,7 @@ static const css_applier_T css_appliers[CSS_PT_LAST] = {
 	/* CSS_PT_DISPLAY */		css_apply_display,
 	/* CSS_PT_FONT_STYLE */		css_apply_font_attribute,
 	/* CSS_PT_FONT_WEIGHT */	css_apply_font_attribute,
+	/* CSS_PT_LIST_STYLE */		css_apply_list_style,
 	/* CSS_PT_TEXT_ALIGN */		css_apply_text_align,
 	/* CSS_PT_TEXT_DECORATION */	css_apply_font_attribute,
 	/* CSS_PT_WHITE_SPACE */	css_apply_font_attribute,
diff --git a/src/document/css/property.c b/src/document/css/property.c
index 553bbcfd..3914fd1c 100644
--- a/src/document/css/property.c
+++ b/src/document/css/property.c
@@ -22,6 +22,7 @@ struct css_property_info css_property_info[CSS_PT_LAST] = {
 	{ "display",		CSS_PT_DISPLAY,		 CSS_VT_DISPLAY,	css_parse_display_value },
 	{ "font-style",		CSS_PT_FONT_STYLE,	 CSS_VT_FONT_ATTRIBUTE,	css_parse_font_style_value },
 	{ "font-weight",	CSS_PT_FONT_WEIGHT,	 CSS_VT_FONT_ATTRIBUTE,	css_parse_font_weight_value },
+	{ "list-style",		CSS_PT_LIST_STYLE,	 CSS_VT_LIST_STYLE,	css_parse_list_style_value },
 	{ "text-align",		CSS_PT_TEXT_ALIGN,	 CSS_VT_TEXT_ALIGN,	css_parse_text_align_value },
 	{ "text-decoration",	CSS_PT_TEXT_DECORATION,	 CSS_VT_FONT_ATTRIBUTE,	css_parse_text_decoration_value },
 	{ "white-space",	CSS_PT_WHITE_SPACE,	 CSS_VT_FONT_ATTRIBUTE,	css_parse_white_space_value },
diff --git a/src/document/css/property.h b/src/document/css/property.h
index 995f460e..3d96e66d 100644
--- a/src/document/css/property.h
+++ b/src/document/css/property.h
@@ -3,6 +3,7 @@
 #define EL__DOCUMENT_CSS_PROPERTY_H
 
 #include "document/format.h"
+#include "document/html/parser.h"
 #include "util/align.h"
 #include "util/color.h"
 #include "util/lists.h"
@@ -23,6 +24,7 @@ struct css_property {
 		CSS_PT_DISPLAY,
 		CSS_PT_FONT_STYLE,
 		CSS_PT_FONT_WEIGHT,
+		CSS_PT_LIST_STYLE,
 		CSS_PT_TEXT_ALIGN,
 		CSS_PT_TEXT_DECORATION,
 		CSS_PT_WHITE_SPACE,
@@ -35,6 +37,7 @@ struct css_property {
 		CSS_VT_COLOR,
 		CSS_VT_DISPLAY,
 		CSS_VT_FONT_ATTRIBUTE,
+		CSS_VT_LIST_STYLE,
 		CSS_VT_TEXT_ALIGN,
 		CSS_VT_LAST,
 	} value_type;
@@ -53,6 +56,30 @@ struct css_property {
 			enum text_style_format add, rem;
 		} font_attribute;
 		enum format_align text_align;
+		enum css_list_style {
+			CSS_LIST_NONE,
+			CSS_LIST_DISC,
+			CSS_LIST_CIRCLE,
+			CSS_LIST_SQUARE,
+			CSS_LIST_ORDINAL, /* Marker value */
+			CSS_LIST_DECIMAL,
+			CSS_LIST_DECIMAL_LEADING_ZERO,
+			CSS_LIST_LOWER_ROMAN,
+			CSS_LIST_UPPER_ROMAN,
+			CSS_LIST_LOWER_ALPHA,
+			CSS_LIST_UPPER_ALPHA,
+			CSS_LIST_LOWER_GREEK,
+			CSS_LIST_LOWER_LATIN,
+			CSS_LIST_UPPER_LATIN,
+			CSS_LIST_HEBREW,
+			CSS_LIST_ARMENIAN,
+			CSS_LIST_GEORGIAN,
+			CSS_LIST_CJK_IDEOGRAPHIC,
+			CSS_LIST_HIRAGANA,
+			CSS_LIST_KATAKANA,
+			CSS_LIST_HIRAGANA_IROHA,
+			CSS_LIST_KATAKANA_IROHA,
+		} list_style;
 		/* TODO:
 		 * Generic numbers
 		 * Percentages
diff --git a/src/document/css/value.c b/src/document/css/value.c
index a58f0521..3d96285e 100644
--- a/src/document/css/value.c
+++ b/src/document/css/value.c
@@ -197,6 +197,88 @@ css_parse_font_weight_value(struct css_property_info *propinfo,
 }
 
 
+int
+css_parse_list_style_value(struct css_property_info *propinfo,
+			   union css_property_value *value,
+			   struct scanner *scanner)
+{
+	struct scanner_token *token = get_scanner_token(scanner);
+
+	assert(propinfo->value_type == CSS_VT_LIST_STYLE);
+
+	if (token->type != CSS_TOKEN_IDENT) return 0;
+
+	if (scanner_token_contains(token, "none")) {
+		value->list_style = CSS_LIST_NONE;
+
+	} else if (scanner_token_contains(token, "disc")) {
+		value->list_style = CSS_LIST_DISC;
+
+	} else if (scanner_token_contains(token, "circle")) {
+		value->list_style = CSS_LIST_CIRCLE;
+
+	} else if (scanner_token_contains(token, "square")) {
+		value->list_style = CSS_LIST_SQUARE;
+
+	} else if (scanner_token_contains(token, "decimal")) {
+		value->list_style = CSS_LIST_DECIMAL;
+
+	} else if (scanner_token_contains(token, "decimal-leading-zero")) {
+		value->list_style = CSS_LIST_DECIMAL_LEADING_ZERO;
+
+	} else if (scanner_token_contains(token, "lower-roman")) {
+		value->list_style = CSS_LIST_LOWER_ROMAN;
+
+	} else if (scanner_token_contains(token, "upper-roman")) {
+		value->list_style = CSS_LIST_UPPER_ROMAN;
+
+	} else if (scanner_token_contains(token, "lower-alpha")) {
+		value->list_style = CSS_LIST_LOWER_ALPHA;
+
+	} else if (scanner_token_contains(token, "upper-alpha")) {
+		value->list_style = CSS_LIST_UPPER_ALPHA;
+
+	} else if (scanner_token_contains(token, "lower-greek")) {
+		value->list_style = CSS_LIST_LOWER_GREEK;
+
+	} else if (scanner_token_contains(token, "lower-latin")) {
+		value->list_style = CSS_LIST_LOWER_LATIN;
+
+	} else if (scanner_token_contains(token, "upper-latin")) {
+		value->list_style = CSS_LIST_UPPER_LATIN;
+
+	} else if (scanner_token_contains(token, "hebrew")) {
+		value->list_style = CSS_LIST_HEBREW;
+
+	} else if (scanner_token_contains(token, "armenian")) {
+		value->list_style = CSS_LIST_ARMENIAN;
+
+	} else if (scanner_token_contains(token, "georgian")) {
+		value->list_style = CSS_LIST_GEORGIAN;
+
+	} else if (scanner_token_contains(token, "cjk-ideographic")) {
+		value->list_style = CSS_LIST_CJK_IDEOGRAPHIC;
+
+	} else if (scanner_token_contains(token, "hiragana")) {
+		value->list_style = CSS_LIST_HIRAGANA;
+
+	} else if (scanner_token_contains(token, "katakana")) {
+		value->list_style = CSS_LIST_KATAKANA;
+
+	} else if (scanner_token_contains(token, "hiragana-iroha")) {
+		value->list_style = CSS_LIST_HIRAGANA_IROHA;
+
+	} else if (scanner_token_contains(token, "katakana-iroha")) {
+		value->list_style = CSS_LIST_KATAKANA_IROHA;
+
+	} else {
+		return 0;
+	}
+
+	skip_css_tokens(scanner, CSS_TOKEN_IDENT);
+	return 1;
+}
+
 int
 css_parse_text_align_value(struct css_property_info *propinfo,
 			   union css_property_value *value,
diff --git a/src/document/css/value.h b/src/document/css/value.h
index 25730170..96ab9b5e 100644
--- a/src/document/css/value.h
+++ b/src/document/css/value.h
@@ -51,6 +51,10 @@ int css_parse_font_style_value(struct css_property_info *propinfo,
 int css_parse_font_weight_value(struct css_property_info *propinfo,
 				union css_property_value *value,
 				struct scanner *scanner);
+/*! Takes no parser_data. */
+int css_parse_list_style_value(struct css_property_info *propinfo,
+                               union css_property_value *value,
+                               struct scanner *scanner);
 
 /*! Takes no parser_data. */
 int css_parse_text_align_value(struct css_property_info *propinfo,
diff --git a/src/document/dom/util.c b/src/document/dom/util.c
index b33cc2a7..fe03df78 100644
--- a/src/document/dom/util.c
+++ b/src/document/dom/util.c
@@ -62,6 +62,7 @@ init_template_by_style(struct screen_char *template, struct document_options *op
 				break;
 			case CSS_PT_DISPLAY:
 			case CSS_PT_NONE:
+			case CSS_PT_LIST_STYLE:
 			case CSS_PT_TEXT_ALIGN:
 			case CSS_PT_WHITE_SPACE:
 			case CSS_PT_LAST:
diff --git a/src/document/html/parser.h b/src/document/html/parser.h
index f989f7a0..b14ad402 100644
--- a/src/document/html/parser.h
+++ b/src/document/html/parser.h
@@ -80,6 +80,7 @@ enum format_list_flag {
 	P_ALPHA = 3,
 	P_roman = 4,
 	P_ROMAN = 5,
+	P_NO_BULLET = 6,
 
 	P_STAR = 1,
 	P_O = 2,
diff --git a/src/document/html/parser/general.c b/src/document/html/parser/general.c
index 7e8de820..1bcef8a9 100644
--- a/src/document/html/parser/general.c
+++ b/src/document/html/parser/general.c
@@ -852,6 +852,8 @@ void
 html_li(struct html_context *html_context, unsigned char *a,
         unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
 {
+	int t = par_format.flags & P_LISTMASK;
+
 	/* When handling the code 
  • @was_li will be 1 and it means we * have to insert a line break since no list item content has done it * for us. */ @@ -862,9 +864,9 @@ html_li(struct html_context *html_context, unsigned char *a, /*kill_html_stack_until(html_context, 0 "", "UL", "OL", NULL);*/ - if (!par_format.list_number) { - int t = par_format.flags & P_LISTMASK; - + if (t == P_NO_BULLET) { + /* Print nothing. */ + } else if (!par_format.list_number) { if (t == P_O) put_chrs(html_context, "○", 7); /* o */ else if (t == P_PLUS) put_chrs(html_context, "⎕", 7); /* + */ else put_chrs(html_context, "•", 7); /* * */ diff --git a/test/css/list-style.html b/test/css/list-style.html new file mode 100644 index 00000000..32c1a12c --- /dev/null +++ b/test/css/list-style.html @@ -0,0 +1,194 @@ + + + +

    + list-style:none +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:disc +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:circle +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:square +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:decimal +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:decimal-leading-zero +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:lower-roman +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:upper-roman +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:lower-alpha +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:upper-alpha +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:lower-greek +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:lower-latin +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:upper-latin +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:hebrew +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:armenian +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:georgian +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:cjk-ideograph +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:hiragana +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:katakana +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:hiragana-iroha +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + +

    + list-style:katakana-iroha +

      +
    1. first
    2. +
    3. second
    4. +
    5. third
    6. +
    +

    + + +