Save also page title in history file (#46).
authorDaniel Carl <danielcarl@gmx.de>
Sun, 14 Jul 2013 19:56:41 +0000 (21:56 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 14 Jul 2013 20:55:03 +0000 (22:55 +0200)
src/history.c
src/history.h
src/main.c
src/util.c
src/util.h

index dcdd853..d71ff6e 100644 (file)
@@ -30,6 +30,11 @@ static const VbFile file_map[HISTORY_LAST] = {
     FILES_HISTORY
 };
 
+typedef struct {
+    char *first;
+    char *second;
+} History;
+
 static struct {
     char  *prefix;
     char  *query;
@@ -40,6 +45,9 @@ static GList *get_list(const char *input);
 static const char *get_file_by_type(HistoryType type);
 static GList *load(const char *file);
 static void write_to_file(GList *list, const char *file);
+static History *line_to_history(const char *line);
+static int history_comp(History *a, History *b);
+static void free_history(History *item);
 
 
 /**
@@ -58,15 +66,18 @@ void history_cleanup(void)
 /**
  * Write a new history entry to the end of history file.
  */
-void history_add(HistoryType type, const char *value)
+void history_add(HistoryType type, const char *value, const char *additional)
 {
     FILE *f;
     const char *file = get_file_by_type(type);
 
     if ((f = fopen(file, "a+"))) {
         file_lock_set(fileno(f), F_WRLCK);
-
-        fprintf(f, "%s\n", value);
+        if (additional) {
+            fprintf(f, "%s\t%s\n", value, additional);
+        } else {
+            fprintf(f, "%s\n", value);
+        }
 
         file_lock_set(fileno(f), F_UNLCK);
         fclose(f);
@@ -82,29 +93,31 @@ GList *history_get_by_tags(HistoryType type, const char *tags)
     GList *res = NULL, *src = NULL;
     char **parts;
     unsigned int len;
+    History *item;
 
     src = load(get_file_by_type(type));
     if (!tags || *tags == '\0') {
         /* without any tags return all items */
         for (GList *l = src; l; l = l->next) {
-            res = g_list_prepend(res, g_strdup((char*)l->data));
+            item = l->data;
+            res = g_list_prepend(res, g_strdup(item->first));
         }
     } else if (HISTORY_URL == type) {
         parts = g_strsplit(tags, " ", 0);
         len   = g_strv_length(parts);
 
         for (GList *l = src; l; l = l->next) {
-            char *value = (char*)l->data;
-            if (util_string_contains_all_tags(value, parts, len)) {
-                res = g_list_prepend(res, g_strdup(value));
+            item = l->data;
+            if (util_string_contains_all_tags(item->first, parts, len)) {
+                res = g_list_prepend(res, g_strdup(item->first));
             }
         }
         g_strfreev(parts);
     } else {
         for (GList *l = src; l; l = l->next) {
-            char *value = (char*)l->data;
-            if (g_str_has_prefix(value, tags)) {
-                res = g_list_prepend(res, g_strdup(value));
+            item = l->data;
+            if (g_str_has_prefix(item->first, tags)) {
+                res = g_list_prepend(res, g_strdup(item->first));
             }
         }
     }
@@ -114,7 +127,7 @@ GList *history_get_by_tags(HistoryType type, const char *tags)
 }
 
 /**
- * Retrieves the command from history to be shown in input box.
+ * Retrieves the item from history to be shown in input box.
  * The result must be freed by the caller.
  */
 char *history_get(const char *input, gboolean prev)
@@ -188,11 +201,12 @@ static GList *get_list(const char *input)
 
     /* generate new history list with the matching items */
     for (GList *l = src; l; l = l->next) {
-        char *value = (char*)l->data;
-        if (g_str_has_prefix(value, history.query)) {
-            result = g_list_prepend(result, g_strdup(value));
+        History *item = l->data;
+        if (g_str_has_prefix(item->first, history.query)) {
+            result = g_list_prepend(result, g_strdup(item->first));
         }
     }
+    g_list_free_full(src, (GDestroyNotify)free_history);
 
     return result;
 }
@@ -208,38 +222,12 @@ static const char *get_file_by_type(HistoryType type)
 static GList *load(const char *file)
 {
     /* read the history items from file */
-    GList *list   = NULL;
-    char buf[BUF_SIZE] = {0};
-    FILE *f;
+    GList *list = NULL;
 
-    if (!(f = fopen(file, "r"))) {
-        return list;
-    }
-
-    file_lock_set(fileno(f), F_RDLCK);
-    while (fgets(buf, sizeof(buf), f)) {
-        g_strstrip(buf);
-
-        /* skip empty lines */
-        if (!*buf) {
-            continue;
-        }
-        /* if the value is already in history, remove this entry */
-        for (GList *l = list; l; l = l->next) {
-            if (*buf && !g_strcmp0(buf, (char*)l->data)) {
-                g_free(l->data);
-                list = g_list_delete_link(list, l);
-                break;
-            }
-        }
-
-        list = g_list_prepend(list, g_strdup(buf));
-    }
-    file_lock_set(fileno(f), F_UNLCK);
-    fclose(f);
-
-    /* reverse to not use the slow g_list_last */
-    list = g_list_reverse(list);
+    list = util_file_to_unique_list(
+        file, (Util_Content_Func)line_to_history, (GCompareFunc)history_comp,
+        (GDestroyNotify)free_history
+    );
 
     /* if list is too long - remove items from end (oldest entries) */
     if (vb.config.history_max < g_list_length(list)) {
@@ -264,12 +252,57 @@ static void write_to_file(GList *list, const char *file)
 
         /* overwrite the history file with new unique history items */
         for (GList *link = list; link; link = link->next) {
-            fprintf(f, "%s\n", (char*)link->data);
+            History *item = link->data;
+            if (item->second) {
+                fprintf(f, "%s\t%s\n", item->first, item->second);
+            } else {
+                fprintf(f, "%s\n", item->first);
+            }
         }
 
         file_lock_set(fileno(f), F_UNLCK);
         fclose(f);
     }
 
-    g_list_free_full(list, (GDestroyNotify)g_free);
+    g_list_free_full(list, (GDestroyNotify)free_history);
+}
+
+static History *line_to_history(const char *line)
+{
+    char **parts;
+    int len;
+
+    while (g_ascii_isspace(*line)) {
+        line++;
+    }
+    if (*line == '\0') {
+        return NULL;
+    }
+
+    History *item = g_new0(History, 1);
+
+    parts = g_strsplit(line, "\t", 2);
+    len   = g_strv_length(parts);
+    if (len == 2) {
+        item->first  = g_strdup(parts[0]);
+        item->second = g_strdup(parts[1]);
+    } else {
+        item->first  = g_strdup(parts[0]);
+    }
+    g_strfreev(parts);
+
+    return item;
+}
+
+static int history_comp(History *a, History *b)
+{
+    /* compare only the first part */
+    return g_strcmp0(a->first, b->first);
+}
+
+static void free_history(History *item)
+{
+    g_free(item->first);
+    g_free(item->second);
+    g_free(item);
 }
index 739cb0c..4b46399 100644 (file)
@@ -29,7 +29,7 @@ typedef enum {
 } HistoryType;
 
 void history_cleanup(void);
-void history_add(HistoryType type, const char *value);
+void history_add(HistoryType type, const char *value, const char *additional);
 GList *history_get_all(HistoryType type);
 GList *history_get_by_tags(HistoryType type, const char *tags);
 char *history_get(const char *input, gboolean prev);
index ff7793d..3da038d 100644 (file)
@@ -466,7 +466,7 @@ static void webview_load_status_cb(WebKitWebView *view, GParamSpec *pspec)
 
             dom_check_auto_insert(view);
 
-            history_add(HISTORY_URL, uri);
+            history_add(HISTORY_URL, uri, webkit_web_view_get_title(view));
             break;
 
         case WEBKIT_LOAD_FAILED:
@@ -505,13 +505,13 @@ static void inputbox_activate_cb(GtkEntry *entry)
         case '?':
             a.i = *text == '/' ? VB_SEARCH_FORWARD : VB_SEARCH_BACKWARD;
             a.s = (command + 1);
-            history_add(HISTORY_SEARCH, command + 1);
+            history_add(HISTORY_SEARCH, command + 1, NULL);
             command_search(&a);
             break;
 
         case ':':
             completion_clean();
-            history_add(HISTORY_COMMAND, command + 1);
+            history_add(HISTORY_COMMAND, command + 1, NULL);
             command_run_string((command + 1));
             break;
     }
index 13128f9..03c81bb 100644 (file)
@@ -98,6 +98,44 @@ char **util_get_lines(const char *filename)
     return lines;
 }
 
+GList *util_file_to_unique_list(const char *filename, Util_Content_Func func,
+    GCompareFunc unique_func, GDestroyNotify free_func)
+{
+    GList *gl = NULL;
+    char *line, **lines = util_get_lines(filename);
+    void *value;
+    int len;
+
+    len = g_strv_length(lines);
+    if (!len) {
+        return gl;
+    }
+
+    for (int i = 0; i < len; i++) {
+        line = lines[i];
+        g_strstrip(line);
+        if (*line == '\0') {
+            continue;
+        }
+
+        if ((value = func(line))) {
+            /* if the value is already in list, remove this entry */
+            for (GList *l = gl; l; l = l->next) {
+                if (!unique_func(value, l->data)) {
+                    free_func(l->data);
+                    gl = g_list_delete_link(gl, l);
+                    break;
+                }
+            }
+            gl = g_list_prepend(gl, value);
+        }
+    }
+    g_strfreev(lines);
+    gl = g_list_reverse(gl);
+
+    return gl;
+}
+
 char *util_strcasestr(const char *haystack, const char *needle)
 {
     unsigned char c1, c2;
index c48c4f9..f93e6b1 100644 (file)
@@ -23,6 +23,7 @@
 #include "main.h"
 
 typedef gboolean (*Util_Comp_Func)(const char*, const char*);
+typedef void *(*Util_Content_Func)(const char*);
 
 char* util_get_config_dir(void);
 char* util_get_cache_dir(void);
@@ -31,6 +32,8 @@ void util_create_dir_if_not_exists(const char* dirpath);
 void util_create_file_if_not_exists(const char* filename);
 char* util_get_file_contents(const char* filename, gsize* length);
 char** util_get_lines(const char* filename);
+GList *util_file_to_unique_list(const char *filename, Util_Content_Func func,
+    GCompareFunc unique_func, GDestroyNotify free_func);
 char* util_strcasestr(const char* haystack, const char* needle);
 gboolean util_array_contains_all_tags(char **src, unsigned int s, char **query, unsigned int q);
 gboolean util_string_contains_all_tags(char *src, char **query, unsigned int q);