Added support for different yank registers.
authorDaniel Carl <danielcarl@gmx.de>
Fri, 30 May 2014 20:26:02 +0000 (22:26 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Fri, 30 May 2014 22:06:43 +0000 (00:06 +0200)
Allow to yank, and paste from different registers.

doc/vimb.1
src/command.c
src/command.h
src/ex.c
src/hints.c
src/main.c
src/main.h
src/normal.c
src/normal.h

index 9a829e3..296c5db 100644 (file)
@@ -112,11 +112,12 @@ Open the last closed page into a new window.
 Open the oldest entry from read it later queue in current browser window, if
 vimb has been compiled with QUEUE feature.
 .TP
-.B p
-Open the URI out of the clipboard.
+.BI [ \[char34]x ]p
+Open the URI out of the register \fIx\fP or if not given from clipboard.
 .TP
-.B P
-Open the URI out of the clipboard into new window.
+.BI [ \[char34]x ]P
+Open the URI out of the register \fIx\fP or if not given from clipboard into
+new window.
 .TP
 .BI [ N ]CTRL\-O
 Go back \fIN\fP steps in the browser history.
@@ -324,11 +325,11 @@ Full-Content Zoom-Out the page by \fIN\fP steps.
 Reset Zoom.
 .SS Yank
 .TP
-.B y
-Yank the URI or current page into clipboard.
+.BI [ \[char34]x ]y
+Yank the URI or current page into register \fIx\fP and clipboard.
 .TP
-.B Y
-Yank the current selection into clipboard.
+.BI [ \[char34]x ]Y
+Yank the current selection into register \fIx\fP and clipboard.
 .SH COMMAND MODE
 .SS Command Line Editing
 .TP
@@ -355,6 +356,9 @@ Moves the cursor after the char in inputbox.
 .TP
 .B CTRL\-V
 Pass the next key press directly to gtk.
+.TP
+.B CTRL\-R {0-9a-z}
+Insert the content of given buffer at cursor position.
 .SS Command Line History
 .TP
 .B <Tab>
index 5133598..de32cbb 100644 (file)
@@ -82,7 +82,7 @@ gboolean command_search(const Arg *arg)
     return true;
 }
 
