about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2013-01-03 00:16:39 +0000
committerJames Booth <boothj5@gmail.com>2013-01-03 00:16:39 +0000
commit439e6486db24fb18f0cb2ac22e16a6327e1d8ad4 (patch)
treef72eb92acbe5688a0d11c2281d5f004210395b05
parentd28930eaf475bdf187585d900e079b6ce9f32deb (diff)
downloadprofani-tty-439e6486db24fb18f0cb2ac22e16a6327e1d8ad4.tar.gz
Handle wide chars on input
-rw-r--r--src/input_win.c63
-rw-r--r--src/profanity.c4
-rw-r--r--src/ui.h6
-rw-r--r--src/windows.c10
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 <stdlib.h>
 #include <string.h>
+#include <wchar.h>
 
 #ifdef HAVE_NCURSES_H
 #include <ncurses.h>
@@ -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 <wchar.h>
+
 #include <glib.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,
     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);