Allow the inputbox to show multiple lines.
authorDaniel Carl <danielcarl@gmx.de>
Tue, 13 Aug 2013 18:13:06 +0000 (20:13 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Wed, 14 Aug 2013 06:33:36 +0000 (08:33 +0200)
src/command.c
src/completion.c
src/config.def.h
src/hints.c
src/keybind.c
src/main.c
src/main.h

index e42777e..0b6162e 100644 (file)
@@ -729,8 +729,9 @@ gboolean command_zoom(const Arg *arg)
 
 gboolean command_history(const Arg *arg)
 {
-    const char *input = GET_TEXT();
-    char *entry       = history_get(input, arg->i);
+    char *input = vb_get_input_text();
+    char *entry = history_get(input, arg->i);
+    g_free(input);
 
     if (!entry) {
         return false;
index f4d98ee..663fb07 100644 (file)
@@ -49,11 +49,12 @@ static gboolean tree_selection_func(GtkTreeSelection *selection,
 gboolean completion_complete(gboolean back)
 {
     VbInputType type;
-    const char *input, *prefix, *suffix;
+    char *input;
+    const char *prefix, *suffix;
     GtkListStore *store = NULL;
     gboolean res = false, sort = true;
 
-    input = GET_TEXT();
+    input = vb_get_input_text();
     type  = vb_get_input_parts(input, VB_INPUT_ALL, &prefix, &suffix);
 
     if (vb.state.mode & VB_MODE_COMPLETE) {
@@ -271,7 +272,7 @@ static gboolean tree_selection_func(GtkTreeSelection *selection,
             comp.text = g_strdup_printf("%s%s", comp.prefix, value);
         }
         /* print the text also into inputbox */
-        PUT_TEXT(comp.text);
+        vb_set_input_text(comp.text);
         g_free(value);
     }
 
index 3fb4937..ccfaa68 100644 (file)
@@ -25,7 +25,6 @@
 #define FEATURE_COOKIE
 #define FEATURE_SEARCH_HIGHLIGHT
 #define FEATURE_NO_SCROLLBARS
-/*#define FEATURE_GTK_PROGRESSBAR*/
 #define FEATURE_TITLE_IN_COMPLETION
 #define FEATURE_QUEUE
 
index 52c9772..1c9f479 100644 (file)
@@ -41,8 +41,8 @@ extern VbCore vb;
 static void run_script(char *js);
 static void fire();
 static void observe_input(gboolean observe);
-static gboolean changed_cb(GtkEditable *entry);
-static gboolean keypress_cb(WebKitWebView *webview, GdkEventKey *event);
+static gboolean changed_cb(GtkTextBuffer *buffer);
+static gboolean keypress_cb(GtkWidget *widget, GdkEventKey *event);
 
 void hints_init(WebKitWebFrame *frame)
 {
@@ -201,30 +201,41 @@ static void observe_input(gboolean observe)
 {
     if (observe) {
         hints.change_handler = g_signal_connect(
-            G_OBJECT(vb.gui.inputbox), "changed", G_CALLBACK(changed_cb), NULL
+            G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(vb.gui.input))),
+            "changed", G_CALLBACK(changed_cb), NULL
         );
+
         hints.keypress_handler = g_signal_connect(
-            G_OBJECT(vb.gui.inputbox), "key-press-event", G_CALLBACK(keypress_cb), NULL
+            G_OBJECT(vb.gui.input), "key-press-event", G_CALLBACK(keypress_cb), NULL
         );
     } else if (hints.change_handler && hints.keypress_handler) {
-        g_signal_handler_disconnect(G_OBJECT(vb.gui.inputbox), hints.change_handler);
-        g_signal_handler_disconnect(G_OBJECT(vb.gui.inputbox), hints.keypress_handler);
+        g_signal_handler_disconnect(
+            G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(vb.gui.input))),
+            hints.change_handler
+        );
+        g_signal_handler_disconnect(G_OBJECT(vb.gui.input), hints.keypress_handler);
 
         hints.change_handler = hints.keypress_handler = 0;
     }
 }
 
-static gboolean changed_cb(GtkEditable *entry)
+static gboolean changed_cb(GtkTextBuffer *buffer)
 {
-    const char *text = GET_TEXT();
+    char *text;
+    GtkTextIter start, end;
+
+    gtk_text_buffer_get_bounds(buffer, &start, &end);
+    text = gtk_text_buffer_get_text(buffer, &start, &end, false);
 
     /* skip hinting prefixes like '.', ',', ';y' ... */
     hints_create(text + hints.prefixLength, hints.mode, hints.prefixLength);
 
+    g_free(text);
+
     return true;
 }
 
-static gboolean keypress_cb(WebKitWebView *webview, GdkEventKey *event)
+static gboolean keypress_cb(GtkWidget *widget, GdkEventKey *event)
 {
     int numval;
     guint keyval = event->keyval;
index ecae4b3..86b2a6a 100644 (file)
@@ -34,15 +34,15 @@ static GSList *find(int mode, guint modkey, guint modmask, guint keyval);
 static void string_to_keybind(char *str, Keybind *key);
 static guint string_to_modmask(const char *str);
 static guint string_to_value(const char *str);
-static gboolean keypress_cb(WebKitWebView *webview, GdkEventKey *event);
+static gboolean keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer is_input);
 static void free_keybind(Keybind *keybind);
 
 
 void keybind_init(void)
 {
     modkeys = g_string_new("");
-    g_signal_connect(G_OBJECT(vb.gui.webview), "key-press-event", G_CALLBACK(keypress_cb), NULL);
-    g_signal_connect(G_OBJECT(vb.gui.box), "key-press-event", G_CALLBACK(keypress_cb), NULL);
+    g_signal_connect(G_OBJECT(vb.gui.webview), "key-press-event", G_CALLBACK(keypress_cb), GINT_TO_POINTER(0));
+    g_signal_connect(G_OBJECT(vb.gui.input), "key-press-event", G_CALLBACK(keypress_cb), GINT_TO_POINTER(1));
 }
 
 void keybind_cleanup(void)
@@ -233,7 +233,7 @@ static guint string_to_value(const char *str)
     return str[0];
 }
 
-static gboolean keypress_cb(WebKitWebView *webview, GdkEventKey *event)
+static gboolean keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer is_input)
 {
     guint keyval, state;
     static GdkKeymap *keymap;
@@ -249,9 +249,12 @@ static gboolean keypress_cb(WebKitWebView *webview, GdkEventKey *event)
     /* check for escape or modkeys or counts */
     if (IS_ESCAPE_KEY(keyval, state)) {
         vb.state.modkey = vb.state.count = 0;
-        /* switch to normal mode and clear the input box */
+        /* switch to normal mode and clear the command line */
         vb_set_mode(VB_MODE_NORMAL, true);
 
+        return true;
+    } else if (GPOINTER_TO_INT(is_input) && keyval == GDK_Return) {
+        vb_input_activate();
         return true;
     }
 
index 08b0641..4c86ff1 100644 (file)
@@ -38,12 +38,11 @@ static char **args;
 VbCore      vb;
 
 /* callbacks */
+static void input_changed_cb(GtkTextBuffer *buffer);
 static void webview_progress_cb(WebKitWebView *view, GParamSpec *pspec);
 static void webview_download_progress_cb(WebKitWebView *view, GParamSpec *pspec);
 static void webview_load_status_cb(WebKitWebView *view, GParamSpec *pspec);
 static void destroy_window_cb(GtkWidget *widget);
-static void inputbox_activate_cb(GtkEntry *entry);
-static gboolean inputbox_keyrelease_cb(GtkEntry *entry, GdkEventKey *event);
 static void scroll_cb(GtkAdjustment *adjustment);
 static WebKitWebView *inspector_new(WebKitWebInspector *inspector, WebKitWebView *webview);
 static gboolean inspector_show(WebKitWebInspector *inspector);
@@ -74,7 +73,7 @@ static void setup_signals();
 static void init_files(void);
 static gboolean hide_message();
 static void set_status(const StatusType status);
-static void inputbox_print(gboolean force, const MessageType type, gboolean hide, const char *message);
+static void input_print(gboolean force, const MessageType type, gboolean hide, const char *message);
 
 void vb_echo_force(const MessageType type, gboolean hide, const char *error, ...)
 {
@@ -85,7 +84,7 @@ void vb_echo_force(const MessageType type, gboolean hide, const char *error, ...
     vsnprintf(message, BUF_SIZE, error, arg_list);
     va_end(arg_list);
 
-    inputbox_print(true, type, hide, message);
+    input_print(true, type, hide, message);
 }
 
 void vb_echo(const MessageType type, gboolean hide, const char *error, ...)
@@ -97,7 +96,80 @@ void vb_echo(const MessageType type, gboolean hide, const char *error, ...)
     vsnprintf(message, BUF_SIZE, error, arg_list);
     va_end(arg_list);
 
-    inputbox_print(false, type, hide, message);
+    input_print(false, type, hide, message);
+}
+
+/**
+ * Writes given text into the command line.
+ */
+void vb_set_input_text(const char *text)
+{
+    GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vb.gui.input));
+    gtk_text_buffer_set_text(buffer, text, -1);
+}
+
+/**
+ * Retrieves the content of the command line.
+ * Retruned string must be freed with g_free.
+ */
+char *vb_get_input_text(void)
+{
+    GtkTextIter start, end;
+    GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vb.gui.input));
+
+    gtk_text_buffer_get_bounds(buffer, &start, &end);
+    return gtk_text_buffer_get_text(buffer, &start, &end, false);
+}
+
+/**
+ * Called if the user hit the return key in the command line.
+ */
+void vb_input_activate(void)
+{
+    char *command  = NULL;
+    char *text = vb_get_input_text();
+
+    Arg a;
+    command = text + 1;
+    switch (*text) {
+        case '/':
+        case '?':
+            a.i = *text == '/' ? VB_SEARCH_FORWARD : VB_SEARCH_BACKWARD;
+            a.s = command;
+            history_add(HISTORY_SEARCH, command, NULL);
+            command_search(&a);
+            break;
+
+        case ':':
+            completion_clean();
+            history_add(HISTORY_COMMAND, command, NULL);
+            command_run_string(command);
+            break;
+    }
+
+    g_free(text);
+}
+
+static void input_changed_cb(GtkTextBuffer *buffer)
+{
+    char *text;
+    GtkTextIter start, end;
+    gboolean forward;
+    if (!gtk_widget_is_focus(GTK_WIDGET(vb.gui.input))) {
+        /* if the widget isn't focused the change comes not from the user and
+         * we can skip further processing */
+        return;
+    }
+
+    gtk_text_buffer_get_bounds(buffer, &start, &end);
+    text = gtk_text_buffer_get_text(buffer, &start, &end, false);
+
+    if ((forward = (*text == '/')) || *text == '?') {
+        webkit_web_view_unmark_text_matches(vb.gui.webview);
+        webkit_web_view_search_text(vb.gui.webview, &text[1], false, forward, false);
+    }
+    /* TODO start hinting also if ., or ; are the first char in inputbox */
+    g_free(text);
 }
 
 gboolean vb_eval_script(WebKitWebFrame *frame, char *script, char *file, char **value)
