From af7389654638ddbd4e6e2803680b5a285385e8ad Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Tue, 3 Mar 2026 16:48:08 +0800 Subject: [PATCH] css: add a simple css parser --- examples/css.html | 18 +++ html/Makefile | 4 +- html/abc_css.c | 300 +++++++++++++++++++++++++++++++++++++++++++++ html/abc_html.c | 109 ++++++++-------- html/abc_html.h | 50 +++----- html/abc_io.h | 51 ++++++++ html/abc_io_file.c | 29 ++--- html/abc_io_http.c | 54 ++++---- html/abc_io_str.c | 65 ++++++++++ html/abc_io_util.c | 97 +++++++++++++++ html/abc_obj.h | 9 ++ html/main.c | 2 +- js/abc_libjs.c | 4 +- js/abc_libjs.so | Bin 64496 -> 64528 bytes ui/Makefile | 3 +- ui/main.c | 6 +- 16 files changed, 654 insertions(+), 147 deletions(-) create mode 100644 examples/css.html create mode 100644 html/abc_css.c create mode 100644 html/abc_io.h create mode 100644 html/abc_io_str.c create mode 100644 html/abc_io_util.c diff --git a/examples/css.html b/examples/css.html new file mode 100644 index 0000000..7e1dda0 --- /dev/null +++ b/examples/css.html @@ -0,0 +1,18 @@ + + + + + + + +

Hello World!

+

这个段落采用CSS样式化。

