css: support css selector by ID or class, such as '#id {}' or 'p.red {}' master
authoryu.dongliang <18588496441@163.com>
Sun, 22 Mar 2026 16:38:07 +0000 (00:38 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 22 Mar 2026 16:38:07 +0000 (00:38 +0800)
examples/css.html
html/abc_css.c
html/abc_html.c
html/abc_obj.c
html/abc_obj.h
ui/abc_layout.c
ui/abc_render.c

index 5a0be37153dc3978d2ab7ee3626d2be9e295c774..5fe90691a7216fe871b33d45a3d9d0f8315f17ce 100644 (file)
@@ -2,17 +2,23 @@
 <html>
 <head>
 <style>
 <html>
 <head>
 <style>
-p
+#a /*css comment*/
 {
        color:blue;
        text-align:center;
 {
        color:blue;
        text-align:center;
-} 
+}
+
+p.red
+{
+       color:red;
+}
 </style>
 </head>
 
 <body>
 </style>
 </head>
 
 <body>
-<p>Hello World!</p>
-<p>这个段落<b>采用</b>CSS样式化。</p>
+<h1 class="red">这个段落采用CSS样式化。</h1>
+<p id="a">Hello World!</p>
+<p class="red">这个段落<b>采用</b>CSS样式化。</p>
 </body>
 
 </html>
 </body>
 
 </html>
index 66ecf581929855068509e7f54cb6c023d4380a08..33d386d301f31466e4af78afc3a13269134d9830 100644 (file)
@@ -1,6 +1,52 @@
 #include"abc_html.h"
 #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);
+
+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);
+html_label_t*  __html_find_label2(const int   type);
+
+static int __css_drop_comment(abc_obj_t* css)
+{
+       abc_char_t* c = __io_pop_char(&css->io);
+       if (!c)
+               return -1;
+
+       if ('*' != c->c) {
+               __io_push_char(&css->io, c);
+               return 1;
+       }
+
+       css->text_pos++;
+       free(c);
+       c = NULL;
+
+       int prev = 0;
+       while (1) {
+               c = __io_pop_char(&css->io);
+               if (!c)
+                       return -1;
+
+               int tmp = c->c;
+               free(c);
+               c = NULL;
+
+               if (EOF == tmp)
+                       return -1;
+
+               if ('\n' == tmp) {
+                       css->text_line++;
+                       css->text_pos = 0;
+               } else {
+                       css->text_pos++;
+
+                       if ('*' == prev && '/' == tmp)
+                               break;
+               }
+
+               prev = tmp;
+       }
+
+       return 0;
+}
 
 static int __css_parse_value(abc_obj_t* css, abc_obj_t* attr)
 {
 
 static int __css_parse_value(abc_obj_t* css, abc_obj_t* attr)
 {
@@ -14,13 +60,31 @@ static int __css_parse_value(abc_obj_t* css, abc_obj_t* attr)
        while (1) {
                c = __io_pop_char(&css->io);
                if (!c) {
        while (1) {
                c = __io_pop_char(&css->io);
                if (!c) {
-                       scf_loge("\n");
                        scf_string_free(value);
                        return -1;
                }
 
                css->text_pos += c->len;
 
                        scf_string_free(value);
                        return -1;
                }
 
                css->text_pos += c->len;
 
+               if ('/' == c->c) {
+                       int ret = __css_drop_comment(css);
+                       if (0 == ret) {
+                               free(c);
+                               continue;
+                       }
+
+                       if (ret < 0) {
+                               free(c);
+                               scf_string_free(value);
+                               return ret;
+                       }
+               }
+
+               if ('\n' == c->c) {
+                       css->text_line++;
+                       css->text_pos = 0;
+               }
+
                if (';' == c->c)
                        break;
                else
                if (';' == c->c)
                        break;
                else
@@ -53,7 +117,6 @@ static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t*
        while (1) {
                c = __io_pop_char(&css->io);
                if (!c) {
        while (1) {
                c = __io_pop_char(&css->io);
                if (!c) {
-                       scf_loge("\n");
                        scf_string_free(key);
                        return -1;
                }
                        scf_string_free(key);
                        return -1;
                }
@@ -69,6 +132,20 @@ static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t*
                if (':' == c->c)
                        break;
 
                if (':' == c->c)
                        break;
 
+               if ('/' == c->c) {
+                       int ret = __css_drop_comment(css);
+                       if (0 == ret) {
+                               free(c);
+                               continue;
+                       }
+
+                       if (ret < 0) {
+                               free(c);
+                               scf_string_free(key);
+                               return ret;
+                       }
+               }
+
                if ('_' == c->c
                                || '-' == c->c
                                || ('a' <= c->c && 'z' >= c->c)) {
                if ('_' == c->c
                                || '-' == c->c
                                || ('a' <= c->c && 'z' >= c->c)) {
@@ -76,10 +153,11 @@ static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t*
 
                } else if (' ' == c->c || '\t' == c->c || '\r' == c->c) {
 
 
                } else if (' ' == c->c || '\t' == c->c || '\r' == c->c) {
 
+               } else if ('\n' == c->c) {
+                       css->text_line++;
+                       css->text_pos = 0;
                } else {
                } 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);
+                       scf_loge("invalid char '%c:%#x' in CSS attribute, file: %s, line: %d\n", c->c, c->c, css->file->data, css->text_line);
                        free(c);
                        scf_string_free(key);
                        return -1;
                        free(c);
                        scf_string_free(key);
                        return -1;
@@ -159,10 +237,9 @@ static int __css_parse_attr(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* a
 
 static int __css_parse_obj(abc_obj_t* css, abc_char_t* c)
 {
 
 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);
+       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);
 
        css->text_pos += c->len;
        free(c);
@@ -171,55 +248,96 @@ static int __css_parse_obj(abc_obj_t* css, abc_char_t* c)
        if (!key)
                return -ENOMEM;
 
        if (!key)
                return -ENOMEM;
 
+       int ret;
+       int dot = -1;
+
        while (1) {
                c = __io_pop_char(&css->io);
                if (!c) {
        while (1) {
                c = __io_pop_char(&css->io);
                if (!c) {
-                       scf_loge("\n");
                        scf_string_free(key);
                        return -1;
                }
 
                css->text_pos += c->len;
 
                        scf_string_free(key);
                        return -1;
                }
 
                css->text_pos += c->len;
 
-               if (' ' == c->c || '{' == c->c)
+               if ('{' == c->c)
                        break;
 
                        break;
 
-               if ('\n' == c->c) {
+               if ('/' == c->c) {
+                       ret = __css_drop_comment(css);
+                       if (0 == ret) {
+                               free(c);
+                               continue;
+                       }
+
+                       if (ret < 0) {
+                               free(c);
+                               scf_string_free(key);
+                               return ret;
+                       }
+               }
+
+               if (' ' == c->c || '\t' == c->c || '\r' == c->c) {
+
+               } else if ('\n' == c->c) {
                        css->text_line++;
                        css->text_pos = 0;
                        css->text_line++;
                        css->text_pos = 0;
-                       break;
+               } else {
+                       if (dot < 0 && '.' == c->c)
+                               dot = key->len;
+
+                       scf_string_cat_cstr_len(key, c->utf8, c->len);
                }
 
                }
 
-               scf_string_cat_cstr_len(key, c->utf8, c->len);
                free(c);
                c = NULL;
        }
 
        int tmp = c->c;
                free(c);
                c = NULL;
        }
 
        int tmp = c->c;
-       int ret;
-
        free(c);
        c = NULL;
 
        free(c);
        c = NULL;
 
-       label = __html_find_label(key->data);
+       switch (key->data[0])
+       {
+               case '#':
+                       dot   = 0;
+                       label = __html_find_label2(ABC_CSS_ID);
+                       break;
+
+               case '.':
+                       dot   = 0;
+                       label = __html_find_label2(ABC_CSS_CLASS);
+                       break;
+               default:
+                       if (dot >= 0)
+                               label = __html_find_label2(ABC_CSS_CLASS);
+                       else
+                               label = __html_find_label(key->data);
+                       break;
+       };
+
        if (!label) {
        if (!label) {
-               scf_loge("invalid HTML label '%s' in file: %s, line: %d\n",
-                               key->data, css->file->data, css->text_line);
+               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);
                return -1;
        }
 
-       scf_string_free(key);
-       key = NULL;
-
        obj = abc_obj_alloc(css->file, css->text_line, css->text_pos, label->type);
        obj = abc_obj_alloc(css->file, css->text_line, css->text_pos, label->type);
-       if (!obj)
+       if (!obj) {
+               scf_string_free(key);
                return -ENOMEM;
                return -ENOMEM;
+       }
 
 
-       obj->flags = label->flags;
-       obj->keys  = label->names;
+       obj->css_dot = dot;
+       obj->flags   = label->flags;
+       obj->keys    = label->names;
+       obj->parent  = css;
 
 
-       obj->parent = css;
+       if (ABC_CSS_ID == obj->type || ABC_CSS_CLASS == obj->type)
+               obj->text = key;
+       else
+               scf_string_free(key);
+       key = NULL;
 
        switch (tmp) {
                case '{':
 
        switch (tmp) {
                case '{':
@@ -241,6 +359,7 @@ static int __css_parse_obj(abc_obj_t* css, abc_char_t* c)
 int abc_css_parse(abc_obj_t* css)
 {
        abc_char_t* c;
 int abc_css_parse(abc_obj_t* css)
 {
        abc_char_t* c;
+       abc_char_t* c2;
        abc_io_t*   io = abc_io_array[ABC_PROTO_STR];
 
        css->io.proto = io->proto;
        abc_io_t*   io = abc_io_array[ABC_PROTO_STR];
 
        css->io.proto = io->proto;
@@ -267,30 +386,39 @@ int abc_css_parse(abc_obj_t* css)
                        return 0;
                }
 
                        return 0;
                }
 
-               if ('\n' == c->c || '\r' == c->c) {
+               if ('\n' == c->c) {
                        css->text_line++;
                        css->text_pos = 0;
                        css->text_line++;
                        css->text_pos = 0;
-
                        free(c);
                        continue;
                }
 
                        free(c);
                        continue;
                }
 
-               if (' ' == c->c || '\t' == c->c) {
+               if (' ' == c->c || '\t' == c->c || '\r' == c->c) {
                        css->text_pos++;
                        free(c);
                        continue;
                }
 
                        css->text_pos++;
                        free(c);
                        continue;
                }
 
-               if (('a' <= c->c && 'z' >= c->c)
-                               || (0x4e00 <= c->c && 0x9fa5 >= c->c)) {
+               if ('/' == c->c) {
+                       ret = __css_drop_comment(css);
+                       if (0 == ret) {
+                               free(c);
+                               continue;
+                       }
+               }
+
+               if ('#' == c->c
+                               || ('a'    <= c->c && 'z'    >= c->c)
+                               || (0x4e00 <= c->c && 0x9fa5 >= c->c)
+                               ||  '.'    == c->c) {
 
 
-                       int ret = __css_parse_obj(css, c);
+                       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 {
                        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);
+                       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;
                }
                        free(c);
                        return -1;
                }
@@ -305,6 +433,7 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj)
                return -EINVAL;
 
        scf_list_t*  l;
                return -EINVAL;
 
        scf_list_t*  l;
+       scf_list_t*  l2;
        abc_obj_t*   css;
        abc_obj_t*   label;
        abc_obj_t*   attr;
        abc_obj_t*   css;
        abc_obj_t*   label;
        abc_obj_t*   attr;
@@ -313,10 +442,28 @@ int abc_css_use(abc_html_t* html, abc_obj_t* obj)
        if (!css)
                return 0;
 
        if (!css)
                return 0;
 
-       label = abc_obj_find_type(css, obj->type);
-       if (label) {
-               for (l   = scf_list_head(&label->attrs); l != scf_list_sentinel(&label->attrs); l = scf_list_next(l)) {
-                       attr = scf_list_data(l, abc_obj_t, list);
+       for (l    = scf_list_head(&css->childs); l != scf_list_sentinel(&css->childs); l = scf_list_next(l)) {
+               label = scf_list_data(l, abc_obj_t, list);
+
+               if (ABC_CSS_ID == label->type || ABC_CSS_CLASS == label->type)
+               {
+                       attr = abc_obj_get_attr(obj, label->type);
+                       if (!attr)
+                               continue;
+
+                       if (strcmp(attr->value->data, label->text->data + label->css_dot + 1))
+                               continue;
+
+                       if (label->css_dot > 0) {
+                               if (strncmp(obj->keys[0], label->text->data, label->css_dot))
+                                       continue;
+                       }
+
+               } else if (label->type != obj->type)
+                       continue;
+
+               for (l2  = scf_list_head(&label->attrs); l2 != scf_list_sentinel(&label->attrs); l2 = scf_list_next(l2)) {
+                       attr = scf_list_data(l2, abc_obj_t, list);
 
                        abc_recursive_set_attr(obj, attr->type, attr->value->data);
                }
 
                        abc_recursive_set_attr(obj, attr->type, attr->value->data);
                }
index 548510078a0297744ca6cbc7a7d1459e6b4eb540..fa99b2a0ea1e841ba58f321ecbae62eb2f48ffc5 100644 (file)
@@ -16,6 +16,7 @@ static char* font_italic_keys[] = {"italic",    "斜体",     NULL};
 
 static char* text_align_keys[] = {"text-align", "对齐",     NULL};
 
 
 static char* text_align_keys[] = {"text-align", "对齐",     NULL};
 
+static char* class_keys[]      = {"class",      "类名",     NULL};
 static char* type_keys[]       = {"type",       "类型",     NULL};
 static char* name_keys[]       = {"name",       "名字",     NULL};
 static char* for_keys[]        = {"for",        "关于",     NULL};
 static char* type_keys[]       = {"type",       "类型",     NULL};
 static char* name_keys[]       = {"name",       "名字",     NULL};
 static char* for_keys[]        = {"for",        "关于",     NULL};
@@ -80,6 +81,9 @@ static char* progress_keys[]   = {"progress",   "进度条",   NULL};
 static char* script_keys[]     = {"script",     "脚本",     NULL};
 static char* style_keys[]      = {"style",      "样式",     NULL};
 
 static char* script_keys[]     = {"script",     "脚本",     NULL};
 static char* style_keys[]      = {"style",      "样式",     NULL};
 
+static char* css_id_keys[]     = {"#",          NULL};
+static char* css_class_keys[]  = {".",          NULL};
+
 static html_attr_t  html_attrs[] =
 {
        {xmlns_keys,       "",           ABC_HTML_ATTR_XMLNS,     0},
 static html_attr_t  html_attrs[] =
 {
        {xmlns_keys,       "",           ABC_HTML_ATTR_XMLNS,     0},
@@ -102,41 +106,75 @@ static html_attr_t  body_attrs[] =
 
 static html_attr_t  h1_attrs[] =
 {
 
 static html_attr_t  h1_attrs[] =
 {
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "40",         ABC_HTML_ATTR_FONT_SIZE, 0},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "40",         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  h2_attrs[] =
 {
 };
 
 static html_attr_t  h2_attrs[] =
 {
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "32",         ABC_HTML_ATTR_FONT_SIZE, 0},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "32",         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  h3_attrs[] =
 {
 };
 
 static html_attr_t  h3_attrs[] =
 {
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "28",         ABC_HTML_ATTR_FONT_SIZE, 0},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "28",         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  h4_attrs[] =
 {
 };
 
 static html_attr_t  h4_attrs[] =
 {
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "24",         ABC_HTML_ATTR_FONT_SIZE, 0},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "24",         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  h5_attrs[] =
 {
 };
 
 static html_attr_t  h5_attrs[] =
 {
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "20",         ABC_HTML_ATTR_FONT_SIZE, 0},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "20",         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  h6_attrs[] =
 {
 };
 
 static html_attr_t  h6_attrs[] =
 {
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
        {font_keys,        "SimHei",     ABC_HTML_ATTR_FONT,      0},
        {font_size_keys,   "16",         ABC_HTML_ATTR_FONT_SIZE, 0},
        {font_keys,        "SimHei",     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  p_attrs[] =
 };
 
 static html_attr_t  p_attrs[] =
+{
+       {class_keys,       "",           ABC_HTML_ATTR_CLASS,      ABC_HTML_FLAG_SHOW},
+       {id_keys,          "",           ABC_HTML_ATTR_ID,         ABC_HTML_FLAG_SHOW},
+       {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  css_id_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},
@@ -233,51 +271,50 @@ static html_attr_t  script_attrs[] =
 
 static html_label_t  html_labels[] =
 {
 
 static html_label_t  html_labels[] =
 {
-       {html_keys,     ABC_HTML,          abc_number_of(html_attrs), html_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {meta_keys,     ABC_HTML_META,     abc_number_of(meta_attrs), meta_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE},
-       {body_keys,     ABC_HTML_BODY,     abc_number_of(body_attrs), body_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-
-       {title_keys,    ABC_HTML_TITLE,    0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {head_keys,     ABC_HTML_HEAD,     0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-
-       {div_keys,      ABC_HTML_DIV,      0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-
-       {h1_keys,       ABC_HTML_H1,       abc_number_of(h1_attrs),    h1_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {h2_keys,       ABC_HTML_H2,       abc_number_of(h2_attrs),    h2_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {h3_keys,       ABC_HTML_H3,       abc_number_of(h3_attrs),    h3_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {h4_keys,       ABC_HTML_H4,       abc_number_of(h4_attrs),    h4_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {h5_keys,       ABC_HTML_H5,       abc_number_of(h5_attrs),    h5_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {h6_keys,       ABC_HTML_H6,       abc_number_of(h6_attrs),    h6_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-
-       {p_keys,        ABC_HTML_P,        abc_number_of(p_attrs),     p_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {br_keys,       ABC_HTML_BR,       0,                          NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
-       {hr_keys,       ABC_HTML_HR,       0,                          NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
-
-       {a_keys,        ABC_HTML_A,        abc_number_of(a_attrs),     a_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {img_keys,      ABC_HTML_IMG,      abc_number_of(img_attrs),   img_attrs,     ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE | ABC_HTML_FLAG_SHOW},
-
-       {form_keys,     ABC_HTML_FORM,     abc_number_of(form_attrs),  form_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {input_keys,    ABC_HTML_INPUT,    abc_number_of(input_attrs), input_attrs,   ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
-       {label_keys,    ABC_HTML_LABEL,    abc_number_of(label_attrs), label_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {center_keys,   ABC_HTML_CENTER,   0,                          NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-
-       {table_keys,    ABC_HTML_TABLE,    0,                          NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {tr_keys,       ABC_HTML_TR,       0,                          NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {td_keys,       ABC_HTML_TD,       0,                          NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-
-       {video_keys,    ABC_HTML_VIDEO,    abc_number_of(video_attrs),  video_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {audio_keys,    ABC_HTML_AUDIO,    abc_number_of(audio_attrs),  audio_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {source_keys,   ABC_HTML_SOURCE,   abc_number_of(source_attrs), source_attrs, ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
-
-       {play_keys,     ABC_HTML_PLAY,     0,                           NULL,         ABC_HTML_FLAG_OPEN},
-       {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},
-
-       {b_keys,        ABC_HTML_B,        abc_number_of(b_attrs),     b_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
-       {i_keys,        ABC_HTML_I,        abc_number_of(i_attrs),     i_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {html_keys,       ABC_HTML,          abc_number_of(html_attrs),    html_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {meta_keys,       ABC_HTML_META,     abc_number_of(meta_attrs),    meta_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE},
+       {body_keys,       ABC_HTML_BODY,     abc_number_of(body_attrs),    body_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {title_keys,      ABC_HTML_TITLE,    0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {head_keys,       ABC_HTML_HEAD,     0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {div_keys,        ABC_HTML_DIV,      0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+
+       {h1_keys,         ABC_HTML_H1,       abc_number_of(h1_attrs),      h1_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {h2_keys,         ABC_HTML_H2,       abc_number_of(h2_attrs),      h2_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {h3_keys,         ABC_HTML_H3,       abc_number_of(h3_attrs),      h3_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {h4_keys,         ABC_HTML_H4,       abc_number_of(h4_attrs),      h4_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {h5_keys,         ABC_HTML_H5,       abc_number_of(h5_attrs),      h5_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {h6_keys,         ABC_HTML_H6,       abc_number_of(h6_attrs),      h6_attrs,      ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+
+       {p_keys,          ABC_HTML_P,        abc_number_of(p_attrs),       p_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {b_keys,          ABC_HTML_B,        abc_number_of(b_attrs),       b_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {i_keys,          ABC_HTML_I,        abc_number_of(i_attrs),       i_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+
+       {br_keys,         ABC_HTML_BR,       0,                            NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
+       {hr_keys,         ABC_HTML_HR,       0,                            NULL,          ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
+
+       {a_keys,          ABC_HTML_A,        abc_number_of(a_attrs),       a_attrs,       ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {img_keys,        ABC_HTML_IMG,      abc_number_of(img_attrs),     img_attrs,     ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE | ABC_HTML_FLAG_SHOW},
+
+       {form_keys,       ABC_HTML_FORM,     abc_number_of(form_attrs),    form_attrs,    ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {input_keys,      ABC_HTML_INPUT,    abc_number_of(input_attrs),   input_attrs,   ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
+       {label_keys,      ABC_HTML_LABEL,    abc_number_of(label_attrs),   label_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {center_keys,     ABC_HTML_CENTER,   0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+
+       {table_keys,      ABC_HTML_TABLE,    0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {tr_keys,         ABC_HTML_TR,       0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {td_keys,         ABC_HTML_TD,       0,                            NULL,          ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+
+       {video_keys,      ABC_HTML_VIDEO,    abc_number_of(video_attrs),   video_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {audio_keys,      ABC_HTML_AUDIO,    abc_number_of(audio_attrs),   audio_attrs,   ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {source_keys,     ABC_HTML_SOURCE,   abc_number_of(source_attrs),  source_attrs,  ABC_HTML_FLAG_OPEN  | ABC_HTML_FLAG_SHOW},
+       {play_keys,       ABC_HTML_PLAY,     0,                            NULL,          ABC_HTML_FLAG_OPEN},
+       {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},
+
+       {css_id_keys,     ABC_CSS_ID,        abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
+       {css_class_keys,  ABC_CSS_CLASS,     abc_number_of(css_id_attrs),  css_id_attrs,  ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW},
 };
 
 static int __html_parse_obj(abc_html_t* html, abc_char_t* c);
 };
 
 static int __html_parse_obj(abc_html_t* html, abc_char_t* c);
@@ -302,6 +339,21 @@ html_label_t* __html_find_label(const char* name)
        return NULL;
 }
 
        return NULL;
 }
 
+html_label_t* __html_find_label2(const int type)
+{
+       html_label_t* label;
+       int i;
+
+       for (i = 0; i < sizeof(html_labels) / sizeof(html_labels[0]); i++) {
+               label     =       &html_labels[i];
+
+               if (type == label->type)
+                       return  label;
+       }
+
+       return NULL;
+}
+
 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);
 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);
index b026202bd21183ba6ab1e696924af5fed985df39..a1177fff78f7f76a4fab63c0f1a64335556fbc14 100644 (file)
@@ -187,9 +187,10 @@ void abc_obj_print(abc_obj_t* obj)
        if (!(ABC_HTML_FLAG_SHOW & obj->flags))
                return;
 
        if (!(ABC_HTML_FLAG_SHOW & obj->flags))
                return;
 
-       if (obj->value)
-               printf(" %s=\"%s\"", obj->keys[0], obj->value->data);
-       else if (obj->keys)
+       if (obj->value) {
+               if (obj->value->len > 0)
+                       printf(" %s=\"%s\"", obj->keys[0], obj->value->data);
+       } else if (obj->keys)
                printf("<%s", obj->keys[0]);
 
 
                printf("<%s", obj->keys[0]);
 
 
index 812b69482dd56379aa6749e1973ede6aa31ab33d..567ad02dd6cbdc57d11e19e69f8ceff840cf77de 100644 (file)
@@ -67,6 +67,7 @@ enum abc_objs
        ABC_HTML_ATTR_TYPE,
        ABC_HTML_ATTR_NAME,
        ABC_HTML_ATTR_VALUE,
        ABC_HTML_ATTR_TYPE,
        ABC_HTML_ATTR_NAME,
        ABC_HTML_ATTR_VALUE,
+       ABC_HTML_ATTR_CLASS,
 
        ABC_HTML_ATTR_HREF,
        ABC_HTML_ATTR_SRC,
 
        ABC_HTML_ATTR_HREF,
        ABC_HTML_ATTR_SRC,
@@ -98,6 +99,10 @@ enum abc_objs
        ABC_HTML_ATTR_ENCTYPE,
 
        ABC_HTML_ATTR_CONTROLS,
        ABC_HTML_ATTR_ENCTYPE,
 
        ABC_HTML_ATTR_CONTROLS,
+
+       // css objects
+       ABC_CSS_ID    = ABC_HTML_ATTR_ID,
+       ABC_CSS_CLASS = ABC_HTML_ATTR_CLASS,
 };
 
 struct abc_obj_s
 };
 
 struct abc_obj_s
@@ -137,6 +142,8 @@ struct abc_obj_s
        int             text_pos;
        abc_io_t        io;
 
        int             text_pos;
        abc_io_t        io;
 
+       int             css_dot; // dot position for css class
+
        scf_string_t*   file; // file name
        int             line; // line
        int             pos;  // position
        scf_string_t*   file; // file name
        int             line; // line
        int             pos;  // position
index b33897a8a863e6cff2f38a8795aedb1afd734a15..de0a2869cbc2e498275b76d1641833356ebf431e 100644 (file)
@@ -72,7 +72,7 @@ static abc_layout_pt abc_layouts[ABC_HTML_NB] =
 int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
 {
        if (obj->type >= ABC_HTML_NB)
 int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
 {
        if (obj->type >= ABC_HTML_NB)
-               return -EINVAL;
+               return 0;
 
        abc_layout_pt f = abc_layouts[obj->type];
        if (!f)
 
        abc_layout_pt f = abc_layouts[obj->type];
        if (!f)
index 0ed4fde78202dea61f9889d7547baa30f5e82d8c..095548db85ff0d26e3b184c7fba15247ecf371a2 100644 (file)
@@ -92,7 +92,7 @@ int abc_renders_fini()
 int abc_render_draw(abc_obj_t* obj, int width, int height)
 {
        if (obj->type >= ABC_HTML_NB)
 int abc_render_draw(abc_obj_t* obj, int width, int height)
 {
        if (obj->type >= ABC_HTML_NB)
-               return -EINVAL;
+               return 0;
 
        abc_render_t* render = abc_renders[obj->type];
        if (!render)
 
        abc_render_t* render = abc_renders[obj->type];
        if (!render)