@@ -224,7 +296,7 @@ gboolean vb_set_mode(Mode mode, gboolean clean)
                 break;
 
             case VB_MODE_COMMAND:
-                gtk_widget_grab_focus(GTK_WIDGET(vb.gui.inputbox));
+                gtk_widget_grab_focus(GTK_WIDGET(vb.gui.input));
                 break;
 
             case VB_MODE_INPUT:
@@ -280,12 +352,6 @@ void vb_update_statusbar()
     if (vb.state.progress != 100) {
         g_string_append_printf(status, " [%i%%]", vb.state.progress);
     }
-#ifdef FEATURE_GTK_PROGRESSBAR
-    gtk_entry_set_progress_fraction(
-        GTK_ENTRY(vb.gui.inputbox),
-        vb.state.progress == 100 ? 0.0 : vb.state.progress/100.0
-    );
-#endif
 
     /* show the scroll status */
     max = gtk_adjustment_get_upper(vb.gui.adjust_v) - gtk_adjustment_get_page_size(vb.gui.adjust_v);
@@ -323,7 +389,7 @@ void vb_update_input_style(void)
 {
     MessageType type = vb.state.input_type;
     vb_set_widget_font(
-        vb.gui.inputbox, &vb.style.input_fg[type], &vb.style.input_bg[type], vb.style.input_font[type]
+        vb.gui.input, &vb.style.input_fg[type], &vb.style.input_bg[type], vb.style.input_font[type]
     );
 }
 
