1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-11-03 19:37:16 -05:00

Handle wide chars on input

This commit is contained in:
James Booth 2013-01-03 00:16:39 +00:00
parent d28930eaf4
commit 439e6486db
4 changed files with 51 additions and 32 deletions

View File

@ -38,11 +38,12 @@
* pad_start : 3 * pad_start : 3
* cols : 4 * cols : 4
*/ */
#define _XOPEN_SOURCE_EXTENDED
#include "config.h" #include "config.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wchar.h>
#ifdef HAVE_NCURSES_H #ifdef HAVE_NCURSES_H
#include <ncurses.h> #include <ncurses.h>
@ -64,9 +65,9 @@
static WINDOW *inp_win; static WINDOW *inp_win;
static int pad_start = 0; static int pad_start = 0;
static int _handle_edit(const int ch, char *input, int *size); static int _handle_edit(const wint_t ch, char *input, int *size);
static int _printable(const int ch); static int _printable(const wint_t ch);
static gboolean _special_key(const int ch); static gboolean _special_key(const wint_t ch);
void void
create_input_window(void) create_input_window(void)
@ -128,59 +129,73 @@ inp_block(void)
wtimeout(inp_win, -1); wtimeout(inp_win, -1);
} }
void wint_t
inp_get_char(int *ch, char *input, int *size) inp_get_char(char *input, int *size)
{ {
int inp_y = 0; int inp_y = 0;
int inp_x = 0; int inp_x = 0;
int i; 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 // echo off, and get some more input
noecho(); noecho();
*ch = wgetch(inp_win); wget_wch(inp_win, &ch);
gboolean in_command = FALSE; gboolean in_command = FALSE;
if ((*size >= 1 && input[0] == '/') || if ((display_size > 0 && input[0] == '/') ||
(*size == 0 && *ch == '/')) { (display_size == 0 && ch == '/')) {
in_command = TRUE; in_command = TRUE;
} }
if (prefs_get_states()) { if (prefs_get_states()) {
if (*ch == ERR) { if (ch == ERR) {
prof_handle_idle(); prof_handle_idle();
} }
if (prefs_get_outtype() && (*ch != ERR) && !in_command if (prefs_get_outtype() && (ch != ERR) && !in_command
&& _printable(*ch)) { && _printable(ch)) {
prof_handle_activity(); prof_handle_activity();
} }
} }
// if it wasn't an arrow key etc // if it wasn't an arrow key etc
if (!_handle_edit(*ch, input, size)) { if (!_handle_edit(ch, input, size)) {
if (_printable(*ch)) { if (_printable(ch)) {
getyx(inp_win, inp_y, inp_x); getyx(inp_win, inp_y, inp_x);
// handle insert if not at end of input // handle insert if not at end of input
if (inp_x < *size) { if (inp_x < display_size) {
winsch(inp_win, *ch); winsch(inp_win, ch);
wmove(inp_win, inp_y, inp_x+1); wmove(inp_win, inp_y, inp_x+1);
for (i = *size; i > inp_x; i--) for (i = *size; i > inp_x; i--)
input[i] = input[i-1]; input[i] = input[i-1];
input[inp_x] = *ch; input[inp_x] = ch;
(*size)++; (*size)++;
// otherwise just append // otherwise just append
} else { } else {
waddch(inp_win, *ch); cchar_t t = { 0, { ch, 0 } };
input[(*size)++] = *ch; 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 // if gone over screen size follow input
int rows, cols; int rows, cols;
getmaxyx(stdscr, rows, cols); getmaxyx(stdscr, rows, cols);
if (*size - pad_start > cols-2) { if (display_size - pad_start > cols-2) {
pad_start++; pad_start++;
prefresh(inp_win, 0, pad_start, rows-1, 0, rows-1, cols-1); 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(); echo();
return ch;
} }
void void
@ -241,7 +258,7 @@ inp_replace_input(char *input, const char * const new_input, int *size)
* return 0 if it wasnt * return 0 if it wasnt
*/ */
static int 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; int i, rows, cols;
char *prev = NULL; char *prev = NULL;
@ -414,7 +431,7 @@ _handle_edit(const int ch, char *input, int *size)
} }
static int static int
_printable(const int ch) _printable(const wint_t ch)
{ {
return (ch != ERR && ch != '\n' && return (ch != ERR && ch != '\n' &&
ch != KEY_PPAGE && ch != KEY_NPAGE && ch != KEY_MOUSE && ch != KEY_PPAGE && ch != KEY_NPAGE && ch != KEY_MOUSE &&
@ -427,7 +444,7 @@ _printable(const int ch)
} }
static gboolean static gboolean
_special_key(const int ch) _special_key(const wint_t ch)
{ {
char *str = unctrl(ch); char *str = unctrl(ch);
return ((strlen(str) > 1) && g_str_has_prefix(str, "^")); return ((strlen(str) > 1) && g_str_has_prefix(str, "^"));

View File

@ -67,7 +67,7 @@ prof_run(const int disable_tls, char *log_level)
int size = 0; int size = 0;
while(cmd_result == TRUE) { while(cmd_result == TRUE) {
int ch = ERR; wint_t ch = ERR;
size = 0; size = 0;
while(ch != '\n') { while(ch != '\n') {
@ -95,7 +95,7 @@ prof_run(const int disable_tls, char *log_level)
ui_refresh(); ui_refresh();
jabber_process_events(); jabber_process_events();
inp_get_char(&ch, inp, &size); ch = inp_get_char(inp, &size);
if (ch != ERR) { if (ch != ERR) {
ui_reset_idle_time(); ui_reset_idle_time();

View File

@ -25,6 +25,8 @@
#include "config.h" #include "config.h"
#include <wchar.h>
#include <glib.h> #include <glib.h>
#ifdef HAVE_NCURSES_H #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, void ui_contact_offline(const char * const from, const char * const show,
const char * const status); const char * const status);
void ui_disconnected(void); 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); void ui_switch_win(const int i);
gboolean ui_windows_full(void); gboolean ui_windows_full(void);
unsigned long ui_get_idle_time(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); void status_bar_update_time(void);
// input window actions // 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_clear(void);
void inp_win_resize(const char * input, const int size); void inp_win_resize(const char * input, const int size);
void inp_put_back(void); void inp_put_back(void);

View File

@ -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_typing(const char * const short_from);
static void _cons_show_incoming_message(const char * const short_from, static void _cons_show_incoming_message(const char * const short_from,
const int win_index); const int win_index);
static void _win_handle_switch(const int * const ch); static void _win_handle_switch(const wint_t * const ch);
static void _win_handle_page(const int * const ch); static void _win_handle_page(const wint_t * const ch);
static void _win_resize_all(void); static void _win_resize_all(void);
static gint _win_get_unread(void); static gint _win_get_unread(void);
static void _win_show_history(WINDOW *win, int win_index, static void _win_show_history(WINDOW *win, int win_index,
@ -506,7 +506,7 @@ ui_disconnected(void)
} }
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_switch(ch);
_win_handle_page(ch); _win_handle_page(ch);
@ -2123,7 +2123,7 @@ _cons_show_contact(PContact contact)
} }
static void static void
_win_handle_switch(const int * const ch) _win_handle_switch(const wint_t * const ch)
{ {
if (*ch == KEY_F(1)) { if (*ch == KEY_F(1)) {
ui_switch_win(0); ui_switch_win(0);
@ -2149,7 +2149,7 @@ _win_handle_switch(const int * const ch)
} }
static void static void
_win_handle_page(const int * const ch) _win_handle_page(const wint_t * const ch)
{ {
int rows = getmaxy(stdscr); int rows = getmaxy(stdscr);
int y = getcury(current->win); int y = getcury(current->win);