-gboolean command_yank(const Arg *arg)
+gboolean command_yank(const Arg *arg, char buf)
 {
     static char *tmpl = "Yanked: %s";
 
@@ -95,6 +95,8 @@ gboolean command_yank(const Arg *arg)
             text = gtk_clipboard_wait_for_text(SECONDARY_CLIPBOARD());
         }
         if (text) {
+            /* put the text into the yank buffer */
+            vb_register_add(buf, text);
             vb_echo(VB_MSG_NORMAL, false, tmpl, text);
             g_free(text);
 
@@ -113,7 +115,9 @@ gboolean command_yank(const Arg *arg)
         a.s = arg->s;
     }
     if (a.s) {
+        /* put the text into the yank buffer */
         vb_set_clipboard(&a);
+        vb_register_add(buf, a.s);
         vb_echo(VB_MSG_NORMAL, false, tmpl, a.s);
 
         return true;
index c552963..3377f83 100644 (file)
@@ -41,7 +41,7 @@ enum {
 #endif
 
 gboolean command_search(const Arg *arg);
-gboolean command_yank(const Arg *arg);
+gboolean command_yank(const Arg *arg, char buf);
 gboolean command_save(const Arg *arg);
 #ifdef FEATURE_QUEUE
 gboolean command_queue(const Arg *arg);
index 121bc3d..5cc44b6 100644 (file)
--- a/src/ex.c
+++ b/src/ex.c
@@ -39,6 +39,7 @@
 #include "handlers.h"
 #include "map.h"
 #include "js.h"
+#include "normal.h"
 
 typedef enum {
     EX_BMA,
@@ -74,6 +75,11 @@ typedef enum {
     EX_TABOPEN,
 } ExCode;
 
+typedef enum {
+    PHASE_START,
+    PHASE_CUTBUF,
+} Phase;
+
 typedef struct {
     int        count;    /* commands count */
     int        idx;      /* index in commands array */
@@ -99,6 +105,11 @@ typedef struct {
     int        flags;
 } ExInfo;
 
+static struct {
+    char cutbuf; /* char for the cut buffer */
+    Phase phase; /* current parsing phase */
+} info = {'\0', PHASE_START};
+
 static void input_activate(void);
 static gboolean parse(const char **input, ExArg *arg);
 static gboolean parse_count(const char **input, ExArg *arg);
@@ -215,92 +226,125 @@ VbResult ex_keypress(int key)
     GtkTextIter start, end;
     GtkTextBuffer *buffer = vb.gui.buffer;
     GtkTextMark *mark;
+    VbResult res;
+    const char *text;
 
     /* delegate call to the submode */
     if (RESULT_COMPLETE == hints_keypress(key)) {
         return RESULT_COMPLETE;
     }
 
-    switch (key) {
-        case KEY_TAB:
-            complete(1);
-            break;
+    /* process the custbuffer */
+    if (info.phase == PHASE_CUTBUF) {
+        info.cutbuf = (char)key;
+        info.phase  = PHASE_CUTBUF;
 
-        case KEY_SHIFT_TAB:
-            complete(-1);
-            break;
+        /* insert the cutbuffer text at cursor position */
+        text = vb_register_get((char)key);
+        if (text) {
+            gtk_text_buffer_insert_at_cursor(buffer, text, strlen(text));
+        }
 
-        case CTRL('['):
-        case CTRL('C'):
-            mode_enter('n');
-            vb_set_input_text("");
-            break;
+        res = RESULT_COMPLETE;
+    } else {
+        res = RESULT_COMPLETE;
+        switch (key) {
+            case KEY_TAB:
+                complete(1);
+                break;
 
-        case KEY_CR:
-            input_activate();
-            break;
+            case KEY_SHIFT_TAB:
+                complete(-1);
+                break;
 
-        case KEY_UP:
-            history(true);
-            break;
+            case CTRL('['):
+            case CTRL('C'):
+                mode_enter('n');
+                vb_set_input_text("");
+                break;
 
-        case KEY_DOWN:
-            history(false);
-            break;
+            case KEY_CR:
+                input_activate();
+                break;
 
-        /* basic command line editing */
-        case CTRL('H'):
-            /* delete the last char before the cursor */
-            mark = gtk_text_buffer_get_insert(buffer);
-            gtk_text_buffer_get_iter_at_mark(buffer, &start, mark);
-            gtk_text_buffer_backspace(buffer, &start, true, true);
-            break;
+            case KEY_UP:
+                history(true);
+                break;
 
-        case CTRL('W'):
-            /* delete word backward from cursor */
-            mark = gtk_text_buffer_get_insert(buffer);
-            gtk_text_buffer_get_iter_at_mark(buffer, &end, mark);
+            case KEY_DOWN:
+                history(false);
+                break;
 
-            /* copy the iter to build start and end point for deletion */
-            start = end;
+            /* basic command line editing */
+            case CTRL('H'):
+                /* delete the last char before the cursor */
+                mark = gtk_text_buffer_get_insert(buffer);
+                gtk_text_buffer_get_iter_at_mark(buffer, &start, mark);
+                gtk_text_buffer_backspace(buffer, &start, true, true);
+                break;
 
-            /* move the iterator to the beginning of previous word */
-            if (gtk_text_iter_backward_word_start(&start)) {
-                gtk_text_buffer_delete(buffer, &start, &end);
-            }
-            break;
+            case CTRL('W'):
+                /* delete word backward from cursor */
+                mark = gtk_text_buffer_get_insert(buffer);
+                gtk_text_buffer_get_iter_at_mark(buffer, &end, mark);
 
-        case CTRL('B'):
-            /* move the cursor direct behind the prompt */
-            gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt));
-            gtk_text_buffer_place_cursor(buffer, &start);
-            break;
+                /* copy the iter to build start and end point for deletion */
+                start = end;
 
-        case CTRL('E'):
-            /* move the cursor to the end of line */
-            gtk_text_buffer_get_end_iter(buffer, &start);
-            gtk_text_buffer_place_cursor(buffer, &start);
-            break;
+                /* move the iterator to the beginning of previous word */
+                if (gtk_text_iter_backward_word_start(&start)) {
+                    gtk_text_buffer_delete(buffer, &start, &end);
+                }
+                break;
 
-        case CTRL('U'):
-            /* remove everythings between cursor and prompt */
-            mark = gtk_text_buffer_get_insert(buffer);
-            gtk_text_buffer_get_iter_at_mark(buffer, &end, mark);
-            gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt));
-            gtk_text_buffer_delete(buffer, &start, &end);
-            break;
+            case CTRL('B'):
+                /* move the cursor direct behind the prompt */
+                gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt));
+                gtk_text_buffer_place_cursor(buffer, &start);
+                break;
 
-        default:
-            /* if is printable ascii char, than write it at the cursor
-             * position into input box */
-            if (key >= 0x20 && key <= 0x7e) {
-                gtk_text_buffer_insert_at_cursor(buffer, (char[2]){key, 0}, 1);
-            } else {
-                vb.state.processed_key = false;
-            }
+            case CTRL('E'):
+                /* move the cursor to the end of line */
+                gtk_text_buffer_get_end_iter(buffer, &start);
+                gtk_text_buffer_place_cursor(buffer, &start);
+                break;
+
+            case CTRL('U'):
+                /* remove everythings between cursor and prompt */
+                mark = gtk_text_buffer_get_insert(buffer);
+                gtk_text_buffer_get_iter_at_mark(buffer, &end, mark);
+                gtk_text_buffer_get_iter_at_offset(buffer, &start, strlen(vb.state.prompt));
+                gtk_text_buffer_delete(buffer, &start, &end);
+                break;
+
+            case CTRL('R'):
+                info.cutbuf     = (char)key;
+                info.phase      = PHASE_CUTBUF;
+                vb.mode->flags |= FLAG_NOMAP;
+                res             = RESULT_MORE;
+                break;
+
+            default:
+                /* if is printable ascii char, than write it at the cursor
+                * position into input box */
+                if (key >= 0x20 && key <= 0x7e) {
+                    gtk_text_buffer_insert_at_cursor(buffer, (char[2]){key, 0}, 1);
+                } else {
+                    vb.state.processed_key = false;
+                }
+        }
+    }
+
+    if (res == RESULT_COMPLETE) {
+        info.cutbuf = 0;
+        info.phase  = PHASE_START;
+    } else {
+        /* if the key sequence is not complete show the already typed keys in
+         * status bar */
+        normal_showcmd(key);
     }
 
