diff --git a/NEWS b/NEWS index df92a5cc..e67bd54c 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ To be released as ELinks 0.13.0. * minor bug 54, Debian bug 338402: Don't force the terminal to 8 bits with no parity. +* enhancement 867: Use bracketed paste mode on xterm. This requires + xterm patch #228 or later configured with --enable-readline-mouse. ELinks 0.12.GIT now: -------------------- diff --git a/src/terminal/event.h b/src/terminal/event.h index 9de3ce1e..a1b81640 100644 --- a/src/terminal/event.h +++ b/src/terminal/event.h @@ -181,7 +181,7 @@ void in_term(struct terminal *); #define get_kbd_modifier(event) (kbd_get_modifier(&(event)->info.keyboard)) #define check_kbd_modifier(event, mod) (kbd_modifier_is(&(event)->info.keyboard, (mod))) -#define check_kbd_textinput_key(event) (get_kbd_key(event) >= ' ' && check_kbd_modifier(event, KBD_MOD_NONE)) +#define check_kbd_textinput_key(event) (get_kbd_key(event) >= ' ' && (check_kbd_modifier(event, KBD_MOD_NONE) || check_kbd_modifier(event, KBD_MOD_PASTE))) #define check_kbd_label_key(event) (get_kbd_key(event) > ' ' && (check_kbd_modifier(event, KBD_MOD_NONE) || check_kbd_modifier(event, KBD_MOD_ALT))) /** @} */ diff --git a/src/terminal/itrm.h b/src/terminal/itrm.h index 1423539e..3e5f8b43 100644 --- a/src/terminal/itrm.h +++ b/src/terminal/itrm.h @@ -108,6 +108,7 @@ struct itrm { * and windows should not be displayed on the terminal of the * itrm; thus the terminal init and done strings are not sent. */ unsigned int remote:1; /**< Whether it is a remote session */ + unsigned int bracketed_pasting:1;/**< Received bracketed-paste escape*/ }; #endif diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c index 1d342323..93d6dc6d 100644 --- a/src/terminal/kbd.c +++ b/src/terminal/kbd.c @@ -148,6 +148,9 @@ kbd_ctrl_c(void) struct interlink_event ev; if (!ditrm) return; + /* This is called because of a signal, and there may be input + * pending from the terminal, so do not reset + * ditrm->bracketed_pasting. */ set_kbd_interlink_event(&ev, KBD_CTRL_C, KBD_MOD_NONE); itrm_queue_event(ditrm, (unsigned char *) &ev, sizeof(ev)); } @@ -158,6 +161,7 @@ kbd_ctrl_c(void) #define INIT_TERMINAL_SEQ "\033)0\0337" /**< Special Character and Line Drawing Set, Save Cursor */ #define INIT_ALT_SCREEN_SEQ "\033[?47h" /**< Use Alternate Screen Buffer */ +#define INIT_BRACKETED_PASTE_SEQ "\033[?2004h" /**< Enable XTerm bracketed paste mode */ static void send_init_sequence(int h, int altscreen) @@ -171,15 +175,18 @@ send_init_sequence(int h, int altscreen) #ifdef CONFIG_MOUSE send_mouse_init_sequence(h); #endif + write_sequence(h, INIT_BRACKETED_PASTE_SEQ); } #define DONE_CLS_SEQ "\033[2J" /**< Erase in Display, Clear All */ #define DONE_TERMINAL_SEQ "\0338\r \b" /**< Restore Cursor (DECRC) + ??? */ #define DONE_ALT_SCREEN_SEQ "\033[?47l" /**< Use Normal Screen Buffer */ +#define DONE_BRACKETED_PASTE_SEQ "\033[?2004l" /**< Disable XTerm bracketed paste mode */ static void send_done_sequence(int h, int altscreen) { + write_sequence(h, DONE_BRACKETED_PASTE_SEQ); write_sequence(h, DONE_CLS_SEQ); #ifdef CONFIG_MOUSE @@ -863,6 +870,9 @@ decode_terminal_escape_sequence(struct itrm *itrm, struct interlink_event *ev) case 33: kbd.key = KBD_F9; kbd.modifier = KBD_MOD_SHIFT; break; case 34: kbd.key = KBD_F10; kbd.modifier = KBD_MOD_SHIFT; break; + case 200: itrm->bracketed_pasting = 1; break; /* xterm */ + case 201: itrm->bracketed_pasting = 0; break; /* xterm */ + } break; case 'R': resize_terminal(); break; /* CPR u6 */ @@ -1006,6 +1016,7 @@ kbd_timeout(struct itrm *itrm) set_kbd_event(&ev, itrm->in.queue.data[0], KBD_MOD_NONE); el = 1; } + itrm->bracketed_pasting = 0; itrm_queue_event(itrm, (char *) &ev, sizeof(ev)); itrm->in.queue.len -= el; @@ -1121,13 +1132,18 @@ process_queue(struct itrm *itrm) if (el == 0) { el = 1; - set_kbd_event(&ev, itrm->in.queue.data[0], KBD_MOD_NONE); + set_kbd_event(&ev, itrm->in.queue.data[0], + itrm->bracketed_pasting ? KBD_MOD_PASTE : KBD_MOD_NONE); } /* The call to decode_terminal_escape_sequence() might have changed the * keyboard event to a mouse event. */ - if (ev.ev == EVENT_MOUSE || ev.info.keyboard.key != KBD_UNDEF) + if (ev.ev == EVENT_MOUSE || ev.info.keyboard.key != KBD_UNDEF) { itrm_queue_event(itrm, (char *) &ev, sizeof(ev)); + itrm->bracketed_pasting = + (ev.ev == EVENT_KBD + && (ev.info.keyboard.modifier & KBD_MOD_PASTE)); + } return_without_event: if (el == -1) { diff --git a/src/terminal/kbd.h b/src/terminal/kbd.h index e886f8cb..c42d3b6a 100644 --- a/src/terminal/kbd.h +++ b/src/terminal/kbd.h @@ -32,7 +32,8 @@ typedef enum { KBD_MOD_NONE = 0, KBD_MOD_SHIFT = 1, KBD_MOD_CTRL = 2, - KBD_MOD_ALT = 4 + KBD_MOD_ALT = 4, + KBD_MOD_PASTE = 8, } term_event_modifier_T; /** A key received from a terminal, with modifiers. */ diff --git a/src/viewer/text/view.c b/src/viewer/text/view.c index 7be9b63b..1ba33469 100644 --- a/src/viewer/text/view.c +++ b/src/viewer/text/view.c @@ -999,7 +999,9 @@ try_prefix_key(struct session *ses, struct document_view *doc_view, if (digit < 0 || digit > 9) return FRAME_EVENT_IGNORED; - if (get_kbd_modifier(ev) + if ((get_kbd_modifier(ev) != KBD_MOD_NONE + && (get_kbd_modifier(ev) & ~(KBD_MOD_ALT | KBD_MOD_CTRL)) + == KBD_MOD_NONE) || ses->kbdprefix.repeat_count /* The user has already begun * entering a prefix. */ || !doc_opts->num_links_key @@ -1027,7 +1029,7 @@ try_prefix_key(struct session *ses, struct document_view *doc_view, return FRAME_EVENT_OK; } - if (digit >= 1 && !get_kbd_modifier(ev)) { + if (digit >= 1 && get_kbd_modifier(ev) == KBD_MOD_NONE) { int nlinks = document->nlinks, length; unsigned char d[2] = { get_kbd_key(ev), 0 }; @@ -1063,7 +1065,9 @@ try_form_insert_mode(struct session *ses, struct document_view *doc_view, action_id = kbd_action(KEYMAP_EDIT, ev, NULL); if (ses->insert_mode == INSERT_MODE_OFF) { - if (action_id == ACT_EDIT_ENTER) { + if (action_id == ACT_EDIT_ENTER + || (action_id == -1 + && check_kbd_modifier(ev, KBD_MOD_PASTE))) { ses->insert_mode = INSERT_MODE_ON; status = FRAME_EVENT_REFRESH; }