mirror of
https://github.com/irssi/irssi.git
synced 2024-11-03 04:27:19 -05: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:
parent
612c061605
commit
afeb6fcb7d
21
configure.in
21
configure.in
@ -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 **
|
||||
|
@ -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--;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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"),
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "term.h"
|
||||
|
||||
#define MODULE_NAME "fe-text"
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user