Allow setting and removing keybindings from string.
authorDaniel Carl <danielcarl@gmx.de>
Sat, 20 Oct 2012 17:51:59 +0000 (19:51 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sat, 20 Oct 2012 17:51:59 +0000 (19:51 +0200)
src/command.c
src/command.h
src/keybind.c
src/keybind.h
src/main.c
src/main.h
src/util.c [new file with mode: 0644]
src/util.h [new file with mode: 0644]

index 2ab0ab6..2764bd2 100644 (file)
@@ -39,6 +39,11 @@ void command_init()
     }
 }
 
+gboolean command_exists(const gchar* name)
+{
+    return g_hash_table_contains(vp.behave.commands, name);
+}
+
 gboolean command_run(const gchar* name, const gchar* param)
 {
     CommandInfo* c = NULL;
index 5cd3942..27dd3f9 100644 (file)
@@ -14,6 +14,7 @@ typedef struct {
 
 
 void command_init(void);
+gboolean command_exists(const gchar* name);
 gboolean command_run(const gchar* name, const gchar* param);
 
 #endif /* end of include guard: COMMAND_H */
index 729b2ce..0b5d30a 100644 (file)
@@ -6,6 +6,8 @@ static GSList* keys = NULL;
 static GString* modkeys = NULL;
 
 static GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval);
+static void keybind_str_to_keybind(gchar* str, Keybind* key);
+static guint keybind_str_to_modmask(const gchar* str);
 static gboolean keybind_keypress_callback(WebKitWebView* webview, GdkEventKey* event);
 
 
@@ -15,34 +17,62 @@ void keybind_init(void)
     g_signal_connect(G_OBJECT(vp.gui.window), "key-press-event", G_CALLBACK(keybind_keypress_callback), NULL);
 }
 
