Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/lexborisov/Modest.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlexborisov <lex.borisov@gmail.com>2016-08-29 00:20:40 +0300
committerlexborisov <lex.borisov@gmail.com>2016-08-29 00:20:40 +0300
commit5afb4ca9b760d62be13b14796a802401d80c7ea4 (patch)
tree3910ba6eeae279e0bbf148c0ed4ce689a496ad46 /source/modest/finder
First commit
Diffstat (limited to 'source/modest/finder')
-rw-r--r--source/modest/finder/finder.c358
-rw-r--r--source/modest/finder/finder.h68
-rw-r--r--source/modest/finder/match.c287
-rw-r--r--source/modest/finder/match.h44
-rw-r--r--source/modest/finder/myosi.h51
-rw-r--r--source/modest/finder/pseudo_class.c832
-rw-r--r--source/modest/finder/pseudo_class.h92
-rw-r--r--source/modest/finder/resource.h125
-rw-r--r--source/modest/finder/type.c126
-rw-r--r--source/modest/finder/type.h54
10 files changed, 2037 insertions, 0 deletions
diff --git a/source/modest/finder/finder.c b/source/modest/finder/finder.c
new file mode 100644
index 0000000..c57807f
--- /dev/null
+++ b/source/modest/finder/finder.c
@@ -0,0 +1,358 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#include "modest/finder/finder.h"
+#include "modest/finder/resource.h"
+
+modest_finder_t * modest_finder_create(void)
+{
+ return (modest_finder_t*)myhtml_calloc(1, sizeof(modest_finder_t));
+}
+
+modest_status_t modest_finder_init(modest_finder_t* finder, myhtml_tree_t* myhtml_tree, mycss_stylesheet_t *stylesheet)
+{
+ finder->tree = myhtml_tree;
+ finder->stylesheet = stylesheet;
+
+ return MODEST_STATUS_OK;
+}
+
+void modest_finder_clean(modest_finder_t* finder)
+{
+ finder->callback_found = NULL;
+ finder->callback_found_ctx = NULL;
+}
+
+modest_finder_t * modest_finder_destroy(modest_finder_t* finder, bool self_destroy)
+{
+ if(finder == NULL)
+ return NULL;
+
+ if(self_destroy) {
+ myhtml_free(finder);
+ return NULL;
+ }
+
+ return finder;
+}
+
+modest_finder_t * modest_finder_create_simple(myhtml_tree_t* myhtml_tree, mycss_stylesheet_t *stylesheet)
+{
+ modest_finder_t *finder = modest_finder_create();
+
+ if(finder == NULL)
+ return NULL;
+
+ if(modest_finder_init(finder, myhtml_tree, stylesheet) != MyHTML_STATUS_OK)
+ return modest_finder_destroy(finder, true);
+
+ return finder;
+}
+
+void modest_finder_callback_found_set(modest_finder_t* finder, modest_finder_callback_f callback, void* callback_ctx)
+{
+ finder->callback_found = callback;
+ finder->callback_found_ctx = callback_ctx;
+}
+
+void modest_finder_callback_found_with_collection(modest_finder_t* finder, myhtml_tree_node_t* node, void* ctx)
+{
+ myhtml_collection_t* collection = (myhtml_collection_t*)finder->callback_found_ctx;
+
+ if(myhtml_collection_check_size(collection, 1, 1024) == MyHTML_STATUS_OK) {
+ collection->list[ collection->length ] = node;
+ collection->length++;
+ }
+}
+
+void modest_finder_callback_found_with_bool(modest_finder_t* finder, myhtml_tree_node_t* node, void* ctx)
+{
+ bool *is = (bool*)ctx;
+
+ if(*is == false)
+ *is = true;
+}
+
+modest_finder_t * modest_finder_by_stylesheet(myhtml_tree_t* myhtml_tree, mycss_stylesheet_t *stylesheet, myhtml_collection_t** collection, myhtml_tree_node_t* base_node, mycss_selectors_list_t* selector_list)
+{
+ if(collection == NULL)
+ return NULL;
+
+ modest_finder_t *finder = modest_finder_create();
+
+ if(finder == NULL)
+ return NULL;
+
+ modest_status_t status = modest_finder_init(finder, myhtml_tree, stylesheet);
+
+ if(status != MODEST_STATUS_OK) {
+ modest_finder_destroy(finder, true);
+ return NULL;
+ }
+
+ if(*collection == NULL) {
+ myhtml_status_t status;
+ *collection = myhtml_collection_create(4096, &status);
+
+ if(status) {
+ modest_finder_destroy(finder, true);
+ return NULL;
+ }
+ }
+ else
+ myhtml_collection_clean(*collection);
+
+ if(base_node == NULL) {
+ if(myhtml_tree->node_html)
+ base_node = myhtml_tree->node_html;
+ else
+ return finder;
+ }
+
+ if(selector_list == NULL) {
+ if(stylesheet->sel_list_first)
+ selector_list = stylesheet->sel_list_first;
+ else
+ return finder;
+ }
+
+ modest_finder_callback_found_set(finder, modest_finder_callback_found_with_collection, *collection);
+
+ while(selector_list) {
+ for(size_t i = 0; i < selector_list->selector_list_length; i++) {
+ modest_finder_node_combinator_begin(finder, base_node, selector_list->selector_list[i]);
+ }
+
+ selector_list = selector_list->next;
+ }
+
+ return finder;
+}
+
+myhtml_collection_t * modest_finder_by_selectors_list(modest_finder_t* finder, mycss_selectors_list_t *sel_list, myhtml_tree_node_t* base_node, myhtml_collection_t* collection)
+{
+ if(finder == NULL || sel_list == NULL || base_node == NULL)
+ return NULL;
+
+ if(collection == NULL) {
+ myhtml_status_t status;
+ collection = myhtml_collection_create(4096, &status);
+
+ if(status)
+ return NULL;
+ }
+
+ modest_finder_callback_found_set(finder, modest_finder_callback_found_with_collection, collection);
+
+ for(size_t i = 0; i < sel_list->selector_list_length; i++) {
+ modest_finder_node_combinator_begin(finder, base_node, sel_list->selector_list[i]);
+ }
+
+ return collection;
+}
+
+void modest_finder_begin(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ modest_finder_node_combinator_begin(finder, base_node, selector);
+}
+
+myhtml_tree_node_t * modest_finder_node_combinator_begin(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT &&
+ modest_finder_static_selector_type_map[selector->type](finder, node, selector))
+ {
+ if(selector->next == NULL) {
+ if(finder->callback_found)
+ finder->callback_found(finder, node, finder->callback_found_ctx);
+ }
+ else {
+ myhtml_tree_node_t *find_node = modest_finder_static_selector_combinator_map[selector->next->combinator](finder, node, selector->next);
+
+ if(find_node == NULL) {
+ while(node != base_node && node->next == NULL)
+ node = node->parent;
+
+ if(node == base_node)
+ break;
+
+ node = node->next;
+ continue;
+ }
+ }
+ }
+
+ if(node->child)
+ node = node->child;
+ else {
+ while(node != base_node && node->next == NULL)
+ node = node->parent;
+
+ if(node == base_node)
+ break;
+
+ node = node->next;
+ }
+ }
+
+ return NULL;
+}
+
+/* some */
+myhtml_tree_node_t * modest_finder_node_combinator_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(base_node->tag_id != MyHTML_TAG__TEXT && base_node->tag_id != MyHTML_TAG__COMMENT &&
+ modest_finder_static_selector_type_map[selector->type](finder, base_node, selector)) {
+ if(selector->next == NULL) {
+ if(finder->callback_found)
+ finder->callback_found(finder, base_node, finder->callback_found_ctx);
+ }
+ else {
+ modest_finder_static_selector_combinator_map[selector->next->combinator](finder, base_node, selector->next);
+ }
+ }
+
+ return base_node;
+}
+
+/* E F or E >> F */
+myhtml_tree_node_t * modest_finder_node_combinator_descendant(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node->child;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT &&
+ modest_finder_static_selector_type_map[selector->type](finder, node, selector))
+ {
+ if(selector->next == NULL) {
+ if(finder->callback_found)
+ finder->callback_found(finder, node, finder->callback_found_ctx);
+ }
+ else {
+ myhtml_tree_node_t *find_node = modest_finder_static_selector_combinator_map[selector->next->combinator](finder, node, selector->next);
+
+ if(find_node == NULL) {
+ while(node != base_node && node->next == NULL)
+ node = node->parent;
+
+ if(node == base_node)
+ break;
+
+ node = node->next;
+ continue;
+ }
+ }
+ }
+
+ if(node->child)
+ node = node->child;
+ else {
+ while(node != base_node && node->next == NULL)
+ node = node->parent;
+
+ if(node == base_node)
+ break;
+
+ node = node->next;
+ }
+ }
+
+ return NULL;
+}
+
+/* E > F */
+myhtml_tree_node_t * modest_finder_node_combinator_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node->child;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT &&
+ modest_finder_static_selector_type_map[selector->type](finder, node, selector))
+ {
+ if(selector->next == NULL) {
+ if(finder->callback_found)
+ finder->callback_found(finder, node, finder->callback_found_ctx);
+ }
+ else {
+ modest_finder_static_selector_combinator_map[selector->next->combinator](finder, node, selector->next);
+ }
+ }
+
+ node = node->next;
+ }
+
+ return base_node;
+}
+
+/* E + F */
+myhtml_tree_node_t * modest_finder_node_combinator_next_sibling(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node->next;
+
+ if(base_node->next) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT &&
+ modest_finder_static_selector_type_map[selector->type](finder, node, selector))
+ {
+ if(selector->next == NULL) {
+ if(finder->callback_found)
+ finder->callback_found(finder, node, finder->callback_found_ctx);
+ }
+ else {
+ modest_finder_static_selector_combinator_map[selector->next->combinator](finder, node, selector->next);
+ }
+ }
+ }
+
+ return base_node;
+}
+
+/* E ~ F */
+myhtml_tree_node_t * modest_finder_node_combinator_following_sibling(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node->next;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT &&
+ modest_finder_static_selector_type_map[selector->type](finder, node, selector))
+ {
+ if(selector->next == NULL) {
+ if(finder->callback_found)
+ finder->callback_found(finder, node, finder->callback_found_ctx);
+ }
+ else {
+ modest_finder_static_selector_combinator_map[selector->next->combinator](finder, node, selector->next);
+ }
+ }
+
+ node = node->next;
+ }
+
+ return base_node;
+}
+
+/* E || F */
+myhtml_tree_node_t * modest_finder_node_combinator_column(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return base_node;
+}
+
+
diff --git a/source/modest/finder/finder.h b/source/modest/finder/finder.h
new file mode 100644
index 0000000..b377393
--- /dev/null
+++ b/source/modest/finder/finder.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#ifndef MODEST_FINDER_FINDER_H
+#define MODEST_FINDER_FINDER_H
+#pragma once
+
+#include "modest/finder/myosi.h"
+#include "modest/finder/type.h"
+#include "mycss/selectors/myosi.h"
+#include "mycss/selectors/list.h"
+
+#ifdef __cplusplus
+//extern "C" {
+#endif
+
+typedef bool (*modest_finder_selector_type_f)(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+typedef myhtml_tree_node_t * (*modest_finder_selector_combinator_f)(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+
+/* init */
+modest_finder_t * modest_finder_create(void);
+modest_status_t modest_finder_init(modest_finder_t* finder, myhtml_tree_t* myhtml_tree, mycss_stylesheet_t *stylesheet);
+void modest_finder_clean(modest_finder_t* finder);
+modest_finder_t * modest_finder_destroy(modest_finder_t* finder, bool self_destroy);
+
+/* simple api */
+modest_finder_t * modest_finder_create_simple(myhtml_tree_t* myhtml_tree, mycss_stylesheet_t *stylesheet);
+
+/* callbacks */
+void modest_finder_callback_found_with_collection(modest_finder_t* finder, myhtml_tree_node_t* node, void* ctx);
+void modest_finder_callback_found_with_bool(modest_finder_t* finder, myhtml_tree_node_t* node, void* ctx);
+
+/* base api */
+void modest_finder_begin(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+modest_finder_t * modest_finder_by_stylesheet(myhtml_tree_t* myhtml_tree, mycss_stylesheet_t *stylesheet, myhtml_collection_t** collection, myhtml_tree_node_t* base_node, mycss_selectors_list_t* selector_list);
+myhtml_collection_t * modest_finder_by_selectors_list(modest_finder_t* finder, mycss_selectors_list_t *sel_list, myhtml_tree_node_t* base_node, myhtml_collection_t* collection);
+
+/* process */
+myhtml_tree_node_t * modest_finder_node_combinator_begin(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+myhtml_tree_node_t * modest_finder_node_combinator_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+myhtml_tree_node_t * modest_finder_node_combinator_descendant(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+myhtml_tree_node_t * modest_finder_node_combinator_child(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+myhtml_tree_node_t * modest_finder_node_combinator_next_sibling(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+myhtml_tree_node_t * modest_finder_node_combinator_following_sibling(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+myhtml_tree_node_t * modest_finder_node_combinator_column(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODEST_FINDER_FINDER_H */
diff --git a/source/modest/finder/match.c b/source/modest/finder/match.c
new file mode 100644
index 0000000..97d5f9d
--- /dev/null
+++ b/source/modest/finder/match.c
@@ -0,0 +1,287 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#include "modest/finder/match.h"
+
+bool modest_finder_match_attribute_only_key(myhtml_token_attr_t* attr, const char* key, size_t key_len)
+{
+ if(key == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ return true;
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+bool modest_finder_match_attribute_eq(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive)
+{
+ if(key == NULL || value == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ {
+ if(attr->value.length == value_len) {
+ if(case_sensitive) {
+ if(strncmp(value, attr->value.data, value_len) == 0) {
+ return true;
+ }
+ }
+ else {
+ if(myhtml_strncasecmp(value, attr->value.data, value_len) == 0) {
+ return true;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+bool modest_finder_match_attribute_ws(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive)
+{
+ if(key == NULL || value == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ {
+ size_t i = 0;
+
+ if(attr->value.length >= value_len) {
+ if(case_sensitive)
+ {
+ while(i < attr->value.length)
+ {
+ size_t end = i + value_len;
+
+ if(end > attr->value.length)
+ return false;
+
+ if(
+ (myhtml_strncmp(value, &attr->value.data[i], value_len) == 0) &&
+ (myhtml_utils_whithspace(attr->value.data[end], ==, ||) || end == attr->value.length))
+ {
+ return true;
+ }
+
+ i++;
+ }
+ }
+ else {
+ while(i < attr->value.length)
+ {
+ size_t end = i + value_len;
+
+ if(end > attr->value.length)
+ return false;
+
+ if(
+ (myhtml_strncasecmp(value, &attr->value.data[i], value_len) == 0) &&
+ (myhtml_utils_whithspace(attr->value.data[end], ==, ||) || end == attr->value.length))
+ {
+ return true;
+ }
+
+ i++;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+bool modest_finder_match_attribute_begin(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive)
+{
+ if(key == NULL || value == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ {
+ if(attr->value.length >= value_len) {
+ if(case_sensitive) {
+ if(myhtml_strncmp(value, attr->value.data, value_len) == 0)
+ return true;
+ }
+ else {
+ if(myhtml_strncasecmp(value, attr->value.data, value_len) == 0)
+ return true;
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+bool modest_finder_match_attribute_end(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive)
+{
+ if(key == NULL || value == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ {
+ if(attr->value.length >= value_len) {
+ if(case_sensitive) {
+ if(myhtml_strncmp(value, &attr->value.data[ (attr->value.length - value_len) ], value_len) == 0)
+ return true;
+ }
+ else {
+ if(myhtml_strncasecmp(value, &attr->value.data[ (attr->value.length - value_len) ], value_len) == 0)
+ return true;
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+bool modest_finder_match_attribute_sub(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive)
+{
+ if(key == NULL || value == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ {
+ if(attr->value.length >= value_len) {
+ size_t i = 0;
+
+ if(case_sensitive)
+ {
+ while ((i + value_len) <= attr->value.length)
+ {
+ if(myhtml_strncmp(value, &attr->value.data[i], value_len) == 0)
+ return true;
+
+ i++;
+ }
+ }
+ else {
+ while ((i + value_len) <= attr->value.length)
+ {
+ if(myhtml_strncasecmp(value, &attr->value.data[i], value_len) == 0)
+ return true;
+
+ i++;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+bool modest_finder_match_attribute_hsp(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive)
+{
+ if(key == NULL || value == NULL)
+ return false;
+
+ while (attr)
+ {
+ if(attr->key.length == key_len) {
+ if(myhtml_strncasecmp(key, attr->key.data, key_len) == 0)
+ {
+ if(attr->value.length == value_len) {
+ if(case_sensitive) {
+ if(myhtml_strncmp(value, attr->value.data, value_len) == 0)
+ return true;
+ }
+ else {
+ if(myhtml_strncasecmp(value, attr->value.data, value_len) == 0)
+ return true;
+ }
+ }
+ else if(attr->value.length > value_len) {
+ if(case_sensitive) {
+ if(myhtml_strncmp(value, attr->value.data, value_len) == 0) {
+ if(attr->value.data[value_len] == '-')
+ return true;
+ }
+ }
+ else {
+ if(myhtml_strncasecmp(value, attr->value.data, value_len) == 0) {
+ if(attr->value.data[value_len] == '-')
+ return true;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+
+ return false;
+}
+
+
diff --git a/source/modest/finder/match.h b/source/modest/finder/match.h
new file mode 100644
index 0000000..c7ee945
--- /dev/null
+++ b/source/modest/finder/match.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#ifndef MODEST_FINDER_MATCH_H
+#define MODEST_FINDER_MATCH_H
+#pragma once
+
+#include "myhtml/myosi.h"
+#include "myhtml/tree.h"
+
+#ifdef __cplusplus
+//extern "C" {
+#endif
+
+bool modest_finder_match_attribute_only_key(myhtml_token_attr_t* attr, const char* key, size_t key_len);
+bool modest_finder_match_attribute_eq(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+bool modest_finder_match_attribute_ws(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+bool modest_finder_match_attribute_begin(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+bool modest_finder_match_attribute_end(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+bool modest_finder_match_attribute_sub(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+bool modest_finder_match_attribute_hsp(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODEST_FINDER_MATCH_H */
diff --git a/source/modest/finder/myosi.h b/source/modest/finder/myosi.h
new file mode 100644
index 0000000..682e452
--- /dev/null
+++ b/source/modest/finder/myosi.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#ifndef MODEST_FINDER_MYOSI_H
+#define MODEST_FINDER_MYOSI_H
+#pragma once
+
+#include "modest/myosi.h"
+#include "myhtml/myosi.h"
+#include "mycss/myosi.h"
+
+#ifdef __cplusplus
+//extern "C" {
+#endif
+
+struct modest_finder typedef modest_finder_t;
+
+typedef void (*modest_finder_callback_f)(modest_finder_t* finder, myhtml_tree_node_t* node, void* ctx);
+typedef bool (*modest_finder_match_f)(myhtml_token_attr_t* attr, const char* key, size_t key_len, const char* value, size_t value_len, bool case_sensitive);
+
+struct modest_finder {
+ myhtml_tree_t* tree;
+ mycss_stylesheet_t* stylesheet;
+
+ modest_finder_callback_f callback_found;
+ void* callback_found_ctx;
+};
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODEST_FINDER_MYOSI_H */
diff --git a/source/modest/finder/pseudo_class.c b/source/modest/finder/pseudo_class.c
new file mode 100644
index 0000000..9cd9653
--- /dev/null
+++ b/source/modest/finder/pseudo_class.c
@@ -0,0 +1,832 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#include "modest/finder/pseudo_class.h"
+#include "modest/finder/resource.h"
+
+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)
+{
+ return false;
+}
+
+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_list_t *list = selector->value;
+
+ modest_finder_callback_f current_callback_found = finder->callback_found;
+ void *current_ctx = finder->callback_found_ctx;
+
+ bool i_found;
+
+ finder->callback_found = modest_finder_callback_found_with_bool;
+ finder->callback_found_ctx = &i_found;
+
+ for(size_t i = 0; i < list->selector_list_length; i++)
+ {
+ i_found = false;
+ modest_finder_node_combinator_undef(finder, base_node, list->selector_list[i]);
+
+ if(i_found == true) {
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return true;
+ }
+ }
+
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return false;
+}
+
+/* after create render */
+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)
+{
+ return false;
+}
+
+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)
+{
+ return false;
+}
+
+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_list_t *list = selector->value;
+
+ modest_finder_callback_f current_callback_found = finder->callback_found;
+ void *current_ctx = finder->callback_found_ctx;
+
+ bool i_found;
+
+ finder->callback_found = modest_finder_callback_found_with_bool;
+ finder->callback_found_ctx = &i_found;
+
+ for(size_t i = 0; i < list->selector_list_length; i++)
+ {
+ i_found = false;
+
+ mycss_selectors_entry_t *sel_entry = list->selector_list[i];
+
+ if(sel_entry->combinator == MyCSS_SELECTORS_COMBINATOR_UNDEF)
+ modest_finder_node_combinator_descendant(finder, base_node, sel_entry);
+ else
+ modest_finder_static_selector_combinator_map[sel_entry->combinator](finder, base_node, sel_entry);
+
+ if(i_found == true) {
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return true;
+ }
+ }
+
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_function_lang(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+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_list_t *list = selector->value;
+
+ modest_finder_callback_f current_callback_found = finder->callback_found;
+ void *current_ctx = finder->callback_found_ctx;
+
+ bool i_found;
+
+ finder->callback_found = modest_finder_callback_found_with_bool;
+ finder->callback_found_ctx = &i_found;
+
+ for(size_t i = 0; i < list->selector_list_length; i++)
+ {
+ i_found = false;
+ modest_finder_node_combinator_undef(finder, base_node, list->selector_list[i]);
+
+ if(i_found == true) {
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return true;
+ }
+ }
+
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return false;
+}
+
+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_list_t *list = selector->value;
+
+ modest_finder_callback_f current_callback_found = finder->callback_found;
+ void *current_ctx = finder->callback_found_ctx;
+
+ bool i_found;
+
+ finder->callback_found = modest_finder_callback_found_with_bool;
+ finder->callback_found_ctx = &i_found;
+
+ for(size_t i = 0; i < list->selector_list_length; i++)
+ {
+ i_found = false;
+ modest_finder_node_combinator_undef(finder, base_node, list->selector_list[i]);
+
+ if(i_found == true) {
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return false;
+ }
+ }
+
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return true;
+}
+
+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)
+{
+ if(selector->value == NULL)
+ return NULL;
+
+ mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
+
+ long node_pos = 0;
+ myhtml_tree_node_t* node = base_node;
+
+ if(anb->of) {
+ modest_finder_callback_f current_callback_found = finder->callback_found;
+ void *current_ctx = finder->callback_found_ctx;
+
+ bool i_found;
+
+ finder->callback_found = modest_finder_callback_found_with_bool;
+ finder->callback_found_ctx = &i_found;
+
+ mycss_selectors_list_t *list = anb->of;
+
+ while(node)
+ {
+ for(size_t i = 0; i < list->selector_list_length; i++)
+ {
+ i_found = false;
+ modest_finder_node_combinator_undef(finder, node, list->selector_list[i]);
+
+ if(i_found == true) {
+ node_pos++;
+ break;
+ }
+ else if(node_pos == 0) {
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return false;
+ }
+ }
+
+ node = node->prev;
+ }
+
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ if(node_pos == 0)
+ return false;
+ }
+ else {
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
+ node_pos++;
+
+ node = node->prev;
+ }
+ }
+
+ if(anb->a == 0) {
+ if(anb->b == node_pos)
+ return true;
+ }
+ else {
+ double n = (double)(node_pos - anb->b) / (double)anb->a;
+
+ if(n >= 0.0f && (n - (double)((long)(n))) == 0.0f)
+ return true;
+ }
+
+ return false;
+}
+
+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)
+{
+ return false;
+}
+
+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)
+{
+ if(selector->value == NULL)
+ return NULL;
+
+ mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
+
+ long node_pos = 0;
+ myhtml_tree_node_t* node = base_node;
+
+ if(anb->of) {
+ modest_finder_callback_f current_callback_found = finder->callback_found;
+ void *current_ctx = finder->callback_found_ctx;
+
+ bool i_found;
+
+ finder->callback_found = modest_finder_callback_found_with_bool;
+ finder->callback_found_ctx = &i_found;
+
+ mycss_selectors_list_t *list = anb->of;
+
+ while(node)
+ {
+ for(size_t i = 0; i < list->selector_list_length; i++)
+ {
+ i_found = false;
+ modest_finder_node_combinator_undef(finder, node, list->selector_list[i]);
+
+ if(i_found == true) {
+ node_pos++;
+ break;
+ }
+ else if(node_pos == 0) {
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ return false;
+ }
+ }
+
+ node = node->next;
+ }
+
+ finder->callback_found = current_callback_found;
+ finder->callback_found_ctx = current_ctx;
+
+ if(node_pos == 0)
+ return false;
+ }
+ else {
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
+ node_pos++;
+
+ node = node->next;
+ }
+ }
+
+ if(anb->a == 0) {
+ if(anb->b == node_pos)
+ return true;
+ }
+ else {
+ double n = (double)(node_pos - anb->b) / (double)anb->a;
+
+ if(n >= 0.0f && (n - (double)((long)(n))) == 0.0f)
+ return true;
+ }
+
+ return false;
+}
+
+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)
+{
+ return false;
+}
+
+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)
+{
+ if(selector->value == NULL)
+ return NULL;
+
+ mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
+
+ long node_pos = 0;
+ myhtml_tree_node_t* node = base_node;
+
+ while(node) {
+ if(node->tag_id == base_node->tag_id && node->ns == base_node->ns) {
+ node_pos++;
+ }
+
+ node = node->next;
+ }
+
+ if(anb->a == 0) {
+ if(anb->b != node_pos)
+ return false;
+ }
+ else {
+ double n = (double)(node_pos - anb->b) / (double)anb->a;
+
+ if(n < 0.0f || (n - (double)((long)(n))) != 0.0f)
+ return false;
+ }
+
+ return true;
+}
+
+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)
+{
+ if(selector->value == NULL)
+ return NULL;
+
+ mycss_an_plus_b_entry_t *anb = mycss_selector_value_an_plus_b(selector->value);
+
+ long node_pos = 0;
+ myhtml_tree_node_t* node = base_node;
+
+ while(node) {
+ if(node->tag_id == base_node->tag_id && node->ns == base_node->ns) {
+ node_pos++;
+ }
+
+ node = node->prev;
+ }
+
+ if(anb->a == 0) {
+ if(anb->b != node_pos)
+ return false;
+ }
+ else {
+ double n = (double)(node_pos - anb->b) / (double)anb->a;
+
+ if(n < 0.0f || (n - (double)((long)(n))) != 0.0f)
+ return false;
+ }
+
+ return true;
+}
+
+/* classes */
+bool modest_finder_selector_sub_type_pseudo_class_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_active(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+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)
+{
+ if(base_node->tag_id == MyHTML_TAG_A ||
+ base_node->tag_id == MyHTML_TAG_AREA ||
+ base_node->tag_id == MyHTML_TAG_MAP)
+ {
+ if(base_node->token)
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "href", 4);
+ }
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_blank(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node->child;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__COMMENT) {
+ if(node->tag_id != MyHTML_TAG__TEXT)
+ return false;
+
+ if(node->token) {
+ const char *data = node->token->str.data;
+ size_t len = node->token->str.length;
+
+ for(size_t i = 0; i < len; i++) {
+ if(data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r')
+ return false;
+ }
+ }
+ }
+
+ if(node->child)
+ node = node->child;
+ else {
+ while(node != base_node && node->next == NULL)
+ node = node->parent;
+
+ if(node == base_node)
+ break;
+
+ node = node->next;
+ }
+ }
+
+ return true;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_checked(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(base_node->tag_id == MyHTML_TAG_INPUT || base_node->tag_id == MyHTML_TAG_MENUITEM)
+ {
+ myhtml_token_attr_t* attr = base_node->token->attr_first;
+
+ while (attr)
+ {
+ if(attr->key.length == 4) {
+ if(myhtml_strncasecmp("type", attr->key.data, 4) == 0)
+ {
+ if(attr->value.length == 8) {
+ if(myhtml_strncasecmp("checkbox", attr->value.data, 8) == 0) {
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "checked", 7);
+ }
+ }
+ else if(attr->value.length == 5) {
+ if(myhtml_strncasecmp("radio", attr->value.data, 5) == 0) {
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "checked", 7);
+ }
+ }
+
+ break;
+ }
+ }
+
+ attr = attr->next;
+ }
+ }
+ else if(base_node->tag_id == MyHTML_TAG_OPTION) {
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "selected", 8);
+ }
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_current(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_default(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_disabled(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(base_node->token == NULL)
+ return false;
+
+ if(base_node->tag_id == MyHTML_TAG_BUTTON ||
+ base_node->tag_id == MyHTML_TAG_INPUT ||
+ base_node->tag_id == MyHTML_TAG_SELECT ||
+ base_node->tag_id == MyHTML_TAG_TEXTAREA)
+ {
+ if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
+ return true;
+
+ myhtml_tree_node_t* node = base_node->parent;
+
+ while(node) {
+ /* oh, see https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled */
+ if(node->tag_id == MyHTML_TAG_FIELDSET) {
+ if(node->child && node->child->tag_id != MyHTML_TAG_LEGEND) {
+ if(node->token && modest_finder_match_attribute_only_key(node->token->attr_first, "disabled", 8))
+ return true;
+ }
+ }
+
+ node = node->parent;
+ }
+
+ return false;
+ }
+
+ /* see https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled */
+ if(base_node->tag_id == MyHTML_TAG_OPTION) {
+ if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
+ return true;
+
+ myhtml_tree_node_t* node = base_node->parent;
+
+ while(node) {
+ if(node->tag_id == MyHTML_TAG_OPTGROUP) {
+ if(node->token)
+ return modest_finder_match_attribute_only_key(node->token->attr_first, "disabled", 8);
+
+ return false;
+ }
+
+ node = node->parent;
+ }
+
+ return false;
+ }
+
+ if(base_node->tag_id == MyHTML_TAG_OPTGROUP ||
+ base_node->tag_id == MyHTML_TAG_MENUITEM) {
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8);
+ }
+
+ if(base_node->tag_id == MyHTML_TAG_FIELDSET)
+ {
+ if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "disabled", 8))
+ return true;
+
+ myhtml_tree_node_t* node = base_node->parent;
+
+ while(node) {
+ /* oh, see https://html.spec.whatwg.org/multipage/forms.html#concept-fieldset-disabled */
+ if(node->tag_id == MyHTML_TAG_FIELDSET) {
+ if(node->child && node->child->tag_id != MyHTML_TAG_LEGEND) {
+ if(node->token && modest_finder_match_attribute_only_key(node->token->attr_first, "disabled", 8))
+ return true;
+ }
+ }
+
+ node = node->parent;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_drop(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_empty(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ myhtml_tree_node_t *node = base_node->child;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__COMMENT)
+ return false;
+
+ if(node->child)
+ node = node->child;
+ else {
+ while(node != base_node && node->next == NULL)
+ node = node->parent;
+
+ if(node == base_node)
+ break;
+
+ node = node->next;
+ }
+ }
+
+ return true;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_enabled(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return ~modest_finder_selector_sub_type_pseudo_class_disabled(finder, base_node, selector);
+}
+
+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)
+{
+ myhtml_tree_node_t *node = base_node->prev;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
+ return false;
+
+ node = node->prev;
+ }
+
+ return true;
+}
+
+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)
+{
+ myhtml_tree_node_t *node = base_node->prev;
+
+ while(node) {
+ if(node->tag_id == base_node->tag_id && node->ns == base_node->ns)
+ return false;
+
+ node = node->prev;
+ }
+
+ return true;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_focus(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_future(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_hover(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+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)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_indeterminate(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_invalid(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+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)
+{
+ myhtml_tree_node_t *node = base_node->next;
+
+ while(node) {
+ if(node->tag_id != MyHTML_TAG__TEXT && node->tag_id != MyHTML_TAG__COMMENT)
+ return false;
+
+ node = node->next;
+ }
+
+ return true;
+}
+
+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)
+{
+ myhtml_tree_node_t *node = base_node->next;
+
+ while(node) {
+ if(node->tag_id == base_node->tag_id && node->ns == base_node->ns)
+ return false;
+
+ node = node->next;
+ }
+
+ return true;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_link(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(base_node->tag_id == MyHTML_TAG_A ||
+ base_node->tag_id == MyHTML_TAG_AREA ||
+ base_node->tag_id == MyHTML_TAG_LINK)
+ {
+ if(base_node->token)
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "href", 4);
+ }
+
+ return false;
+}
+
+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)
+{
+ return
+ modest_finder_selector_sub_type_pseudo_class_first_child(finder, base_node, selector) &&
+ modest_finder_selector_sub_type_pseudo_class_last_child(finder, base_node, selector);
+}
+
+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)
+{
+ return
+ modest_finder_selector_sub_type_pseudo_class_first_of_type(finder, base_node, selector) &&
+ modest_finder_selector_sub_type_pseudo_class_last_of_type(finder, base_node, selector);
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_optional(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(base_node->tag_id == MyHTML_TAG_INPUT ||
+ base_node->tag_id == MyHTML_TAG_SELECT ||
+ base_node->tag_id == MyHTML_TAG_TEXTAREA)
+ {
+ if(base_node->token)
+ return ~modest_finder_match_attribute_only_key(base_node->token->attr_first, "required", 8);
+ else
+ return true;
+ }
+
+ return false;
+}
+
+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)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_past(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+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)
+{
+ if(base_node->tag_id == MyHTML_TAG_INPUT ||
+ base_node->tag_id == MyHTML_TAG_TEXTAREA)
+ {
+ if(base_node->token)
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "placeholder", 11);
+ }
+
+ return false;
+}
+
+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)
+{
+ if(modest_finder_selector_sub_type_pseudo_class_read_write(finder, base_node, selector))
+ return false;
+
+ return true;
+}
+
+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)
+{
+ if(base_node->tag_id == MyHTML_TAG_INPUT ||
+ base_node->tag_id == MyHTML_TAG_TEXTAREA)
+ {
+ if(modest_finder_match_attribute_only_key(base_node->token->attr_first, "readonly", 8))
+ return false;
+
+ return ~modest_finder_selector_sub_type_pseudo_class_disabled(finder, base_node, selector);
+ }
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_required(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(base_node->tag_id == MyHTML_TAG_INPUT ||
+ base_node->tag_id == MyHTML_TAG_SELECT ||
+ base_node->tag_id == MyHTML_TAG_TEXTAREA)
+ {
+ if(base_node->token)
+ return modest_finder_match_attribute_only_key(base_node->token->attr_first, "required", 8);
+ }
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_root(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ if(finder->tree->node_html == base_node)
+ return true;
+
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_scope(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_target(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+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)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_valid(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_sub_type_pseudo_class_visited(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+
diff --git a/source/modest/finder/pseudo_class.h b/source/modest/finder/pseudo_class.h
new file mode 100644
index 0000000..23e736b
--- /dev/null
+++ b/source/modest/finder/pseudo_class.h
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#ifndef MODEST_FINDER_PSEUDO_CLASS_H
+#define MODEST_FINDER_PSEUDO_CLASS_H
+#pragma once
+
+#include "modest/finder/myosi.h"
+#include "mycss/selectors/myosi.h"
+#include "mycss/selectors/value.h"
+#include "modest/finder/finder.h"
+
+#ifdef __cplusplus
+//extern "C" {
+#endif
+
+bool modest_finder_selector_sub_type_pseudo_class_function_undef(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_current(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_dir(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_drop(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_has(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_lang(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_matches(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_not(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_nth_child(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_nth_column(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_child(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_column(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_function_nth_of_type(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+
+/* classes */
+bool modest_finder_selector_sub_type_pseudo_class_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_active(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_blank(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_checked(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_current(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_default(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_disabled(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_drop(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_empty(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_enabled(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_focus(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_future(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_hover(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_indeterminate(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_invalid(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_link(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_optional(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_past(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+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);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_required(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_root(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_scope(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_target(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+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);
+bool modest_finder_selector_sub_type_pseudo_class_valid(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_sub_type_pseudo_class_visited(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODEST_FINDER_PSEUDO_CLASS_H */
diff --git a/source/modest/finder/resource.h b/source/modest/finder/resource.h
new file mode 100644
index 0000000..839914a
--- /dev/null
+++ b/source/modest/finder/resource.h
@@ -0,0 +1,125 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#ifndef MODEST_FINDER_RESOURCE_H
+#define MODEST_FINDER_RESOURCE_H
+#pragma once
+
+/* see enum mycss_selectors_type (mycss_selectors_type_t) on mycss/selectors/myosi.h */
+static const modest_finder_selector_type_f modest_finder_static_selector_type_map[MyCSS_SELECTORS_TYPE_LAST_ENTRY] =
+{
+ modest_finder_selector_type_undef, /* MyCSS_SELECTORS_TYPE_UNDEF */
+ modest_finder_selector_type_element, /* MyCSS_SELECTORS_TYPE_ELEMENT */
+ modest_finder_selector_type_id, /* MyCSS_SELECTORS_TYPE_ID */
+ modest_finder_selector_type_class, /* MyCSS_SELECTORS_TYPE_CLASS */
+ modest_finder_selector_type_attribute, /* MyCSS_SELECTORS_TYPE_ATTRIBUTE */
+ modest_finder_selector_type_pseudo_class_function, /* MyCSS_SELECTORS_TYPE_PSEUDO_CLASS_FUNCTION */
+ modest_finder_selector_type_pseudo_class, /* MyCSS_SELECTORS_TYPE_PSEUDO_CLASS */
+ modest_finder_selector_type_pseudo_element_function, /* MyCSS_SELECTORS_TYPE_PSEUDO_ELEMENT_FUNCTION */
+ modest_finder_selector_type_pseudo_element /* MyCSS_SELECTORS_TYPE_PSEUDO_ELEMENT */
+};
+
+/* see enum mycss_selectors_sub_type (mycss_selectors_sub_type_t) on mycss/selectors/myosi.h */
+static const modest_finder_selector_type_f modest_finder_static_selector_sub_type_pseudo_class_function_map[MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY] =
+{
+ modest_finder_selector_sub_type_pseudo_class_function_undef, /* UNDEF */
+ modest_finder_selector_sub_type_pseudo_class_function_undef, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNKNOWN */
+ modest_finder_selector_sub_type_pseudo_class_function_current, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT */
+ modest_finder_selector_sub_type_pseudo_class_function_dir, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR */
+ modest_finder_selector_sub_type_pseudo_class_function_drop, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP */
+ modest_finder_selector_sub_type_pseudo_class_function_has, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_HAS */
+ modest_finder_selector_sub_type_pseudo_class_function_lang, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LANG */
+ modest_finder_selector_sub_type_pseudo_class_function_matches, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_MATCHES */
+ modest_finder_selector_sub_type_pseudo_class_function_not, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NOT */
+ modest_finder_selector_sub_type_pseudo_class_function_nth_child, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_CHILD */
+ modest_finder_selector_sub_type_pseudo_class_function_nth_column, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_COLUMN */
+ modest_finder_selector_sub_type_pseudo_class_function_nth_last_child, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD */
+ modest_finder_selector_sub_type_pseudo_class_function_nth_last_column, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN */
+ modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE */
+ modest_finder_selector_sub_type_pseudo_class_function_nth_of_type /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE */
+
+};
+
+/* see enum mycss_selectors_sub_type (mycss_selectors_sub_type_t) on mycss/selectors/myosi.h */
+static const modest_finder_selector_type_f modest_finder_static_selector_sub_type_pseudo_class_map[MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_LAST_ENTRY] =
+{
+ modest_finder_selector_sub_type_pseudo_class_undef, /* UNDEF */
+ modest_finder_selector_sub_type_pseudo_class_undef, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_UNKNOWN */
+ modest_finder_selector_sub_type_pseudo_class_active, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_ACTIVE */
+ modest_finder_selector_sub_type_pseudo_class_any_link, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_ANY_LINK */
+ modest_finder_selector_sub_type_pseudo_class_blank, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_BLANK */
+ modest_finder_selector_sub_type_pseudo_class_checked, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_CHECKED */
+ modest_finder_selector_sub_type_pseudo_class_current, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_CURRENT */
+ modest_finder_selector_sub_type_pseudo_class_default, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_DEFAULT */
+ modest_finder_selector_sub_type_pseudo_class_disabled, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_DISABLED */
+ modest_finder_selector_sub_type_pseudo_class_drop, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_DROP */
+ modest_finder_selector_sub_type_pseudo_class_empty, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_EMPTY */
+ modest_finder_selector_sub_type_pseudo_class_enabled, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_ENABLED */
+ modest_finder_selector_sub_type_pseudo_class_first_child, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FIRST_CHILD */
+ modest_finder_selector_sub_type_pseudo_class_first_of_type, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FIRST_OF_TYPE */
+ modest_finder_selector_sub_type_pseudo_class_focus, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FOCUS */
+ modest_finder_selector_sub_type_pseudo_class_future, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUTURE */
+ modest_finder_selector_sub_type_pseudo_class_hover, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_HOVER */
+ modest_finder_selector_sub_type_pseudo_class_in_range, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_IN_RANGE */
+ modest_finder_selector_sub_type_pseudo_class_indeterminate, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_INDETERMINATE */
+ modest_finder_selector_sub_type_pseudo_class_invalid, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_INVALID */
+ modest_finder_selector_sub_type_pseudo_class_last_child, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_LAST_CHILD */
+ modest_finder_selector_sub_type_pseudo_class_last_of_type, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_LAST_OF_TYPE */
+ modest_finder_selector_sub_type_pseudo_class_link, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_LINK */
+ modest_finder_selector_sub_type_pseudo_class_only_child, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_ONLY_CHILD */
+ modest_finder_selector_sub_type_pseudo_class_only_of_type, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_ONLY_OF_TYPE */
+ modest_finder_selector_sub_type_pseudo_class_optional, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_OPTIONAL */
+ modest_finder_selector_sub_type_pseudo_class_out_of_range, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_OUT_OF_RANGE */
+ modest_finder_selector_sub_type_pseudo_class_past, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_PAST */
+ modest_finder_selector_sub_type_pseudo_class_placeholder_shown, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_PLACEHOLDER_SHOWN */
+ modest_finder_selector_sub_type_pseudo_class_read_only, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_READ_ONLY */
+ modest_finder_selector_sub_type_pseudo_class_read_write, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_READ_WRITE */
+ modest_finder_selector_sub_type_pseudo_class_required, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_REQUIRED */
+ modest_finder_selector_sub_type_pseudo_class_root, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_ROOT */
+ modest_finder_selector_sub_type_pseudo_class_scope, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_SCOPE */
+ modest_finder_selector_sub_type_pseudo_class_target, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_TARGET */
+ modest_finder_selector_sub_type_pseudo_class_user_error, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_USER_ERROR */
+ modest_finder_selector_sub_type_pseudo_class_valid, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_VALID */
+ modest_finder_selector_sub_type_pseudo_class_visited /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_VISITED */
+};
+
+/* see enum mycss_selectors_combinator (mycss_selectors_combinator_t) on mycss/selectors/myosi.h */
+static const modest_finder_selector_combinator_f modest_finder_static_selector_combinator_map[MyCSS_SELECTORS_COMBINATOR_LAST_ENTRY] =
+{
+ modest_finder_node_combinator_undef, /* MyCSS_SELECTORS_COMBINATOR_UNDEF */
+ modest_finder_node_combinator_descendant, /* MyCSS_SELECTORS_COMBINATOR_DESCENDANT */
+ modest_finder_node_combinator_child, /* MyCSS_SELECTORS_COMBINATOR_CHILD */
+ modest_finder_node_combinator_next_sibling, /* MyCSS_SELECTORS_COMBINATOR_NEXT_SIBLING */
+ modest_finder_node_combinator_following_sibling, /* MyCSS_SELECTORS_COMBINATOR_FOLLOWING_SIBLING */
+ modest_finder_node_combinator_column /* MyCSS_SELECTORS_COMBINATOR_COLUMN */
+};
+
+/* see enum mycss_selectors_match (mycss_selectors_match_t) on mycss/selectors/myosi.h */
+static const modest_finder_match_f modest_finder_static_selector_match_map[MyCSS_SELECTORS_MATCH_LAST_ENTRY] =
+{
+ modest_finder_match_attribute_eq, /* MyCSS_SELECTORS_MATCH_EQUAL */
+ modest_finder_match_attribute_ws, /* MyCSS_SELECTORS_MATCH_INCLUDE */
+ modest_finder_match_attribute_hsp, /* MyCSS_SELECTORS_MATCH_DASH */
+ modest_finder_match_attribute_begin, /* MyCSS_SELECTORS_MATCH_PREFIX */
+ modest_finder_match_attribute_end, /* MyCSS_SELECTORS_MATCH_SUFFIX */
+ modest_finder_match_attribute_sub /* MyCSS_SELECTORS_MATCH_SUBSTRING */
+};
+
+#endif /* MODEST_FINDER_RESOURCE_H */
diff --git a/source/modest/finder/type.c b/source/modest/finder/type.c
new file mode 100644
index 0000000..ad25b9f
--- /dev/null
+++ b/source/modest/finder/type.c
@@ -0,0 +1,126 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#include "modest/finder/type.h"
+#include "modest/finder/resource.h"
+
+bool modest_finder_selector_type_undef(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_type_element(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ /* namespace */
+ if(selector->ns_entry) {
+ if(selector->ns_entry->ns_id != MyHTML_NAMESPACE_ANY && selector->ns_entry->ns_id != node->ns)
+ return false;
+ }
+
+ /* tag match */
+ myhtml_string_t *str = selector->key;
+ if(str->length == 1 && *str->data == '*')
+ return true;
+
+ myhtml_tag_id_t tag_id = myhtml_tag_id_by_name(finder->tree, str->data, str->length);
+
+ if(tag_id == node->tag_id)
+ return true;
+
+ return false;
+}
+
+bool modest_finder_selector_type_id(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ if(node->token == NULL)
+ return false;
+
+ return modest_finder_match_attribute_eq(node->token->attr_first,
+ "id", 2,
+ selector->key->data, selector->key->length,
+ (finder->tree->compat_mode != MyHTML_TREE_COMPAT_MODE_QUIRKS));
+}
+
+bool modest_finder_selector_type_class(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ if(node->token == NULL)
+ return false;
+
+ return modest_finder_match_attribute_ws(node->token->attr_first,
+ "class", 5,
+ selector->key->data, selector->key->length,
+ (finder->tree->compat_mode != MyHTML_TREE_COMPAT_MODE_QUIRKS));
+}
+
+bool modest_finder_selector_type_attribute(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ /* namespace */
+ if(selector->ns_entry) {
+ if(selector->ns_entry->ns_id != MyHTML_NAMESPACE_ANY && selector->ns_entry->ns_id != node->ns)
+ return false;
+ }
+
+ if(node->token == NULL)
+ return false;
+
+ mycss_selectors_object_attribute_t *sel_attr = mycss_selector_value_attribute(selector->value);
+
+ if(sel_attr) {
+ if(sel_attr->match < MyCSS_SELECTORS_MATCH_LAST_ENTRY)
+ return modest_finder_static_selector_match_map[sel_attr->match](node->token->attr_first,
+ selector->key->data, selector->key->length,
+ sel_attr->value->data, sel_attr->value->length,
+ (sel_attr->mod & MyCSS_SELECTORS_MOD_I));
+ }
+ else {
+ return modest_finder_match_attribute_only_key(node->token->attr_first,
+ selector->key->data, selector->key->length);
+ }
+
+ return false;
+}
+
+bool modest_finder_selector_type_pseudo_class_function(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ if(selector->sub_type < MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY)
+ return modest_finder_static_selector_sub_type_pseudo_class_function_map[selector->sub_type](finder, node, selector);
+
+ return false;
+}
+
+bool modest_finder_selector_type_pseudo_class(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ if(selector->sub_type < MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_LAST_ENTRY)
+ return modest_finder_static_selector_sub_type_pseudo_class_map[selector->sub_type](finder, node, selector);
+
+ return false;
+}
+
+bool modest_finder_selector_type_pseudo_element_function(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+bool modest_finder_selector_type_pseudo_element(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector)
+{
+ return false;
+}
+
+
diff --git a/source/modest/finder/type.h b/source/modest/finder/type.h
new file mode 100644
index 0000000..7070dea
--- /dev/null
+++ b/source/modest/finder/type.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2016 Alexander Borisov
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Author: lex.borisov@gmail.com (Alexander Borisov)
+*/
+
+#ifndef MODEST_FINDER_TYPE_H
+#define MODEST_FINDER_TYPE_H
+#pragma once
+
+#include "modest/finder/myosi.h"
+#include "modest/finder/finder.h"
+#include "modest/finder/pseudo_class.h"
+#include "modest/finder/match.h"
+#include "myhtml/tree.h"
+#include "myhtml/utils.h"
+#include "mycss/selectors/myosi.h"
+#include "mycss/selectors/list.h"
+#include "mycss/selectors/value.h"
+
+#ifdef __cplusplus
+//extern "C" {
+#endif
+
+bool modest_finder_selector_type_undef(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_element(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_id(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_class(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_attribute(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_pseudo_class_function(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_pseudo_class(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_pseudo_element_function(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+bool modest_finder_selector_type_pseudo_element(modest_finder_t* finder, myhtml_tree_node_t* node, mycss_selectors_entry_t* selector);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MODEST_FINDER_TYPE_H */