diff options
author | Nalin Dahyabhai <nalin@src.gnome.org> | 2002-07-18 03:43:18 +0000 |
---|---|---|
committer | Nalin Dahyabhai <nalin@src.gnome.org> | 2002-07-18 03:43:18 +0000 |
commit | cf55403688da83b34f8eb5a7f5b326fd0a7e28ee (patch) | |
tree | 5c082fea5d3e099a4949362ff4f8db2c18d1a718 | |
parent | 623ee6d073c540bd02b2b4f4a9abb2ddf7b7637f (diff) | |
download | vte-cf55403688da83b34f8eb5a7f5b326fd0a7e28ee.tar.gz |
Actually set ALL_LINGUAS so translations get installed. Document the
* configure.in: Actually set ALL_LINGUAS so translations get installed.
* README: Document the weirdness that is cursor movement around wide characters.
* src/vte.defs: Bind set_color_bold().
* src/debug.c: Suppress warnings when $VTE_DEBUG_FLAGS isn't set.
* src/pty.c, src/reaper.c, src/termcap.c, src/trie.c: Provide for debug messages
in the test program.
* src/interpret.c, src/trie.c: Use libc stdio instead of g_print for printing
what might be part of a multibyte sequence because g_print checks for
validity.
* src/interpret.c, src/trie.c, src/utf8echo.c, src/vte.c: Use gunichar instead
of wchar_t in places where a gunichar is expected. Provide a means for
converting from wchar_t to gunichar for the sake of X11 calls which want
a wchar_t.
* src/trie.c: Provide vte_trie_wide_encoding() for finding a giconv target
which is hopefully compatible with gunichar. Likewise provide
vte_trie_narrow_encoding() to find one compatible with iso-8859-1.
* src/vte.c: Fall back to ISO-8859-1 if we can't set things up for the current
locale encoding at startup time. Fall back to the current encoding if
we can't perform a given dynamic switch.
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | README | 21 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | po/sv.po | 48 | ||||
-rw-r--r-- | python/vte.defs | 9 | ||||
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/debug.c | 2 | ||||
-rw-r--r-- | src/interpret.c | 36 | ||||
-rw-r--r-- | src/pty.c | 1 | ||||
-rw-r--r-- | src/reaper.c | 2 | ||||
-rw-r--r-- | src/termcap.c | 4 | ||||
-rw-r--r-- | src/trie.c | 349 | ||||
-rw-r--r-- | src/trie.h | 12 | ||||
-rw-r--r-- | src/utf8echo.c | 5 | ||||
-rw-r--r-- | src/vte.c | 210 | ||||
-rw-r--r-- | src/vte.h | 1 | ||||
-rw-r--r-- | vte.spec | 7 |
17 files changed, 509 insertions, 227 deletions
@@ -1,3 +1,24 @@ +2002-07-17 nalin + * configure.in: Actually set ALL_LINGUAS so translations get installed. + * README: Document the weirdness that is cursor movement around wide + characters. + * src/vte.defs: Bind set_color_bold(). + * src/debug.c: Suppress warnings when $VTE_DEBUG_FLAGS isn't set. + * src/pty.c, src/reaper.c, src/termcap.c, src/trie.c: Provide for + debug messages in the test program. + * src/interpret.c, src/trie.c: Use libc stdio instead of g_print for + printing what might be part of a multibyte sequence because g_print + checks for validity. + * src/interpret.c, src/trie.c, src/utf8echo.c, src/vte.c: Use gunichar + instead of wchar_t in places where a gunichar is expected. Provide a + means for converting from wchar_t to gunichar for the sake of X11 calls + which want a wchar_t. + * src/trie.c: Provide vte_trie_wide_encoding() for finding a giconv + target which is hopefully compatible with gunichar. Likewise provide + vte_trie_narrow_encoding() to find one compatible with iso-8859-1. + * src/vte.c: Fall back to ISO-8859-1 if we can't set things up for the + current locale encoding at startup time. Fall back to the current + encoding if we can't perform a given dynamic switch. 2002-07-16 nalin * configure.in: Set GETTEXT_PACKAGE correctly, noted by menthos. @@ -16,7 +16,7 @@ - The VTE library inserts terminal capability strings into a trie, and then uses it to determine if data received from a pseudo-terminal is a control sequence or just random data. The sample program "interpret" illustrates - what the widget actually sees after it filters incoming data. + more or less what the widget sees after it filters incoming data. * What's missing? - Accessibility isn't completed yet. @@ -36,3 +36,22 @@ things is currently scarce, so some of it's guesswork. - An actual property interface needs to be retrofitted over the various options which are currently hard-coded at startup-time. + +* What's weird? +- Relative cursor motion is weird. When the character to the right of the + cursor is a 3-byte UTF-8 sequence for a character which occupies two + columns on the screen, three things may happen when the application sends + the "cursor left" control sequence: + * the cursor moves two columns (one character) to the left + This eliminates the possibility of moving the cursor into the middle of + a multi-column character. + * the cursor moves one column (one half-character) to the left + This makes determining where the cursor is easier, but requires the + application to emit a control sequence more than once for multi-column + characters. + * the cursor moves one "byte" to the left + This happens to work for a few locales, and is otherwise just broken. + Currently VTE follows the second convention. More on this topic: + http://czyborra.com/unicode/terminals.html + http://mail.nl.linux.org/linux-utf8/1999-10/msg00014.html + http://www.debian.org/doc/manuals/intro-i18n/ch-output.en.html diff --git a/configure.in b/configure.in index 825de11a..931c8b5e 100644 --- a/configure.in +++ b/configure.in @@ -2,6 +2,7 @@ AC_INIT(configure.in) VERSION=`grep ^Version: $srcdir/vte.spec | awk '{print $NF}'` AM_INIT_AUTOMAKE(vte,$VERSION) AM_PROG_LIBTOOL +ALL_LINGUAS="sv" AM_GLIB_GNU_GETTEXT AC_EGREP_CPP(glibc, [ @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: vte\n" -"POT-Creation-Date: 2002-07-17 01:38+0200\n" +"POT-Creation-Date: 2002-07-17 00:07-0400\n" "PO-Revision-Date: 2002-07-17 01:38+0200\n" "Last-Translator: Christian Rose <menthos@menthos.com>\n" "Language-Team: Swedish <sv@li.org>\n" @@ -24,47 +24,48 @@ msgstr "Fel vid tillägg av \"%s\" till miljön, fortsätter." msgid "Error creating signal pipe." msgstr "Fel vid skapande av signalrör." -#: src/trie.c:386 +#: src/trie.c:410 #, c-format msgid "Duplicate (%s/%s)!" msgstr "Dubbel (%s/%s)!" -#: src/vte.c:906 +#: src/vte.c:932 #, c-format msgid "Error compiling regular expression \"%s\"." msgstr "Fel vid kompilering av reguljärt uttryck \"%s\"." -#: src/vte.c:1280 src/vte.c:1285 src/vte.c:1291 +#: src/vte.c:1303 src/vte.c:1312 src/vte.c:1322 src/vte.c:1336 src/vte.c:1341 +#: src/vte.c:1346 #, c-format msgid "Unable to convert characters from %s to %s." msgstr "Kan inte konvertera tecken från %s till %s." -#: src/vte.c:4253 +#: src/vte.c:4307 #, c-format msgid "Got unexpected (key?) sequence `%s'." msgstr "Fick oväntad (tangent?)sekvens \"%s\"." -#: src/vte.c:4956 +#: src/vte.c:5008 #, c-format -msgid "Character %5ld is %d columns wide, guessing 1." -msgstr "Tecknet %5ld är %d kolumner brett, gissar 1." +msgid "Character 0x%x is undefined, allocating one column." +msgstr "" -#: src/vte.c:5150 +#: src/vte.c:5202 #, c-format msgid "No handler for control sequence `%s' defined." msgstr "Ingen hanterare för kontrollsekvensen \"%s\" är angiven." -#: src/vte.c:5766 +#: src/vte.c:5818 #, c-format msgid "Error reading from child: %s." msgstr "Fel vid läsning från barn: %s." -#: src/vte.c:5934 +#: src/vte.c:5986 #, c-format msgid "Error (%s) converting data for child, dropping." msgstr "Fel (%s) vid konvertering av data för barn, kastar." -#: src/vte.c:7671 +#: src/vte.c:7719 #, c-format msgid "" "Warning: using fontset \"%s\", which is missing these character sets: %s." @@ -72,56 +73,59 @@ msgstr "" "Varning: använder typsnittssamlingen \"%s\", som saknar dessa " "teckensamlingar: %s." -#: src/vte.c:8204 +#: src/vte.c:8252 #, c-format msgid "Failed to load Xft font pattern \"%s\", falling back to default font." msgstr "" "Misslyckades med att läsa in XFt-typsnittsmönstret \"%s\", använder " "standardtypsnittet." -#: src/vte.c:8217 +#: src/vte.c:8265 msgid "Failed to load default Xft font." msgstr "Misslyckades med att läsa in Xft-standardtypsnittet." -#: src/vte.c:8260 +#: src/vte.c:8308 msgid "Error allocating Xft font, disabling Xft." msgstr "Fel vid allokering av Xft-typsnitt, deaktiverar Xft." -#: src/vte.c:8284 +#: src/vte.c:8332 #, c-format msgid "Failed to load font set \"%s\", falling back to default font." msgstr "" "Misslyckades med att läsa in typsnittssamlingen \"%s\", använder " "standardtypsnittet." -#: src/vte.c:8296 +#: src/vte.c:8344 msgid "Failed to load default font, crashing or behaving abnormally." msgstr "" "Misslyckades med att läsa in standardtypsnittet, kraschar eller beter sig " "onormalt." -#: src/vte.c:8379 +#: src/vte.c:8427 #, c-format msgid "Error reading PTY size, using defaults: %s." msgstr "Fel vid läsande av PTY-storlek, använder standardvärden: %s." -#: src/vte.c:8400 +#: src/vte.c:8448 #, c-format msgid "Error setting PTY size: %s." msgstr "Fel vid läsande av PTY-storlek: %s." -#: src/vte.c:10411 +#: src/vte.c:10462 msgid "Error allocating layout, disabling Pango." msgstr "Fel vid allokering av layout, deaktiverar Pango." -#: src/vte.c:10421 +#: src/vte.c:10472 msgid "Error allocating draw, disabling Xft." msgstr "Fel vid allokering av ritbar yta, deaktiverar Xft." #. Aaargh. We're screwed. -#: src/vte.c:11629 +#: src/vte.c:11680 msgid "g_iconv_open() failed setting word characters" msgstr "g_iconv_open() misslyckades med att ställa in ordtecken" +#~ msgid "Character %5ld is %d columns wide, guessing 1." +#~ msgstr "Tecknet %5ld är %d kolumner brett, gissar 1." + #~ msgid "Invalid multibyte sequence detected. Munging up %d bytes of data." #~ msgstr "Ogiltig multibytesekvens hittad. Ignorerar %d byte med data." diff --git a/python/vte.defs b/python/vte.defs index f9d2afdb..e721646f 100644 --- a/python/vte.defs +++ b/python/vte.defs @@ -115,6 +115,15 @@ ) ) +(define-method set_color_bold + (of-object "VteTerminal") + (c-name "vte_terminal_set_color_bold") + (return-type "none") + (parameters + '("const-GdkColor*" "bold") + ) +) + (define-method set_color_foreground (of-object "VteTerminal") (c-name "vte_terminal_set_color_foreground") diff --git a/src/Makefile.am b/src/Makefile.am index 56abc64b..3f27b321 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,7 +30,7 @@ libvte_la_SOURCES = \ vteaccess.h libvte_la_LIBADD = @LIBS@ @XFT_LIBS@ @GTK_LIBS@ @X_LIBS@ -libvte_la_LDFLAGS = -version-info 3:0:2 +libvte_la_LDFLAGS = -version-info 2:0:0 CLEANFILES = marshal.c marshal.h @@ -55,7 +55,12 @@ interpret_SOURCES = \ interpret.c interpret_LDADD = @GLIB_LIBS@ +utf8echo_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DUTF8ECHO_MAIN utf8echo_SOURCES = \ + debug.c \ + debug.h \ + trie.c \ + trie.h \ utf8echo.c utf8echo_LDADD = @LIBS@ @GLIB_LIBS@ diff --git a/src/debug.c b/src/debug.c index c5abbd2f..45017f18 100644 --- a/src/debug.c +++ b/src/debug.c @@ -29,7 +29,7 @@ vte_debug_parse_string(const char *string) char **flags = NULL; int i; vte_debug_flags = 0; - flags = g_strsplit(string, ",", 0); + flags = g_strsplit(string ? string : "", ",", 0); if (flags != NULL) { for (i = 0; flags[i] != NULL; i++) { if (g_ascii_strcasecmp(flags[i], "ALL") == 0) { diff --git a/src/interpret.c b/src/interpret.c index ff57aa71..3096a807 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -32,14 +32,6 @@ #include "termcap.h" #include "trie.h" -static void -convert_mbstowcs(const char *i, size_t ilen, wchar_t *o, size_t *olen) -{ - mbstate_t state; - memset(&state, 0, sizeof(state)); - *olen = mbsrtowcs(o, &i, ilen, &state); -} - int main(int argc, char **argv) { @@ -52,8 +44,10 @@ main(int argc, char **argv) GValue *value; FILE *infile = NULL; + vte_debug_parse_string(getenv("VTE_DEBUG_FLAGS")); + if (argc < 2) { - g_print("usage: %s terminal [file]\n", argv[0]); + printf("usage: %s terminal [file]\n", argv[0]); return 1; } @@ -96,26 +90,30 @@ main(int argc, char **argv) const char *tmp; GQuark quark; GValueArray *values; - wchar_t wbuf[LINE_MAX]; - size_t wbuflen; - convert_mbstowcs(array->data, i, wbuf, &wbuflen); - vte_trie_match(trie, wbuf, wbuflen, + GError *error = NULL; + gunichar *ubuf; + gsize ubuflen; + ubuf = (gunichar*) g_convert(array->data, i, + vte_trie_wide_encoding(), + "UTF-8", + NULL, &ubuflen, &error); + vte_trie_match(trie, ubuf, ubuflen / sizeof(gunichar), &tmp, NULL, &quark, &values); if (tmp != NULL) { if (strlen(tmp) > 0) { int j; - g_print("%s(", g_quark_to_string(quark)); + printf("%s(", g_quark_to_string(quark)); for (j = 0; (values != NULL) && (j < values->n_values); j++) { if (j > 0) { - g_print(", "); + printf(", "); } value = g_value_array_get_nth(values, j); if (G_VALUE_HOLDS_LONG(value)) { - g_print("%ld", + printf("%ld", g_value_get_long(value)); } if (G_VALUE_HOLDS_STRING(value)) { - g_print("`%s'", + printf("`%s'", g_value_get_string(value)); } if (G_VALUE_HOLDS_POINTER(value)) { @@ -129,12 +127,12 @@ main(int argc, char **argv) for (j = 0; j < i; j++) { g_byte_array_remove_index(array, 0); } - g_print(")\n"); + printf(")\n"); break; } } else { while (array->len > 0) { - g_print("`%c'\n", array->data[0]); + printf("`%c'\n", array->data[0]); g_byte_array_remove_index(array, 0); } } @@ -239,6 +239,7 @@ main(int argc, char **argv) pid_t child; int fd; char c; + vte_debug_parse_string(getenv("VTE_DEBUG_FLAGS")); fd = vte_pty_open(&child, "/usr/bin/tty"); g_print("Child pid is %d.\n", (int)child); while(read(fd, &c, 1) == 1) { diff --git a/src/reaper.c b/src/reaper.c index 43fd19e1..6053be22 100644 --- a/src/reaper.c +++ b/src/reaper.c @@ -200,6 +200,8 @@ main(int argc, char **argv) VteReaper *reaper; pid_t p, q; + vte_debug_parse_string(getenv("VTE_DEBUG_FLAGS")); + g_type_init(); context = g_main_context_default(); loop = g_main_loop_new(context, FALSE); diff --git a/src/termcap.c b/src/termcap.c index 1820266c..ecd341e1 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -658,7 +658,9 @@ main(int argc, char **argv) const char *tc = (argc > 1) ? argv[1] : "linux"; const char *cap = (argc > 2) ? argv[2] : "so"; char *value; - struct vte_termcap *termcap = vte_termcap_new("/etc/termcap"); + struct vte_termcap *termcap; + vte_debug_parse_string(getenv("VTE_DEBUG_FLAGS")); + termcap = vte_termcap_new("/etc/termcap"); value = vte_termcap_find_string(termcap, tc, cap); printf("%s\n", value); g_free(value); @@ -24,7 +24,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <wchar.h> #include <glib.h> #include <glib-object.h> #include "debug.h" @@ -43,7 +42,7 @@ /* Structures and whatnot for tracking character classes. */ struct char_class_data { - wchar_t c; /* A character. */ + gunichar c; /* A character. */ int i; /* An integer. */ char *s; /* A string. */ int inc; /* An increment value. */ @@ -61,19 +60,19 @@ struct char_class { gboolean multiple; /* Whether a sequence of multiple characters in this class should be counted together. */ - wchar_t *code; /* A magic string that indicates this + gunichar *code; /* A magic string that indicates this class should be found here. */ size_t code_length; size_t ccount; /* The maximum number of characters after the format specifier to consume. */ - gboolean (*check)(const wchar_t c, struct char_class_data *data); + gboolean (*check)(const gunichar c, struct char_class_data *data); /* Function to check if a character is in this class. */ - void (*setup)(const wchar_t *s, struct char_class_data *data, int inc); + void (*setup)(const gunichar *s, struct char_class_data *data, int inc); /* Setup the data struct for use in the * above check function. */ - gboolean (*extract)(const wchar_t *s, size_t length, + gboolean (*extract)(const gunichar *s, size_t length, struct char_class_data *data, GValueArray *array); /* Extract a parameter. */ @@ -104,32 +103,32 @@ struct vte_trie { /* Functions for checking if a particular character is part of a class, and * for setting up a structure for use when determining matches. */ static gboolean -char_class_exact_check(wchar_t c, struct char_class_data *data) +char_class_exact_check(gunichar c, struct char_class_data *data) { return (c == data->c) ? TRUE : FALSE; } static void -char_class_exact_setup(const wchar_t *s, struct char_class_data *data, int inc) +char_class_exact_setup(const gunichar *s, struct char_class_data *data, int inc) { data->c = s[0]; return; } static void -char_class_percent_setup(const wchar_t *s, struct char_class_data *data, +char_class_percent_setup(const gunichar *s, struct char_class_data *data, int inc) { data->c = '%'; return; } static gboolean -char_class_none_extract(const wchar_t *s, size_t length, +char_class_none_extract(const gunichar *s, size_t length, struct char_class_data *data, GValueArray *array) { return FALSE; } static gboolean -char_class_digit_check(wchar_t c, struct char_class_data *data) +char_class_digit_check(gunichar c, struct char_class_data *data) { switch (c) { case '0': @@ -149,13 +148,13 @@ char_class_digit_check(wchar_t c, struct char_class_data *data) return FALSE; } static void -char_class_digit_setup(const wchar_t *s, struct char_class_data *data, int inc) +char_class_digit_setup(const gunichar *s, struct char_class_data *data, int inc) { data->inc = inc; return; } static gboolean -char_class_digit_extract(const wchar_t *s, size_t length, +char_class_digit_extract(const gunichar *s, size_t length, struct char_class_data *data, GValueArray *array) { long ret = 0; @@ -174,7 +173,7 @@ char_class_digit_extract(const wchar_t *s, size_t length, } static gboolean -char_class_multi_check(wchar_t c, struct char_class_data *data) +char_class_multi_check(gunichar c, struct char_class_data *data) { switch (c) { case '0': @@ -195,13 +194,13 @@ char_class_multi_check(wchar_t c, struct char_class_data *data) return FALSE; } static void -char_class_multi_setup(const wchar_t *s, struct char_class_data *data, int inc) +char_class_multi_setup(const gunichar *s, struct char_class_data *data, int inc) { data->inc = inc; return; } static gboolean -char_class_multi_extract(const wchar_t *s, size_t length, +char_class_multi_extract(const gunichar *s, size_t length, struct char_class_data *data, GValueArray *array) { long ret = 0; @@ -226,18 +225,18 @@ char_class_multi_extract(const wchar_t *s, size_t length, } static gboolean -char_class_any_check(wchar_t c, struct char_class_data *data) +char_class_any_check(gunichar c, struct char_class_data *data) { return (c >= data->c) ? TRUE : FALSE; } static void -char_class_any_setup(const wchar_t *s, struct char_class_data *data, int inc) +char_class_any_setup(const gunichar *s, struct char_class_data *data, int inc) { data->c = s[0] + inc; return; } static gboolean -char_class_any_extract(const wchar_t *s, size_t length, +char_class_any_extract(const gunichar *s, size_t length, struct char_class_data *data, GValueArray *array) { long ret = 0; @@ -252,18 +251,18 @@ char_class_any_extract(const wchar_t *s, size_t length, } static gboolean -char_class_string_check(wchar_t c, struct char_class_data *data) +char_class_string_check(gunichar c, struct char_class_data *data) { return (c != data->c) ? TRUE : FALSE; } static void -char_class_string_setup(const wchar_t *s, struct char_class_data *data, int inc) +char_class_string_setup(const gunichar *s, struct char_class_data *data, int inc) { data->c = s[0]; return; } static size_t -xwcsnlen(const wchar_t *s, size_t length) +unichar_snlen(const gunichar *s, size_t length) { size_t i; for (i = 0; i < length; i++) { @@ -273,17 +272,42 @@ xwcsnlen(const wchar_t *s, size_t length) } return length; } +static void +unichar_sncpy(gunichar *d, const gunichar *s, size_t length) +{ + int i; + for (i = 0; i < length; i++) { + d[i] = s[i]; + if (s[i] == 0) { + break; + } + } +} +static int +unichar_sncmp(const gunichar *a, const gunichar *b, size_t length) +{ + int i; + for (i = 0; i < length; i++) { + if (a[i] != b[i]) { + return a[i] - b[i]; + } + if (a[i] == 0) { + break; + } + } + return 0; +} static gboolean -char_class_string_extract(const wchar_t *s, size_t length, +char_class_string_extract(const gunichar *s, size_t length, struct char_class_data *data, GValueArray *array) { - wchar_t *ret = NULL; + gunichar *ret = NULL; size_t len; GValue value; - len = xwcsnlen(s, length); - ret = g_malloc0((len + 1) * sizeof(wchar_t)); - wcsncpy(ret, s, len); + len = unichar_snlen(s, length); + ret = g_malloc0((len + 1) * sizeof(gunichar)); + unichar_sncpy(ret, s, len); #ifdef VTE_DEBUG if (vte_debug_on(VTE_DEBUG_PARSE)) { fprintf(stderr, "Extracting string `%ls'.\n", ret); @@ -299,13 +323,13 @@ char_class_string_extract(const wchar_t *s, size_t length, return TRUE; } -static wchar_t empty_wstring[] = {'\0'}; -static wchar_t digit_wstring1[] = {'%', '2', '\0'}; -static wchar_t digit_wstring2[] = {'%', 'd', '\0'}; -static wchar_t any_wstring[] = {'%', '+', '\0'}; -static wchar_t exact_wstring[] = {'%', '%', '\0'}; -static wchar_t string_wstring[] = {'%', 's', '\0'}; -static wchar_t multi_wstring[] = {'%', 'm', '\0'}; +static gunichar empty_wstring[] = {'\0'}; +static gunichar digit_wstring1[] = {'%', '2', '\0'}; +static gunichar digit_wstring2[] = {'%', 'd', '\0'}; +static gunichar any_wstring[] = {'%', '+', '\0'}; +static gunichar exact_wstring[] = {'%', '%', '\0'}; +static gunichar string_wstring[] = {'%', 's', '\0'}; +static gunichar multi_wstring[] = {'%', 'm', '\0'}; static struct char_class char_classes[] = { {exact, FALSE, empty_wstring, 0, 1, @@ -365,15 +389,15 @@ vte_trie_free(struct vte_trie *trie) /* Add the given pattern, with its own result string, to the trie, with the * given initial increment value. */ static void -vte_trie_addx(struct vte_trie *trie, wchar_t *pattern, size_t length, +vte_trie_addx(struct vte_trie *trie, gunichar *pattern, size_t length, const char *result, GQuark quark, int inc) { unsigned long i; struct char_class *cclass = NULL; struct char_class_data data; - wchar_t *code; + gunichar *code; size_t len = 0, ccount = 0; - wchar_t inc_wstring[] = {'%', 'i', '\0'}; + gunichar inc_wstring[] = {'%', 'i', '\0'}; /* The trivial case -- we'll just set the result at this node. */ if (length == 0) { @@ -394,7 +418,7 @@ vte_trie_addx(struct vte_trie *trie, wchar_t *pattern, size_t length, /* If this part of the control sequence indicates incrementing a * parameter, keep track of the incrementing, skip over the increment * substring, and keep going. */ - if ((length >= 2) && (wcsncmp(pattern, inc_wstring, 2) == 0)) { + if ((length >= 2) && (unichar_sncmp(pattern, inc_wstring, 2) == 0)) { vte_trie_addx(trie, pattern + 2, length - 2, result, quark, inc + 1); return; @@ -406,7 +430,7 @@ vte_trie_addx(struct vte_trie *trie, wchar_t *pattern, size_t length, len = char_classes[i].code_length; code = char_classes[i].code; ccount = char_classes[i].ccount; - if ((len <= length) && (wcsncmp(pattern, code, len) == 0)) { + if ((len <= length) && (unichar_sncmp(pattern, code, len) == 0)) { cclass = &char_classes[i]; break; } @@ -460,7 +484,6 @@ TRIE_MAYBE_STATIC void vte_trie_add(struct vte_trie *trie, const char *pattern, size_t length, const char *result, GQuark quark) { - mbstate_t state; char *wpattern, *wpattern_end, *tpattern; GIConv conv; size_t wlength; @@ -473,18 +496,17 @@ vte_trie_add(struct vte_trie *trie, const char *pattern, size_t length, quark = g_quark_from_string(result); } - wlength = sizeof(wchar_t) * (length + 1); + wlength = sizeof(gunichar) * (length + 1); wpattern = wpattern_end = g_malloc0(wlength + 1); - memset(&state, 0, sizeof(state)); - conv = g_iconv_open("WCHAR_T", "UTF-8"); + conv = g_iconv_open(vte_trie_wide_encoding(), "UTF-8"); g_assert(conv != ((GIConv) -1)); tpattern = (char*)pattern; g_iconv(conv, &tpattern, &length, &wpattern_end, &wlength); if (length == 0) { - wlength = (wpattern_end - wpattern) / sizeof(wchar_t); - vte_trie_addx(trie, (wchar_t*)wpattern, wlength, + wlength = (wpattern_end - wpattern) / sizeof(gunichar); + vte_trie_addx(trie, (gunichar*)wpattern, wlength, result, quark, 0); } g_iconv_close(conv); @@ -496,9 +518,9 @@ vte_trie_add(struct vte_trie *trie, const char *pattern, size_t length, * empty string on a partial initial match, a NULL if there's no match in the * works, and the result string if we have an exact match. */ static const char * -vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length, +vte_trie_matchx(struct vte_trie *trie, const gunichar *pattern, size_t length, gboolean greedy, - const char **res, const wchar_t **consumed, + const char **res, const gunichar **consumed, GQuark *quark, GValueArray *array) { unsigned int i; @@ -509,7 +531,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length, const char *best = NULL; GValueArray *bestarray = NULL; GQuark bestquark = 0; - const wchar_t *bestconsumed = pattern; + const gunichar *bestconsumed = pattern; /* Make sure that attempting to save output values doesn't kill us. */ if (res == NULL) { @@ -579,7 +601,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length, if (trie->trie_paths[i].cclass->type == cc) { /* If it matches this character class... */ if (cclass->check(pattern[0], data)) { - const wchar_t *prospect = pattern + 1; + const gunichar *prospect = pattern + 1; const char *tmp; GQuark tmpquark = 0; GValueArray *tmparray; @@ -664,7 +686,7 @@ vte_trie_matchx(struct vte_trie *trie, const wchar_t *pattern, size_t length, g_value_array_free(bestarray); } #if 0 - g_print("`%s' ", best); + printf("`%s' ", best); dump_array(array); #endif *quark = bestquark; @@ -681,7 +703,7 @@ vte_trie_precompute(struct vte_trie *trie) struct vte_trie_table *table; enum cclass cc; int i; - wchar_t c; + gunichar c; /* Free the precomputed table (if there is one). */ if (trie->table != NULL) { @@ -723,15 +745,15 @@ vte_trie_precompute(struct vte_trie *trie) * empty string on a partial initial match, a NULL if there's no match in the * works, and the result string if we have an exact match. */ TRIE_MAYBE_STATIC const char * -vte_trie_match(struct vte_trie *trie, const wchar_t *pattern, size_t length, - const char **res, const wchar_t **consumed, +vte_trie_match(struct vte_trie *trie, const gunichar *pattern, size_t length, + const char **res, const gunichar **consumed, GQuark *quark, GValueArray **array) { const char *ret = NULL; GQuark tmpquark; GValueArray *valuearray; GValue *value; - const wchar_t *dummyconsumed; + const gunichar *dummyconsumed; gpointer ptr; gboolean greedy = FALSE; int i; @@ -840,7 +862,7 @@ vte_trie_printx(struct vte_trie *trie, const char *previous, size_t *nodecount) break; } if (trie->trie_paths[i].trie->result != NULL) { - g_print("%s = `%s'\n", buf, + printf("%s = `%s'\n", buf, trie->trie_paths[i].trie->result); } vte_trie_printx(trie->trie_paths[i].trie, buf, nodecount); @@ -853,7 +875,124 @@ vte_trie_print(struct vte_trie *trie) { size_t nodecount = 0; vte_trie_printx(trie, "", &nodecount); - g_print("Trie has %ld nodes.\n", (long) nodecount); + printf("Trie has %ld nodes.\n", (long) nodecount); +} + +#define SAMPLE "ABCDEF" +static char * +vte_trie_find_valid_encoding(char **list, size_t length, gboolean wide) +{ + gunichar wbuffer[8]; + unsigned char nbuffer[8]; + void *buffer; + char inbuf[BUFSIZ]; + char outbuf[BUFSIZ]; + char *ibuf, *obuf; + gsize isize, osize; + int i; + gsize outbytes; + GIConv conv; + + if (wide) { + buffer = wbuffer; + } else { + buffer = nbuffer; + } + + for (i = 0; SAMPLE[i] != '\0'; i++) { + wbuffer[i] = nbuffer[i] = SAMPLE[i]; + } + wbuffer[i] = nbuffer[i] = SAMPLE[i]; + + for (i = 0; i < length; i++) { + conv = g_iconv_open(list[i], "UTF-8"); + if (conv == ((GIConv) -1)) { +#ifdef VTE_DEBUG + if (vte_debug_on(VTE_DEBUG_MISC)) { + fprintf(stderr, "Conversions to `%s' are not " + "supported by giconv.\n", list[i]); + } +#endif + continue; + } + + ibuf = (char*) &inbuf; + strcpy(inbuf, SAMPLE); + isize = 3; + obuf = (char*) &outbuf; + osize = sizeof(outbuf); + + g_iconv(conv, &ibuf, &isize, &obuf, &osize); + g_iconv_close(conv); + + outbytes = sizeof(outbuf) - osize; + if ((isize == 0) && (outbytes > 0)) { + if (memcmp(outbuf, buffer, outbytes) == 0) { +#ifdef VTE_DEBUG + if (vte_debug_on(VTE_DEBUG_MISC)) { + fprintf(stderr, "Found iconv target " + "`%s'.\n", list[i]); + } +#endif + return g_strdup(list[i]); + } + } + } + + return NULL; +} + +TRIE_MAYBE_STATIC const char * +vte_trie_wide_encoding() +{ + char *wide[] = { + "10646", + "ISO_10646", + "ISO-10646", + "ISO10646", + "ISO-10646-1", + "ISO10646-1", + "ISO-10646/UCS4", + "UCS-4", + "UCS4", + "UCS-4-BE", + "UCS-4BE", + "UCS4-BE", + "UCS-4-INTERNAL", + "UCS-4-LE", + "UCS-4LE", + "UCS4-LE", + "UNICODE", + "UNICODE-BIG", + "UNICODEBIG", + "UNICODE-LITTLE", + "UNICODELITTLE", + "WCHAR_T", + }; + static char *ret = NULL; + if (ret == NULL) { + ret = vte_trie_find_valid_encoding(wide, + G_N_ELEMENTS(wide), + TRUE); + } + return ret; +} + +TRIE_MAYBE_STATIC const char * +vte_trie_narrow_encoding() +{ + char *narrow[] = { + "8859-1", + "ISO-8859-1", + "ISO8859-1", + }; + static char *ret = NULL; + if (ret == NULL) { + ret = vte_trie_find_valid_encoding(narrow, + G_N_ELEMENTS(narrow), + FALSE); + } + return ret; } #ifdef TRIE_MAIN @@ -862,35 +1001,35 @@ dump_array(GValueArray *array) { unsigned int i; if (array != NULL) { - g_print("args = {"); + printf("args = {"); for (i = 0; i < array->n_values; i++) { GValue *value; value = g_value_array_get_nth(array, i); if (i > 0) { - g_print(", "); + printf(", "); } if (G_VALUE_HOLDS_LONG(value)) { - g_print("%ld", g_value_get_long(value)); + printf("%ld", g_value_get_long(value)); } if (G_VALUE_HOLDS_STRING(value)) { - g_print("`%s'", g_value_get_string(value)); + printf("`%s'", g_value_get_string(value)); } if (G_VALUE_HOLDS_POINTER(value)) { printf("`%ls'", - (wchar_t*)g_value_get_pointer(value)); + (gunichar*)g_value_get_pointer(value)); } } - g_print("}\n"); + printf("}\n"); } } static void convert_mbstowcs(const char *i, size_t ilen, - wchar_t *o, size_t *olen, size_t max_olen) + gunichar *o, size_t *olen, size_t max_olen) { GIConv conv; size_t outlen; - conv = g_iconv_open("WCHAR_T", "UTF-8"); + conv = g_iconv_open(vte_trie_wide_encoding(), "UTF-8"); g_assert(conv != ((GIConv) -1)); memset(o, 0, max_olen); @@ -898,7 +1037,7 @@ convert_mbstowcs(const char *i, size_t ilen, g_iconv(conv, (char**)&i, &ilen, (char**)&o, &outlen); g_iconv_close(conv); - *olen = (max_olen - outlen) / sizeof(wchar_t); + *olen = (max_olen - outlen) / sizeof(gunichar); } int @@ -907,10 +1046,12 @@ main(int argc, char **argv) struct vte_trie *trie; GValueArray *array = NULL; GQuark quark; - wchar_t buf[LINE_MAX]; - const wchar_t *consumed; + gunichar buf[LINE_MAX]; + const gunichar *consumed; size_t buflen; + vte_debug_parse_string(getenv("VTE_DEBUG_FLAGS")); + g_type_init(); trie = vte_trie_new(); @@ -941,15 +1082,19 @@ main(int argc, char **argv) vte_trie_precompute(trie); } } + + printf("Wide encoding is `%s'.\n", vte_trie_wide_encoding()); + printf("Narrow encoding is `%s'.\n", vte_trie_narrow_encoding()); + vte_trie_print(trie); - g_print("\n"); + printf("\n"); quark = 0; convert_mbstowcs("abc", 3, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abc", + printf("`%s' = `%s'\n", "abc", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -958,10 +1103,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abcdef", 6, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abcdef", + printf("`%s' = `%s'\n", "abcdef", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -970,10 +1115,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abcde", 5, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abcde", + printf("`%s' = `%s'\n", "abcde", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -982,10 +1127,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abcdeg", 6, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abcdeg", + printf("`%s' = `%s'\n", "abcdeg", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -994,10 +1139,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abc%deg", 7, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abc%deg", + printf("`%s' = `%s'\n", "abc%deg", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1006,10 +1151,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abc10eg", 7, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abc10eg", + printf("`%s' = `%s'\n", "abc10eg", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1018,10 +1163,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abc%eg", 6, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abc%eg", + printf("`%s' = `%s'\n", "abc%eg", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1030,10 +1175,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abc%10eg", 8, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abc%10eg", + printf("`%s' = `%s'\n", "abc%10eg", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1042,10 +1187,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("abcBeg", 6, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "abcBeg", + printf("`%s' = `%s'\n", "abcBeg", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1054,10 +1199,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>[25;26H", 12, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>[25;26H", + printf("`%s' = `%s'\n", "<esc>[25;26H", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1066,10 +1211,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>[25;2", 10, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>[25;2", + printf("`%s' = `%s'\n", "<esc>[25;2", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1077,10 +1222,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>[25L", 9, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>[25L", + printf("`%s' = `%s'\n", "<esc>[25L", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1088,10 +1233,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>[25L<esc>[24L", 18, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>[25L<esc>[24L", + printf("`%s' = `%s'\n", "<esc>[25L<esc>[24L", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1099,10 +1244,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>[25;26L", 12, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>[25;26L", + printf("`%s' = `%s'\n", "<esc>[25;26L", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1110,10 +1255,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>]2;WoofWoofh", 17, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>]2;WoofWoofh", + printf("`%s' = `%s'\n", "<esc>]2;WoofWoofh", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1123,10 +1268,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>]2;WoofWoofh<esc>]2;WoofWoofh", 34, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>]2;WoofWoofh<esc>]2;WoofWoofh", + printf("`%s' = `%s'\n", "<esc>]2;WoofWoofh<esc>]2;WoofWoofh", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -1135,10 +1280,10 @@ main(int argc, char **argv) quark = 0; convert_mbstowcs("<esc>]2;WoofWoofhfoo", 20, buf, &buflen, sizeof(buf)); - g_print("`%s' = `%s'\n", "<esc>]2;WoofWoofhfoo", + printf("`%s' = `%s'\n", "<esc>]2;WoofWoofhfoo", vte_trie_match(trie, buf, buflen, NULL, &consumed, &quark, &array)); - g_print("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); + printf("=> `%s' (%d)\n", g_quark_to_string(quark), consumed - buf); if (array != NULL) { dump_array(array); g_value_array_free(array); @@ -21,8 +21,8 @@ #ident "$Id$" -#include <wchar.h> #include <glib.h> +#include <glib-object.h> G_BEGIN_DECLS @@ -48,9 +48,9 @@ void vte_trie_add(struct vte_trie *trie, * passed-in string can not be an initial substring of one of the strings in * the trie, then NULL is returned. */ const char *vte_trie_match(struct vte_trie *trie, - const wchar_t *pattern, size_t length, + const gunichar *pattern, size_t length, const char **res, - const wchar_t **consumed, + const gunichar **consumed, GQuark *quark, GValueArray **array); @@ -60,6 +60,12 @@ void vte_trie_print(struct vte_trie *trie); /* Precompute internal information to hopefully make traversal faster. */ void vte_trie_precompute(struct vte_trie *trie); +/* A gunichar-compatible giconv target, if one can be found. */ +const char *vte_trie_wide_encoding(void); + +/* A single-byte iso-8859-1 giconv target, if one can be found. */ +const char *vte_trie_narrow_encoding(void); + G_END_DECLS #endif diff --git a/src/utf8echo.c b/src/utf8echo.c index db610ec0..0b69aedf 100644 --- a/src/utf8echo.c +++ b/src/utf8echo.c @@ -18,11 +18,12 @@ #ident "$Id$" #include "../config.h" -#include <glib/gconvert.h> +#include <glib.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "trie.h" #define ESC "" int @@ -40,7 +41,7 @@ main(int argc, char **argv) return 1; } - conv = g_iconv_open("UTF-8", "WCHAR_T"); + conv = g_iconv_open("UTF-8", vte_trie_wide_encoding()); if (conv == ((GIConv*) -1)) { return 1; } @@ -36,7 +36,6 @@ #include <termios.h> #include <unistd.h> #include <wchar.h> -#include <wctype.h> #include <glib.h> #include <glib-object.h> #include <gdk/gdk.h> @@ -94,9 +93,9 @@ /* The structure we use to hold characters we're supposed to display -- this * includes any supported visible attributes. */ struct vte_charcell { - wchar_t c; /* The wide character. */ + gunichar c; /* The Unicode character. */ guint16 columns: 2; /* Number of visible columns (as determined - by wcwidth(c)). */ + by g_unicode_iswide(c)). */ guint16 fore: 5; /* Indices in the color palette for the */ guint16 back: 5; /* foreground and background of the cell. */ guint16 standout: 1; /* Single-bit attributes. */ @@ -127,7 +126,7 @@ typedef enum { typedef struct _VteScreen VteScreen; typedef struct _VteWordCharRange { - wchar_t start, end; + gunichar start, end; } VteWordCharRange; /* Terminal private data. */ @@ -157,7 +156,7 @@ struct _VteTerminalPrivate { const char *gxencoding[4]; /* alternate encodings */ /* Input data queues. */ - GIConv incoming_conv; /* narrow/wide conversion state */ + GIConv incoming_conv; /* narrow/unichar conversion state */ unsigned char *incoming; /* pending output characters */ size_t n_incoming; gboolean processing; @@ -303,7 +302,7 @@ typedef void (*VteTerminalSequenceHandler)(VteTerminal *terminal, static void vte_terminal_set_termcap(VteTerminal *terminal, const char *path, gboolean reset); static void vte_terminal_ensure_cursor(VteTerminal *terminal, gboolean current); -static void vte_terminal_insert_char(GtkWidget *widget, wchar_t c, +static void vte_terminal_insert_char(GtkWidget *widget, gunichar c, gboolean force_insert); static void vte_sequence_handler_clear_screen(VteTerminal *terminal, const char *match, @@ -369,6 +368,33 @@ vte_new_row_data(void) return g_array_new(FALSE, FALSE, sizeof(struct vte_charcell)); } +/* Guess at how many columns a character takes up. */ +static ssize_t +vte_unichar_width(gunichar c) +{ + return g_unichar_isdefined(c) ? (g_unichar_iswide(c) ? 2 : 1) : -1; +} + +/* Check how long a string of unichars is. Slow version. */ +static ssize_t +vte_unicode_strlen(gunichar *c) +{ + int i; + for (i = 0; c[i] != 0; i++) ; + return i; +} + +/* Convert a gunichar to a wchar_t for use with X. */ +static wchar_t +vte_wc_from_unichar(gunichar c) +{ +#ifdef __STDC_ISO_10646__ + return (wchar_t) c; +#else +#error "Don't know how to convert from gunichar to wchar_t!" +#endif +} + /* Reset defaults for character insertion. */ static void vte_terminal_set_default_attributes(VteTerminal *terminal) @@ -1267,41 +1293,68 @@ vte_terminal_set_encoding(VteTerminal *terminal, const char *codeset) size_t icount, ocount; old_codeset = terminal->pvt->encoding; - if (codeset == NULL) { codeset = nl_langinfo(CODESET); } /* Open new conversions. */ - new_iconv = g_iconv_open("WCHAR_T", codeset); - new_oconvw = g_iconv_open(codeset, "WCHAR_T"); - new_oconvu = g_iconv_open(codeset, "UTF-8"); + new_iconv = g_iconv_open(vte_trie_wide_encoding(), codeset); if (new_iconv == ((GIConv) -1)) { g_warning(_("Unable to convert characters from %s to %s."), - codeset, "WCHAR_T"); - return; + codeset, vte_trie_wide_encoding()); + if (terminal->pvt->encoding != NULL) { + /* Keep the current encoding. */ + return; + } } + new_oconvw = g_iconv_open(codeset, vte_trie_wide_encoding()); if (new_oconvw == ((GIConv) -1)) { g_warning(_("Unable to convert characters from %s to %s."), - "WCHAR_T", codeset); + vte_trie_wide_encoding(), codeset); g_iconv_close(new_iconv); - return; + if (terminal->pvt->encoding != NULL) { + /* Keep the current encoding. */ + return; + } } + new_oconvu = g_iconv_open(codeset, "UTF-8"); if (new_oconvu == ((GIConv) -1)) { g_warning(_("Unable to convert characters from %s to %s."), "UTF-8", codeset); g_iconv_close(new_iconv); g_iconv_close(new_oconvw); - return; + if (terminal->pvt->encoding != NULL) { + /* Keep the current encoding. */ + return; + } + } + + if (new_oconvu == ((GIConv) -1)) { + codeset = vte_trie_narrow_encoding(); + new_iconv = g_iconv_open(vte_trie_wide_encoding(), codeset); + if (new_iconv == ((GIConv) -1)) { + g_error(_("Unable to convert characters from %s to %s."), + codeset, vte_trie_wide_encoding()); + } + new_oconvw = g_iconv_open(codeset, vte_trie_wide_encoding()); + if (new_oconvw == ((GIConv) -1)) { + g_error(_("Unable to convert characters from %s to %s."), + vte_trie_wide_encoding(), codeset); + } + new_oconvu = g_iconv_open(codeset, "UTF-8"); + if (new_oconvu == ((GIConv) -1)) { + g_error(_("Unable to convert characters from %s to %s."), + "UTF-8", codeset); + } } - /* Set up the conversion for incoming-to-wchars. */ + /* Set up the conversion for incoming-to-gunichar. */ if (terminal->pvt->incoming_conv != ((GIConv) -1)) { g_iconv_close(terminal->pvt->incoming_conv); } terminal->pvt->incoming_conv = new_iconv; - /* Set up the conversions for wchar/utf-8 to outgoing. */ + /* Set up the conversions for gunichar/utf-8 to outgoing. */ if (terminal->pvt->outgoing_conv_wide != ((GIConv) -1)) { g_iconv_close(terminal->pvt->outgoing_conv_wide); } @@ -1905,7 +1958,7 @@ vte_terminal_ensure_cursor(VteTerminal *terminal, gboolean current) memset(&cell, 0, sizeof(cell)); cell = screen->defaults; cell.c = ' '; - cell.columns = wcwidth(cell.c); + cell.columns = vte_unichar_width(cell.c); if (!current) { cell.fore = VTE_DEF_FG; cell.back = VTE_DEF_BG; @@ -3071,11 +3124,12 @@ vte_sequence_handler_set_title_int(VteTerminal *terminal, outbufptr = g_value_dup_string(value); } else if (G_VALUE_HOLDS_POINTER(value)) { - /* Convert the wide-character string into a + /* Convert the unicode-character string into a * multibyte string. */ - conv = g_iconv_open("UTF-8", "WCHAR_T"); + conv = g_iconv_open("UTF-8", vte_trie_wide_encoding()); inbuf = g_value_get_pointer(value); - inbuf_len = wcslen((wchar_t*)inbuf) * sizeof(wchar_t); + inbuf_len = vte_unicode_strlen((gunichar*)inbuf) * + sizeof(gunichar); outbuf_len = (inbuf_len * VTE_UTF8_BPC) + 1; outbuf = outbufptr = g_malloc0(outbuf_len); if (conv != ((GIConv) -1)) { @@ -3699,10 +3753,10 @@ vte_sequence_handler_local_charset(VteTerminal *terminal, { g_return_if_fail(VTE_IS_TERMINAL(terminal)); #ifdef VTE_DEFAULT_ISO_8859_1 - vte_terminal_set_encoding(terminal, "ISO-8859-1"); + vte_terminal_set_encoding(terminal, vte_trie_narrow_encoding()); #else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { - vte_terminal_set_encoding(terminal, "ISO-8859-1"); + vte_terminal_set_encoding(terminal, vte_trie_narrow_encoding()); } else { vte_terminal_set_encoding(terminal, nl_langinfo(CODESET)); } @@ -4195,7 +4249,7 @@ vte_sequence_handler_designate_gx(VteTerminal *terminal, case '7': case '=': /* Swiss. */ terminal->pvt->gxencoding[x] = - "ISO-8859-15"; + vte_trie_narrow_encoding(); break; } } @@ -4923,7 +4977,7 @@ vte_terminal_set_default_colors(VteTerminal *terminal) /* Insert a single character into the stored data array. */ static void -vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert) +vte_terminal_insert_char(GtkWidget *widget, gunichar c, gboolean force_insert) { VteTerminal *terminal; GArray *array; @@ -4941,20 +4995,20 @@ vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert) #ifdef VTE_DEBUG if (vte_debug_on(VTE_DEBUG_IO)) { - fprintf(stderr, "Inserting %ld (%d/%d), delta = %ld.\n", + fprintf(stderr, "Inserting %ld %c (%d/%d)(%d), delta = %ld, ", (long)c, + c < 256 ? c : ' ', screen->defaults.fore, screen->defaults.back, + vte_unichar_width(c), (long)screen->insert_delta); } #endif /* Figure out how many columns this character should occupy. */ - columns = wcwidth(c); - - /* FIXME: find why this can happen, and stop it. */ + columns = vte_unichar_width(c); if (columns < 0) { - g_warning(_("Character %5ld is %d columns wide, guessing 1."), - c, columns); + g_warning(_("Character 0x%x is undefined, allocating one " + "column."), c); columns = 1; } @@ -5070,7 +5124,7 @@ vte_terminal_insert_char(GtkWidget *widget, wchar_t c, gboolean force_insert) #ifdef VTE_DEBUG if (vte_debug_on(VTE_DEBUG_IO)) { - fprintf(stderr, "Insertion delta = %ld.\n", + fprintf(stderr, "insertion delta => %ld.\n", (long)screen->insert_delta); } #endif @@ -5086,7 +5140,7 @@ display_control_sequence(const char *name, GValueArray *params) int i; long l; const char *s; - const wchar_t *w; + const gunichar *w; GValue *value; fprintf(stderr, "%s(", name); if (params != NULL) { @@ -5283,7 +5337,7 @@ vte_terminal_im_reset(VteTerminal *terminal) } /* Free a parameter array. Most of the GValue elements can clean up after - * themselves, but we're using gpointers to hold wide character strings, and + * themselves, but we're using gpointers to hold unicode character strings, and * we need to free those ourselves. */ static void free_params_array(GValueArray *params) @@ -5306,7 +5360,7 @@ free_params_array(GValueArray *params) } } -/* Process incoming data, first converting it to wide characters, and then +/* Process incoming data, first converting it to unicode characters, and then * processing escape sequences. */ static gboolean vte_terminal_process_incoming(gpointer data) @@ -5319,12 +5373,12 @@ vte_terminal_process_incoming(gpointer data) GdkRectangle rect; char *ibuf, *obuf, *obufptr, *ubuf, *ubufptr; size_t icount, ocount, ucount; - wchar_t *wbuf, c; + gunichar *wbuf, c; int wcount, start; const char *match, *encoding; GIConv unconv; GQuark quark; - const wchar_t *next; + const gunichar *next; gboolean leftovers, modified, again, bottom; g_return_val_if_fail(GTK_IS_WIDGET(data), FALSE); @@ -5344,29 +5398,30 @@ vte_terminal_process_incoming(gpointer data) /* We should only be called when there's data to process. */ g_assert(terminal->pvt->n_incoming > 0); - /* Try to convert the data into wide characters. */ - ocount = sizeof(wchar_t) * terminal->pvt->n_incoming; + /* Try to convert the data into unicode characters. */ + ocount = sizeof(gunichar) * terminal->pvt->n_incoming; obuf = obufptr = g_malloc(ocount); icount = terminal->pvt->n_incoming; ibuf = terminal->pvt->incoming; - /* Convert the data to wide characters. */ + /* Convert the data to unicode characters. */ if (g_iconv(terminal->pvt->incoming_conv, &ibuf, &icount, &obuf, &ocount) == -1) { /* No dice. Try again when we have more data. */ if ((errno == EILSEQ) && (terminal->pvt->n_incoming > 0)) { /* Discard the offending byte. */ start = terminal->pvt->n_incoming - icount; - terminal->pvt->incoming[start] = '?'; #ifdef VTE_DEBUG - if (vte_debug_on(VTE_DEBUG_IO)) { + if (vte_debug_on(VTE_DEBUG_IO) || 1) { fprintf(stderr, "Error converting %ld incoming " "data bytes: %s, discarding byte %ld " - "and trying again.\n", + "(0x%02x) and trying again.\n", (long) terminal->pvt->n_incoming, - strerror(errno), start); + strerror(errno), start, + terminal->pvt->incoming[start]); } #endif + terminal->pvt->incoming[start] = '?'; /* Try again. */ g_free(obufptr); return TRUE; @@ -5388,9 +5443,9 @@ vte_terminal_process_incoming(gpointer data) /* Store the current encoding. */ encoding = terminal->pvt->encoding; - /* Compute the number of wide characters we got. */ - wcount = (obuf - obufptr) / sizeof(wchar_t); - wbuf = (wchar_t*) obufptr; + /* Compute the number of unicode characters we got. */ + wcount = (obuf - obufptr) / sizeof(gunichar); + wbuf = (gunichar*) obufptr; /* Save the current cursor position. */ screen = terminal->pvt->screen; @@ -5522,7 +5577,7 @@ vte_terminal_process_incoming(gpointer data) match, quark, params); - /* Skip over the proper number of wide chars. */ + /* Skip over the proper number of unicode chars. */ start = (next - wbuf); /* Check if the encoding's changed. If it has, we need * to force our caller to call us again to parse the @@ -5588,9 +5643,9 @@ vte_terminal_process_incoming(gpointer data) if (leftovers) { /* There are leftovers, so convert them back to the terminal's * old encoding and save them for later. */ - unconv = g_iconv_open(encoding, "WCHAR_T"); + unconv = g_iconv_open(encoding, vte_trie_wide_encoding()); if (unconv != ((GIConv) -1)) { - icount = sizeof(wchar_t) * (wcount - start); + icount = sizeof(gunichar) * (wcount - start); ibuf = (char*) &wbuf[start]; ucount = VTE_UTF8_BPC * (wcount - start) + 1; ubuf = ubufptr = g_malloc(ucount); @@ -5616,7 +5671,7 @@ vte_terminal_process_incoming(gpointer data) if (vte_debug_on(VTE_DEBUG_IO)) { fprintf(stderr, "Error unconverting %ld " "pending input bytes (%s), dropping.\n", - (long) (sizeof(wchar_t) * (wcount - start)), + (long) (sizeof(gunichar) * (wcount - start)), strerror(errno)); } #endif @@ -5851,7 +5906,7 @@ vte_terminal_feed(VteTerminal *terminal, const char *data, size_t length) } } -/* Send wide characters to the child. */ +/* Send unicode characters to the child. */ static gboolean vte_terminal_io_write(GIOChannel *channel, GdkInputCondition condition, @@ -5913,13 +5968,13 @@ vte_terminal_send(VteTerminal *terminal, const char *encoding, g_return_if_fail(VTE_IS_TERMINAL(terminal)); g_assert((strcmp(encoding, "UTF-8") == 0) || - (strcmp(encoding, "WCHAR_T") == 0)); + (strcmp(encoding, vte_trie_wide_encoding()) == 0)); conv = NULL; if (strcmp(encoding, "UTF-8") == 0) { conv = &terminal->pvt->outgoing_conv_utf8; } - if (strcmp(encoding, "WCHAR_T") == 0) { + if (strcmp(encoding, vte_trie_wide_encoding()) == 0) { conv = &terminal->pvt->outgoing_conv_wide; } g_assert(conv != NULL); @@ -6593,10 +6648,6 @@ vte_terminal_is_word_char(VteTerminal *terminal, gunichar c) if (terminal->pvt->word_chars == NULL) { return FALSE; } - /* FIXME: if a gunichar isn't a wchar_t, we're probably screwed, so - * should we convert from UCS-4 to WCHAR_T or something here? (Is a - * gunichar even a UCS-4 character)? Or should we convert to UTF-8 - * and then to WCHAR_T? Aaaargh. */ for (i = 0; i < terminal->pvt->word_chars->len; i++) { range = &g_array_index(terminal->pvt->word_chars, VteWordCharRange, @@ -9454,7 +9505,7 @@ vte_terminal_draw_char(VteTerminal *terminal, int fore, back, dcol, i, j, padding; long xcenter, ycenter, xright, ybottom; char utf8_buf[7] = {0,}; - wchar_t ch; + gunichar ch; gboolean drawn, reverse, alternate; PangoAttribute *attr; PangoAttrList *attrlist; @@ -10220,8 +10271,15 @@ vte_terminal_draw_char(VteTerminal *terminal, XftTextExtents32(GDK_DISPLAY(), font, &ftc, 1, &glyph_info); padding = CLAMP((terminal->char_width * - wcwidth(ch) - glyph_info.xOff) / 2, + (g_unichar_iswide(ch) ? 2 : 1) - + glyph_info.xOff) / 2, 0, 3 * terminal->char_width); +#ifdef VTE_DEBUG + if (vte_debug_on(VTE_DEBUG_UPDATES)) { + fprintf(stderr, "Using %d pixels of padding for" + " character 0x%x.\n", padding, ch); + } +#endif g_tree_insert(terminal->pvt->fontpadding, GINT_TO_POINTER(ftc), GINT_TO_POINTER(padding)); @@ -10266,6 +10324,8 @@ vte_terminal_draw_char(VteTerminal *terminal, if (!drawn) { gpointer ptr; XRectangle ink, logic; + wchar_t wc; + wc = vte_wc_from_unichar(ch); ptr = g_tree_lookup(terminal->pvt->fontpadding, GINT_TO_POINTER(ch)); padding = GPOINTER_TO_INT(ptr); @@ -10273,7 +10333,7 @@ vte_terminal_draw_char(VteTerminal *terminal, padding = 0; } else if (padding == 0) { XwcTextExtents(terminal->pvt->fontset, - &ch, 1, &ink, &logic); + &wc, 1, &ink, &logic); padding = CLAMP((terminal->char_width * wcwidth(ch) - logic.width) / 2, 0, 3 * terminal->char_width); @@ -10283,7 +10343,7 @@ vte_terminal_draw_char(VteTerminal *terminal, } /* Set the textitem's fields. */ - textitem.chars = &ch; + textitem.chars = &wc; textitem.nchars = 1; textitem.delta = 0; textitem.font_set = terminal->pvt->fontset; @@ -10510,7 +10570,7 @@ vte_terminal_paint(GtkWidget *widget, GdkRectangle *area) if (terminal->pvt->im_preedit != NULL) { preedit = terminal->pvt->im_preedit; for (i = 0; i < terminal->pvt->im_preedit_cursor; i++) { - col += wcwidth(g_utf8_get_char(preedit)); + col += vte_unichar_width(g_utf8_get_char(preedit)); preedit = g_utf8_next_char(preedit); } } @@ -10641,7 +10701,7 @@ vte_terminal_paint(GtkWidget *widget, GdkRectangle *area) ftdraw, #endif FALSE); - col += wcwidth(im_cell.c); + col += vte_unichar_width(im_cell.c); preedit = g_utf8_next_char(preedit); } if (len > 0) { @@ -10984,6 +11044,14 @@ vte_terminal_class_init(VteTerminalClass *klass, gconstpointer data) _vte_marshal_VOID__UINT_UINT, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + /* Try to determine some acceptable encoding names. */ + if (vte_trie_narrow_encoding() == NULL) { + g_error("Don't know how to read ISO-8859-1 data!"); + } + if (vte_trie_wide_encoding() == NULL) { + g_error("Don't know how to read native-endian unicode data!"); + } + #ifdef VTE_DEBUG /* Turn on debugging if we were asked to. */ if (getenv("VTE_DEBUG_FLAGS") != NULL) { @@ -11609,7 +11677,7 @@ void vte_terminal_set_word_chars(VteTerminal *terminal, const char *spec) { GIConv conv; - wchar_t *wbuf; + gunichar *wbuf; char *ibuf, *ibufptr, *obuf, *obufptr; size_t ilen, olen; VteWordCharRange range; @@ -11622,8 +11690,8 @@ vte_terminal_set_word_chars(VteTerminal *terminal, const char *spec) } terminal->pvt->word_chars = g_array_new(FALSE, TRUE, sizeof(VteWordCharRange)); - /* Convert the spec from UTF-8 to a string of wchar_t. */ - conv = g_iconv_open("WCHAR_T", "UTF-8"); + /* Convert the spec from UTF-8 to a string of gunichars . */ + conv = g_iconv_open(vte_trie_wide_encoding(), "UTF-8"); if (conv == ((GIConv) -1)) { /* Aaargh. We're screwed. */ g_warning(_("g_iconv_open() failed setting word characters")); @@ -11631,13 +11699,13 @@ vte_terminal_set_word_chars(VteTerminal *terminal, const char *spec) } ilen = strlen(spec); ibuf = ibufptr = g_strdup(spec); - olen = (ilen + 1) * sizeof(wchar_t); - obuf = obufptr = g_malloc0(sizeof(wchar_t) * (strlen(spec) + 1)); - wbuf = (wchar_t*) obuf; + olen = (ilen + 1) * sizeof(gunichar); + obuf = obufptr = g_malloc0(sizeof(gunichar) * (strlen(spec) + 1)); + wbuf = (gunichar*) obuf; wbuf[ilen] = '\0'; g_iconv(conv, &ibuf, &ilen, &obuf, &olen); g_iconv_close(conv); - for (i = 0; i < ((obuf - obufptr) / sizeof(wchar_t)); i++) { + for (i = 0; i < ((obuf - obufptr) / sizeof(gunichar)); i++) { /* The hyphen character. */ if (wbuf[i] == '-') { range.start = wbuf[i]; @@ -24,7 +24,6 @@ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> -#include <wchar.h> #include <X11/Xlib.h> #include <glib.h> #include <pango/pango.h> @@ -1,5 +1,5 @@ Name: vte -Version: 0.4.9 +Version: 0.5.0 Release: 1 Summary: An experimental terminal emulator. License: LGPL @@ -36,12 +36,13 @@ rm -fr $RPM_BUILD_ROOT %install rm -fr $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT +%find_lang %{name} %post -p /sbin/ldconfig %postun -p /sbin/ldconfig -%files +%files -f %{name}.lang %defattr(-,root,root) %doc ChangeLog COPYING HACKING NEWS README %{_libdir}/*.so.*.* @@ -75,7 +76,7 @@ make install DESTDIR=$RPM_BUILD_ROOT * Thu Jul 11 2002 Nalin Dahyabhai <nalin@redhat.com> - rework default color selection - provide a means for apps to just set the foreground/background text colors -- don't scroll-on-keystroke when it's just alt, hyper, meta, or super +- don't scroll-on-keystroke when it's just alt, hyper, meta, or super (#68986) * Tue Jul 2 2002 Nalin Dahyabhai <nalin@redhat.com> - allow shift+click to extend the selection (re: gnome 86246) |