@@ -398,7 +464,7 @@ void vb_quit(void)
 
 static gboolean hide_message()
 {
-    inputbox_print(false, VB_MSG_NORMAL, false, "");
+    input_print(false, VB_MSG_NORMAL, false, "");
 
     return false;
 }
@@ -490,49 +556,6 @@ static void destroy_window_cb(GtkWidget *widget)
     vb_quit();
 }
 
-static void inputbox_activate_cb(GtkEntry *entry)
-{
-    const char *text;
-    char *command  = NULL;
-    guint16 length = gtk_entry_get_text_length(entry);
-
-    if (0 == length) {
-        return;
-    }
-
-    /* do not free or modify text */
-    text = GET_TEXT();
-
-    /* duplicate the content because this may change for example if
-     * :set varName? is used the text is changed to the new printed
-     * content of inputbox */
-    command = g_strdup((text));
-
-    Arg a;
-    switch (*text) {
-        case '/':
-        case '?':
-            a.i = *text == '/' ? VB_SEARCH_FORWARD : VB_SEARCH_BACKWARD;
-            a.s = (command + 1);
-            history_add(HISTORY_SEARCH, command + 1, NULL);
-            command_search(&a);
-            break;
-
-        case ':':
-            completion_clean();
-            history_add(HISTORY_COMMAND, command + 1, NULL);
-            command_run_string((command + 1));
-            break;
-    }
-
-    g_free(command);
-}
-
-static gboolean inputbox_keyrelease_cb(GtkEntry *entry, GdkEventKey *event)
-{
-    return false;
-}
-
 static void scroll_cb(GtkAdjustment *adjustment)
 {
     vb_update_statusbar();
@@ -596,10 +619,10 @@ static void set_status(const StatusType status)
     }
 }
 