-void keybind_add(int mode, guint modkey, guint modmask, guint keyval, const gchar* command)
+void keybind_add_from_string(const gchar* str, const Mode mode)
 {
-    Keybind* keybind = g_new0(Keybind, 1);
+    if (str == NULL || *str == '\0') {
+        return;
+    }
+    gchar* line = g_strdup(str);
+    g_strstrip(line);
+
+    /* split into keybinding and command */
+    char **string = g_strsplit(line, " ", 2);
+
+    guint len = g_strv_length(string);
+    if (len == 2 && command_exists(string[1])) {
+        Keybind* keybind = g_new0(Keybind, 1);
+        keybind->mode    = mode;
+        keybind->command = g_strdup(string[1]);
 
-    keybind->mode    = mode;
-    keybind->modkey  = modkey;
-    keybind->modmask = modmask;
-    keybind->keyval  = keyval;
-    keybind->command = g_strdup(command);
+        keybind_str_to_keybind(string[0], keybind);
 
-    keys = g_slist_prepend(keys, keybind);
+        /* add the keybinding to the list */
+        keys = g_slist_prepend(keys, keybind);
 
-    /* save the modkey also in the modkey string */
-    if (modkey) {
-        g_string_append_c(modkeys, modkey);
+        /* save the modkey also in the modkey string */
+        if (keybind->modkey) {
+            g_string_append_c(modkeys, keybind->modkey);
+        }
+    } else {
+        fprintf(stderr, "could not add keybind from '%s'", line);
     }
+
+    g_strfreev(string);
+    g_free(line);
 }
 
-void keybind_remove(int mode, guint modkey, guint modmask, guint keyval)
+void keybind_remove_from_string(const gchar* str, const Mode mode)
 {
-    GSList* link = keybind_find(mode, modkey, modmask, keyval);
+    gchar* line = NULL;
+    Keybind keybind = {0};
+
+    if (str == NULL || *str == '\0') {
+        return;
+    }
+    line = g_strdup(str);
+    g_strstrip(line);
+
+    /* fill the keybind with data from given string */
+    keybind_str_to_keybind(line, &keybind);
+
+    GSList* link = keybind_find(keybind.mode, keybind.modkey, keybind.modmask, keybind.keyval);
     if (link) {
         keys = g_slist_delete_link(keys, link);
     }
     /* TODO remove eventually no more used modkeys */
 }
 
-GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval)
+static GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval)
 {
     GSList* link;
     for (link = keys; link != NULL; link = link->next) {
@@ -59,6 +89,47 @@ GSList* keybind_find(int mode, guint modkey, guint modmask, guint keyval)
     return NULL;
 }
 
+static void keybind_str_to_keybind(gchar* str, Keybind* keybind)
+{
+    gchar** string = NULL;
+    guint len = 0;
+
+    if (str == NULL || *str == '\0') {
+        return;
+    }
+    g_strstrip(str);
+
+    /* [modkey[<modmask>]]keyval */
+    string = g_strsplit_set(str, "<>", 3);
+    len = g_strv_length(string);
+
+    if (len == 1) { /* no modmask set */
+        if (strlen(string[0]) == 2) {
+            keybind->modkey = string[0][0];
+            keybind->keyval = string[0][1];
+        } else {
+            keybind->keyval = string[0][0];
+        }
+    } else { /* contains modmask */
+        keybind->modkey  = (string[0][0] != '\0') ? string[0][0] : 0;
+        keybind->modmask = keybind_str_to_modmask(string[1]);
+        keybind->keyval  = string[2][0];
+    }
+    g_strfreev(string);
+}
+
+static guint keybind_str_to_modmask(const gchar* str)
+{
+    if (!g_ascii_strcasecmp(str, "ctrl")) {
+        return GDK_CONTROL_MASK;
+    }
+    if (!g_ascii_strcasecmp(str, "shift")) {
+        return GDK_SHIFT_MASK;
+    }
+
+    return 0;
+}
+
 static gboolean keybind_keypress_callback(WebKitWebView* webview, GdkEventKey* event)
 {
     GdkModifierType irrelevant;
index 6866dab..021f0de 100644 (file)
@@ -21,7 +21,7 @@ typedef struct {
 } Keybind;
 
 void keybind_init(void);
-void keybind_add(int mode, guint modkey, guint modmask, guint keyval, const gchar* command);
-void keybind_remove(int mode, guint modkey, guint modmask, guint keyval);
+void keybind_add_from_string(const gchar* str, const Mode mode);
+void keybind_remove_from_string(const gchar* str, const Mode mode);
 
 #endif /* end of include guard: KEYBIND_H */
index 9ff9776..f8a9089 100644 (file)
@@ -1,5 +1,6 @@
 #include "config.h"
 #include "main.h"
+#include "util.h"
 #include "command.h"
 #include "keybind.h"
 
@@ -20,6 +21,7 @@ static gboolean vp_process_input(const char* input);
 static void vp_print_version(void);
 static void vp_init(void);
 static void vp_init_gui(void);
+static void vp_init_files(void);
 static void vp_set_widget_font(GtkWidget* widget, const gchar* font_definition, const gchar* bg_color, const gchar* fg_color);
 static void vp_setup_settings(void);
 static void vp_setup_signals(void);
@@ -210,12 +212,20 @@ void vp_scroll(const Arg* arg)
 }
 
 void vp_close_browser(const Arg* arg)
+{
+    vp_clean_up();
+    gtk_main_quit();
+}
+
+void vp_clean_up(void)
 {
     if (vp.behave.commands) {
         g_hash_table_destroy(vp.behave.commands);
         vp.behave.commands = NULL;
     }
-    gtk_main_quit();
+    for (int i = FILES_FIRST; i < FILES_LAST; i++) {
+        g_free(vp.files[i]);
+    }
 }
 
 void vp_view_source(const Arg* arg)
@@ -350,32 +360,34 @@ static void vp_init(void)
     vp_init_gui();
     /* initialize the commands hash map */
     command_init();
+    /* initialize the config files */
+    vp_init_files();
     /* initialize the keybindings */
     keybind_init();
 
     /* TODO read the key bindings from config file */
-    keybind_add(VP_MODE_NORMAL, GDK_g, 0,                GDK_f,      "source");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_colon,  "input");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_o,      "inputopen");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_O,      "inputopencurrent");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_d,      "quit");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_o,      "back");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_i,      "forward");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_r,      "reload");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_R,      "reload!");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_c,      "stop");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_f,      "pagedown");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_b,      "pageup");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_d,      "halfpagedown");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_u,      "halfpageup");
-    keybind_add(VP_MODE_NORMAL, GDK_g, 0,                GDK_g,      "jumptop");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_G,      "jumpbottom");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_0,      "jumpleft");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_dollar, "jumpright");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_h,      "scrollleft");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_l,      "scrollright");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_k,      "scrollup");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_j,      "scrolldown");
+    keybind_add_from_string("gf source", VP_MODE_NORMAL);
+    keybind_add_from_string(": input", VP_MODE_NORMAL);
+    keybind_add_from_string("o inputopen", VP_MODE_NORMAL);
+    keybind_add_from_string("O inputopencurrent", VP_MODE_NORMAL);
+    keybind_add_from_string("d quit", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>o back", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>i forward", VP_MODE_NORMAL);
+    keybind_add_from_string("r reload", VP_MODE_NORMAL);
+    keybind_add_from_string("R reload!", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>c stop", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>f pagedown", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>b pageup", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>d halfpagedown", VP_MODE_NORMAL);
+    keybind_add_from_string("<ctrl>u halfpageup", VP_MODE_NORMAL);
+    keybind_add_from_string("gg jumptop", VP_MODE_NORMAL);
+    keybind_add_from_string("G jumpbottom", VP_MODE_NORMAL);
+    keybind_add_from_string("0 jumpleft", VP_MODE_NORMAL);
+    keybind_add_from_string("$ jumpright", VP_MODE_NORMAL);
+    keybind_add_from_string("h scrollleft", VP_MODE_NORMAL);
+    keybind_add_from_string("l scrollright", VP_MODE_NORMAL);
+    keybind_add_from_string("k scrollup", VP_MODE_NORMAL);
+    keybind_add_from_string("j scrolldown", VP_MODE_NORMAL);
 }
 
 static void vp_init_gui(void)