-    return RESULT_COMPLETE;
+    return res;
 }
 
 /**
index 31f995d..9616550 100644 (file)
@@ -327,7 +327,7 @@ static gboolean call_hints_function(const char *func, int count, JSValueRef para
             case 'Y':
                 a.i = COMMAND_YANK_ARG;
                 a.s = v;
-                command_yank(&a);
+                command_yank(&a, '\0');
                 break;
 
 #ifdef FEATURE_QUEUE
index 04920b6..6efbb51 100644 (file)
@@ -97,6 +97,8 @@ static void setup_signals();
 static void init_files(void);
 static void session_init(void);
 static void session_cleanup(void);
+static void register_init(void);
+static void register_cleanup(void);
 static gboolean hide_message();
 static void set_status(const StatusType status);
 static void input_print(gboolean force, const MessageType type, gboolean hide, const char *message);
@@ -381,6 +383,7 @@ void vb_quit(void)
     setting_cleanup();
     history_cleanup();
     session_cleanup();
+    register_cleanup();
 
     for (int i = 0; i < FILES_LAST; i++) {
         g_free(vb.files[i]);
@@ -747,6 +750,7 @@ static void init_core(void)
     init_files();
     session_init();
     setting_init();
+    register_init();
     read_config();
 
     /* initially apply input style */
@@ -962,6 +966,51 @@ static void session_cleanup(void)
 #endif
 }
 