-static void inputbox_print(gboolean force, const MessageType type, gboolean hide, const char *message)
+static void input_print(gboolean force, const MessageType type, gboolean hide, const char *message)
 {
     /* don't print message if the input is focussed */
-    if (!force && gtk_widget_is_focus(GTK_WIDGET(vb.gui.inputbox))) {
+    if (!force && gtk_widget_is_focus(GTK_WIDGET(vb.gui.input))) {
         return;
     }
 
@@ -608,7 +631,7 @@ static void inputbox_print(gboolean force, const MessageType type, gboolean hide
         vb.state.input_type = type;
         vb_update_input_style();
     }
-    PUT_TEXT(message);
+    vb_set_input_text(message);
     if (hide) {
         g_timeout_add_seconds(MESSAGE_TIMEOUT, (GSourceFunc)hide_message, NULL);
     }
@@ -693,13 +716,8 @@ static void init_core(void)
 #endif
 #endif
 
-    /* Prepare the inputbox */
-    gui->inputbox = gtk_entry_new();
-#ifndef HAS_GTK3
-    gtk_entry_set_inner_border(GTK_ENTRY(gui->inputbox), NULL);
-#endif
-    g_object_set(gtk_widget_get_settings(gui->inputbox), "gtk-entry-select-on-focus", false, NULL);
-
+    /* Prepare the command line */
+    gui->input = gtk_text_view_new();
 #ifdef HAS_GTK3
     gui->pane            = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
     gui->box             = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
@@ -718,8 +736,6 @@ static void init_core(void)
     gtk_paned_pack1(GTK_PANED(gui->pane), GTK_WIDGET(gui->box), true, true);
     gtk_widget_show_all(gui->window);
 
-    setup_signals();
-
     /* Put all part together */
     gtk_container_add(GTK_CONTAINER(gui->scroll), GTK_WIDGET(gui->webview));
     gtk_container_add(GTK_CONTAINER(gui->eventbox), GTK_WIDGET(gui->statusbar.box));
@@ -731,8 +747,9 @@ static void init_core(void)
 
     gtk_box_pack_start(gui->box, gui->scroll, true, true, 0);
     gtk_box_pack_start(gui->box, gui->eventbox, false, false, 0);
-    gtk_entry_set_has_frame(GTK_ENTRY(gui->inputbox), false);
-    gtk_box_pack_end(gui->box, gui->inputbox, false, false, 0);
+    gtk_box_pack_end(gui->box, gui->input, false, false, 0);
+
+    setup_signals();
 
     /* Make sure that when the browser area becomes visible, it will get mouse
      * and keyboard events */
@@ -810,11 +827,11 @@ static void setup_signals()
 #endif
 
     g_object_connect(
-        G_OBJECT(vb.gui.inputbox),
-        "signal::activate",          G_CALLBACK(inputbox_activate_cb),   NULL,
-        "signal::key-release-event", G_CALLBACK(inputbox_keyrelease_cb), NULL,
+        G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(vb.gui.input))),
+        "signal::changed", G_CALLBACK(input_changed_cb), NULL,
         NULL
     );
