Moved url history to own module.
authorDaniel Carl <danielcarl@gmx.de>
Sun, 3 Mar 2013 15:21:25 +0000 (16:21 +0100)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 3 Mar 2013 15:21:25 +0000 (16:21 +0100)
The history is loaded into a list if the browser is started. After that the
history items are only prepended to the internal list. Only if the apllication
is closed, we write the internal url history list to the history file.

config.mk
src/main.c
src/main.h
src/setting.c
src/url_history.c [new file with mode: 0644]
src/url_history.h [new file with mode: 0644]

index 2089a13..cbc8c6b 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -40,7 +40,7 @@ LDFLAGS += $(shell pkg-config --libs $(LIBS)) -lX11 -lXext
 CPPFLAGS += -DFEATURE_COOKIE
 CPPFLAGS += -DFEATURE_SEARCH_HIGHLIGHT
 
-CPPFLAGS += -DVERSION=\"${VERSION}\" -D_BSD_SOURCE
+CPPFLAGS += -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_XOPEN_SOURCE=500
 ifeq ($(USEGTK3), 1)
 CPPFLAGS += -DHAS_GTK3
 endif
index 2096d4c..17b733c 100644 (file)
@@ -28,6 +28,7 @@
 #include "hints.h"
 #include "searchengine.h"
 #include "history.h"
+#include "url_history.h"
 
 /* variables */
 static char **args;
@@ -79,7 +80,6 @@ static void vp_set_cookie(SoupCookie* cookie);
 static const char* vp_get_cookies(SoupURI *uri);
 static gboolean vp_hide_message(void);
 static void vp_set_status(const StatusType status);
-static void vp_save_url_history(const char* url, const char* title);
 
 static void vp_webview_progress_cb(WebKitWebView* view, GParamSpec* pspec, gboolean download)
 {
@@ -148,7 +148,7 @@ static void vp_webview_load_status_cb(WebKitWebView* view, GParamSpec* pspec, gp
 
             dom_check_auto_insert();
 
-            vp_save_url_history(uri, webkit_web_view_get_title(vp.gui.webview));
+            url_history_add(uri, webkit_web_view_get_title(vp.gui.webview));
             break;
 
         case WEBKIT_LOAD_FAILED:
@@ -412,14 +412,16 @@ void vp_clean_up(void)
         g_file_set_contents(core.files[FILES_CLOSED], uri, -1, NULL);
     }
 
-    for (int i = 0; i < FILES_LAST; i++) {
-        g_free(core.files[i]);
-    }
     command_cleanup();
     setting_cleanup();
     keybind_cleanup();
     completion_clean();
     searchengine_cleanup();
+    url_history_cleanup();
+
+    for (int i = 0; i < FILES_LAST; i++) {
+        g_free(core.files[i]);
+    }
 }
 
 void vp_clean_input(void)
@@ -464,45 +466,6 @@ static void vp_set_status(const StatusType status)
     }
 }
 
-static void vp_save_url_history(const char* url, const char* title)
-{
-    FILE* f = NULL;
-    char buf[512] = {0};
-    char* new = NULL;
-    guint max = core.config.max_history_items;
-    f = fopen(core.files[FILES_HISTORY], "r");
-    if (!f) {
-        return;
-    }
-
-    char* title_escaped = g_shell_quote(title ? title : "");
-    char* new_item = g_strdup_printf("%s %s\n", url, title);
-    gint n = strlen(new_item);
-    g_free(title_escaped);
-
-    new = g_new0(char, max * sizeof(buf));
-    /* put the new entry to the top */
-    strncpy(new, new_item, n);
-
-    for (guint i = 1; i < max && fgets(buf, sizeof(buf), f); i++) {
-        if (strncmp(new_item, buf, n) != 0) {
-            strncat(new, buf, sizeof(buf));
-        }
-    }
-    fclose(f);
-
-    f = fopen(core.files[FILES_HISTORY], "w");
-    if (!f) {
-        g_free(new);
-
-        return;
-    }
-    fprintf(f, "%s", new);
-    g_free(new);
-
-    fclose(f);
-}
-
 /**
  * Set the base modes. All other mode flags like completion can be set directly
  * to vp.state.mode.
@@ -724,6 +687,8 @@ static void vp_init(void)
 
     /* set the configuration to the required objects */
     vp_setup_settings();
+
+    url_history_init();
 }
 
 static void vp_read_config(void)
index 4b5fdd8..70764e6 100644 (file)
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <webkit/webkit.h>
 #include <JavaScriptCore/JavaScript.h>
+#include <fcntl.h>
+#include <stdio.h>
 #ifdef HAS_GTK3
 #include <gdk/gdkx.h>
 #include <gtk/gtkx.h>
 #define CLEAN_STATE_WITH_SHIFT(e) ((e)->state & (GDK_MOD1_MASK|GDK_MOD4_MASK|GDK_SHIFT_MASK|GDK_CONTROL_MASK))
 #define CLEAN_STATE(e)            ((e)->state & (GDK_MOD1_MASK|GDK_MOD4_MASK|GDK_CONTROL_MASK))
 
