From 2cdbfc7eb7d90ed286c6c5f432990166cdec0b93 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 27 Jan 2015 22:13:09 +0000 Subject: [PATCH] Added gnu readline --- configure.ac | 2 + src/profanity.c | 62 +++++-- src/ui/core.c | 6 + src/ui/inputwin.c | 80 ++++----- src/ui/inputwin.h | 1 + src/ui/keyhandlers.c | 55 +++++- src/ui/keyhandlers.h | 5 +- src/ui/ui.h | 1 + tests/helpers.c | 18 ++ tests/helpers.h | 2 + tests/test_keyhandlers.c | 365 ++++++++++++++++++++++----------------- tests/test_keyhandlers.h | 35 ++-- tests/testsuite.c | 36 ++-- tests/ui/stub_ui.c | 3 + 14 files changed, 428 insertions(+), 243 deletions(-) diff --git a/configure.ac b/configure.ac index 7369f112..2794ad43 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,8 @@ PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.26], [], [AC_MSG_ERROR([glib 2.26 or higher is required for profanity])]) PKG_CHECK_MODULES([curl], [libcurl], [], [AC_MSG_ERROR([libcurl is required for profanity])]) +AC_CHECK_LIB([readline], [main], [], + [AC_MSG_ERROR([libreadline is required for profanity])]) AS_IF([test "x$PLATFORM" = xosx], [LIBS="-lcurl $LIBS"]) diff --git a/src/profanity.c b/src/profanity.c index 13297124..c105d33f 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -43,6 +43,8 @@ #include #include +#include +#include #include "profanity.h" #include "chat_session.h" @@ -71,6 +73,20 @@ static void _create_directories(void); static void _connect_default(const char * const account); static gboolean idle = FALSE; +static void cb_linehandler(char *); +static gboolean cmd_result = TRUE; + +static void +cb_linehandler(char *line) +{ + /* Can use ^D (stty eof) or `exit' to exit. */ + if (*line) { + add_history(line); + } + rl_redisplay(); + cmd_result = cmd_process_input(line); + free(line); +} void prof_run(const int disable_tls, char *log_level, char *account_name) @@ -79,26 +95,44 @@ prof_run(const int disable_tls, char *log_level, char *account_name) _connect_default(account_name); ui_update(); - char *line = NULL; - gboolean cmd_result = TRUE; + fd_set fds; + int r; + rl_callback_handler_install(NULL, cb_linehandler); log_info("Starting main event loop"); + struct timeval t; + t.tv_sec = 0; + t.tv_usec = 10000; + while(cmd_result) { - while(!line) { - _check_autoaway(); - line = ui_readline(); -#ifdef HAVE_LIBOTR - otr_poll(); -#endif - notify_remind(); - jabber_process_events(); - ui_update(); + _check_autoaway(); + + FD_ZERO(&fds); + FD_SET(fileno (rl_instream), &fds); + r = select(FD_SETSIZE, &fds, NULL, NULL, &t); + if (r < 0) { + perror ("rltest: select"); + rl_callback_handler_remove(); + break; } - cmd_result = cmd_process_input(line); - ui_input_clear(); - FREE_SET_NULL(line); + + if (FD_ISSET (fileno (rl_instream), &fds)) { + rl_callback_read_char(); + ui_write(rl_line_buffer, rl_point); + } + + +// line = ui_readline(); +#ifdef HAVE_LIBOTR + otr_poll(); +#endif + notify_remind(); + jabber_process_events(); + ui_update(); } + + rl_callback_handler_remove(); } void diff --git a/src/ui/core.c b/src/ui/core.c index e295a3ad..efebdb5e 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -177,6 +177,12 @@ ui_close(void) endwin(); } +void +ui_write(char *line, int offset) +{ + inp_write(line, offset); +} + char* ui_readline(void) { diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index 7b5c33d0..64c65a96 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -131,6 +131,43 @@ inp_win_resize(void) _inp_win_update_virtual(); } +static int +offset_to_col(char *str, int offset) +{ + int i = 0; + int col = 0; + mbstate_t internal; + + while (i != offset && str[i] != '\n') { + gunichar uni = g_utf8_get_char(&str[i]); + size_t ch_len = mbrlen(&str[i], 4, &internal); + i += ch_len; + col++; + if (g_unichar_iswide(uni)) { + col++; + } + } + + return col; +} + +void +inp_write(char *line, int offset) +{ + int col = offset_to_col(line, offset); + + cons_debug("LEN BYTES: %d", strlen(line)); + cons_debug("LEN UTF8 : %d", g_utf8_strlen(line, -1)); + cons_debug("OFFSET : %d", offset); + cons_debug("COL : %d", col); + cons_debug(""); + + werase(inp_win); + waddstr(inp_win, line); + wmove(inp_win, 0, col); + _inp_win_update_virtual(); +} + void inp_non_block(gint timeout) { @@ -174,8 +211,8 @@ inp_read(int *key_type, wint_t *ch) } int col = getcurx(inp_win); - int wcols = getmaxx(stdscr); - key_printable(line, &line_utf8_pos, &col, &pad_start, *ch, wcols); + int maxx = getmaxx(stdscr); + key_printable(line, &line_utf8_pos, &col, &pad_start, *ch, maxx); werase(inp_win); waddstr(inp_win, line); @@ -265,44 +302,9 @@ _handle_edit(int key_type, const wint_t ch) return 1; // CTRL-RIGHT - } else if (line_utf8_pos < utf8_len && _is_ctrl_right(key_type, ch)) { - gchar *curr_ch = g_utf8_offset_to_pointer(line, line_utf8_pos); - gunichar curr_uni = g_utf8_get_char(curr_ch); - - // find next word if in whitespace - while (g_unichar_isspace(curr_uni)) { - col++; - line_utf8_pos++; - curr_ch = g_utf8_find_next_char(curr_ch, NULL); - if (!curr_ch) { - break; - } - curr_uni = g_utf8_get_char(curr_ch); - } - - if (curr_ch) { - while (!g_unichar_isspace(curr_uni)) { - line_utf8_pos++; - col++; - if (g_unichar_iswide(curr_uni)) { - col++; - } - curr_ch = g_utf8_find_next_char(curr_ch, NULL); - if (!curr_ch || line_utf8_pos >= utf8_len) { - break; - } - curr_uni = g_utf8_get_char(curr_ch); - } - } - + } else if (_is_ctrl_right(key_type, ch)) { + key_ctrl_right(line, &line_utf8_pos, &col, &pad_start, wcols); wmove(inp_win, 0, col); - - // if gone off screen to right, jump right (half a screen worth) - if (col > pad_start + wcols) { - pad_start = pad_start + (wcols / 2); - _inp_win_update_virtual(); - } - return 1; // ALT-LEFT diff --git a/src/ui/inputwin.h b/src/ui/inputwin.h index a4de16f0..d27bfef7 100644 --- a/src/ui/inputwin.h +++ b/src/ui/inputwin.h @@ -48,5 +48,6 @@ void inp_non_block(gint); void inp_block(void); void inp_get_password(char *passwd); void inp_history_append(char *inp); +void inp_write(char *line, int offset); #endif diff --git a/src/ui/keyhandlers.c b/src/ui/keyhandlers.c index d7c3c616..0836737b 100644 --- a/src/ui/keyhandlers.c +++ b/src/ui/keyhandlers.c @@ -42,7 +42,7 @@ #include "common.h" void -key_printable(char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const wint_t ch, const int wcols) +key_printable(char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const wint_t ch, const int maxx) { int utf8_len = g_utf8_strlen(line, -1); @@ -65,7 +65,7 @@ key_printable(char * const line, int * const line_utf8_pos, int * const col, int free(new_line); gunichar uni = g_utf8_get_char(bytes); - if (*col == (*pad_start + wcols)) { + if (*col == (*pad_start + maxx)) { (*pad_start)++; if (g_unichar_iswide(uni)) { (*pad_start)++; @@ -101,7 +101,7 @@ key_printable(char * const line, int * const line_utf8_pos, int * const col, int (*col)++; } - if (*col - *pad_start > wcols-1) { + if (*col - *pad_start > maxx-1) { (*pad_start)++; if (g_unichar_iswide(uni)) { (*pad_start)++; @@ -112,7 +112,7 @@ key_printable(char * const line, int * const line_utf8_pos, int * const col, int } void -key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const int wcols) +key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const int maxx) { if (*line_utf8_pos == 0) { return; @@ -120,6 +120,7 @@ key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const co gchar *curr_ch = g_utf8_offset_to_pointer(line, *line_utf8_pos); gunichar curr_uni = g_utf8_get_char(curr_ch); + (*line_utf8_pos)--; (*col)--; if (g_unichar_iswide(curr_uni)) { @@ -145,7 +146,7 @@ key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const co prev_uni = g_utf8_get_char(prev_ch); (*line_utf8_pos)--; (*col)--; - if (g_unichar_iswide(prev_uni)) { + if (g_unichar_iswide(curr_uni)) { (*col)--; } if (g_unichar_isspace(prev_uni)) { @@ -169,3 +170,47 @@ key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const co *pad_start = *col; } } + +void +key_ctrl_right(const char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const int maxx) +{ + int utf8_len = g_utf8_strlen(line, -1); + if (*line_utf8_pos >= utf8_len) { + return; + } + + gchar *curr_ch = g_utf8_offset_to_pointer(line, *line_utf8_pos); + gunichar curr_uni = g_utf8_get_char(curr_ch); + + // find next word if in whitespace + while (g_unichar_isspace(curr_uni)) { + (*col)++; + (*line_utf8_pos)++; + curr_ch = g_utf8_find_next_char(curr_ch, NULL); + if (!curr_ch) { + break; + } + curr_uni = g_utf8_get_char(curr_ch); + } + + if (curr_ch) { + while (!g_unichar_isspace(curr_uni)) { + (*line_utf8_pos)++; + (*col)++; + if (g_unichar_iswide(curr_uni)) { + (*col)++; + } + curr_ch = g_utf8_find_next_char(curr_ch, NULL); + if (!curr_ch || *line_utf8_pos >= utf8_len) { + break; + } + curr_uni = g_utf8_get_char(curr_ch); + } + } + + // if gone off screen to right, jump right (half a screen worth) +// if (col > pad_start + wcols) { +// pad_start = pad_start + (wcols / 2); +// _inp_win_update_virtual(); +// } +} diff --git a/src/ui/keyhandlers.h b/src/ui/keyhandlers.h index d8153356..62a2c0d6 100644 --- a/src/ui/keyhandlers.h +++ b/src/ui/keyhandlers.h @@ -37,8 +37,9 @@ #include -void key_printable(char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const wint_t ch, const int wcols); +void key_printable(char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const wint_t ch, const int maxx); -void key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const int wcols); +void key_ctrl_left(const char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const int maxx); +void key_ctrl_right(const char * const line, int * const line_utf8_pos, int * const col, int * const pad_start, const int maxx); #endif diff --git a/src/ui/ui.h b/src/ui/ui.h index 99e73b4a..23315af9 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -230,6 +230,7 @@ void ui_statusbar_new(const int win); char * ui_readline(void); void ui_input_clear(void); void ui_input_nonblocking(gboolean); +void ui_write(char *line, int offset); void ui_invalid_command_usage(const char * const usage, void (*setting_func)(void)); diff --git a/tests/helpers.c b/tests/helpers.c index 10310886..564b2716 100644 --- a/tests/helpers.c +++ b/tests/helpers.c @@ -85,6 +85,24 @@ void close_chat_sessions(void **state) close_preferences(NULL); } +int +utf8_pos_to_col(char *str, int utf8_pos) +{ + int col = 0; + + int i = 0; + for (i = 0; i #include #include @@ -9,26 +7,15 @@ #include +#include "ui/keyhandlers.h" +#include "ui/inputwin.h" +#include "tests/helpers.h" + static char line[INP_WIN_MAX]; -static int utf8_pos_to_col(char *str, int utf8_pos) -{ - int col = 0; +// append - int i = 0; - for (i = 0; i