Author: vince
Date: Sun Sep 26 16:01:57 2010
New Revision: 10848
URL:
http://source.netsurf-browser.org?rev=10848&view=rev
Log:
review comments for url tree
Modified:
branches/jmb/treeview-redux/desktop/tree_url_node.c
Modified: branches/jmb/treeview-redux/desktop/tree_url_node.c
URL:
http://source.netsurf-browser.org/branches/jmb/treeview-redux/desktop/tre...
==============================================================================
--- branches/jmb/treeview-redux/desktop/tree_url_node.c (original)
+++ branches/jmb/treeview-redux/desktop/tree_url_node.c Sun Sep 26 16:01:57 2010
@@ -16,11 +16,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-
+
/** \file
* Creation of URL nodes with use of trees (implementation)
*/
-
+
#include <assert.h>
#include <ctype.h>
@@ -38,14 +38,19 @@
#include "utils/url.h"
#include "utils/utils.h"
-#define TREE_ELEMENT_URL 0x01
-#define TREE_ELEMENT_LAST_VISIT 0x02
-#define TREE_ELEMENT_VISITS 0x03
-#define TREE_ELEMENT_THUMBNAIL 0x04
+/** Flags for each type of url tree node. */
+enum tree_element_url {
+ TREE_ELEMENT_URL = 0x01,
+ TREE_ELEMENT_LAST_VISIT = 0x02,
+ TREE_ELEMENT_VISITS = 0x03,
+ TREE_ELEMENT_THUMBNAIL = 0x04,
+};
#define MAX_ICON_NAME_LEN 256
static bool initialised = false;
+
+static hlcache_handle *folder_icon;
struct icon_entry {
content_type type;
@@ -86,34 +91,23 @@
{CONTENT_SVG, NULL},
#endif
{CONTENT_UNKNOWN, NULL},
-
+
/* this serves as a sentinel */
{CONTENT_HTML, NULL}
};
-static hlcache_handle *folder_icon;
-
-static void tree_url_load_directory(xmlNode *ul, struct tree *tree,
- struct node *directory, tree_node_user_callback callback,
- void *callback_data);
-static void tree_url_load_entry(xmlNode *li, struct tree *tree,
- struct node *directory,
- tree_node_user_callback callback, void *callback_data);
-static xmlNode *tree_url_find_xml_element(xmlNode *node, const char *name);
-static bool tree_url_save_directory(struct node *directory, xmlNode *node);
-static bool tree_url_save_entry(struct node *entry, xmlNode *node);
void tree_url_node_init(void)
{
struct icon_entry *entry;
char icon_name[MAX_ICON_NAME_LEN];
-
+
if (initialised || option_tree_icons_dir == NULL)
return;
initialised = true;
-
+
folder_icon = tree_load_icon(tree_directory_icon_name);
-
+
entry = icon_table;
do {
@@ -122,7 +116,7 @@
++entry;
} while (entry->type != CONTENT_HTML);
-
+
}
@@ -137,12 +131,12 @@
*/
struct node *tree_create_URL_node(struct tree *tree, struct node *parent,
const char *url, const char *title,
- tree_node_user_callback user_callback, void *callback_data)
+ tree_node_user_callback user_callback, void *callback_data)
{
struct node *node;
struct node_element *element;
char *text_cp, *squashed;
-
+
squashed = squash_whitespace(title ? title : url);
text_cp = strdup(squashed);
if (text_cp == NULL) {
@@ -152,7 +146,7 @@
}
free(squashed);
node = tree_create_leaf_node(tree, parent, text_cp, true, false,
- false);
+ false);
if (node == NULL) {
free(text_cp);
return NULL;
@@ -160,17 +154,17 @@
if (user_callback != NULL)
tree_set_node_user_callback(node, user_callback,
- callback_data);
-
+ callback_data);
+
tree_create_node_element(node, NODE_ELEMENT_BITMAP,
- TREE_ELEMENT_THUMBNAIL, false);
+ TREE_ELEMENT_THUMBNAIL, false);
tree_create_node_element(node, NODE_ELEMENT_TEXT, TREE_ELEMENT_VISITS,
- false);
+ false);
tree_create_node_element(node, NODE_ELEMENT_TEXT,
- TREE_ELEMENT_LAST_VISIT, false);
+ TREE_ELEMENT_LAST_VISIT, false);
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
- TREE_ELEMENT_URL, true);
- if (element) {
+ TREE_ELEMENT_URL, true);
+ if (element != NULL) {
text_cp = strdup(url);
if (text_cp == NULL) {
tree_delete_node(tree, node, false);
@@ -198,41 +192,77 @@
*/
struct node *tree_create_URL_node_shared(struct tree *tree, struct node *parent,
const char *url, const struct url_data *data,
- tree_node_user_callback user_callback, void *callback_data)
- {
+ tree_node_user_callback user_callback, void *callback_data)
+{
struct node *node;
struct node_element *element;
const char *title;
assert(url && data);
-
- if (data->title)
+
+ if (data->title != NULL) {
title = data->title;
- else
+ } else {
title = url;
+ }
+
node = tree_create_leaf_node(tree, parent, title, false, false, false);
- if (!node)
+ if (node == NULL)
return NULL;
-
- if (user_callback != NULL)
+
+ if (user_callback != NULL) {
tree_set_node_user_callback(node, user_callback,
- callback_data);
-
+ callback_data);
+ }
+
tree_create_node_element(node, NODE_ELEMENT_BITMAP,
- TREE_ELEMENT_THUMBNAIL, false);
+ TREE_ELEMENT_THUMBNAIL, false);
tree_create_node_element(node, NODE_ELEMENT_TEXT, TREE_ELEMENT_VISITS,
- false);
+ false);
tree_create_node_element(node, NODE_ELEMENT_TEXT,
- TREE_ELEMENT_LAST_VISIT, false);
+ TREE_ELEMENT_LAST_VISIT, false);
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
- TREE_ELEMENT_URL, false);
- if (element)
+ TREE_ELEMENT_URL, false);
+ if (element != NULL) {
tree_update_node_element(tree, element, url, NULL);
+ }
tree_update_URL_node(tree, node, url, data, true);
return node;
}
+/**
+ * Helper to update the text of a node if it has changed.
+ *
+ * \param element The node element to update.
+ * \param text The text to update the element with. The ownership of
+ * this string is taken by this function and must not be
+ * referred to after the function exits.
+ */
+static bool update_element_text(struct tree *tree,
+ struct node_element *element, char *text)
+{
+ const char *node_text; /* existing node text */
+
+ if (text == NULL)
+ return false;
+
+ if (element == NULL) {
+ free(text);
+ return false;
+ }
+
+ node_text = tree_node_element_get_text(element);
+
+ if ((node_text == NULL) || (strcmp(node_text, text) != 0)) {
+ tree_update_node_element(tree, element, text, NULL);
+ } else {
+ /* text does not need changing, free it */
+ free(text);
+ }
+ return true;
+}
+
/**
* Updates the node details for a URL node.
*
@@ -242,17 +272,16 @@
const char *url, const struct url_data *data, bool shared)
{
struct node_element *element;
- char buffer[256];
struct bitmap *bitmap = NULL;
struct icon_entry *entry;
char *text_cp;
-
- assert(node);
+
+ assert(node != NULL);
element = tree_node_find_element(node, TREE_ELEMENT_URL, NULL);
if (element == NULL)
return;
-
+
if (data != NULL) {
if (data->title == NULL)
urldb_set_url_title(url, url);
@@ -261,10 +290,10 @@
return;
element = tree_node_find_element(node, TREE_ELEMENT_TITLE,
- NULL);
+ NULL);
if (shared)
tree_update_node_element(tree, element, data->title,
- NULL);
+ NULL);
else {
text_cp = strdup(data->title);
if (text_cp == NULL) {
@@ -290,41 +319,28 @@
++entry;
} while (entry->type != CONTENT_HTML);
- element = tree_node_find_element(node, TREE_ELEMENT_LAST_VISIT,
- element);
- if (element != NULL) {
- snprintf(buffer, 256, messages_get("TreeLast"),
- (data->last_visit > 0) ?
- ctime((time_t *)&data->last_visit) :
- messages_get("TreeUnknown"));
- if (data->last_visit > 0)
- buffer[strlen(buffer) - 1] = '\0';
- text_cp = strdup(buffer);
- if (text_cp == NULL) {
- LOG(("malloc failed"));
- warn_user("NoMemory", 0);
- return;
- }
- tree_update_node_element(tree, element, text_cp, NULL);
- }
-
+ /* update last visit text */
+ element = tree_node_find_element(node, TREE_ELEMENT_LAST_VISIT, element);
+ update_element_text(tree,
+ element,
+ messages_get_buff("TreeLast",
+ (data->last_visit > 0) ?
+ ctime((time_t *)&data->last_visit) :
+ messages_get("TreeUnknown")));
+
+
+ /* update number of visits text */
element = tree_node_find_element(node, TREE_ELEMENT_VISITS, element);
- if (element != NULL) {
- snprintf(buffer, 256, messages_get("TreeVisits"),
- data->visits);
- text_cp = strdup(buffer);
- if (text_cp == NULL) {
- LOG(("malloc failed"));
- warn_user("NoMemory", 0);
- return;
- }
- tree_update_node_element(tree, element, text_cp, NULL);
- }
-
+ update_element_text(tree,
+ element,
+ messages_get_buff("TreeVisits", data->visits));
+
+
+ /* update thumbnail */
element = tree_node_find_element(node, TREE_ELEMENT_THUMBNAIL, element);
if (element != NULL) {
bitmap = urldb_get_thumbnail(url);
-
+
if (bitmap != NULL) {
tree_update_node_element(tree, element, NULL, bitmap);
}
@@ -366,7 +382,7 @@
}
node_callback_resp tree_url_node_callback(void *user_data,
- struct node_msg_data *msg_data)
+ struct node_msg_data *msg_data)
{
struct tree *tree;
struct node_element *element;
@@ -375,100 +391,277 @@
char *norm_text, *escaped_text;
const struct url_data *data;
- /* TODO: memory leaks on non-shared folder deletion */
+ /** @todo memory leaks on non-shared folder deletion. */
switch (msg_data->msg) {
- case NODE_DELETE_ELEMENT_TXT:
- switch (msg_data->flag) {
- /* only history is using non-editable url
- * elements so only history deletion will run
- * this code
- */
- case TREE_ELEMENT_URL:
- /* reset URL characteristics */
- urldb_reset_url_visit_data(
- msg_data->data.text);
- return NODE_CALLBACK_HANDLED;
- case TREE_ELEMENT_TITLE:
- return NODE_CALLBACK_HANDLED;
- }
- break;
- case NODE_DELETE_ELEMENT_IMG:
- if (msg_data->flag == TREE_ELEMENT_THUMBNAIL ||
- msg_data->flag == TREE_ELEMENT_TITLE)
- return NODE_CALLBACK_HANDLED;
- break;
- case NODE_LAUNCH:
- element = tree_node_find_element(msg_data->node,
- TREE_ELEMENT_URL, NULL);
- if (element != NULL) {
- text = tree_node_element_get_text(element);
- browser_window_create(text, NULL, 0,
- true, false);
- return NODE_CALLBACK_HANDLED;
- }
- break;
- case NODE_ELEMENT_EDIT_FINISHING:
-
- text = msg_data->data.text;
-
- if (msg_data->flag == TREE_ELEMENT_URL) {
- res = url_escape(text, 0, false, NULL,
- &escaped_text);
- if (res == URL_FUNC_OK)
- res = url_normalize(escaped_text,
- &norm_text);
- if (res != URL_FUNC_OK) {
- if (res == URL_FUNC_FAILED) {
- warn_user("NoURLError", 0);
- return NODE_CALLBACK_CONTINUE;
- }
- else {
- warn_user("NoMemory", 0);
- return NODE_CALLBACK_REJECT;
- }
-
+ case NODE_DELETE_ELEMENT_TXT:
+ switch (msg_data->flag) {
+ /* only history is using non-editable url
+ * elements so only history deletion will run
+ * this code
+ */
+ case TREE_ELEMENT_URL:
+ /* reset URL characteristics */
+ urldb_reset_url_visit_data(
+ msg_data->data.text);
+ return NODE_CALLBACK_HANDLED;
+ case TREE_ELEMENT_TITLE:
+ return NODE_CALLBACK_HANDLED;
+ }
+ break;
+ case NODE_DELETE_ELEMENT_IMG:
+ if (msg_data->flag == TREE_ELEMENT_THUMBNAIL ||
+ msg_data->flag == TREE_ELEMENT_TITLE)
+ return NODE_CALLBACK_HANDLED;
+ break;
+ case NODE_LAUNCH:
+ element = tree_node_find_element(msg_data->node,
+ TREE_ELEMENT_URL, NULL);
+ if (element != NULL) {
+ text = tree_node_element_get_text(element);
+ browser_window_create(text, NULL, 0,
+ true, false);
+ return NODE_CALLBACK_HANDLED;
+ }
+ break;
+ case NODE_ELEMENT_EDIT_FINISHING:
+
+ text = msg_data->data.text;
+
+ if (msg_data->flag == TREE_ELEMENT_URL) {
+ res = url_escape(text, 0, false, NULL,
+ &escaped_text);
+ if (res == URL_FUNC_OK)
+ res = url_normalize(escaped_text,
+ &norm_text);
+ if (res != URL_FUNC_OK) {
+ if (res == URL_FUNC_FAILED) {
+ warn_user("NoURLError", 0);
+ return NODE_CALLBACK_CONTINUE;
}
- msg_data->data.text = norm_text;
-
- data = urldb_get_url_data(norm_text);
- if (data == NULL) {
- urldb_add_url(norm_text);
- urldb_set_url_persistence(norm_text,
- true);
- data = urldb_get_url_data(norm_text);
- if (data == NULL)
- return NODE_CALLBACK_REJECT;
- }
- tree = user_data;
- tree_update_URL_node(tree, msg_data->node,
- norm_text, NULL, false);
- }
- else if (msg_data->flag == TREE_ELEMENT_TITLE) {
- while (isspace(*text))
- text++;
- norm_text = strdup(text);
- if (norm_text == NULL) {
- LOG(("malloc failed"));
+ else {
warn_user("NoMemory", 0);
return NODE_CALLBACK_REJECT;
}
- /* don't allow zero length entry text, return
- false */
- if (norm_text[0] == '\0') {
- warn_user("NoNameError", 0);
- msg_data->data.text = NULL;
- return NODE_CALLBACK_CONTINUE;
- }
- msg_data->data.text = norm_text;
+
}
-
- return NODE_CALLBACK_HANDLED;
- default:
- break;
+ msg_data->data.text = norm_text;
+
+ data = urldb_get_url_data(norm_text);
+ if (data == NULL) {
+ urldb_add_url(norm_text);
+ urldb_set_url_persistence(norm_text,
+ true);
+ data = urldb_get_url_data(norm_text);
+ if (data == NULL)
+ return NODE_CALLBACK_REJECT;
+ }
+ tree = user_data;
+ tree_update_URL_node(tree, msg_data->node,
+ norm_text, NULL, false);
+ }
+ else if (msg_data->flag == TREE_ELEMENT_TITLE) {
+ while (isspace(*text))
+ text++;
+ norm_text = strdup(text);
+ if (norm_text == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return NODE_CALLBACK_REJECT;
+ }
+ /* don't allow zero length entry text, return
+ false */
+ if (norm_text[0] == '\0') {
+ warn_user("NoNameError", 0);
+ msg_data->data.text = NULL;
+ return NODE_CALLBACK_CONTINUE;
+ }
+ msg_data->data.text = norm_text;
+ }
+
+ return NODE_CALLBACK_HANDLED;
+ default:
+ break;
}
return NODE_CALLBACK_NOT_HANDLED;
}
+/**
+ * Search the children of an xmlNode for an element.
+ *
+ * \param node xmlNode to search children of, or 0
+ * \param name name of element to find
+ * \return first child of node which is an element and matches name, or
+ * 0 if not found or parameter node is 0
+ */
+static xmlNode *tree_url_find_xml_element(xmlNode *node, const char *name)
+{
+ xmlNode *n;
+ if (!node)
+ return 0;
+ for (n = node->children;
+ n && !(n->type == XML_ELEMENT_NODE &&
+ strcmp((const char *) n->name, name) == 0);
+ n = n->next)
+ ;
+ return n;
+}
+
+/**
+ * Parse an entry represented as a li.
+ *
+ * \param li xmlNode for parsed li
+ * \param directory directory to add this entry to
+ */
+static void tree_url_load_entry(xmlNode *li, struct tree *tree,
+ struct node *directory, tree_node_user_callback callback,
+ void *callback_data)
+{
+ char *url = NULL, *url1 = NULL;
+ char *title = NULL;
+ struct node *entry;
+ xmlNode *n;
+ const struct url_data *data;
+ url_func_result res;
+
+ for (n = li->children; n; n = n->next) {
+ /* The li must contain an "a" element */
+ if (n->type == XML_ELEMENT_NODE &&
+ strcmp((const char *) n->name, "a") == 0) {
+ url1 = (char *) xmlGetProp(n, (const xmlChar *) "href");
+ title = (char *) xmlNodeGetContent(n);
+ }
+ }
+
+ if (!url1 || !title) {
+ warn_user("TreeLoadError", "(Missing <a> in <li> or "
+ "memory exhausted.)");
+ return;
+ }
+
+ /* We're loading external input.
+ * This may be garbage, so attempt to normalise
+ */
+ res = url_normalize(url1, &url);
+ if (res != URL_FUNC_OK) {
+ LOG(("Failed normalising '%s'", url1));
+
+ if (res == URL_FUNC_NOMEM)
+ warn_user("NoMemory", NULL);
+
+ xmlFree(url1);
+ xmlFree(title);
+
+ return;
+ }
+
+ /* No longer need this */
+ xmlFree(url1);
+
+ data = urldb_get_url_data(url);
+ if (data == NULL) {
+ /* No entry in database, so add one */
+ urldb_add_url(url);
+ /* now attempt to get url data */
+ data = urldb_get_url_data(url);
+ }
+ if (data == NULL) {
+ xmlFree(title);
+ free(url);
+
+ return;
+ }
+
+ /* Make this URL persistent */
+ urldb_set_url_persistence(url, true);
+
+ if (data->title == NULL)
+ urldb_set_url_title(url, title);
+
+ entry = tree_create_URL_node(tree, directory, url, title,
+ callback, callback_data);
+
+ if (entry == NULL) {
+ /** \todo why isn't this fatal? */
+ warn_user("NoMemory", 0);
+ }
+ else
+ tree_update_URL_node(tree, entry, url, data, false);
+
+
+ xmlFree(title);
+ free(url);
+}
+
+/**
+ * Parse a directory represented as a ul.
+ *
+ * \param ul xmlNode for parsed ul
+ * \param directory directory to add this directory to
+ */
+static void tree_url_load_directory(xmlNode *ul, struct tree *tree,
+ struct node *directory, tree_node_user_callback callback,
+ void *callback_data)
+{
+ char *title;
+ struct node *dir;
+ xmlNode *n;
+
+ assert(ul);
+ assert(directory);
+
+ for (n = ul->children; n; n = n->next) {
+ /* The ul may contain entries as a li, or directories as
+ * an h4 followed by a ul. Non-element nodes may be present
+ * (eg. text, comments), and are ignored. */
+
+ if (n->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (strcmp((const char *) n->name, "li") == 0) {
+ /* entry */
+ tree_url_load_entry(n, tree, directory, callback,
+ callback_data);
+
+ } else if (strcmp((const char *) n->name, "h4") == 0) {
+ /* directory */
+ title = (char *) xmlNodeGetContent(n);
+ if (!title) {
+ warn_user("TreeLoadError", "(Empty <h4> "
+ "or memory exhausted.)");
+ return;
+ }
+
+ for (n = n->next;
+ n && n->type != XML_ELEMENT_NODE;
+ n = n->next)
+ ;
+ if (!n || strcmp((const char *) n->name, "ul") != 0) {
+ /* next element isn't expected ul */
+ free(title);
+ warn_user("TreeLoadError", "(Expected "
+ "<ul> not present.)");
+ return;
+ }
+
+ dir = tree_create_folder_node(tree, directory, title,
+ true, false, false);
+ if (dir == NULL) {
+ free(title);
+ return;
+ }
+
+ if (callback != NULL)
+ tree_set_node_user_callback(dir, callback,
+ callback_data);
+
+ if (folder_icon != NULL)
+ tree_set_node_icon(tree, dir, folder_icon);
+
+ tree_url_load_directory(n, tree, dir, callback,
+ callback_data);
+ }
+ }
+}
/**
* Loads an url tree from a specified file.
@@ -478,7 +671,7 @@
* \return the file represented as a tree, or NULL on failure
*/
bool tree_urlfile_load(const char *filename, struct tree *tree,
- tree_node_user_callback callback, void *callback_data)
+ tree_node_user_callback callback, void *callback_data)
{
xmlDoc *doc;
xmlNode *html, *body, *ul;
@@ -486,15 +679,15 @@
FILE *fp = NULL;
if (filename == NULL) {
- return false;
+ return false;
}
fp = fopen(filename, "r");
if (fp == NULL) {
- return false;
+ return false;
}
fclose(fp);
-
+
doc = htmlParseFile(filename, "iso-8859-1");
if (doc == NULL) {
warn_user("TreeLoadError", messages_get("ParsingFail"));
@@ -507,7 +700,7 @@
if (ul == NULL) {
xmlFreeDoc(doc);
warn_user("TreeLoadError",
- "(<html>...<body>...<ul> not found.)");
+ "(<html>...<body>...<ul> not found.)");
return false;
}
@@ -519,186 +712,91 @@
return true;
}
-
-/**
- * Parse a directory represented as a ul.
- *
- * \param ul xmlNode for parsed ul
- * \param directory directory to add this directory to
- */
-void tree_url_load_directory(xmlNode *ul, struct tree *tree,
- struct node *directory, tree_node_user_callback callback,
- void *callback_data)
-{
- char *title;
- struct node *dir;
- xmlNode *n;
-
- assert(ul);
- assert(directory);
-
- for (n = ul->children; n; n = n->next) {
- /* The ul may contain entries as a li, or directories as
- * an h4 followed by a ul. Non-element nodes may be present
- * (eg. text, comments), and are ignored. */
-
- if (n->type != XML_ELEMENT_NODE)
- continue;
-
- if (strcmp((const char *) n->name, "li") == 0) {
+/**
+ * Add an entry to the HTML tree for saving.
+ *
+ * The node must contain a sequence of node_elements in the following order:
+ *
+ * \param entry hotlist entry to add
+ * \param node node to add li to
+ * \return true on success, false on memory exhaustion
+ */
+static bool tree_url_save_entry(struct node *entry, xmlNode *node)
+{
+ xmlNode *li, *a;
+ xmlAttr *href;
+ const char *text;
+
+ li = xmlNewChild(node, NULL, (const xmlChar *) "li", NULL);
+ if (!li)
+ return false;
+
+
+ text = tree_url_node_get_title(entry);
+ if (text == NULL)
+ return false;
+ a = xmlNewTextChild(li, NULL, (const xmlChar *) "a",
+ (const xmlChar *) text);
+ if (!a)
+ return false;
+
+ text = tree_url_node_get_url(entry);
+ if (text == NULL)
+ return false;
+ href = xmlNewProp(a, (const xmlChar *) "href", (const xmlChar *) text);
+ if (!href)
+ return false;
+ return true;
+}
+
+/**
+ * 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)
+ return false;
+
+ for (child = tree_node_get_child(directory); child;
+ child = tree_node_get_next(child)) {
+ if (!tree_node_is_folder(child)) {
/* entry */
- tree_url_load_entry(n, tree, directory, callback,
- callback_data);
-
- } else if (strcmp((const char *) n->name, "h4") == 0) {
+ if (!tree_url_save_entry(child, ul))
+ return false;
+ } else {
/* directory */
- title = (char *) xmlNodeGetContent(n);
- if (!title) {
- warn_user("TreeLoadError", "(Empty <h4> "
- "or memory exhausted.)");
- return;
- }
-
- for (n = n->next;
- n && n->type != XML_ELEMENT_NODE;
- n = n->next)
- ;
- if (!n || strcmp((const char *) n->name, "ul") != 0) {
- /* next element isn't expected ul */
- free(title);
- warn_user("TreeLoadError", "(Expected "
- "<ul> not present.)");
- return;
- }
-
- dir = tree_create_folder_node(tree, directory, title,
- true, false, false);
- if (dir == NULL) {
- free(title);
- return;
- }
-
- if (callback != NULL)
- tree_set_node_user_callback(dir, callback,
- callback_data);
-
- if (folder_icon != NULL)
- tree_set_node_icon(tree, dir, folder_icon);
-
- tree_url_load_directory(n, tree, dir, callback,
- callback_data);
- }
- }
-}
-
-
-/**
- * Parse an entry represented as a li.
- *
- * \param li xmlNode for parsed li
- * \param directory directory to add this entry to
- */
-void tree_url_load_entry(xmlNode *li, struct tree *tree,
- struct node *directory, tree_node_user_callback callback,
- void *callback_data)
-{
- char *url = NULL, *url1 = NULL;
- char *title = NULL;
- struct node *entry;
- xmlNode *n;
- const struct url_data *data;
- url_func_result res;
-
- for (n = li->children; n; n = n->next) {
- /* The li must contain an "a" element */
- if (n->type == XML_ELEMENT_NODE &&
- strcmp((const char *) n->name, "a") == 0) {
- url1 = (char *) xmlGetProp(n, (const xmlChar *) "href");
- title = (char *) xmlNodeGetContent(n);
- }
- }
-
- if (!url1 || !title) {
- warn_user("TreeLoadError", "(Missing <a> in <li> or "
- "memory exhausted.)");
- return;
- }
-
- /* We're loading external input.
- * This may be garbage, so attempt to normalise
- */
- res = url_normalize(url1, &url);
- if (res != URL_FUNC_OK) {
- LOG(("Failed normalising '%s'", url1));
-
- if (res == URL_FUNC_NOMEM)
- warn_user("NoMemory", NULL);
-
- xmlFree(url1);
- xmlFree(title);
-
- return;
- }
-
- /* No longer need this */
- xmlFree(url1);
-
- data = urldb_get_url_data(url);
- if (data == NULL) {
- /* No entry in database, so add one */
- urldb_add_url(url);
- /* now attempt to get url data */
- data = urldb_get_url_data(url);
- }
- if (data == NULL) {
- xmlFree(title);
- free(url);
-
- return;
- }
-
- /* Make this URL persistent */
- urldb_set_url_persistence(url, true);
-
- if (data->title == NULL)
- urldb_set_url_title(url, title);
-
- entry = tree_create_URL_node(tree, directory, url, title,
- callback, callback_data);
-
- if (entry == NULL) {
- /** \todo why isn't this fatal? */
- warn_user("NoMemory", 0);
- }
- else
- tree_update_URL_node(tree, entry, url, data, false);
-
-
- xmlFree(title);
- free(url);
-}
-
-
-/**
- * Search the children of an xmlNode for an element.
- *
- * \param node xmlNode to search children of, or 0
- * \param name name of element to find
- * \return first child of node which is an element and matches name, or
- * 0 if not found or parameter node is 0
- */
-xmlNode *tree_url_find_xml_element(xmlNode *node, const char *name)
-{
- xmlNode *n;
- if (!node)
- return 0;
- for (n = node->children;
- n && !(n->type == XML_ELEMENT_NODE &&
- strcmp((const char *) n->name, name) == 0);
- n = n->next)
- ;
- return n;
-}
+ /* 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)
+ return false;
+
+ if (!tree_url_save_directory(child, ul))
+ return false;
+ } }
+
+ return true;
+}
+
+
+
+
+
@@ -709,7 +807,7 @@
* \param page_title title of the page
*/
bool tree_urlfile_save(struct tree *tree, const char *filename,
- const char *page_title)
+ const char *page_title)
{
int res;
xmlDoc *doc;
@@ -741,7 +839,7 @@
}
title = xmlNewTextChild(head, NULL, (const xmlChar *) "title",
- (const xmlChar *) page_title);
+ (const xmlChar *) page_title);
if (title == NULL) {
warn_user("NoMemory", 0);
xmlFreeDoc(doc);
@@ -772,86 +870,3 @@
xmlFreeDoc(doc);
return true;
}
-
-
-/**
- * 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
- */
-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)
- return false;
-
- 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)
- return false;
-
- if (!tree_url_save_directory(child, ul))
- return false;
- } }
-
- return true;
-}
-
-
-/**
- * Add an entry to the HTML tree for saving.
- *
- * The node must contain a sequence of node_elements in the following order:
- *
- * \param entry hotlist entry to add
- * \param node node to add li to
- * \return true on success, false on memory exhaustion
- */
-bool tree_url_save_entry(struct node *entry, xmlNode *node)
-{
- xmlNode *li, *a;
- xmlAttr *href;
- const char *text;
-
- li = xmlNewChild(node, NULL, (const xmlChar *) "li", NULL);
- if (!li)
- return false;
-
-
- text = tree_url_node_get_title(entry);
- if (text == NULL)
- return false;
- a = xmlNewTextChild(li, NULL, (const xmlChar *) "a",
- (const xmlChar *) text);
- if (!a)
- return false;
-
- text = tree_url_node_get_url(entry);
- if (text == NULL)
- return false;
- href = xmlNewProp(a, (const xmlChar *) "href", (const xmlChar *) text);
- if (!href)
- return false;
- return true;
-}