diff options
Diffstat (limited to 'src/ui/inputwin.c')
-rw-r--r-- | src/ui/inputwin.c | 220 |
1 files changed, 122 insertions, 98 deletions
diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index a6877a86..85ddc79a 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -50,6 +50,7 @@ #include "config/accounts.h" #include "config/preferences.h" #include "config/theme.h" +#include "tools/history.h" #include "log.h" #include "muc.h" #include "profanity.h" @@ -72,17 +73,25 @@ #define KEY_CTRL_U 0025 #define KEY_CTRL_W 0027 +#define MAX_HISTORY 100 +#define INP_WIN_MAX 1000 + static WINDOW *inp_win; +static History history; + +static char input[INP_WIN_MAX]; +static int input_len_bytes; + static int pad_start = 0; static int rows, cols; -static int _handle_edit(int result, const wint_t ch, char *input, int *size); -static int _handle_alt_key(char *input, int *size, int key); -static void _handle_backspace(int display_size, int inp_x, int *size, char *input); +static int _handle_edit(int key_type, const wint_t ch); +static int _handle_alt_key(int key); +static void _handle_backspace(void); static int _printable(const wint_t ch); static void _clear_input(void); -static void _go_to_end(int display_size); -static void _delete_previous_word(char *input, int *size); +static void _go_to_end(void); +static void _delete_previous_word(void); void create_input_window(void) @@ -98,6 +107,7 @@ create_input_window(void) keypad(inp_win, TRUE); wmove(inp_win, 0, 0); _inp_win_update_virtual(); + history = history_new(MAX_HISTORY); } void @@ -131,38 +141,34 @@ inp_block(void) wtimeout(inp_win, -1); } -wint_t -inp_get_char(char *input, int *size, int *result) +char * +inp_read(int *key_type, wint_t *ch) { - wint_t ch; - int display_size = 0; - - if (*size != 0) { - display_size = g_utf8_strlen(input, *size); - } + int display_size = utf8_display_len(input); // echo off, and get some more input noecho(); - *result = wget_wch(inp_win, &ch); + *key_type = wget_wch(inp_win, ch); gboolean in_command = FALSE; if ((display_size > 0 && input[0] == '/') || - (display_size == 0 && ch == '/')) { + (display_size == 0 && *ch == '/')) { in_command = TRUE; } - if (*result == ERR) { + if (*key_type == ERR) { prof_handle_idle(); } - if ((*result != ERR) && (*result != KEY_CODE_YES) && !in_command && _printable(ch)) { + if ((*key_type != ERR) && (*key_type != KEY_CODE_YES) && !in_command && _printable(*ch)) { prof_handle_activity(); } // if it wasn't an arrow key etc - if (!_handle_edit(*result, ch, input, size)) { - if (_printable(ch) && *result != KEY_CODE_YES) { - if (*size >= INP_WIN_MAX) { - return ERR; + if (!_handle_edit(*key_type, *ch)) { + if (_printable(*ch) && *key_type != KEY_CODE_YES) { + if (input_len_bytes >= INP_WIN_MAX) { + *ch = ERR; + return NULL; } int inp_x = getcurx(inp_win); @@ -170,11 +176,11 @@ inp_get_char(char *input, int *size, int *result) // handle insert if not at end of input if (inp_x < display_size) { char bytes[MB_CUR_MAX]; - size_t utf_len = wcrtomb(bytes, ch, NULL); + size_t utf_len = wcrtomb(bytes, *ch, NULL); char *next_ch = g_utf8_offset_to_pointer(input, inp_x); char *offset; - for (offset = &input[*size - 1]; offset >= next_ch; offset--) { + for (offset = &input[input_len_bytes - 1]; offset >= next_ch; offset--) { *(offset + utf_len) = *offset; } int i; @@ -182,8 +188,8 @@ inp_get_char(char *input, int *size, int *result) *(next_ch + i) = bytes[i]; } - *size += utf_len; - input[*size] = '\0'; + input_len_bytes += utf_len; + input[input_len_bytes] = '\0'; waddstr(inp_win, next_ch); wmove(inp_win, 0, inp_x + 1); @@ -195,15 +201,15 @@ inp_get_char(char *input, int *size, int *result) // otherwise just append } else { char bytes[MB_CUR_MAX+1]; - size_t utf_len = wcrtomb(bytes, ch, NULL); + size_t utf_len = wcrtomb(bytes, *ch, NULL); // wcrtomb can return (size_t) -1 if (utf_len < MB_CUR_MAX) { int i; for (i = 0 ; i < utf_len; i++) { - input[(*size)++] = bytes[i]; + input[input_len_bytes++] = bytes[i]; } - input[*size] = '\0'; + input[input_len_bytes] = '\0'; bytes[utf_len] = '\0'; waddstr(inp_win, bytes); @@ -225,7 +231,13 @@ inp_get_char(char *input, int *size, int *result) echo(); - return ch; + if (*ch == '\n') { + input[input_len_bytes] = '\0'; + input_len_bytes = 0; + return strdup(input); + } else { + return NULL; + } } void @@ -248,16 +260,14 @@ inp_put_back(void) } void -inp_replace_input(char *input, const char * const new_input, int *size) +inp_replace_input(const char * const new_input) { - int display_size; strncpy(input, new_input, INP_WIN_MAX); - *size = strlen(input); - display_size = g_utf8_strlen(input, *size); + input_len_bytes = strlen(input); inp_win_reset(); - input[*size] = '\0'; + input[input_len_bytes] = '\0'; waddstr(inp_win, input); - _go_to_end(display_size); + _go_to_end(); } void @@ -268,6 +278,12 @@ inp_win_reset(void) _inp_win_update_virtual(); } +void +inp_history_append(char *inp) +{ + history_append(history, inp); +} + static void _clear_input(void) { @@ -281,23 +297,17 @@ _clear_input(void) * return 0 if it wasn't */ static int -_handle_edit(int result, const wint_t ch, char *input, int *size) +_handle_edit(int key_type, const wint_t ch) { char *prev = NULL; char *next = NULL; - int inp_x = 0; + int inp_x = getcurx(inp_win); int next_ch; - int display_size = 0; - - if (*size != 0) { - display_size = g_utf8_strlen(input, *size); - } - - inp_x = getcurx(inp_win); + int display_size = utf8_display_len(input); // CTRL-LEFT - if ((result == KEY_CODE_YES) && (ch == 547 || ch == 545 || ch == 544 || ch == 540 || ch == 539) && (inp_x > 0)) { - input[*size] = '\0'; + if ((key_type == KEY_CODE_YES) && (ch == 547 || ch == 545 || ch == 544 || ch == 540 || ch == 539) && (inp_x > 0)) { + input[input_len_bytes] = '\0'; gchar *curr_ch = g_utf8_offset_to_pointer(input, inp_x); curr_ch = g_utf8_find_prev_char(input, curr_ch); gchar *prev_ch; @@ -346,8 +356,8 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) return 1; // CTRL-RIGHT - } else if ((result == KEY_CODE_YES) && (ch == 562 || ch == 560 || ch == 555 || ch == 559 || ch == 554) && (inp_x < display_size)) { - input[*size] = '\0'; + } else if ((key_type == KEY_CODE_YES) && (ch == 562 || ch == 560 || ch == 555 || ch == 559 || ch == 554) && (inp_x < display_size)) { + input[input_len_bytes] = '\0'; gchar *curr_ch = g_utf8_offset_to_pointer(input, inp_x); gchar *next_ch = g_utf8_find_next_char(curr_ch, NULL); gunichar curr_uni; @@ -389,12 +399,12 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) return 1; // ALT-LEFT - } else if ((result == KEY_CODE_YES) && (ch == 537 || ch == 542)) { + } else if ((key_type == KEY_CODE_YES) && (ch == 537 || ch == 542)) { ui_previous_win(); return 1; // ALT-RIGHT - } else if ((result == KEY_CODE_YES) && (ch == 552 || ch == 557)) { + } else if ((key_type == KEY_CODE_YES) && (ch == 552 || ch == 557)) { ui_next_win(); return 1; @@ -406,34 +416,34 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) // check for ALT-key next_ch = wgetch(inp_win); if (next_ch != ERR) { - return _handle_alt_key(input, size, next_ch); + return _handle_alt_key(next_ch); } else { - *size = 0; + input_len_bytes = 0; inp_win_reset(); return 1; } case 127: - _handle_backspace(display_size, inp_x, size, input); + _handle_backspace(); return 1; case KEY_BACKSPACE: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } - _handle_backspace(display_size, inp_x, size, input); + _handle_backspace(); return 1; case KEY_DC: // DEL - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_D: if (inp_x == display_size-1) { gchar *start = g_utf8_substring(input, 0, inp_x); - for (*size = 0; *size < strlen(start); (*size)++) { - input[*size] = start[*size]; + for (input_len_bytes = 0; input_len_bytes < strlen(start); input_len_bytes++) { + input[input_len_bytes] = start[input_len_bytes]; } - input[*size] = '\0'; + input[input_len_bytes] = '\0'; g_free(start); @@ -441,14 +451,14 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) waddstr(inp_win, input); } else if (inp_x < display_size-1) { gchar *start = g_utf8_substring(input, 0, inp_x); - gchar *end = g_utf8_substring(input, inp_x+1, *size); + gchar *end = g_utf8_substring(input, inp_x+1, input_len_bytes); GString *new = g_string_new(start); g_string_append(new, end); - for (*size = 0; *size < strlen(new->str); (*size)++) { - input[*size] = new->str[*size]; + for (input_len_bytes = 0; input_len_bytes < strlen(new->str); input_len_bytes++) { + input[input_len_bytes] = new->str[input_len_bytes]; } - input[*size] = '\0'; + input[input_len_bytes] = '\0'; g_free(start); g_free(end); @@ -461,7 +471,7 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) return 1; case KEY_LEFT: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_B: @@ -477,7 +487,7 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) return 1; case KEY_RIGHT: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_F: @@ -493,33 +503,35 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) return 1; case KEY_UP: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_P: - prev = cmd_history_previous(input, size); + input[input_len_bytes] = '\0'; + prev = history_previous(history, input); if (prev) { - inp_replace_input(input, prev, size); + inp_replace_input(prev); } return 1; case KEY_DOWN: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_N: - next = cmd_history_next(input, size); + input[input_len_bytes] = '\0'; + next = history_next(history, input); if (next) { - inp_replace_input(input, next, size); - } else if (*size != 0) { - input[*size] = '\0'; - cmd_history_append(input); - inp_replace_input(input, "", size); + inp_replace_input(next); + } else if (input_len_bytes != 0) { + input[input_len_bytes] = '\0'; + history_append(history, input); + inp_replace_input(""); } return 1; case KEY_HOME: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_A: @@ -529,31 +541,40 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) return 1; case KEY_END: - if (result != KEY_CODE_YES) { + if (key_type != KEY_CODE_YES) { return 0; } case KEY_CTRL_E: - _go_to_end(display_size); + _go_to_end(); return 1; case 9: // tab - if (*size != 0) { + if (input_len_bytes != 0) { + input[input_len_bytes] = '\0'; if ((strncmp(input, "/", 1) != 0) && (ui_current_win_type() == WIN_MUC)) { - muc_autocomplete(input, size); + char *result = muc_autocomplete(input); + if (result) { + inp_replace_input(result); + free(result); + } } else if (strncmp(input, "/", 1) == 0) { - cmd_autocomplete(input, size); + char *result = cmd_autocomplete(input); + if (result) { + inp_replace_input(result); + free(result); + } } } return 1; case KEY_CTRL_W: - _delete_previous_word(input, size); + _delete_previous_word(); return 1; break; case KEY_CTRL_U: while (getcurx(inp_win) > 0) { - _delete_previous_word(input, size); + _delete_previous_word(); } return 1; break; @@ -565,18 +586,20 @@ _handle_edit(int result, const wint_t ch, char *input, int *size) } static void -_handle_backspace(int display_size, int inp_x, int *size, char *input) +_handle_backspace(void) { + int inp_x = getcurx(inp_win); + int display_size = utf8_display_len(input); roster_reset_search_attempts(); if (display_size > 0) { // if at end, delete last char if (inp_x >= display_size) { gchar *start = g_utf8_substring(input, 0, inp_x-1); - for (*size = 0; *size < strlen(start); (*size)++) { - input[*size] = start[*size]; + for (input_len_bytes = 0; input_len_bytes < strlen(start); input_len_bytes++) { + input[input_len_bytes] = start[input_len_bytes]; } - input[*size] = '\0'; + input[input_len_bytes] = '\0'; g_free(start); @@ -587,14 +610,14 @@ _handle_backspace(int display_size, int inp_x, int *size, char *input) // if in middle, delete and shift chars left } else if (inp_x > 0 && inp_x < display_size) { gchar *start = g_utf8_substring(input, 0, inp_x - 1); - gchar *end = g_utf8_substring(input, inp_x, *size); + gchar *end = g_utf8_substring(input, inp_x, input_len_bytes); GString *new = g_string_new(start); g_string_append(new, end); - for (*size = 0; *size < strlen(new->str); (*size)++) { - input[*size] = new->str[*size]; + for (input_len_bytes = 0; input_len_bytes < strlen(new->str); input_len_bytes++) { + input[input_len_bytes] = new->str[input_len_bytes]; } - input[*size] = '\0'; + input[input_len_bytes] = '\0'; g_free(start); g_free(end); @@ -619,7 +642,7 @@ _handle_backspace(int display_size, int inp_x, int *size, char *input) } static int -_handle_alt_key(char *input, int *size, int key) +_handle_alt_key(int key) { switch (key) { @@ -661,7 +684,7 @@ _handle_alt_key(char *input, int *size, int key) break; case 263: case 127: - _delete_previous_word(input, size); + _delete_previous_word(); break; default: break; @@ -670,12 +693,12 @@ _handle_alt_key(char *input, int *size, int key) } static void -_delete_previous_word(char *input, int *size) +_delete_previous_word(void) { int end_del = getcurx(inp_win); int start_del = end_del; - input[*size] = '\0'; + input[input_len_bytes] = '\0'; gchar *curr_ch = g_utf8_offset_to_pointer(input, end_del); curr_ch = g_utf8_find_prev_char(input, curr_ch); gchar *prev_ch; @@ -721,8 +744,8 @@ _delete_previous_word(char *input, int *size) input[strlen(start_string)+i] = end_string[i]; } - *size = strlen(start_string)+i; - input[*size] = '\0'; + input_len_bytes = strlen(start_string)+i; + input[input_len_bytes] = '\0'; _clear_input(); waddstr(inp_win, input); @@ -740,8 +763,9 @@ _delete_previous_word(char *input, int *size) } static void -_go_to_end(int display_size) +_go_to_end(void) { + int display_size = utf8_display_len(input); wmove(inp_win, 0, display_size); if (display_size > cols-2) { pad_start = display_size - cols + 1; |