From 439e6486db24fb18f0cb2ac22e16a6327e1d8ad4 Mon Sep 17 00:00:00 2001 From: James Booth Date: Thu, 3 Jan 2013 00:16:39 +0000 Subject: [PATCH] Handle wide chars on input --- src/input_win.c | 63 +++++++++++++++++++++++++++++++------------------ src/profanity.c | 4 ++-- src/ui.h | 6 +++-- src/windows.c | 10 ++++---- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/input_win.c b/src/input_win.c index c809454e..470f7cb9 100644 --- a/src/input_win.c +++ b/src/input_win.c @@ -38,11 +38,12 @@ * pad_start : 3 * cols : 4 */ - +#define _XOPEN_SOURCE_EXTENDED #include "config.h" #include #include +#include #ifdef HAVE_NCURSES_H #include @@ -64,9 +65,9 @@ static WINDOW *inp_win; static int pad_start = 0; -static int _handle_edit(const int ch, char *input, int *size); -static int _printable(const int ch); -static gboolean _special_key(const int ch); +static int _handle_edit(const wint_t ch, char *input, int *size); +static int _printable(const wint_t ch); +static gboolean _special_key(const wint_t ch); void create_input_window(void) @@ -128,59 +129,73 @@ inp_block(void) wtimeout(inp_win, -1); } -void -inp_get_char(int *ch, char *input, int *size) +wint_t +inp_get_char(char *input, int *size) { int inp_y = 0; int inp_x = 0; int i; + wint_t ch; + int display_size = 0; + + if (*size != 0) { + display_size = g_utf8_strlen(input, *size); + } // echo off, and get some more input noecho(); - *ch = wgetch(inp_win); + wget_wch(inp_win, &ch); gboolean in_command = FALSE; - if ((*size >= 1 && input[0] == '/') || - (*size == 0 && *ch == '/')) { + if ((display_size > 0 && input[0] == '/') || + (display_size == 0 && ch == '/')) { in_command = TRUE; } if (prefs_get_states()) { - if (*ch == ERR) { + if (ch == ERR) { prof_handle_idle(); } - if (prefs_get_outtype() && (*ch != ERR) && !in_command - && _printable(*ch)) { + if (prefs_get_outtype() && (ch != ERR) && !in_command + && _printable(ch)) { prof_handle_activity(); } } // if it wasn't an arrow key etc - if (!_handle_edit(*ch, input, size)) { - if (_printable(*ch)) { + if (!_handle_edit(ch, input, size)) { + if (_printable(ch)) { getyx(inp_win, inp_y, inp_x); // handle insert if not at end of input - if (inp_x < *size) { - winsch(inp_win, *ch); + if (inp_x < display_size) { + winsch(inp_win, ch); wmove(inp_win, inp_y, inp_x+1); for (i = *size; i > inp_x; i--) input[i] = input[i-1]; - input[inp_x] = *ch; + input[inp_x] = ch; (*size)++; // otherwise just append } else { - waddch(inp_win, *ch); - input[(*size)++] = *ch; + cchar_t t = { 0, { ch, 0 } }; + wadd_wch(inp_win, &t); + char bytes[5]; + size_t utf_len = wcrtomb(bytes, ch, NULL); + int i; + for (i = 0 ; i < utf_len; i++) { + input[(*size)++] = bytes[i]; + } + + display_size++; // if gone over screen size follow input int rows, cols; getmaxyx(stdscr, rows, cols); - if (*size - pad_start > cols-2) { + if (display_size - pad_start > cols-2) { pad_start++; prefresh(inp_win, 0, pad_start, rows-1, 0, rows-1, cols-1); } @@ -191,6 +206,8 @@ inp_get_char(int *ch, char *input, int *size) } echo(); + + return ch; } void @@ -241,7 +258,7 @@ inp_replace_input(char *input, const char * const new_input, int *size) * return 0 if it wasnt */ static int -_handle_edit(const int ch, char *input, int *size) +_handle_edit(const wint_t ch, char *input, int *size) { int i, rows, cols; char *prev = NULL; @@ -414,7 +431,7 @@ _handle_edit(const int ch, char *input, int *size) } static int -_printable(const int ch) +_printable(const wint_t ch) { return (ch != ERR && ch != '\n' && ch != KEY_PPAGE && ch != KEY_NPAGE && ch != KEY_MOUSE && @@ -427,7 +444,7 @@ _printable(const int ch) } static gboolean -_special_key(const int ch) +_special_key(const wint_t ch) { char *str = unctrl(ch); return ((strlen(str) > 1) && g_str_has_prefix(str, "^")); diff --git a/src/profanity.c b/src/profanity.c index 47440b35..c4df79a6 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -67,7 +67,7 @@ prof_run(const int disable_tls, char *log_level) int size = 0; while(cmd_result == TRUE) { - int ch = ERR; + wint_t ch = ERR; size = 0; while(ch != '\n') { @@ -95,7 +95,7 @@ prof_run(const int disable_tls, char *log_level) ui_refresh(); jabber_process_events(); - inp_get_char(&ch, inp, &size); + ch = inp_get_char(inp, &size); if (ch != ERR) { ui_reset_idle_time(); diff --git a/src/ui.h b/src/ui.h index 9f498a4b..556761d0 100644 --- a/src/ui.h +++ b/src/ui.h @@ -25,6 +25,8 @@ #include "config.h" +#include + #include #ifdef HAVE_NCURSES_H @@ -73,7 +75,7 @@ void ui_contact_online(const char * const from, const char * const show, void ui_contact_offline(const char * const from, const char * const show, const char * const status); void ui_disconnected(void); -void ui_handle_special_keys(const int * const ch); +void ui_handle_special_keys(const wint_t * const ch); void ui_switch_win(const int i); gboolean ui_windows_full(void); unsigned long ui_get_idle_time(void); @@ -170,7 +172,7 @@ void status_bar_new(const int win); void status_bar_update_time(void); // input window actions -void inp_get_char(int *ch, char *input, int *size); +wint_t inp_get_char(char *input, int *size); void inp_clear(void); void inp_win_resize(const char * input, const int size); void inp_put_back(void); diff --git a/src/windows.c b/src/windows.c index cc15c60e..a52ac2e8 100644 --- a/src/windows.c +++ b/src/windows.c @@ -102,8 +102,8 @@ static void _show_status_string(WINDOW *win, const char * const from, static void _cons_show_typing(const char * const short_from); static void _cons_show_incoming_message(const char * const short_from, const int win_index); -static void _win_handle_switch(const int * const ch); -static void _win_handle_page(const int * const ch); +static void _win_handle_switch(const wint_t * const ch); +static void _win_handle_page(const wint_t * const ch); static void _win_resize_all(void); static gint _win_get_unread(void); static void _win_show_history(WINDOW *win, int win_index, @@ -506,7 +506,7 @@ ui_disconnected(void) } void -ui_handle_special_keys(const int * const ch) +ui_handle_special_keys(const wint_t * const ch) { _win_handle_switch(ch); _win_handle_page(ch); @@ -2123,7 +2123,7 @@ _cons_show_contact(PContact contact) } static void -_win_handle_switch(const int * const ch) +_win_handle_switch(const wint_t * const ch) { if (*ch == KEY_F(1)) { ui_switch_win(0); @@ -2149,7 +2149,7 @@ _win_handle_switch(const int * const ch) } static void -_win_handle_page(const int * const ch) +_win_handle_page(const wint_t * const ch) { int rows = getmaxy(stdscr); int y = getcury(current->win);