nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nano-devel] [PATCH] input: add keycodes and routines to allow text sele


From: Benno Schulenberg
Subject: [Nano-devel] [PATCH] input: add keycodes and routines to allow text selection with Shift
Date: Tue, 16 Aug 2016 12:04:33 +0200

This allows the user to skip the explicit setting of the mark
(with M-A or ^6) and instead quickly select a few words or lines
by holding down Shift together with the movement keys.

(Some combinations with Shift are swallowed by some terminal emulators.
To work around some of those, the combinations Shift+Alt+Left/Right work
as Shift+Home/End and Shift+Alt+Up/Down work as Shift+PageUp/PageDown.)
---
 src/files.c  |   1 +
 src/global.c |   4 +++
 src/nano.c   |  28 ++++++++++++++++
 src/nano.h   |  16 +++++++++
 src/proto.h  |  10 ++++++
 src/text.c   |   4 ++-
 src/winio.c  | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 7 files changed, 160 insertions(+), 9 deletions(-)

diff --git a/src/files.c b/src/files.c
index 5a137f0..9a4f8c7 100644
--- a/src/files.c
+++ b/src/files.c
@@ -100,6 +100,7 @@ void make_new_buffer(void)
     openfile->mark_set = FALSE;
     openfile->mark_begin = NULL;
     openfile->mark_begin_x = 0;
+    openfile->kind_of_mark = SOFTMARK;
 
     openfile->fmt = NIX_FILE;
 
diff --git a/src/global.c b/src/global.c
index da404d2..2d0e7c0 100644
--- a/src/global.c
+++ b/src/global.c
@@ -40,6 +40,8 @@ bool console;
 
 bool meta_key;
        /* Whether the current keystroke is a Meta key. */
+bool shift_held;
+       /* Whether Shift was being held together with a movement key. */
 bool focusing = TRUE;
        /* Whether an update of the edit window should center the cursor. */
 
@@ -48,6 +50,8 @@ message_type lastmessage = HUSH;
 
 #ifndef NANO_TINY
 int controlleft, controlright, controlup, controldown;
+int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown;
+int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
 #endif
 
 #ifndef DISABLE_WRAPJUSTIFY
diff --git a/src/nano.c b/src/nano.c
index 356a1de..98f04ac 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -1682,8 +1682,26 @@ int do_input(bool allow_funcs)
                } else
 #endif
                {
+#ifndef NANO_TINY
+                   /* If Shifted movement occurs, set the mark. */
+                   if (shift_held && !openfile->mark_set) {
+                       openfile->mark_set = TRUE;
+                       openfile->mark_begin = openfile->current;
+                       openfile->mark_begin_x = openfile->current_x;
+                       openfile->kind_of_mark = SOFTMARK;
+                   }
+#endif
                    /* Execute the function of the shortcut. */
                    s->scfunc();
+#ifndef NANO_TINY
+                   /* If Shiftless movement occurred, discard a soft mark. */
+                   if (openfile->mark_set && !shift_held &&
+                               openfile->kind_of_mark == SOFTMARK) {
+                       openfile->mark_set = FALSE;
+                       openfile->mark_begin = NULL;
+                       refresh_needed = TRUE;
+                   }
+#endif
 #ifndef DISABLE_COLOR
                    if (f && !f->viewok)
                        reset_multis(openfile->current, FALSE);
@@ -2532,6 +2550,16 @@ int main(int argc, char **argv)
     controlright = get_keycode("kRIT5", CONTROL_RIGHT);
     controlup = get_keycode("kUP5", CONTROL_UP);
     controldown = get_keycode("kDN5", CONTROL_DOWN);
+    /* Ask for the codes for Shift+Control+Left/Right/Up/Down. */
+    shiftcontrolleft = get_keycode("kLFT6", SHIFT_CONTROL_LEFT);
+    shiftcontrolright = get_keycode("kRIT6", SHIFT_CONTROL_RIGHT);
+    shiftcontrolup = get_keycode("kUP6", SHIFT_CONTROL_UP);
+    shiftcontroldown = get_keycode("kDN6", SHIFT_CONTROL_DOWN);
+    /* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */
+    shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT);
+    shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT);
+    shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP);
+    shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN);
 #endif
 
 #ifndef USE_SLANG
