From 27afc1e7d25b9e260b5d03ef19576397fb63204d Mon Sep 17 00:00:00 2001 From: Sebastien Helleu Date: Thu, 18 Aug 2011 17:30:18 +0200 Subject: core: fix input of wide UTF-8 chars under Cygwin (bug #34061) --- ChangeLog | 3 +- src/gui/curses/gui-curses-key.c | 247 +++++++++++++++++++--------------------- 2 files changed, 119 insertions(+), 131 deletions(-) diff --git a/ChangeLog b/ChangeLog index 10628a57a..f215202fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,13 @@ WeeChat ChangeLog ================= Sébastien Helleu -v0.3.6-dev, 2011-08-17 +v0.3.6-dev, 2011-08-18 Version 0.3.6 (under dev!) -------------------------- +* core: fix input of wide UTF-8 chars under Cygwin (bug #34061) * core: allow name of buffer for command /buffer clear (task #11269) * core: add new command /repeat (execute a command several times) * core: save and restore layout for buffers and windows on /upgrade diff --git a/src/gui/curses/gui-curses-key.c b/src/gui/curses/gui-curses-key.c index 9a96275b0..7c21b1f7f 100644 --- a/src/gui/curses/gui-curses-key.c +++ b/src/gui/curses/gui-curses-key.c @@ -287,7 +287,10 @@ void gui_key_flush () { int i, key, insert_ok; - char key_str[32], *key_utf, *input_old; + static char key_str[64] = { '\0' }; + static int length_key_str = 0; + char key_temp[2], *key_utf, *input_old, *ptr_char, *next_char, *ptr_error; + char utf_partial_char[16]; /* * if there's no paste pending, then we use buffer and do actions @@ -301,164 +304,148 @@ gui_key_flush () for (i = 0; i < gui_key_buffer_size; i++) { key = gui_key_buffer[i]; - insert_ok = 1; + utf_partial_char[0] = '\0'; - if (gui_mouse_event_pending) - { - insert_ok = 0; - key_str[0] = (char) key; - key_str[1] = '\0'; - } - else if (key < 32) + if (gui_mouse_event_pending || (key < 32) || (key == 127)) { - insert_ok = 0; - key_str[0] = '\x01'; - key_str[1] = (char) key + '@'; - key_str[2] = '\0'; - } - else if (key == 127) - { - key_str[0] = '\x01'; - key_str[1] = '?'; - key_str[2] = '\0'; + if (gui_mouse_event_pending) + { + insert_ok = 0; + key_str[0] = (char)key; + key_str[1] = '\0'; + length_key_str = 1; + } + else if (key < 32) + { + insert_ok = 0; + key_str[0] = '\x01'; + key_str[1] = (char)key + '@'; + key_str[2] = '\0'; + length_key_str = 2; + } + else if (key == 127) + { + key_str[0] = '\x01'; + key_str[1] = '?'; + key_str[2] = '\0'; + length_key_str = 2; + } } else { if (local_utf8) { - /* 1 char: 0vvvvvvv */ - if (key < 0x80) - { - key_str[0] = (char) key; - key_str[1] = '\0'; - } - /* 2 chars: 110vvvvv 10vvvvvv */ - else if ((key & 0xE0) == 0xC0) - { - key_str[0] = (char) key; - if (i < gui_key_buffer_size - 1) - { - key_str[1] = (char) (gui_key_buffer[++i]); - key_str[2] = '\0'; - } - else - key_str[1] = '\0'; - } - /* 3 chars: 1110vvvv 10vvvvvv 10vvvvvv */ - else if ((key & 0xF0) == 0xE0) + key_str[length_key_str] = (char)key; + key_str[length_key_str + 1] = '\0'; + length_key_str++; + + /* + * replace invalid chars by "?", but NOT last char of + * string, if it is incomplete UTF-8 char (another char + * will be added to the string on next iteration) + */ + ptr_char = key_str; + while (ptr_char && ptr_char[0]) { - key_str[0] = (char) key; - if (i < gui_key_buffer_size - 1) + (void) utf8_is_valid (ptr_char, &ptr_error); + if (!ptr_error) + break; + next_char = utf8_next_char (ptr_error); + if (next_char && next_char[0]) { - key_str[1] = (char) (gui_key_buffer[++i]); - if (i < gui_key_buffer_size - 1) + ptr_char = ptr_error; + while (ptr_char < next_char) { - key_str[2] = (char) (gui_key_buffer[++i]); - key_str[3] = '\0'; + ptr_char[0] = '?'; + ptr_char++; } - else - key_str[2] = '\0'; } else - key_str[1] = '\0'; - } - /* 4 chars: 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv */ - else if ((key & 0xF8) == 0xF0) - { - key_str[0] = (char) key; - if (i < gui_key_buffer_size - 1) { - key_str[1] = (char) (gui_key_buffer[++i]); - if (i < gui_key_buffer_size - 1) - { - key_str[2] = (char) (gui_key_buffer[++i]); - if (i < gui_key_buffer_size - 1) - { - key_str[3] = (char) (gui_key_buffer[++i]); - key_str[4] = '\0'; - } - else - key_str[3] = '\0'; - } - else - key_str[2] = '\0'; + strcpy (utf_partial_char, ptr_char); + ptr_char[0] = '\0'; + break; } - else - key_str[1] = '\0'; + ptr_char = next_char; } } else { - key_str[0] = (char) key; - key_str[1] = '\0'; - - /* convert input to UTF-8 is user is not using UTF-8 as locale */ - if (!local_utf8) - { - key_utf = string_iconv_to_internal (NULL, key_str); - strncpy (key_str, key_utf, sizeof (key_str)); - key_str[sizeof (key_str) - 1] = '\0'; - } + /* convert input to UTF-8 */ + key_temp[0] = (char) key; + key_temp[1] = '\0'; + key_utf = string_iconv_to_internal (NULL, key_temp); + strcat (key_str, key_utf); } } - - hook_signal_send ("key_pressed", - WEECHAT_HOOK_SIGNAL_STRING, key_str); - - if (gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) - input_old = (gui_current_window->buffer->input_buffer) ? - strdup (gui_current_window->buffer->input_buffer) : strdup (""); - else - input_old = NULL; - - if ((gui_key_pressed (key_str) != 0) && (insert_ok) - && (!gui_cursor_mode)) - { - gui_buffer_undo_snap (gui_current_window->buffer); - gui_input_insert_string (gui_current_window->buffer, - key_str, -1); - if (gui_current_window->buffer->completion) - gui_completion_stop (gui_current_window->buffer->completion, 0); - gui_input_text_changed_modifier_and_signal (gui_current_window->buffer, 1); - } - - /* incremental text search in buffer */ - if ((gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) - && ((input_old == NULL) - || (gui_current_window->buffer->input_buffer == NULL) - || (strcmp (input_old, gui_current_window->buffer->input_buffer) != 0))) + + if (key_str[0]) { - /* - * if current input is longer than old input, and that - * beginning of current input is exactly equal to old input, - * then do nothing (search will not find any result and can - * take some time on buffer with many lines..) - */ - if (!gui_current_window->buffer->text_search_found - && (input_old != NULL) - && (input_old[0]) - && (gui_current_window->buffer->input_buffer != NULL) - && (gui_current_window->buffer->input_buffer[0]) - && (strlen (gui_current_window->buffer->input_buffer) > strlen (input_old)) - && (strncmp (gui_current_window->buffer->input_buffer, input_old, - strlen (input_old)) == 0)) + hook_signal_send ("key_pressed", + WEECHAT_HOOK_SIGNAL_STRING, key_str); + + if (gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) + input_old = (gui_current_window->buffer->input_buffer) ? + strdup (gui_current_window->buffer->input_buffer) : strdup (""); + else + input_old = NULL; + + if ((gui_key_pressed (key_str) != 0) && (insert_ok) + && (!gui_cursor_mode)) { - /* - * do not search text in buffer, just alert about text not - * found - */ - if (CONFIG_BOOLEAN(config_look_search_text_not_found_alert)) - printf ("\a"); + gui_buffer_undo_snap (gui_current_window->buffer); + gui_input_insert_string (gui_current_window->buffer, + key_str, -1); + if (gui_current_window->buffer->completion) + gui_completion_stop (gui_current_window->buffer->completion, 0); + gui_input_text_changed_modifier_and_signal (gui_current_window->buffer, 1); } - else + + /* incremental text search in buffer */ + if ((gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) + && ((input_old == NULL) + || (gui_current_window->buffer->input_buffer == NULL) + || (strcmp (input_old, gui_current_window->buffer->input_buffer) != 0))) { - gui_window_search_restart (gui_current_window); + /* + * if current input is longer than old input, and that + * beginning of current input is exactly equal to old input, + * then do nothing (search will not find any result and can + * take some time on buffer with many lines..) + */ + if (!gui_current_window->buffer->text_search_found + && (input_old != NULL) + && (input_old[0]) + && (gui_current_window->buffer->input_buffer != NULL) + && (gui_current_window->buffer->input_buffer[0]) + && (strlen (gui_current_window->buffer->input_buffer) > strlen (input_old)) + && (strncmp (gui_current_window->buffer->input_buffer, input_old, + strlen (input_old)) == 0)) + { + /* + * do not search text in buffer, just alert about text not + * found + */ + if (CONFIG_BOOLEAN(config_look_search_text_not_found_alert)) + printf ("\a"); + } + else + { + gui_window_search_restart (gui_current_window); + } } + + if (input_old) + free (input_old); } - if (input_old) - free (input_old); + /* prepare incomplete UTF-8 char for next iteration */ + if (utf_partial_char[0]) + strcpy (key_str, utf_partial_char); + else + key_str[0] = '\0'; + length_key_str = strlen (key_str); } gui_key_buffer_reset (); -- cgit v1.2.3