+
+static scf_string_t* __li_style_roman(int num, const char** roman)
+{
+ scf_string_t* s = scf_string_alloc();
+ if (!s)
+ return NULL;
+
+ uint32_t data[] = {1000,900, 500,400, 100,90, 50,40, 10,9, 5,4, 1};
+
+ if (num < 0) {
+ num = -num;
+
+ if (scf_string_cat_cstr_len(s, "-", 1) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+ }
+
+ int i;
+ for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
+ {
+ while (num >= data[i])
+ {
+ int k = (i & 0x1) + 1;
+
+ if (scf_string_cat_cstr_len(s, roman[i], k) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ num -= data[i];
+ }
+ }
+
+ if (scf_string_cat_cstr_len(s, ". ", 2) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+static scf_string_t* __li_style_number(int num, uint32_t base, const char c0)
+{
+ scf_string_t* s = scf_string_alloc();
+ if (!s)
+ return NULL;
+
+ if (num < 0) {
+ num = -num;
+
+ if (scf_string_cat_cstr_len(s, "-", 1) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+ }
+
+ int i = s->len;
+ do {
+ uint8_t c = num % base + c0;
+
+ if (scf_string_cat_cstr_len(s, &c, 1) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ num /= base;
+ } while (num > 0);
+
+ int j = s->len - 1;
+ while (i < j) {
+ SCF_XCHG(s->data[i], s->data[j]);
+ i++;
+ j--;
+ }
+
+ if (scf_string_cat_cstr_len(s, ". ", 2) < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ return s;
+}
+
+static const char* ROMAN[] = {"M","CM", "D","CD", "C","XC", "L","XL","X","IX","V","IV","I"};
+static const char* roman[] = {"m","cm", "d","cd", "c","xc", "l","xl","x","ix","v","iv","i"};
+
+scf_string_t* abc_ol_list_style(abc_obj_t* obj, int num)
+{
+ abc_obj_t* attr = abc_obj_find_attr(obj, ABC_CSS_LIST_STYLE_TYPE);
+ if (attr) {
+ const char* p = attr->value->data;
+
+ if (!__html_strcmp(p, "upper-roman"))
+ return __li_style_roman(num + 1, ROMAN);
+
+ else if (!__html_strcmp(p, "lower-roman"))
+ return __li_style_roman(num + 1, roman);
+
+ else if (!__html_strcmp(p, "upper-alpha"))
+ return __li_style_number(num, 26, 'A');
+
+ else if (!__html_strcmp(p, "lower-alpha"))
+ return __li_style_number(num, 26, 'a');
+ }
+
+ return __li_style_number(num, 10, '0');
+}