commit: d57b655fecccbdee1f745e74a4578c14aeef5bcb
parent: b6e995810f9cba4dac83d57643a5f9698699cbad
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Wed, 26 Aug 2020 15:10:51 +0200
Merge branch 'features/suggestions' into develop
Diffstat:
8 files changed, 169 insertions(+), 3 deletions(-)
diff --git a/KnowledgeBase.md b/KnowledgeBase.md
@@ -2,3 +2,20 @@
- WebKit2 Extensions Tutorial: https://blogs.igalia.com/carlosgc/2013/09/10/webkit2gtk-web-process-extensions/
- https://trac.torproject.org/projects/tor/wiki/doc/ImportantGoogleChromeBugs / https://trac.torproject.org/projects/tor/ticket/1925
- https://webkit.org/blog/3476/content-blockers-first-look/
+
+# Bookmark formats
+The different plain-text formats used by web browsers found in the wild, done
+in Augmented Backus–Naur Form (ABNF).
+
+url = *CHAR
+title = *CHAR
+
+## uzbl
+bookmark = URL TAB title [TAB tags]
+tags = *(*CHAR SP)
+
+Documenter comment: How does it manages when the separator (TAB here) is
+present in the title?
+
+## qutebrowser
+bookmark = URL SP title
diff --git a/Makefile b/Makefile
@@ -24,9 +24,9 @@ INKSCAPE ?= inkscape
# for i in 24 32 48 64 128 256; do echo icons/hicolor/${i}x${i}/apps/badwolf.png; done | tr '\n' ' '
ICON_SIZES = icons/hicolor/24x24/apps/badwolf.png icons/hicolor/32x32/apps/badwolf.png icons/hicolor/48x48/apps/badwolf.png icons/hicolor/64x64/apps/badwolf.png icons/hicolor/128x128/apps/badwolf.png icons/hicolor/256x256/apps/badwolf.png
-DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
-SRCS = uri.c uri_test.c keybindings.c downloads.c badwolf.c
-OBJS = uri.o keybindings.o downloads.o badwolf.o
+DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4 libxml-2.0
+SRCS = bookmarks.c uri.c uri_test.c keybindings.c downloads.c badwolf.c
+OBJS = bookmarks.o uri.o keybindings.o downloads.o badwolf.o
OBJS_test = uri_test.o
EXE = badwolf
EXE_test = uri_test
diff --git a/README.md b/README.md
@@ -55,6 +55,7 @@ Dependencies are:
- C11 Compiler (such as clang or gcc)
- [WebKitGTK](https://webkitgtk.org/), only the latest stable is supported
+- [libxml-2.0](http://www.xmlsoft.org/), no known version limitation
- POSIX make with extension for shell in variables (works with GNU, {Net,Free,Open}BSD)
- A pkg-config implementation (pkgconf is recommended)
- (optionnal) gettext implementation (such as GNU Gettext)
diff --git a/badwolf.1 b/badwolf.1
@@ -75,6 +75,14 @@ A more generic variable name is also intended to be used in the future.
.El
.Sh FILES
.Bl -tag -width Ds -compact
+.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/bookmarks.xbel
+XBEL (XML Bookmark Exchange Language) file, known to be currently supported by:
+.Xr elinks 1 ,
+.Xr konqueror 1 ,
+.Xr kbookmarkeditor 1 . Doing a symbolic link from their path works fine.
+.Pp
+For more information about this format see:
+.Lk http://pyxml.sourceforge.net/topics/xbel/
.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extensions/
Directory containing the
.Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions
diff --git a/badwolf.c b/badwolf.c
@@ -6,6 +6,8 @@
#include "config.h"
#include "downloads.h"
+#include "bookmarks.h"
+#include "config.h"
#include "keybindings.h"
#include "uri.h"
@@ -21,6 +23,7 @@ const gchar *version = VERSION;
static gchar *web_extensions_directory;
static int context_id_counter = 0;
+GtkTreeModel *bookmarks_completion_model;
static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data);
static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView,
@@ -736,6 +739,15 @@ new_browser(struct Window *window, const gchar *target_url, struct Client *old_b
gtk_label_set_single_line_mode(GTK_LABEL(browser->statuslabel), TRUE);
gtk_label_set_ellipsize(GTK_LABEL(browser->statuslabel), BADWOLF_STATUSLABEL_ELLIPSIZE);
+ if(bookmarks_completion_model != NULL)
+ {
+ GtkEntryCompletion *location_completion = gtk_entry_completion_new();
+ GtkTreeModel *location_completion_model = bookmarks_completion_model;
+
+ bookmarks_completion_setup(location_completion, location_completion_model);
+ gtk_entry_set_completion(GTK_ENTRY(browser->location), location_completion);
+ }
+
gtk_entry_set_text(GTK_ENTRY(browser->location), target_url);
gtk_entry_set_input_purpose(GTK_ENTRY(browser->location), GTK_INPUT_PURPOSE_URL);
@@ -930,6 +942,9 @@ main(int argc, char *argv[])
g_build_filename(g_get_user_data_dir(), "badwolf", "webkit-web-extension", NULL);
fprintf(stderr, _("webkit-web-extension directory set to: %s\n"), web_extensions_directory);
+ bookmarks_completion_model = bookmarks_completion_init();
+ g_object_ref(bookmarks_completion_model);
+
window->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
window->notebook = gtk_notebook_new();
window->new_tab = gtk_button_new_from_icon_name("tab-new-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
@@ -997,6 +1012,8 @@ main(int argc, char *argv[])
gtk_main();
+ g_object_unref(bookmarks_completion_model);
+
#if 0
/* TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. */
_("ø");
diff --git a/bookmarks.c b/bookmarks.c
@@ -0,0 +1,117 @@
+#include "bookmarks.h"
+
+#include "badwolf.h"
+#include "config.h"
+
+#include <glib/gprintf.h> /* g_fprintf() */
+#include <gtk/gtk.h>
+#include <libxml/xpath.h>
+#include <unistd.h> /* access() */
+
+static gboolean
+location_completion_matches(GtkEntryCompletion *completion,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ (void)user_data;
+ gchar *buffer;
+ gchar *pattern;
+ gboolean result;
+
+ pattern = g_strdup_printf("*%s*", key);
+
+ gtk_tree_model_get(gtk_entry_completion_get_model(completion), iter, 0, &buffer, -1);
+ result = g_pattern_match_simple(pattern, buffer);
+
+ g_free(buffer);
+ g_free(pattern);
+ return result;
+}
+
+void
+bookmarks_completion_setup(GtkEntryCompletion *location_completion, GtkTreeModel *tree_model)
+{
+ gtk_entry_completion_set_model(location_completion, tree_model);
+ gtk_entry_completion_set_text_column(location_completion, 0);
+ gtk_entry_completion_set_match_func(location_completion, location_completion_matches, NULL, NULL);
+ gtk_entry_completion_set_inline_selection(location_completion, BADWOLF_LOCATION_INLINE_SELECTION);
+}
+
+static void
+location_completion_cleanup(xmlXPathObjectPtr xpathObj, xmlXPathContextPtr xpathCtx, xmlDocPtr doc)
+{
+ if(xpathObj != NULL) xmlXPathFreeObject(xpathObj);
+ if(xpathCtx != NULL) xmlXPathFreeContext(xpathCtx);
+ if(doc != NULL) xmlFreeDoc(doc);
+}
+
+static GtkTreeIter
+load_xpath_results(GtkListStore *list_store, xmlNodeSetPtr nodes)
+{
+ GtkTreeIter iter;
+ int size;
+
+ size = (nodes) ? nodes->nodeNr : 0;
+
+ g_fprintf(stderr, "Bookmarks: Found %d bookmarks.\n", size);
+ for(int i = 0; i < size; i++)
+ if(nodes->nodeTab[i])
+ {
+ gtk_list_store_append(list_store, &iter);
+ gtk_list_store_set(
+ list_store, &iter, 0, (char *)xmlXPathCastNodeToString(nodes->nodeTab[i]), -1);
+ }
+
+ return iter;
+}
+
+GtkTreeModel *
+bookmarks_completion_init()
+{
+ const xmlChar *xpathExpr = "//bookmark/@href";
+ char *filename = g_build_filename(g_get_user_data_dir(), "badwolf", "bookmarks.xbel", NULL);
+ xmlDocPtr doc = NULL;
+ xmlXPathContextPtr xpathCtx = NULL;
+ xmlXPathObjectPtr xpathObj = NULL;
+ GtkTreeIter iter;
+ GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING);
+
+ if(access(filename, R_OK) != 0) {
+ g_fprintf(stderr, "Bookmarks: No loadable file found at %s\n", filename);
+ return NULL;
+ }
+
+ g_fprintf(stderr, "Bookmarks: loading at %s\n", filename);
+ doc = xmlParseFile(filename);
+ if(doc == NULL)
+ {
+ g_fprintf(stderr, "Bookmarks: unable to parse file \"%s\"\n", filename);
+ location_completion_cleanup(xpathObj, xpathCtx, doc);
+ return NULL;
+ }
+
+ xpathCtx = xmlXPathNewContext(doc);
+ if(xpathCtx == NULL)
+ {
+ g_fprintf(stderr, "Bookmarks: unable to create new XPath context\n");
+ location_completion_cleanup(xpathObj, xpathCtx, doc);
+ return NULL;
+ }
+
+ xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
+ if(xpathObj == NULL)
+ {
+ g_fprintf(stderr, "Bookmarks: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
+ location_completion_cleanup(xpathObj, xpathCtx, doc);
+ return NULL;
+ }
+
+ iter = load_xpath_results(list_store, xpathObj->nodesetval);
+
+ location_completion_cleanup(xpathObj, xpathCtx, doc);
+
+ g_fprintf(stderr, "Bookmarks: Done.\n");
+
+ return GTK_TREE_MODEL(list_store);
+}
diff --git a/bookmarks.h b/bookmarks.h
@@ -0,0 +1,3 @@
+#include <gtk/gtk.h>
+GtkTreeModel *bookmarks_completion_init();
+void bookmarks_completion_setup(GtkEntryCompletion *location_completion, GtkTreeModel *tree_model);
diff --git a/config.h b/config.h
@@ -104,4 +104,7 @@
*/
#define BADWOLF_DOWNLOAD_FILE_PATH_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE
+// BADWOLF_LOCATION_INLINE_SELECTION: show selected completion as a selection in location entry
+#define BADWOLF_LOCATION_INLINE_SELECTION TRUE
+
#endif /* CONFIG_H_INCLUDED */