1
0
mirror of https://github.com/irssi/irssi.git synced 2024-09-15 04:28:09 -04:00

/SET term_type 8bit|utf8|big5 - Removed --with-big5 configure option, it's

now included the same way as utf8, though i'm not sure if it really works
but at least it should partially :) Input line is now internally using 32bit
chars but it's converted to 8bit chars for external use. Text buffer
supports only 8bit + utf8 for now.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2448 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2002-02-15 13:38:24 +00:00 committed by cras
parent 612c061605
commit afeb6fcb7d
14 changed files with 502 additions and 168 deletions

View File

@ -31,19 +31,6 @@ AC_CHECK_HEADERS(string.h stdlib.h unistd.h dirent.h sys/ioctl.h sys/resource.h)
# check posix headers..
AC_CHECK_HEADERS(sys/time.h sys/utsname.h regex.h)
AC_ARG_WITH(big5,
[ --with-big5 Build with tr-Chinese Big5 support],
if test x$withval = xyes; then
want_big5=yes
else
if test "x$withval" = xno; then
want_big5=no
else
want_big5=yes
fi
fi,
want_big5=no)
AC_ARG_WITH(socks,
[ --with-socks Build with socks support],
if test x$withval = xyes; then
@ -732,14 +719,6 @@ COMMON_LIBS="$FE_COMMON_LIBS $COMMON_NOUI_LIBS"
AC_SUBST(COMMON_NOUI_LIBS)
AC_SUBST(COMMON_LIBS)
dnl **
dnl ** tr-Chinese Big5 support
dnl **
if test "x$want_big5" = "xyes"; then
AC_DEFINE(WANT_BIG5)
fi
dnl **
dnl ** IPv6 support
dnl **

View File

@ -19,6 +19,7 @@
*/
#include "module.h"
#include "misc.h"
#include "utf8.h"
#include "formats.h"
@ -26,8 +27,19 @@
#include "gui-printtext.h"
#include "term.h"
const unichar empty_str[] = { 0 };
GUI_ENTRY_REC *active_entry;
static void entry_text_grow(GUI_ENTRY_REC *entry, int grow_size)
{
if (entry->text_len+grow_size < entry->text_alloc)
return;
entry->text_alloc = nearest_power(entry->text_alloc+grow_size);
entry->text = g_realloc(entry->text, entry->text_alloc);
}
GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
{
GUI_ENTRY_REC *rec;
@ -36,7 +48,9 @@ GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width, int utf8)
rec->xpos = xpos;
rec->ypos = ypos;
rec->width = width;
rec->text = g_string_new(NULL);
rec->text_alloc = 1024;
rec->text = g_new(unichar, rec->text_alloc);
rec->text[0] = '\0';
rec->utf8 = utf8;
return rec;
}
@ -48,8 +62,8 @@ void gui_entry_destroy(GUI_ENTRY_REC *entry)
if (active_entry == entry)
gui_entry_set_active(NULL);
g_free_not_null(entry->prompt);
g_string_free(entry->text, TRUE);
g_free(entry->text);
g_free(entry->prompt);
g_free(entry);
}
@ -76,14 +90,9 @@ static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry)
static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
{
const unsigned char *p, *end;
const unichar *p;
int xpos, end_xpos;
if (entry->utf8) {
/* FIXME: a stupid kludge to make the chars output correctly */
pos = 0;
}
xpos = entry->xpos + entry->promptlen + pos;
end_xpos = entry->xpos + entry->width;
if (xpos > end_xpos)
@ -92,20 +101,14 @@ static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
term_set_color(root_window, ATTR_RESET);
term_move(root_window, xpos, entry->ypos);
p = (unsigned char *) (entry->scrstart + pos >= entry->text->len ? "" :
entry->text->str + entry->scrstart + pos);
p = entry->scrstart + pos < entry->text_len ?
entry->text + entry->scrstart + pos : empty_str;
for (; *p != '\0' && xpos < end_xpos; p++, xpos++) {
end = p;
if (entry->utf8)
get_utf8_char(&end);
if (entry->hidden)
term_addch(root_window, ' ');
else if (*p >= 32 && (end != p || (*p & 127) >= 32)) {
for (; p < end; p++)
term_addch(root_window, *p);
term_addch(root_window, *p);
} else {
else if (*p >= 32 && (entry->utf8 || (*p & 127) >= 32))
term_add_unichar(root_window, *p);
else {
term_set_color(root_window, ATTR_RESET|ATTR_REVERSE);
term_addch(root_window, *p+'A'-1);
term_set_color(root_window, ATTR_RESET);
@ -230,38 +233,67 @@ void gui_entry_set_utf8(GUI_ENTRY_REC *entry, int utf8)
void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str)
{
g_return_if_fail(entry != NULL);
g_return_if_fail(entry != NULL);
g_return_if_fail(str != NULL);
g_string_assign(entry->text, str);
entry->pos = entry->text->len;
entry->text_len = 0;
entry->pos = 0;
entry->text[0] = '\0';
gui_entry_redraw_from(entry, 0);
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
gui_entry_insert_text(entry, str);
}
char *gui_entry_get_text(GUI_ENTRY_REC *entry)
{
char *buf;
int i;
g_return_val_if_fail(entry != NULL, NULL);
return entry->text->str;
buf = g_malloc(entry->text_len*6 + 1);
if (entry->utf8)
utf16_to_utf8(entry->text, buf);
else {
for (i = 0; i <= entry->text_len; i++)
buf[i] = entry->text[i];
}
return buf;
}
void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str)
{
unichar chr;
int i, len;
g_return_if_fail(entry != NULL);
g_return_if_fail(str != NULL);
gui_entry_redraw_from(entry, entry->pos);
g_string_insert(entry->text, entry->pos, str);
entry->pos += strlen(str);
len = !entry->utf8 ? strlen(str) : strlen_utf8(str);
entry_text_grow(entry, len);
/* make space for the string */
g_memmove(entry->text + entry->pos + len, entry->text + entry->pos,
(entry->text_len-entry->pos + 1) * sizeof(unichar));
if (!entry->utf8) {
for (i = 0; i < len; i++)
entry->text[entry->pos+i] = str[i];
} else {
chr = entry->text[entry->pos+len];
utf8_to_utf16(str, entry->text+entry->pos);
entry->text[entry->pos+len] = chr;
}
entry->text_len += len;
entry->pos += len;
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
}
void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr)
void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr)
{
g_return_if_fail(entry != NULL);
@ -269,13 +301,38 @@ void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr)
return; /* never insert NUL, CR or LF characters */
gui_entry_redraw_from(entry, entry->pos);
g_string_insert_c(entry->text, entry->pos, chr);
entry->pos++;
entry_text_grow(entry, 1);
/* make space for the string */
g_memmove(entry->text + entry->pos + 1, entry->text + entry->pos,
(entry->text_len-entry->pos + 1) * sizeof(unichar));
entry->text[entry->pos] = chr;
entry->text_len++;
entry->pos++;
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
}
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry)
{
char *buf;
int i;
g_return_val_if_fail(entry != NULL, NULL);
buf = g_malloc(entry->cutbuffer_len*6 + 1);
if (entry->utf8)
utf16_to_utf8(entry->cutbuffer, buf);
else {
for (i = 0; i <= entry->cutbuffer_len; i++)
buf[i] = entry->cutbuffer[i];
}
return buf;
}
void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
{
g_return_if_fail(entry != NULL);
@ -283,14 +340,22 @@ void gui_entry_erase(GUI_ENTRY_REC *entry, int size)
if (entry->pos < size)
return;
#ifdef WANT_BIG5
if (is_big5(entry->text->str[entry->pos-2],
entry->text->str[entry->pos-1]))
size++;
#endif
/* put erased text to cutbuffer */
if (entry->cutbuffer_len < size) {
g_free(entry->cutbuffer);
entry->cutbuffer = g_new(unichar, size+1);
}
entry->cutbuffer_len = size;
entry->cutbuffer[size] = '\0';
memcpy(entry->cutbuffer, entry->text + entry->pos - size,
size * sizeof(unichar));
g_memmove(entry->text + entry->pos - size, entry->text + entry->pos,
(entry->text_len-entry->pos+1) * sizeof(unichar));
entry->pos -= size;
g_string_erase(entry->text, entry->pos, size);
entry->text_len -= size;
gui_entry_redraw_from(entry, entry->pos);
gui_entry_fix_cursor(entry);
@ -308,52 +373,45 @@ void gui_entry_erase_word(GUI_ENTRY_REC *entry, int to_space)
to = entry->pos - 1;
if (to_space) {
while (entry->text->str[to] == ' ' && to > 0)
while (entry->text[to] == ' ' && to > 0)
to--;
while (entry->text->str[to] != ' ' && to > 0)
while (entry->text[to] != ' ' && to > 0)
to--;
} else {
while (!i_isalnum(entry->text->str[to]) && to > 0)
while (!i_isalnum(entry->text[to]) && to > 0)
to--;
while (i_isalnum(entry->text->str[to]) && to > 0)
while (i_isalnum(entry->text[to]) && to > 0)
to--;
}
if (to > 0) to++;
g_string_erase(entry->text, to, entry->pos - to);
entry->pos = to;
gui_entry_redraw_from(entry, entry->pos);
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
gui_entry_erase(entry, entry->pos-to);
}
void gui_entry_erase_next_word(GUI_ENTRY_REC *entry, int to_space)
{
int to;
int to, size;
g_return_if_fail(entry != NULL);
if (entry->pos == entry->text->len)
if (entry->pos == entry->text_len)
return;
to = entry->pos;
if (to_space) {
while (entry->text->str[to] == ' ' && to < entry->text->len)
while (entry->text[to] == ' ' && to < entry->text_len)
to++;
while (entry->text->str[to] != ' ' && to < entry->text->len)
while (entry->text[to] != ' ' && to < entry->text_len)
to++;
} else {
while (!i_isalnum(entry->text->str[to]) && to < entry->text->len)
while (!i_isalnum(entry->text[to]) && to < entry->text_len)
to++;
while (i_isalnum(entry->text->str[to]) && to < entry->text->len)
while (i_isalnum(entry->text[to]) && to < entry->text_len)
to++;
}
g_string_erase(entry->text, entry->pos, to - entry->pos);
gui_entry_redraw_from(entry, entry->pos);
gui_entry_fix_cursor(entry);
gui_entry_draw(entry);
size = to-entry->pos;
entry->pos = to;
gui_entry_erase(entry, size);
}
int gui_entry_get_pos(GUI_ENTRY_REC *entry)
@ -367,7 +425,7 @@ void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos)
{
g_return_if_fail(entry != NULL);
if (pos >= 0 && pos <= entry->text->len)
if (pos >= 0 && pos <= entry->text_len)
entry->pos = pos;
gui_entry_fix_cursor(entry);
@ -378,16 +436,7 @@ void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos)
{
g_return_if_fail(entry != NULL);
#ifdef WANT_BIG5
if (pos > 0 && is_big5(entry->text->str[entry->pos],
entry->text->str[entry->pos+1]))
pos++;
else if (pos < 0 && is_big5(entry->text->str[entry->pos-1],
entry->text->str[entry->pos]))
pos--;
#endif
if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text->len)
if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text_len)
entry->pos += pos;
gui_entry_fix_cursor(entry);
@ -401,14 +450,14 @@ static void gui_entry_move_words_left(GUI_ENTRY_REC *entry, int count, int to_sp
pos = entry->pos;
while (count > 0 && pos > 0) {
if (to_space) {
while (pos > 0 && entry->text->str[pos-1] == ' ')
while (pos > 0 && entry->text[pos-1] == ' ')
pos--;
while (pos > 0 && entry->text->str[pos-1] != ' ')
while (pos > 0 && entry->text[pos-1] != ' ')
pos--;
} else {
while (pos > 0 && !i_isalnum(entry->text->str[pos-1]))
while (pos > 0 && !i_isalnum(entry->text[pos-1]))
pos--;
while (pos > 0 && i_isalnum(entry->text->str[pos-1]))
while (pos > 0 && i_isalnum(entry->text[pos-1]))
pos--;
}
count--;
@ -422,16 +471,16 @@ static void gui_entry_move_words_right(GUI_ENTRY_REC *entry, int count, int to_s
int pos;
pos = entry->pos;
while (count > 0 && pos < entry->text->len) {
while (count > 0 && pos < entry->text_len) {
if (to_space) {
while (pos < entry->text->len && entry->text->str[pos] == ' ')
while (pos < entry->text_len && entry->text[pos] == ' ')
pos++;
while (pos < entry->text->len && entry->text->str[pos] != ' ')
while (pos < entry->text_len && entry->text[pos] != ' ')
pos++;
} else {
while (pos < entry->text->len && !i_isalnum(entry->text->str[pos]))
while (pos < entry->text_len && !i_isalnum(entry->text[pos]))
pos++;
while (pos < entry->text->len && i_isalnum(entry->text->str[pos]))
while (pos < entry->text_len && i_isalnum(entry->text[pos]))
pos++;
}
count--;

View File

@ -2,7 +2,13 @@
#define __GUI_ENTRY_H
typedef struct {
GString *text;
int text_len, text_alloc; /* as shorts, not chars */
unichar *text;
int cutbuffer_len;
unichar *cutbuffer;
/* all as shorts, not chars */
int xpos, ypos, width; /* entry position in screen */
int pos, scrstart, scrpos; /* cursor position */
int hidden; /* print the chars as spaces in input line (useful for passwords) */
@ -30,8 +36,9 @@ void gui_entry_set_text(GUI_ENTRY_REC *entry, const 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_char(GUI_ENTRY_REC *entry, char chr);
void gui_entry_insert_char(GUI_ENTRY_REC *entry, unichar chr);
char *gui_entry_get_cutbuffer(GUI_ENTRY_REC *entry);
void gui_entry_erase(GUI_ENTRY_REC *entry, int size);
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);

View File

@ -43,7 +43,8 @@ static char *expando_inputline(SERVER_REC *server, void *item, int *free_ret)
/* value of cutbuffer */
static char *expando_cutbuffer(SERVER_REC *server, void *item, int *free_ret)
{
return cutbuffer;
*free_ret = TRUE;
return gui_entry_get_cutbuffer(active_entry);
}
void gui_expandos_init(void)

View File

@ -33,6 +33,7 @@
#include "term.h"
#include "gui-entry.h"
#include "gui-windows.h"
#include "utf8.h"
#include <signal.h>
@ -48,7 +49,6 @@ typedef struct {
static KEYBOARD_REC *keyboard;
static ENTRY_REDIRECT_REC *redir;
char *cutbuffer;
static int readtag;
static time_t idle_time;
@ -133,9 +133,9 @@ static void window_next_page(void)
gui_window_scroll(active_win, get_scroll_count());
}
void handle_key(int key)
void handle_key(unichar key)
{
char str[3];
char str[20];
idle_time = time(NULL);
@ -147,20 +147,23 @@ void handle_key(int key)
if (key >= 0 && key < 32) {
/* control key */
str[0] = '^';
str[1] = key+'@';
str[1] = (char)key+'@';
str[2] = '\0';
} else if (key == 127) {
str[0] = '^';
str[1] = '?';
str[2] = '\0';
} else {
str[0] = key;
} else if (!active_entry->utf8) {
str[0] = (char)key;
str[1] = '\0';
} else {
/* need to convert to utf8 */
str[utf16_char_to_utf8(key, str)] = '\0';
}
if (!key_pressed(keyboard, str)) {
/* key wasn't used for anything, print it */
gui_entry_insert_char(active_entry, (char) key);
gui_entry_insert_char(active_entry, key);
}
}
@ -170,7 +173,10 @@ static void key_send_line(void)
char *str, *add_history;
str = gui_entry_get_text(active_entry);
if (*str == '\0') return;
if (*str == '\0') {
g_free(str);
return;
}
/* we can't use gui_entry_get_text() later, since the entry might
have been destroyed after we get back */
@ -199,6 +205,8 @@ static void key_send_line(void)
if (active_entry != NULL)
gui_entry_set_text(active_entry, "");
command_history_clear_pos(active_win);
g_free(str);
}
static void key_combo(void)
@ -208,17 +216,23 @@ static void key_combo(void)
static void key_backward_history(void)
{
const char *text;
char *line;
text = command_history_prev(active_win, gui_entry_get_text(active_entry));
line = gui_entry_get_text(active_entry);
text = command_history_prev(active_win, line);
gui_entry_set_text(active_entry, text);
g_free(line);
}
static void key_forward_history(void)
{
const char *text;
char *line;
text = command_history_next(active_win, gui_entry_get_text(active_entry));
line = gui_entry_get_text(active_entry);
text = command_history_next(active_win, line);
gui_entry_set_text(active_entry, text);
g_free(line);
}
static void key_beginning_of_line(void)
@ -228,7 +242,7 @@ static void key_beginning_of_line(void)
static void key_end_of_line(void)
{
gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry)));
gui_entry_set_pos(active_entry, active_entry->text_len);
}
static void key_backward_character(void)
@ -263,10 +277,8 @@ static void key_forward_to_space(void)
static void key_erase_line(void)
{
g_free_not_null(cutbuffer);
cutbuffer = g_strdup(gui_entry_get_text(active_entry));
gui_entry_set_text(active_entry, "");
gui_entry_set_pos(active_entry, active_entry->text_len);
gui_entry_erase(active_entry, active_entry->text_len);
}
static void key_erase_to_beg_of_line(void)
@ -274,9 +286,6 @@ static void key_erase_to_beg_of_line(void)
int pos;
pos = gui_entry_get_pos(active_entry);
g_free_not_null(cutbuffer);
cutbuffer = g_strndup(gui_entry_get_text(active_entry), pos);
gui_entry_erase(active_entry, pos);
}
@ -285,21 +294,22 @@ static void key_erase_to_end_of_line(void)
int pos;
pos = gui_entry_get_pos(active_entry);
g_free_not_null(cutbuffer);
cutbuffer = g_strdup(gui_entry_get_text(active_entry)+pos);
gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry)));
gui_entry_erase(active_entry, strlen(gui_entry_get_text(active_entry)) - pos);
gui_entry_set_pos(active_entry, active_entry->text_len);
gui_entry_erase(active_entry, active_entry->text_len - pos);
}
static void key_yank_from_cutbuffer(void)
{
char *cutbuffer;
cutbuffer = gui_entry_get_cutbuffer(active_entry);
if (cutbuffer != NULL)
gui_entry_insert_text(active_entry, cutbuffer);
}
static void key_transpose_characters(void)
{
#if 0 /* FIXME: !!! */
char *line, c;
int pos;
@ -316,11 +326,12 @@ static void key_transpose_characters(void)
gui_entry_insert_char(active_entry, c);
gui_entry_set_pos(active_entry, pos);
gui_entry_move_pos(active_entry, 1);
#endif
}
static void key_delete_character(void)
{
if (gui_entry_get_pos(active_entry) < (int)strlen(gui_entry_get_text(active_entry))) {
if (gui_entry_get_pos(active_entry) < active_entry->text_len) {
gui_entry_move_pos(active_entry, 1);
gui_entry_erase(active_entry, 1);
}
@ -353,7 +364,7 @@ static void key_delete_to_next_space(void)
static void sig_input(void)
{
unsigned char buffer[128];
unichar buffer[128];
int ret, i;
if (!active_entry) {
@ -361,7 +372,7 @@ static void sig_input(void)
return;
}
ret = term_gets(buffer, sizeof(buffer));
ret = term_gets(buffer, sizeof(buffer)/sizeof(buffer[0]));
if (ret == -1) {
/* lost terminal */
if (!term_detached)
@ -404,13 +415,15 @@ static void key_change_window(const char *data)
static void key_completion(int erase)
{
char *line;
char *text, *line;
int pos;
pos = gui_entry_get_pos(active_entry);
line = word_complete(active_win, gui_entry_get_text(active_entry),
&pos, erase);
text = gui_entry_get_text(active_entry);
line = word_complete(active_win, text, &pos, erase);
g_free(text);
if (line != NULL) {
gui_entry_set_text(active_entry, line);
gui_entry_set_pos(active_entry, pos);
@ -430,12 +443,15 @@ static void key_erase_completion(void)
static void key_check_replaces(void)
{
char *line;
char *text, *line;
int pos;
pos = gui_entry_get_pos(active_entry);
line = auto_word_complete(gui_entry_get_text(active_entry), &pos);
text = gui_entry_get_text(active_entry);
line = auto_word_complete(text, &pos);
g_free(text);
if (line != NULL) {
gui_entry_set_text(active_entry, line);
gui_entry_set_pos(active_entry, pos);
@ -537,11 +553,15 @@ static void key_sig_stop(void)
static void sig_window_auto_changed(void)
{
char *text;
if (active_entry == NULL)
return;
command_history_next(active_win, gui_entry_get_text(active_entry));
text = gui_entry_get_text(active_entry);
command_history_next(active_win, text);
gui_entry_set_text(active_entry, "");
g_free(text);
}
static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry,
@ -563,7 +583,6 @@ void gui_readline_init(void)
char *key, data[MAX_INT_STRLEN];
int n;
cutbuffer = NULL;
redir = NULL;
idle_time = time(NULL);
input_listen_init(STDIN_FILENO);
@ -693,7 +712,6 @@ void gui_readline_init(void)
void gui_readline_deinit(void)
{
g_free_not_null(cutbuffer);
input_listen_deinit();
key_configure_freeze();

View File

@ -44,7 +44,7 @@ static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window,
gui->view = textbuffer_view_create(textbuffer_create(),
window->width, window->height,
settings_get_bool("scroll"),
settings_get_bool("term_utf8"));
term_type == TERM_TYPE_UTF8);
textbuffer_view_set_default_indent(gui->view,
settings_get_int("indent"),
!settings_get_bool("indent_always"),

View File

@ -1,4 +1,5 @@
#include "common.h"
#include "term.h"
#define MODULE_NAME "fe-text"

View File

@ -347,8 +347,7 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
rec = g_hash_table_lookup(input_entries, item->bar);
if (rec == NULL) {
rec = gui_entry_create(item->xpos, item->bar->real_ypos,
item->size,
settings_get_bool("term_utf8"));
item->size, term_type == TERM_TYPE_UTF8);
gui_entry_set_active(rec);
g_hash_table_insert(input_entries, item->bar, rec);
}
@ -377,10 +376,8 @@ static void sig_statusbar_destroyed(STATUSBAR_REC *bar)
static void read_settings(void)
{
if (active_entry != NULL) {
gui_entry_set_utf8(active_entry,
settings_get_bool("term_utf8"));
}
if (active_entry != NULL)
gui_entry_set_utf8(active_entry, term_type == TERM_TYPE_UTF8);
}
void statusbar_items_init(void)

View File

@ -22,9 +22,16 @@
#include "signals.h"
#include "term.h"
#include "terminfo-core.h"
#include "utf8.h"
#include <signal.h>
/* returns number of characters in the beginning of the buffer being a
a single character, or -1 if more input is needed. The character will be
saved in result */
typedef int (*TERM_INPUT_FUNC)(const unsigned char *buffer, int size,
unichar *result);
struct _TERM_WINDOW {
/* Terminal to use for window */
TERM_REC *term;
@ -48,6 +55,10 @@ static int last_fg, last_bg, last_attrs;
static int redraw_needed, redraw_tag;
static int freeze_counter;
static TERM_INPUT_FUNC input_func;
static unsigned char term_inbuf[256];
static int term_inbuf_pos;
/* SIGCONT handler */
static void sig_cont(int p)
{
@ -94,6 +105,7 @@ int term_init(void)
term_lines_empty = g_new0(char, term_height);
term_set_input_type(TERM_TYPE_8BIT);
term_common_init();
g_atexit(term_deinit);
return TRUE;
@ -373,6 +385,39 @@ void term_addch(TERM_WINDOW *window, int chr)
putc(chr, window->term->out);
}
static void term_addch_utf8(TERM_WINDOW *window, unichar chr)
{
unsigned char buf[10];
int i, len;
len = utf16_char_to_utf8(chr, buf);
for (i = 0; i < len; i++)
putc(buf[i], window->term->out);
}
void term_add_unichar(TERM_WINDOW *window, unichar chr)
{
if (term_detached) return;
if (vcmove) term_move_real();
term_printed_text(1);
if (vcy == term_height && vcx == 0)
return; /* last char in screen */
switch (term_type) {
case TERM_TYPE_UTF8:
term_addch_utf8(window, chr);
break;
case TERM_TYPE_BIG5:
putc((chr >> 8) & 0xff, window->term->out);
putc((chr & 0xff), window->term->out);
break;
default:
putc(chr, window->term->out);
break;
}
}
void term_addstr(TERM_WINDOW *window, const char *str)
{
int len;
@ -487,15 +532,80 @@ void term_stop(void)
}
}
int term_gets(unsigned char *buffer, int size)
static int input_utf8(const unsigned char *buffer, int size, unichar *result)
{
int ret;
const unsigned char *end = buffer;
*result = get_utf8_char(&end, size);
switch (*result) {
case (unichar) -2:
/* not UTF8 - fallback to 8bit ascii */
*result = *buffer;
return 1;
case (unichar) -1:
/* need more data */
return -1;
default:
return (int) (end-buffer)+1;
}
}
/* 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)) {
/* could be */
if (size == 1)
return -1;
if (is_big5_los(buffer[1]) || is_big5_lox(buffer[1])) {
*result = buffer[1] + ((int) *buffer << 8);
return 2;
}
}
*result = *buffer;
return 1;
}
static int input_8bit(const unsigned char *buffer, int size, unichar *result)
{
*result = *buffer;
return 1;
}
void term_set_input_type(int type)
{
switch (type) {
case TERM_TYPE_UTF8:
input_func = input_utf8;
break;
case TERM_TYPE_BIG5:
input_func = input_big5;
break;
default:
input_func = input_8bit;
}
}
int term_gets(unichar *buffer, int size)
{
int ret, i, char_len;
if (term_detached)
return 0;
/* fread() doesn't work */
ret = read(fileno(current_term->in), buffer, size);
if (size > sizeof(term_inbuf)-term_inbuf_pos)
size = sizeof(term_inbuf)-term_inbuf_pos;
ret = read(fileno(current_term->in),
term_inbuf + term_inbuf_pos, size);
if (ret == 0) {
/* EOF - terminal got lost */
if (auto_detach)
@ -504,5 +614,28 @@ int term_gets(unsigned char *buffer, int size)
} else if (ret == -1 && (errno == EINTR || errno == EAGAIN))
ret = 0;
if (ret > 0) {
/* convert input to unichars. */
term_inbuf_pos += ret;
ret = 0;
for (i = 0; i < term_inbuf_pos; ) {
char_len = input_func(term_inbuf+i, term_inbuf_pos-i,
buffer);
if (char_len < 0)
break;
i += char_len;
buffer++;
ret++;
}
if (i >= term_inbuf_pos)
term_inbuf_pos = 0;
else {
memmove(term_inbuf+i, term_inbuf, term_inbuf_pos-i);
term_inbuf_pos = i;
}
}
return ret;
}

View File

@ -35,6 +35,7 @@
#define MIN_SCREEN_WIDTH 20
int term_use_colors;
int term_type;
static int force_colors;
static int resize_dirty;
@ -91,10 +92,25 @@ static void cmd_resize(void)
static void read_settings(void)
{
const char *str;
int old_colors = term_use_colors;
int old_type = term_type;
term_auto_detach(settings_get_bool("term_auto_detach"));
/* set terminal type */
str = settings_get_str("term_type");
if (g_strcasecmp(str, "utf8") == 0)
term_type = TERM_TYPE_UTF8;
else if (g_strcasecmp(str, "big5") == 0)
term_type = TERM_TYPE_BIG5;
else
term_type = TERM_TYPE_8BIT;
if (old_type != term_type)
term_set_input_type(term_type);
/* change color stuff */
if (force_colors != settings_get_bool("term_force_colors")) {
force_colors = settings_get_bool("term_force_colors");
term_force_colors(force_colors);
@ -115,7 +131,7 @@ void term_common_init(void)
settings_add_bool("lookandfeel", "colors", TRUE);
settings_add_bool("lookandfeel", "term_force_colors", FALSE);
settings_add_bool("lookandfeel", "term_auto_detach", FALSE);
settings_add_bool("lookandfeel", "term_utf8", FALSE);
settings_add_str("lookandfeel", "term_type", "8bit");
force_colors = FALSE;
term_use_colors = term_has_colors() && settings_get_bool("colors");

View File

@ -3,6 +3,7 @@
typedef struct _TERM_WINDOW TERM_WINDOW;
/* text attributes */
#define ATTR_RESETFG 0x0100
#define ATTR_RESETBG 0x0200
#define ATTR_BOLD 0x0400
@ -14,16 +15,16 @@ typedef struct _TERM_WINDOW TERM_WINDOW;
#define ATTR_NOCOLORS (ATTR_UNDERLINE|ATTR_REVERSE)
#ifdef WANT_BIG5
/* XXX I didn't check the encoding range of big5+. This is standard big5. */
# define is_big5_los(lo) (((char)0x40<=lo)&&(lo<=(char)0x7E)) /* standard */
# define is_big5_lox(lo) (((char)0x80<=lo)&&(lo<=(char)0xFE)) /* extended */
# define is_big5_hi(hi) (((char)0x81<=hi)&&(hi<=(char)0xFE))
# define is_big5(hi,lo) is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo))
#endif
/* terminal types */
#define TERM_TYPE_8BIT 0 /* normal 8bit text */
#define TERM_TYPE_UTF8 1
#define TERM_TYPE_BIG5 2
typedef guint32 unichar;
extern TERM_WINDOW *root_window;
extern int term_width, term_height, term_use_colors, term_detached;
extern int term_width, term_height;
extern int term_use_colors, term_type, term_detached;
/* Initialize / deinitialize terminal */
int term_init(void);
@ -63,6 +64,7 @@ void term_set_color(TERM_WINDOW *window, int col);
void term_move(TERM_WINDOW *window, int x, int y);
void term_addch(TERM_WINDOW *window, int chr);
void term_add_unichar(TERM_WINDOW *window, unichar chr);
void term_addstr(TERM_WINDOW *window, const char *str);
void term_clrtoeol(TERM_WINDOW *window);
@ -78,7 +80,10 @@ void term_detach(void);
void term_attach(FILE *in, FILE *out);
void term_stop(void);
int term_gets(unsigned char *buffer, int size);
/* keyboard input handling */
void term_set_input_type(int type);
int term_gets(unichar *buffer, int size);
/* internal */
void term_common_init(void);

View File

@ -231,7 +231,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
}
if (view->utf8)
get_utf8_char(&ptr);
get_utf8_char(&ptr, 6);
xpos++;
if (*ptr++ == ' ') {
@ -398,7 +398,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
if (xpos < term_width) {
const unsigned char *end = text;
if (view->utf8)
get_utf8_char(&end);
get_utf8_char(&end, 6);
if (*text >= 32 &&
(end != text || (*text & 127) >= 32)) {

View File

@ -1,3 +1,29 @@
/* utf8.c - Operations on UTF-8 strings.
*
* Copyright (C) 2002 Timo Sirainen
*
* Based on GLib code by
*
* Copyright (C) 1999 Tom Tromey
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "module.h"
#define UTF8_COMPUTE(Char, Mask, Len) \
if (Char < 128) \
@ -46,19 +72,106 @@
(Result) |= ((Chars)[(Count)] & 0x3f); \
}
void get_utf8_char(const unsigned char **ptr)
unichar get_utf8_char(const unsigned char **ptr, int len)
{
int i, mask = 0, len;
unsigned int result;
unsigned char c = (unsigned char) **ptr;
int i, result, mask, chrlen;
UTF8_COMPUTE(c, mask, len);
mask = 0;
UTF8_COMPUTE(**ptr, mask, chrlen);
if (len == -1)
return;
return (unichar) -2;
if (chrlen > len)
return (unichar) -1;
UTF8_GET(result, *ptr, i, mask, len);
if (result == -1)
return;
return (unichar) -2;
*ptr += len-1;
*ptr += len-1;
return result;
}
int strlen_utf8(const char *str)
{
const unsigned char *p = (const unsigned char *) str;
int len;
len = 0;
while (*p != '\0' && get_utf8_char(&p, 6) > 0) {
len++;
p++;
}
return len;
}
int utf16_char_to_utf8(unichar c, unsigned char *outbuf)
{
int len, i, first;
len = 0;
if (c < 0x80) {
first = 0;
len = 1;
} else if (c < 0x800) {
first = 0xc0;
len = 2;
} else if (c < 0x10000) {
first = 0xe0;
len = 3;
} else if (c < 0x200000) {
first = 0xf0;
len = 4;
} else if (c < 0x4000000) {
first = 0xf8;
len = 5;
} else {
first = 0xfc;
len = 6;
}
if (outbuf) {
for (i = len - 1; i > 0; --i) {
outbuf[i] = (c & 0x3f) | 0x80;
c >>= 6;
}
outbuf[0] = c | first;
}
return len;
}
void utf8_to_utf16(const char *str, unichar *out)
{
const unsigned char *p = (const unsigned char *) str;
int i, result, mask, len;
while (*p != '\0') {
mask = 0;
UTF8_COMPUTE(*p, mask, len);
if (len == -1)
break;
UTF8_GET(result, p, i, mask, len);
if (result == -1)
break;
p += len;
*out++ = result;
}
*out = '\0';
}
void utf16_to_utf8(const unichar *str, char *out)
{
int len;
while (*str != '\0') {
len = utf16_char_to_utf8(*str, out);
out += len;
str++;
}
*out = '\0';
}

View File

@ -1,6 +1,21 @@
#ifndef __UTF8_H
#define __UTF8_H
void get_utf8_char(const unsigned char **ptr);
/* Returns -2 = invalid, -1 = need more data, otherwise unichar. */
unichar get_utf8_char(const unsigned char **ptr, int len);
/* Returns length of UTF8 string */
int strlen_utf8(const char *str);
/* UTF-8 -> unichar string. The NUL is copied as well. */
void utf8_to_utf16(const char *str, unichar *out);
/* unichar -> UTF-8 string. outbuf must be at least 6 chars long.
Returns outbuf string length. */
int utf16_char_to_utf8(unichar c, unsigned char *outbuf);
/* unichar -> UTF-8 string. The NUL is copied as well.
Make sure out is at least 6 x length of str. */
void utf16_to_utf8(const unichar *str, char *out);
#endif