+#define file_lock_set(fd, cmd) \
+{ \
+    struct flock lock = { .l_type = cmd, .l_start = 0, .l_whence = SEEK_SET, .l_len = 0}; \
+    fcntl(fd, F_SETLK, lock); \
+}
+
 #ifdef HAS_GTK3
 #define VpColor GdkRGBA
 #define VP_COLOR_PARSE(color, string)   (gdk_rgba_parse(color, string))
@@ -246,6 +254,7 @@ typedef struct {
     GString*    modkeys;
     GSList*     searchengines;
     GList*      history;
+    GList*      url_history;
 } Behaviour;
 
 typedef struct {
@@ -254,7 +263,7 @@ typedef struct {
     guint  max_completion_items;
     char*  home_page;
     char*  download_dir;
-    guint  max_history_items;
+    guint  url_history_max;
 } Config;
 
 typedef struct {
index 5fd604a..16129e3 100644 (file)
@@ -703,12 +703,12 @@ static gboolean setting_user_style(const Setting* s, const SettingType type)
 static gboolean setting_history_max_items(const Setting* s, const SettingType type)
 {
     if (type == SETTING_GET) {
-        setting_print_value(s, &core.config.max_history_items);
+        setting_print_value(s, &core.config.url_history_max);
 
         return TRUE;
     }
 
-    core.config.max_history_items = s->arg.i;
+    core.config.url_history_max = s->arg.i;
 
     return TRUE;
 }
diff --git a/src/url_history.c b/src/url_history.c
new file mode 100644 (file)
index 0000000..cf09af8
--- /dev/null
@@ -0,0 +1,92 @@
+#include "main.h"
+#include "url_history.h"
+
+static void url_history_free(UrlHist* item);
+
+
+void url_history_init(void)
+{
+    /* read the history items from file */
+    char buf[512] = {0};
+    guint max = core.config.url_history_max;
+    FILE* file = fopen(core.files[FILES_HISTORY], "r");
+    if (!file) {
+        return;
+    }
+
+    file_lock_set(fileno(file), F_WRLCK);
+
+    for (guint i = 0; i < max && fgets(buf, sizeof(buf), file); i++) {
+        char** argv = NULL;
+        gint   argc = 0;
+        if (g_shell_parse_argv(buf, &argc, &argv, NULL)) {
+            url_history_add(argv[0], argc > 1 ? argv[1] : NULL);
+        }
+        g_strfreev(argv);
+    }
+
+    file_lock_set(fileno(file), F_UNLCK);
+    fclose(file);
+}
+
+void url_history_cleanup(void)
+{
+    FILE* file = fopen(core.files[FILES_HISTORY], "w");
+    if (file) {
+        file_lock_set(fileno(file), F_WRLCK);
+
+        /* write the history to the file */
+        GList* link;
+        for (link = core.behave.url_history; link != NULL; link = link->next) {
+            UrlHist* item = (UrlHist*)link->data;
+            char* title = g_shell_quote(item->title ? item->title : "");
+            char* new   = g_strdup_printf("%s %s\n", item->uri, title);
+
+            fwrite(new, strlen(new), 1, file);
+
+            g_free(title);
+            g_free(new);
+        }
+        file_lock_set(fileno(file), F_UNLCK);
+        fclose(file);
+    }
+
+    if (core.behave.url_history) {
+        g_list_free_full(core.behave.url_history, (GDestroyNotify)url_history_free);
+    }
+}
+
+void url_history_add(const char* url, const char* title)
+{
+    /* uf the url is already in history, remove this entry */
+    for (GList* link = core.behave.url_history; link; link = link->next) {
+        UrlHist* hi = (UrlHist*)link->data;
+        if (!g_strcmp0(url, hi->uri)) {
+            url_history_free(hi);
+            core.behave.url_history = g_list_delete_link(core.behave.url_history, link);
+            break;
+        }
+    }
+
+    while (core.config.url_history_max < g_list_length(core.behave.url_history)) {
+        /* if list is too long - remove items from end */
+        core.behave.url_history = g_list_delete_link(
+            core.behave.url_history,
+            g_list_last(core.behave.url_history)
+        );
+    }
+
+    UrlHist* item = g_new0(UrlHist, 1);
+    item->uri   = g_strdup(url);
+    item->title = title ? g_strdup(title) : NULL;
+
+    core.behave.url_history = g_list_prepend(core.behave.url_history, item);
+}
+
+static void url_history_free(UrlHist* item)
+{
+    g_free(item->uri);
+    if (item->title) {
+        g_free(item->title);
+    }
+}
diff --git a/src/url_history.h b/src/url_history.h
new file mode 100644 (file)
index 0000000..36704c0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _URL_HISTORY_H
+#define _URL_HISTORY_H
+
+typedef struct {
+    char* uri;
+    char* title;
+} UrlHist;
+
+void url_history_init(void);
+void url_history_cleanup(void);
+void url_history_add(const char* url, const char* title);
+
+#endif /* end of include guard: _URL_HISTORY_H */