+static void register_init(void)
+{
+    memset(vb.state.reg, 0, sizeof(char*));
+}
+
+void vb_register_add(char buf, const char *value)
+{
+    char *mark;
+    int idx;
+
+    /* make sure the mark is a valid mark char */
+    if ((mark = strchr(VB_REG_CHARS, buf))) {
+        /* get the index of the mark char */
+        idx = mark - VB_REG_CHARS;
+
+        OVERWRITE_STRING(vb.state.reg[idx], value);
+    }
+}
+
+const char *vb_register_get(char buf)
+{
+    char *mark;
+    int idx;
+
+    /* make sure the mark is a valid mark char */
+    if ((mark = strchr(VB_REG_CHARS, buf))) {
+        /* get the index of the mark char */
+        idx = mark - VB_REG_CHARS;
+
+        return vb.state.reg[idx];
+    }
+
+    return NULL;
+}
+
+static void register_cleanup(void)
+{
+    int i;
+    for (i = 0; i < VB_REG_SIZE; i++) {
+        if (vb.state.reg[i]) {
+            g_free(vb.state.reg[i]);
+        }
+    }
+}
+
 static gboolean button_relase_cb(WebKitWebView *webview, GdkEventButton *event)
 {
     gboolean propagate = false;
index 3ff9030..e9fd42e 100644 (file)
 #define VB_MARK_TICK    0
 #define VB_MARK_SIZE    (sizeof(VB_MARK_CHARS) - 1)
 
+#define VB_REG_CHARS    "0123456789abcdefghijklmnopqrstuvwxyz"
+#define VB_REG_SIZE     (sizeof(VB_REG_CHARS) - 1)
+
 /* enums */
 typedef enum {
     RESULT_COMPLETE,
@@ -290,6 +293,8 @@ typedef struct {
     char            prompt[PROMPT_SIZE];    /* current prompt ':', 'g;t', '/' including nul */
     gdouble         marks[VB_MARK_SIZE];    /* holds marks set to page with 'm{markchar}' */
     char            *linkhover;             /* the uri of the curret hovered link */
+    GHashTable      *buffer;                /* holds the yank buffer */
+    char            *reg[VB_REG_SIZE];      /* holds the yank buffer */
 } State;
 
 typedef struct {
@@ -364,6 +369,8 @@ void vb_update_statusbar(void);
 void vb_update_status_style(void);
 void vb_update_input_style(void);
 void vb_update_urlbar(const char *uri);
+void vb_register_add(char buf, const char *value);
+const char *vb_register_get(char buf);
 gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *path);
 void vb_quit(void);
 
index 856a28a..efaf469 100644 (file)
@@ -37,15 +37,19 @@ typedef enum {
     PHASE_KEY2,
     PHASE_KEY3,
     PHASE_COMPLETE,
+    PHASE_CUTBUF,
 } Phase;
 
-struct NormalCmdInfo_s {
+typedef struct NormalCmdInfo_s {
     int count;   /* count used for the command */
     char key;    /* command key */
     char key2;   /* second command key (optional) */
     char key3;   /* third command key only for hinting */
+    char cutbuf; /* char for the cut buffer */
     Phase phase; /* current parsing phase */
-} info = {0, '\0', '\0', PHASE_START};
+} NormalCmdInfo;
+
+static NormalCmdInfo info = {0, '\0', '\0', PHASE_START};
 
 typedef VbResult (*NormalCommand)(const NormalCmdInfo *info);
 
@@ -263,6 +267,12 @@ VbResult normal_keypress(int key)
         info.phase      = PHASE_KEY2;
         info.key        = key;
         vb.mode->flags |= FLAG_NOMAP;
+    } else if ((char)key == '"') {
+        info.phase      = PHASE_CUTBUF;
+        vb.mode->flags |= FLAG_NOMAP;
+    } else if (info.phase ==  PHASE_CUTBUF) {
+        info.cutbuf = (char)key;
+        info.phase  = PHASE_START;
     } else {
         info.key   = key;
         info.phase = PHASE_COMPLETE;
@@ -284,7 +294,7 @@ VbResult normal_keypress(int key)
 
     if (res == RESULT_COMPLETE) {
         /* unset the info */
-        info.key = info.key2 = info.key3 = info.count = 0;
+        info.key = info.key2 = info.key3 = info.count = info.cutbuf = 0;
         info.phase = PHASE_START;
     } else if (res == RESULT_MORE) {
         normal_showcmd(key);
@@ -564,9 +574,15 @@ static VbResult normal_open_clipboard(const NormalCmdInfo *info)
 {
     Arg a = {info->key == 'P' ? VB_TARGET_NEW : VB_TARGET_CURRENT};
 
-    a.s = gtk_clipboard_wait_for_text(PRIMARY_CLIPBOARD());
-    if (!a.s) {
-        a.s = gtk_clipboard_wait_for_text(SECONDARY_CLIPBOARD());
+    /* if cutbuffer is not the default - read out of the internal cutbuffer */
+    if (info->cutbuf) {
+        a.s = g_strdup(vb_register_get(info->cutbuf));
+    } else {
+        /* if no cutbuffer is given use the system clipboard */
+        a.s = gtk_clipboard_wait_for_text(PRIMARY_CLIPBOARD());
+        if (!a.s) {
+            a.s = gtk_clipboard_wait_for_text(SECONDARY_CLIPBOARD());
+        }
     }
 
     if (a.s) {
@@ -763,7 +779,7 @@ static VbResult normal_yank(const NormalCmdInfo *info)
 {
     Arg a = {info->key == 'Y' ? COMMAND_YANK_SELECTION : COMMAND_YANK_URI};
 
-    return command_yank(&a) ? RESULT_COMPLETE : RESULT_ERROR;
+    return command_yank(&a, info->cutbuf) ? RESULT_COMPLETE : RESULT_ERROR;
 }
 
 static VbResult normal_zoom(const NormalCmdInfo *info)
index e027688..38a51cb 100644 (file)
@@ -23,8 +23,6 @@
 #include "config.h"
 #include "main.h"
 
-typedef struct NormalCmdInfo_s NormalCmdInfo;
-
 void normal_enter(void);
 void normal_leave(void);
 VbResult normal_keypress(int key);