diff --git a/src/nano.h b/src/nano.h
index 2c7dee4..53331ac 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -180,6 +180,10 @@ typedef enum {
 } kind_of_writing_type;
 
 typedef enum {
+    SOFTMARK, HARDMARK
+} mark_type;
+
+typedef enum {
     UPWARD, DOWNWARD
 } scroll_dir;
 
@@ -402,6 +406,8 @@ typedef struct openfilestruct {
        /* The file's line where the mark is, if any. */
     size_t mark_begin_x;
        /* The file's mark's x-coordinate position, if any. */
+    mark_type kind_of_mark;
+       /* Whether this is a soft or a hard mark. */
     file_format fmt;
        /* The file's format. */
     undo *undotop;
@@ -560,6 +566,16 @@ enum
 #define CONTROL_RIGHT 0x402
 #define CONTROL_UP 0x403
 #define CONTROL_DOWN 0x404
+#define SHIFT_PAGEUP 0x405
+#define SHIFT_PAGEDOWN 0x406
+#define SHIFT_CONTROL_LEFT 0x407
+#define SHIFT_CONTROL_RIGHT 0x408
+#define SHIFT_CONTROL_UP 0x409
+#define SHIFT_CONTROL_DOWN 0x40a
+#define SHIFT_ALT_LEFT 0x40b
+#define SHIFT_ALT_RIGHT 0x40c
+#define SHIFT_ALT_UP 0x40d
+#define SHIFT_ALT_DOWN 0x40e
 
 #ifndef NANO_TINY
 /* An imaginary key for when we get a SIGWINCH (window resize). */
diff --git a/src/proto.h b/src/proto.h
index 4f6624e..59bd5e0 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -35,6 +35,8 @@ extern bool console;
 #endif
 
 extern bool meta_key;
+extern bool shift_held;
+
 extern bool focusing;
 
 extern message_type lastmessage;
@@ -44,6 +46,14 @@ extern int controlleft;
 extern int controlright;
 extern int controlup;
 extern int controldown;
+extern int shiftcontrolleft;
+extern int shiftcontrolright;
+extern int shiftcontrolup;
+extern int shiftcontroldown;
+extern int shiftaltleft;
+extern int shiftaltright;
+extern int shiftaltup;
+extern int shiftaltdown;
 #endif
 
 #ifndef DISABLE_WRAPJUSTIFY
diff --git a/src/text.c b/src/text.c
index 0e901d4..7eb6256 100644
--- a/src/text.c
+++ b/src/text.c
@@ -49,16 +49,18 @@ static filestruct *jusbottom = NULL;
 void do_mark(void)
 {
     openfile->mark_set = !openfile->mark_set;
+
     if (openfile->mark_set) {
        statusbar(_("Mark Set"));
        openfile->mark_begin = openfile->current;
        openfile->mark_begin_x = openfile->current_x;
+       openfile->kind_of_mark = HARDMARK;
     } else {
        statusbar(_("Mark Unset"));
        openfile->mark_begin = NULL;
        openfile->mark_begin_x = 0;
-       edit_refresh();
     }
+    edit_refresh();
 }
 #endif /* !NANO_TINY */
 
diff --git a/src/winio.c b/src/winio.c
index faf69b3..647907e 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -336,6 +336,7 @@ int parse_kbinput(WINDOW *win)
     int *kbinput, keycode, retval = ERR;
 
     meta_key = FALSE;
+    shift_held = FALSE;
 
     /* Read in a character. */
     kbinput = get_input(win, 1);
@@ -504,25 +505,65 @@ int parse_kbinput(WINDOW *win)
        return sc_seq_or(do_prev_block, 0);
     else if (retval == controldown)
        return sc_seq_or(do_next_block, 0);
+    else if (retval == shiftcontrolleft) {
+       shift_held = TRUE;
+       return sc_seq_or(do_prev_word_void, 0);
+    } else if (retval == shiftcontrolright) {
+       shift_held = TRUE;
+       return sc_seq_or(do_next_word_void, 0);
+    } else if (retval == shiftcontrolup) {
+       shift_held = TRUE;
+       return sc_seq_or(do_prev_block, 0);
+    } else if (retval == shiftcontroldown) {
+       shift_held = TRUE;
+       return sc_seq_or(do_next_block, 0);
+    } else if (retval == shiftaltleft) {
+       shift_held = TRUE;
+       return sc_seq_or(do_home, 0);
+    } else if (retval == shiftaltright) {
+       shift_held = TRUE;
+       return sc_seq_or(do_end, 0);
+    } else if (retval == shiftaltup) {
+       shift_held = TRUE;
+       return sc_seq_or(do_page_up, 0);
+    } else if (retval == shiftaltdown) {
+       shift_held = TRUE;
+       return sc_seq_or(do_page_down, 0);
+    }
 #endif
 
 #if defined(__linux__) && !defined(NANO_TINY)
     /* When not running under X, check for the bare arrow keys whether
-     * the Ctrl key is being held together with them. */
-    if (console && (retval == KEY_UP || retval == KEY_DOWN ||
-                       retval == KEY_LEFT || retval == KEY_RIGHT)) {
-       unsigned char modifiers = 6;
+     * Shift/Ctrl/Alt are being held together with them. */
+    unsigned char modifiers = 6;
+
+    if (console && ioctl(0, TIOCLINUX, &modifiers) >= 0) {
+       if (modifiers & 0x01)
+           shift_held =TRUE;
 
-       if (ioctl(0, TIOCLINUX, &modifiers) >= 0 && (modifiers & 0x04)) {
+       /* Is Ctrl being held? */
+       if (modifiers & 0x04) {
            if (retval == KEY_UP)
                return sc_seq_or(do_prev_block, 0);
            else if (retval == KEY_DOWN)
                return sc_seq_or(do_next_block, 0);
            else if (retval == KEY_LEFT)
                return sc_seq_or(do_prev_word_void, 0);
-           else
+           else if (retval == KEY_RIGHT)
                return sc_seq_or(do_next_word_void, 0);
        }
+
+       /* Are both Shift and Alt being held? */
+       if ((modifiers & 0x09) == 0x09) {
+           if (retval == KEY_UP)
+               return sc_seq_or(do_page_up, 0);
+           else if (retval == KEY_DOWN)
+               return sc_seq_or(do_page_down, 0);
+           else if (retval == KEY_LEFT)
+               return sc_seq_or(do_home, 0);
+           else if (retval == KEY_RIGHT)
+               return sc_seq_or(do_end, 0);
+       }
     }
 #endif /* __linux__ && !NANO_TINY */
 
@@ -530,37 +571,53 @@ int parse_kbinput(WINDOW *win)
 #ifdef KEY_SLEFT
        /* Slang doesn't support KEY_SLEFT. */
        case KEY_SLEFT:
+           shift_held = TRUE;
            return sc_seq_or(do_left, keycode);
 #endif
 #ifdef KEY_SRIGHT
        /* Slang doesn't support KEY_SRIGHT. */
        case KEY_SRIGHT:
+           shift_held = TRUE;
            return sc_seq_or(do_right, keycode);
 #endif
 #ifdef KEY_SUP
        /* ncurses and Slang don't support KEY_SUP. */
        case KEY_SUP:
-           return sc_seq_or(do_up_void, keycode);
 #endif
+       case KEY_SR:    /* Scroll backward, on Xfce4-terminal. */
+           shift_held = TRUE;
+           return sc_seq_or(do_up_void, keycode);
 #ifdef KEY_SDOWN
        /* ncurses and Slang don't support KEY_SDOWN. */
        case KEY_SDOWN:
-           return sc_seq_or(do_down_void, keycode);
 #endif
+       case KEY_SF:    /* Scroll forward, on Xfce4-terminal. */
+           shift_held = TRUE;
+           return sc_seq_or(do_down_void, keycode);
 #ifdef KEY_SHOME
        /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
        case KEY_SHOME:
+           shift_held = TRUE;
 #endif
        case KEY_A1:    /* Home (7) on keypad with NumLock off. */
            return sc_seq_or(do_home, keycode);
 #ifdef KEY_SEND
        /* HP-UX 10-11 and Slang don't support KEY_SEND. */
        case KEY_SEND:
+           shift_held = TRUE;
 #endif
        case KEY_C1:    /* End (1) on keypad with NumLock off. */
            return sc_seq_or(do_end, keycode);
+#ifndef NANO_TINY
+       case SHIFT_PAGEUP:              /* Fake key, from Shift+Alt+Up. */
+           shift_held = TRUE;
+#endif
        case KEY_A3:    /* PageUp (9) on keypad with NumLock off. */
            return sc_seq_or(do_page_up, keycode);
+#ifndef NANO_TINY
+       case SHIFT_PAGEDOWN:    /* Fake key, from Shift+Alt+Down. */
+           shift_held = TRUE;
+#endif
        case KEY_C3:    /* PageDown (3) on keypad with NumLock off. */
            return sc_seq_or(do_page_down, keycode);
 #ifdef KEY_SDC
@@ -646,6 +703,7 @@ int convert_sequence(const int *seq, size_t seq_len)
                    case 'B': /* Esc O 1 ; 2 B == Shift-Down on Terminal. */
                    case 'C': /* Esc O 1 ; 2 C == Shift-Right on Terminal. */
                    case 'D': /* Esc O 1 ; 2 D == Shift-Left on Terminal. */
+                       shift_held = TRUE;
                        return arrow_from_abcd(seq[4]);
                    case 'P': /* Esc O 1 ; 2 P == F13 on Terminal. */
                        return KEY_F(13);
@@ -851,9 +909,26 @@ int convert_sequence(const int *seq, size_t seq_len)
                    case 'B': /* Esc [ 1 ; 2 B == Shift-Down on xterm. */
                    case 'C': /* Esc [ 1 ; 2 C == Shift-Right on xterm. */
                    case 'D': /* Esc [ 1 ; 2 D == Shift-Left on xterm. */
+                       shift_held = TRUE;
                        return arrow_from_abcd(seq[4]);
                }
                break;
+#ifndef NANO_TINY
+           case '4':
+               /* When the arrow keys are held together with Shift+Meta,
+                * act as if they are Home/End/PgUp/PgDn with Shift. */
+               switch (seq[4]) {
+                   case 'A': /* Esc [ 1 ; 4 A == Shift-Alt-Up on xterm. */
+                       return SHIFT_PAGEUP;
+                   case 'B': /* Esc [ 1 ; 4 B == Shift-Alt-Down on xterm. */
+                       return SHIFT_PAGEDOWN;
+                   case 'C': /* Esc [ 1 ; 4 C == Shift-Alt-Right on xterm. */
+                       return KEY_SEND;
+                   case 'D': /* Esc [ 1 ; 4 D == Shift-Alt-Left on xterm. */
+                       return KEY_SHOME;
+               }
+               break;
+#endif
            case '5':
                switch (seq[4]) {
                    case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */
@@ -866,6 +941,20 @@ int convert_sequence(const int *seq, size_t seq_len)
                        return CONTROL_LEFT;
                }
                break;
+#ifndef NANO_TINY
+           case '6':
+               switch (seq[4]) {
+                   case 'A': /* Esc [ 1 ; 6 A == Shift-Ctrl-Up on xterm. */
+                       return shiftcontrolup;
+                   case 'B': /* Esc [ 1 ; 6 B == Shift-Ctrl-Down on xterm. */
+                       return shiftcontroldown;
+                   case 'C': /* Esc [ 1 ; 6 C == Shift-Ctrl-Right on xterm. */
+                       return shiftcontrolright;
+                   case 'D': /* Esc [ 1 ; 6 D == Shift-Ctrl-Left on xterm. */
+                       return shiftcontrolleft;
+               }
+               break;
+#endif
        }
 
                        } else if (seq_len > 2 && seq[2] == '~')
@@ -1001,6 +1090,7 @@ int convert_sequence(const int *seq, size_t seq_len)
                    case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
                    case 'c': /* Esc [ c == Shift-Right on rxvt/Eterm. */
                    case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
+                       shift_held = TRUE;
                        return arrow_from_abcd(seq[1]);
                    case '[':
                        if (seq_len > 2 ) {
-- 
2.9.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]