File Coverage

third_party/modest/source/modest/finder/pseudo_class.c
Criterion Covered Total %
statement 0 437 0.0
branch 0 344 0.0
condition n/a
subroutine n/a
pod n/a
total 0 781 0.0


line stmt bran cond sub pod time code
1             /*
2             Copyright (C) 2016-2017 Alexander Borisov
3            
4             This library is free software; you can redistribute it and/or
5             modify it under the terms of the GNU Lesser General Public
6             License as published by the Free Software Foundation; either
7             version 2.1 of the License, or (at your option) any later version.
8            
9             This library is distributed in the hope that it will be useful,
10             but WITHOUT ANY WARRANTY; without even the implied warranty of
11             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12             Lesser General Public License for more details.
13            
14             You should have received a copy of the GNU Lesser General Public
15             License along with this library; if not, write to the Free Software
16             Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17            
18             Author: lex.borisov@gmail.com (Alexander Borisov)
19             */
20              
21             #include "modest/finder/pseudo_class.h"
22             #include "modest/finder/resource.h"
23              
24 0           bool modest_finder_selector_sub_type_pseudo_class_function_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
25             {
26 0           return false;
27             }
28              
29 0           bool modest_finder_selector_sub_type_pseudo_class_function_current(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
30             {
31 0           mycss_selectors_list_t *list = selector->value;
32             bool i_found;
33            
34 0 0         for(size_t i = 0; i < list->entries_list_length; i++)
35             {
36 0           i_found = false;
37 0           modest_finder_node_combinator_undef(finder, base_node, NULL, list->entries_list[i].entry, spec, modest_finder_callback_found_with_bool, &i_found);
38            
39 0 0         if(i_found == true)
40 0           return true;
41             }
42            
43 0           return false;
44             }
45              
46             /* after create render */
47 0           bool modest_finder_selector_sub_type_pseudo_class_function_dir(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
48             {
49 0           return false;
50             }
51              
52 0           bool modest_finder_selector_sub_type_pseudo_class_function_drop(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
53             {
54 0           return false;
55             }
56              
57 0           bool modest_finder_selector_sub_type_pseudo_class_function_has(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
58             {
59 0           mycss_selectors_list_t *list = selector->value;
60             bool i_found;
61            
62 0 0         for(size_t i = 0; i < list->entries_list_length; i++)
63             {
64 0           i_found = false;
65            
66 0           mycss_selectors_entry_t *sel_entry = list->entries_list[i].entry;
67            
68 0 0         if(sel_entry->combinator == MyCSS_SELECTORS_COMBINATOR_UNDEF)
69 0           modest_finder_node_combinator_descendant(finder, base_node, NULL, sel_entry, spec, modest_finder_callback_found_with_bool, &i_found);
70             else
71 0           modest_finder_static_selector_combinator_map[sel_entry->combinator](finder, base_node, NULL, sel_entry, spec, modest_finder_callback_found_with_bool, &i_found);
72            
73 0 0         if(i_found == true)
74 0           return true;
75             }
76            
77 0           return false;
78             }
79              
80 0           bool modest_finder_selector_sub_type_pseudo_class_function_contains(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
81             {
82 0 0         if(base_node == NULL)
83 0           return false;
84            
85 0           myhtml_tree_node_t *text_node = myhtml_node_child(base_node);
86 0 0         if(text_node == NULL)
87 0           return false;
88              
89 0           const char* text = myhtml_node_text(text_node, NULL);
90 0 0         if(text == NULL)
91 0           return false;
92              
93 0           mycss_selectors_list_t *list = (mycss_selectors_list_t*)selector->value;
94 0 0         for(size_t i = 0; i < list->entries_list_length; i++) {
95 0           char *data = NULL;
96 0           data = mycore_malloc(0);
97 0 0         if(data == NULL) {
98 0           return false;
99             }
100            
101 0           mycss_selectors_entry_t *sel_entry = list->entries_list[i].entry;
102 0 0         if(sel_entry->key->data){
103 0           const char *str = sel_entry->key->data;
104 0           int length = strlen(str) + 1;
105              
106 0           char *new_data = mycore_realloc(data, length);
107 0 0         if(new_data == NULL) {
108 0           mycore_free(data);
109 0           return false;
110             }
111              
112 0           snprintf(new_data, length, "%s", str);
113 0           data = new_data;
114             }
115              
116 0           mycss_selectors_entry_t *next = sel_entry->next;
117 0 0         while(next) {
118 0 0         if(next->key->data) {
119 0           int prev = strlen(data);
120 0 0         const char *whitespace = (prev > 0) ? " " : "";
121 0           const char *str = next->key->data;
122 0           int length = strlen(whitespace) + strlen(str) + 1;
123              
124 0           char *new_data = mycore_realloc(data, prev + length);
125 0 0         if(new_data == NULL) {
126 0           mycore_free(data);
127 0           return false;
128             }
129            
130 0           snprintf(&new_data[prev], length, "%s%s", whitespace, str);
131 0           data = new_data;
132             }
133 0           next = next->next;
134             }
135              
136 0 0         if(strstr(text, data) != NULL) {
137 0           mycore_free(data);
138 0           return true;
139             }
140 0           mycore_free(data);
141             }
142            
143 0           return false;
144             }
145              
146 0           bool modest_finder_selector_sub_type_pseudo_class_function_lang(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
147             {
148 0           return false;
149             }
150              
151 0           bool modest_finder_selector_sub_type_pseudo_class_function_matches(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
152             {
153 0           mycss_selectors_list_t *list = selector->value;
154 0           bool i_found, is_true = false;
155            
156 0 0         for(size_t i = 0; i < list->entries_list_length; i++)
157             {
158 0           i_found = false;
159 0           modest_finder_node_combinator_undef(finder, base_node, NULL, list->entries_list[i].entry, spec, modest_finder_callback_found_with_bool, &i_found);
160            
161 0 0         if(i_found == true) {
162 0           modest_finder_specificity_inc(list->entries_list[i].entry, spec);
163            
164 0 0         if(is_true == false)
165 0           is_true = true;
166             }
167             }
168            
169 0           return is_true;
170             }
171              
172 0           bool modest_finder_selector_sub_type_pseudo_class_function_not(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
173             {
174 0           mycss_selectors_list_t *list = selector->value;
175            
176             bool i_found;
177 0           mycss_selectors_specificity_t work_spec = {0, 0, 0};
178            
179 0 0         for(size_t i = 0; i < list->entries_list_length; i++)
180             {
181 0           i_found = false;
182 0           modest_finder_node_combinator_undef(finder, base_node, NULL, list->entries_list[i].entry, &work_spec, modest_finder_callback_found_with_bool, &i_found);
183            
184 0 0         if(i_found == true)
185 0           return false;
186             else {
187 0           modest_finder_specificity_inc(list->entries_list[i].entry, &work_spec);
188             }
189             }
190            
191 0 0         if(work_spec.a)
192 0           spec->a++;
193 0 0         else if(work_spec.b)
194 0           spec->b++;
195 0 0         else if(work_spec.c)
196 0           spec->c++;
197            
198 0           return true;
199             }
200              
201 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_child_check_selectors(modest_finder_t* finder, bool* i_found, myhtml_tree_node_t* node, mycss_selectors_list_t *list, mycss_selectors_specificity_t* spec)
202             {
203 0 0         for(size_t i = 0; i < list->entries_list_length; i++)
204             {
205 0           *i_found = false;
206 0           modest_finder_node_combinator_undef(finder, node, NULL, list->entries_list[i].entry, spec, modest_finder_callback_found_with_bool, i_found);
207            
208 0 0         if(*i_found) {
209             /*
210             :nth-child(even of li, .item) has a specificity of (0,1,1)--like
211             a tag selector plus a pseudo-class--when matched against
  • ,
  • 212             and a specificity of (0,2,0)--like a class selector plus
    213             a pseudo-class--when matched against
  • .
  • 214             */
    215 0           spec->b++;
    216 0           modest_finder_specificity_inc(list->entries_list[i].entry, spec);
    217             }
    218             else
    219 0           return false;
    220             }
    221            
    222 0           return true;
    223             }
    224              
    225 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    226             {
    227 0 0         if(selector->value == NULL)
    228 0           return false;
    229            
    230 0           mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
    231            
    232 0           long node_pos = 0;
    233 0           myhtml_tree_node_t* node = base_node;
    234            
    235 0 0         if(anb->of) {
    236             bool i_found;
    237 0           mycss_selectors_specificity_t temp_spec = {0, 0, 0};
    238            
    239 0 0         if(spec->b)
    240 0           spec->b--;
    241            
    242 0 0         if(modest_finder_selector_sub_type_pseudo_class_function_nth_child_check_selectors(finder, &i_found, node, anb->of, spec) == false)
    243 0           return false;
    244            
    245 0           node_pos++;
    246 0           node = node->prev;
    247            
    248 0 0         while(node)
    249             {
    250 0 0         for(size_t i = 0; i < anb->of->entries_list_length; i++)
    251             {
    252 0           i_found = false;
    253 0           modest_finder_node_combinator_undef(finder, node, NULL, anb->of->entries_list[i].entry, &temp_spec, modest_finder_callback_found_with_bool, &i_found);
    254            
    255 0 0         if(i_found) {
    256 0           node_pos++;
    257 0           break;
    258             }
    259             }
    260            
    261 0           node = node->prev;
    262             }
    263             }
    264             else {
    265 0 0         while(node) {
    266 0 0         if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
        0          
    267 0           node_pos++;
    268            
    269 0           node = node->prev;
    270             }
    271             }
    272            
    273 0 0         if(anb->a == 0) {
    274 0 0         if(anb->b == node_pos)
    275 0           return true;
    276             }
    277             else {
    278 0           double n = (double)(node_pos - anb->b) / (double)anb->a;
    279            
    280 0 0         if(n >= 0.0f && (n - (double)((long)(n))) == 0.0f)
        0          
    281 0           return true;
    282             }
    283            
    284 0           return false;
    285             }
    286              
    287 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_column(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    288             {
    289 0           return false;
    290             }
    291              
    292 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    293             {
    294 0 0         if(selector->value == NULL)
    295 0           return false;
    296            
    297 0           mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
    298            
    299 0           long node_pos = 0;
    300 0           myhtml_tree_node_t* node = base_node;
    301            
    302 0 0         if(anb->of) {
    303             bool i_found;
    304 0           mycss_selectors_specificity_t temp_spec = {0, 0, 0};
    305            
    306 0 0         if(spec->b)
    307 0           spec->b--;
    308            
    309 0 0         if(modest_finder_selector_sub_type_pseudo_class_function_nth_child_check_selectors(finder, &i_found, node, anb->of, spec) == false)
    310 0           return false;
    311            
    312 0 0         while(node)
    313             {
    314 0 0         for(size_t i = 0; i < anb->of->entries_list_length; i++)
    315             {
    316 0           i_found = false;
    317 0           modest_finder_node_combinator_undef(finder, node, NULL, anb->of->entries_list[i].entry, &temp_spec, modest_finder_callback_found_with_bool, &i_found);
    318            
    319 0 0         if(i_found == true) {
    320 0           node_pos++;
    321 0           break;
    322             }
    323             }
    324            
    325 0           node = node->next;
    326             }
    327             }
    328             else {
    329 0 0         while(node) {
    330 0 0         if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
        0          
    331 0           node_pos++;
    332            
    333 0           node = node->next;
    334             }
    335             }
    336            
    337 0 0         if(anb->a == 0) {
    338 0 0         if(anb->b == node_pos)
    339 0           return true;
    340             }
    341             else {
    342 0           double n = (double)(node_pos - anb->b) / (double)anb->a;
    343            
    344 0 0         if(n >= 0.0f && (n - (double)((long)(n))) == 0.0f)
        0          
    345 0           return true;
    346             }
    347            
    348 0           return false;
    349             }
    350              
    351 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_column(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    352             {
    353 0           return false;
    354             }
    355              
    356 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    357             {
    358 0 0         if(selector->value == NULL)
    359 0           return false;
    360            
    361 0           mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
    362            
    363 0           long node_pos = 0;
    364 0           myhtml_tree_node_t* node = base_node;
    365            
    366 0 0         while(node) {
    367 0 0         if(node->tag_id == base_node->tag_id && node->ns == base_node->ns) {
        0          
    368 0           node_pos++;
    369             }
    370            
    371 0           node = node->next;
    372             }
    373            
    374 0 0         if(anb->a == 0) {
    375 0 0         if(anb->b != node_pos)
    376 0           return false;
    377             }
    378             else {
    379 0           double n = (double)(node_pos - anb->b) / (double)anb->a;
    380            
    381 0 0         if(n < 0.0f || (n - (double)((long)(n))) != 0.0f)
        0          
    382 0           return false;
    383             }
    384            
    385 0           return true;
    386             }
    387              
    388 0           bool modest_finder_selector_sub_type_pseudo_class_function_nth_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    389             {
    390 0 0         if(selector->value == NULL)
    391 0           return false;
    392            
    393 0           mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
    394            
    395 0           long node_pos = 0;
    396 0           myhtml_tree_node_t* node = base_node;
    397            
    398 0 0         while(node) {
    399 0 0         if(node->tag_id == base_node->tag_id && node->ns == base_node->ns) {
        0          
    400 0           node_pos++;
    401             }
    402            
    403 0           node = node->prev;
    404             }
    405            
    406 0 0         if(anb->a == 0) {
    407 0 0         if(anb->b != node_pos)
    408 0           return false;
    409             }
    410             else {
    411 0           double n = (double)(node_pos - anb->b) / (double)anb->a;
    412            
    413 0 0         if(n < 0.0f || (n - (double)((long)(n))) != 0.0f)
        0          
    414 0           return false;
    415             }
    416            
    417 0           return true;
    418             }
    419              
    420             /* classes */
    421 0           bool modest_finder_selector_sub_type_pseudo_class_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    422             {
    423 0           return false;
    424             }
    425              
    426 0           bool modest_finder_selector_sub_type_pseudo_class_active(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    427             {
    428 0 0         if (base_node->token)
    429 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "active", 6);
    430 0           return false;
    431             }
    432              
    433 0           bool modest_finder_selector_sub_type_pseudo_class_any_link(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    434             {
    435 0 0         if(base_node->tag_id == MyHTML_TAG_A ||
        0          
    436 0 0         base_node->tag_id == MyHTML_TAG_AREA ||
    437 0           base_node->tag_id == MyHTML_TAG_MAP)
    438             {
    439 0 0         if(base_node->token)
    440 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "href", 4);
    441             }
    442            
    443 0           return false;
    444             }
    445              
    446 0           bool modest_finder_selector_sub_type_pseudo_class_blank(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    447             {
    448 0           myhtml_tree_node_t *node = base_node->child;
    449            
    450 0 0         while(node) {
    451 0 0         if(node->tag_id != MyHTML_TAG__COMMENT) {
    452 0 0         if(node->tag_id != MyHTML_TAG__TEXT)
    453 0           return false;
    454            
    455 0 0         if(node->token) {
    456 0           const char *data = node->token->str.data;
    457 0           size_t len = node->token->str.length;
    458            
    459 0 0         for(size_t i = 0; i < len; i++) {
    460 0 0         if(data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r')
        0          
        0          
        0          
    461 0           return false;
    462             }
    463             }
    464             }
    465            
    466 0 0         if(node->child)
    467 0           node = node->child;
    468             else {
    469 0 0         while(node != base_node && node->next == NULL)
        0          
    470 0           node = node->parent;
    471            
    472 0 0         if(node == base_node)
    473 0           break;
    474            
    475 0           node = node->next;
    476             }
    477             }
    478            
    479 0           return true;
    480             }
    481              
    482 0           bool modest_finder_selector_sub_type_pseudo_class_checked(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    483             {
    484 0 0         if(base_node->tag_id == MyHTML_TAG_INPUT || base_node->tag_id == MyHTML_TAG_MENUITEM)
        0          
    485 0           {
    486 0           myhtml_token_attr_t* attr = base_node->token->attr_first;
    487            
    488 0 0         while (attr)
    489             {
    490 0 0         if(attr->key.length == 4) {
    491 0 0         if(mycore_strncasecmp("type", attr->key.data, 4) == 0)
    492             {
    493 0 0         if(attr->value.length == 8) {
    494 0 0         if(mycore_strncasecmp("checkbox", attr->value.data, 8) == 0) {
    495 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "checked", 7);
    496             }
    497             }
    498 0 0         else if(attr->value.length == 5) {
    499 0 0         if(mycore_strncasecmp("radio", attr->value.data, 5) == 0) {
    500 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "checked", 7);
    501             }
    502             }
    503            
    504 0           break;
    505             }
    506             }
    507            
    508 0           attr = attr->next;
    509             }
    510             }
    511 0 0         else if(base_node->tag_id == MyHTML_TAG_OPTION)
    512             {
    513 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "selected", 8);
    514             }
    515 0 0         else if(base_node->token && base_node->tag_id >= MyHTML_TAG_LAST_ENTRY)
        0          
    516             {
    517 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "checked", 7);
    518             }
    519 0           return false;
    520             }
    521              
    522 0           bool modest_finder_selector_sub_type_pseudo_class_current(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    523             {
    524 0           return false;
    525             }
    526              
    527 0           bool modest_finder_selector_sub_type_pseudo_class_default(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    528             {
    529 0           return false;
    530             }
    531              
    532 0           bool modest_finder_selector_sub_type_pseudo_class_disabled(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    533             {
    534 0 0         if(base_node->token == NULL)
    535 0           return false;
    536            
    537 0 0         if(base_node->tag_id == MyHTML_TAG_BUTTON ||
        0          
    538 0 0         base_node->tag_id == MyHTML_TAG_INPUT ||
    539 0 0         base_node->tag_id == MyHTML_TAG_SELECT ||
    540 0           base_node->tag_id == MyHTML_TAG_TEXTAREA)
    541             {
    542 0 0         if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
    543 0           return true;
    544            
    545 0           myhtml_tree_node_t* node = base_node->parent;
    546            
    547 0 0         while(node) {
    548             /* oh, see https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled */
    549 0 0         if(node->tag_id == MyHTML_TAG_FIELDSET) {
    550 0 0         if(node->child && node->child->tag_id != MyHTML_TAG_LEGEND) {
        0          
    551 0 0         if(node->token && modest_finder_match_attribute_only_key(node->token->attr_first, "disabled", 8))
        0          
    552 0           return true;
    553             }
    554             }
    555            
    556 0           node = node->parent;
    557             }
    558            
    559 0           return false;
    560             }
    561            
    562             /* see https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled */
    563 0 0         if(base_node->tag_id == MyHTML_TAG_OPTION) {
    564 0 0         if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
    565 0           return true;
    566            
    567 0           myhtml_tree_node_t* node = base_node->parent;
    568            
    569 0 0         while(node) {
    570 0 0         if(node->tag_id == MyHTML_TAG_OPTGROUP) {
    571 0 0         if(node->token)
    572 0           return modest_finder_match_attribute_only_key(node->token->attr_first, "disabled", 8);
    573            
    574 0           return false;
    575             }
    576            
    577 0           node = node->parent;
    578             }
    579            
    580 0           return false;
    581             }
    582            
    583 0 0         if(base_node->tag_id == MyHTML_TAG_OPTGROUP ||
        0          
    584 0           base_node->tag_id == MyHTML_TAG_MENUITEM) {
    585 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8);
    586             }
    587            
    588 0 0         if(base_node->tag_id == MyHTML_TAG_FIELDSET)
    589             {
    590 0 0         if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
    591 0           return true;
    592            
    593 0           myhtml_tree_node_t* node = base_node->parent;
    594            
    595 0 0         while(node) {
    596             /* oh, see https://html.spec.whatwg.org/multipage/forms.html#concept-fieldset-disabled */
    597 0 0         if(node->tag_id == MyHTML_TAG_FIELDSET) {
    598 0 0         if(node->child && node->child->tag_id != MyHTML_TAG_LEGEND) {
        0          
    599 0 0         if(node->token && modest_finder_match_attribute_only_key(node->token->attr_first, "disabled", 8))
        0          
    600 0           return true;
    601             }
    602             }
    603            
    604 0           node = node->parent;
    605             }
    606            
    607 0           return false;
    608             }
    609              
    610             /* custom HTML tag*/
    611 0 0         if(base_node->token && base_node->tag_id >= MyHTML_TAG_LAST_ENTRY)
        0          
    612             {
    613 0 0         if (modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
    614 0           return true;
    615 0           return false;
    616             }
    617            
    618 0           return false;
    619             }
    620              
    621 0           bool modest_finder_selector_sub_type_pseudo_class_drop(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    622             {
    623 0           return false;
    624             }
    625              
    626 0           bool modest_finder_selector_sub_type_pseudo_class_empty(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    627             {
    628 0           myhtml_tree_node_t *node = base_node->child;
    629            
    630 0 0         while(node) {
    631 0 0         if(node->tag_id != MyHTML_TAG__COMMENT)
    632 0           return false;
    633            
    634 0 0         if(node->child)
    635 0           node = node->child;
    636             else {
    637 0 0         while(node != base_node && node->next == NULL)
        0          
    638 0           node = node->parent;
    639            
    640 0 0         if(node == base_node)
    641 0           break;
    642            
    643 0           node = node->next;
    644             }
    645             }
    646            
    647 0           return true;
    648             }
    649              
    650 0           bool modest_finder_selector_sub_type_pseudo_class_enabled(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    651             {
    652 0           return !modest_finder_selector_sub_type_pseudo_class_disabled(finder, base_node, selector, spec);
    653             }
    654              
    655 0           bool modest_finder_selector_sub_type_pseudo_class_first_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    656             {
    657 0           myhtml_tree_node_t *node = base_node->prev;
    658            
    659 0 0         while(node) {
    660 0 0         if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
        0          
    661 0           return false;
    662            
    663 0           node = node->prev;
    664             }
    665            
    666 0           return true;
    667             }
    668              
    669 0           bool modest_finder_selector_sub_type_pseudo_class_first_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    670             {
    671 0           myhtml_tree_node_t *node = base_node->prev;
    672            
    673 0 0         while(node) {
    674 0 0         if(node->tag_id == base_node->tag_id && node->ns == base_node->ns)
        0          
    675 0           return false;
    676            
    677 0           node = node->prev;
    678             }
    679            
    680 0           return true;
    681             }
    682              
    683 0           bool modest_finder_selector_sub_type_pseudo_class_focus(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    684             {
    685 0 0         if (base_node->token)
    686 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "focus", 5);
    687 0           return false;
    688             }
    689              
    690 0           bool modest_finder_selector_sub_type_pseudo_class_future(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    691             {
    692 0           return false;
    693             }
    694              
    695 0           bool modest_finder_selector_sub_type_pseudo_class_hover(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    696             {
    697 0 0         if (base_node->token)
    698 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "hover", 5);
    699 0           return false;
    700             }
    701              
    702 0           bool modest_finder_selector_sub_type_pseudo_class_in_range(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    703             {
    704 0           return false;
    705             }
    706              
    707 0           bool modest_finder_selector_sub_type_pseudo_class_indeterminate(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    708             {
    709 0           return false;
    710             }
    711              
    712 0           bool modest_finder_selector_sub_type_pseudo_class_invalid(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    713             {
    714 0           return false;
    715             }
    716              
    717 0           bool modest_finder_selector_sub_type_pseudo_class_last_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    718             {
    719 0           myhtml_tree_node_t *node = base_node->next;
    720            
    721 0 0         while(node) {
    722 0 0         if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
        0          
    723 0           return false;
    724            
    725 0           node = node->next;
    726             }
    727            
    728 0           return true;
    729             }
    730              
    731 0           bool modest_finder_selector_sub_type_pseudo_class_last_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    732             {
    733 0           myhtml_tree_node_t *node = base_node->next;
    734            
    735 0 0         while(node) {
    736 0 0         if(node->tag_id == base_node->tag_id && node->ns == base_node->ns)
        0          
    737 0           return false;
    738            
    739 0           node = node->next;
    740             }
    741            
    742 0           return true;
    743             }
    744              
    745 0           bool modest_finder_selector_sub_type_pseudo_class_link(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    746             {
    747 0 0         if(base_node->tag_id == MyHTML_TAG_A ||
        0          
    748 0 0         base_node->tag_id == MyHTML_TAG_AREA ||
    749 0           base_node->tag_id == MyHTML_TAG_LINK)
    750             {
    751 0 0         if(base_node->token)
    752 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "href", 4);
    753             }
    754            
    755 0           return false;
    756             }
    757              
    758 0           bool modest_finder_selector_sub_type_pseudo_class_only_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    759             {
    760             return
    761 0           modest_finder_selector_sub_type_pseudo_class_first_child(finder, base_node, selector, spec) &&
    762 0           modest_finder_selector_sub_type_pseudo_class_last_child(finder, base_node, selector, spec);
    763             }
    764              
    765 0           bool modest_finder_selector_sub_type_pseudo_class_only_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    766             {
    767             return
    768 0           modest_finder_selector_sub_type_pseudo_class_first_of_type(finder, base_node, selector, spec) &&
    769 0           modest_finder_selector_sub_type_pseudo_class_last_of_type(finder, base_node, selector, spec);
    770             }
    771              
    772 0           bool modest_finder_selector_sub_type_pseudo_class_optional(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    773             {
    774 0 0         if(base_node->tag_id == MyHTML_TAG_INPUT ||
        0          
    775 0 0         base_node->tag_id == MyHTML_TAG_SELECT ||
    776 0           base_node->tag_id == MyHTML_TAG_TEXTAREA)
    777             {
    778 0 0         if(base_node->token)
    779 0           return !modest_finder_match_attribute_only_key(base_node->token->attr_first, "required", 8);
    780             else
    781 0           return true;
    782             }
    783            
    784 0           return false;
    785             }
    786              
    787 0           bool modest_finder_selector_sub_type_pseudo_class_out_of_range(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    788             {
    789 0           return false;
    790             }
    791              
    792 0           bool modest_finder_selector_sub_type_pseudo_class_past(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    793             {
    794 0           return false;
    795             }
    796              
    797 0           bool modest_finder_selector_sub_type_pseudo_class_placeholder_shown(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    798             {
    799 0 0         if(base_node->tag_id == MyHTML_TAG_INPUT ||
        0          
    800 0           base_node->tag_id == MyHTML_TAG_TEXTAREA)
    801             {
    802 0 0         if(base_node->token)
    803 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "placeholder", 11);
    804             }
    805            
    806 0           return false;
    807             }
    808              
    809 0           bool modest_finder_selector_sub_type_pseudo_class_read_only(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    810             {
    811 0 0         if(modest_finder_selector_sub_type_pseudo_class_read_write(finder, base_node, selector, spec))
    812 0           return false;
    813            
    814 0           return true;
    815             }
    816              
    817 0           bool modest_finder_selector_sub_type_pseudo_class_read_write(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    818             {
    819 0 0         if(base_node->tag_id == MyHTML_TAG_INPUT ||
        0          
    820 0           base_node->tag_id == MyHTML_TAG_TEXTAREA)
    821             {
    822 0 0         if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "readonly", 8))
    823 0           return false;
    824            
    825 0           return !modest_finder_selector_sub_type_pseudo_class_disabled(finder, base_node, selector, spec);
    826             }
    827            
    828 0           return false;
    829             }
    830              
    831 0           bool modest_finder_selector_sub_type_pseudo_class_required(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    832             {
    833 0 0         if(base_node->tag_id == MyHTML_TAG_INPUT ||
        0          
    834 0 0         base_node->tag_id == MyHTML_TAG_SELECT ||
    835 0           base_node->tag_id == MyHTML_TAG_TEXTAREA)
    836             {
    837 0 0         if(base_node->token)
    838 0           return modest_finder_match_attribute_only_key(base_node->token->attr_first, "required", 8);
    839             }
    840            
    841 0           return false;
    842             }
    843              
    844 0           bool modest_finder_selector_sub_type_pseudo_class_root(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    845             {
    846 0 0         if(base_node->tree && base_node->tree->node_html == base_node)
        0          
    847 0           return true;
    848            
    849 0           return false;
    850             }
    851              
    852 0           bool modest_finder_selector_sub_type_pseudo_class_scope(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    853             {
    854 0           return false;
    855             }
    856              
    857 0           bool modest_finder_selector_sub_type_pseudo_class_target(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    858             {
    859 0           return false;
    860             }
    861              
    862 0           bool modest_finder_selector_sub_type_pseudo_class_user_error(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    863             {
    864 0           return false;
    865             }
    866              
    867 0           bool modest_finder_selector_sub_type_pseudo_class_valid(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    868             {
    869 0           return false;
    870             }
    871              
    872 0           bool modest_finder_selector_sub_type_pseudo_class_visited(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec)
    873             {
    874 0           return false;
    875             }
    876              
    877