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
#include "hints.h"
#include "searchengine.h"
#include "history.h"
+#include "url_history.h"
/* variables */
static char **args;
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)
{
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:
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)
}
}
-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.
/* set the configuration to the required objects */
vp_setup_settings();
+
+ url_history_init();
}
static void vp_read_config(void)
#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))
GString* modkeys;
GSList* searchengines;
GList* history;
+ GList* url_history;
} Behaviour;
typedef struct {
guint max_completion_items;
char* home_page;
char* download_dir;
- guint max_history_items;
+ guint url_history_max;
} Config;
typedef struct {
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;
}
--- /dev/null
+#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);
+ }
+}
--- /dev/null
+#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 */