1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

Added pasting detection. All keys except CR and LF are pasted as-is into

prompt in pasting mode.

/SET paste_detect_time controls how closely each others characters must
occur for it to be considered pasting. Pasting mode goes on after /SET
paste_detect_keycount characters have been received and detected as pasting.

The first paste_detect_keycount characters can also contain some command
characters. They are executed, but their action in entry line is reverted
once pasting is detected. Of course, if any such character was followed by
CR/LF, it was already sent to channel/query and is unreversable.

What this means in practise is that even if you have TABs (assuming TAB is
completion key) in the first few pasted characters, they get pasted as TABs
as long as they weren't immediately followed by CR/LF.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3153 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2003-11-16 19:37:31 +00:00 committed by cras
parent c8b792e92b
commit d79cc02a10

View File

@ -37,6 +37,8 @@
#include <signal.h> #include <signal.h>
#define PASTE_MAX_KEYCOUNT 100
typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item); typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item);
typedef void (*ENTRY_REDIRECT_ENTRY_FUNC) (const char *line, void *data, SERVER_REC *server, WI_ITEM_REC *item); typedef void (*ENTRY_REDIRECT_ENTRY_FUNC) (const char *line, void *data, SERVER_REC *server, WI_ITEM_REC *item);
@ -51,7 +53,12 @@ static ENTRY_REDIRECT_REC *redir;
static int escape_next_key; static int escape_next_key;
static int readtag; static int readtag;
static time_t idle_time; static GTimeVal last_keypress;
static int paste_detect_time, paste_detect_keycount;
static int paste_state, paste_start_key;
static char *paste_entry, *prev_entry;
static int paste_entry_pos, prev_entry_pos;
static unichar prev_key, paste_keys[PASTE_MAX_KEYCOUNT];
static void sig_input(void); static void sig_input(void);
@ -134,10 +141,68 @@ static void window_next_page(void)
gui_window_scroll(active_win, get_scroll_count()); gui_window_scroll(active_win, get_scroll_count());
} }
#define IS_PASTE_SKIP_KEY(c) \
((c) == '\r' || (c) == '\n')
static int check_pasting(unichar key, int diff)
{
int i;
if (paste_state == 0) {
/* two keys hit together quick. possibly pasting */
if (diff > paste_detect_time)
return FALSE;
g_free(paste_entry);
paste_entry = g_strdup(prev_entry);
paste_entry_pos = prev_entry_pos;
paste_state++;
paste_start_key = IS_PASTE_SKIP_KEY(prev_key) ? 1 : 0;
paste_keys[0] = prev_key;
} else if (paste_state > 0 && diff > paste_detect_time) {
/* reset paste state */
paste_state = 0;
return FALSE;
}
/* continuing quick hits */
if (paste_state == paste_detect_keycount) {
/* pasting.. */
if (IS_PASTE_SKIP_KEY(key)) {
/* handle CR/LF the normal way */
return FALSE;
}
gui_entry_insert_char(active_entry, key);
return TRUE;
}
if (IS_PASTE_SKIP_KEY(key)) {
/* we might be pasting, but we can't go back from executed
commands.. */
paste_start_key = ++paste_state;
return FALSE;
}
paste_keys[paste_state++] = key;
if (paste_state == paste_detect_keycount) {
/* ok, we started pasting. */
gui_entry_set_text(active_entry, paste_entry);
gui_entry_set_pos(active_entry, paste_entry_pos);
for (i = paste_start_key; i < paste_detect_keycount; i++)
gui_entry_insert_char(active_entry, paste_keys[i]);
return TRUE;
}
return FALSE;
}
static void sig_gui_key_pressed(gpointer keyp) static void sig_gui_key_pressed(gpointer keyp)
{ {
GTimeVal now;
unichar key; unichar key;
char str[20]; char str[20];
int diff;
key = GPOINTER_TO_INT(keyp); key = GPOINTER_TO_INT(keyp);
@ -146,7 +211,13 @@ static void sig_gui_key_pressed(gpointer keyp)
return; return;
} }
idle_time = time(NULL); g_get_current_time(&now);
diff = (now.tv_sec - last_keypress.tv_sec) * 1000 +
(now.tv_usec - last_keypress.tv_usec)/1000;
last_keypress = now;
if (check_pasting(key, diff))
return;
if (key < 32) { if (key < 32) {
/* control key */ /* control key */
@ -177,6 +248,11 @@ static void sig_gui_key_pressed(gpointer keyp)
str[2] = '\0'; str[2] = '\0';
} }
g_free(prev_entry);
prev_entry = gui_entry_get_text(active_entry);
prev_entry_pos = gui_entry_get_pos(active_entry);
prev_key = key;
if (escape_next_key || !key_pressed(keyboard, str)) { if (escape_next_key || !key_pressed(keyboard, str)) {
/* key wasn't used for anything, print it */ /* key wasn't used for anything, print it */
escape_next_key = FALSE; escape_next_key = FALSE;
@ -385,7 +461,7 @@ static void sig_input(void)
time_t get_idle_time(void) time_t get_idle_time(void)
{ {
return idle_time; return last_keypress.tv_sec;
} }
static void key_scroll_backward(void) static void key_scroll_backward(void)
@ -637,6 +713,21 @@ static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry,
gui_entry_set_prompt(active_entry, entry); gui_entry_set_prompt(active_entry, entry);
} }
static void setup_changed(void)
{
paste_detect_time = settings_get_time("paste_detect_time");
if (paste_detect_time == 0)
paste_state = -1;
else if (paste_state == -1)
paste_state = 0;
paste_detect_keycount = settings_get_int("paste_detect_keycount");
if (paste_detect_keycount < 2)
paste_detect_keycount = 2;
else if (paste_detect_keycount > PASTE_MAX_KEYCOUNT)
paste_detect_keycount = PASTE_MAX_KEYCOUNT;
}
void gui_readline_init(void) void gui_readline_init(void)
{ {
static char changekeys[] = "1234567890qwertyuio"; static char changekeys[] = "1234567890qwertyuio";
@ -645,10 +736,16 @@ void gui_readline_init(void)
escape_next_key = FALSE; escape_next_key = FALSE;
redir = NULL; redir = NULL;
idle_time = time(NULL); paste_state = 0;
paste_entry = NULL;
paste_entry_pos = 0;
g_get_current_time(&last_keypress);
input_listen_init(STDIN_FILENO); input_listen_init(STDIN_FILENO);
settings_add_str("history", "scroll_page_count", "/2"); settings_add_str("history", "scroll_page_count", "/2");
settings_add_time("misc", "paste_detect_time", "10msecs");
settings_add_int("misc", "paste_detect_keycount", 5);
setup_changed();
keyboard = keyboard_create(NULL); keyboard = keyboard_create(NULL);
key_configure_freeze(); key_configure_freeze();
@ -774,6 +871,7 @@ void gui_readline_init(void)
signal_add("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed); signal_add("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
signal_add("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect); signal_add("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect);
signal_add("gui key pressed", (SIGNAL_FUNC) sig_gui_key_pressed); signal_add("gui key pressed", (SIGNAL_FUNC) sig_gui_key_pressed);
signal_add("setup changed", (SIGNAL_FUNC) setup_changed);
} }
void gui_readline_deinit(void) void gui_readline_deinit(void)
@ -838,4 +936,5 @@ void gui_readline_deinit(void)
signal_remove("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed); signal_remove("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
signal_remove("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect); signal_remove("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect);
signal_remove("gui key pressed", (SIGNAL_FUNC) sig_gui_key_pressed); signal_remove("gui key pressed", (SIGNAL_FUNC) sig_gui_key_pressed);
signal_remove("setup changed", (SIGNAL_FUNC) setup_changed);
} }