INCLUDES = \
- $(GTK_CFLAGS)
+ $(GTK_CFLAGS) \
+ $(LIBXML_CFLAGS)
noinst_LTLIBRARIES = \
libkatze.la
libkatze_la_LIBADD = \
- $(GTK_LIBS)
+ $(GTK_LIBS) \
+ $(LIBXML_LIBS)
libkatze_la_SOURCES = \
katze.h \
katze-throbber.c katze-throbber.h \
- katze-utils.c katze-utils.h
+ katze-utils.c katze-utils.h \
+ katze-xbel.c katze-xbel.h
--- /dev/null
+/*
+ Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
+
+ 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.
+
+ See the file COPYING for the full license text.
+*/
+
+/**
+ * TODO:
+ * - Support info > metadata, alias, added, modified, visited
+ * - Compatibility: The Nokia 770 *requires* metadata and folder
+ * - Compatibility: Kazehakase's bookmarks
+ * - Compatibility: Epiphany's bookmarks
+ * - XML Indentation
+ **/
+
+#include "katze-xbel.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include "katze-utils.h"
+
+struct _KatzeXbelItemPrivate
+{
+ guint refs;
+ KatzeXbelItemKind kind;
+ KatzeXbelItem* parent;
+
+ GList* items; // folder
+ gboolean folded; // foolder
+ gchar* title; // !separator
+ gchar* desc; // folder and bookmark
+ gchar* href; // bookmark
+ //time_t added; // !separator
+ //time_t modfied; // bookmark
+ //time_t visited; // bookmark
+} ;
+
+#define KATZE_XBEL_ITEM_GET_PRIVATE(item) \
+ item->priv
+
+// Private: Create a new item of a certain type
+static KatzeXbelItem*
+katze_xbel_item_new (KatzeXbelItemKind kind)
+{
+ KatzeXbelItem* item = g_new (KatzeXbelItem, 1);
+ KATZE_XBEL_ITEM_GET_PRIVATE (item) = g_new (KatzeXbelItemPrivate, 1);
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+
+ priv->refs = 1;
+ priv->parent = NULL;
+ priv->kind = kind;
+ if (kind == KATZE_XBEL_ITEM_KIND_FOLDER)
+ {
+ priv->items = NULL;
+ priv->folded = TRUE;
+ }
+ if (kind != KATZE_XBEL_ITEM_KIND_SEPARATOR)
+ {
+ priv->title = NULL;
+ priv->desc = NULL;
+ }
+ if (kind == KATZE_XBEL_ITEM_KIND_BOOKMARK)
+ priv->href = g_strdup ("");
+ return item;
+}
+
+/**
+ * katze_xbel_bookmark_new:
+ *
+ * Create a new empty bookmark.
+ *
+ * Return value: a newly allocated bookmark
+ **/
+KatzeXbelItem*
+katze_xbel_bookmark_new (void)
+{
+ return katze_xbel_item_new (KATZE_XBEL_ITEM_KIND_BOOKMARK);
+}
+
+static KatzeXbelItem*
+katze_xbel_bookmark_from_xmlNodePtr (xmlNodePtr cur)
+{
+ g_return_val_if_fail (cur, NULL);
+
+ KatzeXbelItem* bookmark = katze_xbel_bookmark_new ();
+ xmlChar* key = xmlGetProp (cur, (xmlChar*)"href");
+ katze_xbel_bookmark_set_href (bookmark, (gchar*)key);
+ cur = cur->xmlChildrenNode;
+ while (cur)
+ {
+ if (!xmlStrcmp (cur->name, (const xmlChar*)"title"))
+ {
+ xmlChar* key = xmlNodeGetContent (cur);
+ katze_xbel_item_set_title (bookmark, g_strstrip ((gchar*)key));
+ }
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"desc"))
+ {
+ xmlChar* key = xmlNodeGetContent (cur);
+ katze_xbel_item_set_desc (bookmark, g_strstrip ((gchar*)key));
+ }
+ cur = cur->next;
+ }
+ return bookmark;
+}
+
+/**
+ * katze_katze_xbel_separator_new:
+ *
+ * Create a new separator.
+ *
+ * The returned item must be freed eventually.
+ *
+ * Return value: a newly allocated separator.
+ **/
+KatzeXbelItem*
+katze_xbel_separator_new (void)
+{
+ return katze_xbel_item_new (KATZE_XBEL_ITEM_KIND_SEPARATOR);
+}
+
+/**
+ * katze_xbel_folder_new:
+ *
+ * Create a new empty folder.
+ *
+ * The returned item must be freed eventually.
+ *
+ * Return value: a newly allocated folder.
+ **/
+KatzeXbelItem*
+katze_xbel_folder_new (void)
+{
+ return katze_xbel_item_new (KATZE_XBEL_ITEM_KIND_FOLDER);
+}
+
+// Private: Create a folder from an xmlNodePtr
+static KatzeXbelItem*
+katze_xbel_folder_from_xmlNodePtr (xmlNodePtr cur)
+{
+ g_return_val_if_fail (cur, NULL);
+
+ KatzeXbelItem* folder = katze_xbel_folder_new ();
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+
+ xmlChar* key = xmlGetProp (cur, (xmlChar*)"folded");
+ if (key)
+ {
+ if (!g_ascii_strncasecmp ((gchar*)key, "yes", 3))
+ priv->folded = TRUE;
+ else if (!g_ascii_strncasecmp ((gchar*)key, "no", 2))
+ priv->folded = FALSE;
+ else
+ g_warning ("XBEL: Unknown value for folded.");
+ xmlFree (key);
+ }
+ cur = cur->xmlChildrenNode;
+ while (cur)
+ {
+ if (!xmlStrcmp (cur->name, (const xmlChar*)"title"))
+ {
+ xmlChar* key = xmlNodeGetContent (cur);
+ katze_assign (priv->title, g_strstrip ((gchar*)key));
+ }
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"desc"))
+ {
+ xmlChar* key = xmlNodeGetContent (cur);
+ katze_assign (priv->desc, g_strstrip ((gchar*)key));
+ }
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"folder"))
+ {
+ KatzeXbelItem* item = katze_xbel_folder_from_xmlNodePtr (cur);
+ KATZE_XBEL_ITEM_GET_PRIVATE (item)->parent = folder;
+ priv->items = g_list_prepend (priv->items, item);
+ }
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"bookmark"))
+ {
+ KatzeXbelItem* item = katze_xbel_bookmark_from_xmlNodePtr (cur);
+ priv->parent = folder;
+ priv->items = g_list_prepend (priv->items, item);
+ }
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"separator"))
+ {
+ KatzeXbelItem* item = katze_xbel_separator_new ();
+ priv->parent = folder;
+ priv->items = g_list_prepend (priv->items, item);
+ }
+ cur = cur->next;
+ }
+ // Prepending and reversing is faster than appending
+ priv->items = g_list_reverse (priv->items);
+ return folder;
+}
+
+// Private: Loads the contents from an xmlNodePtr into a folder.
+static gboolean
+katze_xbel_folder_from_xmlDocPtr (KatzeXbelItem* folder,
+ xmlDocPtr doc)
+{
+ g_return_val_if_fail (katze_xbel_folder_is_empty (folder), FALSE);
+ g_return_val_if_fail (doc, FALSE);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+
+ xmlNodePtr cur = xmlDocGetRootElement (doc);
+ xmlChar* version = xmlGetProp (cur, (xmlChar*)"version");
+ if (xmlStrcmp (version, (xmlChar*)"1.0"))
+ g_warning ("XBEL version is not 1.0.");
+ xmlFree (version);
+
+ katze_assign (priv->title, (gchar*)xmlGetProp (cur, (xmlChar*)"title"));
+ katze_assign (priv->desc, (gchar*)xmlGetProp (cur, (xmlChar*)"desc"));
+ if ((cur = xmlDocGetRootElement (doc)) == NULL)
+ {
+ // Empty document
+ return FALSE;
+ }
+ if (xmlStrcmp (cur->name, (const xmlChar*)"xbel"))
+ {
+ // Wrong document kind
+ return FALSE;
+ }
+ cur = cur->xmlChildrenNode;
+ while (cur)
+ {
+ KatzeXbelItem* item = NULL;
+ if (!xmlStrcmp (cur->name, (const xmlChar*)"folder"))
+ item = katze_xbel_folder_from_xmlNodePtr (cur);
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"bookmark"))
+ item = katze_xbel_bookmark_from_xmlNodePtr (cur);
+ else if (!xmlStrcmp (cur->name, (const xmlChar*)"separator"))
+ item = katze_xbel_separator_new ();
+ /*else if (!xmlStrcmp (cur->name, (const xmlChar*)"info"))
+ item = katze_xbel_parse_info (xbel, cur);*/
+ if (item)
+ {
+ KATZE_XBEL_ITEM_GET_PRIVATE (item)->parent = folder;
+ priv->items = g_list_prepend (priv->items, item);
+ }
+ cur = cur->next;
+ }
+ // Prepending and reversing is faster than appending
+ priv->items = g_list_reverse (priv->items);
+ return TRUE;
+}
+
+/**
+ * katze_xbel_item_ref:
+ * @item: a valid item
+ *
+ * Ref an KatzeXbelItem.
+ *
+ * Ref means that the reference count is increased by one.
+ *
+ * This has no effect on children of a folder.
+ **/
+void
+katze_xbel_item_ref (KatzeXbelItem* item)
+{
+ g_return_if_fail (item);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ priv->refs++;
+}
+
+/**
+ * katze_xbel_item_unref:
+ * @item: a valid item
+ *
+ * Unref an KatzeXbelItem. If @item is a folder all of its children will also
+ * be unreffed automatically.
+ *
+ * Unref means that the reference count is decreased. If there are no
+ * references left, the memory will be freed and if needed removed from
+ * its containing folder.
+ **/
+void
+katze_xbel_item_unref (KatzeXbelItem* item)
+{
+ g_return_if_fail (item);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ priv->refs--;
+ if (priv->refs)
+ return;
+
+ if (priv->parent)
+ katze_xbel_folder_remove_item (priv->parent, item);
+
+ if (priv->kind == KATZE_XBEL_ITEM_KIND_FOLDER)
+ {
+ guint n = katze_xbel_folder_get_n_items (item);
+ guint i;
+ for (i = 0; i < n; i++)
+ {
+ KatzeXbelItem* _item = katze_xbel_folder_get_nth_item (item, i);
+ KATZE_XBEL_ITEM_GET_PRIVATE (_item)->parent = NULL;
+ katze_xbel_item_unref (_item);
+ }
+ g_list_free (priv->items);
+ }
+ if (priv->kind != KATZE_XBEL_ITEM_KIND_SEPARATOR)
+ {
+ g_free (priv->title);
+ g_free (priv->desc);
+ }
+ if (priv->kind == KATZE_XBEL_ITEM_KIND_BOOKMARK)
+ g_free (priv->href);
+ g_free (item);
+}
+
+/**
+ * katze_xbel_item_copy:
+ * @item: the item to copy
+ *
+ * Copy an KatzeXbelItem.
+ *
+ * The returned item must be unreffed eventually.
+ *
+ * Return value: a copy of @item
+ **/
+KatzeXbelItem*
+katze_xbel_item_copy (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (item, NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ KatzeXbelItem* copy = katze_xbel_item_new (priv->kind);
+
+ if (katze_xbel_item_is_folder (item))
+ {
+ guint n = katze_xbel_folder_get_n_items (item);
+ guint i;
+ for (i = 0; i < n; i++)
+ {
+ KatzeXbelItem* _item = katze_xbel_folder_get_nth_item (item, i);
+ katze_xbel_folder_append_item (copy, katze_xbel_item_copy (_item));
+ }
+ }
+ if (priv->kind != KATZE_XBEL_ITEM_KIND_SEPARATOR)
+ {
+ katze_xbel_item_set_title (copy, priv->title);
+ katze_xbel_item_set_desc (copy, priv->desc);
+ }
+ if (priv->kind == KATZE_XBEL_ITEM_KIND_BOOKMARK)
+ katze_xbel_bookmark_set_href (copy, priv->href);
+ return copy;
+}
+
+GType
+katze_xbel_item_get_type (void)
+{
+ static GType type = 0;
+ if (!type)
+ type = g_pointer_type_register_static ("katze_xbel_item");
+ return type;
+}
+
+/**
+ * katze_xbel_folder_append_item:
+ * @folder: a folder
+ * @item: the item to append
+ *
+ * Append the given item to a folder.
+ *
+ * The item is actually moved and must not be contained in another folder.
+ *
+ **/
+void
+katze_xbel_folder_append_item (KatzeXbelItem* folder,
+ KatzeXbelItem* item)
+{
+ g_return_if_fail (!katze_xbel_item_get_parent (item));
+ g_return_if_fail (katze_xbel_item_is_folder (folder));
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ priv->items = g_list_append (priv->items, item);
+
+ KATZE_XBEL_ITEM_GET_PRIVATE (item)->parent = folder;
+}
+
+/**
+ * katze_xbel_folder_prepend_item:
+ * @folder: a folder
+ * @item: the item to prepend
+ *
+ * Prepend the given item to a folder.
+ *
+ * The item is actually moved and must not be contained in another folder.
+ *
+ **/
+void
+katze_xbel_folder_prepend_item (KatzeXbelItem* folder,
+ KatzeXbelItem* item)
+{
+ g_return_if_fail (!katze_xbel_item_get_parent (item));
+ g_return_if_fail (katze_xbel_item_is_folder (folder));
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ priv->items = g_list_prepend (priv->items, item);
+
+ KATZE_XBEL_ITEM_GET_PRIVATE (item)->parent = folder;
+}
+
+/**
+ * katze_xbel_folder_remove_item:
+ * @folder: a folder
+ * @item: the item to remove
+ *
+ * Remove the given @item from a @folder.
+ **/
+void
+katze_xbel_folder_remove_item (KatzeXbelItem* folder,
+ KatzeXbelItem* item)
+{
+ g_return_if_fail (item);
+ g_return_if_fail (katze_xbel_item_get_parent(folder) != item);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ // Fortunately we know that items are unique
+ priv->items = g_list_remove (priv->items, item);
+
+ KATZE_XBEL_ITEM_GET_PRIVATE (item)->parent = NULL;
+}
+
+/**
+ * katze_xbel_folder_get_n_items:
+ * @folder: a folder
+ *
+ * Retrieve the number of items contained in the given @folder.
+ *
+ * Return value: number of items
+ **/
+guint
+katze_xbel_folder_get_n_items (KatzeXbelItem* folder)
+{
+ g_return_val_if_fail (katze_xbel_item_is_folder (folder), 0);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ return g_list_length (priv->items);
+}
+
+/**
+ * katze_xbel_folder_get_nth_item:
+ * @folder: a folder
+ * @n: the index of an item
+ *
+ * Retrieve an item contained in the given @folder by its index.
+ *
+ * Return value: the item at the given index or %NULL
+ **/
+KatzeXbelItem*
+katze_xbel_folder_get_nth_item (KatzeXbelItem* folder,
+ guint n)
+{
+ g_return_val_if_fail (katze_xbel_item_is_folder(folder), NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ return (KatzeXbelItem*) g_list_nth_data (priv->items, n);
+}
+
+/**
+ * katze_xbel_folder_is_empty:
+ * @folder: A folder.
+ *
+ * Determines wether or not a folder contains no items. This is significantly
+ * faster than katze_xbel_folder_get_n_items for this particular purpose.
+ *
+ * Return value: Wether the given @folder is folded.
+ **/
+gboolean
+katze_xbel_folder_is_empty (KatzeXbelItem* folder)
+{
+ return !katze_xbel_folder_get_nth_item (folder, 0);
+}
+
+/**
+ * katze_xbel_folder_get_folded:
+ * @folder: A folder.
+ *
+ * Determines wether or not a folder is folded. If a folder is not folded
+ * it should not be exposed in a user interface.
+ *
+ * New folders are folded by default.
+ *
+ * Return value: Wether the given @folder is folded.
+ **/
+gboolean
+katze_xbel_folder_get_folded (KatzeXbelItem* folder)
+{
+ g_return_val_if_fail (katze_xbel_item_is_folder (folder), TRUE);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ return priv->folded;
+}
+
+/**
+ * katze_xbel_item_get_kind:
+ * @item: A item.
+ *
+ * Determines the kind of an item.
+ *
+ * Return value: The kind of the given @item.
+ **/
+KatzeXbelItemKind
+katze_xbel_item_get_kind (KatzeXbelItem* item)
+{
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->kind;
+}
+
+/**
+ * katze_xbel_item_get_parent:
+ * @item: A valid item.
+ *
+ * Retrieves the parent folder of an item.
+ *
+ * Return value: The parent folder of the given @item or %NULL.
+ **/
+KatzeXbelItem*
+katze_xbel_item_get_parent (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (item, NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->parent;
+}
+
+/**
+ * katze_xbel_item_get_title:
+ * @item: A valid item.
+ *
+ * Retrieves the title of an item.
+ *
+ * Return value: The title of the given @item or %NULL.
+ **/
+G_CONST_RETURN gchar*
+katze_xbel_item_get_title (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (!katze_xbel_item_is_separator (item), NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->title;
+}
+
+/**
+ * katze_xbel_item_get_desc:
+ * @item: A valid item.
+ *
+ * Retrieves the description of an item.
+ *
+ * Return value: The description of the @item or %NULL.
+ **/
+G_CONST_RETURN gchar*
+katze_xbel_item_get_desc (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (!katze_xbel_item_is_separator (item), NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->desc;
+}
+
+/**
+ * katze_xbel_bookmark_get_href:
+ * @bookmark: A bookmark.
+ *
+ * Retrieves the uri of a bookmark. The value is guaranteed to not be %NULL.
+ *
+ * Return value: The uri of the @bookmark.
+ **/
+G_CONST_RETURN gchar*
+katze_xbel_bookmark_get_href (KatzeXbelItem* bookmark)
+{
+ g_return_val_if_fail (katze_xbel_item_is_bookmark (bookmark), NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (bookmark);
+ return priv->href;
+}
+
+/**
+ * katze_xbel_item_is_bookmark:
+ * @item: A valid item.
+ *
+ * Determines wether or not an item is a bookmark.
+ *
+ * Return value: %TRUE if the @item is a bookmark.
+ **/
+gboolean
+katze_xbel_item_is_bookmark (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (item, FALSE);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->kind == KATZE_XBEL_ITEM_KIND_BOOKMARK;
+}
+
+/**
+ * katze_xbel_item_is_separator:
+ * @item: A valid item.
+ *
+ * Determines wether or not an item is a separator.
+ *
+ * Return value: %TRUE if the @item is a separator.
+ **/
+gboolean katze_xbel_item_is_separator (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (item, FALSE);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->kind == KATZE_XBEL_ITEM_KIND_SEPARATOR;
+}
+
+/**
+ * katze_xbel_item_is_folder:
+ * @item: A valid item.
+ *
+ * Determines wether or not an item is a folder.
+ *
+ * Return value: %TRUE if the item is a folder.
+ **/
+gboolean
+katze_xbel_item_is_folder (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (item, FALSE);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ return priv->kind == KATZE_XBEL_ITEM_KIND_FOLDER;
+}
+
+/**
+ * katze_xbel_folder_set_folded:
+ * @folder: A folder.
+ * @folded: TRUE if the folder is folded.
+ *
+ * Sets the foldedness of the @folder.
+ **/
+void
+katze_xbel_folder_set_folded (KatzeXbelItem* folder,
+ gboolean folded)
+{
+ g_return_if_fail (katze_xbel_item_is_folder (folder));
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+ priv->folded = folded;
+}
+
+/**
+ * katze_xbel_item_set_title:
+ * @item: A valid item.
+ * @title: A string to use for the title.
+ *
+ * Sets the title of the @item.
+ **/
+void
+katze_xbel_item_set_title (KatzeXbelItem* item,
+ const gchar* title)
+{
+ g_return_if_fail (!katze_xbel_item_is_separator (item));
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ katze_assign (priv->title, g_strdup (title));
+}
+
+/**
+ * katze_xbel_item_set_desc:
+ * @item: A valid item.
+ * @title: A string to use for the description.
+ *
+ * Sets the description of the @item.
+ **/
+void
+katze_xbel_item_set_desc (KatzeXbelItem* item,
+ const gchar* desc)
+{
+ g_return_if_fail (!katze_xbel_item_is_separator (item));
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+ katze_assign (priv->desc, g_strdup (desc));
+}
+
+/**
+ * katze_xbel_bookmark_set_href:
+ * @bookmark: A bookmark.
+ * @href: A string containing a valid uri.
+ *
+ * Sets the uri of the bookmark.
+ *
+ * The uri must not be %NULL.
+ *
+ * This uri is not currently validated in any way. This may change in the future.
+ **/
+void
+katze_xbel_bookmark_set_href (KatzeXbelItem* bookmark,
+ const gchar* href)
+{
+ g_return_if_fail (katze_xbel_item_is_bookmark (bookmark));
+ g_return_if_fail (href);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (bookmark);
+ katze_assign (priv->href, g_strdup (href));
+}
+
+gboolean
+katze_xbel_folder_from_data (KatzeXbelItem* folder,
+ const gchar* data,
+ GError** error)
+{
+ g_return_val_if_fail (katze_xbel_folder_is_empty (folder), FALSE);
+ g_return_val_if_fail (data, FALSE);
+ xmlDocPtr doc;
+ if((doc = xmlParseMemory (data, strlen (data))) == NULL)
+ {
+ // No valid xml or broken encoding
+ *error = g_error_new (KATZE_XBEL_ERROR, KATZE_XBEL_ERROR_READ,
+ "Malformed document.");
+ return FALSE;
+ }
+ if (!katze_xbel_folder_from_xmlDocPtr (folder, doc))
+ {
+ // Parsing failed
+ xmlFreeDoc(doc);
+ *error = g_error_new (KATZE_XBEL_ERROR, KATZE_XBEL_ERROR_READ,
+ "Malformed document.");
+ return FALSE;
+ }
+ xmlFreeDoc(doc);
+ return TRUE;
+}
+
+/**
+ * katze_xbel_folder_from_file:
+ * @folder: An empty folder.
+ * @file: A relative path to a file.
+ * @error: return location for a GError or %NULL
+ *
+ * Tries to load @file.
+ *
+ * Return value: %TRUE on success or %FALSE when an error occured.
+ **/
+gboolean
+katze_xbel_folder_from_file (KatzeXbelItem* folder,
+ const gchar* file,
+ GError** error)
+{
+ g_return_val_if_fail (katze_xbel_folder_is_empty (folder), FALSE);
+ g_return_val_if_fail (file, FALSE);
+ if (!g_file_test (file, G_FILE_TEST_EXISTS))
+ {
+ // File doesn't exist
+ *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_NOENT,
+ "File not found.");
+ return FALSE;
+ }
+ xmlDocPtr doc;
+ if ((doc = xmlParseFile (file)) == NULL)
+ {
+ // No valid xml or broken encoding
+ *error = g_error_new (KATZE_XBEL_ERROR, KATZE_XBEL_ERROR_READ,
+ "Malformed document.");
+ return FALSE;
+ }
+ if (!katze_xbel_folder_from_xmlDocPtr (folder, doc))
+ {
+ // Parsing failed
+ xmlFreeDoc (doc);
+ *error = g_error_new (KATZE_XBEL_ERROR, KATZE_XBEL_ERROR_READ,
+ "Malformed document.");
+ return FALSE;
+ }
+ xmlFreeDoc (doc);
+ return TRUE;
+}
+
+/**
+ * katze_xbel_folder_from_data_dirs:
+ * @folder: An empty folder.
+ * @file: A relative path to a file.
+ * @full_path: return location for the full path of the file or %NULL
+ * @error: return location for a GError or %NULL
+ *
+ * Tries to load @file from the user data dir or any of the system data dirs.
+ *
+ * Return value: %TRUE on success or %FALSE when an error occured.
+ **/
+gboolean
+katze_xbel_folder_from_data_dirs (KatzeXbelItem* folder,
+ const gchar* file,
+ gchar** full_path,
+ GError** error)
+{
+ g_return_val_if_fail (katze_xbel_folder_is_empty (folder), FALSE);
+ g_return_val_if_fail (file, FALSE);
+ // FIXME: Essentially unimplemented
+
+ *error = g_error_new (KATZE_XBEL_ERROR, KATZE_XBEL_ERROR_READ,
+ "Malformed document.");
+ return FALSE;
+}
+
+static gchar*
+katze_xbel_xml_element (const gchar* name,
+ const gchar* value)
+{
+ if (!value)
+ return g_strdup ("");
+ gchar* valueEscaped = g_markup_escape_text (value, -1);
+ gchar* markup = g_strdup_printf ("<%s>%s</%s>\n",
+ name, valueEscaped, name);
+ g_free (valueEscaped);
+ return markup;
+}
+
+static gchar*
+katze_xbel_item_to_data (KatzeXbelItem* item)
+{
+ g_return_val_if_fail (item, NULL);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (item);
+
+ gchar* markup = NULL;
+ switch (priv->kind)
+ {
+ case KATZE_XBEL_ITEM_KIND_FOLDER:
+ {
+ GString* _markup = g_string_new (NULL);
+ guint n = katze_xbel_folder_get_n_items (item);
+ guint i;
+ for (i = 0; i < n; i++)
+ {
+ KatzeXbelItem* _item = katze_xbel_folder_get_nth_item (item, i);
+ gchar* item_markup = katze_xbel_item_to_data (_item);
+ g_string_append (_markup, item_markup);
+ g_free (item_markup);
+ }
+ gchar* folded = priv->folded ? NULL : g_strdup_printf (" folded=\"no\"");
+ gchar* title = katze_xbel_xml_element ("title", priv->title);
+ gchar* desc = katze_xbel_xml_element ("desc", priv->desc);
+ markup = g_strdup_printf ("<folder%s>\n%s%s%s</folder>\n",
+ folded ? folded : "",
+ title, desc,
+ g_string_free (_markup, FALSE));
+ g_free (folded);
+ g_free (title);
+ g_free (desc);
+ break;
+ }
+ case KATZE_XBEL_ITEM_KIND_BOOKMARK:
+ {
+ gchar* href_escaped = g_markup_escape_text (priv->href, -1);
+ gchar* href = g_strdup_printf (" href=\"%s\"", href_escaped);
+ g_free (href_escaped);
+ gchar* title = katze_xbel_xml_element ("title", priv->title);
+ gchar* desc = katze_xbel_xml_element ("desc", priv->desc);
+ markup = g_strdup_printf ("<bookmark%s>\n%s%s%s</bookmark>\n",
+ href,
+ title, desc,
+ "");
+ g_free (href);
+ g_free (title);
+ g_free (desc);
+ break;
+ }
+ case KATZE_XBEL_ITEM_KIND_SEPARATOR:
+ markup = g_strdup ("<separator/>\n");
+ break;
+ default:
+ g_warning ("XBEL: Unknown item kind");
+ }
+ return markup;
+}
+
+/**
+ * katze_xbel_folder_to_data:
+ * @folder: A folder.
+ * @length: return location for the length of the created string or %NULL
+ * @error: return location for a GError or %NULL
+ *
+ * Retrieve the contents of @folder as a string.
+ *
+ * Return value: %TRUE on success or %FALSE when an error occured.
+ **/
+gchar*
+katze_xbel_folder_to_data (KatzeXbelItem* folder,
+ gsize* length,
+ GError** error)
+{
+ g_return_val_if_fail (katze_xbel_item_is_folder (folder), FALSE);
+
+ KatzeXbelItemPrivate* priv = KATZE_XBEL_ITEM_GET_PRIVATE (folder);
+
+ GString* inner_markup = g_string_new (NULL);
+ guint n = katze_xbel_folder_get_n_items (folder);
+ guint i;
+ for (i = 0; i < n; i++)
+ {
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i);
+ gchar* sItem = katze_xbel_item_to_data (item);
+ g_string_append (inner_markup, sItem);
+ g_free (sItem);
+ }
+ gchar* title = katze_xbel_xml_element ("title", priv->title);
+ gchar* desc = katze_xbel_xml_element ("desc", priv->desc);
+ gchar* outer_markup;
+ outer_markup = g_strdup_printf (
+ "%s%s<xbel version=\"1.0\">\n%s%s%s</xbel>\n",
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
+ "<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD "
+ "XML Bookmark Exchange Language 1.0//EN//XML\" "
+ "\"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n",
+ title,
+ desc,
+ g_string_free (inner_markup, FALSE));
+ g_free (title);
+ g_free (desc);
+
+ if (length)
+ *length = strlen (outer_markup);
+ return outer_markup;
+}
+
+/**
+ * katze_xbel_folder_to_file:
+ * @folder: A folder.
+ * @file: The destination filename.
+ * @error: return location for a GError or %NULL
+ *
+ * Write the contents of @folder to the specified file, creating it if necessary.
+ *
+ * Return value: %TRUE on success or %FALSE when an error occured.
+ **/
+gboolean
+katze_xbel_folder_to_file (KatzeXbelItem* folder,
+ const gchar* file,
+ GError** error)
+{
+ g_return_val_if_fail (file, FALSE);
+ gchar* data;
+ if (!(data = katze_xbel_folder_to_data (folder, NULL, error)))
+ return FALSE;
+ FILE* fp;
+ if(!(fp = fopen (file, "w")))
+ {
+ *error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_ACCES,
+ "Writing failed.");
+ return FALSE;
+ }
+ fputs (data, fp);
+ fclose (fp);
+ g_free (data);
+ return TRUE;
+}
--- /dev/null
+/*
+ Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
+
+ 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.
+
+ See the file COPYING for the full license text.
+*/
+
+#ifndef __KATZE_XBEL_H__
+#define __KATZE_XBEL_H__ 1
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define KATZE_TYPE_XBEL_ITEM \
+ (katze_xbel_item_get_type ())
+
+typedef struct _KatzeXbelItem KatzeXbelItem;
+typedef struct _KatzeXbelItemPrivate KatzeXbelItemPrivate;
+
+struct _KatzeXbelItem
+{
+ KatzeXbelItemPrivate* priv;
+
+ /* Padding for future expansion */
+ void (*_katze_reserved1) (void);
+ void (*_katze_reserved2) (void);
+ void (*_katze_reserved3) (void);
+ void (*_katze_reserved4) (void);
+};
+
+#define KATZE_XBEL_ERROR g_quark_from_string("KATZE_XBEL_ERROR")
+
+typedef enum
+{
+ KATZE_XBEL_ERROR_INVALID_URI, /* Malformed uri */
+ KATZE_XBEL_ERROR_INVALID_VALUE, /* Requested field not found */
+ KATZE_XBEL_ERROR_URI_NOT_FOUND, /* Requested uri not found */
+ KATZE_XBEL_ERROR_READ, /* Malformed document */
+ KATZE_XBEL_ERROR_UNKNOWN_ENCODING, /* Parsed text was in an unknown encoding */
+ KATZE_XBEL_ERROR_WRITE, /* Writing failed. */
+} KatzeXbelError;
+
+typedef enum
+{
+ KATZE_XBEL_ITEM_KIND_FOLDER,
+ KATZE_XBEL_ITEM_KIND_BOOKMARK,
+ KATZE_XBEL_ITEM_KIND_SEPARATOR
+} KatzeXbelItemKind;
+
+GType
+katze_xbel_item_get_type (void) G_GNUC_CONST;
+
+KatzeXbelItem*
+katze_xbel_bookmark_new (void);
+
+KatzeXbelItem*
+katze_xbel_separator_new (void);
+
+KatzeXbelItem*
+katze_xbel_folder_new (void);
+
+void
+katze_xbel_item_ref (KatzeXbelItem* item);
+
+void
+katze_xbel_item_unref (KatzeXbelItem* item);
+
+KatzeXbelItem*
+katze_xbel_item_copy (KatzeXbelItem* item);
+
+void
+katze_xbel_folder_append_item (KatzeXbelItem* folder,
+ KatzeXbelItem* item);
+
+void
+katze_xbel_folder_prepend_item (KatzeXbelItem* folder,
+ KatzeXbelItem* item);
+
+void
+katze_xbel_folder_remove_item (KatzeXbelItem* folder,
+ KatzeXbelItem* item);
+
+guint
+katze_xbel_folder_get_n_items (KatzeXbelItem* folder);
+
+KatzeXbelItem*
+katze_xbel_folder_get_nth_item (KatzeXbelItem* folder,
+ guint n);
+
+gboolean
+katze_xbel_folder_is_empty (KatzeXbelItem* folder);
+
+gboolean
+katze_xbel_folder_get_folded (KatzeXbelItem* folder);
+
+KatzeXbelItemKind
+katze_xbel_item_get_kind (KatzeXbelItem* item);
+
+KatzeXbelItem*
+katze_xbel_item_get_parent (KatzeXbelItem* item);
+
+G_CONST_RETURN gchar*
+katze_xbel_item_get_title (KatzeXbelItem* item);
+
+G_CONST_RETURN gchar*
+katze_xbel_item_get_desc (KatzeXbelItem* item);
+
+G_CONST_RETURN gchar*
+katze_xbel_bookmark_get_href (KatzeXbelItem* bookmark);
+
+/*time_t
+katze_xbel_bookmark_get_added (KatzeXbelItem* bookmark);
+
+time_t
+katze_xbel_bookmark_get_modified (KatzeXbelItem* bookmark);
+
+time_t
+katze_xbel_bookmark_get_visited (KatzeXbelItem* bookmark);*/
+
+gboolean
+katze_xbel_item_is_bookmark (KatzeXbelItem* bookmark);
+
+gboolean
+katze_xbel_item_is_separator (KatzeXbelItem* bookmark);
+
+gboolean
+katze_xbel_item_is_folder (KatzeXbelItem* bookmark);
+
+void
+katze_xbel_folder_set_folded (KatzeXbelItem* folder,
+ gboolean folded);
+
+void
+katze_xbel_item_set_title (KatzeXbelItem* item,
+ const gchar* title);
+
+void
+katze_xbel_item_set_desc (KatzeXbelItem* item,
+ const gchar* desc);
+
+void
+katze_xbel_bookmark_set_href (KatzeXbelItem* bookmark,
+ const gchar* href);
+
+gboolean
+katze_xbel_folder_from_data (KatzeXbelItem* folder,
+ const gchar* data,
+ GError** error);
+
+gboolean
+katze_xbel_folder_from_file (KatzeXbelItem* folder,
+ const gchar* file,
+ GError** error);
+
+gboolean
+katze_xbel_folder_from_data_dirs (KatzeXbelItem* folder,
+ const gchar* file,
+ gchar** full_path,
+ GError** error);
+
+gchar*
+katze_xbel_folder_to_data (KatzeXbelItem* folder,
+ gsize* length,
+ GError** error);
+
+gboolean
+katze_xbel_folder_to_file (KatzeXbelItem* folder,
+ const gchar* file,
+ GError** error);
+
+#endif /* !__KATZE_XBEL_H__ */
#include "katze-throbber.h"
#include "katze-utils.h"
+#include "katze-xbel.h"
-#endif /* __KATZE_THROBBER_H__ */
+#endif /* __KATZE_H__ */
INCLUDES = \
$(GTK_CFLAGS) \
$(WEBKIT_CFLAGS) \
- $(LIBXML_CFLAGS) \
$(LIBSEXY_CFLAGS) \
-I../katze
LDADD = \
$(GTK_LIBS) \
$(WEBKIT_LIBS) \
- $(LIBXML_LIBS) \
$(LIBSEXY_LIBS) \
../katze/libkatze.la
sokoke.c sokoke.h \
conf.c conf.h \
search.c search.h \
- xbel.c xbel.h \
global.h \
ui.h \
debug.h
#include "ui.h"
#include "webView.h"
#include "webSearch.h"
-#include "xbel.h"
#include "../katze/katze.h"
#include <gdk/gdkkeysyms.h>
void on_menu_tabsClosed_activate(GtkWidget* widget, CBrowser* browser)
{
GtkWidget* menu = gtk_menu_new();
- guint n = xbel_folder_get_n_items(tabtrash);
+ guint n = katze_xbel_folder_get_n_items(tabtrash);
GtkWidget* menuitem;
guint i;
for(i = 0; i < n; i++)
{
- XbelItem* item = xbel_folder_get_nth_item(tabtrash, i);
- const gchar* title = xbel_item_get_title(item);
- const gchar* uri = xbel_bookmark_get_href(item);
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(tabtrash, i);
+ const gchar* title = katze_xbel_item_get_title(item);
+ const gchar* uri = katze_xbel_bookmark_get_href(item);
menuitem = gtk_image_menu_item_new_with_label(title ? title : uri);
// FIXME: Get the real icon
GtkWidget* icon = gtk_image_new_from_stock(GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), icon);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- g_object_set_data(G_OBJECT(menuitem), "XbelItem", item);
+ g_object_set_data(G_OBJECT(menuitem), "KatzeXbelItem", item);
g_signal_connect(menuitem, "activate", G_CALLBACK(on_menu_tabsClosed_item_activate), browser);
gtk_widget_show(menuitem);
}
void on_menu_tabsClosed_item_activate(GtkWidget* menuitem, CBrowser* browser)
{
// Create a new webView with an uri which has been closed before
- XbelItem* item = g_object_get_data(G_OBJECT(menuitem), "XbelItem");
- const gchar* uri = xbel_bookmark_get_href(item);
+ KatzeXbelItem* item = g_object_get_data(G_OBJECT(menuitem), "KatzeXbelItem");
+ const gchar* uri = katze_xbel_bookmark_get_href(item);
CBrowser* curBrowser = browser_new(browser);
webView_open(curBrowser->webView, uri);
- xbel_item_unref(item);
+ katze_xbel_item_unref(item);
update_browser_actions(curBrowser);
}
void on_action_tabsClosed_undo_activate(GtkAction* action, CBrowser* browser)
{
// Open the most recent tabtrash item
- XbelItem* item = xbel_folder_get_nth_item(tabtrash, 0);
- const gchar* uri = xbel_bookmark_get_href(item);
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(tabtrash, 0);
+ const gchar* uri = katze_xbel_bookmark_get_href(item);
CBrowser* curBrowser = browser_new(browser);
webView_open(curBrowser->webView, uri);
- xbel_item_unref(item);
+ katze_xbel_item_unref(item);
update_browser_actions(curBrowser);
}
void on_action_tabsClosed_clear_activate(GtkAction* action, CBrowser* browser)
{
// Clear the closed tabs list
- xbel_item_unref(tabtrash);
- tabtrash = xbel_folder_new();
+ katze_xbel_item_unref(tabtrash);
+ tabtrash = katze_xbel_folder_new();
update_browser_actions(browser);
}
gtk_clipboard_set_text(clipboard, browser->elementUri, -1);
}
-static void browser_editBookmark_dialog_new(XbelItem* bookmark, CBrowser* browser)
+static void browser_editBookmark_dialog_new(KatzeXbelItem* bookmark, CBrowser* browser)
{
gboolean newBookmark = !bookmark;
GtkWidget* dialog = gtk_dialog_new_with_buttons(
GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
if(newBookmark)
- bookmark = xbel_bookmark_new();
+ bookmark = katze_xbel_bookmark_new();
GtkWidget* hbox = gtk_hbox_new(FALSE, 8);
gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
gtk_entry_set_activates_default(GTK_ENTRY(entry_title), TRUE);
if(!newBookmark)
{
- const gchar* title = xbel_item_get_title(bookmark);
+ const gchar* title = katze_xbel_item_get_title(bookmark);
gtk_entry_set_text(GTK_ENTRY(entry_title), title ? title : "");
}
gtk_box_pack_start(GTK_BOX(hbox), entry_title, TRUE, TRUE, 0);
gtk_entry_set_activates_default(GTK_ENTRY(entry_desc), TRUE);
if(!newBookmark)
{
- const gchar* desc = xbel_item_get_desc(bookmark);
+ const gchar* desc = katze_xbel_item_get_desc(bookmark);
gtk_entry_set_text(GTK_ENTRY(entry_desc), desc ? desc : "");
}
gtk_box_pack_start(GTK_BOX(hbox), entry_desc, TRUE, TRUE, 0);
gtk_widget_show_all(hbox);
GtkWidget* entry_uri = NULL;
- if(xbel_item_is_bookmark(bookmark))
+ if(katze_xbel_item_is_bookmark(bookmark))
{
hbox = gtk_hbox_new(FALSE, 8);
gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
entry_uri = gtk_entry_new();
gtk_entry_set_activates_default(GTK_ENTRY(entry_uri), TRUE);
if(!newBookmark)
- gtk_entry_set_text(GTK_ENTRY(entry_uri), xbel_bookmark_get_href(bookmark));
+ gtk_entry_set_text(GTK_ENTRY(entry_uri), katze_xbel_bookmark_get_href(bookmark));
gtk_box_pack_start(GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
gtk_widget_show_all(hbox);
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
{
- xbel_item_set_title(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_title)));
- xbel_item_set_desc(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_desc)));
- if(xbel_item_is_bookmark(bookmark))
- xbel_bookmark_set_href(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_uri)));
+ katze_xbel_item_set_title(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_title)));
+ katze_xbel_item_set_desc(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_desc)));
+ if(katze_xbel_item_is_bookmark(bookmark))
+ katze_xbel_bookmark_set_href(bookmark, gtk_entry_get_text(GTK_ENTRY(entry_uri)));
// FIXME: We want to choose a folder
if(newBookmark)
- xbel_folder_append_item(bookmarks, bookmark);
+ katze_xbel_folder_append_item(bookmarks, bookmark);
}
gtk_widget_destroy(dialog);
}
GtkTreeIter iter;
if(gtk_tree_model_get_iter(model, &iter, path))
{
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- if(xbel_item_is_bookmark(item))
- webView_open(get_nth_webView(-1, browser), xbel_bookmark_get_href(item));
+ if(katze_xbel_item_is_bookmark(item))
+ webView_open(get_nth_webView(-1, browser), katze_xbel_bookmark_get_href(item));
}
}
static void panel_bookmarks_popup(GtkWidget* widget, GdkEventButton* event
- , XbelItem* item, CBrowser* browser)
+ , KatzeXbelItem* item, CBrowser* browser)
{
- gboolean isBookmark = xbel_item_is_bookmark(item);
- gboolean isSeparator = xbel_item_is_separator(item);
+ gboolean isBookmark = katze_xbel_item_is_bookmark(item);
+ gboolean isSeparator = katze_xbel_item_is_separator(item);
action_set_sensitive("BookmarkOpen", isBookmark, browser);
action_set_sensitive("BookmarkOpenTab", isBookmark, browser);
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- if(event->button == 2 && xbel_item_is_bookmark(item))
+ if(event->button == 2 && katze_xbel_item_is_bookmark(item))
{
CBrowser* newBrowser = browser_new(browser);
- const gchar* uri = xbel_bookmark_get_href(item);
+ const gchar* uri = katze_xbel_bookmark_get_href(item);
webView_open(newBrowser->webView, uri);
}
else
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
panel_bookmarks_popup(widget, NULL, item, browser);
}
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- if(xbel_item_is_bookmark(item))
- webView_open(get_nth_webView(-1, browser), xbel_bookmark_get_href(item));
+ if(katze_xbel_item_is_bookmark(item))
+ webView_open(get_nth_webView(-1, browser), katze_xbel_bookmark_get_href(item));
}
}
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- if(xbel_item_is_bookmark(item))
+ if(katze_xbel_item_is_bookmark(item))
{
CBrowser* newBrowser = browser_new(browser);
- const gchar* uri = xbel_bookmark_get_href(item);
+ const gchar* uri = katze_xbel_bookmark_get_href(item);
webView_open(newBrowser->webView, uri);
}
}
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- if(xbel_item_is_bookmark(item))
+ if(katze_xbel_item_is_bookmark(item))
{
CBrowser* newBrowser = browser_new(NULL);
- const gchar* uri = xbel_bookmark_get_href(item);
+ const gchar* uri = katze_xbel_bookmark_get_href(item);
webView_open(newBrowser->webView, uri);
}
}
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- if(!xbel_item_is_separator(item))
+ if(!katze_xbel_item_is_separator(item))
browser_editBookmark_dialog_new(item, browser);
}
}
GtkTreeModel* model;
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection, &model, &iter);
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
- XbelItem* parent = xbel_item_get_parent(item);
- xbel_folder_remove_item(parent, item);
- xbel_item_unref(item);
+ KatzeXbelItem* parent = katze_xbel_item_get_parent(item);
+ katze_xbel_folder_remove_item(parent, item);
+ katze_xbel_item_unref(item);
}
}
static void tree_store_insert_folder(GtkTreeStore* treestore, GtkTreeIter* parent
- , XbelItem* folder)
+ , KatzeXbelItem* folder)
{
- guint n = xbel_folder_get_n_items(folder);
+ guint n = katze_xbel_folder_get_n_items(folder);
guint i;
for(i = 0; i < n; i++)
{
- XbelItem* item = xbel_folder_get_nth_item(folder, i);
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(folder, i);
GtkTreeIter iter;
gtk_tree_store_insert_with_values(treestore, &iter, parent, n, 0, item, -1);
- xbel_item_ref(item);
- if(xbel_item_is_folder(item))
+ katze_xbel_item_ref(item);
+ if(katze_xbel_item_is_folder(item))
tree_store_insert_folder(treestore, &iter, item);
}
}
, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter
, GtkWidget* treeview)
{
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, iter, 0, &item, -1);
- if(!xbel_item_get_parent(item))
+ if(!katze_xbel_item_get_parent(item))
{
gtk_tree_store_remove(GTK_TREE_STORE(model), iter);
- xbel_item_unref(item);
+ katze_xbel_item_unref(item);
return;
}
// TODO: Would it be better to not do this on every redraw?
GdkPixbuf* pixbuf = NULL;
- if(xbel_item_is_bookmark(item))
+ if(katze_xbel_item_is_bookmark(item))
pixbuf = gtk_widget_render_icon(treeview, STOCK_BOOKMARK
, GTK_ICON_SIZE_MENU, NULL);
- else if(xbel_item_is_folder(item))
+ else if(katze_xbel_item_is_folder(item))
pixbuf = gtk_widget_render_icon(treeview, GTK_STOCK_DIRECTORY
, GTK_ICON_SIZE_MENU, NULL);
g_object_set(renderer, "pixbuf", pixbuf, NULL);
, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter
, GtkWidget* treeview)
{
- XbelItem* item;
+ KatzeXbelItem* item;
gtk_tree_model_get(model, iter, 0, &item, -1);
- if(!xbel_item_get_parent(item))
+ if(!katze_xbel_item_get_parent(item))
{
gtk_tree_store_remove(GTK_TREE_STORE(model), iter);
- xbel_item_unref(item);
+ katze_xbel_item_unref(item);
return;
}
- if(xbel_item_is_separator(item))
+ if(katze_xbel_item_is_separator(item))
g_object_set(renderer
, "markup", "<i>Separator</i>", NULL);
else
g_object_set(renderer
- , "markup", NULL, "text", xbel_item_get_title(item), NULL);
+ , "markup", NULL, "text", katze_xbel_item_get_title(item), NULL);
}
-static void create_bookmark_menu(XbelItem*, GtkWidget*, CBrowser*);
+static void create_bookmark_menu(KatzeXbelItem*, GtkWidget*, CBrowser*);
static void on_bookmark_menu_folder_activate(GtkWidget* menuitem, CBrowser* browser)
{
GtkWidget* menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menuitem));
gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)gtk_widget_destroy, NULL);//...
- XbelItem* folder = (XbelItem*)g_object_get_data(G_OBJECT(menuitem), "XbelItem");
+ KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT(menuitem), "KatzeXbelItem");
create_bookmark_menu(folder, menu, browser);
// Remove all menuitems when the menu is hidden.
// FIXME: We really *want* the line below, but it won't work like that
static void on_bookmark_toolbar_folder_activate(GtkToolItem* toolitem, CBrowser* browser)
{
GtkWidget* menu = gtk_menu_new();
- XbelItem* folder = (XbelItem*)g_object_get_data(G_OBJECT(toolitem), "XbelItem");
+ KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT(toolitem), "KatzeXbelItem");
create_bookmark_menu(folder, menu, browser);
// Remove all menuitems when the menu is hidden.
// FIXME: We really *should* run the line below, but it won't work like that
void on_menu_bookmarks_item_activate(GtkWidget* widget, CBrowser* browser)
{
- XbelItem* item = (XbelItem*)g_object_get_data(G_OBJECT(widget), "XbelItem");
- webView_open(get_nth_webView(-1, browser), xbel_bookmark_get_href(item));
+ KatzeXbelItem* item = (KatzeXbelItem*)g_object_get_data(G_OBJECT(widget), "KatzeXbelItem");
+ webView_open(get_nth_webView(-1, browser), katze_xbel_bookmark_get_href(item));
}
-static void create_bookmark_menu(XbelItem* folder, GtkWidget* menu, CBrowser* browser)
+static void create_bookmark_menu(KatzeXbelItem* folder, GtkWidget* menu, CBrowser* browser)
{
- guint n = xbel_folder_get_n_items(folder);
+ guint n = katze_xbel_folder_get_n_items(folder);
guint i;
for(i = 0; i < n; i++)
{
- XbelItem* item = xbel_folder_get_nth_item(folder, i);
- const gchar* title = xbel_item_is_separator(item) ? "" : xbel_item_get_title(item);
- //const gchar* desc = xbel_item_is_separator(item) ? "" : xbel_item_get_desc(item);
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(folder, i);
+ const gchar* title = katze_xbel_item_is_separator(item) ? "" : katze_xbel_item_get_title(item);
+ //const gchar* desc = katze_xbel_item_is_separator(item) ? "" : katze_xbel_item_get_desc(item);
GtkWidget* menuitem = NULL;
- switch(xbel_item_get_kind(item))
+ switch(katze_xbel_item_get_kind(item))
{
- case XBEL_ITEM_FOLDER:
- // FIXME: what about xbel_folder_is_folded?
+ case KATZE_XBEL_ITEM_KIND_FOLDER:
+ // FIXME: what about katze_xbel_folder_is_folded?
menuitem = gtk_image_menu_item_new_with_label(title);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem)
, gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU));
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), _menu);
g_signal_connect(menuitem, "activate"
, G_CALLBACK(on_bookmark_menu_folder_activate), browser);
- g_object_set_data(G_OBJECT(menuitem), "XbelItem", item);
+ g_object_set_data(G_OBJECT(menuitem), "KatzeXbelItem", item);
break;
- case XBEL_ITEM_BOOKMARK:
+ case KATZE_XBEL_ITEM_KIND_BOOKMARK:
menuitem = menu_item_new(title, STOCK_BOOKMARK
, G_CALLBACK(on_menu_bookmarks_item_activate), TRUE, browser);
- g_object_set_data(G_OBJECT(menuitem), "XbelItem", item);
+ g_object_set_data(G_OBJECT(menuitem), "KatzeXbelItem", item);
break;
- case XBEL_ITEM_SEPARATOR:
+ case KATZE_XBEL_ITEM_KIND_SEPARATOR:
menuitem = gtk_separator_menu_item_new();
break;
default:
{
// Preserve changes to the uri
/*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget));
- xbel_bookmark_set_href(browser->sessionItem, newUri);*/
+ katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/
// FIXME: If we want this feature, this is the wrong approach
}
{
GtkWidget* webView = get_nth_webView(page_num, browser);
browser = get_browser_from_webView(webView);
- const gchar* uri = xbel_bookmark_get_href(browser->sessionItem);
+ const gchar* uri = katze_xbel_bookmark_get_href(browser->sessionItem);
gtk_entry_set_text(GTK_ENTRY(browser->location), uri);
- const gchar* title = xbel_item_get_title(browser->sessionItem);
+ const gchar* title = katze_xbel_item_get_title(browser->sessionItem);
const gchar* effectiveTitle = title ? title : uri;
gchar* windowTitle = g_strconcat(effectiveTitle, " - ", PACKAGE_NAME, NULL);
gtk_window_set_title(GTK_WINDOW(browser->window), windowTitle);
{
CBrowser* browser = g_new0(CBrowser, 1);
browsers = g_list_prepend(browsers, browser);
- browser->sessionItem = xbel_bookmark_new();
- xbel_item_set_title(browser->sessionItem, "about:blank");
- xbel_folder_append_item(session, browser->sessionItem);
+ browser->sessionItem = katze_xbel_bookmark_new();
+ katze_xbel_item_set_title(browser->sessionItem, "about:blank");
+ katze_xbel_folder_append_item(session, browser->sessionItem);
GtkWidget* scrolled;
gtk_toolbar_set_icon_size(GTK_TOOLBAR(browser->bookmarkbar), GTK_ICON_SIZE_MENU);
gtk_toolbar_set_style(GTK_TOOLBAR(browser->bookmarkbar), GTK_TOOLBAR_BOTH_HORIZ);
create_bookmark_menu(bookmarks, browser->menu_bookmarks, browser);
- for(i = 0; i < xbel_folder_get_n_items(bookmarks); i++)
+ for(i = 0; i < katze_xbel_folder_get_n_items(bookmarks); i++)
{
- XbelItem* item = xbel_folder_get_nth_item(bookmarks, i);
- const gchar* title = xbel_item_is_separator(item)
- ? "" : xbel_item_get_title(item);
- const gchar* desc = xbel_item_is_separator(item)
- ? "" : xbel_item_get_desc(item);
- switch(xbel_item_get_kind(item))
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(bookmarks, i);
+ const gchar* title = katze_xbel_item_is_separator(item)
+ ? "" : katze_xbel_item_get_title(item);
+ const gchar* desc = katze_xbel_item_is_separator(item)
+ ? "" : katze_xbel_item_get_desc(item);
+ switch(katze_xbel_item_get_kind(item))
{
- case XBEL_ITEM_FOLDER:
+ case KATZE_XBEL_ITEM_KIND_FOLDER:
toolitem = tool_button_new(title, GTK_STOCK_DIRECTORY, TRUE, TRUE
, G_CALLBACK(on_bookmark_toolbar_folder_activate), desc, browser);
- g_object_set_data(G_OBJECT(toolitem), "XbelItem", item);
+ g_object_set_data(G_OBJECT(toolitem), "KatzeXbelItem", item);
break;
- case XBEL_ITEM_BOOKMARK:
+ case KATZE_XBEL_ITEM_KIND_BOOKMARK:
toolitem = tool_button_new(title, STOCK_BOOKMARK, TRUE, TRUE
, G_CALLBACK(on_menu_bookmarks_item_activate), desc, browser);
- g_object_set_data(G_OBJECT(toolitem), "XbelItem", item);
+ g_object_set_data(G_OBJECT(toolitem), "KatzeXbelItem", item);
break;
- case XBEL_ITEM_SEPARATOR:
+ case KATZE_XBEL_ITEM_KIND_SEPARATOR:
toolitem = gtk_separator_tool_item_new();
break;
default:
// Bookmarks
GtkTreeViewColumn* column;
GtkCellRenderer* renderer_text; GtkCellRenderer* renderer_pixbuf;
- GtkTreeStore* treestore = gtk_tree_store_new(1, G_TYPE_XBEL_ITEM);
+ GtkTreeStore* treestore = gtk_tree_store_new(1, KATZE_TYPE_XBEL_ITEM);
GtkWidget* treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(treestore));
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
column = gtk_tree_view_column_new();
katze_throbber_set_static_stock_id(KATZE_THROBBER(browser->webView_icon)
, GTK_STOCK_FILE);
gtk_box_pack_start(GTK_BOX(hbox), browser->webView_icon, FALSE, FALSE, 0);
- browser->webView_name = gtk_label_new(xbel_item_get_title(browser->sessionItem));
+ browser->webView_name = gtk_label_new(katze_xbel_item_get_title(browser->sessionItem));
gtk_misc_set_alignment(GTK_MISC(browser->webView_name), 0.0, 0.5);
// TODO: make the tab initially look "unvisited" until it's focused
// TODO: gtk's tab scrolling is weird?
//UNDEFINED favicon;
guint security;
gchar* statusMessage; // message from a webView
- XbelItem* sessionItem;
+ KatzeXbelItem* sessionItem;
} CBrowser;
enum
#define __GLOBAL_H__ 1
#include "conf.h"
-#include "xbel.h"
+#include "../katze/katze.h"
#include <gtk/gtk.h>
GList* searchEngines; // Items of type 'SearchEngine'
GList* browsers; // Items of type 'CBrowser'
GtkAccelGroup* accel_group;
-XbelItem* bookmarks;
-XbelItem* session;
-XbelItem* tabtrash;
+KatzeXbelItem* bookmarks;
+KatzeXbelItem* session;
+KatzeXbelItem* tabtrash;
// Custom stock items
void update_security(CBrowser* browser)
{
- const gchar* uri = xbel_bookmark_get_href(browser->sessionItem);
+ const gchar* uri = katze_xbel_bookmark_get_href(browser->sessionItem);
// TODO: This check is bogus, until webkit tells us how secure a page is
if(g_str_has_prefix(uri, "https://"))
{
action_set_sensitive("TabPrevious", active, browser);
action_set_sensitive("TabNext", active, browser);
- gboolean tabtrashEmpty = xbel_folder_is_empty(tabtrash);
+ gboolean tabtrashEmpty = katze_xbel_folder_is_empty(tabtrash);
action_set_sensitive("UndoTabClose", !tabtrashEmpty, browser);
action_set_sensitive("TabsClosed", !tabtrashEmpty, browser);
}
#include "sokoke.h"
#include "search.h"
#include "webView.h"
-#include "xbel.h"
+#include "../katze/katze.h"
#include <string.h>
#include <gtk/gtk.h>
}
g_free(configFile);
configFile = g_build_filename(configPath, "bookmarks.xbel", NULL);
- bookmarks = xbel_folder_new();
+ bookmarks = katze_xbel_folder_new();
error = NULL;
- if(!xbel_folder_from_file(bookmarks, configFile, &error))
+ if(!katze_xbel_folder_from_file(bookmarks, configFile, &error))
{
if(error->code != G_FILE_ERROR_NOENT)
g_string_append_printf(errorMessages
g_error_free(error);
}
g_free(configFile);
- XbelItem* _session = xbel_folder_new();
+ KatzeXbelItem* _session = katze_xbel_folder_new();
if(config->startup == CONFIG_STARTUP_SESSION)
{
configFile = g_build_filename(configPath, "session.xbel", NULL);
error = NULL;
- if(!xbel_folder_from_file(_session, configFile, &error))
+ if(!katze_xbel_folder_from_file(_session, configFile, &error))
{
if(error->code != G_FILE_ERROR_NOENT)
g_string_append_printf(errorMessages
g_free(configFile);
}
configFile = g_build_filename(configPath, "tabtrash.xbel", NULL);
- tabtrash = xbel_folder_new();
+ tabtrash = katze_xbel_folder_new();
error = NULL;
- if(!xbel_folder_from_file(tabtrash, configFile, &error))
+ if(!katze_xbel_folder_from_file(tabtrash, configFile, &error))
{
if(error->code != G_FILE_ERROR_NOENT)
g_string_append_printf(errorMessages
{
config_free(config);
search_engines_free(searchEngines);
- xbel_item_unref(bookmarks);
- xbel_item_unref(_session);
+ katze_xbel_item_unref(bookmarks);
+ katze_xbel_item_unref(_session);
g_string_free(errorMessages, TRUE);
return 0;
}
gchar* uri = argc > 1 ? strtok(g_strdup(argv[1]), "|") : NULL;
while(uri != NULL)
{
- XbelItem* item = xbel_bookmark_new();
+ KatzeXbelItem* item = katze_xbel_bookmark_new();
gchar* uriReady = magic_uri(uri, FALSE);
- xbel_bookmark_set_href(item, uriReady);
+ katze_xbel_bookmark_set_href(item, uriReady);
g_free(uriReady);
- xbel_folder_append_item(_session, item);
+ katze_xbel_folder_append_item(_session, item);
uri = strtok(NULL, "|");
}
g_free(uri);
- if(xbel_folder_is_empty(_session))
+ if(katze_xbel_folder_is_empty(_session))
{
- XbelItem* item = xbel_bookmark_new();
+ KatzeXbelItem* item = katze_xbel_bookmark_new();
if(config->startup == CONFIG_STARTUP_BLANK)
- xbel_bookmark_set_href(item, "about:blank");
+ katze_xbel_bookmark_set_href(item, "about:blank");
else
- xbel_bookmark_set_href(item, config->homepage);
- xbel_folder_prepend_item(_session, item);
+ katze_xbel_bookmark_set_href(item, config->homepage);
+ katze_xbel_folder_prepend_item(_session, item);
}
g_free(configPath);
stock_items_init();
browsers = NULL;
- session = xbel_folder_new();
+ session = katze_xbel_folder_new();
CBrowser* browser = NULL;
- guint n = xbel_folder_get_n_items(_session);
+ guint n = katze_xbel_folder_get_n_items(_session);
guint i;
for(i = 0; i < n; i++)
{
- XbelItem* item = xbel_folder_get_nth_item(_session, i);
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(_session, i);
browser = browser_new(browser);
- webView_open(browser->webView, xbel_bookmark_get_href(item));
+ webView_open(browser->webView, katze_xbel_bookmark_get_href(item));
}
- xbel_item_unref(_session);
+ katze_xbel_item_unref(_session);
gtk_main();
g_free(configFile);
configFile = g_build_filename(configPath, "bookmarks.xbel", NULL);
error = NULL;
- if(!xbel_folder_to_file(bookmarks, configFile, &error))
+ if(!katze_xbel_folder_to_file(bookmarks, configFile, &error))
{
g_warning("Bookmarks couldn't be saved. %s", error->message);
g_error_free(error);
}
- xbel_item_unref(bookmarks);
+ katze_xbel_item_unref(bookmarks);
g_free(configFile);
configFile = g_build_filename(configPath, "tabtrash.xbel", NULL);
error = NULL;
- if(!xbel_folder_to_file(tabtrash, configFile, &error))
+ if(!katze_xbel_folder_to_file(tabtrash, configFile, &error))
{
g_warning("Tabtrash couldn't be saved. %s", error->message);
g_error_free(error);
}
- xbel_item_unref(tabtrash);
+ katze_xbel_item_unref(tabtrash);
g_free(configFile);
if(config->startup == CONFIG_STARTUP_SESSION)
{
configFile = g_build_filename(configPath, "session.xbel", NULL);
error = NULL;
- if(!xbel_folder_to_file(session, configFile, &error))
+ if(!katze_xbel_folder_to_file(session, configFile, &error))
{
g_warning("Session couldn't be saved. %s", error->message);
g_error_free(error);
}
g_free(configFile);
}
- xbel_item_unref(session);
+ katze_xbel_item_unref(session);
configFile = g_build_filename(configPath, "config", NULL);
error = NULL;
if(!config_to_file(config, configFile, &error))
#include "helpers.h"
#include "sokoke.h"
-#include "xbel.h"
+#include "../katze/katze.h"
#include <string.h>
newTitle = title;
else
newTitle = webkit_web_frame_get_uri(frame);
- xbel_item_set_title(browser->sessionItem, newTitle);
+ katze_xbel_item_set_title(browser->sessionItem, newTitle);
gtk_label_set_text(GTK_LABEL(browser->webView_name), newTitle);
sokoke_widget_set_tooltip_text(gtk_widget_get_parent(
gtk_widget_get_parent(browser->webView_name)), newTitle);
{
const gchar* uri = webkit_web_frame_get_uri(frame);
gchar* newUri = g_strdup(uri ? uri : "");
- xbel_bookmark_set_href(browser->sessionItem, newUri);
+ katze_xbel_bookmark_set_href(browser->sessionItem, newUri);
if(webView == get_nth_webView(-1, browser))
{
gtk_entry_set_text(GTK_ENTRY(browser->location), newUri);
g_object_unref(browser->popup_element);
g_object_unref(browser->popup_editable);
guint i;
- guint n = xbel_folder_get_n_items(bookmarks);
+ guint n = katze_xbel_folder_get_n_items(bookmarks);
for(i = 0; i < n; i++)
- xbel_item_unref(xbel_folder_get_nth_item(bookmarks, i));
+ katze_xbel_item_unref(katze_xbel_folder_get_nth_item(bookmarks, i));
gtk_main_quit();
}
}
CBrowser* browser = get_browser_from_webView(webView);
if(browser)
{
- xbel_bookmark_set_href(browser->sessionItem, uri);
- xbel_item_set_title(browser->sessionItem, "");
+ katze_xbel_bookmark_set_href(browser->sessionItem, uri);
+ katze_xbel_item_set_title(browser->sessionItem, "");
}
}
void webView_close(GtkWidget* webView, CBrowser* browser)
{
browser = get_browser_from_webView(webView);
- const gchar* uri = xbel_bookmark_get_href(browser->sessionItem);
- xbel_folder_remove_item(session, browser->sessionItem);
+ const gchar* uri = katze_xbel_bookmark_get_href(browser->sessionItem);
+ katze_xbel_folder_remove_item(session, browser->sessionItem);
if(uri && *uri)
{
- xbel_folder_prepend_item(tabtrash, browser->sessionItem);
- guint n = xbel_folder_get_n_items(tabtrash);
+ katze_xbel_folder_prepend_item(tabtrash, browser->sessionItem);
+ guint n = katze_xbel_folder_get_n_items(tabtrash);
if(n > 10)
{
- XbelItem* item = xbel_folder_get_nth_item(tabtrash, n - 1);
- xbel_item_unref(item);
+ KatzeXbelItem* item = katze_xbel_folder_get_nth_item(tabtrash, n - 1);
+ katze_xbel_item_unref(item);
}
}
else
- xbel_item_unref(browser->sessionItem);
+ katze_xbel_item_unref(browser->sessionItem);
gtk_widget_destroy(browser->webView_menu);
gtk_notebook_remove_page(GTK_NOTEBOOK(browser->webViews)
, get_webView_index(webView, browser));
+++ /dev/null
-/*
- Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
-
- 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.
-
- See the file COPYING for the full license text.
-*/
-
-/**
- * This is an implementation of XBEL based on Glib and libXML2.
- *
- * Design Goals:
- * - XbelItem is the only opaque public data structure.
- * - The interface should be intuitive and familiar to Glib users.
- * - There should be no public exposure of libXML2 specific code.
- * - Bookmarks should actually be easily exchangeable between programs.
- *
- * TODO:
- * - Support info > metadata, alias, added, modified, visited
- * - Compatibility: The Nokia 770 *requires* metadata and folder
- * - Compatibility: Kazehakase's bookmarks
- * - Compatibility: Epiphany's bookmarks
- * - XML Indentation
- * - Export and import to other formats
- **/
-
-#include "xbel.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
-// Private: Create a new item of a certain type
-static XbelItem* xbel_item_new(XbelItemKind kind)
-{
- XbelItem* item = g_new(XbelItem, 1);
- item->refs = 1;
- item->parent = NULL;
- item->kind = kind;
- if(kind == XBEL_ITEM_FOLDER)
- {
- item->items = NULL;
- item->folded = TRUE;
- }
- if(kind != XBEL_ITEM_SEPARATOR)
- {
- item->title = NULL;
- item->desc = NULL;
- }
- if(kind == XBEL_ITEM_BOOKMARK)
- item->href = g_strdup("");
- return item;
-}
-
-/**
- * xbel_bookmark_new:
- *
- * Create a new empty bookmark.
- *
- * Return value: a newly allocated bookmark
- **/
-XbelItem* xbel_bookmark_new(void)
-{
- return xbel_item_new(XBEL_ITEM_BOOKMARK);
-}
-
-static XbelItem* xbel_bookmark_from_xmlNodePtr(xmlNodePtr cur)
-{
- g_return_val_if_fail(cur != NULL, NULL);
- XbelItem* bookmark = xbel_bookmark_new();
- xmlChar* key = xmlGetProp(cur, (xmlChar*)"href");
- xbel_bookmark_set_href(bookmark, (gchar*)key);
- cur = cur->xmlChildrenNode;
- while(cur != NULL)
- {
- if(!xmlStrcmp(cur->name, (const xmlChar*)"title"))
- {
- xmlChar* key = xmlNodeGetContent(cur);
- bookmark->title = (gchar*)g_strstrip((gchar*)key);
- }
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"desc"))
- {
- xmlChar* key = xmlNodeGetContent(cur);
- bookmark->desc = (gchar*)g_strstrip((gchar*)key);
- }
- cur = cur->next;
- }
- return bookmark;
-}
-
-/**
- * xbel_separator_new:
- *
- * Create a new separator.
- *
- * The returned item must be freed eventually.
- *
- * Return value: a newly allocated separator.
- **/
-XbelItem* xbel_separator_new(void)
-{
- return xbel_item_new(XBEL_ITEM_SEPARATOR);
-}
-
-/**
- * xbel_folder_new:
- *
- * Create a new empty folder.
- *
- * The returned item must be freed eventually.
- *
- * Return value: a newly allocated folder.
- **/
-XbelItem* xbel_folder_new(void)
-{
- return xbel_item_new(XBEL_ITEM_FOLDER);
-}
-
-// Private: Create a folder from an xmlNodePtr
-static XbelItem* xbel_folder_from_xmlNodePtr(xmlNodePtr cur)
-{
- g_return_val_if_fail(cur != NULL, NULL);
- XbelItem* folder = xbel_folder_new();
- xmlChar* key = xmlGetProp(cur, (xmlChar*)"folded");
- if(key)
- {
- if(!g_ascii_strncasecmp((gchar*)key, "yes", 3))
- folder->folded = TRUE;
- else if(!g_ascii_strncasecmp((gchar*)key, "no", 2))
- folder->folded = FALSE;
- else
- g_warning("XBEL: Unknown value for folded.");
- xmlFree(key);
- }
- cur = cur->xmlChildrenNode;
- while(cur)
- {
- if(!xmlStrcmp(cur->name, (const xmlChar*)"title"))
- {
- xmlChar* key = xmlNodeGetContent(cur);
- folder->title = (gchar*)g_strstrip((gchar*)key);
- }
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"desc"))
- {
- xmlChar* key = xmlNodeGetContent(cur);
- folder->desc = (gchar*)g_strstrip((gchar*)key);
- }
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"folder"))
- {
- XbelItem* item = xbel_folder_from_xmlNodePtr(cur);
- item->parent = (struct XbelItem*)folder;
- folder->items = g_list_prepend(folder->items, item);
- }
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"bookmark"))
- {
- XbelItem* item = xbel_bookmark_from_xmlNodePtr(cur);
- item->parent = (struct XbelItem*)folder;
- folder->items = g_list_prepend(folder->items, item);
- }
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"separator"))
- {
- XbelItem* item = xbel_separator_new();
- item->parent = (struct XbelItem*)folder;
- folder->items = g_list_prepend(folder->items, item);
- }
- cur = cur->next;
- }
- // Prepending and reversing is faster than appending
- folder->items = g_list_reverse(folder->items);
- return folder;
-}
-
-// Private: Loads the contents from an xmlNodePtr into a folder.
-static gboolean xbel_folder_from_xmlDocPtr(XbelItem* folder, xmlDocPtr doc)
-{
- g_return_val_if_fail(xbel_folder_is_empty(folder), FALSE);
- g_return_val_if_fail(doc != NULL, FALSE);
- xmlNodePtr cur = xmlDocGetRootElement(doc);
- xmlChar* version = xmlGetProp(cur, (xmlChar*)"version");
- if(xmlStrcmp(version, (xmlChar*)"1.0"))
- g_warning("XBEL version is not 1.0.");
- xmlFree(version);
- folder->title = (gchar*)xmlGetProp(cur, (xmlChar*)"title");
- folder->desc = (gchar*)xmlGetProp(cur, (xmlChar*)"desc");
- if((cur = xmlDocGetRootElement(doc)) == NULL)
- {
- // Empty document
- return FALSE;
- }
- if(xmlStrcmp(cur->name, (const xmlChar*)"xbel"))
- {
- // Wrong document kind
- return FALSE;
- }
- cur = cur->xmlChildrenNode;
- while(cur != NULL)
- {
- XbelItem* item = NULL;
- if(!xmlStrcmp(cur->name, (const xmlChar*)"folder"))
- item = xbel_folder_from_xmlNodePtr(cur);
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"bookmark"))
- item = xbel_bookmark_from_xmlNodePtr(cur);
- else if(!xmlStrcmp(cur->name, (const xmlChar*)"separator"))
- item = xbel_separator_new();
- /*else if(!xmlStrcmp(cur->name, (const xmlChar*)"info"))
- item = xbel_parse_info(xbel, cur);*/
- if(item != NULL)
- {
- item->parent = (struct XbelItem*)folder;
- folder->items = g_list_prepend(folder->items, item);
- }
- cur = cur->next;
- }
- // Prepending and reversing is faster than appending
- folder->items = g_list_reverse(folder->items);
- return TRUE;
-}
-
-/**
- * xbel_item_ref:
- * @item: a valid item
- *
- * Ref an XbelItem.
- *
- * Ref means that the reference count is increased by one.
- *
- * This has no effect on children of a folder.
- **/
-void xbel_item_ref(XbelItem* item)
-{
- g_return_if_fail(item);
- item->refs++;
-}
-
-/**
- * xbel_item_unref:
- * @item: a valid item
- *
- * Unref an XbelItem. If @item is a folder all of its children will also
- * be unreffed automatically.
- *
- * Unref means that the reference count is decreased. If there are no
- * references left, the memory will be freed and if needed removed from
- * its containing folder.
- **/
-void xbel_item_unref(XbelItem* item)
-{
- g_return_if_fail(item);
- item->refs--;
- if(item->refs)
- return;
- XbelItem* parent = xbel_item_get_parent(item);
- if(parent)
- xbel_folder_remove_item(parent, item);
- if(xbel_item_is_folder(item))
- {
- guint n = xbel_folder_get_n_items(item);
- guint i;
- for(i = 0; i < n; i++)
- {
- XbelItem* _item = xbel_folder_get_nth_item(item, i);
- _item->parent = NULL;
- xbel_item_unref(_item);
- }
- g_list_free(item->items);
- }
- if(item->kind != XBEL_ITEM_SEPARATOR)
- {
- g_free(item->title);
- g_free(item->desc);
- }
- if(item->kind == XBEL_ITEM_BOOKMARK)
- g_free(item->href);
- g_free(item);
-}
-
-/**
- * xbel_item_copy:
- * @item: the item to copy
- *
- * Copy an XbelItem.
- *
- * The returned item must be unreffed eventually.
- *
- * Return value: a copy of @item
- **/
-XbelItem* xbel_item_copy(XbelItem* item)
-{
- g_return_val_if_fail(item, NULL);
- XbelItem* copy = xbel_folder_new();
- if(xbel_item_is_folder(item))
- {
- guint n = xbel_folder_get_n_items(item);
- guint i;
- for(i = 0; i < n; i++)
- {
- XbelItem* _item = xbel_folder_get_nth_item(item, i);
- xbel_folder_append_item(copy, xbel_item_copy(_item));
- }
- }
- if(item->kind != XBEL_ITEM_SEPARATOR)
- {
- xbel_item_set_title(copy, item->title);
- xbel_item_set_desc(copy, item->desc);
- }
- if(item->kind == XBEL_ITEM_BOOKMARK)
- xbel_bookmark_set_href(copy, item->href);
- return copy;
-}
-
-GType xbel_item_get_type()
-{
- static GType type = 0;
- if(!type)
- type = g_pointer_type_register_static("xbel_item");
- return type;
-}
-
-/**
- * xbel_folder_append_item:
- * @folder: a folder
- * @item: the item to append
- *
- * Append the given item to a folder.
- *
- * The item is actually moved and must not be contained in another folder.
- *
- **/
-void xbel_folder_append_item(XbelItem* folder, XbelItem* item)
-{
- g_return_if_fail(!xbel_item_get_parent(item));
- g_return_if_fail(xbel_item_is_folder(folder));
- item->parent = (struct XbelItem*)folder;
- folder->items = g_list_append(folder->items, item);
-}
-
-/**
- * xbel_folder_prepend_item:
- * @folder: a folder
- * @item: the item to prepend
- *
- * Prepend the given item to a folder.
- *
- * The item is actually moved and must not be contained in another folder.
- *
- **/
-void xbel_folder_prepend_item(XbelItem* folder, XbelItem* item)
-{
- g_return_if_fail(!xbel_item_get_parent(item));
- g_return_if_fail(xbel_item_is_folder(folder));
- item->parent = (struct XbelItem*)folder;
- folder->items = g_list_prepend(folder->items, item);
-}
-
-/**
- * xbel_folder_remove_item:
- * @folder: a folder
- * @item: the item to remove
- *
- * Remove the given @item from a @folder.
- **/
-void xbel_folder_remove_item(XbelItem* folder, XbelItem* item)
-{
- g_return_if_fail(item);
- g_return_if_fail(xbel_item_get_parent(folder) != item);
- item->parent = NULL;
- // Fortunately we know that items are unique
- folder->items = g_list_remove(folder->items, item);
-}
-
-/**
- * xbel_folder_get_n_items:
- * @folder: a folder
- *
- * Retrieve the number of items contained in the given @folder.
- *
- * Return value: number of items
- **/
-guint xbel_folder_get_n_items(XbelItem* folder)
-{
- g_return_val_if_fail(xbel_item_is_folder(folder), 0);
- return g_list_length(folder->items);
-}
-
-/**
- * xbel_folder_get_nth_item:
- * @folder: a folder
- * @n: the index of an item
- *
- * Retrieve an item contained in the given @folder by its index.
- *
- * Return value: the item at the given index or %NULL
- **/
-XbelItem* xbel_folder_get_nth_item(XbelItem* folder, guint n)
-{
- g_return_val_if_fail(xbel_item_is_folder(folder), NULL);
- return (XbelItem*)g_list_nth_data(folder->items, n);
-}
-
-/**
- * xbel_folder_is_empty:
- * @folder: A folder.
- *
- * Determines wether or not a folder contains no items. This is significantly
- * faster than xbel_folder_get_n_items for this particular purpose.
- *
- * Return value: Wether the given @folder is folded.
- **/
-gboolean xbel_folder_is_empty(XbelItem* folder)
-{
- return !xbel_folder_get_nth_item(folder, 0);
-}
-
-/**
- * xbel_folder_get_folded:
- * @folder: A folder.
- *
- * Determines wether or not a folder is folded. If a folder is not folded
- * it should not be exposed in a user interface.
- *
- * New folders are folded by default.
- *
- * Return value: Wether the given @folder is folded.
- **/
-gboolean xbel_folder_get_folded(XbelItem* folder)
-{
- g_return_val_if_fail(xbel_item_is_folder(folder), TRUE);
- return folder->folded;
-}
-
-/**
- * xbel_item_get_kind:
- * @item: A item.
- *
- * Determines the kind of an item.
- *
- * Return value: The kind of the given @item.
- **/
-XbelItemKind xbel_item_get_kind(XbelItem* item)
-{
- return item->kind;
-}
-
-/**
- * xbel_item_get_parent:
- * @item: A valid item.
- *
- * Retrieves the parent folder of an item.
- *
- * Return value: The parent folder of the given @item or %NULL.
- **/
-XbelItem* xbel_item_get_parent(XbelItem* item)
-{
- g_return_val_if_fail(item, NULL);
- return (XbelItem*)item->parent;
-}
-
-/**
- * xbel_item_get_title:
- * @item: A valid item.
- *
- * Retrieves the title of an item.
- *
- * Return value: The title of the given @item or %NULL.
- **/
-G_CONST_RETURN gchar* xbel_item_get_title(XbelItem* item)
-{
- g_return_val_if_fail(!xbel_item_is_separator(item), NULL);
- return item->title;
-}
-
-/**
- * xbel_item_get_desc:
- * @item: A valid item.
- *
- * Retrieves the description of an item.
- *
- * Return value: The description of the @item or %NULL.
- **/
-G_CONST_RETURN gchar* xbel_item_get_desc(XbelItem* item)
-{
- g_return_val_if_fail(!xbel_item_is_separator(item), NULL);
- return item->desc;
-}
-
-/**
- * xbel_bookmark_get_href:
- * @bookmark: A bookmark.
- *
- * Retrieves the uri of a bookmark. The value is guaranteed to not be %NULL.
- *
- * Return value: The uri of the @bookmark.
- **/
-G_CONST_RETURN gchar* xbel_bookmark_get_href(XbelItem* bookmark)
-{
- g_return_val_if_fail(xbel_item_is_bookmark(bookmark), NULL);
- return bookmark->href;
-}
-
-/**
- * xbel_item_is_bookmark:
- * @item: A valid item.
- *
- * Determines wether or not an item is a bookmark.
- *
- * Return value: %TRUE if the @item is a bookmark.
- **/
-gboolean xbel_item_is_bookmark(XbelItem* item)
-{
- g_return_val_if_fail(item, FALSE);
- return item->kind == XBEL_ITEM_BOOKMARK;
-}
-
-/**
- * xbel_item_is_separator:
- * @item: A valid item.
- *
- * Determines wether or not an item is a separator.
- *
- * Return value: %TRUE if the @item is a separator.
- **/
-gboolean xbel_item_is_separator(XbelItem* item)
-{
- g_return_val_if_fail(item, FALSE);
- return item->kind == XBEL_ITEM_SEPARATOR;
-}
-
-/**
- * xbel_item_is_folder:
- * @item: A valid item.
- *
- * Determines wether or not an item is a folder.
- *
- * Return value: %TRUE if the item is a folder.
- **/
-gboolean xbel_item_is_folder(XbelItem* item)
-{
- g_return_val_if_fail(item, FALSE);
- return item->kind == XBEL_ITEM_FOLDER;
-}
-
-/**
- * xbel_folder_set_folded:
- * @folder: A folder.
- * @folded: TRUE if the folder is folded.
- *
- * Sets the foldedness of the @folder.
- **/
-void xbel_folder_set_folded(XbelItem* folder, gboolean folded)
-{
- g_return_if_fail(xbel_item_is_folder(folder));
- folder->folded = folded;
-}
-
-/**
- * xbel_item_set_title:
- * @item: A valid item.
- * @title: A string to use for the title.
- *
- * Sets the title of the @item.
- **/
-void xbel_item_set_title(XbelItem* item, const gchar* title)
-{
- g_return_if_fail(!xbel_item_is_separator(item));
- g_free(item->title);
- item->title = g_strdup(title);
-}
-
-/**
- * xbel_item_set_desc:
- * @item: A valid item.
- * @title: A string to use for the description.
- *
- * Sets the description of the @item.
- **/
-void xbel_item_set_desc(XbelItem* item, const gchar* desc)
-{
- g_return_if_fail(!xbel_item_is_separator(item));
- g_free(item->desc);
- item->desc = g_strdup(desc);
-}
-
-/**
- * xbel_bookmark_set_href:
- * @bookmark: A bookmark.
- * @href: A string containing a valid uri.
- *
- * Sets the uri of the bookmark.
- *
- * The uri must not be %NULL.
- *
- * This uri is not currently validated in any way. This may change in the future.
- **/
-void xbel_bookmark_set_href(XbelItem* bookmark, const gchar* href)
-{
- g_return_if_fail(xbel_item_is_bookmark(bookmark));
- g_return_if_fail(href);
- g_free(bookmark->href);
- bookmark->href = g_strdup(href);
-}
-
-gboolean xbel_folder_from_data(XbelItem* folder, const gchar* data, GError** error)
-{
- g_return_val_if_fail(xbel_folder_is_empty(folder), FALSE);
- g_return_val_if_fail(data, FALSE);
- xmlDocPtr doc;
- if((doc = xmlParseMemory(data, strlen(data))) == NULL)
- {
- // No valid xml or broken encoding
- *error = g_error_new(XBEL_ERROR, XBEL_ERROR_READ
- , "Malformed document.");
- return FALSE;
- }
- if(!xbel_folder_from_xmlDocPtr(folder, doc))
- {
- // Parsing failed
- xmlFreeDoc(doc);
- *error = g_error_new(XBEL_ERROR, XBEL_ERROR_READ
- , "Malformed document.");
- return FALSE;
- }
- xmlFreeDoc(doc);
- return TRUE;
-}
-
-/**
- * xbel_folder_from_file:
- * @folder: An empty folder.
- * @file: A relative path to a file.
- * @error: return location for a GError or %NULL
- *
- * Tries to load @file.
- *
- * Return value: %TRUE on success or %FALSE when an error occured.
- **/
-gboolean xbel_folder_from_file(XbelItem* folder, const gchar* file, GError** error)
-{
- g_return_val_if_fail(xbel_folder_is_empty(folder), FALSE);
- g_return_val_if_fail(file, FALSE);
- if(!g_file_test(file, G_FILE_TEST_EXISTS))
- {
- // File doesn't exist
- *error = g_error_new(G_FILE_ERROR, G_FILE_ERROR_NOENT
- , "File not found.");
- return FALSE;
- }
- xmlDocPtr doc;
- if((doc = xmlParseFile(file)) == NULL)
- {
- // No valid xml or broken encoding
- *error = g_error_new(XBEL_ERROR, XBEL_ERROR_READ
- , "Malformed document.");
- return FALSE;
- }
- if(!xbel_folder_from_xmlDocPtr(folder, doc))
- {
- // Parsing failed
- xmlFreeDoc(doc);
- *error = g_error_new(XBEL_ERROR, XBEL_ERROR_READ
- , "Malformed document.");
- return FALSE;
- }
- xmlFreeDoc(doc);
- return TRUE;
-}
-
-/**
- * xbel_folder_from_data_dirs:
- * @folder: An empty folder.
- * @file: A relative path to a file.
- * @full_path: return location for the full path of the file or %NULL
- * @error: return location for a GError or %NULL
- *
- * Tries to load @file from the user data dir or any of the system data dirs.
- *
- * Return value: %TRUE on success or %FALSE when an error occured.
- **/
-gboolean xbel_folder_from_data_dirs(XbelItem* folder, const gchar* file
- , gchar** full_path, GError** error)
-{
- g_return_val_if_fail(xbel_folder_is_empty(folder), FALSE);
- g_return_val_if_fail(file, FALSE);
- // FIXME: Essentially unimplemented
-
- *error = g_error_new(XBEL_ERROR, XBEL_ERROR_READ
- , "Malformed document.");
- return FALSE;
-}
-
-static gchar* xbel_xml_element(const gchar* name, const gchar* value)
-{
- if(!value)
- return g_strdup("");
- gchar* valueEscaped = g_markup_escape_text(value, -1);
- gchar* XML = g_strdup_printf("<%s>%s</%s>\n", name, valueEscaped, name);
- g_free(valueEscaped);
- return XML;
-}
-
-static gchar* xbel_item_to_data(XbelItem* item)
-{
- g_return_val_if_fail(item, NULL);
- gchar* XML = NULL;
- switch(xbel_item_get_kind(item))
- {
- case XBEL_ITEM_FOLDER:
- {
- GString* _XML = g_string_new(NULL);
- guint n = xbel_folder_get_n_items(item);
- guint i;
- for(i = 0; i < n; i++)
- {
- XbelItem* _item = xbel_folder_get_nth_item(item, i);
- gchar* itemXML = xbel_item_to_data(_item);
- g_string_append(_XML, itemXML);
- g_free(itemXML);
- }
- gchar* folded = item->folded ? NULL : g_strdup_printf(" folded=\"no\"");
- gchar* title = xbel_xml_element("title", item->title);
- gchar* desc = xbel_xml_element("desc", item->desc);
- XML = g_strdup_printf("<folder%s>\n%s%s%s</folder>\n"
- , folded ? folded : ""
- , title
- , desc
- , g_string_free(_XML, FALSE));
- g_free(folded);
- g_free(title);
- g_free(desc);
- break;
- }
- case XBEL_ITEM_BOOKMARK:
- {
- gchar* hrefEscaped = g_markup_escape_text(item->href, -1);
- gchar* href = g_strdup_printf(" href=\"%s\"", hrefEscaped);
- g_free(hrefEscaped);
- gchar* title = xbel_xml_element("title", item->title);
- gchar* desc = xbel_xml_element("desc", item->desc);
- XML = g_strdup_printf("<bookmark%s>\n%s%s%s</bookmark>\n"
- , href
- , title
- , desc
- , "");
- g_free(href);
- g_free(title);
- g_free(desc);
- break;
- }
- case XBEL_ITEM_SEPARATOR:
- XML = g_strdup("<separator/>\n");
- break;
- default:
- g_warning("XBEL: Unknown item kind");
- }
- return XML;
-}
-
-/**
- * xbel_folder_to_data:
- * @folder: A folder.
- * @length: return location for the length of the created string or %NULL
- * @error: return location for a GError or %NULL
- *
- * Retrieve the contents of @folder as a string.
- *
- * Return value: %TRUE on success or %FALSE when an error occured.
- **/
-gchar* xbel_folder_to_data(XbelItem* folder, gsize* length, GError** error)
-{
- g_return_val_if_fail(xbel_item_is_folder(folder), FALSE);
- // FIXME: length is never filled
- GString* innerXML = g_string_new(NULL);
- guint n = xbel_folder_get_n_items(folder);
- guint i;
- for(i = 0; i < n; i++)
- {
- gchar* sItem = xbel_item_to_data(xbel_folder_get_nth_item(folder, i));
- g_string_append(innerXML, sItem);
- g_free(sItem);
- }
- gchar* title = xbel_xml_element("title", folder->title);
- gchar* desc = xbel_xml_element("desc", folder->desc);
- gchar* outerXML;
- outerXML = g_strdup_printf("%s%s<xbel version=\"1.0\">\n%s%s%s</xbel>\n"
- , "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- , "<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML\" \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n"
- , title
- , desc
- , g_string_free(innerXML, FALSE));
- g_free(title);
- g_free(desc);
- return outerXML;
-}
-
-/**
- * xbel_folder_to_file:
- * @folder: A folder.
- * @file: The destination filename.
- * @error: return location for a GError or %NULL
- *
- * Write the contents of @folder to the specified file, creating it if necessary.
- *
- * Return value: %TRUE on success or %FALSE when an error occured.
- **/
-gboolean xbel_folder_to_file(XbelItem* folder, const gchar* file, GError** error)
-{
- g_return_val_if_fail(file, FALSE);
- gchar* data;
- if(!(data = xbel_folder_to_data(folder, NULL, error)))
- return FALSE;
- FILE* fp;
- if(!(fp = fopen(file, "w")))
- {
- *error = g_error_new(G_FILE_ERROR, G_FILE_ERROR_ACCES
- , "Writing failed.");
- return FALSE;
- }
- fputs(data, fp);
- fclose(fp);
- g_free(data);
- return TRUE;
-}
+++ /dev/null
-/*
- Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
-
- 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.
-
- See the file COPYING for the full license text.
-*/
-
-#ifndef __XBEL_H__
-#define __XBEL_H__ 1
-
-#include <glib.h>
-#include <glib-object.h>
-
-#define XBEL_ERROR g_quark_from_string("XBEL_ERROR")
-
-typedef enum
-{
- XBEL_ERROR_INVALID_URI, /* Malformed uri */
- XBEL_ERROR_INVALID_VALUE, /* Requested field not found */
- XBEL_ERROR_URI_NOT_FOUND, /* Requested uri not found */
- XBEL_ERROR_READ, /* Malformed document */
- XBEL_ERROR_UNKNOWN_ENCODING, /* Parsed text was in an unknown encoding */
- XBEL_ERROR_WRITE, /* Writing failed. */
-} XBELError;
-
-typedef enum
-{
- XBEL_ITEM_FOLDER,
- XBEL_ITEM_BOOKMARK,
- XBEL_ITEM_SEPARATOR
-} XbelItemKind;
-
-// Note: This structure is entirely private.
-typedef struct
-{
- guint refs;
- XbelItemKind kind;
- struct XbelItem* parent;
-
- GList* items; // folder
- gboolean folded; // foolder
- gchar* title; // !separator
- gchar* desc; // folder and bookmark
- gchar* href; // bookmark
- //time_t added; // !separator
- //time_t modfied; // bookmark
- //time_t visited; // bookmark
-} XbelItem;
-
-XbelItem*
-xbel_bookmark_new(void);
-
-XbelItem*
-xbel_separator_new(void);
-
-XbelItem*
-xbel_folder_new(void);
-
-void
-xbel_item_ref(XbelItem*);
-
-void
-xbel_item_unref(XbelItem*);
-
-XbelItem*
-xbel_item_copy(XbelItem*);
-
-GType
-xbel_item_get_type();
-
-#define G_TYPE_XBEL_ITEM xbel_item_get_type()
-
-void
-xbel_folder_append_item(XbelItem*, XbelItem*);
-
-void
-xbel_folder_prepend_item(XbelItem*, XbelItem*);
-
-void
-xbel_folder_remove_item(XbelItem*, XbelItem*);
-
-guint
-xbel_folder_get_n_items(XbelItem*);
-
-XbelItem*
-xbel_folder_get_nth_item(XbelItem*, guint);
-
-gboolean
-xbel_folder_is_empty(XbelItem*);
-
-gboolean
-xbel_folder_get_folded(XbelItem*);
-
-XbelItemKind
-xbel_item_get_kind(XbelItem*);
-
-XbelItem*
-xbel_item_get_parent(XbelItem*);
-
-G_CONST_RETURN gchar*
-xbel_item_get_title(XbelItem*);
-
-G_CONST_RETURN gchar*
-xbel_item_get_desc(XbelItem*);
-
-G_CONST_RETURN gchar*
-xbel_bookmark_get_href(XbelItem*);
-
-/*time_t
-xbel_bookmark_get_added(XbelItem*);
-
-time_t
-xbel_bookmark_get_modified(XbelItem*);
-
-time_t
-xbel_bookmark_get_visited(XbelItem*);*/
-
-gboolean
-xbel_item_is_bookmark(XbelItem*);
-
-gboolean
-xbel_item_is_separator(XbelItem*);
-
-gboolean
-xbel_item_is_folder(XbelItem*);
-
-void
-xbel_folder_set_folded(XbelItem*, gboolean);
-
-void
-xbel_item_set_title(XbelItem*, const gchar*);
-
-void
-xbel_item_set_desc(XbelItem*, const gchar*);
-
-void
-xbel_bookmark_set_href(XbelItem*, const gchar*);
-
-gboolean
-xbel_folder_from_data(XbelItem*, const gchar*, GError**);
-
-gboolean
-xbel_folder_from_file(XbelItem*, const gchar*, GError**);
-
-gboolean
-xbel_folder_from_data_dirs(XbelItem*, const gchar*, gchar**, GError**);
-
-gchar*
-xbel_folder_to_data(XbelItem*, gsize*, GError**);
-
-gboolean
-xbel_folder_to_file(XbelItem*, const gchar*, GError**);
-
-#endif /* !__XBEL_H__ */