@@ -456,6 +468,16 @@ static void vp_init_gui(void)
     gtk_widget_show_all(gui->window);
 }
 
+static void vp_init_files(void)
+{
+    gchar* path = util_get_config_dir();
+
+    vp.files[FILES_CONFIG] = g_build_filename(path, "config", NULL);
+    util_create_file_if_not_exists(vp.files[FILES_CONFIG]);
+
+    g_free(path);
+}
+
 static void vp_set_widget_font(GtkWidget* widget, const gchar* font_definition, const gchar* bg_color, const gchar* fg_color)
 {
     GdkColor fg, bg;
index ac11121..692354b 100644 (file)
@@ -72,6 +72,12 @@ typedef enum {
     VP_MSG_ERROR
 } MessageType;
 
+enum {
+    FILES_FIRST = 0,
+    FILES_CONFIG = 0,
+    FILES_LAST
+};
+
 /* structs */
 typedef struct {
     gint  i;
@@ -118,6 +124,7 @@ typedef struct {
     Gui           gui;
     State         state;
     Behaviour     behave;
+    gchar*        files[FILES_LAST];
 #if 0
     Network       net;
     Ssl           ssl;
@@ -136,6 +143,7 @@ void vp_echo(const MessageType type, const gchar *message);
 void vp_navigate(const Arg* arg);
 void vp_scroll(const Arg* arg);
 void vp_close_browser(const Arg* arg);
+void vp_clean_up(void);
 void vp_view_source(const Arg* arg);
 void vp_set_mode(const Arg* arg);
 void vp_input(const Arg* arg);
diff --git a/src/util.c b/src/util.c
new file mode 100644 (file)
index 0000000..f274e9c
--- /dev/null
@@ -0,0 +1,33 @@
+#include "util.h"
+#include <stdio.h>
+#include <glib.h>
+
+char* util_get_config_dir(void)
+{
+    char *path = g_build_filename(g_get_user_config_dir(), PROJECT, NULL);
+    util_create_dir_if_not_exists(path);
+
+    return path;
+}
+
+char* util_get_cache_dir(void)
+{
+    char *path = g_build_filename(g_get_user_cache_dir(), PROJECT, NULL);
+    util_create_dir_if_not_exists(path);
+
+    return path;
+}
+
+void util_create_dir_if_not_exists(const gchar* dirpath)
+{
+    if (!g_file_test(dirpath, G_FILE_TEST_IS_DIR)) {
+        g_mkdir_with_parents(dirpath, 0755);
+    }
+}
+
+void util_create_file_if_not_exists(const char* filename) {
+    if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
+        FILE* f = fopen(filename, "a");
+        fclose(f);
+    }
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..bc359b6
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+char* util_get_config_dir(void);
+char* util_get_cache_dir(void);
+void util_create_dir_if_not_exists(const char* dirpath);
+void util_create_file_if_not_exists(const char* filename);
+
+#endif /* end of include guard: UTIL_H */