+ + + diff --git a/html/Makefile b/html/Makefile index b04c19b..e404606 100644 --- a/html/Makefile +++ b/html/Makefile @@ -1,9 +1,11 @@ CFILES += main.c CFILES += abc_obj.c CFILES += abc_html.c -CFILES += abc_html_util.c +CFILES += abc_css.c +CFILES += abc_io_util.c CFILES += abc_io_file.c CFILES += abc_io_http.c +CFILES += abc_io_str.c CFILES += ../js/util/scf_string.c CFILES += ../js/util/scf_graph.c diff --git a/html/abc_css.c b/html/abc_css.c new file mode 100644 index 0000000..4ddf3b1 --- /dev/null +++ b/html/abc_css.c @@ -0,0 +1,300 @@ +#include"abc_html.h" +int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags); +html_label_t* __html_find_label(const char* name); + +static int __css_parse_value(abc_obj_t* css, abc_obj_t* attr) +{ + scf_string_t* value = scf_string_alloc(); + if (!value) + return -ENOMEM; + + abc_char_t* c = NULL; + abc_char_t* c2 = NULL; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) { + scf_loge("\n"); + scf_string_free(value); + return -1; + } + + css->text_pos += c->len; + + if (';' == c->c) + break; + else + scf_string_cat_cstr_len(value, c->utf8, c->len); + + free(c); + c = NULL; + } + + int tmp = c->c; + + free(c); + c = NULL; + + if (attr->value) + scf_string_free(attr->value); + + attr->value = value; + return tmp; +} + +static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* attrs, int n_attrs) +{ + scf_string_t* key = scf_string_alloc(); + if (!key) + return -ENOMEM; + + abc_char_t* c = NULL; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) { + scf_loge("\n"); + scf_string_free(key); + return -1; + } + + css->text_pos += c->len; + + if ('}' == c->c) { + free(c); + scf_string_free(key); + return '}'; + } + + if (':' == c->c) + break; + + if ('_' == c->c + || '-' == c->c + || ('a' <= c->c && 'z' >= c->c)) { + scf_string_cat_cstr_len(key, c->utf8, c->len); + + } else if (' ' == c->c || '\t' == c->c || '\r' == c->c) { + + } else { + scf_loge("invalid char '%c:%#x' in CSS attribute, file: %s, line: %d\n", + c->c, c->c, css->file->data, css->text_line); + assert(0); + free(c); + scf_string_free(key); + return -1; + } + + free(c); + c = NULL; + } + + int tmp = c->c; + + free(c); + c = NULL; + + scf_list_t* l; + abc_obj_t* attr; + + int i; + int j; + if (attrs && n_attrs > 0) { + for (i = 0; i < n_attrs; i++) { + + for (j = 0; attrs[i].names[j]; j++) { + if (!strcmp(attrs[i].names[j], key->data)) + goto found; + } + } + } + + scf_loge("invalid HTML attribute '%s' in file: %s, line: %d\n", key->data, css->file->data, css->text_pos); + scf_string_free(key); + return -1; + +found: + for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { + attr = scf_list_data(l, abc_obj_t, list); + + for (j = 0; attr->keys[j]; j++) { + if (!strcmp(attr->keys[j], key->data)) + break; + } + } + + if (l == scf_list_sentinel(&obj->attrs)) { + int ret = __html_add_attr(obj, attrs[i].type, attrs[i].names, attrs[i].value, attrs[i].flags); + if (ret < 0) + return ret; + + l = scf_list_tail(&obj->attrs); + attr = scf_list_data(l, abc_obj_t, list); + } + + scf_string_free(key); + key = NULL; + + attr->line = css->text_line; + attr->pos = css->text_pos; + + return __css_parse_value(css, attr); +} + +static int __css_parse_attr(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* attrs, int n_attrs) +{ + int ret = 0; + + while (1) { + ret = __css_parse_attr2(css, obj, attrs, n_attrs); + if (ret < 0) + return ret; + + if ('}' == ret) + break; + } + + return ret; +} + +static int __css_parse_obj(abc_obj_t* css, abc_char_t* c) +{ + html_label_t* label; + abc_obj_t* obj; + + scf_string_t* key = scf_string_cstr_len(c->utf8, c->len); + + css->text_pos += c->len; + free(c); + c = NULL; + + if (!key) + return -ENOMEM; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) { + scf_loge("\n"); + scf_string_free(key); + return -1; + } + + css->text_pos += c->len; + + if (' ' == c->c || '{' == c->c) + break; + + if ('\n' == c->c) { + css->text_line++; + css->text_pos = 0; + break; + } + + scf_string_cat_cstr_len(key, c->utf8, c->len); + free(c); + c = NULL; + } + + int tmp = c->c; + int ret; + + free(c); + c = NULL; + + label = __html_find_label(key->data); + if (!label) { + scf_loge("invalid HTML label '%s' in file: %s, line: %d\n", + key->data, css->file->data, css->text_line); + scf_string_free(key); + return -1; + } + + scf_string_free(key); + key = NULL; + + obj = abc_obj_alloc(css->file, css->text_line, css->text_pos, label->type); + if (!obj) + return -ENOMEM; + + obj->flags = label->flags; + obj->keys = label->names; + + obj->parent = css; + + switch (tmp) { + case '{': + ret = __css_parse_attr(css, obj, label->attrs, label->n_attrs); + if (ret < 0) { + abc_obj_free(obj); + return ret; + } + break; + default: + ret = 0; + break; + }; + + scf_list_add_tail(&css->childs, &obj->list); + return 0; +} + +int abc_css_parse(abc_obj_t* css) +{ + abc_char_t* c; + abc_io_t* io = abc_io_array[ABC_PROTO_STR]; + + css->io.proto = io->proto; + css->io.priv = NULL; + css->io.open = io->open; + css->io.close = io->close; + css->io.popc = io->popc; + css->io.post = io->post; + + css->text_line = 1; + css->text_pos = 0; + + int ret = io->open(&css->io, css->text->data); + if (ret < 0) + return ret; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) + return -1; + + if (EOF == c->c) { + free(c); + return 0; + } + + if ('\n' == c->c || '\r' == c->c) { + css->text_line++; + css->text_pos = 0; + + free(c); + continue; + } + + if (' ' == c->c || '\t' == c->c) { + css->text_pos++; + free(c); + continue; + } + + if (('a' <= c->c && 'z' >= c->c) + || (0x4e00 <= c->c && 0x9fa5 >= c->c)) { + + int ret = __css_parse_obj(css, c); + if (ret < 0) { + scf_loge("css->text_line: %d, css->text_pos: %d\n", css->text_line, css->text_pos); + return ret; + } + } else { + scf_loge("%c:%#x, css->text_line: %d, css->text_pos: %d\n", c->c, c->c, css->text_line, css->text_pos); + free(c); + return -1; + } + } + + return -1; +} diff --git a/html/abc_html.c b/html/abc_html.c index a9b0fe0..664da6b 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -1,33 +1,5 @@ #include"abc_html.h" -typedef struct { - char** names; - char* value; - int type; - int flags; -} html_attr_t; - -typedef struct { - char** names; - int type; - - int n_attrs; - html_attr_t* attrs; - - uint32_t flags; -} html_label_t; - -#define abc_number_of(__array) (sizeof(__array) / sizeof(__array[0])) - -extern abc_io_t abc_io_file; -extern abc_io_t abc_io_http; - -static abc_io_t* abc_io_array[ABC_PROTO_NB] = -{ - [ABC_PROTO_FILE] = &abc_io_file, - [ABC_PROTO_HTTP] = &abc_io_http, -}; - // HTML attrs static char* src_keys[] = {"src", "源", NULL}; static char* href_keys[] = {"href", "地址", NULL}; @@ -37,7 +9,9 @@ static char* height_keys[] = {"height", "高度", NULL}; static char* font_keys[] = {"font", "字体", NULL}; static char* font_size_keys[] = {"font-size", "字号", NULL}; -static char* font_color_keys[] = {"font-color", "字体颜色", NULL}; +static char* font_color_keys[] = {"font-color", "字体颜色", "color", "颜色", NULL}; + +static char* text_align_keys[] = {"text-align", "对齐", NULL}; static char* type_keys[] = {"type", "类型", NULL}; static char* name_keys[] = {"name", "名字", NULL}; @@ -99,6 +73,7 @@ static char* play_keys[] = {"play", "播放", NULL}; static char* progress_keys[] = {"progress", "进度条", NULL}; static char* script_keys[] = {"script", "脚本", NULL}; +static char* style_keys[] = {"style", "样式", NULL}; static html_attr_t html_attrs[] = { @@ -158,8 +133,10 @@ static html_attr_t h6_attrs[] = static html_attr_t p_attrs[] = { - {font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0}, - {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0}, + {font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0}, + {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0}, + {font_color_keys, "black", ABC_HTML_ATTR_FONT_COLOR, ABC_HTML_FLAG_SHOW}, + {text_align_keys, "left", ABC_HTML_ATTR_TEXT_ALIGN, ABC_HTML_FLAG_SHOW}, }; static html_attr_t a_attrs[] = @@ -273,12 +250,13 @@ static html_label_t html_labels[] = {progress_keys, ABC_HTML_PROGRESS, 0, NULL, ABC_HTML_FLAG_OPEN}, {script_keys, ABC_HTML_SCRIPT, abc_number_of(script_attrs), script_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, + + {style_keys, ABC_HTML_STYLE, 0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, }; static int __html_parse_obj(abc_html_t* html, abc_char_t* c); - -static html_label_t* __html_find_label(const char* name) +html_label_t* __html_find_label(const char* name) { html_label_t* label; @@ -298,7 +276,7 @@ static html_label_t* __html_find_label(const char* name) return NULL; } -static int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags) +int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags) { abc_obj_t* attr = abc_obj_alloc(NULL, 0, 0, type); if (!attr) @@ -443,7 +421,7 @@ int abc_html_post(abc_html_t** pp, abc_html_t* form, abc_obj_t* submit) html->io.popc = io->popc; html->io.post = io->post; - ret = io->post(html, url->data + n, content); + ret = io->post(&html->io, url->data + n, content); if (ret < 0) { scf_string_free(url); scf_string_free(content); @@ -495,7 +473,7 @@ int abc_html_open(abc_html_t** pp, const char* path) html->io.popc = io->popc; html->io.post = io->post; - int ret = io->open(html, path + n); + int ret = io->open(&html->io, path + n); if (ret < 0) { free(html); return ret; @@ -518,10 +496,10 @@ void abc_html_close(abc_html_t* html) abc_char_t* c; if (html) { - while ( html->tmp_list) { - c = html->tmp_list; + while ( html->io.tmp_list) { + c = html->io.tmp_list; - html->tmp_list = c->next; + html->io.tmp_list = c->next; free(c); } @@ -529,7 +507,7 @@ void abc_html_close(abc_html_t* html) abc_obj_free(html->root); if (html->io.close) - html->io.close(html); + html->io.close(&html->io); if (html->file) scf_string_free(html->file); @@ -550,7 +528,7 @@ static int __html_parse_end(abc_html_t* html, abc_obj_t* obj) abc_char_t* c = NULL; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(end); @@ -595,7 +573,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) int flag = 0; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(text); @@ -610,14 +588,14 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) if (ABC_HTML_SCRIPT != obj->type) break; - abc_char_t* c2 = __html_pop_char(html); + abc_char_t* c2 = __io_pop_char(&html->io); if (!c2) { scf_loge("\n"); scf_string_free(text); return -1; } - __html_push_char(html, c2); + __io_push_char(&html->io, c2); if ('/' == c2->c) break; @@ -643,7 +621,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) text = NULL; if (ABC_HTML_FLAG_OPEN == (obj->flags & 0x1)) { // single labels - __html_push_char(html, c); + __io_push_char(&html->io, c); c = NULL; return 0; }; @@ -652,7 +630,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) free(c); c = NULL; - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); free(c); @@ -735,7 +713,7 @@ static int __html_parse_value(abc_html_t* html, abc_obj_t* attr) int flag = 0; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(value); @@ -749,9 +727,9 @@ static int __html_parse_value(abc_html_t* html, abc_obj_t* attr) break; if ('/' == c->c) { - c2 = __html_pop_char(html); + c2 = __io_pop_char(&html->io); - __html_push_char(html, c2); + __io_push_char(&html->io, c2); if ('>' == c2->c) break; } @@ -791,7 +769,7 @@ static int __html_parse_attr2(abc_html_t* html, abc_obj_t* obj, const html_attr_ abc_char_t* c = NULL; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(key); @@ -1015,7 +993,7 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) return ret; } #if 1 - assert(!html->tmp_list_js); + assert(!html->io.tmp_list_js); void* so = dlopen(obj->js_so->data, RTLD_LAZY); void (*f)() = dlsym(so, "__js_main"); @@ -1025,13 +1003,13 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) so = NULL; #endif abc_char_t* c; - while ( html->tmp_list_js) { - c = html->tmp_list_js; + while ( html->io.tmp_list_js) { + c = html->io.tmp_list_js; - html->tmp_list_js = c->next; + html->io.tmp_list_js = c->next; - c->next = html->tmp_list; - html->tmp_list = c; + c->next = html->io.tmp_list; + html->io.tmp_list = c; } } @@ -1053,7 +1031,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) return -ENOMEM; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(key); @@ -1135,7 +1113,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) } if ('/' == ret) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); return -1; @@ -1160,6 +1138,15 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) return -1; break; + case ABC_HTML_STYLE: + if (obj->text) { + scf_logi("\033[33mcss: %s\033[0m\n", obj->text->data); + + if (abc_css_parse(obj) < 0) + return -1; + } + break; + case ABC_HTML_VIDEO: html->has_video = 1; @@ -1180,7 +1167,7 @@ int abc_html_parse(abc_html_t* html) abc_char_t* c; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) return -1; @@ -1204,12 +1191,12 @@ int abc_html_parse(abc_html_t* html) free(c); - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if ('!' == c->c) { // free(c); while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); int tmp = c->c; free(c); diff --git a/html/abc_html.h b/html/abc_html.h index 66e9a55..81f7891 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -1,50 +1,35 @@ #ifndef ABC_HTML_H #define ABC_HTML_H +#include"abc_io.h" #include"abc_obj.h" #include"scf_parse.h" -typedef struct abc_char_s abc_char_t; typedef struct abc_html_s abc_html_t; -typedef struct abc_io_s abc_io_t; -enum abc_protos -{ - ABC_PROTO_FILE, - ABC_PROTO_HTTP, - - ABC_PROTO_NB -}; - -#define ABC_UTF8_MAX 6 -struct abc_char_s -{ - abc_char_t* next; - int c; +typedef struct { + char** names; + char* value; + int type; + int flags; +} html_attr_t; - int len; - uint8_t utf8[ABC_UTF8_MAX]; -}; +typedef struct { + char** names; + int type; -struct abc_io_s -{ - char* proto; - void* priv; + int n_attrs; + html_attr_t* attrs; - int (*open )(abc_html_t* html, const char* path); - void (*close)(abc_html_t* html); + uint32_t flags; +} html_label_t; - int (*popc )(abc_html_t* html); - int (*post )(abc_html_t* html, const char* path, scf_string_t* content); -}; +#define abc_number_of(__array) (sizeof(__array) / sizeof(__array[0])) struct abc_html_s { scf_list_t list; - abc_char_t* tmp_list; - abc_char_t* tmp_list_js; - abc_obj_t* root; abc_obj_t* current; @@ -56,7 +41,6 @@ struct abc_html_s scf_parse_t* js; - uint8_t download :1; uint8_t has_video:1; }; @@ -65,8 +49,6 @@ int abc_html_post (abc_html_t** pp, abc_html_t* form, abc_obj_t* submit); void abc_html_close(abc_html_t* html); int abc_html_parse(abc_html_t* html); - -abc_char_t* __html_pop_char (abc_html_t* html); -void __html_push_char(abc_html_t* html, abc_char_t* c); +int abc_css_parse (abc_obj_t* css); #endif diff --git a/html/abc_io.h b/html/abc_io.h new file mode 100644 index 0000000..c5ca2db --- /dev/null +++ b/html/abc_io.h @@ -0,0 +1,51 @@ +#ifndef ABC_IO_H +#define ABC_IO_H + +#include"scf_string.h" +#include"scf_list.h" + +typedef struct abc_char_s abc_char_t; +typedef struct abc_io_s abc_io_t; + +enum abc_protos +{ + ABC_PROTO_FILE, + ABC_PROTO_HTTP, + ABC_PROTO_STR, + + ABC_PROTO_NB +}; + +extern abc_io_t* abc_io_array[ABC_PROTO_NB]; + +#define ABC_UTF8_MAX 6 +struct abc_char_s +{ + abc_char_t* next; + int c; + + int len; + uint8_t utf8[ABC_UTF8_MAX]; +}; + +struct abc_io_s +{ + char* proto; + + void* priv; + uint8_t download:1; + + abc_char_t* tmp_list; + abc_char_t* tmp_list_js; + + int (*open )(abc_io_t* io, const char* path); + void (*close)(abc_io_t* io); + + int (*popc )(abc_io_t* io); + int (*post )(abc_io_t* io, const char* path, scf_string_t* content); +}; + +abc_char_t* __io_pop_char (abc_io_t* io); +void __io_push_char(abc_io_t* io, abc_char_t* c); + +#endif diff --git a/html/abc_io_file.c b/html/abc_io_file.c index 16afbbd..8bf2fed 100644 --- a/html/abc_io_file.c +++ b/html/abc_io_file.c @@ -1,12 +1,12 @@ -#include"abc_html.h" +#include"abc_io.h" -static int __file_open(abc_html_t* html, const char* path) +static int __file_open(abc_io_t* io, const char* path) { - if (!html || !path) + if (!io || !path) return -EINVAL; - html->io.priv = fopen(path, "r"); - if (!html->io.priv) { + io->priv = fopen(path, "r"); + if (!io->priv) { char cwd[4096]; getcwd(cwd, 4095); @@ -14,25 +14,20 @@ static int __file_open(abc_html_t* html, const char* path) return -1; } - html->download = 1; + io->download = 1; return 0; } -static void __file_close(abc_html_t* html) +static void __file_close(abc_io_t* io) { - if (html && html->io.priv) { - - fclose(html->io.priv); - } + if (io && io->priv) + fclose(io->priv); } -static int __file_popc(abc_html_t* html) +static int __file_popc(abc_io_t* io) { - if (html && html->io.priv) { - - return fgetc(html->io.priv); - } - + if (io && io->priv) + return fgetc(io->priv); return EOF; } diff --git a/html/abc_io_http.c b/html/abc_io_http.c index 1d6b246..559fea1 100644 --- a/html/abc_io_http.c +++ b/html/abc_io_http.c @@ -1,4 +1,4 @@ -#include"abc_html.h" +#include"abc_io.h" typedef struct { scf_string_t* host; @@ -89,11 +89,11 @@ static void http_chunk_size(abc_http_t* http) } } -static int http_filter_chunk(abc_html_t* html) +static int http_filter_chunk(abc_io_t* io) { - abc_http_t* http = html->io.priv; + abc_http_t* http = io->priv; - if (html->download) + if (io->download) return 0; while (http->cpos < http->rbuf->len) { @@ -108,7 +108,7 @@ static int http_filter_chunk(abc_html_t* html) http->cpos += 2; if (0 == http->content_length) { - html->download = 1; + io->download = 1; return 0; } @@ -134,8 +134,8 @@ static int http_filter_chunk(abc_html_t* html) static void* http_thread(void* arg) { - abc_html_t* html = arg; - abc_http_t* http = html->io.priv; + abc_io_t* io = arg; + abc_http_t* http = io->priv; while (!http->exit) { struct epoll_event ev; @@ -193,14 +193,14 @@ static void* http_thread(void* arg) if (http->rpos > 0) { if (!http->chunk_flag) { if (http->content_length == http->rbuf->len - http->rpos) { - html->download = 1; + io->download = 1; scf_logi("http response: %s\n", http->rbuf->data); } } else { - http_filter_chunk(html); + http_filter_chunk(io); - if (html->download) + if (io->download) scf_logi("http response: %s\n", http->rbuf->data); } } @@ -212,7 +212,7 @@ static void* http_thread(void* arg) if (ev.events & EPOLLOUT) { pthread_mutex_lock(&http->mutex); if (0 == http->wpos) { - html->download = 0; + io->download = 0; http->rbuf->len = 0; http->rpos = 0; } @@ -379,9 +379,9 @@ static int __http_open2(abc_http_t** pp, const char* path) return 0; } -static int __http_open(abc_html_t* html, const char* path) +static int __http_open(abc_io_t* io, const char* path) { - if (!html || !path) + if (!io || !path) return -EINVAL; abc_http_t* http = NULL; @@ -413,11 +413,11 @@ static int __http_open(abc_html_t* html, const char* path) ABC_HTTP_FILL("Accept: */*\r\n"); ABC_HTTP_FILL("\r\n"); - html->io.priv = http; + io->priv = http; - if (pthread_create(&http->tid, NULL, http_thread, html)) { + if (pthread_create(&http->tid, NULL, http_thread, io)) { abc_http_close(http); - html->io.priv = NULL; + io->priv = NULL; return -1; } @@ -425,9 +425,9 @@ static int __http_open(abc_html_t* html, const char* path) return 0; } -static int __http_post(abc_html_t* html, const char* path, scf_string_t* content) +static int __http_post(abc_io_t* io, const char* path, scf_string_t* content) { - if (!html || !path || !content) + if (!io || !path || !content) return -EINVAL; abc_http_t* http = NULL; @@ -459,11 +459,11 @@ static int __http_post(abc_html_t* html, const char* path, scf_string_t* content ABC_HTTP_FILL(content->data); - html->io.priv = http; + io->priv = http; - if (pthread_create(&http->tid, NULL, http_thread, html)) { + if (pthread_create(&http->tid, NULL, http_thread, io)) { abc_http_close(http); - html->io.priv = NULL; + io->priv = NULL; return -1; } @@ -471,18 +471,18 @@ static int __http_post(abc_html_t* html, const char* path, scf_string_t* content return 0; } -static void __http_close(abc_html_t* html) +static void __http_close(abc_io_t* io) { - if (html) - abc_http_close(html->io.priv); + if (io) + abc_http_close(io->priv); } -static int __http_popc(abc_html_t* html) +static int __http_popc(abc_io_t* io) { abc_http_t* http; - if (html) { - http = html->io.priv; + if (io) { + http = io->priv; if (http) { int c; diff --git a/html/abc_io_str.c b/html/abc_io_str.c new file mode 100644 index 0000000..ba31fcf --- /dev/null +++ b/html/abc_io_str.c @@ -0,0 +1,65 @@ +#include"abc_io.h" + +typedef struct { + scf_string_t* text; + int text_i; +} abc_str_t; + +static int __str_open(abc_io_t* io, const char* path) +{ + if (!io || !path) + return -EINVAL; + + abc_str_t* s = calloc(1, sizeof(abc_str_t)); + if (!s) + return -ENOMEM; + + s->text = scf_string_cstr(path); + if (!s->text) { + free(s); + return -ENOMEM; + } + + io->priv = s; + io->download = 1; + return 0; +} + +static void __str_close(abc_io_t* io) +{ + abc_str_t* s; + + if (io && io->priv) { + s = io->priv; + + if (s->text) + scf_string_free(s->text); + + free(s); + io->priv = NULL; + } +} + +static int __str_popc(abc_io_t* io) +{ + abc_str_t* s; + + if (io && io->priv) { + s = io->priv; + + if (s->text_i < s->text->len) + return s->text->data[s->text_i++]; + } + + return EOF; +} + +abc_io_t abc_io_str = +{ + .proto = "str://", + + .open = __str_open, + .close = __str_close, + + .popc = __str_popc, +}; diff --git a/html/abc_io_util.c b/html/abc_io_util.c new file mode 100644 index 0000000..dd1fa0b --- /dev/null +++ b/html/abc_io_util.c @@ -0,0 +1,97 @@ +#include"abc_io.h" + +extern abc_io_t abc_io_file; +extern abc_io_t abc_io_http; +extern abc_io_t abc_io_str; + +abc_io_t* abc_io_array[ABC_PROTO_NB] = +{ + [ABC_PROTO_FILE] = &abc_io_file, + [ABC_PROTO_HTTP] = &abc_io_http, + [ABC_PROTO_STR] = &abc_io_str, +}; + +abc_char_t* __io_pop_char(abc_io_t* io) +{ + assert(io); + + abc_char_t* c; + + if (io->tmp_list) { + c = io->tmp_list; + io->tmp_list = c->next; + return c; + } + + c = malloc(sizeof(abc_char_t)); + if (!c) + return NULL; + + int ret = io->popc(io); + if (EOF == ret) { + c->c = ret; + return c; + } + + if (ret < 0x80) { + c->c = ret; + c->len = 1; + c->utf8[0] = ret; + return c; + } + + if (0x6 == (ret >> 5)) { + c->c = ret & 0x1f; + c->len = 2; + + } else if (0xe == (ret >> 4)) { + c->c = ret & 0xf; + c->len = 3; + + } else if (0x1e == (ret >> 3)) { + c->c = ret & 0x7; + c->len = 4; + + } else if (0x3e == (ret >> 2)) { + c->c = ret & 0x3; + c->len = 5; + + } else if (0x7e == (ret >> 1)) { + c->c = ret & 0x1; + c->len = 6; + } else { + scf_loge("utf8 first byte wrong %#x\n", ret); + free(c); + return NULL; + } + + c->utf8[0] = ret; + + int i; + for (i = 1; i < c->len; i++) { + + ret = io->popc(io); + + if (0x2 == (ret >> 6)) { + c->c <<= 6; + c->c |= ret & 0x3f; + + c->utf8[i] = ret; + } else { + scf_loge("utf8 byte[%d] wrong %#x\n", i + 1, ret); + free(c); + return NULL; + } + } + + return c; +} + +void __io_push_char(abc_io_t* io, abc_char_t* c) +{ + assert(io); + assert(c); + + c->next = io->tmp_list; + io->tmp_list = c; +} diff --git a/html/abc_obj.h b/html/abc_obj.h index f87c59a..c1a74f3 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -4,6 +4,7 @@ #include"scf_string.h" #include"scf_list.h" #include"abc_ffmpeg.h" +#include"abc_io.h" typedef struct abc_obj_s abc_obj_t; @@ -56,6 +57,8 @@ enum abc_objs ABC_HTML_SCRIPT, + ABC_HTML_STYLE, + ABC_HTML_NB, // total HTML objects ABC_HTML_ATTR_ID, @@ -75,6 +78,8 @@ enum abc_objs ABC_HTML_ATTR_FONT_SIZE, ABC_HTML_ATTR_FONT_COLOR, + ABC_HTML_ATTR_TEXT_ALIGN, + ABC_HTML_ATTR_WIDTH, ABC_HTML_ATTR_HEIGHT, @@ -124,6 +129,10 @@ struct abc_obj_s scf_string_t* value; scf_string_t* text; + int text_line; + int text_pos; + abc_io_t io; + scf_string_t* file; // file name int line; // line int pos; // position diff --git a/html/main.c b/html/main.c index ff8a438..4a8eb4b 100644 --- a/html/main.c +++ b/html/main.c @@ -14,7 +14,7 @@ int main(int argc, char* argv[]) return -1; } - while (!html->download) + while (!html->io.download) usleep(50 * 1000); if (abc_html_parse(html) < 0) { diff --git a/js/abc_libjs.c b/js/abc_libjs.c index 5532441..f8a1312 100644 --- a/js/abc_libjs.c +++ b/js/abc_libjs.c @@ -126,9 +126,9 @@ int abc_html_write(abc_html_t* html, const char* s) while (*pp) pp = &(*pp)->next; - *pp = html->tmp_list_js; + *pp = html->io.tmp_list_js; - html->tmp_list_js = h; + html->io.tmp_list_js = h; return 0; error: diff --git a/js/abc_libjs.so b/js/abc_libjs.so index 376eaa007efa1e1da105f67eaf01a94be84e17be..b5d7e51efae8bd855a2bd95d04bf4c0060ff4aea 100755 GIT binary patch delta 17636 zcmZX533yXg`u_ROy-9A8CQXwxNt-U&+9oC43zWT3ma-_|3JgNoi)@ue!2!Y!qGB;R z;*R@{D2}4y3~EtSL=^YG3hFrHf{Nq5&HUf*Twr{jU!SKZ=RM1JzWtnga&!Dgt@9_X zGf9UYNTzZrd>wqD|Cz4Yv(YS<-Xnse~xd z{Tdzhdy07ps~Cd%z9_eA-=F|zv%#5@>-K|K>}^Y(u}%sh^Q$3mgNyWA`aA~x#wD+YZPXp;9qL6&|B zG|M#*(bB9ytE}?_3{+r@oL2=fNP%&3dL2M!aNtI8+9p>G1{&(W6`)I=60N(y=ZWpKFeM|xT9=Ub-!SIl&Ek8@qfDmbF6hXRJsUP7Dos$4YnRCRj` zC?(wi<6`)(%)kil&fuoyc|JICO;aEwtNH^> zS1UwharUmEmDM|%g~$yf9EFG^b6f0H7AWc0ax@Mp(m|p4-0r9kHB|e8?0<(ARrd!| zxvkoN(Hp7F9cjPl)Rfc0EU-D{bVIc-$POP?MC-FNhm~YLgxNgy6N*T|r92J=ba{(1 zwW$c%ics<7D3BwaP?5)_fJbhE6L{PT_~mNk3s0^BAsO@ncoZm-i@~5LPl1Sh9IE#C zbC5E!T5E{5XNy|H71Ka9uc(N_$Nmt!)#H7{xZDb@Ztf|B_fgAu)P=k=JE=9D*@vXy zydMo37deljaC{0$oO`*Ai<}p^Z8_BLe4X34$oYWVv{JNv%57Za{F~b@0pHHwxQ&Y( zD?-m;bL|SpyFbI26EgJlJ}M1Hox4%16I_80w**&p4YW^4MU$ z_Yk4`Y<9X zx4O|);f({-$~q>I^7aI1lJ-1+O78@KW}(@!xSMJJf=Vt&p+zXp-RQTd;wX}?&{$-R z2X$kbsz+!cRMluEjW(8FOP*{z`{Y0ildv!p8e2>2i)zV1uxMc=g`U3_I5`CYNjbb2 zO^TtQH?adq8Veycs)5hwbSK>2BBIkF0$N2VpWekx8jYYAR9A{Eo#-?uTv7o_jV7bi z=}|0cp|9DPbl)&+2f}_c{KP2e?U7j1n7?G6DClEXTeUGA#w+NnfR0@P;|ls|yh?AI z&TAGHxi4WxU5H9SXCQWo9<1ag?@wcWjh4b}I@vJRLNg$Nm2L#PHkt&tHpqt3P8qa2 zs1N8Q={@YRDcX?|qLS7mpkK;E9!}F{pAc0P!!p&v+7lmzHPVe4_WkH+Ega;j$1wS@ zA05N;l#S$u45G8}G~ZD47}7Qz;H;we0X*_z0+^`83dy&M0j4TYBaxBPKHRm1&?oqZFxZ{frzG&Z%i1lY>PFU)GJ zWakz%l>7yft0*cOR^~(eB}@CkCBHx+Xk&l&&Kl@l(gi9YRt#Y0EP!WN=uYg}R{9mC zjrw94gTAU`=R6--z(HSj!wU3Z1UZc2F>KrPTMDUy>cC1aEvSXu^gQV2(PJpRbS^CD z%g{M+20sl&nNJ%)C_q<$M35rzvJedbvjwz;9fm@z9eN9si|B4FTufI%dnNP?(rPJ< ztAIgiFA`Ifo&|*%{S|Hyr#{GX2?`{ID5IAVOXc)nAM69P7AYV}nYW>r6iq`)ucRv> zaW`54>C?0UyjRg2gjY4)foxbqFF@j2`hRedIvR`Kdiog*HPAyaT_bHoy*q(`=s^OK z^`sB6a1*V75u2z56q=|Dq1TJP!&<#*L$eTl=(o&JA^OrDboZkk`9k!kpP_>RGzCuE zOk0pe2GX}UY78P5dRwTxP>8{_661%^QuGd`Jvf98qst)uFnR-;Xr)pq#BkE;g&09y z(9lS_vQ>ytl!C;kQMpBk)9DGf5TohMvWyU8=uKE|EZvKR&!CHuhR&qxp{TQHG8A<- z4Z`k!4&4MlIG5fj5n>!|#?~{QCZJ^k{emU`L=S=JM9PPIokwqD)+DOLtjY8vY~Myh z;DS?V0n*k~@z;J2MFfHTgf+aT-tlmkDQLl?w^ zm`m5Cg_uVbu>E|RhXl8P@Ve*i z=oWZGz2K(8VCJl759jDveFJSl z%Z=n6Cd5s21D3p*)CyLtQZ3z4R$U^genR!{>L= z?^xy$dIFRGN=G2fqqG~6Jw`JSe!J;au=P021EWvS98HKPsTTU%LqX{8DcXc+`Wt;W zT!_EZukfM0^ek3+nm&a8Jwy9z;GWOY25{X){{pA`D1j(=j)p>-=cyD6@2BwzAzq;N zln^hH2HsyHC%oYRU4W{~!H;W!|G|xX=646F%_)wL;1x^d?9g zr6216~GLF{t@B4`#XG4QYDzx z=ovVKPMJJ-goUaR)8WsG*0L=G?_=`A#C^eOSWzo4|xtp@aOr7O{4BR|A7s4Iup zZ3ZU}n%clC_5_I>8i~4#E(dRJx&>t}T?J3{&<3=7Xd(2RN4G$*JbD|7@zPlMxKBja zf>FiQ6!~}Nss>UEnvduqx(H-4k`_aDjV?g+>U1{LX(57)R(dbWTpjcQjAuJ{6D_EUq0h~+HF&IswbHKPxt;h-%8Utlm zX*d?NiIS^(p=l*171vZismWL1TJ#?!`3p>t{t2Iuv>T#jH2Ma~LZ{mym4)h1x6(vt z+(tJ+g9crxWZr0DneTxlPI?d2a%eoX?4s`?Ec1`BK`xDfKpwgd0hdQ(;4#HC3vpFK zZq!TZAj$|WMkGXO1pFpOAvjDtLkR>;f^Nq$WpqAdET^fcWBUaENg4=pDOwNnR?_?6 zy&F9M?W9u|I?*jtmj>~nrEaRgho0IE@&60?%Laje)?o31b09yx-HbZ9Ap_A(u(PCE zaIDe#euzI^6!pZikzyZtwqSJr?CGM|PkvUtP-nv8d~$G)uKyJ*7YE3R*v939`x|`R zgbwwPk}G^nr#MI&FPbiHrGxk^&A^$8&n0gmJTW$JN{1*up9;B0XqcN3MZM7xD(*?1 z5QNbO!YIXkselb9bbhcY9%!By_53BGcn;a_Lyuvy(qXdV5k4kTd;w{P(OGgEoJ85b zq~|4|ne?EbeQ_d5WF zdY~?yKIUg9qDW`^C!==qlp+_t#?R!(@LRuvxc34bf*P_bs3{eGvqRVw2-!(yljvZ6FV$xw_E<=nb>4 zLw7Ni_e``{_u~8*{lr8|^-gBy3kvZw^>Tf*73esr2i;Yf{Eo$oMD%-d{Q%8x(hozx z=x-+K)URhbb*YAK)4xOdiQ3J_mF+43q6JdL;@$f3IQpv0zMZ<(4AjF!kLa72(f%gd ztuGh?G}J_U^vnU6D>}-AdrehNkY0WQ-tW2vkw>lB)ngcaIG7ZqY=p<#6SlQmLt#T=yVOo-|P_x!50`mC7B)kjswc517l3 zBUd5(=zSASB-b=3{~uDhN*lSJtU&yIXTo-JErKroBXiitI>=S&MK(3jQgZFXJ|#5O zw~AcHz#5ro6S??WHBVDSJIVD5^c2wYIh$=G*9I^e))d=2Nhoh-M^h=&CfphJCHA!w z4I1YMH+wQ`{bVC!?FTeyd^qv3KSzr+tqwpdgX%O+a~hM4}I0biQx{ou$O|Ei^Kq${=O-MEtW>i^Jgf0DS5s}HGleynIe28 z6&%fAiqOwQ5#B}x1Mz9-qu`<88%&gwzi38>2;W5oyxAbpqZHx0Nn^R3Oe-CJmPTW- z*z6vSBHTrJ97wV0Q|F5CKJxG_L~POGg(CbMZ&NuV()9=0o&Nra3x6KW=RsRcQh`meUT8tT^k1q#0W(qh? z-v#5%C3#qLs)+hs$k-;M>*T+tz z*F^qBBG$`XJDJ}uV!h3JTIKmzA2WH^>YUnQEoN?O(m5x_1|unE5QlwrPQtNa=EP>5 z6G*I8stnSq_JG(}lT4ewv_JYL$?y#jr(NF<|Bp>GQKztej6@$B87V@aljU`AgS8rQ z8XFa<;s&l;f5wp}c3MS$ZpbjO--R7I8C&4F5>4{Td~`1ka9zk9%-OOa14FK6ovbXm z2EZeCvq9FXVIlb&EEZd*KtyO!4AAOPSebBagVut2IyQvH*x-qQd4psEv8W%!)mxuI0Rcpy$pcX>a?t#0s$6oOCfip-IPcNUi!~KBW>vaVT zsiNuq5RdXm6)*o(ASBnZF^;S7j7Z)BW8bTDL(+^nNiII&rOmLinW!qG-_Me{Ojxat z#rZT=L{3&tt$r4x1`{>upK)9bpq!CdyIEIex}I!zLxNV_(+7Pwn!z$gzqJhLW)q#I z*D)^-kaH>KjnhYSbUbO&Y(xGDVtzL!c|w29s4CU*aMfnsvvTsZ9E1AQ$yyac8-p=E z)?924X+yxXa|K$o&0MetYWxtTar!En3`c8@{Ukk{GR$Q5v-D@oZ02C5ev!f3(P!v3 zM!%ZT?a`$j=y$1dTgXf`PEBbxVx}6ei4y8a6f4lwktnHu$VsU}E4l|XYjs}=D5WVX zO+vd3d^r+*asJb~qhI4h?OVY!{w3XG(V|qa02NaOh~7U6?(=iP{a(74pB&1`(j2O4 zYP=U7aY9jp(XFwAYE09|%7|5J+HD!u&ki(Mtw;&+yyyYctA0h?)>3=|zsMjD0K_K- zSAqi}CtzofPf|cPF2q%Pd~)!R0i_vJ7_=!6k^?I+Y^nlDISI?grzy}ROA&qX8A0A8 zTje<|8K9X#-VMhXOGUh0Q66V36Y<%qI#KcwIDWnYZIVyG@i_`immHJvxj_!eb~zg{ z8K0*p&6Rw_jn7wLv0Mpj#uunL%O!_y{DL4y?kb72ml5%WYTP3m6?C_M%T(-pjNzL4MjlUbCQMk%+Gj-U6ra@a7j^6J)CU$Gy#;_z*(h1i}O!aa!2-y!#mzb`A zN8ZUjGZcu(Bk+a9EH6)~l|N>f+HCc$Pm|n?Ggabz?dohQr71$(~LD0k+MXuB6Sg=SW)+%t7 zd}26y)~jLL^b8(0QGfy*?!+IsGF`|_JWVol%Xy=%3jz1iyn`XpzKW#ixW~3 zl)bG$1QNjhW$&2Vq!OX*T?Nv@dNwptW<+1(Rr|w@jj~4#UPtLEFH(xj~-##cWRJJkSJ}3{HZy(4ZeEushQm+yOgmnQ^wiR_TUlj$_L5DtJzL+{?-^M~=rHQeN)m6cI9Jc8Kz%_Y=q&Q6?y_REAE< z@3D84cT?=tW|Tq7t5jE$tm}rZYSq=O>``8$z+j=VN;MYKdKe3n9-R$l?C#-+z=}L0 z4-@6EA-K5o1wI6QA$Ma>smKo;1WWDeJXH}4u>Lw!pjH&-a-c5FsL-k?aLvkE4aWbfSBJ!vYAf!M-u7I@3LIslY2jtmgm_bIQm88jHwPvl7 zG+Ck~ZIUZv4CFkPcC{I+TlsF7HUjjczoDT zlC^=ws>{QMNY<;RIzpbmBQBE-3M~$K;!M6#p`{_uayU-1yF$w|Ax~*vz#f51KxS3Q z^E-SuIY|Eyv^Rx3vm!u)mEUxRYzG>Eh6Xr{_jcJnfEy-ETCj^GM=P|y%T~%n z$13zfmu(;-H+hCaFLv1$u!LtS^ir2?T@2_fg%055$R@-nIf}1>ne1uQlc}Bt2MHnp z`7hO^Lcw&zRBxphj|z)aUj_Vd#8iLfh#?hYsb~zb40!}fO!-c%@)1A(r~IBSkPArxwo`$?A?QBRZws1|@&J^TDp70K z%1L+-N=4MvCSyT|NJV`wU{te=>F9|2I0jnfD3qy0fRoS|`3|(3Dhn{X<7_Q(+Ej&7 zi_mQIv9YBxNd-x>y#`-Tr4*8yZ5obusY-=3&9;#zc2h{#Y!VKWN-Jd1lpCa~6tZfz zmjz=78V`9^Gq-8~+dv_z!EI%_ z+W$Ux9l(hwUF-h{^(1+gR{+&1mTJkBYgkkP^m24qB2}eL%9ih6uweMoiKGdHG!cDdNab_eiP?%`ofBoMUP`-H~Nu1j;;d} zRdgT5S5q0RSVR56TrC~L@^$nLT%n#uVP9>a8zDv`9YNWhUWaaa&|Y{=PkIw&6JCbF zgkJPBwBMVafWBB_2aj%goaw_d9XX2z6Q+^bQkI)X&yHCQPhqxr_sAstbaN!1sF|V z+xWe$>%auw+luphTeYy_ne#WWV#RaHhL7Am_oDROjBvLLkz`>TX$mPnNE4&aRwFR zf@LPzu>34~5DT=^X<%qJr9tj|DuHLtp&gKTE^UNS=FwH~mHAYdz3akw<{21q37rSh z7t-UPa3S64=l8Q#V#$l>aU{E?v>z0f(Nl2li|I*>{4;Gs`*OMs3g;+8`=2o}|sr2MOcCxl=^aP=^Zh zz22l<9WC)PH=k6jd*J3thsIG8F_KM^4-t5DOZNKTqg%4~{~q0veNH~QHHu{4lTU8R zekY&YlKs__TLzDA$pI%H-IC2J`{Z?q9U1>};ra$%lM zN56G6T%yLG;9D>I5Y(G$dK*vk`X8aUrmvbU_Yl8Zpbh5A{e*t8w9}bw&h^ zO4i|fC~HQA&IWIWd<(u?b6V(8wa`$6V9n{Fvk+M!VI4jUD3n;k)Ow@tsVO&@JN0B< zlMGaVfO*WSNd*v}8T>ZFTG5P2g}F>mdlH3ulzs&jiz-+34Q(_~ug02nMGXtlUi2f9NqgOLGJ0YM)gx%CTS=y+^r6UP zb*sp91O2`hpw$$}Fv}jj5m8pR*6a-FU&0aV)|n`x&q8*qTW_MI`lhvR1F4g2t-c7% z)on6SlimZSsJp~O&H6rYU$@yr_#!e1beTzIjJ}R(UJjJO^5gWbLclF%XB&2H=&IgP z(gGpuHK;e&2aLx7_3`{GFs?~hJK@Xq&XRr1LOHyDe|?L= z#O1x%pX&z))yw5F0)5vH4XXSpUqI%sAExeEJ@QfbYyI%xRhSZzd*J@{BZ8cFA~FK^ zuOAuYTcM=MyQ&-eW zWj+ob^^;ZCD!GuuUFia?=&qt{(I1X9oF*+-y;Y;`&(% z4Ya5ObA7u)gDmQZT%Vb(V2j1}y9-q2C^XojE@I3fW->z723a`1dUxtn~9*%_`2P?Z~%@v8KdY9*vKAs;~t~I zVN}4p>Qvm2bK-`&9iGtOR`<{zISjjUL#_fLWA*~kkmu!J_e9j~T!T;D&b7+~l-S@` zS)@bV&NbvKu-G_%k!T2dd6A_y?@(U9K;0<{T#9nc`Z_?Z@kLUN&NRmPTA-K4gH$pS zKK96L_b{No_hV4SQIlXtGN#!D|@V}D1ZB?RhbR4>Jzk_zW78#2n_zTTI^mfmF zxGHGr-V9pV-%+cAw=`x8R!4`ueq!ARF=-K0ZmB~dsyhPavKzRG3!yPn)rU`r!mrtz zLqpfVHjUZUtGio9;AqsCeR6e#8nf@Mj!v&)-GFzVKN@RW`h$dp`M0nGTGSVNys(9P zg*Fw{&{H7N;~L84VRO)|zS0oYpCKT-cayG_+=Ot$NPf4mXLiaOU(rLz=G}{=o7*4Y z0X$iR%G7|)HAU9`cVI+Q_Te>^mUxhBAFe5)@!9{ZDUF^F_T|mtWi4P}>)p!>E<$w5 zo9lUB)3$D3UhrtP|Jq{DZisNJoB7wa9$oHVmYuV`KZQZ#-G-u=M8zrWU zU!P1JhBsfs@_r6SXC^RB)VkGA5Vy7k+C|-o`j~rqMG3}Z-p{YPe zhggy8%HFdf9poOxvRgQLO^r#$&(0p(P)L_#Z5t2Oc&oMmA-+wkyj7P|=b4B4J2&4uzq3i!l z2=_puQZpJTa%#pQY-81G#kPU3=mRWIfZi>2{ntLu}NT|7^|IcbW zPEJTr>ePfs;NzugLgoLNaOC8KQYt$&;TZCCAtq$^Zt@2_*j5$)g@53GP4@Fm;lRL? zUHKG0HTmgm_>yp7;mIz~AN15eI|^O5o$PW_;?%59vn$Z``pGWqAGq;lcc6=tieiKQ zw^n6I_Q)lL!S3iPV4Kiyr?gc0YgyK_xxhL@^<`@|R|c*=HSFItC)cgKBD-L7VPM~> zt}iQ3cD0mcZ{A!?ZP}+b@1W?extBgJ@#{&=-P_s6*~>ZH=W@<*;t^h_{!S;L+03_c zeSD<3ofb4$dO5kFFP=KwMOHlByTou`6K3_VrU3;fNmUdK_w_B{fdia$c91L0PRb*% z4d+?MsTK1GFB1>?SGL;~%QMC~2n}Nj7yN5WV;&b5al&$vW^*(7w^jMt&98*FWU9&(O1Y?U0u_@cwV;iqmjEl{-_&SKymhhU5NT`#(Q4+iuUkinh&J X`>zA=6)dCZ!8a%To3N1zH3JK?OxEP_W2WDIg#ac5nyd zf;-n0y)G!IsHmtY;ELk)x}f5E74=@1>xO#$-)~MqpXcX!I-PfxZ@zuz%sFM_&)PRX zX&Y0t?SYE>rN3jvl4mRT-zw+iEIV)Nx|5q+-5Vd+{*}xG?Cs4L58Ky#abs(Ce!)9` zL8pc9^@q^+dGm$d=8I1`tcG1UCbT_N_*}W?%Vr@gf((IwJ-*0(IXITdcL|}r7VL|b zpkZ?jz%SjFi(fsBAQ=nGfTiu_7=Dp;5s>wAuMm29a3oKVmQ!od^jsa9D*VgQ)JwO_ zm@{8kw^pF3TVODntZl#RPgUt7pyt{8?-uADszVONcr9cg;DXi;FkTvG)w(zy+6FOo-l0gTQY3$Q{y1-n>I%$WeNN`8<4ILWvZ)K<%jp=`_8 zoJRmQ$PG+jqI(yHZIrUK0O*Y1)9BhPch~?X6}$+rMGnu#n#yaN-Dql6Ywwo(od8pe z1L)r)tQ%7>g{|Os5bAv$tG3ePXv?18R7!tjuWzbO?}by?!oGRvw@!yqY=yo}T;Bvf zjgaqbuHOwWF~a_}T>m2bOH*;i4Vyb0dHc}f?4!Y+A{Pd7I*oY%@{$HLdtKZsONMvlA+@#u-DE|;8_O$;wT^V;rc zO89>U{gAM?V$oXnS;ogqbu_%j-CFRJVy6)9>7J~BArHbg+*7cb7yzBc>E@JLMy zn96C^{y=ZEHs=KU`NyY>E@XktDJL4LeQma7M1(eGr;jMk`~rucjFG0TW<|q)7)p-D31tKy72EDloMCBf+ z+Us{AWn{JH5IvlYG#4fpgKBOh!r^1z1#k7{?JzF2LaSHx79#Iq%S6zSS0lA>3#7q#5iWQA+{ZAxK6w!z?jLjhg-k^px5 zDuW|UYlc>=YZ}qy(8i)E8OpcX_n;!J1=*z|Lm3{PZ+CK{^&(pnkVDI2fHjs9B48~% zgt|R|x;J1Lx*aoL#@YdUfa^l`g@*?m3Sc=NT>Oa#35L^naPLrzNlk{|kPC@O(EKNFZny!F*bSsdN&YQ_u+5glH;CN!?Luv;d_}4`Ve8 z{RgF$9v*?LCF~ECbHeKDy$7?6ISXcsP(QocQH-`}b3~}W0=lsBxX=J?O$Ouo*mPdA zAmXWaV4)DaN6?w@F`~!1@tThy4QsTznb+j>WT6Wnft9v{TN}-Q_6^EIX{W2u?x21U zI7Q!KE2yAHD}?Aqn-fA*QUvLuinjQKsHSSHQX{OHA^2U;UG4-Q_V>}#Trk9Y2yDoG zesqk;JFm zm(Kzwq=mtv;PoJoNy&4tLcww;fw@|F0)y4=FhGMWK!_GxQB)7mD4c^ZH;>t2E-X+6 zl=2~}kq^LoWB6Y3t^z^*YOoroKogbgy`Cn)$lb|k-k zWC%K6BijSeTPT0_j5#9wI=O~ek+bq=PhKR#2ThdHV@UYnw@fm%`gZ6%{DHYdgK+); zmNe!hkA-C!yLi2X+t?SLVzmb>qqBkSSgbQW< z9Jr~_6WE2qB~poD=$|8)!=)y232h56!`fjTs-?Tuw*u$Ypx_@1$0ygi<(aq3aF};jT zQ9^T&Z=$ptdti*-jza%&dJ%q5N@GjmnpBk%qKw``FqP9|{gAI{wa&rxF|=Aii;;P{ z(N;)YNy{L86>X~EU|N}gR_Sr1-|n;@64%maaFH}kLT?@AU{*ctMQrq-8^K&p0s+yB zoDeM2n|{K=4YUDPY@mrC(LnDY^!ktkUfGv6H44#>Y{)MC>2>rDpi%ik3?v=Q4We1_ z*+#kyHXBTK7-WYz4bzjpj#mQ2s#W+G*b!Ot|ddBIw3~V zt5DGibYrs+qo@KBkEU|$(I?UY{%38d^>#%Wxsipa(#65=9X(XVS-*brxlMV%pgx(bP(3 zzy&AM+Cm|wPzmIoN_V5TjUIxfr_r^Lbvg~hv~#Ei?6%WVIO7a@6tbR6arnVZS|1l; z7TsPY#B8dA?dQ-U>A*+p~)qTpis5%o*xBk+DHy#>;j z(G6JUa=N%b&fs(#B;G_9K>90aG-S=vUD={>MVT{k8oHMD!6mPwuOaL8v>o=ofi6SK zjZ_5hxry$?k~h;v=w=J$gZ|%W4GeS(4TD*4rG=Pv8%5D_JKX_J?x6l~*gNTbIO$e; z3YNKx-hq|wrtcAlHV zh^OdR_|R^81*<$wU%~&Lp@ZEsLOe^G!1W&b9h^Q#eGvuE(A#D3~T zK)yg8@ctqNV2GFKW-R$Km7w<(`UPfsm5!k001eQEc#WQf0IyS#O^AckA40xCO%UK8 zL^!#;-6F}kwxC3r?BMPbUU2!9omb9-z7q%9HJ(8&wDf)KJh+{gOnf8hahp7 z;)uHs=_L5XN2J3XACmxuPlU6@h1~QOWQA{t!b*7p9Fh_+gP@~P&bvMsMp7e~)#zn7 zgie_VJiwOHTs-*-J>Wibc+G~TWKpgY}5_n8uTh;uu~&A zanNjdqLYSzgo{o^-A%WGHxE66GKX%4=w8}{b}!9?o^$CD2$oA9Los=D4t(4vVynTZ z;%c&-0Vb#~q!zRoIfdv_kjY4z57{+Z51w^ug@P>X$LU5D{5`U%{+X#l*!L$6@99J&e%cxfBTTv`s7%@eTzY@|53SYE-Lys7k) zITt1&x*RQ%(iPxD#I|(r8u_$5$Rj_)Qi6Vg)rsc9xg`ArqiJ+17}seWGL41KfHJH! z9t+w;@s>VlT8>GP?yo_$sZZfrWXCu`AAk#@Z{ZV?UV&&Cjcg@M<~B%Wp%KU%Ryqe7 zx6ux0(4ZTY%yGt7@a?(O+@_UXVsf$!bm_$_v92k(9`a%hRZMPLbf51J(U6**ASGSmL25@=ITtY@JdlvWxDhqF-<+BE2&Fpr)1Xy~Bz zQMUhR1NIlrSFw`yAY8C`WC3R?2iNVdLIt7XlfBE)A`i3u$K`NcsHeN)(><#J4E5Ys ze3qvM^5fx6Ye1tWA%d0X7oV-Qpusv3&Qfw#(H7JlT-P@6uqMb+d_O2E3rExQS-5G~ zU*O`%RzxTCWZ~X~<}`X9uB6ki@C6IG;IUSE3FffTzhFUwmK9@tJMD+NIOxqd3-=9# zaM6iyRyTzqsD~~{v2&NeVZ3w@3*^!r2=_eN3ub&YrkoF#qd*~_`oh5iv=Po7q(+2t zhz_EqfPPHy;j#^(RY)lWPlQf^s6`?Y4q*LM)K1?05JEjwL>*LoKPU^GA8(^hG8Lxt zgL2eG&=~m8$HG8SH~Dy4D1XX==_2Z(yxTD^Dzqz^F_0F~9MV`jeJ_BtJ1M%BypyrK zN%=bRFo6G;AcsXCB>Q=Qjd~H(5PgPnRsyx^oe&`Uvgv>AdOg?%^0GJ1(tW*v{$ciY z=pm+Z$VBt?R1VOmCR(K5!OVO~A%3P_s-I*9`i9hl?utx)$NWwa{ej#+Lh~E+_aR{P zHxq5tA7D9ksfKRW|3LbQ+Rew6Eh+$_1yaT0R^196N2|@gZMvrssF#U$=viiTpow5W}R8$Y!M^x9sL4*BfvSUUf!8~!N158`Rbsdf zQQ@KgA-m;J9madb(}7t-sQ%WtVr z-GS&=vp_$Z*&ro+yhQjX(*B3_GFm6r(ReZIWu-#ITA~-C?p%Z-!VQ~a`^k6`%G6(i zm&INn|J|^P&^M=nUZVUyF;*F0-NarY^DPL4SzRo956)eOUw0Tjqw_tlt9}V((DlJ0LnnpIZ*} zl_}r^{ar+3?0XYU(hK3Nu^*`D6O3%t+Yw^1pG-#E^(G1bi~Vd8?a*6rAdUS(?k_NO zk$x)5*inbPLwCbw|qVFtOI2;nR>+i!$VpC1DQCR=o3-E;K^AOd^ z@;bP|+6QqO8x{R0H*npmGb^K$pL0Wof&B^W9;w(|Z+}pgTl3L9KfrY%?_%W9zi9QLl;(qq{J(JUQXPDJzP_>t%Xpimpej0_?DxO~My2AZ0 zyVn~E7*a*kdm$d>l`397Qy?U-V`F@y!ZRv)3yl4s&aEjk<|MiKgjZ#TmCZ!e8T}EK z%x%INeJswWu?RU?IkozDM)f9Y(Es4L8bq!iuy&)a%yd23PR7V)y|5qpZZv~sjJ~rB z=w=g**ZVUs_mYz@dM4=8I659TX|{@(_B1q5$t1h`)0(-)X)1Cq4$O_QpQV>mgPF8`kzGkE%4;8$!4u=0w2B!0Y6h`a zmk6!c?^30(keN}Ono?j?=XTpR!`osz}b@WN;KXLL&YLRguTB{dV099y;OoPxy zg9%6X{$TC{=8*HTFUu4DB|X2QMM+wKnM!)|(s#K4$lV5?W_yr2=kheAgELC8q zF&_`I@nym9b=-Q%@A{%=d2j%v+$SGm+L<6f)PK``ZbzqxuMD1mkn!>!7he@*qozn$ zkKpVU&x@5LGRP0_0;J+M7<1TI`~oC?Q;-i7LXKh~wgfvt!H{=)0R9$S&*Y4G3t+2T z6bQ-p!ASg81){?GGg~eYTLNnKFHzqaUu!TAD#66p2gjf;RDy|b2xb@=@_u+z{G#AA z_>NcpowabW0wFn##k)l5Cn_hhCta#QN>0OFNc{5P(=bl0^kTP(Z&aYcbc!pKRT@p5 zUa2(KZ0htX1x6{IX5v>XG{#iwHA<-yOr>sCN^LcjdaY9G2BEP_YwO{#DropcyhRnP zG4!m!AjWcEpHmMzj6j8GzlTXBpo@?ecoKR%vSap=v3OC_ak~5RRopJ$YbW3m03$? zDt^YO6kd8>o(Hjz8IPzb?Nl8cHKp@ab&_$uC|#hctwy^jU8t&U@;M~j(nSii%XR`- ztjNrg<8uHm$m?ar6NcQ5R8_h(?^p1#NL~vkDqW_)3faUQW)#>U7xPnU=?X<|qtP+9 zQqrevVK8TjCRbZ<;Zy3Nj1-99?4hPtv_}Og{+9eQN zW1rUe-Lmx$xNpK1bHO9+-=JQbc-~mRPf6-^ablnEF7%lGpV;r?WM!zEjl>)JedzHj zITCMrS*VbbBk`63QIM1*(K~Ce)HJVk>#o7PzvJc-Y{DBrlNIX=M6Y zc~vXqNIYsV&~Z_S0Z}9IqV%Nj@G(OqUh*A*cjYdquM>%veQdW}ekMq~;^QosyMXJj z`uNnBJ6$9W_?S*^n@GH-URCBU5sBA*3qUltQzQ=NvIN390ExKFnu&z5hP?wts4U+& z2fvj*%7S?kMijDOCA_B$uE5$b`~TTfhM7`Mm@|YGl7Rt*dMOK zVp~r}`X)V=LWg|>>buKxjRVZ~$uLg2FR%ro2+40_%ku-5A``W%!&G@NzzXe9(OVwQ z;pknY;;lU5U@LDxER`22_u44?4#)Ho)xKH!ZCJlN9>@W)E$Zg1JfXU_N`5O{UZ%i3 z@+)9NKPFA5L7);`6E(oGNeF4E`zkmumUOR z!YL_Ps6dsHG+Ct9tYt|>vRDb)ATM+QL<1~NV@5s&M@q&61whSm7lTqYX^i|gjws25 zA~znNh5(ofnV?jaOsZj%yj3kg-GKlMFaJu`2I?7ky=;hNom#3RGx1*QOLU=kGRl@%c`U->16=v(lZu_5GL76ocjZj;#$I24(r`}Y+t|^ zlOq&*dXH@_%hRmTGka_+*g`D|J-f%&%&d)6XwM$oudse{ltRz#vAxZVj#lXTJ+^n* zm?tW>j3k9_sC>9OFlLgE`-HWT7GJT09>a6 zfy<%$X#de@O39C)t5h*Boxv75A5TH4sG8bf%RV!rGY;O)iUyVXG&2|CeEY)2hL$hrQ0HqbOYs#9bdW9UCtsl;V zsU8YBHDOJ`?Qx08dbPfSkR(s0gfE`$PXRheucV36{YNng*FNw9A z{V$2No6}6J!ula%pK@c5U{dw#s5eukH2|+w6e?~0KQnWs-EU@QX1mhqH#74;V8=?A z0*jP$R(kxLrdP5Z02JNE!d56`koRBAM5X@< zII5StmoT$c{%e3j)EzgKm6;m<4czw;6i`{~{~PKl@?L>-Rhd>S)snXbiLJ6;p&t04 ziu-yf)Ii>A81+=BKiN7xK)wB($%Ml;Xb4b)LgY}Htg^2{(xEb0Wk0_sgQ1$kW`Sc? z_E(*{LnWxn0SZ|hwp#4Cm4g(rI&8lqAyzgjWOLZ=$^{y%km0aBgFIe2L?OFFWwOel z3OO7qE-IT8ayo2Ju+E1AA^*D^wx?O^BUGo`f!9-rHuA;d(5rnk>g`o_<7)OdKA=}Q zx)K}Tq*OW8Y08USR^{$WWqT3FRXHkAL}dv2sq(5BDR~6ESLG_uAWuVRR^??BYL*!| zSd~wK3BuY0(v%;&1#3EbqHc}a(GZC7r%R4p)U9`5HU(pQxZxVqt?%MFl0vb6aKlTe zTRreNDvW=|4Ra8J)&uZvio}27hJV4N)-Mu>KPrkFc>Z&|*9R?Q;bT-BFW`pl@c-i9 zU`Tb{PVt$@pTx&7K_g)_qKDusk{*VSYUD@4)u|8S-a;p1wv`Sx@}2u;Fkw(R+`>*p z2zPvIfaRSu2z3{o-b0*)w{eRteCa+DTTKon5Z+!YfC_V|H}Y~G{RrNDv=2$#Plu5| z^Jy@62+$M6Z{s4E6{1fg{5H;6irZ(}h`=tSKfp?aPRRbYpdvF3x=qkaxi}Qk^{{j~ zod|}K^i`Cd{Vt^P3i{H@@1bAiFeizasiND#Lp42&@io*BR_spW!CNhTh1Jva8$6+o zPQ$)hPg|ja9&`j{PkIBY=|wNXX?oL#C>!YZ3?}p;9lqI@4niOO=n%;DC+kT5a_g#; zz?WNAh&PC)gRMsTwNc>9t>OXv<<`*={N>i$5VeWwL17p@iT2_2N)3Orbq5sGOs^w8 zTF3%ABk4iZPoUM<;73s>#*C(StXTg0(8?rD_5wcvCr!t&?PV_2Y_rh=gv)Enf^r3!fF zOu7#e&!Y7(%51tBzA}f(vY(${nt2OGTtJ;5y^vl7g@v@s&!1*ph$YXbJuuuNItU7j z=^&hY3B87q7tpO}UrP6(Tt<(gTuvoeD?>k{TtThS=t}ZbaCrm{u!^pS;a1b+r*9_5maD*5Dgh~!{( zV<qDCqt7o#V4;pBND zRp3{gfr)ApgB zs;M&m#k6^ssHq8jg*n2Qfho0t8K7p!wcL>os6R$f_d7N9UBd8vX-!Y%PEpweVQP9S zkPsQ`7jXKTK;nB|=UvpJHO)p(&@K6IJiAs1g1>e^>&ig-u8YlY$1qbgvP>ZY&DN!4iYLCmO^87t9vjOTk#?^3#!%~Fk*LWi0|yIO;AQ{ zq&|)Ih#St;Ub~cxAA$5rB!k-JWLioei%eF#f=oBiA07&{k^<_s(yI@u1YB))hV-A| zh_!1>6xHV;yVb5WQA)jKtzAdzAX}?DG7(-vBAeG< zVp18SU(Pfy1>(O_o1niF2E5GdY!%ji&{f(|EWy9MJL-+;fUyWbo`VFI4&|%s7F^ye z66pd3aMO+#g6YEiCM0&R(KdauNEhX^@j~(w=qFvA-+~@ow_v$+G@tF1Qt_5a#}ulS zX)n4;^Z7578ie(F_;T7=yoOmw!~6H8hZ;;=K7{Q#-4s+Gmdjqb0Kufu2l^n3+&3+)bws<8`c zW$;R^0EP8LHx4`*Tciy(vR{Q`MySqj+{QNMzqY9hg$ zt-1n_%9FAA*QFIm88haJy81jOW?l-`^;DOFt+Fp{Ro6?g)2=QB>v}6N%Q&}F)b+_r z!c{wLM{_W$pSsE1t=Wo(1NB$vX*@oEnt@{K?2+l9Za;*2ZC#PUa?3+y=qSlkSswcY zKvbn7L%l+&i{~B2D6e{jQdgSy4M0ea;HAp)bgUbdC5Vl>^1L_z_N)m|jAHIxjI^ji zCH9QQ8rSxswUUXbF1+wXRSjoaU2Q)cYh#jslCY@DUyVN*)i~|>I*=slUmzu;vkJ|= ziLiA2D^z>}kLklLeW3gLJ2g5p1LW|-&wb4x&rNf=? ziYCw7sv|nq>D#u+^O;fkQ8u@U66zoXWG7_840tc;ELpo^3HF{u;2XGxi1fUMa(LKGG@CDuYW|C~-=k8xmva-67)A~NkG-;! zSNS4)L+Ff154YdT19&q2mP`%UxGG{D@Hj^F&OW%Ro25^XYagzPP+RtYt4d-kz`ne> zaPd$uuxabkf>m%)d2<~*m9}Zi(t@Y616LP$pM?mwc$j}})8VE5HQAY~i%Moe8FyHh zV<~OZ8%zBo(0gYW+_u#Je)i7Q6&ZdR@b|99155ok#lWGHrPns?Sn8h-3ioxvolE`8 z;4RzS%)GYgt)>1|VC?}9D+rt|^Y_L{ZM&cC1ICv5C&LSNx=ofoU+UMf9qj6wyKz}M zfE;z%P<)hY*Sz(t4Ls=e#nHw=wq4yC!pn^o-T7Fhj z+SfL1TP6l&OV{?0m@;u~s^Sa8ru&PQ){4Iq`T^48u=x%Tu0HaRh5!7Dlx^xui=n%_t zjO=~us)F33IQ9r9uc%z1q>so)h9DGu?eSKuu4h#(7i%xGIKmN;2V??+O zuGl~<;ura*Y-Ptq{1n3r`DJng#d(C>gwNJq$nIZX7ziM%s;+v99`E`rdvtxFb%g55 z7H+5vEIKx-f+~-Xnw_1rp)hdQv91JF9PfG|dnvl!Io4G|WyiaI%07uMC(a9M+3;VM z-JJaoy80jM%BRxfvtG(ZFDwkqKGx;^iyST4u@@F*ZaUWGq{Q)A|3f;kDxHi*jPpM{ z`lx?&!>h+8SpULY1w5S8gjCmrKb0t;V8t^1$yc`?2_b&NdMzTiYXXA3YlT`&C}6GA zZ^xC^Ef@GFX7DJYhyVRKzEzFS_PD59X5;ax-*rDGO}Fb1jbAf*vTN#}yzM?d{_AeX z#t-R-ZHzv5F~0Wy%`h4J{J4e%VXN~*aF)QIdS&0cC`-}p=Ux1$%;+@G>2$XE`a1hL z`#1@N`ua%oI4x+fm<|2ZR4eXL+@i(T02%{oXi$OXG3O);T73Nrc;-MSof72AASdNg zo(%^r2UazQ_-AOb zfJ_d4g7}Hyry4)K@gwo~bU6*#p_ebs*d`#=+Royljf>e_Ea&1PF0x!)#|8iY4aU7F z?2n;v>_I{N{k`)&u6@qMPh9XjOv>e=h>I#N8n_sO!Ziwobpi@^8^ewQl#UBfc=*p| zJhh~V__uG#&h_{@r%pe6{^E{lXLpKY)$Q?H`jKPul&NP= zZJ#{v?9T0zZoU66c>Z?B?VAd>-?6(ky8Xk$uTb`lk3!j3KT7NE^JmZ6{@X|0X?u@P zZlLTKY2AL{)2N^Rll}IW-u9O+g7Wb1*X*}PgW2YzQTyJ@%$85G=N;`$f6v}^bdY`j fhi2RL7}Xp5S;en|XmfT3%Es(nCcurrent->download) + if (!ctx->current->io.download) return 0; if (!ctx->current->root) @@ -375,7 +375,7 @@ static gboolean timer_handler(gpointer user_data) abc_obj_t* obj; if (ctx->current) { - if (!ctx->current->download) + if (!ctx->current->io.download) return TRUE; if (!ctx->current->root) { @@ -494,7 +494,7 @@ int main(int argc, char *argv[]) return ret; } - while (!html->download) + while (!html->io.download) usleep(50 * 1000); ret = abc_html_parse(html); -- 2.25.1