gboolean watch_tree_check (WatchTree *tree, const gchar *path) { WatchTree *root_node = (WatchTree *) tree; WatchTree *node; StringRef ref; /* '/' */ node = root_node; ref.str = (gchar *) path; ref.len = 1; if (node->watchers) return TRUE; while (ref.str[ref.len]) { ref.str += ref.len; ref.len = strcspn (ref.str, "/"); if (ref.str[ref.len] == '/') ref.len++; node = tree_node_get_child (node, &ref, FALSE); if (!node) break; if (node->watchers) return TRUE; } return FALSE; }
void watch_tree_add (WatchTree *tree, const gchar *path, gpointer data) { WatchTree *root_node = (WatchTree *) tree; WatchTree *node; StringRef ref; /* '/' */ node = root_node; ref.str = (gchar *) path; ref.len = 1; while (ref.str[ref.len]) { ref.str += ref.len; ref.len = strcspn (ref.str, "/"); if (ref.str[ref.len] == '/') ref.len++; node = tree_node_get_child (node, &ref, TRUE); } node->watchers = g_slist_prepend (node->watchers, data); }
/** * Informs the hotlist that some content has been visited. Internal procedure. * * \param content the content visited * \param node the node to update siblings and children of */ static void hotlist_visited_internal(hlcache_handle *content, struct node *node) { struct node *child; const char *text; const char *url; if (content == NULL || hlcache_handle_get_url(content) == NULL || hotlist_tree == NULL) return; /* TODO: do this with a nsurl instead */ url = nsurl_access(hlcache_handle_get_url(content)); for (; node; node = tree_node_get_next(node)) { if (!tree_node_is_folder(node)) { text = tree_url_node_get_url(node); if (strcmp(text, url) == 0) { tree_update_URL_node(hotlist_tree, node, url, NULL); } } child = tree_node_get_child(node); if (child != NULL) { hotlist_visited_internal(content, child); } } }
WatchTreeRemoveResult watch_tree_remove (WatchTree *tree, const gchar *path, gpointer data) { WatchTree *root_node = (WatchTree *) tree; WatchTreeRemoveResult result; GSList *backtrack; WatchTree *node; StringRef ref; /* '/' */ node = root_node; ref.str = (gchar *) path; ref.len = 1; backtrack = NULL; while (ref.str[ref.len]) { GSList *tmp = g_newa (GSList, 1); tmp->data = node; tmp->next = backtrack; backtrack = tmp; ref.str += ref.len; ref.len = strcspn (ref.str, "/"); if (ref.str[ref.len] == '/') ref.len++; node = tree_node_get_child (node, &ref, FALSE); g_assert (node != NULL); } node->watchers = g_slist_remove (node->watchers, data); if (node->watchers != NULL) /* nothing changes */ result = WATCH_TREE_REMOVE_RESULT_NONE; else if (node->children && g_hash_table_size (node->children)) /* there are still child watches, so we have to check */ result = WATCH_TREE_REMOVE_RESULT_SOME; else /* no watchers and no child watches -- remove all */ result = WATCH_TREE_REMOVE_RESULT_ALL; while (node->watchers == NULL && (!node->children || g_hash_table_size (node->children)) == 0 && backtrack) { WatchTree *parent = backtrack->data; g_hash_table_remove (parent->children, node); backtrack = backtrack->next; node = parent; } return result; }
/** * Add a directory to the HTML tree for saving. * * \param directory hotlist directory to add * \param node node to add ul to * \return true on success, false on memory exhaustion */ static bool tree_url_save_directory(struct node *directory, xmlNode *node) { struct node *child; xmlNode *ul, *h4; const char *text; ul = xmlNewChild(node, NULL, (const xmlChar *)"ul", NULL); if (ul == NULL) return false; if (tree_node_is_default(directory) == true) xmlSetProp(ul, (const xmlChar *) "id", (const xmlChar *) "default"); for (child = tree_node_get_child(directory); child; child = tree_node_get_next(child)) { if (!tree_node_is_folder(child)) { /* entry */ if (!tree_url_save_entry(child, ul)) return false; } else { /* directory */ /* invalid HTML */ text = tree_url_node_get_title(child); if (text == NULL) return false; h4 = xmlNewTextChild(ul, NULL, (const xmlChar *) "h4", (const xmlChar *) text); if (h4 == NULL) return false; if (!tree_url_save_directory(child, ul)) return false; } } return true; }
GSList * watch_tree_collect (WatchTree *tree, const gchar *path) { WatchTree *root_node = (WatchTree *) tree; GSList *list = NULL; WatchTree *node; StringRef ref; /* '/' */ node = root_node; ref.str = (gchar *) path; ref.len = 1; if (node->watchers) list = g_slist_prepend (list, node); while (ref.str[ref.len]) { ref.str += ref.len; ref.len = strcspn (ref.str, "/"); if (ref.str[ref.len] == '/') ref.len++; node = tree_node_get_child (node, &ref, FALSE); if (!node) break; if (node->watchers) list = g_slist_prepend (list, node); } /* if this was a directory operation, it impacts all children as well */ if (node && ref.str[ref.len - 1] == '/') watch_tree_collect_children (node, &list); return list; }