From 2ed78fe5afaa0197de65a0edbf2423b5d7fe9792 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 20 Jan 2015 00:09:47 +0000 Subject: Extracted keyhandler for printable characters --- src/ui/core.c | 2 +- src/ui/inputwin.c | 129 ++++++++++++++++----------------------------------- src/ui/inputwin.h | 6 ++- src/ui/keyhandlers.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ui/keyhandlers.h | 42 +++++++++++++++++ 5 files changed, 211 insertions(+), 91 deletions(-) create mode 100644 src/ui/keyhandlers.c create mode 100644 src/ui/keyhandlers.h (limited to 'src/ui') diff --git a/src/ui/core.c b/src/ui/core.c index 14ea2c17..e295a3ad 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -212,7 +212,7 @@ ui_inp_history_append(char *inp) void ui_input_clear(void) { - inp_win_reset(); + inp_win_clear(); } void diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index dba2f9d5..59292482 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -60,8 +60,7 @@ #include "ui/inputwin.h" #include "ui/windows.h" #include "xmpp/xmpp.h" - -#define _inp_win_update_virtual() pnoutrefresh(inp_win, 0, pad_start, wrows-1, 0, wrows-1, wcols-1) +#include "ui/keyhandlers.h" #define KEY_CTRL_A 0001 #define KEY_CTRL_B 0002 @@ -74,7 +73,6 @@ #define KEY_CTRL_W 0027 #define MAX_HISTORY 100 -#define INP_WIN_MAX 1000 static WINDOW *inp_win; static History history; @@ -85,7 +83,6 @@ static char line[INP_WIN_MAX]; static int line_utf8_pos; static int pad_start = 0; -static int wrows, wcols; static int _handle_edit(int key_type, const wint_t ch); static int _handle_alt_key(int key); @@ -96,6 +93,8 @@ static void _handle_backspace(void); static gboolean _is_ctrl_left(int key_type, const wint_t ch); static gboolean _is_ctrl_right(int key_type, const wint_t ch); +static void _inp_win_update_virtual(void); + void create_input_window(void) { @@ -104,7 +103,6 @@ create_input_window(void) #else ESCDELAY = 25; #endif - getmaxyx(stdscr, wrows, wcols); inp_win = newpad(1, INP_WIN_MAX); wbkgd(inp_win, theme_attrs(THEME_INPUT_TEXT));; keypad(inp_win, TRUE); @@ -118,9 +116,8 @@ create_input_window(void) void inp_win_resize(void) { - int col; - getmaxyx(stdscr, wrows, wcols); - col = getcurx(inp_win); + int col = getcurx(inp_win); + int wcols = getmaxx(stdscr); // if lost cursor off screen, move contents to show it if (col >= pad_start + wcols) { @@ -177,85 +174,13 @@ inp_read(int *key_type, wint_t *ch) } int col = getcurx(inp_win); - int utf8_len = g_utf8_strlen(line, -1); - - // handle insert if not at end of input - if (line_utf8_pos < utf8_len) { - char bytes[MB_CUR_MAX]; - size_t utf8_ch_len = wcrtomb(bytes, *ch, NULL); - bytes[utf8_ch_len] = '\0'; - - gchar *start = g_utf8_substring(line, 0, line_utf8_pos); - gchar *end = g_utf8_substring(line, line_utf8_pos, utf8_len); - GString *new_line = g_string_new(start); - g_string_append(new_line, bytes); - g_string_append(new_line, end); - - int old_pos = line_utf8_pos; - werase(inp_win); - wmove(inp_win, 0, 0); - pad_start = 0; - line[0] = '\0'; - line_utf8_pos = 0; - strncpy(line, new_line->str, INP_WIN_MAX); - waddstr(inp_win, line); - - int display_len = utf8_display_len(line); - wmove(inp_win, 0, display_len); - line_utf8_pos = g_utf8_strlen(line, -1); - - if (display_len > wcols-2) { - pad_start = display_len - wcols + 1; - _inp_win_update_virtual(); - } - - line_utf8_pos = old_pos+1; - - g_free(start); - g_free(end); - g_string_free(new_line, TRUE); - - col++; - gunichar uni = g_utf8_get_char(bytes); - if (g_unichar_iswide(uni)) { - col++; - } - wmove(inp_win, 0, col); - - // otherwise just append - } else { - char bytes[MB_CUR_MAX+1]; - size_t utf8_ch_len = wcrtomb(bytes, *ch, NULL); - - // wcrtomb can return (size_t) -1 - if (utf8_ch_len < MB_CUR_MAX) { - int i; - for (i = 0 ; i < utf8_ch_len; i++) { - line[bytes_len++] = bytes[i]; - } - line[bytes_len] = '\0'; - - bytes[utf8_ch_len] = '\0'; - waddstr(inp_win, bytes); - - line_utf8_pos++; + int wcols = getmaxx(stdscr); + key_printable(line, &line_utf8_pos, &col, &pad_start, *ch, wcols); - col++; - gunichar uni = g_utf8_get_char(bytes); - if (g_unichar_iswide(uni)) { - col++; - } - wmove(inp_win, 0, col); - - // if gone over screen size follow input - int wrows, wcols; - getmaxyx(stdscr, wrows, wcols); - if (col - pad_start > wcols-2) { - pad_start++; - _inp_win_update_virtual(); - } - } - } + werase(inp_win); + waddstr(inp_win, line); + wmove(inp_win, 0, col); + _inp_win_update_virtual(); cmd_reset_autocomplete(); } @@ -271,7 +196,7 @@ inp_read(int *key_type, wint_t *ch) } if (*ch != ERR && *key_type != ERR) { - cons_debug("BYTE LEN = %d", bytes_len); + cons_debug("BYTE LEN = %d", strlen(line)); cons_debug("UTF8 LEN = %d", utf8_display_len(line)); cons_debug("CURR COL = %d", getcurx(inp_win)); cons_debug("CURR UNI = %d", line_utf8_pos); @@ -305,7 +230,7 @@ inp_put_back(void) } void -inp_win_reset(void) +inp_win_clear(void) { werase(inp_win); wmove(inp_win, 0, 0); @@ -383,6 +308,7 @@ _handle_edit(int key_type, const wint_t ch) } // if gone off screen to left, jump left (half a screen worth) + int wcols = getmaxx(stdscr); if (col <= pad_start) { pad_start = pad_start - (wcols / 2); if (pad_start < 0) { @@ -427,6 +353,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, col); // if gone off screen to right, jump right (half a screen worth) + int wcols = getmaxx(stdscr); if (col > pad_start + wcols) { pad_start = pad_start + (wcols / 2); _inp_win_update_virtual(); @@ -458,7 +385,12 @@ _handle_edit(int key_type, const wint_t ch) if (next_ch != ERR) { return _handle_alt_key(next_ch); } else { - inp_win_reset(); + werase(inp_win); + wmove(inp_win, 0, 0); + pad_start = 0; + line[0] = '\0'; + line_utf8_pos = 0; + _inp_win_update_virtual(); return 1; } @@ -557,6 +489,7 @@ _handle_edit(int key_type, const wint_t ch) line_utf8_pos++; // current position off screen to right + int wcols = getmaxx(stdscr); if ((col + 1 - pad_start) >= wcols) { pad_start++; _inp_win_update_virtual(); @@ -584,6 +517,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -611,6 +545,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -630,6 +565,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -657,6 +593,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -681,6 +618,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -703,6 +641,7 @@ _handle_edit(int key_type, const wint_t ch) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -755,6 +694,7 @@ _handle_backspace(void) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -783,6 +723,7 @@ _handle_backspace(void) wmove(inp_win, 0, display_len); line_utf8_pos = g_utf8_strlen(line, -1); + int wcols = getmaxx(stdscr); if (display_len > wcols-2) { pad_start = display_len - wcols + 1; _inp_win_update_virtual(); @@ -804,6 +745,7 @@ _handle_backspace(void) // if gone off screen to left, jump left (half a screen worth) if (col <= pad_start) { + int wcols = getmaxx(stdscr); pad_start = pad_start - (wcols / 2); if (pad_start < 0) { pad_start = 0; @@ -931,6 +873,7 @@ _handle_delete_previous_word(void) // if gone off screen to left, jump left (half a screen worth) if (start_del <= pad_start) { + int wcols = getmaxx(stdscr); pad_start = pad_start - (wcols / 2); if (pad_start < 0) { pad_start = 0; @@ -952,4 +895,12 @@ _is_ctrl_right(int key_type, const wint_t ch) { return ((key_type == KEY_CODE_YES) && (ch == 562 || ch == 560 || ch == 555 || ch == 559 || ch == 554)); +} + +static void +_inp_win_update_virtual(void) +{ + int wrows, wcols; + getmaxyx(stdscr, wrows, wcols); + pnoutrefresh(inp_win, 0, pad_start, wrows-1, 0, wrows-1, wcols-1); } \ No newline at end of file diff --git a/src/ui/inputwin.h b/src/ui/inputwin.h index ecca4d5b..a4de16f0 100644 --- a/src/ui/inputwin.h +++ b/src/ui/inputwin.h @@ -35,9 +35,13 @@ #ifndef UI_INPUTWIN_H #define UI_INPUTWIN_H +#include + +#define INP_WIN_MAX 1000 + void create_input_window(void); char* inp_read(int *key_type, wint_t *ch); -void inp_win_reset(void); +void inp_win_clear(void); void inp_win_resize(void); void inp_put_back(void); void inp_non_block(gint); diff --git a/src/ui/keyhandlers.c b/src/ui/keyhandlers.c new file mode 100644 index 00000000..513997ef --- /dev/null +++ b/src/ui/keyhandlers.c @@ -0,0 +1,123 @@ +/* + * keyhandlers.c + * + * Copyright (C) 2012 - 2014 James Booth + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see . + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#include +#include +#include + +#include + +#include "ui/inputwin.h" +#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) +{ + int utf8_len = g_utf8_strlen(line, -1); + + // handle insert if not at end of input + if (*line_utf8_pos < utf8_len) { + // create new line + char bytes[MB_CUR_MAX]; + size_t utf8_ch_len = wcrtomb(bytes, ch, NULL); + bytes[utf8_ch_len] = '\0'; + gchar *start = g_utf8_substring(line, 0, *line_utf8_pos); + gchar *end = g_utf8_substring(line, *line_utf8_pos, utf8_len); + GString *new_line_str = g_string_new(start); + g_string_append(new_line_str, bytes); + g_string_append(new_line_str, end); + char *new_line = new_line_str->str; + g_free(start); + g_free(end); + g_string_free(new_line_str, FALSE); + + // replace old line + strncpy(line, new_line, INP_WIN_MAX); + free(new_line); + + // set utf8 position + (*line_utf8_pos)++; + + // set col position + (*col)++; + gunichar uni = g_utf8_get_char(bytes); + if (g_unichar_iswide(uni)) { + (*col)++; + } + + // set pad_start + int display_len = utf8_display_len(line); + (*pad_start) = 0; + if (display_len > wcols-2) { + (*pad_start) = display_len - wcols + 1; + } + + // otherwise just append + } else { + char bytes[MB_CUR_MAX+1]; + size_t utf8_ch_len = wcrtomb(bytes, ch, NULL); + + // wcrtomb can return (size_t) -1 + if (utf8_ch_len < MB_CUR_MAX) { + // update old line + int i; + int bytes_len = strlen(line); + + for (i = 0 ; i < utf8_ch_len; i++) { + line[bytes_len++] = bytes[i]; + } + line[bytes_len] = '\0'; + + // set utf8 position + (*line_utf8_pos)++; + + // set col position + (*col)++; + bytes[utf8_ch_len] = '\0'; + gunichar uni = g_utf8_get_char(bytes); + if (g_unichar_iswide(uni)) { + (*col)++; + } + + // set pad_start + // if gone over screen size follow input + if (*col - *pad_start > wcols-2) { + (*pad_start)++; + if (g_unichar_iswide(uni)) { + (*pad_start)++; + } + } + } + } +} \ No newline at end of file diff --git a/src/ui/keyhandlers.h b/src/ui/keyhandlers.h new file mode 100644 index 00000000..cb1b14d8 --- /dev/null +++ b/src/ui/keyhandlers.h @@ -0,0 +1,42 @@ +/* + * keyhandlers.c + * + * Copyright (C) 2012 - 2014 James Booth + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see . + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#ifndef UI_KEYHANDLERS_H +#define UI_KEYHANDLERS_H + +#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); + +#endif -- cgit 1.4.1-2-gfad0