+
     /* webview adjustment */
     g_object_connect(G_OBJECT(vb.gui.adjust_v),
         "signal::value-changed", G_CALLBACK(scroll_cb), NULL,
index 17a89d4..d8f8c05 100644 (file)
 #define TIMER_END
 #endif
 
-#define GET_TEXT() (gtk_entry_get_text(GTK_ENTRY(vb.gui.inputbox)))
-#define PUT_TEXT(x) { \
-    gtk_entry_set_text(GTK_ENTRY(vb.gui.inputbox), x); \
-    gtk_editable_set_position(GTK_EDITABLE(vb.gui.inputbox), -1); \
-}
 #define GET_URI() (webkit_web_view_get_uri(vb.gui.webview))
 #define CLEAN_MODE(mode) ((mode) & (VB_MODE_NORMAL|VB_MODE_COMMAND|VB_MODE_INPUT))
 #define CLEAR_INPUT() (vb_echo(VB_MSG_NORMAL, ""))
@@ -253,7 +248,7 @@ typedef struct {
     WebKitWebInspector *inspector;
     GtkBox             *box;
     GtkWidget          *eventbox;
-    GtkWidget          *inputbox;
+    GtkWidget          *input;
     GtkWidget          *pane;
     StatusBar          statusbar;
     GtkScrollbar       *sb_h;
@@ -319,6 +314,9 @@ extern VbCore core;
 /* functions */
 void vb_echo_force(const MessageType type,gboolean hide, const char *error, ...);
 void vb_echo(const MessageType type, gboolean hide, const char *error, ...);
+void vb_set_input_text(const char *text);
+char *vb_get_input_text(void);
+void vb_input_activate(void);
 gboolean vb_eval_script(WebKitWebFrame *frame, char *script, char *file, char **value);
 gboolean vb_load_uri(const Arg *arg);
 gboolean vb_set_clipboard(const Arg *arg);