Hi,
I'd like to file a patch against the existing bug related to Chinese
inputing. The multibyte 8bit Chinese characters was lost on the input
line. That is, When you type them, the cursor on the input line
doesn't move and nothing is echoed there, but they will be send to server correctly
after you
press enter.
I've tried the irssi-snapshot (debian sid package, cvs 200307
version) and qvr's unstable packages(cvs 20031001). They all have
that problem.
So I made some search and found that there are already a patch for
this in the FreeBSD ports[1]. After applying it, the problem is
solved and it has been tested working.
So would you please accepted this patch and commit it into the CVS?
The patch is in the attachment.
Thanks in advance.
Best regards
Wang WenRui
[1] http://www.freshports.org/chinese/irssi/
--- irssi-snapshot-0.8.6+cvs.20030712.orig/src/fe-text/gui-entry.c
+++ irssi-snapshot-0.8.6+cvs.20030712/src/fe-text/gui-entry.c
@@ -68,6 +68,27 @@
g_free(entry);
}
+/* Fixes the cursor position if it at big5_lo .
+ Direct: -1 , left shift 1 byte.
+ Direct: 0, +1 , right shift 1 byte.
+*/
+static int _fix_big5_pos(unichar *p, int pos, int direct)
+{
+ int newpos;
+
+ for (newpos=0; newpos<pos && p[newpos] != 0; ) {
+ if (is_big5(p[newpos], p[newpos+1]))
+ newpos += 2;
+ else
+ newpos ++;
+ }
+
+ if (newpos != pos)
+ pos += direct > 0 ? 1 : -1;
+
+ return pos;
+}
+
/* Fixes the cursor position in screen */
static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry)
{
@@ -85,6 +106,8 @@
entry->scrstart = entry->pos - entry->scrpos;
}
+ entry->scrstart = _fix_big5_pos(entry->text, entry->scrstart, -1);
+
if (old_scrstart != entry->scrstart)
entry->redraw_needed_from = 0;
}
@@ -200,7 +223,7 @@
}
}
-void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str)
+void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const unsigned char *str)
{
int oldlen;
@@ -236,7 +259,7 @@
entry->utf8 = utf8;
}
-void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str)
+void gui_entry_set_text(GUI_ENTRY_REC *entry, const unsigned char *str)
{
g_return_if_fail(entry != NULL);
g_return_if_fail(str != NULL);
@@ -265,7 +288,7 @@
return buf;
}
-void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str)
+void gui_entry_insert_text(GUI_ENTRY_REC *entry, const unsigned char *str)
{
unichar chr;
int i, len;
@@ -341,13 +364,30 @@
return buf;
}
+void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer)
+{
+ int newpos, size = 0;
+
+ g_return_if_fail(entry != NULL);
+ for(newpos = gui_entry_get_pos(entry); newpos > pos; size ++)
+ newpos = _fix_big5_pos(entry->text, newpos - 1, -1);
+ gui_entry_erase(entry, size, update_cutbuffer);
+}
+
void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer)
{
+ int newpos;
+
g_return_if_fail(entry != NULL);
if (entry->pos < size)
return;
+ /* recount the erase size with big5 charsets */
+ for (newpos = entry->pos; newpos > 0 && size > 0; size--)
+ newpos = _fix_big5_pos(entry->text, newpos-1, -1);
+ size = entry->pos - newpos;
+
if (update_cutbuffer) {
/* put erased text to cutbuffer */
if (entry->cutbuffer == NULL || entry->cutbuffer_len < size) {
@@ -471,10 +511,24 @@
void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos)
{
+ int newpos;
+
g_return_if_fail(entry != NULL);
- if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text_len)
- entry->pos += pos;
+ /* move cursor with big5 charset */
+ newpos = _fix_big5_pos(entry->text, entry->pos, -1);
+ if (pos > 0) {
+ while (pos > 0 && newpos < entry->text_len) {
+ newpos = _fix_big5_pos(entry->text, newpos+1, 1);
+ pos --;
+ }
+ } else {
+ while (pos < 0 && newpos > 0) {
+ newpos = _fix_big5_pos(entry->text, newpos-1, -1);
+ pos ++;
+ }
+ }
+ entry->pos = newpos;
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
--- irssi-snapshot-0.8.6+cvs.20030712.orig/src/fe-text/gui-entry.h
+++ irssi-snapshot-0.8.6+cvs.20030712/src/fe-text/gui-entry.h
@@ -28,17 +28,18 @@
void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width);
void gui_entry_set_active(GUI_ENTRY_REC *entry);
-void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str);
+void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const unsigned char *str);
void gui_entry_set_hidden(GUI_ENTRY_REC *entry, int hidden);
void gui_entry_set_utf8(GUI_ENTRY_REC *entry, int utf8);
-void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str);
+void gui_entry_set_text(GUI_ENTRY_REC *entry, const unsigned char *str);
char *gui_entry_get_text(GUI_ENTRY_REC *entry);
-void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str);
+void gui_entry_insert_text(GUI_ENTRY_REC *entry, const unsigned char *str);
void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr);
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry);
+void gui_entry_erase_to(GUI_ENTRY_REC *entry, int pos, int update_cutbuffer);
void gui_entry_erase(GUI_ENTRY_REC *entry, int size, int update_cutbuffer);
void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space);
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space);
--- irssi-snapshot-0.8.6+cvs.20030712.orig/src/fe-text/gui-readline.c
+++ irssi-snapshot-0.8.6+cvs.20030712/src/fe-text/gui-readline.c
@@ -50,6 +50,10 @@
static ENTRY_REDIRECT_REC *redir;
static int escape_next_key;
+static int big5high = FALSE;
+static unichar prekey = '\0';
+
+
static int readtag;
static time_t idle_time;
@@ -148,7 +152,25 @@
idle_time = time(NULL);
- if (key < 32) {
+ if(big5high || is_big5_hi(key))
+ {
+ if(big5high)
+ {
+ big5high = FALSE;
+ str[0] = prekey;
+ str[1] = key;
+ str[2] = '\0';
+ gui_entry_insert_text(active_entry, str);
+ return;
+ }
+ else
+ {
+ big5high = TRUE;
+ prekey = key;
+ return;
+ }
+ }
+ else if (key < 32) {
/* control key */
str[0] = '^';
str[1] = (char)key+'@';
--- irssi-snapshot-0.8.6+cvs.20030712.orig/src/fe-text/term-terminfo.c
+++ irssi-snapshot-0.8.6+cvs.20030712/src/fe-text/term-terminfo.c
@@ -564,12 +564,6 @@
}
}
-/* XXX I didn't check the encoding range of big5+. This is standard big5. */
-#define is_big5_los(lo) (0x40 <= (lo) && (lo) <= 0x7E) /* standard */
-#define is_big5_lox(lo) (0x80 <= (lo) && (lo) <= 0xFE) /* extended */
-#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE)
-#define is_big5(hi,lo) (is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo)))
-
static int input_big5(const unsigned char *buffer, int size, unichar *result)
{
if (is_big5_hi(*buffer)) {
--- irssi-snapshot-0.8.6+cvs.20030712.orig/src/fe-text/textbuffer-view.c
+++ irssi-snapshot-0.8.6+cvs.20030712/src/fe-text/textbuffer-view.c
@@ -199,8 +199,14 @@
}
if (!view->utf8) {
- next_ptr = ptr+1;
+ /* MH */
char_len = 1;
+ if(ptr[1] != '\0' && is_big5(ptr[0], ptr[1]))
+ {
+ char_len = 2;
+ }
+ next_ptr = ptr+char_len;
+ /* */
} else {
char_len = 1;
while (ptr[char_len] != '\0' && char_len < 6)
@@ -251,7 +257,15 @@
continue;
}
- if (*ptr == ' ') {
+ /* MH */
+ if (!view->utf8 && char_len > 1)
+ {
+ last_space = xpos;
+ last_space_ptr = next_ptr;
+ last_color = color;
+ }
+ /* */
+ else if (*ptr == ' ') {
last_space = xpos;
last_space_ptr = ptr;
last_color = color;
--- irssi-snapshot-0.8.6+cvs.20030712.orig/src/fe-text/utf8.h
+++ irssi-snapshot-0.8.6+cvs.20030712/src/fe-text/utf8.h
@@ -18,6 +18,13 @@
Make sure out is at least 6 x length of str. */
void utf16_to_utf8(const unichar *str, char *out);
+/* XXX I didn't check the encoding range of big5+. This is standard big5. */
+#define is_big5_los(lo) (0x40 <= (lo) && (lo) <= 0x7E) /* standard */
+#define is_big5_lox(lo) (0x80 <= (lo) && (lo) <= 0xFE) /* extended */
+#define is_big5_lo(lo) ((is_big5_los(lo) || is_big5_lox(lo)))
+#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE)
+#define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo))
+
/* Returns width for character (0-2). */
int utf8_width(unichar c);