summaryrefslogtreecommitdiff
path: root/src/select/format_list_style.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/select/format_list_style.c')
-rw-r--r--src/select/format_list_style.c1229
1 files changed, 1229 insertions, 0 deletions
diff --git a/src/select/format_list_style.c b/src/select/format_list_style.c
new file mode 100644
index 0000000..0e3a39e
--- /dev/null
+++ b/src/select/format_list_style.c
@@ -0,0 +1,1229 @@
+/*
+ * This file is part of LibCSS
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2021 Vincent Sanders <vince@netsurf-browser.org>
+ */
+
+#include "select/propget.h"
+#include "utils/utils.h"
+
+#define SYMBOL_SIZE 8
+typedef char symbol_t[SYMBOL_SIZE];
+
+/**
+ * numeric representation of the value using a system
+ */
+struct numeric {
+ uint8_t *val; /* buffer containing the numeric values */
+ size_t len; /* length of alen */
+ size_t used; /* number of numeric values used */
+ bool negative; /* if the value is negative */
+};
+
+/**
+ * list counter style
+ */
+struct list_counter_style {
+ /** style name for debug purposes */
+ const char *name;
+ /** function to calculate the system */
+ css_error (*system)(int value, const struct list_counter_style *cstyle, struct numeric *nval);
+ /** fallback style if this system fails */
+ const struct list_counter_style* fallback;
+ /** array of symbols which represent this style */
+ const symbol_t *symbols;
+ /** symbol weights for additive schemes */
+ const int *weights;
+ /** number of items in symbol and weight table */
+ const size_t items;
+ /** range of acceptable values */
+ struct {
+ const int start; /**< first acceptable value for this style */
+ const int end; /**< last acceptable value for this style */
+ } range;
+
+ /** padding formatting */
+ struct {
+ const unsigned int length;
+ const symbol_t value;
+ } pad;
+ /** negative value formating */
+ struct {
+ const char *pre;
+ const char *post;
+ } negative;
+ /** prefix formatting */
+ const char *prefix;
+ /** suffix formatting */
+ const char *suffix;
+};
+
+
+/**
+ * Copy a null-terminated UTF-8 string to buffer at offset, if there is space
+ *
+ * \param[in] buf The output buffer
+ * \param[in] buflen The length of \a buf
+ * \param[in] pos Current position in \a buf
+ * \param[in] str The string to copy into \a buf
+ * \return The number of bytes needed in the output buffer which may be
+ * larger than \a buflen but the buffer will not be overrun
+ */
+static inline size_t
+copy_string(char *buf, const size_t buflen, size_t pos, const char *str)
+{
+ size_t sidx = 0; /* current string index */
+
+ while (str[sidx] != '\0') {
+ if (pos < buflen) {
+ buf[pos] = str[sidx];
+ }
+ pos++;
+ sidx++;
+ }
+
+ return sidx;
+}
+
+/**
+ * Copy a UTF-8 symbol to buffer at offset, if there is space
+ *
+ * \param[in] buf The output buffer
+ * \param[in] buflen The length of \a buf
+ * \param[in] pos Current position in \a buf
+ * \param[in] symbol The symbol to copy into \a buf
+ * \return The number of bytes needed in the output buffer which may be
+ * larger than \a buflen but the buffer will not be overrun
+ */
+static inline size_t
+copy_symbol(char *buf, const size_t buflen, size_t pos, const symbol_t symbol)
+{
+ size_t sidx = 0; /* current symbol index */
+
+ while ((sidx < sizeof(symbol_t)) && (symbol[sidx] != '\0')) {
+ if (pos < buflen) {
+ buf[pos] = symbol[sidx];
+ }
+ pos++;
+ sidx++;
+ }
+
+ return sidx;
+}
+
+/**
+ * maps numeric values to output values with a symbol table
+ *
+ * Takes a list of numeric values and for each one outputs the
+ * compete symbol (in utf8) to an output buffer.
+ *
+ * \param buf The output buffer
+ * \param buflen the length of \a buf
+ * \param aval array of alphabet values
+ * \param alen The number of values in \a alen
+ * \param symtab The symbol table
+ * \param symtablen The number of symbols in \a symtab
+ * \return The number of bytes needed in the output buffer whichmay be
+ * larger than \a buflen but the buffer will not be overrun
+ */
+static size_t
+nval_to_symbols(struct numeric *nval,
+ const struct list_counter_style *cstyle,
+ char *buf, const size_t buflen)
+{
+ size_t oidx = 0;
+ size_t aidx; /* numeral index */
+ const char *suffix = "."; /* default sufffix string */
+ const char *negative_pre = "-"; /* default negative string */
+
+ /* prefix */
+ if (cstyle->prefix != NULL) {
+ oidx += copy_string(buf, buflen, oidx, cstyle->prefix);
+ }
+
+ /* negative pre */
+ if (nval->negative) {
+ if (cstyle->negative.pre != NULL) {
+ negative_pre = cstyle->negative.pre;
+ }
+ oidx += copy_string(buf, buflen, oidx, negative_pre);
+ }
+
+ /* add padding if required */
+ if (nval->used < cstyle->pad.length) {
+ size_t pidx; /* padding index */
+ for (pidx = cstyle->pad.length - nval->used; pidx > 0; pidx--) {
+ oidx += copy_symbol(buf, buflen, oidx,
+ cstyle->pad.value);
+ }
+ }
+
+ /* map symbols */
+ for (aidx = 0; aidx < nval->used; aidx++) {
+ oidx += copy_symbol(buf, buflen, oidx,
+ cstyle->symbols[nval->val[aidx]]);
+ }
+
+ /* negative post */
+ if ((nval->negative) && (cstyle->negative.post != NULL)) {
+ oidx += copy_string(buf, buflen, oidx, cstyle->negative.post);
+ }
+
+ /* suffix */
+ if (cstyle->suffix != NULL) {
+ suffix = cstyle->suffix;
+ }
+ oidx += copy_string(buf, buflen, oidx, suffix);
+
+ return oidx;
+}
+
+
+/**
+ * generate numeric symbol values
+ *
+ * fills array with numeric values that represent the input value
+ *
+ * \param ares Buffer to recive the converted values
+ * \param alen the length of \a ares buffer
+ * \param value The value to convert
+ * \param cstyle The counter style in use
+ * \return The length a complete conversion which may be larger than \a alen
+ */
+static css_error
+calc_numeric_system(int value,
+ const struct list_counter_style *cstyle,
+ struct numeric *nval)
+{
+ size_t idx = 0;
+ uint8_t *first;
+ uint8_t *last;
+
+ if (value == 0) {
+ if (nval->len >= 1) {
+ nval->val[0] = 0;
+ }
+ nval->used = 1;
+ return CSS_OK;
+ }
+
+ if (value < 0) {
+ nval->negative = true;
+ value = abs(value);
+ } else {
+ nval->negative = false;
+ }
+
+ /* generate alphabet values in ascending order */
+ while (value > 0) {
+ if (idx < nval->len) {
+ nval->val[idx] = value % cstyle->items;
+ }
+ idx++;
+ value = value / cstyle->items;
+ }
+
+ /* put the values in decending order */
+ first = nval->val;
+ if (idx < nval->len) {
+ last = first + (idx - 1);
+ } else {
+ last = first + (nval->len - 1);
+ }
+ while (first < last) {
+ *first ^= *last;
+ *last ^= *first;
+ *first ^= *last;
+ first++;
+ last--;
+ }
+
+ nval->used = idx;
+
+ return CSS_OK;
+}
+
+
+/**
+ * generate cyclic symbol values
+ *
+ * fills array with cyclic values that represent the input value
+ *
+ * \param ares Buffer to recive the converted values
+ * \param alen the length of \a ares buffer
+ * \param value The value to convert
+ * \param cstyle The counter style in use
+ * \return The length a complete conversion which may be larger than \a alen
+ */
+static css_error
+calc_cyclic_system(int value,
+ const struct list_counter_style *cstyle,
+ struct numeric *nval)
+{
+ if (nval->len == 0) {
+ return CSS_INVALID;
+ }
+ if (cstyle->items == 1) {
+ /* there is only one symbol so select it */
+ nval->val[0] = 0;
+ } else {
+ nval->val[0] = (value - 1) % cstyle->items;
+ }
+ nval->used = 1;
+ nval->negative = false;
+
+ return CSS_OK;
+}
+
+
+/**
+ * generate addative symbol values
+ *
+ * fills array with numeric values that represent the input value
+ *
+ * \param ares Buffer to recive the converted values
+ * \param alen the length of \a ares buffer
+ * \param value The value to convert
+ * \param wlen The number of weights
+ * \return The length a complete conversion which may be larger than \a alen
+ */
+static css_error
+calc_additive_system(int value,
+ const struct list_counter_style *cstyle,
+ struct numeric *nval)
+{
+ size_t widx; /* weight index */
+ size_t aidx = 0; /* numerals used */
+ size_t idx;
+ size_t times; /* number of times a weight occours */
+
+ /* ensure value is within acceptable range of this system */
+ if ((value < cstyle->range.start) || (value > cstyle->range.end)) {
+ return CSS_INVALID;
+ }
+
+ /* zero needs a specific weight */
+ if (value == 0) {
+ /* search weights for a zero entry */
+ for (widx = 0; widx < cstyle->items; widx++) {
+ if (cstyle->weights[widx] == 0) {
+ if (nval->len > 0) {
+ nval->val[0] = widx;
+ }
+
+ nval->used = 1;
+ nval->negative = false;
+ return CSS_OK;
+ }
+ }
+ return CSS_INVALID;
+ }
+
+ /* negative values */
+ if (value < 0) {
+ nval->negative = true;
+ value = abs(value);
+ } else {
+ nval->negative = false;
+ }
+
+ /* iterate over the available weights */
+ for (widx = 0; widx < cstyle->items; widx++) {
+ if (cstyle->weights[widx] == 0) {
+ break;
+ }
+ times = value / cstyle->weights[widx];
+ if (times > 0) {
+ for (idx = 0;idx < times;idx++) {
+ if (aidx < nval->len) {
+ nval->val[aidx] = widx;
+ }
+ aidx++;
+ }
+
+ value -= times * cstyle->weights[widx];
+ }
+ }
+
+ nval->used = aidx;
+
+ return CSS_OK;
+}
+
+
+/**
+ * generate alphabet symbol values for latin and greek labelling
+ *
+ * fills array with alphabet values suitable for the input value
+ *
+ * \param ares Buffer to recive the converted values
+ * \param alen the length of \a ares buffer
+ * \param value The value to convert
+ * \param slen The number of symbols in the alphabet
+ * \return The length a complete conversion which may be larger than \a alen
+ */
+static css_error
+calc_alphabet_system(int value,
+ const struct list_counter_style *cstyle,
+ struct numeric *nval)
+{
+ size_t idx = 0;
+ uint8_t *first;
+ uint8_t *last;
+
+ if (value < 1) {
+ return CSS_INVALID;
+ }
+
+ /* generate alphabet values in ascending order */
+ while (value > 0) {
+ --value;
+ if (idx < nval->len) {
+ nval->val[idx] = value % cstyle->items;
+ }
+ idx++;
+ value = value / cstyle->items;
+ }
+
+ /* put the values in decending order */
+ first = nval->val;
+ if (idx < nval->len) {
+ last = first + (idx - 1);
+ } else {
+ last = first + (nval->len - 1);
+ }
+ while (first < last) {
+ *first ^= *last;
+ *last ^= *first;
+ *first ^= *last;
+ first++;
+ last--;
+ }
+
+ nval->used = idx;
+ nval->negative = false;
+
+ return CSS_OK;
+}
+
+
+/**
+ * Roman numeral conversion
+ *
+ * \return The number of numerals that are nesesary for full output
+ */
+static css_error
+calc_roman_system(int value,
+ const struct list_counter_style *cstyle,
+ struct numeric *nval)
+{
+ const int S[] = { 0, 2, 4, 2, 4, 2, 4 };
+ size_t k = 0; /* index into output buffer */
+ unsigned int i = 0; /* index into maps */
+ int r;
+ int r2 = 0;
+ size_t L;
+
+ assert(cstyle->items == 7);
+
+ /* ensure value is within acceptable range of this system */
+ if ((value < cstyle->range.start) || (value > cstyle->range.end)) {
+ return CSS_INVALID;
+ }
+
+ L = cstyle->items - 1;
+
+ while (value > 0) {
+ if (cstyle->weights[i] <= value) {
+ r = value / cstyle->weights[i];
+ value = value - (r * cstyle->weights[i]);
+ if (i < L) {
+ /* lookahead */
+ r2 = value / cstyle->weights[i+1];
+ }
+ if (i < L && r2 >= S[i+1]) {
+ /* will violate repeat boundary on next pass */
+ value = value - (r2 * cstyle->weights[i+1]);
+ if (k < nval->len) {
+ nval->val[k++] = i+1;
+ }
+ if (k < nval->len) {
+ nval->val[k++] = i-1;
+ }
+ } else if (S[i] && r >= S[i]) {
+ /* violated repeat boundary on this pass */
+ if (k < nval->len) {
+ nval->val[k++] = i;
+ }
+ if (k < nval->len) {
+ nval->val[k++] = i-1;
+ }
+ } else {
+ while ((r-- > 0) && (k < nval->len)) {
+ nval->val[k++] = i;
+ }
+ }
+ }
+ i++;
+ }
+
+ nval->used = k;
+ nval->negative = false;
+
+ return CSS_OK;
+}
+
+
+/* tables for all the counter styles */
+
+static const symbol_t decimal_symbols[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
+};
+static const struct list_counter_style lcs_decimal = {
+ .name = "decimal",
+ .system = calc_numeric_system,
+ .symbols = decimal_symbols,
+ .items = (sizeof(decimal_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t georgian_symbols[] = {
+ "ჵ",
+ "ჰ", "ჯ", "ჴ", "ხ", "ჭ", "წ", "ძ", "ც", "ჩ",
+ "შ", "ყ", "ღ", "ქ", "ფ", "ჳ", "ტ", "ს", "რ",
+ "ჟ", "პ", "ო", "ჲ", "ნ", "მ", "ლ", "კ", "ი",
+ "თ", "ჱ", "ზ", "ვ", "ე", "დ", "გ", "ბ", "ა",
+};
+static const int georgian_weights[] = {
+ 10000,
+ 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000,
+ 900, 800, 700, 600, 500, 400, 300, 200, 100,
+ 90, 80, 70, 60, 50, 40, 30, 20, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+static const struct list_counter_style lcs_georgian = {
+ .name="georgian",
+ .system = calc_additive_system,
+ .fallback = &lcs_decimal,
+ .symbols = georgian_symbols,
+ .weights = georgian_weights,
+ .items = (sizeof(georgian_symbols) / SYMBOL_SIZE),
+ .range = { .start = 1, .end = 19999 },
+};
+
+
+static const symbol_t upper_armenian_symbols[] = {
+ "Ք", "Փ", "Ւ", "Ց", "Ր", "Տ", "Վ", "Ս", "Ռ",
+ "Ջ", "Պ", "Չ", "Ո", "Շ", "Ն", "Յ", "Մ", "Ճ",
+ "Ղ", "Ձ", "Հ", "Կ", "Ծ", "Խ", "Լ", "Ի", "Ժ",
+ "Թ", "Ը", "Է", "Զ", "Ե", "Դ", "Գ", "Բ", "Ա"
+};
+static const int armenian_weights[] = {
+ 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000,
+ 900, 800, 700, 600, 500, 400, 300, 200, 100,
+ 90, 80, 70, 60, 50, 40, 30, 20, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+static const struct list_counter_style lcs_upper_armenian = {
+ .name = "upper-armenian",
+ .system = calc_additive_system,
+ .fallback = &lcs_decimal,
+ .symbols = upper_armenian_symbols,
+ .weights = armenian_weights,
+ .items = (sizeof(upper_armenian_symbols) / SYMBOL_SIZE),
+ .range = { .start = 1, .end = 9999 },
+};
+
+
+static const symbol_t lower_armenian_symbols[] = {
+ "ք", "փ", "ւ", "ց", "ր", "տ", "վ", "ս", "ռ",
+ "ջ", "պ", "չ", "ո", "շ", "ն", "յ", "մ", "ճ",
+ "ղ", "ձ", "հ", "կ", "ծ", "խ", "լ", "ի", "ժ",
+ "թ", "ը", "է", "զ", "ե", "դ", "գ", "բ", "ա"
+};
+static const struct list_counter_style lcs_lower_armenian = {
+ .name = "lower-armenian",
+ .system = calc_additive_system,
+ .fallback = &lcs_decimal,
+ .symbols = lower_armenian_symbols,
+ .weights = armenian_weights,
+ .items = (sizeof(lower_armenian_symbols) / SYMBOL_SIZE),
+ .range = { .start = 1, .end = 9999 },
+};
+
+
+static const struct list_counter_style lcs_decimal_leading_zero = {
+ .name = "decimal-leading-zero",
+ .system = calc_numeric_system,
+ .symbols = decimal_symbols,
+ .items = (sizeof(decimal_symbols) / SYMBOL_SIZE),
+ .pad = { .length = 2, .value = "0" },
+};
+
+
+static const symbol_t lower_greek_symbols[] = {
+ "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ",
+ "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ",
+ "φ", "χ", "ψ", "ω"
+};
+static const struct list_counter_style lcs_lower_greek = {
+ .name = "lower-greek",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = lower_greek_symbols,
+ .items = (sizeof(lower_greek_symbols) / SYMBOL_SIZE),
+};
+
+
+static const symbol_t upper_alpha_symbols[] = {
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z"
+};
+static const struct list_counter_style lcs_upper_alpha = {
+ .name = "upper-alpha",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = upper_alpha_symbols,
+ .items = (sizeof(upper_alpha_symbols) / SYMBOL_SIZE),
+};
+
+
+static const symbol_t lower_alpha_symbols[] = {
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v", "w", "x", "y", "z"
+};
+static struct list_counter_style lcs_lower_alpha = {
+ .name = "lower-alpha",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = lower_alpha_symbols,
+ .items = (sizeof(lower_alpha_symbols) / SYMBOL_SIZE),
+};
+
+
+static const int roman_weights[] = {
+ 1000, 500, 100, 50, 10, 5, 1
+};
+static const symbol_t upper_roman_symbols[] = {
+ "M", "D", "C", "L", "X", "V", "I"
+};
+static const struct list_counter_style lcs_upper_roman = {
+ .name = "upper-roman",
+ .system = calc_roman_system,
+ .fallback = &lcs_decimal,
+ .symbols = upper_roman_symbols,
+ .weights = roman_weights,
+ .items = (sizeof(upper_roman_symbols) / SYMBOL_SIZE),
+ .range = { .start = 1, .end = 3999 },
+};
+
+
+static const symbol_t lower_roman_symbols[] = {
+ "m", "d", "c", "l", "x", "v", "i"
+};
+static const struct list_counter_style lcs_lower_roman = {
+ .name = "lower-roman",
+ .system = calc_roman_system,
+ .fallback = &lcs_decimal,
+ .symbols = lower_roman_symbols,
+ .weights = roman_weights,
+ .items = (sizeof(lower_roman_symbols) / SYMBOL_SIZE),
+ .range = { .start = 1, .end = 3999 },
+};
+
+static const symbol_t disc_symbols[] = { "\xE2\x80\xA2"}; /* 2022 BULLET */
+static const struct list_counter_style lcs_disc = {
+ .name = "disc",
+ .system = calc_cyclic_system,
+ .symbols = disc_symbols,
+ .items = (sizeof(disc_symbols) / SYMBOL_SIZE),
+ .suffix = " ",
+};
+
+static const symbol_t circle_symbols[] = { "\342\227\213"}; /* 25CB WHITE CIRCLE */
+static const struct list_counter_style lcs_circle = {
+ .name = "circle",
+ .system = calc_cyclic_system,
+ .symbols = circle_symbols,
+ .items = (sizeof(circle_symbols) / SYMBOL_SIZE),
+ .suffix = " ",
+};
+
+static const symbol_t square_symbols[] = { "\342\226\252"}; /* 25AA BLACK SMALL SQUARE */
+static const struct list_counter_style lcs_square = {
+ .name = "square",
+ .system = calc_cyclic_system,
+ .symbols = square_symbols,
+ .items = (sizeof(square_symbols) / SYMBOL_SIZE),
+ .suffix = " ",
+};
+
+static const symbol_t binary_symbols[] = { "0", "1" };
+static const struct list_counter_style lcs_binary = {
+ .name = "binary",
+ .system = calc_numeric_system,
+ .symbols = binary_symbols,
+ .items = (sizeof(binary_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t octal_symbols[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7"
+};
+static const struct list_counter_style lcs_octal = {
+ .name = "octal",
+ .system = calc_numeric_system,
+ .symbols = octal_symbols,
+ .items = (sizeof(octal_symbols) / SYMBOL_SIZE),
+};
+
+
+static const symbol_t lower_hexadecimal_symbols[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "a", "b", "c", "d", "e", "f"
+};
+static const struct list_counter_style lcs_lower_hexadecimal = {
+ .name = "lower-hexadecimal",
+ .system = calc_numeric_system,
+ .symbols = lower_hexadecimal_symbols,
+ .items = (sizeof(lower_hexadecimal_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t upper_hexadecimal_symbols[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "a", "b", "c", "d", "e", "f"
+};
+static const struct list_counter_style lcs_upper_hexadecimal = {
+ .name = "upper-hexadecimal",
+ .system = calc_numeric_system,
+ .symbols = upper_hexadecimal_symbols,
+ .items = (sizeof(upper_hexadecimal_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t arabic_indic_symbols[] = {
+ "\xd9\xa0", "\xd9\xa1", "\xd9\xa2", "\xd9\xa3", "\xd9\xa4", "\xd9\xa5", "\xd9\xa6", "\xd9\xa7", "\xd9\xa8", "\xd9\xa9"
+};
+static const struct list_counter_style lcs_arabic_indic = {
+ .name = "arabic-indic",
+ .system = calc_numeric_system,
+ .symbols = arabic_indic_symbols,
+ .items = (sizeof(arabic_indic_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t bengali_symbols[] = {
+ "০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"
+};
+static const struct list_counter_style lcs_bengali = {
+ .name = "bengali",
+ .system = calc_numeric_system,
+ .symbols = bengali_symbols,
+ .items = (sizeof(bengali_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t cambodian_symbols[] = {
+ "០", "១", "២", "៣", "៤", "៥", "៦", "៧", "៨", "៩"
+};
+static const struct list_counter_style lcs_cambodian = {
+ .name = "cambodian",
+ .system = calc_numeric_system,
+ .symbols = cambodian_symbols,
+ .items = (sizeof(cambodian_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t cjk_decimal_symbols[] = {
+ "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九"
+};
+static const struct list_counter_style lcs_cjk_decimal = {
+ .name = "cjk-decimal",
+ .system = calc_numeric_system,
+ .symbols = cjk_decimal_symbols,
+ .suffix = "、",
+ .items = (sizeof(cjk_decimal_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t devanagari_symbols[] = {
+ "०", "१", "२", "३", "४", "५", "६", "७", "८", "९"
+};
+static const struct list_counter_style lcs_devanagari = {
+ .name = "devanagari",
+ .system = calc_numeric_system,
+ .symbols = devanagari_symbols,
+ .items = (sizeof(devanagari_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t gujarati_symbols[] = {
+ "૦", "૧", "૨", "૩", "૪", "૫", "૬", "૭", "૮", "૯"
+};
+static const struct list_counter_style lcs_gujarati = {
+ .name = "gujarati",
+ .system = calc_numeric_system,
+ .symbols = gujarati_symbols,
+ .items = (sizeof(gujarati_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t gurmukhi_symbols[] = {
+ "੦", "੧", "੨", "੩", "੪", "੫", "੬", "੭", "੮", "੯"
+};
+static const struct list_counter_style lcs_gurmukhi = {
+ .name = "gurmukhi",
+ .system = calc_numeric_system,
+ .symbols = gurmukhi_symbols,
+ .items = (sizeof(gurmukhi_symbols) / SYMBOL_SIZE),
+};
+
+static const int hebrew_weights[] = {
+ 10000,
+ 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000,
+ 400, 300, 200, 100,
+ 90, 80, 70, 60, 50, 40, 30, 20, 19, 18, 17, 16, 15, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+static const symbol_t hebrew_symbols[] = {
+ "\xD7\x99\xD7\xB3",
+ "\xD7\x98\xD7\xB3", "\xD7\x97\xD7\xB3", "\xD7\x96\xD7\xB3", "\xD7\x95\xD7\xB3", "\xD7\x94\xD7\xB3", "\xD7\x93\xD7\xB3", "\xD7\x92\xD7\xB3", "\xD7\x91\xD7\xB3", "\xD7\x90\xD7\xB3",
+ "\xD7\xAA", "\xD7\xA9", "\xD7\xA8", "\xD7\xA7",
+ "\xD7\xA6", "\xD7\xA4", "\xD7\xA2", "\xD7\xA1", "\xD7\xA0", "\xD7\x9E", "\xD7\x9C", /* 20 */"\xD7\x9B", "\xD7\x99\xD7\x98", "\xD7\x99\xD7\x97", "\xD7\x99\xD7\x96", "\xD7\x98\xD7\x96", "\xD7\x98\xD7\x95", "\xD7\x99",
+ "\xD7\x98", "\xD7\x97", "\xD7\x96", "\xD7\x95", "\xD7\x94", "\xD7\x93", "\xD7\x92", "\xD7\x91", "\xD7\x90"
+};
+static const struct list_counter_style lcs_hebrew = {
+ .name = "hebrew",
+ .system = calc_additive_system,
+ .fallback = &lcs_decimal,
+ .symbols = hebrew_symbols,
+ .weights = hebrew_weights,
+ .items = (sizeof(hebrew_symbols) / SYMBOL_SIZE),
+ .range = { .start = 1, .end = 10999 },
+};
+
+static const symbol_t kannada_symbols[] = {
+ "\xE0\xB3\xA6", "\xE0\xB3\xA7", "\xE0\xB3\xA8", "\xE0\xB3\xA9", "\xE0\xB3\xAA", "\xE0\xB3\xAB", "\xE0\xB3\xAC", "\xE0\xB3\xAD", "\xE0\xB3\xAE", "\xE0\xB3\xAF"
+};
+static const struct list_counter_style lcs_kannada = {
+ .name = "kannada",
+ .system = calc_numeric_system,
+ .symbols = kannada_symbols,
+ .items = (sizeof(kannada_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t lao_symbols[] = {
+ "໐", "໑", "໒", "໓", "໔", "໕", "໖", "໗", "໘", "໙"
+};
+static const struct list_counter_style lcs_lao = {
+ .name = "lao",
+ .system = calc_numeric_system,
+ .symbols = lao_symbols,
+ .items = (sizeof(lao_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t malayalam_symbols[] = {
+ "൦", "൧", "൨", "൩", "൪", "൫", "൬", "൭", "൮", "൯"
+};
+static const struct list_counter_style lcs_malayalam = {
+ .name = "malayalam",
+ .system = calc_numeric_system,
+ .symbols = malayalam_symbols,
+ .items = (sizeof(malayalam_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t mongolian_symbols[] = {
+ "᠐", "᠑", "᠒", "᠓", "᠔", "᠕", "᠖", "᠗", "᠘", "᠙"
+};
+static const struct list_counter_style lcs_mongolian = {
+ .name = "mongolian",
+ .system = calc_numeric_system,
+ .symbols = mongolian_symbols,
+ .items = (sizeof(mongolian_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t myanmar_symbols[] = {
+ "၀", "၁", "၂", "၃", "၄", "၅", "၆", "၇", "၈", "၉"
+};
+static const struct list_counter_style lcs_myanmar = {
+ .name = "myanmar",
+ .system = calc_numeric_system,
+ .symbols = myanmar_symbols,
+ .items = (sizeof(myanmar_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t oriya_symbols[] = {
+ "୦", "୧", "୨", "୩", "୪", "୫", "୬", "୭", "୮", "୯"
+};
+static const struct list_counter_style lcs_oriya = {
+ .name = "oriya",
+ .system = calc_numeric_system,
+ .symbols = oriya_symbols,
+ .items = (sizeof(oriya_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t persian_symbols[] = {
+ "۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"
+};
+static const struct list_counter_style lcs_persian = {
+ .name = "persian",
+ .system = calc_numeric_system,
+ .symbols = persian_symbols,
+ .items = (sizeof(persian_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t tamil_symbols[] = {
+ "௦", "௧", "௨", "௩", "௪", "௫", "௬", "௭", "௮", "௯"
+};
+static const struct list_counter_style lcs_tamil = {
+ .name = "tamil",
+ .system = calc_numeric_system,
+ .symbols = tamil_symbols,
+ .items = (sizeof(tamil_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t telugu_symbols[] = {
+ "౦", "౧", "౨", "౩", "౪", "౫", "౬", "౭", "౮", "౯"
+};
+static const struct list_counter_style lcs_telugu = {
+ .name = "telugu",
+ .system = calc_numeric_system,
+ .symbols = telugu_symbols,
+ .items = (sizeof(telugu_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t thai_symbols[] = {
+ "๐", "๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙"
+};
+static const struct list_counter_style lcs_thai = {
+ .name = "thai",
+ .system = calc_numeric_system,
+ .symbols = thai_symbols,
+ .items = (sizeof(thai_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t tibetan_symbols[] = {
+ "༠", "༡", "༢", "༣", "༤", "༥", "༦", "༧", "༨", "༩"
+};
+static const struct list_counter_style lcs_tibetan = {
+ .name = "tibetan",
+ .system = calc_numeric_system,
+ .symbols = tibetan_symbols,
+ .items = (sizeof(tibetan_symbols) / SYMBOL_SIZE),
+};
+
+static const symbol_t cjk_earthly_branch_symbols[] = {
+ "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"
+};
+static struct list_counter_style lcs_cjk_earthly_branch = {
+ .name = "cjk-earthly-branch",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = cjk_earthly_branch_symbols,
+ .items = (sizeof(cjk_earthly_branch_symbols) / SYMBOL_SIZE),
+ .suffix = "、",
+};
+
+static const symbol_t cjk_heavenly_stem_symbols[] = {
+ "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"
+};
+static struct list_counter_style lcs_cjk_heavenly_stem = {
+ .name = "cjk-heavenly-stem",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = cjk_heavenly_stem_symbols,
+ .items = (sizeof(cjk_heavenly_stem_symbols) / SYMBOL_SIZE),
+ .suffix = "、",
+};
+
+static const symbol_t hiragana_symbols[] = {
+ "あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "や", "ゆ", "よ", "ら", "り", "る", "れ", "ろ", "わ", "ゐ", "ゑ", "を", "ん"
+};
+static struct list_counter_style lcs_hiragana = {
+ .name = "hiragana",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = hiragana_symbols,
+ .items = (sizeof(hiragana_symbols) / SYMBOL_SIZE),
+ .suffix = "、",
+};
+
+static const symbol_t hiragana_iroha_symbols[] = {
+ "い", "ろ", "は", "に", "ほ", "へ", "と", "ち", "り", "ぬ", "る", "を", "わ", "か", "よ", "た", "れ", "そ", "つ", "ね", "な", "ら", "む", "う", "ゐ", "の", "お", "く", "や", "ま", "け", "ふ", "こ", "え", "て", "あ", "さ", "き", "ゆ", "め", "み", "し", "ゑ", "ひ", "も", "せ", "す"
+};
+static struct list_counter_style lcs_hiragana_iroha = {
+ .name = "hiragana-iroha",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = hiragana_iroha_symbols,
+ .items = (sizeof(hiragana_iroha_symbols) / SYMBOL_SIZE),
+ .suffix = "、",
+};
+
+static const symbol_t katakana_symbols[] = {
+ "ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ヤ", "ユ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヰ", "ヱ", "ヲ", "ン"
+};
+static struct list_counter_style lcs_katakana = {
+ .name = "katakana",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = katakana_symbols,
+ .items = (sizeof(katakana_symbols) / SYMBOL_SIZE),
+ .suffix = "、",
+};
+
+static const symbol_t katakana_iroha_symbols[] = {
+ "イ", "ロ", "ハ", "ニ", "ホ", "ヘ", "ト", "チ", "リ", "ヌ", "ル", "ヲ", "ワ", "カ", "ヨ", "タ", "レ", "ソ", "ツ", "ネ", "ナ", "ラ", "ム", "ウ", "ヰ", "ノ", "オ", "ク", "ヤ", "マ", "ケ", "フ", "コ", "エ", "テ", "ア", "サ", "キ", "ユ", "メ", "ミ", "シ", "ヱ", "ヒ", "モ", "セ", "ス"
+};
+static struct list_counter_style lcs_katakana_iroha = {
+ .name = "katakana-iroha",
+ .system = calc_alphabet_system,
+ .fallback = &lcs_decimal,
+ .symbols = katakana_iroha_symbols,
+ .items = (sizeof(katakana_iroha_symbols) / SYMBOL_SIZE),
+ .suffix = "、",
+};
+
+/**
+ * weights suitable for the five complex addative styles
+ */
+static const int complex_counter_weights[] = {
+ 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000,
+ 900, 800, 700, 600, 500, 400, 300, 200, 100,
+ 90, 80, 70, 60, 50, 40, 30, 20, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+static const symbol_t japanese_informal_symbols[] = {
+ "九千", "八千", "七千", "六千", "五千", "四千", "三千", "二千", "千",
+ "九百", "八百", "七百", "六百", "五百", "四百", "三百", "二百", "百",
+ "九十", "八十", "七十", "六十", "五十", "四十", "三十", "二十", "十",
+ "九", "八", "七", "六", "五", "四", "三", "二", "一", "〇",
+};
+static const struct list_counter_style lcs_japanese_informal = {
+ .name = "japanese-informal",
+ .system = calc_additive_system,
+ .fallback = &lcs_cjk_decimal,
+ .symbols = japanese_informal_symbols,
+ .weights = complex_counter_weights,
+ .items = (sizeof(japanese_informal_symbols) / SYMBOL_SIZE),
+ .range = { .start = -9999, .end = 9999 },
+ .negative = { .pre = "マイナス" },
+ .suffix = "\xE3\x80\x81",
+};
+
+static const symbol_t japanese_formal_symbols[] = {
+ "九阡", "八阡", "七阡", "六阡", "伍阡", "四阡", "参阡", "弐阡", "壱阡",
+ "九百", "八百", "七百", "六百", "伍百", "四百", "参百", "弐百", "壱百",
+ "九拾", "八拾", "七拾", "六拾", "伍拾", "四拾", "参拾", "弐拾", "壱拾",
+ "九", "八", "七", "六", "伍", "四", "参", "弐", "壱", "零",
+};
+static const struct list_counter_style lcs_japanese_formal = {
+ .name = "japanese-formal",
+ .system = calc_additive_system,
+ .fallback = &lcs_cjk_decimal,
+ .symbols = japanese_formal_symbols,
+ .weights = complex_counter_weights,
+ .items = (sizeof(japanese_formal_symbols) / SYMBOL_SIZE),
+ .range = { .start = -9999, .end = 9999 },
+ .negative = { .pre = "マイナス" },
+ .suffix = "\xE3\x80\x81",
+};
+
+static const symbol_t korean_hangul_formal_symbols[] = {
+ "구천", "팔천", "칠천", "육천", "오천", "사천", "삼천", "이천", "일천",
+ "구백", "팔백", "칠백", "육백", "오백", "사백", "삼백", "이백", "일백",
+ "구십", "팔십", "칠십", "육십", "오십", "사십", "삼십", "이십", "일십",
+ "구", "팔", "칠", "육", "오", "사", "삼", "이", "일", "영"
+};
+static const struct list_counter_style lcs_korean_hangul_formal = {
+ .name = "korean-hangul-formal",
+ .system = calc_additive_system,
+ .fallback = &lcs_cjk_decimal,
+ .symbols = korean_hangul_formal_symbols,
+ .weights = complex_counter_weights,
+ .items = (sizeof(korean_hangul_formal_symbols) / SYMBOL_SIZE),
+ .range = { .start = -9999, .end = 9999 },
+ .negative = { .pre = "\xEB\xA7\x88\xEC\x9D\xB4\xEB\x84\x88\xEC\x8A\xA4 " },
+ .suffix = ", ",
+};
+
+static const symbol_t korean_hanja_informal_symbols[] = {
+ "九千", "八千", "七千", "六千", "五千", "四千", "三千", "二千", "千",
+ "九百", "八百", "七百", "六百", "五百", "四百", "三百", "二百", "百",
+ "九十", "八十", "七十", "六十", "五十", "四十", "三十", "二十", "十",
+ "九", "八", "七", "六", "五", "四", "三", "二", "一", "零"
+};
+static const struct list_counter_style lcs_korean_hanja_informal = {
+ .name = "korean-hanja-informal",
+ .system = calc_additive_system,
+ .fallback = &lcs_cjk_decimal,
+ .symbols = korean_hanja_informal_symbols,
+ .weights = complex_counter_weights,
+ .items = (sizeof(korean_hanja_informal_symbols) / SYMBOL_SIZE),
+ .range = { .start = -9999, .end = 9999 },
+ .negative = { .pre = "\xEB\xA7\x88\xEC\x9D\xB4\xEB\x84\x88\xEC\x8A\xA4 " },
+ .suffix = ", ",
+};
+
+static const symbol_t korean_hanja_formal_symbols[] = {
+ "九仟", "八仟", "七仟", "六仟", "五仟", "四仟", "參仟", "貳仟", "壹仟",
+ "九百", "八百", "七百", "六百", "五百", "四百", "參百", "貳百", "壹百",
+ "九拾", "八拾", "七拾", "六拾", "五拾", "四拾", "參拾", "貳拾", "壹拾",
+ "九", "八", "七", "六", "五", "四", "參", "貳", "壹", "零"
+};
+static const struct list_counter_style lcs_korean_hanja_formal = {
+ .name = "korean-hanja-formal",
+ .system = calc_additive_system,
+ .fallback = &lcs_cjk_decimal,
+ .symbols = korean_hanja_formal_symbols,
+ .weights = complex_counter_weights,
+ .items = (sizeof(korean_hanja_formal_symbols) / SYMBOL_SIZE),
+ .range = { .start = -9999, .end = 9999 },
+ .negative = { .pre = "\xEB\xA7\x88\xEC\x9D\xB4\xEB\x84\x88\xEC\x8A\xA4 " },
+ .suffix = ", ",
+};
+
+
+
+static const struct list_counter_style *
+counter_style_from_computed_style(const css_computed_style *style)
+{
+ switch (get_list_style_type(style)) {
+ case CSS_LIST_STYLE_TYPE_DISC:
+ return &lcs_disc;
+ case CSS_LIST_STYLE_TYPE_CIRCLE:
+ return &lcs_circle;
+ case CSS_LIST_STYLE_TYPE_SQUARE:
+ return &lcs_square;
+ case CSS_LIST_STYLE_TYPE_DECIMAL:
+ return &lcs_decimal;
+ case CSS_LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO:
+ return &lcs_decimal_leading_zero;
+ case CSS_LIST_STYLE_TYPE_LOWER_ROMAN:
+ return &lcs_lower_roman;
+ case CSS_LIST_STYLE_TYPE_UPPER_ROMAN:
+ return &lcs_upper_roman;
+ case CSS_LIST_STYLE_TYPE_LOWER_GREEK:
+ return &lcs_lower_greek;
+ case CSS_LIST_STYLE_TYPE_LOWER_ALPHA:
+ case CSS_LIST_STYLE_TYPE_LOWER_LATIN:
+ return &lcs_lower_alpha;
+ case CSS_LIST_STYLE_TYPE_UPPER_ALPHA:
+ case CSS_LIST_STYLE_TYPE_UPPER_LATIN:
+ return &lcs_upper_alpha;
+ case CSS_LIST_STYLE_TYPE_UPPER_ARMENIAN:
+ case CSS_LIST_STYLE_TYPE_ARMENIAN:
+ return &lcs_upper_armenian;
+ case CSS_LIST_STYLE_TYPE_GEORGIAN:
+ return &lcs_georgian;
+ case CSS_LIST_STYLE_TYPE_NONE:
+ return NULL;
+ case CSS_LIST_STYLE_TYPE_BINARY:
+ return &lcs_binary;
+ case CSS_LIST_STYLE_TYPE_OCTAL:
+ return &lcs_octal;
+ case CSS_LIST_STYLE_TYPE_LOWER_HEXADECIMAL:
+ return &lcs_lower_hexadecimal;
+ case CSS_LIST_STYLE_TYPE_UPPER_HEXADECIMAL:
+ return &lcs_upper_hexadecimal;
+ case CSS_LIST_STYLE_TYPE_ARABIC_INDIC:
+ return &lcs_arabic_indic;
+ case CSS_LIST_STYLE_TYPE_LOWER_ARMENIAN:
+ return &lcs_lower_armenian;
+ case CSS_LIST_STYLE_TYPE_BENGALI:
+ return &lcs_bengali;
+ case CSS_LIST_STYLE_TYPE_CAMBODIAN:
+ case CSS_LIST_STYLE_TYPE_KHMER:
+ return &lcs_cambodian;
+ case CSS_LIST_STYLE_TYPE_CJK_DECIMAL:
+ return &lcs_cjk_decimal;
+ case CSS_LIST_STYLE_TYPE_DEVANAGARI:
+ return &lcs_devanagari;
+ case CSS_LIST_STYLE_TYPE_GUJARATI:
+ return &lcs_gujarati;
+ case CSS_LIST_STYLE_TYPE_GURMUKHI:
+ return &lcs_gurmukhi;
+ case CSS_LIST_STYLE_TYPE_HEBREW:
+ return &lcs_hebrew;
+ case CSS_LIST_STYLE_TYPE_KANNADA:
+ return &lcs_kannada;
+ case CSS_LIST_STYLE_TYPE_LAO:
+ return &lcs_lao;
+ case CSS_LIST_STYLE_TYPE_MALAYALAM:
+ return &lcs_malayalam;
+ case CSS_LIST_STYLE_TYPE_MONGOLIAN:
+ return &lcs_mongolian;
+ case CSS_LIST_STYLE_TYPE_MYANMAR:
+ return &lcs_myanmar;
+ case CSS_LIST_STYLE_TYPE_ORIYA:
+ return &lcs_oriya;
+ case CSS_LIST_STYLE_TYPE_PERSIAN:
+ return &lcs_persian;
+ case CSS_LIST_STYLE_TYPE_TAMIL:
+ return &lcs_tamil;
+ case CSS_LIST_STYLE_TYPE_TELUGU:
+ return &lcs_telugu;
+ case CSS_LIST_STYLE_TYPE_THAI:
+ return &lcs_thai;
+ case CSS_LIST_STYLE_TYPE_TIBETAN:
+ return &lcs_tibetan;
+ case CSS_LIST_STYLE_TYPE_CJK_EARTHLY_BRANCH:
+ return &lcs_cjk_earthly_branch;
+ case CSS_LIST_STYLE_TYPE_CJK_HEAVENLY_STEM:
+ return &lcs_cjk_heavenly_stem;
+ case CSS_LIST_STYLE_TYPE_HIAGANA:
+ return &lcs_hiragana;
+ case CSS_LIST_STYLE_TYPE_HIAGANA_IROHA:
+ return &lcs_hiragana_iroha;
+ case CSS_LIST_STYLE_TYPE_KATAKANA:
+ return &lcs_katakana;
+ case CSS_LIST_STYLE_TYPE_KATAKANA_IROHA:
+ return &lcs_katakana_iroha;
+ case CSS_LIST_STYLE_TYPE_JAPANESE_INFORMAL:
+ return &lcs_japanese_informal;
+ case CSS_LIST_STYLE_TYPE_JAPANESE_FORMAL:
+ return &lcs_japanese_formal;
+ case CSS_LIST_STYLE_TYPE_KOREAN_HANGUL_FORMAL:
+ return &lcs_korean_hangul_formal;
+ case CSS_LIST_STYLE_TYPE_KOREAN_HANJA_INFORMAL:
+ return &lcs_korean_hanja_informal;
+ case CSS_LIST_STYLE_TYPE_KOREAN_HANJA_FORMAL:
+ return &lcs_korean_hanja_formal;
+ }
+ return NULL;
+}
+
+
+/* exported interface defined in select.h */
+css_error css_computed_format_list_style(
+ const css_computed_style *style,
+ int value,
+ char *buffer,
+ size_t buffer_length,
+ size_t *format_length)
+{
+ css_error res = CSS_INVALID;
+ const struct list_counter_style *cstyle;
+ uint8_t aval[20];
+ struct numeric nval = {
+ .val = aval,
+ .len = sizeof(aval),
+ .used = 0,
+ .negative = false
+ };
+
+
+ cstyle = counter_style_from_computed_style(style);
+ while (cstyle != NULL) {
+ res = cstyle->system(value, cstyle, &nval);
+
+ if ((res == CSS_OK) &&
+ (nval.used < nval.len)) {
+ /* system sucessfully generated numeric values */
+ *format_length = nval_to_symbols(&nval,
+ cstyle,
+ buffer,
+ buffer_length);
+ break;
+ }
+
+ res = CSS_INVALID;
+ cstyle = cstyle->fallback;
+ }
+
+ return res;
+}