diff options
author | Yorhel <git@yorhel.nl> | 2014-05-11 08:34:26 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2014-05-11 08:36:42 +0200 |
commit | 505b387717bea9ea4623059cfff9e41965003bb6 (patch) | |
tree | 91342a6d7826093e5a313931ed7b8883e8911c25 /src | |
parent | 4b5607df10dc78a22ee09603e2f5c598f62055dc (diff) |
Add support for bracketed paste mode + confirm-to-send multiline strings
Slightly modified patch from http://dev.yorhel.nl/ncdc/bug/66
Diffstat (limited to 'src')
-rw-r--r-- | src/commands.c | 7 | ||||
-rw-r--r-- | src/main.c | 9 | ||||
-rw-r--r-- | src/ui.c | 7 | ||||
-rw-r--r-- | src/ui_textinput.c | 45 |
4 files changed, 63 insertions, 5 deletions
diff --git a/src/commands.c b/src/commands.c index f234d18..6c83267 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1313,6 +1313,13 @@ void cmd_handle(char *ostr) { // it is a command, extract cmd and args } else { cmd++; + + if(strchr(cmd, '\n')) { + g_free(str); + ui_m(NULL, 0, "Commands cannot contain newlines"); + return; + } + char *sep = strchr(cmd, ' '); if(sep) *sep = 0; @@ -50,7 +50,9 @@ GMainLoop *main_loop; #define INPT_CODE(key) ((gunichar)((key)&G_GUINT64_CONSTANT(0xFFFFFFFF))) #define INPT_TYPE(key) ((char)((key)>>32)) -#define KEY_ESCAPE (KEY_MAX+1) +#define KEY_ESCAPE (KEY_MAX+1) +#define KEY_BRACKETED_PASTE_START (KEY_ESCAPE+1) +#define KEY_BRACKETED_PASTE_END (KEY_BRACKETED_PASTE_START+1) #endif @@ -126,7 +128,7 @@ static void handle_input() { if(INPT_TYPE(key) != 1) continue; if(INPT_CODE(key) == '[') { - curignore = 0; + curignore = 1; continue; } key |= (guint64)3<<32; // a not very nice way of saying "turn this key into a INPT_ALT" @@ -503,6 +505,9 @@ int main(int argc, char **argv) { refresh(); endwin(); + // reset bracketed paste mode + printf("\x1b[?2004l"); // http://www.xfree86.org/current/ctlseqs.html#C1%20%288-Bit%29%20Control%20Characters + printf("Flushing unsaved data to disk..."); fflush(stdout); } @@ -254,6 +254,13 @@ void ui_init() { keypad(stdscr, 1); nodelay(stdscr, 1); + // ensure curses is init'd before event-keys defined before events happen + define_key("\x1b[200~", KEY_BRACKETED_PASTE_START); + define_key("\x1b[201~", KEY_BRACKETED_PASTE_END); + + const char paste_mode[] = "\x1b[?2004h"; + write(STDOUT_FILENO, paste_mode, sizeof(paste_mode)-1); + // global textinput field ui_global_textinput = ui_textinput_create(TRUE, cmd_suggest); diff --git a/src/ui_textinput.c b/src/ui_textinput.c index b8608ea..a67cd18 100644 --- a/src/ui_textinput.c +++ b/src/ui_textinput.c @@ -152,6 +152,7 @@ struct ui_textinput_t { void (*complete)(char *, char **); char *c_q, *c_last, **c_sug; int c_cur; + gboolean bracketed_paste; }; #endif @@ -163,6 +164,7 @@ ui_textinput_t *ui_textinput_create(gboolean usehist, void (*complete)(char *, c ti->usehist = usehist; ti->s_pos = -1; ti->complete = complete; + ti->bracketed_paste = FALSE; return ti; } @@ -284,7 +286,9 @@ void ui_textinput_draw(ui_textinput_t *ti, int y, int x, int col, ui_cursor_t *c if(f <= -col) break; if(f < 0) { - addnstr(ostr, str-ostr); + // Don't display control characters + if(*ostr >= 32) + addnstr(ostr, str-ostr); if(i < ti->pos) pos += l; } @@ -426,12 +430,47 @@ gboolean ui_textinput_key(ui_textinput_t *ti, guint64 key, char **str) { return FALSE; break; case INPT_CTRL('i'): // tab - autocomplete - ui_textinput_complete(ti); - completereset = FALSE; + if(ti->bracketed_paste) { + g_string_insert_unichar(ti->str, g_utf8_offset_to_pointer(ti->str->str, ti->pos)-ti->str->str, ' '); + ti->pos++; + return FALSE; + } else { + ui_textinput_complete(ti); + completereset = FALSE; + } break; case INPT_CTRL('j'): // newline - accept & clear + if(ti->bracketed_paste) { + g_string_insert_unichar(ti->str, g_utf8_offset_to_pointer(ti->str->str, ti->pos)-ti->str->str, '\n'); + ti->pos++; + return FALSE; + } + + // if not responded to, input simply keeps buffering; avoids modality + // reappearing after each (non-bracketed) newline avoids user confusion + // UTF-8: <32 always 1 byte from trusted input + { + int num_lines = 1; + char *c; + for(c=ti->str->str; *c; c++) + num_lines += *c == '\n'; + if(num_lines > 1) { + ui_mf(NULL, UIM_NOLOG, "Press Ctrl-y to accept %d-line paste", num_lines); + break; + } + } + + *str = ui_textinput_reset(ti); + break; + case INPT_CTRL('y'): // C-y - accept bracketed paste *str = ui_textinput_reset(ti); break; + case KEY_BRACKETED_PASTE_START: + ti->bracketed_paste = TRUE; + break; + case KEY_BRACKETED_PASTE_END: + ti->bracketed_paste = FALSE; + break; default: if(INPT_TYPE(key) == 1) { // char g_string_insert_unichar(ti->str, g_utf8_offset_to_pointer(ti->str->str, ti->pos)-ti->str->str, INPT_CODE(key)); |